Merge branch '0.18' into projects

This commit is contained in:
Nick O'Leary
2018-01-16 11:21:54 +00:00
146 changed files with 6584 additions and 1498 deletions

View File

@@ -28,22 +28,73 @@ describe('inject node', function() {
helper.unload();
});
it('should inject once', function(done) {
it('should inject once with default delay property', function(done) {
helper.load(injectNode, [{id:"n1", type:"inject", topic: "t1",
payload:"",payloadType:"date",
once: true, wires:[["n2"]] },
{id:"n2", type:"helper"}],
function() {
var n1 = helper.getNode("n1");
n1.should.have.property('onceDelay', 100);
done();
});
});
helper.load(injectNode, [{id:"n1", type:"inject",
payload:"payload", topic: "t1",
it('should inject once with default delay', function(done) {
var timestamp = new Date();
timestamp.setSeconds(timestamp.getSeconds() + 1);
helper.load(injectNode, [{id:"n1", type:"inject", topic: "t1",
payload:"",payloadType:"date",
once: true, wires:[["n2"]] },
{id:"n2", type:"helper"}],
function() {
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
msg.should.have.property('topic', 't1');
msg.should.have.property('payload', 'payload');
done();
try {
msg.should.have.property('topic', 't1');
msg.should.have.property('payload');
should(msg.payload).be.lessThan(timestamp.getTime());
done();
} catch(err) {
done(err);
}
});
});
});
it('should inject once with 500 msec. delay', function(done) {
helper.load(injectNode, [{id:"n1", type:"inject", topic: "t1",
payload:"",payloadType:"date",
once: true, onceDelay: 0.5, wires:[["n2"]] },
{id:"n2", type:"helper"}],
function() {
var n1 = helper.getNode("n1");
n1.should.have.property('onceDelay', 500);
done();
});
});
it('should inject once with delay of two seconds', function(done) {
this.timeout(2700); // have to wait for the inject with delay of two seconds
var timestamp = new Date();
timestamp.setSeconds(timestamp.getSeconds() + 1);
helper.load(injectNode, [{id:"n1", type:"inject", topic: "t1",
payload:"",payloadType:"date",
once: true, onceDelay: 2, wires:[["n2"]] },
{id:"n2", type:"helper"}],
function() {
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
msg.should.have.property('topic', 't1');
should(msg.payload).be.greaterThan(timestamp.getTime());
done();
});
});
});
it('should inject repeatedly', function(done) {
helper.load(injectNode, [{id:"n1", type:"inject",
@@ -66,6 +117,30 @@ describe('inject node', function() {
});
});
it('should inject once with delay of two seconds and repeatedly', function(done) {
var timestamp = new Date();
timestamp.setSeconds(timestamp.getSeconds() + 1);
helper.load(injectNode, [{id:"n1", type:"inject", topic: "t1",
payload:"",payloadType:"date", repeat: 0.2,
once: true, onceDelay: 1.2, wires:[["n2"]] },
{id:"n2", type:"helper"}],
function() {
var n2 = helper.getNode("n2");
var count = 0;
n2.on("input", function(msg) {
msg.should.have.property('topic', 't1');
should(msg.payload).be.greaterThan(timestamp.getTime());
count += 1;
if (count > 2) {
helper.clearFlows().then(function() {
done();
});
}
});
});
});
it('should inject with cron', function(done) {
helper.load(injectNode, [{id:"n1", type:"inject",
payloadType:"date", topic: "t3",

View File

@@ -25,13 +25,19 @@ describe('debug node', function() {
helper.startServer(done);
});
beforeEach(function (done) {
setTimeout(function() {
done();
}, 55);
});
afterEach(function() {
helper.unload();
});
it('should be loaded', function(done) {
var flow = [{id:"n1", type:"debug", name: "Debug", complete:"false" }];
var flow = [{id:"n1", type:"debug", name:"Debug", complete:"false" }];
helper.load(debugNode, flow, function() {
var n1 = helper.getNode("n1");
n1.should.have.property('name', 'Debug');
@@ -41,31 +47,31 @@ describe('debug node', function() {
});
it('should publish on input', function(done) {
var flow = [{id:"n1", type:"debug", name: "Debug" }];
var flow = [{id:"n1", type:"debug", name:"Debug" }];
helper.load(debugNode, flow, function() {
var n1 = helper.getNode("n1");
websocket_test(function() {
n1.emit("input", {payload:"test"});
}, function(msg) {
JSON.parse(msg).should.eql({
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",name:"Debug",msg:"test",
format:"string[4]",property:"payload"}
});
}]);
}, done);
});
});
it('should publish to console', function(done) {
var flow = [{id:"n1", type:"debug", console: "true"}];
var flow = [{id:"n1", type:"debug", console:"true"}];
helper.load(debugNode, flow, function() {
var n1 = helper.getNode("n1");
var count = 0;
websocket_test(function() {
n1.emit("input", {payload:"test"});
}, function(msg) {
JSON.parse(msg).should.eql({
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",msg:"test",property:"payload",format:"string[4]"}
});
}]);
count++;
}, function() {
try {
@@ -86,44 +92,72 @@ describe('debug node', function() {
});
it('should publish complete message', function(done) {
var flow = [{id:"n1", type:"debug", complete: "true" }];
var flow = [{id:"n1", type:"debug", complete:"true" }];
helper.load(debugNode, flow, function() {
var n1 = helper.getNode("n1");
websocket_test(function() {
n1.emit("input", {payload:"test"});
}, function(msg) {
JSON.parse(msg).should.eql({
JSON.parse(msg).should.eql([{
topic:"debug",
data:{id:"n1",msg:'{\n "payload": "test"\n}',format:"Object"}
});
}]);
}, done);
});
});
it('should publish complete message to console', function(done) {
var flow = [{id:"n1", type:"debug", complete:"true", console:"true" }];
helper.load(debugNode, flow, function() {
var n1 = helper.getNode("n1");
websocket_test(function() {
n1.emit("input", {payload:"test"});
}, function(msg) {
JSON.parse(msg).should.eql([{
topic:"debug",
data:{id:"n1",msg:'{\n "payload": "test"\n}',format:"Object"}
}]);
}, function() {
try {
helper.log().called.should.be.true();
var logEvents = helper.log().args.filter(function(evt) {
return evt[0].type == "debug";
});
logEvents.should.have.length(1);
var tstmp = logEvents[0][0].timestamp;
logEvents[0][0].should.eql({level:helper.log().INFO, id:"n1",type:"debug",msg:'\n{ payload: \'test\' }',timestamp:tstmp});
done();
} catch(err) {
done(err);
}
});
});
});
it('should publish other property', function(done) {
var flow = [{id:"n1", type:"debug", complete: "foo" }];
var flow = [{id:"n1", type:"debug", complete:"foo" }];
helper.load(debugNode, flow, function() {
var n1 = helper.getNode("n1");
websocket_test(function() {
n1.emit("input", {payload:"test", foo:"bar"});
}, function(msg) {
JSON.parse(msg).should.eql({
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",msg:"bar",property:"foo",format:"string[3]"}
});
}]);
}, done);
});
});
it('should publish multi-level properties', function(done) {
var flow = [{id:"n1", type:"debug", complete: "foo.bar" }];
var flow = [{id:"n1", type:"debug", complete:"foo.bar" }];
helper.load(debugNode, flow, function() {
var n1 = helper.getNode("n1");
websocket_test(function() {
n1.emit("input", {payload:"test", foo: {bar: "bar"}});
n1.emit("input", {payload:"test", foo: {bar:"bar"}});
}, function(msg) {
JSON.parse(msg).should.eql({
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",msg:"bar",property:"foo.bar",format:"string[3]"}
});
}]);
}, done);
});
});
@@ -135,9 +169,9 @@ describe('debug node', function() {
websocket_test(function() {
n1.emit("input", {payload: new Error("oops")});
}, function(msg) {
JSON.parse(msg).should.eql({
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",msg:'{"name":"Error","message":"oops"}',property:"payload",format:"error"}
});
}]);
}, done);
});
});
@@ -149,9 +183,37 @@ describe('debug node', function() {
websocket_test(function() {
n1.emit("input", {payload: true});
}, function(msg) {
JSON.parse(msg).should.eql({
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",msg: 'true',property:"payload",format:"boolean"}
});
}]);
}, done);
});
});
it('should publish a number', function(done) {
var flow = [{id:"n1", type:"debug", console:"true" }];
helper.load(debugNode, flow, function() {
var n1 = helper.getNode("n1");
websocket_test(function() {
n1.emit("input", {payload: 7});
}, function(msg) {
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",msg:"7",property:"payload",format:"number"}
}]);
}, done);
});
});
it('should publish a NaN', function(done) {
var flow = [{id:"n1", type:"debug", console:"true" }];
helper.load(debugNode, flow, function() {
var n1 = helper.getNode("n1");
websocket_test(function() {
n1.emit("input", {payload: Number.NaN});
}, function(msg) {
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",msg:"NaN",property:"payload",format:"number"}
}]);
}, done);
});
});
@@ -163,9 +225,23 @@ describe('debug node', function() {
websocket_test(function() {
n1.emit("input", {});
}, function(msg) {
JSON.parse(msg).should.eql({
topic:"debug",data:{id:"n1",msg: '(undefined)',property:"payload",format:"undefined"}
});
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",msg:'(undefined)',property:"payload",format:"undefined"}
}]);
}, done);
});
});
it('should publish a null', function(done) {
var flow = [{id:"n1", type:"debug" }];
helper.load(debugNode, flow, function() {
var n1 = helper.getNode("n1");
websocket_test(function() {
n1.emit("input", {payload:null});
}, function(msg) {
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",msg:'(undefined)',property:"payload",format:"null"}
}]);
}, done);
});
});
@@ -177,10 +253,10 @@ describe('debug node', function() {
websocket_test(function() {
n1.emit("input", {payload: {type:'foo'}});
}, function(msg) {
JSON.parse(msg).should.eql({
JSON.parse(msg).should.eql([{
topic:"debug",
data:{id:"n1",msg:'{\n "type": "foo"\n}',property:"payload",format:"Object"}
});
}]);
}, done);
});
});
@@ -192,11 +268,11 @@ describe('debug node', function() {
websocket_test(function() {
n1.emit("input", {payload: [0,1,2,3]});
}, function(msg) {
JSON.parse(msg).should.eql({
JSON.parse(msg).should.eql([{
topic:"debug",
data:{id:"n1",msg: '[\n 0,\n 1,\n 2,\n 3\n]',format:"array[4]",
property:"payload"}
});
}]);
}, done);
});
});
@@ -210,27 +286,81 @@ describe('debug node', function() {
o.o = o;
n1.emit("input", {payload: o});
}, function(msg) {
JSON.parse(msg).should.eql({
JSON.parse(msg).should.eql([{
topic:"debug",
data:{
id:"n1",
msg:'{\n "name": "bar",\n "o": "[Circular ~]"\n}',
property:"payload",format:"Object"
}
});
}]);
}, done);
});
});
it('should publish an object to console', function(done) {
var flow = [{id:"n1", type:"debug", console:"true"}];
helper.load(debugNode, flow, function() {
var n1 = helper.getNode("n1");
websocket_test(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"}
}]);
}, function() {
try {
helper.log().called.should.be.true();
var logEvents = helper.log().args.filter(function(evt) {
return evt[0].type == "debug";
});
logEvents.should.have.length(1);
var tstmp = logEvents[0][0].timestamp;
logEvents[0][0].should.eql({level:helper.log().INFO,id:"n1",type:"debug",msg:'\n{ type: \'foo\' }',timestamp:tstmp});
done();
} catch(err) {
done(err);
}
});
});
});
it('should publish a string after a newline to console if the string contains \\n', function(done) {
var flow = [{id:"n1", type:"debug", console:"true"}];
helper.load(debugNode, flow, function() {
var n1 = helper.getNode("n1");
websocket_test(function() {
n1.emit("input", {payload:"test\ntest"});
}, function(msg) {
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",msg:"test\ntest",property:"payload",format:"string[9]"}
}]);
}, function() {
try {
helper.log().called.should.be.true();
var logEvents = helper.log().args.filter(function(evt) {
return evt[0].type == "debug";
});
logEvents.should.have.length(1);
var tstmp = logEvents[0][0].timestamp;
logEvents[0][0].should.eql({level:helper.log().INFO,id:"n1",type:"debug",msg:"\ntest\ntest",timestamp:tstmp});
done();
} catch(err) {
done(err);
}
});
});
});
it('should truncate a long message', function(done) {
var flow = [{id:"n1", type:"debug" }];
helper.load(debugNode, flow, function() {
var n1 = helper.getNode("n1");
websocket_test(function() {
n1.emit("input", {payload: Array(1002).join("X")});
n1.emit("input", {payload:Array(1002).join("X")});
}, function(msg) {
var a = JSON.parse(msg);
a.should.eql({
a.should.eql([{
topic:"debug",
data:{
id:"n1",
@@ -238,6 +368,130 @@ describe('debug node', function() {
property:"payload",
format:"string[1001]"
}
}]);
}, done);
});
});
it('should truncate a long string in the object', function(done) {
var flow = [{id:"n1", type:"debug"}];
helper.load(debugNode, flow, function() {
var n1 = helper.getNode("n1");
websocket_test(function() {
n1.emit("input", {payload: {foo: Array(1002).join("X")}});
}, function(msg) {
var a = JSON.parse(msg);
a.should.eql([{
topic:"debug",
data:{
id:"n1",
msg:'{\n "foo": "'+Array(1001).join("X")+'..."\n}',
property:"payload",
format:"Object"
}
}]);
}, done);
});
});
it('should truncate a large array', function(done) {
var flow = [{id:"n1", type:"debug" }];
helper.load(debugNode, flow, function() {
var n1 = helper.getNode("n1");
websocket_test(function() {
n1.emit("input", {payload: Array(1001).fill("X")});
}, function(msg) {
var a = JSON.parse(msg);
a.should.eql([{
topic:"debug",
data:{
id:"n1",
msg:JSON.stringify({
__encoded__: true,
type: "array",
data: Array(1000).fill("X"),
length: 1001
},null," "),
property:"payload",
format:"array[1001]"
}
}]);
}, done);
});
});
it('should truncate a large array in the object', function(done) {
var flow = [{id:"n1", type:"debug"}];
helper.load(debugNode, flow, function() {
var n1 = helper.getNode("n1");
websocket_test(function() {
n1.emit("input", {payload: {foo: Array(1001).fill("X")}});
}, function(msg) {
var a = JSON.parse(msg);
a.should.eql([{
topic:"debug",
data:{
id:"n1",
msg:JSON.stringify({
foo:{
__encoded__: true,
type: "array",
data: Array(1000).fill("X"),
length: 1001
}
},null," "),
property:"payload",
format:"Object"
}
}]);
}, done);
});
});
it('should truncate a large buffer', function(done) {
var flow = [{id:"n1", type:"debug" }];
helper.load(debugNode, flow, function() {
var n1 = helper.getNode("n1");
websocket_test(function() {
n1.emit("input", {payload: Buffer(501).fill("\"")});
}, function(msg) {
var a = JSON.parse(msg);
a[0].should.eql({
topic:"debug",
data:{
id:"n1",
msg: Array(1001).join("2"),
property:"payload",
format:"buffer[501]"
}
});
}, done);
});
});
it('should truncate a large buffer in the object', function(done) {
var flow = [{id:"n1", type:"debug"}];
helper.load(debugNode, flow, function() {
var n1 = helper.getNode("n1");
websocket_test(function() {
n1.emit("input", {payload: {foo: Buffer(1001).fill("X")}});
}, function(msg) {
var a = JSON.parse(msg);
a[0].should.eql({
topic:"debug",
data:{
id:"n1",
msg:JSON.stringify({
foo:{
type: "Buffer",
data: Array(1000).fill(88),
__encoded__: true,
length: 1001
}
},null," "),
property:"payload",
format:"Object"
}
});
}, done);
});
@@ -248,17 +502,17 @@ describe('debug node', function() {
helper.load(debugNode, flow, function() {
var n1 = helper.getNode("n1");
websocket_test(function() {
n1.emit("input", {payload: new Buffer('HELLO', 'utf8')});
n1.emit("input", {payload: new Buffer.from('HELLO', 'utf8')});
}, function(msg) {
JSON.parse(msg).should.eql({
JSON.parse(msg).should.eql([{
topic:"debug",
data:{
id:"n1",
msg: '48454c4c4f',
msg:'48454c4c4f',
property:"payload",
format: "buffer[5]"
format:"buffer[5]"
}
});
}]);
}, done);
});
});
@@ -276,9 +530,9 @@ describe('debug node', function() {
n1.emit("input", {payload:"message 2"});
});
}, function(msg) {
JSON.parse(msg).should.eql({
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",msg:"message 2",property:"payload",format:"string[9]"}
});
}]);
}, done);
});
});
@@ -324,6 +578,18 @@ describe('debug node', function() {
});
});
describe('get', function() {
it('should return the view.html', function(done) {
var flow = [{id:"n1", type:"debug"}];
helper.load(debugNode, flow, function() {
helper.request()
.get('/debug/view/view.html')
.expect(200)
.end(done);
});
});
});
});
function websocket_test(open_callback, message_callback, done_callback) {
@@ -331,8 +597,12 @@ function websocket_test(open_callback, message_callback, done_callback) {
var close_callback = function() { ws.close(); };
ws.on('open', function() { open_callback(close_callback); });
ws.on('message', function(msg) {
message_callback(msg, close_callback);
ws.close();
done_callback();
try {
message_callback(msg, close_callback);
ws.close();
done_callback();
} catch(err) {
done_callback(err);
}
});
}

View File

@@ -0,0 +1,118 @@
/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
var should = require("should");
var linkNode = require("../../../../nodes/core/core/60-link.js");
var helper = require("../../helper.js");
describe('link Node', function() {
before(function(done) {
helper.startServer(done);
});
afterEach(function() {
helper.unload();
});
it('should be loaded (link in)', function(done) {
var flow = [{id:"n1", type:"link in", name: "link-in" }];
helper.load(linkNode, flow, function() {
var n1 = helper.getNode("n1");
n1.should.have.property('name', 'link-in');
done();
});
});
it('should be loaded (link out)', function(done) {
var flow = [{id:"n1", type:"link out", name: "link-out" }];
helper.load(linkNode, flow, function() {
var n1 = helper.getNode("n1");
n1.should.have.property('name', 'link-out');
done();
});
});
it('should be linked', function(done) {
var flow = [{id:"n1", type:"link out", name: "link-out", links:["n2"]},
{id:"n2", type:"link in", name: "link-in", wires:[["n3"]]},
{id:"n3", type:"helper"}];
helper.load(linkNode, flow, function() {
var n1 = helper.getNode("n1");
var n3 = helper.getNode("n3");
n3.on("input", function(msg) {
try {
msg.should.have.property('payload', 'hello');
done();
} catch(err) {
done(err);
}
});
n1.receive({payload:"hello"});
});
});
it('should be linked to multiple nodes', function(done) {
var flow = [{id:"n1", type:"link out", name: "link-out", links:["n2", "n3"]},
{id:"n2", type:"link in", name: "link-in0", wires:[["n4"]]},
{id:"n3", type:"link in", name: "link-in1", wires:[["n4"]]},
{id:"n4", type:"helper"} ];
helper.load(linkNode, flow, function() {
var n1 = helper.getNode("n1");
var n4 = helper.getNode("n4");
var count = 0;
n4.on("input", function (msg) {
try {
msg.should.have.property('payload', 'hello');
count++;
if(count == 2) {
done();
}
} catch(err) {
done(err);
}
});
n1.receive({payload:"hello"});
});
});
it('should be linked from multiple nodes', function(done) {
var flow = [{id:"n1", type:"link out", name: "link-out0", links:["n3"]},
{id:"n2", type:"link out", name: "link-out1", links:["n3"]},
{id:"n3", type:"link in", name: "link-in", wires:[["n4"]]},
{id:"n4", type:"helper"} ];
helper.load(linkNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
var n4 = helper.getNode("n4");
var count = 0;
n4.on("input", function(msg) {
try {
msg.should.have.property('payload', 'hello');
count++;
if(count == 2) {
done();
}
} catch(err) {
done(err);
}
});
n1.receive({payload:"hello"});
n2.receive({payload:"hello"});
});
});
});

