Move tests to reflect package structure

This commit is contained in:
Nick O'Leary
2018-08-19 11:28:03 +01:00
parent 974ba40f28
commit 998bf92ad4
118 changed files with 39 additions and 26 deletions

View File

@@ -0,0 +1,235 @@
/**
* 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 request = require('supertest');
var express = require('express');
var bodyParser = require('body-parser');
var sinon = require('sinon');
var when = require('when');
var context = require("../../../../red/api/admin/context");
var Context = require("../../../../red/runtime/nodes/context");
var Util = require("../../../../red/runtime/util");
describe("api/admin/context", function() {
it.skip("NEEDS TESTS WRITING",function() {});
});
/*
var app = undefined;
before(function (done) {
var node_context = undefined;
app = express();
app.use(bodyParser.json());
app.get("/context/:scope(global)", context.get);
app.get("/context/:scope(global)/*", context.get);
app.get("/context/:scope(node|flow)/:id", context.get);
app.get("/context/:scope(node|flow)/:id/*", context.get);
context.init({
settings: {
},
log:{warn:function(){},_:function(){},audit:function(){}},
nodes: {
listContextStores: Context.listStores,
getContext: Context.get,
getNode: function(id) {
if (id === 'NID') {
return {
id: 'NID',
context: function () {
return node_context;
}
};
}
return null;
}
},
util: Util
});
Context.init({
contextStorage: {
memory0: {
module: "memory"
},
memory1: {
module: "memory"
}
}
});
Context.load().then(function () {
var ctx = Context.get("NID", "FID");
node_context = ctx;
ctx.set("foo", "n_v00", "memory0");
ctx.set("bar", "n_v01", "memory0");
ctx.set("baz", "n_v10", "memory1");
ctx.set("bar", "n_v11", "memory1");
ctx.flow.set("foo", "f_v00", "memory0");
ctx.flow.set("bar", "f_v01", "memory0");
ctx.flow.set("baz", "f_v10", "memory1");
ctx.flow.set("bar", "f_v11", "memory1");
ctx.global.set("foo", "g_v00", "memory0");
ctx.global.set("bar", "g_v01", "memory0");
ctx.global.set("baz", "g_v10", "memory1");
ctx.global.set("bar", "g_v11", "memory1");
done();
});
});
after(function () {
Context.clean({allNodes:{}});
Context.close();
});
function check_mem(body, mem, name, val) {
var mem0 = body[mem];
mem0.should.have.property(name);
mem0[name].should.deepEqual(val);
}
function check_scope(scope, prefix, id) {
describe('# '+scope, function () {
var xid = id ? ("/"+id) : "";
it('should return '+scope+' contexts', function (done) {
request(app)
.get('/context/'+scope+xid)
.set('Accept', 'application/json')
.expect(200)
.end(function (err, res) {
if (err) {
return done(err);
}
var body = res.body;
body.should.have.key('memory0', 'memory1');
check_mem(body, 'memory0',
'foo', {msg:prefix+'_v00', format:'string[5]'});
check_mem(body, 'memory0',
'bar', {msg:prefix+'_v01', format:'string[5]'});
check_mem(body, 'memory1',
'baz', {msg:prefix+'_v10', format:'string[5]'});
check_mem(body, 'memory1',
'bar', {msg:prefix+'_v11', format:'string[5]'});
done();
});
});
it('should return a value from default '+scope+' context', function (done) {
request(app)
.get('/context/'+scope+xid+'/foo')
.set('Accept', 'application/json')
.expect(200)
.end(function (err, res) {
if (err) {
return done(err);
}
var body = res.body;
body.should.deepEqual({msg: prefix+'_v00', format: 'string[5]'});
done();
});
});
it('should return a value from specified '+scope+' context', function (done) {
request(app)
.get('/context/'+scope+xid+'/bar?store=memory1')
.set('Accept', 'application/json')
.expect(200)
.end(function (err, res) {
if (err) {
return done(err);
}
var body = res.body;
body.should.deepEqual({msg: prefix+'_v11', format: 'string[5]', store: 'memory1'});
done();
});
});
it('should return specified '+scope+' store', function (done) {
request(app)
.get('/context/'+scope+xid+'?store=memory1')
.set('Accept', 'application/json')
.expect(200)
.end(function (err, res) {
if (err) {
return done(err);
}
var body = res.body;
body.should.deepEqual({
memory1: {
baz: { msg: prefix+'_v10', format: 'string[5]' },
bar: { msg: prefix+'_v11', format: 'string[5]' }
}
});
done();
});
});
it('should return undefined for unknown key of default '+scope+' store', function (done) {
request(app)
.get('/context/'+scope+xid+'/unknown')
.set('Accept', 'application/json')
.expect(200)
.end(function (err, res) {
if (err) {
return done(err);
}
var body = res.body;
body.should.deepEqual({msg:'(undefined)', format:'undefined'});
done();
});
});
it('should cause error for unknown '+scope+' store', function (done) {
request(app)
.get('/context/'+scope+xid+'?store=unknown')
.set('Accept', 'application/json')
.expect(200)
.end(function (err, res) {
if (err) {
return done();
}
done("unexpected");
});
});
});
}
check_scope("global", "g", undefined);
check_scope("node", "n", "NID");
check_scope("flow", "f", "FID");
describe("# errors", function () {
it('should cause error for unknown scope', function (done) {
request(app)
.get('/context/scope')
.set('Accept', 'application/json')
.expect(200)
.end(function (err, res) {
if (err) {
return done();
}
done("unexpected");
});
});
});
});
*/

