mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Add runtime-api tests
This commit is contained in:
parent
54cc04fd96
commit
fc4edde6e6
@ -71,7 +71,7 @@ module.exports = {
|
|||||||
if (userSettings.httpAdminRoot !== false) {
|
if (userSettings.httpAdminRoot !== false) {
|
||||||
runtime.init(userSettings,redUtil,api);
|
runtime.init(userSettings,redUtil,api);
|
||||||
runtimeAPI.init(runtime,redUtil);
|
runtimeAPI.init(runtime,redUtil);
|
||||||
api.init(httpServer,userSettings,runtime.storage,runtimeAPI,redUtil);
|
api.init(httpServer,userSettings,runtime.storage,runtimeAPI);
|
||||||
|
|
||||||
apiEnabled = true;
|
apiEnabled = true;
|
||||||
server = runtime.adminApi.server;
|
server = runtime.adminApi.server;
|
||||||
@ -106,7 +106,7 @@ module.exports = {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
nodes: runtime.nodes,
|
nodes: runtime.nodes,
|
||||||
get log() { return redUtil.log },
|
log: redUtil.log,
|
||||||
settings:runtime.settings,
|
settings:runtime.settings,
|
||||||
util: runtime.util,
|
util: runtime.util,
|
||||||
version: runtime.version,
|
version: runtime.version,
|
||||||
|
@ -49,7 +49,6 @@ var api = module.exports = {
|
|||||||
getFlows: function(opts) {
|
getFlows: function(opts) {
|
||||||
return new Promise(function(resolve,reject) {
|
return new Promise(function(resolve,reject) {
|
||||||
runtime.log.audit({event: "flows.get"}/*,req*/);
|
runtime.log.audit({event: "flows.get"}/*,req*/);
|
||||||
var version = opts.version||"v1";
|
|
||||||
return resolve(runtime.nodes.getFlows());
|
return resolve(runtime.nodes.getFlows());
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -61,7 +60,6 @@ var api = module.exports = {
|
|||||||
* @memberof RED.flows
|
* @memberof RED.flows
|
||||||
*/
|
*/
|
||||||
setFlows: function(opts) {
|
setFlows: function(opts) {
|
||||||
var err;
|
|
||||||
return new Promise(function(resolve,reject) {
|
return new Promise(function(resolve,reject) {
|
||||||
|
|
||||||
var flows = opts.flows;
|
var flows = opts.flows;
|
||||||
@ -75,6 +73,7 @@ var api = module.exports = {
|
|||||||
if (flows.hasOwnProperty('rev')) {
|
if (flows.hasOwnProperty('rev')) {
|
||||||
var currentVersion = runtime.nodes.getFlows().rev;
|
var currentVersion = runtime.nodes.getFlows().rev;
|
||||||
if (currentVersion !== flows.rev) {
|
if (currentVersion !== flows.rev) {
|
||||||
|
var err;
|
||||||
err = new Error();
|
err = new Error();
|
||||||
err.code = "version_mismatch";
|
err.code = "version_mismatch";
|
||||||
err.status = 409;
|
err.status = 409;
|
||||||
@ -193,18 +192,22 @@ var api = module.exports = {
|
|||||||
var id = opts.id;
|
var id = opts.id;
|
||||||
try {
|
try {
|
||||||
runtime.nodes.removeFlow(id).then(function() {
|
runtime.nodes.removeFlow(id).then(function() {
|
||||||
log.audit({event: "flow.remove",id:id});
|
runtime.log.audit({event: "flow.remove",id:id});
|
||||||
return resolve();
|
return resolve();
|
||||||
})
|
}).catch(function(err) {
|
||||||
|
runtime.log.audit({event: "flow.remove",id:id,error:err.code||"unexpected_error",message:err.toString()});
|
||||||
|
err.status = 400;
|
||||||
|
return reject(err);
|
||||||
|
});
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
if (err.code === 404) {
|
if (err.code === 404) {
|
||||||
log.audit({event: "flow.remove",id:id,error:"not_found"});
|
runtime.log.audit({event: "flow.remove",id:id,error:"not_found"});
|
||||||
// TODO: this swap around of .code and .status isn't ideal
|
// TODO: this swap around of .code and .status isn't ideal
|
||||||
err.status = 404;
|
err.status = 404;
|
||||||
err.code = "not_found";
|
err.code = "not_found";
|
||||||
return reject(err);
|
return reject(err);
|
||||||
} else {
|
} else {
|
||||||
log.audit({event: "flow.remove",id:id,error:err.code||"unexpected_error",message:err.toString()});
|
runtime.log.audit({event: "flow.remove",id:id,error:err.code||"unexpected_error",message:err.toString()});
|
||||||
err.status = 400;
|
err.status = 400;
|
||||||
return reject(err);
|
return reject(err);
|
||||||
}
|
}
|
||||||
@ -228,7 +231,7 @@ var api = module.exports = {
|
|||||||
if (!credentials) {
|
if (!credentials) {
|
||||||
return resolve({});
|
return resolve({});
|
||||||
}
|
}
|
||||||
var definition = runtime.nodes.getCredentialDefinition(opts.type);
|
var definition = runtime.nodes.getCredentialDefinition(opts.type) || {};
|
||||||
|
|
||||||
var sendCredentials = {};
|
var sendCredentials = {};
|
||||||
for (var cred in definition) {
|
for (var cred in definition) {
|
||||||
|
@ -27,6 +27,7 @@ var api = module.exports = {
|
|||||||
available: function(opts) {
|
available: function(opts) {
|
||||||
return Promise.resolve(!!runtime.storage.projects);
|
return Promise.resolve(!!runtime.storage.projects);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List projects known to the runtime
|
* List projects known to the runtime
|
||||||
* @param {Object} opts
|
* @param {Object} opts
|
||||||
@ -50,8 +51,6 @@ var api = module.exports = {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new project
|
* Create a new project
|
||||||
* @param {Object} opts
|
* @param {Object} opts
|
||||||
|
@ -14,278 +14,400 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
describe("runtime-api/flows", function() {
|
|
||||||
it.skip('more tests needed', function(){})
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
var should = require("should");
|
var should = require("should");
|
||||||
var request = require('supertest');
|
var sinon = require("sinon");
|
||||||
var express = require('express');
|
|
||||||
var bodyParser = require('body-parser');
|
|
||||||
var sinon = require('sinon');
|
|
||||||
var when = require('when');
|
|
||||||
|
|
||||||
var flows = require("../../../../red/api/admin/flows");
|
var flows = require("../../../red/runtime-api/flows")
|
||||||
|
|
||||||
describe("api/admin/flows", function() {
|
var mockLog = () => ({
|
||||||
|
log: sinon.stub(),
|
||||||
|
debug: sinon.stub(),
|
||||||
|
trace: sinon.stub(),
|
||||||
|
warn: sinon.stub(),
|
||||||
|
info: sinon.stub(),
|
||||||
|
metric: sinon.stub(),
|
||||||
|
audit: sinon.stub(),
|
||||||
|
_: function() { return "abc"}
|
||||||
|
})
|
||||||
|
|
||||||
var app;
|
describe("runtime-api/flows", function() {
|
||||||
|
describe("getFlows", function() {
|
||||||
before(function() {
|
it("returns the current flow configuration", function(done) {
|
||||||
app = express();
|
flows.init({
|
||||||
app.use(bodyParser.json());
|
log: mockLog(),
|
||||||
app.get("/flows",flows.get);
|
nodes: {
|
||||||
app.post("/flows",flows.post);
|
getFlows: function() { return [1,2,3] }
|
||||||
});
|
|
||||||
|
|
||||||
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]}; }
|
|
||||||
}
|
|
||||||
});
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
flows.getFlows({}).then(function(result) {
|
||||||
it('returns flow - v2', function(done) {
|
result.should.eql([1,2,3]);
|
||||||
flows.init({
|
|
||||||
settings: {},
|
|
||||||
log:{warn:function(){},_:function(){},audit:function(){}},
|
|
||||||
nodes:{
|
|
||||||
getFlows: function() { return {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 when.resolve();});
|
|
||||||
flows.init({
|
|
||||||
log:{warn:function(){},_:function(){},audit:function(){}},
|
|
||||||
nodes:{
|
|
||||||
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[1].should.eql('full');
|
|
||||||
done();
|
done();
|
||||||
});
|
}).catch(done);
|
||||||
});
|
|
||||||
it('sets flows - non-default - v1', function(done) {
|
|
||||||
var setFlows = sinon.spy(function() { return when.resolve();});
|
|
||||||
flows.init({
|
|
||||||
log:{warn:function(){},_:function(){},audit:function(){}},
|
|
||||||
nodes:{
|
|
||||||
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[1].should.eql('nodes');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('set flows - rejects mismatched revision - v2', function(done) {
|
describe("setFlows", function() {
|
||||||
var setFlows = sinon.spy(function() { return when.resolve();});
|
var setFlows;
|
||||||
var getFlows = sinon.spy(function() { return {rev:123,flows:[1,2,3]}});
|
var loadFlows;
|
||||||
flows.init({
|
var reloadError = false;
|
||||||
log:{warn:function(){},_:function(){},audit:function(){}},
|
beforeEach(function() {
|
||||||
nodes:{
|
setFlows = sinon.spy(function(flows,type) {
|
||||||
setFlows: setFlows,
|
if (flows[0] === "error") {
|
||||||
getFlows: getFlows
|
var err = new Error("error");
|
||||||
}
|
err.code = "error";
|
||||||
});
|
var p = Promise.reject(err);
|
||||||
request(app)
|
p.catch(()=>{});
|
||||||
.post('/flows')
|
return p;
|
||||||
.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");
|
return Promise.resolve("newRev");
|
||||||
|
});
|
||||||
|
loadFlows = sinon.spy(function() {
|
||||||
|
if (!reloadError) {
|
||||||
|
return Promise.resolve("newLoadRev");
|
||||||
|
} else {
|
||||||
|
var err = new Error("error");
|
||||||
|
err.code = "error";
|
||||||
|
var p = Promise.reject(err);
|
||||||
|
p.catch(()=>{});
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
flows.init({
|
||||||
|
log: mockLog(),
|
||||||
|
nodes: {
|
||||||
|
getFlows: function() { return {rev:"currentRev",flows:[]} },
|
||||||
|
setFlows: setFlows,
|
||||||
|
loadFlows: loadFlows
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
it("defaults to full deploy", function(done) {
|
||||||
|
flows.setFlows({
|
||||||
|
flows: {flows:[4,5,6]}
|
||||||
|
}).then(function(result) {
|
||||||
|
result.should.eql({rev:"newRev"});
|
||||||
|
setFlows.called.should.be.true();
|
||||||
|
setFlows.lastCall.args[0].should.eql([4,5,6]);
|
||||||
|
setFlows.lastCall.args[1].should.eql("full");
|
||||||
done();
|
done();
|
||||||
});
|
}).catch(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)
|
it("passes through other deploy types", function(done) {
|
||||||
.post('/flows')
|
flows.setFlows({
|
||||||
.set('Accept', 'application/json')
|
deploymentType: "nodes",
|
||||||
.set('Node-RED-API-Version','v2')
|
flows: {flows:[4,5,6]}
|
||||||
.send({rev:123,flows:[4,5,6]})
|
}).then(function(result) {
|
||||||
.expect(200)
|
result.should.eql({rev:"newRev"});
|
||||||
.end(function(err,res) {
|
setFlows.called.should.be.true();
|
||||||
if (err) {
|
setFlows.lastCall.args[0].should.eql([4,5,6]);
|
||||||
return done(err);
|
setFlows.lastCall.args[1].should.eql("nodes");
|
||||||
}
|
|
||||||
res.body.should.have.property("rev",456);
|
|
||||||
done();
|
done();
|
||||||
});
|
}).catch(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)
|
it("triggers a flow reload", function(done) {
|
||||||
.post('/flows')
|
flows.setFlows({
|
||||||
.set('Accept', 'application/json')
|
deploymentType: "reload"
|
||||||
.set('Node-RED-API-Version','v2')
|
}).then(function(result) {
|
||||||
.send({flows:[4,5,6]})
|
result.should.eql({rev:"newLoadRev"});
|
||||||
.expect(200)
|
setFlows.called.should.be.false();
|
||||||
.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')
|
|
||||||
.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 loadFlows = sinon.spy(function() { return when.resolve(); });
|
|
||||||
flows.init({
|
|
||||||
log:{warn:function(){},_:function(){},audit:function(){}},
|
|
||||||
nodes:{
|
|
||||||
loadFlows: loadFlows
|
|
||||||
}
|
|
||||||
});
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
loadFlows.called.should.be.true();
|
loadFlows.called.should.be.true();
|
||||||
done();
|
done();
|
||||||
});
|
}).catch(done);
|
||||||
|
});
|
||||||
|
it("allows update when revision matches", function(done) {
|
||||||
|
flows.setFlows({
|
||||||
|
deploymentType: "nodes",
|
||||||
|
flows: {flows:[4,5,6],rev:"currentRev"}
|
||||||
|
}).then(function(result) {
|
||||||
|
result.should.eql({rev:"newRev"});
|
||||||
|
setFlows.called.should.be.true();
|
||||||
|
setFlows.lastCall.args[0].should.eql([4,5,6]);
|
||||||
|
setFlows.lastCall.args[1].should.eql("nodes");
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
it("rejects update when revision does not match", function(done) {
|
||||||
|
flows.setFlows({
|
||||||
|
deploymentType: "nodes",
|
||||||
|
flows: {flows:[4,5,6],rev:"notTheCurrentRev"}
|
||||||
|
}).then(function(result) {
|
||||||
|
done(new Error("Did not reject rev mismatch"));
|
||||||
|
}).catch(function(err) {
|
||||||
|
err.should.have.property('code','version_mismatch');
|
||||||
|
err.should.have.property('status',409);
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
it("rejects when reload fails",function(done) {
|
||||||
|
reloadError = true;
|
||||||
|
flows.setFlows({
|
||||||
|
deploymentType: "reload"
|
||||||
|
}).then(function(result) {
|
||||||
|
done(new Error("Did not return internal error"));
|
||||||
|
}).catch(function(err) {
|
||||||
|
err.should.have.property('code','error');
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
it("rejects when update fails",function(done) {
|
||||||
|
flows.setFlows({
|
||||||
|
deploymentType: "full",
|
||||||
|
flows: {flows:["error",5,6]}
|
||||||
|
}).then(function(result) {
|
||||||
|
done(new Error("Did not return internal error"));
|
||||||
|
}).catch(function(err) {
|
||||||
|
err.should.have.property('code','error');
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns error when set fails', function(done) {
|
describe("addFlow", function() {
|
||||||
flows.init({
|
var addFlow;
|
||||||
log:{warn:function(){},_:function(){},audit:function(){}},
|
beforeEach(function() {
|
||||||
nodes:{
|
addFlow = sinon.spy(function(flow) {
|
||||||
setFlows: function() { return when.reject(new Error("expected error")); }
|
if (flow === "error") {
|
||||||
}
|
var err = new Error("error");
|
||||||
});
|
err.code = "error";
|
||||||
request(app)
|
var p = Promise.reject(err);
|
||||||
.post('/flows')
|
p.catch(()=>{});
|
||||||
.set('Accept', 'application/json')
|
return p;
|
||||||
.expect(500)
|
|
||||||
.end(function(err,res) {
|
|
||||||
if (err) {
|
|
||||||
return done(err);
|
|
||||||
}
|
}
|
||||||
res.body.should.have.property("message","expected error");
|
return Promise.resolve("newId");
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
|
flows.init({
|
||||||
|
log: mockLog(),
|
||||||
|
nodes: {
|
||||||
|
addFlow: addFlow
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
it("adds a flow", function(done) {
|
||||||
|
flows.addFlow({flow:{a:"123"}}).then(function(id) {
|
||||||
|
addFlow.called.should.be.true();
|
||||||
|
addFlow.lastCall.args[0].should.eql({a:"123"});
|
||||||
|
id.should.eql("newId");
|
||||||
|
done()
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
it("rejects when add fails", function(done) {
|
||||||
|
flows.addFlow({flow:"error"}).then(function(id) {
|
||||||
|
done(new Error("Did not return internal error"));
|
||||||
|
}).catch(function(err) {
|
||||||
|
err.should.have.property('code','error');
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe("getFlow", function() {
|
||||||
|
var getFlow;
|
||||||
|
beforeEach(function() {
|
||||||
|
getFlow = sinon.spy(function(flow) {
|
||||||
|
if (flow === "unknown") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return [1,2,3];
|
||||||
|
});
|
||||||
|
flows.init({
|
||||||
|
log: mockLog(),
|
||||||
|
nodes: {
|
||||||
|
getFlow: getFlow
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
it("gets a flow", function(done) {
|
||||||
|
flows.getFlow({id:"123"}).then(function(flow) {
|
||||||
|
flow.should.eql([1,2,3]);
|
||||||
|
done()
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
it("rejects when flow not found", function(done) {
|
||||||
|
flows.getFlow({id:"unknown"}).then(function(flow) {
|
||||||
|
done(new Error("Did not return internal error"));
|
||||||
|
}).catch(function(err) {
|
||||||
|
err.should.have.property('code','not_found');
|
||||||
|
err.should.have.property('status',404);
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("updateFlow", function() {
|
||||||
|
var updateFlow;
|
||||||
|
beforeEach(function() {
|
||||||
|
updateFlow = sinon.spy(function(id,flow) {
|
||||||
|
if (id === "unknown") {
|
||||||
|
var err = new Error();
|
||||||
|
// TODO: quirk of internal api - uses .code for .status
|
||||||
|
err.code = 404;
|
||||||
|
throw err;
|
||||||
|
} else if (id === "error") {
|
||||||
|
var err = new Error();
|
||||||
|
// TODO: quirk of internal api - uses .code for .status
|
||||||
|
err.code = "error";
|
||||||
|
var p = Promise.reject(err);
|
||||||
|
p.catch(()=>{});
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
});
|
||||||
|
flows.init({
|
||||||
|
log: mockLog(),
|
||||||
|
nodes: {
|
||||||
|
updateFlow: updateFlow
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
it("updates a flow", function(done) {
|
||||||
|
flows.updateFlow({id:"123",flow:[1,2,3]}).then(function(id) {
|
||||||
|
id.should.eql("123");
|
||||||
|
updateFlow.called.should.be.true();
|
||||||
|
updateFlow.lastCall.args[0].should.eql("123");
|
||||||
|
updateFlow.lastCall.args[1].should.eql([1,2,3]);
|
||||||
|
done()
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
it("rejects when flow not found", function(done) {
|
||||||
|
flows.updateFlow({id:"unknown"}).then(function(flow) {
|
||||||
|
done(new Error("Did not return internal error"));
|
||||||
|
}).catch(function(err) {
|
||||||
|
err.should.have.property('code','not_found');
|
||||||
|
err.should.have.property('status',404);
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
it("rejects when update fails", function(done) {
|
||||||
|
flows.updateFlow({id:"error"}).then(function(flow) {
|
||||||
|
done(new Error("Did not return internal error"));
|
||||||
|
}).catch(function(err) {
|
||||||
|
err.should.have.property('code','error');
|
||||||
|
err.should.have.property('status',400);
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe("deleteFlow", function() {
|
||||||
|
var removeFlow;
|
||||||
|
beforeEach(function() {
|
||||||
|
removeFlow = sinon.spy(function(flow) {
|
||||||
|
if (flow === "unknown") {
|
||||||
|
var err = new Error();
|
||||||
|
// TODO: quirk of internal api - uses .code for .status
|
||||||
|
err.code = 404;
|
||||||
|
throw err;
|
||||||
|
} else if (flow === "error") {
|
||||||
|
var err = new Error();
|
||||||
|
// TODO: quirk of internal api - uses .code for .status
|
||||||
|
err.code = "error";
|
||||||
|
var p = Promise.reject(err);
|
||||||
|
p.catch(()=>{});
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
});
|
||||||
|
flows.init({
|
||||||
|
log: mockLog(),
|
||||||
|
nodes: {
|
||||||
|
removeFlow: removeFlow
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
it("deletes a flow", function(done) {
|
||||||
|
flows.deleteFlow({id:"123"}).then(function() {
|
||||||
|
removeFlow.called.should.be.true();
|
||||||
|
removeFlow.lastCall.args[0].should.eql("123");
|
||||||
|
done()
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
it("rejects when flow not found", function(done) {
|
||||||
|
flows.deleteFlow({id:"unknown"}).then(function(flow) {
|
||||||
|
done(new Error("Did not return internal error"));
|
||||||
|
}).catch(function(err) {
|
||||||
|
err.should.have.property('code','not_found');
|
||||||
|
err.should.have.property('status',404);
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
it("rejects when delete fails", function(done) {
|
||||||
|
flows.deleteFlow({id:"error"}).then(function(flow) {
|
||||||
|
done(new Error("Did not return internal error"));
|
||||||
|
}).catch(function(err) {
|
||||||
|
err.should.have.property('code','error');
|
||||||
|
err.should.have.property('status',400);
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getNodeCredentials", function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
flows.init({
|
||||||
|
log: mockLog(),
|
||||||
|
nodes: {
|
||||||
|
getCredentials: function(id) {
|
||||||
|
if (id === "unknown") {
|
||||||
|
return undefined;
|
||||||
|
} else if (id === "known") {
|
||||||
|
return {
|
||||||
|
username: "abc",
|
||||||
|
password: "123"
|
||||||
|
}
|
||||||
|
} else if (id === "known2") {
|
||||||
|
return {
|
||||||
|
username: "abc",
|
||||||
|
password: ""
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getCredentialDefinition: function(type) {
|
||||||
|
if (type === "node") {
|
||||||
|
return {
|
||||||
|
username: {type:"text"},
|
||||||
|
password: {type:"password"}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
it("returns an empty object for an unknown node", function(done) {
|
||||||
|
flows.getNodeCredentials({id:"unknown", type:"node"}).then(function(result) {
|
||||||
|
result.should.eql({});
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
it("gets the filtered credentials for a known node with password", function(done) {
|
||||||
|
flows.getNodeCredentials({id:"known", type:"node"}).then(function(result) {
|
||||||
|
result.should.eql({
|
||||||
|
username: "abc",
|
||||||
|
has_password: true
|
||||||
|
});
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
it("gets the filtered credentials for a known node without password", function(done) {
|
||||||
|
flows.getNodeCredentials({id:"known2", type:"node"}).then(function(result) {
|
||||||
|
result.should.eql({
|
||||||
|
username: "abc",
|
||||||
|
has_password: false
|
||||||
|
});
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
it("gets the empty credentials for a known node without a registered definition", function(done) {
|
||||||
|
flows.getNodeCredentials({id:"known2", type:"unknown-type"}).then(function(result) {
|
||||||
|
result.should.eql({});
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
*/
|
|
||||||
|
@ -14,8 +14,168 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
var should = require("should");
|
||||||
|
var sinon = require("sinon");
|
||||||
|
|
||||||
|
var nodes = require("../../../red/runtime-api/nodes")
|
||||||
|
|
||||||
|
var mockLog = () => ({
|
||||||
|
log: sinon.stub(),
|
||||||
|
debug: sinon.stub(),
|
||||||
|
trace: sinon.stub(),
|
||||||
|
warn: sinon.stub(),
|
||||||
|
info: sinon.stub(),
|
||||||
|
metric: sinon.stub(),
|
||||||
|
audit: sinon.stub(),
|
||||||
|
_: function() { return "abc"}
|
||||||
|
})
|
||||||
|
|
||||||
describe("runtime-api/nodes", function() {
|
describe("runtime-api/nodes", function() {
|
||||||
it.skip('more tests needed', function(){})
|
describe("getNodeInfo", function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
nodes.init({
|
||||||
|
log: mockLog(),
|
||||||
|
nodes: {
|
||||||
|
getNodeInfo: function(id) {
|
||||||
|
if (id === "known") {
|
||||||
|
return {id:"known"};
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
it("returns node info", function(done) {
|
||||||
|
nodes.getNodeInfo({id:"known"}).then(function(result) {
|
||||||
|
result.should.eql({id:"known"});
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
it("returns 404 if node not known", function(done) {
|
||||||
|
nodes.getNodeInfo({id:"unknown"}).then(function(result) {
|
||||||
|
done(new Error("Did not return internal error"));
|
||||||
|
}).catch(function(err) {
|
||||||
|
err.should.have.property('code','not_found');
|
||||||
|
err.should.have.property('status',404);
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe("getNodeList", function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
nodes.init({
|
||||||
|
log: mockLog(),
|
||||||
|
nodes: {
|
||||||
|
getNodeList: function() {
|
||||||
|
return [1,2,3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
it("returns node list", function(done) {
|
||||||
|
nodes.getNodeList({}).then(function(result) {
|
||||||
|
result.should.eql([1,2,3]);
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getNodeConfig", function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
nodes.init({
|
||||||
|
log: mockLog(),
|
||||||
|
nodes: {
|
||||||
|
getNodeConfig: function(id,lang) {
|
||||||
|
if (id === "known") {
|
||||||
|
return id+lang;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
it("returns node config", function(done) {
|
||||||
|
nodes.getNodeConfig({id:"known",lang:'lang'}).then(function(result) {
|
||||||
|
result.should.eql("knownlang");
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
it("returns 404 if node not known", function(done) {
|
||||||
|
nodes.getNodeConfig({id:"unknown",lang:'lang'}).then(function(result) {
|
||||||
|
done(new Error("Did not return internal error"));
|
||||||
|
}).catch(function(err) {
|
||||||
|
err.should.have.property('code','not_found');
|
||||||
|
err.should.have.property('status',404);
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getNodeConfigs", function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
nodes.init({
|
||||||
|
log: mockLog(),
|
||||||
|
nodes: {
|
||||||
|
getNodeConfigs: function(lang) {
|
||||||
|
return lang;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
it("returns all node configs", function(done) {
|
||||||
|
nodes.getNodeConfigs({lang:'lang'}).then(function(result) {
|
||||||
|
result.should.eql("lang");
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getModuleInfo", function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
nodes.init({
|
||||||
|
log: mockLog(),
|
||||||
|
nodes: {
|
||||||
|
getModuleInfo: function(id) {
|
||||||
|
if (id === "known") {
|
||||||
|
return {module:"known"};
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
it("returns node info", function(done) {
|
||||||
|
nodes.getModuleInfo({module:"known"}).then(function(result) {
|
||||||
|
result.should.eql({module:"known"});
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
it("returns 404 if node not known", function(done) {
|
||||||
|
nodes.getModuleInfo({module:"unknown"}).then(function(result) {
|
||||||
|
done(new Error("Did not return internal error"));
|
||||||
|
}).catch(function(err) {
|
||||||
|
err.should.have.property('code','not_found');
|
||||||
|
err.should.have.property('status',404);
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe.skip("addModule", function() {});
|
||||||
|
describe.skip("removeModule", function() {});
|
||||||
|
describe.skip("setModuleState", function() {});
|
||||||
|
describe.skip("setNodeSetState", function() {});
|
||||||
|
|
||||||
|
describe.skip("getModuleCatalogs", function() {});
|
||||||
|
describe.skip("getModuleCatalog", function() {});
|
||||||
|
|
||||||
|
describe.skip("getIconList", function() {});
|
||||||
|
describe.skip("getIcon", function() {});
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -14,9 +14,36 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
var should = require("should");
|
||||||
|
var sinon = require("sinon");
|
||||||
|
|
||||||
|
var settings = require("../../../red/runtime-api/settings")
|
||||||
|
|
||||||
|
var mockLog = () => ({
|
||||||
|
log: sinon.stub(),
|
||||||
|
debug: sinon.stub(),
|
||||||
|
trace: sinon.stub(),
|
||||||
|
warn: sinon.stub(),
|
||||||
|
info: sinon.stub(),
|
||||||
|
metric: sinon.stub(),
|
||||||
|
audit: sinon.stub(),
|
||||||
|
_: function() { return "abc"}
|
||||||
|
})
|
||||||
|
|
||||||
describe("runtime-api/settings", function() {
|
describe("runtime-api/settings", function() {
|
||||||
it.skip('more tests needed', function(){})
|
describe.skip("getRuntimeSettings", function() {});
|
||||||
|
describe.skip("getUserSettings", function() {});
|
||||||
|
describe.skip("updateUserSettings", function() {});
|
||||||
|
describe.skip("getUserKeys", function() {});
|
||||||
|
describe.skip("getUserKey", function() {});
|
||||||
|
describe.skip("generateUserKey", function() {});
|
||||||
|
describe.skip("removeUserKey", function() {});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
it('returns the filtered settings', function(done) {
|
it('returns the filtered settings', function(done) {
|
||||||
info.init({
|
info.init({
|
||||||
|
Loading…
Reference in New Issue
Block a user