View File

@@ -76,11 +76,15 @@ describe('exec node', function() {
msg.should.have.property("payload");
msg.payload.should.be.a.String();
msg.payload.should.equal("echo");
msg.should.have.property("rc");
msg.rc.should.have.property("code",0);
msg = messages[1];
msg.should.have.property("payload");
msg.payload.should.be.a.String();
msg.payload.should.equal("ECHO");
msg.should.have.property("rc");
msg.rc.should.have.property("code",0);
msg = messages[2];
msg.should.have.property("payload");
@@ -88,7 +92,8 @@ describe('exec node', function() {
child_process.exec.restore();
done();
} catch(err) {
}
catch(err) {
child_process.exec.restore();
done(err);
}
@@ -136,20 +141,23 @@ describe('exec node', function() {
msg.should.have.property("payload");
msg.payload.should.be.a.String();
msg.payload.should.equal("echo and more");
msg.should.have.property("rc");
msg.rc.should.have.property("code",0);
msg = messages[1];
msg.should.have.property("payload");
msg.payload.should.be.a.String();
msg.payload.should.equal("ECHO AND MORE");
msg.should.have.property("rc");
msg.rc.should.have.property("code",0);
child_process.exec.restore();
done();
} catch(err) {
}
catch(err) {
child_process.exec.restore();
done(err);
}
};
n2.on("input", function(msg) {
messages[0] = msg;
completeTest();
@@ -169,7 +177,7 @@ describe('exec node', function() {
function(arg1, arg2, arg3, arg4) {
//console.log(arg1);
// arg3(error,stdout,stderr);
arg3("error",new Buffer([0x01,0x02,0x03,0x88]));
arg3("error",new Buffer([0x01,0x02,0x03,0x88]),new Buffer([0x01,0x02,0x03,0x88]));
});
helper.load(execNode, flow, function() {
var n1 = helper.getNode("n1");
@@ -199,33 +207,11 @@ describe('exec node', function() {
// Although Windows timeout command is equivalent to sleep, this cannot be used because it promptly outputs a message.
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping", addpay:false, append:"192.0.2.0 -n 1 -w 1000 > NUL", timer:"0.3", oldrc:"false"},
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
} else {
}
else {
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"sleep", addpay:false, append:"1", timer:"0.3", oldrc:"false"},
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
}
helper.load(execNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
var n3 = helper.getNode("n3");
var n4 = helper.getNode("n4");
n4.on("input", function(msg) {
msg.should.have.property("payload");
msg.payload.should.have.property("signal","SIGTERM");
done();
});
n1.receive({});
});
});
it('should be able to kill a long running command', function(done) {
var flow;
if (osType === "Windows_NT") {
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping", addpay:false, append:"192.0.2.0 -n 1 -w 1000 > NUL", timer:"2", oldrc:"false"},
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
} else {
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"sleep", addpay:false, append:"1", timer:"2", oldrc:"false"},
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
}
helper.load(execNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
@@ -236,9 +222,42 @@ describe('exec node', function() {
msg.should.have.property("payload");
msg.payload.should.have.property("signal","SIGTERM");
done();
} catch(err) {
done(err);
}
catch(err) { done(err); }
});
n1.receive({});
});
});
it('should be able to kill a long running command', function(done) {
var flow;
if (osType === "Windows_NT") {
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping", addpay:false, append:"192.0.2.0 -n 1 -w 1000 > NUL", timer:"2", oldrc:"false"},
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
}
else {
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"sleep", addpay:false, append:"1", timer:"2", oldrc:"false"},
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
}
helper.load(execNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
var n3 = helper.getNode("n3");
var n4 = helper.getNode("n4");
n2.on("input", function(msg) {
try {
msg.should.have.property("rc");
msg.rc.should.have.property("code",null);
msg.rc.should.have.property("signal","SIGTERM");
} catch(err) { done(err); }
});
n4.on("input", function(msg) {
try {
msg.should.have.property("payload");
msg.payload.should.have.property("signal","SIGTERM");
done();
}
catch(err) { done(err); }
});
setTimeout(function() {
n1.receive({kill:""});
@@ -262,14 +281,19 @@ describe('exec node', function() {
var n2 = helper.getNode("n2");
var n3 = helper.getNode("n3");
var n4 = helper.getNode("n4");
n2.on("input", function(msg) {
try {
msg.should.have.property("rc");
msg.rc.should.have.property("code",null);
msg.rc.should.have.property("signal","SIGINT");
} catch(err) { done(err); }
});
n4.on("input", function(msg) {
try {
msg.should.have.property("payload");
msg.payload.should.have.property("signal",sig);
done();
} catch(err) {
done(err);
}
} catch(err) { done(err); }
});
setTimeout(function() {
n1.receive({kill:"SIGINT"});
@@ -278,7 +302,6 @@ describe('exec node', function() {
});
});
it('should return the rc for a failing command', function(done) {
var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"error", addpay:false, append:"", oldrc:"false"},
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
@@ -305,6 +328,9 @@ describe('exec node', function() {
msg.should.have.property("payload");
msg.payload.should.be.a.String();
msg.payload.should.equal("error");
msg.should.have.property("rc");
msg.rc.should.have.property("code",1);
msg.rc.should.have.property("message",undefined);
msg = messages[1];
msg.should.have.property("payload");
@@ -317,7 +343,8 @@ describe('exec node', function() {
child_process.exec.restore();
done();
} catch(err) {
}
catch(err) {
child_process.exec.restore();
done(err);
}
@@ -369,9 +396,8 @@ describe('exec node', function() {
msg.payload.should.be.a.String();
msg.payload.should.equal(expected);
done();
} catch(err) {
done(err);
}
catch(err) { done(err); }
});
n1.receive({payload:"hello world"});
});
@@ -397,10 +423,13 @@ describe('exec node', function() {
var n4 = helper.getNode("n4");
n2.on("input", function(msg) {
//console.log(msg);
msg.should.have.property("payload");
msg.payload.should.be.a.String();
msg.payload.should.equal(expected);
done();
try {
msg.should.have.property("payload");
msg.payload.should.be.a.String();
msg.payload.should.equal(expected);
done();
}
catch(err) { done(err); }
});
n1.receive({payload:12345});
});
@@ -431,9 +460,8 @@ describe('exec node', function() {
msg.payload.length.should.equal(7);
}
done();
} catch(err) {
done(err);
}
catch(err) { done(err); }
});
n1.receive({payload:new Buffer([0x01,0x02,0x03,0x88])});
});
@@ -474,12 +502,12 @@ describe('exec node', function() {
should.exist(msg.payload);
msg.payload.should.have.property("code",0);
done();
} catch(err) {
}
catch(err) {
done(err);
}
};
n2.on("input", function(msg) {
messages[0] = msg;
completeTest();
@@ -501,10 +529,13 @@ describe('exec node', function() {
var n3 = helper.getNode("n3");
var n4 = helper.getNode("n4");
n4.on("input", function(msg) {
msg.should.have.property("payload");
msg.payload.should.have.property("code");
msg.payload.code.should.be.below(0);
done();
try {
msg.should.have.property("payload");
msg.payload.should.have.property("code");
msg.payload.code.should.be.below(0);
done();
}
catch(err) { done(err); }
});
n1.receive({payload:null});
});
@@ -513,6 +544,7 @@ describe('exec node', function() {
it('should return an error for a failing command', function(done) {
var flow;
var expected;
var expectedFound = false;
if (osType === "Windows_NT") {
// Cannot use mkdir because Windows mkdir command automatically creates non-existent directories.
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping /foo/bar/doo/dah", addpay:false, append:"", useSpawn:"true", oldrc:"false"},
@@ -521,7 +553,7 @@ describe('exec node', function() {
} else {
flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"mkdir /foo/bar/doo/dah", addpay:false, append:"", useSpawn:"true", oldrc:"false"},
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
expected = "mkdir: /foo/bar/doo: No such file or directory\n";
expected = ' directory';
}
helper.load(execNode, flow, function() {
var n1 = helper.getNode("n1");
@@ -529,14 +561,26 @@ describe('exec node', function() {
var n3 = helper.getNode("n3");
var n4 = helper.getNode("n4");
n3.on("input", function(msg) {
msg.should.have.property("payload");
msg.payload.should.be.a.String();
msg.payload.should.equal(expected);
try {
msg.should.have.property("payload");
msg.payload.should.be.a.String();
if (msg.payload.indexOf(expected) >= 0) {
// The error text on the stderr stream might get sent in more than one piece.
// We only need to know that it occurred before the return code is sent,
// as checked below in node n4.
expectedFound = true;
}
}
catch(err) { done(err); }
});
n4.on("input", function(msg) {
msg.should.have.property("payload");
msg.payload.should.have.property("code",1);
done();
try {
expectedFound.should.be.true;
msg.should.have.property("payload");
msg.payload.should.have.property("code",1);
done();
}
catch(err) { done(err); }
});
n1.receive({payload:null});
});
@@ -557,10 +601,13 @@ describe('exec node', function() {
var n3 = helper.getNode("n3");
var n4 = helper.getNode("n4");
n4.on("input", function(msg) {
msg.should.have.property("payload");
msg.payload.should.have.property("code",null);
msg.payload.should.have.property("signal","SIGTERM");
done();
try {
msg.should.have.property("payload");
msg.payload.should.have.property("code",null);
msg.payload.should.have.property("signal","SIGTERM");
done();
}
catch(err) { done(err); }
});
n1.receive({});
});
@@ -581,9 +628,12 @@ describe('exec node', function() {
var n3 = helper.getNode("n3");
var n4 = helper.getNode("n4");
n4.on("input", function(msg) {
msg.should.have.property("payload");
msg.payload.should.have.property("signal","SIGTERM");
done();
try {
msg.should.have.property("payload");
msg.payload.should.have.property("signal","SIGTERM");
done();
}
catch(err) { done(err); }
});
setTimeout(function() {
n1.receive({kill:""});
@@ -608,9 +658,12 @@ describe('exec node', function() {
var n3 = helper.getNode("n3");
var n4 = helper.getNode("n4");
n4.on("input", function(msg) {
msg.should.have.property("payload");
msg.payload.should.have.property("signal",sig);
done();
try {
msg.should.have.property("payload");
msg.payload.should.have.property("signal",sig);
done();
}
catch(err) { done(err); }
});
setTimeout(function() {
n1.receive({kill:"SIGINT"});

View File

@@ -52,6 +52,21 @@ describe('function node', function() {
});
});
it('should send returned message using send()', function(done) {
var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"node.send(msg);"},
{id:"n2", type:"helper"}];
helper.load(functionNode, flow, 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', 'foo');
done();
});
n1.receive({payload:"foo",topic: "bar"});
});
});
it('should pass through _topic', function(done) {
var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"return msg;"},
{id:"n2", type:"helper"}];
@@ -160,6 +175,22 @@ describe('function node', function() {
});
});
it('should get keys in global context', function(done) {
var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"msg.payload=global.keys();return msg;"},
{id:"n2", type:"helper"}];
helper.load(functionNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
n1.context().global.set("count","0");
n2.on("input", function(msg) {
msg.should.have.property('topic', 'bar');
msg.should.have.property('payload', ['count']);
done();
});
n1.receive({payload:"foo",topic: "bar"});
});
});
function testNonObjectMessage(functionText,done) {
var flow = [{id:"n1",type:"function",wires:[["n2"]],func:functionText},
{id:"n2", type:"helper"}];
@@ -228,6 +259,251 @@ describe('function node', function() {
}
});
});
it('should handle node.on()', function(done) {
var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"node.on('close',function(){node.log('closed')});"}];
helper.load(functionNode, flow, function() {
var n1 = helper.getNode("n1");
n1.receive({payload:"foo",topic: "bar"});
helper.getNode("n1").close();
try {
helper.log().called.should.be.true();
var logEvents = helper.log().args.filter(function(evt) {
return evt[0].type == "function";
});
logEvents.should.have.length(1);
var msg = logEvents[0][0];
msg.should.have.property('level', helper.log().INFO);
msg.should.have.property('id', 'n1');
msg.should.have.property('type', 'function');
msg.should.have.property('msg', 'closed');
done();
} catch(err) {
done(err);
}
});
});
it('should set node context', function(done) {
var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"context.set('count','0');return msg;"},
{id:"n2", type:"helper"}];
helper.load(functionNode, flow, 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', 'foo');
n1.context().get("count").should.equal("0");
done();
});
n1.receive({payload:"foo",topic: "bar"});
});
});
it('should get node context', function(done) {
var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"msg.payload=context.get('count');return msg;"},
{id:"n2", type:"helper"}];
helper.load(functionNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
n1.context().set("count","0");
n2.on("input", function(msg) {
msg.should.have.property('topic', 'bar');
msg.should.have.property('payload', '0');
done();
});
n1.receive({payload:"foo",topic: "bar"});
});
});
it('should get keys in node context', function(done) {
var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"msg.payload=context.keys();return msg;"},
{id:"n2", type:"helper"}];
helper.load(functionNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
n1.context().set("count","0");
n2.on("input", function(msg) {
msg.should.have.property('topic', 'bar');
msg.should.have.property('payload', ['count']);
done();
});
n1.receive({payload:"foo",topic: "bar"});
});
});
it('should set flow context', function(done) {
var flow = [{id:"n1",type:"function",z:"flowA",wires:[["n2"]],func:"flow.set('count','0');return msg;"},
{id:"n2", type:"helper",z:"flowA"}];
helper.load(functionNode, flow, 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', 'foo');
n2.context().flow.get("count").should.equal("0");
done();
});
n1.receive({payload:"foo",topic: "bar"});
});
});
it('should get flow context', function(done) {
var flow = [{id:"n1",type:"function",z:"flowA",wires:[["n2"]],func:"msg.payload=flow.get('count');return msg;"},
{id:"n2", type:"helper",z:"flowA"}];
helper.load(functionNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
n1.context().flow.set("count","0");
n2.on("input", function(msg) {
msg.should.have.property('topic', 'bar');
msg.should.have.property('payload', '0');
done();
});
n1.receive({payload:"foo",topic: "bar"});
});
});
it('should get flow context', function(done) {
var flow = [{id:"n1",type:"function",z:"flowA",wires:[["n2"]],func:"msg.payload=context.flow.get('count');return msg;"},
{id:"n2", type:"helper",z:"flowA"}];
helper.load(functionNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
n1.context().flow.set("count","0");
n2.on("input", function(msg) {
msg.should.have.property('topic', 'bar');
msg.should.have.property('payload', '0');
done();
});
n1.receive({payload:"foo",topic: "bar"});
});
});
it('should get keys in flow context', function(done) {
var flow = [{id:"n1",type:"function",z:"flowA",wires:[["n2"]],func:"msg.payload=flow.keys();return msg;"},
{id:"n2", type:"helper",z:"flowA"}];
helper.load(functionNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
n1.context().flow.set("count","0");
n2.on("input", function(msg) {
msg.should.have.property('topic', 'bar');
msg.should.have.property('payload', ['count']);
done();
});
n1.receive({payload:"foo",topic: "bar"});
});
});
it('should set global context', function(done) {
var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"global.set('count','0');return msg;"},
{id:"n2", type:"helper"}];
helper.load(functionNode, flow, 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', 'foo');
n2.context().global.get("count").should.equal("0");
done();
});
n1.receive({payload:"foo",topic: "bar"});
});
});
it('should get global context', function(done) {
var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"msg.payload=global.get('count');return msg;"},
{id:"n2", type:"helper"}];
helper.load(functionNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
n1.context().global.set("count","0");
n2.on("input", function(msg) {
msg.should.have.property('topic', 'bar');
msg.should.have.property('payload', '0');
done();
});
n1.receive({payload:"foo",topic: "bar"});
});
});
it('should get global context', function(done) {
var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"msg.payload=context.global.get('count');return msg;"},
{id:"n2", type:"helper"}];
helper.load(functionNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
n1.context().global.set("count","0");
n2.on("input", function(msg) {
msg.should.have.property('topic', 'bar');
msg.should.have.property('payload', '0');
done();
});
n1.receive({payload:"foo",topic: "bar"});
});
});
it('should handle setTimeout()', function(done) {
var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"setTimeout(function(){node.send(msg);},1000);"},
{id:"n2", type:"helper"}];
helper.load(functionNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
var endTime = process.hrtime(startTime);
var nanoTime = endTime[0] * 1000000000 + endTime[1];
msg.should.have.property('topic', 'bar');
msg.should.have.property('payload', 'foo');
if (900000000 < nanoTime && nanoTime < 1100000000) {
done();
} else {
try {
should.fail(null, null, "Delayed time was not between 900 and 1100 ms");
} catch (err) {
done(err);
}
}
});
var startTime = process.hrtime();
n1.receive({payload:"foo",topic: "bar"});
});
});
it('should handle setInterval()', function(done) {
var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"setInterval(function(){node.send(msg);},100);"},
{id:"n2", type:"helper"}];
helper.load(functionNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
var count = 0;
n2.on("input", function(msg) {
msg.should.have.property('topic', 'bar');
msg.should.have.property('payload', 'foo');
count++;
if (count > 2) {
done();
}
});
n1.receive({payload:"foo",topic: "bar"});
});
});
it('should handle clearInterval()', function(done) {
var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"var id=setInterval(null,100);setTimeout(function(){clearInterval(id);node.send(msg);},1000);"},
{id:"n2", type:"helper"}];
helper.load(functionNode, flow, 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', 'foo');
done();
});
n1.receive({payload:"foo",topic: "bar"});
});
});
describe('Logger', function () {
it('should log an Info Message', function (done) {
var flow = [{id: "n1", type: "function", wires: [["n2"]], func: "node.log('test');"}];

View File

@@ -37,9 +37,40 @@ describe('template node', function() {
n2.on("input", function(msg) {
msg.should.have.property('topic', 'bar');
msg.should.have.property('payload', 'payload=foo');
msg.should.have.property('template', '{{payload}}');
done();
});
n1.receive({payload:"foo",topic: "bar"});
n1.receive({payload:"foo",topic: "bar", template: "{{payload}}"});
});
});
it('should modify template from msg.template', function(done) {
var flow = [{id:"n1", type:"template", field:"template", template:"",wires:[["n2"]]},{id:"n2",type:"helper"}];
helper.load(templateNode, flow, 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', 'foo');
msg.should.have.property('template', 'payload=foo');
done();
});
n1.receive({payload:"foo", topic: "bar", template: "payload={{payload}}"});
});
});
it('should modify payload from msg.template', function(done) {
var flow = [{id:"n1", type:"template", field:"payload", template:"",wires:[["n2"]]},{id:"n2",type:"helper"}];
helper.load(templateNode, flow, 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', 'topic=bar');
msg.should.have.property('template', 'topic={{topic}}');
done();
});
n1.receive({payload:"foo", topic: "bar", template: "topic={{topic}}"});
});
});
@@ -88,6 +119,18 @@ describe('template node', function() {
});
});
it('should handle escape characters in Mustache format and JSON output mode', function(done) {
var flow = [{id:"n1", type:"template", field:"payload", syntax:"mustache", template:"{\"data\":\"{{payload}}\"}", output:"json", wires:[["n2"]]},{id:"n2",type:"helper"}];
helper.load(templateNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
msg.payload.should.have.property('data', 'line\t1\nline\\2\r\nline\b3\f');
done();
});
n1.receive({payload:"line\t1\nline\\2\r\nline\b3\f"});
});
});
it('should modify payload in plain text mode', function(done) {
var flow = [{id:"n1", type:"template", field:"payload", syntax:"plain", template:"payload={{payload}}",wires:[["n2"]]},{id:"n2",type:"helper"}];

View File

@@ -347,7 +347,7 @@ describe('delay Node', function() {
* @param delay - the variable delay: milliseconds
*/
function variableDelayTest(aTimeoutFrom, aTimeoutTo, aTimeoutUnit, delay, done) {
var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"delayv","timeout":5,"timeoutUnits":"seconds","rate":"1","rateUnits":"second","randomFirst":aTimeoutFrom,"randomLast":aTimeoutTo,"randomUnits":aTimeoutUnit,"drop":false,"wires":[["helperNode1"]]},
var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"delayv","timeout":0.5,"timeoutUnits":"seconds","rate":"1","rateUnits":"second","randomFirst":aTimeoutFrom,"randomLast":aTimeoutTo,"randomUnits":aTimeoutUnit,"drop":false,"wires":[["helperNode1"]]},
{id:"helperNode1", type:"helper", wires:[]}];
helper.load(delayNode, flow, function() {
var delayNode1 = helper.getNode("delayNode1");
@@ -400,12 +400,16 @@ describe('delay Node', function() {
variableDelayTest("200", "300", "milliseconds", 250, done);
});
it('variable delay is zero if msg.delay not specified', function(done) {
variableDelayTest("0", "50", "milliseconds", null, done);
it('variable delay is the default if msg.delay not specified', function(done) {
variableDelayTest("450", "550", "milliseconds", null, done);
});
it('variable delay is zero if msg.delay is zero', function(done) {
variableDelayTest("0", "20", "milliseconds", 0, done);
});
it('variable delay is zero if msg.delay is negative', function(done) {
variableDelayTest("0", "50", "milliseconds", -250, done);
variableDelayTest("0", "20", "milliseconds", -250, done);
});
/**

View File

@@ -15,8 +15,10 @@
**/
var should = require("should");
var sinon = require("sinon");
var helper = require("../../helper.js");
var triggerNode = require("../../../../nodes/core/core/89-trigger.js");
var RED = require("../../../../red/red.js");
describe('trigger node', function() {
@@ -81,14 +83,17 @@ describe('trigger node', function() {
var n2 = helper.getNode("n2");
var c = 0;
n2.on("input", function(msg) {
if (c === 0) {
msg.should.have.a.property("payload", '1');
c+=1;
}
else {
msg.should.have.a.property("payload", '0');
done();
try {
if (c === 0) {
msg.should.have.a.property("payload", '1');
c+=1;
}
else {
msg.should.have.a.property("payload", '0');
done();
}
}
catch(err) { done(err); }
});
n1.emit("input", {payload:null});
});
@@ -161,6 +166,155 @@ describe('trigger node', function() {
});
});
it('should handle multiple topics as one if not asked to handle', function(done) {
var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", bytopic:"all", op1:"1", op2:"0", op1type:"num", op2type:"num", duration:"30", wires:[["n2"]] },
{id:"n2", type:"helper"} ];
helper.load(triggerNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
var c = 0;
n2.on("input", function(msg) {
try {
c += 1;
if (c === 1) {
msg.should.have.a.property("payload", 1);
msg.should.have.a.property("topic", "A");
}
else if (c === 2) {
msg.should.have.a.property("payload", 0);
msg.should.have.a.property("topic", "A");
done();
}
} catch(err) {
done(err);
}
});
n1.emit("input", {payload:1,topic:"A"});
n1.emit("input", {payload:2,topic:"B"});
n1.emit("input", {payload:3,topic:"C"});
});
});
it('should handle multiple topics individually if asked to do so', function(done) {
var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", bytopic:"topic", op1:"1", op2:"0", op1type:"num", op2type:"num", duration:"30", wires:[["n2"]] },
{id:"n2", type:"helper"} ];
helper.load(triggerNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
var c = 0;
n2.on("input", function(msg) {
try {
c += 1;
if (c === 1) {
msg.should.have.a.property("payload", 1);
msg.should.have.a.property("topic", "A");
}
else if (c === 2) {
msg.should.have.a.property("payload", 1);
msg.should.have.a.property("topic", "B");
}
else if (c === 3) {
msg.should.have.a.property("payload", 1);
msg.should.have.a.property("topic", "C");
}
else if (c === 4) {
msg.should.have.a.property("payload", 0);
msg.should.have.a.property("topic", "A");
}
else if (c === 5) {
msg.should.have.a.property("payload", 0);
msg.should.have.a.property("topic", "B");
}
else if (c === 6) {
msg.should.have.a.property("payload", 0);
msg.should.have.a.property("topic", "C");
done();
}
} catch(err) {
done(err);
}
});
n1.emit("input", {payload:1,topic:"A"});
n1.emit("input", {payload:2,topic:"B"});
n1.emit("input", {payload:3,topic:"C"});
});
});
it('should handle multiple topics individually, and extend one, if asked to do so', function(done) {
var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", bytopic:"topic", extend:"true", op1:"1", op2:"0", op1type:"num", op2type:"num", duration:"30", wires:[["n2"]] },
{id:"n2", type:"helper"} ];
helper.load(triggerNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
var c = 0;
n2.on("input", function(msg) {
try {
c += 1;
if (c === 1) {
msg.should.have.a.property("payload", 1);
msg.should.have.a.property("topic", "A");
}
else if (c === 2) {
msg.should.have.a.property("payload", 1);
msg.should.have.a.property("topic", "B");
}
else if (c === 3) {
msg.should.have.a.property("payload", 1);
msg.should.have.a.property("topic", "C");
}
else if (c === 4) {
msg.should.have.a.property("payload", 0);
msg.should.have.a.property("topic", "A");
}
else if (c === 5) {
msg.should.have.a.property("payload", 0);
msg.should.have.a.property("topic", "C");
}
else if (c === 6) {
msg.should.have.a.property("payload", 0);
msg.should.have.a.property("topic", "B");
done();
}
} catch(err) {
done(err);
}
});
n1.emit("input", {payload:1,topic:"A"});
n1.emit("input", {payload:2,topic:"B"});
n1.emit("input", {payload:3,topic:"C"});
setTimeout( function() { n1.emit("input", {payload:2,topic:"B"})}, 20 );
});
});
it('should be able to return things from flow and global context variables', function(done) {
var spy = sinon.stub(RED.util, 'evaluateNodeProperty',
function(arg1, arg2, arg3, arg4) { return arg1; }
);
var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", op1:"foo", op1type:"flow", op2:"bar", op2type:"global", duration:"20", wires:[["n2"]] },
{id:"n2", type:"helper"} ];
helper.load(triggerNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
var c = 0;
n2.on("input", function(msg) {
try {
if (c === 0) {
msg.should.have.a.property("payload", "foo");
c+=1;
}
else {
msg.should.have.a.property("payload", "bar");
spy.restore();
done();
}
}
catch(err) { spy.restore(); done(err); }
});
n1.emit("input", {payload:null});
});
});
it('should be able to not output anything on first trigger', function(done) {
var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", op1type:"nul", op1:"true",op2:"false",op2type:"val",duration:"30", wires:[["n2"]] },
{id:"n2", type:"helper"} ];
@@ -187,8 +341,11 @@ describe('trigger node', function() {
var n2 = helper.getNode("n2");
var c = 0;
n2.on("input", function(msg) {
msg.should.have.a.property("payload", true);
c += 1;
try {
msg.should.have.a.property("payload", true);
c += 1;
}
catch(err) { done(err); }
});
setTimeout( function() {
c.should.equal(1); // should only have had one output.
@@ -199,23 +356,30 @@ describe('trigger node', function() {
});
it('should be able to extend the delay', function(done) {
var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", extend:"true", op1type:"pay", op1:"false", op2:"true", duration:"100", wires:[["n2"]] },
var spy = sinon.stub(RED.util, 'evaluateNodeProperty',
function(arg1, arg2, arg3, arg4) { return arg1; }
);
var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", extend:"true", op1type:"flow", op1:"foo", op2:"bar", op2type:"global", duration:"100", wires:[["n2"]] },
{id:"n2", type:"helper"} ];
helper.load(triggerNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
var c = 0;
n2.on("input", function(msg) {
if (c === 0) {
msg.should.have.a.property("payload", "Hello");
c += 1;
}
else {
msg.should.have.a.property("payload", "true");
//console.log(Date.now() - ss);
(Date.now() - ss).should.be.greaterThan(149);
done();
try {
if (c === 0) {
msg.should.have.a.property("payload", "foo");
c += 1;
}
else {
msg.should.have.a.property("payload", "bar");
//console.log(Date.now() - ss);
(Date.now() - ss).should.be.greaterThan(149);
spy.restore();
done();
}
}
catch(err) { spy.restore(); done(err); }
});
var ss = Date.now();
n1.emit("input", {payload:"Hello"});
@@ -233,16 +397,19 @@ describe('trigger node', function() {
var n2 = helper.getNode("n2");
var c = 0;
n2.on("input", function(msg) {
if (c === 0) {
msg.should.have.a.property("payload", "Hello");
c += 1;
}
else {
msg.should.have.a.property("payload", "World");
//console.log(Date.now() - ss);
(Date.now() - ss).should.be.greaterThan(70);
done();
try {
if (c === 0) {
msg.should.have.a.property("payload", "Hello");
c += 1;
}
else {
msg.should.have.a.property("payload", "World");
//console.log(Date.now() - ss);
(Date.now() - ss).should.be.greaterThan(70);
done();
}
}
catch(err) { done(err); }
});
var ss = Date.now();
n1.emit("input", {payload:"Hello"});
@@ -263,15 +430,18 @@ describe('trigger node', function() {
var n2 = helper.getNode("n2");
var c = 0;
n2.on("input", function(msg) {
if (c === 0) {
msg.should.have.a.property("payload", "Goodbye");
c += 1;
}
else {
msg.should.have.a.property("payload", "World");
(Date.now() - ss).should.be.greaterThan(70);
done();
try {
if (c === 0) {
msg.should.have.a.property("payload", "Goodbye");
c += 1;
}
else {
msg.should.have.a.property("payload", "World");
(Date.now() - ss).should.be.greaterThan(70);
done();
}
}
catch(err) { done(err); }
});
var ss = Date.now();
n1.emit("input", {payload:"Hello"});
@@ -292,15 +462,18 @@ describe('trigger node', function() {
var n2 = helper.getNode("n2");
var c = 0;
n2.on("input", function(msg) {
if (c === 0) {
msg.should.have.a.property("payload", "Goodbye");
c += 1;
}
else {
msg.should.have.a.property("payload", "World");
(Date.now() - ss).should.be.greaterThan(70);
done();
try {
if (c === 0) {
msg.should.have.a.property("payload", "Goodbye");
c += 1;
}
else {
msg.should.have.a.property("payload", "World");
(Date.now() - ss).should.be.greaterThan(70);
done();
}
}
catch(err) { done(err); }
});
var ss = Date.now();
n1.emit("input", {payload:"Hello"});
@@ -321,14 +494,17 @@ describe('trigger node', function() {
var n2 = helper.getNode("n2");
var c = 0;
n2.on("input", function(msg) {
if (c === 0) {
msg.should.have.a.property("payload", "Hello");
c+=1;
}
else {
msg.should.have.a.property("payload", "World");
done();
try {
if (c === 0) {
msg.should.have.a.property("payload", "Hello");
c+=1;
}
else {
msg.should.have.a.property("payload", "World");
done();
}
}
catch(err) { done(err); }
});
n1.emit("input", {payload:"Hello",topic:"World"});
});
@@ -342,19 +518,46 @@ describe('trigger node', function() {
var n2 = helper.getNode("n2");
var c = 0;
n2.on("input", function(msg) {
if (c === 0) {
msg.should.have.a.property("payload", null);
c+=1;
}
else {
msg.should.have.a.property("payload", "World");
done();
try {
if (c === 0) {
msg.should.have.a.property("payload", null);
c+=1;
}
else {
msg.should.have.a.property("payload", "World");
done();
}
}
catch(err) { done(err); }
});
n1.emit("input", {payload:"World"});
});
});
it('should handle string null as null on op2', function(done) {
var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", op1type:"val", op2type:"val", op1:"null", op2:"null", duration:"40", wires:[["n2"]] },
{id:"n2", type:"helper"} ];
helper.load(triggerNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
var c = 0;
n2.on("input", function(msg) {
try {
if (c === 0) {
msg.should.have.a.property("payload", null);
c+=1;
}
else {
msg.should.have.a.property("payload", null);
done();
}
}
catch(err) { done(err); }
});
n1.emit("input", {payload:"null"});
});
});
it('should be able to set infinite timeout, and clear timeout', function(done) {
var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", duration:"0", extend: false, wires:[["n2"]] },
{id:"n2", type:"helper"} ];
@@ -363,8 +566,11 @@ describe('trigger node', function() {
var n2 = helper.getNode("n2");
var c = 0;
n2.on("input", function(msg) {
c += 1;
msg.should.have.a.property("payload", 1);
try {
c += 1;
msg.should.have.a.property("payload", "1");
}
catch(err) { done(err); }
});
setTimeout( function() {
if (c === 2) { done(); }
@@ -388,8 +594,11 @@ describe('trigger node', function() {
var n2 = helper.getNode("n2");
var c = 0;
n2.on("input", function(msg) {
c += 1;
msg.should.have.a.property("payload", 1);
try {
c += 1;
msg.should.have.a.property("payload", "1");
}
catch(err) { done(err); }
});
setTimeout( function() {
if (c === 2) { done(); }
@@ -406,7 +615,7 @@ describe('trigger node', function() {
});
it('should be able to set a repeat, and clear loop by reset', function(done) {
var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", reset:"boo", duration:-25, wires:[["n2"]] },
var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", reset:"boo", op1:"", op1type:"pay", duration:-25, wires:[["n2"]] },
{id:"n2", type:"helper"} ];
helper.load(triggerNode, flow, function() {
var n1 = helper.getNode("n1");
@@ -414,9 +623,14 @@ describe('trigger node', function() {
var c = 0;
n2.on("input", function(msg) {
c += 1;
msg.should.have.a.property("payload", "foo");
try {
msg.should.have.property('payload','foo');
msg.payload = "bar"; // try to provoke pass by reference error
}
catch(err) { done(err); }
});
n1.emit("input", {payload:"foo"}); // trigger
n1.emit("input", {payload:"foo"}); // trigger
setTimeout( function() {
n1.emit("input", {reset:true}); // reset
},90);

View File

@@ -101,6 +101,8 @@ describe('websocket Node', function() {
helper.load(websocketNode, flow, function() {
createClient("n1").then(function(sock) {
done();
}).catch(function(err) {
done(err);
});
});
});
@@ -113,6 +115,8 @@ describe('websocket Node', function() {
done();
});
helper.clearFlows();
}).catch(function(err) {
done(err);
});
});
});
@@ -129,6 +133,8 @@ describe('websocket Node', function() {
done();
});
sock.send("hello");
}).catch(function(err) {
done(err);
});
});
});
@@ -145,6 +151,8 @@ describe('websocket Node', function() {
msg.should.have.property("text", "hello");
done();
});
}).catch(function(err) {
done(err);
});
});
});
@@ -161,6 +169,8 @@ describe('websocket Node', function() {
msg.should.have.property("payload", "hello");
done();
});
}).catch(function(err) {
done(err);
});
});
});
@@ -179,6 +189,8 @@ describe('websocket Node', function() {
helper.getNode("n2").send({
payload: "hello"
});
}).catch(function(err) {
done(err);
});
});
});
@@ -197,6 +209,8 @@ describe('websocket Node', function() {
helper.getNode("n3").send({
text: "hello"
});
}).catch(function(err) {
done(err);
});
});
});
@@ -216,6 +230,8 @@ describe('websocket Node', function() {
done();
},100);
helper.getNode("n2").send({topic: "hello"});
}).catch(function(err) {
done(err);
});
});
});
@@ -232,6 +248,8 @@ describe('websocket Node', function() {
done();
});
sock.send("hello");
}).catch(function(err) {
done(err);
});
});
});
@@ -248,6 +266,8 @@ describe('websocket Node', function() {
done();
});
sock.send('{"text":"hello"}');
}).catch(function(err) {
done(err);
});
});
});
@@ -272,10 +292,11 @@ describe('websocket Node', function() {
helper.getNode("n3").send({
payload: "hello"
});
});
when.all([def1.promise, def2.promise]).then(function() {
done();
return when.all([def1.promise, def2.promise]).then(function() {
done();
});
}).catch(function(err) {
done(err);
});
});
});