View File

@@ -0,0 +1,247 @@
/**
* 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 request = require('supertest');
var express = require('express');
var bodyParser = require('body-parser');
var sinon = require('sinon');
var when = require('when');
var flow = require("../../../../red/api/admin/flow");
describe("api/admin/flow", function() {
var app;
before(function() {
app = express();
app.use(bodyParser.json());
app.get("/flow/:id",flow.get);
app.post("/flow",flow.post);
app.put("/flow/:id",flow.put);
app.delete("/flow/:id",flow.delete);
});
describe("get", function() {
before(function() {
var opts;
flow.init({
flows: {
getFlow: function(_opts) {
opts = _opts;
if (opts.id === '123') {
return Promise.resolve({id:'123'});
} else {
var err = new Error("message");
err.code = "not_found";
err.status = 404;
var p = Promise.reject(err);
p.catch(()=>{});
return p;
}
}
}
});
})
it('gets a known flow', function(done) {
request(app)
.get('/flow/123')
.set('Accept', 'application/json')
.expect(200)
.end(function(err,res) {
if (err) {
return done(err);
}
res.body.should.has.a.property('id','123');
done();
});
})
it('404s an unknown flow', function(done) {
request(app)
.get('/flow/456')
.set('Accept', 'application/json')
.expect(404)
.end(done);
})
});
describe("add", function() {
var opts;
before(function() {
flow.init({
flows: {
addFlow: function(_opts) {
opts = _opts;
if (opts.flow.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;
}
}
}
});
})
it('adds a new flow', function(done) {
request(app)
.post('/flow')
.set('Accept', 'application/json')
.send({id:'123'})
.expect(200)
.end(function(err,res) {
if (err) {
return done(err);
}
res.body.should.has.a.property('id','123');
done();
});
})
it('400 an invalid flow', function(done) {
request(app)
.post('/flow')
.set('Accept', 'application/json')
.send({id:'error'})
.expect(400)
.end(function(err,res) {
if (err) {
return done(err);
}
res.body.should.has.a.property('code','random_error');
res.body.should.has.a.property('message','random error');
done();
});
})
})
describe("update", function() {
var opts;
before(function() {
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;
}
}
}
});
})
it('updates an existing flow', function(done) {
request(app)
.put('/flow/123')
.set('Accept', 'application/json')
.send({id:'123'})
.expect(200)
.end(function(err,res) {
if (err) {
return done(err);
}
res.body.should.has.a.property('id','123');
opts.should.have.property('id','123');
opts.should.have.property('flow',{id:'123'})
done();
});
})
it('400 an invalid flow', function(done) {
request(app)
.put('/flow/456')
.set('Accept', 'application/json')
.send({id:'456'})
.expect(400)
.end(function(err,res) {
if (err) {
return done(err);
}
res.body.should.has.a.property('code','random_error');
res.body.should.has.a.property('message','random error');
done();
});
})
})
describe("delete", function() {
var opts;
before(function() {
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;
}
}
}
});
})
it('deletes an existing flow', function(done) {
request(app)
.del('/flow/123')
.set('Accept', 'application/json')
.expect(204)
.end(function(err,res) {
if (err) {
return done(err);
}
opts.should.have.property('id','123');
done();
});
})
it('400 an invalid flow', function(done) {
request(app)
.del('/flow/456')
.set('Accept', 'application/json')
.expect(400)
.end(function(err,res) {
if (err) {
return done(err);
}
res.body.should.has.a.property('code','random_error');
res.body.should.has.a.property('message','random error');
done();
});
})
})
});

View File

@@ -0,0 +1,209 @@
/**
* 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 request = require('supertest');
var express = require('express');
var bodyParser = require('body-parser');
var sinon = require('sinon');
var flows = require("../../../../red/api/admin/flows");
describe("api/admin/flows", function() {
var app;
before(function() {
app = express();
app.use(bodyParser.json());
app.get("/flows",flows.get);
app.post("/flows",flows.post);
});
it('returns flow - v1', function(done) {
flows.init({
flows:{
getFlows: function() { return Promise.resolve({rev:"123",flows:[1,2,3]}); }
}
});
request(app)
.get('/flows')
.set('Accept', 'application/json')
.expect(200)
.end(function(err,res) {
if (err) {
return done(err);
}
try {
res.body.should.have.lengthOf(3);
done();
} catch(e) {
return done(e);
}
});
});
it('returns flow - v2', function(done) {
flows.init({
flows:{
getFlows: function() { return Promise.resolve({rev:"123",flows:[1,2,3]}); }
}
});
request(app)
.get('/flows')
.set('Accept', 'application/json')
.set('Node-RED-API-Version','v2')
.expect(200)
.end(function(err,res) {
if (err) {
return done(err);
}
try {
res.body.should.have.a.property('rev','123');
res.body.should.have.a.property('flows');
res.body.flows.should.have.lengthOf(3);
done();
} catch(e) {
return done(e);
}
});
});
it('returns flow - bad version', function(done) {
request(app)
.get('/flows')
.set('Accept', 'application/json')
.set('Node-RED-API-Version','xxx')
.expect(400)
.end(function(err,res) {
if (err) {
return done(err);
}
try {
res.body.should.have.a.property('code','invalid_api_version');
done();
} catch(e) {
return done(e);
}
});
});
it('sets flows - default - v1', function(done) {
var setFlows = sinon.spy(function() { return Promise.resolve();});
flows.init({
flows:{
setFlows: setFlows
}
});
request(app)
.post('/flows')
.set('Accept', 'application/json')
.expect(204)
.end(function(err,res) {
if (err) {
return done(err);
}
setFlows.calledOnce.should.be.true();
setFlows.lastCall.args[0].should.have.property('deploymentType','full');
done();
});
});
it('sets flows - non-default - v1', function(done) {
var setFlows = sinon.spy(function() { return Promise.resolve();});
flows.init({
flows:{
setFlows: setFlows
}
});
request(app)
.post('/flows')
.set('Accept', 'application/json')
.set('Node-RED-Deployment-Type','nodes')
.expect(204)
.end(function(err,res) {
if (err) {
return done(err);
}
setFlows.calledOnce.should.be.true();
setFlows.lastCall.args[0].should.have.property('deploymentType','nodes');
done();
});
});
it('set flows - rejects mismatched revision - v2', function(done) {
flows.init({
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)
.post('/flows')
.set('Accept', 'application/json')
.set('Node-RED-API-Version','v2')
.send({rev:456,flows:[4,5,6]})
.expect(409)
.end(function(err,res) {
if (err) {
return done(err);
}
res.body.should.have.property("code","version_mismatch");
done();
});
});
it('sets flow - bad version', function(done) {
request(app)
.post('/flows')
.set('Accept', 'application/json')
.set('Node-RED-API-Version','xxx')
.expect(400)
.end(function(err,res) {
if (err) {
return done(err);
}
try {
res.body.should.have.a.property('code','invalid_api_version');
done();
} catch(e) {
return done(e);
}
});
});
it('reloads flows', function(done) {
var setFlows = sinon.spy(function() { return Promise.resolve();});
flows.init({
flows:{
setFlows: setFlows
}
});
request(app)
.post('/flows')
.set('Accept', 'application/json')
.set('Node-RED-Deployment-Type','reload')
.expect(204)
.end(function(err,res) {
if (err) {
return done(err);
}
setFlows.called.should.be.true();
setFlows.lastCall.args[0].should.not.have.property('flows');
done();
});
});
});

View File

@@ -0,0 +1,319 @@
/**
* 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 sinon = require("sinon");
var request = require("supertest");
var express = require("express");
var adminApi = require("../../../../red/api/admin");
var auth = require("../../../../red/api/auth");
var nodes = require("../../../../red/api/admin/nodes");
var flows = require("../../../../red/api/admin/flows");
var flow = require("../../../../red/api/admin/flow");
/**
* Ensure all API routes are correctly mounted, with the expected permissions checks
*/
describe("api/admin/index", function() {
describe("Ensure all API routes are correctly mounted, with the expected permissions checks", function() {
var app;
var mockList = [
flows,flow,nodes
]
var permissionChecks = {};
var lastRequest;
var stubApp = function(req,res,next) {
lastRequest = req;
res.status(200).end();
};
before(function() {
mockList.forEach(function(m) {
sinon.stub(m,"init",function(){});
});
sinon.stub(auth,"needsPermission", function(permission) {
return function(req,res,next) {
permissionChecks[permission] = (permissionChecks[permission]||0)+1;
next();
}
});
sinon.stub(flows,"get",stubApp);
sinon.stub(flows,"post",stubApp);
sinon.stub(flow,"get",stubApp);
sinon.stub(flow,"post",stubApp);
sinon.stub(flow,"delete",stubApp);
sinon.stub(flow,"put",stubApp);
sinon.stub(nodes,"getAll",stubApp);
sinon.stub(nodes,"post",stubApp);
sinon.stub(nodes,"getModule",stubApp);
sinon.stub(nodes,"putModule",stubApp);
sinon.stub(nodes,"delete",stubApp);
sinon.stub(nodes,"getSet",stubApp);
sinon.stub(nodes,"putSet",stubApp);
sinon.stub(nodes,"getModuleCatalog",stubApp);
sinon.stub(nodes,"getModuleCatalogs",stubApp);
});
after(function() {
mockList.forEach(function(m) {
m.init.restore();
});
auth.needsPermission.restore();
flows.get.restore();
flows.post.restore();
flow.get.restore();
flow.post.restore();
flow.delete.restore();
flow.put.restore();
nodes.getAll.restore();
nodes.post.restore();
nodes.getModule.restore();
nodes.putModule.restore();
nodes.delete.restore();
nodes.getSet.restore();
nodes.putSet.restore();
nodes.getModuleCatalog.restore();
nodes.getModuleCatalogs.restore();
});
before(function() {
app = adminApi.init({});
});
beforeEach(function() {
permissionChecks = {};
})
it('GET /flows', function(done) {
request(app).get("/flows").expect(200).end(function(err,res) {
if (err) {
return done(err);
}
permissionChecks.should.have.property('flows.read',1);
done();
})
});
it('POST /flows', function(done) {
request(app).post("/flows").expect(200).end(function(err,res) {
if (err) {
return done(err);
}
permissionChecks.should.have.property('flows.write',1);
done();
})
});
it('GET /flow/1234', function(done) {
request(app).get("/flow/1234").expect(200).end(function(err,res) {
if (err) {
return done(err);
}
permissionChecks.should.have.property('flows.read',1);
lastRequest.params.should.have.property('id','1234')
done();
})
});
it('POST /flow', function(done) {
request(app).post("/flow").expect(200).end(function(err,res) {
if (err) {
return done(err);
}
permissionChecks.should.have.property('flows.write',1);
done();
})
});
it('DELETE /flow/1234', function(done) {
request(app).del("/flow/1234").expect(200).end(function(err,res) {
if (err) {
return done(err);
}
permissionChecks.should.have.property('flows.write',1);
lastRequest.params.should.have.property('id','1234')
done();
})
});
it('PUT /flow/1234', function(done) {
request(app).put("/flow/1234").expect(200).end(function(err,res) {
if (err) {
return done(err);
}
permissionChecks.should.have.property('flows.write',1);
lastRequest.params.should.have.property('id','1234')
done();
})
});
it('GET /nodes', function(done) {
request(app).get("/nodes").expect(200).end(function(err,res) {
if (err) {
return done(err);
}
permissionChecks.should.have.property('nodes.read',1);
done();
})
});
it('POST /nodes', function(done) {
request(app).post("/nodes").expect(200).end(function(err,res) {
if (err) {
return done(err);
}
permissionChecks.should.have.property('nodes.write',1);
done();
})
});
it('GET /nodes/module', function(done) {
request(app).get("/nodes/module").expect(200).end(function(err,res) {
if (err) {
return done(err);
}
permissionChecks.should.have.property('nodes.read',1);
lastRequest.params.should.have.property(0,'module')
done();
})
});
it('GET /nodes/@scope/module', function(done) {
request(app).get("/nodes/@scope/module").expect(200).end(function(err,res) {
if (err) {
return done(err);
}
permissionChecks.should.have.property('nodes.read',1);
lastRequest.params.should.have.property(0,'@scope/module')
done();
})
});
it('PUT /nodes/module', function(done) {
request(app).put("/nodes/module").expect(200).end(function(err,res) {
if (err) {
return done(err);
}
permissionChecks.should.have.property('nodes.write',1);
lastRequest.params.should.have.property(0,'module')
done();
})
});
it('PUT /nodes/@scope/module', function(done) {
request(app).put("/nodes/@scope/module").expect(200).end(function(err,res) {
if (err) {
return done(err);
}
permissionChecks.should.have.property('nodes.write',1);
lastRequest.params.should.have.property(0,'@scope/module')
done();
})
});
it('DELETE /nodes/module', function(done) {
request(app).del("/nodes/module").expect(200).end(function(err,res) {
if (err) {
return done(err);
}
permissionChecks.should.have.property('nodes.write',1);
lastRequest.params.should.have.property(0,'module')
done();
})
});
it('DELETE /nodes/@scope/module', function(done) {
request(app).del("/nodes/@scope/module").expect(200).end(function(err,res) {
if (err) {
return done(err);
}
permissionChecks.should.have.property('nodes.write',1);
lastRequest.params.should.have.property(0,'@scope/module')
done();
})
});
it('GET /nodes/module/set', function(done) {
request(app).get("/nodes/module/set").expect(200).end(function(err,res) {
if (err) {
return done(err);
}
permissionChecks.should.have.property('nodes.read',1);
lastRequest.params.should.have.property(0,'module')
lastRequest.params.should.have.property(2,'set')
done();
})
});
it('GET /nodes/@scope/module/set', function(done) {
request(app).get("/nodes/@scope/module/set").expect(200).end(function(err,res) {
if (err) {
return done(err);
}
permissionChecks.should.have.property('nodes.read',1);
lastRequest.params.should.have.property(0,'@scope/module')
lastRequest.params.should.have.property(2,'set')
done();
})
});
it('PUT /nodes/module/set', function(done) {
request(app).put("/nodes/module/set").expect(200).end(function(err,res) {
if (err) {
return done(err);
}
permissionChecks.should.have.property('nodes.write',1);
lastRequest.params.should.have.property(0,'module')
lastRequest.params.should.have.property(2,'set')
done();
})
});
it('PUT /nodes/@scope/module/set', function(done) {
request(app).put("/nodes/@scope/module/set").expect(200).end(function(err,res) {
if (err) {
return done(err);
}
permissionChecks.should.have.property('nodes.write',1);
lastRequest.params.should.have.property(0,'@scope/module')
lastRequest.params.should.have.property(2,'set')
done();
})
});
it('GET /nodes/messages', function(done) {
request(app).get("/nodes/messages").expect(200).end(function(err,res) {
if (err) {
return done(err);
}
permissionChecks.should.have.property('nodes.read',1);
done();
})
});
it('GET /nodes/module/set/messages', function(done) {
request(app).get("/nodes/module/set/messages").expect(200).end(function(err,res) {
if (err) {
return done(err);
}
permissionChecks.should.have.property('nodes.read',1);
lastRequest.params.should.have.property(0,'module/set');
done();
})
});
it('GET /nodes/@scope/module/set/messages', function(done) {
request(app).get("/nodes/@scope/module/set/messages").expect(200).end(function(err,res) {
if (err) {
return done(err);
}
permissionChecks.should.have.property('nodes.read',1);
lastRequest.params.should.have.property(0,'@scope/module/set');
done();
})
});
});
});

