1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

Add registry test for node module loading

This commit is contained in:
Nick O'Leary 2014-08-03 21:17:24 +01:00
parent 1697aee9f6
commit f7f58a2347
6 changed files with 101 additions and 17 deletions

View File

@ -219,7 +219,8 @@ function loadNodesFromModule(moduleDir,pkg) {
var iconDirs = []; var iconDirs = [];
for (var n in nodes) { for (var n in nodes) {
if (nodes.hasOwnProperty(n)) { if (nodes.hasOwnProperty(n)) {
results.push(loadNodeConfig(path.join(moduleDir,nodes[n]),pkg.name+":"+n)); var file = path.join(moduleDir,nodes[n]);
results.push(loadNodeConfig(file,pkg.name+":"+n));
var iconDir = path.join(moduleDir,path.dirname(nodes[n]),"icons"); var iconDir = path.join(moduleDir,path.dirname(nodes[n]),"icons");
if (iconDirs.indexOf(iconDir) == -1) { if (iconDirs.indexOf(iconDir) == -1) {
if (fs.existsSync(iconDir)) { if (fs.existsSync(iconDir)) {
@ -302,7 +303,7 @@ function loadNodeConfig(file,name) {
* location of nodeFiles - used by the tests * location of nodeFiles - used by the tests
* @return a promise that resolves on completion of loading * @return a promise that resolves on completion of loading
*/ */
function load(defaultNodesDir) { function load(defaultNodesDir,disableNodePathScan) {
return when.promise(function(resolve,reject) { return when.promise(function(resolve,reject) {
// Find all of the nodes to load // Find all of the nodes to load
var nodeFiles; var nodeFiles;
@ -330,7 +331,7 @@ function load(defaultNodesDir) {
// This indicates a test is being run - don't want to pick up // This indicates a test is being run - don't want to pick up
// unexpected nodes. // unexpected nodes.
// Urgh. // Urgh.
if (!defaultNodesDir) { if (!disableNodePathScan) {
// Find all of the modules containing nodes // Find all of the modules containing nodes
var moduleFiles = scanTreeForNodesModules(); var moduleFiles = scanTreeForNodesModules();
moduleFiles.forEach(function(moduleFile) { moduleFiles.forEach(function(moduleFile) {

View File

@ -39,7 +39,7 @@ describe('NodeRegistry', function() {
it('handles nodes that export a function', function(done) { it('handles nodes that export a function', function(done) {
typeRegistry.init({}); typeRegistry.init({});
typeRegistry.load(__dirname+"/resources/TestNode1").then(function() { typeRegistry.load(__dirname+"/resources/TestNode1",true).then(function() {
var list = typeRegistry.getNodeList(); var list = typeRegistry.getNodeList();
list.should.be.an.Array.and.have.lengthOf(1); list.should.be.an.Array.and.have.lengthOf(1);
list[0].should.have.property("id"); list[0].should.have.property("id");
@ -61,7 +61,7 @@ describe('NodeRegistry', function() {
it('handles nodes that export a function returning a resolving promise', function(done) { it('handles nodes that export a function returning a resolving promise', function(done) {
typeRegistry.init({}); typeRegistry.init({});
typeRegistry.load(__dirname+"/resources/TestNode2").then(function() { typeRegistry.load(__dirname+"/resources/TestNode2",true).then(function() {
var list = typeRegistry.getNodeList(); var list = typeRegistry.getNodeList();
list.should.be.an.Array.and.have.lengthOf(1); list.should.be.an.Array.and.have.lengthOf(1);
list[0].should.have.property("id"); list[0].should.have.property("id");
@ -81,7 +81,7 @@ describe('NodeRegistry', function() {
it('handles nodes that export a function returning a rejecting promise', function(done) { it('handles nodes that export a function returning a rejecting promise', function(done) {
typeRegistry.init({}); typeRegistry.init({});
typeRegistry.load(__dirname+"/resources/TestNode3").then(function() { typeRegistry.load(__dirname+"/resources/TestNode3",true).then(function() {
var list = typeRegistry.getNodeList(); var list = typeRegistry.getNodeList();
list.should.be.an.Array.and.have.lengthOf(1); list.should.be.an.Array.and.have.lengthOf(1);
list[0].should.have.property("id"); list[0].should.have.property("id");
@ -103,7 +103,7 @@ describe('NodeRegistry', function() {
it('handles files containing multiple nodes', function(done) { it('handles files containing multiple nodes', function(done) {
typeRegistry.init({}); typeRegistry.init({});
typeRegistry.load(__dirname+"/resources/MultipleNodes1").then(function() { typeRegistry.load(__dirname+"/resources/MultipleNodes1",true).then(function() {
var list = typeRegistry.getNodeList(); var list = typeRegistry.getNodeList();
list.should.be.an.Array.and.have.lengthOf(1); list.should.be.an.Array.and.have.lengthOf(1);
list[0].should.have.property("id"); list[0].should.have.property("id");
@ -126,7 +126,7 @@ describe('NodeRegistry', function() {
it('handles nested directories', function(done) { it('handles nested directories', function(done) {
typeRegistry.init({}); typeRegistry.init({});
typeRegistry.load(__dirname+"/resources/NestedDirectoryNode").then(function() { typeRegistry.load(__dirname+"/resources/NestedDirectoryNode",true).then(function() {
var list = typeRegistry.getNodeList(); var list = typeRegistry.getNodeList();
list.should.be.an.Array.and.have.lengthOf(1); list.should.be.an.Array.and.have.lengthOf(1);
list[0].should.have.property("id"); list[0].should.have.property("id");
@ -143,7 +143,7 @@ describe('NodeRegistry', function() {
it('emits type-registered and node-icon-dir events', function(done) { it('emits type-registered and node-icon-dir events', function(done) {
var eventEmitSpy = sinon.spy(events,"emit"); var eventEmitSpy = sinon.spy(events,"emit");
typeRegistry.init({}); typeRegistry.init({});
typeRegistry.load(__dirname+"/resources/NestedDirectoryNode").then(function() { typeRegistry.load(__dirname+"/resources/NestedDirectoryNode",true).then(function() {
var list = typeRegistry.getNodeList(); var list = typeRegistry.getNodeList();
list.should.be.an.Array.and.have.lengthOf(1); list.should.be.an.Array.and.have.lengthOf(1);
list[0].should.have.property("name","NestedNode.js"); list[0].should.have.property("name","NestedNode.js");
@ -171,7 +171,7 @@ describe('NodeRegistry', function() {
typeRegistry.init({ typeRegistry.init({
nodesDir:[__dirname+"/resources/TestNode1",__dirname+"/resources/DuplicateTestNode"] nodesDir:[__dirname+"/resources/TestNode1",__dirname+"/resources/DuplicateTestNode"]
}); });
typeRegistry.load("wontexist").then(function() { typeRegistry.load("wontexist",true).then(function() {
var list = typeRegistry.getNodeList(); var list = typeRegistry.getNodeList();
list.should.be.an.Array.and.have.lengthOf(2); list.should.be.an.Array.and.have.lengthOf(2);
@ -206,7 +206,7 @@ describe('NodeRegistry', function() {
} }
typeRegistry.init(settings); typeRegistry.init(settings);
typeRegistry.load("wontexist").then(function(){ typeRegistry.load("wontexist",true).then(function(){
var list = typeRegistry.getNodeList(); var list = typeRegistry.getNodeList();
list.should.be.an.Array.and.have.lengthOf(1); list.should.be.an.Array.and.have.lengthOf(1);
list[0].should.have.property("types",["test-node-1"]); list[0].should.have.property("types",["test-node-1"]);
@ -223,7 +223,7 @@ describe('NodeRegistry', function() {
} }
typeRegistry.init(settings); typeRegistry.init(settings);
typeRegistry.load("wontexist").then(function(){ typeRegistry.load("wontexist",true).then(function(){
var list = typeRegistry.getNodeList(); var list = typeRegistry.getNodeList();
list.should.be.an.Array.and.be.empty; list.should.be.an.Array.and.be.empty;
done(); done();
@ -234,7 +234,7 @@ describe('NodeRegistry', function() {
it('returns nothing for an unregistered type config', function() { it('returns nothing for an unregistered type config', function() {
typeRegistry.init({}); typeRegistry.init({});
typeRegistry.load("wontexist").then(function(){ typeRegistry.load("wontexist",true).then(function(){
var config = typeRegistry.getNodeConfig("imaginary-shark"); var config = typeRegistry.getNodeConfig("imaginary-shark");
(config === null).should.be.true; (config === null).should.be.true;
}).catch(function(e) { }).catch(function(e) {
@ -247,7 +247,7 @@ describe('NodeRegistry', function() {
nodesExcludes: [ "TestNode1.js" ], nodesExcludes: [ "TestNode1.js" ],
nodesDir:[__dirname+"/resources/TestNode1",__dirname+"/resources/TestNode2"] nodesDir:[__dirname+"/resources/TestNode1",__dirname+"/resources/TestNode2"]
}); });
typeRegistry.load("wontexist").then(function() { typeRegistry.load("wontexist",true).then(function() {
var list = typeRegistry.getNodeList(); var list = typeRegistry.getNodeList();
list.should.be.an.Array.and.have.lengthOf(1); list.should.be.an.Array.and.have.lengthOf(1);
list[0].should.have.property("types",["test-node-2"]); list[0].should.have.property("types",["test-node-2"]);
@ -261,7 +261,7 @@ describe('NodeRegistry', function() {
typeRegistry.init({ typeRegistry.init({
nodesDir:[__dirname+"/resources/TestNode1",__dirname+"/resources/TestNode2"] nodesDir:[__dirname+"/resources/TestNode1",__dirname+"/resources/TestNode2"]
}); });
typeRegistry.load("wontexist").then(function() { typeRegistry.load("wontexist",true).then(function() {
var list = typeRegistry.getNodeList(); var list = typeRegistry.getNodeList();
var nodeConfigs = typeRegistry.getNodeConfigs(); var nodeConfigs = typeRegistry.getNodeConfigs();
@ -280,7 +280,7 @@ describe('NodeRegistry', function() {
it('allows nodes to be added', function(done) { it('allows nodes to be added', function(done) {
typeRegistry.init({}); typeRegistry.init({});
typeRegistry.load("wontexist").then(function(){ typeRegistry.load("wontexist",true).then(function(){
var list = typeRegistry.getNodeList(); var list = typeRegistry.getNodeList();
list.should.be.an.Array.and.be.empty; list.should.be.an.Array.and.be.empty;
@ -306,7 +306,7 @@ describe('NodeRegistry', function() {
it('rejects adding duplicate nodes', function(done) { it('rejects adding duplicate nodes', function(done) {
typeRegistry.init({}); typeRegistry.init({});
typeRegistry.load(__dirname+"/resources/TestNode1").then(function(){ typeRegistry.load(__dirname+"/resources/TestNode1",true).then(function(){
var list = typeRegistry.getNodeList(); var list = typeRegistry.getNodeList();
list.should.be.an.Array.and.have.lengthOf(1); list.should.be.an.Array.and.have.lengthOf(1);
@ -323,4 +323,64 @@ describe('NodeRegistry', function() {
}); });
}); });
it('scans the node_modules path for node files', function(done) {
var fs = require("fs");
var path = require("path");
var eventEmitSpy = sinon.spy(events,"emit");
var pathJoin = (function() {
var _join = path.join;
return sinon.stub(path,"join",function() {
if (arguments.length == 3 && arguments[2] == "package.json") {
return _join(__dirname,"/resources/TestNodeModule/node_modules/",arguments[1],arguments[2]);
}
if (arguments.length == 2 && arguments[1] == "TestNodeModule") {
return _join(__dirname,"/resources/TestNodeModule/node_modules/",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(__dirname+"/resources/TestNodeModule/node_modules");
}
callCount++;
return result;
});
})();
typeRegistry.init({});
typeRegistry.load("wontexist",false).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","TestNodeModule:TestNodeMod1");
list[0].should.have.property("types",["test-node-mod-1"]);
list[0].should.have.property("enabled",true);
list[0].should.not.have.property("err");
eventEmitSpy.callCount.should.equal(2);
eventEmitSpy.firstCall.args[0].should.be.equal("node-icon-dir");
eventEmitSpy.firstCall.args[1].should.be.equal(__dirname+"/resources/TestNodeModule/node_modules/TestNodeModule/icons");
eventEmitSpy.secondCall.args[0].should.be.equal("type-registered");
eventEmitSpy.secondCall.args[1].should.be.equal("test-node-mod-1");
done();
}).catch(function(e) {
done(e);
}).finally(function() {
readdirSync.restore();
pathJoin.restore();
eventEmitSpy.restore();
});
});
}); });

View File

@ -0,0 +1,5 @@
<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

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

View File

@ -0,0 +1,3 @@
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

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