View File

@@ -0,0 +1,217 @@
/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
var fs = require("fs-extra");
var path = require("path");
var should = require("should");
var helper = require("../../helper.js");
var watchNode = require("../../../../nodes/core/io/23-watch.js");
describe('watch Node', function() {
this.timeout(5000);
var resourcesDir = path.join(__dirname,"..","..","..","resources");
var baseDir = path.join(resourcesDir, "23-watch-test-dir");
var count = 0;
function prepareDir() {
var dirToWatch = path.join(baseDir, "base"+count);
fs.mkdirSync(dirToWatch);
count++;
return {
dirToWatch:dirToWatch,
file0ToWatch:path.join(dirToWatch, "file0.txt"),
file1ToWatch:path.join(dirToWatch, "file1.txt"),
subDirToWatch:path.join(dirToWatch, "subdir"),
file2ToWatch:path.join(dirToWatch, "subdir", "file2.txt")
}
}
function wait(msec, func) {
setTimeout(func, msec);
}
before(function(done) {
fs.ensureDirSync(baseDir);
done();
});
after(function(done) {
fs.removeSync(baseDir);
done();
});
afterEach(function(done) {
helper.unload();
done();
});
function testWatch(flow, change_func, results, done) {
var processed = {};
helper.load(watchNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
var count = 0;
var len = Object.keys(results).length;
n2.on("input", function(msg) {
try {
// console.log(msg);
msg.should.have.property('file');
var file = msg.file;
if (file in processed) {
// multiple messages come in rare case
return;
}
processed[file] = true;
if (file === 'subdir') {
// On OSX, we get a change event on subdir when a file inside changes.
// On Travis, we don't. *sigh*
return;
}
(file in results).should.be.true();
var result = results[file];
msg.should.have.property('payload', result.payload);
msg.should.have.property('type', result.type);
if('size' in result) {
msg.should.have.property('size', result.size);
}
count++;
if(count === len) {
n1.close();
// wait for close
wait(100, done);
}
}catch(err) {
done(err);
}
});
// wait for preparation
wait(500, change_func);
});
}
it('should watch a file to be changed', function(done) {
var files = prepareDir();
fs.writeFileSync(files.file0ToWatch, '');
var flow = [{id:"n1", type:"watch", name: "watch",
files: files.file0ToWatch, recursive: false,
wires:[["n2"]]},
{id:"n2", type:"helper"}];
var results = {
'file0.txt' : {
'payload' : files.file0ToWatch,
'topic': files.file0ToWatch,
'type': 'file',
'size': 5
}
};
testWatch(flow, function() {
fs.appendFileSync(files.file0ToWatch, "ABCDE");
}, results, done);
});
it('should watch multiple files to be changed', function(done) {
var files = prepareDir();
fs.writeFileSync(files.file0ToWatch, '');
fs.writeFileSync(files.file1ToWatch, '');
var flow = [{id:"n1", type:"watch", name: "watch",
files: files.file0ToWatch +","+files.file1ToWatch, recursive: false,
wires:[["n2"]]},
{id:"n2", type:"helper"}];
var results = {
'file0.txt' : {
'payload' : files.file0ToWatch,
'topic': files.file0ToWatch,
'type': 'file'//,
// 'size': 5
},
'file1.txt' : {
'payload' : files.file1ToWatch,
'topic': files.file1ToWatch,
'type': 'file'//,
// 'size': 3
}
};
testWatch(flow, function() {
fs.appendFileSync(files.file0ToWatch, "ABCDE");
fs.appendFileSync(files.file1ToWatch, "123");
}, results, done);
});
it('should watch attribute of a file to be changed', function(done) {
var files = prepareDir();
fs.writeFileSync(files.file0ToWatch, '');
fs.chmodSync(files.file0ToWatch, 0o444);
var flow = [{id:"n1", type:"watch", name: "watch",
files: files.file0ToWatch, recursive: false,
wires:[["n2"]]},
{id:"n2", type:"helper"}];
var results = {
'file0.txt' : {
'payload' : files.file0ToWatch,
'topic': files.file0ToWatch,
'type': 'file'//,
// 'size': 0
}
};
testWatch(flow, function() {
fs.chmodSync(files.file0ToWatch, 0o777);
}, results, done);
});
it('should watch a file in a directory to be changed', function(done) {
var files = prepareDir();
fs.writeFileSync(files.file0ToWatch, '');
var flow = [{id:"n1", type:"watch", name: "watch",
files: files.dirToWatch, recursive: true,
wires:[["n2"]]},
{id:"n2", type:"helper"}];
var results = {
'file0.txt' : {
'payload' : files.file0ToWatch,
'topic': files.file0ToWatch,
'type': 'file'//,
// 'size': 5
}
};
testWatch(flow, function() {
fs.appendFileSync(files.file0ToWatch, "ABCDE");
}, results, done);
});
it('should watch a sub directory in a directory to be changed', function(done) {
var files = prepareDir();
fs.mkdirSync(files.subDirToWatch);
var flow = [{id:"n1", type:"watch", name: "watch",
files: files.dirToWatch, recursive: true,
wires:[["n2"]]},
{id:"n2", type:"helper"}];
var results = {
'file2.txt': {
payload: files.file2ToWatch,
type: 'file'//,
// size: 5
}
};
testWatch(flow, function() {
fs.appendFileSync(files.file2ToWatch, "ABCDE");
}, results, done);
});
});

