diff --git a/editor/js/nodes.js b/editor/js/nodes.js
index 36f7a3291..c227d1856 100644
--- a/editor/js/nodes.js
+++ b/editor/js/nodes.js
@@ -272,10 +272,19 @@ RED.nodes = (function() {
if (updatedConfigNode) {
RED.workspaces.refresh();
}
+ try {
+ if (node._def.oneditdelete) {
+ node._def.oneditdelete.call(node);
+ }
+ } catch(err) {
+ console.log("oneditdelete",node.id,node.type,err.toString());
+ }
RED.events.emit('nodes:remove',node);
}
}
if (node && node._def.onremove) {
+ // Deprecated: never documented but used by some early nodes
+ console.log("Deprecated API warning: node type ",node.type," has an onremove function - should be oneditremove - please report");
node._def.onremove.call(n);
}
return {links:removedLinks,nodes:removedNodes};
diff --git a/editor/js/ui/editor.js b/editor/js/ui/editor.js
index 31133dc36..e82acc081 100644
--- a/editor/js/ui/editor.js
+++ b/editor/js/ui/editor.js
@@ -779,6 +779,16 @@ RED.editor = (function() {
var fileName = selectIconFile.val();
iconFileHidden.val(fileName);
});
+ var clear = $('').appendTo(iconForm);
+ clear.click(function(evt) {
+ evt.preventDefault();
+ var iconPath = RED.utils.getDefaultNodeIcon(node._def, node);
+ selectIconModule.val(iconPath.module);
+ moduleChange(selectIconModule, selectIconFile, iconModuleHidden, iconFileHidden, iconSets, true);
+ selectIconFile.removeClass("input-error");
+ selectIconFile.val(iconPath.file);
+ iconFileHidden.val(iconPath.file);
+ });
moduleChange(selectIconModule, selectIconFile, iconModuleHidden, iconFileHidden, iconSets, false);
var iconFileList = iconSets[selectIconModule.val()];
diff --git a/editor/js/ui/palette.js b/editor/js/ui/palette.js
index eb581b6fd..78b3b9cd6 100644
--- a/editor/js/ui/palette.js
+++ b/editor/js/ui/palette.js
@@ -412,16 +412,17 @@ RED.palette = (function() {
for (var j=0;j -1);
},
+ sort: function(A,B) {
+ if (activeFilter === "") {
+ return A.i - B.i;
+ }
+ var Ai = A.index.indexOf(activeFilter);
+ var Bi = B.index.indexOf(activeFilter);
+ if (Ai === -1) {
+ return 1;
+ }
+ if (Bi === -1) {
+ return -1;
+ }
+ if (Ai === Bi) {
+ return sortTypeLabels(A,B);
+ }
+ return Ai-Bi;
+ },
addItem: function(container,i,object) {
var def = object.def;
object.index = object.type.toLowerCase();
@@ -225,7 +243,17 @@ RED.typeSearch = (function() {
}
return label;
}
-
+ function sortTypeLabels(a,b) {
+ var al = a.label.toLowerCase();
+ var bl = b.label.toLowerCase();
+ if (al < bl) {
+ return -1;
+ } else if (al === bl) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
function refreshTypeList() {
var i;
searchResults.editableList('empty');
@@ -250,27 +278,19 @@ RED.typeSearch = (function() {
items.push({type:t,def: def, label:getTypeLabel(t,def)});
}
});
- items.sort(function(a,b) {
- var al = a.label.toLowerCase();
- var bl = b.label.toLowerCase();
- if (al < bl) {
- return -1;
- } else if (al === bl) {
- return 0;
- } else {
- return 1;
- }
- })
+ items.sort(sortTypeLabels);
var commonCount = 0;
var item;
+ var index = 0;
for(i=0;i
diff --git a/nodes/core/analysis/72-sentiment.js b/nodes/core/analysis/72-sentiment.js
index 43a800e2a..ff0cf33e8 100644
--- a/nodes/core/analysis/72-sentiment.js
+++ b/nodes/core/analysis/72-sentiment.js
@@ -1,18 +1,3 @@
-/**
- * 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.
- **/
module.exports = function(RED) {
"use strict";
@@ -20,16 +5,18 @@ module.exports = function(RED) {
function SentimentNode(n) {
RED.nodes.createNode(this,n);
+ this.property = n.property||"payload";
var node = this;
this.on("input", function(msg) {
- if (msg.hasOwnProperty("payload")) {
- sentiment(msg.payload, msg.overrides || null, function (err, result) {
+ var value = RED.util.getMessageProperty(msg,node.property);
+ if (value !== undefined) {
+ sentiment(value, msg.overrides || null, function (err, result) {
msg.sentiment = result;
node.send(msg);
});
}
- else { node.send(msg); } // If no payload - just pass it on.
+ else { node.send(msg); } // If no matching property - just pass it on.
});
}
RED.nodes.registerType("sentiment",SentimentNode);
diff --git a/nodes/core/locales/en-US/messages.json b/nodes/core/locales/en-US/messages.json
index e524b78f3..dcf639f59 100644
--- a/nodes/core/locales/en-US/messages.json
+++ b/nodes/core/locales/en-US/messages.json
@@ -5,7 +5,8 @@
"topic": "Topic",
"name": "Name",
"username": "Username",
- "password": "Password"
+ "password": "Password",
+ "property": "Property"
},
"status": {
"connected": "connected",
@@ -542,7 +543,7 @@
"label": {
"property": "Property",
"rule": "rule",
- "repair" : "repair sequence (reconstruct parts property of outgoing messages)"
+ "repair" : "recreate message sequences"
},
"and": "and",
"checkall": "checking all rules",
@@ -558,7 +559,7 @@
"nnull":"is not null",
"head":"head",
"tail":"tail",
- "index":"is between",
+ "index":"index between",
"exp":"JSONata exp",
"else":"otherwise"
},
@@ -608,7 +609,7 @@
"maxout": "e.g. 255"
},
"scale": {
- "payload": "Scale msg.payload",
+ "payload": "Scale the message property",
"limit": "Scale and limit to the target range",
"wrap": "Scale and wrap within the target range"
},
@@ -846,7 +847,7 @@
"mode":{
"mode":"Mode",
"auto":"automatic",
- "merge":"merge sequence",
+ "merge":"merge sequences",
"reduce":"reduce sequence",
"custom":"manual"
},
@@ -881,8 +882,8 @@
"exp": "Reduce exp",
"exp-value": "exp",
"init": "Initial value",
- "right": "Evaluate in reverse order (right to left)",
- "fixup": "Fixup exp"
+ "right": "Evaluate in reverse order (last to first)",
+ "fixup": "Fix-up exp"
},
"errors": {
"invalid-expr": "Invalid JSONata expression: __error__"
@@ -904,20 +905,19 @@
"batch" : {
"mode": {
"label" : "Mode",
- "num-msgs" : "number of messages",
- "interval" : "interval in seconds",
- "concat" : "concatenate sequences"
+ "num-msgs" : "Group by number of messages",
+ "interval" : "Group by time interval",
+ "concat" : "Concatenate sequences"
},
"count": {
- "label" : "Number of msgs",
- "overwrap" : "Overwrap",
+ "label" : "Number of messages",
+ "overlap" : "Overlap",
"count" : "count",
- "invalid" : "Invalid count and overwrap"
+ "invalid" : "Invalid count and overlap"
},
"interval": {
- "label" : "Interval (sec)",
+ "label" : "Interval",
"seconds" : "seconds",
- "sec" : "sec",
"empty" : "send empty message when no message arrives"
},
"concat": {
diff --git a/nodes/core/logic/10-switch.html b/nodes/core/logic/10-switch.html
index 5a39c2bee..7605135cc 100644
--- a/nodes/core/logic/10-switch.html
+++ b/nodes/core/logic/10-switch.html
@@ -40,7 +40,7 @@
diff --git a/nodes/core/logic/16-range.js b/nodes/core/logic/16-range.js
index 1de073fee..b92b155ed 100644
--- a/nodes/core/logic/16-range.js
+++ b/nodes/core/logic/16-range.js
@@ -24,11 +24,13 @@ module.exports = function(RED) {
this.maxin = Number(n.maxin);
this.minout = Number(n.minout);
this.maxout = Number(n.maxout);
+ this.property = n.property||"payload";
var node = this;
this.on('input', function (msg) {
- if (msg.hasOwnProperty("payload")) {
- var n = Number(msg.payload);
+ var value = RED.util.getMessageProperty(msg,node.property);
+ if (value !== undefined) {
+ var n = Number(value);
if (!isNaN(n)) {
if (node.action == "clamp") {
if (n < node.minin) { n = node.minin; }
@@ -38,11 +40,12 @@ module.exports = function(RED) {
var divisor = node.maxin - node.minin;
n = ((n - node.minin) % divisor + divisor) % divisor + node.minin;
}
- msg.payload = ((n - node.minin) / (node.maxin - node.minin) * (node.maxout - node.minout)) + node.minout;
- if (node.round) { msg.payload = Math.round(msg.payload); }
+ value = ((n - node.minin) / (node.maxin - node.minin) * (node.maxout - node.minout)) + node.minout;
+ if (node.round) { value = Math.round(value); }
+ RED.util.setMessageProperty(msg,node.property,value);
node.send(msg);
}
- else { node.log(RED._("range.errors.notnumber")+": "+msg.payload); }
+ else { node.log(RED._("range.errors.notnumber")+": "+value); }
}
else { node.send(msg); } // If no payload - just pass it on.
});
diff --git a/nodes/core/logic/17-split.html b/nodes/core/logic/17-split.html
index 592516d38..49480ba53 100644
--- a/nodes/core/logic/17-split.html
+++ b/nodes/core/logic/17-split.html
@@ -90,11 +90,9 @@
a message and send each complete segment. If there is a partial segment at the end,
the node will hold on to it and prepend it to the next message that is received.
-
When operating in this mode, the node will not set the `msg.parts.count`
+
When operating in this mode, the node will not set the msg.parts.count
property as it does not know how many messages to expect in the stream. This
means it cannot be used with the join node in its automatic mode
-
-
diff --git a/nodes/core/logic/17-split.js b/nodes/core/logic/17-split.js
index 803131671..88a6c3d6f 100644
--- a/nodes/core/logic/17-split.js
+++ b/nodes/core/logic/17-split.js
@@ -233,10 +233,10 @@ module.exports = function(RED) {
var _max_kept_msgs_count = undefined;
-
+
function max_kept_msgs_count(node) {
if (_max_kept_msgs_count === undefined) {
- var name = "joinMaxKeptMsgsCount";
+ var name = "nodeMessageBufferMaxLength";
if (RED.settings.hasOwnProperty(name)) {
_max_kept_msgs_count = RED.settings[name];
}
@@ -247,89 +247,6 @@ module.exports = function(RED) {
return _max_kept_msgs_count;
}
- function add_to_topic(node, pending, topic, msg) {
- var merge_on_change = node.merge_on_change;
- if (!pending.hasOwnProperty(topic)) {
- pending[topic] = [];
- }
- var topics = pending[topic];
- topics.push(msg);
- if (merge_on_change) {
- var counts = node.topic_counts;
- if (topics.length > counts[topic]) {
- topics.shift();
- node.pending_count--;
- }
- }
- }
-
- function compute_topic_counts(topics) {
- var counts = {};
- for (var topic of topics) {
- counts[topic] = (counts.hasOwnProperty(topic) ? counts[topic] : 0) +1;
- }
- return counts;
- }
-
- function try_merge(node, pending, merge_on_change) {
- var topics = node.topics;
- var counts = node.topic_counts;
- for(var topic of topics) {
- if(!pending.hasOwnProperty(topic) ||
- (pending[topic].length < counts[topic])) {
- return;
- }
- }
- var merge_on_change = node.merge_on_change;
- var msgs = [];
- var vals = [];
- var new_msg = {payload: vals};
- for (var topic of topics) {
- var pmsgs = pending[topic];
- var msg = pmsgs.shift();
- if (merge_on_change) {
- pmsgs.push(msg);
- }
- var pval = msg.payload;
- var val = new_msg[topic];
- msgs.push(msg);
- vals.push(pval);
- if (val instanceof Array) {
- new_msg[topic].push(pval);
- }
- else if (val === undefined) {
- new_msg[topic] = pval;
- }
- else {
- new_msg[topic] = [val, pval]
- }
- }
- node.send(new_msg);
- if (!merge_on_change) {
- node.pending_count -= topics.length;
- }
- }
-
- function merge_msg(node, msg) {
- var topics = node.topics;
- var topic = msg.topic;
- if(node.topics.indexOf(topic) >= 0) {
- var pending = node.pending;
- if(node.topic_counts == undefined) {
- node.topic_counts = compute_topic_counts(topics)
- }
- add_to_topic(node, pending, topic, msg);
- node.pending_count++;
- var max_msgs = max_kept_msgs_count(node);
- if ((max_msgs > 0) && (node.pending_count > max_msgs)) {
- node.pending = {};
- node.pending_count = 0;
- node.error(RED._("join.too-many"), msg);
- }
- try_merge(node, pending);
- }
- }
-
function apply_r(exp, accum, msg, index, count) {
exp.assign("I", index);
exp.assign("N", count);
@@ -350,7 +267,7 @@ module.exports = function(RED) {
}
return exp
}
-
+
function reduce_and_send_group(node, group) {
var is_right = node.reduce_right;
var flag = is_right ? -1 : 1;
@@ -374,15 +291,15 @@ module.exports = function(RED) {
}
node.send({payload: accum});
}
-
+
function reduce_msg(node, msg) {
if(msg.hasOwnProperty('parts')) {
var parts = msg.parts;
var pending = node.pending;
var pending_count = node.pending_count;
var gid = msg.parts.id;
+ var count;
if(!pending.hasOwnProperty(gid)) {
- var count = undefined;
if(parts.hasOwnProperty('count')) {
count = msg.parts.count;
}
@@ -568,10 +485,6 @@ module.exports = function(RED) {
node.warn("Message missing msg.parts property - cannot join in 'auto' mode")
return;
}
- if (node.mode === 'merge' && !msg.hasOwnProperty("topic")) {
- node.warn("Message missing msg.topic property - cannot join in 'merge' mode");
- return;
- }
if (node.propertyType == "full") {
property = msg;
@@ -602,10 +515,6 @@ module.exports = function(RED) {
arrayLen = msg.parts.len;
propertyIndex = msg.parts.index;
}
- else if (node.mode === 'merge') {
- merge_msg(node, msg);
- return;
- }
else if (node.mode === 'reduce') {
reduce_msg(node, msg);
return;
diff --git a/nodes/core/logic/18-sort.html b/nodes/core/logic/18-sort.html
index 5ce1a9f82..af66bef84 100644
--- a/nodes/core/logic/18-sort.html
+++ b/nodes/core/logic/18-sort.html
@@ -81,7 +81,7 @@
Note: This node internally keeps messages for its operation. In order to prevent unexpected memory usage, maximum number of messages kept can be specified. Default is no limit on number of messages.
-
maxKeptMsgsCount property set in settings.js.
+
nodeMessageBufferMaxLength property set in settings.js.
diff --git a/nodes/core/logic/18-sort.js b/nodes/core/logic/18-sort.js
index 65d8e6c45..e30535dc1 100644
--- a/nodes/core/logic/18-sort.js
+++ b/nodes/core/logic/18-sort.js
@@ -21,7 +21,7 @@ module.exports = function(RED) {
function max_kept_msgs_count(node) {
if (_max_kept_msgs_count === undefined) {
- var name = "maxKeptMsgsCount";
+ var name = "nodeMessageBufferMaxLength";
if (RED.settings.hasOwnProperty(name)) {
_max_kept_msgs_count = RED.settings[name];
}
diff --git a/nodes/core/logic/19-batch.html b/nodes/core/logic/19-batch.html
index 07fda4915..371a48bf9 100644
--- a/nodes/core/logic/19-batch.html
+++ b/nodes/core/logic/19-batch.html
@@ -18,7 +18,7 @@
diff --git a/nodes/core/parsers/70-XML.js b/nodes/core/parsers/70-XML.js
index 32991f07d..3bfd38101 100644
--- a/nodes/core/parsers/70-XML.js
+++ b/nodes/core/parsers/70-XML.js
@@ -1,18 +1,3 @@
-/**
- * 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.
- **/
module.exports = function(RED) {
"use strict";
@@ -23,35 +8,39 @@ module.exports = function(RED) {
RED.nodes.createNode(this,n);
this.attrkey = n.attr;
this.charkey = n.chr;
+ this.property = n.property||"payload";
var node = this;
this.on("input", function(msg) {
- if (msg.hasOwnProperty("payload")) {
+ var value = RED.util.getMessageProperty(msg,node.property);
+ if (value !== undefined) {
var options;
- if (typeof msg.payload === "object") {
+ if (typeof value === "object") {
options = {renderOpts:{pretty:false}};
if (msg.hasOwnProperty("options") && typeof msg.options === "object") { options = msg.options; }
options.async = false;
var builder = new xml2js.Builder(options);
- msg.payload = builder.buildObject(msg.payload, options);
+ value = builder.buildObject(value, options);
+ RED.util.setMessageProperty(msg,node.property,value);
node.send(msg);
}
- else if (typeof msg.payload == "string") {
+ else if (typeof value == "string") {
options = {};
if (msg.hasOwnProperty("options") && typeof msg.options === "object") { options = msg.options; }
options.async = true;
options.attrkey = node.attrkey || options.attrkey || '$';
options.charkey = node.charkey || options.charkey || '_';
- parseString(msg.payload, options, function (err, result) {
+ parseString(value, options, function (err, result) {
if (err) { node.error(err, msg); }
else {
- msg.payload = result;
+ value = result;
+ RED.util.setMessageProperty(msg,node.property,value);
node.send(msg);
}
});
}
else { node.warn(RED._("xml.errors.xml_js")); }
}
- else { node.send(msg); } // If no payload - just pass it on.
+ else { node.send(msg); } // If no property - just pass it on.
});
}
RED.nodes.registerType("xml",XMLNode);
diff --git a/nodes/core/parsers/70-YAML.html b/nodes/core/parsers/70-YAML.html
index 3f970e9e5..2f8914366 100644
--- a/nodes/core/parsers/70-YAML.html
+++ b/nodes/core/parsers/70-YAML.html
@@ -1,5 +1,9 @@
diff --git a/nodes/core/parsers/70-YAML.js b/nodes/core/parsers/70-YAML.js
index ae4ca1a8c..1a34fdd57 100644
--- a/nodes/core/parsers/70-YAML.js
+++ b/nodes/core/parsers/70-YAML.js
@@ -4,20 +4,24 @@ module.exports = function(RED) {
var yaml = require('js-yaml');
function YAMLNode(n) {
RED.nodes.createNode(this,n);
+ this.property = n.property||"payload";
var node = this;
this.on("input", function(msg) {
- if (msg.hasOwnProperty("payload")) {
- if (typeof msg.payload === "string") {
+ var value = RED.util.getMessageProperty(msg,node.property);
+ if (value !== undefined) {
+ if (typeof value === "string") {
try {
- msg.payload = yaml.load(msg.payload);
+ value = yaml.load(value);
+ RED.util.setMessageProperty(msg,node.property,value);
node.send(msg);
}
catch(e) { node.error(e.message,msg); }
}
- else if (typeof msg.payload === "object") {
- if (!Buffer.isBuffer(msg.payload)) {
+ else if (typeof value === "object") {
+ if (!Buffer.isBuffer(value)) {
try {
- msg.payload = yaml.dump(msg.payload);
+ value = yaml.dump(value);
+ RED.util.setMessageProperty(msg,node.property,value);
node.send(msg);
}
catch(e) {
diff --git a/red/api/auth/clients.js b/red/api/auth/clients.js
index 4495efba0..63e59ccce 100644
--- a/red/api/auth/clients.js
+++ b/red/api/auth/clients.js
@@ -13,8 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
**/
-
-var when = require("when");
var clients = [
{id:"node-red-editor",secret:"not_available"},
@@ -25,9 +23,9 @@ module.exports = {
get: function(id) {
for (var i=0;i 0) {
- user.image = arguments[0].photos[0].value;
+ } else {
+ // Try to extract common profile information
+ if (args[0].hasOwnProperty('photos') && args[0].photos.length > 0) {
+ user.image = args[0].photos[0].value;
+ }
+ return cleanUser(user);
}
- return when.resolve(user);
}
- }
- return when.resolve(null);
+ return null;
+ });
}
function get(username) {
- return when.resolve(users[username]);
+ return Promise.resolve(users[username]);
}
function getDefaultUser() {
- return when.resolve(null);
+ return Promise.resolve(null);
}
var api = {
@@ -63,7 +64,6 @@ var api = {
function init(config) {
users = {};
- passwords = {};
defaultUser = null;
if (config.type == "credentials" || config.type == "strategy") {
if (config.users) {
@@ -77,11 +77,7 @@ function init(config) {
}
for (var i=0;i {
+ output += data;
+ });
+ child.stderr.on('data', (data) => {
+ output += data;
+ });
+ child.on('close', (code) => {
+ if (code !== 0) {
+ var e;
+ var lookFor404 = new RegExp(" 404 .*"+module,"m");
+ var lookForVersionNotFound = new RegExp("version not found: "+module+"@"+version,"m");
+ if (lookFor404.test(output)) {
+ log.warn(log._("server.install.install-failed-not-found",{name:module}));
+ e = new Error("Module not found");
+ e.code = 404;
+ reject(e);
+ } else if (isUpgrade && lookForVersionNotFound.test(output)) {
+ log.warn(log._("server.install.upgrade-failed-not-found",{name:module}));
+ e = new Error("Module not found");
+ e.code = 404;
+ reject(e);
} else {
- if (!isUpgrade) {
- log.info(log._("server.install.installed",{name:module}));
- resolve(require("./index").addModule(module).then(reportAddedModules));
- } else {
- log.info(log._("server.install.upgraded",{name:module, version:version}));
- events.emit("runtime-event",{id:"restart-required",payload:{type:"warning",text:"notification.warnings.restartRequired"},retain:true});
- resolve(require("./registry").setModulePendingUpdated(module,version));
- }
+ log.warn(log._("server.install.install-failed-long",{name:module}));
+ log.warn("------------------------------------------");
+ log.warn(output);
+ log.warn("------------------------------------------");
+ reject(new Error(log._("server.install.install-failed")));
+ }
+ } else {
+ if (!isUpgrade) {
+ log.info(log._("server.install.installed",{name:module}));
+ resolve(require("./index").addModule(module).then(reportAddedModules));
+ } else {
+ log.info(log._("server.install.upgraded",{name:module, version:version}));
+ events.emit("runtime-event",{id:"restart-required",payload:{type:"warning",text:"notification.warnings.restartRequired"},retain:true});
+ resolve(require("./registry").setModulePendingUpdated(module,version));
}
}
- );
+ });
});
}
diff --git a/red/runtime/nodes/registry/localfilesystem.js b/red/runtime/nodes/registry/localfilesystem.js
index 26562c50d..c2f0f9359 100644
--- a/red/runtime/nodes/registry/localfilesystem.js
+++ b/red/runtime/nodes/registry/localfilesystem.js
@@ -115,12 +115,26 @@ function getLocalNodeFiles(dir) {
function scanDirForNodesModules(dir,moduleName) {
var results = [];
+ var scopeName;
try {
var files = fs.readdirSync(dir);
+ if (moduleName) {
+ var m = /^(?:(@[^/]+)[/])?([^@/]+)/.exec(moduleName);
+ if (m) {
+ scopeName = m[1];
+ moduleName = m[2];
+ }
+ }
for (var i=0;i\n John\n Smith\n');
+ var index = msg.foo.indexOf('\n John\n Smith\n');
index.should.be.above(-1);
done();
});
var obj = {"employees":{"firstName":["John"],"lastName":["Smith"] }};
- n1.receive({payload:obj, topic:"bar", options:{headless:true}});
+ n1.receive({foo:obj, topic:"bar", options:{headless:true}});
});
});
@@ -133,7 +153,7 @@ describe('XML node', function() {
},200);
});
});
-
+
it('should log an error if asked to parse something thats not xml or js', function(done) {
var flow = [{id:"n1",type:"xml",wires:[["n2"]],func:"return msg;"},
{id:"n2", type:"helper"}];
diff --git a/test/nodes/core/parsers/70-YAML_spec.js b/test/nodes/core/parsers/70-YAML_spec.js
index 9055efa3d..9f2fa7ec5 100644
--- a/test/nodes/core/parsers/70-YAML_spec.js
+++ b/test/nodes/core/parsers/70-YAML_spec.js
@@ -55,6 +55,24 @@ describe('YAML node', function() {
});
});
+ it('should convert a valid yaml string to a javascript object - using another property', function(done) {
+ var flow = [{id:"yn1",type:"yaml",property:"foo",wires:[["yn2"]],func:"return msg;"},
+ {id:"yn2", type:"helper"}];
+ helper.load(yamlNode, flow, function() {
+ var yn1 = helper.getNode("yn1");
+ var yn2 = helper.getNode("yn2");
+ yn2.on("input", function(msg) {
+ msg.should.have.property('topic', 'bar');
+ msg.foo.should.have.property('employees');
+ msg.foo.employees[0].should.have.property('firstName', 'John');
+ msg.foo.employees[0].should.have.property('lastName', 'Smith');
+ done();
+ });
+ var yamlString = "employees:\n - firstName: John\n lastName: Smith\n";
+ yn1.receive({foo:yamlString,topic: "bar"});
+ });
+ });
+
it('should convert a javascript object to a yaml string', function(done) {
var flow = [{id:"yn1",type:"yaml",wires:[["yn2"]],func:"return msg;"},
{id:"yn2", type:"helper"}];
@@ -70,6 +88,21 @@ describe('YAML node', function() {
});
});
+ it('should convert a javascript object to a yaml string - using another property', function(done) {
+ var flow = [{id:"yn1",type:"yaml",property:"foo",wires:[["yn2"]],func:"return msg;"},
+ {id:"yn2", type:"helper"}];
+ helper.load(yamlNode, flow, function() {
+ var yn1 = helper.getNode("yn1");
+ var yn2 = helper.getNode("yn2");
+ yn2.on("input", function(msg) {
+ should.equal(msg.foo, "employees:\n - firstName: John\n lastName: Smith\n");
+ done();
+ });
+ var obj = {employees:[{firstName:"John", lastName:"Smith"}]};
+ yn1.receive({foo:obj});
+ });
+ });
+
it('should convert an array to a yaml string', function(done) {
var flow = [{id:"yn1",type:"yaml",wires:[["yn2"]],func:"return msg;"},
{id:"yn2", type:"helper"}];
diff --git a/test/red/runtime/nodes/registry/installer_spec.js b/test/red/runtime/nodes/registry/installer_spec.js
index de401316c..9b8990057 100644
--- a/test/red/runtime/nodes/registry/installer_spec.js
+++ b/test/red/runtime/nodes/registry/installer_spec.js
@@ -19,6 +19,7 @@ var sinon = require("sinon");
var when = require("when");
var path = require("path");
var fs = require('fs');
+var EventEmitter = require('events');
var child_process = require('child_process');
var installer = require("../../../../../red/runtime/nodes/registry/installer");
@@ -31,6 +32,9 @@ describe('nodes/registry/installer', function() {
installer.init({});
});
afterEach(function() {
+ if (child_process.spawn.restore) {
+ child_process.spawn.restore();
+ }
if (child_process.execFile.restore) {
child_process.execFile.restore();
}
@@ -58,8 +62,15 @@ describe('nodes/registry/installer', function() {
describe("installs module", function() {
it("rejects when npm returns a 404", function(done) {
- sinon.stub(child_process,"execFile",function(cmd,args,opt,cb) {
- cb(new Error(),""," 404 this_wont_exist");
+ sinon.stub(child_process,"spawn",function(cmd,args,opt) {
+ var ee = new EventEmitter();
+ ee.stdout = new EventEmitter();
+ ee.stderr = new EventEmitter();
+ setTimeout(function() {
+ ee.stderr.emit('data'," 404 this_wont_exist");
+ ee.emit('close',1);
+ },10)
+ return ee;
});
installer.installModule("this_wont_exist").otherwise(function(err) {
@@ -68,8 +79,15 @@ describe('nodes/registry/installer', function() {
});
});
it("rejects when npm does not find specified version", function(done) {
- sinon.stub(child_process,"execFile",function(cmd,args,opt,cb) {
- cb(new Error(),""," version not found: this_wont_exist@0.1.2");
+ sinon.stub(child_process,"spawn",function(cmd,args,opt) {
+ var ee = new EventEmitter();
+ ee.stdout = new EventEmitter();
+ ee.stderr = new EventEmitter();
+ setTimeout(function() {
+ ee.stderr.emit('data'," version not found: this_wont_exist@0.1.2");
+ ee.emit('close',1);
+ },10)
+ return ee;
});
sinon.stub(typeRegistry,"getModuleInfo", function() {
return {
@@ -94,8 +112,15 @@ describe('nodes/registry/installer', function() {
});
});
it("rejects with generic error", function(done) {
- sinon.stub(child_process,"execFile",function(cmd,args,opt,cb) {
- cb(new Error("test_error"),"","");
+ sinon.stub(child_process,"spawn",function(cmd,args,opt,cb) {
+ var ee = new EventEmitter();
+ ee.stdout = new EventEmitter();
+ ee.stderr = new EventEmitter();
+ setTimeout(function() {
+ ee.stderr.emit('data'," kaboom!");
+ ee.emit('close',1);
+ },10)
+ return ee;
});
installer.installModule("this_wont_exist").then(function() {
@@ -106,8 +131,14 @@ describe('nodes/registry/installer', function() {
});
it("succeeds when module is found", function(done) {
var nodeInfo = {nodes:{module:"foo",types:["a"]}};
- sinon.stub(child_process,"execFile",function(cmd,args,opt,cb) {
- cb(null,"","");
+ sinon.stub(child_process,"spawn",function(cmd,args,opt) {
+ var ee = new EventEmitter();
+ ee.stdout = new EventEmitter();
+ ee.stderr = new EventEmitter();
+ setTimeout(function() {
+ ee.emit('close',0);
+ },10)
+ return ee;
});
var addModule = sinon.stub(registry,"addModule",function(md) {
return when.resolve(nodeInfo);
@@ -146,8 +177,14 @@ describe('nodes/registry/installer', function() {
return when.resolve(nodeInfo);
});
var resourcesDir = path.resolve(path.join(__dirname,"..","resources","local","TestNodeModule","node_modules","TestNodeModule"));
- sinon.stub(child_process,"execFile",function(cmd,args,opt,cb) {
- cb(null,"","");
+ sinon.stub(child_process,"spawn",function(cmd,args,opt) {
+ var ee = new EventEmitter();
+ ee.stdout = new EventEmitter();
+ ee.stderr = new EventEmitter();
+ setTimeout(function() {
+ ee.emit('close',0);
+ },10)
+ return ee;
});
installer.installModule(resourcesDir).then(function(info) {
info.should.eql(nodeInfo);