From d5bdc1600b9c374b95ce4b687c257391ada8e4a7 Mon Sep 17 00:00:00 2001 From: t4skforce <7422037+t4skforce@users.noreply.github.com> Date: Tue, 31 Jul 2018 22:54:15 +0200 Subject: [PATCH 1/7] fixed some linting issues * added some semicolons * removed double parsing of ```err.stack``` into ```var stack``` --- nodes/core/core/80-function.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/nodes/core/core/80-function.js b/nodes/core/core/80-function.js index 7edb6c4a8..931958c7b 100644 --- a/nodes/core/core/80-function.js +++ b/nodes/core/core/80-function.js @@ -42,7 +42,7 @@ module.exports = function(RED) { if (type === 'object') { type = Buffer.isBuffer(msg)?'Buffer':(util.isArray(msg)?'Array':'Date'); } - node.error(RED._("function.error.non-message-returned",{ type: type })) + node.error(RED._("function.error.non-message-returned",{ type: type })); } } } @@ -203,9 +203,9 @@ module.exports = function(RED) { if (util.hasOwnProperty('promisify')) { sandbox.setTimeout[util.promisify.custom] = function(after, value) { return new Promise(function(resolve, reject) { - sandbox.setTimeout(function(){ resolve(value) }, after); + sandbox.setTimeout(function(){ resolve(value); }, after); }); - } + }; } var context = vm.createContext(sandbox); try { @@ -241,7 +241,6 @@ module.exports = function(RED) { var line = 0; var errorMessage; - var stack = err.stack.split(/\r?\n/); if (stack.length > 0) { while (line < stack.length && stack[line].indexOf("ReferenceError") !== 0) { line++; @@ -265,13 +264,13 @@ module.exports = function(RED) { }); this.on("close", function() { while (node.outstandingTimers.length > 0) { - clearTimeout(node.outstandingTimers.pop()) + clearTimeout(node.outstandingTimers.pop()); } while (node.outstandingIntervals.length > 0) { - clearInterval(node.outstandingIntervals.pop()) + clearInterval(node.outstandingIntervals.pop()); } this.status({}); - }) + }); } catch(err) { // eg SyntaxError - which v8 doesn't include line number information // so we can't do better than this @@ -280,4 +279,4 @@ module.exports = function(RED) { } RED.nodes.registerType("function",FunctionNode); RED.library.register("functions"); -} +}; From 15da19dceaa26f02b0e346c37dc265ceb19dec3e Mon Sep 17 00:00:00 2001 From: Hiroyasu Nishiyama Date: Mon, 6 Aug 2018 10:28:02 +0900 Subject: [PATCH 2/7] fix use of HTML tag or CSS class specification as icon of typedInput --- editor/js/ui/common/typedInput.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/editor/js/ui/common/typedInput.js b/editor/js/ui/common/typedInput.js index 2243f0718..6aab0bf53 100644 --- a/editor/js/ui/common/typedInput.js +++ b/editor/js/ui/common/typedInput.js @@ -522,10 +522,18 @@ this.selectLabel.empty(); var image; if (opt.icon) { - image = new Image(); - image.name = opt.icon; - image.src = opt.icon; - $('',{src:opt.icon,style:"margin-right: 4px;height: 18px;"}).prependTo(this.selectLabel); + if (opt.icon.indexOf("<") === 0) { + $(opt.icon).prependTo(this.selectLabel); + } + else if (opt.icon.indexOf("/") !== -1) { + image = new Image(); + image.name = opt.icon; + image.src = opt.icon; + $('',{src:opt.icon,style:"margin-right: 4px;height: 18px;"}).prependTo(this.selectLabel); + } + else { + $('',{class:"red-ui-typedInput-icon "+opt.icon}).prependTo(this.selectLabel); + } } else { this.selectLabel.text(opt.label); } From 695873d35a30d371359da08cf5ca4f5270767d43 Mon Sep 17 00:00:00 2001 From: Kazuhito Yokoi Date: Mon, 6 Aug 2018 21:14:53 +0900 Subject: [PATCH 3/7] Fix typo in test case for function node --- test/nodes/core/core/80-function_spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/nodes/core/core/80-function_spec.js b/test/nodes/core/core/80-function_spec.js index fd8f816f3..9c6d9e041 100644 --- a/test/nodes/core/core/80-function_spec.js +++ b/test/nodes/core/core/80-function_spec.js @@ -1216,7 +1216,7 @@ describe('function node', function() { msg.should.have.property('payload', n1.id); done(); }); - n1.receive({payload:"foo",topicb: "bar"}); + n1.receive({payload:"foo",topic: "bar"}); }); }); @@ -1230,7 +1230,7 @@ describe('function node', function() { msg.should.have.property('payload', n1.name); done(); }); - n1.receive({payload:"foo",topicb: "bar"}); + n1.receive({payload:"foo",topic: "bar"}); }); }); From 72fe30892efc023a282ea86fa030943ad28758ab Mon Sep 17 00:00:00 2001 From: nakanishi Date: Wed, 22 Aug 2018 14:36:30 +0900 Subject: [PATCH 4/7] Refactor UI testing code following a design note --- .../{workspace => editor}/debugTab_page.js | 0 .../{workspace => editor}/palette_page.js | 0 .../{workspace => editor}/workspace_page.js | 0 .../nodes/core/core/20-inject_page.js | 47 +++++++------------ .../nodes/core/core/58-debug_page.js | 20 ++++---- .../nodes/core/core/80-function_page.js | 6 +-- .../nodes/core/core/80-template_page.js | 23 +++------ .../nodes/core/io/21-httpin_page.js | 24 ++-------- .../nodes/core/io/21-httprequest_page.js | 32 +++---------- .../nodes/core/logic/15-change_page.js | 12 ++--- .../nodes/core/logic/16-range_page.js | 4 +- .../nodes/core/parsers/70-HTML_page.js | 4 +- .../nodes/core/storage/50-filein_page.js | 8 ++-- .../{workspace => editor}/workspace_uispec.js | 4 +- .../scenario/cookbook_endpoint_uispec.js | 34 +++++++------- test/editor/specs/scenario/cookbook_uispec.js | 26 +++++----- 16 files changed, 90 insertions(+), 154 deletions(-) rename test/editor/pageobjects/{workspace => editor}/debugTab_page.js (100%) rename test/editor/pageobjects/{workspace => editor}/palette_page.js (100%) rename test/editor/pageobjects/{workspace => editor}/workspace_page.js (100%) rename test/editor/specs/{workspace => editor}/workspace_uispec.js (91%) diff --git a/test/editor/pageobjects/workspace/debugTab_page.js b/test/editor/pageobjects/editor/debugTab_page.js similarity index 100% rename from test/editor/pageobjects/workspace/debugTab_page.js rename to test/editor/pageobjects/editor/debugTab_page.js diff --git a/test/editor/pageobjects/workspace/palette_page.js b/test/editor/pageobjects/editor/palette_page.js similarity index 100% rename from test/editor/pageobjects/workspace/palette_page.js rename to test/editor/pageobjects/editor/palette_page.js diff --git a/test/editor/pageobjects/workspace/workspace_page.js b/test/editor/pageobjects/editor/workspace_page.js similarity index 100% rename from test/editor/pageobjects/workspace/workspace_page.js rename to test/editor/pageobjects/editor/workspace_page.js diff --git a/test/editor/pageobjects/nodes/core/core/20-inject_page.js b/test/editor/pageobjects/nodes/core/core/20-inject_page.js index 70321e69e..82a4e6d6e 100644 --- a/test/editor/pageobjects/nodes/core/core/20-inject_page.js +++ b/test/editor/pageobjects/nodes/core/core/20-inject_page.js @@ -24,7 +24,7 @@ function injectNode(id) { util.inherits(injectNode, nodePage); -var payloadType = { +var payloadTypeList = { "flow": 1, "global": 2, "str": 3, @@ -36,54 +36,43 @@ var payloadType = { "env": 9, }; -var timeType = { +var repeatTypeList = { "none": 1, "interval": 2, "intervalBetweenTimes": 3, "atASpecificTime": 4, }; -var timeType = { - "none": 1, - "interval": 2, - "intervalBetweenTimes": 3, - "atASpecificTime": 4, -}; - -var timeType = { - "none": 1, - "interval": 2, - "intervalBetweenTimes": 3, - "atASpecificTime": 4, -}; - -injectNode.prototype.setPayload = function(type, value) { +injectNode.prototype.setPayload = function(payloadType, payload) { // 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] + ']'; + var payloadTypeXPath = '//*[@class="red-ui-typedInput-options"]/a[' + payloadTypeList[payloadType] + ']'; browser.clickWithWait(payloadTypeXPath); - if (value) { + if (payload) { // Input a value. - browser.setValue('//*[@class="red-ui-typedInput-input"]/input', value); + browser.setValue('//*[@class="red-ui-typedInput-input"]/input', payload); } } -injectNode.prototype.setTopic = function(value) { - browser.setValue('#node-input-topic', value); +injectNode.prototype.setTopic = function(topic) { + browser.setValue('#node-input-topic', topic); } -injectNode.prototype.setOnce = function(value) { - browser.clickWithWait('#node-input-once'); +injectNode.prototype.setOnce = function(once) { + var isChecked = browser.isSelected('#node-input-once'); + if (isChecked !== once) { + browser.clickWithWait('#node-input-once'); + } } -injectNode.prototype.setTimeType = function(type) { - var timeTypeXPath = '//*[@id="inject-time-type-select"]/option[' + timeType[type] + ']'; - browser.clickWithWait(timeTypeXPath); +injectNode.prototype.setRepeat = function(repeatType) { + var repeatTypeXPath = '//*[@id="inject-time-type-select"]/option[' + repeatTypeList[repeatType] + ']'; + browser.clickWithWait(repeatTypeXPath); } -injectNode.prototype.setRepeat = function(sec) { - browser.setValue('#inject-time-interval-count', sec); +injectNode.prototype.setRepeatInterval = function(repeat) { + browser.setValue('#inject-time-interval-count', repeat); } module.exports = injectNode; diff --git a/test/editor/pageobjects/nodes/core/core/58-debug_page.js b/test/editor/pageobjects/nodes/core/core/58-debug_page.js index b04e4a228..c8c1d8871 100644 --- a/test/editor/pageobjects/nodes/core/core/58-debug_page.js +++ b/test/editor/pageobjects/nodes/core/core/58-debug_page.js @@ -24,22 +24,20 @@ function debugNode(id) { util.inherits(debugNode, nodePage); -var target = { - "msg": 1, - "full": 2 -}; - -debugNode.prototype.setTarget = function(type, value) { +debugNode.prototype.setOutput = function(complete) { // 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) { + if (complete !== 'true') { + // Select the "msg" type. + browser.clickWithWait('/html/body/div[11]/a[1]'); + // Input the path in msg. 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); + browser.setValue('//*[contains(@class, "red-ui-typedInput-input")]/input', complete); + } else { + // Select the "complete msg object" type. + browser.clickWithWait('/html/body/div[11]/a[2]'); } } diff --git a/test/editor/pageobjects/nodes/core/core/80-function_page.js b/test/editor/pageobjects/nodes/core/core/80-function_page.js index 1cd47f8b9..56082c8a6 100644 --- a/test/editor/pageobjects/nodes/core/core/80-function_page.js +++ b/test/editor/pageobjects/nodes/core/core/80-function_page.js @@ -24,11 +24,11 @@ function functionNode(id) { util.inherits(functionNode, nodePage); -functionNode.prototype.setCode = function(value) { +functionNode.prototype.setFunction = function(func) { browser.click('#node-input-func-editor'); browser.keys(['Control', 'Home', 'Control']); - for (var i=0; i Date: Wed, 22 Aug 2018 13:20:49 +0200 Subject: [PATCH 5/7] Allows MQTT Shared Subscriptions for MQTT-In core node --- nodes/core/io/10-mqtt.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/nodes/core/io/10-mqtt.js b/nodes/core/io/10-mqtt.js index 509099aa4..d7cc027d3 100644 --- a/nodes/core/io/10-mqtt.js +++ b/nodes/core/io/10-mqtt.js @@ -24,6 +24,19 @@ module.exports = function(RED) { if (ts == "#") { return true; } + /* The following allows shared subscriptions (as in MQTT v5) + http://docs.oasis-open.org/mqtt/mqtt/v5.0/cs02/mqtt-v5.0-cs02.html#_Toc514345522 + + 4.8.2 describes shares like: + $share/{ShareName}/{filter} + $share is a literal string that marks the Topic Filter as being a Shared Subscription Topic Filter. + {ShareName} is a character string that does not include "/", "+" or "#" + {filter} The remainder of the string has the same syntax and semantics as a Topic Filter in a non-shared subscription. Refer to section 4.7. + */ + else if(ts.startsWith("$share")){ + ts = ts.replace(/^\$share\/[^#+/]+\/(.*)/g,"$1"); + + } var re = new RegExp("^"+ts.replace(/([\[\]\?\(\)\\\\$\^\*\.|])/g,"\\$1").replace(/\+/g,"[^/]+").replace(/\/#$/,"(\/.*)?")+"$"); return re.test(t); } From ecc49736459ae723d5328009edded84a366262d5 Mon Sep 17 00:00:00 2001 From: nakanishi Date: Mon, 27 Aug 2018 17:34:04 +0900 Subject: [PATCH 6/7] Fixed the problems that were caused by timing issue --- .../nodes/core/core/80-function_page.js | 7 ++++++- .../nodes/core/core/80-template_page.js | 4 ++-- .../nodes/core/io/21-httpin_page.js | 2 +- .../nodes/core/io/21-httprequest_page.js | 4 ++-- .../nodes/core/logic/15-change_page.js | 2 +- .../nodes/core/logic/16-range_page.js | 2 +- test/editor/pageobjects/util/util_page.js | 6 ++++++ .../specs/scenario/cookbook_endpoint_uispec.js | 18 +++++++++--------- test/editor/specs/scenario/cookbook_uispec.js | 6 +++--- 9 files changed, 31 insertions(+), 20 deletions(-) diff --git a/test/editor/pageobjects/nodes/core/core/80-function_page.js b/test/editor/pageobjects/nodes/core/core/80-function_page.js index 56082c8a6..238ce06f9 100644 --- a/test/editor/pageobjects/nodes/core/core/80-function_page.js +++ b/test/editor/pageobjects/nodes/core/core/80-function_page.js @@ -28,8 +28,13 @@ functionNode.prototype.setFunction = function(func) { browser.click('#node-input-func-editor'); browser.keys(['Control', 'Home', 'Control']); for (var i = 0; i < func.length; i++) { - browser.keys([func.substr(i, 1)]); + browser.keys([func.charAt(i)]); } + // Delete the unnecessary code that ace editor does the autocompletion. + browser.keys(['Control', 'Shift', 'End', 'Shift', 'Control']); + browser.keys(['Delete']); + // Need to wait until ace editor correctly checks the syntax. + browser.pause(50); } module.exports = functionNode; diff --git a/test/editor/pageobjects/nodes/core/core/80-template_page.js b/test/editor/pageobjects/nodes/core/core/80-template_page.js index a72be1347..01e3a6af3 100644 --- a/test/editor/pageobjects/nodes/core/core/80-template_page.js +++ b/test/editor/pageobjects/nodes/core/core/80-template_page.js @@ -25,11 +25,11 @@ function templateNode(id) { util.inherits(templateNode, nodePage); templateNode.prototype.setSyntax = function(syntax) { - browser.selectByValue('#node-input-syntax', syntax); + browser.selectWithWait('#node-input-syntax', syntax); } templateNode.prototype.setFormat = function(format) { - browser.selectByValue('#node-input-format', format); + browser.selectWithWait('#node-input-format', format); } templateNode.prototype.setTemplate = function(template) { diff --git a/test/editor/pageobjects/nodes/core/io/21-httpin_page.js b/test/editor/pageobjects/nodes/core/io/21-httpin_page.js index 7c81ae2d7..97648f395 100644 --- a/test/editor/pageobjects/nodes/core/io/21-httpin_page.js +++ b/test/editor/pageobjects/nodes/core/io/21-httpin_page.js @@ -25,7 +25,7 @@ function httpinNode(id) { util.inherits(httpinNode, nodePage); httpinNode.prototype.setMethod = function(method) { - browser.selectByValue('#node-input-method', method); + browser.selectWithWait('#node-input-method', method); } httpinNode.prototype.setUrl = function(url) { diff --git a/test/editor/pageobjects/nodes/core/io/21-httprequest_page.js b/test/editor/pageobjects/nodes/core/io/21-httprequest_page.js index d317ec103..b2ca812e3 100644 --- a/test/editor/pageobjects/nodes/core/io/21-httprequest_page.js +++ b/test/editor/pageobjects/nodes/core/io/21-httprequest_page.js @@ -29,11 +29,11 @@ httpRequestNode.prototype.setUrl = function(url) { } httpRequestNode.prototype.setMethod = function(method) { - browser.selectByValue('#node-input-method', method); + browser.selectWithWait('#node-input-method', method); } httpRequestNode.prototype.setReturn = function(ret) { - browser.selectByValue('#node-input-ret', ret); + browser.selectWithWait('#node-input-ret', ret); } module.exports = httpRequestNode; diff --git a/test/editor/pageobjects/nodes/core/logic/15-change_page.js b/test/editor/pageobjects/nodes/core/logic/15-change_page.js index 4d31c1b72..1336e8069 100644 --- a/test/editor/pageobjects/nodes/core/logic/15-change_page.js +++ b/test/editor/pageobjects/nodes/core/logic/15-change_page.js @@ -45,7 +45,7 @@ var ptType = { }; function setT(t, index) { - browser.selectByValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/select', t); + browser.selectWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/select', t); } // It is better to create a function whose input value is the object type in the future, diff --git a/test/editor/pageobjects/nodes/core/logic/16-range_page.js b/test/editor/pageobjects/nodes/core/logic/16-range_page.js index 63fcd9df8..230929995 100644 --- a/test/editor/pageobjects/nodes/core/logic/16-range_page.js +++ b/test/editor/pageobjects/nodes/core/logic/16-range_page.js @@ -25,7 +25,7 @@ function rangeNode(id) { util.inherits(rangeNode, nodePage); rangeNode.prototype.setAction = function(action) { - browser.selectByValue('#node-input-action', action); + browser.selectWithWait('#node-input-action', action); } rangeNode.prototype.setRange = function(minin, maxin, minout, maxout) { diff --git a/test/editor/pageobjects/util/util_page.js b/test/editor/pageobjects/util/util_page.js index e2b6c3177..a53dae06a 100644 --- a/test/editor/pageobjects/util/util_page.js +++ b/test/editor/pageobjects/util/util_page.js @@ -38,6 +38,12 @@ function init() { var ret = browser.getText(selector); return ret; }, false); + + browser.addCommand("selectWithWait", function(selector, value) { + browser.waitForVisible(selector, 5000); + var ret = browser.selectByValue(selector, value); + return ret; + }, false); } module.exports = { diff --git a/test/editor/specs/scenario/cookbook_endpoint_uispec.js b/test/editor/specs/scenario/cookbook_endpoint_uispec.js index f0eeea2fe..bb54da557 100644 --- a/test/editor/specs/scenario/cookbook_endpoint_uispec.js +++ b/test/editor/specs/scenario/cookbook_endpoint_uispec.js @@ -185,7 +185,7 @@ describe('cookbook', function() { var debugNode = workspace.addNode("debug", nodeWidth * 3, nodeHeight); changeNode.edit(); - changeNode.ruleSet("headers", "msg", "{\"user-agent\":\"Mozilla/5.0 (Windows NT 10.0; Win64; x64)\"}", "json"); + changeNode.ruleSet("headers", "msg", '{"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}', "json"); changeNode.clickOk(); httpRequestNode.edit(); @@ -280,7 +280,7 @@ describe('cookbook', function() { templateNode.edit(); templateNode.setSyntax("mustache"); templateNode.setFormat("handlebars"); - templateNode.setTemplate("{ \"Hello\": \"World\" }"); + templateNode.setTemplate('{ "Hello": "World" }'); templateNode.clickOk(); changeNode.edit(); @@ -440,7 +440,7 @@ describe('cookbook', function() { injectNode.clickOk(); changeNode.edit(); - changeNode.ruleSet("headers", "msg", "{\"content-type\":\"application/x-www-form-urlencoded\"}", "json"); + changeNode.ruleSet("headers", "msg", '{"content-type":"application/x-www-form-urlencoded"}', "json"); changeNode.clickOk(); httpRequestNode.edit(); @@ -486,11 +486,11 @@ describe('cookbook', function() { var debugNode = workspace.addNode("debug", nodeWidth * 3, nodeHeight); injectNode.edit() - injectNode.setPayload("json", "{\"name\":\"Nick\"}"); + injectNode.setPayload("json", '{"name":"Nick"}'); injectNode.clickOk(); changeNode.edit(); - changeNode.ruleSet("headers", "msg", "{\"content-type\":\"application/json\"}", "json"); + changeNode.ruleSet("headers", "msg", '{"content-type":"application/json"}', "json"); changeNode.clickOk(); httpRequestNode.edit(); @@ -531,13 +531,13 @@ describe('cookbook', function() { httpinNodeFormat.clickOk(); functionNodeFormat.edit(); - functionNodeFormat.setFunction("msg.payload = JSON.stringify(msg.req.cookies,null,4);"); + 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.setTemplate('\n\n\n

Cookies

\n

Add a cookieClear cookies

\n
{{ payload }}
\n\n'); templateNode.clickOk(); httpinNodeFormat.connect(functionNodeFormat); @@ -550,7 +550,7 @@ describe('cookbook', function() { httpinNodeAdd.clickOk(); functionNodeAdd.edit(); - functionNodeAdd.setFunction("msg.cookies = { };\n msg.cookies[\"demo-\"+(Math.floor(Math.random()*1000))] = Date.now();"); + functionNodeAdd.setFunction('msg.cookies = { };\n msg.cookies["demo-"+(Math.floor(Math.random()*1000))] = Date.now();\nreturn msg;'); functionNodeAdd.clickOk(); changeNode.edit(); @@ -571,7 +571,7 @@ describe('cookbook', function() { 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});\n\n"); + 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); diff --git a/test/editor/specs/scenario/cookbook_uispec.js b/test/editor/specs/scenario/cookbook_uispec.js index 834eadd02..20bc4fe39 100644 --- a/test/editor/specs/scenario/cookbook_uispec.js +++ b/test/editor/specs/scenario/cookbook_uispec.js @@ -364,11 +364,11 @@ describe('cookbook', function() { templateNode.edit(); templateNode.setSyntax("mustache"); templateNode.setFormat("handlebars"); - templateNode.setTemplate("{\"title\": \"Hello\"}"); + templateNode.setTemplate('{"title": "Hello"}'); templateNode.clickOk(); changeNodeSetHeader.edit(); - changeNodeSetHeader.ruleSet("headers", "msg", "{\"content-type\":\"application/json\"}", "json"); + changeNodeSetHeader.ruleSet("headers", "msg", '{"content-type":"application/json"}', "json"); changeNodeSetHeader.clickOk(); httpinNode.connect(templateNode); @@ -413,7 +413,7 @@ describe('cookbook', function() { var debugNode = workspace.addNode("debug", nodeWidth * 3); functionNode.edit(); - functionNode.setFunction("msg.payload = \"data to post\";"); + functionNode.setFunction('msg.payload = "data to post";\nreturn msg;'); functionNode.clickOk(); httpRequetNode.edit(); From c0e7d6d8263ba0031f3dd86fc1b47359a204a3ca Mon Sep 17 00:00:00 2001 From: Stefan Machmeier Date: Thu, 1 Mar 2018 17:22:39 +0100 Subject: [PATCH 7/7] Mqtt proxy configuration for websocket connection, #1651. --- nodes/core/io/10-mqtt.js | 21 ++++++++++++++++++++- package.json | 1 + 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/nodes/core/io/10-mqtt.js b/nodes/core/io/10-mqtt.js index d7cc027d3..233bef1b6 100644 --- a/nodes/core/io/10-mqtt.js +++ b/nodes/core/io/10-mqtt.js @@ -19,6 +19,8 @@ module.exports = function(RED) { var mqtt = require("mqtt"); var util = require("util"); var isUtf8 = require('is-utf8'); + var HttpsProxyAgent = require('https-proxy-agent'); + var url = require('url'); function matchTopic(ts,t) { if (ts == "#") { @@ -109,12 +111,29 @@ module.exports = function(RED) { if (typeof this.cleansession === 'undefined') { this.cleansession = true; } + var prox; + if (process.env.http_proxy != null) { prox = process.env.http_proxy; } + if (process.env.HTTP_PROXY != null) { prox = process.env.HTTP_PROXY; } // Create the URL to pass in to the MQTT.js library if (this.brokerurl === "") { // if the broker may be ws:// or wss:// or even tcp:// if (this.broker.indexOf("://") > -1) { this.brokerurl = this.broker; + // Only for ws or wss, check if proxy env var for additional configuration + if (this.brokerurl.indexOf("wss://") > -1 || this.brokerurl.indexOf("ws://") > -1 ) + // check if proxy is set in env + if (prox) { + var parsedUrl = url.parse(this.brokerurl); + var proxyOpts = url.parse(prox); + // true for wss + proxyOpts.secureEndpoint = parsedUrl.protocol ? parsedUrl.protocol === 'wss:' : true; + // Set Agent for wsOption in MQTT + var agent = new HttpsProxyAgent(proxyOpts); + this.options.wsOptions = { + agent: agent + } + } } else { // construct the std mqtt:// url if (this.usetls) { @@ -448,4 +467,4 @@ module.exports = function(RED) { } } RED.nodes.registerType("mqtt out",MQTTOutNode); -}; +}; \ No newline at end of file diff --git a/package.json b/package.json index 870806d5b..0dcd300e2 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "fs-extra": "5.0.0", "fs.notify": "0.0.4", "hash-sum": "1.0.2", + "https-proxy-agent": "2.2.1", "i18next": "11.6.0", "is-utf8": "0.2.1", "js-yaml": "3.12.0",