View File

@@ -0,0 +1,229 @@
/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
var net = require("net");
var should = require("should");
var helper = require("../../helper.js");
var tcpinNode = require("../../../../nodes/core/io/31-tcpin.js");
describe('TCP in Node', function() {
var port = 9200;
var server = undefined;
var server_port = 9300;
var reply_data = undefined;
before(function(done) {
done();
});
after(function() {
});
beforeEach(function(done) {
startServer(done);
});
afterEach(function() {
stopServer();
helper.unload();
});
function sendArray(sock, array) {
if(array.length > 0) {
sock.write(array[0], function() {
sendArray(sock, array.slice(1));
});
}
else {
sock.end();
}
}
function startServer(done) {
server_port += 1;
server = net.createServer(function(c) {
sendArray(c, reply_data);
}).listen(server_port, "localhost", function(err) {
done(err);
});
}
function stopServer() {
server.close();
}
function send(wdata) {
var opt = {port:port, host:"localhost"};
var client = net.createConnection(opt, function() {
client.write(wdata[0], function() {
client.end();
if(wdata.length > 1) {
send(wdata.slice(1));
}
});
});
}
function eql(v0, v1) {
return((v0 === v1) || ((typeof v0) === 'object' && v0.equals(v1)));
}
function testTCP(flow, wdata, rdata, is_server, done) {
if(is_server) {
reply_data = wdata;
}
helper.load(tcpinNode, flow, function() {
var n2 = helper.getNode("n2");
var rcount = 0;
n2.on("input", function(msg) {
if(eql(msg.payload, rdata[rcount])) {
rcount++;
}
else {
should.fail();
}
if(rcount === rdata.length) {
done();
}
});
if(!is_server) {
send(wdata);
}
});
}
function testTCP0(flow, wdata, rdata, done) {
testTCP(flow, wdata, rdata, false, done);
}
function testTCP1(flow, wdata, rdata, done) {
testTCP(flow, wdata, rdata, true, done);
}
it('should recv data (Stream/Buffer)', function(done) {
var flow = [{id:"n1", type:"tcp in", server:"server", host:"localhost", port:port, datamode:"stream", datatype:"buffer", newline:"", topic:"", base64:false, wires:[["n2"]] },
{id:"n2", type:"helper"}];
testTCP0(flow, ["foo"], [Buffer("foo")], done);
});
it('should recv data (Stream/String/Delimiter:\\n)', function(done) {
var flow = [{id:"n1", type:"tcp in", server:"server", host:"localhost", port:port, datamode:"stream", datatype:"utf8", newline:"\n", topic:"", base64:false, wires:[["n2"]] },
{id:"n2", type:"helper"}];
testTCP0(flow, ["foo\nbar"], ["foo", "bar"], done);
});
it('should recv data (Stream/String/No delimiter)', function(done) {
var flow = [{id:"n1", type:"tcp in", server:"server", host:"localhost", port:port, datamode:"stream", datatype:"utf8", newline:"", topic:"", base64:false, wires:[["n2"]] },
{id:"n2", type:"helper"}];
testTCP0(flow, ["foo\nbar"], ["foo\nbar"], done);
});
it('should recv data (Stream/Base64)', function(done) {
var flow = [{id:"n1", type:"tcp in", server:"server", host:"localhost", port:port, datamode:"stream", datatype:"base64", newline:"", topic:"", base64:false, wires:[["n2"]] },
{id:"n2", type:"helper"}];
testTCP0(flow, ["foo"], [Buffer("foo").toString('base64')], done);
});
it('should recv data (Single/Buffer)', function(done) {
var flow = [{id:"n1", type:"tcp in", server:"server", host:"localhost", port:port, datamode:"single", datatype:"buffer", newline:"", topic:"", base64:false, wires:[["n2"]] },
{id:"n2", type:"helper"}];
testTCP0(flow, ["foo"], [Buffer("foo")], done);
});
it('should recv data (Single/String)', function(done) {
var flow = [{id:"n1", type:"tcp in", server:"server", host:"localhost", port:port, datamode:"single", datatype:"utf8", newline:"\n", topic:"", base64:false, wires:[["n2"]] },
{id:"n2", type:"helper"}];
testTCP0(flow, ["foo\nbar\nbaz"], ["foo\nbar\nbaz"], done);
});
it('should recv data (Stream/Base64)', function(done) {
var flow = [{id:"n1", type:"tcp in", server:"server", host:"localhost", port:port, datamode:"single", datatype:"base64", newline:"", topic:"", base64:false, wires:[["n2"]] },
{id:"n2", type:"helper"}];
testTCP0(flow, ["foo"], [Buffer("foo").toString('base64')], done);
});
it('should recv multiple data (Stream/Buffer)', function(done) {
var flow = [{id:"n1", type:"tcp in", server:"server", host:"localhost", port:port, datamode:"stream", datatype:"buffer", newline:"", topic:"", base64:false, wires:[["n2"]] },
{id:"n2", type:"helper"}];
testTCP0(flow, ["foo", "bar"], [Buffer("foo"), Buffer("bar")], done);
});
it('should recv multiple data (Stream/String/Delimiter:\\n)', function(done) {
var flow = [{id:"n1", type:"tcp in", server:"server", host:"localhost", port:port, datamode:"stream", datatype:"utf8", newline:"\n", topic:"", base64:false, wires:[["n2"]] },
{id:"n2", type:"helper"}];
testTCP0(flow, ["foo", "bar\nbaz"], ["foo", "bar", "baz"], done);
});
it('should recv multiple data (Stream/String/No delimiter)', function(done) {
var flow = [{id:"n1", type:"tcp in", server:"server", host:"localhost", port:port, datamode:"stream", datatype:"utf8", newline:"", topic:"", base64:false, wires:[["n2"]] },
{id:"n2", type:"helper"}];
testTCP0(flow, ["foo", "bar\nbaz"], ["foo", "bar\nbaz"], done);
});
it('should recv multiple data (Stream/Base64)', function(done) {
var flow = [{id:"n1", type:"tcp in", server:"server", host:"localhost", port:port, datamode:"stream", datatype:"base64", newline:"", topic:"", base64:false, wires:[["n2"]] },
{id:"n2", type:"helper"}];
var wdata = ["foo", "bar"];
var rdata = wdata.map(function(x) {
return Buffer(x).toString('base64');
});
testTCP0(flow, wdata, rdata, done);
});
it('should connect & recv data (Stream/Buffer)', function(done) {
var flow = [{id:"n1", type:"tcp in", server:"client", host:"localhost", port:server_port, datamode:"stream", datatype:"buffer", newline:"", topic:"", base64:false, wires:[["n2"]] },
{id:"n2", type:"helper"}];
testTCP1(flow, ["foo"], [Buffer("foo")], done);
});
it('should connect & recv data (Stream/String/Delimiter:\\n)', function(done) {
var flow = [{id:"n1", type:"tcp in", server:"client", host:"localhost", port:server_port, datamode:"stream", datatype:"utf8", newline:"\n", topic:"", base64:false, wires:[["n2"]] },
{id:"n2", type:"helper"}];
testTCP1(flow, ["foo\nbar"], ["foo", "bar"], done);
});
it('should connect & recv data (Stream/String/No delimiter)', function(done) {
var flow = [{id:"n1", type:"tcp in", server:"client", host:"localhost", port:server_port, datamode:"stream", datatype:"utf8", newline:"", topic:"", base64:false, wires:[["n2"]] },
{id:"n2", type:"helper"}];
testTCP1(flow, ["foo\nbar"], ["foo\nbar"], done);
});
it('should connect & recv data (Stream/Base64)', function(done) {
var flow = [{id:"n1", type:"tcp in", server:"client", host:"localhost", port:server_port, datamode:"stream", datatype:"base64", newline:"", topic:"", base64:false, wires:[["n2"]] },
{id:"n2", type:"helper"}];
testTCP1(flow, ["foo"], [Buffer("foo").toString('base64')], done);
});
it('should connect & recv data (Single/Buffer)', function(done) {
var flow = [{id:"n1", type:"tcp in", server:"client", host:"localhost", port:server_port, datamode:"single", datatype:"buffer", newline:"", topic:"", base64:false, wires:[["n2"]] },
{id:"n2", type:"helper"}];
testTCP1(flow, ["foo"], [Buffer("foo")], done);
});
it('should connect & recv data (Single/String)', function(done) {
var flow = [{id:"n1", type:"tcp in", server:"client", host:"localhost", port:server_port, datamode:"single", datatype:"utf8", newline:"\n", topic:"", base64:false, wires:[["n2"]] },
{id:"n2", type:"helper"}];
testTCP1(flow, ["foo\nbar\nbaz"], ["foo\nbar\nbaz"], done);
});
it('should connect & recv data (Stream/Base64)', function(done) {
var flow = [{id:"n1", type:"tcp in", server:"client", host:"localhost", port:server_port, datamode:"single", datatype:"base64", newline:"", topic:"", base64:false, wires:[["n2"]] },
{id:"n2", type:"helper"}];
testTCP1(flow, ["foo"], [Buffer("foo").toString('base64')], done);
});
});

