diff --git a/test/nodes/core/core/20-inject_spec.js b/test/nodes/core/core/20-inject_spec.js new file mode 100644 index 000000000..b5902a7a4 --- /dev/null +++ b/test/nodes/core/core/20-inject_spec.js @@ -0,0 +1,107 @@ +/** + * Copyright 2014 IBM Corp. + * + * 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 injectNode = require("../../../../nodes/core/core/20-inject.js"); +var helper = require("../../helper.js"); + +describe('inject node', function() { + + before(function(done) { + helper.startServer(done); + }); + + it('should inject once', function(done) { + + helper.load(injectNode, [{id:"n1", type:"inject", + payload:"payload", topic: "t1", + 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(); + }); + }); + }); + + it('should inject repeatedly', function(done) { + + helper.load(injectNode, [{id:"n1", type:"inject", + payload:"payload", topic: "t2", + repeat: 0.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', 't2'); + msg.should.have.property('payload', 'payload'); + 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", + crontab: "* * * * * *", wires:[["n3"]] }, + {id:"n3", type:"helper"}], + function() { + var n3 = helper.getNode("n3"); + n3.on("input", function(msg) { + msg.should.have.property('topic', 't3'); + msg.should.have.property('payload').be.a.Number; + helper.clearFlows().then(function() { + done(); + }); + }); + }); + }); + + describe('post', function() { + it('should inject message', function(done) { + helper.load(injectNode, + [{id:"n1", type:"inject", + payloadType:"some type", topic: "t4", + wires:[["n4"]] }, + { id:"n4", type:"helper"}], function() { + var n4 = helper.getNode("n4"); + n4.on("input", function(msg) { + msg.should.have.property('topic', 't4'); + msg.should.have.property('payload', ''); + helper.clearFlows().then(function() { + done(); + }); + }); + helper.request() + .post('/inject/n1') + .expect(200).end(function() {}); + }); + }); + + it('should fail for invalid node', function(done) { + helper.request().post('/inject/invalid').expect(404).end(done); + }); + }); +}); diff --git a/test/nodes/core/core/58-debug_spec.js b/test/nodes/core/core/58-debug_spec.js new file mode 100644 index 000000000..1e0c4d0ae --- /dev/null +++ b/test/nodes/core/core/58-debug_spec.js @@ -0,0 +1,288 @@ +/** + * Copyright 2014 IBM Corp. + * + * 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 debugNode = require("../../../../nodes/core/core/58-debug.js"); +var helper = require("../../helper.js"); +var WebSocket = require('ws'); + +describe('debug node', function() { + + before(function(done) { + helper.startServer(done); + }); + + it('should be loaded', function(done) { + var flow = [{id:"n1", type:"debug", name: "Debug" }]; + helper.load(debugNode, flow, function() { + var n1 = helper.getNode("n1"); + n1.should.have.property('name', 'Debug'); + done(); + }); + }); + + it('should publish on input', function(done) { + 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({ + topic:"debug",data:{id:"n1",name:"Debug",msg:"test"} + }); + }, done); + }); + }); + + it('should publish to console', function(done) { + var flow = [{id:"n1", type:"debug", console: "true" }]; + helper.load(debugNode, flow, function() { + var n1 = helper.getNode("n1"); + var count = 0; + n1.on('log', function(msg) { + msg.should.eql({level:'log',id:'n1',type:'debug',msg:'test'}); + count++; + if (count == 2) { + done(); + } + }); + websocket_test(function() { + n1.emit("input", {payload:"test"}); + }, function(msg) { + JSON.parse(msg).should.eql({ + topic:"debug",data:{id:"n1",msg:"test"} + }); + count++; + }, function() { + if (count == 2) { + done(); + } + }); + }); + }); + + it('should publish complete message', function(done) { + 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({ + topic:"debug", + data:{id:"n1",msg:'(Object) {\n "payload": "test"\n}'} + }); + }, done); + }); + }); + + it('should publish an Error', 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: new Error("oops")}); + }, function(msg) { + JSON.parse(msg).should.eql({ + topic:"debug",data:{id:"n1",msg:"Error: oops"} + }); + }, done); + }); + }); + + it('should publish a boolean', 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: true}); + }, function(msg) { + JSON.parse(msg).should.eql({ + topic:"debug",data:{id:"n1",msg: '(boolean) true'} + }); + }, done); + }); + }); + + it('should publish with no payload', function(done) { + var flow = [{id:"n1", type:"debug" }]; + helper.load(debugNode, flow, function() { + var n1 = helper.getNode("n1"); + websocket_test(function() { + n1.emit("input", {}); + }, function(msg) { + JSON.parse(msg).should.eql({ + topic:"debug",data:{id:"n1",msg: '(undefined)'} + }); + }, done); + }); + }); + + it('should publish an 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: {type:'foo'}}); + }, function(msg) { + JSON.parse(msg).should.eql({ + topic:"debug", + data:{id:"n1",msg:'(Object) {\n "type": "foo"\n}'} + }); + }, done); + }); + }); + + it('should publish an 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: [0,1,2,3]}); + }, function(msg) { + JSON.parse(msg).should.eql({ + topic:"debug", + data:{id:"n1",msg: '(Array) [\n 0,\n 1,\n 2,\n 3\n]'} + }); + }, done); + }); + }); + + it('should publish an object with circular references', function(done) { + var flow = [{id:"n1", type:"debug" }]; + helper.load(debugNode, flow, function() { + var n1 = helper.getNode("n1"); + websocket_test(function() { + var o = { name: 'bar' }; + o.o = o; + n1.emit("input", {payload: o}); + }, function(msg) { + JSON.parse(msg).should.eql({ + topic:"debug", + data:{ + id:"n1", + msg:'(Object) {\n "name": "bar",\n "o": "[circular]"\n}' + } + }); + }, done); + }); + }); + + it('should truncated 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")}); + }, function(msg) { + JSON.parse(msg).should.eql({ + topic:"debug", + data:{ + id:"n1", + msg: Array(1001).join("X")+' ....' + } + }); + }, done); + }); + }); + + it('should convert Buffer to hex', 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: new Buffer('HELLO', 'utf8')}); + }, function(msg) { + JSON.parse(msg).should.eql({ + topic:"debug", + data:{ + id:"n1", + msg: '(Buffer) 48454c4c4f', + } + }); + }, done); + }); + }); + + it('should publish when active', function(done) { + var flow = [{id:"n1", type:"debug", active: false }]; + helper.load(debugNode, flow, function() { + var n1 = helper.getNode("n1"); + websocket_test(function() { + n1.emit("input", {payload:"message 1"}); + helper.request() + .post('/debug/n1/enable') + .expect(200).end(function() { + n1.emit("input", {payload:"message 2"}); + }); + }, function(msg) { + JSON.parse(msg).should.eql({ + topic:"debug",data:{id:"n1",msg:"message 2"} + }); + }, done); + }); + }); + + it('should not publish when inactive', function(done) { + var flow = [{id:"n1", type:"debug", active: true }]; + helper.load(debugNode, flow, function() { + var n1 = helper.getNode("n1"); + websocket_test(function(close) { + helper.request() + .post('/debug/n1/disable') + .expect(200).end(function() { + n1.emit("input", {payload:"message"}); + setTimeout(function() { + close(); + done(); + }, 200); + }); + }, function(msg) { + should.fail(null,null,"unexpected message"); + }, function() {}); + }); + }); + + describe('post', function() { + it('should return 404 on invalid state', function(done) { + var flow = [{id:"n1", type:"debug", active: true }]; + helper.load(debugNode, flow, function() { + helper.request() + .post('/debug/n1/foobar') + .expect(404).end(done); + }); + }); + + it('should return 404 on invalid node', function(done) { + helper.request() + .post('/debug/n99/enable') + .expect(404).end(done); + }); + }); + +}); + +function websocket_test(open_callback, message_callback, done_callback) { + var ws = new WebSocket(helper.url() + "/comms"); + 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(); + }); +} diff --git a/test/nodes/core/core/80-function_spec.js b/test/nodes/core/core/80-function_spec.js new file mode 100644 index 000000000..b034bcc13 --- /dev/null +++ b/test/nodes/core/core/80-function_spec.js @@ -0,0 +1,67 @@ +/** + * Copyright 2014 IBM Corp. + * + * 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 functionNode = require("../../../../nodes/core/core/80-function.js"); +var helper = require("../../helper.js"); + +describe('function node', function() { + + before(function(done) { + helper.startServer(done); + }); + + it('should be loaded', function(done) { + var flow = [{id:"n1", type:"function", name: "function" }]; + helper.load(functionNode, flow, function() { + var n1 = helper.getNode("n1"); + n1.should.have.property('name', 'function'); + done(); + }); + }); + + it('should send returned message', function(done) { + var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"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'); + done(); + }); + n1.receive({payload:"foo",topic: "bar"}); + }); + }); + + it('should allow input to be discarded by returning null', function(done) { + var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"return null"}, + {id:"n2", type:"helper"}]; + helper.load(functionNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + setTimeout(function() { + done(); + }, 200); + n2.on("input", function(msg) { + should.fail(null,null,"unexpected message"); + }); + n1.receive({payload:"foo",topic: "bar"}); + }); + }); + +}); diff --git a/test/nodes/core/core/80-template_spec.js b/test/nodes/core/core/80-template_spec.js new file mode 100644 index 000000000..3ba1e8c07 --- /dev/null +++ b/test/nodes/core/core/80-template_spec.js @@ -0,0 +1,41 @@ +/** + * Copyright 2014 IBM Corp. + * + * 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 templateNode = require("../../../../nodes/core/core/80-template.js"); +var helper = require("../../helper.js"); + +describe('template node', function() { + + before(function(done) { + helper.startServer(done); + }); + + it('should modify payload', function(done) { + var flow = [{id:"n1", type:"template", field: "payload", template: "payload={{payload}}",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', 'payload=foo'); + done(); + }); + n1.receive({payload:"foo",topic: "bar"}); + }); + }); + +}); diff --git a/test/nodes/core/core/90-comment_spec.js b/test/nodes/core/core/90-comment_spec.js new file mode 100644 index 000000000..5eaf2e437 --- /dev/null +++ b/test/nodes/core/core/90-comment_spec.js @@ -0,0 +1,32 @@ +/** + * Copyright 2014 IBM Corp. + * + * 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 commentNode = require("../../../../nodes/core/core/90-comment.js"); +var helper = require("../../helper.js"); + +describe('comment node', function() { + + it('should be loaded', function(done) { + var flow = [{id:"n1", type:"comment", name: "comment" }]; + helper.load(commentNode, flow, function() { + var n1 = helper.getNode("n1"); + n1.should.have.property('name', 'comment'); + done(); + }); + }); + +}); diff --git a/test/nodes/helper.js b/test/nodes/helper.js new file mode 100644 index 000000000..d38e27d82 --- /dev/null +++ b/test/nodes/helper.js @@ -0,0 +1,87 @@ +/** + * Copyright 2014 IBM Corp. + * + * 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 when = require("when"); +var request = require('supertest'); +var RED = require("../../red/red.js"); +var redNodes = require("../../red/nodes"); +var flows = require("../../red/nodes/flows"); +var comms = require("../../red/comms.js"); + +var http = require('http'); +var express = require('express'); +var app = express(); + +var address = '127.0.0.1'; +var listenPort = 0; // use ephemeral port +var port; +var url; + +function helperNode(n) { + RED.nodes.createNode(this, n); +} + +module.exports = { + load: function(testNode, testFlows, cb) { + var storage = { + getFlows: function() { + var defer = when.defer(); + defer.resolve(testFlows); + return defer.promise; + }, + getCredentials: function() { + var defer = when.defer(); + defer.resolve({}); + return defer.promise; + }, + }; + redNodes.init({}, storage); + RED.nodes.registerType("helper", helperNode); + testNode(RED); + flows.load().then(function() { + should.deepEqual(testFlows, flows.getFlows()); + cb(); + }); + }, + + getNode: function(id) { + return flows.get(id); + }, + + clearFlows: function() { + return flows.clear(); + }, + + request: function() { + return request(RED.httpAdmin); + }, + + startServer: function(done) { + var server = http.createServer(function(req,res){app(req,res);}); + RED.init(server, {}); + server.listen(listenPort, address); + server.on('listening', function() { + port = server.address().port; + url = 'http://' + address + ':' + port; + comms.start(); + done(); + }); + }, + + url: function() { return url; }, + +};