Move node registry to its own top level dir

This commit is contained in:
Nick O'Leary 2018-04-26 12:32:05 +01:00
parent 5866d414ce
commit 11d87205d7
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
63 changed files with 674 additions and 584 deletions

View File

@ -17,6 +17,7 @@
var registry = require("./registry");
var loader = require("./loader");
var installer = require("./installer");
var library = require("./library");
var settings;
@ -24,7 +25,8 @@ function init(runtime) {
settings = runtime.settings;
installer.init(runtime);
loader.init(runtime);
registry.init(settings,loader);
registry.init(settings,loader,runtime.events);
library.init();
}
function load() {
@ -79,5 +81,11 @@ module.exports = {
cleanModuleList: registry.cleanModuleList,
paletteEditorEnabled: installer.paletteEditorEnabled
paletteEditorEnabled: installer.paletteEditorEnabled,
getNodeExampleFlows: library.getExampleFlows,
getNodeExampleFlowPath: library.getExampleFlowPath,
deprecated: require("./deprecated")
};

View File

@ -19,9 +19,10 @@ var path = require("path");
var fs = require("fs");
var registry = require("./registry");
var library = require("./library");
var log;
var events = require("../../events");
var events;
var child_process = require('child_process');
var npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm';
@ -32,6 +33,7 @@ var moduleRe = /^(@[^/]+?[/])?[^/]+?$/;
var slashRe = process.platform === "win32" ? /\\|[/]/ : /[/]/;
function init(runtime) {
events = runtime.events;
settings = runtime.settings;
log = runtime.log;
}
@ -210,8 +212,7 @@ function uninstallModule(module) {
} else {
log.info(log._("server.install.uninstalled",{name:module}));
reportRemovedModules(list);
// TODO: tidy up internal event names
events.emit("node-module-uninstalled",module)
library.removeExamplesDir(module);
resolve(list);
}
}

View File