View File

@@ -0,0 +1,110 @@
/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
var net = require("net");
var should = require("should");
var helper = require("../../helper.js");
var tcpinNode = require("../../../../nodes/core/io/31-tcpin.js");
describe('TCP Request Node', function() {
var server = undefined;
var port = 9000;
function startServer(done) {
port += 1;
server = net.createServer(function(c) {
c.on('data', function(data) {
var rdata = "ACK:"+data.toString();
c.write(rdata);
});
c.on('error', function(err) {
startServer(done);
});
}).listen(port, "127.0.0.1", function(err) {
done();
});
}
before(function(done) {
startServer(done);
});
after(function() {
server.close();
});
afterEach(function() {
helper.unload();
});
function testTCP(flow, val0, val1, done) {
helper.load(tcpinNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
try {
msg.should.have.property('payload', Buffer(val1));
done();
} catch(err) {
done(err);
}
});
if((typeof val0) === 'object') {
n1.receive(val0);
} else {
n1.receive({payload:val0});
}
});
}
it('should send & recv data', function(done) {
var flow = [{id:"n1", type:"tcp request", server:"localhost", port:port, out:"time", splitc: "0", wires:[["n2"]] },
{id:"n2", type:"helper"}];
testTCP(flow, "foo", "ACK:foo", done)
});
it('should send & recv data when specified character received', function(done) {
var flow = [{id:"n1", type:"tcp request", server:"localhost", port:port, out:"char", splitc: "0", wires:[["n2"]] },
{id:"n2", type:"helper"}];
testTCP(flow, "foo0bar0", "ACK:foo0", done);
});
it('should send & recv data after fixed number of chars received', function(done) {
var flow = [{id:"n1", type:"tcp request", server:"localhost", port:port, out:"count", splitc: "7", wires:[["n2"]] },
{id:"n2", type:"helper"}];
testTCP(flow, "foo bar", "ACK:foo", done);
});
it('should send & receive, then keep connection', function(done) {
var flow = [{id:"n1", type:"tcp request", server:"localhost", port:port, out:"sit", splitc: "5", wires:[["n2"]] },
{id:"n2", type:"helper"}];
testTCP(flow, "foo", "ACK:foo", done);
});
it('should send & close', function(done) {
var flow = [{id:"n1", type:"tcp request", server:"localhost", port:port, out:"sit", splitc: "5", wires:[["n2"]] },
{id:"n2", type:"helper"}];
testTCP(flow, "foo", "ACK:foo", done);
});
it('should send & recv data to/from server:port from msg', function(done) {
var flow = [{id:"n1", type:"tcp request", server:"", port:"", out:"time", splitc: "0", wires:[["n2"]] },
{id:"n2", type:"helper"}];
testTCP(flow, {payload:"foo", host:"localhost", port:port}, "ACK:foo", done)
});
});

View File

@@ -0,0 +1,93 @@
/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
var dgram = require("dgram");
var should = require("should");
var helper = require("../../helper.js");
var udpNode = require("../../../../nodes/core/io/32-udp.js");
describe('UDP in Node', function() {
var port = 9100;
before(function(done) {
helper.startServer(done);
});
after(function() {
});
afterEach(function() {
helper.unload();
});
function sendIPv4(msg) {
var sock = dgram.createSocket('udp4');
sock.send(msg, 0, msg.length, port, "127.0.0.1", function(msg) {
sock.close();
});
}
function checkRecv(dt, proto, val0, val1, done) {
var flow = [{id:"n1", type:"udp in",
group: "", multicast:false,
port:port, ipv:proto,
datatype: dt, iface: "",
wires:[["n2"]] },
{id:"n2", type:"helper"}];
helper.load(udpNode, flow, function() {
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
try {
var ip = ((proto === 'udp6') ? '::ffff:':'') +'127.0.0.1';
msg.should.have.property('ip', ip);
msg.should.have.property('port');
msg.should.have.property('payload');
msg.payload.should.deepEqual(val1);
done();
} catch(err) {
done(err);
}
});
sendIPv4(val0);
});
}
it('should recv IPv4 data (Buffer)', function(done) {
checkRecv('buffer', 'udp4', 'hello', Buffer('hello'), done);
});
it('should recv IPv4 data (String)', function(done) {
checkRecv('utf8', 'udp4', 'hello', 'hello', done);
});
it('should recv IPv4 data (base64)', function(done) {
checkRecv('base64', 'udp4', 'hello', Buffer('hello').toString('base64'), done);
});
it('should recv IPv6 data (Buffer)', function(done) {
checkRecv('buffer', 'udp6', 'hello', Buffer('hello'), done);
});
it('should recv IPv6 data (String)', function(done) {
checkRecv('utf8', 'udp6', 'hello', 'hello', done);
});
it('should recv IPv6 data (base64)', function(done) {
checkRecv('base64', 'udp6', 'hello', Buffer('hello').toString('base64'), done);
});
});

View File

@@ -0,0 +1,85 @@
/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
var dgram = require("dgram");
var should = require("should");
var helper = require("../../helper.js");
var udpNode = require("../../../../nodes/core/io/32-udp.js");
describe('UDP out Node', function() {
var port = 9200;
before(function(done) {
helper.startServer(done);
});
after(function() {
});
afterEach(function() {
helper.unload();
});
function recvData(data, done) {
var sock = dgram.createSocket('udp4');
sock.on('message', function(msg, rinfo) {
msg.should.deepEqual(data);
done();
});
sock.bind(port, '127.0.0.1');
port++;
}
function checkSend(proto, val0, val1, decode, dest_in_msg, done) {
var dst_ip = dest_in_msg ? undefined : "127.0.0.1";
var dst_port = dest_in_msg ? undefined : port;
var flow = [{id:"n1", type:"udp out",
addr:dst_ip, port:dst_port, iface: "",
ipv:proto, outport: "random",
base64:decode, multicast:false,
wires:[] }];
helper.load(udpNode, flow, function() {
var n1 = helper.getNode("n1");
var msg = {};
if(decode) {
msg.payload = Buffer("hello").toString('base64');
}
else {
msg.payload = "hello";
}
if(dest_in_msg) {
msg.ip = "127.0.0.1";
msg.port = port;
}
recvData(val1, done);
n1.receive(msg);
});
}
it('should send IPv4 data', function(done) {
checkSend('udp4', 'hello', Buffer('hello'), false, false, done);
});
it('should send IPv4 data (base64)', function(done) {
checkSend('udp4', 'hello', Buffer('hello'), true, false, done);
});
it('should send IPv4 data with dest from msg', function(done) {
checkSend('udp4', 'hello', Buffer('hello'), false, true, done);
});
});

View File

@@ -187,6 +187,10 @@ describe('switch Node', function() {
twoFieldSwitchTest("btwn", "3", "5", true, true, 4, done);
});
it('should check if payload is between given string values', function(done) {
twoFieldSwitchTest("btwn", "c", "e", true, true, "d", done);
});
it('should check if payload is not between given values', function(done) {
twoFieldSwitchTest("btwn", 3, 5, true, false, 12, done);
});
@@ -489,4 +493,9 @@ describe('switch Node', function() {
});
});
it('should handle JSONata expression', function(done) {
var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"$abs(payload)",propertyType:"jsonata",rules:[{"t":"btwn","v":"$sqrt(16)","vt":"jsonata","v2":"$sqrt(36)","v2t":"jsonata"}],checkall:true,outputs:1,wires:[["helperNode1"]]},
{id:"helperNode1", type:"helper", wires:[]}];
customFlowSwitchTest(flow, true, -5, done);
});
});

