Fixup all the tests

This commit is contained in:
Nick O'Leary
2018-04-24 15:01:49 +01:00
parent 34832d5942
commit 5d064aa1d7
50 changed files with 3480 additions and 1762 deletions

View File

@@ -38,18 +38,23 @@ describe("api/admin/flow", function() {
describe("get", function() {
before(function() {
var opts;
flow.init({
settings:{},
nodes: {
getFlow: function(id) {
if (id === '123') {
return {id:'123'}
flows: {
getFlow: function(_opts) {
opts = _opts;
if (opts.id === '123') {
return Promise.resolve({id:'123'});
} else {
return null;
var err = new Error("message");
err.code = "not_found";
err.status = 404;
var p = Promise.reject(err);
p.catch(()=>{});
return p;
}
}
},
log:{ audit: sinon.stub() }
}
});
})
it('gets a known flow', function(done) {
@@ -75,19 +80,24 @@ describe("api/admin/flow", function() {
});
describe("add", function() {
var opts;
before(function() {
flow.init({
settings:{},
nodes: {
addFlow: function(f) {
if (f.id === "123") {
return when.resolve('123')
flows: {
addFlow: function(_opts) {
opts = _opts;
if (opts.flow.id === "123") {
return Promise.resolve('123')
} else {
return when.reject(new Error("test error"));
var err = new Error("random error");
err.code = "random_error";
err.status = 400;
var p = Promise.reject(err);
p.catch(()=>{});
return p;
}
}
},
log:{ audit: sinon.stub() }
}
});
})
it('adds a new flow', function(done) {
@@ -114,8 +124,8 @@ describe("api/admin/flow", function() {
if (err) {
return done(err);
}
res.body.should.has.a.property('error','unexpected_error');
res.body.should.has.a.property('message','Error: test error');
res.body.should.has.a.property('code','random_error');
res.body.should.has.a.property('message','random error');
done();
});
@@ -123,35 +133,29 @@ describe("api/admin/flow", function() {
})
describe("update", function() {
var nodes;
var opts;
before(function() {
nodes = {
updateFlow: function(id,f) {
var err;
if (id === "123") {
return when.resolve()
} else if (id === "unknown") {
err = new Error();
err.code = 404;
throw err;
} else if (id === "unexpected") {
err = new Error();
err.code = 500;
throw err;
} else {
return when.reject(new Error("test error"));
flow.init({
flows: {
updateFlow: function(_opts) {
opts = _opts;
if (opts.id === "123") {
return Promise.resolve('123')
} else {
var err = new Error("random error");
err.code = "random_error";
err.status = 400;
var p = Promise.reject(err);
p.catch(()=>{});
return p;
}
}
}
};
flow.init({
settings:{},
nodes: nodes,
log:{ audit: sinon.stub() }
});
})
it('updates an existing flow', function(done) {
sinon.spy(nodes,"updateFlow");
request(app)
.put('/flow/123')
.set('Accept', 'application/json')
@@ -162,115 +166,79 @@ describe("api/admin/flow", function() {
return done(err);
}
res.body.should.has.a.property('id','123');
nodes.updateFlow.calledOnce.should.be.true();
nodes.updateFlow.lastCall.args[0].should.eql('123');
nodes.updateFlow.lastCall.args[1].should.eql({id:'123'});
nodes.updateFlow.restore();
opts.should.have.property('id','123');
opts.should.have.property('flow',{id:'123'})
done();
});
})
it('404s on an unknown flow', function(done) {
it('400 an invalid flow', function(done) {
request(app)
.put('/flow/unknown')
.put('/flow/456')
.set('Accept', 'application/json')
.send({id:'123'})
.expect(404)
.end(done);
})
it('400 on async update error', function(done) {
request(app)
.put('/flow/async_error')
.set('Accept', 'application/json')
.send({id:'123'})
.send({id:'456'})
.expect(400)
.end(function(err,res) {
if (err) {
return done(err);
}
res.body.should.has.a.property('error','unexpected_error');
res.body.should.has.a.property('message','Error: test error');
done();
});
})
res.body.should.has.a.property('code','random_error');
res.body.should.has.a.property('message','random error');
it('400 on sync update error', function(done) {
request(app)
.put('/flow/unexpected')
.set('Accept', 'application/json')
.send({id:'123'})
.expect(400)
.end(function(err,res) {
if (err) {
return done(err);
}
res.body.should.has.a.property('error',500);
res.body.should.has.a.property('message','Error');
done();
});
})
})
describe("delete", function() {
var nodes;
var opts;
before(function() {
nodes = {
removeFlow: function(id) {
var err;
if (id === "123") {
return when.resolve()
} else if (id === "unknown") {
err = new Error();
err.code = 404;
throw err;
} else if (id === "unexpected") {
err = new Error();
err.code = 500;
throw err;
flow.init({
flows: {
deleteFlow: function(_opts) {
opts = _opts;
if (opts.id === "123") {
return Promise.resolve()
} else {
var err = new Error("random error");
err.code = "random_error";
err.status = 400;
var p = Promise.reject(err);
p.catch(()=>{});
return p;
}
}
}
};
flow.init({
settings:{},
nodes: nodes,
log:{ audit: sinon.stub() }
});
})
it('updates an existing flow', function(done) {
sinon.spy(nodes,"removeFlow");
it('deletes an existing flow', function(done) {
request(app)
.delete('/flow/123')
.del('/flow/123')
.set('Accept', 'application/json')
.expect(204)
.end(function(err,res) {
if (err) {
return done(err);
}
nodes.removeFlow.calledOnce.should.be.true();
nodes.removeFlow.lastCall.args[0].should.eql('123');
nodes.removeFlow.restore();
opts.should.have.property('id','123');
done();
});
})
it('404s on an unknown flow', function(done) {
it('400 an invalid flow', function(done) {
request(app)
.delete('/flow/unknown')
.expect(404)
.end(done);
})
it('400 on remove error', function(done) {
request(app)
.delete('/flow/unexpected')
.del('/flow/456')
.set('Accept', 'application/json')
.expect(400)
.end(function(err,res) {
if (err) {
return done(err);
}
res.body.should.has.a.property('error',500);
res.body.should.has.a.property('message','Error');
res.body.should.has.a.property('code','random_error');
res.body.should.has.a.property('message','random error');
done();
});
})

View File

@@ -19,7 +19,6 @@ var request = require('supertest');
var express = require('express');
var bodyParser = require('body-parser');
var sinon = require('sinon');
var when = require('when');
var flows = require("../../../../red/api/admin/flows");
@@ -36,10 +35,8 @@ describe("api/admin/flows", function() {
it('returns flow - v1', function(done) {
flows.init({
settings: {},
log:{warn:function(){},_:function(){},audit:function(){}},
nodes:{
getFlows: function() { return {rev:"123",flows:[1,2,3]}; }
flows:{
getFlows: function() { return Promise.resolve({rev:"123",flows:[1,2,3]}); }
}
});
request(app)
@@ -60,10 +57,8 @@ describe("api/admin/flows", function() {
});
it('returns flow - v2', function(done) {
flows.init({
settings: {},
log:{warn:function(){},_:function(){},audit:function(){}},
nodes:{
getFlows: function() { return {rev:"123",flows:[1,2,3]}; }
flows:{
getFlows: function() { return Promise.resolve({rev:"123",flows:[1,2,3]}); }
}
});
request(app)
@@ -104,10 +99,9 @@ describe("api/admin/flows", function() {
});
});
it('sets flows - default - v1', function(done) {
var setFlows = sinon.spy(function() { return when.resolve();});
var setFlows = sinon.spy(function() { return Promise.resolve();});
flows.init({
log:{warn:function(){},_:function(){},audit:function(){}},
nodes:{
flows:{
setFlows: setFlows
}
});
@@ -120,15 +114,14 @@ describe("api/admin/flows", function() {
return done(err);
}
setFlows.calledOnce.should.be.true();
setFlows.lastCall.args[1].should.eql('full');
setFlows.lastCall.args[0].should.have.property('deploymentType','full');
done();
});
});
it('sets flows - non-default - v1', function(done) {
var setFlows = sinon.spy(function() { return when.resolve();});
var setFlows = sinon.spy(function() { return Promise.resolve();});
flows.init({
log:{warn:function(){},_:function(){},audit:function(){}},
nodes:{
flows:{
setFlows: setFlows
}
});
@@ -142,19 +135,22 @@ describe("api/admin/flows", function() {
return done(err);
}
setFlows.calledOnce.should.be.true();
setFlows.lastCall.args[1].should.eql('nodes');
setFlows.lastCall.args[0].should.have.property('deploymentType','nodes');
done();
});
});
it('set flows - rejects mismatched revision - v2', function(done) {
var setFlows = sinon.spy(function() { return when.resolve();});
var getFlows = sinon.spy(function() { return {rev:123,flows:[1,2,3]}});
flows.init({
log:{warn:function(){},_:function(){},audit:function(){}},
nodes:{
setFlows: setFlows,
getFlows: getFlows
flows:{
setFlows: function() {
var err = new Error("mismatch");
err.code = "version_mismatch";
err.status = 409;
var p = Promise.reject(err);
p.catch(()=>{});
return p;
}
}
});
request(app)
@@ -171,54 +167,6 @@ describe("api/admin/flows", function() {
done();
});
});
it('set flows - rev provided - v2', function(done) {
var setFlows = sinon.spy(function() { return when.resolve(456);});
var getFlows = sinon.spy(function() { return {rev:123,flows:[1,2,3]}});
flows.init({
log:{warn:function(){},_:function(){},audit:function(){}},
nodes:{
setFlows: setFlows,
getFlows: getFlows
}
});
request(app)
.post('/flows')
.set('Accept', 'application/json')
.set('Node-RED-API-Version','v2')
.send({rev:123,flows:[4,5,6]})
.expect(200)
.end(function(err,res) {
if (err) {
return done(err);
}
res.body.should.have.property("rev",456);
done();
});
});
it('set flows - no rev provided - v2', function(done) {
var setFlows = sinon.spy(function() { return when.resolve(456);});
var getFlows = sinon.spy(function() { return {rev:123,flows:[1,2,3]}});
flows.init({
log:{warn:function(){},_:function(){},audit:function(){}},
nodes:{
setFlows: setFlows,
getFlows: getFlows
}
});
request(app)
.post('/flows')
.set('Accept', 'application/json')
.set('Node-RED-API-Version','v2')
.send({flows:[4,5,6]})
.expect(200)
.end(function(err,res) {
if (err) {
return done(err);
}
res.body.should.have.property("rev",456);
done();
});
});
it('sets flow - bad version', function(done) {
request(app)
.post('/flows')
@@ -238,11 +186,10 @@ describe("api/admin/flows", function() {
});
});
it('reloads flows', function(done) {
var loadFlows = sinon.spy(function() { return when.resolve(); });
var setFlows = sinon.spy(function() { return Promise.resolve();});
flows.init({
log:{warn:function(){},_:function(){},audit:function(){}},
nodes:{
loadFlows: loadFlows
flows:{
setFlows: setFlows
}
});
request(app)
@@ -254,29 +201,9 @@ describe("api/admin/flows", function() {
if (err) {
return done(err);
}
loadFlows.called.should.be.true();
setFlows.called.should.be.true();
setFlows.lastCall.args[0].should.not.have.property('flows');
done();
});
});
it('returns error when set fails', function(done) {
flows.init({
log:{warn:function(){},_:function(){},audit:function(){}},
nodes:{
setFlows: function() { return when.reject(new Error("expected error")); }
}
});
request(app)
.post('/flows')
.set('Accept', 'application/json')
.expect(500)
.end(function(err,res) {
if (err) {
return done(err);
}
res.body.should.have.property("message","expected error");
done();
});
});
});

View File

@@ -27,31 +27,17 @@ var apiUtil = require("../../../../red/api/util");
describe("api/admin/nodes", function() {
var app;
function initNodes(runtime) {
runtime.log = {
audit:function(e){},//console.log(e)},
_:function(){},
info: function(){},
warn: function(){}
}
runtime.events = {
emit: function(){}
}
nodes.init(runtime);
}
before(function() {
app = express();
app.use(bodyParser.json());
app.get("/nodes",nodes.getAll);
app.post("/nodes",nodes.post);
app.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,nodes.getModule);
app.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,nodes.getSet);
app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,nodes.putModule);
app.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,nodes.getSet);
app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,nodes.putSet);
app.get("/getIcons",nodes.getIcons);
app.delete("/nodes/:id",nodes.delete);
app.delete(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,nodes.delete);
sinon.stub(apiUtil,"determineLangFromHeaders", function() {
return "en-US";
});
@@ -62,10 +48,10 @@ describe("api/admin/nodes", function() {
describe('get nodes', function() {
it('returns node list', function(done) {
initNodes({
nodes.init({
nodes:{
getNodeList: function() {
return [1,2,3];
return Promise.resolve([1,2,3]);
}
}
});
@@ -84,10 +70,10 @@ describe("api/admin/nodes", function() {
});
it('returns node configs', function(done) {
initNodes({
nodes.init({
nodes:{
getNodeConfigs: function() {
return "<script></script>";
return Promise.resolve("<script></script>");
}
},
i18n: {
@@ -108,10 +94,10 @@ describe("api/admin/nodes", function() {
});
it('returns node module info', function(done) {
initNodes({
nodes.init({
nodes:{
getModuleInfo: function(id) {
return {"node-red":{name:"node-red"}}[id];
getModuleInfo: function(opts) {
return Promise.resolve({"node-red":{name:"node-red"}}[opts.module]);
}
}
});
@@ -128,10 +114,15 @@ describe("api/admin/nodes", function() {
});
it('returns 404 for unknown module', function(done) {
initNodes({
nodes.init({
nodes:{
getModuleInfo: function(id) {
return {"node-red":{name:"node-red"}}[id];
getModuleInfo: function(opts) {
var errInstance = new Error("Not Found");
errInstance.code = "not_found";
errInstance.status = 404;
var p = Promise.reject(errInstance);
p.catch(()=>{});
return p;
}
}
});
@@ -147,10 +138,10 @@ describe("api/admin/nodes", function() {
});
it('returns individual node info', function(done) {
initNodes({
nodes.init({
nodes:{
getNodeInfo: function(id) {
return {"node-red/123":{id:"node-red/123"}}[id];
getNodeInfo: function(opts) {
return Promise.resolve({"node-red/123":{id:"node-red/123"}}[opts.id]);
}
}
});
@@ -168,10 +159,10 @@ describe("api/admin/nodes", function() {
});
it('returns individual node configs', function(done) {
initNodes({
nodes.init({
nodes:{
getNodeConfig: function(id) {
return {"node-red/123":"<script></script>"}[id];
getNodeConfig: function(opts) {
return Promise.resolve({"node-red/123":"<script></script>"}[opts.id]);
}
},
i18n: {
@@ -190,12 +181,16 @@ describe("api/admin/nodes", function() {
done();
});
});
it('returns 404 for unknown node', function(done) {
initNodes({
nodes.init({
nodes:{
getNodeInfo: function(id) {
return {"node-red/123":{id:"node-red/123"}}[id];
getNodeInfo: function(opts) {
var errInstance = new Error("Not Found");
errInstance.code = "not_found";
errInstance.status = 404;
var p = Promise.reject(errInstance);
p.catch(()=>{});
return p;
}
}
});
@@ -213,142 +208,96 @@ describe("api/admin/nodes", function() {
});
describe('install', function() {
it('returns 400 if settings are unavailable', function(done) {
initNodes({
settings:{available:function(){return false}}
it('installs the module and returns module info', function(done) {
var opts;
nodes.init({
nodes:{
addModule: function(_opts) {
opts = _opts;
return Promise.resolve({
name:"foo",
nodes:[{id:"123"}]
});
}
}
});
request(app)
.post('/nodes')
.send({module: 'foo',version:"1.2.3"})
.expect(200)
.end(function(err,res) {
if (err) {
throw err;
}
res.body.should.have.property("name","foo");
res.body.should.have.property("nodes");
res.body.nodes[0].should.have.property("id","123");
opts.should.have.property("module","foo");
opts.should.have.property("version","1.2.3");
done();
});
});
it('returns error', function(done) {
nodes.init({
nodes:{
addModule: function(opts) {
var errInstance = new Error("Message");
errInstance.code = "random_error";
errInstance.status = 400;
var p = Promise.reject(errInstance);
p.catch(()=>{});
return p;
}
}
});
request(app)
.post('/nodes')
.send({module: 'foo',version:"1.2.3"})
.expect(400)
.end(function(err,res) {
if (err) {
throw err;
}
res.body.should.have.a.property('code','random_error');
done();
});
});
it('returns 400 if request is invalid', function(done) {
initNodes({
settings:{available:function(){return true}}
});
request(app)
.post('/nodes')
.send({})
.expect(400)
.end(function(err,res) {
if (err) {
throw err;
}
done();
});
});
describe('by module', function() {
it('installs the module and returns module info', function(done) {
initNodes({
settings:{available:function(){return true}},
nodes:{
getModuleInfo: function(id) { return null; },
installModule: function() {
return when.resolve({
name:"foo",
nodes:[{id:"123"}]
});
}
}
});
request(app)
.post('/nodes')
.send({module: 'foo'})
.expect(200)
.end(function(err,res) {
if (err) {
throw err;
}
res.body.should.have.property("name","foo");
res.body.should.have.property("nodes");
res.body.nodes[0].should.have.property("id","123");
done();
});
});
it('fails the install if already installed', function(done) {
initNodes({
settings:{available:function(){return true}},
nodes:{
getModuleInfo: function(id) { return {nodes:{id:"123"}}; },
installModule: function() {
return when.resolve({id:"123"});
}
}
});
request(app)
.post('/nodes')
.send({module: 'foo'})
.expect(400)
.end(function(err,res) {
if (err) {
throw err;
}
done();
});
});
it('fails the install if module error', function(done) {
initNodes({
settings:{available:function(){return true}},
nodes:{
getModuleInfo: function(id) { return null },
installModule: function() {
return when.reject(new Error("test error"));
}
}
});
request(app)
.post('/nodes')
.send({module: 'foo'})
.expect(400)
.end(function(err,res) {
if (err) {
throw err;
}
res.body.should.have.property("message","Error: test error");
done();
});
});
it('fails the install if module not found', function(done) {
initNodes({
settings:{available:function(){return true}},
nodes:{
getModuleInfo: function(id) { return null },
installModule: function() {
var err = new Error("test error");
err.code = 404;
return when.reject(err);
}
}
});
request(app)
.post('/nodes')
.send({module: 'foo'})
.expect(404)
.end(function(err,res) {
if (err) {
throw err;
}
done();
});
});
});
});
describe('delete', function() {
it('returns 400 if settings are unavailable', function(done) {
initNodes({
settings:{available:function(){return false}}
it('uninstalls the module', function(done) {
var opts;
nodes.init({
nodes:{
removeModule: function(_opts) {
opts = _opts;
return Promise.resolve();
}
}
});
request(app)
.del('/nodes/123')
.expect(204)
.end(function(err,res) {
if (err) {
throw err;
}
opts.should.have.property("module","123");
done();
});
});
it('returns error', function(done) {
nodes.init({
nodes:{
removeModule: function(opts) {
var errInstance = new Error("Message");
errInstance.code = "random_error";
errInstance.status = 400;
var p = Promise.reject(errInstance);
p.catch(()=>{});
return p;
}
}
});
request(app)
.del('/nodes/123')
.expect(400)
@@ -356,93 +305,18 @@ describe("api/admin/nodes", function() {
if (err) {
throw err;
}
res.body.should.have.a.property('code','random_error');
done();
});
});
describe('by module', function() {
it('uninstalls the module', function(done) {
initNodes({
settings:{available:function(){return true}},
nodes:{
getModuleInfo: function(id) { return {nodes:[{id:"123"}]} },
getNodeInfo: function() { return null },
uninstallModule: function() { return when.resolve({id:"123"});}
}
});
request(app)
.del('/nodes/foo')
.expect(204)
.end(function(err,res) {
if (err) {
throw err;
}
done();
});
});
it('fails the uninstall if the module is not installed', function(done) {
initNodes({
settings:{available:function(){return true}},
nodes:{
getModuleInfo: function(id) { return null },
getNodeInfo: function() { return null }
}
});
request(app)
.del('/nodes/foo')
.expect(404)
.end(function(err,res) {
if (err) {
throw err;
}
done();
});
});
it('fails the uninstall if the module is not installed', function(done) {
initNodes({
settings:{available:function(){return true}},
nodes:{
getModuleInfo: function(id) { return {nodes:[{id:"123"}]} },
getNodeInfo: function() { return null },
uninstallModule: function() { return when.reject(new Error("test error"));}
}
});
request(app)
.del('/nodes/foo')
.expect(400)
.end(function(err,res) {
if (err) {
throw err;
}
res.body.should.have.property("message","Error: test error");
done();
});
});
});
});
describe('enable/disable', function() {
it('returns 400 if settings are unavailable', function(done) {
initNodes({
settings:{available:function(){return false}}
});
request(app)
.put('/nodes/123')
.expect(400)
.end(function(err,res) {
if (err) {
throw err;
}
done();
});
});
it('returns 400 for invalid node payload', function(done) {
initNodes({
settings:{available:function(){return true}}
describe('enable/disable node set', function() {
it('returns 400 for invalid request payload', function(done) {
nodes.init({
nodes:{
setNodeSetState: function(opts) {return Promise.resolve()}
}
});
request(app)
.put('/nodes/node-red/foo')
@@ -452,77 +326,23 @@ describe("api/admin/nodes", function() {
if (err) {
throw err;
}
res.body.should.have.property("code","invalid_request");
res.body.should.have.property("message","Invalid request");
done();
});
});
it('returns 400 for invalid module payload', function(done) {
initNodes({
settings:{available:function(){return true}}
});
request(app)
.put('/nodes/foo')
.send({})
.expect(400)
.end(function(err,res) {
if (err) {
throw err;
}
res.body.should.have.property("message","Invalid request");
done();
});
});
it('returns 404 for unknown node', function(done) {
initNodes({
settings:{available:function(){return true}},
it('sets node state and returns node info', function(done) {
var opts;
nodes.init({
nodes:{
getNodeInfo: function() { return null }
setNodeSetState: function(_opts) {
opts = _opts;
return Promise.resolve({id:"123",enabled: true });
}
}
});
request(app)
.put('/nodes/node-red/foo')
.send({enabled:false})
.expect(404)
.end(function(err,res) {
if (err) {
throw err;
}
done();
});
});
it('returns 404 for unknown module', function(done) {
initNodes({
settings:{available:function(){return true}},
nodes:{
getModuleInfo: function(id) { return null }
}
});
request(app)
.put('/nodes/node-blue')
.send({enabled:false})
.expect(404)
.end(function(err,res) {
if (err) {
throw err;
}
done();
});
});
it('enables disabled node', function(done) {
initNodes({
settings:{available:function(){return true}},
nodes:{
getNodeInfo: function() { return {id:"123",enabled: false} },
enableNode: function() { return when.resolve({id:"123",enabled: true,types:['a']}); }
}
});
request(app)
.put('/nodes/node-red/foo')
.send({enabled:true})
@@ -533,130 +353,41 @@ describe("api/admin/nodes", function() {
}
res.body.should.have.property("id","123");
res.body.should.have.property("enabled",true);
opts.should.have.property("enabled",true);
opts.should.have.property("id","node-red/foo");
done();
});
});
it('disables enabled node', function(done) {
initNodes({
settings:{available:function(){return true}},
});
describe('enable/disable module' ,function() {
it('returns 400 for invalid request payload', function(done) {
nodes.init({
nodes:{
getNodeInfo: function() { return {id:"123",enabled: true} },
disableNode: function() { return when.resolve({id:"123",enabled: false,types:['a']}); }
setModuleState: function(opts) {return Promise.resolve()}
}
});
request(app)
.put('/nodes/node-red/foo')
.send({enabled:false})
.expect(200)
.put('/nodes/node-red')
.send({})
.expect(400)
.end(function(err,res) {
if (err) {
throw err;
}
res.body.should.have.property("id","123");
res.body.should.have.property("enabled",false);
res.body.should.have.property("code","invalid_request");
res.body.should.have.property("message","Invalid request");
done();
});
});
describe('no-ops if already in the right state', function() {
function run(state,done) {
var enableNode = sinon.spy(function() { return when.resolve({id:"123",enabled: true,types:['a']}) });
var disableNode = sinon.spy(function() { return when.resolve({id:"123",enabled: false,types:['a']}) });
initNodes({
settings:{available:function(){return true}},
nodes:{
getNodeInfo: function() { return {id:"123",enabled: state} },
enableNode: enableNode,
disableNode: disableNode
}
});
request(app)
.put('/nodes/node-red/foo')
.send({enabled:state})
.expect(200)
.end(function(err,res) {
var enableNodeCalled = enableNode.called;
var disableNodeCalled = disableNode.called;
if (err) {
throw err;
}
enableNodeCalled.should.be.false();
disableNodeCalled.should.be.false();
res.body.should.have.property("id","123");
res.body.should.have.property("enabled",state);
done();
});
}
it('already enabled', function(done) {
run(true,done);
});
it('already disabled', function(done) {
run(false,done);
});
});
describe('does not no-op if err on node', function() {
function run(state,done) {
var enableNode = sinon.spy(function() { return when.resolve({id:"123",enabled: true,types:['a']}) });
var disableNode = sinon.spy(function() { return when.resolve({id:"123",enabled: false,types:['a']}) });
initNodes({
settings:{available:function(){return true}},
nodes:{
getNodeInfo: function() { return {id:"123",enabled: state, err:"foo"} },
enableNode: enableNode,
disableNode: disableNode
}
});
request(app)
.put('/nodes/node-red/foo')
.send({enabled:state})
.expect(200)
.end(function(err,res) {
var enableNodeCalled = enableNode.called;
var disableNodeCalled = disableNode.called;
if (err) {
throw err;
}
enableNodeCalled.should.be.equal(state);
disableNodeCalled.should.be.equal(!state);
res.body.should.have.property("id","123");
res.body.should.have.property("enabled",state);
done();
});
}
it('already enabled', function(done) {
run(true,done);
});
it('already disabled', function(done) {
run(false,done);
});
});
it('enables disabled module', function(done) {
var n1 = {id:"123",enabled:false,types:['a']};
var n2 = {id:"456",enabled:false,types:['b']};
var enableNode = sinon.stub();
enableNode.onFirstCall().returns((function() {
n1.enabled = true;
return when.resolve(n1);
})());
enableNode.onSecondCall().returns((function() {
n2.enabled = true;
return when.resolve(n2);
})());
enableNode.returns(null);
initNodes({
settings:{available:function(){return true}},
it('sets module state and returns module info', function(done) {
var opts;
nodes.init({
nodes:{
getModuleInfo: function() { return {name:"node-red", nodes:[n1, n2]} },
enableNode: enableNode
setModuleState: function(_opts) {
opts = _opts;
return Promise.resolve({name:"node-red"});
}
}
});
@@ -669,154 +400,20 @@ describe("api/admin/nodes", function() {
throw err;
}
res.body.should.have.property("name","node-red");
res.body.should.have.property("nodes");
res.body.nodes[0].should.have.property("enabled",true);
res.body.nodes[1].should.have.property("enabled",true);
opts.should.have.property("enabled",true);
opts.should.have.property("module","node-red");
done();
});
});
it('disables enabled module', function(done) {
var n1 = {id:"123",enabled:true,types:['a']};
var n2 = {id:"456",enabled:true,types:['b']};
var disableNode = sinon.stub();
disableNode.onFirstCall().returns((function() {
n1.enabled = false;
return when.resolve(n1);
})());
disableNode.onSecondCall().returns((function() {
n2.enabled = false;
return when.resolve(n2);
})());
disableNode.returns(null);
initNodes({
settings:{available:function(){return true}},
nodes:{
getModuleInfo: function() { return {name:"node-red", nodes:[n1, n2]} },
disableNode: disableNode
}
});
request(app)
.put('/nodes/node-red')
.send({enabled:false})
.expect(200)
.end(function(err,res) {
if (err) {
throw err;
}
res.body.should.have.property("name","node-red");
res.body.should.have.property("nodes");
res.body.nodes[0].should.have.property("enabled",false);
res.body.nodes[1].should.have.property("enabled",false);
done();
});
});
describe('no-ops if a node in module already in the right state', function() {
function run(state,done) {
var node = {id:"123",enabled:state,types:['a']};
var enableNode = sinon.spy(function(id) {
node.enabled = true;
return when.resolve(node);
});
var disableNode = sinon.spy(function(id) {
node.enabled = false;
return when.resolve(node);
});
initNodes({
settings:{available:function(){return true}},
nodes:{
getModuleInfo: function() { return {name:"node-red", nodes:[node]}; },
enableNode: enableNode,
disableNode: disableNode
}
});
request(app)
.put('/nodes/node-red')
.send({enabled:state})
.expect(200)
.end(function(err,res) {
var enableNodeCalled = enableNode.called;
var disableNodeCalled = disableNode.called;
if (err) {
throw err;
}
enableNodeCalled.should.be.false();
disableNodeCalled.should.be.false();
res.body.should.have.property("name","node-red");
res.body.should.have.property("nodes");
res.body.nodes[0].should.have.property("enabled",state);
done();
});
}
it('already enabled', function(done) {
run(true,done);
});
it('already disabled', function(done) {
run(false,done);
});
});
describe('does not no-op if err on a node in module', function() {
function run(state,done) {
var node = {id:"123",enabled:state,types:['a'],err:"foo"};
var enableNode = sinon.spy(function(id) {
node.enabled = true;
return when.resolve(node);
});
var disableNode = sinon.spy(function(id) {
node.enabled = false;
return when.resolve(node);
});
initNodes({
settings:{available:function(){return true}},
nodes:{
getModuleInfo: function() { return {name:"node-red", nodes:[node]}; },
enableNode: enableNode,
disableNode: disableNode
}
});
request(app)
.put('/nodes/node-red')
.send({enabled:state})
.expect(200)
.end(function(err,res) {
var enableNodeCalled = enableNode.called;
var disableNodeCalled = disableNode.called;
if (err) {
throw err;
}
enableNodeCalled.should.be.equal(state);
disableNodeCalled.should.be.equal(!state);
res.body.should.have.property("name","node-red");
res.body.should.have.property("nodes");
res.body.nodes[0].should.have.property("enabled",state);
done();
});
}
it('already enabled', function(done) {
run(true,done);
});
it('already disabled', function(done) {
run(false,done);
});
});
});
describe('get icons', function() {
it('returns icon list', function(done) {
initNodes({
nodes.init({
nodes:{
getNodeIcons: function() {
return {"module":["1.png","2.png","3.png"]};
getIconList: function() {
return Promise.resolve({module:[1,2,3]});
}
}
});
@@ -827,7 +424,6 @@ describe("api/admin/nodes", function() {
if (err) {
throw err;
}
console.log(res.body);
res.body.should.have.property("module");
res.body.module.should.be.an.Array();
res.body.module.should.have.lengthOf(3);