@ -59,11 +59,11 @@ function getFlowsFromPath(path) {
})
}
function addNodeExamplesDir(module) {
exampleRoots[module.name] = module.path;
getFlowsFromPath(module.path).then(function(result) {
function addNodeExamplesDir(module,path) {
exampleRoots[module] = path;
return getFlowsFromPath(path).then(function(result) {
exampleFlows = exampleFlows||{d:{}};
exampleFlows.d[module.name] = result;
exampleFlows.d[module] = result;
});
}
function removeNodeExamplesDir(module) {
@ -77,17 +77,9 @@ function removeNodeExamplesDir(module) {
}
function init(_runtime) {
runtime = _runtime;
function init() {
exampleRoots = {};
exampleFlows = null;
runtime.events.removeListener("node-examples-dir",addNodeExamplesDir);
runtime.events.on("node-examples-dir",addNodeExamplesDir);
runtime.events.removeListener("node-module-uninstalled",removeNodeExamplesDir);
runtime.events.on("node-module-uninstalled",removeNodeExamplesDir);
}
function getExampleFlows() {
@ -103,6 +95,8 @@ function getExampleFlowPath(module,path) {
module.exports = {
init: init,
addExamplesDir: addNodeExamplesDir,
removeExamplesDir: removeNodeExamplesDir,
getExampleFlows: getExampleFlows,
getExampleFlowPath: getExampleFlowPath
}

View File

@ -22,6 +22,8 @@ var semver = require("semver");
var localfilesystem = require("./localfilesystem");
var registry = require("./registry");
var i18n = require("../util").i18n; // TODO: separate module
var settings;
var runtime;
@ -110,7 +112,7 @@ function createNodeApi(node) {
if (args[0].indexOf(":") === -1) {
args[0] = node.namespace+":"+args[0];
}
return runtime.i18n._.apply(null,args);
return i18n._.apply(null,args);
}
return red;
}
@ -118,6 +120,7 @@ function createNodeApi(node) {
function loadNodeFiles(nodeFiles) {
var promises = [];
var nodes = [];
for (var module in nodeFiles) {
/* istanbul ignore else */
if (nodeFiles.hasOwnProperty(module)) {
@ -125,6 +128,7 @@ function loadNodeFiles(nodeFiles) {
!semver.satisfies(runtime.version().replace(/(\-[1-9A-Za-z-][0-9A-Za-z-\.]*)?(\+[0-9A-Za-z-\.]+)?$/,""), nodeFiles[module].redVersion)) {
//TODO: log it
runtime.log.warn("["+module+"] "+runtime.log._("server.node-version-mismatch",{version:nodeFiles[module].redVersion}));
nodeFiles[module].err = "version_mismatch";
continue;
}
if (module == "node-red" || !registry.getModuleInfo(module)) {
@ -154,7 +158,14 @@ function loadNodeFiles(nodeFiles) {
}
try {
promises.push(loadNodeConfig(nodeFiles[module].nodes[node]))
promises.push(loadNodeConfig(nodeFiles[module].nodes[node]).then((function() {
var m = module;
var n = node;
return function(nodeSet) {
nodeFiles[m].nodes[n] = nodeSet;
nodes.push(nodeSet);
}
})()));
} catch(err) {
//
}
@ -164,10 +175,13 @@ function loadNodeFiles(nodeFiles) {
}
}
return when.settle(promises).then(function(results) {
var nodes = results.map(function(r) {
registry.addNodeSet(r.value.id,r.value,r.value.version);
return r.value;
});
for (var module in nodeFiles) {
if (nodeFiles.hasOwnProperty(module)) {
if (!nodeFiles[module].err) {
registry.addModule(nodeFiles[module]);
}
}
}
return loadNodeSetList(nodes);
});
}
@ -239,7 +253,7 @@ function loadNodeConfig(fileInfo) {
index = regExp.lastIndex;
var help = content.substring(regExp.lastIndex-match[1].length,regExp.lastIndex);
var lang = runtime.i18n.defaultLang;
var lang = i18n.defaultLang;
if ((match = langRegExp.exec(help)) !== null) {
lang = match[1];
}
@ -270,7 +284,7 @@ function loadNodeConfig(fileInfo) {
fs.stat(path.join(path.dirname(file),"locales"),function(err,stat) {
if (!err) {
node.namespace = node.id;
runtime.i18n.registerMessageCatalog(node.id,
i18n.registerMessageCatalog(node.id,
path.join(path.dirname(file),"locales"),
path.basename(file,".js")+".json")
.then(function() {
@ -414,10 +428,10 @@ function getNodeHelp(node,lang) {
}
if (help) {
node.help[lang] = help;
} else if (lang === runtime.i18n.defaultLang) {
} else if (lang === i18n.defaultLang) {
return null;
} else {
node.help[lang] = getNodeHelp(node, runtime.i18n.defaultLang);
node.help[lang] = getNodeHelp(node, i18n.defaultLang);
}
}
return node.help[lang];

View File

@ -19,7 +19,8 @@ var path = require("path");
var events;
var log;
var i18n;
var i18n = require("../util").i18n; // TODO: separate module
var settings;
var disableNodePathScan = false;
@ -29,7 +30,6 @@ function init(runtime) {
settings = runtime.settings;
events = runtime.events;
log = runtime.log;
i18n = runtime.i18n;
}
function isIncluded(name) {
@ -84,6 +84,7 @@ function getLocalNodeFiles(dir) {
var result = [];
var files = [];
var icons = [];
try {
files = fs.readdirSync(dir);
} catch(err) {
@ -102,14 +103,16 @@ function getLocalNodeFiles(dir) {
} else if (stats.isDirectory()) {
// Ignore /.dirs/, /lib/ /node_modules/
if (!/^(\..*|lib|icons|node_modules|test|locales)$/.test(fn)) {
result = result.concat(getLocalNodeFiles(path.join(dir,fn)));
var subDirResults = getLocalNodeFiles(path.join(dir,fn));
result = result.concat(subDirResults.files);
icons = icons.concat(subDirResults.icons);
} else if (fn === "icons") {
var iconList = scanIconDir(path.join(dir,fn));
events.emit("node-icon-dir",{name:'node-red',path:path.join(dir,fn),icons:iconList});
icons.push({path:path.join(dir,fn),icons:iconList});
}
}
});
return result;
return {files: result, icons: icons}
}
function scanDirForNodesModules(dir,moduleName) {
@ -197,7 +200,7 @@ function getModuleNodeFiles(module) {
var nodes = pkg['node-red'].nodes||{};
var results = [];
var iconDirs = [];
var iconList = [];
for (var n in nodes) {
/* istanbul ignore else */
if (nodes.hasOwnProperty(n)) {
@ -212,47 +215,55 @@ function getModuleNodeFiles(module) {
if (iconDirs.indexOf(iconDir) == -1) {
try {
fs.statSync(iconDir);
var iconList = scanIconDir(iconDir);
events.emit("node-icon-dir",{name:pkg.name,path:iconDir,icons:iconList});
var icons = scanIconDir(iconDir);
iconList.push({path:iconDir,icons:icons});
iconDirs.push(iconDir);
} catch(err) {
}
}
}
}
var result = {files:results,icons:iconList};
var examplesDir = path.join(moduleDir,"examples");
try {
fs.statSync(examplesDir)
events.emit("node-examples-dir",{name:pkg.name,path:examplesDir});
result.examples = {path:examplesDir};
// events.emit("node-examples-dir",{name:pkg.name,path:examplesDir});
} catch(err) {
}
return results;
return result;
}
function getNodeFiles(disableNodePathScan) {
var dir;
// Find all of the nodes to load
var nodeFiles = [];
var results;
var dir = path.resolve(__dirname + '/../../../../public/icons');
var iconList = scanIconDir(dir);
events.emit("node-icon-dir",{name:'node-red',path:dir,icons:iconList});
var dir = path.resolve(__dirname + '/../../public/icons');
var iconList = [{path:dir,icons:scanIconDir(dir)}];
if (settings.coreNodesDir) {
nodeFiles = getLocalNodeFiles(path.resolve(settings.coreNodesDir));
results = getLocalNodeFiles(path.resolve(settings.coreNodesDir));
nodeFiles = nodeFiles.concat(results.files);
iconList = iconList.concat(results.icons);
var defaultLocalesPath = path.join(settings.coreNodesDir,"core","locales");
i18n.registerMessageCatalog("node-red",defaultLocalesPath,"messages.json");
}
if (settings.userDir) {
dir = path.join(settings.userDir,"lib","icons");
iconList = scanIconDir(dir);
if (iconList.length > 0) {
events.emit("node-icon-dir",{name:'Library',path:dir,icons:iconList});
var icons = scanIconDir(dir);
if (icons.length > 0) {
iconList.push({path:dir,icons:icons});
}
dir = path.join(settings.userDir,"nodes");
nodeFiles = nodeFiles.concat(getLocalNodeFiles(dir));
results = getLocalNodeFiles(path.resolve(dir));
nodeFiles = nodeFiles.concat(results.files);
iconList = iconList.concat(results.icons);
}
if (settings.nodesDir) {
dir = settings.nodesDir;
@ -260,7 +271,9 @@ function getNodeFiles(disableNodePathScan) {
dir = [dir];
}
for (var i=0;i<dir.length;i++) {
nodeFiles = nodeFiles.concat(getLocalNodeFiles(dir[i]));
results = getLocalNodeFiles(dir[i]);
nodeFiles = nodeFiles.concat(results.files);
iconList = iconList.concat(results.icons);
}
}
@ -268,7 +281,8 @@ function getNodeFiles(disableNodePathScan) {
"node-red": {
name: "node-red",
version: settings.version,
nodes: {}
nodes: {},
icons: iconList
}
}
nodeFiles.forEach(function(node) {
@ -283,19 +297,21 @@ function getNodeFiles(disableNodePathScan) {
name: moduleFile.package.name,
version: moduleFile.package.version,
local: moduleFile.local||false,
nodes: {}
nodes: {},
icons: nodeModuleFiles.icons,
examples: nodeModuleFiles.examples
};
if (moduleFile.package['node-red'].version) {
nodeList[moduleFile.package.name].redVersion = moduleFile.package['node-red'].version;
}
nodeModuleFiles.forEach(function(node) {
nodeModuleFiles.files.forEach(function(node) {
node.local = moduleFile.local||false;
nodeList[moduleFile.package.name].nodes[node.name] = node;
});
nodeFiles = nodeFiles.concat(nodeModuleFiles);
nodeFiles = nodeFiles.concat(nodeModuleFiles.files);
});
} else {
console.log("node path scan disabled");
// console.log("node path scan disabled");
}
return nodeList;
}
@ -315,12 +331,14 @@ function getModuleFiles(module) {
nodeList[moduleFile.package.name] = {
name: moduleFile.package.name,
version: moduleFile.package.version,
nodes: {}
nodes: {},
icons: nodeModuleFiles.icons,
examples: nodeModuleFiles.examples
};
if (moduleFile.package['node-red'].version) {
nodeList[moduleFile.package.name].redVersion = moduleFile.package['node-red'].version;
}
nodeModuleFiles.forEach(function(node) {
nodeModuleFiles.files.forEach(function(node) {
nodeList[moduleFile.package.name].nodes[node.name] = node;
nodeList[moduleFile.package.name].nodes[node.name].local = moduleFile.local || false;
});

View File

@ -15,16 +15,13 @@
**/
//var UglifyJS = require("uglify-js");
var util = require("util");
var path = require("path");
var fs = require("fs");
var events = require("../../events");
var library = require("./library");
var events;
var settings;
var Node;
var loader;
var nodeConfigCache = null;
@ -34,18 +31,15 @@ var nodeConstructors = {};
var nodeTypeToId = {};
var moduleNodes = {};
function init(_settings,_loader) {
function init(_settings,_loader, _events) {
settings = _settings;
loader = _loader;
events = _events;
moduleNodes = {};
nodeTypeToId = {};
nodeConstructors = {};
nodeList = [];
nodeConfigCache = null;
Node = require("../Node");
events.removeListener("node-icon-dir",nodeIconDir);
events.on("node-icon-dir",nodeIconDir);
}
function load() {
@ -180,46 +174,46 @@ function loadNodeConfigs() {
}
}
function addNodeSet(id,set,version) {
if (!set.err) {
set.types.forEach(function(t) {
if (nodeTypeToId.hasOwnProperty(t)) {
set.err = new Error("Type already registered");
set.err.code = "type_already_registered";
set.err.details = {
type: t,
moduleA: getNodeInfo(t).module,
moduleB: set.module
}
function addModule(module) {
moduleNodes[module.name] = [];
moduleConfigs[module.name] = module;
for (var setName in module.nodes) {
if (module.nodes.hasOwnProperty(setName)) {
var set = module.nodes[setName];
moduleNodes[module.name].push(set.name);
nodeList.push(set.id);
if (!set.err) {
set.types.forEach(function(t) {
if (nodeTypeToId.hasOwnProperty(t)) {
set.err = new Error("Type already registered");
set.err.code = "type_already_registered";
set.err.details = {
type: t,
moduleA: getNodeInfo(t).module,
moduleB: set.module
}
}
});
if (!set.err) {
set.types.forEach(function(t) {
nodeTypeToId[t] = set.id;
});
}
}
});
if (!set.err) {
set.types.forEach(function(t) {
nodeTypeToId[t] = id;
});
}
}
moduleNodes[set.module] = moduleNodes[set.module]||[];
moduleNodes[set.module].push(set.name);
if (!moduleConfigs[set.module]) {
moduleConfigs[set.module] = {
name: set.module,
nodes: {}
};
if (module.icons) {
icon_paths[module.name] = [];
module.icons.forEach(icon=>icon_paths[module.name].push(path.resolve(icon.path)) )
}
if (version) {
moduleConfigs[set.module].version = version;
if (module.examples) {
library.addExamplesDir(module.name,module.examples.path);
}
moduleConfigs[set.module].local = set.local;
moduleConfigs[set.module].nodes[set.name] = set;
nodeList.push(id);
nodeConfigCache = null;
}
function removeNode(id) {
var config = moduleConfigs[getModule(id)].nodes[getNode(id)];
if (!config) {
@ -370,27 +364,6 @@ function getCaller(){
return stack[0].getFileName();
}
function inheritNode(constructor) {
if(Object.getPrototypeOf(constructor.prototype) === Object.prototype) {
util.inherits(constructor,Node);
} else {
var proto = constructor.prototype;
while(Object.getPrototypeOf(proto) !== Object.prototype) {
proto = Object.getPrototypeOf(proto);
}
//TODO: This is a partial implementation of util.inherits >= node v5.0.0
// which should be changed when support for node < v5.0.0 is dropped
// see: https://github.com/nodejs/node/pull/3455
proto.constructor.super_ = Node;
if(Object.setPrototypeOf) {
Object.setPrototypeOf(proto, Node.prototype);
} else {
// hack for node v0.10
proto.__proto__ = Node.prototype;
}
}
}
function registerNodeConstructor(nodeSet,type,constructor) {
if (nodeConstructors.hasOwnProperty(type)) {
throw new Error(type+" already registered");
@ -398,9 +371,6 @@ function registerNodeConstructor(nodeSet,type,constructor) {
//TODO: Ensure type is known - but doing so will break some tests
// that don't have a way to register a node template ahead
// of registering the constructor
if(!(constructor.prototype instanceof Node)) {
inheritNode(constructor);
}
var nodeSetInfo = getFullNodeInfo(nodeSet);
if (nodeSetInfo) {
@ -584,10 +554,10 @@ function setModulePendingUpdated(module,version) {
}
var icon_paths = {
"node-red":[path.resolve(__dirname + '/../../../../public/icons')]
"node-red":[path.resolve(__dirname + '/../../public/icons')]
};
var iconCache = {};
var defaultIcon = path.resolve(__dirname + '/../../../../public/icons/arrow-in.png');
var defaultIcon = path.resolve(__dirname + '/../../public/icons/arrow-in.png');
function nodeIconDir(dir) {
icon_paths[dir.name] = icon_paths[dir.name] || [];
@ -648,7 +618,8 @@ function getNodeIcons() {
for (var module in moduleConfigs) {
if (moduleConfigs.hasOwnProperty(module)) {
if (moduleConfigs[module].icons) {
iconList[module] = moduleConfigs[module].icons;
iconList[module] = [];
moduleConfigs[module].icons.forEach(icon=>{ iconList[module] = iconList[module].concat(icon.icons)})
}
}
}
@ -664,7 +635,9 @@ var registry = module.exports = {
registerNodeConstructor: registerNodeConstructor,
getNodeConstructor: getNodeConstructor,
addNodeSet: addNodeSet,
addModule: addModule,
enableNodeSet: enableNodeSet,
disableNodeSet: disableNodeSet,

View File

@ -69,6 +69,7 @@ function getEntry(type,path) {
} catch(err) {
return reject(err);
}
return;
}
}
// IF we get here, we didn't find the file

View File

@ -16,10 +16,11 @@
var when = require("when");
var clone = require("clone");
var typeRegistry = require("../registry");
var typeRegistry = require("../../../runtime-registry");
var Log;
var redUtil = require("../../util");
var flowUtil = require("./util");
var Node;
var nodeCloseTimeout = 15000;
@ -292,6 +293,7 @@ function Flow(global,flow) {
function createNode(type,config) {
var nn = null;
try {
var nt = typeRegistry.get(type);
if (nt) {
var conf = clone(config);
@ -315,6 +317,9 @@ function createNode(type,config) {
} else {
Log.error(Log._("nodes.flow.unknown-type", {type:type}));
}
} catch(err) {
Log.error(err);
}
return nn;
}
@ -498,6 +503,7 @@ module.exports = {
init: function(runtime) {
nodeCloseTimeout = runtime.settings.nodeCloseTimeout || 15000;
Log = runtime.log;
Node = require("../Node");
},
create: function(global,conf) {
return new Flow(global,conf);

View File

@ -19,7 +19,10 @@ var when = require("when");
var Flow = require('./Flow');
var typeRegistry = require("../registry");
var typeRegistry = require("../../../runtime-registry");
var deprecated = typeRegistry.deprecated;
var context = require("../context")
var credentials = require("../credentials");
@ -27,7 +30,6 @@ var flowUtil = require("./util");
var log;
var events = require("../../events");
var redUtil = require("../../util");
var deprecated = require("../registry/deprecated");
var storage = null;
var settings = null;

View File

@ -16,7 +16,7 @@
var clone = require("clone");
var redUtil = require("../../util");
var subflowInstanceRE = /^subflow:(.+)$/;
var typeRegistry = require("../registry");
var typeRegistry = require("../../../runtime-registry");
function diffNodes(oldNode,newNode) {
if (oldNode == null) {
@ -203,7 +203,7 @@ module.exports = {
var linkMap = {};
var changedTabs = {};
// Look for tabs that have been removed
for (id in oldConfig.flows) {
if (oldConfig.flows.hasOwnProperty(id) && (!newConfig.flows.hasOwnProperty(id))) {

View File

@ -18,15 +18,16 @@ var when = require("when");
var path = require("path");
var fs = require("fs");
var clone = require("clone");
var util = require("util");
var registry = require("../../runtime-registry");
var registry = require("./registry");
var credentials = require("./credentials");
var flows = require("./flows");
var flowUtil = require("./flows/util")
var context = require("./context");
var Node = require("./Node");
var log;
var library = require("./library");
var events = require("../events");
@ -61,6 +62,26 @@ function registerType(nodeSet,type,constructor,opts) {
}
}
}
if(!(constructor.prototype instanceof Node)) {
if(Object.getPrototypeOf(constructor.prototype) === Object.prototype) {
util.inherits(constructor,Node);
} else {
var proto = constructor.prototype;
while(Object.getPrototypeOf(proto) !== Object.prototype) {
proto = Object.getPrototypeOf(proto);
}
//TODO: This is a partial implementation of util.inherits >= node v5.0.0
// which should be changed when support for node < v5.0.0 is dropped
// see: https://github.com/nodejs/node/pull/3455
proto.constructor.super_ = Node;
if(Object.setPrototypeOf) {
Object.setPrototypeOf(proto, Node.prototype);
} else {
// hack for node v0.10
proto.__proto__ = Node.prototype;
}
}
}
registry.registerType(nodeSet,type,constructor);
}
@ -99,7 +120,6 @@ function init(runtime) {
flows.init(runtime);
registry.init(runtime);
context.init(runtime.settings);
library.init(runtime);
}
function disableNode(id) {
@ -188,8 +208,8 @@ module.exports = {
getNodeConfig: registry.getNodeConfig,
getNodeIconPath: registry.getNodeIconPath,
getNodeIcons: registry.getNodeIcons,
getNodeExampleFlows: library.getExampleFlows,
getNodeExampleFlowPath: library.getExampleFlowPath,
getNodeExampleFlows: registry.getNodeExampleFlows,
getNodeExampleFlowPath: registry.getNodeExampleFlowPath,
clearRegistry: registry.clear,
cleanModuleList: registry.cleanModuleList,

View File

@ -83,7 +83,6 @@ module.exports = {
try {
fs.renameSync(path,backupPath);
} catch(err) {
console.log(err);
}
}
return when.promise(function(resolve,reject) {

View File

@ -16,7 +16,7 @@
var should = require("should");
var deprecated = require("../../../../../red/runtime/nodes/registry/deprecated.js");
var deprecated = require("../../../red/runtime-registry/deprecated.js");
describe('deprecated', function() {
it('should return info on a node',function() {

View File

@ -20,16 +20,13 @@ var path = require("path");
var when = require("when");
var fs = require("fs");
var registry = require("../../../../../red/runtime/nodes/registry");
var registry = require("../../../red/runtime-registry");
var installer = require("../../../../../red/runtime/nodes/registry/installer");
var loader = require("../../../../../red/runtime/nodes/registry/loader");
var typeRegistry = require("../../../../../red/runtime/nodes/registry/registry");
var installer = require("../../../red/runtime-registry/installer");
var loader = require("../../../red/runtime-registry/loader");
var typeRegistry = require("../../../red/runtime-registry/registry");
describe('red/nodes/registry/index', function() {
describe('red/registry/index', function() {
var stubs = [];
afterEach(function() {
while(stubs.length) {

View File

@ -22,9 +22,9 @@ var fs = require('fs');
var EventEmitter = require('events');
var child_process = require('child_process');
var installer = require("../../../../../red/runtime/nodes/registry/installer");
var registry = require("../../../../../red/runtime/nodes/registry/index");
var typeRegistry = require("../../../../../red/runtime/nodes/registry/registry");
var installer = require("../../../red/runtime-registry/installer");
var registry = require("../../../red/runtime-registry/index");
var typeRegistry = require("../../../red/runtime-registry/registry");
describe('nodes/registry/installer', function() {
@ -39,7 +39,7 @@ describe('nodes/registry/installer', function() {
}
before(function() {
installer.init({log:mockLog, settings:{}});
installer.init({log:mockLog, settings:{}, events: new EventEmitter()});
});
afterEach(function() {
if (child_process.spawn.restore) {
@ -166,7 +166,7 @@ describe('nodes/registry/installer', function() {
});
it("rejects when non-existant path is provided", function(done) {
this.timeout(10000);
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() {
done(new Error("Unexpected success"));
}).catch(function(err) {
@ -186,7 +186,7 @@ describe('nodes/registry/installer', function() {
var addModule = sinon.stub(registry,"addModule",function(md) {
return when.resolve(nodeInfo);
});
var resourcesDir = path.resolve(path.join(__dirname,"..","resources","local","TestNodeModule","node_modules","TestNodeModule"));
var resourcesDir = path.resolve(path.join(__dirname,"resources","local","TestNodeModule","node_modules","TestNodeModule"));
sinon.stub(child_process,"spawn",function(cmd,args,opt) {
var ee = new EventEmitter();
ee.stdout = new EventEmitter();

View File

@ -14,56 +14,47 @@
* limitations under the License.
**/
var EventEmitter = require('events').EventEmitter;
var events = new EventEmitter();
var should = require("should");
var fs = require("fs");
var path = require("path");
var library = require("../../../../red/runtime/nodes/library")
var library = require("../../../red/runtime-registry/library");
describe("library api", function() {
it('returns null list when no modules have been registered', function() {
library.init({events:events});
library.init();
should.not.exist(library.getExampleFlows());
});
it('returns null path when module is not known', function() {
library.init({events:events});
library.init();
should.not.exist(library.getExampleFlowPath('foo','bar'));
});
it('returns a valid example path', function(done) {
library.init({events:events});
events.emit('node-examples-dir',{
name: "test-module",
path: path.resolve(__dirname+'/../../../resources/examples')
});
setTimeout(function() {
library.init();
library.addExamplesDir("test-module",path.resolve(__dirname+'/resources/examples')).then(function() {
try {
var flows = library.getExampleFlows();
flows.should.deepEqual({"d":{"test-module":{"f":["one"]}}});
var examplePath = library.getExampleFlowPath('test-module','one');
examplePath.should.eql(path.resolve(__dirname+'/../../../resources/examples/one.json'))
examplePath.should.eql(path.resolve(__dirname+'/resources/examples/one.json'))
events.emit('node-module-uninstalled', 'test-module');
library.removeExamplesDir('test-module');
setTimeout(function() {
try {
should.not.exist(library.getExampleFlows());
should.not.exist(library.getExampleFlowPath('test-module','one'));
done();
} catch(err) {
done(err);
}
},20);
try {
should.not.exist(library.getExampleFlows());
should.not.exist(library.getExampleFlowPath('test-module','one'));
done();
} catch(err) {
done(err);
}
}catch(err) {
done(err);
}
},20);
});
})
});

View File

@ -20,14 +20,14 @@ var sinon = require("sinon");
var path = require("path");
var fs = require("fs");
var loader = require("../../../../../red/runtime/nodes/registry/loader");
var loader = require("../../../red/runtime-registry/loader");
var localfilesystem = require("../../../../../red/runtime/nodes/registry/localfilesystem");
var registry = require("../../../../../red/runtime/nodes/registry/registry");
var localfilesystem = require("../../../red/runtime-registry/localfilesystem");
var registry = require("../../../red/runtime-registry/registry");
var nodes = require("../../../../../red/runtime/nodes/registry");
var nodes = require("../../../red/runtime-registry");
var resourcesDir = path.resolve(path.join(__dirname,"..","resources","local"));
var resourcesDir = path.resolve(path.join(__dirname,"resources","local"));
describe("red/nodes/registry/loader",function() {
var stubs = [];
@ -42,18 +42,12 @@ describe("red/nodes/registry/loader",function() {
stubs.pop().restore();
}
})
describe("#init",function() {
it("init",function() {
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){},log:{info:function(){},_:function(){}}}});
localfilesystem.init.called.should.be.true();
});
});
describe("#load",function() {
it("load empty set without settings available", function(done) {
stubs.push(sinon.stub(localfilesystem,"getNodeFiles", function(){ return {};}));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return {};}));
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return false;}}});
loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return false;}}});
loader.load("foo",true).then(function() {
localfilesystem.getNodeFiles.called.should.be.true();
localfilesystem.getNodeFiles.lastCall.args[0].should.eql('foo');
@ -65,7 +59,7 @@ describe("red/nodes/registry/loader",function() {
it("load empty set with settings available triggers registery save", function(done) {
stubs.push(sinon.stub(localfilesystem,"getNodeFiles", function(){ return {};}));
stubs.push(sinon.stub(registry,"saveNodeList", 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,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.load("foo",true).then(function() {
registry.saveNodeList.called.should.be.true();
done();
@ -79,6 +73,7 @@ describe("red/nodes/registry/loader",function() {
var result = {};
result["node-red"] = {
"name": "node-red",
"version": "1.2.3",
"nodes": {
"TestNode1": {
"file": path.join(resourcesDir,"TestNode1","TestNode1.js"),
@ -91,27 +86,32 @@ describe("red/nodes/registry/loader",function() {
}));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return }));
stubs.push(sinon.stub(registry,"addNodeSet", function(){ return }));
stubs.push(sinon.stub(registry,"addModule", function(){ return }));
// This module isn't already loaded
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
stubs.push(sinon.stub(nodes,"registerType"));
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,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.load().then(function(result) {
registry.addNodeSet.called.should.be.true();
registry.addNodeSet.lastCall.args[0].should.eql("node-red/TestNode1");
registry.addNodeSet.lastCall.args[1].should.have.a.property('id',"node-red/TestNode1");
registry.addNodeSet.lastCall.args[1].should.have.a.property('module',"node-red");
registry.addNodeSet.lastCall.args[1].should.have.a.property('enabled',true);
registry.addNodeSet.lastCall.args[1].should.have.a.property('loaded',true);
registry.addNodeSet.lastCall.args[1].should.have.a.property('version',undefined);
registry.addNodeSet.lastCall.args[1].should.have.a.property('types');
registry.addNodeSet.lastCall.args[1].types.should.have.a.length(1);
registry.addNodeSet.lastCall.args[1].types[0].should.eql('test-node-1');
registry.addNodeSet.lastCall.args[1].should.have.a.property('config');
registry.addNodeSet.lastCall.args[1].should.have.a.property('help');
registry.addNodeSet.lastCall.args[1].should.have.a.property('namespace','node-red');
registry.addNodeSet.lastCall.args[1].should.not.have.a.property('err');
registry.addModule.called.should.be.true();
var module = registry.addModule.lastCall.args[0];
module.should.have.property("name","node-red");
module.should.have.property("version","1.2.3");
module.should.have.property("nodes");
module.nodes.should.have.property("TestNode1");
module.nodes.TestNode1.should.have.property("id","node-red/TestNode1");
module.nodes.TestNode1.should.have.property("module","node-red");
module.nodes.TestNode1.should.have.property("name","TestNode1");
module.nodes.TestNode1.should.have.property("file");
module.nodes.TestNode1.should.have.property("template");
module.nodes.TestNode1.should.have.property("enabled",true);
module.nodes.TestNode1.should.have.property("loaded",true);
module.nodes.TestNode1.should.have.property("types");
module.nodes.TestNode1.types.should.have.a.length(1);
module.nodes.TestNode1.types[0].should.eql('test-node-1');
module.nodes.TestNode1.should.have.property("config");
module.nodes.TestNode1.should.have.property("help");
module.nodes.TestNode1.should.have.property("namespace","node-red");
nodes.registerType.calledOnce.should.be.true();
nodes.registerType.lastCall.args[0].should.eql('node-red/TestNode1');
@ -128,6 +128,7 @@ describe("red/nodes/registry/loader",function() {
var result = {};
result["node-red"] = {
"name": "node-red",
"version": "4.5.6",
"nodes": {
"MultipleNodes1": {
"file": path.join(resourcesDir,"MultipleNodes1","MultipleNodes1.js"),
@ -140,27 +141,33 @@ describe("red/nodes/registry/loader",function() {
}));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return }));
stubs.push(sinon.stub(registry,"addNodeSet", function(){ return }));
stubs.push(sinon.stub(registry,"addModule", function(){ return }));
// This module isn't already loaded
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
stubs.push(sinon.stub(nodes,"registerType"));
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,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.load().then(function(result) {
registry.addNodeSet.called.should.be.true();
registry.addNodeSet.lastCall.args[0].should.eql("node-red/MultipleNodes1");
registry.addNodeSet.lastCall.args[1].should.have.a.property('id',"node-red/MultipleNodes1");
registry.addNodeSet.lastCall.args[1].should.have.a.property('module',"node-red");
registry.addNodeSet.lastCall.args[1].should.have.a.property('enabled',true);
registry.addNodeSet.lastCall.args[1].should.have.a.property('loaded',true);
registry.addNodeSet.lastCall.args[1].should.have.a.property('version',undefined);
registry.addNodeSet.lastCall.args[1].should.have.a.property('types');
registry.addNodeSet.lastCall.args[1].types.should.have.a.length(2);
registry.addNodeSet.lastCall.args[1].types[0].should.eql('test-node-multiple-1a');
registry.addNodeSet.lastCall.args[1].types[1].should.eql('test-node-multiple-1b');
registry.addNodeSet.lastCall.args[1].should.have.a.property('config');
registry.addNodeSet.lastCall.args[1].should.have.a.property('help');
registry.addNodeSet.lastCall.args[1].should.have.a.property('namespace','node-red');
registry.addNodeSet.lastCall.args[1].should.not.have.a.property('err');
registry.addModule.called.should.be.true();
var module = registry.addModule.lastCall.args[0];
module.should.have.property("name","node-red");
module.should.have.property("version","4.5.6");
module.should.have.property("nodes");
module.nodes.should.have.property("MultipleNodes1");
module.nodes.MultipleNodes1.should.have.property("id","node-red/MultipleNodes1");
module.nodes.MultipleNodes1.should.have.property("module","node-red");
module.nodes.MultipleNodes1.should.have.property("name","MultipleNodes1");
module.nodes.MultipleNodes1.should.have.property("file");
module.nodes.MultipleNodes1.should.have.property("template");
module.nodes.MultipleNodes1.should.have.property("enabled",true);
module.nodes.MultipleNodes1.should.have.property("loaded",true);
module.nodes.MultipleNodes1.should.have.property("types");
module.nodes.MultipleNodes1.types.should.have.a.length(2);
module.nodes.MultipleNodes1.types[0].should.eql('test-node-multiple-1a');
module.nodes.MultipleNodes1.types[1].should.eql('test-node-multiple-1b');
module.nodes.MultipleNodes1.should.have.property("config");
module.nodes.MultipleNodes1.should.have.property("help");
module.nodes.MultipleNodes1.should.have.property("namespace","node-red");
nodes.registerType.calledTwice.should.be.true();
nodes.registerType.firstCall.args[0].should.eql('node-red/MultipleNodes1');
@ -168,6 +175,7 @@ describe("red/nodes/registry/loader",function() {
nodes.registerType.secondCall.args[0].should.eql('node-red/MultipleNodes1');
nodes.registerType.secondCall.args[1].should.eql('test-node-multiple-1b');
done();
}).catch(function(err) {
done(err);
@ -180,6 +188,7 @@ describe("red/nodes/registry/loader",function() {
var result = {};
result["node-red"] = {
"name": "node-red",
"version":"2.4.6",
"nodes": {
"TestNode2": {
"file": path.join(resourcesDir,"TestNode2","TestNode2.js"),
@ -192,27 +201,34 @@ describe("red/nodes/registry/loader",function() {
}));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return }));
stubs.push(sinon.stub(registry,"addNodeSet", function(){ return }));
stubs.push(sinon.stub(registry,"addModule", function(){ return }));
// This module isn't already loaded
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
stubs.push(sinon.stub(nodes,"registerType"));
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,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.load().then(function(result) {
registry.addNodeSet.called.should.be.true();
registry.addNodeSet.lastCall.args[0].should.eql("node-red/TestNode2");
registry.addNodeSet.lastCall.args[1].should.have.a.property('id',"node-red/TestNode2");
registry.addNodeSet.lastCall.args[1].should.have.a.property('module',"node-red");
registry.addNodeSet.lastCall.args[1].should.have.a.property('enabled',true);
registry.addNodeSet.lastCall.args[1].should.have.a.property('loaded',true);
registry.addNodeSet.lastCall.args[1].should.have.a.property('version',undefined);
registry.addNodeSet.lastCall.args[1].should.have.a.property('types');
registry.addNodeSet.lastCall.args[1].types.should.have.a.length(1);
registry.addNodeSet.lastCall.args[1].types[0].should.eql('test-node-2');
registry.addNodeSet.lastCall.args[1].should.have.a.property('config');
registry.addNodeSet.lastCall.args[1].should.have.a.property('help');
registry.addNodeSet.lastCall.args[1].should.have.a.property('namespace','node-red');
registry.addNodeSet.lastCall.args[1].should.not.have.a.property('err');
registry.addModule.called.should.be.true();
var module = registry.addModule.lastCall.args[0];
module.should.have.property("name","node-red");
module.should.have.property("version","2.4.6");
module.should.have.property("nodes");
module.nodes.should.have.property("TestNode2");
module.nodes.TestNode2.should.have.property("id","node-red/TestNode2");
module.nodes.TestNode2.should.have.property("module","node-red");
module.nodes.TestNode2.should.have.property("name","TestNode2");
module.nodes.TestNode2.should.have.property("file");
module.nodes.TestNode2.should.have.property("template");
module.nodes.TestNode2.should.have.property("enabled",true);
module.nodes.TestNode2.should.have.property("loaded",true);
module.nodes.TestNode2.should.have.property("types");
module.nodes.TestNode2.types.should.have.a.length(1);
module.nodes.TestNode2.types[0].should.eql('test-node-2');
module.nodes.TestNode2.should.have.property("config");
module.nodes.TestNode2.should.have.property("help");
module.nodes.TestNode2.should.have.property("namespace","node-red");
module.nodes.TestNode2.should.not.have.property('err');
nodes.registerType.calledOnce.should.be.true();
nodes.registerType.lastCall.args[0].should.eql('node-red/TestNode2');
@ -230,6 +246,7 @@ describe("red/nodes/registry/loader",function() {
var result = {};
result["node-red"] = {
"name": "node-red",
"version":"1.2.3",
"nodes": {
"TestNode3": {
"file": path.join(resourcesDir,"TestNode3","TestNode3.js"),
@ -242,29 +259,35 @@ describe("red/nodes/registry/loader",function() {
}));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return }));
stubs.push(sinon.stub(registry,"addNodeSet", function(){ return }));
stubs.push(sinon.stub(registry,"addModule", function(){ return }));
// This module isn't already loaded
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
stubs.push(sinon.stub(nodes,"registerType"));
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,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.load().then(function(result) {
registry.addNodeSet.called.should.be.true();
registry.addNodeSet.lastCall.args[0].should.eql("node-red/TestNode3");
registry.addNodeSet.lastCall.args[1].should.have.a.property('id',"node-red/TestNode3");
registry.addNodeSet.lastCall.args[1].should.have.a.property('module',"node-red");
registry.addNodeSet.lastCall.args[1].should.have.a.property('enabled',true);
registry.addNodeSet.lastCall.args[1].should.have.a.property('loaded',false);
registry.addNodeSet.lastCall.args[1].should.have.a.property('version',undefined);
registry.addNodeSet.lastCall.args[1].should.have.a.property('types');
registry.addNodeSet.lastCall.args[1].types.should.have.a.length(1);
registry.addNodeSet.lastCall.args[1].types[0].should.eql('test-node-3');
registry.addNodeSet.lastCall.args[1].should.have.a.property('config');
registry.addNodeSet.lastCall.args[1].should.have.a.property('help');
registry.addNodeSet.lastCall.args[1].should.have.a.property('namespace','node-red');
registry.addNodeSet.lastCall.args[1].should.have.a.property('err','fail');
registry.addModule.called.should.be.true();
var module = registry.addModule.lastCall.args[0];
module.should.have.property("name","node-red");
module.should.have.property("version","1.2.3");
module.should.have.property("nodes");
module.nodes.should.have.property("TestNode3");
module.nodes.TestNode3.should.have.property("id","node-red/TestNode3");
module.nodes.TestNode3.should.have.property("module","node-red");
module.nodes.TestNode3.should.have.property("name","TestNode3");
module.nodes.TestNode3.should.have.property("file");
module.nodes.TestNode3.should.have.property("template");
module.nodes.TestNode3.should.have.property("enabled",true);
module.nodes.TestNode3.should.have.property("loaded",false);
module.nodes.TestNode3.should.have.property("types");
module.nodes.TestNode3.types.should.have.a.length(1);
module.nodes.TestNode3.types[0].should.eql('test-node-3');
module.nodes.TestNode3.should.have.property("config");
module.nodes.TestNode3.should.have.property("help");
module.nodes.TestNode3.should.have.property("namespace","node-red");
module.nodes.TestNode3.should.have.property('err','fail');
nodes.registerType.calledOnce.should.be.false();
nodes.registerType.called.should.be.false();
done();
}).catch(function(err) {
@ -277,6 +300,7 @@ describe("red/nodes/registry/loader",function() {
var result = {};
result["node-red"] = {
"name": "node-red",
"version":"1.2.3",
"nodes": {
"DoesNotExist": {
"file": path.join(resourcesDir,"doesnotexist"),
@ -289,28 +313,34 @@ describe("red/nodes/registry/loader",function() {
}));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return }));
stubs.push(sinon.stub(registry,"addNodeSet", function(){ return }));
stubs.push(sinon.stub(registry,"addModule", function(){ return }));
// This module isn't already loaded
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
stubs.push(sinon.stub(nodes,"registerType"));
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,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.load().then(function(result) {
registry.addNodeSet.called.should.be.true();
registry.addNodeSet.lastCall.args[0].should.eql("node-red/DoesNotExist");
registry.addNodeSet.lastCall.args[1].should.have.a.property('id',"node-red/DoesNotExist");
registry.addNodeSet.lastCall.args[1].should.have.a.property('module',"node-red");
registry.addNodeSet.lastCall.args[1].should.have.a.property('enabled',true);
registry.addNodeSet.lastCall.args[1].should.have.a.property('loaded',false);
registry.addNodeSet.lastCall.args[1].should.have.a.property('version',undefined);
registry.addNodeSet.lastCall.args[1].should.have.a.property('types');
registry.addNodeSet.lastCall.args[1].types.should.have.a.length(0);
registry.addNodeSet.lastCall.args[1].should.not.have.a.property('config');
registry.addNodeSet.lastCall.args[1].should.not.have.a.property('help');
registry.addNodeSet.lastCall.args[1].should.not.have.a.property('namespace','node-red');
registry.addNodeSet.lastCall.args[1].should.have.a.property('err');
registry.addModule.called.should.be.true();
var module = registry.addModule.lastCall.args[0];
module.should.have.property("name","node-red");
module.should.have.property("version","1.2.3");
module.should.have.property("nodes");
module.nodes.should.have.property("DoesNotExist");
module.nodes.DoesNotExist.should.have.property("id","node-red/DoesNotExist");
module.nodes.DoesNotExist.should.have.property("module","node-red");
module.nodes.DoesNotExist.should.have.property("name","DoesNotExist");
module.nodes.DoesNotExist.should.have.property("file");
module.nodes.DoesNotExist.should.have.property("template");
module.nodes.DoesNotExist.should.have.property("enabled",true);
module.nodes.DoesNotExist.should.have.property("loaded",false);
module.nodes.DoesNotExist.should.have.property("types");
module.nodes.DoesNotExist.types.should.have.a.length(0);
module.nodes.DoesNotExist.should.not.have.property("config");
module.nodes.DoesNotExist.should.not.have.property("help");
module.nodes.DoesNotExist.should.not.have.property("namespace","node-red");
module.nodes.DoesNotExist.should.have.property('err');
nodes.registerType.calledOnce.should.be.false();
nodes.registerType.called.should.be.false();
done();
}).catch(function(err) {
@ -323,6 +353,7 @@ describe("red/nodes/registry/loader",function() {
var result = {};
result["node-red"] = {
"name": "node-red",
"version": "1.2.3",
"nodes": {
"DuffNode": {
"file": path.join(resourcesDir,"DuffNode","DuffNode.js"),
@ -335,29 +366,36 @@ describe("red/nodes/registry/loader",function() {
}));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return }));
stubs.push(sinon.stub(registry,"addNodeSet", function(){ return }));
stubs.push(sinon.stub(registry,"addModule", function(){ return }));
// This module isn't already loaded
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
stubs.push(sinon.stub(nodes,"registerType"));
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,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.load().then(function(result) {
registry.addNodeSet.called.should.be.true();
registry.addNodeSet.lastCall.args[0].should.eql("node-red/DuffNode");
registry.addNodeSet.lastCall.args[1].should.have.a.property('id',"node-red/DuffNode");
registry.addNodeSet.lastCall.args[1].should.have.a.property('module',"node-red");
registry.addNodeSet.lastCall.args[1].should.have.a.property('enabled',true);
registry.addNodeSet.lastCall.args[1].should.have.a.property('loaded',false);
registry.addNodeSet.lastCall.args[1].should.have.a.property('version',undefined);
registry.addNodeSet.lastCall.args[1].should.have.a.property('types');
registry.addNodeSet.lastCall.args[1].types.should.have.a.length(0);
registry.addNodeSet.lastCall.args[1].should.not.have.a.property('config');
registry.addNodeSet.lastCall.args[1].should.not.have.a.property('help');
registry.addNodeSet.lastCall.args[1].should.not.have.a.property('namespace','node-red');
registry.addNodeSet.lastCall.args[1].should.have.a.property('err');
registry.addNodeSet.lastCall.args[1].err.should.endWith("DuffNode.html does not exist");
nodes.registerType.calledOnce.should.be.false();
registry.addModule.called.should.be.true();
var module = registry.addModule.lastCall.args[0];
module.should.have.property("name","node-red");
module.should.have.property("version","1.2.3");
module.should.have.property("nodes");
module.nodes.should.have.property("DuffNode");
module.nodes.DuffNode.should.have.property("id","node-red/DuffNode");
module.nodes.DuffNode.should.have.property("module","node-red");
module.nodes.DuffNode.should.have.property("name","DuffNode");
module.nodes.DuffNode.should.have.property("file");
module.nodes.DuffNode.should.have.property("template");
module.nodes.DuffNode.should.have.property("enabled",true);
module.nodes.DuffNode.should.have.property("loaded",false);
module.nodes.DuffNode.should.have.property("types");
module.nodes.DuffNode.types.should.have.a.length(0);
module.nodes.DuffNode.should.not.have.property("config");
module.nodes.DuffNode.should.not.have.property("help");
module.nodes.DuffNode.should.not.have.property("namespace","node-red");
module.nodes.DuffNode.should.have.property('err');
module.nodes.DuffNode.err.should.endWith("DuffNode.html does not exist");
nodes.registerType.called.should.be.false();
done();
}).catch(function(err) {
@ -368,7 +406,7 @@ describe("red/nodes/registry/loader",function() {
describe("#addModule",function() {
it("throws error if settings unavailable", function() {
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return false;}}});
loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return false;}}});
/*jshint immed: false */
(function(){
loader.addModule("test-module");
@ -377,7 +415,7 @@ describe("red/nodes/registry/loader",function() {
it("returns rejected error if module already loaded", function(done) {
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,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.addModule("test-module").catch(function(err) {
err.code.should.eql("module_already_loaded");
@ -389,7 +427,7 @@ describe("red/nodes/registry/loader",function() {
stubs.push(sinon.stub(localfilesystem,"getModuleFiles",function() {
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,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.addModule("test-module").catch(function(err) {
err.message.should.eql("failure");
done();
@ -419,25 +457,32 @@ describe("red/nodes/registry/loader",function() {
}));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return "a node list" }));
stubs.push(sinon.stub(registry,"addNodeSet", function(){ return }));
stubs.push(sinon.stub(registry,"addModule", function(){ return }));
stubs.push(sinon.stub(nodes,"registerType"));
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,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.addModule("TestNodeModule").then(function(result) {
result.should.eql("a node list");
registry.addNodeSet.calledOnce.should.be.true();
registry.addNodeSet.lastCall.args[0].should.eql("TestNodeModule/TestNode1");
registry.addNodeSet.lastCall.args[1].should.have.a.property('id',"TestNodeModule/TestNode1");
registry.addNodeSet.lastCall.args[1].should.have.a.property('module',"TestNodeModule");
registry.addNodeSet.lastCall.args[1].should.have.a.property('enabled',true);
registry.addNodeSet.lastCall.args[1].should.have.a.property('loaded',true);
registry.addNodeSet.lastCall.args[1].should.have.a.property('version',"1.2.3");
registry.addNodeSet.lastCall.args[1].should.have.a.property('types');
registry.addNodeSet.lastCall.args[1].types.should.have.a.length(1);
registry.addNodeSet.lastCall.args[1].types[0].should.eql('test-node-mod-1');
registry.addNodeSet.lastCall.args[1].should.have.a.property('config');
registry.addNodeSet.lastCall.args[1].should.have.a.property('help');
registry.addNodeSet.lastCall.args[1].should.have.a.property('namespace','TestNodeModule');
registry.addNodeSet.lastCall.args[1].should.not.have.a.property('err');
registry.addModule.called.should.be.true();
var module = registry.addModule.lastCall.args[0];
module.should.have.property("name","TestNodeModule");
module.should.have.property("version","1.2.3");
module.should.have.property("nodes");
module.nodes.should.have.property("TestNode1");
module.nodes.TestNode1.should.have.property("id","TestNodeModule/TestNode1");
module.nodes.TestNode1.should.have.property("module","TestNodeModule");
module.nodes.TestNode1.should.have.property("name","TestNode1");
module.nodes.TestNode1.should.have.property("file");
module.nodes.TestNode1.should.have.property("template");
module.nodes.TestNode1.should.have.property("enabled",true);
module.nodes.TestNode1.should.have.property("loaded",true);
module.nodes.TestNode1.should.have.property("types");
module.nodes.TestNode1.types.should.have.a.length(1);
module.nodes.TestNode1.types[0].should.eql('test-node-mod-1');
module.nodes.TestNode1.should.have.property("config");
module.nodes.TestNode1.should.have.property("help");
module.nodes.TestNode1.should.have.property("namespace","TestNodeModule");
module.nodes.TestNode1.should.not.have.property('err');
nodes.registerType.calledOnce.should.be.true();
done();
@ -469,12 +514,12 @@ describe("red/nodes/registry/loader",function() {
}));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return "a node list" }));
stubs.push(sinon.stub(registry,"addNodeSet", function(){ return }));
stubs.push(sinon.stub(registry,"addModule", function(){ return }));
stubs.push(sinon.stub(nodes,"registerType"));
loader.init({log:{"_":function(){},warn:function(){}},nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},version: function() { return "0.12.0"}, settings:{available:function(){return true;}}});
loader.init({log:{"_":function(){},warn:function(){}},nodes:nodes,version: function() { return "0.12.0"}, settings:{available:function(){return true;}}});
loader.addModule("TestNodeModule").then(function(result) {
result.should.eql("a node list");
registry.addNodeSet.called.should.be.false();
registry.addModule.called.should.be.false();
nodes.registerType.called.should.be.false();
done();
}).catch(function(err) {

View File

@ -19,13 +19,19 @@ var when = require("when");
var sinon = require("sinon");
var path = require("path");
var localfilesystem = require("../../../../../red/runtime/nodes/registry/localfilesystem");
var localfilesystem = require("../../../red/runtime-registry/localfilesystem");
var resourcesDir = path.resolve(path.join(__dirname,"..","resources","local"));
var userDir = path.resolve(path.join(__dirname,"..","resources","userDir"));
var moduleDir = path.resolve(path.join(__dirname,"..","resources","local","TestNodeModule"));
var resourcesDir = path.resolve(path.join(__dirname,"resources","local"));
var userDir = path.resolve(path.join(__dirname,"resources","userDir"));
var moduleDir = path.resolve(path.join(__dirname,"resources","local","TestNodeModule"));
var i18n = require("../../../red/util").i18n; // TODO: separate module
describe("red/nodes/registry/localfilesystem",function() {
beforeEach(function() {
stubs.push(sinon.stub(i18n,"registerMessageCatalog", function() { return Promise.resolve(); }));
})
var stubs = [];
afterEach(function() {
while(stubs.length) {
@ -46,7 +52,7 @@ describe("red/nodes/registry/localfilesystem",function() {
}
describe("#getNodeFiles",function() {
it("Finds all the node files in the resources tree",function(done) {
localfilesystem.init({i18n:{registerMessageCatalog:function(){}},events:{emit:function(){}},settings:{coreNodesDir:resourcesDir}});
localfilesystem.init({settings:{coreNodesDir:resourcesDir}});
var nodeList = localfilesystem.getNodeFiles(true);
nodeList.should.have.a.property("node-red");
var nm = nodeList['node-red'];
@ -54,10 +60,14 @@ describe("red/nodes/registry/localfilesystem",function() {
nm.should.have.a.property("nodes");
var nodes = nm.nodes;
checkNodes(nm.nodes,['TestNode1','MultipleNodes1','NestedNode','TestNode2','TestNode3','TestNode4'],['TestNodeModule']);
i18n.registerMessageCatalog.called.should.be.true();
i18n.registerMessageCatalog.lastCall.args[0].should.eql('node-red');
i18n.registerMessageCatalog.lastCall.args[1].should.eql(path.resolve(path.join(resourcesDir,"core","locales")));
i18n.registerMessageCatalog.lastCall.args[2].should.eql('messages.json');
done();
});
it("Includes node files from settings",function(done) {
localfilesystem.init({i18n:{registerMessageCatalog:function(){}},events:{emit:function(){}},settings:{nodesIncludes:['TestNode1.js'],coreNodesDir:resourcesDir}});
localfilesystem.init({settings:{nodesIncludes:['TestNode1.js'],coreNodesDir:resourcesDir}});
var nodeList = localfilesystem.getNodeFiles(true);
nodeList.should.have.a.property("node-red");
var nm = nodeList['node-red'];
@ -67,7 +77,7 @@ describe("red/nodes/registry/localfilesystem",function() {
done();
});
it("Excludes node files from settings",function(done) {
localfilesystem.init({i18n:{registerMessageCatalog:function(){}},events:{emit:function(){}},settings:{nodesExcludes:['TestNode1.js'],coreNodesDir:resourcesDir}});
localfilesystem.init({settings:{nodesExcludes:['TestNode1.js'],coreNodesDir:resourcesDir}});
var nodeList = localfilesystem.getNodeFiles(true);
nodeList.should.have.a.property("node-red");
var nm = nodeList['node-red'];
@ -77,7 +87,7 @@ describe("red/nodes/registry/localfilesystem",function() {
done();
});
it("Finds nodes in userDir/nodes",function(done) {
localfilesystem.init({i18n:{registerMessageCatalog:function(){}},events:{emit:function(){}},settings:{userDir:userDir,coreNodesDir:__dirname}});
localfilesystem.init({settings:{userDir:userDir}});
var nodeList = localfilesystem.getNodeFiles(true);
nodeList.should.have.a.property("node-red");
var nm = nodeList['node-red'];
@ -88,7 +98,7 @@ describe("red/nodes/registry/localfilesystem",function() {
});
it("Finds nodes in settings.nodesDir (string)",function(done) {
localfilesystem.init({i18n:{registerMessageCatalog:function(){}},events:{emit:function(){}},settings:{nodesDir:userDir,coreNodesDir:__dirname}});
localfilesystem.init({settings:{nodesDir:userDir}});
var nodeList = localfilesystem.getNodeFiles(true);
nodeList.should.have.a.property("node-red");
var nm = nodeList['node-red'];
@ -97,19 +107,19 @@ describe("red/nodes/registry/localfilesystem",function() {
checkNodes(nm.nodes,['TestNode5'],['TestNode1']);
done();
});
it("Finds nodes in settings.nodesDir (string,relative path)",function(done) {
var relativeUserDir = path.join("test","red","runtime","nodes","resources","userDir");
localfilesystem.init({i18n:{registerMessageCatalog:function(){}},events:{emit:function(){}},settings:{nodesDir:relativeUserDir,coreNodesDir:__dirname}});
var nodeList = localfilesystem.getNodeFiles(true);
nodeList.should.have.a.property("node-red");
var nm = nodeList['node-red'];
nm.should.have.a.property('name','node-red');
nm.should.have.a.property("nodes");
checkNodes(nm.nodes,['TestNode5'],['TestNode1']);
done();
});
it("Finds nodes in settings.nodesDir (array)",function(done) {
localfilesystem.init({i18n:{registerMessageCatalog:function(){}},events:{emit:function(){}},settings:{nodesDir:[userDir],coreNodesDir:__dirname}});
it("Finds nodes in settings.nodesDir (string,relative path)",function(done) {
var relativeUserDir = path.join("test","red","runtime-registry","resources","userDir");
localfilesystem.init({settings:{nodesDir:relativeUserDir}});
var nodeList = localfilesystem.getNodeFiles(true);
nodeList.should.have.a.property("node-red");
var nm = nodeList['node-red'];
nm.should.have.a.property('name','node-red');
nm.should.have.a.property("nodes");
checkNodes(nm.nodes,['TestNode5'],['TestNode1']);
done();
});
it("Finds nodes in settings.nodesDir (array)",function(done) {
localfilesystem.init({settings:{nodesDir:[userDir]}});
var nodeList = localfilesystem.getNodeFiles(true);
nodeList.should.have.a.property("node-red");
var nm = nodeList['node-red'];
@ -128,7 +138,7 @@ describe("red/nodes/registry/localfilesystem",function() {
}
return _join.apply(null,arguments);
}));
localfilesystem.init({i18n:{registerMessageCatalog:function(){}},events:{emit:function(){}},settings:{coreNodesDir:moduleDir}});
localfilesystem.init({settings:{coreNodesDir:moduleDir}});
var nodeList = localfilesystem.getNodeFiles();
nodeList.should.have.a.property("node-red");
var nm = nodeList['node-red'];
@ -146,6 +156,13 @@ describe("red/nodes/registry/localfilesystem",function() {
nm.should.have.a.property("nodes");
checkNodes(nm.nodes,['VersionMismatchMod1','VersionMismatchMod2'],[],'VersionMismatchModule');
i18n.registerMessageCatalog.called.should.be.true();
i18n.registerMessageCatalog.lastCall.args[0].should.eql('node-red');
i18n.registerMessageCatalog.lastCall.args[1].should.eql(path.resolve(path.join(moduleDir,"core","locales")));
i18n.registerMessageCatalog.lastCall.args[2].should.eql('messages.json');
done();
});
it.skip("finds locales directory");
@ -153,42 +170,58 @@ describe("red/nodes/registry/localfilesystem",function() {
it("scans icon files in the resources tree",function(done) {
var count = 0;
localfilesystem.init({
i18n:{registerMessageCatalog:function(){}},
events:{emit:function(eventName,dir){
if (count === 0) {
eventName.should.equal("node-icon-dir");
dir.name.should.equal("node-red");
dir.icons.should.be.an.Array();
count = 1;
} else if (count === 1) {
done();
}
}},
// events:{emit:function(eventName,dir){
// if (count === 0) {
// eventName.should.equal("node-icon-dir");
// dir.name.should.equal("node-red");
// dir.icons.should.be.an.Array();
// count = 1;
// } else if (count === 1) {
// done();
// }
// }},
settings:{coreNodesDir:resourcesDir}
});
localfilesystem.getNodeFiles(true);
var list = localfilesystem.getNodeFiles(true);
list.should.have.property("node-red");
list["node-red"].should.have.property("icons");
list["node-red"].icons.should.have.length(2);
list["node-red"].icons[1].should.have.property("path",path.join(__dirname,"resources/local/NestedDirectoryNode/NestedNode/icons"))
list["node-red"].icons[1].should.have.property("icons");
list["node-red"].icons[1].icons.should.have.length(1);
list["node-red"].icons[1].icons[0].should.eql("arrow-in.png");
done();
});
it("scans icons dir in library",function(done) {
var count = 0;
localfilesystem.init({
i18n:{registerMessageCatalog:function(){}},
events:{emit:function(eventName,dir){
eventName.should.equal("node-icon-dir");
if (count === 0) {
dir.name.should.equal("node-red");
dir.icons.should.be.an.Array();
count = 1;
} else if (count === 1) {
dir.name.should.equal("Library");
dir.icons.should.be.an.Array();
dir.icons.length.should.equal(1);
dir.icons[0].should.be.equal("test_icon.png");
done();
}
}},
//
// events:{emit:function(eventName,dir){
// eventName.should.equal("node-icon-dir");
// if (count === 0) {
// dir.name.should.equal("node-red");
// dir.icons.should.be.an.Array();
// count = 1;
// } else if (count === 1) {
// dir.name.should.equal("Library");
// dir.icons.should.be.an.Array();
// dir.icons.length.should.equal(1);
// dir.icons[0].should.be.equal("test_icon.png");
// done();
// }
// }},
settings:{userDir:userDir}
});
localfilesystem.getNodeFiles(true);
var list = localfilesystem.getNodeFiles(true);
list.should.have.property("node-red");
list["node-red"].should.have.property("icons");
list["node-red"].icons.should.have.length(2);
list["node-red"].icons[1].should.have.property("path",path.join(__dirname,"resources/userDir/lib/icons"))
list["node-red"].icons[1].should.have.property("icons");
list["node-red"].icons[1].icons.should.have.length(1);
list["node-red"].icons[1].icons[0].should.eql("test_icon.png");
done();
});
});
describe("#getModuleFiles",function() {
@ -202,7 +235,7 @@ describe("red/nodes/registry/localfilesystem",function() {
}
return _join.apply(null,arguments);
}));
localfilesystem.init({i18n:{registerMessageCatalog:function(){}},events:{emit:function(){}},settings:{coreNodesDir:moduleDir}});
localfilesystem.init({settings:{coreNodesDir:moduleDir}});
var nodeModule = localfilesystem.getModuleFiles('TestNodeModule');
nodeModule.should.have.a.property('TestNodeModule');
nodeModule['TestNodeModule'].should.have.a.property('name','TestNodeModule');
@ -226,7 +259,7 @@ describe("red/nodes/registry/localfilesystem",function() {
}
return _join.apply(null,arguments);
}));
localfilesystem.init({i18n:{registerMessageCatalog:function(){}},events:{emit:function(){}},settings:{coreNodesDir:moduleDir}});
localfilesystem.init({settings:{coreNodesDir:moduleDir}});
/*jshint immed: false */
(function(){
localfilesystem.getModuleFiles('WontExistModule');
@ -246,16 +279,24 @@ describe("red/nodes/registry/localfilesystem",function() {
return _join.apply(null,arguments);
}));
localfilesystem.init({
i18n:{registerMessageCatalog:function(){}},
events:{emit:function(eventName,dir){
eventName.should.equal("node-icon-dir");
dir.name.should.equal("TestNodeModule");
dir.icons.should.be.an.Array();
done();
}},
// events:{emit:function(eventName,dir){
// eventName.should.equal("node-icon-dir");
// dir.name.should.equal("TestNodeModule");
// dir.icons.should.be.an.Array();
// done();
// }},
settings:{coreNodesDir:moduleDir}
});
var nodeModule = localfilesystem.getModuleFiles('TestNodeModule');
nodeModule.should.have.property("TestNodeModule");
nodeModule.TestNodeModule.should.have.property('icons');
nodeModule.TestNodeModule.icons.should.have.length(1);
nodeModule.TestNodeModule.icons[0].should.have.property("path");
nodeModule.TestNodeModule.icons[0].should.have.property("icons");
nodeModule.TestNodeModule.icons[0].icons[0].should.eql("arrow-in.png");
done();
});
});
});

View File

@ -19,13 +19,10 @@ var when = require("when");
var sinon = require("sinon");
var path = require("path");
var typeRegistry = require("../../../../../red/runtime/nodes/registry/registry");
var typeRegistry = require("../../../red/runtime-registry/registry");
var EventEmitter = require('events');
var Node = require("../../../../../red/runtime/nodes/Node");
var events = require("../../../../../red/runtime/events");
var inherits = require("util").inherits;
var events = new EventEmitter();
describe("red/nodes/registry/registry",function() {
@ -86,7 +83,7 @@ describe("red/nodes/registry/registry",function() {
describe('#init/load', function() {
it('loads initial config', function(done) {
typeRegistry.init(settingsWithStorageAndInitialConfig);
typeRegistry.init(settingsWithStorageAndInitialConfig,null,events);
typeRegistry.getNodeList().should.have.lengthOf(0);
typeRegistry.load();
typeRegistry.getNodeList().should.have.lengthOf(1);
@ -123,7 +120,7 @@ describe("red/nodes/registry/registry",function() {
}}
};
var expected = JSON.parse('{"node-red":{"name":"node-red","nodes":{"sentiment":{"name":"sentiment","types":["sentiment"],"enabled":true,"module":"node-red"},"inject":{"name":"inject","types":["inject"],"enabled":true,"module":"node-red"}}},"testModule":{"name":"testModule","nodes":{"a-module.js":{"name":"a-module.js","types":["example"],"enabled":true,"module":"testModule"}}}}');
typeRegistry.init(legacySettings);
typeRegistry.init(legacySettings,null,events);
typeRegistry.load();
legacySettings.set.calledOnce.should.be.true();
legacySettings.set.args[0][1].should.eql(expected);
@ -132,10 +129,10 @@ describe("red/nodes/registry/registry",function() {
});
describe('#addNodeSet', function() {
describe.skip('#addNodeSet', function() {
it('adds a node set for an unknown module', function() {
typeRegistry.init(settings);
typeRegistry.init(settings,null,events);
typeRegistry.getNodeList().should.have.lengthOf(0);
typeRegistry.getModuleList().should.eql({});
@ -164,7 +161,7 @@ describe("red/nodes/registry/registry",function() {
it('adds a node set to an existing module', function() {
typeRegistry.init(settings);
typeRegistry.init(settings,null,events);
typeRegistry.getNodeList().should.have.lengthOf(0);
typeRegistry.getModuleList().should.eql({});
@ -193,7 +190,7 @@ describe("red/nodes/registry/registry",function() {
});
it('doesnt add node set types if node set has an error', function() {
typeRegistry.init(settings);
typeRegistry.init(settings,null,events);
typeRegistry.getNodeList().should.have.lengthOf(0);
typeRegistry.getModuleList().should.eql({});
@ -209,7 +206,7 @@ describe("red/nodes/registry/registry",function() {
});
it('doesnt add node set if type already exists', function() {
typeRegistry.init(settings);
typeRegistry.init(settings,null,events);
typeRegistry.getNodeList().should.have.lengthOf(0);
typeRegistry.getModuleList().should.eql({});
@ -243,7 +240,7 @@ describe("red/nodes/registry/registry",function() {
describe("#enableNodeSet", function() {
it('throws error if settings unavailable', function() {
typeRegistry.init(settings);
typeRegistry.init(settings,null,events);
/*jshint immed: false */
(function(){
typeRegistry.enableNodeSet("test-module/test-name");
@ -251,7 +248,7 @@ describe("red/nodes/registry/registry",function() {
});
it('throws error if module unknown', function() {
typeRegistry.init(settingsWithStorageAndInitialConfig);
typeRegistry.init(settingsWithStorageAndInitialConfig,null,events);
/*jshint immed: false */
(function(){
typeRegistry.enableNodeSet("test-module/unknown");
@ -262,7 +259,7 @@ describe("red/nodes/registry/registry",function() {
});
describe("#disableNodeSet", function() {
it('throws error if settings unavailable', function() {
typeRegistry.init(settings);
typeRegistry.init(settings,null,events);
/*jshint immed: false */
(function(){
typeRegistry.disableNodeSet("test-module/test-name");
@ -270,7 +267,7 @@ describe("red/nodes/registry/registry",function() {
});
it('throws error if module unknown', function() {
typeRegistry.init(settingsWithStorageAndInitialConfig);
typeRegistry.init(settingsWithStorageAndInitialConfig,null,events);
/*jshint immed: false */
(function(){
typeRegistry.disableNodeSet("test-module/unknown");
@ -281,7 +278,7 @@ describe("red/nodes/registry/registry",function() {
describe('#getNodeConfig', function() {
it('returns nothing for an unregistered type config', function(done) {
typeRegistry.init(settings);
typeRegistry.init(settings,null,events);
var config = typeRegistry.getNodeConfig("imaginary-shark");
(config === null).should.be.true();
done();
@ -290,26 +287,32 @@ describe("red/nodes/registry/registry",function() {
describe('#saveNodeList',function() {
it('rejects when settings unavailable',function(done) {
typeRegistry.init(stubSettings({},false,{}));
typeRegistry.addNodeSet("test-module/test-name",testNodeSet1, "0.0.1");
typeRegistry.init(stubSettings({},false,{}),null,events);
typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {"test-name":{module:"test-module",name:"test-name",types:[]}}});
typeRegistry.saveNodeList().catch(function(err) {
done();
});
});
it('saves the list',function(done) {
var s = stubSettings({},true,{});
typeRegistry.init(s);
typeRegistry.addNodeSet("test-module/test-name",testNodeSet1, "0.0.1");
typeRegistry.addNodeSet("test-module/test-name-2",testNodeSet2WithError, "0.0.1");
typeRegistry.init(s,null,events);
typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
"test-name":testNodeSet1,
"test-name-2":testNodeSet2WithError
}});
typeRegistry.saveNodeList().then(function() {
s.set.called.should.be.true();
s.set.lastCall.args[0].should.eql('nodes');
var nodes = s.set.lastCall.args[1];
nodes.should.have.property('test-module');
for (var n in nodes['test-module'].nodes) {
var nn = nodes['test-module'].nodes[n];
nn.should.not.have.property('err');
nn.should.not.have.property('id');
if (nodes['test-module'].nodes.hasOwnProperty(n)) {
var nn = nodes['test-module'].nodes[n];
nn.should.not.have.property('err');
nn.should.not.have.property('id');
}
}
done();
}).catch(function(err) {
@ -321,7 +324,7 @@ describe("red/nodes/registry/registry",function() {
describe('#removeModule',function() {
it('throws error for unknown module', function() {
var s = stubSettings({},true,{});
typeRegistry.init(s);
typeRegistry.init(s,null,events);
/*jshint immed: false */
(function(){
typeRegistry.removeModule("test-module/unknown");
@ -329,7 +332,7 @@ describe("red/nodes/registry/registry",function() {
});
it('throws error for unavaiable settings', function() {
var s = stubSettings({},false,{});
typeRegistry.init(s);
typeRegistry.init(s,null,events);
/*jshint immed: false */
(function(){
typeRegistry.removeModule("test-module/unknown");
@ -337,8 +340,10 @@ describe("red/nodes/registry/registry",function() {
});
it('removes a known module', function() {
var s = stubSettings({},true,{});
typeRegistry.init(s);
typeRegistry.addNodeSet("test-module/test-name",testNodeSet1, "0.0.1");
typeRegistry.init(s,null,events);
typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
"test-name":testNodeSet1
}});
var moduleList = typeRegistry.getModuleList();
moduleList.should.have.a.property("test-module");
typeRegistry.getNodeList().should.have.lengthOf(1);
@ -354,45 +359,48 @@ describe("red/nodes/registry/registry",function() {
it('returns node config', function() {
typeRegistry.init(settings,{
getNodeHelp: function(config) { return "HE"+config.name+"LP" }
});
typeRegistry.addNodeSet("test-module/test-name",{
id: "test-module/test-name",
module: "test-module",
name: "test-name",
enabled: true,
loaded: false,
config: "configA",
types: [ "test-a","test-b"]
}, "0.0.1");
typeRegistry.getNodeConfig("test-module/test-name").should.eql('configAHEtest-nameLP');
typeRegistry.getAllNodeConfigs().should.eql('configAHEtest-nameLP');
},events);
typeRegistry.addNodeSet("test-module/test-name-2",{
id: "test-module/test-name-2",
module: "test-module",
name: "test-name-2",
enabled: true,
loaded: false,
config: "configB",
types: [ "test-c","test-d"]
}, "0.0.1");
typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
"test-name":{
id: "test-module/test-name",
module: "test-module",
name: "test-name",
enabled: true,
loaded: false,
config: "configA",
types: [ "test-a","test-b"]
},
"test-name-2":{
id: "test-module/test-name-2",
module: "test-module",
name: "test-name-2",
enabled: true,
loaded: false,
config: "configB",
types: [ "test-c","test-d"]
}
}});
typeRegistry.getNodeConfig("test-module/test-name").should.eql('configAHEtest-nameLP');
typeRegistry.getNodeConfig("test-module/test-name-2").should.eql('configBHEtest-name-2LP');
typeRegistry.getAllNodeConfigs().should.eql('configAHEtest-nameLPconfigBHEtest-name-2LP');
});
});
describe('#getModuleInfo', function() {
it('returns module info', function() {
typeRegistry.init(settings,{});
typeRegistry.addNodeSet("test-module/test-name",{
id: "test-module/test-name",
module: "test-module",
name: "test-name",
enabled: true,
loaded: false,
config: "configA",
types: [ "test-a","test-b"],
file: "abc"
}, "0.0.1");
typeRegistry.init(settings,{},events);
typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
"test-name":{
id: "test-module/test-name",
module: "test-module",
name: "test-name",
enabled: true,
loaded: false,
config: "configA",
types: [ "test-a","test-b"],
file: "abc"
}
}});
var moduleInfo = typeRegistry.getModuleInfo("test-module");
moduleInfo.should.have.a.property('name','test-module');
moduleInfo.should.have.a.property('version','0.0.1');
@ -404,17 +412,19 @@ describe("red/nodes/registry/registry",function() {
});
describe('#getNodeInfo', function() {
it('returns node info', function() {
typeRegistry.init(settings,{});
typeRegistry.addNodeSet("test-module/test-name",{
id: "test-module/test-name",
module: "test-module",
name: "test-name",
enabled: true,
loaded: false,
config: "configA",
types: [ "test-a","test-b"],
file: "abc"
}, "0.0.1");
typeRegistry.init(settings,{},events);
typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
"test-name":{
id: "test-module/test-name",
module: "test-module",
name: "test-name",
enabled: true,
loaded: false,
config: "configA",
types: [ "test-a","test-b"],
file: "abc"
}
}});
var nodeSetInfo = typeRegistry.getNodeInfo("test-module/test-name");
nodeSetInfo.should.have.a.property('id',"test-module/test-name");
nodeSetInfo.should.not.have.a.property('config');
@ -423,18 +433,20 @@ describe("red/nodes/registry/registry",function() {
});
describe('#getFullNodeInfo', function() {
it('returns node info', function() {
typeRegistry.init(settings,{});
typeRegistry.addNodeSet("test-module/test-name",{
id: "test-module/test-name",
module: "test-module",
name: "test-name",
enabled: true,
loaded: false,
config: "configA",
types: [ "test-a","test-b"],
file: "abc"
typeRegistry.init(settings,{},events);
typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
"test-name":{
id: "test-module/test-name",
module: "test-module",
name: "test-name",
enabled: true,
loaded: false,
config: "configA",
types: [ "test-a","test-b"],
file: "abc"
}, "0.0.1");
}
}});
var nodeSetInfo = typeRegistry.getFullNodeInfo("test-module/test-name");
nodeSetInfo.should.have.a.property('id',"test-module/test-name");
nodeSetInfo.should.have.a.property('config');
@ -446,27 +458,29 @@ describe("red/nodes/registry/registry",function() {
});
describe('#getNodeList', function() {
it("returns a filtered list", function() {
typeRegistry.init(settings,{});
typeRegistry.addNodeSet("test-module/test-name",{
id: "test-module/test-name",
module: "test-module",
name: "test-name",
enabled: true,
loaded: false,
config: "configA",
types: [ "test-a","test-b"],
file: "abc"
}, "0.0.1");
typeRegistry.addNodeSet("test-module/test-name-2",{
id: "test-module/test-name-2",
module: "test-module",
name: "test-name-2",
enabled: true,
loaded: false,
config: "configB",
types: [ "test-c","test-d"],
file: "def"
}, "0.0.1");
typeRegistry.init(settings,{},events);
typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
"test-name":{
id: "test-module/test-name",
module: "test-module",
name: "test-name",
enabled: true,
loaded: false,
config: "configA",
types: [ "test-a","test-b"],
file: "abc"
},
"test-name-2":{
id: "test-module/test-name-2",
module: "test-module",
name: "test-name-2",
enabled: true,
loaded: false,
config: "configB",
types: [ "test-c","test-d"],
file: "def"
}
}});
var filterCallCount = 0;
var filteredList = typeRegistry.getNodeList(function(n) { filterCallCount++; return n.name === 'test-name-2';});
filterCallCount.should.eql(2);
@ -478,8 +492,7 @@ describe("red/nodes/registry/registry",function() {
describe('#registerNodeConstructor', function() {
var TestNodeConstructor;
beforeEach(function() {
TestNodeConstructor = function TestNodeConstructor() {
};
TestNodeConstructor = function TestNodeConstructor() {};
sinon.stub(events,'emit');
});
afterEach(function() {
@ -502,44 +515,36 @@ describe("red/nodes/registry/registry",function() {
}).should.throw("node-type already registered");
events.emit.calledOnce.should.be.true();
});
it('extends a constructor with the Node constructor', function() {
TestNodeConstructor.prototype.should.not.be.an.instanceOf(Node);
typeRegistry.registerNodeConstructor('node-set','node-type',TestNodeConstructor);
TestNodeConstructor.prototype.should.be.an.instanceOf(Node);
});
it('does not override a constructor\'s prototype', function() {
function Foo(){};
inherits(TestNodeConstructor,Foo);
TestNodeConstructor.prototype.should.be.an.instanceOf(Foo);
TestNodeConstructor.prototype.should.not.be.an.instanceOf(Node);
typeRegistry.registerNodeConstructor('node-set','node-type',TestNodeConstructor);
TestNodeConstructor.prototype.should.be.an.instanceOf(Node);
TestNodeConstructor.prototype.should.be.an.instanceOf(Foo);
typeRegistry.registerNodeConstructor('node-set','node-type2',TestNodeConstructor);
TestNodeConstructor.prototype.should.be.an.instanceOf(Node);
TestNodeConstructor.prototype.should.be.an.instanceOf(Foo);
});
});
describe('#getNodeIconPath', function() {
it('returns the default icon when getting an unknown icon', function() {
var defaultIcon = path.resolve(__dirname+'/../../../../../public/icons/arrow-in.png');
var defaultIcon = path.resolve(__dirname+'/../../../public/icons/arrow-in.png');
var iconPath = typeRegistry.getNodeIconPath('random-module','youwonthaveme.png');
iconPath.should.eql(defaultIcon);
});
it('returns a registered icon' , function() {
var testIcon = path.resolve(__dirname+'/../../../../resources/icons/test_icon.png');
events.emit("node-icon-dir",{name:"test-module", path: path.resolve(__dirname+'/../../../../resources/icons'), icons:[]});
var testIcon = path.resolve(__dirname+'/resources/userDir/lib/icons/');
typeRegistry.init(settings,{},events);
typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
"test-name":{
id: "test-module/test-name",
module: "test-module",
name: "test-name",
enabled: true,
loaded: false,
config: "configA",
types: [ "test-a","test-b"],
file: "abc"
}
},icons: [{path:testIcon,icons:['test_icon.png']}]});
var iconPath = typeRegistry.getNodeIconPath('test-module','test_icon.png');
iconPath.should.eql(testIcon);
iconPath.should.eql(testIcon+"/test_icon.png");
});
it('returns the debug icon when getting an unknown module', function() {
var debugIcon = path.resolve(__dirname+'/../../../../../public/icons/debug.png');
var debugIcon = path.resolve(__dirname+'/../../../public/icons/debug.png');
var iconPath = typeRegistry.getNodeIconPath('unknown-module', 'debug.png');
iconPath.should.eql(debugIcon);
});
@ -552,16 +557,22 @@ describe("red/nodes/registry/registry",function() {
});
it('returns an icon list of registered node module', function() {
typeRegistry.addNodeSet("test-module/test-name",testNodeSet1,"0.0.1");
events.emit("node-icon-dir",{name:"test-module", path:"",icons:["test_icon1.png"]});
var testIcon = path.resolve(__dirname+'/resources/userDir/lib/icons/');
typeRegistry.init(settings,{},events);
typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
"test-name":{
id: "test-module/test-name",
module: "test-module",
name: "test-name",
enabled: true,
loaded: false,
config: "configA",
types: [ "test-a","test-b"],
file: "abc"
}
},icons: [{path:testIcon,icons:['test_icon.png']}]});
var iconList = typeRegistry.getNodeIcons();
iconList.should.eql({"test-module":["test_icon1.png"]});
});
it('returns an icon list of unregistered node module', function() {
events.emit("node-icon-dir",{name:"test-module", path:"", icons:["test_icon1.png", "test_icon2.png"]});
var iconList = typeRegistry.getNodeIcons();
iconList.should.eql({"test-module":["test_icon1.png","test_icon2.png"]});
iconList.should.eql({"test-module":["test_icon.png"]});
});
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 393 B

View File

Before

Width:  |  Height:  |  Size: 163 B

After

Width:  |  Height:  |  Size: 163 B

View File

@ -24,7 +24,7 @@ var flowUtils = require("../../../../../red/runtime/nodes/flows/util");
var Flow = require("../../../../../red/runtime/nodes/flows/Flow");
var flows = require("../../../../../red/runtime/nodes/flows");
var Node = require("../../../../../red/runtime/nodes/Node");
var typeRegistry = require("../../../../../red/runtime/nodes/registry");
var typeRegistry = require("../../../../../red/runtime-registry");
describe('Flow', function() {

View File

@ -23,7 +23,7 @@ var RedNode = require("../../../../../red/runtime/nodes/Node");
var RED = require("../../../../../red/runtime/nodes");
var events = require("../../../../../red/runtime/events");
var credentials = require("../../../../../red/runtime/nodes/credentials");
var typeRegistry = require("../../../../../red/runtime/nodes/registry");
var typeRegistry = require("../../../../../red/runtime-registry");
var Flow = require("../../../../../red/runtime/nodes/flows/Flow");
describe('flows/index', function() {

View File

@ -19,7 +19,7 @@ var sinon = require("sinon");
var when = require("when");
var clone = require("clone");
var flowUtil = require("../../../../../red/runtime/nodes/flows/util");
var typeRegistry = require("../../../../../red/runtime/nodes/registry");
var typeRegistry = require("../../../../../red/runtime-registry");
var redUtil = require("../../../../../red/runtime/util");
describe('flows/util', function() {

View File

@ -19,9 +19,12 @@ var fs = require('fs-extra');
var path = require('path');
var when = require("when");
var sinon = require('sinon');
var inherits = require("util").inherits;
var index = require("../../../../red/runtime/nodes/index");
var flows = require("../../../../red/runtime/nodes/flows");
var registry = require("../../../../red/runtime/nodes/registry");
var registry = require("../../../../red/runtime-registry");
var Node = require("../../../../red/runtime/nodes/Node");
describe("red/nodes/index", function() {
before(function() {
@ -122,7 +125,45 @@ describe("red/nodes/index", function() {
registry.registerType.firstCall.args[2].should.eql(TestNode);
});
});
describe("extends constructor with Node constructor", function() {
var TestNodeConstructor;
before(function() {
sinon.stub(registry,"registerType");
});
after(function() {
registry.registerType.restore();
});
beforeEach(function() {
TestNodeConstructor = function TestNodeConstructor() {};
var runtime = {
settings: settings,
storage: storage,
log: {debug:function() {}, warn:sinon.spy()},
events: new EventEmitter()
}
index.init(runtime);
})
it('extends a constructor with the Node constructor', function() {
TestNodeConstructor.prototype.should.not.be.an.instanceOf(Node);
index.registerType('node-set','node-type',TestNodeConstructor);
TestNodeConstructor.prototype.should.be.an.instanceOf(Node);
});
it('does not override a constructor prototype', function() {
function Foo(){};
inherits(TestNodeConstructor,Foo);
TestNodeConstructor.prototype.should.be.an.instanceOf(Foo);
TestNodeConstructor.prototype.should.not.be.an.instanceOf(Node);
index.registerType('node-set','node-type',TestNodeConstructor);
TestNodeConstructor.prototype.should.be.an.instanceOf(Node);
TestNodeConstructor.prototype.should.be.an.instanceOf(Foo);
index.registerType('node-set','node-type2',TestNodeConstructor);
TestNodeConstructor.prototype.should.be.an.instanceOf(Node);
TestNodeConstructor.prototype.should.be.an.instanceOf(Foo);
});
});
describe("register credentials definition", function() {
var http = require('http');
var express = require('express');
@ -294,7 +335,6 @@ describe("red/nodes/index", function() {
});
describe('allows modules to be removed from the registry', function() {
var registry = require("../../../../red/runtime/nodes/registry");
var randomNodeInfo = {id:"5678",types:["random"]};
var randomModuleInfo = {
name:"random",

View File

@ -1,3 +0,0 @@
This file exists just to ensure the 'icons' directory is in the repository.
TODO: a future test needs to ensure the right icon files are loaded - this
directory can be used for that

View File

@ -1 +0,0 @@
This file exists just to ensure the parent directory is in the repository.

View File

@ -1,5 +0,0 @@
<script type="text/x-red" data-template-name="test-node-mod-1"></script>
<script type="text/x-red" data-help-name="test-node-mod-1"></script>
<script type="text/javascript">RED.nodes.registerType('test-node-mod-1',{});</script>
<style></style>
<p>this should be filtered out</p>

View File

@ -1,5 +0,0 @@
// A test node that exports a function
module.exports = function(RED) {
function TestNode(n) {}
RED.nodes.registerType("test-node-mod-1",TestNode);
}

View File

@ -1,5 +0,0 @@
<script type="text/x-red" data-template-name="test-node-mod-2"></script>
<script type="text/x-red" data-help-name="test-node-mod-2"></script>
<script type="text/javascript">RED.nodes.registerType('test-node-mod-2',{});</script>
<style></style>
<p>this should be filtered out</p>

View File

@ -1,4 +0,0 @@
// A test node that exports a function
module.exports = function(RED) {
throw new Error("fail to load");
}

View File

@ -1,3 +0,0 @@
This file exists just to ensure the 'icons' directory is in the repository.
TODO: a future test needs to ensure the right icon files are loaded - this
directory can be used for that

View File

@ -1,11 +0,0 @@
{
"name" : "TestNodeModule",
"version" : "0.0.1",
"description" : "A test node module",
"node-red" : {
"nodes": {
"TestNodeMod1": "TestNodeModule.js",
"TestNodeMod2": "TestNodeModule2.js"
}
}
}

View File

@ -1,5 +0,0 @@
<script type="text/x-red" data-template-name="test-node-mod-1"></script>
<script type="text/x-red" data-help-name="test-node-mod-1"></script>
<script type="text/javascript">RED.nodes.registerType('test-node-mod-1',{});</script>
<style></style>
<p>this should be filtered out</p>

View File

@ -1,5 +0,0 @@
// A test node that exports a function
module.exports = function(RED) {
function TestNode(n) {}
RED.nodes.registerType("test-node-mod-1",TestNode);
}

View File

@ -1,5 +0,0 @@
<script type="text/x-red" data-template-name="test-node-mod-2"></script>
<script type="text/x-red" data-help-name="test-node-mod-2"></script>
<script type="text/javascript">RED.nodes.registerType('test-node-mod-2',{});</script>
<style></style>
<p>this should be filtered out</p>

View File

@ -1,4 +0,0 @@
// A test node that exports a function
module.exports = function(RED) {
throw new Error("fail to load");
}

View File

@ -1,3 +0,0 @@
This file exists just to ensure the 'icons' directory is in the repository.
TODO: a future test needs to ensure the right icon files are loaded - this
directory can be used for that

View File

@ -1,12 +0,0 @@
{
"name" : "VersionMismatchModule",
"version" : "0.0.1",
"description" : "A test node module",
"node-red" : {
"version": "100.0.0",
"nodes": {
"VersionMismatchMod1": "TestNodeModule.js",
"VersionMismatchMod2": "TestNodeModule2.js"
}
}
}