View File

@@ -64,7 +64,6 @@ describe('change Node', function() {
helper.load(changeNode, flow, function() {
var changeNode1 = helper.getNode("changeNode1");
var helperNode1 = helper.getNode("helperNode1");
var rule = helper.getNode("changeNode1").rules[0];
helperNode1.on("input", function(msg) {
try {
msg.payload.should.equal("changed");
@@ -77,13 +76,31 @@ describe('change Node', function() {
});
});
it('sets the value of global context property', function(done) {
var flow = [{"id":"changeNode1","type":"change",rules:[{ "t":"set","p":"globalValue","pt":"global","to":"changed","tot":"str"}],"name":"changeNode","wires":[["helperNode1"]]},
{id:"helperNode1", type:"helper", wires:[]}];
helper.load(changeNode, flow, function() {
var changeNode1 = helper.getNode("changeNode1");
var helperNode1 = helper.getNode("helperNode1");
helperNode1.on("input", function(msg) {
try {
changeNode1.context().global.get("globalValue").should.equal("changed");
done();
} catch(err) {
done(err);
}
});
changeNode1.context().global.set("globalValue","changeMe");
changeNode1.receive({payload:""});
});
});
it('sets the value and type of the message property', function(done) {
var flow = [{"id":"changeNode1","type":"change",rules:[{ "t": "set", "p": "payload", "pt": "msg", "to": "12345", "tot": "num" }],"reg":false,"name":"changeNode","wires":[["helperNode1"]]},
{id:"helperNode1", type:"helper", wires:[]}];
helper.load(changeNode, flow, function() {
var changeNode1 = helper.getNode("changeNode1");
var helperNode1 = helper.getNode("helperNode1");
var rule = helper.getNode("changeNode1").rules[0];
helperNode1.on("input", function(msg) {
try {
msg.payload.should.equal(12345);
@@ -263,6 +280,44 @@ describe('change Node', function() {
});
});
it('changes the value to flow context property', function(done) {
var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","to":"flowValue","tot":"flow"}],"name":"changeNode","wires":[["helperNode1"]],"z":"flow"},
{id:"helperNode1", type:"helper", wires:[]}];
helper.load(changeNode, flow, function() {
var changeNode1 = helper.getNode("changeNode1");
var helperNode1 = helper.getNode("helperNode1");
helperNode1.on("input", function(msg) {
try {
msg.payload.should.eql("Hello World!");
done();
} catch(err) {
done(err);
}
});
changeNode1.context().flow.set("flowValue","Hello World!");
changeNode1.receive({payload:""});
});
});
it('changes the value to global context property', function(done) {
var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","to":"globalValue","tot":"global"}],"name":"changeNode","wires":[["helperNode1"]]},
{id:"helperNode1", type:"helper", wires:[]}];
helper.load(changeNode, flow, function() {
var changeNode1 = helper.getNode("changeNode1");
var helperNode1 = helper.getNode("helperNode1");
helperNode1.on("input", function(msg) {
try {
msg.payload.should.eql("Hello World!");
done();
} catch(err) {
done(err);
}
});
changeNode1.context().global.set("globalValue","Hello World!");
changeNode1.receive({payload:""});
});
});
it('changes the value to a number', function(done) {
var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","to":"123","tot":"num"}],"name":"changeNode","wires":[["helperNode1"]]},
{id:"helperNode1", type:"helper", wires:[]}];
@@ -281,6 +336,24 @@ describe('change Node', function() {
});
});
it('changes the value to a boolean value', function(done) {
var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","to":"true","tot":"bool"}],"name":"changeNode","wires":[["helperNode1"]]},
{id:"helperNode1", type:"helper", wires:[]}];
helper.load(changeNode, flow, function() {
var changeNode1 = helper.getNode("changeNode1");
var helperNode1 = helper.getNode("helperNode1");
helperNode1.on("input", function(msg) {
try {
msg.payload.should.eql(true);
done();
} catch(err) {
done(err);
}
});
changeNode1.receive({payload:""});
});
});
it('changes the value to a js object', function(done) {
var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","to":'{"a":123}',"tot":"json"}],"name":"changeNode","wires":[["helperNode1"]]},
{id:"helperNode1", type:"helper", wires:[]}];
@@ -299,13 +372,31 @@ describe('change Node', function() {
});
});
it('changes the value to a buffer object', function(done) {
var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","to":"[72,101,108,108,111,32,87,111,114,108,100]","tot":"bin"}],"name":"changeNode","wires":[["helperNode1"]]},
{id:"helperNode1", type:"helper", wires:[]}];
helper.load(changeNode, flow, function() {
var changeNode1 = helper.getNode("changeNode1");
var helperNode1 = helper.getNode("helperNode1");
helperNode1.on("input", function(msg) {
try {
var buff = Buffer.from("Hello World");
msg.payload.should.eql(buff);
done();
} catch(err) {
done(err);
}
});
changeNode1.receive({payload:""});
});
});
it('sets the value of the message property to the current timestamp', function(done) {
var flow = [{"id":"changeNode1","type":"change","rules":[{"t":"set","p":"ts","pt":"msg","to":"","tot":"date"}],"name":"changeNode","wires":[["helperNode1"]]},
{id:"helperNode1", type:"helper", wires:[]}];
helper.load(changeNode, flow, function() {
var changeNode1 = helper.getNode("changeNode1");
var helperNode1 = helper.getNode("helperNode1");
var rule = helper.getNode("changeNode1").rules[0];
helperNode1.on("input", function(msg) {
try {
(Date.now() - msg.ts).should.be.approximately(0,50);
@@ -318,6 +409,24 @@ describe('change Node', function() {
});
});
it('changes the value using jsonata', function(done) {
var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","to":"$length(payload)","tot":"jsonata"}],"name":"changeNode","wires":[["helperNode1"]]},
{id:"helperNode1", type:"helper", wires:[]}];
helper.load(changeNode, flow, function() {
var changeNode1 = helper.getNode("changeNode1");
var helperNode1 = helper.getNode("helperNode1");
helperNode1.on("input", function(msg) {
try {
msg.payload.should.eql(12);
done();
} catch(err) {
done(err);
}
});
changeNode1.receive({payload:"Hello World!"});
});
});
});
describe('#change', function() {
it('changes the value of the message property', function(done) {
@@ -344,7 +453,6 @@ describe('change Node', function() {
helper.load(changeNode, flow, function() {
var changeNode1 = helper.getNode("changeNode1");
var helperNode1 = helper.getNode("helperNode1");
var rule = helper.getNode("changeNode1").rules[0];
helperNode1.on("input", function(msg) {
try {
msg.payload.should.equal("Change456Me");
@@ -365,7 +473,6 @@ describe('change Node', function() {
helper.load(changeNode, flow, function() {
var changeNode1 = helper.getNode("changeNode1");
var helperNode1 = helper.getNode("helperNode1");
var rule = helper.getNode("changeNode1").rules[0];
helperNode1.on("input", function(msg) {
try {
msg.payload.should.equal(456);
@@ -541,6 +648,63 @@ describe('change Node', function() {
});
});
it('changes the value using flow context property', function(done) {
var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"change","p":"payload","from":"topic","to":"123","fromt":"flow","tot":"str"}],"name":"changeNode","wires":[["helperNode1"]],"z":"flow"},
{id:"helperNode1", type:"helper", wires:[]}];
helper.load(changeNode, flow, function() {
var changeNode1 = helper.getNode("changeNode1");
var helperNode1 = helper.getNode("helperNode1");
helperNode1.on("input", function(msg) {
try {
msg.payload.should.equal("abc123abc");
done();
} catch(err) {
done(err);
}
});
changeNode1.context().flow.set("topic","ABC");
changeNode1.receive({payload:"abcABCabc"});
});
});
it('changes the value using global context property', function(done) {
var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"change","p":"payload","from":"topic","to":"123","fromt":"global","tot":"str"}],"name":"changeNode","wires":[["helperNode1"]]},
{id:"helperNode1", type:"helper", wires:[]}];
helper.load(changeNode, flow, function() {
var changeNode1 = helper.getNode("changeNode1");
var helperNode1 = helper.getNode("helperNode1");
helperNode1.on("input", function(msg) {
try {
msg.payload.should.equal("abc123abc");
done();
} catch(err) {
done(err);
}
});
changeNode1.context().global.set("topic","ABC");
changeNode1.receive({payload:"abcABCabc"});
});
});
it('changes the number using global context property', function(done) {
var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"change","p":"payload","from":"topic","to":"ABC","fromt":"global","tot":"str"}],"name":"changeNode","wires":[["helperNode1"]]},
{id:"helperNode1", type:"helper", wires:[]}];
helper.load(changeNode, flow, function() {
var changeNode1 = helper.getNode("changeNode1");
var helperNode1 = helper.getNode("helperNode1");
helperNode1.on("input", function(msg) {
try {
msg.payload.should.equal("ABC");
done();
} catch(err) {
done(err);
}
});
changeNode1.context().global.set("topic",123);
changeNode1.receive({payload:123});
});
});
it('changes the value using number - string payload', function(done) {
var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"change","p":"payload","from":"123","to":"456","fromt":"num","tot":"str"}],"name":"changeNode","wires":[["helperNode1"]]},
{id:"helperNode1", type:"helper", wires:[]}];
@@ -612,6 +776,103 @@ describe('change Node', function() {
changeNode1.receive({payload:true});
});
});
it('changes the value of the global context', function(done) {
var flow = [{"id":"changeNode1","type":"change",rules:[{ "t": "change", "p": "payload", "pt": "global", "from": "Hello", "fromt": "str", "to": "Goodbye", "tot": "str" }],"reg":false,"name":"changeNode","wires":[["helperNode1"]],"z":"flow"},
{id:"helperNode1", type:"helper", wires:[],"z":"flow"}];
helper.load(changeNode, flow, function() {
var changeNode1 = helper.getNode("changeNode1");
var helperNode1 = helper.getNode("helperNode1");
helperNode1.on("input", function(msg) {
try {
helperNode1.context().global.get("payload").should.equal("Goodbye World!");
done();
} catch(err) {
done(err);
}
});
changeNode1.context().global.set("payload","Hello World!");
changeNode1.receive({payload:""});
});
});
it('changes the value and doesnt change type of the flow context for partial match', function(done) {
var flow = [{"id":"changeNode1","type":"change",rules:[{ "t": "change", "p": "payload", "pt": "flow", "from": "123", "fromt": "str", "to": "456", "tot": "num" }],"reg":false,"name":"changeNode","wires":[["helperNode1"]],"z":"flow"},
{id:"helperNode1", type:"helper", wires:[],"z":"flow"}];
helper.load(changeNode, flow, function() {
var changeNode1 = helper.getNode("changeNode1");
var helperNode1 = helper.getNode("helperNode1");
helperNode1.on("input", function(msg) {
try {
helperNode1.context().flow.get("payload").should.equal("Change456Me");
helperNode1.context().flow.get("payload").should.be.a.String();
done();
} catch(err) {
done(err);
}
});
changeNode1.context().flow.set("payload","Change123Me");
changeNode1.receive({payload:""});
});
});
it('changes the value and type of the flow context if a complete match', function(done) {
var flow = [{"id":"changeNode1","type":"change",rules:[{ "t": "change", "p": "payload", "pt": "flow", "from": "123", "fromt": "str", "to": "456", "tot": "num" }],"reg":false,"name":"changeNode","wires":[["helperNode1"]],"z":"flow"},
{id:"helperNode1", type:"helper", wires:[],"z":"flow"}];
helper.load(changeNode, flow, function() {
var changeNode1 = helper.getNode("changeNode1");
var helperNode1 = helper.getNode("helperNode1");
helperNode1.on("input", function(msg) {
try {
helperNode1.context().flow.get("payload").should.equal(456);
helperNode1.context().flow.get("payload").should.be.a.Number();
done();
} catch(err) {
done(err);
}
});
changeNode1.context().flow.set("payload","123");
changeNode1.receive({payload:""});
});
});
it('changes the value using number - number flow context', function(done) {
var flow = [{"id":"changeNode1","type":"change",rules:[{ "t": "change", "p": "payload", "pt": "flow", "from": "123", "fromt": "num", "to": "abc", "tot": "str" }],"reg":false,"name":"changeNode","wires":[["helperNode1"]],"z":"flow"},
{id:"helperNode1", type:"helper", wires:[],"z":"flow"}];
helper.load(changeNode, flow, function() {
var changeNode1 = helper.getNode("changeNode1");
var helperNode1 = helper.getNode("helperNode1");
helperNode1.on("input", function(msg) {
try {
helperNode1.context().flow.get("payload").should.equal("abc");
done();
} catch(err) {
done(err);
}
});
changeNode1.context().flow.set("payload",123);
changeNode1.receive({payload:""});
});
});
it('changes the value using boolean - boolean flow context', function(done) {
var flow = [{"id":"changeNode1","type":"change",rules:[{ "t": "change", "p": "payload", "pt": "flow", "from": "true", "fromt": "bool", "to": "abc", "tot": "str" }],"reg":false,"name":"changeNode","wires":[["helperNode1"]],"z":"flow"},
{id:"helperNode1", type:"helper", wires:[],"z":"flow"}];
helper.load(changeNode, flow, function() {
var changeNode1 = helper.getNode("changeNode1");
var helperNode1 = helper.getNode("helperNode1");
helperNode1.on("input", function(msg) {
try {
helperNode1.context().flow.get("payload").should.equal("abc");
done();
} catch(err) {
done(err);
}
});
changeNode1.context().flow.set("payload",true);
changeNode1.receive({payload:""});
});
});
});
describe("#delete", function() {
@@ -633,6 +894,25 @@ describe('change Node', function() {
});
});
it('deletes the value of global context property', function(done) {
var flow = [{"id":"changeNode1","type":"change",rules:[{ "t": "delete", "p": "globalValue", "pt": "global"}],"name":"changeNode","wires":[["helperNode1"]]},
{id:"helperNode1", type:"helper", wires:[]}];
helper.load(changeNode, flow, function() {
var changeNode1 = helper.getNode("changeNode1");
var helperNode1 = helper.getNode("helperNode1");
helperNode1.on("input", function(msg) {
try {
changeNode1.context().global.should.not.have.property("globalValue");
done();
} catch(err) {
done(err);
}
});
changeNode1.context().global.set("globalValue","Hello World!");
changeNode1.receive({payload:""});
});
});
it('deletes the value of a multi-level message property', function(done) {
var flow = [{"id":"changeNode1","type":"change","action":"delete","property":"foo.bar","from":"","to":"","reg":false,"name":"changeNode","wires":[["helperNode1"]]},
{id:"helperNode1", type:"helper", wires:[]}];

View File

@@ -323,6 +323,7 @@ describe('JOIN node', function() {
n1.receive({payload:"D", parts:{id:1, type:"string", ch:",", index:3, count:4}});
});
});
it('should join bits of buffer back together automatically', function(done) {
var flow = [{id:"n1", type:"join", wires:[["n2"]], joiner:",", build:"buffer", mode:"auto"},
{id:"n2", type:"helper"}];
@@ -425,6 +426,34 @@ describe('JOIN node', function() {
});
});
it('should merge full msg objects', function(done) {
var flow = [{id:"n1", type:"join", wires:[["n2"]], count:6, build:"merged", mode:"custom", propertyType:"full", property:""},
{id:"n2", type:"helper"}];
helper.load(joinNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
try {
msg.payload.should.have.property("payload",7);
msg.payload.should.have.property("aha",'c');
msg.payload.should.have.property("bar",'b');
msg.payload.should.have.property("bingo",'e');
msg.payload.should.have.property("foo",'d');
msg.payload.should.have.property("topic",'a');
done();
}
catch(e) { done(e)}
});
n1.receive({payload:1, topic:"f"});
n1.receive({payload:2, topic:"a"});
n1.receive({payload:3, foo:"b"});
n1.receive({payload:4, bar:"b"});
n1.receive({payload:5, aha:"c"});
n1.receive({payload:6, foo:"d"});
n1.receive({payload:7, bingo:"e"});
});
});
it('should accumulate a merged object', function(done) {
var flow = [{id:"n1", type:"join", wires:[["n2"]], build:"merged",mode:"custom",accumulate:true, count:1},
{id:"n2", type:"helper"}];
@@ -559,6 +588,31 @@ describe('JOIN node', function() {
});
});
it('should join complete message objects into an array after a count', function(done) {
var flow = [{id:"n1", type:"join", wires:[["n2"]], build:"array", timeout:0, count:3, propertyType:"full",mode:"custom"},
{id:"n2", type:"helper"}];
helper.load(joinNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
try {
msg.payload.should.be.an.Array();
msg.payload[0].should.be.an.Object();
msg.payload[0].should.have.property("payload","a");
msg.payload[1].should.be.an.Object();
msg.payload[1].should.have.property("payload","b");
msg.payload[2].should.be.an.Object();
msg.payload[2].should.have.property("payload","c");
done();
}
catch(e) { done(e); }
});
n1.receive({payload:"a"});
n1.receive({payload:"b"});
n1.receive({payload:"c"});
});
});
it('should join split things back into an array', function(done) {
var flow = [{id:"n1", type:"join", wires:[["n2"]]},
{id:"n2", type:"helper"}];

View File

@@ -0,0 +1,232 @@
/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
var should = require("should");
var sortNode = require("../../../../nodes/core/logic/18-sort.js");
var helper = require("../../helper.js");
var RED = require("../../../../red/red.js");
describe('SORT node', function() {
before(function(done) {
helper.startServer(done);
});
afterEach(function() {
helper.unload();
});
it('should be loaded', function(done) {
var flow = [{id:"n1", type:"sort", order:"ascending", as_num:false, keyType:"payload", name: "SortNode", wires:[["n2"]]},
{id:"n2", type:"helper"}];
helper.load(sortNode, flow, function() {
var n1 = helper.getNode("n1");
n1.should.have.property('name', 'SortNode');
done();
});
});
function check_sort0(flow, data_in, data_out, done) {
helper.load(sortNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
var count = 0;
n2.on("input", function(msg) {
msg.should.have.property("payload");
msg.should.have.property("parts");
msg.parts.should.have.property("count", data_out.length);
var index = data_out.indexOf(msg.payload);
msg.parts.should.have.property("index", index);
count++;
if (count === data_out.length) {
done();
}
});
var len = data_in.length;
for(var i = 0; i < len; i++) {
var parts = { id: "X", index: i, count: len };
n1.receive({payload:data_in[i], parts: parts});
}
});
}
function check_sort1(flow, data_in, data_out, done) {
helper.load(sortNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
msg.should.have.property("payload");
msg.payload.length.should.equal(data_out.length);
for(var i = 0; i < data_out.length; i++) {
msg.payload[i].should.equal(data_out[i]);
}
done();
});
n1.receive({payload:data_in});
});
}
(function() {
var flow = [{id:"n1", type:"sort", order:"ascending", as_num:false, keyType:"payload", wires:[["n2"]]},
{id:"n2", type:"helper"}];
var data_in = [ "200", "4", "30", "1000" ];
var data_out = [ "1000", "200", "30", "4" ];
it('should sort message group (payload, not number, ascending)', function(done) {
check_sort0(flow, data_in, data_out, done);
});
it('should sort payload (payload, not number, ascending)', function(done) {
check_sort1(flow, data_in, data_out, done);
});
})();
(function() {
var flow = [{id:"n1", type:"sort", order:"descending", as_num:false, keyType:"payload", wires:[["n2"]]},
{id:"n2", type:"helper"}];
var data_in = [ "200", "4", "30", "1000" ];
var data_out = [ "4", "30", "200", "1000" ];
it('should sort message group (payload, not number, descending)', function(done) {
check_sort0(flow, data_in, data_out, done);
});
it('should sort payload (payload, not number, descending)', function(done) {
check_sort1(flow, data_in, data_out, done);
});
})();
(function() {
var flow = [{id:"n1", type:"sort", order:"ascending", as_num:true, keyType:"payload", wires:[["n2"]]},
{id:"n2", type:"helper"}];
var data_in = [ "200", "4", "30", "1000" ];
var data_out = [ "4", "30", "200", "1000" ];
it('should sort message group (payload, number, ascending)', function(done) {
check_sort0(flow, data_in, data_out, done);
});
it('should sort payload (payload, number, ascending)', function(done) {
check_sort1(flow, data_in, data_out, done);
});
})();
(function() {
var flow = [{id:"n1", type:"sort", order:"descending", as_num:true, keyType:"payload", wires:[["n2"]]},
{id:"n2", type:"helper"}];
var data_in = [ "200", "4", "30", "1000" ];
var data_out = [ "1000", "200", "30", "4" ];
it('should sort message group (payload, number, descending)', function(done) {
check_sort0(flow, data_in, data_out, done);
});
it('should sort payload (payload, number, descending)', function(done) {
check_sort1(flow, data_in, data_out, done);
});
})();
(function() {
var data_in = [ "C200", "A4", "B30", "D1000" ];
var data_out = [ "D1000", "C200", "B30", "A4" ];
it('should sort message group (exp, not number, ascending)', function(done) {
var flow = [{id:"n1", type:"sort", order:"ascending", as_num:false, keyType:"exp", key:"$substring(payload, 1)", wires:[["n2"]]},
{id:"n2", type:"helper"}];
check_sort0(flow, data_in, data_out, done);
});
it('should sort payload (exp, not number, ascending)', function(done) {
var flow = [{id:"n1", type:"sort", order:"ascending", as_num:false, keyType:"exp", key:"$substring($, 1)", wires:[["n2"]]},
{id:"n2", type:"helper"}];
check_sort1(flow, data_in, data_out, done);
});
})();
(function() {
var data_in = [ "C200", "A4", "B30", "D1000" ];
var data_out = [ "A4", "B30", "C200", "D1000" ];
it('should sort message group (exp, not number, descending)', function(done) {
var flow = [{id:"n1", type:"sort", order:"descending", as_num:false, keyType:"exp", key:"$substring(payload, 1)", wires:[["n2"]]},
{id:"n2", type:"helper"}];
check_sort0(flow, data_in, data_out, done);
});
it('should sort payload (exp, not number, descending)', function(done) {
var flow = [{id:"n1", type:"sort", order:"descending", as_num:false, keyType:"exp", key:"$substring($, 1)", wires:[["n2"]]},
{id:"n2", type:"helper"}];
check_sort1(flow, data_in, data_out, done);
});
})();
it('should handle JSONata script error', function(done) {
var flow = [{id:"n1", type:"sort", order:"ascending", as_num:false, keyType:"exp", key:"$unknown()", wires:[["n2"]]},
{id:"n2", type:"helper"}];
helper.load(sortNode, flow, function() {
var n1 = helper.getNode("n1");
setTimeout(function() {
var logEvents = helper.log().args.filter(function (evt) {
return evt[0].type == "sort";
});
var evt = logEvents[0][0];
evt.should.have.property('id', "n1");
evt.should.have.property('type', "sort");
evt.should.have.property('msg', "sort.invalid-exp");
done();
}, 150);
var msg0 = { payload: "A", parts: { id: "X", index: 0, count: 2} };
var msg1 = { payload: "B", parts: { id: "X", index: 1, count: 2} };
n1.receive(msg0);
n1.receive(msg1);
});
});
it('should handle too many pending messages', function(done) {
var flow = [{id:"n1", type:"sort", order:"ascending", as_num:false, keyType:"payload", wires:[["n2"]]},
{id:"n2", type:"helper"}];
helper.load(sortNode, flow, function() {
var n1 = helper.getNode("n1");
RED.settings.sortMaxKeptMsgsCount = 2;
setTimeout(function() {
var logEvents = helper.log().args.filter(function (evt) {
return evt[0].type == "sort";
});
var evt = logEvents[0][0];
evt.should.have.property('id', "n1");
evt.should.have.property('type', "sort");
evt.should.have.property('msg', "sort.too-many");
done();
}, 150);
for(var i = 0; i < 4; i++) {
var msg = { payload: "V"+i,
parts: { id: "X", index: i, count: 4} };
n1.receive(msg);
}
});
});
it('should clear pending messages on close', function(done) {
var flow = [{id:"n1", type:"sort", order:"ascending", as_num:false, keyType:"payload", wires:[["n2"]]},
{id:"n2", type:"helper"}];
helper.load(sortNode, flow, function() {
var n1 = helper.getNode("n1");
setTimeout(function() {
var logEvents = helper.log().args.filter(function (evt) {
return evt[0].type == "sort";
});
var evt = logEvents[0][0];
evt.should.have.property('id', "n1");
evt.should.have.property('type', "sort");
evt.should.have.property('msg', "sort.clear");
done();
}, 150);
var msg = { payload: 0,
parts: { id: "X", index: 0, count: 2} };
n1.receive(msg);
n1.close();
});
});
});

