diff --git a/test/editor/editor_helper.js b/test/editor/editor_helper.js index 733df8a87..281988484 100644 --- a/test/editor/editor_helper.js +++ b/test/editor/editor_helper.js @@ -14,67 +14,125 @@ * limitations under the License. **/ -var RED = require("../../red/red.js"); - var when = require("when"); var http = require('http'); var express = require("express"); var fs = require('fs-extra'); +var path = require('path'); var app = express(); +var RED = require("../../red/red.js"); + +var utilPage = require("./pageobjects/util/util_page"); + var server; var homeDir = './test/resources/home'; var address = '127.0.0.1'; var listenPort = 0; // use ephemeral port var url; +/* + * Set false when you need a flow to reproduce the failed test case. + * The flow file is under "homeDir" defined above. + */ +var isDeleteFlow = true; -function cleanup() { - var flowsFile = homeDir + '/flows_'+require('os').hostname()+'.json'; +function getFlowFilename() { + var orig = Error.prepareStackTrace; + var err = new Error(); + Error.prepareStackTrace = function (err, stack) { + return stack; + }; + // Two level higher caller is the actual caller (e.g. a caller of startServer). + var filepath = err.stack[2].getFileName(); + var filename = path.basename(filepath, ".js"); + Error.prepareStackTrace = orig; + + var flowFile = 'flows_' + filename + '.json'; + return flowFile; +} + +function cleanup(flowFile) { + deleteFile(homeDir+"/"+flowFile); + deleteFile(homeDir+"/."+flowFile+".backup"); +} + +function deleteFile(flowFile) { try { - fs.statSync(flowsFile); - fs.unlinkSync(flowsFile); - } catch (err) { - } + fs.statSync(flowFile); + if (isDeleteFlow) { + fs.unlinkSync(flowFile); + } + } catch (e) {} }; module.exports = { - startServer: function(done) { - cleanup(); - app.use("/",express.static("public")); - server = http.createServer(app); - var settings = { - httpAdminRoot: "/", - httpNodeRoot: "/api", - userDir: homeDir, - functionGlobalContext: { }, // enables global context - SKIP_BUILD_CHECK: true, - logging: {console: {level:'off'}} - }; - RED.init(server, settings); - app.use(settings.httpAdminRoot,RED.httpAdmin); - app.use(settings.httpNodeRoot,RED.httpNode); - server.listen(listenPort, address); - server.on('listening', function() { - var port = server.address().port; - url = 'http://' + address + ':' + port; - }); - RED.start().then(function() { - done(); - }); + startServer: function() { + try{ + utilPage.init(); + + // Name a flow file including caller filename so that multiple Node-RED servers can run simultaneously. + // Call this method here because retrieving the caller filename by call stack. + var flowFilename = getFlowFilename(); + browser.windowHandleMaximize(); + browser.call(function () { + // return when.promise(function(resolve, reject) { + return new Promise(function(resolve, reject) { + cleanup(flowFilename); + app.use("/",express.static("public")); + server = http.createServer(app); + var settings = { + httpAdminRoot: "/", + httpNodeRoot: "/api", + userDir: homeDir, + flowFile: flowFilename, + functionGlobalContext: { }, // enables global context + SKIP_BUILD_CHECK: true, + logging: {console: {level:'off'}} + }; + RED.init(server, settings); + app.use(settings.httpAdminRoot,RED.httpAdmin); + app.use(settings.httpNodeRoot,RED.httpNode); + server.listen(listenPort, address); + server.on('listening', function() { + var port = server.address().port; + url = 'http://' + address + ':' + port; + }); + RED.start().then(function() { + resolve(); + }); + }); + }); + browser.url(url); + browser.waitForExist('#palette_node_inject'); + } catch (err) { + console.log(err); + throw err; + } }, stopServer: function(done) { - if (server) { - try { - RED.stop().then(function() { - server.close(done); - cleanup(); - done(); + try { + // Call this method here because retrieving the caller filename by call stack. + var flowFilename = getFlowFilename(); + browser.call(function () { + browser.close(); // need to call this inside browser.call(). + return when.promise(function(resolve, reject) { + if (server) { + RED.stop().then(function() { + server.close(function() { + cleanup(flowFilename); + resolve(); + }); + }); + } else { + cleanup(flowFilename); + resolve(); + } }); - } catch(e) { - cleanup(); - done(); - } + }); + } catch (err) { + console.log(err); + throw err; } }, diff --git a/test/editor/pageobjects/nodes/core/core/20-inject_page.js b/test/editor/pageobjects/nodes/core/core/20-inject_page.js new file mode 100644 index 000000000..09aa8cca1 --- /dev/null +++ b/test/editor/pageobjects/nodes/core/core/20-inject_page.js @@ -0,0 +1,52 @@ +/** + * Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var util = require("util"); + +var nodePage = require("../../node_page"); + +function injectNode(id) { + nodePage.call(this, id); +} + +util.inherits(injectNode, nodePage); + +var payloadType = { + "flow": 1, + "global": 2, + "string": 3, + "num": 4, + "bool": 5, + "json": 6, + "bin": 7, + "date": 8, +}; + +injectNode.prototype.setPayload = function(type, value) { + // Open a payload type list. + browser.clickWithWait('//*[contains(@class, "red-ui-typedInput-container")]'); + // Select a payload type. + var payloadTypeXPath = '//*[@class="red-ui-typedInput-options"]/a[' + payloadType[type] + ']'; + browser.clickWithWait(payloadTypeXPath); + // Input a value. + browser.setValue('#node-input-payload', value); +} + +injectNode.prototype.setTopic = function(value) { + browser.setValue('#node-input-topic', value); +} + +module.exports = injectNode; diff --git a/test/editor/pageobjects/workspace/editWindow_page.js b/test/editor/pageobjects/nodes/core/core/58-debug_page.js similarity index 76% rename from test/editor/pageobjects/workspace/editWindow_page.js rename to test/editor/pageobjects/nodes/core/core/58-debug_page.js index 25ceecc8f..f87f29646 100644 --- a/test/editor/pageobjects/workspace/editWindow_page.js +++ b/test/editor/pageobjects/nodes/core/core/58-debug_page.js @@ -14,11 +14,14 @@ * limitations under the License. **/ -function clickOk() { - browser.click('#node-dialog-ok'); - browser.pause(300); +var util = require("util"); + +var nodePage = require("../../node_page"); + +function debugNode(id) { + nodePage.call(this, id); } -module.exports = { - clickOk: clickOk, -}; +util.inherits(debugNode, nodePage); + +module.exports = debugNode; diff --git a/test/editor/pageobjects/nodes/core/logic/15-change_page.js b/test/editor/pageobjects/nodes/core/logic/15-change_page.js new file mode 100644 index 000000000..aa8b8a73b --- /dev/null +++ b/test/editor/pageobjects/nodes/core/logic/15-change_page.js @@ -0,0 +1,53 @@ +/** + * Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var util = require("util"); + +var nodePage = require("../../node_page"); + +function changeNode(id) { + nodePage.call(this, id); +} + +util.inherits(changeNode, nodePage); + +function setT(rule, index) { + browser.selectByValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/select', rule); +} + +changeNode.prototype.ruleSet = function(to, index) { + index = index ? index : 1; + setT("set", index); + 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; + setT("delete", index); +} + +changeNode.prototype.ruleMove = function(p, to, index) { + 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() { + browser.clickWithWait('//*[@id="dialog-form"]/div[3]/div/a'); +} + +module.exports = changeNode; diff --git a/test/editor/pageobjects/nodes/core/logic/16-range_page.js b/test/editor/pageobjects/nodes/core/logic/16-range_page.js new file mode 100644 index 000000000..630abc86a --- /dev/null +++ b/test/editor/pageobjects/nodes/core/logic/16-range_page.js @@ -0,0 +1,38 @@ +/** + * Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var util = require("util"); + +var nodePage = require("../../node_page"); + +function rangeNode(id) { + nodePage.call(this, id); +} + +util.inherits(rangeNode, nodePage); + +rangeNode.prototype.setAction = function(value) { + browser.selectByValue('#node-input-action', value); +} + +rangeNode.prototype.setRange = function(minin, maxin, minout, maxout) { + browser.setValue('#node-input-minin', minin); + browser.setValue('#node-input-maxin', maxin); + browser.setValue('#node-input-minout', minout); + browser.setValue('#node-input-maxout', maxout); +} + +module.exports = rangeNode; diff --git a/test/editor/pageobjects/workspace/node_page.js b/test/editor/pageobjects/nodes/node_page.js similarity index 59% rename from test/editor/pageobjects/workspace/node_page.js rename to test/editor/pageobjects/nodes/node_page.js index 3fd5ba630..3937f15b7 100644 --- a/test/editor/pageobjects/workspace/node_page.js +++ b/test/editor/pageobjects/nodes/node_page.js @@ -14,29 +14,21 @@ * limitations under the License. **/ -var icons = { - // input - "inject": "icons/node-red/inject.png", - // output - "debug": "icons/node-red/debug.png", - // function - "change": "icons/node-red/swap.png", -}; - -function getIdWithIcon(icon) { - //*[name()="image" and @*="icons/node-red/inject.png"]/../.. - var id = browser.getAttribute('//*[name()="image" and @*="' + icon + '"]/../..', 'id'); - return id; -} - -function Node(type) { - this.id = '//*[@id="' + getIdWithIcon(icons[type]) + '"]'; +function Node(id) { + this.id = '//*[@id="' + id + '"]'; } Node.prototype.edit = function() { - browser.click(this.id); - browser.click(this.id); - browser.pause(500); // Necessary for headless mode. + browser.clickWithWait(this.id); + browser.clickWithWait(this.id); + // Wait until an edit dialog opens. + browser.waitForVisible('#node-dialog-ok', 2000); +} + +Node.prototype.clickOk = function() { + browser.clickWithWait('#node-dialog-ok'); + // Wait untile an edit dialog closes. + browser.waitForVisible('#node-dialog-ok', 2000, true); } Node.prototype.connect = function(targetNode) { @@ -46,7 +38,7 @@ Node.prototype.connect = function(targetNode) { } Node.prototype.clickLeftButton = function() { - browser.click(this.id + '/*[@class="node_button node_left_button"]'); + browser.clickWithWait(this.id + '/*[@class="node_button node_left_button"]'); } module.exports = Node; diff --git a/test/editor/pageobjects/nodes/nodefactory_page.js b/test/editor/pageobjects/nodes/nodefactory_page.js new file mode 100644 index 000000000..8d06d3342 --- /dev/null +++ b/test/editor/pageobjects/nodes/nodefactory_page.js @@ -0,0 +1,39 @@ +/** + * Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var injectNode = require('./core/core/20-inject_page'); +var debugNode = require('./core/core/58-debug_page'); +var changeNode = require('./core/logic/15-change_page'); +var rangeNode = require('./core/logic/16-range_page'); + +var nodeCatalog = { + // input + "inject": injectNode, + // output + "debug": debugNode, + // function + "change": changeNode, + "range": rangeNode, +} + +function create(type, id) { + var node = nodeCatalog[type]; + return new node(id); +} + +module.exports = { + create: create, +}; diff --git a/test/editor/pageobjects/util/util_page.js b/test/editor/pageobjects/util/util_page.js new file mode 100644 index 000000000..e2b6c3177 --- /dev/null +++ b/test/editor/pageobjects/util/util_page.js @@ -0,0 +1,45 @@ +/** + * Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +function init() { + browser.addCommand("clickWithWait", function(selector) { + browser.waitForVisible(selector); + // Wait at most 10 seconds. + for (var i = 0; i < 50; i++) { + try { + var ret = browser.click(selector); + return ret; + } catch (err) { + if (err.message.indexOf('is not clickable') !== -1) { + browser.pause(200); + } else { + throw err; + } + } + } + }, false); + + browser.addCommand("getTextWithWait", function(selector) { + browser.waitForExist(selector); + browser.waitForValue(selector); + var ret = browser.getText(selector); + return ret; + }, false); +} + + module.exports = { + init: init, + }; diff --git a/test/editor/pageobjects/workspace/debugTab_page.js b/test/editor/pageobjects/workspace/debugTab_page.js index c46314b27..c66122d70 100644 --- a/test/editor/pageobjects/workspace/debugTab_page.js +++ b/test/editor/pageobjects/workspace/debugTab_page.js @@ -15,17 +15,17 @@ **/ function open() { - browser.click('#red-ui-tab-debug'); + browser.clickWithWait('#red-ui-tab-debug'); } -function getMessage() { - var debugMessagePath = '//div[@class="debug-content debug-content-list"]//span[contains(@class, "debug-message-type")]'; - browser.waitForExist(debugMessagePath); - return browser.getText(debugMessagePath); +function getMessage(index) { + index = index ? index : 1; + var debugMessagePath = '//div[@class="debug-content debug-content-list"]/div[contains(@class,"debug-message")][' + index + ']//span[contains(@class, "debug-message-type")]'; + return browser.getTextWithWait(debugMessagePath); } function clearMessage() { - browser.click('//a[@id="debug-tab-clear"]'); + browser.clickWithWait('//a[@id="debug-tab-clear"]'); } module.exports = { diff --git a/test/editor/pageobjects/workspace/palette_page.js b/test/editor/pageobjects/workspace/palette_page.js new file mode 100644 index 000000000..764f5e55c --- /dev/null +++ b/test/editor/pageobjects/workspace/palette_page.js @@ -0,0 +1,33 @@ +/** + * Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var idMap = { + // input + "inject": "#palette_node_inject", + // output + "debug": "#palette_node_debug", + // function + "change": "#palette_node_change", + "range": "#palette_node_range", +}; + +function getId(type) { + return idMap[type]; +} + +module.exports = { + getId: getId, +}; diff --git a/test/editor/pageobjects/workspace/workspace_page.js b/test/editor/pageobjects/workspace/workspace_page.js index 95b8d2260..6c802486d 100644 --- a/test/editor/pageobjects/workspace/workspace_page.js +++ b/test/editor/pageobjects/workspace/workspace_page.js @@ -14,26 +14,25 @@ * limitations under the License. **/ - var when = require('when'); + var when = require("when"); var events = require("../../../../red/runtime/events.js"); -var node = require('./node_page'); - -var palette = { - "inject": "#palette_node_inject", - "debug": "#palette_node_debug", - "change": "#palette_node_change", -}; +var palette = require("./palette_page"); +var nodeFactory = require("../nodes/nodefactory_page"); function addNode(type, x, y) { var offsetX = x ? x : 0; var offsetY = y ? y : 0; - browser.moveToObject(palette[type]); + browser.moveToObject(palette.getId(type)); browser.buttonDown(); browser.moveToObject("#palette-search", offsetX + 300, offsetY + 100); // adjust to the top-left corner of workspace. browser.buttonUp(); - return new node(type); + // Last node is the one that has been created right now. + var nodeElement = browser.elements('//*[@class="node nodegroup"][last()]'); + var nodeId = nodeElement.getAttribute('id'); + var node = nodeFactory.create(type, nodeId); + return node; } function deleteAllNodes() { @@ -49,10 +48,10 @@ function deploy() { resolve(); } }); - browser.click('#btn-deploy'); + browser.clickWithWait('#btn-deploy'); }); }); - browser.pause(500); // Necessary for headless mode. + browser.waitForText('#btn-deploy', 2000); } module.exports = { diff --git a/test/editor/specs/editor_uispec.js b/test/editor/specs/editor_uispec.js deleted file mode 100644 index e14b89250..000000000 --- a/test/editor/specs/editor_uispec.js +++ /dev/null @@ -1,92 +0,0 @@ -/** - * Copyright JS Foundation and other contributors, http://js.foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ - -var when = require('when'); -var should = require("should"); -var fs = require('fs-extra'); - -var helper = require("../editor_helper"); -var editWindow = require('../pageobjects/workspace/editWindow_page'); -var debugTab = require('../pageobjects/workspace/debugTab_page'); -var workspace = require('../pageobjects/workspace/workspace_page'); - -var nodeWidth = 200; - -describe('Node-RED main page', function() { - beforeEach(function() { - workspace.deleteAllNodes(); - }); - - before(function() { - browser.windowHandleMaximize(); - browser.call(function () { - return when.promise(function(resolve, reject) { - helper.startServer(function() { - resolve(); - }); - }); - }); - browser.url(helper.url()); - browser.waitForExist('#palette_node_inject'); - }); - - after(function() { - browser.call(function () { - return when.promise(function(resolve, reject) { - helper.stopServer(function() { - resolve(); - }); - }); - }); - }); - - it('should have a right title', function () { - browser.getTitle().should.equal('Node-RED'); - }); - - it('should output a timestamp', function() { - var injectNode = workspace.addNode("inject"); - var debugNode = workspace.addNode("debug", nodeWidth); - injectNode.connect(debugNode); - - workspace.deploy(); - - debugTab.open(); - debugTab.clearMessage(); - injectNode.clickLeftButton(); - debugTab.getMessage().should.within(1500000000000, 3000000000000); - }); - - it('should set a message property to a fixed value', function() { - var injectNode = workspace.addNode("inject"); - var changeNode = workspace.addNode("change", nodeWidth); - var debugNode = workspace.addNode("debug", nodeWidth * 2); - - changeNode.edit(); - browser.setValue('.node-input-rule-property-value', 'Hello World!'); - editWindow.clickOk(); - - injectNode.connect(changeNode); - changeNode.connect(debugNode); - - workspace.deploy(); - - debugTab.open(); - debugTab.clearMessage(); - injectNode.clickLeftButton(); - debugTab.getMessage().should.be.equal('"Hello World!"'); - }); -}); diff --git a/test/editor/specs/scenario/cookbook_uispec.js b/test/editor/specs/scenario/cookbook_uispec.js new file mode 100644 index 000000000..fb3b5705e --- /dev/null +++ b/test/editor/specs/scenario/cookbook_uispec.js @@ -0,0 +1,145 @@ +/** + * Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var when = require('when'); +var should = require("should"); +var fs = require('fs-extra'); + +var helper = require("../../editor_helper"); +var debugTab = require('../../pageobjects/workspace/debugTab_page'); +var workspace = require('../../pageobjects/workspace/workspace_page'); + +var nodeWidth = 200; + +// https://cookbook.nodered.org/ +describe('cookbook', function() { + beforeEach(function() { + workspace.deleteAllNodes(); + }); + + before(function() { + helper.startServer(); + }); + + after(function() { + helper.stopServer(); + }); + + describe('messages', function() { + it('set a message property to a fixed value', function() { + var injectNode = workspace.addNode("inject"); + var changeNode = workspace.addNode("change", nodeWidth); + var debugNode = workspace.addNode("debug", nodeWidth * 2); + + changeNode.edit(); + changeNode.ruleSet("Hello World!"); + changeNode.clickOk(); + + injectNode.connect(changeNode); + changeNode.connect(debugNode); + + workspace.deploy(); + + debugTab.open(); + debugTab.clearMessage(); + injectNode.clickLeftButton(); + debugTab.getMessage().should.be.equal('"Hello World!"'); + }); + + it('delete a message property', function() { + var injectNode = workspace.addNode("inject"); + var changeNode = workspace.addNode("change", nodeWidth); + var debugNode = workspace.addNode("debug", nodeWidth * 2); + + changeNode.edit(); + changeNode.ruleDelete(); + changeNode.clickOk(); + + injectNode.connect(changeNode); + changeNode.connect(debugNode); + + workspace.deploy(); + + debugTab.open(); + debugTab.clearMessage(); + injectNode.clickLeftButton(); + debugTab.getMessage().should.be.equal("undefined"); + }); + + it('move a message property', function() { + var injectNode = workspace.addNode("inject"); + var changeNode = workspace.addNode("change", nodeWidth); + var debugNode = workspace.addNode("debug", nodeWidth * 2); + + injectNode.edit(); + injectNode.setTopic("Hello"); + injectNode.clickOk(); + + changeNode.edit(); + changeNode.ruleMove("topic", "payload"); + changeNode.clickOk(); + + injectNode.connect(changeNode); + changeNode.connect(debugNode); + + workspace.deploy(); + + debugTab.open(); + debugTab.clearMessage(); + injectNode.clickLeftButton(); + debugTab.getMessage().should.be.equal('"Hello"'); + }); + + it('map a property between different numeric ranges', function() { + var injectNode1 = workspace.addNode("inject"); + var injectNode2 = workspace.addNode("inject", 0, 50); + var injectNode3 = workspace.addNode("inject", 0, 100); + var rangeNode = workspace.addNode("range", nodeWidth); + var debugNode = workspace.addNode("debug", nodeWidth * 2); + + injectNode1.edit(); + injectNode1.setPayload("num", 0); + injectNode1.clickOk(); + injectNode2.edit(); + injectNode2.setPayload("num", 512); + injectNode2.clickOk(); + injectNode3.edit(); + injectNode3.setPayload("num", 1023); + injectNode3.clickOk(); + + rangeNode.edit(); + rangeNode.setAction("clamp"); + rangeNode.setRange(0, 1023, 0, 5); + rangeNode.clickOk(); + + injectNode1.connect(rangeNode); + injectNode2.connect(rangeNode); + injectNode3.connect(rangeNode); + rangeNode.connect(debugNode); + + workspace.deploy(); + + debugTab.open(); + debugTab.clearMessage(); + injectNode1.clickLeftButton(); + debugTab.getMessage(1).should.be.equal('0'); + injectNode2.clickLeftButton(); + debugTab.getMessage(2).should.be.equal('2.5024437927663734'); + injectNode3.clickLeftButton(); + debugTab.getMessage(3).should.be.equal('5'); + }); + }); +}); diff --git a/test/editor/specs/workspace/workspace_uispec.js b/test/editor/specs/workspace/workspace_uispec.js new file mode 100644 index 000000000..0b901cc1f --- /dev/null +++ b/test/editor/specs/workspace/workspace_uispec.js @@ -0,0 +1,57 @@ +/** + * Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var when = require('when'); +var should = require("should"); +var fs = require('fs-extra'); + +var helper = require("../../editor_helper"); +var debugTab = require('../../pageobjects/workspace/debugTab_page'); +var workspace = require('../../pageobjects/workspace/workspace_page'); + +var nodeWidth = 200; + +describe('Workspace', function() { + beforeEach(function() { + workspace.deleteAllNodes(); + }); + + before(function() { + helper.startServer(); + }); + + after(function() { + helper.stopServer(); + }); + + it('should have a right title', function () { + browser.getTitle().should.equal('Node-RED'); + }); + + it('should output a timestamp', function() { + var injectNode = workspace.addNode("inject"); + var debugNode = workspace.addNode("debug", nodeWidth); + injectNode.connect(debugNode); + + workspace.deploy(); + + debugTab.open(); + debugTab.clearMessage(); + injectNode.clickLeftButton(); + debugTab.getMessage().should.within(1500000000000, 3000000000000); + }); + +});