2014-11-04 18:05:29 +01:00
|
|
|
/**
|
2017-01-11 16:24:33 +01:00
|
|
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
2014-11-04 18:05:29 +01:00
|
|
|
*
|
|
|
|
* 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');
|
2015-07-15 23:43:24 +02:00
|
|
|
var bodyParser = require('body-parser');
|
2014-11-04 18:05:29 +01:00
|
|
|
var sinon = require('sinon');
|
|
|
|
var when = require('when');
|
|
|
|
|
2017-08-22 23:26:29 +02:00
|
|
|
var nodes = require("../../../../red/api/admin/nodes");
|
|
|
|
var apiUtil = require("../../../../red/api/util");
|
2015-11-18 11:35:22 +01:00
|
|
|
|
2017-09-20 11:30:07 +02:00
|
|
|
describe("api/admin/nodes", function() {
|
2014-11-20 16:17:13 +01:00
|
|
|
|
2014-11-04 18:05:29 +01:00
|
|
|
var app;
|
|
|
|
before(function() {
|
|
|
|
app = express();
|
2015-07-15 23:43:24 +02:00
|
|
|
app.use(bodyParser.json());
|
2014-11-04 18:05:29 +01:00
|
|
|
app.get("/nodes",nodes.getAll);
|
|
|
|
app.post("/nodes",nodes.post);
|
2016-05-17 22:56:03 +02:00
|
|
|
app.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,nodes.getModule);
|
|
|
|
app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,nodes.putModule);
|
2018-04-24 16:01:49 +02:00
|
|
|
app.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,nodes.getSet);
|
2016-05-17 22:56:03 +02:00
|
|
|
app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,nodes.putSet);
|
2017-11-30 14:13:35 +01:00
|
|
|
app.get("/getIcons",nodes.getIcons);
|
2018-04-24 16:01:49 +02:00
|
|
|
app.delete(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,nodes.delete);
|
2017-08-22 23:26:29 +02:00
|
|
|
sinon.stub(apiUtil,"determineLangFromHeaders", function() {
|
2015-11-22 00:12:39 +01:00
|
|
|
return "en-US";
|
|
|
|
});
|
2015-11-18 11:35:22 +01:00
|
|
|
});
|
2017-08-22 23:26:29 +02:00
|
|
|
after(function() {
|
|
|
|
apiUtil.determineLangFromHeaders.restore();
|
|
|
|
})
|
2014-11-20 16:17:13 +01:00
|
|
|
|
2014-11-04 18:05:29 +01:00
|
|
|
describe('get nodes', function() {
|
|
|
|
it('returns node list', function(done) {
|
2018-04-24 16:01:49 +02:00
|
|
|
nodes.init({
|
2015-11-24 23:38:42 +01:00
|
|
|
nodes:{
|
2015-11-11 23:11:02 +01:00
|
|
|
getNodeList: function() {
|
2018-04-24 16:01:49 +02:00
|
|
|
return Promise.resolve([1,2,3]);
|
2015-11-11 23:11:02 +01:00
|
|
|
}
|
|
|
|
}
|
2014-11-04 18:05:29 +01:00
|
|
|
});
|
|
|
|
request(app)
|
|
|
|
.get('/nodes')
|
|
|
|
.set('Accept', 'application/json')
|
|
|
|
.expect(200)
|
|
|
|
.end(function(err,res) {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
2016-10-10 14:27:43 +02:00
|
|
|
res.body.should.be.an.Array();
|
2016-04-18 13:40:08 +02:00
|
|
|
res.body.should.have.lengthOf(3);
|
2014-11-04 18:05:29 +01:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2014-11-20 16:17:13 +01:00
|
|
|
|
2014-11-04 18:05:29 +01:00
|
|
|
it('returns node configs', function(done) {
|
2018-04-24 16:01:49 +02:00
|
|
|
nodes.init({
|
2015-11-24 23:38:42 +01:00
|
|
|
nodes:{
|
2015-11-11 23:11:02 +01:00
|
|
|
getNodeConfigs: function() {
|
2018-04-24 16:01:49 +02:00
|
|
|
return Promise.resolve("<script></script>");
|
2015-11-11 23:11:02 +01:00
|
|
|
}
|
|
|
|
},
|
|
|
|
i18n: {
|
|
|
|
determineLangFromHeaders: function(){}
|
|
|
|
}
|
2014-11-04 18:05:29 +01:00
|
|
|
});
|
|
|
|
request(app)
|
|
|
|
.get('/nodes')
|
|
|
|
.set('Accept', 'text/html')
|
|
|
|
.expect(200)
|
|
|
|
.expect("<script></script>")
|
|
|
|
.end(function(err,res) {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2014-11-20 16:17:13 +01:00
|
|
|
|
|
|
|
it('returns node module info', function(done) {
|
2018-04-24 16:01:49 +02:00
|
|
|
nodes.init({
|
2015-11-24 23:38:42 +01:00
|
|
|
nodes:{
|
2018-04-24 16:01:49 +02:00
|
|
|
getModuleInfo: function(opts) {
|
|
|
|
return Promise.resolve({"node-red":{name:"node-red"}}[opts.module]);
|
2015-11-11 23:11:02 +01:00
|
|
|
}
|
|
|
|
}
|
2014-11-20 16:17:13 +01:00
|
|
|
});
|
|
|
|
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) {
|
2018-04-24 16:01:49 +02:00
|
|
|
nodes.init({
|
2015-11-24 23:38:42 +01:00
|
|
|
nodes:{
|
2018-04-24 16:01:49 +02:00
|
|
|
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;
|
2015-11-11 23:11:02 +01:00
|
|
|
}
|
|
|
|
}
|
2014-11-20 16:17:13 +01:00
|
|
|
});
|
|
|
|
request(app)
|
|
|
|
.get('/nodes/node-blue')
|
|
|
|
.expect(404)
|
|
|
|
.end(function(err,res) {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('returns individual node info', function(done) {
|
2018-04-24 16:01:49 +02:00
|
|
|
nodes.init({
|
2015-11-24 23:38:42 +01:00
|
|
|
nodes:{
|
2018-04-24 16:01:49 +02:00
|
|
|
getNodeInfo: function(opts) {
|
|
|
|
return Promise.resolve({"node-red/123":{id:"node-red/123"}}[opts.id]);
|
2015-11-11 23:11:02 +01:00
|
|
|
}
|
|
|
|
}
|
2014-11-04 18:05:29 +01:00
|
|
|
});
|
|
|
|
request(app)
|
2014-11-20 16:17:13 +01:00
|
|
|
.get('/nodes/node-red/123')
|
2014-11-04 18:05:29 +01:00
|
|
|
.set('Accept', 'application/json')
|
|
|
|
.expect(200)
|
|
|
|
.end(function(err,res) {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
2014-11-20 16:17:13 +01:00
|
|
|
res.body.should.have.property("id","node-red/123");
|
2014-11-04 18:05:29 +01:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2014-11-20 16:17:13 +01:00
|
|
|
|
|
|
|
it('returns individual node configs', function(done) {
|
2018-04-24 16:01:49 +02:00
|
|
|
nodes.init({
|
2015-11-24 23:38:42 +01:00
|
|
|
nodes:{
|
2018-04-24 16:01:49 +02:00
|
|
|
getNodeConfig: function(opts) {
|
|
|
|
return Promise.resolve({"node-red/123":"<script></script>"}[opts.id]);
|
2015-11-11 23:11:02 +01:00
|
|
|
}
|
|
|
|
},
|
|
|
|
i18n: {
|
|
|
|
determineLangFromHeaders: function(){}
|
|
|
|
}
|
2014-11-04 18:05:29 +01:00
|
|
|
});
|
|
|
|
request(app)
|
2014-11-20 16:17:13 +01:00
|
|
|
.get('/nodes/node-red/123')
|
2014-11-04 18:05:29 +01:00
|
|
|
.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) {
|
2018-04-24 16:01:49 +02:00
|
|
|
nodes.init({
|
2015-11-24 23:38:42 +01:00
|
|
|
nodes:{
|
2018-04-24 16:01:49 +02:00
|
|
|
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;
|
2015-11-11 23:11:02 +01:00
|
|
|
}
|
|
|
|
}
|
2014-11-04 18:05:29 +01:00
|
|
|
});
|
|
|
|
request(app)
|
2014-11-20 16:17:13 +01:00
|
|
|
.get('/nodes/node-red/456')
|
2014-11-04 18:05:29 +01:00
|
|
|
.set('Accept', 'application/json')
|
|
|
|
.expect(404)
|
|
|
|
.end(function(err,res) {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2014-11-20 16:17:13 +01:00
|
|
|
|
2014-11-04 18:05:29 +01:00
|
|
|
describe('install', function() {
|
2018-04-24 16:01:49 +02:00
|
|
|
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"}]
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
2014-11-04 18:05:29 +01:00
|
|
|
});
|
|
|
|
request(app)
|
2018-04-24 16:01:49 +02:00
|
|
|
.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();
|
|
|
|
});
|
2014-11-04 18:05:29 +01:00
|
|
|
});
|
2018-04-24 16:01:49 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2014-11-05 23:41:05 +01:00
|
|
|
});
|
|
|
|
request(app)
|
|
|
|
.post('/nodes')
|
2018-04-24 16:01:49 +02:00
|
|
|
.send({module: 'foo',version:"1.2.3"})
|
2014-11-05 23:41:05 +01:00
|
|
|
.expect(400)
|
|
|
|
.end(function(err,res) {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
2018-04-24 16:01:49 +02:00
|
|
|
res.body.should.have.a.property('code','random_error');
|
2014-11-05 23:41:05 +01:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2014-11-04 18:05:29 +01:00
|
|
|
});
|
|
|
|
describe('delete', function() {
|
2018-04-24 16:01:49 +02:00
|
|
|
it('uninstalls the module', function(done) {
|
|
|
|
var opts;
|
|
|
|
nodes.init({
|
|
|
|
nodes:{
|
|
|
|
removeModule: function(_opts) {
|
|
|
|
opts = _opts;
|
|
|
|
return Promise.resolve();
|
2015-11-11 23:11:02 +01:00
|
|
|
}
|
2018-04-24 16:01:49 +02:00
|
|
|
}
|
2014-11-04 18:05:29 +01:00
|
|
|
});
|
2018-04-24 16:01:49 +02:00
|
|
|
request(app)
|
|
|
|
.del('/nodes/123')
|
|
|
|
.expect(204)
|
|
|
|
.end(function(err,res) {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
opts.should.have.property("module","123");
|
|
|
|
done();
|
2014-11-04 18:05:29 +01:00
|
|
|
});
|
|
|
|
});
|
2018-04-24 16:01:49 +02:00
|
|
|
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;
|
2014-11-04 18:05:29 +01:00
|
|
|
}
|
2018-04-24 16:01:49 +02:00
|
|
|
}
|
2014-11-21 11:36:32 +01:00
|
|
|
});
|
|
|
|
request(app)
|
2018-04-24 16:01:49 +02:00
|
|
|
.del('/nodes/123')
|
2014-11-21 11:36:32 +01:00
|
|
|
.expect(400)
|
|
|
|
.end(function(err,res) {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
2018-04-24 16:01:49 +02:00
|
|
|
res.body.should.have.a.property('code','random_error');
|
2014-11-21 11:36:32 +01:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2018-04-24 16:01:49 +02:00
|
|
|
});
|
2014-11-21 11:36:32 +01:00
|
|
|
|
2018-04-24 16:01:49 +02:00
|
|
|
describe('enable/disable node set', function() {
|
|
|
|
it('returns 400 for invalid request payload', function(done) {
|
|
|
|
nodes.init({
|
|
|
|
nodes:{
|
|
|
|
setNodeSetState: function(opts) {return Promise.resolve()}
|
|
|
|
}
|
2014-11-04 18:05:29 +01:00
|
|
|
});
|
|
|
|
request(app)
|
2018-04-24 16:01:49 +02:00
|
|
|
.put('/nodes/node-red/foo')
|
2014-11-04 18:05:29 +01:00
|
|
|
.send({})
|
|
|
|
.expect(400)
|
|
|
|
.end(function(err,res) {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
2018-04-24 16:01:49 +02:00
|
|
|
res.body.should.have.property("code","invalid_request");
|
2015-03-30 15:16:04 +02:00
|
|
|
res.body.should.have.property("message","Invalid request");
|
2014-11-04 18:05:29 +01:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2014-11-21 11:36:32 +01:00
|
|
|
|
2018-04-24 16:01:49 +02:00
|
|
|
it('sets node state and returns node info', function(done) {
|
|
|
|
var opts;
|
|
|
|
nodes.init({
|
2015-11-24 23:38:42 +01:00
|
|
|
nodes:{
|
2018-04-24 16:01:49 +02:00
|
|
|
setNodeSetState: function(_opts) {
|
|
|
|
opts = _opts;
|
|
|
|
return Promise.resolve({id:"123",enabled: true });
|
2014-11-04 18:05:29 +01:00
|
|
|
}
|
2015-11-11 23:11:02 +01:00
|
|
|
}
|
2014-11-21 11:36:32 +01:00
|
|
|
});
|
|
|
|
|
2014-11-04 18:05:29 +01:00
|
|
|
request(app)
|
2014-11-21 11:36:32 +01:00
|
|
|
.put('/nodes/node-red/foo')
|
2014-11-04 18:05:29 +01:00
|
|
|
.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);
|
2018-04-24 16:01:49 +02:00
|
|
|
opts.should.have.property("enabled",true);
|
|
|
|
opts.should.have.property("id","node-red/foo");
|
2014-11-20 16:17:13 +01:00
|
|
|
|
2014-11-04 18:05:29 +01:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2018-04-24 16:01:49 +02:00
|
|
|
});
|
|
|
|
describe('enable/disable module' ,function() {
|
|
|
|
it('returns 400 for invalid request payload', function(done) {
|
|
|
|
nodes.init({
|
2015-11-24 23:38:42 +01:00
|
|
|
nodes:{
|
2018-04-24 16:01:49 +02:00
|
|
|
setModuleState: function(opts) {return Promise.resolve()}
|
2015-11-11 23:11:02 +01:00
|
|
|
}
|
|
|
|
});
|
2014-11-21 11:36:32 +01:00
|
|
|
request(app)
|
|
|
|
.put('/nodes/node-red')
|
2018-04-24 16:01:49 +02:00
|
|
|
.send({})
|
|
|
|
.expect(400)
|
2014-11-21 11:36:32 +01:00
|
|
|
.end(function(err,res) {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
2018-04-24 16:01:49 +02:00
|
|
|
res.body.should.have.property("code","invalid_request");
|
|
|
|
res.body.should.have.property("message","Invalid request");
|
2014-11-21 11:36:32 +01:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2018-04-24 16:01:49 +02:00
|
|
|
it('sets module state and returns module info', function(done) {
|
|
|
|
var opts;
|
|
|
|
nodes.init({
|
2015-11-24 23:38:42 +01:00
|
|
|
nodes:{
|
2018-04-24 16:01:49 +02:00
|
|
|
setModuleState: function(_opts) {
|
|
|
|
opts = _opts;
|
|
|
|
return Promise.resolve({name:"node-red"});
|
|
|
|
}
|
2015-11-11 23:11:02 +01:00
|
|
|
}
|
|
|
|
});
|
2014-11-21 11:36:32 +01:00
|
|
|
|
|
|
|
request(app)
|
|
|
|
.put('/nodes/node-red')
|
2018-04-24 16:01:49 +02:00
|
|
|
.send({enabled:true})
|
2014-11-21 11:36:32 +01:00
|
|
|
.expect(200)
|
|
|
|
.end(function(err,res) {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
res.body.should.have.property("name","node-red");
|
2018-04-24 16:01:49 +02:00
|
|
|
opts.should.have.property("enabled",true);
|
|
|
|
opts.should.have.property("module","node-red");
|
2014-11-21 11:36:32 +01:00
|
|
|
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2014-11-04 18:05:29 +01:00
|
|
|
});
|
2014-11-20 16:17:13 +01:00
|
|
|
|
2017-11-30 14:13:35 +01:00
|
|
|
describe('get icons', function() {
|
|
|
|
it('returns icon list', function(done) {
|
2018-04-24 16:01:49 +02:00
|
|
|
nodes.init({
|
2017-11-30 14:13:35 +01:00
|
|
|
nodes:{
|
2018-04-24 16:01:49 +02:00
|
|
|
getIconList: function() {
|
|
|
|
return Promise.resolve({module:[1,2,3]});
|
2017-11-30 14:13:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
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();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2014-11-20 16:17:13 +01:00
|
|
|
});
|