View File

@@ -46,6 +46,23 @@ describe('CSV node', function() {
});
describe('csv to json', function() {
var parts_id = undefined;
afterEach(function() {
parts_id = undefined;
});
function check_parts(msg, index, count) {
msg.should.have.property('parts');
if(parts_id === undefined) {
parts_id = msg.parts.id;
}
else {
msg.parts.should.have.property('id', parts_id);
}
msg.parts.should.have.property('index', index);
msg.parts.should.have.property('count', count);
}
it('should convert a simple csv string to a javascript object', function(done) {
var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d", wires:[["n2"]] },
@@ -55,6 +72,7 @@ describe('CSV node', function() {
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
msg.should.have.property('payload', { a: 1, b: 2, c: 3, d: 4 });
check_parts(msg, 0, 1);
done();
});
var testString = "1,2,3,4"+String.fromCharCode(10);
@@ -70,6 +88,7 @@ describe('CSV node', function() {
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
msg.should.have.property('payload', { a: 1, b: 2, c: 3, d: 4 });
check_parts(msg, 0, 1);
done();
});
var testString = "1,2,3,4"+String.fromCharCode(10);
@@ -85,6 +104,7 @@ describe('CSV node', function() {
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
msg.should.have.property('payload', { col1: 1, col2: 2, col3: 3, col4: 4 });
check_parts(msg, 0, 1);
done();
});
var testString = "1,2,3,4"+String.fromCharCode(10);
@@ -100,6 +120,7 @@ describe('CSV node', function() {
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
msg.should.have.property('payload', { a: 1, d: 4 });
check_parts(msg, 0, 1);
done();
});
var testString = "1,2,3,4"+String.fromCharCode(10);
@@ -117,6 +138,7 @@ describe('CSV node', function() {
n2.on("input", function(msg) {
//console.log(msg);
msg.should.have.property('payload', { a: 1, b: -2, c: '+3', d: 4, e: -5, f: 'ab"cd', g: 'with,a,comma' });
check_parts(msg, 0, 1);
done();
});
var testString = '"1","-2","+3","04","-05","ab""cd","with,a,comma"'+String.fromCharCode(10);
@@ -134,6 +156,7 @@ describe('CSV node', function() {
//console.log(msg);
msg.should.have.property('payload', { a: "with,an", b: "odd,number", c: "ofquotes" });
//msg.should.have.property('payload', { a: 1, b: -2, c: '+3', d: 4, e: -5, f: 'ab"cd', g: 'with,a,comma' });
check_parts(msg, 0, 1);
done();
});
var testString = '"with,a"n,odd","num"ber","of"qu"ot"es"'+String.fromCharCode(10);
@@ -152,10 +175,12 @@ describe('CSV node', function() {
//console.log(msg);
if (c === 0) {
msg.should.have.property('payload', { w: 1, x: 2, y: 3, z: 4 });
check_parts(msg, 0, 2);
c += 1;
}
else {
msg.should.have.property('payload', { w: 5, x: 6, y: 7, z: 8 });
check_parts(msg, 1, 2);
done();
}
});
@@ -172,6 +197,7 @@ describe('CSV node', function() {
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
msg.should.have.property('payload', [ { a: 1, b: 2, c: 3, d: 4 },{ a: 5, b: -6, c: 7, d: '+8' },{ a: 9, b: 0, c: 'a', d: 'b' },{ a: 'c', b: 'd', c: 'e', d: 'f' } ]);
msg.should.not.have.property('parts');
done();
});
var testString = "1,2,3,4\n5,-6,07,+8\n9,0,a,b\nc,d,e,f";
@@ -187,30 +213,200 @@ describe('CSV node', function() {
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
msg.should.have.property('payload', { a: "a", b: "127.0.0.1", c: 56.7, d: -32.8, e: "+76.22C" });
check_parts(msg, 0, 1);
done();
});
var testString = "a,127.0.0.1,56.7,-32.8,+76.22C";
n1.emit("input", {payload:testString});
});
});
});
describe('json object to csv', function() {
it('should convert a simple object back to a csv', function(done) {
it('should preserve parts property', function(done) {
var flow = [ { id:"n1", type:"csv", temp:"a,b,c,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, c: 3, d: 4 });
check_parts(msg, 3, 4);
done();
});
var testString = "1,2,3,4"+String.fromCharCode(10);
n1.emit("input", {payload:testString, parts: {id:"X", index:3, count:4} });
});
});
it('should be able to use the first of multiple parts as a template if parts are present', function(done) {
var flow = [ { id:"n1", type:"csv", temp:"", hdrin:true, wires:[["n2"]] },
{id:"n2", type:"helper"} ];
helper.load(csvNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
var c = 0;
n2.on("input", function(msg) {
if (c === 0) {
msg.should.have.property('payload', { w: 1, x: 2, y: 3, z: 4 });
check_parts(msg, 0, 2);
c += 1;
}
else {
msg.should.have.property('payload', { w: 5, x: 6, y: 7, z: 8 });
check_parts(msg, 1, 2);
done();
}
});
var testString1 = "w,x,y,z\n";
var testString2 = "1,2,3,4\n";
var testString3 = "5,6,7,8\n";
n1.emit("input", {payload:testString1, parts:{id:"X", index:0, count:3}});
n1.emit("input", {payload:testString2, parts:{id:"X", index:1, count:3}});
n1.emit("input", {payload:testString3, parts:{id:"X", index:2, count:3}});
});
});
it('should skip several lines from start if requested', function(done) {
var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d", skip: 2, 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: 9, b: 0, c: "A", d: "B" });
check_parts(msg, 0, 1);
done();
});
var testString = "1,2,3,4"+String.fromCharCode(10)+"5,6,7,8"+String.fromCharCode(10)+"9,0,A,B"+String.fromCharCode(10);
n1.emit("input", {payload:testString});
});
});
it('should skip several lines from start then use next line as a tempate', function(done) {
var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d", hdrin:true, skip: 2, 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', { "9": "C", "0": "D", "A": "E", "B": "F" });
check_parts(msg, 0, 1);
done();
});
var testString = "1,2,3,4"+String.fromCharCode(10)+"5,6,7,8"+String.fromCharCode(10)+"9,0,A,B"+String.fromCharCode(10)+"C,D,E,F"+String.fromCharCode(10);
n1.emit("input", {payload:testString});
});
});
it('should skip several lines from start and correct parts', function(done) {
var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d", skip: 2, wires:[["n2"]] },
{id:"n2", type:"helper"} ];
helper.load(csvNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
var c = 0;
n2.on("input", function(msg) {
if (c===0) {
msg.should.have.property('payload', { a: 9, b: 0, c: "A", d: "B" });
check_parts(msg, 0, 2);
c = c+1;
}
else {
msg.should.have.property('payload', { a: "C", b: "D", c: "E", d: "F" });
check_parts(msg, 1, 2);
done();
}
});
var testString = "1,2,3,4"+String.fromCharCode(10)+"5,6,7,8"+String.fromCharCode(10)+"9,0,A,B"+String.fromCharCode(10)+"C,D,E,F"+String.fromCharCode(10);
n1.emit("input", {payload:testString});
});
});
it('should be able to skip and then use the first of multiple parts as a template if parts are present', function(done) {
var flow = [ { id:"n1", type:"csv", temp:"", hdrin:true, skip:2, wires:[["n2"]] },
{id:"n2", type:"helper"} ];
helper.load(csvNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
var c = 0;
n2.on("input", function(msg) {
if (c === 0) {
msg.should.have.property('payload', { w: 1, x: 2, y: 3, z: 4 });
check_parts(msg, 0, 2);
c += 1;
}
else {
msg.should.have.property('payload', { w: 5, x: 6, y: 7, z: 8 });
check_parts(msg, 1, 2);
done();
}
});
var testStringA = "foo\n";
var testStringB = "bar\n";
var testString1 = "w,x,y,z\n";
var testString2 = "1,2,3,4\n";
var testString3 = "5,6,7,8\n";
n1.emit("input", {payload:testStringA, parts:{id:"X", index:0, count:5}});
n1.emit("input", {payload:testStringB, parts:{id:"X", index:1, count:5}});
n1.emit("input", {payload:testString1, parts:{id:"X", index:2, count:5}});
n1.emit("input", {payload:testString2, parts:{id:"X", index:3, count:5}});
n1.emit("input", {payload:testString3, parts:{id:"X", index:4, count:5}});
});
});
});
describe('json object to csv', function() {
it('should convert a simple object back to a csv', function(done) {
var flow = [ { id:"n1", type:"csv", temp:"a,b,c,,e", 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', '4,3,2,1\n');
msg.should.have.property('payload', '4,foo,true,,0\n');
done();
}
catch(e) { done(e); }
});
var testJson = { d: 1, b: 3, c: 2, a: 4 };
var testJson = { e:0, d:1, b:"foo", c:true, a:4 };
n1.emit("input", {payload:testJson});
});
});
it('should convert a simple object back to a csv with no template', function(done) {
var flow = [ { id:"n1", type:"csv", temp:" ", 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,foo,"ba""r","di,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"} ];
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', '4,foo,true,,0\n');
done();
}
catch(e) { done(e); }
});
var testJson = { e:0, d:1, "b o":"foo", "c p":true, a:4 };
n1.emit("input", {payload:testJson});
});
});
@@ -241,12 +437,12 @@ describe('CSV node', function() {
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
try {
msg.should.have.property('payload', '0,1,2,3,4\n');
msg.should.have.property('payload', ',0,1,foo,"ba""r","di,ng"\n');
done();
}
catch(e) { done(e); }
});
var testJson = [0,1,2,3,4];
var testJson = ["",0,1,"foo",'ba"r','di,ng'];
n1.emit("input", {payload:testJson});
});
});

