/** * 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 should = require("should"); var helper = require("../../editor_helper"); var debugTab = require('../../pageobjects/editor/debugTab_page'); var workspace = require('../../pageobjects/editor/workspace_page'); var httpNodeRoot = "/api"; // https://cookbook.nodered.org/ describe('cookbook', function() { beforeEach(function() { workspace.init(); }); before(function() { helper.startServer(); }); after(function() { helper.stopServer(); }); describe('HTTP endpoints', function () { it('create an HTTP endpoint', function () { var httpinNode = workspace.addNode("httpin"); var templateNode = workspace.addNode("template"); var httpResponseNode = workspace.addNode("httpResponse"); httpinNode.edit(); httpinNode.setMethod("get"); httpinNode.setUrl("/hello"); httpinNode.clickOk(); templateNode.edit(); templateNode.setSyntax("mustache"); templateNode.setFormat("handlebars"); templateNode.setTemplate("\n\n\n

Hello World!

\n\n"); templateNode.clickOk(); httpinNode.connect(templateNode); templateNode.connect(httpResponseNode); // The code for confirmation starts from here. var injectNode = workspace.addNode("inject"); var httpRequestNode = workspace.addNode("httpRequest"); var debugNode = workspace.addNode("debug"); httpRequestNode.edit(); httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello'); httpRequestNode.setMethod("GET"); httpRequestNode.clickOk(); injectNode.connect(httpRequestNode); httpRequestNode.connect(debugNode); // The code for confirmation ends here. workspace.deploy(); debugTab.open(); debugTab.clearMessage(); injectNode.clickLeftButton(); debugTab.getMessage().indexOf('Hello World!').should.not.eql(-1); }); it('handle query parameters passed to an HTTP endpoint', function () { var httpinNode = workspace.addNode("httpin"); var templateNode = workspace.addNode("template"); var httpResponseNode = workspace.addNode("httpResponse"); httpinNode.edit(); httpinNode.setMethod("get"); httpinNode.setUrl("/hello-query"); httpinNode.clickOk(); templateNode.edit(); templateNode.setSyntax("mustache"); templateNode.setFormat("handlebars"); templateNode.setTemplate("\n\n\n

Hello {{req.query.name}}!

\n\n"); templateNode.clickOk(); httpinNode.connect(templateNode); templateNode.connect(httpResponseNode); // The code for confirmation starts from here. var injectNode = workspace.addNode("inject"); var httpRequestNode = workspace.addNode("httpRequest"); var debugNode = workspace.addNode("debug"); httpRequestNode.edit(); httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-query?name=Nick'); httpRequestNode.setMethod("GET"); httpRequestNode.clickOk(); injectNode.connect(httpRequestNode); httpRequestNode.connect(debugNode); // The code for confirmation ends here. workspace.deploy(); debugTab.open(); debugTab.clearMessage(); injectNode.clickLeftButton(); debugTab.getMessage().indexOf('Hello Nick!').should.not.eql(-1); }); it('handle url parameters in an HTTP endpoint', function () { var httpinNode = workspace.addNode("httpin"); var templateNode = workspace.addNode("template"); var httpResponseNode = workspace.addNode("httpResponse"); httpinNode.edit(); httpinNode.setMethod("get"); httpinNode.setUrl("/hello-param/:name"); httpinNode.clickOk(); templateNode.edit(); templateNode.setSyntax("mustache"); templateNode.setFormat("handlebars"); templateNode.setTemplate("\n\n\n

Hello {{req.params.name}}!

\n\n"); templateNode.clickOk(); httpinNode.connect(templateNode); templateNode.connect(httpResponseNode); // The code for confirmation starts from here. var injectNode = workspace.addNode("inject"); var httpRequestNode = workspace.addNode("httpRequest"); var debugNode = workspace.addNode("debug"); httpRequestNode.edit(); httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-param/Dave'); httpRequestNode.setMethod("GET"); httpRequestNode.clickOk(); injectNode.connect(httpRequestNode); httpRequestNode.connect(debugNode); // The code for confirmation ends here. workspace.deploy(); debugTab.open(); debugTab.clearMessage(); injectNode.clickLeftButton(); debugTab.getMessage().indexOf('Hello Dave!').should.not.eql(-1); }); it('access HTTP request headers', function () { var httpinNode = workspace.addNode("httpin"); var templateNode = workspace.addNode("template"); var httpResponseNode = workspace.addNode("httpResponse"); httpinNode.edit(); httpinNode.setMethod("get"); httpinNode.setUrl("/hello-headers"); httpinNode.clickOk(); templateNode.edit(); templateNode.setSyntax("mustache"); templateNode.setFormat("handlebars"); templateNode.setTemplate("\n\n\n

User agent: {{req.headers.user-agent}}

\n\n"); templateNode.clickOk(); httpinNode.connect(templateNode); templateNode.connect(httpResponseNode); // The code for confirmation starts from here. var injectNode = workspace.addNode("inject", 0, 100); var changeNode = workspace.addNode("change"); var httpRequestNode = workspace.addNode("httpRequest"); var debugNode = workspace.addNode("debug"); changeNode.edit(); changeNode.ruleSet("headers", "msg", '{"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}', "json"); changeNode.clickOk(); httpRequestNode.edit(); httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-headers'); httpRequestNode.setMethod("GET"); httpRequestNode.clickOk(); injectNode.connect(changeNode); changeNode.connect(httpRequestNode); httpRequestNode.connect(debugNode); // The code for confirmation ends here. workspace.deploy(); debugTab.open(); debugTab.clearMessage(); injectNode.clickLeftButton(); debugTab.getMessage().indexOf('Mozilla').should.not.eql(-1); }); it('include data captured in another flow', function () { var injectNodeTimestamp = workspace.addNode("inject"); var changeNodeStore = workspace.addNode("change"); var httpinNode = workspace.addNode("httpin", 0, 100); var changeNodeCopy = workspace.addNode("change"); var templateNode = workspace.addNode("template"); var httpResponseNode = workspace.addNode("httpResponse"); injectNodeTimestamp.edit(); injectNodeTimestamp.setPayload("date"); injectNodeTimestamp.clickOk(); changeNodeStore.edit(); changeNodeStore.ruleSet("timestamp", "flow", "payload", "msg"); changeNodeStore.clickOk(); injectNodeTimestamp.connect(changeNodeStore); httpinNode.edit(); httpinNode.setMethod("get"); httpinNode.setUrl("/hello-data"); httpinNode.clickOk(); changeNodeCopy.edit(); changeNodeCopy.ruleSet("timestamp", "msg", "timestamp", "flow"); changeNodeCopy.clickOk(); templateNode.edit(); templateNode.setSyntax("mustache"); templateNode.setFormat("handlebars"); templateNode.setTemplate("\n\n\n

Time: {{ timestamp }}

\n\n"); templateNode.clickOk(); httpinNode.connect(changeNodeCopy); changeNodeCopy.connect(templateNode); templateNode.connect(httpResponseNode); // The code for confirmation starts from here. var injectNodeCheck = workspace.addNode("inject", 0, 300); var httpRequestNode = workspace.addNode("httpRequest"); var debugNode = workspace.addNode("debug"); httpRequestNode.edit(); httpRequestNode.setMethod("GET"); httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-data'); httpRequestNode.clickOk(); injectNodeCheck.connect(httpRequestNode); httpRequestNode.connect(debugNode); // The code for confirmation ends here. workspace.deploy(); debugTab.open(); debugTab.clearMessage(); injectNodeTimestamp.clickLeftButton(); injectNodeCheck.clickLeftButton(); var index = debugTab.getMessage().indexOf('Time: ') + 6; debugTab.getMessage().substring(index, index + 13).should.within(1500000000000, 3000000000000); }); it('serve JSON content', function () { var httpinNode = workspace.addNode("httpin"); var templateNode = workspace.addNode("template"); var changeNode = workspace.addNode("change"); var httpResponseNode = workspace.addNode("httpResponse"); httpinNode.edit(); httpinNode.setMethod("get"); httpinNode.setUrl("/hello-json"); httpinNode.clickOk(); templateNode.edit(); templateNode.setSyntax("mustache"); templateNode.setFormat("handlebars"); templateNode.setTemplate('{ "Hello": "World" }'); templateNode.clickOk(); changeNode.edit(); changeNode.ruleSet("headers", "msg", "{}", "json", "1"); changeNode.addRule(); changeNode.ruleSet("headers.content-type", "msg", "application/json", "str", "2"); changeNode.clickOk(); httpinNode.connect(templateNode); templateNode.connect(changeNode); changeNode.connect(httpResponseNode); // The code for confirmation starts from here. var injectNode = workspace.addNode("inject", 0, 200); var httpRequestNode = workspace.addNode("httpRequest"); var debugNode = workspace.addNode("debug"); httpRequestNode.edit(); httpRequestNode.setMethod("GET"); httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-json'); httpRequestNode.clickOk(); debugNode.edit(); debugNode.setOutput("headers"); debugNode.clickOk(); injectNode.connect(httpRequestNode); httpRequestNode.connect(debugNode); // The code for confirmation ends here. workspace.deploy(); debugTab.open(); debugTab.clearMessage(); injectNode.clickLeftButton(); var messages = debugTab.getMessage(); var contents = messages.join([separator = ""]); contents.indexOf('application/json').should.not.eql(-1); }); it('serve a local file', function () { var httpinNode = workspace.addNode("httpin"); var fileinNode = workspace.addNode("filein"); var changeNode = workspace.addNode("change", 200, 100); var httpResponseNode = workspace.addNode("httpResponse"); httpinNode.edit(); httpinNode.setMethod("get"); httpinNode.setUrl("/hello-file"); httpinNode.clickOk(); fileinNode.edit(); fileinNode.setFilename("test/resources/file-in-node/test.txt"); fileinNode.setOutput(""); fileinNode.clickOk(); changeNode.edit(); changeNode.ruleSet("headers", "msg", "{}", "json"); changeNode.addRule(); changeNode.ruleSet("headers.content-type", "msg", "text/plain", "str", "2"); changeNode.clickOk(); httpinNode.connect(fileinNode); fileinNode.connect(changeNode); changeNode.connect(httpResponseNode); // The code for confirmation starts from here. var injectNode = workspace.addNode("inject", 0, 200); var httpRequestNode = workspace.addNode("httpRequest"); var debugNode = workspace.addNode("debug"); httpRequestNode.edit(); httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-file'); httpRequestNode.setMethod("GET"); httpRequestNode.clickOk(); injectNode.connect(httpRequestNode); httpRequestNode.connect(debugNode); // The code for confirmation ends here. workspace.deploy(); debugTab.open(); debugTab.clearMessage(); injectNode.clickLeftButton(); debugTab.getMessage().indexOf('Text file').should.not.eql(-1); }); it('post raw data to a flow', function() { var httpinNode = workspace.addNode("httpin"); var templateNode = workspace.addNode("template"); var httpResponseNode = workspace.addNode("httpResponse"); httpinNode.edit(); httpinNode.setMethod("post"); httpinNode.setUrl("/hello-raw"); httpinNode.clickOk(); templateNode.edit(); templateNode.setSyntax("mustache"); templateNode.setFormat("handlebars"); templateNode.setTemplate("\n\n\n

Hello {{ payload }}!

\n\n"); templateNode.clickOk(); httpinNode.connect(templateNode); templateNode.connect(httpResponseNode); // The code for confirmation starts from here. var injectNode = workspace.addNode("inject"); var httpRequestNode = workspace.addNode("httpRequest"); var debugNode = workspace.addNode("debug"); injectNode.edit() injectNode.setPayload("str", "Nick"); injectNode.clickOk(); httpRequestNode.edit(); httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-raw'); httpRequestNode.setMethod("POST"); httpRequestNode.clickOk(); injectNode.connect(httpRequestNode); httpRequestNode.connect(debugNode); // The code for confirmation ends here. workspace.deploy(); debugTab.open(); debugTab.clearMessage(); injectNode.clickLeftButton(); debugTab.getMessage().indexOf('Hello Nick!').should.not.eql(-1); }); it('post form data to a flow', function () { var httpinNode = workspace.addNode("httpin"); var templateNode = workspace.addNode("template"); var httpResponseNode = workspace.addNode("httpResponse"); httpinNode.edit(); httpinNode.setMethod("post"); httpinNode.setUrl("/hello-form"); httpinNode.clickOk(); templateNode.edit(); templateNode.setSyntax("mustache"); templateNode.setFormat("handlebars"); templateNode.setTemplate("\n\n\n

Hello {{ payload.name }}!

\n\n"); templateNode.clickOk(); httpinNode.connect(templateNode); templateNode.connect(httpResponseNode); // The code for confirmation starts from here. var injectNode = workspace.addNode("inject", 0, 100); var changeNode = workspace.addNode("change"); var httpRequestNode = workspace.addNode("httpRequest"); var debugNode = workspace.addNode("debug"); injectNode.edit() injectNode.setPayload("str", "name=Nick"); injectNode.clickOk(); changeNode.edit(); changeNode.ruleSet("headers", "msg", '{"content-type":"application/x-www-form-urlencoded"}', "json"); changeNode.clickOk(); httpRequestNode.edit(); httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-form'); httpRequestNode.setMethod("POST"); httpRequestNode.clickOk(); injectNode.connect(changeNode); changeNode.connect(httpRequestNode); httpRequestNode.connect(debugNode); // The code for confirmation ends here. workspace.deploy(); debugTab.open(); debugTab.clearMessage(); injectNode.clickLeftButton(); debugTab.getMessage().indexOf('Hello Nick!').should.not.eql(-1); }); it('post JSON data to a flow', function() { var httpinNode = workspace.addNode("httpin"); var templateNode = workspace.addNode("template"); var httpResponseNode = workspace.addNode("httpResponse"); httpinNode.edit(); httpinNode.setMethod("post"); httpinNode.setUrl("/hello-json"); httpinNode.clickOk(); templateNode.edit(); templateNode.setSyntax("mustache"); templateNode.setFormat("handlebars"); templateNode.setTemplate("\n\n\n

Hello {{ payload.name }}!

\n\n"); templateNode.clickOk(); httpinNode.connect(templateNode); templateNode.connect(httpResponseNode); // The code for confirmation starts from here. var injectNode = workspace.addNode("inject", 0, 100); var changeNode = workspace.addNode("change"); var httpRequestNode = workspace.addNode("httpRequest"); var debugNode = workspace.addNode("debug"); injectNode.edit() injectNode.setPayload("json", '{"name":"Nick"}'); injectNode.clickOk(); changeNode.edit(); changeNode.ruleSet("headers", "msg", '{"content-type":"application/json"}', "json"); changeNode.clickOk(); httpRequestNode.edit(); httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-json'); httpRequestNode.setMethod("POST"); httpRequestNode.clickOk(); injectNode.connect(changeNode); changeNode.connect(httpRequestNode); httpRequestNode.connect(debugNode); // The code for confirmation ends here. workspace.deploy(); debugTab.open(); debugTab.clearMessage(); injectNode.clickLeftButton(); debugTab.getMessage().indexOf('Hello Nick!').should.not.eql(-1); }); it('work with cookies', function () { this.timeout(60000); var httpinNodeFormat = workspace.addNode("httpin"); var functionNodeFormat = workspace.addNode("function", 240); var templateNode = workspace.addNode("template", 400); var httpResponseNode = workspace.addNode("httpResponse", 600); var httpinNodeAdd = workspace.addNode("httpin", 0, 100); var functionNodeAdd = workspace.addNode("function", 240); var changeNode = workspace.addNode("change", 400); var httpinNodeClear = workspace.addNode("httpin", 0, 200); var functionNodeClear = workspace.addNode("function", 240); httpinNodeFormat.edit(); httpinNodeFormat.setMethod("get"); httpinNodeFormat.setUrl("/hello-cookie"); httpinNodeFormat.clickOk(); functionNodeFormat.edit(); functionNodeFormat.setFunction("msg.payload = JSON.stringify(msg.req.cookies,null,4);\nreturn msg;"); functionNodeFormat.clickOk(); templateNode.edit(); templateNode.setSyntax("mustache"); templateNode.setFormat("handlebars"); templateNode.setTemplate('\n\n\n

Cookies

\n

Add a cookieClear cookies

\n
{{ payload }}
\n\n'); templateNode.clickOk(); httpinNodeFormat.connect(functionNodeFormat); functionNodeFormat.connect(templateNode); templateNode.connect(httpResponseNode); httpinNodeAdd.edit(); httpinNodeAdd.setMethod("get"); httpinNodeAdd.setUrl("/hello-cookie/add"); httpinNodeAdd.clickOk(); functionNodeAdd.edit(); functionNodeAdd.setFunction('msg.cookies = { };\n msg.cookies["demo-"+(Math.floor(Math.random()*1000))] = Date.now();\nreturn msg;'); functionNodeAdd.clickOk(); changeNode.edit(); changeNode.ruleSet("statusCode", "msg", "302", "num"); changeNode.addRule(); changeNode.ruleSet("headers", "msg", "{}", "json", "2"); changeNode.addRule(); changeNode.ruleSet("headers.location", "msg", httpNodeRoot + "/hello-cookie", "str", "3"); changeNode.clickOk(); httpinNodeAdd.connect(functionNodeAdd); functionNodeAdd.connect(changeNode); changeNode.connect(httpResponseNode); httpinNodeClear.edit(); httpinNodeClear.setMethod("get"); httpinNodeClear.setUrl("/hello-cookie/clear"); httpinNodeClear.clickOk(); functionNodeClear.edit(); functionNodeClear.setFunction("var cookieNames = Object.keys(msg.req.cookies).filter(function(cookieName) { return /^demo-/.test(cookieName);});\nmsg.cookies = {};\n\ncookieNames.forEach(function(cookieName) {\n msg.cookies[cookieName] = null;\n});\nreturn msg;\n"); functionNodeClear.clickOk(); httpinNodeClear.connect(functionNodeClear); functionNodeClear.connect(changeNode); workspace.deploy(); // This case cannot be checked since http request node does not transfer cookies when redirected. }); }); });