View File

@@ -0,0 +1,477 @@
/**
* 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 request = require('supertest');
var express = require('express');
var bodyParser = require('body-parser');
var sinon = require('sinon');
var when = require('when');
var nodes = require("../../../../red/api/admin/nodes");
var apiUtil = require("../../../../red/api/util");
describe("api/admin/nodes", function() {
var app;
before(function() {
app = express();
app.use(bodyParser.json());
app.get("/nodes",nodes.getAll);
app.post("/nodes",nodes.post);
app.get(/\/nodes\/messages/,nodes.getModuleCatalogs);
app.get(/\/nodes\/((@[^\/]+\/)?[^\/]+\/[^\/]+)\/messages/,nodes.getModuleCatalog);
app.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,nodes.getModule);
app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,nodes.putModule);
app.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,nodes.getSet);
app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,nodes.putSet);
app.get("/getIcons",nodes.getIcons);
app.delete(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,nodes.delete);
sinon.stub(apiUtil,"determineLangFromHeaders", function() {
return "en-US";
});
});
after(function() {
apiUtil.determineLangFromHeaders.restore();
})
describe('get nodes', function() {
it('returns node list', function(done) {
nodes.init({
nodes:{
getNodeList: function() {
return Promise.resolve([1,2,3]);
}
}
});
request(app)
.get('/nodes')
.set('Accept', 'application/json')
.expect(200)
.end(function(err,res) {
if (err) {
throw err;
}
res.body.should.be.an.Array();
res.body.should.have.lengthOf(3);
done();
});
});
it('returns node configs', function(done) {
nodes.init({
nodes:{
getNodeConfigs: function() {
return Promise.resolve("<script></script>");
}
},
i18n: {
determineLangFromHeaders: function(){}
}
});
request(app)
.get('/nodes')
.set('Accept', 'text/html')
.expect(200)
.expect("<script></script>")
.end(function(err,res) {
if (err) {
throw err;
}
done();
});
});
it('returns node module info', function(done) {
nodes.init({
nodes:{
getModuleInfo: function(opts) {
return Promise.resolve({"node-red":{name:"node-red"}}[opts.module]);
}
}
});
request(app)
.get('/nodes/node-red')
.expect(200)
.end(function(err,res) {
if (err) {
throw err;
}
res.body.should.have.property("name","node-red");
done();
});
});
it('returns 404 for unknown module', function(done) {
nodes.init({
nodes:{
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;
}
}
});
request(app)
.get('/nodes/node-blue')
.expect(404)
.end(function(err,res) {
if (err) {
throw err;
}
done();
});
});
it('returns individual node info', function(done) {
nodes.init({
nodes:{
getNodeInfo: function(opts) {
return Promise.resolve({"node-red/123":{id:"node-red/123"}}[opts.id]);
}
}
});
request(app)
.get('/nodes/node-red/123')
.set('Accept', 'application/json')
.expect(200)
.end(function(err,res) {
if (err) {
throw err;
}
res.body.should.have.property("id","node-red/123");
done();
});
});
it('returns individual node configs', function(done) {
nodes.init({
nodes:{
getNodeConfig: function(opts) {
return Promise.resolve({"node-red/123":"<script></script>"}[opts.id]);
}
},
i18n: {
determineLangFromHeaders: function(){}
}
});
request(app)
.get('/nodes/node-red/123')
.set('Accept', 'text/html')
.expect(200)
.expect("<script></script>")
.end(function(err,res) {
if (err) {
throw err;
}
done();
});
});
it('returns 404 for unknown node', function(done) {
nodes.init({
nodes:{
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;
}
}
});
request(app)
.get('/nodes/node-red/456')
.set('Accept', 'application/json')
.expect(404)
.end(function(err,res) {
if (err) {
throw err;
}
done();
});
});
});
describe('install', function() {
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();
});
});
});
describe('delete', function() {
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)
.end(function(err,res) {
if (err) {
throw err;
}
res.body.should.have.a.property('code','random_error');
done();
});
});
});
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')
.send({})
.expect(400)
.end(function(err,res) {
if (err) {
throw err;
}
res.body.should.have.property("code","invalid_request");
res.body.should.have.property("message","Invalid request");
done();
});
});
it('sets node state and returns node info', function(done) {
var opts;
nodes.init({
nodes:{
setNodeSetState: function(_opts) {
opts = _opts;
return Promise.resolve({id:"123",enabled: true });
}
}
});
request(app)
.put('/nodes/node-red/foo')
.send({enabled:true})
.expect(200)
.end(function(err,res) {
if (err) {
throw err;
}
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();
});
});
});
describe('enable/disable module' ,function() {
it('returns 400 for invalid request payload', function(done) {
nodes.init({
nodes:{
setModuleState: function(opts) {return Promise.resolve()}
}
});
request(app)
.put('/nodes/node-red')
.send({})
.expect(400)
.end(function(err,res) {
if (err) {
throw err;
}
res.body.should.have.property("code","invalid_request");
res.body.should.have.property("message","Invalid request");
done();
});
});
it('sets module state and returns module info', function(done) {
var opts;
nodes.init({
nodes:{
setModuleState: function(_opts) {
opts = _opts;
return Promise.resolve({name:"node-red"});
}
}
});
request(app)
.put('/nodes/node-red')
.send({enabled:true})
.expect(200)
.end(function(err,res) {
if (err) {
throw err;
}
res.body.should.have.property("name","node-red");
opts.should.have.property("enabled",true);
opts.should.have.property("module","node-red");
done();
});
});
});
describe('get icons', function() {
it('returns icon list', function(done) {
nodes.init({
nodes:{
getIconList: function() {
return Promise.resolve({module:[1,2,3]});
}
}
});
request(app)
.get('/getIcons')
.expect(200)
.end(function(err,res) {
if (err) {
throw err;
}
res.body.should.have.property("module");
res.body.module.should.be.an.Array();
res.body.module.should.have.lengthOf(3);
done();
});
});
});
describe('get module messages', function() {
it('returns message catalog', function(done) {
nodes.init({
nodes:{
getModuleCatalog: function(opts) {
return Promise.resolve(opts);
}
}
});
request(app)
.get('/nodes/module/set/messages')
.expect(200)
.end(function(err,res) {
if (err) {
throw err;
}
res.body.should.eql({ module: 'module/set' });
done();
});
});
it('returns all node catalogs', function(done) {
nodes.init({
nodes:{
getModuleCatalogs: function(opts) {
return Promise.resolve({a:1});
}
}
});
request(app)
.get('/nodes/messages')
.expect(200)
.end(function(err,res) {
if (err) {
throw err;
}
res.body.should.eql({a:1});
done();
});
});
})
});