View File

@@ -207,12 +207,29 @@ describe('html node', function() {
describe('multiple messages', function(){
var cnt = 0;
var parts_id = undefined;
afterEach(function() {
cnt.should.be.exactly(2);
cnt = 0;
parts_id = undefined;
});
function check_parts(msg, index, count) {
msg.should.have.property('parts');
msg.parts.should.have.property('id');
if(parts_id === undefined) {
parts_id = msg.parts.id;
}
else {
msg.parts.should.have.property('id', parts_id);
}
msg.parts.should.have.property('index', index);
msg.parts.should.have.property('count', count);
msg.parts.should.have.property('type', 'string');
msg.parts.should.have.property('ch', '');
}
it('should retrieve list contents as html as default with output as multiple msgs ', function(done) {
fs.readFile(file, 'utf8', function(err, data) {
var flow = [{id:"n1",type:"html",wires:[["n2"]],tag:"ul",as:"multi"},
@@ -224,6 +241,7 @@ describe('html node', function() {
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;
}
@@ -252,6 +270,7 @@ describe('html node', function() {
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;
}
@@ -281,6 +300,7 @@ describe('html node', function() {
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();
});

View File

@@ -28,17 +28,8 @@ describe('JSON node', function() {
helper.unload();
});
it('should be loaded', function(done) {
var flow = [{id:"jsonNode1", type:"json", name: "jsonNode" }];
helper.load(jsonNode, flow, function() {
var jsonNode1 = helper.getNode("jsonNode1");
jsonNode1.should.have.property('name', 'jsonNode');
done();
});
});
it('should convert a valid json string to a javascript object', function(done) {
var flow = [{id:"jn1",type:"json",wires:[["jn2"]],func:"return msg;"},
var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
{id:"jn2", type:"helper"}];
helper.load(jsonNode, flow, function() {
var jn1 = helper.getNode("jn1");
@@ -56,7 +47,7 @@ describe('JSON node', function() {
});
it('should convert a javascript object to a json string', function(done) {
var flow = [{id:"jn1",type:"json",wires:[["jn2"]],func:"return msg;"},
var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
{id:"jn2", type:"helper"}];
helper.load(jsonNode, flow, function() {
var jn1 = helper.getNode("jn1");
@@ -71,7 +62,7 @@ describe('JSON node', function() {
});
it('should convert a array to a json string', function(done) {
var flow = [{id:"jn1",type:"json",wires:[["jn2"]],func:"return msg;"},
var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
{id:"jn2", type:"helper"}];
helper.load(jsonNode, flow, function() {
var jn1 = helper.getNode("jn1");
@@ -86,7 +77,7 @@ describe('JSON node', function() {
});
it('should log an error if asked to parse an invalid json string', function(done) {
var flow = [{id:"jn1",type:"json",wires:[["jn2"]],func:"return msg;"},
var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
{id:"jn2", type:"helper"}];
helper.load(jsonNode, flow, function() {
try {
@@ -108,7 +99,7 @@ describe('JSON node', function() {
});
it('should log an error if asked to parse something thats not json or js', function(done) {
var flow = [{id:"jn1",type:"json",wires:[["jn2"]],func:"return msg;"},
var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
{id:"jn2", type:"helper"}];
helper.load(jsonNode, flow, function() {
var jn1 = helper.getNode("jn1");
@@ -137,7 +128,7 @@ describe('JSON node', function() {
});
it('should pass straight through if no payload set', function(done) {
var flow = [{id:"jn1",type:"json",wires:[["jn2"]],func:"return msg;"},
var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
{id:"jn2", type:"helper"}];
helper.load(jsonNode, flow, function() {
var jn1 = helper.getNode("jn1");
@@ -151,4 +142,105 @@ describe('JSON node', function() {
});
});
it('should ensure the result is a json string', function(done) {
var flow = [{id:"jn1",type:"json",action:"str",wires:[["jn2"]]},
{id:"jn2", type:"helper"}];
helper.load(jsonNode, flow, function() {
var jn1 = helper.getNode("jn1");
var jn2 = helper.getNode("jn2");
var count = 0;
jn2.on("input", function(msg) {
try {
should.equal(msg.payload, '{"employees":[{"firstName":"John","lastName":"Smith"}]}');
count++;
if (count === 2) {
done();
}
} catch(err) {
done(err);
}
});
var obj = {employees:[{firstName:"John", lastName:"Smith"}]};
jn1.receive({payload:obj,topic: "bar"});
jn1.receive({payload:JSON.stringify(obj),topic: "bar"});
});
});
it('should ensure the result is a JS Object', function(done) {
var flow = [{id:"jn1",type:"json",action:"obj",wires:[["jn2"]]},
{id:"jn2", type:"helper"}];
helper.load(jsonNode, flow, function() {
var jn1 = helper.getNode("jn1");
var jn2 = helper.getNode("jn2");
var count = 0;
jn2.on("input", function(msg) {
try {
msg.should.have.property('topic', 'bar');
msg.payload.should.have.property('employees');
msg.payload.employees[0].should.have.property('firstName', 'John');
msg.payload.employees[0].should.have.property('lastName', 'Smith');
count++;
if (count === 2) {
done();
}
} catch(err) {
done(err);
}
});
var obj = {employees:[{firstName:"John", lastName:"Smith"}]};
jn1.receive({payload:obj,topic: "bar"});
jn1.receive({payload:JSON.stringify(obj),topic: "bar"});
});
});
it('should handle any msg property - receive existing string', function(done) {
var flow = [{id:"jn1",type:"json",property:"one.two",wires:[["jn2"]]},
{id:"jn2", type:"helper"}];
helper.load(jsonNode, flow, function() {
var jn1 = helper.getNode("jn1");
var jn2 = helper.getNode("jn2");
jn2.on("input", function(msg) {
try {
msg.should.have.property('topic', 'bar');
msg.should.have.property('one');
msg.one.should.have.property('two');
msg.one.two.should.have.property('employees');
msg.one.two.employees[0].should.have.property('firstName', 'John');
msg.one.two.employees[0].should.have.property('lastName', 'Smith');
done();
} catch(err) {
done(err);
}
});
var jsonString = '{"employees":[{"firstName":"John", "lastName":"Smith"}]}';
jn1.receive({payload:"",one:{two:jsonString},topic: "bar"});
var logEvents = helper.log().args.filter(function(evt) {
return evt[0].type == "json";
});
});
});
it('should handle any msg property - receive existing obj', function(done) {
var flow = [{id:"jn1",type:"json",property:"one.two",wires:[["jn2"]]},
{id:"jn2", type:"helper"}];
helper.load(jsonNode, flow, function() {
var jn1 = helper.getNode("jn1");
var jn2 = helper.getNode("jn2");
jn2.on("input", function(msg) {
try {
should.equal(msg.one.two, '{"employees":[{"firstName":"John","lastName":"Smith"}]}');
done();
} catch(err) {
done(err);
}
});
var jsonString = '{"employees":[{"firstName":"John", "lastName":"Smith"}]}';
jn1.receive({payload:"",one:{two:JSON.parse(jsonString)},topic: "bar"});
var logEvents = helper.log().args.filter(function(evt) {
return evt[0].type == "json";
});
});
});
});

View File

@@ -36,6 +36,7 @@ describe('file Nodes', function() {
});
afterEach(function(done) {
fs.removeSync(path.join(resourcesDir,"file-out-node"));
helper.unload().then(function() {
//fs.unlinkSync(fileToTest);
helper.stopServer(done);
@@ -154,32 +155,43 @@ describe('file Nodes', function() {
var f = fs.readFileSync(fileToTest).toString();
f.should.equal("onetwo");
// Delete the file
fs.unlinkSync(fileToTest);
// Recreate it
fs.writeFileSync(fileToTest,"");
// Send two more messages to the file
n1.emit("input", {payload:"three"});
n1.emit("input", {payload:"four"});
setTimeout(function() {
// Check the file was updated
try {
var f = fs.readFileSync(fileToTest).toString();
f.should.equal("threefour");
fs.unlinkSync(fileToTest);
done();
} catch(err) {
done(err);
}
},wait);
if (os.type() === "Windows_NT") {
var dummyFile = path.join(resourcesDir,"50-file-test-dummy.txt");
fs.rename(fileToTest, dummyFile, function() {
recreateTest(n1, dummyFile);
});
} else {
recreateTest(n1, fileToTest);
}
} catch(err) {
done(err);
}
},wait);
});
function recreateTest(n1, fileToDelete) {
// Delete the file
fs.unlinkSync(fileToDelete);
// Recreate it
fs.writeFileSync(fileToTest,"");
// Send two more messages to the file
n1.emit("input", {payload:"three"});
n1.emit("input", {payload:"four"});
setTimeout(function() {
// Check the file was updated
try {
var f = fs.readFileSync(fileToTest).toString();
f.should.equal("threefour");
fs.unlinkSync(fileToTest);
done();
} catch(err) {
done(err);
}
},wait);
}
});
@@ -357,7 +369,7 @@ describe('file Nodes', function() {
it('should fail to create a new directory if not asked to do so (append)', function(done) {
// Stub file write so we can make writes fail
var fileToTest2 = path.join(resourcesDir,"a","50-file-test-file.txt");
var fileToTest2 = path.join(resourcesDir,"file-out-node","50-file-test-file.txt");
//var spy = sinon.stub(fs, 'appendFile', function(arg,arg2,arg3,arg4){ arg4(new Error("Stub error message")); });
var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest2, "appendNewline":true, "overwriteFile":false}];
@@ -383,7 +395,7 @@ describe('file Nodes', function() {
it('should try to create a new directory if asked to do so (append)', function(done) {
// Stub file write so we can make writes fail
var fileToTest2 = path.join(resourcesDir,"a","50-file-test-file.txt");
var fileToTest2 = path.join(resourcesDir,"file-out-node","50-file-test-file.txt");
var spy = sinon.stub(fs, "ensureDir", function(arg1,arg2,arg3,arg4) { arg2(null); });
var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest2, "appendNewline":true, "overwriteFile":false, "createDir":true}];
helper.load(fileNode, flow, function() {
@@ -394,9 +406,7 @@ describe('file Nodes', function() {
return evt[0].type == "file";
});
//console.log(logEvents);
logEvents.should.have.length(1);
logEvents[0][0].should.have.a.property('msg');
logEvents[0][0].msg.toString().should.startWith("file.errors.appendfail");
logEvents.should.have.length(0);
done();
}
catch(e) { done(e); }
@@ -408,7 +418,7 @@ describe('file Nodes', function() {
it('should fail to create a new directory if not asked to do so (overwrite)', function(done) {
// Stub file write so we can make writes fail
var fileToTest2 = path.join(resourcesDir,"a","50-file-test-file.txt");
var fileToTest2 = path.join(resourcesDir,"file-out-node","50-file-test-file.txt");
//var spy = sinon.stub(fs, 'appendFile', function(arg,arg2,arg3,arg4){ arg4(new Error("Stub error message")); });
var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest2, "appendNewline":false, "overwriteFile":true}];
@@ -434,7 +444,7 @@ describe('file Nodes', function() {
it('should try to create a new directory if asked to do so (overwrite)', function(done) {
// Stub file write so we can make writes fail
var fileToTest2 = path.join(resourcesDir,"a","50-file-test-file.txt");
var fileToTest2 = path.join(resourcesDir,"file-out-node","50-file-test-file.txt");
var spy = sinon.stub(fs, "ensureDir", function(arg1,arg2,arg3,arg4) { arg2(null); });
var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest2, "appendNewline":true, "overwriteFile":true, "createDir":true}];
@@ -446,9 +456,7 @@ describe('file Nodes', function() {
return evt[0].type == "file";
});
//console.log(logEvents);
logEvents.should.have.length(1);
logEvents[0][0].should.have.a.property('msg');
logEvents[0][0].msg.toString().should.startWith("file.errors.writefail");
logEvents.should.have.length(0);
done();
}
catch(e) { done(e); }