mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Merge pull request #1872 from node-red-hitachi/uitest-mqtt
Add UI testing code for MQTT node
This commit is contained in:
commit
ec4d24af91
@ -104,6 +104,7 @@
|
|||||||
"http-proxy": "^1.16.2",
|
"http-proxy": "^1.16.2",
|
||||||
"istanbul": "0.4.5",
|
"istanbul": "0.4.5",
|
||||||
"mocha": "^5.2.0",
|
"mocha": "^5.2.0",
|
||||||
|
"mosca": "^2.8.3",
|
||||||
"node-red-node-test-helper": "0.1.7",
|
"node-red-node-test-helper": "0.1.7",
|
||||||
"should": "^8.4.0",
|
"should": "^8.4.0",
|
||||||
"sinon": "1.17.7",
|
"sinon": "1.17.7",
|
||||||
|
@ -18,9 +18,11 @@ var idMap = {
|
|||||||
// input
|
// input
|
||||||
"inject": "#palette_node_inject",
|
"inject": "#palette_node_inject",
|
||||||
"httpin": "#palette_node_http_in",
|
"httpin": "#palette_node_http_in",
|
||||||
|
"mqttIn": "#palette_node_mqtt_in",
|
||||||
// output
|
// output
|
||||||
"debug": "#palette_node_debug",
|
"debug": "#palette_node_debug",
|
||||||
"httpResponse": "#palette_node_http_response",
|
"httpResponse": "#palette_node_http_response",
|
||||||
|
"mqttOut": "#palette_node_mqtt_out",
|
||||||
// function
|
// function
|
||||||
"function": "#palette_node_function",
|
"function": "#palette_node_function",
|
||||||
"template": "#palette_node_template",
|
"template": "#palette_node_template",
|
||||||
@ -28,6 +30,7 @@ var idMap = {
|
|||||||
"range": "#palette_node_range",
|
"range": "#palette_node_range",
|
||||||
"httpRequest": "#palette_node_http_request",
|
"httpRequest": "#palette_node_http_request",
|
||||||
"html": "#palette_node_html",
|
"html": "#palette_node_html",
|
||||||
|
"json": "#palette_node_json",
|
||||||
// storage
|
// storage
|
||||||
"filein": "#palette_node_file_in",
|
"filein": "#palette_node_file_in",
|
||||||
};
|
};
|
||||||
|
39
test/editor/pageobjects/nodes/core/io/10-mqttconfig_page.js
Normal file
39
test/editor/pageobjects/nodes/core/io/10-mqttconfig_page.js
Normal file
@ -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.
|
||||||
|
**/
|
||||||
|
|
||||||
|
function setServer(broker, port) {
|
||||||
|
browser.setValue('#node-config-input-broker', broker);
|
||||||
|
port = port ? port : 1883;
|
||||||
|
browser.setValue('#node-config-input-port', port);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickOk() {
|
||||||
|
browser.clickWithWait('#node-config-dialog-ok');
|
||||||
|
// Wait until an config dialog closes.
|
||||||
|
browser.waitForVisible('#node-config-dialog-ok', 2000, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function edit() {
|
||||||
|
browser.clickWithWait('#node-input-lookup-broker');
|
||||||
|
// Wait until a config dialog opens.
|
||||||
|
browser.waitForVisible('#node-config-dialog-ok', 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
setServer: setServer,
|
||||||
|
clickOk: clickOk,
|
||||||
|
edit: edit
|
||||||
|
};
|
35
test/editor/pageobjects/nodes/core/io/10-mqttin_page.js
Normal file
35
test/editor/pageobjects/nodes/core/io/10-mqttin_page.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* 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 mqttInNode(id) {
|
||||||
|
nodePage.call(this, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
util.inherits(mqttInNode, nodePage);
|
||||||
|
|
||||||
|
mqttInNode.prototype.setTopic = function (topic) {
|
||||||
|
browser.setValue('#node-input-topic', topic);
|
||||||
|
}
|
||||||
|
|
||||||
|
mqttInNode.prototype.setQoS = function (qos) {
|
||||||
|
browser.selectWithWait('#node-input-qos', qos);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = mqttInNode;
|
35
test/editor/pageobjects/nodes/core/io/10-mqttout_page.js
Normal file
35
test/editor/pageobjects/nodes/core/io/10-mqttout_page.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* 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 mqttOutNode(id) {
|
||||||
|
nodePage.call(this, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
util.inherits(mqttOutNode, nodePage);
|
||||||
|
|
||||||
|
mqttOutNode.prototype.setTopic = function(topic) {
|
||||||
|
browser.setValue('#node-input-topic', topic);
|
||||||
|
}
|
||||||
|
|
||||||
|
mqttOutNode.prototype.setRetain = function (retain) {
|
||||||
|
browser.selectWithWait('#node-input-retain', retain);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = mqttOutNode;
|
35
test/editor/pageobjects/nodes/core/parsers/70-JSON_page.js
Normal file
35
test/editor/pageobjects/nodes/core/parsers/70-JSON_page.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* 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 jsonNode(id) {
|
||||||
|
nodePage.call(this, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
util.inherits(jsonNode, nodePage);
|
||||||
|
|
||||||
|
jsonNode.prototype.setAction = function (action) {
|
||||||
|
browser.setValue('node-input-action', action);
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonNode.prototype.setProperty = function(property) {
|
||||||
|
browser.setValue('//*[@id="dialog-form"]/div[2]/div/div/input', property);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = jsonNode;
|
@ -18,12 +18,15 @@ var injectNode = require('./core/core/20-inject_page');
|
|||||||
var debugNode = require('./core/core/58-debug_page');
|
var debugNode = require('./core/core/58-debug_page');
|
||||||
var templateNode = require('./core/core/80-template_page');
|
var templateNode = require('./core/core/80-template_page');
|
||||||
var functionNode = require('./core/core/80-function_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 httpinNode = require('./core/io/21-httpin_page');
|
||||||
var httpResponseNode = require('./core/io/21-httpresponse_page');
|
var httpResponseNode = require('./core/io/21-httpresponse_page');
|
||||||
var changeNode = require('./core/logic/15-change_page');
|
var changeNode = require('./core/logic/15-change_page');
|
||||||
var rangeNode = require('./core/logic/16-range_page');
|
var rangeNode = require('./core/logic/16-range_page');
|
||||||
var httpRequestNode = require('./core/io/21-httprequest_page');
|
var httpRequestNode = require('./core/io/21-httprequest_page');
|
||||||
var htmlNode = require('./core/parsers/70-HTML_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/50-filein_page');
|
||||||
|
|
||||||
|
|
||||||
@ -31,9 +34,11 @@ var nodeCatalog = {
|
|||||||
// input
|
// input
|
||||||
"inject": injectNode,
|
"inject": injectNode,
|
||||||
"httpin": httpinNode,
|
"httpin": httpinNode,
|
||||||
|
"mqttIn":mqttInNode,
|
||||||
// output
|
// output
|
||||||
"debug": debugNode,
|
"debug": debugNode,
|
||||||
"httpResponse": httpResponseNode,
|
"httpResponse": httpResponseNode,
|
||||||
|
"mqttOut": mqttOutNode,
|
||||||
// function
|
// function
|
||||||
"function": functionNode,
|
"function": functionNode,
|
||||||
"template": templateNode,
|
"template": templateNode,
|
||||||
@ -41,6 +46,7 @@ var nodeCatalog = {
|
|||||||
"range": rangeNode,
|
"range": rangeNode,
|
||||||
"httpRequest": httpRequestNode,
|
"httpRequest": httpRequestNode,
|
||||||
"html": htmlNode,
|
"html": htmlNode,
|
||||||
|
"json":jsonNode,
|
||||||
// storage
|
// storage
|
||||||
"filein": fileinNode,
|
"filein": fileinNode,
|
||||||
}
|
}
|
||||||
|
228
test/editor/specs/scenario/cookbook_mqtt_uispec.js
Normal file
228
test/editor/specs/scenario/cookbook_mqtt_uispec.js
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
/**
|
||||||
|
* 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/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 nodeWidth = 200;
|
||||||
|
var nodeHeight = 100;
|
||||||
|
var httpNodeRoot = "/api";
|
||||||
|
|
||||||
|
var mqttServer;
|
||||||
|
var mosca = require('mosca');
|
||||||
|
var moscaSettings = {
|
||||||
|
port: 1883,
|
||||||
|
persistence: {
|
||||||
|
// Needs for retaining messages.
|
||||||
|
factory: mosca.persistence.Memory
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// https://cookbook.nodered.org/
|
||||||
|
describe('cookbook', function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
workspace.deleteAllNodes();
|
||||||
|
});
|
||||||
|
|
||||||
|
before(function() {
|
||||||
|
browser.call(function() {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
mqttServer = new mosca.Server(moscaSettings, function() {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
helper.startServer();
|
||||||
|
});
|
||||||
|
|
||||||
|
after(function() {
|
||||||
|
browser.call(function() {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
mqttServer.close(function() {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
helper.stopServer();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('MQTT', function() {
|
||||||
|
it('Add an MQTT broker to prepare for UI test', function() {
|
||||||
|
var mqttOutNode = workspace.addNode("mqttOut", nodeWidth);
|
||||||
|
|
||||||
|
mqttOutNode.edit();
|
||||||
|
mqttConfig.edit();
|
||||||
|
mqttConfig.setServer("localhost");
|
||||||
|
mqttConfig.clickOk();
|
||||||
|
mqttOutNode.clickOk();
|
||||||
|
|
||||||
|
workspace.deploy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Connect to an MQTT broker', function() {
|
||||||
|
var injectNode = workspace.addNode("inject");
|
||||||
|
var mqttOutNode = workspace.addNode("mqttOut", nodeWidth);
|
||||||
|
|
||||||
|
var mqttInNode = workspace.addNode("mqttIn", 0, nodeHeight);
|
||||||
|
var debugNode = workspace.addNode("debug", nodeWidth * 2, nodeHeight);
|
||||||
|
|
||||||
|
injectNode.edit();
|
||||||
|
injectNode.setPayload("num", 22);
|
||||||
|
injectNode.clickOk();
|
||||||
|
|
||||||
|
mqttOutNode.edit();
|
||||||
|
mqttOutNode.setTopic("sensors/livingroom/temp");
|
||||||
|
mqttOutNode.clickOk();
|
||||||
|
|
||||||
|
injectNode.connect(mqttOutNode);
|
||||||
|
|
||||||
|
mqttInNode.edit();
|
||||||
|
mqttInNode.setTopic("sensors/livingroom/temp");
|
||||||
|
mqttInNode.setQoS("2");
|
||||||
|
mqttInNode.clickOk();
|
||||||
|
|
||||||
|
mqttInNode.connect(debugNode);
|
||||||
|
|
||||||
|
workspace.deploy();
|
||||||
|
|
||||||
|
debugTab.open();
|
||||||
|
debugTab.clearMessage();
|
||||||
|
injectNode.clickLeftButton();
|
||||||
|
debugTab.getMessage().should.eql('"22"');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 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() {
|
||||||
|
var injectNode = workspace.addNode("inject");
|
||||||
|
var mqttOutNode = workspace.addNode("mqttOut", nodeWidth * 2);
|
||||||
|
|
||||||
|
injectNode.edit();
|
||||||
|
injectNode.setPayload("num", 22);
|
||||||
|
injectNode.setTopic("sensors/kitchen/temperature");
|
||||||
|
injectNode.clickOk();
|
||||||
|
|
||||||
|
mqttOutNode.edit();
|
||||||
|
mqttOutNode.clickOk();
|
||||||
|
|
||||||
|
injectNode.connect(mqttOutNode);
|
||||||
|
|
||||||
|
// The code for confirmation starts from here.
|
||||||
|
var mqttInNode = workspace.addNode("mqttIn", 0, nodeHeight);
|
||||||
|
var debugNode = workspace.addNode("debug", nodeWidth * 2, nodeHeight);
|
||||||
|
|
||||||
|
mqttInNode.edit();
|
||||||
|
mqttInNode.setTopic("sensors/kitchen/temperature");
|
||||||
|
mqttInNode.clickOk();
|
||||||
|
|
||||||
|
mqttInNode.connect(debugNode);
|
||||||
|
// The code for confirmation ends here.
|
||||||
|
|
||||||
|
workspace.deploy();
|
||||||
|
|
||||||
|
debugTab.open();
|
||||||
|
debugTab.clearMessage();
|
||||||
|
injectNode.clickLeftButton();
|
||||||
|
debugTab.getMessage().should.eql('"22"');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Publish a retained message to a topic', function() {
|
||||||
|
var injectNode = workspace.addNode("inject");
|
||||||
|
var mqttOutNode = workspace.addNode("mqttOut", nodeWidth);
|
||||||
|
|
||||||
|
injectNode.edit();
|
||||||
|
injectNode.setPayload("num", 22);
|
||||||
|
injectNode.clickOk();
|
||||||
|
|
||||||
|
mqttOutNode.edit();
|
||||||
|
mqttOutNode.setTopic("sensors/livingroom/temp");
|
||||||
|
mqttOutNode.setRetain("true");
|
||||||
|
mqttOutNode.clickOk();
|
||||||
|
|
||||||
|
injectNode.connect(mqttOutNode);
|
||||||
|
|
||||||
|
workspace.deploy();
|
||||||
|
debugTab.open();
|
||||||
|
injectNode.clickLeftButton();
|
||||||
|
debugTab.clearMessage();
|
||||||
|
|
||||||
|
// The code for confirmation starts from here.
|
||||||
|
var mqttInNode = workspace.addNode("mqttIn", 0, nodeHeight);
|
||||||
|
var debugNode = workspace.addNode("debug", nodeWidth * 2, nodeHeight);
|
||||||
|
|
||||||
|
mqttInNode.edit();
|
||||||
|
mqttInNode.setTopic("sensors/livingroom/temp");
|
||||||
|
mqttInNode.clickOk();
|
||||||
|
|
||||||
|
mqttInNode.connect(debugNode);
|
||||||
|
// The code for confirmation ends here.
|
||||||
|
|
||||||
|
workspace.deploy();
|
||||||
|
debugTab.open();
|
||||||
|
debugTab.getMessage().should.eql('"22"');
|
||||||
|
});
|
||||||
|
|
||||||
|
// skip this case since it is same as other cases.
|
||||||
|
it.skip('Subscribe to a topic');
|
||||||
|
|
||||||
|
it('Receive a parsed JSON message', function() {
|
||||||
|
var injectNode = workspace.addNode("inject");
|
||||||
|
var mqttOutNode = workspace.addNode("mqttOut", nodeWidth);
|
||||||
|
|
||||||
|
var mqttInNode = workspace.addNode("mqttIn", 0, nodeHeight);
|
||||||
|
var jsonNode = workspace.addNode("json", nodeWidth, nodeHeight);
|
||||||
|
var debugNode = workspace.addNode("debug", nodeWidth * 2, nodeHeight);
|
||||||
|
|
||||||
|
injectNode.edit();
|
||||||
|
injectNode.setPayload("json", '{"sensor_id": 1234, "temperature": 13 }');
|
||||||
|
injectNode.clickOk();
|
||||||
|
|
||||||
|
mqttOutNode.edit();
|
||||||
|
mqttOutNode.setTopic("sensors/livingroom/temp");
|
||||||
|
mqttOutNode.clickOk();
|
||||||
|
|
||||||
|
injectNode.connect(mqttOutNode);
|
||||||
|
|
||||||
|
mqttInNode.edit();
|
||||||
|
mqttInNode.setTopic("sensors/#");
|
||||||
|
mqttInNode.setQoS("2");
|
||||||
|
mqttInNode.clickOk();
|
||||||
|
|
||||||
|
jsonNode.edit();
|
||||||
|
jsonNode.setProperty("payload");
|
||||||
|
jsonNode.clickOk();
|
||||||
|
|
||||||
|
mqttInNode.connect(jsonNode);
|
||||||
|
jsonNode.connect(debugNode);
|
||||||
|
|
||||||
|
workspace.deploy();
|
||||||
|
|
||||||
|
debugTab.open();
|
||||||
|
debugTab.clearMessage();
|
||||||
|
injectNode.clickLeftButton();
|
||||||
|
debugTab.getMessage().should.eql(['1234', '13']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user