mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Fixup all the tests
This commit is contained in:
parent
34832d5942
commit
5d064aa1d7
@ -15,6 +15,7 @@
|
|||||||
**/
|
**/
|
||||||
|
|
||||||
var runtimeAPI;
|
var runtimeAPI;
|
||||||
|
var apiUtils = require("../util");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
init: function(_runtimeAPI) {
|
init: function(_runtimeAPI) {
|
||||||
@ -23,7 +24,7 @@ module.exports = {
|
|||||||
get: function(req,res) {
|
get: function(req,res) {
|
||||||
var version = req.get("Node-RED-API-Version")||"v1";
|
var version = req.get("Node-RED-API-Version")||"v1";
|
||||||
if (!/^v[12]$/.test(version)) {
|
if (!/^v[12]$/.test(version)) {
|
||||||
return res.status(500).json({code:"invalid_api_version", message:"Invalid API Version requested"});
|
return res.status(400).json({code:"invalid_api_version", message:"Invalid API Version requested"});
|
||||||
}
|
}
|
||||||
var opts = {
|
var opts = {
|
||||||
user: req.user
|
user: req.user
|
||||||
@ -41,7 +42,7 @@ module.exports = {
|
|||||||
post: function(req,res) {
|
post: function(req,res) {
|
||||||
var version = req.get("Node-RED-API-Version")||"v1";
|
var version = req.get("Node-RED-API-Version")||"v1";
|
||||||
if (!/^v[12]$/.test(version)) {
|
if (!/^v[12]$/.test(version)) {
|
||||||
return res.status(500).json({code:"invalid_api_version", message:"Invalid API Version requested"});
|
return res.status(400).json({code:"invalid_api_version", message:"Invalid API Version requested"});
|
||||||
}
|
}
|
||||||
var opts = {
|
var opts = {
|
||||||
user: req.user,
|
user: req.user,
|
||||||
|
@ -56,7 +56,7 @@ module.exports = {
|
|||||||
user: req.user,
|
user: req.user,
|
||||||
module: req.params[0]
|
module: req.params[0]
|
||||||
}
|
}
|
||||||
runtimeAPI.nodes.removeModule(opts).then(function(info) {
|
runtimeAPI.nodes.removeModule(opts).then(function() {
|
||||||
res.status(204).end();
|
res.status(204).end();
|
||||||
}).catch(function(err) {
|
}).catch(function(err) {
|
||||||
apiUtils.rejectHandler(req,res,err);
|
apiUtils.rejectHandler(req,res,err);
|
||||||
@ -77,7 +77,7 @@ module.exports = {
|
|||||||
} else {
|
} else {
|
||||||
opts.lang = apiUtils.determineLangFromHeaders(req.acceptsLanguages());
|
opts.lang = apiUtils.determineLangFromHeaders(req.acceptsLanguages());
|
||||||
runtimeAPI.nodes.getNodeConfig(opts).then(function(result) {
|
runtimeAPI.nodes.getNodeConfig(opts).then(function(result) {
|
||||||
return res.json(result);
|
return res.send(result);
|
||||||
}).catch(function(err) {
|
}).catch(function(err) {
|
||||||
apiUtils.rejectHandler(req,res,err);
|
apiUtils.rejectHandler(req,res,err);
|
||||||
})
|
})
|
||||||
@ -100,7 +100,7 @@ module.exports = {
|
|||||||
var body = req.body;
|
var body = req.body;
|
||||||
if (!body.hasOwnProperty("enabled")) {
|
if (!body.hasOwnProperty("enabled")) {
|
||||||
// log.audit({event: "nodes.module.set",error:"invalid_request"},req);
|
// log.audit({event: "nodes.module.set",error:"invalid_request"},req);
|
||||||
res.status(400).json({error:"invalid_request", message:"Invalid request"});
|
res.status(400).json({code:"invalid_request", message:"Invalid request"});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var opts = {
|
var opts = {
|
||||||
@ -119,7 +119,7 @@ module.exports = {
|
|||||||
var body = req.body;
|
var body = req.body;
|
||||||
if (!body.hasOwnProperty("enabled")) {
|
if (!body.hasOwnProperty("enabled")) {
|
||||||
// log.audit({event: "nodes.module.set",error:"invalid_request"},req);
|
// log.audit({event: "nodes.module.set",error:"invalid_request"},req);
|
||||||
res.status(400).json({error:"invalid_request", message:"Invalid request"});
|
res.status(400).json({code:"invalid_request", message:"Invalid request"});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var opts = {
|
var opts = {
|
||||||
|
@ -28,6 +28,8 @@ var runtimeAPI;
|
|||||||
var wsServer;
|
var wsServer;
|
||||||
var activeConnections = [];
|
var activeConnections = [];
|
||||||
|
|
||||||
|
var anonymousUser;
|
||||||
|
|
||||||
var retained = {};
|
var retained = {};
|
||||||
|
|
||||||
var heartbeatTimer;
|
var heartbeatTimer;
|
||||||
@ -173,7 +175,8 @@ CommsConnection.prototype.subscribe = function(topic) {
|
|||||||
|
|
||||||
function start() {
|
function start() {
|
||||||
if (!settings.disableEditor) {
|
if (!settings.disableEditor) {
|
||||||
Users.default().then(function(anonymousUser) {
|
Users.default().then(function(_anonymousUser) {
|
||||||
|
anonymousUser = _anonymousUser;
|
||||||
var webSocketKeepAliveTime = settings.webSocketKeepAliveTime || 15000;
|
var webSocketKeepAliveTime = settings.webSocketKeepAliveTime || 15000;
|
||||||
var path = settings.httpAdminRoot || "/";
|
var path = settings.httpAdminRoot || "/";
|
||||||
path = (path.slice(0,1) != "/" ? "/":"") + path + (path.slice(-1) == "/" ? "":"/") + "comms";
|
path = (path.slice(0,1) != "/" ? "/":"") + path + (path.slice(-1) == "/" ? "":"/") + "comms";
|
||||||
|
@ -89,7 +89,6 @@ module.exports = {
|
|||||||
// Library
|
// Library
|
||||||
var library = require("./library");
|
var library = require("./library");
|
||||||
library.init(runtimeAPI);
|
library.init(runtimeAPI);
|
||||||
|
|
||||||
editorApp.get("/library/flows",needsPermission("library.read"),library.getAll,apiUtil.errorHandler);
|
editorApp.get("/library/flows",needsPermission("library.read"),library.getAll,apiUtil.errorHandler);
|
||||||
editorApp.get(/library\/([^\/]+)(?:$|\/(.*))/,needsPermission("library.read"),library.getEntry);
|
editorApp.get(/library\/([^\/]+)(?:$|\/(.*))/,needsPermission("library.read"),library.getEntry);
|
||||||
editorApp.post(/library\/([^\/]+)\/(.*)/,needsPermission("library.write"),library.saveEntry);
|
editorApp.post(/library\/([^\/]+)\/(.*)/,needsPermission("library.write"),library.saveEntry);
|
||||||
@ -107,7 +106,7 @@ module.exports = {
|
|||||||
// User Settings
|
// User Settings
|
||||||
editorApp.post("/settings/user",needsPermission("settings.write"),info.updateUserSettings,apiUtil.errorHandler);
|
editorApp.post("/settings/user",needsPermission("settings.write"),info.updateUserSettings,apiUtil.errorHandler);
|
||||||
// SSH keys
|
// SSH keys
|
||||||
editorApp.use("/settings/user/keys",info.sshkeys());
|
editorApp.use("/settings/user/keys",needsPermission("settings.write"),info.sshkeys());
|
||||||
|
|
||||||
return editorApp;
|
return editorApp;
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
var apiUtils = require("../util");
|
||||||
var express = require("express");
|
var express = require("express");
|
||||||
var runtimeAPI;
|
var runtimeAPI;
|
||||||
var needsPermission = require("../auth").needsPermission;
|
|
||||||
|
|
||||||
function getUsername(userObj) {
|
function getUsername(userObj) {
|
||||||
var username = '__default';
|
var username = '__default';
|
||||||
@ -34,7 +34,7 @@ module.exports = {
|
|||||||
var app = express();
|
var app = express();
|
||||||
|
|
||||||
// List all SSH keys
|
// List all SSH keys
|
||||||
app.get("/", needsPermission("settings.read"), function(req,res) {
|
app.get("/", function(req,res) {
|
||||||
var opts = {
|
var opts = {
|
||||||
user: req.user
|
user: req.user
|
||||||
}
|
}
|
||||||
@ -48,7 +48,7 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Get SSH key detail
|
// Get SSH key detail
|
||||||
app.get("/:id", needsPermission("settings.read"), function(req,res) {
|
app.get("/:id", function(req,res) {
|
||||||
var opts = {
|
var opts = {
|
||||||
user: req.user,
|
user: req.user,
|
||||||
id: req.params.id
|
id: req.params.id
|
||||||
@ -63,11 +63,17 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Generate a SSH key
|
// Generate a SSH key
|
||||||
app.post("/", needsPermission("settings.write"), function(req,res) {
|
app.post("/", function(req,res) {
|
||||||
var opts = {
|
var opts = {
|
||||||
user: req.user,
|
user: req.user,
|
||||||
id: req.params.id
|
id: req.params.id
|
||||||
}
|
}
|
||||||
|
// TODO: validate params
|
||||||
|
opts.name = req.body.name;
|
||||||
|
opts.password = req.body.password;
|
||||||
|
opts.comment = req.body.comment;
|
||||||
|
opts.size = req.body.size;
|
||||||
|
|
||||||
runtimeAPI.settings.generateUserKey(opts).then(function(name) {
|
runtimeAPI.settings.generateUserKey(opts).then(function(name) {
|
||||||
res.json({
|
res.json({
|
||||||
name: name
|
name: name
|
||||||
@ -78,12 +84,12 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Delete a SSH key
|
// Delete a SSH key
|
||||||
app.delete("/:id", needsPermission("settings.write"), function(req,res) {
|
app.delete("/:id", function(req,res) {
|
||||||
var opts = {
|
var opts = {
|
||||||
user: req.user,
|
user: req.user,
|
||||||
id: req.params.id
|
id: req.params.id
|
||||||
}
|
}
|
||||||
runtimeAPI.settings.generateUserKey(opts).then(function(name) {
|
runtimeAPI.settings.removeUserKey(opts).then(function(name) {
|
||||||
res.status(204).end();
|
res.status(204).end();
|
||||||
}).catch(function(err) {
|
}).catch(function(err) {
|
||||||
apiUtils.rejectHandler(req,res,err);
|
apiUtils.rejectHandler(req,res,err);
|
||||||
|
@ -89,23 +89,9 @@ module.exports = {
|
|||||||
init: init,
|
init: init,
|
||||||
start: start,
|
start: start,
|
||||||
stop: stop,
|
stop: stop,
|
||||||
library: {
|
|
||||||
register: function(type) {
|
|
||||||
if (editor) {
|
|
||||||
editor.registerLibrary(type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
auth: {
|
auth: {
|
||||||
needsPermission: auth.needsPermission
|
needsPermission: auth.needsPermission
|
||||||
},
|
},
|
||||||
comms: {
|
|
||||||
publish: function(topic,data,retain) {
|
|
||||||
if (editor) {
|
|
||||||
editor.publish(topic,data,retain);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
get adminApp() { return adminApp; },
|
get adminApp() { return adminApp; },
|
||||||
get server() { return server; }
|
get server() { return server; }
|
||||||
};
|
};
|
||||||
|
@ -21,7 +21,6 @@ var i18n = require("../util").i18n; // TODO: separate module
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
errorHandler: function(err,req,res,next) {
|
errorHandler: function(err,req,res,next) {
|
||||||
console.error(err.stack);
|
|
||||||
if (err.message === "request entity too large") {
|
if (err.message === "request entity too large") {
|
||||||
log.error(err);
|
log.error(err);
|
||||||
} else {
|
} else {
|
||||||
@ -40,13 +39,9 @@ module.exports = {
|
|||||||
return lang;
|
return lang;
|
||||||
},
|
},
|
||||||
rejectHandler: function(req,res,err) {
|
rejectHandler: function(req,res,err) {
|
||||||
res.status(err.status||500);
|
res.status(err.status||500).json({
|
||||||
if (err.code || err.message) {
|
|
||||||
res.json({
|
|
||||||
code: err.code||"unexpected_error",
|
code: err.code||"unexpected_error",
|
||||||
message: err.message
|
message: err.message||err.toString()
|
||||||
})
|
});
|
||||||
}
|
|
||||||
res.end();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
17
red/red.js
17
red/red.js
@ -111,9 +111,20 @@ module.exports = {
|
|||||||
util: runtime.util,
|
util: runtime.util,
|
||||||
version: runtime.version,
|
version: runtime.version,
|
||||||
events: runtime.events,
|
events: runtime.events,
|
||||||
|
comms: {
|
||||||
comms: api.comms,
|
publish: function(topic,data,retain) {
|
||||||
library: api.library,
|
runtime.events.emit("comms",{
|
||||||
|
topic: topic,
|
||||||
|
data: data,
|
||||||
|
retain: retain
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
library: {
|
||||||
|
register: function(type) {
|
||||||
|
return runtime.library.register(null,type);
|
||||||
|
}
|
||||||
|
},
|
||||||
auth: api.auth,
|
auth: api.auth,
|
||||||
|
|
||||||
get app() { console.log("Deprecated use of RED.app - use RED.httpAdmin instead"); return runtime.app },
|
get app() { console.log("Deprecated use of RED.app - use RED.httpAdmin instead"); return runtime.app },
|
||||||
|
@ -49,13 +49,15 @@ function publish(topic,data,retain) {
|
|||||||
} else {
|
} else {
|
||||||
delete retained[topic];
|
delete retained[topic];
|
||||||
}
|
}
|
||||||
connections.forEach(connection => connection.send(topic,data,retain))
|
connections.forEach(connection => connection.send(topic,data))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var api = module.exports = {
|
var api = module.exports = {
|
||||||
init: function(_runtime) {
|
init: function(_runtime) {
|
||||||
runtime = _runtime;
|
runtime = _runtime;
|
||||||
|
connections = [];
|
||||||
|
retained = {};
|
||||||
runtime.events.removeListener("node-status",handleStatusEvent);
|
runtime.events.removeListener("node-status",handleStatusEvent);
|
||||||
runtime.events.on("node-status",handleStatusEvent);
|
runtime.events.on("node-status",handleStatusEvent);
|
||||||
runtime.events.removeListener("runtime-event",handleRuntimeEvent);
|
runtime.events.removeListener("runtime-event",handleRuntimeEvent);
|
||||||
|
@ -135,6 +135,7 @@ var api = module.exports = {
|
|||||||
} else {
|
} else {
|
||||||
runtime.log.audit({event: "flow.get",id:opts.id,error:"not_found"});
|
runtime.log.audit({event: "flow.get",id:opts.id,error:"not_found"});
|
||||||
var err = new Error();
|
var err = new Error();
|
||||||
|
err.code = "not_found";
|
||||||
err.status = 404;
|
err.status = 404;
|
||||||
return reject(err);
|
return reject(err);
|
||||||
}
|
}
|
||||||
|
@ -42,9 +42,6 @@ var stubbedExpressApp = {
|
|||||||
delete: function() {}
|
delete: function() {}
|
||||||
}
|
}
|
||||||
var adminApi = {
|
var adminApi = {
|
||||||
library: {
|
|
||||||
register: function() {}
|
|
||||||
},
|
|
||||||
auth: {
|
auth: {
|
||||||
needsPermission: function() {}
|
needsPermission: function() {}
|
||||||
},
|
},
|
||||||
|
@ -29,17 +29,20 @@ function init(_runtime) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function registerType(id,type) {
|
function registerType(id,type) {
|
||||||
if (knownTypes.hasOwnProperty(type)) {
|
// TODO: would like to enforce this, but currently the tests register the same type multiple
|
||||||
throw new Error(`Library type '${type}' already registerd by ${id}'`)
|
// times and have no way to remove themselves.
|
||||||
}
|
// if (knownTypes.hasOwnProperty(type)) {
|
||||||
|
// throw new Error(`Library type '${type}' already registered by ${id}'`)
|
||||||
|
// }
|
||||||
knownTypes[type] = id;
|
knownTypes[type] = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAllEntries(type) {
|
// function getAllEntries(type) {
|
||||||
if (!knownTypes.hasOwnProperty(type)) {
|
// if (!knownTypes.hasOwnProperty(type)) {
|
||||||
throw new Error(`Unknown library type '${type}'`);
|
// throw new Error(`Unknown library type '${type}'`);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
function getEntry(type,path) {
|
function getEntry(type,path) {
|
||||||
if (type !== 'flows') {
|
if (type !== 'flows') {
|
||||||
if (!knownTypes.hasOwnProperty(type)) {
|
if (!knownTypes.hasOwnProperty(type)) {
|
||||||
@ -67,12 +70,11 @@ function getEntry(type,path) {
|
|||||||
return reject(err);
|
return reject(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
// IF we get here, we didn't find the file
|
// IF we get here, we didn't find the file
|
||||||
var error = new Error("not_found");
|
var error = new Error("not_found");
|
||||||
error.code = "not_found";
|
error.code = "not_found";
|
||||||
return reject(error);
|
return reject(error);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
resolve(storage.getFlow(path));
|
resolve(storage.getFlow(path));
|
||||||
}
|
}
|
||||||
@ -92,8 +94,8 @@ function saveEntry(type,path,meta,body) {
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
init: init,
|
init: init,
|
||||||
registerType: registerType,
|
register: registerType,
|
||||||
getAllEntries: getAllEntries,
|
// getAllEntries: getAllEntries,
|
||||||
getEntry: getEntry,
|
getEntry: getEntry,
|
||||||
saveEntry: saveEntry
|
saveEntry: saveEntry
|
||||||
|
|
||||||
|
@ -79,6 +79,11 @@ function createNodeApi(node) {
|
|||||||
retain: retain
|
retain: retain
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
library: {
|
||||||
|
register: function(type) {
|
||||||
|
return runtime.library.register(node.id,type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
copyObjectProperties(runtime.nodes,red.nodes,["createNode","getNode","eachNode","addCredentials","getCredentials","deleteCredentials" ]);
|
copyObjectProperties(runtime.nodes,red.nodes,["createNode","getNode","eachNode","addCredentials","getCredentials","deleteCredentials" ]);
|
||||||
@ -88,11 +93,6 @@ function createNodeApi(node) {
|
|||||||
copyObjectProperties(runtime.log,red.log,null,["init"]);
|
copyObjectProperties(runtime.log,red.log,null,["init"]);
|
||||||
copyObjectProperties(runtime.settings,red.settings,null,["init","load","reset"]);
|
copyObjectProperties(runtime.settings,red.settings,null,["init","load","reset"]);
|
||||||
if (runtime.adminApi) {
|
if (runtime.adminApi) {
|
||||||
red.library = {
|
|
||||||
register: function(type) {
|
|
||||||
return runtime.library.registerType(node.id,type);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
red.auth = runtime.adminApi.auth;
|
red.auth = runtime.adminApi.auth;
|
||||||
red.httpAdmin = runtime.adminApi.adminApp;
|
red.httpAdmin = runtime.adminApi.adminApp;
|
||||||
red.httpNode = runtime.nodeApp;
|
red.httpNode = runtime.nodeApp;
|
||||||
@ -100,12 +100,6 @@ function createNodeApi(node) {
|
|||||||
} else {
|
} else {
|
||||||
//TODO: runtime.adminApi is always stubbed if not enabled, so this block
|
//TODO: runtime.adminApi is always stubbed if not enabled, so this block
|
||||||
// is unused - but may be needed for the unit tests
|
// is unused - but may be needed for the unit tests
|
||||||
red.comms = {
|
|
||||||
publish: function() {}
|
|
||||||
};
|
|
||||||
red.library = {
|
|
||||||
register: function() {}
|
|
||||||
};
|
|
||||||
red.auth = {
|
red.auth = {
|
||||||
needsPermission: function() {}
|
needsPermission: function() {}
|
||||||
};
|
};
|
||||||
|
@ -35,7 +35,7 @@ var redNodes = require("../../red/runtime/nodes");
|
|||||||
var flows = require("../../red/runtime/nodes/flows");
|
var flows = require("../../red/runtime/nodes/flows");
|
||||||
var credentials = require("../../red/runtime/nodes/credentials");
|
var credentials = require("../../red/runtime/nodes/credentials");
|
||||||
var comms = require("../../red/api/editor/comms.js");
|
var comms = require("../../red/api/editor/comms.js");
|
||||||
var log = require("../../red/runtime/log.js");
|
var log = require("../../red/util/log.js");
|
||||||
var context = require("../../red/runtime/nodes/context.js");
|
var context = require("../../red/runtime/nodes/context.js");
|
||||||
var events = require("../../red/runtime/events.js");
|
var events = require("../../red/runtime/events.js");
|
||||||
|
|
||||||
|
@ -38,18 +38,23 @@ describe("api/admin/flow", function() {
|
|||||||
|
|
||||||
describe("get", function() {
|
describe("get", function() {
|
||||||
before(function() {
|
before(function() {
|
||||||
|
var opts;
|
||||||
flow.init({
|
flow.init({
|
||||||
settings:{},
|
flows: {
|
||||||
nodes: {
|
getFlow: function(_opts) {
|
||||||
getFlow: function(id) {
|
opts = _opts;
|
||||||
if (id === '123') {
|
if (opts.id === '123') {
|
||||||
return {id:'123'}
|
return Promise.resolve({id:'123'});
|
||||||
} else {
|
} 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) {
|
it('gets a known flow', function(done) {
|
||||||
@ -75,19 +80,24 @@ describe("api/admin/flow", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("add", function() {
|
describe("add", function() {
|
||||||
|
var opts;
|
||||||
before(function() {
|
before(function() {
|
||||||
flow.init({
|
flow.init({
|
||||||
settings:{},
|
flows: {
|
||||||
nodes: {
|
addFlow: function(_opts) {
|
||||||
addFlow: function(f) {
|
opts = _opts;
|
||||||
if (f.id === "123") {
|
if (opts.flow.id === "123") {
|
||||||
return when.resolve('123')
|
return Promise.resolve('123')
|
||||||
} else {
|
} 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) {
|
it('adds a new flow', function(done) {
|
||||||
@ -114,8 +124,8 @@ describe("api/admin/flow", function() {
|
|||||||
if (err) {
|
if (err) {
|
||||||
return done(err);
|
return done(err);
|
||||||
}
|
}
|
||||||
res.body.should.has.a.property('error','unexpected_error');
|
res.body.should.has.a.property('code','random_error');
|
||||||
res.body.should.has.a.property('message','Error: test error');
|
res.body.should.has.a.property('message','random error');
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -123,35 +133,29 @@ describe("api/admin/flow", function() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe("update", function() {
|
describe("update", function() {
|
||||||
var nodes;
|
|
||||||
|
var opts;
|
||||||
before(function() {
|
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({
|
flow.init({
|
||||||
settings:{},
|
flows: {
|
||||||
nodes: nodes,
|
updateFlow: function(_opts) {
|
||||||
log:{ audit: sinon.stub() }
|
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) {
|
it('updates an existing flow', function(done) {
|
||||||
sinon.spy(nodes,"updateFlow");
|
|
||||||
request(app)
|
request(app)
|
||||||
.put('/flow/123')
|
.put('/flow/123')
|
||||||
.set('Accept', 'application/json')
|
.set('Accept', 'application/json')
|
||||||
@ -162,115 +166,79 @@ describe("api/admin/flow", function() {
|
|||||||
return done(err);
|
return done(err);
|
||||||
}
|
}
|
||||||
res.body.should.has.a.property('id','123');
|
res.body.should.has.a.property('id','123');
|
||||||
nodes.updateFlow.calledOnce.should.be.true();
|
opts.should.have.property('id','123');
|
||||||
nodes.updateFlow.lastCall.args[0].should.eql('123');
|
opts.should.have.property('flow',{id:'123'})
|
||||||
nodes.updateFlow.lastCall.args[1].should.eql({id:'123'});
|
|
||||||
nodes.updateFlow.restore();
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
it('404s on an unknown flow', function(done) {
|
it('400 an invalid flow', function(done) {
|
||||||
request(app)
|
request(app)
|
||||||
.put('/flow/unknown')
|
.put('/flow/456')
|
||||||
.set('Accept', 'application/json')
|
.set('Accept', 'application/json')
|
||||||
.send({id:'123'})
|
.send({id:'456'})
|
||||||
.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'})
|
|
||||||
.expect(400)
|
.expect(400)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return done(err);
|
return done(err);
|
||||||
}
|
}
|
||||||
res.body.should.has.a.property('error','unexpected_error');
|
res.body.should.has.a.property('code','random_error');
|
||||||
res.body.should.has.a.property('message','Error: test error');
|
res.body.should.has.a.property('message','random error');
|
||||||
done();
|
|
||||||
});
|
|
||||||
})
|
|
||||||
|
|
||||||
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();
|
done();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("delete", function() {
|
describe("delete", function() {
|
||||||
var nodes;
|
|
||||||
|
var opts;
|
||||||
before(function() {
|
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({
|
flow.init({
|
||||||
settings:{},
|
flows: {
|
||||||
nodes: nodes,
|
deleteFlow: function(_opts) {
|
||||||
log:{ audit: sinon.stub() }
|
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('updates an existing flow', function(done) {
|
it('deletes an existing flow', function(done) {
|
||||||
sinon.spy(nodes,"removeFlow");
|
|
||||||
request(app)
|
request(app)
|
||||||
.delete('/flow/123')
|
.del('/flow/123')
|
||||||
|
.set('Accept', 'application/json')
|
||||||
.expect(204)
|
.expect(204)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return done(err);
|
return done(err);
|
||||||
}
|
}
|
||||||
nodes.removeFlow.calledOnce.should.be.true();
|
opts.should.have.property('id','123');
|
||||||
nodes.removeFlow.lastCall.args[0].should.eql('123');
|
|
||||||
nodes.removeFlow.restore();
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
it('404s on an unknown flow', function(done) {
|
it('400 an invalid flow', function(done) {
|
||||||
request(app)
|
request(app)
|
||||||
.delete('/flow/unknown')
|
.del('/flow/456')
|
||||||
.expect(404)
|
.set('Accept', 'application/json')
|
||||||
.end(done);
|
|
||||||
})
|
|
||||||
|
|
||||||
it('400 on remove error', function(done) {
|
|
||||||
request(app)
|
|
||||||
.delete('/flow/unexpected')
|
|
||||||
.expect(400)
|
.expect(400)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return done(err);
|
return done(err);
|
||||||
}
|
}
|
||||||
res.body.should.has.a.property('error',500);
|
res.body.should.has.a.property('code','random_error');
|
||||||
res.body.should.has.a.property('message','Error');
|
res.body.should.has.a.property('message','random error');
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -19,7 +19,6 @@ var request = require('supertest');
|
|||||||
var express = require('express');
|
var express = require('express');
|
||||||
var bodyParser = require('body-parser');
|
var bodyParser = require('body-parser');
|
||||||
var sinon = require('sinon');
|
var sinon = require('sinon');
|
||||||
var when = require('when');
|
|
||||||
|
|
||||||
var flows = require("../../../../red/api/admin/flows");
|
var flows = require("../../../../red/api/admin/flows");
|
||||||
|
|
||||||
@ -36,10 +35,8 @@ describe("api/admin/flows", function() {
|
|||||||
|
|
||||||
it('returns flow - v1', function(done) {
|
it('returns flow - v1', function(done) {
|
||||||
flows.init({
|
flows.init({
|
||||||
settings: {},
|
flows:{
|
||||||
log:{warn:function(){},_:function(){},audit:function(){}},
|
getFlows: function() { return Promise.resolve({rev:"123",flows:[1,2,3]}); }
|
||||||
nodes:{
|
|
||||||
getFlows: function() { return {rev:"123",flows:[1,2,3]}; }
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
request(app)
|
request(app)
|
||||||
@ -60,10 +57,8 @@ describe("api/admin/flows", function() {
|
|||||||
});
|
});
|
||||||
it('returns flow - v2', function(done) {
|
it('returns flow - v2', function(done) {
|
||||||
flows.init({
|
flows.init({
|
||||||
settings: {},
|
flows:{
|
||||||
log:{warn:function(){},_:function(){},audit:function(){}},
|
getFlows: function() { return Promise.resolve({rev:"123",flows:[1,2,3]}); }
|
||||||
nodes:{
|
|
||||||
getFlows: function() { return {rev:"123",flows:[1,2,3]}; }
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
request(app)
|
request(app)
|
||||||
@ -104,10 +99,9 @@ describe("api/admin/flows", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('sets flows - default - v1', function(done) {
|
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({
|
flows.init({
|
||||||
log:{warn:function(){},_:function(){},audit:function(){}},
|
flows:{
|
||||||
nodes:{
|
|
||||||
setFlows: setFlows
|
setFlows: setFlows
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -120,15 +114,14 @@ describe("api/admin/flows", function() {
|
|||||||
return done(err);
|
return done(err);
|
||||||
}
|
}
|
||||||
setFlows.calledOnce.should.be.true();
|
setFlows.calledOnce.should.be.true();
|
||||||
setFlows.lastCall.args[1].should.eql('full');
|
setFlows.lastCall.args[0].should.have.property('deploymentType','full');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('sets flows - non-default - v1', function(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({
|
flows.init({
|
||||||
log:{warn:function(){},_:function(){},audit:function(){}},
|
flows:{
|
||||||
nodes:{
|
|
||||||
setFlows: setFlows
|
setFlows: setFlows
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -142,19 +135,22 @@ describe("api/admin/flows", function() {
|
|||||||
return done(err);
|
return done(err);
|
||||||
}
|
}
|
||||||
setFlows.calledOnce.should.be.true();
|
setFlows.calledOnce.should.be.true();
|
||||||
setFlows.lastCall.args[1].should.eql('nodes');
|
setFlows.lastCall.args[0].should.have.property('deploymentType','nodes');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('set flows - rejects mismatched revision - v2', function(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({
|
flows.init({
|
||||||
log:{warn:function(){},_:function(){},audit:function(){}},
|
flows:{
|
||||||
nodes:{
|
setFlows: function() {
|
||||||
setFlows: setFlows,
|
var err = new Error("mismatch");
|
||||||
getFlows: getFlows
|
err.code = "version_mismatch";
|
||||||
|
err.status = 409;
|
||||||
|
var p = Promise.reject(err);
|
||||||
|
p.catch(()=>{});
|
||||||
|
return p;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
request(app)
|
request(app)
|
||||||
@ -171,54 +167,6 @@ describe("api/admin/flows", function() {
|
|||||||
done();
|
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) {
|
it('sets flow - bad version', function(done) {
|
||||||
request(app)
|
request(app)
|
||||||
.post('/flows')
|
.post('/flows')
|
||||||
@ -238,11 +186,10 @@ describe("api/admin/flows", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('reloads flows', function(done) {
|
it('reloads flows', function(done) {
|
||||||
var loadFlows = sinon.spy(function() { return when.resolve(); });
|
var setFlows = sinon.spy(function() { return Promise.resolve();});
|
||||||
flows.init({
|
flows.init({
|
||||||
log:{warn:function(){},_:function(){},audit:function(){}},
|
flows:{
|
||||||
nodes:{
|
setFlows: setFlows
|
||||||
loadFlows: loadFlows
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
request(app)
|
request(app)
|
||||||
@ -254,29 +201,9 @@ describe("api/admin/flows", function() {
|
|||||||
if (err) {
|
if (err) {
|
||||||
return done(err);
|
return done(err);
|
||||||
}
|
}
|
||||||
loadFlows.called.should.be.true();
|
setFlows.called.should.be.true();
|
||||||
|
setFlows.lastCall.args[0].should.not.have.property('flows');
|
||||||
done();
|
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();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -27,31 +27,17 @@ var apiUtil = require("../../../../red/api/util");
|
|||||||
describe("api/admin/nodes", function() {
|
describe("api/admin/nodes", function() {
|
||||||
|
|
||||||
var app;
|
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() {
|
before(function() {
|
||||||
app = express();
|
app = express();
|
||||||
app.use(bodyParser.json());
|
app.use(bodyParser.json());
|
||||||
app.get("/nodes",nodes.getAll);
|
app.get("/nodes",nodes.getAll);
|
||||||
app.post("/nodes",nodes.post);
|
app.post("/nodes",nodes.post);
|
||||||
app.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,nodes.getModule);
|
app.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,nodes.getModule);
|
||||||
app.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,nodes.getSet);
|
|
||||||
app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,nodes.putModule);
|
app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,nodes.putModule);
|
||||||
|
app.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,nodes.getSet);
|
||||||
app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,nodes.putSet);
|
app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,nodes.putSet);
|
||||||
app.get("/getIcons",nodes.getIcons);
|
app.get("/getIcons",nodes.getIcons);
|
||||||
app.delete("/nodes/:id",nodes.delete);
|
app.delete(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,nodes.delete);
|
||||||
sinon.stub(apiUtil,"determineLangFromHeaders", function() {
|
sinon.stub(apiUtil,"determineLangFromHeaders", function() {
|
||||||
return "en-US";
|
return "en-US";
|
||||||
});
|
});
|
||||||
@ -62,10 +48,10 @@ describe("api/admin/nodes", function() {
|
|||||||
|
|
||||||
describe('get nodes', function() {
|
describe('get nodes', function() {
|
||||||
it('returns node list', function(done) {
|
it('returns node list', function(done) {
|
||||||
initNodes({
|
nodes.init({
|
||||||
nodes:{
|
nodes:{
|
||||||
getNodeList: function() {
|
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) {
|
it('returns node configs', function(done) {
|
||||||
initNodes({
|
nodes.init({
|
||||||
nodes:{
|
nodes:{
|
||||||
getNodeConfigs: function() {
|
getNodeConfigs: function() {
|
||||||
return "<script></script>";
|
return Promise.resolve("<script></script>");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
i18n: {
|
i18n: {
|
||||||
@ -108,10 +94,10 @@ describe("api/admin/nodes", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('returns node module info', function(done) {
|
it('returns node module info', function(done) {
|
||||||
initNodes({
|
nodes.init({
|
||||||
nodes:{
|
nodes:{
|
||||||
getModuleInfo: function(id) {
|
getModuleInfo: function(opts) {
|
||||||
return {"node-red":{name:"node-red"}}[id];
|
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) {
|
it('returns 404 for unknown module', function(done) {
|
||||||
initNodes({
|
nodes.init({
|
||||||
nodes:{
|
nodes:{
|
||||||
getModuleInfo: function(id) {
|
getModuleInfo: function(opts) {
|
||||||
return {"node-red":{name:"node-red"}}[id];
|
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) {
|
it('returns individual node info', function(done) {
|
||||||
initNodes({
|
nodes.init({
|
||||||
nodes:{
|
nodes:{
|
||||||
getNodeInfo: function(id) {
|
getNodeInfo: function(opts) {
|
||||||
return {"node-red/123":{id:"node-red/123"}}[id];
|
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) {
|
it('returns individual node configs', function(done) {
|
||||||
initNodes({
|
nodes.init({
|
||||||
nodes:{
|
nodes:{
|
||||||
getNodeConfig: function(id) {
|
getNodeConfig: function(opts) {
|
||||||
return {"node-red/123":"<script></script>"}[id];
|
return Promise.resolve({"node-red/123":"<script></script>"}[opts.id]);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
i18n: {
|
i18n: {
|
||||||
@ -190,12 +181,16 @@ describe("api/admin/nodes", function() {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns 404 for unknown node', function(done) {
|
it('returns 404 for unknown node', function(done) {
|
||||||
initNodes({
|
nodes.init({
|
||||||
nodes:{
|
nodes:{
|
||||||
getNodeInfo: function(id) {
|
getNodeInfo: function(opts) {
|
||||||
return {"node-red/123":{id:"node-red/123"}}[id];
|
var errInstance = new Error("Not Found");
|
||||||
|
errInstance.code = "not_found";
|
||||||
|
errInstance.status = 404;
|
||||||
|
var p = Promise.reject(errInstance);
|
||||||
|
p.catch(()=>{});
|
||||||
|
return p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -213,46 +208,13 @@ describe("api/admin/nodes", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('install', function() {
|
describe('install', function() {
|
||||||
|
|
||||||
it('returns 400 if settings are unavailable', function(done) {
|
|
||||||
initNodes({
|
|
||||||
settings:{available:function(){return false}}
|
|
||||||
});
|
|
||||||
request(app)
|
|
||||||
.post('/nodes')
|
|
||||||
.expect(400)
|
|
||||||
.end(function(err,res) {
|
|
||||||
if (err) {
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
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) {
|
it('installs the module and returns module info', function(done) {
|
||||||
initNodes({
|
var opts;
|
||||||
settings:{available:function(){return true}},
|
nodes.init({
|
||||||
nodes:{
|
nodes:{
|
||||||
getModuleInfo: function(id) { return null; },
|
addModule: function(_opts) {
|
||||||
installModule: function() {
|
opts = _opts;
|
||||||
return when.resolve({
|
return Promise.resolve({
|
||||||
name:"foo",
|
name:"foo",
|
||||||
nodes:[{id:"123"}]
|
nodes:[{id:"123"}]
|
||||||
});
|
});
|
||||||
@ -261,7 +223,7 @@ describe("api/admin/nodes", function() {
|
|||||||
});
|
});
|
||||||
request(app)
|
request(app)
|
||||||
.post('/nodes')
|
.post('/nodes')
|
||||||
.send({module: 'foo'})
|
.send({module: 'foo',version:"1.2.3"})
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -270,85 +232,72 @@ describe("api/admin/nodes", function() {
|
|||||||
res.body.should.have.property("name","foo");
|
res.body.should.have.property("name","foo");
|
||||||
res.body.should.have.property("nodes");
|
res.body.should.have.property("nodes");
|
||||||
res.body.nodes[0].should.have.property("id","123");
|
res.body.nodes[0].should.have.property("id","123");
|
||||||
|
opts.should.have.property("module","foo");
|
||||||
|
opts.should.have.property("version","1.2.3");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('returns error', function(done) {
|
||||||
it('fails the install if already installed', function(done) {
|
nodes.init({
|
||||||
initNodes({
|
|
||||||
settings:{available:function(){return true}},
|
|
||||||
nodes:{
|
nodes:{
|
||||||
getModuleInfo: function(id) { return {nodes:{id:"123"}}; },
|
addModule: function(opts) {
|
||||||
installModule: function() {
|
var errInstance = new Error("Message");
|
||||||
return when.resolve({id:"123"});
|
errInstance.code = "random_error";
|
||||||
|
errInstance.status = 400;
|
||||||
|
var p = Promise.reject(errInstance);
|
||||||
|
p.catch(()=>{});
|
||||||
|
return p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
request(app)
|
request(app)
|
||||||
.post('/nodes')
|
.post('/nodes')
|
||||||
.send({module: 'foo'})
|
.send({module: 'foo',version:"1.2.3"})
|
||||||
.expect(400)
|
.expect(400)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
res.body.should.have.a.property('code','random_error');
|
||||||
done();
|
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() {
|
describe('delete', function() {
|
||||||
it('returns 400 if settings are unavailable', function(done) {
|
it('uninstalls the module', function(done) {
|
||||||
initNodes({
|
var opts;
|
||||||
settings:{available:function(){return false}}
|
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)
|
request(app)
|
||||||
.del('/nodes/123')
|
.del('/nodes/123')
|
||||||
.expect(400)
|
.expect(400)
|
||||||
@ -356,94 +305,19 @@ describe("api/admin/nodes", function() {
|
|||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
res.body.should.have.a.property('code','random_error');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('by module', function() {
|
describe('enable/disable node set', function() {
|
||||||
it('uninstalls the module', function(done) {
|
it('returns 400 for invalid request payload', function(done) {
|
||||||
initNodes({
|
nodes.init({
|
||||||
settings:{available:function(){return true}},
|
|
||||||
nodes:{
|
nodes:{
|
||||||
getModuleInfo: function(id) { return {nodes:[{id:"123"}]} },
|
setNodeSetState: function(opts) {return Promise.resolve()}
|
||||||
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}}
|
|
||||||
});
|
|
||||||
request(app)
|
request(app)
|
||||||
.put('/nodes/node-red/foo')
|
.put('/nodes/node-red/foo')
|
||||||
.send({})
|
.send({})
|
||||||
@ -452,77 +326,23 @@ describe("api/admin/nodes", function() {
|
|||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
res.body.should.have.property("code","invalid_request");
|
||||||
res.body.should.have.property("message","Invalid request");
|
res.body.should.have.property("message","Invalid request");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns 400 for invalid module payload', function(done) {
|
it('sets node state and returns node info', function(done) {
|
||||||
initNodes({
|
var opts;
|
||||||
settings:{available:function(){return true}}
|
nodes.init({
|
||||||
});
|
|
||||||
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}},
|
|
||||||
nodes:{
|
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)
|
request(app)
|
||||||
.put('/nodes/node-red/foo')
|
.put('/nodes/node-red/foo')
|
||||||
.send({enabled:true})
|
.send({enabled:true})
|
||||||
@ -533,130 +353,41 @@ describe("api/admin/nodes", function() {
|
|||||||
}
|
}
|
||||||
res.body.should.have.property("id","123");
|
res.body.should.have.property("id","123");
|
||||||
res.body.should.have.property("enabled",true);
|
res.body.should.have.property("enabled",true);
|
||||||
|
opts.should.have.property("enabled",true);
|
||||||
|
opts.should.have.property("id","node-red/foo");
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
it('disables enabled node', function(done) {
|
describe('enable/disable module' ,function() {
|
||||||
initNodes({
|
it('returns 400 for invalid request payload', function(done) {
|
||||||
settings:{available:function(){return true}},
|
nodes.init({
|
||||||
nodes:{
|
nodes:{
|
||||||
getNodeInfo: function() { return {id:"123",enabled: true} },
|
setModuleState: function(opts) {return Promise.resolve()}
|
||||||
disableNode: function() { return when.resolve({id:"123",enabled: false,types:['a']}); }
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
request(app)
|
request(app)
|
||||||
.put('/nodes/node-red/foo')
|
.put('/nodes/node-red')
|
||||||
.send({enabled:false})
|
.send({})
|
||||||
.expect(200)
|
.expect(400)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
res.body.should.have.property("id","123");
|
res.body.should.have.property("code","invalid_request");
|
||||||
res.body.should.have.property("enabled",false);
|
res.body.should.have.property("message","Invalid request");
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('sets module state and returns module info', function(done) {
|
||||||
describe('no-ops if already in the right state', function() {
|
var opts;
|
||||||
function run(state,done) {
|
nodes.init({
|
||||||
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:{
|
nodes:{
|
||||||
getNodeInfo: function() { return {id:"123",enabled: state} },
|
setModuleState: function(_opts) {
|
||||||
enableNode: enableNode,
|
opts = _opts;
|
||||||
disableNode: disableNode
|
return Promise.resolve({name:"node-red"});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
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}},
|
|
||||||
nodes:{
|
|
||||||
getModuleInfo: function() { return {name:"node-red", nodes:[n1, n2]} },
|
|
||||||
enableNode: enableNode
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -669,154 +400,20 @@ describe("api/admin/nodes", function() {
|
|||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
res.body.should.have.property("name","node-red");
|
res.body.should.have.property("name","node-red");
|
||||||
res.body.should.have.property("nodes");
|
opts.should.have.property("enabled",true);
|
||||||
res.body.nodes[0].should.have.property("enabled",true);
|
opts.should.have.property("module","node-red");
|
||||||
res.body.nodes[1].should.have.property("enabled",true);
|
|
||||||
|
|
||||||
done();
|
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() {
|
describe('get icons', function() {
|
||||||
it('returns icon list', function(done) {
|
it('returns icon list', function(done) {
|
||||||
initNodes({
|
nodes.init({
|
||||||
nodes:{
|
nodes:{
|
||||||
getNodeIcons: function() {
|
getIconList: function() {
|
||||||
return {"module":["1.png","2.png","3.png"]};
|
return Promise.resolve({module:[1,2,3]});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -827,7 +424,6 @@ describe("api/admin/nodes", function() {
|
|||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
console.log(res.body);
|
|
||||||
res.body.should.have.property("module");
|
res.body.should.have.property("module");
|
||||||
res.body.module.should.be.an.Array();
|
res.body.module.should.be.an.Array();
|
||||||
res.body.module.should.have.lengthOf(3);
|
res.body.module.should.have.lengthOf(3);
|
||||||
|
@ -23,6 +23,7 @@ var passport = require("passport");
|
|||||||
var auth = require("../../../../red/api/auth");
|
var auth = require("../../../../red/api/auth");
|
||||||
var Users = require("../../../../red/api/auth/users");
|
var Users = require("../../../../red/api/auth/users");
|
||||||
var Tokens = require("../../../../red/api/auth/tokens");
|
var Tokens = require("../../../../red/api/auth/tokens");
|
||||||
|
var Permissions = require("../../../../red/api/auth/permissions");
|
||||||
|
|
||||||
describe("api/auth/index",function() {
|
describe("api/auth/index",function() {
|
||||||
|
|
||||||
@ -30,7 +31,7 @@ describe("api/auth/index",function() {
|
|||||||
|
|
||||||
describe("ensureClientSecret", function() {
|
describe("ensureClientSecret", function() {
|
||||||
before(function() {
|
before(function() {
|
||||||
auth.init({settings:{},log:{audit:function(){}}})
|
auth.init({},{})
|
||||||
});
|
});
|
||||||
it("leaves client_secret alone if not present",function(done) {
|
it("leaves client_secret alone if not present",function(done) {
|
||||||
var req = {
|
var req = {
|
||||||
@ -85,7 +86,7 @@ describe("api/auth/index",function() {
|
|||||||
Users.init.restore();
|
Users.init.restore();
|
||||||
});
|
});
|
||||||
it("returns login details - credentials", function(done) {
|
it("returns login details - credentials", function(done) {
|
||||||
auth.init({settings:{adminAuth:{type:"credentials"}},log:{audit:function(){}}})
|
auth.init({adminAuth:{type:"credentials"}},{})
|
||||||
auth.login(null,{json: function(resp) {
|
auth.login(null,{json: function(resp) {
|
||||||
resp.should.have.a.property("type","credentials");
|
resp.should.have.a.property("type","credentials");
|
||||||
resp.should.have.a.property("prompts");
|
resp.should.have.a.property("prompts");
|
||||||
@ -94,14 +95,14 @@ describe("api/auth/index",function() {
|
|||||||
}});
|
}});
|
||||||
});
|
});
|
||||||
it("returns login details - none", function(done) {
|
it("returns login details - none", function(done) {
|
||||||
auth.init({settings:{},log:{audit:function(){}}})
|
auth.init({},{})
|
||||||
auth.login(null,{json: function(resp) {
|
auth.login(null,{json: function(resp) {
|
||||||
resp.should.eql({});
|
resp.should.eql({});
|
||||||
done();
|
done();
|
||||||
}});
|
}});
|
||||||
});
|
});
|
||||||
it("returns login details - strategy", function(done) {
|
it("returns login details - strategy", function(done) {
|
||||||
auth.init({settings:{adminAuth:{type:"strategy",strategy:{label:"test-strategy",icon:"test-icon"}}},log:{audit:function(){}}})
|
auth.init({adminAuth:{type:"strategy",strategy:{label:"test-strategy",icon:"test-icon"}}},{})
|
||||||
auth.login(null,{json: function(resp) {
|
auth.login(null,{json: function(resp) {
|
||||||
resp.should.have.a.property("type","strategy");
|
resp.should.have.a.property("type","strategy");
|
||||||
resp.should.have.a.property("prompts");
|
resp.should.have.a.property("prompts");
|
||||||
@ -115,5 +116,100 @@ describe("api/auth/index",function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
describe("needsPermission", function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
sinon.stub(Tokens,"init",function(){});
|
||||||
|
sinon.stub(Users,"init",function(){});
|
||||||
|
});
|
||||||
|
afterEach(function() {
|
||||||
|
Tokens.init.restore();
|
||||||
|
Users.init.restore();
|
||||||
|
if (passport.authenticate.restore) {
|
||||||
|
passport.authenticate.restore();
|
||||||
|
}
|
||||||
|
if (Permissions.hasPermission.restore) {
|
||||||
|
Permissions.hasPermission.restore();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('no-ops if adminAuth not set', function(done) {
|
||||||
|
sinon.stub(passport,"authenticate",function(scopes,opts) {
|
||||||
|
return function(req,res,next) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
auth.init({});
|
||||||
|
var func = auth.needsPermission("foo");
|
||||||
|
func({},{},function() {
|
||||||
|
passport.authenticate.called.should.be.false();
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
it('skips auth if req.user undefined', function(done) {
|
||||||
|
sinon.stub(passport,"authenticate",function(scopes,opts) {
|
||||||
|
return function(req,res,next) {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sinon.stub(Permissions,"hasPermission",function(perm) { return true });
|
||||||
|
auth.init({adminAuth:{}});
|
||||||
|
var func = auth.needsPermission("foo");
|
||||||
|
func({user:null},{},function() {
|
||||||
|
try {
|
||||||
|
passport.authenticate.called.should.be.true();
|
||||||
|
Permissions.hasPermission.called.should.be.false();
|
||||||
|
done();
|
||||||
|
} catch(err) {
|
||||||
|
done(err);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
it('passes for valid user permission', function(done) {
|
||||||
|
sinon.stub(passport,"authenticate",function(scopes,opts) {
|
||||||
|
return function(req,res,next) {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sinon.stub(Permissions,"hasPermission",function(perm) { return true });
|
||||||
|
auth.init({adminAuth:{}});
|
||||||
|
var func = auth.needsPermission("foo");
|
||||||
|
func({user:true,authInfo: { scope: "read"}},{},function() {
|
||||||
|
try {
|
||||||
|
passport.authenticate.called.should.be.true();
|
||||||
|
Permissions.hasPermission.called.should.be.true();
|
||||||
|
Permissions.hasPermission.lastCall.args[0].should.eql("read");
|
||||||
|
Permissions.hasPermission.lastCall.args[1].should.eql("foo");
|
||||||
|
done();
|
||||||
|
} catch(err) {
|
||||||
|
done(err);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects for invalid user permission', function(done) {
|
||||||
|
sinon.stub(passport,"authenticate",function(scopes,opts) {
|
||||||
|
return function(req,res,next) {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sinon.stub(Permissions,"hasPermission",function(perm) { return false });
|
||||||
|
auth.init({adminAuth:{}});
|
||||||
|
var func = auth.needsPermission("foo");
|
||||||
|
func({user:true,authInfo: { scope: "read"}},{
|
||||||
|
status: function(status) {
|
||||||
|
return { end: function() {
|
||||||
|
try {
|
||||||
|
status.should.eql(401);
|
||||||
|
done();
|
||||||
|
} catch(err) {
|
||||||
|
done(err);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
},function() {
|
||||||
|
done(new Error("hasPermission unexpected passed"))
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -24,9 +24,6 @@ var Tokens = require("../../../../red/api/auth/tokens");
|
|||||||
var Clients = require("../../../../red/api/auth/clients");
|
var Clients = require("../../../../red/api/auth/clients");
|
||||||
|
|
||||||
describe("api/auth/strategies", function() {
|
describe("api/auth/strategies", function() {
|
||||||
before(function() {
|
|
||||||
strategies.init({log:{audit:function(){}}})
|
|
||||||
});
|
|
||||||
describe("Password Token Exchange", function() {
|
describe("Password Token Exchange", function() {
|
||||||
var userAuthentication;
|
var userAuthentication;
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
|
@ -33,6 +33,24 @@ var listenPort = 0; // use ephemeral port
|
|||||||
|
|
||||||
|
|
||||||
describe("api/editor/comms", function() {
|
describe("api/editor/comms", function() {
|
||||||
|
var connections = [];
|
||||||
|
var mockComms = {
|
||||||
|
addConnection: function(opts) {
|
||||||
|
connections.push(opts.client);
|
||||||
|
return Promise.resolve()
|
||||||
|
},
|
||||||
|
removeConnection: function(opts) {
|
||||||
|
for (var i=0;i<connections.length;i++) {
|
||||||
|
if (connections[i] === opts.client) {
|
||||||
|
connections.splice(i,1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Promise.resolve()
|
||||||
|
},
|
||||||
|
subscribe: function() { return Promise.resolve()},
|
||||||
|
unsubscribe: function() { return Promise.resolve(); }
|
||||||
|
}
|
||||||
|
|
||||||
describe("with default keepalive", function() {
|
describe("with default keepalive", function() {
|
||||||
var server;
|
var server;
|
||||||
@ -41,11 +59,7 @@ describe("api/editor/comms", function() {
|
|||||||
before(function(done) {
|
before(function(done) {
|
||||||
sinon.stub(Users,"default",function() { return when.resolve(null);});
|
sinon.stub(Users,"default",function() { return when.resolve(null);});
|
||||||
server = stoppable(http.createServer(function(req,res){app(req,res)}));
|
server = stoppable(http.createServer(function(req,res){app(req,res)}));
|
||||||
comms.init(server, {
|
comms.init(server, {}, {comms: mockComms});
|
||||||
settings:{},
|
|
||||||
log:{warn:function(){},_:function(){},trace:function(){},audit:function(){}},
|
|
||||||
events:{on:function(){},removeListener:function(){}}
|
|
||||||
});
|
|
||||||
server.listen(listenPort, address);
|
server.listen(listenPort, address);
|
||||||
server.on('listening', function() {
|
server.on('listening', function() {
|
||||||
port = server.address().port;
|
port = server.address().port;
|
||||||
@ -63,9 +77,15 @@ describe("api/editor/comms", function() {
|
|||||||
|
|
||||||
it('accepts connection', function(done) {
|
it('accepts connection', function(done) {
|
||||||
var ws = new WebSocket(url);
|
var ws = new WebSocket(url);
|
||||||
|
connections.length.should.eql(0);
|
||||||
ws.on('open', function() {
|
ws.on('open', function() {
|
||||||
|
try {
|
||||||
|
connections.length.should.eql(1);
|
||||||
ws.close();
|
ws.close();
|
||||||
done();
|
done();
|
||||||
|
} catch(err) {
|
||||||
|
done(err);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -73,7 +93,8 @@ describe("api/editor/comms", function() {
|
|||||||
var ws = new WebSocket(url);
|
var ws = new WebSocket(url);
|
||||||
ws.on('open', function() {
|
ws.on('open', function() {
|
||||||
ws.send('{"subscribe":"topic1"}');
|
ws.send('{"subscribe":"topic1"}');
|
||||||
comms.publish('topic1', 'foo');
|
connections.length.should.eql(1);
|
||||||
|
connections[0].send('topic1', 'foo');
|
||||||
});
|
});
|
||||||
ws.on('message', function(msg) {
|
ws.on('message', function(msg) {
|
||||||
msg.should.equal('[{"topic":"topic1","data":"foo"}]');
|
msg.should.equal('[{"topic":"topic1","data":"foo"}]');
|
||||||
@ -82,43 +103,13 @@ describe("api/editor/comms", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('publishes retained message for subscription', function(done) {
|
|
||||||
comms.publish('topic2', 'bar', true);
|
|
||||||
var ws = new WebSocket(url);
|
|
||||||
ws.on('open', function() {
|
|
||||||
ws.send('{"subscribe":"topic2"}');
|
|
||||||
});
|
|
||||||
ws.on('message', function(msg) {
|
|
||||||
console.log(msg);
|
|
||||||
msg.should.equal('[{"topic":"topic2","data":"bar"}]');
|
|
||||||
ws.close();
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('retained message is deleted by non-retained message', function(done) {
|
|
||||||
comms.publish('topic3', 'retained', true);
|
|
||||||
comms.publish('topic3', 'non-retained');
|
|
||||||
var ws = new WebSocket(url);
|
|
||||||
ws.on('open', function() {
|
|
||||||
ws.send('{"subscribe":"topic3"}');
|
|
||||||
comms.publish('topic3', 'new');
|
|
||||||
});
|
|
||||||
ws.on('message', function(msg) {
|
|
||||||
console.log(msg);
|
|
||||||
msg.should.equal('[{"topic":"topic3","data":"new"}]');
|
|
||||||
ws.close();
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('malformed messages are ignored',function(done) {
|
it('malformed messages are ignored',function(done) {
|
||||||
var ws = new WebSocket(url);
|
var ws = new WebSocket(url);
|
||||||
ws.on('open', function() {
|
ws.on('open', function() {
|
||||||
ws.send('not json');
|
ws.send('not json');
|
||||||
ws.send('[]');
|
ws.send('[]');
|
||||||
ws.send('{"subscribe":"topic3"}');
|
ws.send('{"subscribe":"topic3"}');
|
||||||
comms.publish('topic3', 'correct');
|
connections[0].send('topic3', 'correct');
|
||||||
});
|
});
|
||||||
ws.on('message', function(msg) {
|
ws.on('message', function(msg) {
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
@ -127,40 +118,16 @@ describe("api/editor/comms", function() {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// The following test currently fails due to minimum viable
|
|
||||||
// implementation. More test should be written to test topic
|
|
||||||
// matching once this one is passing
|
|
||||||
|
|
||||||
it.skip('receives message on correct topic', function(done) {
|
|
||||||
var ws = new WebSocket(url);
|
|
||||||
ws.on('open', function() {
|
|
||||||
ws.send('{"subscribe":"topic4"}');
|
|
||||||
comms.publish('topic5', 'foo');
|
|
||||||
comms.publish('topic4', 'bar');
|
|
||||||
});
|
|
||||||
ws.on('message', function(msg) {
|
|
||||||
console.log(msg);
|
|
||||||
msg.should.equal('[{"topic":"topic4","data":"bar"}]');
|
|
||||||
ws.close();
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('listens for node/status events');
|
|
||||||
});
|
|
||||||
describe("disabled editor", function() {
|
describe("disabled editor", function() {
|
||||||
var server;
|
var server;
|
||||||
var url;
|
var url;
|
||||||
var port;
|
var port;
|
||||||
before(function(done) {
|
before(function(done) {
|
||||||
sinon.stub(Users,"default",function() { return when.resolve(null);});
|
sinon.stub(Users,"default",function() { return Promise.resolve(null);});
|
||||||
server = stoppable(http.createServer(function(req,res){app(req,res)}));
|
server = stoppable(http.createServer(function(req,res){app(req,res)}));
|
||||||
comms.init(server, {
|
comms.init(server, {disableEditor:true}, {comms: mockComms});
|
||||||
settings:{disableEditor:true},
|
|
||||||
log:{warn:function(){},_:function(){},trace:function(){},audit:function(){}},
|
|
||||||
events:{on:function(){},removeListener:function(){}}
|
|
||||||
});
|
|
||||||
server.listen(listenPort, address);
|
server.listen(listenPort, address);
|
||||||
server.on('listening', function() {
|
server.on('listening', function() {
|
||||||
port = server.address().port;
|
port = server.address().port;
|
||||||
@ -177,12 +144,14 @@ describe("api/editor/comms", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('rejects websocket connections',function(done) {
|
it('rejects websocket connections',function(done) {
|
||||||
|
connections.length.should.eql(0);
|
||||||
var ws = new WebSocket(url);
|
var ws = new WebSocket(url);
|
||||||
ws.on('open', function() {
|
ws.on('open', function() {
|
||||||
done(new Error("Socket connection unexpectedly accepted"));
|
done(new Error("Socket connection unexpectedly accepted"));
|
||||||
ws.close();
|
ws.close();
|
||||||
});
|
});
|
||||||
ws.on('error', function() {
|
ws.on('error', function() {
|
||||||
|
connections.length.should.eql(0);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -196,11 +165,7 @@ describe("api/editor/comms", function() {
|
|||||||
before(function(done) {
|
before(function(done) {
|
||||||
sinon.stub(Users,"default",function() { return when.resolve(null);});
|
sinon.stub(Users,"default",function() { return when.resolve(null);});
|
||||||
server = stoppable(http.createServer(function(req,res){app(req,res)}));
|
server = stoppable(http.createServer(function(req,res){app(req,res)}));
|
||||||
comms.init(server, {
|
comms.init(server, {httpAdminRoot:"/adminPath"}, {comms: mockComms});
|
||||||
settings:{httpAdminRoot:"/adminPath"},
|
|
||||||
log:{warn:function(){},_:function(){},trace:function(){},audit:function(){}},
|
|
||||||
events:{on:function(){},removeListener:function(){}}
|
|
||||||
});
|
|
||||||
server.listen(listenPort, address);
|
server.listen(listenPort, address);
|
||||||
server.on('listening', function() {
|
server.on('listening', function() {
|
||||||
port = server.address().port;
|
port = server.address().port;
|
||||||
@ -217,8 +182,10 @@ describe("api/editor/comms", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('accepts connections',function(done) {
|
it('accepts connections',function(done) {
|
||||||
|
connections.length.should.eql(0);
|
||||||
var ws = new WebSocket(url);
|
var ws = new WebSocket(url);
|
||||||
ws.on('open', function() {
|
ws.on('open', function() {
|
||||||
|
connections.length.should.eql(1);
|
||||||
ws.close();
|
ws.close();
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -236,11 +203,7 @@ describe("api/editor/comms", function() {
|
|||||||
before(function(done) {
|
before(function(done) {
|
||||||
sinon.stub(Users,"default",function() { return when.resolve(null);});
|
sinon.stub(Users,"default",function() { return when.resolve(null);});
|
||||||
server = stoppable(http.createServer(function(req,res){app(req,res)}));
|
server = stoppable(http.createServer(function(req,res){app(req,res)}));
|
||||||
comms.init(server,{
|
comms.init(server, {httpAdminRoot:"/adminPath/"}, {comms: mockComms});
|
||||||
settings:{httpAdminRoot:"/adminPath"},
|
|
||||||
log:{warn:function(){},_:function(){},trace:function(){},audit:function(){}},
|
|
||||||
events:{on:function(){},removeListener:function(){}}
|
|
||||||
});
|
|
||||||
server.listen(listenPort, address);
|
server.listen(listenPort, address);
|
||||||
server.on('listening', function() {
|
server.on('listening', function() {
|
||||||
port = server.address().port;
|
port = server.address().port;
|
||||||
@ -257,8 +220,10 @@ describe("api/editor/comms", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('accepts connections',function(done) {
|
it('accepts connections',function(done) {
|
||||||
|
connections.length.should.eql(0);
|
||||||
var ws = new WebSocket(url);
|
var ws = new WebSocket(url);
|
||||||
ws.on('open', function() {
|
ws.on('open', function() {
|
||||||
|
connections.length.should.eql(1);
|
||||||
ws.close();
|
ws.close();
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -276,11 +241,7 @@ describe("api/editor/comms", function() {
|
|||||||
before(function(done) {
|
before(function(done) {
|
||||||
sinon.stub(Users,"default",function() { return when.resolve(null);});
|
sinon.stub(Users,"default",function() { return when.resolve(null);});
|
||||||
server = stoppable(http.createServer(function(req,res){app(req,res)}));
|
server = stoppable(http.createServer(function(req,res){app(req,res)}));
|
||||||
comms.init(server, {
|
comms.init(server, {httpAdminRoot:"adminPath"}, {comms: mockComms});
|
||||||
settings:{httpAdminRoot:"adminPath"},
|
|
||||||
log:{warn:function(){},_:function(){},trace:function(){},audit:function(){}},
|
|
||||||
events:{on:function(){},removeListener:function(){}}
|
|
||||||
});
|
|
||||||
server.listen(listenPort, address);
|
server.listen(listenPort, address);
|
||||||
server.on('listening', function() {
|
server.on('listening', function() {
|
||||||
port = server.address().port;
|
port = server.address().port;
|
||||||
@ -297,8 +258,10 @@ describe("api/editor/comms", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('accepts connections',function(done) {
|
it('accepts connections',function(done) {
|
||||||
|
connections.length.should.eql(0);
|
||||||
var ws = new WebSocket(url);
|
var ws = new WebSocket(url);
|
||||||
ws.on('open', function() {
|
ws.on('open', function() {
|
||||||
|
connections.length.should.eql(1);
|
||||||
ws.close();
|
ws.close();
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -316,11 +279,7 @@ describe("api/editor/comms", function() {
|
|||||||
before(function(done) {
|
before(function(done) {
|
||||||
sinon.stub(Users,"default",function() { return when.resolve(null);});
|
sinon.stub(Users,"default",function() { return when.resolve(null);});
|
||||||
server = stoppable(http.createServer(function(req,res){app(req,res)}));
|
server = stoppable(http.createServer(function(req,res){app(req,res)}));
|
||||||
comms.init(server, {
|
comms.init(server, {webSocketKeepAliveTime: 100}, {comms: mockComms});
|
||||||
settings:{webSocketKeepAliveTime: 100},
|
|
||||||
log:{warn:function(){},_:function(){},trace:function(){},audit:function(){}},
|
|
||||||
events:{on:function(){},removeListener:function(){}}
|
|
||||||
});
|
|
||||||
server.listen(listenPort, address);
|
server.listen(listenPort, address);
|
||||||
server.on('listening', function() {
|
server.on('listening', function() {
|
||||||
port = server.address().port;
|
port = server.address().port;
|
||||||
@ -355,7 +314,7 @@ describe("api/editor/comms", function() {
|
|||||||
ws.on('open', function() {
|
ws.on('open', function() {
|
||||||
ws.send('{"subscribe":"foo"}');
|
ws.send('{"subscribe":"foo"}');
|
||||||
interval = setInterval(function() {
|
interval = setInterval(function() {
|
||||||
comms.publish('foo', 'bar');
|
connections[0].send('foo', 'bar');
|
||||||
}, 50);
|
}, 50);
|
||||||
});
|
});
|
||||||
ws.on('message', function(data) {
|
ws.on('message', function(data) {
|
||||||
@ -403,11 +362,7 @@ describe("api/editor/comms", function() {
|
|||||||
|
|
||||||
|
|
||||||
server = stoppable(http.createServer(function(req,res){app(req,res)}));
|
server = stoppable(http.createServer(function(req,res){app(req,res)}));
|
||||||
comms.init(server,{
|
comms.init(server, {adminAuth:{}}, {comms: mockComms});
|
||||||
settings:{adminAuth:{}},
|
|
||||||
log:{warn:function(){},_:function(){},trace:function(){},audit:function(){}},
|
|
||||||
events:{on:function(){},removeListener:function(){}}
|
|
||||||
});
|
|
||||||
server.listen(listenPort, address);
|
server.listen(listenPort, address);
|
||||||
server.on('listening', function() {
|
server.on('listening', function() {
|
||||||
port = server.address().port;
|
port = server.address().port;
|
||||||
@ -447,7 +402,7 @@ describe("api/editor/comms", function() {
|
|||||||
if (received == 1) {
|
if (received == 1) {
|
||||||
msg.should.equal('{"auth":"ok"}');
|
msg.should.equal('{"auth":"ok"}');
|
||||||
ws.send('{"subscribe":"foo"}');
|
ws.send('{"subscribe":"foo"}');
|
||||||
comms.publish('foo', 'correct');
|
connections[0].send('foo', 'correct');
|
||||||
} else {
|
} else {
|
||||||
msg.should.equal('[{"topic":"foo","data":"correct"}]');
|
msg.should.equal('[{"topic":"foo","data":"correct"}]');
|
||||||
ws.close();
|
ws.close();
|
||||||
@ -494,11 +449,7 @@ describe("api/editor/comms", function() {
|
|||||||
before(function(done) {
|
before(function(done) {
|
||||||
getDefaultUser = sinon.stub(Users,"default",function() { return when.resolve({permissions:"read"});});
|
getDefaultUser = sinon.stub(Users,"default",function() { return when.resolve({permissions:"read"});});
|
||||||
server = stoppable(http.createServer(function(req,res){app(req,res)}));
|
server = stoppable(http.createServer(function(req,res){app(req,res)}));
|
||||||
comms.init(server, {
|
comms.init(server, {adminAuth:{}}, {comms: mockComms});
|
||||||
settings:{adminAuth:{}},
|
|
||||||
log:{warn:function(){},_:function(){},trace:function(){},audit:function(){}},
|
|
||||||
events:{on:function(){},removeListener:function(){}}
|
|
||||||
});
|
|
||||||
server.listen(listenPort, address);
|
server.listen(listenPort, address);
|
||||||
server.on('listening', function() {
|
server.on('listening', function() {
|
||||||
port = server.address().port;
|
port = server.address().port;
|
||||||
@ -520,7 +471,7 @@ describe("api/editor/comms", function() {
|
|||||||
ws.on('open', function() {
|
ws.on('open', function() {
|
||||||
ws.send('{"subscribe":"foo"}');
|
ws.send('{"subscribe":"foo"}');
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
comms.publish('foo', 'correct');
|
connections[0].send('foo', 'correct');
|
||||||
},200);
|
},200);
|
||||||
});
|
});
|
||||||
ws.on('message', function(msg) {
|
ws.on('message', function(msg) {
|
||||||
|
@ -29,64 +29,30 @@ describe('api/editor/credentials', function() {
|
|||||||
app = express();
|
app = express();
|
||||||
app.get('/credentials/:type/:id',credentials.get);
|
app.get('/credentials/:type/:id',credentials.get);
|
||||||
credentials.init({
|
credentials.init({
|
||||||
log:{audit:function(){}},
|
flows: {
|
||||||
nodes:{
|
getNodeCredentials: function(opts) {
|
||||||
getCredentials: function(id) {
|
if (opts.type === "known-type" && opts.id === "n1") {
|
||||||
if (id === "n1") {
|
return Promise.resolve({
|
||||||
return {user1:"abc",password1:"123"};
|
user1:"abc",
|
||||||
|
has_password1: true
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
return null;
|
var err = new Error("message");
|
||||||
}
|
err.code = "test_code";
|
||||||
},
|
var p = Promise.reject(err);
|
||||||
getCredentialDefinition:function(type) {
|
p.catch(()=>{});
|
||||||
if (type === "known-type") {
|
return p;
|
||||||
return {user1:{type:"text"},password1:{type:"password"}};
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('returns empty credentials if unknown type',function(done) {
|
|
||||||
request(app)
|
|
||||||
.get("/credentials/unknown-type/n1")
|
|
||||||
.expect(200)
|
|
||||||
.expect("Content-Type",/json/)
|
|
||||||
.end(function(err,res) {
|
|
||||||
if (err) {
|
|
||||||
done(err);
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
res.body.should.eql({});
|
|
||||||
done();
|
|
||||||
} catch(e) {
|
|
||||||
done(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
it('returns empty credentials if none are stored',function(done) {
|
|
||||||
request(app)
|
|
||||||
.get("/credentials/known-type/n2")
|
|
||||||
.expect("Content-Type",/json/)
|
|
||||||
.end(function(err,res) {
|
|
||||||
if (err) {
|
|
||||||
done(err);
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
res.body.should.eql({});
|
|
||||||
done();
|
|
||||||
} catch(e) {
|
|
||||||
done(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
it('returns stored credentials',function(done) {
|
it('returns stored credentials',function(done) {
|
||||||
request(app)
|
request(app)
|
||||||
.get("/credentials/known-type/n1")
|
.get("/credentials/known-type/n1")
|
||||||
.expect("Content-Type",/json/)
|
.expect("Content-Type",/json/)
|
||||||
|
.expect(200)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
done(err);
|
done(err);
|
||||||
@ -102,5 +68,26 @@ describe('api/editor/credentials', function() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
it('returns any error',function(done) {
|
||||||
|
request(app)
|
||||||
|
.get("/credentials/unknown-type/n2")
|
||||||
|
.expect("Content-Type",/json/)
|
||||||
|
.expect(500)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
done(err);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
res.body.should.have.property('code');
|
||||||
|
res.body.code.should.be.equal("test_code");
|
||||||
|
res.body.should.have.property('message');
|
||||||
|
res.body.message.should.be.equal('message');
|
||||||
|
done();
|
||||||
|
} catch(e) {
|
||||||
|
done(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -22,6 +22,10 @@ var editorApi = require("../../../../red/api/editor");
|
|||||||
var comms = require("../../../../red/api/editor/comms");
|
var comms = require("../../../../red/api/editor/comms");
|
||||||
var info = require("../../../../red/api/editor/settings");
|
var info = require("../../../../red/api/editor/settings");
|
||||||
var auth = require("../../../../red/api/auth");
|
var auth = require("../../../../red/api/auth");
|
||||||
|
|
||||||
|
var log = require("../../../../red/util/log");
|
||||||
|
|
||||||
|
|
||||||
var when = require("when");
|
var when = require("when");
|
||||||
|
|
||||||
|
|
||||||
@ -37,9 +41,7 @@ describe("api/editor/index", function() {
|
|||||||
info.init.restore();
|
info.init.restore();
|
||||||
});
|
});
|
||||||
it("disables the editor", function() {
|
it("disables the editor", function() {
|
||||||
var editorApp = editorApi.init({},{
|
var editorApp = editorApi.init({},{disableEditor:true},{});
|
||||||
settings:{disableEditor:true}
|
|
||||||
});
|
|
||||||
should.not.exist(editorApp);
|
should.not.exist(editorApp);
|
||||||
comms.init.called.should.be.false();
|
comms.init.called.should.be.false();
|
||||||
info.init.called.should.be.false();
|
info.init.called.should.be.false();
|
||||||
@ -67,15 +69,13 @@ describe("api/editor/index", function() {
|
|||||||
})
|
})
|
||||||
require("../../../../red/api/editor/theme").app.restore();
|
require("../../../../red/api/editor/theme").app.restore();
|
||||||
auth.needsPermission.restore();
|
auth.needsPermission.restore();
|
||||||
|
log.error.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
app = editorApi.init({},{
|
sinon.stub(log,"error",function(err) { errors.push(err)})
|
||||||
log:{audit:function(){},error:function(msg){errors.push(msg)}},
|
app = editorApi.init({},{httpNodeRoot:true, httpAdminRoot: true,disableEditor:false,exportNodeSettings:function(){}},{
|
||||||
settings:{httpNodeRoot:true, httpAdminRoot: true,disableEditor:false,exportNodeSettings:function(){}},
|
isStarted: () => Promise.resolve(isStarted)
|
||||||
events:{on:function(){},removeListener:function(){}},
|
|
||||||
isStarted: function() { return isStarted; },
|
|
||||||
nodes: {paletteEditorEnabled: function() { return false }}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('serves the editor', function(done) {
|
it('serves the editor', function(done) {
|
||||||
@ -117,7 +117,7 @@ describe("api/editor/index", function() {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// it('GET /settings', function(done) {
|
// it.skip('GET /settings', function(done) {
|
||||||
// request(app).get("/settings").expect(200).end(function(err,res) {
|
// request(app).get("/settings").expect(200).end(function(err,res) {
|
||||||
// if (err) {
|
// if (err) {
|
||||||
// return done(err);
|
// return done(err);
|
||||||
|
@ -16,334 +16,287 @@
|
|||||||
|
|
||||||
var should = require("should");
|
var should = require("should");
|
||||||
var sinon = require("sinon");
|
var sinon = require("sinon");
|
||||||
var fs = require("fs");
|
|
||||||
var fspath = require('path');
|
|
||||||
var request = require('supertest');
|
var request = require('supertest');
|
||||||
var express = require('express');
|
var express = require('express');
|
||||||
var bodyParser = require('body-parser');
|
var bodyParser = require('body-parser');
|
||||||
|
|
||||||
var when = require('when');
|
|
||||||
|
|
||||||
var app;
|
var app;
|
||||||
|
|
||||||
var library = require("../../../../red/api/editor/library");
|
var library = require("../../../../red/api/editor/library");
|
||||||
var auth = require("../../../../red/api/auth");
|
|
||||||
|
|
||||||
describe("api/editor/library", function() {
|
describe("api/editor/library", function() {
|
||||||
|
|
||||||
function initLibrary(_flows,_libraryEntries,_examples,_exampleFlowPathFunction) {
|
|
||||||
var flows = _flows;
|
|
||||||
var libraryEntries = _libraryEntries;
|
|
||||||
library.init(app,{
|
|
||||||
log:{audit:function(){},_:function(){},warn:function(){}},
|
|
||||||
storage: {
|
|
||||||
init: function() {
|
|
||||||
return when.resolve();
|
|
||||||
},
|
|
||||||
getAllFlows: function() {
|
|
||||||
return when.resolve(flows);
|
|
||||||
},
|
|
||||||
getFlow: function(fn) {
|
|
||||||
if (flows[fn]) {
|
|
||||||
return when.resolve(flows[fn]);
|
|
||||||
} else if (fn.indexOf("..")!==-1) {
|
|
||||||
var err = new Error();
|
|
||||||
err.code = 'forbidden';
|
|
||||||
return when.reject(err);
|
|
||||||
} else {
|
|
||||||
return when.reject();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
saveFlow: function(fn,data) {
|
|
||||||
if (fn.indexOf("..")!==-1) {
|
|
||||||
var err = new Error();
|
|
||||||
err.code = 'forbidden';
|
|
||||||
return when.reject(err);
|
|
||||||
}
|
|
||||||
flows[fn] = data;
|
|
||||||
return when.resolve();
|
|
||||||
},
|
|
||||||
getLibraryEntry: function(type,path) {
|
|
||||||
if (path.indexOf("..")!==-1) {
|
|
||||||
var err = new Error();
|
|
||||||
err.code = 'forbidden';
|
|
||||||
return when.reject(err);
|
|
||||||
}
|
|
||||||
if (libraryEntries[type] && libraryEntries[type][path]) {
|
|
||||||
return when.resolve(libraryEntries[type][path]);
|
|
||||||
} else {
|
|
||||||
return when.reject();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
saveLibraryEntry: function(type,path,meta,body) {
|
|
||||||
if (path.indexOf("..")!==-1) {
|
|
||||||
var err = new Error();
|
|
||||||
err.code = 'forbidden';
|
|
||||||
return when.reject(err);
|
|
||||||
}
|
|
||||||
libraryEntries[type][path] = body;
|
|
||||||
return when.resolve();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
events: {
|
|
||||||
on: function(){},
|
|
||||||
removeListener: function(){}
|
|
||||||
},
|
|
||||||
nodes: {
|
|
||||||
getNodeExampleFlows: function() {
|
|
||||||
return _examples;
|
|
||||||
},
|
|
||||||
getNodeExampleFlowPath: _exampleFlowPathFunction
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("flows", function() {
|
|
||||||
before(function() {
|
before(function() {
|
||||||
app = express();
|
app = express();
|
||||||
app.use(bodyParser.json());
|
app.use(bodyParser.json());
|
||||||
|
|
||||||
app.get("/library/flows",library.getAll);
|
app.get("/library/flows",library.getAll);
|
||||||
app.post(new RegExp("/library/flows\/(.*)"),library.post);
|
app.post(/library\/([^\/]+)\/(.*)/,library.saveEntry);
|
||||||
app.get(new RegExp("/library/flows\/(.*)"),library.get);
|
app.get(/library\/([^\/]+)(?:$|\/(.*))/,library.getEntry);
|
||||||
app.response.sendFile = function (path) {
|
|
||||||
app.response.json.call(this, {sendFile: path});
|
|
||||||
};
|
|
||||||
sinon.stub(fs,"statSync",function() { return true; });
|
|
||||||
});
|
});
|
||||||
after(function() {
|
after(function() {
|
||||||
fs.statSync.restore();
|
|
||||||
});
|
});
|
||||||
it('returns empty result', function(done) {
|
it('returns all flows', function(done) {
|
||||||
initLibrary({},{flows:{}});
|
library.init({
|
||||||
|
library: {
|
||||||
|
getEntries: function(opts) {
|
||||||
|
return Promise.resolve({a:1,b:2});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
request(app)
|
request(app)
|
||||||
.get('/library/flows')
|
.get('/library/flows')
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
return done(err);
|
||||||
}
|
}
|
||||||
res.body.should.not.have.property('f');
|
res.body.should.have.property('a',1);
|
||||||
res.body.should.not.have.property('d');
|
res.body.should.have.property('b',2);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
})
|
||||||
|
it('returns an error on all flows', function(done) {
|
||||||
it('returns 404 for non-existent entry', function(done) {
|
library.init({
|
||||||
initLibrary({},{flows:{}});
|
library: {
|
||||||
request(app)
|
getEntries: function(opts) {
|
||||||
.get('/library/flows/foo')
|
var err = new Error("message");
|
||||||
.expect(404)
|
err.code = "random_error";
|
||||||
.end(done);
|
err.status = 400;
|
||||||
});
|
var p = Promise.reject(err);
|
||||||
|
p.catch(()=>{});
|
||||||
|
return p;
|
||||||
it('can store and retrieve item', function(done) {
|
|
||||||
initLibrary({},{flows:{}});
|
|
||||||
var flow = '[]';
|
|
||||||
request(app)
|
|
||||||
.post('/library/flows/foo')
|
|
||||||
.set('Content-Type', 'application/json')
|
|
||||||
.send(flow)
|
|
||||||
.expect(204).end(function (err, res) {
|
|
||||||
if (err) {
|
|
||||||
throw err;
|
|
||||||
}
|
}
|
||||||
request(app)
|
|
||||||
.get('/library/flows/foo')
|
|
||||||
.expect(200)
|
|
||||||
.end(function(err,res) {
|
|
||||||
if (err) {
|
|
||||||
throw err;
|
|
||||||
}
|
}
|
||||||
res.text.should.equal(flow);
|
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('lists a stored item', function(done) {
|
|
||||||
initLibrary({f:["bar"]});
|
|
||||||
request(app)
|
request(app)
|
||||||
.get('/library/flows')
|
.get('/library/flows')
|
||||||
.expect(200)
|
.expect(400)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
return done(err);
|
||||||
}
|
}
|
||||||
res.body.should.have.property('f');
|
res.body.should.have.property('code');
|
||||||
should.deepEqual(res.body.f,['bar']);
|
res.body.code.should.be.equal("random_error");
|
||||||
|
res.body.should.have.property('message');
|
||||||
|
res.body.message.should.be.equal("message");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns 403 for malicious get attempt', function(done) {
|
it('returns an individual entry - flow type', function(done) {
|
||||||
initLibrary({});
|
var opts;
|
||||||
// without the userDir override the malicious url would be
|
library.init({
|
||||||
// http://127.0.0.1:1880/library/flows/../../package to
|
library: {
|
||||||
// obtain package.json from the node-red root.
|
getEntry: function(_opts) {
|
||||||
request(app)
|
opts = _opts;
|
||||||
.get('/library/flows/../../../../../package')
|
return Promise.resolve('{"a":1,"b":2}');
|
||||||
.expect(403)
|
}
|
||||||
.end(done);
|
}
|
||||||
});
|
});
|
||||||
it('returns 403 for malicious post attempt', function(done) {
|
|
||||||
initLibrary({});
|
|
||||||
// without the userDir override the malicious url would be
|
|
||||||
// http://127.0.0.1:1880/library/flows/../../package to
|
|
||||||
// obtain package.json from the node-red root.
|
|
||||||
request(app)
|
request(app)
|
||||||
.post('/library/flows/../../../../../package')
|
.get('/library/flows/abc')
|
||||||
.expect(403)
|
|
||||||
.end(done);
|
|
||||||
});
|
|
||||||
it('includes examples flows if set', function(done) {
|
|
||||||
var examples = {"d":{"node-module":{"f":["example-one"]}}};
|
|
||||||
initLibrary({},{},examples);
|
|
||||||
request(app)
|
|
||||||
.get('/library/flows')
|
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
return done(err);
|
||||||
}
|
}
|
||||||
res.body.should.have.property('d');
|
res.body.should.have.property('a',1);
|
||||||
res.body.d.should.have.property('_examples_');
|
res.body.should.have.property('b',2);
|
||||||
should.deepEqual(res.body.d._examples_,examples);
|
opts.should.have.property('type','flows');
|
||||||
|
opts.should.have.property('path','abc');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
})
|
||||||
|
it('returns a directory listing - flow type', function(done) {
|
||||||
it('can retrieve an example flow', function(done) {
|
var opts;
|
||||||
var examples = {"d":{"node-module":{"f":["example-one"]}}};
|
library.init({
|
||||||
initLibrary({},{},examples,function(module,path) {
|
library: {
|
||||||
return module + ':' + path
|
getEntry: function(_opts) {
|
||||||
|
opts = _opts;
|
||||||
|
return Promise.resolve({"a":1,"b":2});
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
request(app)
|
request(app)
|
||||||
.get('/library/flows/_examples_/node-module/example-one')
|
.get('/library/flows/abc/def')
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
return done(err);
|
||||||
}
|
}
|
||||||
res.body.should.have.property('sendFile',
|
res.body.should.have.property('a',1);
|
||||||
'node-module:example-one');
|
res.body.should.have.property('b',2);
|
||||||
|
opts.should.have.property('type','flows');
|
||||||
|
opts.should.have.property('path','abc/def');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
})
|
||||||
|
it('returns an individual entry - non-flow type', function(done) {
|
||||||
it('can retrieve an example flow in an org scoped package', function(done) {
|
var opts;
|
||||||
var examples = {"d":{"@org_scope/node_package":{"f":["example-one"]}}};
|
library.init({
|
||||||
initLibrary({},{},examples,function(module,path) {
|
library: {
|
||||||
return module + ':' + path
|
getEntry: function(_opts) {
|
||||||
|
opts = _opts;
|
||||||
|
return Promise.resolve('{"a":1,"b":2}');
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
request(app)
|
request(app)
|
||||||
.get('/library/flows/_examples_/@org_scope/node_package/example-one')
|
.get('/library/non-flow/abc')
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
return done(err);
|
||||||
}
|
}
|
||||||
res.body.should.have.property('sendFile',
|
opts.should.have.property('type','non-flow');
|
||||||
'@org_scope/node_package:example-one');
|
opts.should.have.property('path','abc');
|
||||||
|
res.text.should.eql('{"a":1,"b":2}');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
})
|
||||||
|
it('returns a directory listing - non-flow type', function(done) {
|
||||||
|
var opts;
|
||||||
|
library.init({
|
||||||
|
library: {
|
||||||
|
getEntry: function(_opts) {
|
||||||
|
opts = _opts;
|
||||||
|
return Promise.resolve({"a":1,"b":2});
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
describe("type", function() {
|
|
||||||
before(function() {
|
|
||||||
|
|
||||||
app = express();
|
|
||||||
app.use(bodyParser.json());
|
|
||||||
initLibrary({},{});
|
|
||||||
auth.init({settings:{}});
|
|
||||||
library.register("test");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns empty result', function(done) {
|
|
||||||
initLibrary({},{'test':{"":[]}});
|
|
||||||
request(app)
|
request(app)
|
||||||
.get('/library/test')
|
.get('/library/non-flow/abc/def')
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
return done(err);
|
||||||
}
|
}
|
||||||
res.body.should.not.have.property('f');
|
res.body.should.have.property('a',1);
|
||||||
|
res.body.should.have.property('b',2);
|
||||||
|
opts.should.have.property('type','non-flow');
|
||||||
|
opts.should.have.property('path','abc/def');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
})
|
||||||
|
|
||||||
it('returns 404 for non-existent entry', function(done) {
|
it('returns an error on individual get', function(done) {
|
||||||
initLibrary({},{});
|
var opts;
|
||||||
request(app)
|
library.init({
|
||||||
.get('/library/test/foo')
|
library: {
|
||||||
.expect(404)
|
getEntry: function(_opts) {
|
||||||
.end(done);
|
opts = _opts;
|
||||||
});
|
var err = new Error("message");
|
||||||
|
err.code = "random_error";
|
||||||
it('can store and retrieve item', function(done) {
|
err.status = 400;
|
||||||
initLibrary({},{'test':{}});
|
var p = Promise.reject(err);
|
||||||
var flow = {text:"test content"};
|
p.catch(()=>{});
|
||||||
request(app)
|
return p;
|
||||||
.post('/library/test/foo')
|
|
||||||
.set('Content-Type', 'application/json')
|
|
||||||
.send(flow)
|
|
||||||
.expect(204).end(function (err, res) {
|
|
||||||
if (err) {
|
|
||||||
throw err;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
request(app)
|
request(app)
|
||||||
.get('/library/test/foo')
|
.get('/library/flows/123')
|
||||||
.expect(200)
|
.expect(400)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
return done(err);
|
||||||
}
|
}
|
||||||
res.text.should.equal(flow.text);
|
opts.should.have.property('type','flows');
|
||||||
done();
|
opts.should.have.property('path','123');
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('lists a stored item', function(done) {
|
res.body.should.have.property('code');
|
||||||
initLibrary({},{'test':{'a':['abc','def']}});
|
res.body.code.should.be.equal("random_error");
|
||||||
request(app)
|
res.body.should.have.property('message');
|
||||||
.get('/library/test/a')
|
res.body.message.should.be.equal("message");
|
||||||
.expect(200)
|
|
||||||
.end(function(err,res) {
|
|
||||||
if (err) {
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
// This response isn't strictly accurate - but it
|
|
||||||
// verifies the api returns what storage gave it
|
|
||||||
should.deepEqual(res.body,['abc','def']);
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('returns 403 for malicious access attempt', function(done) {
|
it('saves an individual entry - flow type', function(done) {
|
||||||
|
var opts;
|
||||||
|
library.init({
|
||||||
|
library: {
|
||||||
|
saveEntry: function(_opts) {
|
||||||
|
opts = _opts;
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
request(app)
|
request(app)
|
||||||
.get('/library/test/../../../../../../../../../../etc/passwd')
|
.post('/library/flows/abc/def')
|
||||||
.expect(403)
|
.expect(204)
|
||||||
.end(done);
|
.send({a:1,b:2,c:3})
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
opts.should.have.property('type','flows');
|
||||||
|
opts.should.have.property('path','abc/def');
|
||||||
|
opts.should.have.property('meta',{});
|
||||||
|
opts.should.have.property('body',JSON.stringify({a:1,b:2,c:3}));
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
|
})
|
||||||
|
|
||||||
it('returns 403 for malicious access attempt', function(done) {
|
it('saves an individual entry - non-flow type', function(done) {
|
||||||
|
var opts;
|
||||||
|
library.init({
|
||||||
|
library: {
|
||||||
|
saveEntry: function(_opts) {
|
||||||
|
opts = _opts;
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
request(app)
|
request(app)
|
||||||
.get('/library/test/..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\etc\\passwd')
|
.post('/library/non-flow/abc/def')
|
||||||
.expect(403)
|
.expect(204)
|
||||||
.end(done);
|
.send({a:1,b:2,text:"123"})
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
opts.should.have.property('type','non-flow');
|
||||||
|
opts.should.have.property('path','abc/def');
|
||||||
|
opts.should.have.property('meta',{a:1,b:2});
|
||||||
|
opts.should.have.property('body',"123");
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
|
})
|
||||||
|
|
||||||
it('returns 403 for malicious access attempt', function(done) {
|
it('returns an error on individual save', function(done) {
|
||||||
|
var opts;
|
||||||
|
library.init({
|
||||||
|
library: {
|
||||||
|
saveEntry: function(_opts) {
|
||||||
|
opts = _opts;
|
||||||
|
var err = new Error("message");
|
||||||
|
err.code = "random_error";
|
||||||
|
err.status = 400;
|
||||||
|
var p = Promise.reject(err);
|
||||||
|
p.catch(()=>{});
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
request(app)
|
request(app)
|
||||||
.post('/library/test/../../../../../../../../../../etc/passwd')
|
.post('/library/non-flow/abc/def')
|
||||||
.set('Content-Type', 'text/plain')
|
.send({a:1,b:2,text:"123"})
|
||||||
.send('root:x:0:0:root:/root:/usr/bin/tclsh')
|
.expect(400)
|
||||||
.expect(403)
|
.end(function(err,res) {
|
||||||
.end(done);
|
if (err) {
|
||||||
});
|
return done(err);
|
||||||
|
}
|
||||||
|
opts.should.have.property('type','non-flow');
|
||||||
|
opts.should.have.property('path','abc/def');
|
||||||
|
|
||||||
|
res.body.should.have.property('code');
|
||||||
|
res.body.code.should.be.equal("random_error");
|
||||||
|
res.body.should.have.property('message');
|
||||||
|
res.body.message.should.be.equal("message");
|
||||||
|
done();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -20,6 +20,8 @@ var express = require('express');
|
|||||||
var sinon = require('sinon');
|
var sinon = require('sinon');
|
||||||
|
|
||||||
var locales = require("../../../../red/api/editor/locales");
|
var locales = require("../../../../red/api/editor/locales");
|
||||||
|
var i18n = require("../../../../red/util/i18n");
|
||||||
|
|
||||||
|
|
||||||
describe("api/editor/locales", function() {
|
describe("api/editor/locales", function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
@ -30,24 +32,18 @@ describe("api/editor/locales", function() {
|
|||||||
var app;
|
var app;
|
||||||
before(function() {
|
before(function() {
|
||||||
// bit of a mess of internal workings
|
// bit of a mess of internal workings
|
||||||
locales.init({
|
locales.init({});
|
||||||
i18n: {
|
sinon.stub(i18n.i,'lng',function() { return 'en-US'});
|
||||||
i: {
|
sinon.stub(i18n.i,'setLng',function(lang,callback) { if (callback) {callback();}});
|
||||||
lng: function() { return 'en-US'},
|
sinon.stub(i18n,'catalog',function(namespace, lang) {return {namespace:namespace, lang:lang};});
|
||||||
setLng: function(lang,callback) {
|
|
||||||
if (callback) {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
catalog: function(namespace, lang) {
|
|
||||||
return {namespace:namespace, lang:lang};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
app = express();
|
app = express();
|
||||||
app.get(/locales\/(.+)\/?$/,locales.get);
|
app.get(/locales\/(.+)\/?$/,locales.get);
|
||||||
});
|
});
|
||||||
|
after(function() {
|
||||||
|
i18n.i.lng.restore();
|
||||||
|
i18n.i.setLng.restore();
|
||||||
|
i18n.catalog.restore();
|
||||||
|
})
|
||||||
it('returns with default language', function(done) {
|
it('returns with default language', function(done) {
|
||||||
request(app)
|
request(app)
|
||||||
.get("/locales/message-catalog")
|
.get("/locales/message-catalog")
|
||||||
@ -79,30 +75,31 @@ describe("api/editor/locales", function() {
|
|||||||
var app;
|
var app;
|
||||||
before(function() {
|
before(function() {
|
||||||
// bit of a mess of internal workings
|
// bit of a mess of internal workings
|
||||||
locales.init({
|
sinon.stub(i18n,'catalog',function(namespace, lang) {
|
||||||
i18n: {
|
|
||||||
catalog: function(namespace, lang) {
|
|
||||||
return {
|
return {
|
||||||
"node-red": "should not return",
|
"node-red": "should not return",
|
||||||
"test-module-a-id": "test-module-a-catalog",
|
"test-module-a-id": "test-module-a-catalog",
|
||||||
"test-module-b-id": "test-module-b-catalog",
|
"test-module-b-id": "test-module-b-catalog",
|
||||||
"test-module-c-id": "test-module-c-catalog"
|
"test-module-c-id": "test-module-c-catalog"
|
||||||
}[namespace]
|
}[namespace]
|
||||||
}
|
});
|
||||||
},
|
locales.init({
|
||||||
nodes: {
|
nodes: {
|
||||||
getNodeList: function() {
|
getNodeList: function(opts) {
|
||||||
return [
|
return Promise.resolve([
|
||||||
{module:"node-red",id:"node-red-id"},
|
{module:"node-red",id:"node-red-id"},
|
||||||
{module:"test-module-a",id:"test-module-a-id"},
|
{module:"test-module-a",id:"test-module-a-id"},
|
||||||
{module:"test-module-b",id:"test-module-b-id"}
|
{module:"test-module-b",id:"test-module-b-id"}
|
||||||
];
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
app = express();
|
app = express();
|
||||||
app.get("/locales/nodes",locales.getAllNodes);
|
app.get("/locales/nodes",locales.getAllNodes);
|
||||||
});
|
});
|
||||||
|
after(function() {
|
||||||
|
i18n.catalog.restore();
|
||||||
|
})
|
||||||
it('returns with the node catalogs', function(done) {
|
it('returns with the node catalogs', function(done) {
|
||||||
request(app)
|
request(app)
|
||||||
.get("/locales/nodes")
|
.get("/locales/nodes")
|
||||||
|
@ -17,215 +17,103 @@
|
|||||||
var should = require("should");
|
var should = require("should");
|
||||||
var request = require('supertest');
|
var request = require('supertest');
|
||||||
var express = require('express');
|
var express = require('express');
|
||||||
|
var bodyParser = require("body-parser");
|
||||||
var sinon = require('sinon');
|
var sinon = require('sinon');
|
||||||
var when = require('when');
|
|
||||||
|
|
||||||
var app = express();
|
var app;
|
||||||
var info = require("../../../../red/api/editor/settings");
|
var info = require("../../../../red/api/editor/settings");
|
||||||
var theme = require("../../../../red/api/editor/theme");
|
var theme = require("../../../../red/api/editor/theme");
|
||||||
|
|
||||||
describe("api/editor/settings", function() {
|
describe("api/editor/settings", function() {
|
||||||
describe("settings handler", function() {
|
|
||||||
before(function() {
|
before(function() {
|
||||||
sinon.stub(theme,"settings",function() { return { test: 456 };});
|
sinon.stub(theme,"settings",function() { return { test: 456 };});
|
||||||
app = express();
|
app = express();
|
||||||
|
app.use(bodyParser.json());
|
||||||
app.get("/settings",info.runtimeSettings);
|
app.get("/settings",info.runtimeSettings);
|
||||||
|
app.get("/settings/user",function(req,res,next) {req.user = "fred"; next()}, info.userSettings);
|
||||||
|
app.post("/settings/user",function(req,res,next) {req.user = "fred"; next()},info.updateUserSettings);
|
||||||
});
|
});
|
||||||
|
|
||||||
after(function() {
|
after(function() {
|
||||||
theme.settings.restore();
|
theme.settings.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns the filtered settings', function(done) {
|
it('returns the runtime settings', function(done) {
|
||||||
info.init({
|
info.init({
|
||||||
settings: {
|
settings: {
|
||||||
foo: 123,
|
getRuntimeSettings: function(opts) {
|
||||||
httpNodeRoot: "testHttpNodeRoot",
|
return Promise.resolve({
|
||||||
version: "testVersion",
|
a:1,
|
||||||
paletteCategories :["red","blue","green"],
|
b:2
|
||||||
exportNodeSettings: function(obj) {
|
|
||||||
obj.testNodeSetting = "helloWorld";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
nodes: {
|
|
||||||
paletteEditorEnabled: function() { return true; },
|
|
||||||
getCredentialKeyType: function() { return "test-key-type"}
|
|
||||||
},
|
|
||||||
log: { error: console.error },
|
|
||||||
storage: {}
|
|
||||||
});
|
|
||||||
request(app)
|
|
||||||
.get("/settings")
|
|
||||||
.expect(200)
|
|
||||||
.end(function(err,res) {
|
|
||||||
if (err) {
|
|
||||||
return done(err);
|
|
||||||
}
|
|
||||||
res.body.should.have.property("httpNodeRoot","testHttpNodeRoot");
|
|
||||||
res.body.should.have.property("version","testVersion");
|
|
||||||
res.body.should.have.property("paletteCategories",["red","blue","green"]);
|
|
||||||
res.body.should.have.property("editorTheme",{test:456});
|
|
||||||
res.body.should.have.property("testNodeSetting","helloWorld");
|
|
||||||
res.body.should.not.have.property("foo",123);
|
|
||||||
res.body.should.have.property("flowEncryptionType","test-key-type");
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('includes project settings if projects available', function(done) {
|
|
||||||
info.init({
|
|
||||||
settings: {
|
|
||||||
foo: 123,
|
|
||||||
httpNodeRoot: "testHttpNodeRoot",
|
|
||||||
version: "testVersion",
|
|
||||||
paletteCategories :["red","blue","green"],
|
|
||||||
exportNodeSettings: function(obj) {
|
|
||||||
obj.testNodeSetting = "helloWorld";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
nodes: {
|
|
||||||
paletteEditorEnabled: function() { return true; },
|
|
||||||
getCredentialKeyType: function() { return "test-key-type"}
|
|
||||||
},
|
|
||||||
log: { error: console.error },
|
|
||||||
storage: {
|
|
||||||
projects: {
|
|
||||||
getActiveProject: () => 'test-active-project',
|
|
||||||
getFlowFilename: () => 'test-flow-file',
|
|
||||||
getCredentialsFilename: () => 'test-creds-file',
|
|
||||||
getGlobalGitUser: () => {return {name:'foo',email:'foo@example.com'}}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
request(app)
|
|
||||||
.get("/settings")
|
|
||||||
.expect(200)
|
|
||||||
.end(function(err,res) {
|
|
||||||
if (err) {
|
|
||||||
return done(err);
|
|
||||||
}
|
|
||||||
res.body.should.have.property("project","test-active-project");
|
|
||||||
res.body.should.not.have.property("files");
|
|
||||||
res.body.should.have.property("git");
|
|
||||||
res.body.git.should.have.property("globalUser",{name:'foo',email:'foo@example.com'});
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('includes existing files details if projects enabled but no active project and files exist', function(done) {
|
|
||||||
info.init({
|
|
||||||
settings: {
|
|
||||||
foo: 123,
|
|
||||||
httpNodeRoot: "testHttpNodeRoot",
|
|
||||||
version: "testVersion",
|
|
||||||
paletteCategories :["red","blue","green"],
|
|
||||||
exportNodeSettings: function(obj) {
|
|
||||||
obj.testNodeSetting = "helloWorld";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
nodes: {
|
|
||||||
paletteEditorEnabled: function() { return true; },
|
|
||||||
getCredentialKeyType: function() { return "test-key-type"}
|
|
||||||
},
|
|
||||||
log: { error: console.error },
|
|
||||||
storage: {
|
|
||||||
projects: {
|
|
||||||
flowFileExists: () => true,
|
|
||||||
getActiveProject: () => false,
|
|
||||||
getFlowFilename: () => 'test-flow-file',
|
|
||||||
getCredentialsFilename: () => 'test-creds-file',
|
|
||||||
getGlobalGitUser: () => {return {name:'foo',email:'foo@example.com'}}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
request(app)
|
|
||||||
.get("/settings")
|
|
||||||
.expect(200)
|
|
||||||
.end(function(err,res) {
|
|
||||||
if (err) {
|
|
||||||
return done(err);
|
|
||||||
}
|
|
||||||
res.body.should.not.have.property("project");
|
|
||||||
res.body.should.have.property("files");
|
|
||||||
res.body.files.should.have.property("flow",'test-flow-file');
|
|
||||||
res.body.files.should.have.property("credentials",'test-creds-file');
|
|
||||||
res.body.should.have.property("git");
|
|
||||||
res.body.git.should.have.property("globalUser",{name:'foo',email:'foo@example.com'});
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('does not include file details if projects enabled but no active project and files do not exist', function(done) {
|
|
||||||
info.init({
|
|
||||||
settings: {
|
|
||||||
foo: 123,
|
|
||||||
httpNodeRoot: "testHttpNodeRoot",
|
|
||||||
version: "testVersion",
|
|
||||||
paletteCategories :["red","blue","green"],
|
|
||||||
exportNodeSettings: function(obj) {
|
|
||||||
obj.testNodeSetting = "helloWorld";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
nodes: {
|
|
||||||
paletteEditorEnabled: function() { return true; },
|
|
||||||
getCredentialKeyType: function() { return "test-key-type"}
|
|
||||||
},
|
|
||||||
log: { error: console.error },
|
|
||||||
storage: {
|
|
||||||
projects: {
|
|
||||||
flowFileExists: () => false,
|
|
||||||
getActiveProject: () => false,
|
|
||||||
getFlowFilename: () => 'test-flow-file',
|
|
||||||
getCredentialsFilename: () => 'test-creds-file',
|
|
||||||
getGlobalGitUser: () => {return {name:'foo',email:'foo@example.com'}}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
request(app)
|
|
||||||
.get("/settings")
|
|
||||||
.expect(200)
|
|
||||||
.end(function(err,res) {
|
|
||||||
if (err) {
|
|
||||||
return done(err);
|
|
||||||
}
|
|
||||||
res.body.should.not.have.property("project");
|
|
||||||
res.body.should.not.have.property("files");
|
|
||||||
res.body.should.have.property("git");
|
|
||||||
res.body.git.should.have.property("globalUser",{name:'foo',email:'foo@example.com'});
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('overrides palette editable if runtime says it is disabled', function(done) {
|
|
||||||
info.init({
|
|
||||||
settings: {
|
|
||||||
httpNodeRoot: "testHttpNodeRoot",
|
|
||||||
version: "testVersion",
|
|
||||||
paletteCategories :["red","blue","green"],
|
|
||||||
exportNodeSettings: function() {}
|
|
||||||
},
|
|
||||||
nodes: {
|
|
||||||
paletteEditorEnabled: function() { return false; },
|
|
||||||
getCredentialKeyType: function() { return "test-key-type"}
|
|
||||||
|
|
||||||
},
|
|
||||||
log: { error: console.error },
|
|
||||||
storage: {}
|
|
||||||
|
|
||||||
});
|
|
||||||
request(app)
|
|
||||||
.get("/settings")
|
|
||||||
.expect(200)
|
|
||||||
.end(function(err,res) {
|
|
||||||
if (err) {
|
|
||||||
return done(err);
|
|
||||||
}
|
|
||||||
res.body.should.have.property("httpNodeRoot","testHttpNodeRoot");
|
|
||||||
res.body.should.have.property("version","testVersion");
|
|
||||||
res.body.should.have.property("paletteCategories",["red","blue","green"]);
|
|
||||||
res.body.should.have.property("editorTheme");
|
|
||||||
res.body.editorTheme.should.have.property("test",456);
|
|
||||||
|
|
||||||
res.body.editorTheme.should.have.property("palette",{editable:false});
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
request(app)
|
||||||
|
.get("/settings")
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property("a",1);
|
||||||
|
res.body.should.have.property("b",2);
|
||||||
|
res.body.should.have.property("editorTheme",{test:456});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('returns the user settings', function(done) {
|
||||||
|
info.init({
|
||||||
|
settings: {
|
||||||
|
getUserSettings: function(opts) {
|
||||||
|
if (opts.user !== "fred") {
|
||||||
|
return Promise.reject(new Error("Unknown user"));
|
||||||
|
}
|
||||||
|
return Promise.resolve({
|
||||||
|
c:3,
|
||||||
|
d:4
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
request(app)
|
||||||
|
.get("/settings/user")
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.eql({c:3,d:4});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('updates the user settings', function(done) {
|
||||||
|
var update;
|
||||||
|
info.init({
|
||||||
|
settings: {
|
||||||
|
updateUserSettings: function(opts) {
|
||||||
|
if (opts.user !== "fred") {
|
||||||
|
return Promise.reject(new Error("Unknown user"));
|
||||||
|
}
|
||||||
|
update = opts.settings;
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
request(app)
|
||||||
|
.post("/settings/user")
|
||||||
|
.send({
|
||||||
|
e:4,
|
||||||
|
f:5
|
||||||
|
})
|
||||||
|
.expect(204)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
update.should.eql({e:4,f:5});
|
||||||
|
done();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -18,83 +18,42 @@ var should = require("should");
|
|||||||
var sinon = require("sinon");
|
var sinon = require("sinon");
|
||||||
var request = require("supertest");
|
var request = require("supertest");
|
||||||
var express = require("express");
|
var express = require("express");
|
||||||
var editorApi = require("../../../../red/api/editor");
|
|
||||||
var comms = require("../../../../red/api/editor/comms");
|
|
||||||
var info = require("../../../../red/api/editor/settings");
|
|
||||||
var auth = require("../../../../red/api/auth");
|
|
||||||
var sshkeys = require("../../../../red/api/editor/sshkeys");
|
var sshkeys = require("../../../../red/api/editor/sshkeys");
|
||||||
var when = require("when");
|
|
||||||
var bodyParser = require("body-parser");
|
var bodyParser = require("body-parser");
|
||||||
var fs = require("fs-extra");
|
|
||||||
var fspath = require("path");
|
|
||||||
|
|
||||||
|
|
||||||
describe("api/editor/sshkeys", function() {
|
describe("api/editor/sshkeys", function() {
|
||||||
var app;
|
var app;
|
||||||
var mockList = [
|
|
||||||
'library','theme','locales','credentials','comms'
|
|
||||||
]
|
|
||||||
var isStarted = true;
|
|
||||||
var errors = [];
|
|
||||||
var session_data = {};
|
|
||||||
|
|
||||||
var mockRuntime = {
|
var mockRuntime = {
|
||||||
settings: {
|
settings: {
|
||||||
httpNodeRoot: true,
|
getUserKeys: function() {},
|
||||||
httpAdminRoot: true,
|
getUserKey: function() {},
|
||||||
disableEditor: false,
|
generateUserKey: function() {},
|
||||||
exportNodeSettings:function(){},
|
removeUserKey: function() {}
|
||||||
storage: {
|
|
||||||
getSessions: function(){
|
|
||||||
return when.resolve(session_data);
|
|
||||||
},
|
|
||||||
setSessions: function(_session) {
|
|
||||||
session_data = _session;
|
|
||||||
return when.resolve();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
log:{audit:function(){},error:function(msg){errors.push(msg)},trace:function(){}},
|
|
||||||
storage: {
|
|
||||||
projects: {
|
|
||||||
ssh: {
|
|
||||||
init: function(){},
|
|
||||||
listSSHKeys: function(){},
|
|
||||||
getSSHKey: function(){},
|
|
||||||
generateSSHKey: function(){},
|
|
||||||
deleteSSHKey: function(){}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
events:{on:function(){},removeListener:function(){}},
|
|
||||||
isStarted: function() { return isStarted; },
|
|
||||||
nodes: {paletteEditorEnabled: function() { return false }}
|
|
||||||
};
|
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
auth.init(mockRuntime);
|
sshkeys.init(mockRuntime);
|
||||||
app = express();
|
app = express();
|
||||||
app.use(bodyParser.json());
|
app.use(bodyParser.json());
|
||||||
app.use(editorApi.init({},mockRuntime));
|
app.use("/settings/user/keys", sshkeys.app());
|
||||||
});
|
});
|
||||||
after(function() {
|
|
||||||
})
|
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
sinon.stub(mockRuntime.storage.projects.ssh, "listSSHKeys");
|
sinon.stub(mockRuntime.settings, "getUserKeys");
|
||||||
sinon.stub(mockRuntime.storage.projects.ssh, "getSSHKey");
|
sinon.stub(mockRuntime.settings, "getUserKey");
|
||||||
sinon.stub(mockRuntime.storage.projects.ssh, "generateSSHKey");
|
sinon.stub(mockRuntime.settings, "generateUserKey");
|
||||||
sinon.stub(mockRuntime.storage.projects.ssh, "deleteSSHKey");
|
sinon.stub(mockRuntime.settings, "removeUserKey");
|
||||||
})
|
})
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
mockRuntime.storage.projects.ssh.listSSHKeys.restore();
|
mockRuntime.settings.getUserKeys.restore();
|
||||||
mockRuntime.storage.projects.ssh.getSSHKey.restore();
|
mockRuntime.settings.getUserKey.restore();
|
||||||
mockRuntime.storage.projects.ssh.generateSSHKey.restore();
|
mockRuntime.settings.generateUserKey.restore();
|
||||||
mockRuntime.storage.projects.ssh.deleteSSHKey.restore();
|
mockRuntime.settings.removeUserKey.restore();
|
||||||
})
|
})
|
||||||
|
|
||||||
it('GET /settings/user/keys --- return empty list', function(done) {
|
it('GET /settings/user/keys --- return empty list', function(done) {
|
||||||
mockRuntime.storage.projects.ssh.listSSHKeys.returns(Promise.resolve([]));
|
mockRuntime.settings.getUserKeys.returns(Promise.resolve([]));
|
||||||
request(app)
|
request(app)
|
||||||
.get("/settings/user/keys")
|
.get("/settings/user/keys")
|
||||||
.expect(200)
|
.expect(200)
|
||||||
@ -118,7 +77,7 @@ describe("api/editor/sshkeys", function() {
|
|||||||
name: elem
|
name: elem
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
mockRuntime.storage.projects.ssh.listSSHKeys.returns(Promise.resolve(retList));
|
mockRuntime.settings.getUserKeys.returns(Promise.resolve(retList));
|
||||||
request(app)
|
request(app)
|
||||||
.get("/settings/user/keys")
|
.get("/settings/user/keys")
|
||||||
.expect(200)
|
.expect(200)
|
||||||
@ -139,16 +98,16 @@ describe("api/editor/sshkeys", function() {
|
|||||||
errInstance.code = "test_code";
|
errInstance.code = "test_code";
|
||||||
var p = Promise.reject(errInstance);
|
var p = Promise.reject(errInstance);
|
||||||
p.catch(()=>{});
|
p.catch(()=>{});
|
||||||
mockRuntime.storage.projects.ssh.listSSHKeys.returns(p);
|
mockRuntime.settings.getUserKeys.returns(p);
|
||||||
request(app)
|
request(app)
|
||||||
.get("/settings/user/keys")
|
.get("/settings/user/keys")
|
||||||
.expect(400)
|
.expect(500)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return done(err);
|
return done(err);
|
||||||
}
|
}
|
||||||
res.body.should.have.property('error');
|
res.body.should.have.property('code');
|
||||||
res.body.error.should.be.equal(errInstance.code);
|
res.body.code.should.be.equal(errInstance.code);
|
||||||
res.body.should.have.property('message');
|
res.body.should.have.property('message');
|
||||||
res.body.message.should.be.equal(errInstance.message);
|
res.body.message.should.be.equal(errInstance.message);
|
||||||
done();
|
done();
|
||||||
@ -156,7 +115,12 @@ describe("api/editor/sshkeys", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('GET /settings/user/keys/<key_file_name> --- return 404', function(done) {
|
it('GET /settings/user/keys/<key_file_name> --- return 404', function(done) {
|
||||||
mockRuntime.storage.projects.ssh.getSSHKey.returns(Promise.resolve(null));
|
var errInstance = new Error("Not Found.");
|
||||||
|
errInstance.code = "not_found";
|
||||||
|
errInstance.status = 404;
|
||||||
|
var p = Promise.reject(errInstance);
|
||||||
|
p.catch(()=>{});
|
||||||
|
mockRuntime.settings.getUserKey.returns(p);
|
||||||
request(app)
|
request(app)
|
||||||
.get("/settings/user/keys/NOT_REAL")
|
.get("/settings/user/keys/NOT_REAL")
|
||||||
.expect(404)
|
.expect(404)
|
||||||
@ -168,19 +132,19 @@ describe("api/editor/sshkeys", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('GET /settings/user/keys --- return Unexpected Error', function(done) {
|
it('GET /settings/user/keys --- return Unexpected Error', function(done) {
|
||||||
var errInstance = new Error("Messages.....");
|
var errInstance = new Error();
|
||||||
var p = Promise.reject(errInstance);
|
var p = Promise.reject(errInstance);
|
||||||
p.catch(()=>{});
|
p.catch(()=>{});
|
||||||
mockRuntime.storage.projects.ssh.listSSHKeys.returns(p);
|
mockRuntime.settings.getUserKeys.returns(p)
|
||||||
request(app)
|
request(app)
|
||||||
.get("/settings/user/keys")
|
.get("/settings/user/keys")
|
||||||
.expect(400)
|
.expect(500)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return done(err);
|
return done(err);
|
||||||
}
|
}
|
||||||
res.body.should.have.property('error');
|
res.body.should.have.property('code');
|
||||||
res.body.error.should.be.equal("unexpected_error");
|
res.body.code.should.be.equal("unexpected_error");
|
||||||
res.body.should.have.property('message');
|
res.body.should.have.property('message');
|
||||||
res.body.message.should.be.equal(errInstance.toString());
|
res.body.message.should.be.equal(errInstance.toString());
|
||||||
done();
|
done();
|
||||||
@ -190,7 +154,7 @@ describe("api/editor/sshkeys", function() {
|
|||||||
it('GET /settings/user/keys/<key_file_name> --- return content', function(done) {
|
it('GET /settings/user/keys/<key_file_name> --- return content', function(done) {
|
||||||
var key_file_name = "test_key";
|
var key_file_name = "test_key";
|
||||||
var fileContent = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQD3a+sgtgzSbbliWxmOq5p6+H/mE+0gjWfLWrkIVmHENd1mifV4uCmIHAR2NfuadUYMQ3+bQ90kpmmEKTMYPsyentsKpHQZxTzG7wOCAIpJnbPTHDMxEJhVTaAwEjbVyMSIzTTPfnhoavWIBu0+uMgKDDlBm+RjlgkFlyhXyCN6UwFrIUUMH6Gw+eQHLiooKIl8ce7uDxIlt+9b7hFCU+sQ3kvuse239DZluu6+8buMWqJvrEHgzS9adRFKku8nSPAEPYn85vDi7OgVAcLQufknNgs47KHBAx9h04LeSrFJ/P5J1b//ItRpMOIme+O9d1BR46puzhvUaCHLdvO9czj+OmW+dIm+QIk6lZIOOMnppG72kZxtLfeKT16ur+2FbwAdL9ItBp4BI/YTlBPoa5mLMxpuWfmX1qHntvtGc9wEwS1P7YFfmF3XiK5apxalzrn0Qlr5UmDNbVIqJb1OlbC0w03Z0oktti1xT+R2DGOLWM4lBbpXDHV1BhQ7oYOvbUD8Cnof55lTP0WHHsOHlQc/BGDti1XA9aBX/OzVyzBUYEf0pkimsD0RYo6aqt7QwehJYdlz9x1NBguBffT0s4NhNb9IWr+ASnFPvNl2sw4XH/8U0J0q8ZkMpKkbLM1Zdp1Fv00GF0f5UNRokai6uM3w/ccantJ3WvZ6GtctqytWrw== \n";
|
var fileContent = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQD3a+sgtgzSbbliWxmOq5p6+H/mE+0gjWfLWrkIVmHENd1mifV4uCmIHAR2NfuadUYMQ3+bQ90kpmmEKTMYPsyentsKpHQZxTzG7wOCAIpJnbPTHDMxEJhVTaAwEjbVyMSIzTTPfnhoavWIBu0+uMgKDDlBm+RjlgkFlyhXyCN6UwFrIUUMH6Gw+eQHLiooKIl8ce7uDxIlt+9b7hFCU+sQ3kvuse239DZluu6+8buMWqJvrEHgzS9adRFKku8nSPAEPYn85vDi7OgVAcLQufknNgs47KHBAx9h04LeSrFJ/P5J1b//ItRpMOIme+O9d1BR46puzhvUaCHLdvO9czj+OmW+dIm+QIk6lZIOOMnppG72kZxtLfeKT16ur+2FbwAdL9ItBp4BI/YTlBPoa5mLMxpuWfmX1qHntvtGc9wEwS1P7YFfmF3XiK5apxalzrn0Qlr5UmDNbVIqJb1OlbC0w03Z0oktti1xT+R2DGOLWM4lBbpXDHV1BhQ7oYOvbUD8Cnof55lTP0WHHsOHlQc/BGDti1XA9aBX/OzVyzBUYEf0pkimsD0RYo6aqt7QwehJYdlz9x1NBguBffT0s4NhNb9IWr+ASnFPvNl2sw4XH/8U0J0q8ZkMpKkbLM1Zdp1Fv00GF0f5UNRokai6uM3w/ccantJ3WvZ6GtctqytWrw== \n";
|
||||||
mockRuntime.storage.projects.ssh.getSSHKey.returns(Promise.resolve(fileContent));
|
mockRuntime.settings.getUserKey.returns(Promise.resolve(fileContent));
|
||||||
request(app)
|
request(app)
|
||||||
.get("/settings/user/keys/" + key_file_name)
|
.get("/settings/user/keys/" + key_file_name)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
@ -198,7 +162,8 @@ describe("api/editor/sshkeys", function() {
|
|||||||
if (err) {
|
if (err) {
|
||||||
return done(err);
|
return done(err);
|
||||||
}
|
}
|
||||||
mockRuntime.storage.projects.ssh.getSSHKey.called.should.be.true();
|
mockRuntime.settings.getUserKey.called.should.be.true();
|
||||||
|
mockRuntime.settings.getUserKey.firstCall.args[0].should.eql({ user: undefined, id: 'test_key' });
|
||||||
res.body.should.be.deepEqual({ publickey: fileContent });
|
res.body.should.be.deepEqual({ publickey: fileContent });
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -210,16 +175,16 @@ describe("api/editor/sshkeys", function() {
|
|||||||
errInstance.code = "test_code";
|
errInstance.code = "test_code";
|
||||||
var p = Promise.reject(errInstance);
|
var p = Promise.reject(errInstance);
|
||||||
p.catch(()=>{});
|
p.catch(()=>{});
|
||||||
mockRuntime.storage.projects.ssh.getSSHKey.returns(p);
|
mockRuntime.settings.getUserKey.returns(p);
|
||||||
request(app)
|
request(app)
|
||||||
.get("/settings/user/keys/" + key_file_name)
|
.get("/settings/user/keys/" + key_file_name)
|
||||||
.expect(400)
|
.expect(500)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return done(err);
|
return done(err);
|
||||||
}
|
}
|
||||||
res.body.should.have.property('error');
|
res.body.should.have.property('code');
|
||||||
res.body.error.should.be.equal(errInstance.code);
|
res.body.code.should.be.equal(errInstance.code);
|
||||||
res.body.should.have.property('message');
|
res.body.should.have.property('message');
|
||||||
res.body.message.should.be.equal(errInstance.message);
|
res.body.message.should.be.equal(errInstance.message);
|
||||||
done();
|
done();
|
||||||
@ -231,25 +196,25 @@ describe("api/editor/sshkeys", function() {
|
|||||||
var errInstance = new Error("Messages.....");
|
var errInstance = new Error("Messages.....");
|
||||||
var p = Promise.reject(errInstance);
|
var p = Promise.reject(errInstance);
|
||||||
p.catch(()=>{});
|
p.catch(()=>{});
|
||||||
mockRuntime.storage.projects.ssh.getSSHKey.returns(p);
|
mockRuntime.settings.getUserKey.returns(p);
|
||||||
request(app)
|
request(app)
|
||||||
.get("/settings/user/keys/" + key_file_name)
|
.get("/settings/user/keys/" + key_file_name)
|
||||||
.expect(400)
|
.expect(500)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return done(err);
|
return done(err);
|
||||||
}
|
}
|
||||||
res.body.should.have.property('error');
|
res.body.should.have.property('code');
|
||||||
res.body.error.should.be.equal("unexpected_error");
|
res.body.code.should.be.equal("unexpected_error");
|
||||||
res.body.should.have.property('message');
|
res.body.should.have.property('message');
|
||||||
res.body.message.should.be.equal(errInstance.toString());
|
res.body.message.should.be.equal("Messages.....");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('POST /settings/user/keys --- success', function(done) {
|
it('POST /settings/user/keys --- success', function(done) {
|
||||||
var key_file_name = "test_key";
|
var key_file_name = "test_key";
|
||||||
mockRuntime.storage.projects.ssh.generateSSHKey.returns(Promise.resolve(key_file_name));
|
mockRuntime.settings.generateUserKey.returns(Promise.resolve(key_file_name));
|
||||||
request(app)
|
request(app)
|
||||||
.post("/settings/user/keys")
|
.post("/settings/user/keys")
|
||||||
.send({ name: key_file_name })
|
.send({ name: key_file_name })
|
||||||
@ -262,41 +227,23 @@ describe("api/editor/sshkeys", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('POST /settings/user/keys --- return parameter error', function(done) {
|
|
||||||
var key_file_name = "test_key";
|
|
||||||
mockRuntime.storage.projects.ssh.generateSSHKey.returns(Promise.resolve(key_file_name));
|
|
||||||
request(app)
|
|
||||||
.post("/settings/user/keys")
|
|
||||||
.expect(400)
|
|
||||||
.end(function(err,res) {
|
|
||||||
if (err) {
|
|
||||||
return done(err);
|
|
||||||
}
|
|
||||||
res.body.should.have.property('error');
|
|
||||||
res.body.error.should.be.equal("unexpected_error");
|
|
||||||
res.body.should.have.property('message');
|
|
||||||
res.body.message.should.be.equal("You need to have body or body.name");
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('POST /settings/user/keys --- return Error', function(done) {
|
it('POST /settings/user/keys --- return Error', function(done) {
|
||||||
var key_file_name = "test_key";
|
var key_file_name = "test_key";
|
||||||
var errInstance = new Error("Messages.....");
|
var errInstance = new Error("Messages.....");
|
||||||
errInstance.code = "test_code";
|
errInstance.code = "test_code";
|
||||||
var p = Promise.reject(errInstance);
|
var p = Promise.reject(errInstance);
|
||||||
p.catch(()=>{});
|
p.catch(()=>{});
|
||||||
mockRuntime.storage.projects.ssh.generateSSHKey.returns(p);
|
mockRuntime.settings.generateUserKey.returns(p);
|
||||||
request(app)
|
request(app)
|
||||||
.post("/settings/user/keys")
|
.post("/settings/user/keys")
|
||||||
.send({ name: key_file_name })
|
.send({ name: key_file_name })
|
||||||
.expect(400)
|
.expect(500)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return done(err);
|
return done(err);
|
||||||
}
|
}
|
||||||
res.body.should.have.property('error');
|
res.body.should.have.property('code');
|
||||||
res.body.error.should.be.equal("test_code");
|
res.body.code.should.be.equal("test_code");
|
||||||
res.body.should.have.property('message');
|
res.body.should.have.property('message');
|
||||||
res.body.message.should.be.equal(errInstance.message);
|
res.body.message.should.be.equal(errInstance.message);
|
||||||
done();
|
done();
|
||||||
@ -308,26 +255,26 @@ describe("api/editor/sshkeys", function() {
|
|||||||
var errInstance = new Error("Messages.....");
|
var errInstance = new Error("Messages.....");
|
||||||
var p = Promise.reject(errInstance);
|
var p = Promise.reject(errInstance);
|
||||||
p.catch(()=>{});
|
p.catch(()=>{});
|
||||||
mockRuntime.storage.projects.ssh.generateSSHKey.returns(p);
|
mockRuntime.settings.generateUserKey.returns(p);
|
||||||
request(app)
|
request(app)
|
||||||
.post("/settings/user/keys")
|
.post("/settings/user/keys")
|
||||||
.send({ name: key_file_name })
|
.send({ name: key_file_name })
|
||||||
.expect(400)
|
.expect(500)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return done(err);
|
return done(err);
|
||||||
}
|
}
|
||||||
res.body.should.have.property('error');
|
res.body.should.have.property('code');
|
||||||
res.body.error.should.be.equal("unexpected_error");
|
res.body.code.should.be.equal("unexpected_error");
|
||||||
res.body.should.have.property('message');
|
res.body.should.have.property('message');
|
||||||
res.body.message.should.be.equal(errInstance.toString());
|
res.body.message.should.be.equal("Messages.....");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('DELETE /settings/user/keys/<key_file_name> --- success', function(done) {
|
it('DELETE /settings/user/keys/<key_file_name> --- success', function(done) {
|
||||||
var key_file_name = "test_key";
|
var key_file_name = "test_key";
|
||||||
mockRuntime.storage.projects.ssh.deleteSSHKey.returns(Promise.resolve(true));
|
mockRuntime.settings.removeUserKey.returns(Promise.resolve(true));
|
||||||
request(app)
|
request(app)
|
||||||
.delete("/settings/user/keys/" + key_file_name)
|
.delete("/settings/user/keys/" + key_file_name)
|
||||||
.expect(204)
|
.expect(204)
|
||||||
@ -346,16 +293,16 @@ describe("api/editor/sshkeys", function() {
|
|||||||
errInstance.code = "test_code";
|
errInstance.code = "test_code";
|
||||||
var p = Promise.reject(errInstance);
|
var p = Promise.reject(errInstance);
|
||||||
p.catch(()=>{});
|
p.catch(()=>{});
|
||||||
mockRuntime.storage.projects.ssh.deleteSSHKey.returns(p);
|
mockRuntime.settings.removeUserKey.returns(p);
|
||||||
request(app)
|
request(app)
|
||||||
.delete("/settings/user/keys/" + key_file_name)
|
.delete("/settings/user/keys/" + key_file_name)
|
||||||
.expect(400)
|
.expect(500)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return done(err);
|
return done(err);
|
||||||
}
|
}
|
||||||
res.body.should.have.property('error');
|
res.body.should.have.property('code');
|
||||||
res.body.error.should.be.equal("test_code");
|
res.body.code.should.be.equal("test_code");
|
||||||
res.body.should.have.property('message');
|
res.body.should.have.property('message');
|
||||||
res.body.message.should.be.equal(errInstance.message);
|
res.body.message.should.be.equal(errInstance.message);
|
||||||
done();
|
done();
|
||||||
@ -367,18 +314,18 @@ describe("api/editor/sshkeys", function() {
|
|||||||
var errInstance = new Error("Messages.....");
|
var errInstance = new Error("Messages.....");
|
||||||
var p = Promise.reject(errInstance);
|
var p = Promise.reject(errInstance);
|
||||||
p.catch(()=>{});
|
p.catch(()=>{});
|
||||||
mockRuntime.storage.projects.ssh.deleteSSHKey.returns(p);
|
mockRuntime.settings.removeUserKey.returns(p);
|
||||||
request(app)
|
request(app)
|
||||||
.delete("/settings/user/keys/" + key_file_name)
|
.delete("/settings/user/keys/" + key_file_name)
|
||||||
.expect(400)
|
.expect(500)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return done(err);
|
return done(err);
|
||||||
}
|
}
|
||||||
res.body.should.have.property('error');
|
res.body.should.have.property('code');
|
||||||
res.body.error.should.be.equal("unexpected_error");
|
res.body.code.should.be.equal("unexpected_error");
|
||||||
res.body.should.have.property('message');
|
res.body.should.have.property('message');
|
||||||
res.body.message.should.be.equal(errInstance.toString());
|
res.body.message.should.be.equal('Messages.....');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -33,7 +33,7 @@ describe("api/editor/theme", function() {
|
|||||||
fs.statSync.restore();
|
fs.statSync.restore();
|
||||||
});
|
});
|
||||||
it("applies the default theme", function() {
|
it("applies the default theme", function() {
|
||||||
var result = theme.init({settings:{},version:function() { return '123.456'}});
|
var result = theme.init({});
|
||||||
should.not.exist(result);
|
should.not.exist(result);
|
||||||
|
|
||||||
var context = theme.context();
|
var context = theme.context();
|
||||||
@ -43,13 +43,12 @@ describe("api/editor/theme", function() {
|
|||||||
context.should.have.a.property("header");
|
context.should.have.a.property("header");
|
||||||
context.header.should.have.a.property("title","Node-RED");
|
context.header.should.have.a.property("title","Node-RED");
|
||||||
context.header.should.have.a.property("image","red/images/node-red.png");
|
context.header.should.have.a.property("image","red/images/node-red.png");
|
||||||
context.should.have.a.property("version","123.456");
|
|
||||||
|
|
||||||
should.not.exist(theme.settings());
|
should.not.exist(theme.settings());
|
||||||
});
|
});
|
||||||
|
|
||||||
it("picks up custom theme", function() {
|
it("picks up custom theme", function() {
|
||||||
theme.init({settings:{
|
theme.init({
|
||||||
editorTheme: {
|
editorTheme: {
|
||||||
page: {
|
page: {
|
||||||
title: "Test Page Title",
|
title: "Test Page Title",
|
||||||
@ -84,7 +83,7 @@ describe("api/editor/theme", function() {
|
|||||||
image: "/absolute/path/to/login/page/big/image" // a 256x256 image
|
image: "/absolute/path/to/login/page/big/image" // a 256x256 image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}});
|
});
|
||||||
|
|
||||||
theme.app();
|
theme.app();
|
||||||
|
|
||||||
|
@ -20,8 +20,6 @@ var express = require("express");
|
|||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
|
|
||||||
var EventEmitter = require('events').EventEmitter;
|
|
||||||
var events = new EventEmitter();
|
|
||||||
var ui = require("../../../../red/api/editor/ui");
|
var ui = require("../../../../red/api/editor/ui");
|
||||||
|
|
||||||
|
|
||||||
@ -30,10 +28,13 @@ describe("api/editor/ui", function() {
|
|||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
ui.init({
|
ui.init({
|
||||||
events:events,
|
|
||||||
nodes: {
|
nodes: {
|
||||||
getNodeIconPath: function(module,icon) {
|
getIcon: function(opts) {
|
||||||
return path.resolve(__dirname+'/../../../../public/icons/arrow-in.png');
|
return new Promise(function(resolve,reject) {
|
||||||
|
fs.readFile(path.resolve(__dirname+'/../../../../public/icons/arrow-in.png'), function(err,data) {
|
||||||
|
resolve(data);
|
||||||
|
})
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -23,7 +23,6 @@ var fs = require("fs");
|
|||||||
var path = require("path");
|
var path = require("path");
|
||||||
var api = require("../../../red/api");
|
var api = require("../../../red/api");
|
||||||
|
|
||||||
var apiUtil = require("../../../red/api/util");
|
|
||||||
var apiAuth = require("../../../red/api/auth");
|
var apiAuth = require("../../../red/api/auth");
|
||||||
var apiEditor = require("../../../red/api/editor");
|
var apiEditor = require("../../../red/api/editor");
|
||||||
var apiAdmin = require("../../../red/api/admin");
|
var apiAdmin = require("../../../red/api/admin");
|
||||||
@ -31,7 +30,6 @@ var apiAdmin = require("../../../red/api/admin");
|
|||||||
|
|
||||||
describe("api/index", function() {
|
describe("api/index", function() {
|
||||||
var beforeEach = function() {
|
var beforeEach = function() {
|
||||||
sinon.stub(apiUtil,"init",function(){});
|
|
||||||
sinon.stub(apiAuth,"init",function(){});
|
sinon.stub(apiAuth,"init",function(){});
|
||||||
sinon.stub(apiEditor,"init",function(){
|
sinon.stub(apiEditor,"init",function(){
|
||||||
var app = express();
|
var app = express();
|
||||||
@ -48,7 +46,6 @@ describe("api/index", function() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
var afterEach = function() {
|
var afterEach = function() {
|
||||||
apiUtil.init.restore();
|
|
||||||
apiAuth.init.restore();
|
apiAuth.init.restore();
|
||||||
apiAuth.login.restore();
|
apiAuth.login.restore();
|
||||||
apiEditor.init.restore();
|
apiEditor.init.restore();
|
||||||
@ -59,18 +56,14 @@ describe("api/index", function() {
|
|||||||
afterEach(afterEach);
|
afterEach(afterEach);
|
||||||
|
|
||||||
it("does not setup admin api if httpAdminRoot is false", function(done) {
|
it("does not setup admin api if httpAdminRoot is false", function(done) {
|
||||||
api.init({},{
|
api.init({},{ httpAdminRoot: false },{},{});
|
||||||
settings: { httpAdminRoot: false }
|
|
||||||
});
|
|
||||||
should.not.exist(api.adminApp);
|
should.not.exist(api.adminApp);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
describe('initalises admin api without adminAuth', function(done) {
|
describe('initalises admin api without adminAuth', function(done) {
|
||||||
before(function() {
|
before(function() {
|
||||||
beforeEach();
|
beforeEach();
|
||||||
api.init({},{
|
api.init({},{},{},{});
|
||||||
settings: { }
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
after(afterEach);
|
after(afterEach);
|
||||||
it('exposes the editor',function(done) {
|
it('exposes the editor',function(done) {
|
||||||
@ -87,9 +80,7 @@ describe("api/index", function() {
|
|||||||
describe('initalises admin api without editor', function(done) {
|
describe('initalises admin api without editor', function(done) {
|
||||||
before(function() {
|
before(function() {
|
||||||
beforeEach();
|
beforeEach();
|
||||||
api.init({},{
|
api.init({},{ disableEditor: true },{},{});
|
||||||
settings: { disableEditor: true }
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
after(afterEach);
|
after(afterEach);
|
||||||
it('does not expose the editor',function(done) {
|
it('does not expose the editor',function(done) {
|
||||||
|
@ -15,11 +15,17 @@
|
|||||||
**/
|
**/
|
||||||
|
|
||||||
var should = require("should");
|
var should = require("should");
|
||||||
|
var sinon = require("sinon");
|
||||||
var request = require('supertest');
|
var request = require('supertest');
|
||||||
var express = require('express');
|
var express = require('express');
|
||||||
|
|
||||||
var apiUtil = require("../../../red/api/util");
|
var apiUtil = require("../../../red/api/util");
|
||||||
|
|
||||||
|
var log = require("../../../red/util").log; // TODO: separate module
|
||||||
|
var i18n = require("../../../red/util").i18n; // TODO: separate module
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
describe("api/util", function() {
|
describe("api/util", function() {
|
||||||
describe("errorHandler", function() {
|
describe("errorHandler", function() {
|
||||||
var loggedError = null;
|
var loggedError = null;
|
||||||
@ -27,17 +33,8 @@ describe("api/util", function() {
|
|||||||
var app;
|
var app;
|
||||||
before(function() {
|
before(function() {
|
||||||
app = express();
|
app = express();
|
||||||
apiUtil.init({
|
sinon.stub(log,'error',function(msg) {loggedError = msg;});
|
||||||
log:{
|
sinon.stub(log,'audit',function(event) {loggedEvent = event;});
|
||||||
error: function(msg) {
|
|
||||||
loggedError = msg;
|
|
||||||
},
|
|
||||||
audit: function(event) {
|
|
||||||
loggedEvent = event;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
i18n:{}
|
|
||||||
})
|
|
||||||
app.get("/tooLarge", function(req,res) {
|
app.get("/tooLarge", function(req,res) {
|
||||||
var err = new Error();
|
var err = new Error();
|
||||||
err.message = "request entity too large";
|
err.message = "request entity too large";
|
||||||
@ -49,6 +46,10 @@ describe("api/util", function() {
|
|||||||
throw err;
|
throw err;
|
||||||
},apiUtil.errorHandler)
|
},apiUtil.errorHandler)
|
||||||
});
|
});
|
||||||
|
after(function() {
|
||||||
|
log.error.restore();
|
||||||
|
log.audit.restore();
|
||||||
|
})
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
loggedError = null;
|
loggedError = null;
|
||||||
loggedEvent = null;
|
loggedEvent = null;
|
||||||
@ -91,11 +92,13 @@ describe("api/util", function() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('determineLangFromHeaders', function() {
|
describe('determineLangFromHeaders', function() {
|
||||||
|
var oldDefaultLang;
|
||||||
before(function() {
|
before(function() {
|
||||||
apiUtil.init({
|
oldDefaultLang = i18n.defaultLang;
|
||||||
log:{},
|
i18n.defaultLang = "en-US";
|
||||||
i18n:{defaultLang:"en-US"}
|
})
|
||||||
});
|
after(function() {
|
||||||
|
i18n.defaultLang = oldDefaultLang;
|
||||||
})
|
})
|
||||||
it('returns the default lang if non provided', function() {
|
it('returns the default lang if non provided', function() {
|
||||||
apiUtil.determineLangFromHeaders(null).should.eql("en-US");
|
apiUtil.determineLangFromHeaders(null).should.eql("en-US");
|
||||||
|
@ -14,6 +14,229 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
var should = require("should");
|
||||||
|
var sinon = require("sinon");
|
||||||
|
|
||||||
|
var comms = require("../../../red/runtime-api/comms");
|
||||||
|
|
||||||
describe("runtime-api/comms", function() {
|
describe("runtime-api/comms", function() {
|
||||||
it.skip('more tests needed', function(){})
|
describe("listens for events", function() {
|
||||||
|
var messages = [];
|
||||||
|
var clientConnection = {
|
||||||
|
send: function(topic,data) {
|
||||||
|
messages.push({topic,data})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var eventHandlers = {};
|
||||||
|
before(function(done) {
|
||||||
|
comms.init({
|
||||||
|
log: {
|
||||||
|
trace: function(){}
|
||||||
|
},
|
||||||
|
events: {
|
||||||
|
removeListener: function() {},
|
||||||
|
on: function(evt,handler) {
|
||||||
|
eventHandlers[evt] = handler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
comms.addConnection({client: clientConnection}).then(done);
|
||||||
|
})
|
||||||
|
after(function(done) {
|
||||||
|
comms.removeConnection({client: clientConnection}).then(done);
|
||||||
|
})
|
||||||
|
afterEach(function() {
|
||||||
|
messages = [];
|
||||||
|
})
|
||||||
|
|
||||||
|
it('runtime events',function(){
|
||||||
|
eventHandlers.should.have.property('runtime-event');
|
||||||
|
eventHandlers['runtime-event']({
|
||||||
|
id: "my-event",
|
||||||
|
payload: "my-payload"
|
||||||
|
})
|
||||||
|
messages.should.have.length(1);
|
||||||
|
messages[0].should.have.property("topic","notification/my-event");
|
||||||
|
messages[0].should.have.property("data","my-payload")
|
||||||
|
})
|
||||||
|
it('status events',function(){
|
||||||
|
eventHandlers.should.have.property('node-status');
|
||||||
|
eventHandlers['node-status']({
|
||||||
|
id: "my-event",
|
||||||
|
status: "my-status"
|
||||||
|
})
|
||||||
|
messages.should.have.length(1);
|
||||||
|
messages[0].should.have.property("topic","status/my-event");
|
||||||
|
messages[0].should.have.property("data","my-status")
|
||||||
|
})
|
||||||
|
it('comms events',function(){
|
||||||
|
eventHandlers.should.have.property('runtime-event');
|
||||||
|
eventHandlers['comms']({
|
||||||
|
topic: "my-topic",
|
||||||
|
data: "my-payload"
|
||||||
|
})
|
||||||
|
messages.should.have.length(1);
|
||||||
|
messages[0].should.have.property("topic","my-topic");
|
||||||
|
messages[0].should.have.property("data","my-payload")
|
||||||
|
})
|
||||||
|
});
|
||||||
|
describe("manages connections", function() {
|
||||||
|
var eventHandlers = {};
|
||||||
|
var messages = [];
|
||||||
|
var clientConnection1 = {
|
||||||
|
send: function(topic,data) {
|
||||||
|
messages.push({topic,data})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var clientConnection2 = {
|
||||||
|
send: function(topic,data) {
|
||||||
|
messages.push({topic,data})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
before(function() {
|
||||||
|
comms.init({
|
||||||
|
log: {
|
||||||
|
trace: function(){}
|
||||||
|
},
|
||||||
|
events: {
|
||||||
|
removeListener: function() {},
|
||||||
|
on: function(evt,handler) {
|
||||||
|
eventHandlers[evt] = handler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
afterEach(function(done) {
|
||||||
|
comms.removeConnection({client: clientConnection1}).then(function() {
|
||||||
|
comms.removeConnection({client: clientConnection2}).then(done);
|
||||||
|
});
|
||||||
|
messages = [];
|
||||||
|
})
|
||||||
|
it('adds new connections',function(done){
|
||||||
|
eventHandlers['comms']({
|
||||||
|
topic: "my-topic",
|
||||||
|
data: "my-payload"
|
||||||
|
})
|
||||||
|
messages.should.have.length(0);
|
||||||
|
comms.addConnection({client: clientConnection1}).then(function() {
|
||||||
|
eventHandlers['comms']({
|
||||||
|
topic: "my-topic",
|
||||||
|
data: "my-payload"
|
||||||
|
})
|
||||||
|
messages.should.have.length(1);
|
||||||
|
comms.addConnection({client: clientConnection2}).then(function() {
|
||||||
|
eventHandlers['comms']({
|
||||||
|
topic: "my-topic",
|
||||||
|
data: "my-payload"
|
||||||
|
})
|
||||||
|
messages.should.have.length(3);
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('removes connections',function(done){
|
||||||
|
eventHandlers['comms']({
|
||||||
|
topic: "my-topic",
|
||||||
|
data: "my-payload"
|
||||||
|
})
|
||||||
|
messages.should.have.length(0);
|
||||||
|
comms.addConnection({client: clientConnection1}).then(function() {
|
||||||
|
comms.addConnection({client: clientConnection2}).then(function() {
|
||||||
|
eventHandlers['comms']({
|
||||||
|
topic: "my-topic",
|
||||||
|
data: "my-payload"
|
||||||
|
})
|
||||||
|
messages.should.have.length(2);
|
||||||
|
comms.removeConnection({client: clientConnection1}).then(function() {
|
||||||
|
eventHandlers['comms']({
|
||||||
|
topic: "my-topic",
|
||||||
|
data: "my-payload"
|
||||||
|
})
|
||||||
|
messages.should.have.length(3);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("subscriptions", function() {
|
||||||
|
var messages = [];
|
||||||
|
var clientConnection = {
|
||||||
|
send: function(topic,data) {
|
||||||
|
messages.push({topic,data})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var clientConnection2 = {
|
||||||
|
send: function(topic,data) {
|
||||||
|
messages.push({topic,data})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var eventHandlers = {};
|
||||||
|
before(function() {
|
||||||
|
comms.init({
|
||||||
|
log: {
|
||||||
|
trace: function(){}
|
||||||
|
},
|
||||||
|
events: {
|
||||||
|
removeListener: function() {},
|
||||||
|
on: function(evt,handler) {
|
||||||
|
eventHandlers[evt] = handler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
afterEach(function(done) {
|
||||||
|
messages = [];
|
||||||
|
comms.removeConnection({client: clientConnection}).then(done);
|
||||||
|
})
|
||||||
|
|
||||||
|
it('subscribe triggers retained messages',function(done){
|
||||||
|
eventHandlers['comms']({
|
||||||
|
topic: "my-event",
|
||||||
|
data: "my-payload",
|
||||||
|
retain: true
|
||||||
|
})
|
||||||
|
messages.should.have.length(0);
|
||||||
|
comms.addConnection({client: clientConnection}).then(function() {
|
||||||
|
return comms.subscribe({client: clientConnection, topic: "my-event"}).then(function() {
|
||||||
|
messages.should.have.length(1);
|
||||||
|
messages[0].should.have.property("topic","my-event");
|
||||||
|
messages[0].should.have.property("data","my-payload");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
}).catch(done);
|
||||||
|
})
|
||||||
|
it('retained messages get cleared',function(done) {
|
||||||
|
eventHandlers['comms']({
|
||||||
|
topic: "my-event",
|
||||||
|
data: "my-payload",
|
||||||
|
retain: true
|
||||||
|
})
|
||||||
|
messages.should.have.length(0);
|
||||||
|
comms.addConnection({client: clientConnection}).then(function() {
|
||||||
|
return comms.subscribe({client: clientConnection, topic: "my-event"}).then(function() {
|
||||||
|
messages.should.have.length(1);
|
||||||
|
messages[0].should.have.property("topic","my-event");
|
||||||
|
messages[0].should.have.property("data","my-payload");
|
||||||
|
// Now we have a retained message, clear it
|
||||||
|
eventHandlers['comms']({
|
||||||
|
topic: "my-event",
|
||||||
|
data: "my-payload-cleared"
|
||||||
|
});
|
||||||
|
messages.should.have.length(2);
|
||||||
|
messages[1].should.have.property("topic","my-event");
|
||||||
|
messages[1].should.have.property("data","my-payload-cleared");
|
||||||
|
// Now add a second client and subscribe - no message should arrive
|
||||||
|
return comms.addConnection({client: clientConnection2}).then(function() {
|
||||||
|
return comms.subscribe({client: clientConnection2, topic: "my-event"}).then(function() {
|
||||||
|
messages.should.have.length(2);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -17,3 +17,275 @@
|
|||||||
describe("runtime-api/flows", function() {
|
describe("runtime-api/flows", function() {
|
||||||
it.skip('more tests needed', function(){})
|
it.skip('more tests needed', function(){})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
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 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({
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
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]}; }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
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) {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
});
|
||||||
|
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('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')
|
||||||
|
.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();
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
*/
|
||||||
|
@ -14,6 +14,41 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
var should = require("should");
|
||||||
|
var sinon = require("sinon");
|
||||||
|
|
||||||
|
var index = require("../../../red/runtime-api/index");
|
||||||
|
|
||||||
|
|
||||||
describe("runtime-api/index", function() {
|
describe("runtime-api/index", function() {
|
||||||
it.skip('more tests needed', function(){})
|
before(function() {
|
||||||
|
["comms","flows","nodes","settings","library","projects"].forEach(n => {
|
||||||
|
sinon.stub(require(`../../../red/runtime-api/${n}`),"init",()=>{});
|
||||||
|
})
|
||||||
|
});
|
||||||
|
after(function() {
|
||||||
|
["comms","flows","nodes","settings","library","projects"].forEach(n => {
|
||||||
|
require(`../../../red/runtime-api/${n}`).init.restore()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
it('isStarted', function(done) {
|
||||||
|
index.init({
|
||||||
|
isStarted: ()=>true
|
||||||
|
});
|
||||||
|
index.isStarted({}).then(function(started) {
|
||||||
|
started.should.be.true();
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
})
|
||||||
|
|
||||||
|
it('isStarted', function(done) {
|
||||||
|
index.init({
|
||||||
|
version: ()=>"1.2.3.4"
|
||||||
|
});
|
||||||
|
index.version({}).then(function(version) {
|
||||||
|
version.should.eql("1.2.3.4");
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
})
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -17,3 +17,342 @@
|
|||||||
describe("runtime-api/library", function() {
|
describe("runtime-api/library", function() {
|
||||||
it.skip('more tests needed', function(){})
|
it.skip('more tests needed', function(){})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
var should = require("should");
|
||||||
|
var sinon = require("sinon");
|
||||||
|
var fs = require("fs");
|
||||||
|
var fspath = require('path');
|
||||||
|
var request = require('supertest');
|
||||||
|
var express = require('express');
|
||||||
|
var bodyParser = require('body-parser');
|
||||||
|
|
||||||
|
var when = require('when');
|
||||||
|
|
||||||
|
var app;
|
||||||
|
var library = require("../../../../red/api/editor/library");
|
||||||
|
var auth = require("../../../../red/api/auth");
|
||||||
|
|
||||||
|
describe("api/editor/library", function() {
|
||||||
|
|
||||||
|
function initLibrary(_flows,_libraryEntries,_examples,_exampleFlowPathFunction) {
|
||||||
|
var flows = _flows;
|
||||||
|
var libraryEntries = _libraryEntries;
|
||||||
|
library.init(app,{
|
||||||
|
log:{audit:function(){},_:function(){},warn:function(){}},
|
||||||
|
storage: {
|
||||||
|
init: function() {
|
||||||
|
return when.resolve();
|
||||||
|
},
|
||||||
|
getAllFlows: function() {
|
||||||
|
return when.resolve(flows);
|
||||||
|
},
|
||||||
|
getFlow: function(fn) {
|
||||||
|
if (flows[fn]) {
|
||||||
|
return when.resolve(flows[fn]);
|
||||||
|
} else if (fn.indexOf("..")!==-1) {
|
||||||
|
var err = new Error();
|
||||||
|
err.code = 'forbidden';
|
||||||
|
return when.reject(err);
|
||||||
|
} else {
|
||||||
|
return when.reject();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
saveFlow: function(fn,data) {
|
||||||
|
if (fn.indexOf("..")!==-1) {
|
||||||
|
var err = new Error();
|
||||||
|
err.code = 'forbidden';
|
||||||
|
return when.reject(err);
|
||||||
|
}
|
||||||
|
flows[fn] = data;
|
||||||
|
return when.resolve();
|
||||||
|
},
|
||||||
|
getLibraryEntry: function(type,path) {
|
||||||
|
if (path.indexOf("..")!==-1) {
|
||||||
|
var err = new Error();
|
||||||
|
err.code = 'forbidden';
|
||||||
|
return when.reject(err);
|
||||||
|
}
|
||||||
|
if (libraryEntries[type] && libraryEntries[type][path]) {
|
||||||
|
return when.resolve(libraryEntries[type][path]);
|
||||||
|
} else {
|
||||||
|
return when.reject();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
saveLibraryEntry: function(type,path,meta,body) {
|
||||||
|
if (path.indexOf("..")!==-1) {
|
||||||
|
var err = new Error();
|
||||||
|
err.code = 'forbidden';
|
||||||
|
return when.reject(err);
|
||||||
|
}
|
||||||
|
libraryEntries[type][path] = body;
|
||||||
|
return when.resolve();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
events: {
|
||||||
|
on: function(){},
|
||||||
|
removeListener: function(){}
|
||||||
|
},
|
||||||
|
nodes: {
|
||||||
|
getNodeExampleFlows: function() {
|
||||||
|
return _examples;
|
||||||
|
},
|
||||||
|
getNodeExampleFlowPath: _exampleFlowPathFunction
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("flows", function() {
|
||||||
|
before(function() {
|
||||||
|
app = express();
|
||||||
|
app.use(bodyParser.json());
|
||||||
|
app.get("/library/flows",library.getAll);
|
||||||
|
app.post(new RegExp("/library/flows\/(.*)"),library.post);
|
||||||
|
app.get(new RegExp("/library/flows\/(.*)"),library.get);
|
||||||
|
app.response.sendFile = function (path) {
|
||||||
|
app.response.json.call(this, {sendFile: path});
|
||||||
|
};
|
||||||
|
sinon.stub(fs,"statSync",function() { return true; });
|
||||||
|
});
|
||||||
|
after(function() {
|
||||||
|
fs.statSync.restore();
|
||||||
|
});
|
||||||
|
it('returns empty result', function(done) {
|
||||||
|
initLibrary({},{flows:{}});
|
||||||
|
request(app)
|
||||||
|
.get('/library/flows')
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
res.body.should.not.have.property('f');
|
||||||
|
res.body.should.not.have.property('d');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns 404 for non-existent entry', function(done) {
|
||||||
|
initLibrary({},{flows:{}});
|
||||||
|
request(app)
|
||||||
|
.get('/library/flows/foo')
|
||||||
|
.expect(404)
|
||||||
|
.end(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('can store and retrieve item', function(done) {
|
||||||
|
initLibrary({},{flows:{}});
|
||||||
|
var flow = '[]';
|
||||||
|
request(app)
|
||||||
|
.post('/library/flows/foo')
|
||||||
|
.set('Content-Type', 'application/json')
|
||||||
|
.send(flow)
|
||||||
|
.expect(204).end(function (err, res) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
request(app)
|
||||||
|
.get('/library/flows/foo')
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
res.text.should.equal(flow);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('lists a stored item', function(done) {
|
||||||
|
initLibrary({f:["bar"]});
|
||||||
|
request(app)
|
||||||
|
.get('/library/flows')
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
res.body.should.have.property('f');
|
||||||
|
should.deepEqual(res.body.f,['bar']);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns 403 for malicious get attempt', function(done) {
|
||||||
|
initLibrary({});
|
||||||
|
// without the userDir override the malicious url would be
|
||||||
|
// http://127.0.0.1:1880/library/flows/../../package to
|
||||||
|
// obtain package.json from the node-red root.
|
||||||
|
request(app)
|
||||||
|
.get('/library/flows/../../../../../package')
|
||||||
|
.expect(403)
|
||||||
|
.end(done);
|
||||||
|
});
|
||||||
|
it('returns 403 for malicious post attempt', function(done) {
|
||||||
|
initLibrary({});
|
||||||
|
// without the userDir override the malicious url would be
|
||||||
|
// http://127.0.0.1:1880/library/flows/../../package to
|
||||||
|
// obtain package.json from the node-red root.
|
||||||
|
request(app)
|
||||||
|
.post('/library/flows/../../../../../package')
|
||||||
|
.expect(403)
|
||||||
|
.end(done);
|
||||||
|
});
|
||||||
|
it('includes examples flows if set', function(done) {
|
||||||
|
var examples = {"d":{"node-module":{"f":["example-one"]}}};
|
||||||
|
initLibrary({},{},examples);
|
||||||
|
request(app)
|
||||||
|
.get('/library/flows')
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
res.body.should.have.property('d');
|
||||||
|
res.body.d.should.have.property('_examples_');
|
||||||
|
should.deepEqual(res.body.d._examples_,examples);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can retrieve an example flow', function(done) {
|
||||||
|
var examples = {"d":{"node-module":{"f":["example-one"]}}};
|
||||||
|
initLibrary({},{},examples,function(module,path) {
|
||||||
|
return module + ':' + path
|
||||||
|
});
|
||||||
|
request(app)
|
||||||
|
.get('/library/flows/_examples_/node-module/example-one')
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
res.body.should.have.property('sendFile',
|
||||||
|
'node-module:example-one');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can retrieve an example flow in an org scoped package', function(done) {
|
||||||
|
var examples = {"d":{"@org_scope/node_package":{"f":["example-one"]}}};
|
||||||
|
initLibrary({},{},examples,function(module,path) {
|
||||||
|
return module + ':' + path
|
||||||
|
});
|
||||||
|
request(app)
|
||||||
|
.get('/library/flows/_examples_/@org_scope/node_package/example-one')
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
res.body.should.have.property('sendFile',
|
||||||
|
'@org_scope/node_package:example-one');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("type", function() {
|
||||||
|
before(function() {
|
||||||
|
|
||||||
|
app = express();
|
||||||
|
app.use(bodyParser.json());
|
||||||
|
initLibrary({},{});
|
||||||
|
auth.init({settings:{}});
|
||||||
|
library.register("test");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns empty result', function(done) {
|
||||||
|
initLibrary({},{'test':{"":[]}});
|
||||||
|
request(app)
|
||||||
|
.get('/library/test')
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
res.body.should.not.have.property('f');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns 404 for non-existent entry', function(done) {
|
||||||
|
initLibrary({},{});
|
||||||
|
request(app)
|
||||||
|
.get('/library/test/foo')
|
||||||
|
.expect(404)
|
||||||
|
.end(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can store and retrieve item', function(done) {
|
||||||
|
initLibrary({},{'test':{}});
|
||||||
|
var flow = {text:"test content"};
|
||||||
|
request(app)
|
||||||
|
.post('/library/test/foo')
|
||||||
|
.set('Content-Type', 'application/json')
|
||||||
|
.send(flow)
|
||||||
|
.expect(204).end(function (err, res) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
request(app)
|
||||||
|
.get('/library/test/foo')
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
res.text.should.equal(flow.text);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('lists a stored item', function(done) {
|
||||||
|
initLibrary({},{'test':{'a':['abc','def']}});
|
||||||
|
request(app)
|
||||||
|
.get('/library/test/a')
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
// This response isn't strictly accurate - but it
|
||||||
|
// verifies the api returns what storage gave it
|
||||||
|
should.deepEqual(res.body,['abc','def']);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('returns 403 for malicious access attempt', function(done) {
|
||||||
|
request(app)
|
||||||
|
.get('/library/test/../../../../../../../../../../etc/passwd')
|
||||||
|
.expect(403)
|
||||||
|
.end(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns 403 for malicious access attempt', function(done) {
|
||||||
|
request(app)
|
||||||
|
.get('/library/test/..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\etc\\passwd')
|
||||||
|
.expect(403)
|
||||||
|
.end(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns 403 for malicious access attempt', function(done) {
|
||||||
|
request(app)
|
||||||
|
.post('/library/test/../../../../../../../../../../etc/passwd')
|
||||||
|
.set('Content-Type', 'text/plain')
|
||||||
|
.send('root:x:0:0:root:/root:/usr/bin/tclsh')
|
||||||
|
.expect(403)
|
||||||
|
.end(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
*/
|
||||||
|
@ -17,3 +17,829 @@
|
|||||||
describe("runtime-api/nodes", function() {
|
describe("runtime-api/nodes", function() {
|
||||||
it.skip('more tests needed', function(){})
|
it.skip('more tests needed', function(){})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
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;
|
||||||
|
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.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,nodes.putSet);
|
||||||
|
app.get("/getIcons",nodes.getIcons);
|
||||||
|
app.delete("/nodes/:id",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) {
|
||||||
|
initNodes({
|
||||||
|
nodes:{
|
||||||
|
getNodeList: function() {
|
||||||
|
return [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) {
|
||||||
|
initNodes({
|
||||||
|
nodes:{
|
||||||
|
getNodeConfigs: function() {
|
||||||
|
return "<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) {
|
||||||
|
initNodes({
|
||||||
|
nodes:{
|
||||||
|
getModuleInfo: function(id) {
|
||||||
|
return {"node-red":{name:"node-red"}}[id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
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) {
|
||||||
|
initNodes({
|
||||||
|
nodes:{
|
||||||
|
getModuleInfo: function(id) {
|
||||||
|
return {"node-red":{name:"node-red"}}[id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
request(app)
|
||||||
|
.get('/nodes/node-blue')
|
||||||
|
.expect(404)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns individual node info', function(done) {
|
||||||
|
initNodes({
|
||||||
|
nodes:{
|
||||||
|
getNodeInfo: function(id) {
|
||||||
|
return {"node-red/123":{id:"node-red/123"}}[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) {
|
||||||
|
initNodes({
|
||||||
|
nodes:{
|
||||||
|
getNodeConfig: function(id) {
|
||||||
|
return {"node-red/123":"<script></script>"}[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) {
|
||||||
|
initNodes({
|
||||||
|
nodes:{
|
||||||
|
getNodeInfo: function(id) {
|
||||||
|
return {"node-red/123":{id:"node-red/123"}}[id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
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('returns 400 if settings are unavailable', function(done) {
|
||||||
|
initNodes({
|
||||||
|
settings:{available:function(){return false}}
|
||||||
|
});
|
||||||
|
request(app)
|
||||||
|
.post('/nodes')
|
||||||
|
.expect(400)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
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}}
|
||||||
|
});
|
||||||
|
|
||||||
|
request(app)
|
||||||
|
.del('/nodes/123')
|
||||||
|
.expect(400)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
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}}
|
||||||
|
});
|
||||||
|
request(app)
|
||||||
|
.put('/nodes/node-red/foo')
|
||||||
|
.send({})
|
||||||
|
.expect(400)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
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}},
|
||||||
|
nodes:{
|
||||||
|
getNodeInfo: function() { return null }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
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})
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
res.body.should.have.property("id","123");
|
||||||
|
res.body.should.have.property("enabled",true);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('disables enabled node', function(done) {
|
||||||
|
initNodes({
|
||||||
|
settings:{available:function(){return true}},
|
||||||
|
nodes:{
|
||||||
|
getNodeInfo: function() { return {id:"123",enabled: true} },
|
||||||
|
disableNode: function() { return when.resolve({id:"123",enabled: false,types:['a']}); }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
request(app)
|
||||||
|
.put('/nodes/node-red/foo')
|
||||||
|
.send({enabled:false})
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
res.body.should.have.property("id","123");
|
||||||
|
res.body.should.have.property("enabled",false);
|
||||||
|
|
||||||
|
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}},
|
||||||
|
nodes:{
|
||||||
|
getModuleInfo: function() { return {name:"node-red", nodes:[n1, n2]} },
|
||||||
|
enableNode: enableNode
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
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");
|
||||||
|
res.body.should.have.property("nodes");
|
||||||
|
res.body.nodes[0].should.have.property("enabled",true);
|
||||||
|
res.body.nodes[1].should.have.property("enabled",true);
|
||||||
|
|
||||||
|
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:{
|
||||||
|
getNodeIcons: function() {
|
||||||
|
return {"module":["1.png","2.png","3.png"]};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
request(app)
|
||||||
|
.get('/getIcons')
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
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);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
*/
|
||||||
|
@ -17,3 +17,569 @@
|
|||||||
describe("runtime-api/settings", function() {
|
describe("runtime-api/settings", function() {
|
||||||
it.skip('more tests needed', function(){})
|
it.skip('more tests needed', function(){})
|
||||||
});
|
});
|
||||||
|
/*
|
||||||
|
it('returns the filtered settings', function(done) {
|
||||||
|
info.init({
|
||||||
|
settings: {
|
||||||
|
foo: 123,
|
||||||
|
httpNodeRoot: "testHttpNodeRoot",
|
||||||
|
version: "testVersion",
|
||||||
|
paletteCategories :["red","blue","green"],
|
||||||
|
exportNodeSettings: function(obj) {
|
||||||
|
obj.testNodeSetting = "helloWorld";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
nodes: {
|
||||||
|
paletteEditorEnabled: function() { return true; },
|
||||||
|
getCredentialKeyType: function() { return "test-key-type"}
|
||||||
|
},
|
||||||
|
log: { error: console.error },
|
||||||
|
storage: {}
|
||||||
|
});
|
||||||
|
request(app)
|
||||||
|
.get("/settings")
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property("httpNodeRoot","testHttpNodeRoot");
|
||||||
|
res.body.should.have.property("version","testVersion");
|
||||||
|
res.body.should.have.property("paletteCategories",["red","blue","green"]);
|
||||||
|
res.body.should.have.property("editorTheme",{test:456});
|
||||||
|
res.body.should.have.property("testNodeSetting","helloWorld");
|
||||||
|
res.body.should.not.have.property("foo",123);
|
||||||
|
res.body.should.have.property("flowEncryptionType","test-key-type");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('includes project settings if projects available', function(done) {
|
||||||
|
info.init({
|
||||||
|
settings: {
|
||||||
|
foo: 123,
|
||||||
|
httpNodeRoot: "testHttpNodeRoot",
|
||||||
|
version: "testVersion",
|
||||||
|
paletteCategories :["red","blue","green"],
|
||||||
|
exportNodeSettings: function(obj) {
|
||||||
|
obj.testNodeSetting = "helloWorld";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
nodes: {
|
||||||
|
paletteEditorEnabled: function() { return true; },
|
||||||
|
getCredentialKeyType: function() { return "test-key-type"}
|
||||||
|
},
|
||||||
|
log: { error: console.error },
|
||||||
|
storage: {
|
||||||
|
projects: {
|
||||||
|
getActiveProject: () => 'test-active-project',
|
||||||
|
getFlowFilename: () => 'test-flow-file',
|
||||||
|
getCredentialsFilename: () => 'test-creds-file',
|
||||||
|
getGlobalGitUser: () => {return {name:'foo',email:'foo@example.com'}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
request(app)
|
||||||
|
.get("/settings")
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property("project","test-active-project");
|
||||||
|
res.body.should.not.have.property("files");
|
||||||
|
res.body.should.have.property("git");
|
||||||
|
res.body.git.should.have.property("globalUser",{name:'foo',email:'foo@example.com'});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('includes existing files details if projects enabled but no active project and files exist', function(done) {
|
||||||
|
info.init({
|
||||||
|
settings: {
|
||||||
|
foo: 123,
|
||||||
|
httpNodeRoot: "testHttpNodeRoot",
|
||||||
|
version: "testVersion",
|
||||||
|
paletteCategories :["red","blue","green"],
|
||||||
|
exportNodeSettings: function(obj) {
|
||||||
|
obj.testNodeSetting = "helloWorld";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
nodes: {
|
||||||
|
paletteEditorEnabled: function() { return true; },
|
||||||
|
getCredentialKeyType: function() { return "test-key-type"}
|
||||||
|
},
|
||||||
|
log: { error: console.error },
|
||||||
|
storage: {
|
||||||
|
projects: {
|
||||||
|
flowFileExists: () => true,
|
||||||
|
getActiveProject: () => false,
|
||||||
|
getFlowFilename: () => 'test-flow-file',
|
||||||
|
getCredentialsFilename: () => 'test-creds-file',
|
||||||
|
getGlobalGitUser: () => {return {name:'foo',email:'foo@example.com'}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
request(app)
|
||||||
|
.get("/settings")
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.not.have.property("project");
|
||||||
|
res.body.should.have.property("files");
|
||||||
|
res.body.files.should.have.property("flow",'test-flow-file');
|
||||||
|
res.body.files.should.have.property("credentials",'test-creds-file');
|
||||||
|
res.body.should.have.property("git");
|
||||||
|
res.body.git.should.have.property("globalUser",{name:'foo',email:'foo@example.com'});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('does not include file details if projects enabled but no active project and files do not exist', function(done) {
|
||||||
|
info.init({
|
||||||
|
settings: {
|
||||||
|
foo: 123,
|
||||||
|
httpNodeRoot: "testHttpNodeRoot",
|
||||||
|
version: "testVersion",
|
||||||
|
paletteCategories :["red","blue","green"],
|
||||||
|
exportNodeSettings: function(obj) {
|
||||||
|
obj.testNodeSetting = "helloWorld";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
nodes: {
|
||||||
|
paletteEditorEnabled: function() { return true; },
|
||||||
|
getCredentialKeyType: function() { return "test-key-type"}
|
||||||
|
},
|
||||||
|
log: { error: console.error },
|
||||||
|
storage: {
|
||||||
|
projects: {
|
||||||
|
flowFileExists: () => false,
|
||||||
|
getActiveProject: () => false,
|
||||||
|
getFlowFilename: () => 'test-flow-file',
|
||||||
|
getCredentialsFilename: () => 'test-creds-file',
|
||||||
|
getGlobalGitUser: () => {return {name:'foo',email:'foo@example.com'}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
request(app)
|
||||||
|
.get("/settings")
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.not.have.property("project");
|
||||||
|
res.body.should.not.have.property("files");
|
||||||
|
res.body.should.have.property("git");
|
||||||
|
res.body.git.should.have.property("globalUser",{name:'foo',email:'foo@example.com'});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('overrides palette editable if runtime says it is disabled', function(done) {
|
||||||
|
info.init({
|
||||||
|
settings: {
|
||||||
|
httpNodeRoot: "testHttpNodeRoot",
|
||||||
|
version: "testVersion",
|
||||||
|
paletteCategories :["red","blue","green"],
|
||||||
|
exportNodeSettings: function() {}
|
||||||
|
},
|
||||||
|
nodes: {
|
||||||
|
paletteEditorEnabled: function() { return false; },
|
||||||
|
getCredentialKeyType: function() { return "test-key-type"}
|
||||||
|
|
||||||
|
},
|
||||||
|
log: { error: console.error },
|
||||||
|
storage: {}
|
||||||
|
|
||||||
|
});
|
||||||
|
request(app)
|
||||||
|
.get("/settings")
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property("httpNodeRoot","testHttpNodeRoot");
|
||||||
|
res.body.should.have.property("version","testVersion");
|
||||||
|
res.body.should.have.property("paletteCategories",["red","blue","green"]);
|
||||||
|
res.body.should.have.property("editorTheme");
|
||||||
|
res.body.editorTheme.should.have.property("test",456);
|
||||||
|
|
||||||
|
res.body.editorTheme.should.have.property("palette",{editable:false});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
|
||||||
|
|
||||||
|
var should = require("should");
|
||||||
|
var sinon = require("sinon");
|
||||||
|
var request = require("supertest");
|
||||||
|
var express = require("express");
|
||||||
|
var editorApi = require("../../../../red/api/editor");
|
||||||
|
var comms = require("../../../../red/api/editor/comms");
|
||||||
|
var info = require("../../../../red/api/editor/settings");
|
||||||
|
var auth = require("../../../../red/api/auth");
|
||||||
|
var sshkeys = require("../../../../red/api/editor/sshkeys");
|
||||||
|
var when = require("when");
|
||||||
|
var bodyParser = require("body-parser");
|
||||||
|
var fs = require("fs-extra");
|
||||||
|
var fspath = require("path");
|
||||||
|
|
||||||
|
|
||||||
|
describe("api/editor/sshkeys", function() {
|
||||||
|
var app;
|
||||||
|
var mockList = [
|
||||||
|
'library','theme','locales','credentials','comms'
|
||||||
|
]
|
||||||
|
var isStarted = true;
|
||||||
|
var errors = [];
|
||||||
|
var session_data = {};
|
||||||
|
|
||||||
|
var mockRuntime = {
|
||||||
|
settings:{
|
||||||
|
httpNodeRoot: true,
|
||||||
|
httpAdminRoot: true,
|
||||||
|
disableEditor: false,
|
||||||
|
exportNodeSettings:function(){},
|
||||||
|
storage: {
|
||||||
|
getSessions: function(){
|
||||||
|
return when.resolve(session_data);
|
||||||
|
},
|
||||||
|
setSessions: function(_session) {
|
||||||
|
session_data = _session;
|
||||||
|
return when.resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
log:{audit:function(){},error:function(msg){errors.push(msg)},trace:function(){}},
|
||||||
|
storage: {
|
||||||
|
projects: {
|
||||||
|
ssh: {
|
||||||
|
init: function(){},
|
||||||
|
listSSHKeys: function(){},
|
||||||
|
getSSHKey: function(){},
|
||||||
|
generateSSHKey: function(){},
|
||||||
|
deleteSSHKey: function(){}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
events:{on:function(){},removeListener:function(){}},
|
||||||
|
isStarted: function() { return isStarted; },
|
||||||
|
nodes: {paletteEditorEnabled: function() { return false }}
|
||||||
|
};
|
||||||
|
|
||||||
|
before(function() {
|
||||||
|
auth.init(mockRuntime);
|
||||||
|
app = express();
|
||||||
|
app.use(bodyParser.json());
|
||||||
|
app.use(editorApi.init({},mockRuntime));
|
||||||
|
});
|
||||||
|
after(function() {
|
||||||
|
})
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
sinon.stub(mockRuntime.storage.projects.ssh, "listSSHKeys");
|
||||||
|
sinon.stub(mockRuntime.storage.projects.ssh, "getSSHKey");
|
||||||
|
sinon.stub(mockRuntime.storage.projects.ssh, "generateSSHKey");
|
||||||
|
sinon.stub(mockRuntime.storage.projects.ssh, "deleteSSHKey");
|
||||||
|
})
|
||||||
|
afterEach(function() {
|
||||||
|
mockRuntime.storage.projects.ssh.listSSHKeys.restore();
|
||||||
|
mockRuntime.storage.projects.ssh.getSSHKey.restore();
|
||||||
|
mockRuntime.storage.projects.ssh.generateSSHKey.restore();
|
||||||
|
mockRuntime.storage.projects.ssh.deleteSSHKey.restore();
|
||||||
|
})
|
||||||
|
|
||||||
|
it('GET /settings/user/keys --- return empty list', function(done) {
|
||||||
|
mockRuntime.storage.projects.ssh.listSSHKeys.returns(Promise.resolve([]));
|
||||||
|
request(app)
|
||||||
|
.get("/settings/user/keys")
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property('keys');
|
||||||
|
res.body.keys.should.be.empty();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('GET /settings/user/keys --- return normal list', function(done) {
|
||||||
|
var fileList = [
|
||||||
|
'test_key01',
|
||||||
|
'test_key02'
|
||||||
|
];
|
||||||
|
var retList = fileList.map(function(elem) {
|
||||||
|
return {
|
||||||
|
name: elem
|
||||||
|
};
|
||||||
|
});
|
||||||
|
mockRuntime.storage.projects.ssh.listSSHKeys.returns(Promise.resolve(retList));
|
||||||
|
request(app)
|
||||||
|
.get("/settings/user/keys")
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property('keys');
|
||||||
|
for (var item of retList) {
|
||||||
|
res.body.keys.should.containEql(item);
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('GET /settings/user/keys --- return Error', function(done) {
|
||||||
|
var errInstance = new Error("Messages here.....");
|
||||||
|
errInstance.code = "test_code";
|
||||||
|
var p = Promise.reject(errInstance);
|
||||||
|
p.catch(()=>{});
|
||||||
|
mockRuntime.storage.projects.ssh.listSSHKeys.returns(p);
|
||||||
|
request(app)
|
||||||
|
.get("/settings/user/keys")
|
||||||
|
.expect(400)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property('error');
|
||||||
|
res.body.error.should.be.equal(errInstance.code);
|
||||||
|
res.body.should.have.property('message');
|
||||||
|
res.body.message.should.be.equal(errInstance.message);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('GET /settings/user/keys/<key_file_name> --- return 404', function(done) {
|
||||||
|
mockRuntime.storage.projects.ssh.getSSHKey.returns(Promise.resolve(null));
|
||||||
|
request(app)
|
||||||
|
.get("/settings/user/keys/NOT_REAL")
|
||||||
|
.expect(404)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('GET /settings/user/keys --- return Unexpected Error', function(done) {
|
||||||
|
var errInstance = new Error("Messages.....");
|
||||||
|
var p = Promise.reject(errInstance);
|
||||||
|
p.catch(()=>{});
|
||||||
|
mockRuntime.storage.projects.ssh.listSSHKeys.returns(p);
|
||||||
|
request(app)
|
||||||
|
.get("/settings/user/keys")
|
||||||
|
.expect(400)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property('error');
|
||||||
|
res.body.error.should.be.equal("unexpected_error");
|
||||||
|
res.body.should.have.property('message');
|
||||||
|
res.body.message.should.be.equal(errInstance.toString());
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('GET /settings/user/keys/<key_file_name> --- return content', function(done) {
|
||||||
|
var key_file_name = "test_key";
|
||||||
|
var fileContent = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQD3a+sgtgzSbbliWxmOq5p6+H/mE+0gjWfLWrkIVmHENd1mifV4uCmIHAR2NfuadUYMQ3+bQ90kpmmEKTMYPsyentsKpHQZxTzG7wOCAIpJnbPTHDMxEJhVTaAwEjbVyMSIzTTPfnhoavWIBu0+uMgKDDlBm+RjlgkFlyhXyCN6UwFrIUUMH6Gw+eQHLiooKIl8ce7uDxIlt+9b7hFCU+sQ3kvuse239DZluu6+8buMWqJvrEHgzS9adRFKku8nSPAEPYn85vDi7OgVAcLQufknNgs47KHBAx9h04LeSrFJ/P5J1b//ItRpMOIme+O9d1BR46puzhvUaCHLdvO9czj+OmW+dIm+QIk6lZIOOMnppG72kZxtLfeKT16ur+2FbwAdL9ItBp4BI/YTlBPoa5mLMxpuWfmX1qHntvtGc9wEwS1P7YFfmF3XiK5apxalzrn0Qlr5UmDNbVIqJb1OlbC0w03Z0oktti1xT+R2DGOLWM4lBbpXDHV1BhQ7oYOvbUD8Cnof55lTP0WHHsOHlQc/BGDti1XA9aBX/OzVyzBUYEf0pkimsD0RYo6aqt7QwehJYdlz9x1NBguBffT0s4NhNb9IWr+ASnFPvNl2sw4XH/8U0J0q8ZkMpKkbLM1Zdp1Fv00GF0f5UNRokai6uM3w/ccantJ3WvZ6GtctqytWrw== \n";
|
||||||
|
mockRuntime.storage.projects.ssh.getSSHKey.returns(Promise.resolve(fileContent));
|
||||||
|
request(app)
|
||||||
|
.get("/settings/user/keys/" + key_file_name)
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
mockRuntime.storage.projects.ssh.getSSHKey.called.should.be.true();
|
||||||
|
res.body.should.be.deepEqual({ publickey: fileContent });
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('GET /settings/user/keys/<key_file_name> --- return Error', function(done) {
|
||||||
|
var key_file_name = "test_key";
|
||||||
|
var errInstance = new Error("Messages.....");
|
||||||
|
errInstance.code = "test_code";
|
||||||
|
var p = Promise.reject(errInstance);
|
||||||
|
p.catch(()=>{});
|
||||||
|
mockRuntime.storage.projects.ssh.getSSHKey.returns(p);
|
||||||
|
request(app)
|
||||||
|
.get("/settings/user/keys/" + key_file_name)
|
||||||
|
.expect(400)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property('error');
|
||||||
|
res.body.error.should.be.equal(errInstance.code);
|
||||||
|
res.body.should.have.property('message');
|
||||||
|
res.body.message.should.be.equal(errInstance.message);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('GET /settings/user/keys/<key_file_name> --- return Unexpected Error', function(done) {
|
||||||
|
var key_file_name = "test_key";
|
||||||
|
var errInstance = new Error("Messages.....");
|
||||||
|
var p = Promise.reject(errInstance);
|
||||||
|
p.catch(()=>{});
|
||||||
|
mockRuntime.storage.projects.ssh.getSSHKey.returns(p);
|
||||||
|
request(app)
|
||||||
|
.get("/settings/user/keys/" + key_file_name)
|
||||||
|
.expect(400)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property('error');
|
||||||
|
res.body.error.should.be.equal("unexpected_error");
|
||||||
|
res.body.should.have.property('message');
|
||||||
|
res.body.message.should.be.equal(errInstance.toString());
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('POST /settings/user/keys --- success', function(done) {
|
||||||
|
var key_file_name = "test_key";
|
||||||
|
mockRuntime.storage.projects.ssh.generateSSHKey.returns(Promise.resolve(key_file_name));
|
||||||
|
request(app)
|
||||||
|
.post("/settings/user/keys")
|
||||||
|
.send({ name: key_file_name })
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('POST /settings/user/keys --- return parameter error', function(done) {
|
||||||
|
var key_file_name = "test_key";
|
||||||
|
mockRuntime.storage.projects.ssh.generateSSHKey.returns(Promise.resolve(key_file_name));
|
||||||
|
request(app)
|
||||||
|
.post("/settings/user/keys")
|
||||||
|
.expect(400)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property('error');
|
||||||
|
res.body.error.should.be.equal("unexpected_error");
|
||||||
|
res.body.should.have.property('message');
|
||||||
|
res.body.message.should.be.equal("You need to have body or body.name");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('POST /settings/user/keys --- return Error', function(done) {
|
||||||
|
var key_file_name = "test_key";
|
||||||
|
var errInstance = new Error("Messages.....");
|
||||||
|
errInstance.code = "test_code";
|
||||||
|
var p = Promise.reject(errInstance);
|
||||||
|
p.catch(()=>{});
|
||||||
|
mockRuntime.storage.projects.ssh.generateSSHKey.returns(p);
|
||||||
|
request(app)
|
||||||
|
.post("/settings/user/keys")
|
||||||
|
.send({ name: key_file_name })
|
||||||
|
.expect(400)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property('error');
|
||||||
|
res.body.error.should.be.equal("test_code");
|
||||||
|
res.body.should.have.property('message');
|
||||||
|
res.body.message.should.be.equal(errInstance.message);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('POST /settings/user/keys --- return Unexpected error', function(done) {
|
||||||
|
var key_file_name = "test_key";
|
||||||
|
var errInstance = new Error("Messages.....");
|
||||||
|
var p = Promise.reject(errInstance);
|
||||||
|
p.catch(()=>{});
|
||||||
|
mockRuntime.storage.projects.ssh.generateSSHKey.returns(p);
|
||||||
|
request(app)
|
||||||
|
.post("/settings/user/keys")
|
||||||
|
.send({ name: key_file_name })
|
||||||
|
.expect(400)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property('error');
|
||||||
|
res.body.error.should.be.equal("unexpected_error");
|
||||||
|
res.body.should.have.property('message');
|
||||||
|
res.body.message.should.be.equal(errInstance.toString());
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('DELETE /settings/user/keys/<key_file_name> --- success', function(done) {
|
||||||
|
var key_file_name = "test_key";
|
||||||
|
mockRuntime.storage.projects.ssh.deleteSSHKey.returns(Promise.resolve(true));
|
||||||
|
request(app)
|
||||||
|
.delete("/settings/user/keys/" + key_file_name)
|
||||||
|
.expect(204)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.be.deepEqual({});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('DELETE /settings/user/keys/<key_file_name> --- return Error', function(done) {
|
||||||
|
var key_file_name = "test_key";
|
||||||
|
var errInstance = new Error("Messages.....");
|
||||||
|
errInstance.code = "test_code";
|
||||||
|
var p = Promise.reject(errInstance);
|
||||||
|
p.catch(()=>{});
|
||||||
|
mockRuntime.storage.projects.ssh.deleteSSHKey.returns(p);
|
||||||
|
request(app)
|
||||||
|
.delete("/settings/user/keys/" + key_file_name)
|
||||||
|
.expect(400)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property('error');
|
||||||
|
res.body.error.should.be.equal("test_code");
|
||||||
|
res.body.should.have.property('message');
|
||||||
|
res.body.message.should.be.equal(errInstance.message);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('DELETE /settings/user/keys/<key_file_name> --- return Unexpected Error', function(done) {
|
||||||
|
var key_file_name = "test_key";
|
||||||
|
var errInstance = new Error("Messages.....");
|
||||||
|
var p = Promise.reject(errInstance);
|
||||||
|
p.catch(()=>{});
|
||||||
|
mockRuntime.storage.projects.ssh.deleteSSHKey.returns(p);
|
||||||
|
request(app)
|
||||||
|
.delete("/settings/user/keys/" + key_file_name)
|
||||||
|
.expect(400)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property('error');
|
||||||
|
res.body.error.should.be.equal("unexpected_error");
|
||||||
|
res.body.should.have.property('message');
|
||||||
|
res.body.message.should.be.equal(errInstance.toString());
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
**/
|
**/
|
||||||
var should = require("should");
|
var should = require("should");
|
||||||
var when = require("when");
|
|
||||||
var sinon = require("sinon");
|
var sinon = require("sinon");
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
|
|
||||||
@ -45,6 +44,7 @@ describe("runtime", function() {
|
|||||||
log: sinon.stub(),
|
log: sinon.stub(),
|
||||||
warn: sinon.stub(),
|
warn: sinon.stub(),
|
||||||
info: sinon.stub(),
|
info: sinon.stub(),
|
||||||
|
trace: sinon.stub(),
|
||||||
metric: sinon.stub().returns(!!metrics),
|
metric: sinon.stub().returns(!!metrics),
|
||||||
_: function() { return "abc"}
|
_: function() { return "abc"}
|
||||||
},
|
},
|
||||||
@ -90,11 +90,11 @@ describe("runtime", function() {
|
|||||||
var redNodesLoadFlows;
|
var redNodesLoadFlows;
|
||||||
var redNodesStartFlows;
|
var redNodesStartFlows;
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
storageInit = sinon.stub(storage,"init",function(settings) {return when.resolve();});
|
storageInit = sinon.stub(storage,"init",function(settings) {return Promise.resolve();});
|
||||||
redNodesInit = sinon.stub(redNodes,"init", function() {});
|
redNodesInit = sinon.stub(redNodes,"init", function() {});
|
||||||
redNodesLoad = sinon.stub(redNodes,"load", function() {return when.resolve()});
|
redNodesLoad = sinon.stub(redNodes,"load", function() {return Promise.resolve()});
|
||||||
redNodesCleanModuleList = sinon.stub(redNodes,"cleanModuleList",function(){});
|
redNodesCleanModuleList = sinon.stub(redNodes,"cleanModuleList",function(){});
|
||||||
redNodesLoadFlows = sinon.stub(redNodes,"loadFlows",function() {return when.resolve()});
|
redNodesLoadFlows = sinon.stub(redNodes,"loadFlows",function() {return Promise.resolve()});
|
||||||
redNodesStartFlows = sinon.stub(redNodes,"startFlows",function() {});
|
redNodesStartFlows = sinon.stub(redNodes,"startFlows",function() {});
|
||||||
});
|
});
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
@ -114,7 +114,7 @@ describe("runtime", function() {
|
|||||||
].filter(cb);
|
].filter(cb);
|
||||||
});
|
});
|
||||||
var util = mockUtil();
|
var util = mockUtil();
|
||||||
runtime.init({testSettings: true, httpAdminRoot:"/", load:function() { return when.resolve();}},util);
|
runtime.init({testSettings: true, httpAdminRoot:"/", load:function() { return Promise.resolve();}},util);
|
||||||
// sinon.stub(console,"log");
|
// sinon.stub(console,"log");
|
||||||
runtime.start().then(function() {
|
runtime.start().then(function() {
|
||||||
// console.log.restore();
|
// console.log.restore();
|
||||||
@ -143,9 +143,9 @@ describe("runtime", function() {
|
|||||||
{ module:"node-red",enabled:true,loaded:false,types:["typeC","typeD"]} // missing
|
{ module:"node-red",enabled:true,loaded:false,types:["typeC","typeD"]} // missing
|
||||||
].filter(cb);
|
].filter(cb);
|
||||||
});
|
});
|
||||||
var serverInstallModule = sinon.stub(redNodes,"installModule",function(name) { return when.resolve({nodes:[]});});
|
var serverInstallModule = sinon.stub(redNodes,"installModule",function(name) { return Promise.resolve({nodes:[]});});
|
||||||
var util = mockUtil();
|
var util = mockUtil();
|
||||||
runtime.init({testSettings: true, autoInstallModules:true, httpAdminRoot:"/", load:function() { return when.resolve();}},util);
|
runtime.init({testSettings: true, autoInstallModules:true, httpAdminRoot:"/", load:function() { return Promise.resolve();}},util);
|
||||||
sinon.stub(console,"log");
|
sinon.stub(console,"log");
|
||||||
runtime.start().then(function() {
|
runtime.start().then(function() {
|
||||||
console.log.restore();
|
console.log.restore();
|
||||||
@ -172,7 +172,7 @@ describe("runtime", function() {
|
|||||||
].filter(cb);
|
].filter(cb);
|
||||||
});
|
});
|
||||||
var util = mockUtil();
|
var util = mockUtil();
|
||||||
runtime.init({testSettings: true, verbose:true, httpAdminRoot:"/", load:function() { return when.resolve();}},util);
|
runtime.init({testSettings: true, verbose:true, httpAdminRoot:"/", load:function() { return Promise.resolve();}},util);
|
||||||
sinon.stub(console,"log");
|
sinon.stub(console,"log");
|
||||||
runtime.start().then(function() {
|
runtime.start().then(function() {
|
||||||
console.log.restore();
|
console.log.restore();
|
||||||
@ -190,7 +190,7 @@ describe("runtime", function() {
|
|||||||
var stopFlows = sinon.stub(redNodes,"stopFlows",function() {} );
|
var stopFlows = sinon.stub(redNodes,"stopFlows",function() {} );
|
||||||
redNodesGetNodeList = sinon.stub(redNodes,"getNodeList", function() {return []});
|
redNodesGetNodeList = sinon.stub(redNodes,"getNodeList", function() {return []});
|
||||||
var util = mockUtil(true);
|
var util = mockUtil(true);
|
||||||
runtime.init({testSettings: true, runtimeMetricInterval:200, httpAdminRoot:"/", load:function() { return when.resolve();}},util);
|
runtime.init({testSettings: true, runtimeMetricInterval:200, httpAdminRoot:"/", load:function() { return Promise.resolve();}},util);
|
||||||
sinon.stub(console,"log");
|
sinon.stub(console,"log");
|
||||||
runtime.start().then(function() {
|
runtime.start().then(function() {
|
||||||
console.log.restore();
|
console.log.restore();
|
||||||
|
@ -14,6 +14,167 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
var should = require("should");
|
||||||
|
var sinon = require("sinon");
|
||||||
|
var fs = require("fs");
|
||||||
|
|
||||||
|
var library = require("../../../../red/runtime/library/index")
|
||||||
|
|
||||||
|
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/library", function() {
|
describe("runtime/library", function() {
|
||||||
it.skip('more tests needed', function(){})
|
describe("register", function() {
|
||||||
|
// it("throws error for duplicate type", function() {
|
||||||
|
// library.init({});
|
||||||
|
// library.register("unknown","/abc");
|
||||||
|
// should(()=>{library.register("unknown","/abc")} ).throw();
|
||||||
|
// })
|
||||||
|
})
|
||||||
|
describe("getEntry", function() {
|
||||||
|
before(function() {
|
||||||
|
library.init({
|
||||||
|
log: mockLog,
|
||||||
|
storage: {
|
||||||
|
getLibraryEntry: function(type,path) {
|
||||||
|
return Promise.resolve({type,path});
|
||||||
|
},
|
||||||
|
getFlow: function(path) {
|
||||||
|
return Promise.resolve({path});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
nodes: {
|
||||||
|
getNodeExampleFlowPath: function(module,entryPath) {
|
||||||
|
if (module === "unknown") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return "/tmp/"+module+"/"+entryPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sinon.stub(fs,"readFile", function(path,opts,callback) {
|
||||||
|
if (path === "/tmp/test-module/abc") {
|
||||||
|
callback(null,"Example flow result");
|
||||||
|
} else if (path === "/tmp/@scope/test-module/abc") {
|
||||||
|
callback(null,"Example scope flow result");
|
||||||
|
} else if (path === "/tmp/test-module/throw") {
|
||||||
|
throw new Error("Instant error")
|
||||||
|
} else {
|
||||||
|
callback(new Error("Unexpected path:"+path))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
after(function() {
|
||||||
|
fs.readFile.restore();
|
||||||
|
})
|
||||||
|
it('throws error for unregistered type', function() {
|
||||||
|
should(()=>{library.getEntry("unknown","/abc")} ).throw();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns a registered non-flow entry', function(done) {
|
||||||
|
library.register("test-module","test-type");
|
||||||
|
library.getEntry("test-type","/abc").then(function(result) {
|
||||||
|
result.should.have.property("type","test-type")
|
||||||
|
result.should.have.property("path","/abc")
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it ('returns a flow entry', function(done) {
|
||||||
|
library.getEntry("flows","/abc").then(function(result) {
|
||||||
|
result.should.have.property("path","/abc")
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it ('returns a flow example entry', function(done) {
|
||||||
|
library.getEntry("flows","_examples_/test-module/abc").then(function(result) {
|
||||||
|
result.should.eql("Example flow result");
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it ('returns a flow example entry from scoped module', function(done) {
|
||||||
|
library.getEntry("flows","_examples_/@scope/test-module/abc").then(function(result) {
|
||||||
|
result.should.eql("Example scope flow result");
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
it ('returns an error for unknown flow example entry', function(done) {
|
||||||
|
library.getEntry("flows","_examples_/unknown/abc").then(function(result) {
|
||||||
|
done(new Error("No error thrown"))
|
||||||
|
}).catch(function(err) {
|
||||||
|
err.should.have.property("code","not_found");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it ('returns an error for file load error - async', function(done) {
|
||||||
|
library.getEntry("flows","_examples_/test-module/unknown").then(function(result) {
|
||||||
|
done(new Error("No error thrown"))
|
||||||
|
}).catch(function(err) {
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it ('returns an error for file load error - sync', function(done) {
|
||||||
|
library.getEntry("flows","_examples_/test-module/throw").then(function(result) {
|
||||||
|
done(new Error("No error thrown"))
|
||||||
|
}).catch(function(err) {
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("saveEntry", function() {
|
||||||
|
before(function() {
|
||||||
|
library.init({
|
||||||
|
log: mockLog,
|
||||||
|
storage: {
|
||||||
|
saveLibraryEntry: function(type, path, meta, body) {
|
||||||
|
return Promise.resolve({type,path,meta,body})
|
||||||
|
},
|
||||||
|
saveFlow: function(path,body) {
|
||||||
|
return Promise.resolve({path,body});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
nodes: {
|
||||||
|
getNodeExampleFlowPath: function(module,entryPath) {
|
||||||
|
if (module === "unknown") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return "/tmp/"+module+"/"+entryPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('throws error for unregistered type', function() {
|
||||||
|
should(()=>{library.saveEntry("unknown","/abc",{id:"meta"},{id:"body"})} ).throw();
|
||||||
|
});
|
||||||
|
it('saves a flow entry', function(done) {
|
||||||
|
library.saveEntry('flows','/abc',{id:"meta"},{id:"body"}).then(function(result) {
|
||||||
|
result.should.have.property("path","/abc");
|
||||||
|
result.should.have.property("body",{id:"body"});
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
})
|
||||||
|
it('saves a non-flow entry', function(done) {
|
||||||
|
library.register("test-module","test-type");
|
||||||
|
library.saveEntry('test-type','/abc',{id:"meta"},{id:"body"}).then(function(result) {
|
||||||
|
result.should.have.property("type","test-type");
|
||||||
|
result.should.have.property("path","/abc");
|
||||||
|
result.should.have.property("meta",{id:"meta"});
|
||||||
|
result.should.have.property("body",{id:"body"});
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
})
|
||||||
|
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -110,7 +110,7 @@ describe('Node', function() {
|
|||||||
p.then(function() {
|
p.then(function() {
|
||||||
callbacksClosed.should.eql(3);
|
callbacksClosed.should.eql(3);
|
||||||
testdone();
|
testdone();
|
||||||
}).otherwise(function(e) {
|
}).catch(function(e) {
|
||||||
testdone(e);
|
testdone(e);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -427,7 +427,7 @@ describe('red/runtime/nodes/credentials', function() {
|
|||||||
// credentials.dirty().should.be.true();
|
// credentials.dirty().should.be.true();
|
||||||
// should.not.exist(credentials.get("node"));
|
// should.not.exist(credentials.get("node"));
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
err.should.have.property('code','credentials_load_failed');
|
err.should.have.property('code','credentials_load_failed');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -443,7 +443,7 @@ describe('red/runtime/nodes/credentials', function() {
|
|||||||
// credentials.dirty().should.be.true();
|
// credentials.dirty().should.be.true();
|
||||||
// should.not.exist(credentials.get("node"));
|
// should.not.exist(credentials.get("node"));
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
err.should.have.property('code','credentials_load_failed');
|
err.should.have.property('code','credentials_load_failed');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -524,7 +524,7 @@ describe('flows/index', function() {
|
|||||||
]
|
]
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
done(new Error('failed to reject duplicate node id'));
|
done(new Error('failed to reject duplicate node id'));
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done();
|
done();
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
@ -559,7 +559,7 @@ describe('flows/index', function() {
|
|||||||
createdFlows.should.have.lengthOf(3);
|
createdFlows.should.have.lengthOf(3);
|
||||||
createdFlows[2].should.eql(id);
|
createdFlows[2].should.eql(id);
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
@ -19,7 +19,6 @@ var fs = require('fs-extra');
|
|||||||
var path = require('path');
|
var path = require('path');
|
||||||
var when = require("when");
|
var when = require("when");
|
||||||
var sinon = require('sinon');
|
var sinon = require('sinon');
|
||||||
console.log(__dirname);
|
|
||||||
var index = require("../../../../red/runtime/nodes/index");
|
var index = require("../../../../red/runtime/nodes/index");
|
||||||
var flows = require("../../../../red/runtime/nodes/flows");
|
var flows = require("../../../../red/runtime/nodes/flows");
|
||||||
var registry = require("../../../../red/runtime/nodes/registry");
|
var registry = require("../../../../red/runtime/nodes/registry");
|
||||||
@ -81,7 +80,7 @@ describe("red/nodes/index", function() {
|
|||||||
testnode.credentials.should.have.property('c',"2");
|
testnode.credentials.should.have.property('c',"2");
|
||||||
testnode.credentials.should.have.property('d',"bar");
|
testnode.credentials.should.have.property('d',"bar");
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -93,7 +92,7 @@ describe("red/nodes/index", function() {
|
|||||||
// console.log(index.getFlows());
|
// console.log(index.getFlows());
|
||||||
should.deepEqual(testFlows, index.getFlows().flows);
|
should.deepEqual(testFlows, index.getFlows().flows);
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -258,7 +257,7 @@ describe("red/nodes/index", function() {
|
|||||||
info.should.eql(randomNodeInfo);
|
info.should.eql(randomNodeInfo);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -273,7 +272,7 @@ describe("red/nodes/index", function() {
|
|||||||
}).should.throw();
|
}).should.throw();
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -288,7 +287,7 @@ describe("red/nodes/index", function() {
|
|||||||
}).should.throw();
|
}).should.throw();
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -341,7 +340,7 @@ describe("red/nodes/index", function() {
|
|||||||
}).should.throw();
|
}).should.throw();
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -356,7 +355,7 @@ describe("red/nodes/index", function() {
|
|||||||
}).should.throw();
|
}).should.throw();
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -60,7 +60,7 @@ describe('red/nodes/registry/index', function() {
|
|||||||
registry.addModule("foo").then(function(info) {
|
registry.addModule("foo").then(function(info) {
|
||||||
info.should.eql("info");
|
info.should.eql("info");
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) { done(err); });
|
}).catch(function(err) { done(err); });
|
||||||
});
|
});
|
||||||
it('rejects if loader rejects', function(done) {
|
it('rejects if loader rejects', function(done) {
|
||||||
stubs.push(sinon.stub(loader,"addModule",function(module) {
|
stubs.push(sinon.stub(loader,"addModule",function(module) {
|
||||||
@ -71,7 +71,7 @@ describe('red/nodes/registry/index', function() {
|
|||||||
}));
|
}));
|
||||||
registry.addModule("foo").then(function(info) {
|
registry.addModule("foo").then(function(info) {
|
||||||
done(new Error("unexpected resolve"));
|
done(new Error("unexpected resolve"));
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
err.should.eql("error");
|
err.should.eql("error");
|
||||||
done();
|
done();
|
||||||
})
|
})
|
||||||
@ -90,7 +90,7 @@ describe('red/nodes/registry/index', function() {
|
|||||||
typeRegistry.enableNodeSet.called.should.be.true();
|
typeRegistry.enableNodeSet.called.should.be.true();
|
||||||
ns.should.have.a.property('id','node-set');
|
ns.should.have.a.property('id','node-set');
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) { done(err); });
|
}).catch(function(err) { done(err); });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('rejects if node unknown',function() {
|
it('rejects if node unknown',function() {
|
||||||
@ -121,7 +121,7 @@ describe('red/nodes/registry/index', function() {
|
|||||||
ns.should.have.a.property('id','node-set');
|
ns.should.have.a.property('id','node-set');
|
||||||
ns.should.have.a.property('loaded',true);
|
ns.should.have.a.property('loaded',true);
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) { done(err); });
|
}).catch(function(err) { done(err); });
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -83,7 +83,7 @@ describe('nodes/registry/installer', function() {
|
|||||||
return ee;
|
return ee;
|
||||||
});
|
});
|
||||||
|
|
||||||
installer.installModule("this_wont_exist").otherwise(function(err) {
|
installer.installModule("this_wont_exist").catch(function(err) {
|
||||||
err.should.have.property("code",404);
|
err.should.have.property("code",404);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -105,7 +105,7 @@ describe('nodes/registry/installer', function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
installer.installModule("this_wont_exist","0.1.2").otherwise(function(err) {
|
installer.installModule("this_wont_exist","0.1.2").catch(function(err) {
|
||||||
err.code.should.be.eql(404);
|
err.code.should.be.eql(404);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -116,7 +116,7 @@ describe('nodes/registry/installer', function() {
|
|||||||
version: "0.1.1"
|
version: "0.1.1"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
installer.installModule("this_wont_exist","0.1.1").otherwise(function(err) {
|
installer.installModule("this_wont_exist","0.1.1").catch(function(err) {
|
||||||
err.code.should.be.eql('module_already_loaded');
|
err.code.should.be.eql('module_already_loaded');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -135,7 +135,7 @@ describe('nodes/registry/installer', function() {
|
|||||||
|
|
||||||
installer.installModule("this_wont_exist").then(function() {
|
installer.installModule("this_wont_exist").then(function() {
|
||||||
done(new Error("Unexpected success"));
|
done(new Error("Unexpected success"));
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -160,7 +160,7 @@ describe('nodes/registry/installer', function() {
|
|||||||
// commsMessages[0].topic.should.equal("node/added");
|
// commsMessages[0].topic.should.equal("node/added");
|
||||||
// commsMessages[0].msg.should.eql(nodeInfo.nodes);
|
// commsMessages[0].msg.should.eql(nodeInfo.nodes);
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -169,7 +169,7 @@ describe('nodes/registry/installer', function() {
|
|||||||
var resourcesDir = path.resolve(path.join(__dirname,"..","resources","local","TestNodeModule","node_modules","NonExistant"));
|
var resourcesDir = path.resolve(path.join(__dirname,"..","resources","local","TestNodeModule","node_modules","NonExistant"));
|
||||||
installer.installModule(resourcesDir).then(function() {
|
installer.installModule(resourcesDir).then(function() {
|
||||||
done(new Error("Unexpected success"));
|
done(new Error("Unexpected success"));
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
if (err.hasOwnProperty("code")) {
|
if (err.hasOwnProperty("code")) {
|
||||||
err.code.should.eql(404);
|
err.code.should.eql(404);
|
||||||
done();
|
done();
|
||||||
@ -199,7 +199,7 @@ describe('nodes/registry/installer', function() {
|
|||||||
installer.installModule(resourcesDir).then(function(info) {
|
installer.installModule(resourcesDir).then(function(info) {
|
||||||
info.should.eql(nodeInfo);
|
info.should.eql(nodeInfo);
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -228,7 +228,7 @@ describe('nodes/registry/installer', function() {
|
|||||||
|
|
||||||
installer.uninstallModule("this_wont_exist").then(function() {
|
installer.uninstallModule("this_wont_exist").then(function() {
|
||||||
done(new Error("Unexpected success"));
|
done(new Error("Unexpected success"));
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -252,7 +252,7 @@ describe('nodes/registry/installer', function() {
|
|||||||
// commsMessages[0].topic.should.equal("node/removed");
|
// commsMessages[0].topic.should.equal("node/removed");
|
||||||
// commsMessages[0].msg.should.eql(nodeInfo);
|
// commsMessages[0].msg.should.eql(nodeInfo);
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -69,7 +69,7 @@ describe("red/nodes/registry/loader",function() {
|
|||||||
loader.load("foo",true).then(function() {
|
loader.load("foo",true).then(function() {
|
||||||
registry.saveNodeList.called.should.be.true();
|
registry.saveNodeList.called.should.be.true();
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
@ -118,7 +118,7 @@ describe("red/nodes/registry/loader",function() {
|
|||||||
nodes.registerType.lastCall.args[1].should.eql('test-node-1');
|
nodes.registerType.lastCall.args[1].should.eql('test-node-1');
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -169,7 +169,7 @@ describe("red/nodes/registry/loader",function() {
|
|||||||
nodes.registerType.secondCall.args[1].should.eql('test-node-multiple-1b');
|
nodes.registerType.secondCall.args[1].should.eql('test-node-multiple-1b');
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -219,7 +219,7 @@ describe("red/nodes/registry/loader",function() {
|
|||||||
nodes.registerType.lastCall.args[1].should.eql('test-node-2');
|
nodes.registerType.lastCall.args[1].should.eql('test-node-2');
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -267,7 +267,7 @@ describe("red/nodes/registry/loader",function() {
|
|||||||
nodes.registerType.calledOnce.should.be.false();
|
nodes.registerType.calledOnce.should.be.false();
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -313,7 +313,7 @@ describe("red/nodes/registry/loader",function() {
|
|||||||
nodes.registerType.calledOnce.should.be.false();
|
nodes.registerType.calledOnce.should.be.false();
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -360,7 +360,7 @@ describe("red/nodes/registry/loader",function() {
|
|||||||
nodes.registerType.calledOnce.should.be.false();
|
nodes.registerType.calledOnce.should.be.false();
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -379,7 +379,7 @@ describe("red/nodes/registry/loader",function() {
|
|||||||
stubs.push(sinon.stub(registry,"getModuleInfo",function(){return{}}));
|
stubs.push(sinon.stub(registry,"getModuleInfo",function(){return{}}));
|
||||||
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
|
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
|
||||||
|
|
||||||
loader.addModule("test-module").otherwise(function(err) {
|
loader.addModule("test-module").catch(function(err) {
|
||||||
err.code.should.eql("module_already_loaded");
|
err.code.should.eql("module_already_loaded");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -390,7 +390,7 @@ describe("red/nodes/registry/loader",function() {
|
|||||||
throw new Error("failure");
|
throw new Error("failure");
|
||||||
}));
|
}));
|
||||||
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
|
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
|
||||||
loader.addModule("test-module").otherwise(function(err) {
|
loader.addModule("test-module").catch(function(err) {
|
||||||
err.message.should.eql("failure");
|
err.message.should.eql("failure");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -441,7 +441,7 @@ describe("red/nodes/registry/loader",function() {
|
|||||||
|
|
||||||
nodes.registerType.calledOnce.should.be.true();
|
nodes.registerType.calledOnce.should.be.true();
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -477,7 +477,7 @@ describe("red/nodes/registry/loader",function() {
|
|||||||
registry.addNodeSet.called.should.be.false();
|
registry.addNodeSet.called.should.be.false();
|
||||||
nodes.registerType.called.should.be.false();
|
nodes.registerType.called.should.be.false();
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -498,7 +498,7 @@ describe("red/nodes/registry/loader",function() {
|
|||||||
node.enabled.should.be.false();
|
node.enabled.should.be.false();
|
||||||
nodes.registerType.called.should.be.false();
|
nodes.registerType.called.should.be.false();
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -517,7 +517,7 @@ describe("red/nodes/registry/loader",function() {
|
|||||||
node.err.toString().should.eql("Error: fail to require (line:1)");
|
node.err.toString().should.eql("Error: fail to require (line:1)");
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -292,7 +292,7 @@ describe("red/nodes/registry/registry",function() {
|
|||||||
it('rejects when settings unavailable',function(done) {
|
it('rejects when settings unavailable',function(done) {
|
||||||
typeRegistry.init(stubSettings({},false,{}));
|
typeRegistry.init(stubSettings({},false,{}));
|
||||||
typeRegistry.addNodeSet("test-module/test-name",testNodeSet1, "0.0.1");
|
typeRegistry.addNodeSet("test-module/test-name",testNodeSet1, "0.0.1");
|
||||||
typeRegistry.saveNodeList().otherwise(function(err) {
|
typeRegistry.saveNodeList().catch(function(err) {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -312,7 +312,7 @@ describe("red/nodes/registry/registry",function() {
|
|||||||
nn.should.not.have.property('id');
|
nn.should.not.have.property('id');
|
||||||
}
|
}
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
**/
|
**/
|
||||||
var should = require("should");
|
var should = require("should");
|
||||||
var when = require("when");
|
|
||||||
|
|
||||||
var settings = require("../../../red/runtime/settings");
|
var settings = require("../../../red/runtime/settings");
|
||||||
|
|
||||||
@ -86,12 +85,12 @@ describe("red/settings", function() {
|
|||||||
var saveCount = 0;
|
var saveCount = 0;
|
||||||
var storage = {
|
var storage = {
|
||||||
getSettings: function() {
|
getSettings: function() {
|
||||||
return when.resolve({globalA:789});
|
return Promise.resolve({globalA:789});
|
||||||
},
|
},
|
||||||
saveSettings: function(settings) {
|
saveSettings: function(settings) {
|
||||||
saveCount++;
|
saveCount++;
|
||||||
savedSettings = settings;
|
savedSettings = settings;
|
||||||
return when.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
settings.init(userSettings);
|
settings.init(userSettings);
|
||||||
@ -115,7 +114,7 @@ describe("red/settings", function() {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -47,7 +47,7 @@ describe('storage/localfilesystem', function() {
|
|||||||
fs.existsSync(path.join(userDir,"lib")).should.be.true();
|
fs.existsSync(path.join(userDir,"lib")).should.be.true();
|
||||||
fs.existsSync(path.join(userDir,"lib",'flows')).should.be.true();
|
fs.existsSync(path.join(userDir,"lib",'flows')).should.be.true();
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -70,7 +70,7 @@ describe('storage/localfilesystem', function() {
|
|||||||
} finally {
|
} finally {
|
||||||
process.env.NODE_RED_HOME = oldNRH;
|
process.env.NODE_RED_HOME = oldNRH;
|
||||||
}
|
}
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -96,7 +96,7 @@ describe('storage/localfilesystem', function() {
|
|||||||
process.env.NODE_RED_HOME = oldNRH;
|
process.env.NODE_RED_HOME = oldNRH;
|
||||||
process.env.NODE_HOMEPATH = oldHOMEPATH;
|
process.env.NODE_HOMEPATH = oldHOMEPATH;
|
||||||
}
|
}
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -124,7 +124,7 @@ describe('storage/localfilesystem', function() {
|
|||||||
process.env.HOME = oldHOME;
|
process.env.HOME = oldHOME;
|
||||||
process.env.HOMEPATH = oldHOMEPATH;
|
process.env.HOMEPATH = oldHOMEPATH;
|
||||||
}
|
}
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -155,7 +155,7 @@ describe('storage/localfilesystem', function() {
|
|||||||
process.env.HOMEPATH = oldHOMEPATH;
|
process.env.HOMEPATH = oldHOMEPATH;
|
||||||
process.env.USERPROFILE = oldUSERPROFILE;
|
process.env.USERPROFILE = oldUSERPROFILE;
|
||||||
}
|
}
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -168,10 +168,10 @@ describe('storage/localfilesystem', function() {
|
|||||||
localfilesystem.getFlows().then(function(flows) {
|
localfilesystem.getFlows().then(function(flows) {
|
||||||
flows.should.eql([]);
|
flows.should.eql([]);
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -186,10 +186,10 @@ describe('storage/localfilesystem', function() {
|
|||||||
localfilesystem.getFlows().then(function(flows) {
|
localfilesystem.getFlows().then(function(flows) {
|
||||||
flows.should.eql([]);
|
flows.should.eql([]);
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -208,11 +208,11 @@ describe('storage/localfilesystem', function() {
|
|||||||
localfilesystem.getFlows().then(function(flows) {
|
localfilesystem.getFlows().then(function(flows) {
|
||||||
flows.should.eql(testFlow);
|
flows.should.eql(testFlow);
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
},50);
|
},50);
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -230,13 +230,13 @@ describe('storage/localfilesystem', function() {
|
|||||||
localfilesystem.getFlows().then(function(flows) {
|
localfilesystem.getFlows().then(function(flows) {
|
||||||
flows.should.eql(testFlow);
|
flows.should.eql(testFlow);
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -257,13 +257,13 @@ describe('storage/localfilesystem', function() {
|
|||||||
localfilesystem.getFlows().then(function(flows) {
|
localfilesystem.getFlows().then(function(flows) {
|
||||||
flows.should.eql(testFlow);
|
flows.should.eql(testFlow);
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -278,13 +278,13 @@ describe('storage/localfilesystem', function() {
|
|||||||
localfilesystem.getFlows().then(function(flows) {
|
localfilesystem.getFlows().then(function(flows) {
|
||||||
flows.should.eql(testFlow);
|
flows.should.eql(testFlow);
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -298,11 +298,11 @@ describe('storage/localfilesystem', function() {
|
|||||||
fs.fsync.callCount.should.be.greaterThan(0);
|
fs.fsync.callCount.should.be.greaterThan(0);
|
||||||
fs.fsync.restore();
|
fs.fsync.restore();
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
fs.fsync.restore();
|
fs.fsync.restore();
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -321,10 +321,10 @@ describe('storage/localfilesystem', function() {
|
|||||||
fs.fsync.callCount.should.be.greaterThan(0);
|
fs.fsync.callCount.should.be.greaterThan(0);
|
||||||
fs.fsync.restore();
|
fs.fsync.restore();
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -358,14 +358,14 @@ describe('storage/localfilesystem', function() {
|
|||||||
content2.should.not.equal(backupContent);
|
content2.should.not.equal(backupContent);
|
||||||
done();
|
done();
|
||||||
|
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -382,10 +382,10 @@ describe('storage/localfilesystem', function() {
|
|||||||
localfilesystem.getCredentials().then(function(creds) {
|
localfilesystem.getCredentials().then(function(creds) {
|
||||||
creds.should.eql({});
|
creds.should.eql({});
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -406,13 +406,13 @@ describe('storage/localfilesystem', function() {
|
|||||||
localfilesystem.getCredentials().then(function(creds) {
|
localfilesystem.getCredentials().then(function(creds) {
|
||||||
creds.should.eql(credentials);
|
creds.should.eql(credentials);
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -437,10 +437,10 @@ describe('storage/localfilesystem', function() {
|
|||||||
fs.existsSync(credFile).should.be.true();
|
fs.existsSync(credFile).should.be.true();
|
||||||
fs.existsSync(credFileBackup).should.be.true();
|
fs.existsSync(credFileBackup).should.be.true();
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -463,13 +463,13 @@ describe('storage/localfilesystem', function() {
|
|||||||
localfilesystem.getCredentials().then(function(creds) {
|
localfilesystem.getCredentials().then(function(creds) {
|
||||||
creds.should.eql(credentials);
|
creds.should.eql(credentials);
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -38,7 +38,7 @@ describe('storage/localfilesystem/sessions', function() {
|
|||||||
localfilesystemSessions.getSessions().then(function(sessions) {
|
localfilesystemSessions.getSessions().then(function(sessions) {
|
||||||
sessions.should.eql({});
|
sessions.should.eql({});
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -51,7 +51,7 @@ describe('storage/localfilesystem/sessions', function() {
|
|||||||
localfilesystemSessions.getSessions().then(function(sessions) {
|
localfilesystemSessions.getSessions().then(function(sessions) {
|
||||||
sessions.should.eql({});
|
sessions.should.eql({});
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -69,10 +69,10 @@ describe('storage/localfilesystem/sessions', function() {
|
|||||||
localfilesystemSessions.getSessions().then(function(_sessions) {
|
localfilesystemSessions.getSessions().then(function(_sessions) {
|
||||||
_sessions.should.eql(sessions);
|
_sessions.should.eql(sessions);
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -39,7 +39,7 @@ describe('storage/localfilesystem/settings', function() {
|
|||||||
localfilesystemSettings.getSettings().then(function(settings) {
|
localfilesystemSettings.getSettings().then(function(settings) {
|
||||||
settings.should.eql({});
|
settings.should.eql({});
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -52,7 +52,7 @@ describe('storage/localfilesystem/settings', function() {
|
|||||||
localfilesystemSettings.getSettings().then(function(settings) {
|
localfilesystemSettings.getSettings().then(function(settings) {
|
||||||
settings.should.eql({});
|
settings.should.eql({});
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -70,10 +70,10 @@ describe('storage/localfilesystem/settings', function() {
|
|||||||
localfilesystemSettings.getSettings().then(function(_settings) {
|
localfilesystemSettings.getSettings().then(function(_settings) {
|
||||||
_settings.should.eql(settings);
|
_settings.should.eql(settings);
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
}).otherwise(function(err) {
|
}).catch(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user