From 63978e226bc90464cd7b1c2ff3e6df32fa847afe Mon Sep 17 00:00:00 2001 From: Kazuhito Yokoi Date: Tue, 14 Jan 2020 15:42:56 +0900 Subject: [PATCH 01/10] Move node files for UI testing to v1.0 directory structures --- .../core/{core => common}/20-inject_page.js | 0 .../21-debug_page.js} | 0 .../10-function_page.js} | 0 .../{logic => function}/15-change_page.js | 0 .../core/{logic => function}/16-range_page.js | 0 .../{core => function}/80-template_page.js | 0 .../{io => network}/10-mqttconfig_page.js | 0 .../core/{io => network}/10-mqttin_page.js | 0 .../core/{io => network}/10-mqttout_page.js | 0 .../core/{io => network}/21-httpin_page.js | 0 .../{io => network}/21-httprequest_page.js | 0 .../{io => network}/21-httpresponse_page.js | 0 .../{50-filein_page.js => 10-filein_page.js} | 0 .../pageobjects/nodes/nodefactory_page.js | 50 +++++++++---------- .../specs/scenario/cookbook_mqtt_uispec.js | 2 +- 15 files changed, 26 insertions(+), 26 deletions(-) rename test/editor/pageobjects/nodes/core/{core => common}/20-inject_page.js (100%) rename test/editor/pageobjects/nodes/core/{core/58-debug_page.js => common/21-debug_page.js} (100%) rename test/editor/pageobjects/nodes/core/{core/80-function_page.js => function/10-function_page.js} (100%) rename test/editor/pageobjects/nodes/core/{logic => function}/15-change_page.js (100%) rename test/editor/pageobjects/nodes/core/{logic => function}/16-range_page.js (100%) rename test/editor/pageobjects/nodes/core/{core => function}/80-template_page.js (100%) rename test/editor/pageobjects/nodes/core/{io => network}/10-mqttconfig_page.js (100%) rename test/editor/pageobjects/nodes/core/{io => network}/10-mqttin_page.js (100%) rename test/editor/pageobjects/nodes/core/{io => network}/10-mqttout_page.js (100%) rename test/editor/pageobjects/nodes/core/{io => network}/21-httpin_page.js (100%) rename test/editor/pageobjects/nodes/core/{io => network}/21-httprequest_page.js (100%) rename test/editor/pageobjects/nodes/core/{io => network}/21-httpresponse_page.js (100%) rename test/editor/pageobjects/nodes/core/storage/{50-filein_page.js => 10-filein_page.js} (100%) diff --git a/test/editor/pageobjects/nodes/core/core/20-inject_page.js b/test/editor/pageobjects/nodes/core/common/20-inject_page.js similarity index 100% rename from test/editor/pageobjects/nodes/core/core/20-inject_page.js rename to test/editor/pageobjects/nodes/core/common/20-inject_page.js diff --git a/test/editor/pageobjects/nodes/core/core/58-debug_page.js b/test/editor/pageobjects/nodes/core/common/21-debug_page.js similarity index 100% rename from test/editor/pageobjects/nodes/core/core/58-debug_page.js rename to test/editor/pageobjects/nodes/core/common/21-debug_page.js diff --git a/test/editor/pageobjects/nodes/core/core/80-function_page.js b/test/editor/pageobjects/nodes/core/function/10-function_page.js similarity index 100% rename from test/editor/pageobjects/nodes/core/core/80-function_page.js rename to test/editor/pageobjects/nodes/core/function/10-function_page.js diff --git a/test/editor/pageobjects/nodes/core/logic/15-change_page.js b/test/editor/pageobjects/nodes/core/function/15-change_page.js similarity index 100% rename from test/editor/pageobjects/nodes/core/logic/15-change_page.js rename to test/editor/pageobjects/nodes/core/function/15-change_page.js diff --git a/test/editor/pageobjects/nodes/core/logic/16-range_page.js b/test/editor/pageobjects/nodes/core/function/16-range_page.js similarity index 100% rename from test/editor/pageobjects/nodes/core/logic/16-range_page.js rename to test/editor/pageobjects/nodes/core/function/16-range_page.js diff --git a/test/editor/pageobjects/nodes/core/core/80-template_page.js b/test/editor/pageobjects/nodes/core/function/80-template_page.js similarity index 100% rename from test/editor/pageobjects/nodes/core/core/80-template_page.js rename to test/editor/pageobjects/nodes/core/function/80-template_page.js diff --git a/test/editor/pageobjects/nodes/core/io/10-mqttconfig_page.js b/test/editor/pageobjects/nodes/core/network/10-mqttconfig_page.js similarity index 100% rename from test/editor/pageobjects/nodes/core/io/10-mqttconfig_page.js rename to test/editor/pageobjects/nodes/core/network/10-mqttconfig_page.js diff --git a/test/editor/pageobjects/nodes/core/io/10-mqttin_page.js b/test/editor/pageobjects/nodes/core/network/10-mqttin_page.js similarity index 100% rename from test/editor/pageobjects/nodes/core/io/10-mqttin_page.js rename to test/editor/pageobjects/nodes/core/network/10-mqttin_page.js diff --git a/test/editor/pageobjects/nodes/core/io/10-mqttout_page.js b/test/editor/pageobjects/nodes/core/network/10-mqttout_page.js similarity index 100% rename from test/editor/pageobjects/nodes/core/io/10-mqttout_page.js rename to test/editor/pageobjects/nodes/core/network/10-mqttout_page.js diff --git a/test/editor/pageobjects/nodes/core/io/21-httpin_page.js b/test/editor/pageobjects/nodes/core/network/21-httpin_page.js similarity index 100% rename from test/editor/pageobjects/nodes/core/io/21-httpin_page.js rename to test/editor/pageobjects/nodes/core/network/21-httpin_page.js diff --git a/test/editor/pageobjects/nodes/core/io/21-httprequest_page.js b/test/editor/pageobjects/nodes/core/network/21-httprequest_page.js similarity index 100% rename from test/editor/pageobjects/nodes/core/io/21-httprequest_page.js rename to test/editor/pageobjects/nodes/core/network/21-httprequest_page.js diff --git a/test/editor/pageobjects/nodes/core/io/21-httpresponse_page.js b/test/editor/pageobjects/nodes/core/network/21-httpresponse_page.js similarity index 100% rename from test/editor/pageobjects/nodes/core/io/21-httpresponse_page.js rename to test/editor/pageobjects/nodes/core/network/21-httpresponse_page.js diff --git a/test/editor/pageobjects/nodes/core/storage/50-filein_page.js b/test/editor/pageobjects/nodes/core/storage/10-filein_page.js similarity index 100% rename from test/editor/pageobjects/nodes/core/storage/50-filein_page.js rename to test/editor/pageobjects/nodes/core/storage/10-filein_page.js diff --git a/test/editor/pageobjects/nodes/nodefactory_page.js b/test/editor/pageobjects/nodes/nodefactory_page.js index c518d89ff..744c1570d 100644 --- a/test/editor/pageobjects/nodes/nodefactory_page.js +++ b/test/editor/pageobjects/nodes/nodefactory_page.js @@ -14,46 +14,46 @@ * limitations under the License. **/ -var injectNode = require('./core/core/20-inject_page'); -var debugNode = require('./core/core/58-debug_page'); -var templateNode = require('./core/core/80-template_page'); -var functionNode = require('./core/core/80-function_page'); -var mqttInNode = require('./core/io/10-mqttin_page'); -var mqttOutNode = require('./core/io/10-mqttout_page'); -var httpInNode = require('./core/io/21-httpin_page'); -var httpResponseNode = require('./core/io/21-httpresponse_page'); -var changeNode = require('./core/logic/15-change_page'); -var rangeNode = require('./core/logic/16-range_page'); -var httpRequestNode = require('./core/io/21-httprequest_page'); +var injectNode = require('./core/common/20-inject_page'); +var debugNode = require('./core/common/21-debug_page'); +var functionNode = require('./core/function/10-function_page'); +var changeNode = require('./core/function/15-change_page'); +var rangeNode = require('./core/function/16-range_page'); +var templateNode = require('./core/function/80-template_page'); +var mqttInNode = require('./core/network/10-mqttin_page'); +var mqttOutNode = require('./core/network/10-mqttout_page'); +var httpInNode = require('./core/network/21-httpin_page'); +var httpResponseNode = require('./core/network/21-httpresponse_page'); +var httpRequestNode = require('./core/network/21-httprequest_page'); var htmlNode = require('./core/parsers/70-HTML_page'); var jsonNode = require('./core/parsers/70-JSON_page'); -var fileInNode = require('./core/storage/50-filein_page'); - +var fileInNode = require('./core/storage/10-filein_page'); var nodeCatalog = { - // input + // common "inject": injectNode, - "httpIn": httpInNode, - "mqttIn":mqttInNode, - // output "debug": debugNode, - "httpResponse": httpResponseNode, - "mqttOut": mqttOutNode, // function "function": functionNode, - "template": templateNode, "change": changeNode, "range": rangeNode, + "template": templateNode, + // network + "mqttIn": mqttInNode, + "mqttOut": mqttOutNode, + "httpIn": httpInNode, + "httpResponse": httpResponseNode, "httpRequest": httpRequestNode, + // parser "html": htmlNode, - "json":jsonNode, + "json": jsonNode, // storage - "fileIn": fileInNode, -} + "fileIn": fileInNode +}; function create(type, id) { - var node = nodeCatalog[type]; - return new node(id); + var Node = nodeCatalog[type]; + return new Node(id); } module.exports = { diff --git a/test/editor/specs/scenario/cookbook_mqtt_uispec.js b/test/editor/specs/scenario/cookbook_mqtt_uispec.js index ecfe8da7d..887d9735c 100644 --- a/test/editor/specs/scenario/cookbook_mqtt_uispec.js +++ b/test/editor/specs/scenario/cookbook_mqtt_uispec.js @@ -22,7 +22,7 @@ var helper = require("../../editor_helper"); var debugTab = require('../../pageobjects/editor/debugTab_page'); var workspace = require('../../pageobjects/editor/workspace_page'); var specUtil = require('../../pageobjects/util/spec_util_page'); -var mqttConfig = require('../../pageobjects/nodes/core/io/10-mqttconfig_page.js'); +var mqttConfig = require('../../pageobjects/nodes/core/network/10-mqttconfig_page.js'); var httpNodeRoot = "/api"; From faf46e4447508715a481c029c693266972770e10 Mon Sep 17 00:00:00 2001 From: Kazuhito Yokoi Date: Tue, 14 Jan 2020 16:37:43 +0900 Subject: [PATCH 02/10] Improve node files for UI testing --- .../nodes/core/function/10-function_page.js | 7 +++---- .../nodes/core/function/15-change_page.js | 16 ++++++++-------- .../nodes/core/function/80-template_page.js | 12 +++++------- .../nodes/core/network/10-mqttconfig_page.js | 4 ++-- test/editor/pageobjects/nodes/node_page.js | 4 ++-- test/editor/wdio.conf.js | 14 +++++++------- 6 files changed, 27 insertions(+), 30 deletions(-) diff --git a/test/editor/pageobjects/nodes/core/function/10-function_page.js b/test/editor/pageobjects/nodes/core/function/10-function_page.js index f39aba912..c1bb80a80 100644 --- a/test/editor/pageobjects/nodes/core/function/10-function_page.js +++ b/test/editor/pageobjects/nodes/core/function/10-function_page.js @@ -26,12 +26,11 @@ function functionNode(id) { util.inherits(functionNode, nodePage); -functionNode.prototype.setFunction = function(func) { +functionNode.prototype.setFunction = function (func) { browser.clickWithWait('#node-input-func-editor'); browser.keys(keyPage.selectAll()); - for (var i = 0; i < func.length; i++) { - browser.keys([func.charAt(i)]); - } + browser.keys(['Delete']); + browser.keys(func); // Delete the unnecessary code that ace editor does the autocompletion. browser.keys(keyPage.selectToEnd()); browser.keys(['Delete']); diff --git a/test/editor/pageobjects/nodes/core/function/15-change_page.js b/test/editor/pageobjects/nodes/core/function/15-change_page.js index 82441c9bc..8e72afe38 100644 --- a/test/editor/pageobjects/nodes/core/function/15-change_page.js +++ b/test/editor/pageobjects/nodes/core/function/15-change_page.js @@ -49,8 +49,8 @@ function setT(t, index) { } // It is better to create a function whose input value is the object type in the future, -changeNode.prototype.ruleSet = function(p, pt, to, tot, index) { - index = index ? index : 1; +changeNode.prototype.ruleSet = function (p, pt, to, tot, index) { + index = index || 1; setT("set", index); if (pt) { browser.clickWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/div/button[1]'); @@ -68,23 +68,23 @@ changeNode.prototype.ruleSet = function(p, pt, to, tot, index) { browser.clickWithWait(totXPath); } if (to) { - browser.setValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[2]/div[2]/div/input' , to); + browser.setValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[2]/div[2]/div/input', to); } } -changeNode.prototype.ruleDelete = function(index) { - index = index ? index : 1; +changeNode.prototype.ruleDelete = function (index) { + index = index || 1; setT("delete", index); } -changeNode.prototype.ruleMove = function(p, to, index) { - index = index ? index : 1; +changeNode.prototype.ruleMove = function (p, to, index) { + index = index || 1; setT("move", index); browser.setValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/div/div/input', p); browser.setValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[4]/div[2]/div/input', to); } -changeNode.prototype.addRule = function() { +changeNode.prototype.addRule = function () { browser.clickWithWait('//*[@id="dialog-form"]/div[3]/div/a'); } diff --git a/test/editor/pageobjects/nodes/core/function/80-template_page.js b/test/editor/pageobjects/nodes/core/function/80-template_page.js index 68cf46acf..bf1786ba2 100644 --- a/test/editor/pageobjects/nodes/core/function/80-template_page.js +++ b/test/editor/pageobjects/nodes/core/function/80-template_page.js @@ -26,21 +26,19 @@ function templateNode(id) { util.inherits(templateNode, nodePage); -templateNode.prototype.setSyntax = function(syntax) { +templateNode.prototype.setSyntax = function (syntax) { browser.selectWithWait('#node-input-syntax', syntax); } -templateNode.prototype.setFormat = function(format) { +templateNode.prototype.setFormat = function (format) { browser.selectWithWait('#node-input-format', format); } -templateNode.prototype.setTemplate = function(template) { +templateNode.prototype.setTemplate = function (template) { browser.clickWithWait('#node-input-template-editor'); browser.keys(keyPage.selectAll()); - // Need to add a character one by one since some words such as 'Control' are treated as a special word. - for (var i = 0; i < template.length; i++) { - browser.keys([template.charAt(i)]); - } + browser.keys(['Delete']); + browser.keys(template); browser.keys(keyPage.selectToEnd()); browser.keys(['Delete']); // Need to wait until ace editor correctly checks the syntax. diff --git a/test/editor/pageobjects/nodes/core/network/10-mqttconfig_page.js b/test/editor/pageobjects/nodes/core/network/10-mqttconfig_page.js index 3266a1bd3..c7cdc90c5 100644 --- a/test/editor/pageobjects/nodes/core/network/10-mqttconfig_page.js +++ b/test/editor/pageobjects/nodes/core/network/10-mqttconfig_page.js @@ -23,14 +23,14 @@ function setServer(broker, port) { function clickOk() { browser.clickWithWait('#node-config-dialog-ok'); // Wait until an config dialog closes. - browser.waitForVisible('#node-config-dialog-ok', 4000, true); + browser.waitForVisible('#node-config-dialog-ok', 10000, true); } function edit() { browser.waitForVisible('#node-input-lookup-broker'); browser.click('#node-input-lookup-broker'); // Wait until a config dialog opens. - browser.waitForVisible('#node-config-dialog-ok', 4000); + browser.waitForVisible('#node-config-dialog-ok', 10000); } module.exports = { diff --git a/test/editor/pageobjects/nodes/node_page.js b/test/editor/pageobjects/nodes/node_page.js index 5234362ae..123c1cc9d 100644 --- a/test/editor/pageobjects/nodes/node_page.js +++ b/test/editor/pageobjects/nodes/node_page.js @@ -22,13 +22,13 @@ Node.prototype.edit = function() { browser.clickWithWait(this.id); browser.clickWithWait(this.id); // Wait until an edit dialog opens. - browser.waitForVisible('#node-dialog-ok', 4000); + browser.waitForVisible('#node-dialog-ok', 10000); } Node.prototype.clickOk = function() { browser.clickWithWait('#node-dialog-ok'); // Wait untile an edit dialog closes. - browser.waitForVisible('#node-dialog-ok', 4000, true); + browser.waitForVisible('#node-dialog-ok', 10000, true); browser.pause(50); } diff --git a/test/editor/wdio.conf.js b/test/editor/wdio.conf.js index 26d30570f..7bbfcbe24 100644 --- a/test/editor/wdio.conf.js +++ b/test/editor/wdio.conf.js @@ -15,7 +15,7 @@ **/ exports.config = { - + // // ================== // Specify Test Files @@ -150,12 +150,12 @@ exports.config = { // The only one supported by default is 'dot' // see also: http://webdriver.io/guide/reporters/dot.html reporters: ['spec'], - + // // Options to be passed to Mocha. // See the full list at http://mochajs.org/ mochaOpts: { - timeout: 60000, + timeout: 100000, ui: 'bdd' }, // @@ -197,7 +197,7 @@ exports.config = { */ // beforeCommand: function (commandName, args) { // }, - + /** * Hook that gets executed before the suite starts * @param {Object} suite suite details @@ -217,13 +217,13 @@ exports.config = { // beforeHook: function () { // }, /** - * Hook that gets executed _after_ a hook within the suite starts (e.g. runs after calling + * Hook that gets executed _after_ a hook within the suite ends (e.g. runs after calling * afterEach in Mocha) */ // afterHook: function () { // }, /** - * Function to be executed after a test (in Mocha/Jasmine) or a step (in Cucumber) starts. + * Function to be executed after a test (in Mocha/Jasmine) or a step (in Cucumber) ends. * @param {Object} test test details */ // afterTest: function (test) { @@ -234,7 +234,7 @@ exports.config = { */ // afterSuite: function (suite) { // }, - + /** * Runs after a WebdriverIO command gets executed * @param {String} commandName hook command name From 8801ace24721f559ca9e1f0eb608dca55c28432c Mon Sep 17 00:00:00 2001 From: Kazuhito Yokoi Date: Tue, 14 Jan 2020 16:56:39 +0900 Subject: [PATCH 03/10] Remain .payload in debug node property --- test/editor/pageobjects/nodes/core/common/21-debug_page.js | 5 +---- test/editor/specs/scenario/cookbook_uispec.js | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/test/editor/pageobjects/nodes/core/common/21-debug_page.js b/test/editor/pageobjects/nodes/core/common/21-debug_page.js index 52cb60f44..602d4d542 100644 --- a/test/editor/pageobjects/nodes/core/common/21-debug_page.js +++ b/test/editor/pageobjects/nodes/core/common/21-debug_page.js @@ -26,16 +26,13 @@ function debugNode(id) { util.inherits(debugNode, nodePage); -debugNode.prototype.setOutput = function(complete) { +debugNode.prototype.setOutput = function (complete) { // Open a payload type list. browser.clickWithWait('//*[contains(@class, "red-ui-typedInput-container")]/button'); if (complete !== 'true') { // Select the "msg" type. browser.clickWithWait('//div[contains(@class, "red-ui-typedInput-options")][1]/a[1]'); // Input the path in msg. - browser.clickWithWait('//*[contains(@class, "red-ui-typedInput-input")]/input'); - browser.keys(keyPage.selectAll()); - browser.keys(['Delete']); browser.setValue('//*[contains(@class, "red-ui-typedInput-input")]/input', complete); } else { // Select the "complete msg object" type. diff --git a/test/editor/specs/scenario/cookbook_uispec.js b/test/editor/specs/scenario/cookbook_uispec.js index 8619ddb0d..6e16ca8a7 100644 --- a/test/editor/specs/scenario/cookbook_uispec.js +++ b/test/editor/specs/scenario/cookbook_uispec.js @@ -331,7 +331,7 @@ describe('cookbook', function() { httpRequetNode.clickOk(); debugNode.edit(); - debugNode.setOutput("payload.title"); + debugNode.setOutput(".title"); debugNode.clickOk(); injectNode.connect(changeNodeSetPost); From 3f72eb51a05ed347431e5a2d2db0356c2701df2f Mon Sep 17 00:00:00 2001 From: Kazuhito Yokoi Date: Tue, 14 Jan 2020 17:18:46 +0900 Subject: [PATCH 04/10] Fix shortcut key handling --- test/editor/pageobjects/util/key_page.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/test/editor/pageobjects/util/key_page.js b/test/editor/pageobjects/util/key_page.js index 9a8a867b4..509af9e22 100644 --- a/test/editor/pageobjects/util/key_page.js +++ b/test/editor/pageobjects/util/key_page.js @@ -17,21 +17,20 @@ var os = require("os"); var shortCutKeyMap = { - "selectAll": ['Control', 'a', 'Control'], + "selectAll": ['Control', 'a', 'a', 'Control'], "selectToEnd": ['Control', 'Shift', 'End', 'Shift', 'Control'], }; var shortCutKeyMapForMac = { - "selectAll": ['Command', 'a', 'Command'], + "selectAll": ['Command', 'a', 'a', 'Command'], "selectToEnd": ['Command', 'Shift', 'ArrowDown', 'Shift', 'Command'], }; function getShortCutKey(type) { - if (os.type() === "Darwin") { + if (os.type() === 'Darwin') { return shortCutKeyMapForMac[type]; - } else { - return shortCutKeyMap[type]; } + return shortCutKeyMap[type]; } function selectAll() { From 7640bc029c958dacb4067c0e14f50e908bfcc64c Mon Sep 17 00:00:00 2001 From: Kazuhito Yokoi Date: Tue, 14 Jan 2020 17:24:16 +0900 Subject: [PATCH 05/10] Add handling to remove unused file and directories in UI testing --- test/editor/editor_helper.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/editor/editor_helper.js b/test/editor/editor_helper.js index 81e3a54f5..73177c2ca 100644 --- a/test/editor/editor_helper.js +++ b/test/editor/editor_helper.js @@ -57,6 +57,9 @@ function cleanup(flowFile) { deleteFile(homeDir + "/." + flowFile + ".backup"); deleteFile(homeDir + "/" + credentialFile); deleteFile(homeDir + "/." + credentialFile + ".backup"); + deleteFile(homeDir + "/package.json"); + deleteFile(homeDir + "/lib/flows"); + deleteFile(homeDir + "/lib"); } function deleteFile(flowFile) { @@ -66,7 +69,7 @@ function deleteFile(flowFile) { fs.unlinkSync(flowFile); } } catch (e) {} -}; +} module.exports = { startServer: function() { @@ -104,7 +107,7 @@ module.exports = { }); }); browser.url(url); - browser.waitForExist(".red-ui-palette-node[data-palette-type='inject']") + browser.waitForExist(".red-ui-palette-node[data-palette-type='inject']"); } catch (err) { console.log(err); throw err; From ccc98370eb804b7242c5e012eceb52c4d0d2313e Mon Sep 17 00:00:00 2001 From: Kazuhito Yokoi Date: Tue, 14 Jan 2020 17:44:56 +0900 Subject: [PATCH 06/10] Use ephemeral port number for MQTT broker --- .../specs/scenario/cookbook_mqtt_uispec.js | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/test/editor/specs/scenario/cookbook_mqtt_uispec.js b/test/editor/specs/scenario/cookbook_mqtt_uispec.js index 887d9735c..655074750 100644 --- a/test/editor/specs/scenario/cookbook_mqtt_uispec.js +++ b/test/editor/specs/scenario/cookbook_mqtt_uispec.js @@ -29,35 +29,38 @@ var httpNodeRoot = "/api"; var mqttServer; var mosca = require('mosca'); var moscaSettings = { - port: 1883, + port: parseInt(Math.random() * 16383 + 49152), persistence: { // Needs for retaining messages. factory: mosca.persistence.Memory } }; - // https://cookbook.nodered.org/ -describe('cookbook', function() { - beforeEach(function() { +describe('cookbook', function () { + beforeEach(function () { workspace.init(); }); - before(function() { - browser.call(function() { - return new Promise(function(resolve, reject) { - mqttServer = new mosca.Server(moscaSettings, function() { - resolve(); + before(function () { + browser.call(function () { + return new Promise(function (resolve, reject) { + mqttServer = new mosca.Server(moscaSettings, function (err) { + if (err) { + reject(err); + } else { + resolve(); + } }); }); }); helper.startServer(); }); - after(function() { - browser.call(function() { - return new Promise(function(resolve, reject) { - mqttServer.close(function() { + after(function () { + browser.call(function () { + return new Promise(function (resolve, reject) { + mqttServer.close(function () { resolve(); }); }); @@ -65,20 +68,20 @@ describe('cookbook', function() { helper.stopServer(); }); - describe('MQTT', function() { - it('Add an MQTT broker to prepare for UI test', function() { + describe('MQTT', function () { + it('Add an MQTT broker to prepare for UI test', function () { var mqttOutNode = workspace.addNode("mqttOut"); mqttOutNode.edit(); mqttConfig.edit(); - mqttConfig.setServer("localhost"); + mqttConfig.setServer("localhost", moscaSettings.port); mqttConfig.clickOk(); mqttOutNode.clickOk(); workspace.deploy(); }); - it('Connect to an MQTT broker', function() { + it('Connect to an MQTT broker', function () { var injectNode = workspace.addNode("inject"); var mqttOutNode = workspace.addNode("mqttOut"); @@ -112,7 +115,7 @@ describe('cookbook', function() { // skip this case since it is same as other cases. it.skip('Publish messages to a topic'); - it('Set the topic of a published message', function() { + it('Set the topic of a published message', function () { var injectNode = workspace.addNode("inject"); var mqttOutNode = workspace.addNode("mqttOut"); @@ -144,7 +147,7 @@ describe('cookbook', function() { debugTab.getMessage().should.eql('"22"'); }); - it('Publish a retained message to a topic', function() { + it('Publish a retained message to a topic', function () { var injectNode = workspace.addNode("inject"); var mqttOutNode = workspace.addNode("mqttOut"); @@ -182,7 +185,7 @@ describe('cookbook', function() { // skip this case since it is same as other cases. it.skip('Subscribe to a topic'); - it('Receive a parsed JSON message', function() { + it('Receive a parsed JSON message', function () { var injectNode = workspace.addNode("inject"); var mqttOutNode = workspace.addNode("mqttOut"); From 530bf22bd5fe92324d2c69b3df2641d9aa3b2ad5 Mon Sep 17 00:00:00 2001 From: Kazuhito Yokoi Date: Tue, 14 Jan 2020 18:02:27 +0900 Subject: [PATCH 07/10] Use palette search when selecting nodes --- test/editor/pageobjects/editor/workspace_page.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/editor/pageobjects/editor/workspace_page.js b/test/editor/pageobjects/editor/workspace_page.js index 560a0992f..653d32165 100644 --- a/test/editor/pageobjects/editor/workspace_page.js +++ b/test/editor/pageobjects/editor/workspace_page.js @@ -44,6 +44,9 @@ function addNode(type, x, y) { previousY = previousY + flowLayout.heightInterval; } } + browser.waitForVisible('#red-ui-palette-search'); + browser.setValue('//*[@id="red-ui-palette-search"]/div/input', type.replace(/([A-Z])/g,' $1').toLowerCase()); + browser.pause(300); browser.waitForVisible(palette.getId(type)); browser.moveToObject(palette.getId(type)); browser.buttonDown(); From 214d788029046f4c1f13f1291f4f0c1fd41eb896 Mon Sep 17 00:00:00 2001 From: Kazuhito Yokoi Date: Tue, 14 Jan 2020 19:24:50 +0900 Subject: [PATCH 08/10] Use enter key to open node property instead of double click --- test/editor/pageobjects/nodes/node_page.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/test/editor/pageobjects/nodes/node_page.js b/test/editor/pageobjects/nodes/node_page.js index 123c1cc9d..5250250e7 100644 --- a/test/editor/pageobjects/nodes/node_page.js +++ b/test/editor/pageobjects/nodes/node_page.js @@ -18,21 +18,24 @@ function Node(id) { this.id = '//*[@id="' + id + '"]'; } -Node.prototype.edit = function() { - browser.clickWithWait(this.id); - browser.clickWithWait(this.id); +Node.prototype.edit = function () { + browser.waitForVisible(this.id); + browser.moveToObject(this.id); + browser.buttonDown(); + browser.buttonUp(); + browser.keys(['Enter']); // Wait until an edit dialog opens. browser.waitForVisible('#node-dialog-ok', 10000); } -Node.prototype.clickOk = function() { +Node.prototype.clickOk = function () { browser.clickWithWait('#node-dialog-ok'); // Wait untile an edit dialog closes. browser.waitForVisible('#node-dialog-ok', 10000, true); browser.pause(50); } -Node.prototype.connect = function(targetNode) { +Node.prototype.connect = function (targetNode) { var outputPort = this.id + '/*[@class="red-ui-flow-port-output"]'; var inputPort = targetNode.id + '/*[@class="red-ui-flow-port-input"]'; browser.dragAndDrop(outputPort, inputPort) From 0f8af4ba1c0bf9bcf8f346820ddecddb02238b39 Mon Sep 17 00:00:00 2001 From: Kazuhito Yokoi Date: Tue, 14 Jan 2020 20:36:10 +0900 Subject: [PATCH 09/10] Use boolean value as flag instead of string value --- Gruntfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gruntfile.js b/Gruntfile.js index a6e896b9e..67739afe2 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -28,7 +28,7 @@ module.exports = function(grunt) { var nonHeadless = grunt.option('non-headless'); if (nonHeadless) { - process.env.NODE_RED_NON_HEADLESS = 'true'; + process.env.NODE_RED_NON_HEADLESS = true; } grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), From 44a07c74fd19f3de72e451c4b751ba88b07dc77c Mon Sep 17 00:00:00 2001 From: Kazuhito Yokoi Date: Wed, 15 Jan 2020 10:42:59 +0900 Subject: [PATCH 10/10] Click tab instead of workspace --- .../pageobjects/editor/workspace_page.js | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/test/editor/pageobjects/editor/workspace_page.js b/test/editor/pageobjects/editor/workspace_page.js index 653d32165..f3bbf1aa2 100644 --- a/test/editor/pageobjects/editor/workspace_page.js +++ b/test/editor/pageobjects/editor/workspace_page.js @@ -15,18 +15,15 @@ **/ var when = require("when"); - var events = require("nr-test-utils").require("@node-red/runtime/lib/events.js"); - var palette = require("./palette_page"); var nodeFactory = require("../nodes/nodefactory_page"); - +var keyPage = require("../util/key_page"); var flowLayout = { flowRightEnd : 600, widthInterval : 300, heightInterval : 80 }; - var previousX = -flowLayout.widthInterval; var previousY = 0; @@ -60,13 +57,10 @@ function addNode(type, x, y) { } function deleteAllNodes() { - browser.waitForVisible('.red-ui-workspace-chart-event-layer'); - try { - browser.click('.red-ui-workspace-chart-event-layer'); - } catch (e) { - console.log(e); - } - browser.keys(['Control', 'a', 'a', 'Control']); // call twice to release the keys. + browser.waitForVisible('//*[contains(@class, "active")]/a[@class="red-ui-tab-label"]'); + browser.click('//*[contains(@class, "active")]/a[@class="red-ui-tab-label"]'); + browser.pause(1000); + browser.keys(keyPage.selectAll()); browser.keys(['Delete']); } @@ -81,7 +75,7 @@ function deploy() { browser.clickWithWait('#red-ui-header-button-deploy'); }); }); - browser.waitForText('#red-ui-header-button-deploy', 2000); + browser.waitForText('#red-ui-header-button-deploy', 10000); // Need additional wait until buttons becomes clickable. browser.pause(50); }