mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Merge branch 'dev' into get-got
This commit is contained in:
@@ -510,6 +510,36 @@ describe('inject node', function() {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should inject custom properties in message', function (done) {
|
||||
//n1: inject node with { topic:"static", payload:"static", bool1:true, str1:"1" }
|
||||
var flow = [{id: "n1", type: "inject", props: [{p:"payload", v:"static", vt:"str"}, {p:"topic", v:"static", vt:"str"}, {p:"bool1", v:"true", vt:"bool"}, {p:"str1", v:"1", vt:"str"}], wires: [["n2"]], z: "flow"},
|
||||
{id: "n2", type: "helper"}];
|
||||
helper.load(injectNode, flow, function () {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function (msg) {
|
||||
try {
|
||||
msg.should.not.have.property("payload"); //payload removed
|
||||
msg.should.have.property("topic", "t_override"); //changed value to t_override
|
||||
msg.should.have.property("str1", 1);//changed type from str to num
|
||||
msg.should.have.property("num1", 1);//new prop
|
||||
msg.should.have.property("bool1", false);//changed value to false
|
||||
done();
|
||||
} catch (err) {
|
||||
done(err);
|
||||
}
|
||||
});
|
||||
n1.receive({ __user_inject_props__: [
|
||||
{p:"topic", v:"t_override", vt:"str"}, //change value to t_override
|
||||
{p:"str1", v:"1", vt:"num"}, //change type
|
||||
{p:"num1", v:"1", vt:"num"}, //new prop
|
||||
{p:"bool1", v:"false", vt:"bool"}, //change value to false
|
||||
]});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should inject multiple properties using legacy props if needed', function (done) {
|
||||
var flow = [{id: "n1", type: "inject", payload:"123", payloadType:"num", topic:"foo", props: [{p:"topic", vt:"str"}, {p:"payload"}], wires: [["n2"]], z: "flow"},
|
||||
{id: "n2", type: "helper"}];
|
||||
@@ -592,6 +622,46 @@ describe('inject node', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should inject custom properties in posted message', function(done) {
|
||||
var flow = [{id:"n1", type:"inject", payloadType:"str", topic: "t4",payload:"hello", wires:[["n4"]] },
|
||||
{ id:"n4", type:"helper"}];
|
||||
helper.load(injectNode, flow, function() {
|
||||
var n4 = helper.getNode("n4");
|
||||
n4.on("input", function(msg) {
|
||||
msg.should.not.have.property("payload"); //payload removed
|
||||
msg.should.have.property("topic", "t_override"); //changed value to t_override
|
||||
msg.should.have.property("str1", "1"); //injected prop
|
||||
msg.should.have.property("num1", 1); //injected prop
|
||||
msg.should.have.property("bool1", true); //injected prop
|
||||
|
||||
helper.clearFlows().then(function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
try {
|
||||
helper.request()
|
||||
.post('/inject/n1')
|
||||
.send({ __user_inject_props__: [
|
||||
{p:"topic", v:"t_override", vt:"str"}, //change value to t_override
|
||||
{p:"str1", v:"1", vt:"str"}, //new prop
|
||||
{p:"num1", v:"1", vt:"num"}, //new prop
|
||||
{p:"bool1", v:"true", vt:"bool"}, //new prop
|
||||
]})
|
||||
.expect(200).end(function(err) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
return helper.clearFlows()
|
||||
.then(function () {
|
||||
done(err);
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch(err) {
|
||||
done(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail for invalid node', function(done) {
|
||||
helper.request().post('/inject/invalid').expect(404).end(done);
|
||||
});
|
||||
|
@@ -104,7 +104,7 @@ describe('debug node', function() {
|
||||
}, function(msg) {
|
||||
JSON.parse(msg).should.eql([{
|
||||
topic:"debug",
|
||||
data:{id:"n1",msg:'{\n "payload": "test"\n}',format:"Object",path:"global"}
|
||||
data:{id:"n1",msg:'{"payload":"test"}',format:"Object",path:"global"}
|
||||
}]);
|
||||
}, done);
|
||||
});
|
||||
@@ -119,7 +119,7 @@ describe('debug node', function() {
|
||||
}, function(msg) {
|
||||
JSON.parse(msg).should.eql([{
|
||||
topic:"debug",
|
||||
data:{id:"n1",msg:'{\n "payload": "test"\n}',format:"Object",path:"global"}
|
||||
data:{id:"n1",msg:'{"payload":"test"}',format:"Object",path:"global"}
|
||||
}]);
|
||||
}, function() {
|
||||
try {
|
||||
@@ -259,7 +259,7 @@ describe('debug node', function() {
|
||||
}, function(msg) {
|
||||
JSON.parse(msg).should.eql([{
|
||||
topic:"debug",
|
||||
data:{id:"n1",msg:'{\n "type": "foo"\n}',property:"payload",format:"Object",path:"global"}
|
||||
data:{id:"n1",msg:'{"type":"foo"}',property:"payload",format:"Object",path:"global"}
|
||||
}]);
|
||||
}, done);
|
||||
});
|
||||
@@ -274,7 +274,7 @@ describe('debug node', function() {
|
||||
}, function(msg) {
|
||||
JSON.parse(msg).should.eql([{
|
||||
topic:"debug",
|
||||
data:{id:"n1",msg: '[\n 0,\n 1,\n 2,\n 3\n]',format:"array[4]",
|
||||
data:{id:"n1",msg: '[0,1,2,3]',format:"array[4]",
|
||||
property:"payload",path:"global"}
|
||||
}]);
|
||||
}, done);
|
||||
@@ -294,7 +294,7 @@ describe('debug node', function() {
|
||||
topic:"debug",
|
||||
data:{
|
||||
id:"n1",
|
||||
msg:'{\n "name": "bar",\n "o": "[Circular ~]"\n}',
|
||||
msg:'{"name":"bar","o":"[Circular ~]"}',
|
||||
property:"payload",format:"Object",path:"global"
|
||||
}
|
||||
}]);
|
||||
@@ -310,7 +310,7 @@ describe('debug node', function() {
|
||||
n1.emit("input", {payload: {type:'foo'}});
|
||||
}, function(msg) {
|
||||
JSON.parse(msg).should.eql([{
|
||||
topic:"debug",data:{id:"n1",msg:'{\n "type": "foo"\n}',property:"payload",format:"Object",path:"global"}
|
||||
topic:"debug",data:{id:"n1",msg:'{"type":"foo"}',property:"payload",format:"Object",path:"global"}
|
||||
}]);
|
||||
}, function() {
|
||||
try {
|
||||
@@ -406,7 +406,7 @@ describe('debug node', function() {
|
||||
topic:"debug",
|
||||
data:{
|
||||
id:"n1",
|
||||
msg:'{\n "foo": "'+Array(1001).join("X")+'..."\n}',
|
||||
msg:'{"foo":"'+Array(1001).join("X")+'..."}',
|
||||
property:"payload",
|
||||
format:"Object",
|
||||
path:"global"
|
||||
@@ -433,7 +433,7 @@ describe('debug node', function() {
|
||||
type: "array",
|
||||
data: Array(1000).fill("X"),
|
||||
length: 1001
|
||||
},null," "),
|
||||
}),
|
||||
property:"payload",
|
||||
format:"array[1001]",
|
||||
path:"global"
|
||||
@@ -462,7 +462,7 @@ describe('debug node', function() {
|
||||
data: Array(1000).fill("X"),
|
||||
length: 1001
|
||||
}
|
||||
},null," "),
|
||||
}),
|
||||
property:"payload",
|
||||
format:"Object",
|
||||
path:"global"
|
||||
@@ -513,7 +513,7 @@ describe('debug node', function() {
|
||||
__enc__: true,
|
||||
length: 1001
|
||||
}
|
||||
},null," "),
|
||||
}),
|
||||
property:"payload",
|
||||
format:"Object",
|
||||
path:"global"
|
||||
|
@@ -1134,4 +1134,20 @@ describe('switch Node', function() {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should handle empty rule', function(done) {
|
||||
var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[],checkall:true,outputs:0,wires:[]}];
|
||||
helper.load(switchNode, flow, function() {
|
||||
var n1 = helper.getNode("switchNode1");
|
||||
setTimeout(function() {
|
||||
var logEvents = helper.log().args.filter(function (evt) {
|
||||
return evt[0].type == "switch";
|
||||
});
|
||||
if (logEvents.length === 0) {
|
||||
done();
|
||||
}
|
||||
}, 150);
|
||||
n1.receive({payload:1});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -18,6 +18,7 @@ var should = require("should");
|
||||
|
||||
var delayNode = require("nr-test-utils").require("@node-red/nodes/core/function/89-delay.js");
|
||||
var helper = require("node-red-node-test-helper");
|
||||
var RED = require("nr-test-utils").require("node-red/lib/red");
|
||||
|
||||
var GRACE_PERCENTAGE=10;
|
||||
|
||||
@@ -35,6 +36,7 @@ describe('delay Node', function() {
|
||||
});
|
||||
|
||||
afterEach(function(done) {
|
||||
RED.settings.nodeMessageBufferMaxLength = 0;
|
||||
helper.unload();
|
||||
helper.stopServer(done);
|
||||
});
|
||||
@@ -150,6 +152,7 @@ describe('delay Node', function() {
|
||||
* We send a message, take a timestamp then when the message is received by the helper node, we take another timestamp.
|
||||
* Then check if the message has been delayed by the expected amount.
|
||||
*/
|
||||
|
||||
it('delays the message in seconds', function(done) {
|
||||
genericDelayTest(0.5, "seconds", done);
|
||||
});
|
||||
@@ -176,14 +179,14 @@ describe('delay Node', function() {
|
||||
* @param nbUnit - the multiple of the unit, aLimit Message for nbUnit Seconds
|
||||
* @param runtimeInMillis - when to terminate run and count messages received
|
||||
*/
|
||||
function genericRateLimitSECONDSTest(aLimit, nbUnit, runtimeInMillis, done) {
|
||||
function genericRateLimitSECONDSTest(aLimit, nbUnit, runtimeInMillis, rateValue, done) {
|
||||
var flow = [{"id":"delayNode1","type":"delay","nbRateUnits":nbUnit,"name":"delayNode","pauseType":"rate","timeout":5,"timeoutUnits":"seconds","rate":aLimit,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[["helperNode1"]]},
|
||||
{id:"helperNode1", type:"helper", wires:[]}];
|
||||
helper.load(delayNode, flow, function() {
|
||||
var delayNode1 = helper.getNode("delayNode1");
|
||||
var helperNode1 = helper.getNode("helperNode1");
|
||||
var receivedMessagesStack = [];
|
||||
var rate = 1000/aLimit;
|
||||
var rate = 1000 / aLimit * nbUnit;
|
||||
|
||||
var receiveTimestamp;
|
||||
|
||||
@@ -201,7 +204,7 @@ describe('delay Node', function() {
|
||||
|
||||
var i = 0;
|
||||
for (; i < possibleMaxMessageCount + 1; i++) {
|
||||
delayNode1.receive({payload:i});
|
||||
delayNode1.receive({ payload: i, rate: rateValue });
|
||||
}
|
||||
|
||||
setTimeout(function() {
|
||||
@@ -224,17 +227,22 @@ describe('delay Node', function() {
|
||||
}
|
||||
|
||||
it('limits the message rate to 1 per second', function(done) {
|
||||
genericRateLimitSECONDSTest(1, 1, 1500, done);
|
||||
genericRateLimitSECONDSTest(1, 1, 1500, null, done);
|
||||
});
|
||||
|
||||
it('limits the message rate to 1 per 2 seconds', function(done) {
|
||||
this.timeout(6000);
|
||||
genericRateLimitSECONDSTest(1, 2, 3000, done);
|
||||
genericRateLimitSECONDSTest(1, 2, 3000, null, done);
|
||||
});
|
||||
|
||||
it('limits the message rate to 2 per seconds, 2 seconds', function(done) {
|
||||
this.timeout(6000);
|
||||
genericRateLimitSECONDSTest(2, 1, 2100, done);
|
||||
genericRateLimitSECONDSTest(2, 1, 2100, null, done);
|
||||
});
|
||||
|
||||
it('limits the message rate using msg.rate', function (done) {
|
||||
RED.settings.nodeMessageBufferMaxLength = 3;
|
||||
genericRateLimitSECONDSTest(1, 1, 1500, 2000, done);
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -243,7 +251,7 @@ describe('delay Node', function() {
|
||||
* @param nbUnit - the multiple of the unit, aLimit Message for nbUnit Seconds
|
||||
* @param runtimeInMillis - when to terminate run and count messages received
|
||||
*/
|
||||
function dropRateLimitSECONDSTest(aLimit, nbUnit, runtimeInMillis, done) {
|
||||
function dropRateLimitSECONDSTest(aLimit, nbUnit, runtimeInMillis, rateValue, done) {
|
||||
var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"rate","timeout":5,"nbRateUnits":nbUnit,"timeoutUnits":"seconds","rate":aLimit,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"wires":[["helperNode1"]]},
|
||||
{id:"helperNode1", type:"helper", wires:[]}];
|
||||
helper.load(delayNode, flow, function() {
|
||||
@@ -269,7 +277,7 @@ describe('delay Node', function() {
|
||||
var possibleMaxMessageCount = Math.ceil(aLimit * (runtimeInMillis / 1000) + aLimit); // +aLimit as at the start of the 2nd period, we're allowing the 3rd burst
|
||||
|
||||
var i = 0;
|
||||
delayNode1.receive({payload:i});
|
||||
delayNode1.receive({ payload: i, rate: rateValue });
|
||||
i++;
|
||||
for (; i < possibleMaxMessageCount + 1; i++) {
|
||||
setTimeout(function() {
|
||||
@@ -306,17 +314,23 @@ describe('delay Node', function() {
|
||||
|
||||
it('limits the message rate to 1 per second, 4 seconds, with drop', function(done) {
|
||||
this.timeout(6000);
|
||||
dropRateLimitSECONDSTest(1, 1, 4000, done);
|
||||
dropRateLimitSECONDSTest(1, 1, 4000, null, done);
|
||||
});
|
||||
|
||||
it('limits the message rate to 1 per 2 seconds, 4 seconds, with drop', function(done) {
|
||||
this.timeout(6000);
|
||||
dropRateLimitSECONDSTest(1, 2, 4500, done);
|
||||
dropRateLimitSECONDSTest(1, 2, 4500, null, done);
|
||||
});
|
||||
|
||||
it('limits the message rate to 2 per second, 5 seconds, with drop', function(done) {
|
||||
this.timeout(6000);
|
||||
dropRateLimitSECONDSTest(2, 1, 5000, done);
|
||||
dropRateLimitSECONDSTest(2, 1, 5000, null, done);
|
||||
});
|
||||
|
||||
it('limits the message rate with drop using msg.rate', function (done) {
|
||||
this.timeout(6000);
|
||||
RED.settings.nodeMessageBufferMaxLength = 3;
|
||||
dropRateLimitSECONDSTest(2, 1, 5000, 1000, done);
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -719,7 +733,7 @@ describe('delay Node', function() {
|
||||
setImmediate( function() { delayNode1.receive({reset:true}); }); // reset the queue
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
/* Messaging API support */
|
||||
function mapiDoneTestHelper(done, pauseType, drop, msgAndTimings) {
|
||||
const completeNode = require("nr-test-utils").require("@node-red/nodes/core/common/24-complete.js");
|
||||
@@ -747,7 +761,7 @@ describe('delay Node', function() {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
it('calls done when queued message is emitted (type: delay)', function(done) {
|
||||
mapiDoneTestHelper(done, "delay", false, [{msg:{payload:1}, avr:1000, var:100}]);
|
||||
});
|
||||
|
@@ -541,13 +541,17 @@ describe('exec node', function() {
|
||||
var n2 = helper.getNode("n2");
|
||||
var n3 = helper.getNode("n3");
|
||||
var n4 = helper.getNode("n4");
|
||||
var payload = "";
|
||||
n2.on("input", function(msg) {
|
||||
//console.log(msg);
|
||||
try {
|
||||
msg.should.have.property("payload");
|
||||
msg.payload.should.be.a.String();
|
||||
msg.payload.should.equal(expected);
|
||||
done();
|
||||
payload += msg.payload;
|
||||
if (payload.endsWith("\n")) {
|
||||
payload.should.equal(expected);
|
||||
done();
|
||||
}
|
||||
}
|
||||
catch(err) { done(err); }
|
||||
});
|
||||
@@ -567,6 +571,7 @@ describe('exec node', function() {
|
||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||
expected = "12345 deg C\n";
|
||||
}
|
||||
var payload = "";
|
||||
|
||||
helper.load(execNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
@@ -578,8 +583,11 @@ describe('exec node', function() {
|
||||
try {
|
||||
msg.should.have.property("payload");
|
||||
msg.payload.should.be.a.String();
|
||||
msg.payload.should.equal(expected);
|
||||
done();
|
||||
payload += msg.payload;
|
||||
if (payload.endsWith("\n")) {
|
||||
payload.should.equal(expected);
|
||||
done();
|
||||
}
|
||||
}
|
||||
catch(err) { done(err); }
|
||||
});
|
||||
@@ -661,8 +669,16 @@ describe('exec node', function() {
|
||||
};
|
||||
|
||||
n2.on("input", function(msg) {
|
||||
messages[0] = msg;
|
||||
completeTest();
|
||||
var payload = msg.payload;
|
||||
if (messages[0]) {
|
||||
messages[0].payload += payload;
|
||||
}
|
||||
else {
|
||||
messages[0] = msg;
|
||||
}
|
||||
if (payload.endsWith("\n")) {
|
||||
completeTest();
|
||||
}
|
||||
});
|
||||
n4.on("input", function(msg) {
|
||||
messages[1] = msg;
|
||||
@@ -869,8 +885,16 @@ describe('exec node', function() {
|
||||
};
|
||||
|
||||
n2.on("input", function(msg) {
|
||||
messages[0] = msg;
|
||||
completeTest();
|
||||
var payload = msg.payload;
|
||||
if (messages[0]) {
|
||||
messages[0].payload += payload;
|
||||
}
|
||||
else {
|
||||
messages[0] = msg;
|
||||
}
|
||||
if (payload.endsWith("\n")) {
|
||||
completeTest();
|
||||
}
|
||||
});
|
||||
n4.on("input", function(msg) {
|
||||
messages[1] = msg;
|
||||
|
@@ -87,6 +87,57 @@ describe('CSV node', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should convert a simple string to a javascript object with | separator (no template)', function(done) {
|
||||
var flow = [ { id:"n1", type:"csv", sep:"|", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(csvNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
msg.should.have.property('payload', { col1: 1, col2: 2, col3: 3, col4: 4 });
|
||||
msg.should.have.property('columns', "col1,col2,col3,col4");
|
||||
check_parts(msg, 0, 1);
|
||||
done();
|
||||
});
|
||||
var testString = "1|2|3|4"+String.fromCharCode(10);
|
||||
n1.emit("input", {payload:testString});
|
||||
});
|
||||
});
|
||||
|
||||
it('should convert a simple string to a javascript object with tab separator (with template)', function(done) {
|
||||
var flow = [ { id:"n1", type:"csv", sep:"\t", temp:"A,B,,D", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(csvNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
msg.should.have.property('payload', { A: 1, B: 2, D: 4 });
|
||||
msg.should.have.property('columns', "A,B,D");
|
||||
check_parts(msg, 0, 1);
|
||||
done();
|
||||
});
|
||||
var testString = "1\t2\t3\t4"+String.fromCharCode(10);
|
||||
n1.emit("input", {payload:testString});
|
||||
});
|
||||
});
|
||||
|
||||
it('should convert a simple string to a javascript object with space separator (with spaced template)', function(done) {
|
||||
var flow = [ { id:"n1", type:"csv", sep:" ", temp:"A, B, , D", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(csvNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
msg.should.have.property('payload', { A: 1, B: 2, D: 4 });
|
||||
msg.should.have.property('columns', "A,B,D");
|
||||
check_parts(msg, 0, 1);
|
||||
done();
|
||||
});
|
||||
var testString = "1 2 3 4"+String.fromCharCode(10);
|
||||
n1.emit("input", {payload:testString});
|
||||
});
|
||||
});
|
||||
|
||||
it('should remove quotes and whitespace from template', function(done) {
|
||||
var flow = [ { id:"n1", type:"csv", temp:'"a", "b" , " c "," d " ', wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
@@ -170,6 +221,58 @@ describe('CSV node', function() {
|
||||
n1.emit("input", {payload:testString});
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow passing in a template as first line of CSV (not comma)', function(done) {
|
||||
var flow = [ { id:"n1", type:"csv", temp:"", hdrin:true, sep:";", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(csvNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
msg.should.have.property('payload', { a: 1, "b b":2, "c;c":3, "d, d": 4 });
|
||||
msg.should.have.property('columns', 'a,b b,c;c,"d, d"');
|
||||
check_parts(msg, 0, 1);
|
||||
done();
|
||||
});
|
||||
var testString = 'a;b b;"c;c";" d, d "'+"\n"+"1;2;3;4"+String.fromCharCode(10);
|
||||
n1.emit("input", {payload:testString});
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow passing in a template as first line of CSV (special char /)', function(done) {
|
||||
var flow = [ { id:"n1", type:"csv", temp:"", hdrin:true, sep:"/", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(csvNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
msg.should.have.property('payload', { a: 1, "b b":2, "c/c":3, "d, d": 4 });
|
||||
msg.should.have.property('columns', 'a,b b,c/c,"d, d"');
|
||||
check_parts(msg, 0, 1);
|
||||
done();
|
||||
});
|
||||
var testString = 'a/b b/"c/c"/" d, d "'+"\n"+"1/2/3/4"+String.fromCharCode(10);
|
||||
n1.emit("input", {payload:testString});
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow passing in a template as first line of CSV (special char \\)', function(done) {
|
||||
var flow = [ { id:"n1", type:"csv", temp:"", hdrin:true, sep:"\\", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(csvNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
msg.should.have.property('payload', { a: 1, "b b":2, "c\\c":3, "d, d": 4 });
|
||||
msg.should.have.property('columns', 'a,b b,c\\c,"d, d"');
|
||||
check_parts(msg, 0, 1);
|
||||
done();
|
||||
});
|
||||
var testString = 'a\\b b\\"c\\c"\\" d, d "'+"\n"+"1\\2\\3\\4"+String.fromCharCode(10);
|
||||
n1.emit("input", {payload:testString});
|
||||
});
|
||||
});
|
||||
|
||||
it('should leave numbers starting with 0, e and + as strings (except 0.)', function(done) {
|
||||
var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d,e,f,g", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
@@ -609,6 +712,24 @@ describe('CSV node', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should convert a simple object back to a tsv using a tab as a separator', function(done) {
|
||||
var flow = [ { id:"n1", type:"csv", temp:"", sep:"\t", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(csvNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
try {
|
||||
msg.should.have.property('payload', '1\tfoo\t"ba""r"\tdi,ng\n');
|
||||
done();
|
||||
}
|
||||
catch(e) { done(e); }
|
||||
});
|
||||
var testJson = { d:1, b:"foo", c:"ba\"r", a:"di,ng" };
|
||||
n1.emit("input", {payload:testJson});
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle a template with spaces in the property names', function(done) {
|
||||
var flow = [ { id:"n1", type:"csv", temp:"a,b o,c p,,e", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
|
@@ -60,9 +60,13 @@ describe('HTML node', function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
msg.should.have.property('topic', 'bar');
|
||||
should.equal(msg.payload, 'This is a test page for node 70-HTML');
|
||||
done();
|
||||
try {
|
||||
msg.should.have.property('topic', 'bar');
|
||||
should.equal(msg.payload, 'This is a test page for node 70-HTML');
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err)
|
||||
}
|
||||
});
|
||||
n1.receive({payload:data,topic:"bar",select:"h1"});
|
||||
});
|
||||
@@ -78,9 +82,13 @@ describe('HTML node', function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
msg.should.have.property('topic', 'bar');
|
||||
msg.foo[0].should.equal('This is a test page for node 70-HTML');
|
||||
done();
|
||||
try {
|
||||
msg.should.have.property('topic', 'bar');
|
||||
msg.foo[0].should.equal('This is a test page for node 70-HTML');
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err)
|
||||
}
|
||||
});
|
||||
n1.receive({foo:data,topic:"bar",select:"h1"});
|
||||
});
|
||||
@@ -96,9 +104,13 @@ describe('HTML node', function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
msg.should.have.property('topic', 'bar');
|
||||
msg.bar[0].should.equal('This is a test page for node 70-HTML');
|
||||
done();
|
||||
try {
|
||||
msg.should.have.property('topic', 'bar');
|
||||
msg.bar[0].should.equal('This is a test page for node 70-HTML');
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err)
|
||||
}
|
||||
});
|
||||
n1.receive({foo:data,topic:"bar"});
|
||||
});
|
||||
@@ -114,10 +126,14 @@ describe('HTML node', function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
msg.should.have.property('topic', 'bar');
|
||||
msg.should.have.property('payload');
|
||||
msg.payload.should.be.empty;
|
||||
done();
|
||||
try {
|
||||
msg.should.have.property('topic', 'bar');
|
||||
msg.should.have.property('payload');
|
||||
msg.payload.should.be.empty;
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err)
|
||||
}
|
||||
});
|
||||
n1.receive({payload:data,topic:"bar",select:"h4"});
|
||||
});
|
||||
@@ -133,9 +149,13 @@ describe('HTML node', function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
msg.should.have.property('topic', 'bar');
|
||||
should.equal(msg.payload, 'There\'s nothing to read here.');
|
||||
done();
|
||||
try {
|
||||
msg.should.have.property('topic', 'bar');
|
||||
should.equal(msg.payload, 'There\'s nothing to read here.');
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err)
|
||||
}
|
||||
});
|
||||
n1.receive({payload:data,topic: "bar"});
|
||||
});
|
||||
@@ -151,10 +171,14 @@ describe('HTML node', function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
msg.should.have.property('topic', 'bar');
|
||||
msg.payload[0].indexOf("<li>Blue</li>").should.be.above(-1);
|
||||
msg.payload[0].indexOf("<li>Red</li>").should.be.above(-1);
|
||||
done();
|
||||
try {
|
||||
msg.should.have.property('topic', 'bar');
|
||||
msg.payload[0].indexOf("<li>Blue</li>").should.be.above(-1);
|
||||
msg.payload[0].indexOf("<li>Red</li>").should.be.above(-1);
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err)
|
||||
}
|
||||
});
|
||||
n1.receive({payload:data,topic: "bar"});
|
||||
});
|
||||
@@ -170,11 +194,14 @@ describe('HTML node', function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
msg.should.have.property('topic', 'bar');
|
||||
msg.payload[0].indexOf("Blue").should.be.above(-1);
|
||||
msg.payload[0].indexOf("Red").should.be.above(-1);
|
||||
done();
|
||||
|
||||
try {
|
||||
msg.should.have.property('topic', 'bar');
|
||||
msg.payload[0].indexOf("Blue").should.be.above(-1);
|
||||
msg.payload[0].indexOf("Red").should.be.above(-1);
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err)
|
||||
}
|
||||
});
|
||||
n1.receive({payload:data,topic: "bar"});
|
||||
});
|
||||
@@ -190,9 +217,13 @@ describe('HTML node', function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
msg.should.have.property('topic', 'bar');
|
||||
should.equal(msg.payload, '<img src="foo.png"/>');
|
||||
done();
|
||||
try {
|
||||
msg.should.have.property('topic', 'bar');
|
||||
should.equal(msg.payload, '<img src="foo.png"/>');
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err)
|
||||
}
|
||||
});
|
||||
n1.receive({payload:data,topic: "bar"});
|
||||
});
|
||||
@@ -208,10 +239,14 @@ describe('HTML node', function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
msg.should.have.property('payload');
|
||||
msg.payload[0].should.have.property('src','foo.png');
|
||||
msg.should.have.property('topic', 'bar');
|
||||
done();
|
||||
try {
|
||||
msg.should.have.property('payload');
|
||||
msg.payload[0].should.have.property('src','foo.png');
|
||||
msg.should.have.property('topic', 'bar');
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err)
|
||||
}
|
||||
});
|
||||
n1.receive({payload:data,topic: "bar"});
|
||||
});
|
||||
@@ -258,9 +293,13 @@ describe('HTML node', function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
msg.should.have.property('topic', 'bar');
|
||||
msg.should.not.have.property('payload');
|
||||
done();
|
||||
try {
|
||||
msg.should.have.property('topic', 'bar');
|
||||
msg.should.not.have.property('payload');
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err)
|
||||
}
|
||||
});
|
||||
n1.receive({topic: "bar"});
|
||||
});
|
||||
@@ -301,20 +340,25 @@ describe('HTML node', function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
cnt++;
|
||||
msg.should.have.property('topic', 'bar');
|
||||
check_parts(msg, cnt -1, 2);
|
||||
if (cnt !== 1 && cnt !== 2) {
|
||||
return false;
|
||||
}
|
||||
if (cnt === 1) {
|
||||
msg.payload.indexOf("<li>Apple</li>").should.be.above(-1);
|
||||
msg.payload.indexOf("<li>Pear</li>").should.be.above(-1);
|
||||
} else if (cnt === 2) {
|
||||
msg.payload.indexOf("<li>Potato</li>").should.be.above(-1);
|
||||
msg.payload.indexOf("<li>Parsnip</li>").should.be.above(-1);
|
||||
done();
|
||||
try {
|
||||
cnt++;
|
||||
msg.should.have.property('topic', 'bar');
|
||||
check_parts(msg, cnt -1, 2);
|
||||
if (cnt !== 1 && cnt !== 2) {
|
||||
return false;
|
||||
}
|
||||
if (cnt === 1) {
|
||||
msg.payload.indexOf("<li>Apple</li>").should.be.above(-1);
|
||||
msg.payload.indexOf("<li>Pear</li>").should.be.above(-1);
|
||||
} else if (cnt === 2) {
|
||||
msg.payload.indexOf("<li>Potato</li>").should.be.above(-1);
|
||||
msg.payload.indexOf("<li>Parsnip</li>").should.be.above(-1);
|
||||
done();
|
||||
}
|
||||
} catch(err) {
|
||||
done(err)
|
||||
}
|
||||
|
||||
});
|
||||
n1.receive({payload:data,topic: "bar"});
|
||||
});
|
||||
@@ -331,19 +375,23 @@ describe('HTML node', function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
cnt++;
|
||||
msg.should.have.property('topic', 'bar');
|
||||
check_parts(msg, cnt -1, 2);
|
||||
if (cnt !== 1 && cnt !== 2) {
|
||||
return false;
|
||||
}
|
||||
if (cnt === 1) {
|
||||
msg.foo.indexOf("<li>Apple</li>").should.be.above(-1);
|
||||
msg.foo.indexOf("<li>Pear</li>").should.be.above(-1);
|
||||
} else if (cnt === 2) {
|
||||
msg.foo.indexOf("<li>Potato</li>").should.be.above(-1);
|
||||
msg.foo.indexOf("<li>Parsnip</li>").should.be.above(-1);
|
||||
done();
|
||||
try {
|
||||
cnt++;
|
||||
msg.should.have.property('topic', 'bar');
|
||||
check_parts(msg, cnt -1, 2);
|
||||
if (cnt !== 1 && cnt !== 2) {
|
||||
return false;
|
||||
}
|
||||
if (cnt === 1) {
|
||||
msg.foo.indexOf("<li>Apple</li>").should.be.above(-1);
|
||||
msg.foo.indexOf("<li>Pear</li>").should.be.above(-1);
|
||||
} else if (cnt === 2) {
|
||||
msg.foo.indexOf("<li>Potato</li>").should.be.above(-1);
|
||||
msg.foo.indexOf("<li>Parsnip</li>").should.be.above(-1);
|
||||
done();
|
||||
}
|
||||
} catch(err) {
|
||||
done(err)
|
||||
}
|
||||
});
|
||||
n1.receive({foo:data, topic:"bar"});
|
||||
@@ -360,19 +408,23 @@ describe('HTML node', function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
cnt++;
|
||||
msg.should.have.property('topic', 'bar');
|
||||
check_parts(msg, cnt -1, 2);
|
||||
if (cnt !== 1 && cnt !== 2) {
|
||||
return false;
|
||||
}
|
||||
if (cnt === 1) {
|
||||
msg.payload.indexOf("Apple").should.be.above(-1);
|
||||
msg.payload.indexOf("Pear").should.be.above(-1);
|
||||
} else if (cnt === 2) {
|
||||
msg.payload.indexOf("Potato").should.be.above(-1);
|
||||
msg.payload.indexOf("Parsnip").should.be.above(-1);
|
||||
done();
|
||||
try {
|
||||
cnt++;
|
||||
msg.should.have.property('topic', 'bar');
|
||||
check_parts(msg, cnt -1, 2);
|
||||
if (cnt !== 1 && cnt !== 2) {
|
||||
return false;
|
||||
}
|
||||
if (cnt === 1) {
|
||||
msg.payload.indexOf("Apple").should.be.above(-1);
|
||||
msg.payload.indexOf("Pear").should.be.above(-1);
|
||||
} else if (cnt === 2) {
|
||||
msg.payload.indexOf("Potato").should.be.above(-1);
|
||||
msg.payload.indexOf("Parsnip").should.be.above(-1);
|
||||
done();
|
||||
}
|
||||
} catch(err) {
|
||||
done(err)
|
||||
}
|
||||
});
|
||||
n1.receive({payload:data,topic: "bar"});
|
||||
@@ -389,12 +441,16 @@ describe('HTML node', function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
msg.should.have.property('payload');
|
||||
msg.payload.should.have.property('src','foo.png');
|
||||
msg.should.have.property('topic', 'bar');
|
||||
check_parts(msg, 0, 1);
|
||||
cnt = 2; // frig the answer as only one img tag
|
||||
done();
|
||||
try {
|
||||
msg.should.have.property('payload');
|
||||
msg.payload.should.have.property('src','foo.png');
|
||||
msg.should.have.property('topic', 'bar');
|
||||
check_parts(msg, 0, 1);
|
||||
cnt = 2; // frig the answer as only one img tag
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err)
|
||||
}
|
||||
});
|
||||
n1.receive({payload:data,topic: "bar"});
|
||||
});
|
||||
@@ -411,15 +467,19 @@ describe('HTML node', function() {
|
||||
var n2 = helper.getNode("n2");
|
||||
var prev_msg = undefined;
|
||||
n2.on("input", function(msg) {
|
||||
cnt++;
|
||||
if (prev_msg == undefined) {
|
||||
prev_msg = msg;
|
||||
}
|
||||
else {
|
||||
msg.should.not.equal(prev_msg);
|
||||
}
|
||||
if (cnt == 2) {
|
||||
done();
|
||||
try {
|
||||
cnt++;
|
||||
if (prev_msg == undefined) {
|
||||
prev_msg = msg;
|
||||
}
|
||||
else {
|
||||
msg.should.not.equal(prev_msg);
|
||||
}
|
||||
if (cnt == 2) {
|
||||
done();
|
||||
}
|
||||
} catch(err) {
|
||||
done(err)
|
||||
}
|
||||
});
|
||||
n1.receive({payload:data,topic: "bar"});
|
||||
|
@@ -389,7 +389,7 @@ describe('JSON node', function() {
|
||||
});
|
||||
logEvents.should.have.length(1);
|
||||
logEvents[0][0].should.have.a.property('msg');
|
||||
logEvents[0][0].msg.should.equal("json.errors.schema-error: data.number should be number, data.string should be string");
|
||||
logEvents[0][0].msg.should.startWith("json.errors.schema-error");
|
||||
logEvents[0][0].should.have.a.property('level',helper.log().ERROR);
|
||||
done();
|
||||
} catch(err) { done(err) }
|
||||
@@ -417,7 +417,7 @@ describe('JSON node', function() {
|
||||
});
|
||||
logEvents.should.have.length(1);
|
||||
logEvents[0][0].should.have.a.property('msg');
|
||||
logEvents[0][0].msg.should.equal("json.errors.schema-error: data.number should be number, data.string should be string");
|
||||
logEvents[0][0].msg.should.startWith("json.errors.schema-error");
|
||||
logEvents[0][0].should.have.a.property('level',helper.log().ERROR);
|
||||
done();
|
||||
} catch(err) { done(err) }
|
||||
@@ -445,7 +445,7 @@ describe('JSON node', function() {
|
||||
});
|
||||
logEvents.should.have.length(1);
|
||||
logEvents[0][0].should.have.a.property('msg');
|
||||
logEvents[0][0].msg.should.equal("json.errors.schema-error: data.number should be number, data.string should be string");
|
||||
logEvents[0][0].msg.should.startWith("json.errors.schema-error");
|
||||
logEvents[0][0].should.have.a.property('level',helper.log().ERROR);
|
||||
done();
|
||||
} catch(err) { done(err) }
|
||||
@@ -473,7 +473,7 @@ describe('JSON node', function() {
|
||||
});
|
||||
logEvents.should.have.length(1);
|
||||
logEvents[0][0].should.have.a.property('msg');
|
||||
logEvents[0][0].msg.should.equal("json.errors.schema-error: data.number should be number, data.string should be string");
|
||||
logEvents[0][0].msg.should.startWith("json.errors.schema-error");
|
||||
logEvents[0][0].should.have.a.property('level',helper.log().ERROR);
|
||||
done();
|
||||
} catch(err) { done(err) }
|
||||
|
@@ -22,6 +22,7 @@ var sinon = require("sinon");
|
||||
var iconv = require("iconv-lite");
|
||||
var fileNode = require("nr-test-utils").require("@node-red/nodes/core/storage/10-file.js");
|
||||
var helper = require("node-red-node-test-helper");
|
||||
var RED = require("nr-test-utils").require("node-red/lib/red");
|
||||
|
||||
describe('file Nodes', function() {
|
||||
|
||||
@@ -41,8 +42,9 @@ describe('file Nodes', function() {
|
||||
|
||||
describe('file out Node', function() {
|
||||
|
||||
var relativePathToFile = "50-file-test-file.txt";
|
||||
var resourcesDir = path.join(__dirname,"..","..","..","resources");
|
||||
var fileToTest = path.join(resourcesDir,"50-file-test-file.txt");
|
||||
var fileToTest = path.join(resourcesDir,relativePathToFile);
|
||||
var wait = 250;
|
||||
|
||||
beforeEach(function(done) {
|
||||
@@ -51,6 +53,7 @@ describe('file Nodes', function() {
|
||||
});
|
||||
|
||||
afterEach(function(done) {
|
||||
delete RED.settings.fileWorkingDirectory;
|
||||
fs.removeSync(path.join(resourcesDir,"file-out-node"));
|
||||
helper.unload().then(function() {
|
||||
//fs.unlinkSync(fileToTest);
|
||||
@@ -94,6 +97,30 @@ describe('file Nodes', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should write to a file using RED.settings.fileWorkingDirectory', function(done) {
|
||||
var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":relativePathToFile, "appendNewline":false, "overwriteFile":true, wires: [["helperNode1"]]},
|
||||
{id:"helperNode1", type:"helper"}];
|
||||
helper.load(fileNode, flow, function() {
|
||||
RED.settings.fileWorkingDirectory = resourcesDir;
|
||||
var n1 = helper.getNode("fileNode1");
|
||||
var n2 = helper.getNode("helperNode1");
|
||||
n2.on("input", function(msg) {
|
||||
try {
|
||||
var f = fs.readFileSync(fileToTest);
|
||||
f.should.have.length(4);
|
||||
fs.unlinkSync(fileToTest);
|
||||
msg.should.have.property("payload", "test");
|
||||
done();
|
||||
}
|
||||
catch (e) {
|
||||
done(e);
|
||||
}
|
||||
});
|
||||
n1.receive({payload:"test"});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should write multi-byte string to a file', function(done) {
|
||||
var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":false, "overwriteFile":true, wires: [["helperNode1"]]},
|
||||
{id:"helperNode1", type:"helper"}];
|
||||
@@ -1036,9 +1063,10 @@ describe('file Nodes', function() {
|
||||
|
||||
describe('file in Node', function() {
|
||||
|
||||
var relativePathToFile = "50-file-test-file.txt";
|
||||
var resourcesDir = path.join(__dirname,"..","..","..","resources");
|
||||
var fileToTest = path.join(resourcesDir,"50-file-test-file.txt");
|
||||
var fileToTest2 = "\t"+path.join(resourcesDir,"50-file-test-file.txt")+"\r\n";
|
||||
var fileToTest = path.join(resourcesDir,relativePathToFile);
|
||||
var fileToTest2 = "\t"+path.join(resourcesDir,relativePathToFile)+"\r\n";
|
||||
var wait = 150;
|
||||
|
||||
beforeEach(function(done) {
|
||||
@@ -1047,6 +1075,7 @@ describe('file Nodes', function() {
|
||||
});
|
||||
|
||||
afterEach(function(done) {
|
||||
delete RED.settings.fileWorkingDirectory;
|
||||
helper.unload().then(function() {
|
||||
fs.unlinkSync(fileToTest);
|
||||
helper.stopServer(done);
|
||||
@@ -1100,6 +1129,30 @@ describe('file Nodes', function() {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should read in a file using fileWorkingDirectory to set cwd', function(done) {
|
||||
var flow = [{id:"fileInNode1", type:"file in", name: "fileInNode", "filename":relativePathToFile, "format":"utf8", wires:[["n2"]]},
|
||||
{id:"n2", type:"helper"}];
|
||||
helper.load(fileNode, flow, function() {
|
||||
RED.settings.fileWorkingDirectory = resourcesDir;
|
||||
var n1 = helper.getNode("fileInNode1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
try {
|
||||
msg.should.have.property('payload');
|
||||
msg.payload.should.be.a.String();
|
||||
msg.payload.should.have.length(40)
|
||||
msg.payload.should.equal("File message line 1\nFile message line 2\n");
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err);
|
||||
}
|
||||
});
|
||||
n1.receive({payload:""});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should read in a file ending in cr and output a utf8 string', function(done) {
|
||||
var flow = [{id:"fileInNode1", type:"file in", name: "fileInNode", "filename":fileToTest2, "format":"utf8", wires:[["n2"]]},
|
||||
{id:"n2", type:"helper"}];
|
||||
|
@@ -14,6 +14,7 @@ const os = require("os");
|
||||
const NR_TEST_UTILS = require("nr-test-utils");
|
||||
const externalModules = NR_TEST_UTILS.require("@node-red/registry/lib/externalModules");
|
||||
const exec = NR_TEST_UTILS.require("@node-red/util/lib/exec");
|
||||
const hooks = NR_TEST_UTILS.require("@node-red/util/lib/hooks");
|
||||
|
||||
let homeDir;
|
||||
|
||||
@@ -40,19 +41,21 @@ describe("externalModules api", function() {
|
||||
await createUserDir()
|
||||
})
|
||||
afterEach(async function() {
|
||||
hooks.clear();
|
||||
await fs.remove(homeDir);
|
||||
})
|
||||
describe("checkFlowDependencies", function() {
|
||||
beforeEach(function() {
|
||||
sinon.stub(exec,"run").callsFake(async function(cmd, args, options) {
|
||||
let error;
|
||||
if (args[1] === "moduleNotFound") {
|
||||
let moduleName = args[args.length-1];
|
||||
if (moduleName === "moduleNotFound") {
|
||||
error = new Error();
|
||||
error.stderr = "E404";
|
||||
} else if (args[1] === "moduleVersionNotFound") {
|
||||
} else if (moduleName === "moduleVersionNotFound") {
|
||||
error = new Error();
|
||||
error.stderr = "ETARGET";
|
||||
} else if (args[1] === "moduleFail") {
|
||||
} else if (moduleName === "moduleFail") {
|
||||
error = new Error();
|
||||
error.stderr = "Some unexpected install error";
|
||||
}
|
||||
@@ -102,6 +105,45 @@ describe("externalModules api", function() {
|
||||
fs.existsSync(path.join(homeDir,"externalModules")).should.be.true();
|
||||
})
|
||||
|
||||
|
||||
it("calls pre/postInstall hooks", async function() {
|
||||
externalModules.init({userDir: homeDir});
|
||||
externalModules.register("function", "libs");
|
||||
let receivedPreEvent,receivedPostEvent;
|
||||
hooks.add("preInstall", function(event) { event.args = ["a"]; receivedPreEvent = event; })
|
||||
hooks.add("postInstall", function(event) { receivedPostEvent = event; })
|
||||
|
||||
await externalModules.checkFlowDependencies([
|
||||
{type: "function", libs:[{module: "foo"}]}
|
||||
])
|
||||
exec.run.called.should.be.true();
|
||||
// exec.run.lastCall.args[1].should.eql([ 'install', 'a', 'foo' ]);
|
||||
receivedPreEvent.should.have.property("module","foo")
|
||||
receivedPreEvent.should.have.property("version")
|
||||
receivedPreEvent.should.have.property("dir")
|
||||
receivedPreEvent.should.eql(receivedPostEvent)
|
||||
fs.existsSync(path.join(homeDir,"externalModules")).should.be.true();
|
||||
})
|
||||
|
||||
it("skips npm install if preInstall returns false", async function() {
|
||||
externalModules.init({userDir: homeDir});
|
||||
externalModules.register("function", "libs");
|
||||
let receivedPreEvent,receivedPostEvent;
|
||||
hooks.add("preInstall", function(event) { receivedPreEvent = event; return false })
|
||||
hooks.add("postInstall", function(event) { receivedPostEvent = event; })
|
||||
|
||||
await externalModules.checkFlowDependencies([
|
||||
{type: "function", libs:[{module: "foo"}]}
|
||||
])
|
||||
exec.run.called.should.be.false();
|
||||
receivedPreEvent.should.have.property("module","foo")
|
||||
receivedPreEvent.should.have.property("version")
|
||||
receivedPreEvent.should.have.property("dir")
|
||||
receivedPreEvent.should.eql(receivedPostEvent)
|
||||
fs.existsSync(path.join(homeDir,"externalModules")).should.be.true();
|
||||
})
|
||||
|
||||
|
||||
it("installs missing modules from inside subflow module", async function() {
|
||||
externalModules.init({userDir: homeDir});
|
||||
externalModules.register("function", "libs");
|
||||
@@ -299,4 +341,4 @@ describe("externalModules api", function() {
|
||||
}
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
@@ -25,7 +25,7 @@ var NR_TEST_UTILS = require("nr-test-utils");
|
||||
var installer = NR_TEST_UTILS.require("@node-red/registry/lib/installer");
|
||||
var registry = NR_TEST_UTILS.require("@node-red/registry/lib/index");
|
||||
var typeRegistry = NR_TEST_UTILS.require("@node-red/registry/lib/registry");
|
||||
const { events, exec, log } = NR_TEST_UTILS.require("@node-red/util");
|
||||
const { events, exec, log, hooks } = NR_TEST_UTILS.require("@node-red/util");
|
||||
|
||||
describe('nodes/registry/installer', function() {
|
||||
|
||||
@@ -68,6 +68,7 @@ describe('nodes/registry/installer', function() {
|
||||
fs.statSync.restore();
|
||||
}
|
||||
exec.run.restore();
|
||||
hooks.clear();
|
||||
});
|
||||
|
||||
describe("installs module", function() {
|
||||
@@ -251,6 +252,70 @@ describe('nodes/registry/installer', function() {
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it("triggers preInstall and postInstall hooks", function(done) {
|
||||
let receivedPreEvent,receivedPostEvent;
|
||||
hooks.add("preInstall", function(event) { event.args = ["a"]; receivedPreEvent = event; })
|
||||
hooks.add("postInstall", function(event) { receivedPostEvent = event; })
|
||||
var nodeInfo = {nodes:{module:"foo",types:["a"]}};
|
||||
var res = {code: 0,stdout:"",stderr:""}
|
||||
var p = Promise.resolve(res);
|
||||
p.catch((err)=>{});
|
||||
execResponse = p;
|
||||
|
||||
var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
|
||||
return Promise.resolve(nodeInfo);
|
||||
});
|
||||
|
||||
installer.installModule("this_wont_exist","1.2.3").then(function(info) {
|
||||
exec.run.called.should.be.true();
|
||||
exec.run.lastCall.args[1].should.eql([ 'install', 'a', 'this_wont_exist@1.2.3' ]);
|
||||
info.should.eql(nodeInfo);
|
||||
should.exist(receivedPreEvent)
|
||||
receivedPreEvent.should.have.property("module","this_wont_exist")
|
||||
receivedPreEvent.should.have.property("version","1.2.3")
|
||||
receivedPreEvent.should.have.property("dir")
|
||||
receivedPreEvent.should.have.property("url")
|
||||
receivedPreEvent.should.have.property("isExisting")
|
||||
receivedPreEvent.should.have.property("isUpgrade")
|
||||
receivedPreEvent.should.eql(receivedPostEvent)
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it("fails install if preInstall hook fails", function(done) {
|
||||
let receivedEvent;
|
||||
hooks.add("preInstall", function(event) { throw new Error("preInstall-error"); })
|
||||
var nodeInfo = {nodes:{module:"foo",types:["a"]}};
|
||||
|
||||
installer.installModule("this_wont_exist","1.2.3").catch(function(err) {
|
||||
exec.run.called.should.be.false();
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it("skips invoking npm if preInstall returns false", function(done) {
|
||||
let receivedEvent;
|
||||
hooks.add("preInstall", function(event) { return false })
|
||||
hooks.add("postInstall", function(event) { receivedEvent = event; })
|
||||
var nodeInfo = {nodes:{module:"foo",types:["a"]}};
|
||||
|
||||
installer.installModule("this_wont_exist","1.2.3").catch(function(err) {
|
||||
exec.run.called.should.be.false();
|
||||
should.exist(receivedEvent);
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it("rollsback install if postInstall hook fails", function(done) {
|
||||
hooks.add("postInstall", function(event) { throw new Error("fail"); })
|
||||
installer.installModule("this_wont_exist","1.2.3").catch(function(err) {
|
||||
exec.run.calledTwice.should.be.true();
|
||||
exec.run.firstCall.args[1].includes("install").should.be.true();
|
||||
exec.run.secondCall.args[1].includes("remove").should.be.true();
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
});
|
||||
describe("uninstalls module", function() {
|
||||
it("rejects invalid module names", function(done) {
|
||||
|
@@ -26,7 +26,7 @@ var flowUtils = NR_TEST_UTILS.require("@node-red/runtime/lib/flows/util");
|
||||
var Flow = NR_TEST_UTILS.require("@node-red/runtime/lib/flows/Flow");
|
||||
var flows = NR_TEST_UTILS.require("@node-red/runtime/lib/flows");
|
||||
var Node = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/Node");
|
||||
var hooks = NR_TEST_UTILS.require("@node-red/runtime/lib/hooks");
|
||||
var hooks = NR_TEST_UTILS.require("@node-red/util/lib/hooks");
|
||||
var typeRegistry = NR_TEST_UTILS.require("@node-red/registry");
|
||||
|
||||
|
||||
|
@@ -19,7 +19,7 @@ var sinon = require('sinon');
|
||||
var NR_TEST_UTILS = require("nr-test-utils");
|
||||
var RedNode = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/Node");
|
||||
var Log = NR_TEST_UTILS.require("@node-red/util").log;
|
||||
var hooks = NR_TEST_UTILS.require("@node-red/runtime/lib/hooks");
|
||||
var hooks = NR_TEST_UTILS.require("@node-red/util/lib/hooks");
|
||||
var flows = NR_TEST_UTILS.require("@node-red/runtime/lib/flows");
|
||||
|
||||
describe('Node', function() {
|
||||
|
@@ -1006,7 +1006,155 @@ describe('context', function() {
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
it('should throw an error in context.get if key is empty string', function (done) {
|
||||
Context.init({ contextStorage: memoryStorage });
|
||||
Context.load().then(function () {
|
||||
var context = Context.get("1", "flow");
|
||||
context.get("");
|
||||
done("should throw an error.");
|
||||
}).catch(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should throw an error in context.get if key is an object', function (done) {
|
||||
Context.init({ contextStorage: memoryStorage });
|
||||
Context.load().then(function () {
|
||||
var context = Context.get("1", "flow");
|
||||
context.get({});
|
||||
done("should throw an error.");
|
||||
}).catch(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should throw an error in context.get if key is a number', function (done) {
|
||||
Context.init({ contextStorage: memoryStorage });
|
||||
Context.load().then(function () {
|
||||
var context = Context.get("1", "flow");
|
||||
context.get(1);
|
||||
done("should throw an error.");
|
||||
}).catch(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should throw an error in context.get if key array contains an empty string', function (done) {
|
||||
Context.init({ contextStorage: memoryStorage });
|
||||
Context.load().then(function () {
|
||||
var context = Context.get("1", "flow");
|
||||
context.get(["ok1", "", "ok2"]);
|
||||
done("should throw an error.");
|
||||
}).catch(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should throw an error in context.get if key array contains an object', function (done) {
|
||||
Context.init({ contextStorage: memoryStorage });
|
||||
Context.load().then(function () {
|
||||
var context = Context.get("1", "flow");
|
||||
context.get(["ok1", {}, "ok2"]);
|
||||
done("should throw an error.");
|
||||
}).catch(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should throw an error in context.get if key array contains a number', function (done) {
|
||||
Context.init({ contextStorage: memoryStorage });
|
||||
Context.load().then(function () {
|
||||
var context = Context.get("1", "flow");
|
||||
context.get(["ok1", 1, "ok2"]);
|
||||
done("should throw an error.");
|
||||
}).catch(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw an error in context.set if key is empty string', function (done) {
|
||||
Context.init({ contextStorage: memoryStorage });
|
||||
Context.load().then(function () {
|
||||
var context = Context.get("1", "flow");
|
||||
context.set("", 1);
|
||||
done("should throw an error.");
|
||||
}).catch(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should throw an error in context.set if key is an object', function (done) {
|
||||
Context.init({ contextStorage: memoryStorage });
|
||||
Context.load().then(function () {
|
||||
var context = Context.get("1", "flow");
|
||||
context.set({}, 1);
|
||||
done("should throw an error.");
|
||||
}).catch(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should throw an error in context.set if key is a number', function (done) {
|
||||
Context.init({ contextStorage: memoryStorage });
|
||||
Context.load().then(function () {
|
||||
var context = Context.get("1", "flow");
|
||||
context.set(1, 1);
|
||||
done("should throw an error.");
|
||||
}).catch(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should throw an error in context.set if key array contains an empty string', function (done) {
|
||||
Context.init({ contextStorage: memoryStorage });
|
||||
Context.load().then(function () {
|
||||
var context = Context.get("1", "flow");
|
||||
context.set(["ok1", "", "ok2"], 1);
|
||||
done("should throw an error.");
|
||||
}).catch(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should throw an error in context.set if key array contains an object', function (done) {
|
||||
Context.init({ contextStorage: memoryStorage });
|
||||
Context.load().then(function () {
|
||||
var context = Context.get("1", "flow");
|
||||
context.set(["ok1", {}, "ok2"], 1);
|
||||
done("should throw an error.");
|
||||
}).catch(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should throw an error in context.set if key array contains a number', function (done) {
|
||||
Context.init({ contextStorage: memoryStorage });
|
||||
Context.load().then(function () {
|
||||
var context = Context.get("1", "flow");
|
||||
context.set(["ok1", 1, "ok2"], 1);
|
||||
done("should throw an error.");
|
||||
}).catch(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should have an err set in callback for invalid key in context.get', function (done) {
|
||||
Context.init({ contextStorage: memoryStorage });
|
||||
Context.load().then(function () {
|
||||
var context = Context.get("1", "flow");
|
||||
context.get("", function(err) {
|
||||
if(err) {
|
||||
done();
|
||||
} else {
|
||||
done("should throw an error.");
|
||||
}
|
||||
});
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it('should have an err set in callback for invalid key in context.set', function (done) {
|
||||
Context.init({ contextStorage: memoryStorage });
|
||||
Context.load().then(function () {
|
||||
var context = Context.get("1", "flow");
|
||||
context.set("", "value", function(err) {
|
||||
if(err) {
|
||||
done();
|
||||
} else {
|
||||
done("should throw an error.");
|
||||
}
|
||||
});
|
||||
}).catch(done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('listStores', function () {
|
||||
|
@@ -36,102 +36,96 @@ describe('red/runtime/nodes/credentials', function() {
|
||||
index.clearRegistry();
|
||||
});
|
||||
|
||||
it('loads provided credentials',function(done) {
|
||||
it('loads provided credentials',function() {
|
||||
credentials.init({
|
||||
log: log,
|
||||
settings: encryptionDisabledSettings
|
||||
});
|
||||
|
||||
credentials.load({"a":{"b":1,"c":2}}).then(function() {
|
||||
|
||||
return credentials.load({"a":{"b":1,"c":2}}).then(function() {
|
||||
credentials.get("a").should.have.property('b',1);
|
||||
credentials.get("a").should.have.property('c',2);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('adds a new credential',function(done) {
|
||||
it('adds a new credential',function() {
|
||||
credentials.init({
|
||||
log: log,
|
||||
settings: encryptionDisabledSettings
|
||||
});
|
||||
credentials.load({"a":{"b":1,"c":2}}).then(function() {
|
||||
return credentials.load({"a":{"b":1,"c":2}}).then(function() {
|
||||
credentials.dirty().should.be.false();
|
||||
should.not.exist(credentials.get("b"));
|
||||
credentials.add("b",{"foo":"bar"}).then(function() {
|
||||
return credentials.add("b",{"foo":"bar"}).then(function() {
|
||||
credentials.get("b").should.have.property("foo","bar");
|
||||
credentials.dirty().should.be.true();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
it('deletes an existing credential',function(done) {
|
||||
it('deletes an existing credential',function() {
|
||||
credentials.init({
|
||||
log: log,
|
||||
settings: encryptionDisabledSettings
|
||||
});
|
||||
credentials.load({"a":{"b":1,"c":2}}).then(function() {
|
||||
return credentials.load({"a":{"b":1,"c":2}}).then(function() {
|
||||
credentials.dirty().should.be.false();
|
||||
credentials.delete("a");
|
||||
should.not.exist(credentials.get("a"));
|
||||
credentials.dirty().should.be.true();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('exports the credentials, clearing dirty flag', function(done) {
|
||||
it('exports the credentials, clearing dirty flag', function() {
|
||||
credentials.init({
|
||||
log: log,
|
||||
settings: encryptionDisabledSettings
|
||||
});
|
||||
var creds = {"a":{"b":1,"c":2}};
|
||||
credentials.load(creds).then(function() {
|
||||
credentials.add("b",{"foo":"bar"}).then(function() {
|
||||
credentials.dirty().should.be.true();
|
||||
credentials.export().then(function(exported) {
|
||||
exported.should.eql(creds);
|
||||
credentials.dirty().should.be.false();
|
||||
done();
|
||||
})
|
||||
});
|
||||
return credentials.load(creds).then(function() {
|
||||
return credentials.add("b",{"foo":"bar"})
|
||||
}).then(function() {
|
||||
credentials.dirty().should.be.true();
|
||||
return credentials.export().then(function(exported) {
|
||||
exported.should.eql(creds);
|
||||
credentials.dirty().should.be.false();
|
||||
})
|
||||
});
|
||||
})
|
||||
|
||||
describe("#clean",function() {
|
||||
it("removes credentials of unknown nodes",function(done) {
|
||||
it("removes credentials of unknown nodes",function() {
|
||||
credentials.init({
|
||||
log: log,
|
||||
settings: encryptionDisabledSettings
|
||||
settings: encryptionDisabledSettings,
|
||||
nodes: { getType: () => function(){} }
|
||||
});
|
||||
var creds = {"a":{"b":1,"c":2},"b":{"d":3}};
|
||||
credentials.load(creds).then(function() {
|
||||
return credentials.load(creds).then(function() {
|
||||
credentials.dirty().should.be.false();
|
||||
should.exist(credentials.get("a"));
|
||||
should.exist(credentials.get("b"));
|
||||
credentials.clean([{id:"b"}]).then(function() {
|
||||
return credentials.clean([{id:"b"}]).then(function() {
|
||||
credentials.dirty().should.be.true();
|
||||
should.not.exist(credentials.get("a"));
|
||||
should.exist(credentials.get("b"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
it("extracts credentials of known nodes",function(done) {
|
||||
it("extracts credentials of known nodes",function() {
|
||||
credentials.init({
|
||||
log: log,
|
||||
settings: encryptionDisabledSettings
|
||||
settings: encryptionDisabledSettings,
|
||||
nodes: { getType: () => function(){} }
|
||||
});
|
||||
credentials.register("testNode",{"b":"text","c":"password"})
|
||||
var creds = {"a":{"b":1,"c":2}};
|
||||
var newConfig = [{id:"a",type:"testNode",credentials:{"b":"newBValue","c":"newCValue"}}];
|
||||
credentials.load(creds).then(function() {
|
||||
return credentials.load(creds).then(function() {
|
||||
credentials.dirty().should.be.false();
|
||||
credentials.clean(newConfig).then(function() {
|
||||
return credentials.clean(newConfig).then(function() {
|
||||
credentials.dirty().should.be.true();
|
||||
credentials.get("a").should.have.property('b',"newBValue");
|
||||
credentials.get("a").should.have.property('c',"newCValue");
|
||||
should.not.exist(newConfig[0].credentials);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -139,12 +133,13 @@ describe('red/runtime/nodes/credentials', function() {
|
||||
|
||||
});
|
||||
|
||||
it('warns if a node has no credential definition', function(done) {
|
||||
it('warns if a node has no credential definition', function() {
|
||||
credentials.init({
|
||||
log: log,
|
||||
settings: encryptionDisabledSettings
|
||||
settings: encryptionDisabledSettings,
|
||||
nodes: { getType: () => function(){} }
|
||||
});
|
||||
credentials.load({}).then(function() {
|
||||
return credentials.load({}).then(function() {
|
||||
var node = {id:"node",type:"test",credentials:{
|
||||
user1:"newUser",
|
||||
password1:"newPassword"
|
||||
@@ -154,14 +149,14 @@ describe('red/runtime/nodes/credentials', function() {
|
||||
log.warn.called.should.be.true();
|
||||
should.not.exist(node.credentials);
|
||||
log.warn.restore();
|
||||
done();
|
||||
});
|
||||
})
|
||||
|
||||
it('extract credential updates in the provided node', function(done) {
|
||||
credentials.init({
|
||||
log: log,
|
||||
settings: encryptionDisabledSettings
|
||||
settings: encryptionDisabledSettings,
|
||||
nodes: { getType: () => function(){} }
|
||||
});
|
||||
var defintion = {
|
||||
user1:{type:"text"},
|
||||
@@ -205,7 +200,8 @@ describe('red/runtime/nodes/credentials', function() {
|
||||
it('extract ignores node without credentials', function(done) {
|
||||
credentials.init({
|
||||
log: log,
|
||||
settings: encryptionDisabledSettings
|
||||
settings: encryptionDisabledSettings,
|
||||
nodes: { getType: () => function(){} }
|
||||
});
|
||||
credentials.load({"node":{user1:"abc",password1:"123"}}).then(function() {
|
||||
var node = {id:"node",type:"test"};
|
||||
@@ -233,7 +229,8 @@ describe('red/runtime/nodes/credentials', function() {
|
||||
delete settings[key];
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
},
|
||||
nodes: { getType: () => function(){} }
|
||||
}
|
||||
it('migrates to encrypted and generates default key', function(done) {
|
||||
settings = {};
|
||||
@@ -341,7 +338,7 @@ describe('red/runtime/nodes/credentials', function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
it('migrates from default key to user key', function(done) {
|
||||
it('migrates from default key to user key', function() {
|
||||
settings = {
|
||||
_credentialSecret: "e3a36f47f005bf2aaa51ce3fc6fcaafd79da8d03f2b1a9281f8fb0a285e6255a",
|
||||
credentialSecret: "aaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbcccccccccccccddddddddddddeeeee"
|
||||
@@ -349,21 +346,20 @@ describe('red/runtime/nodes/credentials', function() {
|
||||
// {"node":{user1:"abc",password1:"123"}}
|
||||
var cryptedFlows = {"$":"5b89d8209b5158a3c313675561b1a5b5phN1gDBe81Zv98KqS/hVDmc9EKvaKqRIvcyXYvBlFNzzzJtvN7qfw06i"};
|
||||
credentials.init(runtime);
|
||||
credentials.load(cryptedFlows).then(function() {
|
||||
return credentials.load(cryptedFlows).then(function() {
|
||||
credentials.dirty().should.be.true();
|
||||
should.exist(credentials.get("node"));
|
||||
credentials.export().then(function(result) {
|
||||
return credentials.export().then(function(result) {
|
||||
result.should.have.a.property("$");
|
||||
settings.should.not.have.a.property("_credentialSecret");
|
||||
|
||||
// reset everything - but with _credentialSecret still set
|
||||
credentials.init(runtime);
|
||||
// load the freshly encrypted version
|
||||
credentials.load(result).then(function() {
|
||||
return credentials.load(result).then(function() {
|
||||
should.exist(credentials.get("node"));
|
||||
credentials.get("node").should.have.a.property("user1","abc");
|
||||
credentials.get("node").should.have.a.property("password1","123");
|
||||
done();
|
||||
})
|
||||
});
|
||||
});
|
||||
@@ -459,7 +455,8 @@ describe('red/runtime/nodes/credentials', function() {
|
||||
set: function(key,value) {
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
},
|
||||
nodes: { getType: () => function(){} }
|
||||
}
|
||||
// {"node":{user1:"abc",password1:"123"}}
|
||||
credentials.init(runtime);
|
||||
|
@@ -1,9 +1,9 @@
|
||||
const should = require("should");
|
||||
const NR_TEST_UTILS = require("nr-test-utils");
|
||||
|
||||
const hooks = NR_TEST_UTILS.require("@node-red/runtime/lib/hooks");
|
||||
const hooks = NR_TEST_UTILS.require("@node-red/util/lib/hooks");
|
||||
|
||||
describe("runtime/hooks", function() {
|
||||
describe("util/hooks", function() {
|
||||
afterEach(function() {
|
||||
hooks.clear();
|
||||
})
|
||||
@@ -81,7 +81,7 @@ describe("runtime/hooks", function() {
|
||||
hooks.has("onSend.A").should.be.false();
|
||||
hooks.has("onSend.B").should.be.false();
|
||||
hooks.has("onSend").should.be.false();
|
||||
|
||||
|
||||
done(err);
|
||||
} catch(err2) {
|
||||
done(err2);
|
||||
@@ -121,7 +121,46 @@ describe("runtime/hooks", function() {
|
||||
})
|
||||
})
|
||||
})
|
||||
it("allows a hook to remove itself whilst being called", function(done) {
|
||||
let data = { order: [] }
|
||||
hooks.add("onSend.A", function(payload) { payload.order.push("A") } )
|
||||
hooks.add("onSend.B", function(payload) {
|
||||
hooks.remove("*.B");
|
||||
})
|
||||
hooks.add("onSend.C", function(payload) { payload.order.push("C") } )
|
||||
hooks.add("onSend.D", function(payload) { payload.order.push("D") } )
|
||||
|
||||
hooks.trigger("onSend", data, err => {
|
||||
try {
|
||||
should.not.exist(err);
|
||||
data.order.should.eql(["A","C","D"])
|
||||
done();
|
||||
} catch(e) {
|
||||
done(e);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
it("allows a hook to remove itself and others whilst being called", function(done) {
|
||||
let data = { order: [] }
|
||||
hooks.add("onSend.A", function(payload) { payload.order.push("A") } )
|
||||
hooks.add("onSend.B", function(payload) {
|
||||
hooks.remove("*.B");
|
||||
hooks.remove("*.C");
|
||||
})
|
||||
hooks.add("onSend.C", function(payload) { payload.order.push("C") } )
|
||||
hooks.add("onSend.D", function(payload) { payload.order.push("D") } )
|
||||
|
||||
hooks.trigger("onSend", data, err => {
|
||||
try {
|
||||
should.not.exist(err);
|
||||
data.order.should.eql(["A","D"])
|
||||
done();
|
||||
} catch(e) {
|
||||
done(e);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
it("halts execution on return false", function(done) {
|
||||
hooks.add("onSend.A", function(payload) { payload.order.push("A"); return false } )
|
||||
@@ -249,4 +288,51 @@ describe("runtime/hooks", function() {
|
||||
done();
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
it("handler can use callback function - promise API", function(done) {
|
||||
hooks.add("onSend.A", function(payload, done) {
|
||||
setTimeout(function() {
|
||||
payload.order.push("A")
|
||||
done()
|
||||
},30)
|
||||
})
|
||||
hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
|
||||
|
||||
let data = { order:[] };
|
||||
hooks.trigger("onSend",data).then(() => {
|
||||
data.order.should.eql(["A","B"])
|
||||
done()
|
||||
}).catch(done)
|
||||
})
|
||||
|
||||
it("handler can halt execution - promise API", function(done) {
|
||||
hooks.add("onSend.A", function(payload, done) {
|
||||
setTimeout(function() {
|
||||
payload.order.push("A")
|
||||
done(false)
|
||||
},30)
|
||||
})
|
||||
hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
|
||||
|
||||
let data = { order:[] };
|
||||
hooks.trigger("onSend",data).then(() => {
|
||||
data.order.should.eql(["A"])
|
||||
done()
|
||||
}).catch(done)
|
||||
})
|
||||
|
||||
it("handler can halt execution on error - promise API", function(done) {
|
||||
hooks.add("onSend.A", function(payload, done) {
|
||||
throw new Error("error");
|
||||
})
|
||||
hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
|
||||
|
||||
let data = { order:[] };
|
||||
hooks.trigger("onSend",data).then(() => {
|
||||
done("hooks.trigger resolved unexpectedly")
|
||||
}).catch(err => {
|
||||
done();
|
||||
})
|
||||
})
|
||||
});
|
Reference in New Issue
Block a user