diff --git a/services/web/client/source/class/osparc/Application.js b/services/web/client/source/class/osparc/Application.js index 5113b887429..14b5bec133a 100644 --- a/services/web/client/source/class/osparc/Application.js +++ b/services/web/client/source/class/osparc/Application.js @@ -220,9 +220,6 @@ qx.Class.define("osparc.Application", { if (isLogged) { this.__loadMainPage(); } else { - // Reset store (cache) - osparc.store.Store.getInstance().invalidate(); - osparc.auth.Manager.getInstance().validateToken() .then(data => { if (data.role.toLowerCase() === "guest") { @@ -287,6 +284,7 @@ qx.Class.define("osparc.Application", { if (this.__mainPage) { this.__mainPage.closeEditor(); } + osparc.store.Store.getInstance().dispose(); this.__restart(); }, diff --git a/services/web/client/source/class/osparc/dashboard/SideSearch.js b/services/web/client/source/class/osparc/dashboard/SideSearch.js index d0c0cfcd58a..db178d63824 100644 --- a/services/web/client/source/class/osparc/dashboard/SideSearch.js +++ b/services/web/client/source/class/osparc/dashboard/SideSearch.js @@ -59,7 +59,7 @@ qx.Class.define("osparc.dashboard.SideSearch", { marginLeft: -12, marginTop: -5 }); - osparc.store.Store.getInstance().addListener("changeClassifiers", e => { + osparc.store.Store.getInstance().addListener("changeClassifiers", () => { classifier.recreateTree(); }, this); this._add(classifier, { diff --git a/services/web/client/source/class/osparc/dashboard/StudyBrowser.js b/services/web/client/source/class/osparc/dashboard/StudyBrowser.js index d8ff75f4ac7..a4716d7c236 100644 --- a/services/web/client/source/class/osparc/dashboard/StudyBrowser.js +++ b/services/web/client/source/class/osparc/dashboard/StudyBrowser.js @@ -284,9 +284,7 @@ qx.Class.define("osparc.dashboard.StudyBrowser", { this.resetSelection(); }); osparc.store.Store.getInstance().addListener("changeTags", () => { - if (osparc.auth.Manager.getInstance().isLoggedIn()) { - this.reloadUserStudies(); - } + this.reloadUserStudies(); }, this); }, diff --git a/services/web/client/source/class/osparc/desktop/WorkbenchView.js b/services/web/client/source/class/osparc/desktop/WorkbenchView.js index e0d723fb2dd..c59f2f89790 100644 --- a/services/web/client/source/class/osparc/desktop/WorkbenchView.js +++ b/services/web/client/source/class/osparc/desktop/WorkbenchView.js @@ -94,26 +94,24 @@ qx.Class.define("osparc.desktop.WorkbenchView", { const study = this.getStudy(); const workbench = study.getWorkbench(); - if (nodeId === study.getUuid()) { - this.__showInMainView(this.__workbenchUI, nodeId); + const node = workbench.getNode(nodeId); + if (node === null || nodeId === study.getUuid()) { + this.__showInMainView(this.__workbenchUI, study.getUuid()); this.__workbenchUI.loadModel(workbench); + } else if (node.isContainer()) { + this.__groupNodeView.setNode(node); + this.__showInMainView(this.__workbenchUI, nodeId); + this.__workbenchUI.loadModel(node); + this.__groupNodeView.populateLayout(); + } else if (node.isFilePicker()) { + const nodeView = new osparc.component.node.FilePickerNodeView(); + nodeView.setNode(node); + this.__showInMainView(nodeView, nodeId); + nodeView.populateLayout(); } else { - const node = workbench.getNode(nodeId); - if (node.isContainer()) { - this.__groupNodeView.setNode(node); - this.__showInMainView(this.__workbenchUI, nodeId); - this.__workbenchUI.loadModel(node); - this.__groupNodeView.populateLayout(); - } else if (node.isFilePicker()) { - const nodeView = new osparc.component.node.FilePickerNodeView(); - nodeView.setNode(node); - this.__showInMainView(nodeView, nodeId); - nodeView.populateLayout(); - } else { - this.__nodeView.setNode(node); - this.__showInMainView(this.__nodeView, nodeId); - this.__nodeView.populateLayout(); - } + this.__nodeView.setNode(node); + this.__showInMainView(this.__nodeView, nodeId); + this.__nodeView.populateLayout(); } }, diff --git a/services/web/client/source/class/osparc/file/FilePicker.js b/services/web/client/source/class/osparc/file/FilePicker.js index 67e03361f61..8d8fb43941a 100644 --- a/services/web/client/source/class/osparc/file/FilePicker.js +++ b/services/web/client/source/class/osparc/file/FilePicker.js @@ -245,7 +245,10 @@ qx.Class.define("osparc.file.FilePicker", { __isOutputFileSelectedFromStore: function() { const outFile = this.__getOutputFile(); - if (outFile && "value" in outFile && "path" in outFile.value) { + if (outFile && + "value" in outFile && + typeof outFile["value"] === "object" && + "path" in outFile["value"]) { return true; } return false; @@ -253,7 +256,10 @@ qx.Class.define("osparc.file.FilePicker", { __isOutputFileSelectedFromLink: function() { const outFile = this.__getOutputFile(); - if (outFile && "value" in outFile && "downloadLink" in outFile.value) { + if (outFile && + "value" in outFile && + typeof outFile["value"] === "object" && + "downloadLink" in outFile.value) { return true; } return false; diff --git a/services/web/client/source/class/osparc/ui/mixin/FetchButton.js b/services/web/client/source/class/osparc/ui/mixin/FetchButton.js index 712e9531197..41df88ed0f6 100644 --- a/services/web/client/source/class/osparc/ui/mixin/FetchButton.js +++ b/services/web/client/source/class/osparc/ui/mixin/FetchButton.js @@ -28,9 +28,14 @@ qx.Mixin.define("osparc.ui.mixin.FetchButton", { if (isFetching !== old) { this.setIcon(this.__icon); } - this.getChildControl("icon").getContentElement().removeClass("rotate"); + if (this.getChildControl("icon")) { + this.getChildControl("icon").getContentElement().removeClass("rotate"); + } + } + // Might have been destroyed already + if (this.getLayoutParent()) { + this.setEnabled(!isFetching); } - this.setEnabled(!isFetching); } } }); diff --git a/services/web/client/source/class/osparc/wrapper/WebSocket.js b/services/web/client/source/class/osparc/wrapper/WebSocket.js index 47ab23723a1..15d29077230 100644 --- a/services/web/client/source/class/osparc/wrapper/WebSocket.js +++ b/services/web/client/source/class/osparc/wrapper/WebSocket.js @@ -251,12 +251,7 @@ qx.Class.define("osparc.wrapper.WebSocket", { }, slotExists: function(name) { - for (let i = 0; i < this.__name.length; ++i) { - if (this.__name[i] === name) { - return true; - } - } - return false; + return this.__name && this.__name.includes(name); }, removeSlot: function(name) { diff --git a/tests/e2e/portal/Kember.js b/tests/e2e/portal/Kember.js new file mode 100644 index 00000000000..dbdd71bc801 --- /dev/null +++ b/tests/e2e/portal/Kember.js @@ -0,0 +1,85 @@ +// node kember.js [url_prefix] [template_uuid] [--demo] + +const tutorialBase = require('../tutorials/tutorialBase'); +const auto = require('../utils/auto'); +const utils = require('../utils/utils'); + +const args = process.argv.slice(2); +const { + urlPrefix, + templateUuid, + enableDemoMode +} = utils.parseCommandLineArgumentsTemplate(args); + +const anonURL = urlPrefix + templateUuid; +const screenshotPrefix = "Kember_"; + + +async function runTutorial () { + const tutorial = new tutorialBase.TutorialBase(anonURL, screenshotPrefix, null, null, null, enableDemoMode); + + tutorial.startScreenshooter(); + const page = await tutorial.beforeScript(); + const studyData = await tutorial.openStudyLink(); + const studyId = studyData["data"]["uuid"]; + console.log("Study ID:", studyId); + + // Some time for loading the workbench + await tutorial.waitFor(10000); + await utils.takeScreenshot(page, screenshotPrefix + 'workbench_loaded'); + + await tutorial.runPipeline(studyId, 120000); + await utils.takeScreenshot(page, screenshotPrefix + 'pipeline_run'); + + await tutorial.openNodeFiles(0); + const outFiles = [ + "logs.zip", + "outputController.dat" + ]; + await tutorial.checkResults(outFiles.length); + + + // open kember viewer + auto.openNode(page, 1); + + await tutorial.waitFor(2000); + await utils.takeScreenshot(page, screenshotPrefix + 'iFrame0'); + const iframeHandles = await page.$$("iframe"); + // expected two iframes = loading + raw-graph + const frame = await iframeHandles[1].contentFrame(); + + // - restart kernel: click restart and accept + const restartSelector = "#run_int > button:nth-child(3)"; + await frame.waitForSelector(restartSelector); + await frame.click(restartSelector); + await tutorial.waitFor(2000); + await utils.takeScreenshot(page, screenshotPrefix + 'restart_pressed'); + const acceptSelector = "body > div.modal.fade.in > div > div > div.modal-footer > button.btn.btn-default.btn-sm.btn-danger"; + await frame.waitForSelector(acceptSelector); + await frame.click(acceptSelector); + await tutorial.waitFor(2000); + await utils.takeScreenshot(page, screenshotPrefix + 'restart_accept'); + + await tutorial.waitFor(8000); + await utils.takeScreenshot(page, screenshotPrefix + 'notebook_run'); + + // - check output + await tutorial.openNodeFiles(0); + const outFiles2 = [ + "Hear_Rate.csv", + "notebooks.zip", + "Parasympathetic_Cell_Activity.csv", + "Table_Data.csv" + ]; + await tutorial.checkResults(outFiles2.length); + + await tutorial.logOut(); + tutorial.stopScreenshooter(); + await tutorial.close(); +} + +runTutorial() + .catch(error => { + console.log('Puppeteer error: ' + error); + process.exit(1); + }); diff --git a/tests/e2e/tutorials/isolve.js b/tests/e2e/tutorials/isolve.js new file mode 100644 index 00000000000..aadcf132040 --- /dev/null +++ b/tests/e2e/tutorials/isolve.js @@ -0,0 +1,65 @@ +// node isolve.js [url] [user] [password] [--demo] + +// https://itisfoundation.github.io/osparc-manual-z43/#/Tutorials/GeneralTutorial + +const utils = require('../utils/utils'); +const tutorialBase = require('./tutorialBase'); + +const args = process.argv.slice(2); +const { + url, + user, + pass, + newUser, + enableDemoMode +} = utils.parseCommandLineArguments(args) + +const templateName = "isolve-gpu"; + +async function runTutorial() { + const tutorial = new tutorialBase.TutorialBase(url, templateName, user, pass, newUser, enableDemoMode); + + try { + tutorial.startScreenshooter(); + await tutorial.start(); + const studyData = await tutorial.openService(1000); + const studyId = studyData["data"]["uuid"]; + console.log("Study ID:", studyId); + + // Some time for loading the workbench + await tutorial.waitFor(5000); + + await tutorial.runPipeline(studyId, 20000); + console.log('Checking isolve results:'); + await tutorial.openNodeFiles(1); + const outFiles = [ + "logs.zip", + "output.h5", + "log.tgz" + ]; + await tutorial.checkResults(outFiles.length); + + await tutorial.toDashboard(); + + await tutorial.removeStudy(studyId); + } + catch(err) { + tutorial.setTutorialFailed(true); + console.log('Tutorial error: ' + err); + } + finally { + await tutorial.logOut(); + tutorial.stopScreenshooter(); + await tutorial.close(); + } + + if (tutorial.getTutorialFailed()) { + throw "Tutorial Failed"; + } +} + +runTutorial() + .catch(error => { + console.log('Puppeteer error: ' + error); + process.exit(1); + });