1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

Merge pull request #1821 from node-red-hitachi/uitest-httprequest

Add UItest for http request
This commit is contained in:
Nick O'Leary 2018-07-20 11:42:28 +01:00 committed by GitHub
commit 5832f7930d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 620 additions and 5 deletions

View File

@ -27,7 +27,7 @@ util.inherits(injectNode, nodePage);
var payloadType = {
"flow": 1,
"global": 2,
"string": 3,
"str": 3,
"num": 4,
"bool": 5,
"json": 6,
@ -43,6 +43,13 @@ var timeType = {
"atASpecificTime": 4,
};
var timeType = {
"none": 1,
"interval": 2,
"intervalBetweenTimes": 3,
"atASpecificTime": 4,
};
injectNode.prototype.setPayload = function(type, value) {
// Open a payload type list.
browser.clickWithWait('//*[contains(@class, "red-ui-typedInput-container")]');

View File

@ -24,4 +24,23 @@ function debugNode(id) {
util.inherits(debugNode, nodePage);
var target = {
"msg": 1,
"full": 2
};
debugNode.prototype.setTarget = function(type, value) {
// Open a payload type list.
browser.clickWithWait('//*[contains(@class, "red-ui-typedInput-container")]/button');
// Select a payload type.
var xPath = '/html/body/div[11]/a[' + target[type] + ']';
browser.clickWithWait(xPath);
if (value) {
browser.clickWithWait('//*[contains(@class, "red-ui-typedInput-input")]/input');
browser.keys(['Control', 'a', 'Control']);
browser.keys(['Delete']);
browser.setValue('//*[contains(@class, "red-ui-typedInput-input")]/input', value);
}
}
module.exports = debugNode;

View 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 functionNode(id) {
nodePage.call(this, id);
}
util.inherits(functionNode, nodePage);
functionNode.prototype.setCode = function(value) {
browser.click('#node-input-func-editor');
browser.keys(['Control', 'Home', 'Control']);
for (var i=0; i<value.length; i++) {
browser.keys([value.substr(i, 1)]);
}
}
module.exports = functionNode;

View File

@ -0,0 +1,55 @@
/**
* 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 templateNode(id) {
nodePage.call(this, id);
}
util.inherits(templateNode, nodePage);
var syntaxType = {
"mustache": 1,
"plain": 2
};
templateNode.prototype.setSyntax = function(type) {
// Open a method type list.
browser.clickWithWait('#node-input-syntax');
// Select a method type.
var syntaxTypeXPath = '//*[@id="node-input-syntax"]/option[' + syntaxType[type] + ']';
browser.clickWithWait(syntaxTypeXPath);
}
templateNode.prototype.setFormat = function(type) {
browser.selectByValue('#node-input-format', type);
}
templateNode.prototype.setTemplate = function(value) {
browser.click('#node-input-template-editor');
browser.keys(['Control', 'a', 'Control']); // call twice to release the keys.
// 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<value.length; i++) {
browser.keys([value.charAt(i)]);
}
browser.keys(['Control', 'Shift', 'End', 'Shift', 'Control']);
browser.keys(['Delete']);
}
module.exports = templateNode;

View File

@ -0,0 +1,51 @@
/**
* 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 httpinNode(id) {
nodePage.call(this, id);
}
function setMethod(type) {
browser.selectByValue('#node-input-method', type);
}
util.inherits(httpinNode, nodePage);
var methodType = {
"get": 1,
"post": 2,
"put": 3,
"delete": 4,
"patch": 5,
};
httpinNode.prototype.setMethod = function(type) {
// Open a method type list.
browser.clickWithWait('#node-input-method');
// Select a method type.
var methodTypeXPath = '//*[@id="node-input-method"]/option[' + methodType[type] + ']';
browser.clickWithWait(methodTypeXPath);
}
httpinNode.prototype.setUrl = function(value) {
browser.setValue('#node-input-url', value);
}
module.exports = httpinNode;

View File

@ -0,0 +1,59 @@
/**
* 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 httpRequestNode(id) {
nodePage.call(this, id);
}
util.inherits(httpRequestNode, nodePage);
var methodType = {
"get": 1,
"post": 2,
"put": 3,
"delete": 4,
"setByMsgMethod": 5,
};
var retType = {
"txt": 1,
"bin": 2,
"obj": 3,
};
httpRequestNode.prototype.setUrl = function(value) {
browser.setValue('#node-input-url', value);
}
httpRequestNode.prototype.setMethod = function(type) {
// Open a method type list.
browser.clickWithWait('#node-input-method');
// Select a method type.
var methodTypeXPath = '//*[@id="node-input-method"]/option[' + methodType[type] + ']';
browser.clickWithWait(methodTypeXPath);
}
httpRequestNode.prototype.setRet = function(type) {
browser.clickWithWait('#node-input-ret');
var retTypeXPath = '//*[@id="node-input-ret"]/option[' + retType[type] + ']';
browser.clickWithWait(retTypeXPath);
}
module.exports = httpRequestNode;

View File

@ -0,0 +1,27 @@
/**
* 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 httpResponseNode(id) {
nodePage.call(this, id);
}
util.inherits(httpResponseNode, nodePage);
module.exports = httpResponseNode;

View File

@ -24,14 +24,58 @@ function changeNode(id) {
util.inherits(changeNode, nodePage);
var tType = {
"set": 1,
"change": 2,
"delete": 3,
"move": 4,
};
var totType = {
"msg": 1,
"flow": 2,
"global": 3,
"str": 4,
"num": 5,
"bool": 6,
"json": 7,
"bin": 8,
"date": 9,
"jsonata": 10,
};
var ptType = {
"msg": 1,
"flow": 2,
"global": 3,
};
function setT(rule, index) {
browser.selectByValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/select', rule);
}
changeNode.prototype.ruleSet = function(to, 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;
setT("set", index);
browser.setValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[2]/div[2]/div/input', to);
if (pt) {
browser.clickWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/div/button[1]');
var num = 5 * index + 6;
var ptXPath = '/html/body/div[' + num + ']/a[' + ptType[pt] + ']';
browser.clickWithWait(ptXPath);
}
if (p) {
browser.setValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/div/div/input', p);
}
if (tot) {
browser.clickWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[2]/div[2]/button[1]');
var num = 5 * index + 7;
var totXPath = '/html/body/div[' + num + ']/a[' + totType[tot] + ']';
browser.clickWithWait(totXPath);
}
if (to) {
browser.setValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[2]/div[2]/div/input' , to);
}
}
changeNode.prototype.ruleDelete = function(index) {

View File

@ -0,0 +1,31 @@
/**
* 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 htmlNode(id) {
nodePage.call(this, id);
}
util.inherits(htmlNode, nodePage);
htmlNode.prototype.setTag = function(value) {
browser.setValue('#node-input-tag', value);
}
module.exports = htmlNode;

View File

@ -16,17 +16,30 @@
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 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 htmlNode = require('./core/parsers/70-HTML_page');
var nodeCatalog = {
// input
"inject": injectNode,
"httpin": httpinNode,
// output
"debug": debugNode,
"httpResponse": httpResponseNode,
// function
"function": functionNode,
"template": templateNode,
"change": changeNode,
"range": rangeNode,
"httpRequest": httpRequestNode,
"html": htmlNode,
}
function create(type, id) {

View File

@ -17,11 +17,17 @@
var idMap = {
// input
"inject": "#palette_node_inject",
"httpin": "#palette_node_http_in",
// output
"debug": "#palette_node_debug",
"httpResponse": "#palette_node_http_response",
// function
"function": "#palette_node_function",
"template": "#palette_node_template",
"change": "#palette_node_change",
"range": "#palette_node_range",
"httpRequest": "#palette_node_http_request",
"html": "#palette_node_html",
};
function getId(type) {

View File

@ -24,6 +24,8 @@ var workspace = require('../../pageobjects/workspace/workspace_page');
var specUtil = require('../../pageobjects/util/spec_util_page');
var nodeWidth = 200;
var nodeHeight = 100;
var httpNodeRoot = "/api";
// https://cookbook.nodered.org/
describe('cookbook', function() {
@ -46,7 +48,7 @@ describe('cookbook', function() {
var debugNode = workspace.addNode("debug", nodeWidth * 2);
changeNode.edit();
changeNode.ruleSet("Hello World!");
changeNode.ruleSet("payload", "msg", "Hello World!");
changeNode.clickOk();
injectNode.connect(changeNode);
@ -150,7 +152,7 @@ describe('cookbook', function() {
var debugNode = workspace.addNode("debug", nodeWidth * 2);
injectNode.edit();
injectNode.setPayload("string", "Started!")
injectNode.setPayload("str", "Started!")
injectNode.setOnce(true);
injectNode.clickOk();
injectNode.connect(debugNode);
@ -185,4 +187,270 @@ describe('cookbook', function() {
// skip this case since it needs up to one minite.
it.skip('trigger a flow at a specific time');
});
describe('HTTP requests', function() {
it('simple get request', function() {
var injectNode = workspace.addNode("inject");
var httpRequetNode = workspace.addNode("httpRequest", nodeWidth);
var htmlNode = workspace.addNode("html", nodeWidth * 2);
var debugNode = workspace.addNode("debug", nodeWidth * 3);
httpRequetNode.edit();
httpRequetNode.setMethod("get");
httpRequetNode.setUrl(helper.url());
httpRequetNode.clickOk();
htmlNode.edit();
htmlNode.setTag("title");
htmlNode.clickOk();
injectNode.connect(httpRequetNode);
httpRequetNode.connect(htmlNode);
htmlNode.connect(debugNode);
workspace.deploy();
debugTab.open();
debugTab.clearMessage();
injectNode.clickLeftButton();
debugTab.getMessage().should.be.equal('"Node-RED"');
});
it('set the URL of a request', function() {
var injectNode = workspace.addNode("inject");
var changeNode = workspace.addNode("change", nodeWidth * 1.5);
var httpRequetNode = workspace.addNode("httpRequest", nodeWidth * 2.5);
var debugNode = workspace.addNode("debug", nodeWidth * 3.5);
injectNode.edit();
injectNode.setPayload("str", helper.url());
injectNode.clickOk();
changeNode.edit();
changeNode.ruleSet("url", "msg", "payload", "msg");
changeNode.clickOk();
injectNode.connect(changeNode);
changeNode.connect(httpRequetNode);
httpRequetNode.connect(debugNode);
workspace.deploy();
debugTab.open();
debugTab.clearMessage();
injectNode.clickLeftButton();
debugTab.getMessage().should.containEql('<title>Node-RED</title>');
});
it('set the URL of a request using a template', function() {
var injectNode = workspace.addNode("inject");
var changeNode = workspace.addNode("change", nodeWidth * 1.5);
var httpRequetNode = workspace.addNode("httpRequest", nodeWidth * 2.5);
var debugNode = workspace.addNode("debug", nodeWidth * 3.5);
injectNode.edit();
injectNode.setPayload("str", 'settings');
injectNode.clickOk();
changeNode.edit();
changeNode.ruleSet("query", "msg", "payload", "msg");
changeNode.clickOk();
httpRequetNode.edit();
httpRequetNode.setUrl(helper.url() + "/{{{query}}}");
httpRequetNode.clickOk();
injectNode.connect(changeNode);
changeNode.connect(httpRequetNode);
httpRequetNode.connect(debugNode);
workspace.deploy();
debugTab.open();
debugTab.clearMessage();
injectNode.clickLeftButton();
debugTab.getMessage().should.containEql('httpNodeRoot');
});
it('set the query string parameters', function() {
var injectNode = workspace.addNode("inject");
var changeNode = workspace.addNode("change", nodeWidth);
var httpRequetNode = workspace.addNode("httpRequest", nodeWidth * 2);
var debugNode = workspace.addNode("debug", nodeWidth * 3);
injectNode.edit();
injectNode.setPayload("str", 'Nick');
injectNode.clickOk();
changeNode.edit();
changeNode.ruleSet("query", "msg", "payload", "msg");
changeNode.clickOk();
httpRequetNode.edit();
httpRequetNode.setUrl(helper.url() + httpNodeRoot + '/set-query?q={{{query}}}');
httpRequetNode.clickOk();
injectNode.connect(changeNode);
changeNode.connect(httpRequetNode);
httpRequetNode.connect(debugNode);
// The code for confirmation starts from here.
var httpinNode = workspace.addNode("httpin", 0, nodeHeight);
var templateNode = workspace.addNode("template", nodeWidth, nodeHeight);
var httpResponseNode = workspace.addNode("httpResponse", nodeWidth * 2, nodeHeight);
httpinNode.edit();
httpinNode.setMethod("get");
httpinNode.setUrl("/set-query");
httpinNode.clickOk();
templateNode.edit();
templateNode.setSyntax("mustache");
templateNode.setFormat("handlebars");
templateNode.setTemplate("Hello {{req.query.q}}");
templateNode.clickOk();
httpinNode.connect(templateNode);
templateNode.connect(httpResponseNode);
// The code for confirmation ends here.
workspace.deploy();
debugTab.open();
debugTab.clearMessage();
injectNode.clickLeftButton();
debugTab.getMessage().should.eql('"Hello Nick"');
});
it('get a parsed JSON response', function() {
var injectNode = workspace.addNode("inject");
var changeNode_setPost = workspace.addNode("change", nodeWidth);
var httpRequetNode = workspace.addNode("httpRequest", nodeWidth * 2);
var debugNode = workspace.addNode("debug", nodeWidth * 3);
injectNode.edit();
injectNode.setPayload("str", "json-response");
injectNode.clickOk();
changeNode_setPost.edit();
changeNode_setPost.ruleSet("post", "msg", "payload", "msg");
changeNode_setPost.clickOk();
httpRequetNode.edit();
httpRequetNode.setMethod("get");
var url = helper.url() + httpNodeRoot + "/{{post}}";
httpRequetNode.setUrl(url);
httpRequetNode.setRet("obj");
httpRequetNode.clickOk();
debugNode.edit();
debugNode.setTarget("msg", "payload.title");
debugNode.clickOk();
injectNode.connect(changeNode_setPost);
changeNode_setPost.connect(httpRequetNode);
httpRequetNode.connect(debugNode);
// The code for confirmation starts from here.
var httpinNode = workspace.addNode("httpin", 0, nodeHeight);
var templateNode = workspace.addNode("template", nodeWidth * 1.5, nodeHeight);
var changeNode_setHeader = workspace.addNode("change", nodeWidth * 2.5, nodeHeight);
var httpResponseNode = workspace.addNode("httpResponse", nodeWidth * 3.5, nodeHeight);
httpinNode.edit();
httpinNode.setMethod("get");
httpinNode.setUrl("/json-response");
httpinNode.clickOk();
templateNode.edit();
templateNode.setSyntax("mustache");
templateNode.setFormat("handlebars");
templateNode.setTemplate("{\"title\": \"Hello\"}");
templateNode.clickOk();
changeNode_setHeader.edit();
changeNode_setHeader.ruleSet("headers", "msg", "{\"content-type\":\"application/json\"}", "json");
changeNode_setHeader.clickOk();
httpinNode.connect(templateNode);
templateNode.connect(changeNode_setHeader);
changeNode_setHeader.connect(httpResponseNode);
// The code for confirmation ends here.
workspace.deploy();
debugTab.open();
debugTab.clearMessage();
injectNode.clickLeftButton();
debugTab.getMessage().should.eql('"Hello"');
});
it('get a binary response', function() {
var injectNode = workspace.addNode("inject");
var httpRequetNode = workspace.addNode("httpRequest", nodeWidth);
var debugNode = workspace.addNode("debug", nodeWidth * 2);
httpRequetNode.edit();
httpRequetNode.setMethod("get");
httpRequetNode.setUrl(helper.url() + "/settings");
httpRequetNode.setRet("bin");
httpRequetNode.clickOk();
injectNode.connect(httpRequetNode);
httpRequetNode.connect(debugNode);
workspace.deploy();
debugTab.open();
debugTab.clearMessage();
injectNode.clickLeftButton();
debugTab.getMessage().should.eql(['123', '34', '104', '116', '116', '112', '78', '111', '100', '101']);
});
it('set a request header', function() {
var injectNode = workspace.addNode("inject");
var functionNode = workspace.addNode("function", nodeWidth);
var httpRequetNode = workspace.addNode("httpRequest", nodeWidth * 2);
var debugNode = workspace.addNode("debug", nodeWidth * 3);
functionNode.edit();
functionNode.setCode("msg.payload = \"data to post\";");
functionNode.clickOk();
httpRequetNode.edit();
httpRequetNode.setMethod("post");
var url = helper.url() + httpNodeRoot + "/set-header";
httpRequetNode.setUrl(url);
httpRequetNode.clickOk();
injectNode.connect(functionNode);
functionNode.connect(httpRequetNode);
httpRequetNode.connect(debugNode);
// The code for confirmation starts from here.
var httpinNode = workspace.addNode("httpin", 0, nodeHeight);
var templateNode = workspace.addNode("template", nodeWidth * 1.5, nodeHeight);
var httpResponseNode = workspace.addNode("httpResponse", nodeWidth * 2.5, nodeHeight);
httpinNode.edit();
httpinNode.setMethod("post");
httpinNode.setUrl("/set-header");
httpinNode.clickOk();
templateNode.edit();
templateNode.setSyntax("mustache");
templateNode.setFormat("handlebars");
templateNode.setTemplate("{{ payload }}");
templateNode.clickOk();
httpinNode.connect(templateNode);
templateNode.connect(httpResponseNode);
// The code for confirmation ends here.
workspace.deploy();
debugTab.open();
debugTab.clearMessage();
injectNode.clickLeftButton();
debugTab.getMessage().should.eql('"data to post"');
});
});
});