mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Merge pull request #498 from anna2130/nr-cli-enhancements
nr-cli enhancements - server side api
This commit is contained in:
commit
14b84f0c7b
@ -19,7 +19,6 @@ var util = require('util');
|
||||
|
||||
var ui = require("./ui");
|
||||
var nodes = require("./nodes");
|
||||
var plugins = require("./plugins");
|
||||
var flows = require("./flows");
|
||||
var library = require("./library");
|
||||
|
||||
@ -52,20 +51,18 @@ function init(adminApp) {
|
||||
adminApp.get("/nodes",nodes.getAll);
|
||||
adminApp.post("/nodes",nodes.post);
|
||||
|
||||
adminApp.get("/nodes/:id",nodes.get);
|
||||
adminApp.put("/nodes/:id",nodes.put);
|
||||
adminApp.delete("/nodes/:id",nodes.delete);
|
||||
adminApp.get("/nodes/:mod",nodes.getModule);
|
||||
adminApp.put("/nodes/:mod",nodes.putModule);
|
||||
adminApp.delete("/nodes/:mod",nodes.delete);
|
||||
|
||||
// Plugins
|
||||
adminApp.get("/plugins",plugins.getAll);
|
||||
adminApp.get("/plugins/:id",plugins.get);
|
||||
adminApp.get("/nodes/:mod/:set",nodes.getSet);
|
||||
adminApp.put("/nodes/:mod/:set",nodes.putSet);
|
||||
|
||||
// Library
|
||||
adminApp.post(new RegExp("/library/flows\/(.*)"),library.post);
|
||||
adminApp.get("/library/flows",library.getAll);
|
||||
adminApp.get(new RegExp("/library/flows\/(.*)"),library.get);
|
||||
|
||||
|
||||
// Error Handler
|
||||
adminApp.use(errorHandler);
|
||||
}
|
||||
|
104
red/api/nodes.js
104
red/api/nodes.js
@ -34,6 +34,7 @@ module.exports = {
|
||||
res.send(redNodes.getNodeConfigs());
|
||||
}
|
||||
},
|
||||
|
||||
post: function(req,res) {
|
||||
if (!settings.available()) {
|
||||
res.send(400,new Error("Settings unavailable").toString());
|
||||
@ -55,7 +56,7 @@ module.exports = {
|
||||
return;
|
||||
}
|
||||
promise.then(function(info) {
|
||||
res.json(info);
|
||||
res.json(redNodes.getModuleInfo(node.module));
|
||||
}).otherwise(function(err) {
|
||||
if (err.code === 404) {
|
||||
res.send(404);
|
||||
@ -64,31 +65,25 @@ module.exports = {
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
delete: function(req,res) {
|
||||
if (!settings.available()) {
|
||||
res.send(400,new Error("Settings unavailable").toString());
|
||||
return;
|
||||
}
|
||||
var id = req.params.id;
|
||||
var removedNodes = [];
|
||||
var mod = req.params.mod;
|
||||
try {
|
||||
var node = redNodes.getNodeInfo(id);
|
||||
var promise = null;
|
||||
if (!node) {
|
||||
var module = redNodes.getNodeModuleInfo(id);
|
||||
if (!module) {
|
||||
res.send(404);
|
||||
return;
|
||||
} else {
|
||||
promise = server.uninstallModule(id);
|
||||
}
|
||||
var module = redNodes.getNodeModuleInfo(mod);
|
||||
if (!module) {
|
||||
res.send(404);
|
||||
return;
|
||||
} else {
|
||||
promise = when.resolve([redNodes.removeNode(id)]).then(server.reportRemovedModules);
|
||||
promise = server.uninstallModule(mod);
|
||||
}
|
||||
|
||||
promise.then(function(removedNodes) {
|
||||
res.json(removedNodes);
|
||||
|
||||
promise.then(function() {
|
||||
res.send(204);
|
||||
}).otherwise(function(err) {
|
||||
res.send(400,err.toString());
|
||||
});
|
||||
@ -96,11 +91,11 @@ module.exports = {
|
||||
res.send(400,err.toString());
|
||||
}
|
||||
},
|
||||
|
||||
get: function(req,res) {
|
||||
var id = req.params.id;
|
||||
|
||||
getSet: function(req,res) {
|
||||
var id = req.params.mod + "/" + req.params.set;
|
||||
var result = null;
|
||||
if (req.get("accept") == "application/json") {
|
||||
if (req.get("accept") === "application/json") {
|
||||
result = redNodes.getNodeInfo(id);
|
||||
} else {
|
||||
result = redNodes.getNodeConfig(id);
|
||||
@ -111,8 +106,18 @@ module.exports = {
|
||||
res.send(404);
|
||||
}
|
||||
},
|
||||
|
||||
put: function(req,res) {
|
||||
|
||||
getModule: function(req,res) {
|
||||
var module = req.params.mod;
|
||||
var result = redNodes.getModuleInfo(module);
|
||||
if (result) {
|
||||
res.send(result);
|
||||
} else {
|
||||
res.send(404);
|
||||
}
|
||||
},
|
||||
|
||||
putSet: function(req,res) {
|
||||
if (!settings.available()) {
|
||||
res.send(400,new Error("Settings unavailable").toString());
|
||||
return;
|
||||
@ -123,9 +128,9 @@ module.exports = {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
var info;
|
||||
var id = req.params.id;
|
||||
var id = req.params.mod+"/"+req.params.set;
|
||||
var node = redNodes.getNodeInfo(id);
|
||||
var info;
|
||||
if (!node) {
|
||||
res.send(404);
|
||||
} else if (!node.err && node.enabled === body.enabled) {
|
||||
@ -150,6 +155,51 @@ module.exports = {
|
||||
}
|
||||
} catch(err) {
|
||||
res.send(400,err.toString());
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
putModule: function(req,res) {
|
||||
if (!settings.available()) {
|
||||
res.send(400,new Error("Settings unavailable").toString());
|
||||
return;
|
||||
}
|
||||
var body = req.body;
|
||||
if (!body.hasOwnProperty("enabled")) {
|
||||
res.send(400,"Invalid request");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
var mod = req.params.mod;
|
||||
var module = redNodes.getModuleInfo(mod);
|
||||
if (!module) {
|
||||
res.send(404);
|
||||
return;
|
||||
}
|
||||
var nodes = module.nodes;
|
||||
for (var i = 0; i < nodes.length; ++i) {
|
||||
var node = nodes[i];
|
||||
var info;
|
||||
if (node.err || node.enabled !== body.enabled) {
|
||||
if (body.enabled) {
|
||||
info = redNodes.enableNode(node.id);
|
||||
} else {
|
||||
info = redNodes.disableNode(node.id);
|
||||
}
|
||||
if (info.enabled === body.enabled && !info.err) {
|
||||
comms.publish("node/"+(body.enabled?"enabled":"disabled"),info,false);
|
||||
util.log("[red] "+(body.enabled?"Enabled":"Disabled")+" node types:");
|
||||
for (var j = 0; j < info.types.length; j++) {
|
||||
util.log("[red] - " + info.types[j]);
|
||||
}
|
||||
} else if (body.enabled && info.err) {
|
||||
util.log("[red] Failed to enable node:");
|
||||
util.log("[red] - "+info.name+" : "+info.err);
|
||||
}
|
||||
}
|
||||
}
|
||||
res.json(redNodes.getModuleInfo(mod));
|
||||
} catch(err) {
|
||||
res.send(400,err.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1,32 +0,0 @@
|
||||
/**
|
||||
* Copyright 2014 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var redNodes = require("../nodes");
|
||||
|
||||
module.exports = {
|
||||
getAll: function(req,res) {
|
||||
res.json(redNodes.getPluginList());
|
||||
},
|
||||
get: function(req,res) {
|
||||
var id = req.params.id;
|
||||
var result = redNodes.getPluginInfo(id);
|
||||
if (result) {
|
||||
res.send(result);
|
||||
} else {
|
||||
res.send(404);
|
||||
}
|
||||
}
|
||||
};
|
@ -1,53 +0,0 @@
|
||||
/**
|
||||
* Copyright 2014 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var path = require("path");
|
||||
var fs = require("fs");
|
||||
|
||||
var userHome = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;
|
||||
|
||||
var configDir = path.join(userHome,".nodered");
|
||||
var configFile = path.join(configDir,"config.json");
|
||||
|
||||
var config;
|
||||
|
||||
function load() {
|
||||
if (config == null) {
|
||||
try {
|
||||
config = JSON.parse(fs.readFileSync(configFile));
|
||||
} catch(err) {
|
||||
config = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function save() {
|
||||
try {
|
||||
fs.mkdirSync(configDir);
|
||||
} catch(err) {
|
||||
if (err.code != "EEXIST") {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
fs.writeFileSync(configFile,JSON.stringify(config,null,4));
|
||||
}
|
||||
module.exports = {
|
||||
unload: function() {
|
||||
config = null;
|
||||
}
|
||||
};
|
||||
module.exports.__defineGetter__('target',function() { load(); return config.target|| "http://localhost:1880" });
|
||||
module.exports.__defineSetter__('target',function(v) { load(); config.target = v; save();});
|
@ -1,51 +0,0 @@
|
||||
/**
|
||||
* Copyright 2014 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var when = require("when");
|
||||
var request = require("request");
|
||||
var config = require("./config");
|
||||
|
||||
module.exports = function(path, options) {
|
||||
var basePath = config.target;
|
||||
return when.promise(function(resolve,reject) {
|
||||
options.headers = options.headers||{};
|
||||
options.headers['Accept'] = 'application/json';
|
||||
if (options.method == 'PUT' || options.method == "POST") {
|
||||
options.headers['content-type'] = 'application/json';
|
||||
}
|
||||
options.url = basePath+path;
|
||||
|
||||
// Pull out the request function so we can stub it in the tests
|
||||
var requestFunc = request.get;
|
||||
|
||||
if (options.method == 'PUT') {
|
||||
requestFunc = request.put;
|
||||
} else if (options.method == 'POST') {
|
||||
requestFunc = request.post;
|
||||
} else if (options.method == 'DELETE') {
|
||||
requestFunc = request.del;
|
||||
}
|
||||
requestFunc(options, function(error,response,body) {
|
||||
if (!error && response.statusCode == 200) {
|
||||
resolve(JSON.parse(body));
|
||||
} else if (error) {
|
||||
reject(error.toString());
|
||||
} else {
|
||||
reject(response.statusCode+": "+body)
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
@ -1,151 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
;(function() {
|
||||
/**
|
||||
* Copyright 2014 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var util = require("util");
|
||||
var request = require("request");
|
||||
var colors = require('colors');
|
||||
var apiRequest = require("./lib/request");
|
||||
var config = require("./lib/config");
|
||||
|
||||
var commands = {
|
||||
"target": function() {
|
||||
var target = process.argv[3];
|
||||
if (target) {
|
||||
if (!/^https?:\/\/.+/.test(target)) {
|
||||
console.warn("Invalid target url");
|
||||
return;
|
||||
}
|
||||
if (target.slice(-1) == "/") {
|
||||
target = target.slice(0,target.length-1);
|
||||
}
|
||||
var oldTarget = config.target;
|
||||
config.target = target;
|
||||
} else {
|
||||
console.log("Target: ".yellow+config.target);
|
||||
}
|
||||
|
||||
},
|
||||
"nodes": function() {
|
||||
apiRequest('/nodes',{}).then(logNodeList).otherwise(logFailure);
|
||||
},
|
||||
"node": function() {
|
||||
apiRequest('/nodes/'+process.argv[3],{}).then(logNodeList).otherwise(logFailure);
|
||||
},
|
||||
"enable-node": function() {
|
||||
apiRequest('/nodes/'+process.argv[3],{
|
||||
method: "PUT",
|
||||
body: JSON.stringify({enabled:true})
|
||||
}).then(logNodeList).otherwise(logFailure);
|
||||
},
|
||||
"disable-node": function() {
|
||||
apiRequest('/nodes/'+process.argv[3],{
|
||||
method: "PUT",
|
||||
body: JSON.stringify({enabled:false})
|
||||
}).then(logNodeList).otherwise(logFailure);
|
||||
},
|
||||
"install": function() {
|
||||
apiRequest('/nodes',{
|
||||
method: "POST",
|
||||
body: JSON.stringify({module:process.argv[3]})
|
||||
}).then(logNodeList).otherwise(logFailure);
|
||||
},
|
||||
"remove": function() {
|
||||
apiRequest('/nodes/'+process.argv[3],{
|
||||
method: "DELETE"
|
||||
}).then(logNodeList).otherwise(logFailure);
|
||||
},
|
||||
"search": function() {
|
||||
var options = {
|
||||
method: "GET",
|
||||
url: 'https://registry.npmjs.org/-/_view/byKeyword?startkey=["node-red"]&endkey=["node-red",{}]&group_level=3' ,
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
}
|
||||
};
|
||||
request(options, function (error, response, body) {
|
||||
if (!error && response.statusCode == 200) {
|
||||
var info = (JSON.parse(body)).rows;
|
||||
var filter = null;
|
||||
if (process.argv[3]) {
|
||||
filter = new RegExp(process.argv[3]);
|
||||
}
|
||||
for (var i=0;i<info.length;i++) {
|
||||
var n = info[i];
|
||||
if (!filter || filter.test(n.key[1]) || filter.test(n.key[2])) {
|
||||
console.log(n.key[1] + (" - "+ n.key[2]).grey);
|
||||
}
|
||||
}
|
||||
} else if (error) {
|
||||
console.log(error.toString().red);
|
||||
} else {
|
||||
console.log((response.statusCode+": "+body).red);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function logNodeList(nodes) {
|
||||
if (!util.isArray(nodes)) {
|
||||
nodes = [nodes];
|
||||
}
|
||||
for (var i=0;i<nodes.length;i++) {
|
||||
var n = nodes[i];
|
||||
console.log(formatNodeInfo(n))
|
||||
}
|
||||
}
|
||||
|
||||
function logFailure(msg) {
|
||||
console.log(msg.red);
|
||||
}
|
||||
|
||||
function formatBoolean(v,c) {
|
||||
if (v) {
|
||||
return ("["+c+"]");
|
||||
} else {
|
||||
return ("[ ]");
|
||||
}
|
||||
}
|
||||
|
||||
function formatNodeInfo(n) {
|
||||
var inError = n.hasOwnProperty("err");
|
||||
|
||||
var str = formatBoolean(n.enabled,"X")+formatBoolean(n.loaded,"L")+" ";
|
||||
str += n.id;
|
||||
if (n.enabled && n.loaded) {
|
||||
str = str.green;
|
||||
} else if (n.enabled && n.err) {
|
||||
str = str.red;
|
||||
} else {
|
||||
str = str.yellow;
|
||||
}
|
||||
if (n.module) {
|
||||
str += " ["+n.module+"]";
|
||||
}
|
||||
str += " "+n.types.join(", ");
|
||||
if (n.err) {
|
||||
str+=" "+n.err.red;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
if (commands[process.argv[2]]) {
|
||||
commands[process.argv[2]].call();
|
||||
}
|
||||
|
||||
|
||||
})();
|
@ -55,20 +55,21 @@ function checkTypeInUse(id) {
|
||||
var nodeInfo = registry.getNodeInfo(id);
|
||||
if (!nodeInfo) {
|
||||
throw new Error("Unrecognised id: "+id);
|
||||
}
|
||||
var inUse = {};
|
||||
flows.each(function(n) {
|
||||
inUse[n.type] = (inUse[n.type]||0)+1;
|
||||
});
|
||||
var nodesInUse = [];
|
||||
nodeInfo.types.forEach(function(t) {
|
||||
if (inUse[t]) {
|
||||
nodesInUse.push(t);
|
||||
} else {
|
||||
var inUse = {};
|
||||
flows.each(function(n) {
|
||||
inUse[n.type] = (inUse[n.type]||0)+1;
|
||||
});
|
||||
var nodesInUse = [];
|
||||
nodeInfo.types.forEach(function(t) {
|
||||
if (inUse[t]) {
|
||||
nodesInUse.push(t);
|
||||
}
|
||||
});
|
||||
if (nodesInUse.length > 0) {
|
||||
var msg = nodesInUse.join(", ");
|
||||
throw new Error("Type in use: "+msg);
|
||||
}
|
||||
});
|
||||
if (nodesInUse.length > 0) {
|
||||
var msg = nodesInUse.join(", ");
|
||||
throw new Error("Type in use: "+msg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,13 +80,16 @@ function removeNode(id) {
|
||||
|
||||
function removeModule(module) {
|
||||
var info = registry.getNodeModuleInfo(module);
|
||||
for (var i=0;i<info.nodes.length;i++) {
|
||||
checkTypeInUse(info.nodes[i]);
|
||||
if (!info) {
|
||||
throw new Error("Unrecognised module: "+module);
|
||||
} else {
|
||||
for (var i=0;i<info.length;i++) {
|
||||
checkTypeInUse(module+"/"+info[i]);
|
||||
}
|
||||
return registry.removeModule(module);
|
||||
}
|
||||
return registry.removeModule(module);
|
||||
}
|
||||
|
||||
|
||||
function disableNode(id) {
|
||||
checkTypeInUse(id);
|
||||
return registry.disableNode(id);
|
||||
@ -112,15 +116,20 @@ module.exports = {
|
||||
// Node type registry
|
||||
registerType: registerType,
|
||||
getType: registry.get,
|
||||
|
||||
getNodeInfo: registry.getNodeInfo,
|
||||
getNodeModuleInfo: registry.getNodeModuleInfo,
|
||||
getPluginInfo: registry.getPluginInfo,
|
||||
getNodeList: registry.getNodeList,
|
||||
getPluginList: registry.getPluginList,
|
||||
|
||||
getNodeModuleInfo: registry.getNodeModuleInfo,
|
||||
|
||||
getModuleInfo: registry.getModuleInfo,
|
||||
getModuleList: registry.getModuleList,
|
||||
|
||||
getNodeConfigs: registry.getNodeConfigs,
|
||||
getNodeConfig: registry.getNodeConfig,
|
||||
|
||||
clearRegistry: registry.clear,
|
||||
cleanNodeList: registry.cleanNodeList,
|
||||
cleanModuleList: registry.cleanModuleList,
|
||||
|
||||
// Flow handling
|
||||
loadFlows: flows.load,
|
||||
|
@ -46,31 +46,48 @@ function filterNodeInfo(n) {
|
||||
return r;
|
||||
}
|
||||
|
||||
function getModule(id) {
|
||||
return id.split("/")[0];
|
||||
}
|
||||
|
||||
function getNode(id) {
|
||||
return id.split("/")[1];
|
||||
}
|
||||
|
||||
var registry = (function() {
|
||||
var nodeConfigCache = null;
|
||||
var nodeConfigs = {};
|
||||
var moduleConfigs = {};
|
||||
var nodeList = [];
|
||||
var nodeConstructors = {};
|
||||
var nodeTypeToId = {};
|
||||
var nodeModules = {};
|
||||
var moduleNodes = {};
|
||||
|
||||
function saveNodeList() {
|
||||
var nodeList = {};
|
||||
var moduleList = {};
|
||||
|
||||
for (var i in nodeConfigs) {
|
||||
if (nodeConfigs.hasOwnProperty(i)) {
|
||||
var nodeConfig = nodeConfigs[i];
|
||||
var n = filterNodeInfo(nodeConfig);
|
||||
n.file = nodeConfig.file;
|
||||
delete n.loaded;
|
||||
delete n.err;
|
||||
delete n.file;
|
||||
delete n.id;
|
||||
nodeList[i] = n;
|
||||
for (var module in moduleConfigs) {
|
||||
if (moduleConfigs.hasOwnProperty(module)) {
|
||||
if (!moduleList[module]) {
|
||||
moduleList[module] = {};
|
||||
moduleList[module].name = module;
|
||||
moduleList[module].nodes = {};
|
||||
}
|
||||
var nodes = moduleConfigs[module].nodes;
|
||||
for(var node in nodes) {
|
||||
if (nodes.hasOwnProperty(node)) {
|
||||
var config = nodes[node];
|
||||
var n = filterNodeInfo(config);
|
||||
delete n.loaded;
|
||||
delete n.err;
|
||||
delete n.file;
|
||||
delete n.id;
|
||||
moduleList[module].nodes[node] = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (settings.available()) {
|
||||
return settings.set("nodes",nodeList);
|
||||
return settings.set("modules",moduleList);
|
||||
} else {
|
||||
return when.reject("Settings unavailable");
|
||||
}
|
||||
@ -79,45 +96,47 @@ var registry = (function() {
|
||||
return {
|
||||
init: function() {
|
||||
if (settings.available()) {
|
||||
nodeConfigs = settings.get("nodes")||{};
|
||||
// Restore the node id property to individual entries
|
||||
for (var id in nodeConfigs) {
|
||||
if (nodeConfigs.hasOwnProperty(id)) {
|
||||
nodeConfigs[id].id = id;
|
||||
}
|
||||
}
|
||||
moduleConfigs = settings.get("modules")||{};
|
||||
} else {
|
||||
nodeConfigs = {};
|
||||
moduleConfigs = {};
|
||||
}
|
||||
nodeModules = {};
|
||||
moduleNodes = {};
|
||||
nodeTypeToId = {};
|
||||
nodeConstructors = {};
|
||||
nodeList = [];
|
||||
nodeConfigCache = null;
|
||||
},
|
||||
|
||||
addNodeSet: function(id,set) {
|
||||
addNodeSet: function(id,set,version) {
|
||||
if (!set.err) {
|
||||
set.types.forEach(function(t) {
|
||||
nodeTypeToId[t] = id;
|
||||
});
|
||||
}
|
||||
|
||||
if (set.module) {
|
||||
nodeModules[set.module] = nodeModules[set.module]||{nodes:[]};
|
||||
nodeModules[set.module].nodes.push(id);
|
||||
moduleNodes[set.module] = moduleNodes[set.module]||[];
|
||||
moduleNodes[set.module].push(set.name);
|
||||
|
||||
if (!moduleConfigs[set.module]) {
|
||||
moduleConfigs[set.module] = {
|
||||
name: set.module,
|
||||
nodes: {}
|
||||
};
|
||||
}
|
||||
|
||||
nodeConfigs[id] = set;
|
||||
if (version) {
|
||||
moduleConfigs[set.module].version = version;
|
||||
}
|
||||
|
||||
moduleConfigs[set.module].nodes[set.name] = set;
|
||||
nodeList.push(id);
|
||||
nodeConfigCache = null;
|
||||
},
|
||||
removeNode: function(id) {
|
||||
var config = nodeConfigs[id];
|
||||
var config = moduleConfigs[getModule(id)].nodes[getNode(id)];
|
||||
if (!config) {
|
||||
throw new Error("Unrecognised id: "+id);
|
||||
}
|
||||
delete nodeConfigs[id];
|
||||
delete moduleConfigs[getModule(id)].nodes[getNode(id)];
|
||||
var i = nodeList.indexOf(id);
|
||||
if (i > -1) {
|
||||
nodeList.splice(i,1);
|
||||
@ -135,62 +154,81 @@ var registry = (function() {
|
||||
if (!settings.available()) {
|
||||
throw new Error("Settings unavailable");
|
||||
}
|
||||
var nodes = nodeModules[module];
|
||||
var nodes = moduleNodes[module];
|
||||
if (!nodes) {
|
||||
throw new Error("Unrecognised module: "+module);
|
||||
}
|
||||
var infoList = [];
|
||||
for (var i=0;i<nodes.nodes.length;i++) {
|
||||
infoList.push(registry.removeNode(nodes.nodes[i]));
|
||||
for (var i=0;i<nodes.length;i++) {
|
||||
infoList.push(registry.removeNode(module+"/"+nodes[i]));
|
||||
}
|
||||
delete nodeModules[module];
|
||||
delete moduleNodes[module];
|
||||
saveNodeList();
|
||||
return infoList;
|
||||
},
|
||||
getNodeInfo: function(typeOrId) {
|
||||
var id = typeOrId;
|
||||
if (nodeTypeToId[typeOrId]) {
|
||||
return filterNodeInfo(nodeConfigs[nodeTypeToId[typeOrId]]);
|
||||
} else if (nodeConfigs[typeOrId]) {
|
||||
return filterNodeInfo(nodeConfigs[typeOrId]);
|
||||
id = nodeTypeToId[typeOrId];
|
||||
}
|
||||
if (id) {
|
||||
var module = moduleConfigs[getModule(id)];
|
||||
if (module) {
|
||||
var config = module.nodes[getNode(id)];
|
||||
if (config) {
|
||||
return filterNodeInfo(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
getNodeList: function() {
|
||||
var list = [];
|
||||
for (var id in nodeConfigs) {
|
||||
if (nodeConfigs.hasOwnProperty(id)) {
|
||||
list.push(filterNodeInfo(nodeConfigs[id]));
|
||||
for (var module in moduleConfigs) {
|
||||
if (moduleConfigs.hasOwnProperty(module)) {
|
||||
var nodes = moduleConfigs[module].nodes;
|
||||
for (var node in nodes) {
|
||||
if (nodes.hasOwnProperty(node)) {
|
||||
list.push(filterNodeInfo(nodes[node]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
},
|
||||
getPluginList: function() {
|
||||
getModuleList: function() {
|
||||
var list = [];
|
||||
for (var plugin in nodeModules) {
|
||||
if (nodeModules.hasOwnProperty(plugin)) {
|
||||
var nodes = nodeModules[plugin].nodes;
|
||||
for (var module in moduleNodes) {
|
||||
if (moduleNodes.hasOwnProperty(module)) {
|
||||
var nodes = moduleNodes[module];
|
||||
var m = {
|
||||
name: plugin,
|
||||
name: module,
|
||||
version: moduleConfigs[module].version,
|
||||
nodes: []
|
||||
};
|
||||
for (var i = 0; i < nodes.length; ++i) {
|
||||
m.nodes.push(filterNodeInfo(nodeConfigs[nodes[i]]));
|
||||
m.nodes.push(filterNodeInfo(moduleConfigs[module].nodes[nodes[i]]));
|
||||
}
|
||||
list.push(m);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
},
|
||||
getPluginInfo: function(plugin) {
|
||||
var nodes = nodeModules[plugin].nodes;
|
||||
var m = {
|
||||
name: plugin,
|
||||
nodes: []
|
||||
};
|
||||
for (var i = 0; i < nodes.length; ++i) {
|
||||
m.nodes.push(filterNodeInfo(nodeConfigs[nodes[i]]));
|
||||
getModuleInfo: function(module) {
|
||||
if (moduleNodes[module]) {
|
||||
var nodes = moduleNodes[module];
|
||||
var m = {
|
||||
name: module,
|
||||
version: moduleConfigs[module].version,
|
||||
nodes: []
|
||||
};
|
||||
for (var i = 0; i < nodes.length; ++i) {
|
||||
m.nodes.push(filterNodeInfo(moduleConfigs[module].nodes[nodes[i]]));
|
||||
}
|
||||
return m;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return m;
|
||||
},
|
||||
registerNodeConstructor: function(type,constructor) {
|
||||
if (nodeConstructors[type]) {
|
||||
@ -214,7 +252,8 @@ var registry = (function() {
|
||||
var result = "";
|
||||
var script = "";
|
||||
for (var i=0;i<nodeList.length;i++) {
|
||||
var config = nodeConfigs[nodeList[i]];
|
||||
var id = nodeList[i];
|
||||
var config = moduleConfigs[getModule(id)].nodes[getNode(id)];
|
||||
if (config.enabled && !config.err) {
|
||||
result += config.config;
|
||||
script += config.script;
|
||||
@ -231,7 +270,7 @@ var registry = (function() {
|
||||
},
|
||||
|
||||
getNodeConfig: function(id) {
|
||||
var config = nodeConfigs[id];
|
||||
var config = moduleConfigs[getModule(id)].nodes[getNode(id)];
|
||||
if (config) {
|
||||
var result = config.config;
|
||||
if (config.script) {
|
||||
@ -244,7 +283,15 @@ var registry = (function() {
|
||||
},
|
||||
|
||||
getNodeConstructor: function(type) {
|
||||
var config = nodeConfigs[nodeTypeToId[type]];
|
||||
var id = nodeTypeToId[type];
|
||||
|
||||
var config;
|
||||
if (typeof id === "undefined") {
|
||||
config = undefined;
|
||||
} else {
|
||||
config = moduleConfigs[getModule(id)].nodes[getNode(id)];
|
||||
}
|
||||
|
||||
if (!config || (config.enabled && !config.err)) {
|
||||
return nodeConstructors[type];
|
||||
}
|
||||
@ -253,7 +300,7 @@ var registry = (function() {
|
||||
|
||||
clear: function() {
|
||||
nodeConfigCache = null;
|
||||
nodeConfigs = {};
|
||||
moduleConfigs = {};
|
||||
nodeList = [];
|
||||
nodeConstructors = {};
|
||||
nodeTypeToId = {};
|
||||
@ -263,21 +310,23 @@ var registry = (function() {
|
||||
return nodeTypeToId[type];
|
||||
},
|
||||
|
||||
getModuleInfo: function(type) {
|
||||
return nodeModules[type];
|
||||
getNodeModuleInfo: function(module) {
|
||||
return moduleNodes[module];
|
||||
},
|
||||
|
||||
enableNodeSet: function(id) {
|
||||
enableNodeSet: function(typeOrId) {
|
||||
if (!settings.available()) {
|
||||
throw new Error("Settings unavailable");
|
||||
}
|
||||
var config;
|
||||
if (nodeTypeToId[id]) {
|
||||
config = nodeConfigs[nodeTypeToId[id]];
|
||||
} else {
|
||||
config = nodeConfigs[id];
|
||||
|
||||
var id = typeOrId;
|
||||
if (nodeTypeToId[typeOrId]) {
|
||||
id = nodeTypeToId[typeOrId];
|
||||
}
|
||||
if (config) {
|
||||
|
||||
var config;
|
||||
try {
|
||||
config = moduleConfigs[getModule(id)].nodes[getNode(id)];
|
||||
delete config.err;
|
||||
config.enabled = true;
|
||||
if (!config.loaded) {
|
||||
@ -286,28 +335,28 @@ var registry = (function() {
|
||||
}
|
||||
nodeConfigCache = null;
|
||||
saveNodeList();
|
||||
} else {
|
||||
throw new Error("Unrecognised id: "+id);
|
||||
} catch (err) {
|
||||
throw new Error("Unrecognised id: "+typeOrId);
|
||||
}
|
||||
return filterNodeInfo(config);
|
||||
},
|
||||
|
||||
disableNodeSet: function(id) {
|
||||
disableNodeSet: function(typeOrId) {
|
||||
if (!settings.available()) {
|
||||
throw new Error("Settings unavailable");
|
||||
}
|
||||
var config;
|
||||
if (nodeTypeToId[id]) {
|
||||
config = nodeConfigs[nodeTypeToId[id]];
|
||||
} else {
|
||||
config = nodeConfigs[id];
|
||||
var id = typeOrId;
|
||||
if (nodeTypeToId[typeOrId]) {
|
||||
id = nodeTypeToId[typeOrId];
|
||||
}
|
||||
if (config) {
|
||||
var config;
|
||||
try {
|
||||
config = moduleConfigs[getModule(id)].nodes[getNode(id)];
|
||||
// TODO: persist setting
|
||||
config.enabled = false;
|
||||
nodeConfigCache = null;
|
||||
saveNodeList();
|
||||
} else {
|
||||
} catch (err) {
|
||||
throw new Error("Unrecognised id: "+id);
|
||||
}
|
||||
return filterNodeInfo(config);
|
||||
@ -315,13 +364,18 @@ var registry = (function() {
|
||||
|
||||
saveNodeList: saveNodeList,
|
||||
|
||||
cleanNodeList: function() {
|
||||
cleanModuleList: function() {
|
||||
var removed = false;
|
||||
for (var id in nodeConfigs) {
|
||||
if (nodeConfigs.hasOwnProperty(id)) {
|
||||
if (nodeConfigs[id].module && !nodeModules[nodeConfigs[id].module]) {
|
||||
registry.removeNode(id);
|
||||
removed = true;
|
||||
for (var mod in moduleConfigs) {
|
||||
if (moduleConfigs.hasOwnProperty(mod)) {
|
||||
if (moduleConfigs[mod] && !moduleNodes[mod]) {
|
||||
var nodes = moduleConfigs[mod].nodes;
|
||||
for (var node in nodes) {
|
||||
if (nodes.hasOwnProperty(node)) {
|
||||
registry.removeNode(mod+"/"+node);
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -401,7 +455,7 @@ function scanTreeForNodesModules(moduleName) {
|
||||
var files = fs.readdirSync(pm);
|
||||
for (var i=0;i<files.length;i++) {
|
||||
var fn = files[i];
|
||||
if (!registry.getModuleInfo(fn)) {
|
||||
if (!registry.getNodeModuleInfo(fn)) {
|
||||
if (!moduleName || fn == moduleName) {
|
||||
var pkgfn = path.join(pm,fn,"package.json");
|
||||
try {
|
||||
@ -435,7 +489,7 @@ function scanTreeForNodesModules(moduleName) {
|
||||
* @param moduleDir the root directory of the package
|
||||
* @param pkg the module's package.json object
|
||||
*/
|
||||
function loadNodesFromModule(moduleDir,pkg) {
|
||||
function loadNodesFromModule(moduleDir,pkg,version) {
|
||||
var nodes = pkg['node-red'].nodes||{};
|
||||
var results = [];
|
||||
var iconDirs = [];
|
||||
@ -443,7 +497,7 @@ function loadNodesFromModule(moduleDir,pkg) {
|
||||
if (nodes.hasOwnProperty(n)) {
|
||||
var file = path.join(moduleDir,nodes[n]);
|
||||
try {
|
||||
results.push(loadNodeConfig(file,pkg.name,n));
|
||||
results.push(loadNodeConfig(file,pkg.name,n,version));
|
||||
} catch(err) {
|
||||
}
|
||||
var iconDir = path.join(moduleDir,path.dirname(nodes[n]),"icons");
|
||||
@ -474,20 +528,8 @@ function loadNodesFromModule(moduleDir,pkg) {
|
||||
* types: an array of node type names in this file
|
||||
* }
|
||||
*/
|
||||
function loadNodeConfig(file,module,name) {
|
||||
var id = crypto.createHash('sha1').update(file).digest("hex");
|
||||
if (module && name) {
|
||||
var newid = crypto.createHash('sha1').update(module+":"+name).digest("hex");
|
||||
var existingInfo = registry.getNodeInfo(id);
|
||||
if (existingInfo) {
|
||||
// For a brief period, id for modules were calculated incorrectly.
|
||||
// To prevent false-duplicates, this removes the old id entry
|
||||
registry.removeNode(id);
|
||||
registry.saveNodeList();
|
||||
}
|
||||
id = newid;
|
||||
|
||||
}
|
||||
function loadNodeConfig(file,module,name,version) {
|
||||
var id = module + "/" + name;
|
||||
var info = registry.getNodeInfo(id);
|
||||
|
||||
var isEnabled = true;
|
||||
@ -501,18 +543,14 @@ function loadNodeConfig(file,module,name) {
|
||||
|
||||
var node = {
|
||||
id: id,
|
||||
module: module,
|
||||
name: name,
|
||||
file: file,
|
||||
template: file.replace(/\.js$/,".html"),
|
||||
enabled: isEnabled,
|
||||
loaded:false
|
||||
};
|
||||
|
||||
if (module) {
|
||||
node.name = module+":"+name;
|
||||
node.module = module;
|
||||
} else {
|
||||
node.name = path.basename(file);
|
||||
}
|
||||
try {
|
||||
var content = fs.readFileSync(node.template,'utf8');
|
||||
|
||||
@ -544,7 +582,7 @@ function loadNodeConfig(file,module,name) {
|
||||
node.err = err.toString();
|
||||
}
|
||||
}
|
||||
registry.addNodeSet(id,node);
|
||||
registry.addNodeSet(id,node,version);
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -576,7 +614,7 @@ function load(defaultNodesDir,disableNodePathScan) {
|
||||
var nodes = [];
|
||||
nodeFiles.forEach(function(file) {
|
||||
try {
|
||||
nodes.push(loadNodeConfig(file));
|
||||
nodes.push(loadNodeConfig(file,"node-red",path.basename(file).replace(/^\d+-/,"").replace(/\.js$/,"")));
|
||||
} catch(err) {
|
||||
//
|
||||
}
|
||||
@ -682,19 +720,19 @@ function addNode(file) {
|
||||
}
|
||||
var nodes = [];
|
||||
try {
|
||||
nodes.push(loadNodeConfig(file));
|
||||
nodes.push(loadNodeConfig(file,"node-red",path.basename(file).replace(/^\d+-/,"").replace(/\.js$/,"")));
|
||||
} catch(err) {
|
||||
return when.reject(err);
|
||||
}
|
||||
return loadNodeList(nodes);
|
||||
}
|
||||
|
||||
function addModule(module) {
|
||||
function addModule(module,version) {
|
||||
if (!settings.available()) {
|
||||
throw new Error("Settings unavailable");
|
||||
}
|
||||
var nodes = [];
|
||||
if (registry.getModuleInfo(module)) {
|
||||
if (registry.getNodeModuleInfo(module)) {
|
||||
return when.reject(new Error("Module already loaded"));
|
||||
}
|
||||
var moduleFiles = scanTreeForNodesModules(module);
|
||||
@ -704,7 +742,7 @@ function addModule(module) {
|
||||
return when.reject(err);
|
||||
}
|
||||
moduleFiles.forEach(function(moduleFile) {
|
||||
nodes = nodes.concat(loadNodesFromModule(moduleFile.dir,moduleFile.package));
|
||||
nodes = nodes.concat(loadNodesFromModule(moduleFile.dir,moduleFile.package,version));
|
||||
});
|
||||
return loadNodeList(nodes);
|
||||
}
|
||||
@ -714,14 +752,19 @@ module.exports = {
|
||||
load:load,
|
||||
clear: registry.clear,
|
||||
registerType: registry.registerNodeConstructor,
|
||||
|
||||
get: registry.getNodeConstructor,
|
||||
getNodeInfo: registry.getNodeInfo,
|
||||
getNodeModuleInfo: registry.getModuleInfo,
|
||||
getPluginInfo: registry.getPluginInfo,
|
||||
getNodeList: registry.getNodeList,
|
||||
getPluginList: registry.getPluginList,
|
||||
|
||||
getNodeModuleInfo: registry.getNodeModuleInfo,
|
||||
|
||||
getModuleInfo: registry.getModuleInfo,
|
||||
getModuleList: registry.getModuleList,
|
||||
|
||||
getNodeConfigs: registry.getAllNodeConfigs,
|
||||
getNodeConfig: registry.getNodeConfig,
|
||||
|
||||
addNode: addNode,
|
||||
removeNode: registry.removeNode,
|
||||
enableNode: registry.enableNodeSet,
|
||||
@ -729,5 +772,5 @@ module.exports = {
|
||||
|
||||
addModule: addModule,
|
||||
removeModule: registry.removeModule,
|
||||
cleanNodeList: registry.cleanNodeList
|
||||
cleanModuleList: registry.cleanModuleList
|
||||
};
|
||||
|
@ -33,10 +33,10 @@ function init(_server,_settings) {
|
||||
settings = _settings;
|
||||
|
||||
comms.init(_server,_settings);
|
||||
|
||||
|
||||
nodeApp = express();
|
||||
app = express();
|
||||
|
||||
|
||||
if (settings.httpAdminRoot !== false) {
|
||||
require("./api").init(app);
|
||||
}
|
||||
@ -44,7 +44,7 @@ function init(_server,_settings) {
|
||||
|
||||
function start() {
|
||||
var defer = when.defer();
|
||||
|
||||
|
||||
storage.init(settings).then(function() {
|
||||
settings.load(storage).then(function() {
|
||||
console.log("\nWelcome to Node-RED\n===================\n");
|
||||
@ -91,11 +91,11 @@ function start() {
|
||||
}
|
||||
if (!settings.autoInstallModules) {
|
||||
util.log("[red] Removing modules from config");
|
||||
redNodes.cleanNodeList();
|
||||
redNodes.cleanModuleList();
|
||||
}
|
||||
}
|
||||
defer.resolve();
|
||||
|
||||
|
||||
redNodes.loadFlows();
|
||||
}).otherwise(function(err) {
|
||||
console.log(err);
|
||||
@ -105,7 +105,7 @@ function start() {
|
||||
}).otherwise(function(err) {
|
||||
defer.reject(err);
|
||||
});
|
||||
|
||||
|
||||
return defer.promise;
|
||||
}
|
||||
|
||||
@ -138,7 +138,7 @@ function reportRemovedModules(removedNodes) {
|
||||
return removedNodes;
|
||||
}
|
||||
|
||||
function installModule(module) {
|
||||
function installModule(module) {
|
||||
//TODO: ensure module is 'safe'
|
||||
return when.promise(function(resolve,reject) {
|
||||
if (/[\s;]/.test(module)) {
|
||||
@ -162,8 +162,11 @@ function installModule(module) {
|
||||
reject(new Error("Install failed"));
|
||||
}
|
||||
} else {
|
||||
util.log("[red] Installed module: "+module);
|
||||
resolve(redNodes.addModule(module).then(reportAddedModules));
|
||||
var grandchild = child_process.exec('npm view '+module+' version', function(err, stdin, stdout) {
|
||||
var version = stdin.replace(/\s/g, "");
|
||||
util.log("[red] Installed module: "+module+":"+version);
|
||||
resolve(redNodes.addModule(module,version).then(reportAddedModules));
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -200,11 +203,11 @@ function stop() {
|
||||
comms.stop();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
module.exports = {
|
||||
init: init,
|
||||
start: start,
|
||||
stop: stop,
|
||||
|
||||
|
||||
reportAddedModules: reportAddedModules,
|
||||
reportRemovedModules: reportRemovedModules,
|
||||
installModule: installModule,
|
||||
|
@ -28,7 +28,7 @@ var settings = require("../../../red/settings");
|
||||
var nodes = require("../../../red/api/nodes");
|
||||
|
||||
describe("nodes api", function() {
|
||||
|
||||
|
||||
var app;
|
||||
|
||||
before(function() {
|
||||
@ -36,11 +36,13 @@ describe("nodes api", function() {
|
||||
app.use(express.json());
|
||||
app.get("/nodes",nodes.getAll);
|
||||
app.post("/nodes",nodes.post);
|
||||
app.get("/nodes/:id",nodes.get);
|
||||
app.put("/nodes/:id",nodes.put);
|
||||
app.get("/nodes/:mod",nodes.getModule);
|
||||
app.get("/nodes/:mod/:set",nodes.getSet);
|
||||
app.put("/nodes/:mod",nodes.putModule);
|
||||
app.put("/nodes/:mod/:set",nodes.putSet);
|
||||
app.delete("/nodes/:id",nodes.delete);
|
||||
});
|
||||
|
||||
|
||||
describe('get nodes', function() {
|
||||
it('returns node list', function(done) {
|
||||
var getNodeList = sinon.stub(redNodes,'getNodeList', function() {
|
||||
@ -59,7 +61,7 @@ describe("nodes api", function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('returns node configs', function(done) {
|
||||
var getNodeConfigs = sinon.stub(redNodes,'getNodeConfigs', function() {
|
||||
return "<script></script>";
|
||||
@ -77,13 +79,46 @@ describe("nodes api", function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('returns an individual node info', function(done) {
|
||||
var getNodeInfo = sinon.stub(redNodes,'getNodeInfo', function(id) {
|
||||
return {"123":{id:"123"}}[id];
|
||||
|
||||
it('returns node module info', function(done) {
|
||||
var getNodeInfo = sinon.stub(redNodes,'getModuleInfo', function(id) {
|
||||
return {"node-red":{name:"node-red"}}[id];
|
||||
});
|
||||
request(app)
|
||||
.get('/nodes/123')
|
||||
.get('/nodes/node-red')
|
||||
.expect(200)
|
||||
.end(function(err,res) {
|
||||
getNodeInfo.restore();
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
res.body.should.have.property("name","node-red");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('returns 404 for unknown module', function(done) {
|
||||
var getNodeInfo = sinon.stub(redNodes,'getModuleInfo', function(id) {
|
||||
return {"node-red":{name:"node-red"}}[id];
|
||||
});
|
||||
request(app)
|
||||
.get('/nodes/node-blue')
|
||||
.expect(404)
|
||||
.end(function(err,res) {
|
||||
getNodeInfo.restore();
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('returns individual node info', function(done) {
|
||||
var getNodeInfo = sinon.stub(redNodes,'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) {
|
||||
@ -91,17 +126,17 @@ describe("nodes api", function() {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
res.body.should.have.property("id","123");
|
||||
res.body.should.have.property("id","node-red/123");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('returns an individual node configs', function(done) {
|
||||
|
||||
it('returns individual node configs', function(done) {
|
||||
var getNodeConfig = sinon.stub(redNodes,'getNodeConfig', function(id) {
|
||||
return {"123":"<script></script>"}[id];
|
||||
return {"node-red/123":"<script></script>"}[id];
|
||||
});
|
||||
request(app)
|
||||
.get('/nodes/123')
|
||||
.get('/nodes/node-red/123')
|
||||
.set('Accept', 'text/html')
|
||||
.expect(200)
|
||||
.expect("<script></script>")
|
||||
@ -113,13 +148,13 @@ describe("nodes api", function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('returns 404 for unknown node', function(done) {
|
||||
var getNodeInfo = sinon.stub(redNodes,'getNodeInfo', function(id) {
|
||||
return {"123":{id:"123"}}[id];
|
||||
return {"node-red/123":{id:"node-red/123"}}[id];
|
||||
});
|
||||
request(app)
|
||||
.get('/nodes/456')
|
||||
.get('/nodes/node-red/456')
|
||||
.set('Accept', 'application/json')
|
||||
.expect(404)
|
||||
.end(function(err,res) {
|
||||
@ -131,9 +166,9 @@ describe("nodes api", function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('install', function() {
|
||||
|
||||
|
||||
it('returns 400 if settings are unavailable', function(done) {
|
||||
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||
return false;
|
||||
@ -166,19 +201,27 @@ describe("nodes api", function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('by module', function() {
|
||||
it('installs the module and returns node info', function(done) {
|
||||
it('installs the module and returns module info', function(done) {
|
||||
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||
return true;
|
||||
});
|
||||
var getNodeModuleInfo = sinon.stub(redNodes,'getNodeModuleInfo',function(id) {
|
||||
return null;
|
||||
});
|
||||
var getModuleInfo = sinon.stub(redNodes,'getModuleInfo',function(module) {
|
||||
if (module === "foo") {
|
||||
return {
|
||||
name:"foo",
|
||||
nodes:[{id:123}]
|
||||
};
|
||||
}
|
||||
});
|
||||
var installModule = sinon.stub(server,'installModule', function() {
|
||||
return when.resolve({id:"123"});
|
||||
});
|
||||
|
||||
|
||||
request(app)
|
||||
.post('/nodes')
|
||||
.send({module: 'foo'})
|
||||
@ -186,15 +229,18 @@ describe("nodes api", function() {
|
||||
.end(function(err,res) {
|
||||
settingsAvailable.restore();
|
||||
getNodeModuleInfo.restore();
|
||||
getModuleInfo.restore();
|
||||
installModule.restore();
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
res.body.should.have.property("id","123");
|
||||
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) {
|
||||
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||
return true;
|
||||
@ -205,7 +251,7 @@ describe("nodes api", function() {
|
||||
var installModule = sinon.stub(server,'installModule', function() {
|
||||
return when.resolve({id:"123"});
|
||||
});
|
||||
|
||||
|
||||
request(app)
|
||||
.post('/nodes')
|
||||
.send({module: 'foo'})
|
||||
@ -220,7 +266,7 @@ describe("nodes api", function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('fails the install if module error', function(done) {
|
||||
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||
return true;
|
||||
@ -231,7 +277,7 @@ describe("nodes api", function() {
|
||||
var installModule = sinon.stub(server,'installModule', function() {
|
||||
return when.reject(new Error("test error"));
|
||||
});
|
||||
|
||||
|
||||
request(app)
|
||||
.post('/nodes')
|
||||
.send({module: 'foo'})
|
||||
@ -259,7 +305,7 @@ describe("nodes api", function() {
|
||||
err.code = 404;
|
||||
return when.reject(err);
|
||||
});
|
||||
|
||||
|
||||
request(app)
|
||||
.post('/nodes')
|
||||
.send({module: 'foo'})
|
||||
@ -292,9 +338,9 @@ describe("nodes api", function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('by module', function() {
|
||||
it('uninstalls the module and returns node info', function(done) {
|
||||
it('uninstalls the module', function(done) {
|
||||
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||
return true;
|
||||
});
|
||||
@ -307,10 +353,10 @@ describe("nodes api", function() {
|
||||
var uninstallModule = sinon.stub(server,'uninstallModule', function() {
|
||||
return when.resolve({id:"123"});
|
||||
});
|
||||
|
||||
|
||||
request(app)
|
||||
.del('/nodes/foo')
|
||||
.expect(200)
|
||||
.expect(204)
|
||||
.end(function(err,res) {
|
||||
settingsAvailable.restore();
|
||||
getNodeInfo.restore();
|
||||
@ -319,11 +365,10 @@ describe("nodes api", function() {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
res.body.should.have.property("id","123");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('fails the uninstall if the module is not installed', function(done) {
|
||||
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||
return true;
|
||||
@ -334,7 +379,7 @@ describe("nodes api", function() {
|
||||
var getNodeModuleInfo = sinon.stub(redNodes,'getNodeModuleInfo',function(id) {
|
||||
return null;
|
||||
});
|
||||
|
||||
|
||||
request(app)
|
||||
.del('/nodes/foo')
|
||||
.expect(404)
|
||||
@ -381,7 +426,7 @@ describe("nodes api", function() {
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('enable/disable', function() {
|
||||
it('returns 400 if settings are unavailable', function(done) {
|
||||
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||
@ -398,8 +443,28 @@ describe("nodes api", function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('returns 400 for invalid payload', function(done) {
|
||||
|
||||
it('returns 400 for invalid node payload', function(done) {
|
||||
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||
return true;
|
||||
});
|
||||
|
||||
request(app)
|
||||
.put('/nodes/node-red/foo')
|
||||
.send({})
|
||||
.expect(400)
|
||||
.end(function(err,res) {
|
||||
settingsAvailable.restore();
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
res.text.should.equal("Invalid request");
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('returns 400 for invalid module payload', function(done) {
|
||||
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||
return true;
|
||||
});
|
||||
@ -418,6 +483,7 @@ describe("nodes api", function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('returns 404 for unknown node', function(done) {
|
||||
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||
return true;
|
||||
@ -427,7 +493,7 @@ describe("nodes api", function() {
|
||||
});
|
||||
|
||||
request(app)
|
||||
.put('/nodes/foo')
|
||||
.put('/nodes/node-red/foo')
|
||||
.send({enabled:false})
|
||||
.expect(404)
|
||||
.end(function(err,res) {
|
||||
@ -439,7 +505,29 @@ describe("nodes api", function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('returns 404 for unknown module', function(done) {
|
||||
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||
return true;
|
||||
});
|
||||
var getModuleInfo = sinon.stub(redNodes,'getModuleInfo',function(id) {
|
||||
return null;
|
||||
});
|
||||
|
||||
request(app)
|
||||
.put('/nodes/node-blue')
|
||||
.send({enabled:false})
|
||||
.expect(404)
|
||||
.end(function(err,res) {
|
||||
settingsAvailable.restore();
|
||||
getModuleInfo.restore();
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('enables disabled node', function(done) {
|
||||
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||
return true;
|
||||
@ -452,7 +540,7 @@ describe("nodes api", function() {
|
||||
});
|
||||
|
||||
request(app)
|
||||
.put('/nodes/foo')
|
||||
.put('/nodes/node-red/foo')
|
||||
.send({enabled:true})
|
||||
.expect(200)
|
||||
.end(function(err,res) {
|
||||
@ -464,10 +552,11 @@ describe("nodes api", function() {
|
||||
}
|
||||
res.body.should.have.property("id","123");
|
||||
res.body.should.have.property("enabled",true);
|
||||
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('disables enabled node', function(done) {
|
||||
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||
return true;
|
||||
@ -480,7 +569,7 @@ describe("nodes api", function() {
|
||||
});
|
||||
|
||||
request(app)
|
||||
.put('/nodes/foo')
|
||||
.put('/nodes/node-red/foo')
|
||||
.send({enabled:false})
|
||||
.expect(200)
|
||||
.end(function(err,res) {
|
||||
@ -492,10 +581,11 @@ describe("nodes api", function() {
|
||||
}
|
||||
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 settingsAvailable = sinon.stub(settings,'available', function() {
|
||||
@ -507,13 +597,13 @@ describe("nodes api", function() {
|
||||
var enableNode = sinon.stub(redNodes,'enableNode',function(id) {
|
||||
return {id:"123",enabled: true,types:['a']};
|
||||
});
|
||||
|
||||
|
||||
var disableNode = sinon.stub(redNodes,'disableNode',function(id) {
|
||||
return {id:"123",enabled: false,types:['a']};
|
||||
});
|
||||
|
||||
|
||||
request(app)
|
||||
.put('/nodes/foo')
|
||||
.put('/nodes/node-red/foo')
|
||||
.send({enabled:state})
|
||||
.expect(200)
|
||||
.end(function(err,res) {
|
||||
@ -530,7 +620,7 @@ describe("nodes api", function() {
|
||||
disableNodeCalled.should.be.false;
|
||||
res.body.should.have.property("id","123");
|
||||
res.body.should.have.property("enabled",state);
|
||||
|
||||
|
||||
done();
|
||||
});
|
||||
}
|
||||
@ -541,6 +631,7 @@ describe("nodes api", function() {
|
||||
run(false,done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('does not no-op if err on node', function() {
|
||||
function run(state,done) {
|
||||
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||
@ -552,13 +643,13 @@ describe("nodes api", function() {
|
||||
var enableNode = sinon.stub(redNodes,'enableNode',function(id) {
|
||||
return {id:"123",enabled: true,types:['a']};
|
||||
});
|
||||
|
||||
|
||||
var disableNode = sinon.stub(redNodes,'disableNode',function(id) {
|
||||
return {id:"123",enabled: false,types:['a']};
|
||||
});
|
||||
|
||||
|
||||
request(app)
|
||||
.put('/nodes/foo')
|
||||
.put('/nodes/node-red/foo')
|
||||
.send({enabled:state})
|
||||
.expect(200)
|
||||
.end(function(err,res) {
|
||||
@ -575,7 +666,187 @@ describe("nodes api", function() {
|
||||
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 settingsAvailable = sinon.stub(settings,'available', function() {
|
||||
return true;
|
||||
});
|
||||
var getModuleInfo = sinon.stub(redNodes,'getModuleInfo',function(name) {
|
||||
return {name:"node-red", nodes:[n1, n2]};
|
||||
});
|
||||
|
||||
var enableNode = sinon.stub(redNodes,'enableNode');
|
||||
enableNode.onFirstCall().returns((function() {
|
||||
n1.enabled = true;
|
||||
return n1;
|
||||
})());
|
||||
enableNode.onSecondCall().returns((function() {
|
||||
n2.enabled = true;
|
||||
return n2;
|
||||
})());
|
||||
enableNode.returns(null);
|
||||
|
||||
request(app)
|
||||
.put('/nodes/node-red')
|
||||
.send({enabled:true})
|
||||
.expect(200)
|
||||
.end(function(err,res) {
|
||||
settingsAvailable.restore();
|
||||
getModuleInfo.restore();
|
||||
enableNode.restore();
|
||||
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 settingsAvailable = sinon.stub(settings,'available', function() {
|
||||
return true;
|
||||
});
|
||||
var getModuleInfo = sinon.stub(redNodes,'getModuleInfo',function(name) {
|
||||
return {name:"node-red", nodes:[n1, n2]};
|
||||
});
|
||||
|
||||
var disableNode = sinon.stub(redNodes,'disableNode');
|
||||
disableNode.onFirstCall().returns((function() {
|
||||
n1.enabled = false;
|
||||
return n1;
|
||||
})());
|
||||
disableNode.onSecondCall().returns((function() {
|
||||
n2.enabled = false;
|
||||
return n2;
|
||||
})());
|
||||
disableNode.returns(null);
|
||||
|
||||
request(app)
|
||||
.put('/nodes/node-red')
|
||||
.send({enabled:false})
|
||||
.expect(200)
|
||||
.end(function(err,res) {
|
||||
settingsAvailable.restore();
|
||||
getModuleInfo.restore();
|
||||
disableNode.restore();
|
||||
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 settingsAvailable = sinon.stub(settings,'available', function() {
|
||||
return true;
|
||||
});
|
||||
var getModuleInfo = sinon.stub(redNodes,'getModuleInfo',function(id) {
|
||||
return {name:"node-red", nodes:[node]};
|
||||
});
|
||||
var enableNode = sinon.stub(redNodes,'enableNode',function(id) {
|
||||
node.enabled = true;
|
||||
return node;
|
||||
});
|
||||
var disableNode = sinon.stub(redNodes,'disableNode',function(id) {
|
||||
node.enabled = false;
|
||||
return node;
|
||||
});
|
||||
|
||||
request(app)
|
||||
.put('/nodes/node-red')
|
||||
.send({enabled:state})
|
||||
.expect(200)
|
||||
.end(function(err,res) {
|
||||
settingsAvailable.restore();
|
||||
getModuleInfo.restore();
|
||||
var enableNodeCalled = enableNode.called;
|
||||
var disableNodeCalled = disableNode.called;
|
||||
enableNode.restore();
|
||||
disableNode.restore();
|
||||
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 settingsAvailable = sinon.stub(settings,'available', function() {
|
||||
return true;
|
||||
});
|
||||
var getModuleInfo = sinon.stub(redNodes,'getModuleInfo',function(id) {
|
||||
return {name:"node-red", nodes:[node]};
|
||||
});
|
||||
var enableNode = sinon.stub(redNodes,'enableNode',function(id) {
|
||||
node.enabled = true;
|
||||
return node;
|
||||
});
|
||||
var disableNode = sinon.stub(redNodes,'disableNode',function(id) {
|
||||
node.enabled = false;
|
||||
return node;
|
||||
});
|
||||
|
||||
request(app)
|
||||
.put('/nodes/node-red')
|
||||
.send({enabled:state})
|
||||
.expect(200)
|
||||
.end(function(err,res) {
|
||||
settingsAvailable.restore();
|
||||
getModuleInfo.restore();
|
||||
var enableNodeCalled = enableNode.called;
|
||||
var disableNodeCalled = disableNode.called;
|
||||
enableNode.restore();
|
||||
disableNode.restore();
|
||||
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();
|
||||
});
|
||||
}
|
||||
@ -587,6 +858,6 @@ describe("nodes api", function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
@ -1,77 +0,0 @@
|
||||
/**
|
||||
* Copyright 2014 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var should = require("should");
|
||||
var request = require('supertest');
|
||||
var express = require('express');
|
||||
var sinon = require('sinon');
|
||||
var when = require('when');
|
||||
|
||||
var app = express();
|
||||
var redNodes = require("../../../red/nodes");
|
||||
var server = require("../../../red/server");
|
||||
var settings = require("../../../red/settings");
|
||||
|
||||
var plugins = require("../../../red/api/plugins");
|
||||
|
||||
describe("plugins api", function() {
|
||||
|
||||
var app;
|
||||
|
||||
before(function() {
|
||||
app = express();
|
||||
app.use(express.json());
|
||||
app.get("/plugins",plugins.getAll);
|
||||
app.get("/plugins/:id",plugins.get);
|
||||
});
|
||||
|
||||
describe('get plugins', function() {
|
||||
it('returns plugins list', function(done) {
|
||||
var getPluginList = sinon.stub(redNodes,'getPluginList', function() {
|
||||
return [1,2,3];
|
||||
});
|
||||
request(app)
|
||||
.get('/plugins')
|
||||
.expect(200)
|
||||
.end(function(err,res) {
|
||||
getPluginList.restore();
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
res.body.should.be.an.Array.and.have.lengthOf(3);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('returns an individual plugin info', function(done) {
|
||||
var getPluginInfo = sinon.stub(redNodes,'getPluginInfo', function(id) {
|
||||
return {"name":"123", "nodes":[1,2,3]};
|
||||
});
|
||||
request(app)
|
||||
.get('/plugins/123')
|
||||
.expect(200)
|
||||
.end(function(err,res) {
|
||||
getPluginInfo.restore();
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
res.body.should.have.property("name","123");
|
||||
res.body.should.have.property("nodes",[1,2,3]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -1,53 +0,0 @@
|
||||
/**
|
||||
* Copyright 2014 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var should = require("should");
|
||||
var sinon = require("sinon");
|
||||
var fs = require("fs");
|
||||
|
||||
var config = require("../../../../red/cli/lib/config");
|
||||
|
||||
describe("cli config", function() {
|
||||
afterEach(function() {
|
||||
config.unload();
|
||||
});
|
||||
it('loads preferences when target referenced', sinon.test(function() {
|
||||
this.stub(fs,"readFileSync",function() {
|
||||
return '{"target":"http://example.com:1880"}'
|
||||
});
|
||||
config.target.should.eql("http://example.com:1880");
|
||||
}));
|
||||
it('provide default value for target', sinon.test(function() {
|
||||
this.stub(fs,"readFileSync",function() {
|
||||
return '{}'
|
||||
});
|
||||
config.target.should.eql("http://localhost:1880");
|
||||
}));
|
||||
it('saves preferences when target set', sinon.test(function() {
|
||||
this.stub(fs,"readFileSync",function() {
|
||||
return '{"target":"http://another.example.com:1880"}'
|
||||
});
|
||||
this.stub(fs,"writeFileSync",function() {});
|
||||
|
||||
config.target.should.eql("http://another.example.com:1880");
|
||||
config.target = "http://final.example.com:1880";
|
||||
|
||||
fs.readFileSync.calledOnce.should.be.true;
|
||||
fs.writeFileSync.calledOnce.should.be.true;
|
||||
|
||||
}));
|
||||
|
||||
});
|
@ -1,46 +0,0 @@
|
||||
/**
|
||||
* Copyright 2014 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var should = require("should");
|
||||
var sinon = require("sinon");
|
||||
var fs = require("fs");
|
||||
var request = require("request");
|
||||
|
||||
var apiRequest = require("../../../../red/cli/lib/request");
|
||||
var config = require("../../../../red/cli/lib/config");
|
||||
|
||||
describe("cli request", function() {
|
||||
var sandbox = sinon.sandbox.create();
|
||||
before(function() {
|
||||
sandbox.stub(fs,"readFileSync",function() {
|
||||
return '{"target":"http://example.com:1880"}'
|
||||
});
|
||||
});
|
||||
after(function() {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
it('returns the json response to a get', sinon.test(function(done) {
|
||||
this.stub(request, 'get').yields(null, {statusCode:200}, JSON.stringify({a: "b"}));
|
||||
|
||||
apiRequest("/foo",{}).then(function(res) {
|
||||
res.should.eql({a:"b"});
|
||||
done();
|
||||
}).otherwise(function(err) {
|
||||
done(err);
|
||||
});
|
||||
}));
|
||||
});
|
@ -1,15 +0,0 @@
|
||||
/**
|
||||
* Copyright 2014 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
@ -23,7 +23,7 @@ var sinon = require('sinon');
|
||||
var index = require("../../../red/nodes/index");
|
||||
|
||||
describe("red/nodes/index", function() {
|
||||
|
||||
|
||||
afterEach(function() {
|
||||
index.clearRegistry();
|
||||
});
|
||||
@ -44,7 +44,7 @@ describe("red/nodes/index", function() {
|
||||
return when(true);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var settings = {
|
||||
available: function() { return false }
|
||||
};
|
||||
@ -56,13 +56,13 @@ describe("red/nodes/index", function() {
|
||||
// do nothing
|
||||
});
|
||||
}
|
||||
|
||||
it('nodes are initialised with credentials',function(done) {
|
||||
|
||||
it('nodes are initialised with credentials',function(done) {
|
||||
|
||||
index.init(settings, storage);
|
||||
index.registerType('test', TestNode);
|
||||
index.registerType('test', TestNode);
|
||||
index.loadFlows().then(function() {
|
||||
var testnode = new TestNode({id:'tab1',type:'test',name:'barney'});
|
||||
var testnode = new TestNode({id:'tab1',type:'test',name:'barney'});
|
||||
testnode.credentials.should.have.property('b',1);
|
||||
testnode.credentials.should.have.property('c',2);
|
||||
done();
|
||||
@ -71,8 +71,8 @@ describe("red/nodes/index", function() {
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('flows should be initialised',function(done) {
|
||||
|
||||
it('flows should be initialised',function(done) {
|
||||
index.init(settings, storage);
|
||||
index.loadFlows().then(function() {
|
||||
should.deepEqual(testFlows, index.getFlows());
|
||||
@ -82,7 +82,7 @@ describe("red/nodes/index", function() {
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe("registerType should register credentials definition", function() {
|
||||
var http = require('http');
|
||||
var express = require('express');
|
||||
@ -91,7 +91,7 @@ describe("red/nodes/index", function() {
|
||||
var credentials = require("../../../red/nodes/credentials");
|
||||
var localfilesystem = require("../../../red/storage/localfilesystem");
|
||||
var RED = require("../../../red/red.js");
|
||||
|
||||
|
||||
var userDir = path.join(__dirname,".testUserHome");
|
||||
before(function(done) {
|
||||
fs.remove(userDir,function(err) {
|
||||
@ -109,7 +109,7 @@ describe("red/nodes/index", function() {
|
||||
RED.init(http.createServer(function(req,res){app(req,res)}),
|
||||
{userDir: userDir});
|
||||
server.start().then(function () {
|
||||
done();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -121,24 +121,24 @@ describe("red/nodes/index", function() {
|
||||
index.load.restore();
|
||||
localfilesystem.getCredentials.restore();
|
||||
});
|
||||
|
||||
it(': definition defined',function(done) {
|
||||
|
||||
it(': definition defined',function(done) {
|
||||
index.registerType('test', TestNode, {
|
||||
credentials: {
|
||||
foo: {type:"test"}
|
||||
}
|
||||
});
|
||||
var testnode = new TestNode({id:'tab1',type:'test',name:'barney'});
|
||||
}
|
||||
});
|
||||
var testnode = new TestNode({id:'tab1',type:'test',name:'barney'});
|
||||
credentials.getDefinition("test").should.have.property('foo');
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('allows nodes to be added/remove/enabled/disabled from the registry', function() {
|
||||
|
||||
describe('allows nodes to be added/removed/enabled/disabled from the registry', function() {
|
||||
var registry = require("../../../red/nodes/registry");
|
||||
var randomNodeInfo = {id:"5678",types:["random"]};
|
||||
|
||||
|
||||
before(function() {
|
||||
sinon.stub(registry,"getNodeInfo",function(id) {
|
||||
if (id == "test") {
|
||||
@ -162,9 +162,9 @@ describe("red/nodes/index", function() {
|
||||
registry.disableNode.restore();
|
||||
});
|
||||
|
||||
it(': allows an unused node type to be removed',function(done) {
|
||||
it(': allows an unused node type to be removed',function(done) {
|
||||
index.init(settings, storage);
|
||||
index.registerType('test', TestNode);
|
||||
index.registerType('test', TestNode);
|
||||
index.loadFlows().then(function() {
|
||||
var info = index.removeNode("5678");
|
||||
registry.removeNode.calledOnce.should.be.true;
|
||||
@ -175,10 +175,10 @@ describe("red/nodes/index", function() {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
it(': allows an unused node type to be disabled',function(done) {
|
||||
|
||||
it(': allows an unused node type to be disabled',function(done) {
|
||||
index.init(settings, storage);
|
||||
index.registerType('test', TestNode);
|
||||
index.registerType('test', TestNode);
|
||||
index.loadFlows().then(function() {
|
||||
var info = index.disableNode("5678");
|
||||
registry.disableNode.calledOnce.should.be.true;
|
||||
@ -190,66 +190,131 @@ describe("red/nodes/index", function() {
|
||||
});
|
||||
});
|
||||
|
||||
it(': prevents removing a node type that is in use',function(done) {
|
||||
it(': prevents removing a node type that is in use',function(done) {
|
||||
index.init(settings, storage);
|
||||
index.registerType('test', TestNode);
|
||||
index.registerType('test', TestNode);
|
||||
index.loadFlows().then(function() {
|
||||
/*jshint immed: false */
|
||||
(function() {
|
||||
index.removeNode("test");
|
||||
}).should.throw();
|
||||
|
||||
}).should.throw();
|
||||
|
||||
done();
|
||||
}).otherwise(function(err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it(': prevents disabling a node type that is in use',function(done) {
|
||||
index.init(settings, storage);
|
||||
index.registerType('test', TestNode);
|
||||
index.registerType('test', TestNode);
|
||||
index.loadFlows().then(function() {
|
||||
/*jshint immed: false */
|
||||
(function() {
|
||||
index.disabledNode("test");
|
||||
}).should.throw();
|
||||
|
||||
}).should.throw();
|
||||
|
||||
done();
|
||||
}).otherwise(function(err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
it(': prevents removing a node type that is unknown',function(done) {
|
||||
|
||||
it(': prevents removing a node type that is unknown',function(done) {
|
||||
index.init(settings, storage);
|
||||
index.registerType('test', TestNode);
|
||||
index.registerType('test', TestNode);
|
||||
index.loadFlows().then(function() {
|
||||
/*jshint immed: false */
|
||||
(function() {
|
||||
index.removeNode("doesnotexist");
|
||||
}).should.throw();
|
||||
|
||||
}).should.throw();
|
||||
|
||||
done();
|
||||
}).otherwise(function(err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
it(': prevents disabling a node type that is unknown',function(done) {
|
||||
it(': prevents disabling a node type that is unknown',function(done) {
|
||||
index.init(settings, storage);
|
||||
index.registerType('test', TestNode);
|
||||
index.registerType('test', TestNode);
|
||||
index.loadFlows().then(function() {
|
||||
/*jshint immed: false */
|
||||
(function() {
|
||||
index.disableNode("doesnotexist");
|
||||
}).should.throw();
|
||||
|
||||
}).should.throw();
|
||||
|
||||
done();
|
||||
}).otherwise(function(err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('allows modules to be removed from the registry', function() {
|
||||
var registry = require("../../../red/nodes/registry");
|
||||
var randomNodeInfo = {id:"5678",types:["random"]};
|
||||
var randomModuleInfo = {
|
||||
name:"random",
|
||||
nodes: [randomNodeInfo]
|
||||
};
|
||||
|
||||
before(function() {
|
||||
sinon.stub(registry,"getNodeInfo",function(id) {
|
||||
if (id == "node-red/foo") {
|
||||
return {id:"1234",types:["test"]};
|
||||
} else if (id == "doesnotexist") {
|
||||
return null;
|
||||
} else {
|
||||
return randomNodeInfo;
|
||||
}
|
||||
});
|
||||
sinon.stub(registry,"getNodeModuleInfo",function(module) {
|
||||
if (module == "node-red") {
|
||||
return ["foo"];
|
||||
} else if (module == "doesnotexist") {
|
||||
return null;
|
||||
} else {
|
||||
return randomModuleInfo.nodes;
|
||||
}
|
||||
});
|
||||
sinon.stub(registry,"removeModule",function(id) {
|
||||
return randomModuleInfo;
|
||||
});
|
||||
});
|
||||
after(function() {
|
||||
registry.getNodeInfo.restore();
|
||||
registry.getNodeModuleInfo.restore();
|
||||
registry.removeModule.restore();
|
||||
});
|
||||
|
||||
it(': prevents removing a module that is in use',function(done) {
|
||||
index.init(settings, storage);
|
||||
index.registerType('test', TestNode);
|
||||
index.loadFlows().then(function() {
|
||||
/*jshint immed: false */
|
||||
(function() {
|
||||
index.removeModule("node-red");
|
||||
}).should.throw();
|
||||
|
||||
done();
|
||||
}).otherwise(function(err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
it(': prevents removing a module that is unknown',function(done) {
|
||||
index.init(settings, storage);
|
||||
index.registerType('test', TestNode);
|
||||
index.loadFlows().then(function() {
|
||||
/*jshint immed: false */
|
||||
(function() {
|
||||
index.removeModule("doesnotexist");
|
||||
}).should.throw();
|
||||
|
||||
done();
|
||||
}).otherwise(function(err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
@ -33,10 +33,10 @@ describe('NodeRegistry', function() {
|
||||
var resourcesDir = __dirname+ path.sep + "resources" + path.sep;
|
||||
|
||||
function stubSettings(s,available) {
|
||||
s.available = function() {return available;}
|
||||
s.set = function(s,v) { return when.resolve()},
|
||||
s.get = function(s) { return null;}
|
||||
return s
|
||||
s.available = function() {return available;};
|
||||
s.set = function(s,v) { return when.resolve();};
|
||||
s.get = function(s) { return null;};
|
||||
return s;
|
||||
}
|
||||
var settings = stubSettings({},false);
|
||||
var settingsWithStorage = stubSettings({},true);
|
||||
@ -56,8 +56,9 @@ describe('NodeRegistry', function() {
|
||||
typeRegistry.load(resourcesDir + "TestNode1",true).then(function() {
|
||||
var list = typeRegistry.getNodeList();
|
||||
list.should.be.an.Array.and.have.lengthOf(1);
|
||||
list[0].should.have.property("id");
|
||||
list[0].should.have.property("name","TestNode1.js");
|
||||
list[0].should.have.property("id","node-red/TestNode1");
|
||||
list[0].should.have.property("name","TestNode1");
|
||||
list[0].should.have.property("module","node-red");
|
||||
list[0].should.have.property("types",["test-node-1"]);
|
||||
list[0].should.have.property("enabled",true);
|
||||
list[0].should.not.have.property("err");
|
||||
@ -78,8 +79,9 @@ describe('NodeRegistry', function() {
|
||||
typeRegistry.load(resourcesDir + "TestNode2",true).then(function() {
|
||||
var list = typeRegistry.getNodeList();
|
||||
list.should.be.an.Array.and.have.lengthOf(1);
|
||||
list[0].should.have.property("id");
|
||||
list[0].should.have.property("name","TestNode2.js");
|
||||
list[0].should.have.property("id","node-red/TestNode2");
|
||||
list[0].should.have.property("name","TestNode2");
|
||||
list[0].should.have.property("module","node-red");
|
||||
list[0].should.have.property("types",["test-node-2"]);
|
||||
list[0].should.have.property("enabled",true);
|
||||
list[0].should.not.have.property("err");
|
||||
@ -98,8 +100,9 @@ describe('NodeRegistry', function() {
|
||||
typeRegistry.load(resourcesDir + "TestNode3",true).then(function() {
|
||||
var list = typeRegistry.getNodeList();
|
||||
list.should.be.an.Array.and.have.lengthOf(1);
|
||||
list[0].should.have.property("id");
|
||||
list[0].should.have.property("name","TestNode3.js");
|
||||
list[0].should.have.property("id","node-red/TestNode3");
|
||||
list[0].should.have.property("name","TestNode3");
|
||||
list[0].should.have.property("module","node-red");
|
||||
list[0].should.have.property("types",["test-node-3"]);
|
||||
list[0].should.have.property("enabled",true);
|
||||
list[0].should.have.property("err","fail");
|
||||
@ -119,8 +122,9 @@ describe('NodeRegistry', function() {
|
||||
typeRegistry.load(resourcesDir + "MultipleNodes1",true).then(function() {
|
||||
var list = typeRegistry.getNodeList();
|
||||
list.should.be.an.Array.and.have.lengthOf(1);
|
||||
list[0].should.have.property("id");
|
||||
list[0].should.have.property("name","MultipleNodes1.js");
|
||||
list[0].should.have.property("id","node-red/MultipleNodes1");
|
||||
list[0].should.have.property("name","MultipleNodes1");
|
||||
list[0].should.have.property("module","node-red");
|
||||
list[0].should.have.property("types",["test-node-multiple-1a","test-node-multiple-1b"]);
|
||||
list[0].should.have.property("enabled",true);
|
||||
list[0].should.not.have.property("err");
|
||||
@ -142,8 +146,9 @@ describe('NodeRegistry', function() {
|
||||
typeRegistry.load(resourcesDir + "NestedDirectoryNode",true).then(function() {
|
||||
var list = typeRegistry.getNodeList();
|
||||
list.should.be.an.Array.and.have.lengthOf(1);
|
||||
list[0].should.have.property("id");
|
||||
list[0].should.have.property("name","NestedNode.js");
|
||||
list[0].should.have.property("id","node-red/NestedNode");
|
||||
list[0].should.have.property("name","NestedNode");
|
||||
list[0].should.have.property("module","node-red");
|
||||
list[0].should.have.property("types",["nested-node-1"]);
|
||||
list[0].should.have.property("enabled",true);
|
||||
list[0].should.not.have.property("err");
|
||||
@ -159,7 +164,9 @@ describe('NodeRegistry', function() {
|
||||
typeRegistry.load(resourcesDir + "NestedDirectoryNode",true).then(function() {
|
||||
var list = typeRegistry.getNodeList();
|
||||
list.should.be.an.Array.and.have.lengthOf(1);
|
||||
list[0].should.have.property("name","NestedNode.js");
|
||||
list[0].should.have.property("id","node-red/NestedNode");
|
||||
list[0].should.have.property("name","NestedNode");
|
||||
list[0].should.have.property("module","node-red");
|
||||
list[0].should.have.property("types",["nested-node-1"]);
|
||||
list[0].should.have.property("enabled",true);
|
||||
list[0].should.not.have.property("err");
|
||||
@ -189,26 +196,13 @@ describe('NodeRegistry', function() {
|
||||
typeRegistry.load("wontexist",true).then(function() {
|
||||
var list = typeRegistry.getNodeList();
|
||||
|
||||
list.should.be.an.Array.and.have.lengthOf(2);
|
||||
list[0].should.have.property("id");
|
||||
list[0].should.have.property("name","TestNode1.js");
|
||||
list.should.be.an.Array.and.have.lengthOf(1);
|
||||
list[0].should.have.property("id","node-red/TestNode1");
|
||||
list[0].should.have.property("name","TestNode1");
|
||||
list[0].should.have.property("types",["test-node-1"]);
|
||||
list[0].should.have.property("enabled",true);
|
||||
list[0].should.not.have.property("err");
|
||||
|
||||
list[1].should.have.property("id");
|
||||
list[1].id.should.not.equal(list[0].id);
|
||||
|
||||
list[1].should.have.property("name","TestNode1.js");
|
||||
list[1].should.have.property("types",["test-node-1"]);
|
||||
list[1].should.have.property("enabled",true);
|
||||
list[1].should.have.property("err");
|
||||
/already registered/.test(list[1].err).should.be.true;
|
||||
|
||||
var nodeConstructor = typeRegistry.get("test-node-1");
|
||||
// Verify the duplicate node hasn't replaced the original one
|
||||
nodeConstructor.name.should.be.equal("TestNode");
|
||||
|
||||
done();
|
||||
}).catch(function(e) {
|
||||
done(e);
|
||||
@ -295,26 +289,30 @@ describe('NodeRegistry', function() {
|
||||
var settings = {
|
||||
nodesDir:[resourcesDir + "TestNode1",resourcesDir + "TestNode2",resourcesDir + "TestNode3"],
|
||||
available: function() { return true; },
|
||||
set: function(s,v) {return when.resolve();},
|
||||
get: function(s) { return null;}
|
||||
}
|
||||
set: function(s,v) { return when.resolve(); },
|
||||
get: function(s) { return null; }
|
||||
};
|
||||
var settingsSave = sinon.spy(settings,"set");
|
||||
typeRegistry.init(settings);
|
||||
typeRegistry.load("wontexist",true).then(function() {
|
||||
var list = typeRegistry.getNodeList();
|
||||
list.should.be.Array.and.have.length(3);
|
||||
var nodeList = typeRegistry.getNodeList();
|
||||
var moduleList = typeRegistry.getModuleList();
|
||||
nodeList.should.be.Array.and.have.length(3);
|
||||
moduleList.should.be.Array.and.have.length(1);
|
||||
|
||||
settingsSave.callCount.should.equal(1);
|
||||
settingsSave.firstCall.args[0].should.be.equal("nodes");
|
||||
settingsSave.firstCall.args[0].should.be.equal("modules");
|
||||
var savedList = settingsSave.firstCall.args[1];
|
||||
|
||||
savedList[list[0].id].name == list[0].name;
|
||||
savedList[list[1].id].name == list[1].name;
|
||||
savedList[list[2].id].name == list[2].name;
|
||||
savedList[moduleList[0].name].name.should.equal(moduleList[0].name);
|
||||
|
||||
savedList[list[0].id].should.not.have.property("err");
|
||||
savedList[list[1].id].should.not.have.property("err");
|
||||
savedList[list[2].id].should.not.have.property("err");
|
||||
savedList[moduleList[0].name].nodes[moduleList[0].nodes[0].name].name.should.equal(moduleList[0].nodes[0].name);
|
||||
savedList[moduleList[0].name].nodes[moduleList[0].nodes[1].name].name.should.equal(moduleList[0].nodes[1].name);
|
||||
savedList[moduleList[0].name].nodes[moduleList[0].nodes[2].name].name.should.equal(moduleList[0].nodes[2].name);
|
||||
|
||||
savedList[moduleList[0].name].nodes[moduleList[0].nodes[0].name].should.not.have.property("err");
|
||||
savedList[moduleList[0].name].nodes[moduleList[0].nodes[1].name].should.not.have.property("err");
|
||||
savedList[moduleList[0].name].nodes[moduleList[0].nodes[2].name].should.not.have.property("err");
|
||||
|
||||
done();
|
||||
}).catch(function(e) {
|
||||
@ -336,10 +334,12 @@ describe('NodeRegistry', function() {
|
||||
var list = typeRegistry.getNodeList();
|
||||
list.should.be.an.Array.and.be.empty;
|
||||
|
||||
// TODO: Needs module and name params for loadNodeConfig
|
||||
typeRegistry.addNode(resourcesDir + "TestNode1/TestNode1.js").then(function(node) {
|
||||
list = typeRegistry.getNodeList();
|
||||
list[0].should.have.property("id");
|
||||
list[0].should.have.property("name","TestNode1.js");
|
||||
list[0].should.have.property("id","node-red/TestNode1");
|
||||
list[0].should.have.property("name","TestNode1");
|
||||
list[0].should.have.property("module","node-red");
|
||||
list[0].should.have.property("types",["test-node-1"]);
|
||||
list[0].should.have.property("enabled",true);
|
||||
list[0].should.not.have.property("err");
|
||||
@ -386,8 +386,9 @@ describe('NodeRegistry', function() {
|
||||
var id = list[0].id;
|
||||
var type = list[0].types[0];
|
||||
|
||||
list[0].should.have.property("id");
|
||||
list[0].should.have.property("name","TestNode1.js");
|
||||
list[0].should.have.property("id","node-red/TestNode1");
|
||||
list[0].should.have.property("name","TestNode1");
|
||||
list[0].should.have.property("module","node-red");
|
||||
list[0].should.have.property("types",["test-node-1"]);
|
||||
list[0].should.have.property("enabled",true);
|
||||
list[0].should.not.have.property("err");
|
||||
@ -405,7 +406,7 @@ describe('NodeRegistry', function() {
|
||||
|
||||
});
|
||||
|
||||
it('returns plugins list', function(done) {
|
||||
it('returns modules list', function(done) {
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
|
||||
@ -438,7 +439,7 @@ describe('NodeRegistry', function() {
|
||||
typeRegistry.load("wontexist",true).then(function(){
|
||||
|
||||
typeRegistry.addModule("TestNodeModule").then(function() {
|
||||
var list = typeRegistry.getPluginList();
|
||||
var list = typeRegistry.getModuleList();
|
||||
list.should.be.an.Array.and.have.lengthOf(1);
|
||||
list[0].should.have.property("name", "TestNodeModule");
|
||||
list[0].should.have.property("nodes");
|
||||
@ -457,7 +458,7 @@ describe('NodeRegistry', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('returns plugin info', function(done) {
|
||||
it('returns module info', function(done) {
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
|
||||
@ -490,11 +491,11 @@ describe('NodeRegistry', function() {
|
||||
typeRegistry.load("wontexist",true).then(function(){
|
||||
|
||||
typeRegistry.addModule("TestNodeModule").then(function(nodes) {
|
||||
var list = typeRegistry.getPluginList();
|
||||
var list = typeRegistry.getModuleList();
|
||||
|
||||
var plugin = typeRegistry.getPluginInfo(list[0].name);
|
||||
plugin.should.have.property("name", list[0].name);
|
||||
plugin.should.have.property("nodes", nodes);
|
||||
var module = typeRegistry.getModuleInfo(list[0].name);
|
||||
module.should.have.property("name", list[0].name);
|
||||
module.should.have.property("nodes", nodes);
|
||||
done();
|
||||
}).catch(function(e) {
|
||||
done(e);
|
||||
@ -532,8 +533,9 @@ describe('NodeRegistry', function() {
|
||||
typeRegistry.load(resourcesDir + "TestNode1",true).then(function() {
|
||||
var list = typeRegistry.getNodeList();
|
||||
list.should.be.an.Array.and.have.lengthOf(1);
|
||||
list[0].should.have.property("id");
|
||||
list[0].should.have.property("name","TestNode1.js");
|
||||
list[0].should.have.property("id","node-red/TestNode1");
|
||||
list[0].should.have.property("name","TestNode1");
|
||||
list[0].should.have.property("module","node-red");
|
||||
list[0].should.have.property("types",["test-node-1"]);
|
||||
list[0].should.have.property("enabled",true);
|
||||
list[0].should.have.property("loaded",true);
|
||||
@ -552,7 +554,6 @@ describe('NodeRegistry', function() {
|
||||
var nodeConstructor = typeRegistry.get("test-node-1");
|
||||
(typeof nodeConstructor).should.be.equal("undefined");
|
||||
|
||||
|
||||
done();
|
||||
}).catch(function(e) {
|
||||
done(e);
|
||||
@ -612,14 +613,16 @@ describe('NodeRegistry', function() {
|
||||
typeRegistry.load("wontexist",false).then(function(){
|
||||
var list = typeRegistry.getNodeList();
|
||||
list.should.be.an.Array.and.have.lengthOf(2);
|
||||
list[0].should.have.property("id");
|
||||
list[0].should.have.property("name","TestNodeModule:TestNodeMod1");
|
||||
list[0].should.have.property("id","TestNodeModule/TestNodeMod1");
|
||||
list[0].should.have.property("name","TestNodeMod1");
|
||||
list[0].should.have.property("module","TestNodeModule");
|
||||
list[0].should.have.property("types",["test-node-mod-1"]);
|
||||
list[0].should.have.property("enabled",true);
|
||||
list[0].should.not.have.property("err");
|
||||
|
||||
list[1].should.have.property("id");
|
||||
list[1].should.have.property("name","TestNodeModule:TestNodeMod2");
|
||||
list[1].should.have.property("id","TestNodeModule/TestNodeMod2");
|
||||
list[1].should.have.property("name","TestNodeMod2");
|
||||
list[1].should.have.property("module","TestNodeModule");
|
||||
list[1].should.have.property("types",["test-node-mod-2"]);
|
||||
list[1].should.have.property("enabled",true);
|
||||
list[1].should.have.property("err");
|
||||
@ -681,14 +684,16 @@ describe('NodeRegistry', function() {
|
||||
typeRegistry.addModule("TestNodeModule").then(function(node) {
|
||||
list = typeRegistry.getNodeList();
|
||||
list.should.be.an.Array.and.have.lengthOf(2);
|
||||
list[0].should.have.property("id");
|
||||
list[0].should.have.property("name","TestNodeModule:TestNodeMod1");
|
||||
list[0].should.have.property("id","TestNodeModule/TestNodeMod1");
|
||||
list[0].should.have.property("name","TestNodeMod1");
|
||||
list[0].should.have.property("module","TestNodeModule");
|
||||
list[0].should.have.property("types",["test-node-mod-1"]);
|
||||
list[0].should.have.property("enabled",true);
|
||||
list[0].should.not.have.property("err");
|
||||
|
||||
list[1].should.have.property("id");
|
||||
list[1].should.have.property("name","TestNodeModule:TestNodeMod2");
|
||||
list[1].should.have.property("id","TestNodeModule/TestNodeMod2");
|
||||
list[1].should.have.property("name","TestNodeMod2");
|
||||
list[1].should.have.property("module","TestNodeModule");
|
||||
list[1].should.have.property("types",["test-node-mod-2"]);
|
||||
list[1].should.have.property("enabled",true);
|
||||
list[1].should.have.property("err");
|
||||
@ -708,6 +713,60 @@ describe('NodeRegistry', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('adds module with version number', function(done) {
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
|
||||
var pathJoin = (function() {
|
||||
var _join = path.join;
|
||||
return sinon.stub(path,"join",function() {
|
||||
if (arguments.length == 3 && arguments[2] == "package.json") {
|
||||
return _join(resourcesDir,"TestNodeModule" + path.sep + "node_modules" + path.sep,arguments[1],arguments[2]);
|
||||
}
|
||||
if (arguments.length == 2 && arguments[1] == "TestNodeModule") {
|
||||
return _join(resourcesDir,"TestNodeModule" + path.sep + "node_modules" + path.sep,arguments[1]);
|
||||
}
|
||||
return _join.apply(this,arguments);
|
||||
});
|
||||
})();
|
||||
|
||||
var readdirSync = (function() {
|
||||
var originalReaddirSync = fs.readdirSync;
|
||||
var callCount = 0;
|
||||
return sinon.stub(fs,"readdirSync",function(dir) {
|
||||
var result = [];
|
||||
if (callCount == 1) {
|
||||
result = originalReaddirSync(resourcesDir + "TestNodeModule" + path.sep + "node_modules");
|
||||
}
|
||||
callCount++;
|
||||
return result;
|
||||
});
|
||||
})();
|
||||
typeRegistry.init(settingsWithStorage);
|
||||
typeRegistry.load("wontexist",true).then(function(){
|
||||
typeRegistry.addModule("TestNodeModule","0.0.1").then(function(node) {
|
||||
var module = typeRegistry.getModuleInfo("TestNodeModule");
|
||||
|
||||
module.should.have.property("name","TestNodeModule");
|
||||
module.should.have.property("version","0.0.1");
|
||||
|
||||
var modules = typeRegistry.getModuleList();
|
||||
|
||||
modules[0].should.have.property("name","TestNodeModule");
|
||||
modules[0].should.have.property("version","0.0.1");
|
||||
|
||||
done();
|
||||
}).catch(function(e) {
|
||||
done(e);
|
||||
});
|
||||
|
||||
}).catch(function(e) {
|
||||
done(e);
|
||||
}).finally(function() {
|
||||
readdirSync.restore();
|
||||
pathJoin.restore();
|
||||
});
|
||||
});
|
||||
|
||||
it('rejects adding duplicate node modules', function(done) {
|
||||
var fs = require("fs");
|
||||
@ -847,13 +906,14 @@ describe('NodeRegistry', function() {
|
||||
});
|
||||
|
||||
|
||||
it('allows nodes to be enabled and disabled by hex-id', function(done) {
|
||||
it('allows nodes to be enabled and disabled by id', function(done) {
|
||||
typeRegistry.init(settingsWithStorage);
|
||||
typeRegistry.load(resourcesDir+path.sep+"TestNode1",true).then(function() {
|
||||
var list = typeRegistry.getNodeList();
|
||||
list.should.be.an.Array.and.have.lengthOf(1);
|
||||
list[0].should.have.property("id");
|
||||
list[0].should.have.property("name","TestNode1.js");
|
||||
list[0].should.have.property("id","node-red/TestNode1");
|
||||
list[0].should.have.property("name","TestNode1");
|
||||
list[0].should.have.property("module","node-red");
|
||||
list[0].should.have.property("enabled",true);
|
||||
|
||||
var nodeConfig = typeRegistry.getNodeConfigs();
|
||||
@ -892,8 +952,9 @@ describe('NodeRegistry', function() {
|
||||
var list = typeRegistry.getNodeList();
|
||||
|
||||
list.should.be.an.Array.and.have.lengthOf(1);
|
||||
list[0].should.have.property("id");
|
||||
list[0].should.have.property("name","TestNode1.js");
|
||||
list[0].should.have.property("id","node-red/TestNode1");
|
||||
list[0].should.have.property("name","TestNode1");
|
||||
list[0].should.have.property("module","node-red");
|
||||
list[0].should.have.property("types",["test-node-1"]);
|
||||
list[0].should.have.property("enabled",true);
|
||||
|
||||
@ -930,14 +991,14 @@ describe('NodeRegistry', function() {
|
||||
});
|
||||
|
||||
it('fails to enable/disable non-existent nodes', function(done) {
|
||||
typeRegistry.init(settings);
|
||||
typeRegistry.init(settingsWithStorage);
|
||||
typeRegistry.load("wontexist",true).then(function() {
|
||||
var list = typeRegistry.getNodeList();
|
||||
list.should.be.an.Array.and.be.empty;
|
||||
|
||||
/*jshint immed: false */
|
||||
(function() {
|
||||
typeRegistry.disableNode("123");
|
||||
typeRegistry.disableNode("123");
|
||||
}).should.throw();
|
||||
|
||||
/*jshint immed: false */
|
||||
|
Loading…
Reference in New Issue
Block a user