mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Remove known unused files
This commit is contained in:
@@ -1,30 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var should = require("should");
|
||||
|
||||
var NR_TEST_UTILS = require("nr-test-utils");
|
||||
|
||||
var deprecated = NR_TEST_UTILS.require("@node-red/registry/lib/deprecated.js");
|
||||
|
||||
describe('deprecated', function() {
|
||||
it('should return info on a node',function() {
|
||||
deprecated.get("irc in").should.eql({module:"node-red-node-irc"});
|
||||
});
|
||||
it('should return null for non-deprecated node',function() {
|
||||
should.not.exist(deprecated.get("foo"));
|
||||
});
|
||||
});
|
||||
@@ -1,371 +0,0 @@
|
||||
// init: init,
|
||||
// register: register,
|
||||
// registerSubflow: registerSubflow,
|
||||
// checkFlowDependencies: checkFlowDependencies,
|
||||
// require: requireModule
|
||||
//
|
||||
|
||||
const should = require("should");
|
||||
const sinon = require("sinon");
|
||||
const fs = require("fs-extra");
|
||||
const path = require("path");
|
||||
const os = require("os");
|
||||
|
||||
const NR_TEST_UTILS = require("nr-test-utils");
|
||||
const externalModules = NR_TEST_UTILS.require("@node-red/registry/lib/externalModules");
|
||||
const exec = NR_TEST_UTILS.require("@node-red/util/lib/exec");
|
||||
const hooks = NR_TEST_UTILS.require("@node-red/util/lib/hooks");
|
||||
|
||||
let homeDir;
|
||||
|
||||
async function createUserDir() {
|
||||
if (!homeDir) {
|
||||
homeDir = path.join(os.tmpdir(),"nr-test-"+Math.floor(Math.random()*100000));
|
||||
}
|
||||
await fs.ensureDir(homeDir);
|
||||
}
|
||||
|
||||
async function setupExternalModulesPackage(dependencies) {
|
||||
await fs.writeFile(path.join(homeDir,"package.json"),`{
|
||||
"name": "Node-RED-External-Modules",
|
||||
"description": "These modules are automatically installed by Node-RED to use in Function nodes.",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"dependencies": ${JSON.stringify(dependencies)}
|
||||
}`)
|
||||
}
|
||||
|
||||
describe("externalModules api", function() {
|
||||
beforeEach(async function() {
|
||||
await createUserDir()
|
||||
})
|
||||
afterEach(async function() {
|
||||
hooks.clear();
|
||||
await fs.remove(homeDir);
|
||||
})
|
||||
describe("checkFlowDependencies", function() {
|
||||
beforeEach(function() {
|
||||
sinon.stub(exec,"run").callsFake(async function(cmd, args, options) {
|
||||
let error;
|
||||
let moduleName = args[args.length-1];
|
||||
if (moduleName === "moduleNotFound") {
|
||||
error = new Error();
|
||||
error.stderr = "E404";
|
||||
} else if (moduleName === "moduleVersionNotFound") {
|
||||
error = new Error();
|
||||
error.stderr = "ETARGET";
|
||||
} else if (moduleName === "moduleFail") {
|
||||
error = new Error();
|
||||
error.stderr = "Some unexpected install error";
|
||||
}
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
})
|
||||
})
|
||||
afterEach(function() {
|
||||
exec.run.restore();
|
||||
})
|
||||
it("does nothing when no types are registered",async function() {
|
||||
externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
|
||||
await externalModules.checkFlowDependencies([
|
||||
{type: "function", libs:[{module: "foo"}]}
|
||||
])
|
||||
exec.run.called.should.be.false();
|
||||
});
|
||||
|
||||
it("skips install for modules already installed", async function() {
|
||||
externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
|
||||
externalModules.register("function", "libs");
|
||||
await setupExternalModulesPackage({"foo": "1.2.3", "bar":"2.3.4"});
|
||||
await externalModules.checkFlowDependencies([
|
||||
{type: "function", libs:[{module: "foo"}]}
|
||||
])
|
||||
exec.run.called.should.be.false();
|
||||
})
|
||||
|
||||
it("skips install for built-in modules", async function() {
|
||||
externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
|
||||
externalModules.register("function", "libs");
|
||||
await externalModules.checkFlowDependencies([
|
||||
{type: "function", libs:[{module: "fs"}]}
|
||||
])
|
||||
exec.run.called.should.be.false();
|
||||
})
|
||||
|
||||
it("installs missing modules", async function() {
|
||||
externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
|
||||
externalModules.register("function", "libs");
|
||||
await externalModules.checkFlowDependencies([
|
||||
{type: "function", libs:[{module: "foo"}]}
|
||||
])
|
||||
exec.run.called.should.be.true();
|
||||
})
|
||||
|
||||
|
||||
it("calls pre/postInstall hooks", async function() {
|
||||
externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
|
||||
externalModules.register("function", "libs");
|
||||
let receivedPreEvent,receivedPostEvent;
|
||||
hooks.add("preInstall", function(event) { event.args = ["a"]; receivedPreEvent = event; })
|
||||
hooks.add("postInstall", function(event) { receivedPostEvent = event; })
|
||||
|
||||
await externalModules.checkFlowDependencies([
|
||||
{type: "function", libs:[{module: "foo"}]}
|
||||
])
|
||||
exec.run.called.should.be.true();
|
||||
// exec.run.lastCall.args[1].should.eql([ 'install', 'a', 'foo' ]);
|
||||
receivedPreEvent.should.have.property("module","foo")
|
||||
receivedPreEvent.should.have.property("version")
|
||||
receivedPreEvent.should.have.property("dir")
|
||||
receivedPreEvent.should.eql(receivedPostEvent)
|
||||
})
|
||||
|
||||
it("skips npm install if preInstall returns false", async function() {
|
||||
externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
|
||||
externalModules.register("function", "libs");
|
||||
let receivedPreEvent,receivedPostEvent;
|
||||
hooks.add("preInstall", function(event) { receivedPreEvent = event; return false })
|
||||
hooks.add("postInstall", function(event) { receivedPostEvent = event; })
|
||||
|
||||
await externalModules.checkFlowDependencies([
|
||||
{type: "function", libs:[{module: "foo"}]}
|
||||
])
|
||||
exec.run.called.should.be.false();
|
||||
receivedPreEvent.should.have.property("module","foo")
|
||||
receivedPreEvent.should.have.property("version")
|
||||
receivedPreEvent.should.have.property("dir")
|
||||
receivedPreEvent.should.eql(receivedPostEvent)
|
||||
})
|
||||
|
||||
|
||||
it("installs missing modules from inside subflow module", async function() {
|
||||
externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
|
||||
externalModules.register("function", "libs");
|
||||
externalModules.registerSubflow("sf", {"flow":[{type: "function", libs:[{module: "foo"}]}]});
|
||||
await externalModules.checkFlowDependencies([
|
||||
{type: "sf"}
|
||||
])
|
||||
exec.run.called.should.be.true();
|
||||
})
|
||||
|
||||
it("reports install fail - 404", async function() {
|
||||
externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
|
||||
externalModules.register("function", "libs");
|
||||
try {
|
||||
await externalModules.checkFlowDependencies([
|
||||
{type: "function", libs:[{module: "moduleNotFound"}]}
|
||||
])
|
||||
throw new Error("checkFlowDependencies did not reject after install fail")
|
||||
} catch(err) {
|
||||
exec.run.called.should.be.true();
|
||||
Array.isArray(err).should.be.true();
|
||||
err.should.have.length(1);
|
||||
err[0].should.have.property("module");
|
||||
err[0].module.should.have.property("module","moduleNotFound");
|
||||
err[0].should.have.property("error");
|
||||
err[0].error.should.have.property("code",404);
|
||||
|
||||
}
|
||||
})
|
||||
it("reports install fail - target", async function() {
|
||||
externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
|
||||
externalModules.register("function", "libs");
|
||||
try {
|
||||
await externalModules.checkFlowDependencies([
|
||||
{type: "function", libs:[{module: "moduleVersionNotFound"}]}
|
||||
])
|
||||
throw new Error("checkFlowDependencies did not reject after install fail")
|
||||
} catch(err) {
|
||||
exec.run.called.should.be.true();
|
||||
Array.isArray(err).should.be.true();
|
||||
err.should.have.length(1);
|
||||
err[0].should.have.property("module");
|
||||
err[0].module.should.have.property("module","moduleVersionNotFound");
|
||||
err[0].should.have.property("error");
|
||||
err[0].error.should.have.property("code",404);
|
||||
}
|
||||
})
|
||||
|
||||
it("reports install fail - unexpected", async function() {
|
||||
externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
|
||||
externalModules.register("function", "libs");
|
||||
try {
|
||||
await externalModules.checkFlowDependencies([
|
||||
{type: "function", libs:[{module: "moduleFail"}]}
|
||||
])
|
||||
throw new Error("checkFlowDependencies did not reject after install fail")
|
||||
} catch(err) {
|
||||
exec.run.called.should.be.true();
|
||||
Array.isArray(err).should.be.true();
|
||||
err.should.have.length(1);
|
||||
err[0].should.have.property("module");
|
||||
err[0].module.should.have.property("module","moduleFail");
|
||||
err[0].should.have.property("error");
|
||||
err[0].error.should.have.property("code","unexpected_error");
|
||||
}
|
||||
})
|
||||
it("reports install fail - multiple", async function() {
|
||||
externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
|
||||
externalModules.register("function", "libs");
|
||||
try {
|
||||
await externalModules.checkFlowDependencies([
|
||||
{type: "function", libs:[{module: "moduleNotFound"},{module: "moduleFail"}]}
|
||||
])
|
||||
throw new Error("checkFlowDependencies did not reject after install fail")
|
||||
} catch(err) {
|
||||
exec.run.called.should.be.true();
|
||||
Array.isArray(err).should.be.true();
|
||||
err.should.have.length(2);
|
||||
// Sort the array so we know the order to test for
|
||||
err.sort(function(A,B) {
|
||||
return A.module.module.localeCompare(B.module.module);
|
||||
})
|
||||
err[1].should.have.property("module");
|
||||
err[1].module.should.have.property("module","moduleNotFound");
|
||||
err[1].should.have.property("error");
|
||||
err[1].error.should.have.property("code",404);
|
||||
err[0].should.have.property("module");
|
||||
err[0].module.should.have.property("module","moduleFail");
|
||||
err[0].should.have.property("error");
|
||||
err[0].error.should.have.property("code","unexpected_error");
|
||||
|
||||
}
|
||||
})
|
||||
it("reports install fail - install disabled", async function() {
|
||||
externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}, externalModules: {
|
||||
modules: {
|
||||
allowInstall: false
|
||||
}
|
||||
}});
|
||||
externalModules.register("function", "libs");
|
||||
try {
|
||||
await externalModules.checkFlowDependencies([
|
||||
{type: "function", libs:[{module: "foo"}]}
|
||||
])
|
||||
throw new Error("checkFlowDependencies did not reject after install fail")
|
||||
} catch(err) {
|
||||
// Should not try to install
|
||||
exec.run.called.should.be.false();
|
||||
Array.isArray(err).should.be.true();
|
||||
err.should.have.length(1);
|
||||
err[0].should.have.property("module");
|
||||
err[0].module.should.have.property("module","foo");
|
||||
err[0].should.have.property("error");
|
||||
err[0].error.should.have.property("code","install_not_allowed");
|
||||
}
|
||||
})
|
||||
|
||||
it("reports install fail - module disallowed", async function() {
|
||||
externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}, externalModules: {
|
||||
modules: {
|
||||
denyList: ['foo']
|
||||
}
|
||||
}});
|
||||
externalModules.register("function", "libs");
|
||||
try {
|
||||
await externalModules.checkFlowDependencies([
|
||||
// foo disallowed
|
||||
// bar allowed
|
||||
{type: "function", libs:[{module: "foo"},{module: "bar"}]}
|
||||
])
|
||||
throw new Error("checkFlowDependencies did not reject after install fail")
|
||||
} catch(err) {
|
||||
exec.run.calledOnce.should.be.true();
|
||||
Array.isArray(err).should.be.true();
|
||||
err.should.have.length(1);
|
||||
err[0].should.have.property("module");
|
||||
err[0].module.should.have.property("module","foo");
|
||||
err[0].should.have.property("error");
|
||||
err[0].error.should.have.property("code","install_not_allowed");
|
||||
}
|
||||
})
|
||||
|
||||
it("reports install fail - built-in module disallowed", async function() {
|
||||
externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}, externalModules: {
|
||||
modules: {
|
||||
denyList: ['fs']
|
||||
}
|
||||
}});
|
||||
externalModules.register("function", "libs");
|
||||
try {
|
||||
await externalModules.checkFlowDependencies([
|
||||
// foo disallowed
|
||||
// bar allowed
|
||||
{type: "function", libs:[{module: "fs"},{module: "bar"}]}
|
||||
])
|
||||
throw new Error("checkFlowDependencies did not reject after install fail")
|
||||
} catch(err) {
|
||||
exec.run.calledOnce.should.be.true();
|
||||
Array.isArray(err).should.be.true();
|
||||
err.should.have.length(1);
|
||||
err[0].should.have.property("module");
|
||||
err[0].module.should.have.property("module","fs");
|
||||
err[0].should.have.property("error");
|
||||
err[0].error.should.have.property("code","module_not_allowed");
|
||||
}
|
||||
})
|
||||
})
|
||||
describe("require", async function() {
|
||||
it("requires built-in modules", async function() {
|
||||
externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
|
||||
const result = externalModules.require("fs")
|
||||
result.should.eql(require("fs"));
|
||||
})
|
||||
it("rejects unknown modules", async function() {
|
||||
externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
|
||||
try {
|
||||
externalModules.require("foo")
|
||||
throw new Error("require did not reject after fail")
|
||||
} catch(err) {
|
||||
err.should.have.property("code","module_not_allowed");
|
||||
}
|
||||
})
|
||||
|
||||
it("rejects disallowed modules", async function() {
|
||||
externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}, externalModules: {
|
||||
modules: {
|
||||
denyList: ['fs']
|
||||
}
|
||||
}});
|
||||
try {
|
||||
externalModules.require("fs")
|
||||
throw new Error("require did not reject after fail")
|
||||
} catch(err) {
|
||||
err.should.have.property("code","module_not_allowed");
|
||||
}
|
||||
})
|
||||
})
|
||||
describe("import", async function() {
|
||||
it("import built-in modules", async function() {
|
||||
externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
|
||||
const result = await externalModules.import("fs")
|
||||
// `result` won't have the `should` property
|
||||
should.exist(result);
|
||||
should.exist(result.existsSync);
|
||||
})
|
||||
it("rejects unknown modules", async function() {
|
||||
externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
|
||||
try {
|
||||
await externalModules.import("foo")
|
||||
throw new Error("import did not reject after fail")
|
||||
} catch(err) {
|
||||
err.should.have.property("code","module_not_allowed");
|
||||
}
|
||||
})
|
||||
|
||||
it("rejects disallowed modules", async function() {
|
||||
externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}, externalModules: {
|
||||
modules: {
|
||||
denyList: ['fs']
|
||||
}
|
||||
}});
|
||||
try {
|
||||
await externalModules.import("fs")
|
||||
throw new Error("import did not reject after fail")
|
||||
} catch(err) {
|
||||
err.should.have.property("code","module_not_allowed");
|
||||
}
|
||||
})
|
||||
})
|
||||
});
|
||||
@@ -1,127 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var should = require("should");
|
||||
var sinon = require("sinon");
|
||||
var path = require("path");
|
||||
var fs = require("fs");
|
||||
|
||||
var NR_TEST_UTILS = require("nr-test-utils");
|
||||
|
||||
var registry = NR_TEST_UTILS.require("@node-red/registry");
|
||||
|
||||
var installer = NR_TEST_UTILS.require("@node-red/registry/lib/installer");
|
||||
var loader = NR_TEST_UTILS.require("@node-red/registry/lib/loader");
|
||||
var typeRegistry = NR_TEST_UTILS.require("@node-red/registry/lib/registry");
|
||||
|
||||
describe('red/registry/index', function() {
|
||||
var stubs = [];
|
||||
afterEach(function() {
|
||||
while(stubs.length) {
|
||||
stubs.pop().restore();
|
||||
}
|
||||
})
|
||||
describe('#init',function() {
|
||||
it('intialises components', function() {
|
||||
stubs.push(sinon.stub(installer,"init"));
|
||||
stubs.push(sinon.stub(loader,"init"));
|
||||
stubs.push(sinon.stub(typeRegistry,"init"));
|
||||
|
||||
registry.init({settings:{}});
|
||||
installer.init.called.should.be.true();
|
||||
loader.init.called.should.be.true();
|
||||
typeRegistry.init.called.should.be.true();
|
||||
})
|
||||
});
|
||||
|
||||
describe('#addModule', function() {
|
||||
it('loads the module and returns its info', function(done) {
|
||||
stubs.push(sinon.stub(loader,"addModule").callsFake(function(module) {
|
||||
return Promise.resolve();
|
||||
}));
|
||||
stubs.push(sinon.stub(typeRegistry,"getModuleInfo").callsFake(function(module) {
|
||||
return "info";
|
||||
}));
|
||||
registry.addModule("foo").then(function(info) {
|
||||
info.should.eql("info");
|
||||
done();
|
||||
}).catch(function(err) { done(err); });
|
||||
});
|
||||
it('rejects if loader rejects', function(done) {
|
||||
stubs.push(sinon.stub(loader,"addModule").callsFake(function(module) {
|
||||
return Promise.reject("error");
|
||||
}));
|
||||
stubs.push(sinon.stub(typeRegistry,"getModuleInfo").callsFake(function(module) {
|
||||
return "info";
|
||||
}));
|
||||
registry.addModule("foo").then(function(info) {
|
||||
done(new Error("unexpected resolve"));
|
||||
}).catch(function(err) {
|
||||
err.should.eql("error");
|
||||
done();
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('#enableNode',function() {
|
||||
it('enables a node set',function(done) {
|
||||
stubs.push(sinon.stub(typeRegistry,"enableNodeSet").callsFake(function() {
|
||||
return Promise.resolve();
|
||||
}));
|
||||
stubs.push(sinon.stub(typeRegistry,"getNodeInfo").callsFake(function() {
|
||||
return {id:"node-set",loaded:true};
|
||||
}));
|
||||
registry.enableNode("node-set").then(function(ns) {
|
||||
typeRegistry.enableNodeSet.called.should.be.true();
|
||||
ns.should.have.a.property('id','node-set');
|
||||
done();
|
||||
}).catch(function(err) { done(err); });
|
||||
});
|
||||
|
||||
it('rejects if node unknown',function() {
|
||||
stubs.push(sinon.stub(typeRegistry,"enableNodeSet").callsFake(function() {
|
||||
throw new Error('failure');
|
||||
}));
|
||||
/*jshint immed: false */
|
||||
(function(){
|
||||
registry.enableNode("node-set")
|
||||
}).should.throw();
|
||||
});
|
||||
|
||||
it('triggers a node load',function(done) {
|
||||
stubs.push(sinon.stub(typeRegistry,"enableNodeSet").callsFake(function() {
|
||||
return Promise.resolve();
|
||||
}));
|
||||
var calls = 0;
|
||||
stubs.push(sinon.stub(typeRegistry,"getNodeInfo").callsFake(function() {
|
||||
// loaded=false on first call, true on subsequent
|
||||
return {id:"node-set",loaded:(calls++>0)};
|
||||
}));
|
||||
stubs.push(sinon.stub(loader,"loadNodeSet").callsFake(function(){return Promise.resolve();}));
|
||||
stubs.push(sinon.stub(typeRegistry,"getFullNodeInfo"));
|
||||
|
||||
registry.enableNode("node-set").then(function(ns) {
|
||||
typeRegistry.enableNodeSet.called.should.be.true();
|
||||
loader.loadNodeSet.called.should.be.true();
|
||||
ns.should.have.a.property('id','node-set');
|
||||
ns.should.have.a.property('loaded',true);
|
||||
done();
|
||||
}).catch(function(err) { done(err); });
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,528 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var should = require("should");
|
||||
var sinon = require("sinon");
|
||||
var path = require("path");
|
||||
var fs = require('fs-extra');
|
||||
var EventEmitter = require('events');
|
||||
|
||||
var NR_TEST_UTILS = require("nr-test-utils");
|
||||
|
||||
var installer = NR_TEST_UTILS.require("@node-red/registry/lib/installer");
|
||||
var registry = NR_TEST_UTILS.require("@node-red/registry/lib/index");
|
||||
var typeRegistry = NR_TEST_UTILS.require("@node-red/registry/lib/registry");
|
||||
const { events, exec, log, hooks } = NR_TEST_UTILS.require("@node-red/util");
|
||||
|
||||
describe('nodes/registry/installer', function() {
|
||||
|
||||
var mockLog = {
|
||||
log: sinon.stub(),
|
||||
debug: sinon.stub(),
|
||||
trace: sinon.stub(),
|
||||
warn: sinon.stub(),
|
||||
info: sinon.stub(),
|
||||
metric: sinon.stub(),
|
||||
_: function(msg) { return msg }
|
||||
}
|
||||
|
||||
var execResponse;
|
||||
|
||||
beforeEach(function() {
|
||||
sinon.stub(exec,"run").callsFake(() => execResponse || Promise.resolve(""))
|
||||
installer.init({})
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
execResponse = null;
|
||||
if (registry.addModule.restore) {
|
||||
registry.addModule.restore();
|
||||
}
|
||||
if (registry.removeModule.restore) {
|
||||
registry.removeModule.restore();
|
||||
}
|
||||
if (typeRegistry.removeModule.restore) {
|
||||
typeRegistry.removeModule.restore();
|
||||
}
|
||||
if (registry.getModuleInfo.restore) {
|
||||
registry.getModuleInfo.restore();
|
||||
}
|
||||
if (typeRegistry.getModuleInfo.restore) {
|
||||
typeRegistry.getModuleInfo.restore();
|
||||
}
|
||||
if (typeRegistry.setModulePendingUpdated.restore) {
|
||||
typeRegistry.setModulePendingUpdated.restore();
|
||||
}
|
||||
if (fs.statSync.restore) {
|
||||
fs.statSync.restore();
|
||||
}
|
||||
exec.run.restore();
|
||||
hooks.clear();
|
||||
});
|
||||
|
||||
describe("installs module", function() {
|
||||
it("rejects module name that includes version", function(done) {
|
||||
installer.installModule("module@version",null,null).catch(function(err) {
|
||||
err.code.should.be.eql('invalid_module_name');
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
it("rejects missing module name", function(done) {
|
||||
installer.installModule("",null,null).catch(function(err) {
|
||||
err.code.should.be.eql('invalid_module_name');
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
it("rejects null module name", function(done) {
|
||||
installer.installModule(null,null,null).catch(function(err) {
|
||||
err.code.should.be.eql('invalid_module_name');
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
it("rejects invalid url", function(done) {
|
||||
installer.installModule("module",null,"abc").catch(function(err) {
|
||||
err.code.should.be.eql('invalid_module_url');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("rejects when npm returns a 404", function(done) {
|
||||
var res = {
|
||||
code: 1,
|
||||
stdout:"",
|
||||
stderr:" 404 this_wont_exist"
|
||||
}
|
||||
var p = Promise.reject(res);
|
||||
p.catch((err)=>{});
|
||||
execResponse = p;
|
||||
installer.installModule("this_wont_exist").catch(function(err) {
|
||||
err.should.have.property("code",404);
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
it("rejects when npm does not find specified version", function(done) {
|
||||
var res = {
|
||||
code: 1,
|
||||
stdout:"",
|
||||
stderr:" version not found: this_wont_exist@0.1.2"
|
||||
}
|
||||
var p = Promise.reject(res);
|
||||
p.catch((err)=>{});
|
||||
execResponse = p;
|
||||
sinon.stub(typeRegistry,"getModuleInfo").callsFake(function() {
|
||||
return {
|
||||
version: "0.1.1"
|
||||
}
|
||||
});
|
||||
installer.installModule("this_wont_exist","0.1.2").catch(function(err) {
|
||||
err.code.should.be.eql(404);
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
it("rejects when update requested to existing version", function(done) {
|
||||
sinon.stub(typeRegistry,"getModuleInfo").callsFake(function() {
|
||||
return {
|
||||
user: true,
|
||||
version: "0.1.1"
|
||||
}
|
||||
});
|
||||
installer.installModule("this_wont_exist","0.1.1").catch(function(err) {
|
||||
err.code.should.be.eql('module_already_loaded');
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
it("rejects when update requested to existing version and url", function(done) {
|
||||
sinon.stub(typeRegistry,"getModuleInfo").callsFake(function() {
|
||||
return {
|
||||
user: true,
|
||||
version: "0.1.1"
|
||||
}
|
||||
});
|
||||
installer.installModule("this_wont_exist","0.1.1","https://example/foo-0.1.1.tgz").catch(function(err) {
|
||||
err.code.should.be.eql('module_already_loaded');
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
it("rejects with generic error", function(done) {
|
||||
var res = {
|
||||
code: 1,
|
||||
stdout:"",
|
||||
stderr:" kaboom!"
|
||||
}
|
||||
var p = Promise.reject(res);
|
||||
p.catch((err)=>{});
|
||||
execResponse = p;
|
||||
installer.installModule("this_wont_exist").then(function() {
|
||||
done(new Error("Unexpected success"));
|
||||
}).catch(err => {
|
||||
// Expected result
|
||||
done()
|
||||
});
|
||||
});
|
||||
it("succeeds when module is found", function(done) {
|
||||
var nodeInfo = {nodes:{module:"foo",types:["a"]}};
|
||||
|
||||
var res = {
|
||||
code: 0,
|
||||
stdout:"",
|
||||
stderr:""
|
||||
}
|
||||
var p = Promise.resolve(res);
|
||||
p.catch((err)=>{});
|
||||
execResponse = p;
|
||||
|
||||
var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
|
||||
return Promise.resolve(nodeInfo);
|
||||
});
|
||||
|
||||
installer.installModule("this_wont_exist").then(function(info) {
|
||||
info.should.eql(nodeInfo);
|
||||
// commsMessages.should.have.length(1);
|
||||
// commsMessages[0].topic.should.equal("node/added");
|
||||
// commsMessages[0].msg.should.eql(nodeInfo.nodes);
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
it("rejects when non-existant path is provided", function(done) {
|
||||
this.timeout(20000);
|
||||
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) {
|
||||
if (err.hasOwnProperty("code")) {
|
||||
err.code.should.eql(404);
|
||||
done();
|
||||
}
|
||||
else {
|
||||
console.log("ERRROR::"+err.toString()+"::");
|
||||
err.toString().should.eql("Error: Install failed");
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
it("succeeds when path is valid node-red module", function(done) {
|
||||
var nodeInfo = {nodes:{module:"foo",types:["a"]}};
|
||||
var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
|
||||
return Promise.resolve(nodeInfo);
|
||||
});
|
||||
var resourcesDir = path.resolve(path.join(__dirname,"resources","local","TestNodeModule","node_modules","TestNodeModule"));
|
||||
|
||||
var res = {
|
||||
code: 0,
|
||||
stdout:"",
|
||||
stderr:""
|
||||
}
|
||||
var p = Promise.resolve(res);
|
||||
p.catch((err)=>{});
|
||||
execResponse = p;
|
||||
installer.installModule(resourcesDir).then(function(info) {
|
||||
info.should.eql(nodeInfo);
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
it("succeeds when url is valid node-red module", function(done) {
|
||||
var nodeInfo = {nodes:{module:"foo",types:["a"]}};
|
||||
|
||||
var res = {
|
||||
code: 0,
|
||||
stdout:"",
|
||||
stderr:""
|
||||
}
|
||||
var p = Promise.resolve(res);
|
||||
p.catch((err)=>{});
|
||||
execResponse = p;
|
||||
|
||||
var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
|
||||
return Promise.resolve(nodeInfo);
|
||||
});
|
||||
|
||||
installer.installModule("this_wont_exist",null,"https://example/foo-0.1.1.tgz").then(function(info) {
|
||||
info.should.eql(nodeInfo);
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it("triggers preInstall and postInstall hooks", function(done) {
|
||||
let receivedPreEvent,receivedPostEvent;
|
||||
hooks.add("preInstall", function(event) { event.args = ["a"]; receivedPreEvent = event; })
|
||||
hooks.add("postInstall", function(event) { receivedPostEvent = event; })
|
||||
var nodeInfo = {nodes:{module:"foo",types:["a"]}};
|
||||
var res = {code: 0,stdout:"",stderr:""}
|
||||
var p = Promise.resolve(res);
|
||||
p.catch((err)=>{});
|
||||
execResponse = p;
|
||||
|
||||
var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
|
||||
return Promise.resolve(nodeInfo);
|
||||
});
|
||||
|
||||
installer.installModule("this_wont_exist","1.2.3").then(function(info) {
|
||||
exec.run.called.should.be.true();
|
||||
exec.run.lastCall.args[1].should.eql([ 'install', 'a', 'this_wont_exist@1.2.3' ]);
|
||||
info.should.eql(nodeInfo);
|
||||
should.exist(receivedPreEvent)
|
||||
receivedPreEvent.should.have.property("module","this_wont_exist")
|
||||
receivedPreEvent.should.have.property("version","1.2.3")
|
||||
receivedPreEvent.should.have.property("dir")
|
||||
receivedPreEvent.should.have.property("url")
|
||||
receivedPreEvent.should.have.property("isExisting")
|
||||
receivedPreEvent.should.have.property("isUpgrade")
|
||||
receivedPreEvent.should.eql(receivedPostEvent)
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it("fails install if preInstall hook fails", function(done) {
|
||||
let receivedEvent;
|
||||
hooks.add("preInstall", function(event) { throw new Error("preInstall-error"); })
|
||||
var nodeInfo = {nodes:{module:"foo",types:["a"]}};
|
||||
|
||||
installer.installModule("this_wont_exist","1.2.3").catch(function(err) {
|
||||
exec.run.called.should.be.false();
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it("skips invoking npm if preInstall returns false", function(done) {
|
||||
let receivedEvent;
|
||||
hooks.add("preInstall", function(event) { return false })
|
||||
hooks.add("postInstall", function(event) { receivedEvent = event; })
|
||||
var nodeInfo = {nodes:{module:"foo",types:["a"]}};
|
||||
var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
|
||||
return Promise.resolve(nodeInfo);
|
||||
});
|
||||
|
||||
installer.installModule("this_wont_exist","1.2.3").then(function() {
|
||||
exec.run.called.should.be.false();
|
||||
should.exist(receivedEvent);
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it("rollsback install if postInstall hook fails", function(done) {
|
||||
hooks.add("postInstall", function(event) { throw new Error("fail"); })
|
||||
installer.installModule("this_wont_exist","1.2.3").catch(function(err) {
|
||||
exec.run.calledTwice.should.be.true();
|
||||
exec.run.firstCall.args[1].includes("install").should.be.true();
|
||||
exec.run.secondCall.args[1].includes("remove").should.be.true();
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
describe("allowUpdate lists", function() {
|
||||
it("rejects when update requested with allowUpdate set to false", function(done) {
|
||||
installer.init({ externalModules: { palette: { allowUpdate: false } } })
|
||||
sinon.stub(typeRegistry,"getModuleInfo").callsFake(function() {
|
||||
return {
|
||||
user: true,
|
||||
version: "0.1.1"
|
||||
}
|
||||
});
|
||||
installer.installModule("this_wont_exist","0.1.2").catch(function(err) {
|
||||
err.code.should.be.eql('update_not_allowed');
|
||||
done();
|
||||
}).catch(done);
|
||||
})
|
||||
it("succeeds when update requested with module not on denyUpdateList", function(done) {
|
||||
installer.init({ externalModules: { palette: { denyUpdateList: ['this_wont_exist'] } } })
|
||||
sinon.stub(typeRegistry,"getModuleInfo").callsFake(function() {
|
||||
return {
|
||||
user: true,
|
||||
version: "0.1.1"
|
||||
}
|
||||
});
|
||||
|
||||
var res = {
|
||||
code: 0,
|
||||
stdout:"",
|
||||
stderr:""
|
||||
}
|
||||
var p = Promise.resolve(res);
|
||||
p.catch((err)=>{});
|
||||
execResponse = p;
|
||||
|
||||
var nodeInfo = {nodes:{module:"this_is_allowed",types:["a"]}};
|
||||
|
||||
var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
|
||||
return Promise.resolve(nodeInfo);
|
||||
});
|
||||
sinon.stub(typeRegistry,"setModulePendingUpdated").callsFake(function() {
|
||||
return Promise.resolve(nodeInfo);
|
||||
});
|
||||
|
||||
installer.installModule("this_is_allowed","0.1.2").then(function() {
|
||||
done();
|
||||
}).catch(done);
|
||||
})
|
||||
it("rejects when update requested with module on denyUpdateList", function(done) {
|
||||
installer.init({ externalModules: { palette: { denyUpdateList: ['this_wont_exist'] } } })
|
||||
sinon.stub(typeRegistry,"getModuleInfo").callsFake(function() {
|
||||
return {
|
||||
user: true,
|
||||
version: "0.1.1"
|
||||
}
|
||||
});
|
||||
|
||||
var res = {
|
||||
code: 0,
|
||||
stdout:"",
|
||||
stderr:""
|
||||
}
|
||||
var p = Promise.resolve(res);
|
||||
p.catch((err)=>{});
|
||||
execResponse = p;
|
||||
|
||||
var nodeInfo = {nodes:{module:"this_is_allowed",types:["a"]}};
|
||||
|
||||
var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
|
||||
return Promise.resolve(nodeInfo);
|
||||
});
|
||||
sinon.stub(typeRegistry,"setModulePendingUpdated").callsFake(function() {
|
||||
return Promise.resolve(nodeInfo);
|
||||
});
|
||||
|
||||
installer.installModule("this_wont_exist","0.1.2").catch(function(err) {
|
||||
err.code.should.be.eql('update_not_allowed');
|
||||
done();
|
||||
}).catch(done);
|
||||
})
|
||||
it("succeeds when update requested with module on allowUpdateList", function(done) {
|
||||
installer.init({ externalModules: { palette: { allowUpdateList: ['this_is_allowed'] } } })
|
||||
sinon.stub(typeRegistry,"getModuleInfo").callsFake(function() {
|
||||
return {
|
||||
user: true,
|
||||
version: "0.1.1"
|
||||
}
|
||||
});
|
||||
|
||||
var res = {
|
||||
code: 0,
|
||||
stdout:"",
|
||||
stderr:""
|
||||
}
|
||||
var p = Promise.resolve(res);
|
||||
p.catch((err)=>{});
|
||||
execResponse = p;
|
||||
|
||||
var nodeInfo = {nodes:{module:"this_is_allowed",types:["a"]}};
|
||||
|
||||
var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
|
||||
return Promise.resolve(nodeInfo);
|
||||
});
|
||||
sinon.stub(typeRegistry,"setModulePendingUpdated").callsFake(function() {
|
||||
return Promise.resolve(nodeInfo);
|
||||
});
|
||||
|
||||
installer.installModule("this_is_allowed","0.1.2").then(function() {
|
||||
done();
|
||||
}).catch(done);
|
||||
})
|
||||
it("rejects when update requested with module not on allowUpdateList", function(done) {
|
||||
installer.init({ externalModules: { palette: { allowUpdateList: ['this_is_allowed'] } } })
|
||||
sinon.stub(typeRegistry,"getModuleInfo").callsFake(function() {
|
||||
return {
|
||||
user: true,
|
||||
version: "0.1.1"
|
||||
}
|
||||
});
|
||||
|
||||
var res = {
|
||||
code: 0,
|
||||
stdout:"",
|
||||
stderr:""
|
||||
}
|
||||
var p = Promise.resolve(res);
|
||||
p.catch((err)=>{});
|
||||
execResponse = p;
|
||||
|
||||
var nodeInfo = {nodes:{module:"this_wont_exist",types:["a"]}};
|
||||
|
||||
var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
|
||||
return Promise.resolve(nodeInfo);
|
||||
});
|
||||
sinon.stub(typeRegistry,"setModulePendingUpdated").callsFake(function() {
|
||||
return Promise.resolve(nodeInfo);
|
||||
});
|
||||
|
||||
installer.installModule("this_wont_exist","0.1.2").catch(function(err) {
|
||||
err.code.should.be.eql('update_not_allowed');
|
||||
done();
|
||||
}).catch(done);
|
||||
})
|
||||
});
|
||||
});
|
||||
describe("uninstalls module", function() {
|
||||
it("rejects invalid module names", function(done) {
|
||||
var promises = [];
|
||||
var rejectedCount = 0;
|
||||
|
||||
promises.push(installer.uninstallModule("this_wont_exist ").catch(() => {rejectedCount++}));
|
||||
promises.push(installer.uninstallModule("this_wont_exist;no_it_really_wont").catch(() => {rejectedCount++}));
|
||||
Promise.all(promises).then(function() {
|
||||
rejectedCount.should.eql(2);
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it("rejects with generic error", function(done) {
|
||||
var nodeInfo = [{module:"foo",types:["a"]}];
|
||||
var removeModule = sinon.stub(registry,"removeModule").callsFake(function(md) {
|
||||
return Promise.resolve(nodeInfo);
|
||||
});
|
||||
var res = {
|
||||
code: 1,
|
||||
stdout:"",
|
||||
stderr:"error"
|
||||
}
|
||||
var p = Promise.reject(res);
|
||||
p.catch((err)=>{});
|
||||
execResponse = p;
|
||||
|
||||
installer.uninstallModule("this_wont_exist").then(function() {
|
||||
done(new Error("Unexpected success"));
|
||||
}).catch(err => {
|
||||
// Expected result
|
||||
done()
|
||||
});
|
||||
});
|
||||
it("succeeds when module is found", function(done) {
|
||||
var nodeInfo = [{module:"foo",types:["a"]}];
|
||||
var removeModule = sinon.stub(typeRegistry,"removeModule").callsFake(function(md) {
|
||||
return nodeInfo;
|
||||
});
|
||||
var getModuleInfo = sinon.stub(registry,"getModuleInfo").callsFake(function(md) {
|
||||
return {nodes:[]};
|
||||
});
|
||||
var res = {
|
||||
code: 0,
|
||||
stdout:"",
|
||||
stderr:""
|
||||
}
|
||||
var p = Promise.resolve(res);
|
||||
p.catch((err)=>{});
|
||||
execResponse = p;
|
||||
|
||||
sinon.stub(fs,"statSync").callsFake(function(fn) { return {}; });
|
||||
|
||||
installer.uninstallModule("this_wont_exist").then(function(info) {
|
||||
info.should.eql(nodeInfo);
|
||||
// commsMessages.should.have.length(1);
|
||||
// commsMessages[0].topic.should.equal("node/removed");
|
||||
// commsMessages[0].msg.should.eql(nodeInfo);
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,62 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var should = require("should");
|
||||
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
|
||||
var NR_TEST_UTILS = require("nr-test-utils");
|
||||
|
||||
var library = NR_TEST_UTILS.require("@node-red/registry/lib/library");
|
||||
|
||||
describe("library api", function() {
|
||||
it('returns null list when no modules have been registered', function() {
|
||||
library.init();
|
||||
should.not.exist(library.getExampleFlows());
|
||||
});
|
||||
it('returns null path when module is not known', function() {
|
||||
library.init();
|
||||
should.not.exist(library.getExampleFlowPath('foo','bar'));
|
||||
});
|
||||
|
||||
it('returns a valid example path', function(done) {
|
||||
library.init();
|
||||
library.addExamplesDir("test-module",path.resolve(__dirname+'/resources/examples')).then(function() {
|
||||
try {
|
||||
var flows = library.getExampleFlows();
|
||||
flows.should.deepEqual({"test-module":{"f":["one"]}});
|
||||
|
||||
var examplePath = library.getExampleFlowPath('test-module','one');
|
||||
examplePath.should.eql(path.resolve(__dirname+'/resources/examples/one.json'))
|
||||
|
||||
|
||||
library.removeExamplesDir('test-module');
|
||||
|
||||
try {
|
||||
should.not.exist(library.getExampleFlows());
|
||||
should.not.exist(library.getExampleFlowPath('test-module','one'));
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err);
|
||||
}
|
||||
}catch(err) {
|
||||
done(err);
|
||||
}
|
||||
});
|
||||
|
||||
})
|
||||
});
|
||||
@@ -1,720 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var should = require("should");
|
||||
var sinon = require("sinon");
|
||||
var path = require("path");
|
||||
var fs = require("fs-extra");
|
||||
|
||||
var NR_TEST_UTILS = require("nr-test-utils");
|
||||
|
||||
var loader = NR_TEST_UTILS.require("@node-red/registry/lib/loader");
|
||||
|
||||
var localfilesystem = NR_TEST_UTILS.require("@node-red/registry/lib/localfilesystem");
|
||||
var registry = NR_TEST_UTILS.require("@node-red/registry/lib/registry");
|
||||
|
||||
var nodes = NR_TEST_UTILS.require("@node-red/registry");
|
||||
|
||||
var resourcesDir = path.resolve(path.join(__dirname,"resources","local"));
|
||||
|
||||
describe("red/nodes/registry/loader",function() {
|
||||
var stubs = [];
|
||||
before(function() {
|
||||
sinon.stub(localfilesystem,"init");
|
||||
});
|
||||
after(function() {
|
||||
localfilesystem.init.restore();
|
||||
});
|
||||
afterEach(function() {
|
||||
while(stubs.length) {
|
||||
stubs.pop().restore();
|
||||
}
|
||||
})
|
||||
|
||||
describe("#load",function() {
|
||||
it("load empty set without settings available", function(done) {
|
||||
stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){ return {};}));
|
||||
stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return {};}));
|
||||
loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return false;}}});
|
||||
loader.load(true).then(function() {
|
||||
localfilesystem.getNodeFiles.called.should.be.true();
|
||||
localfilesystem.getNodeFiles.lastCall.args[0].should.be.true();
|
||||
registry.saveNodeList.called.should.be.false();
|
||||
done();
|
||||
})
|
||||
});
|
||||
it("load empty set with settings available triggers registery save", function(done) {
|
||||
stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){ return {};}));
|
||||
stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return {};}));
|
||||
loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
|
||||
loader.load(true).then(function() {
|
||||
registry.saveNodeList.called.should.be.true();
|
||||
done();
|
||||
}).catch(function(err) {
|
||||
done(err);
|
||||
})
|
||||
});
|
||||
|
||||
it("load core node files scanned by lfs - single node single file", function(done) {
|
||||
stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){
|
||||
var result = {};
|
||||
result["node-red"] = {
|
||||
"name": "node-red",
|
||||
"version": "1.2.3",
|
||||
"nodes": {
|
||||
"TestNode1": {
|
||||
"file": path.join(resourcesDir,"TestNode1","TestNode1.js"),
|
||||
"module": "node-red",
|
||||
"name": "TestNode1"
|
||||
}
|
||||
}
|
||||
};
|
||||
return result;
|
||||
}));
|
||||
|
||||
stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
|
||||
// This module isn't already loaded
|
||||
stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
|
||||
|
||||
stubs.push(sinon.stub(nodes,"registerType"));
|
||||
loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
|
||||
loader.load().then(function(result) {
|
||||
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.config.should.not.eql("");
|
||||
module.nodes.TestNode1.should.have.property("help");
|
||||
module.nodes.TestNode1.help.should.have.property("en-US");
|
||||
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');
|
||||
nodes.registerType.lastCall.args[1].should.eql('test-node-1');
|
||||
|
||||
done();
|
||||
}).catch(function(err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
it("load core node files scanned by lfs - ignore html if disableEditor true", function(done) {
|
||||
stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){
|
||||
var result = {};
|
||||
result["node-red"] = {
|
||||
"name": "node-red",
|
||||
"version": "1.2.3",
|
||||
"nodes": {
|
||||
"TestNode1": {
|
||||
"file": path.join(resourcesDir,"TestNode1","TestNode1.js"),
|
||||
"module": "node-red",
|
||||
"name": "TestNode1"
|
||||
}
|
||||
}
|
||||
};
|
||||
return result;
|
||||
}));
|
||||
|
||||
stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
|
||||
// This module isn't already loaded
|
||||
stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
|
||||
|
||||
stubs.push(sinon.stub(nodes,"registerType"));
|
||||
loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{disableEditor: true, available:function(){return true;}}});
|
||||
loader.load().then(function(result) {
|
||||
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);
|
||||
// With disableEditor true, the types property is not populated by the
|
||||
// html file - but instead is populated as nodes register themselves.
|
||||
// But for this test, we have stubbed out registerType, so we won't get any types
|
||||
// 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');
|
||||
|
||||
// With disableEditor set, config should be blank
|
||||
module.nodes.TestNode1.should.have.property("config");
|
||||
module.nodes.TestNode1.config.should.eql("");
|
||||
|
||||
// help should be an empty object
|
||||
module.nodes.TestNode1.should.have.property("help");
|
||||
module.nodes.TestNode1.help.should.eql({})
|
||||
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');
|
||||
nodes.registerType.lastCall.args[1].should.eql('test-node-1');
|
||||
|
||||
done();
|
||||
}).catch(function(err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
it("load core node files scanned by lfs - multiple nodes single file", function(done) {
|
||||
stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){
|
||||
var result = {};
|
||||
result["node-red"] = {
|
||||
"name": "node-red",
|
||||
"version": "4.5.6",
|
||||
"nodes": {
|
||||
"MultipleNodes1": {
|
||||
"file": path.join(resourcesDir,"MultipleNodes1","MultipleNodes1.js"),
|
||||
"module": "node-red",
|
||||
"name": "MultipleNodes1"
|
||||
}
|
||||
}
|
||||
};
|
||||
return result;
|
||||
}));
|
||||
|
||||
stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
|
||||
// This module isn't already loaded
|
||||
stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
|
||||
stubs.push(sinon.stub(nodes,"registerType"));
|
||||
loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
|
||||
loader.load().then(function(result) {
|
||||
|
||||
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');
|
||||
nodes.registerType.firstCall.args[1].should.eql('test-node-multiple-1a');
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it("load core node files scanned by lfs - node with promise", function(done) {
|
||||
stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){
|
||||
var result = {};
|
||||
result["node-red"] = {
|
||||
"name": "node-red",
|
||||
"version":"2.4.6",
|
||||
"nodes": {
|
||||
"TestNode2": {
|
||||
"file": path.join(resourcesDir,"TestNode2","TestNode2.js"),
|
||||
"module": "node-red",
|
||||
"name": "TestNode2"
|
||||
}
|
||||
}
|
||||
};
|
||||
return result;
|
||||
}));
|
||||
|
||||
stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
|
||||
// This module isn't already loaded
|
||||
stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
|
||||
|
||||
stubs.push(sinon.stub(nodes,"registerType"));
|
||||
loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
|
||||
loader.load().then(function(result) {
|
||||
|
||||
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');
|
||||
nodes.registerType.lastCall.args[1].should.eql('test-node-2');
|
||||
|
||||
done();
|
||||
}).catch(function(err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it("load core node files scanned by lfs - node with rejecting promise", function(done) {
|
||||
stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){
|
||||
var result = {};
|
||||
result["node-red"] = {
|
||||
"name": "node-red",
|
||||
"version":"1.2.3",
|
||||
"nodes": {
|
||||
"TestNode3": {
|
||||
"file": path.join(resourcesDir,"TestNode3","TestNode3.js"),
|
||||
"module": "node-red",
|
||||
"name": "TestNode3"
|
||||
}
|
||||
}
|
||||
};
|
||||
return result;
|
||||
}));
|
||||
|
||||
stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
|
||||
// This module isn't already loaded
|
||||
stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
|
||||
|
||||
stubs.push(sinon.stub(nodes,"registerType"));
|
||||
loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
|
||||
loader.load().then(function(result) {
|
||||
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.called.should.be.false();
|
||||
|
||||
done();
|
||||
}).catch(function(err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
it("load core node files scanned by lfs - missing file", function(done) {
|
||||
stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){
|
||||
var result = {};
|
||||
result["node-red"] = {
|
||||
"name": "node-red",
|
||||
"version":"1.2.3",
|
||||
"nodes": {
|
||||
"DoesNotExist": {
|
||||
"file": path.join(resourcesDir,"doesnotexist"),
|
||||
"module": "node-red",
|
||||
"name": "DoesNotExist"
|
||||
}
|
||||
}
|
||||
};
|
||||
return result;
|
||||
}));
|
||||
|
||||
stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
|
||||
// This module isn't already loaded
|
||||
stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
|
||||
|
||||
stubs.push(sinon.stub(nodes,"registerType"));
|
||||
loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
|
||||
loader.load().then(function(result) {
|
||||
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.have.property("config","");
|
||||
module.nodes.DoesNotExist.should.have.property("help",{});
|
||||
module.nodes.DoesNotExist.should.have.property("namespace","node-red");
|
||||
module.nodes.DoesNotExist.should.have.property('err');
|
||||
|
||||
nodes.registerType.called.should.be.false();
|
||||
|
||||
done();
|
||||
}).catch(function(err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
// it("load core node files scanned by lfs - missing html file", function(done) {
|
||||
// // This is now an okay situation
|
||||
// stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){
|
||||
// var result = {};
|
||||
// result["node-red"] = {
|
||||
// "name": "node-red",
|
||||
// "version": "1.2.3",
|
||||
// "nodes": {
|
||||
// "DuffNode": {
|
||||
// "file": path.join(resourcesDir,"DuffNode","DuffNode.js"),
|
||||
// "module": "node-red",
|
||||
// "name": "DuffNode"
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
// return result;
|
||||
// }));
|
||||
//
|
||||
// stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return }));
|
||||
// stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
|
||||
// // This module isn't already loaded
|
||||
// stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
|
||||
//
|
||||
// stubs.push(sinon.stub(nodes,"registerType"));
|
||||
// loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
|
||||
// loader.load().then(function(result) {
|
||||
//
|
||||
// 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.have.property("config","");
|
||||
// module.nodes.DuffNode.should.have.property("help",{});
|
||||
// module.nodes.DuffNode.should.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) {
|
||||
// done(err);
|
||||
// });
|
||||
// });
|
||||
});
|
||||
|
||||
describe("#addModule",function() {
|
||||
it("throws error if settings unavailable", function() {
|
||||
loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return false;}}});
|
||||
/*jshint immed: false */
|
||||
(function(){
|
||||
loader.addModule("test-module");
|
||||
}).should.throw("Settings unavailable");
|
||||
});
|
||||
|
||||
it("returns rejected error if module already loaded", function(done) {
|
||||
stubs.push(sinon.stub(registry,"getModuleInfo").callsFake(function(){return{}}));
|
||||
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");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("returns rejected error if module not found", function(done) {
|
||||
stubs.push(sinon.stub(registry,"getModuleInfo").callsFake(function(){return null}));
|
||||
stubs.push(sinon.stub(localfilesystem,"getModuleFiles").callsFake(function() {
|
||||
throw new Error("failure");
|
||||
}));
|
||||
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();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("loads module by name", function(done) {
|
||||
// This module isn't already loaded
|
||||
stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
|
||||
stubs.push(sinon.stub(registry,"getModuleInfo").callsFake(function(){ return null; }));
|
||||
stubs.push(sinon.stub(localfilesystem,"getModuleFiles").callsFake(function(){
|
||||
var result = {};
|
||||
result["TestNodeModule"] = {
|
||||
"name": "TestNodeModule",
|
||||
"version": "1.2.3",
|
||||
"nodes": {
|
||||
"TestNode1": {
|
||||
"file": path.join(resourcesDir,"TestNodeModule","node_modules","TestNodeModule","TestNodeModule.js"),
|
||||
"module": "TestNodeModule",
|
||||
"name": "TestNode1",
|
||||
"version": "1.2.3"
|
||||
}
|
||||
}
|
||||
};
|
||||
return result;
|
||||
}));
|
||||
|
||||
stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return "a node list" }));
|
||||
stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
|
||||
stubs.push(sinon.stub(nodes,"registerType"));
|
||||
loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
|
||||
loader.addModule("TestNodeModule").then(function(result) {
|
||||
result.should.eql("TestNodeModule");
|
||||
|
||||
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();
|
||||
}).catch(function(err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
it("skips module that fails version check", function(done) {
|
||||
// This module isn't already loaded
|
||||
stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
|
||||
stubs.push(sinon.stub(registry,"getModuleInfo").callsFake(function(){ return null; }));
|
||||
stubs.push(sinon.stub(localfilesystem,"getModuleFiles").callsFake(function(){
|
||||
var result = {};
|
||||
result["TestNodeModule"] = {
|
||||
"name": "TestNodeModule",
|
||||
"version": "1.2.3",
|
||||
"redVersion":"999.0.0",
|
||||
"nodes": {
|
||||
"TestNode1": {
|
||||
"file": path.join(resourcesDir,"TestNodeModule","node_modules","TestNodeModule","TestNodeModule.js"),
|
||||
"module": "TestNodeModule",
|
||||
"name": "TestNode1",
|
||||
"version": "1.2.3"
|
||||
}
|
||||
}
|
||||
};
|
||||
return result;
|
||||
}));
|
||||
|
||||
stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return "a node list" }));
|
||||
stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
|
||||
stubs.push(sinon.stub(nodes,"registerType"));
|
||||
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("TestNodeModule");
|
||||
registry.addModule.called.should.be.false();
|
||||
nodes.registerType.called.should.be.false();
|
||||
done();
|
||||
}).catch(function(err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
it.skip('registers a message catalog');
|
||||
|
||||
|
||||
});
|
||||
describe("#loadNodeSet",function() {
|
||||
it("no-ops the load if node is not enabled", function(done) {
|
||||
stubs.push(sinon.stub(nodes,"registerType"));
|
||||
loader.loadNodeSet({
|
||||
"file": path.join(resourcesDir,"TestNode1","TestNode1.js"),
|
||||
"module": "node-red",
|
||||
"name": "TestNode1",
|
||||
"enabled": false
|
||||
}).then(function(node) {
|
||||
node.enabled.should.be.false();
|
||||
nodes.registerType.called.should.be.false();
|
||||
done();
|
||||
}).catch(function(err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
it("handles node that errors on require", function(done) {
|
||||
stubs.push(sinon.stub(nodes,"registerType"));
|
||||
loader.loadNodeSet({
|
||||
"file": path.join(resourcesDir,"TestNode4","TestNode4.js"),
|
||||
"module": "node-red",
|
||||
"name": "TestNode4",
|
||||
"enabled": true
|
||||
}).then(function(node) {
|
||||
node.enabled.should.be.true();
|
||||
nodes.registerType.called.should.be.false();
|
||||
node.should.have.property('err');
|
||||
node.err.toString().should.eql("Error: fail to require (line:1)");
|
||||
|
||||
done();
|
||||
}).catch(function(err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe("#getNodeHelp",function() {
|
||||
it("returns preloaded help", function() {
|
||||
loader.getNodeHelp({
|
||||
help:{
|
||||
en:"foo"
|
||||
}
|
||||
},"en").should.eql("foo");
|
||||
});
|
||||
it("loads help, caching result", function() {
|
||||
stubs.push(sinon.stub(fs,"readFileSync").callsFake(function(path) {
|
||||
return 'bar';
|
||||
}))
|
||||
var node = {
|
||||
template: "/tmp/node/directory/file.html",
|
||||
help:{
|
||||
en:"foo"
|
||||
}
|
||||
};
|
||||
loader.getNodeHelp(node,"fr").should.eql("bar");
|
||||
node.help['fr'].should.eql("bar");
|
||||
fs.readFileSync.calledOnce.should.be.true();
|
||||
fs.readFileSync.lastCall.args[0].should.eql(path.normalize("/tmp/node/directory/locales/fr/file.html"));
|
||||
loader.getNodeHelp(node,"fr").should.eql("bar");
|
||||
fs.readFileSync.calledOnce.should.be.true();
|
||||
});
|
||||
it("loads help, defaulting to en-US content", function() {
|
||||
stubs.push(sinon.stub(fs,"readFileSync").callsFake(function(path) {
|
||||
throw new Error("not found");
|
||||
}))
|
||||
var node = {
|
||||
template: "/tmp/node/directory/file.html",
|
||||
help:{}
|
||||
};
|
||||
node.help['en-US'] = 'foo';
|
||||
|
||||
loader.getNodeHelp(node,"fr").should.eql("foo");
|
||||
node.help['fr'].should.eql("foo");
|
||||
fs.readFileSync.calledOnce.should.be.true();
|
||||
fs.readFileSync.lastCall.args[0].should.eql(path.normalize("/tmp/node/directory/locales/fr/file.html"));
|
||||
loader.getNodeHelp(node,"fr").should.eql("foo");
|
||||
fs.readFileSync.calledOnce.should.be.true();
|
||||
});
|
||||
it("loads help, defaulting to en-US content for extra nodes", function() {
|
||||
stubs.push(sinon.stub(fs,"readFileSync").callsFake(function(path) {
|
||||
if (path.indexOf("en-US") >= 0) {
|
||||
return 'bar';
|
||||
}
|
||||
throw new Error("not found");
|
||||
}));
|
||||
var node = {
|
||||
template: "/tmp/node/directory/file.html",
|
||||
help:{}
|
||||
};
|
||||
delete node.help['en-US'];
|
||||
|
||||
loader.getNodeHelp(node,"fr").should.eql("bar");
|
||||
node.help['fr'].should.eql("bar");
|
||||
fs.readFileSync.calledTwice.should.be.true();
|
||||
fs.readFileSync.firstCall.args[0].should.eql(path.normalize("/tmp/node/directory/locales/fr/file.html"));
|
||||
fs.readFileSync.lastCall.args[0].should.eql(path.normalize("/tmp/node/directory/locales/en-US/file.html"));
|
||||
loader.getNodeHelp(node,"fr").should.eql("bar");
|
||||
fs.readFileSync.calledTwice.should.be.true();
|
||||
});
|
||||
it("fails to load en-US help content", function() {
|
||||
stubs.push(sinon.stub(fs,"readFileSync").callsFake(function(path) {
|
||||
throw new Error("not found");
|
||||
}));
|
||||
var node = {
|
||||
template: "/tmp/node/directory/file.html",
|
||||
help:{}
|
||||
};
|
||||
delete node.help['en-US'];
|
||||
|
||||
should.not.exist(loader.getNodeHelp(node,"en-US"));
|
||||
should.not.exist(node.help['en-US']);
|
||||
fs.readFileSync.calledTwice.should.be.true();
|
||||
fs.readFileSync.firstCall.args[0].should.eql(path.normalize("/tmp/node/directory/locales/en-US/file.html"));
|
||||
fs.readFileSync.lastCall.args[0].should.eql(path.normalize("/tmp/node/directory/locales/en/file.html"));
|
||||
should.not.exist(loader.getNodeHelp(node,"en-US"));
|
||||
fs.readFileSync.callCount.should.eql(4);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
@@ -1,276 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var should = require("should");
|
||||
var sinon = require("sinon");
|
||||
var path = require("path");
|
||||
|
||||
var NR_TEST_UTILS = require("nr-test-utils");
|
||||
|
||||
var localfilesystem = NR_TEST_UTILS.require("@node-red/registry/lib/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 i18n = NR_TEST_UTILS.require("@node-red/util").i18n;
|
||||
|
||||
describe("red/nodes/registry/localfilesystem",function() {
|
||||
beforeEach(function() {
|
||||
stubs.push(sinon.stub(i18n,"registerMessageCatalog").callsFake(function() { return Promise.resolve(); }));
|
||||
})
|
||||
|
||||
var stubs = [];
|
||||
afterEach(function() {
|
||||
while(stubs.length) {
|
||||
stubs.pop().restore();
|
||||
}
|
||||
})
|
||||
function checkNodes(nodes,shouldHaveNodes,shouldNotHaveNodes,module) {
|
||||
for (var i=0;i<shouldHaveNodes.length;i++) {
|
||||
nodes.should.have.a.property(shouldHaveNodes[i]);
|
||||
nodes[shouldHaveNodes[i]].should.have.a.property('file');
|
||||
nodes[shouldHaveNodes[i]].file.should.equal(path.resolve(nodes[shouldHaveNodes[i]].file));
|
||||
nodes[shouldHaveNodes[i]].should.have.a.property('module',module||'node-red');
|
||||
nodes[shouldHaveNodes[i]].should.have.a.property('name',shouldHaveNodes[i]);
|
||||
}
|
||||
for (i=0;i<shouldNotHaveNodes.length;i++) {
|
||||
nodes.should.not.have.a.property(shouldNotHaveNodes[i]);
|
||||
}
|
||||
}
|
||||
describe("#getNodeFiles",function() {
|
||||
it("Finds all the node files in the resources tree",function(done) {
|
||||
localfilesystem.init({coreNodesDir:resourcesDir});
|
||||
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");
|
||||
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,"locales")));
|
||||
i18n.registerMessageCatalog.lastCall.args[2].should.eql('messages.json');
|
||||
done();
|
||||
});
|
||||
it("Includes node files from settings",function(done) {
|
||||
localfilesystem.init({nodesIncludes:['TestNode1.js'],coreNodesDir:resourcesDir});
|
||||
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,['TestNode1'],['MultipleNodes1','NestedNode','TestNode2','TestNode3','TestNode4','TestNodeModule']);
|
||||
done();
|
||||
});
|
||||
it("Excludes node files from settings",function(done) {
|
||||
localfilesystem.init({nodesExcludes:['TestNode1.js'],coreNodesDir:resourcesDir});
|
||||
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,['MultipleNodes1','NestedNode','TestNode2','TestNode3','TestNode4'],['TestNode1','TestNodeModule']);
|
||||
done();
|
||||
});
|
||||
it("Finds nodes in userDir/nodes",function(done) {
|
||||
localfilesystem.init({userDir:userDir});
|
||||
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 (string)",function(done) {
|
||||
localfilesystem.init({nodesDir:userDir});
|
||||
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 (string,relative path)",function(done) {
|
||||
var relativeUserDir = path.join("test","unit","@node-red","registry","lib","resources","userDir");
|
||||
localfilesystem.init({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({nodesDir:[userDir]});
|
||||
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 module path",function(done) {
|
||||
var _join = path.join;
|
||||
stubs.push(sinon.stub(path,"join").callsFake(function() {
|
||||
if (arguments[0] == resourcesDir) {
|
||||
// This stops the module tree scan from going any higher
|
||||
// up the tree than resourcesDir.
|
||||
return arguments[0];
|
||||
}
|
||||
return _join.apply(null,arguments);
|
||||
}));
|
||||
localfilesystem.init({coreNodesDir:moduleDir});
|
||||
var nodeList = localfilesystem.getNodeFiles();
|
||||
nodeList.should.have.a.property("node-red");
|
||||
var nm = nodeList['node-red'];
|
||||
// The `node-red` module is loaded differently to those scanned for
|
||||
// It doesn't get the `path` property set. Maybe it should.
|
||||
nm.should.have.a.property('name','node-red');
|
||||
nm.should.have.a.property("nodes");
|
||||
checkNodes(nm.nodes,[],['TestNode1']);
|
||||
|
||||
nm = nodeList['TestNodeModule'];
|
||||
nm.should.have.a.property('path')
|
||||
nm.should.have.a.property('name','TestNodeModule');
|
||||
nm.should.have.a.property("nodes");
|
||||
checkNodes(nm.nodes,['TestNodeMod1','TestNodeMod2'],[],'TestNodeModule');
|
||||
|
||||
nm = nodeList['VersionMismatchModule'];
|
||||
nm.should.have.a.property('path')
|
||||
nm.should.have.a.property('name','VersionMismatchModule');
|
||||
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,"locales")));
|
||||
i18n.registerMessageCatalog.lastCall.args[2].should.eql('messages.json');
|
||||
|
||||
|
||||
|
||||
done();
|
||||
});
|
||||
it.skip("finds locales directory");
|
||||
it.skip("finds icon path directory");
|
||||
it("scans icon files in the resources tree",function(done) {
|
||||
var count = 0;
|
||||
localfilesystem.init({
|
||||
coreNodesDir: resourcesDir
|
||||
});
|
||||
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(1);
|
||||
list["node-red"].icons[0].should.have.property("path",path.join(__dirname,"resources/local/NestedDirectoryNode/NestedNode/icons"))
|
||||
list["node-red"].icons[0].should.have.property("icons");
|
||||
list["node-red"].icons[0].icons.should.have.length(1);
|
||||
list["node-red"].icons[0].icons[0].should.eql("arrow-in.png");
|
||||
done();
|
||||
});
|
||||
it("scans icons dir in library",function(done) {
|
||||
var count = 0;
|
||||
localfilesystem.init({
|
||||
userDir: userDir
|
||||
});
|
||||
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(1);
|
||||
list["node-red"].icons[0].should.have.property("path",path.join(__dirname,"resources/userDir/lib/icons"))
|
||||
list["node-red"].icons[0].should.have.property("icons");
|
||||
list["node-red"].icons[0].icons.should.have.length(1);
|
||||
list["node-red"].icons[0].icons[0].should.eql("test_icon.png");
|
||||
done();
|
||||
});
|
||||
});
|
||||
describe("#getModuleFiles",function() {
|
||||
it("gets a nodes module files",function(done) {
|
||||
var _join = path.join;
|
||||
stubs.push(sinon.stub(path,"join").callsFake(function() {
|
||||
if (arguments[0] == resourcesDir) {
|
||||
// This stops the module tree scan from going any higher
|
||||
// up the tree than resourcesDir.
|
||||
return arguments[0];
|
||||
}
|
||||
return _join.apply(null,arguments);
|
||||
}));
|
||||
localfilesystem.init({coreNodesDir:moduleDir});
|
||||
var nodeModule = localfilesystem.getModuleFiles('TestNodeModule');
|
||||
nodeModule.should.have.a.property('TestNodeModule');
|
||||
nodeModule['TestNodeModule'].should.have.a.property('name','TestNodeModule');
|
||||
nodeModule['TestNodeModule'].should.have.a.property('version','0.0.1');
|
||||
nodeModule['TestNodeModule'].should.have.a.property('nodes');
|
||||
nodeModule['TestNodeModule'].should.have.a.property('path');
|
||||
|
||||
checkNodes(nodeModule['TestNodeModule'].nodes,['TestNodeMod1','TestNodeMod2'],[],'TestNodeModule');
|
||||
|
||||
nodeModule = localfilesystem.getModuleFiles('VersionMismatchModule');
|
||||
nodeModule.should.have.a.property('VersionMismatchModule');
|
||||
nodeModule['VersionMismatchModule'].should.have.a.property('redVersion','100.0.0');
|
||||
|
||||
done();
|
||||
});
|
||||
it("throws an error if a node isn't found",function(done) {
|
||||
var _join = path.join;
|
||||
stubs.push(sinon.stub(path,"join").callsFake(function() {
|
||||
if (arguments[0] == resourcesDir) {
|
||||
// This stops the module tree scan from going any higher
|
||||
// up the tree than resourcesDir.
|
||||
return arguments[0];
|
||||
}
|
||||
return _join.apply(null,arguments);
|
||||
}));
|
||||
localfilesystem.init({coreNodesDir:moduleDir});
|
||||
/*jshint immed: false */
|
||||
(function(){
|
||||
localfilesystem.getModuleFiles('WontExistModule');
|
||||
}).should.throw();
|
||||
done();
|
||||
});
|
||||
it.skip("finds locales directory");
|
||||
it.skip("finds icon path directory");
|
||||
it("scans icon files with a module file",function(done) {
|
||||
var _join = path.join;
|
||||
stubs.push(sinon.stub(path,"join").callsFake(function() {
|
||||
if (arguments[0] == resourcesDir) {
|
||||
// This stops the module tree scan from going any higher
|
||||
// up the tree than resourcesDir.
|
||||
return arguments[0];
|
||||
}
|
||||
return _join.apply(null,arguments);
|
||||
}));
|
||||
localfilesystem.init({
|
||||
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();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,200 +0,0 @@
|
||||
|
||||
const should = require("should");
|
||||
const sinon = require("sinon");
|
||||
const path = require("path");
|
||||
|
||||
const NR_TEST_UTILS = require("nr-test-utils");
|
||||
|
||||
const plugins = NR_TEST_UTILS.require("@node-red/registry/lib/plugins");
|
||||
const registry = NR_TEST_UTILS.require("@node-red/registry/lib/registry");
|
||||
const { events } = NR_TEST_UTILS.require("@node-red/util");
|
||||
|
||||
describe("red/nodes/registry/plugins",function() {
|
||||
let receivedEvents = [];
|
||||
let modules;
|
||||
function handleEvent(evnt) {
|
||||
receivedEvents.push(evnt);
|
||||
}
|
||||
beforeEach(function() {
|
||||
plugins.init({});
|
||||
receivedEvents = [];
|
||||
modules = {
|
||||
"test-module": {
|
||||
plugins: {
|
||||
"test-set": {
|
||||
id: "test-module/test-set",
|
||||
enabled: true,
|
||||
config: "test-module-config",
|
||||
plugins: []
|
||||
},
|
||||
"test-disabled-set": {
|
||||
id: "test-module/test-disabled-set",
|
||||
enabled: false,
|
||||
config: "disabled-plugin-config",
|
||||
plugins: []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
events.on("registry:plugin-added",handleEvent);
|
||||
sinon.stub(registry,"getModule").callsFake(moduleId => modules[moduleId]);
|
||||
sinon.stub(registry,"getModuleList").callsFake(() => modules)
|
||||
});
|
||||
afterEach(function() {
|
||||
events.removeListener("registry:plugin-added",handleEvent);
|
||||
registry.getModule.restore();
|
||||
registry.getModuleList.restore();
|
||||
})
|
||||
|
||||
describe("registerPlugin", function() {
|
||||
it("registers a plugin", function() {
|
||||
let pluginDef = {}
|
||||
plugins.registerPlugin("test-module/test-set","a-plugin",pluginDef);
|
||||
receivedEvents.length.should.eql(1);
|
||||
receivedEvents[0].should.eql("a-plugin");
|
||||
should.exist(modules['test-module'].plugins['test-set'].plugins[0])
|
||||
modules['test-module'].plugins['test-set'].plugins[0].should.equal(pluginDef)
|
||||
})
|
||||
it("calls a plugins onadd function", function() {
|
||||
let pluginDef = { onadd: sinon.stub() }
|
||||
plugins.registerPlugin("test-module/test-set","a-plugin",pluginDef);
|
||||
pluginDef.onadd.called.should.be.true();
|
||||
})
|
||||
})
|
||||
|
||||
describe("getPlugin", function() {
|
||||
it("returns a registered plugin", function() {
|
||||
let pluginDef = {}
|
||||
plugins.registerPlugin("test-module/test-set","a-plugin",pluginDef);
|
||||
pluginDef.should.equal(plugins.getPlugin("a-plugin"));
|
||||
})
|
||||
})
|
||||
describe("getPluginsByType", function() {
|
||||
it("returns a plugins of a given type", function() {
|
||||
let pluginDef = {type: "foo"}
|
||||
let pluginDef2 = {type: "bar"}
|
||||
let pluginDef3 = {type: "foo"}
|
||||
plugins.registerPlugin("test-module/test-set","a-plugin",pluginDef);
|
||||
plugins.registerPlugin("test-module/test-set","a-plugin2",pluginDef2);
|
||||
plugins.registerPlugin("test-module/test-set","a-plugin3",pluginDef3);
|
||||
|
||||
let fooPlugins = plugins.getPluginsByType("foo");
|
||||
let barPlugins = plugins.getPluginsByType("bar");
|
||||
let noPlugins = plugins.getPluginsByType("none");
|
||||
|
||||
noPlugins.should.be.of.length(0);
|
||||
|
||||
fooPlugins.should.be.of.length(2);
|
||||
fooPlugins.should.containEql(pluginDef);
|
||||
fooPlugins.should.containEql(pluginDef3);
|
||||
|
||||
barPlugins.should.be.of.length(1);
|
||||
barPlugins.should.containEql(pluginDef2);
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
describe("getPluginConfigs", function() {
|
||||
it("gets all plugin configs", function() {
|
||||
let configs = plugins.getPluginConfigs("en-US");
|
||||
configs.should.eql(`
|
||||
<!-- --- [red-plugin:test-module/test-set] --- -->
|
||||
test-module-config`)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
describe("getPluginList", function() {
|
||||
it("returns a plugins of a given type", function() {
|
||||
let pluginDef = {type: "foo"}
|
||||
let pluginDef2 = {type: "bar"}
|
||||
let pluginDef3 = {type: "foo"}
|
||||
plugins.registerPlugin("test-module/test-set","a-plugin",pluginDef);
|
||||
plugins.registerPlugin("test-module/test-set","a-plugin2",pluginDef2);
|
||||
plugins.registerPlugin("test-module/test-set","a-plugin3",pluginDef3);
|
||||
|
||||
let pluginList = plugins.getPluginList();
|
||||
JSON.stringify(pluginList).should.eql(JSON.stringify(
|
||||
[
|
||||
{
|
||||
"id": "test-module/test-set",
|
||||
"enabled": true,
|
||||
"local": false,
|
||||
"user": false,
|
||||
"plugins": [
|
||||
{
|
||||
"type": "foo",
|
||||
"id": "a-plugin",
|
||||
"module": "test-module"
|
||||
},
|
||||
{
|
||||
"type": "bar",
|
||||
"id": "a-plugin2",
|
||||
"module": "test-module"
|
||||
},
|
||||
{
|
||||
"type": "foo",
|
||||
"id": "a-plugin3",
|
||||
"module": "test-module"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "test-module/test-disabled-set",
|
||||
"enabled": false,
|
||||
"local": false,
|
||||
"user": false,
|
||||
"plugins": []
|
||||
}
|
||||
]
|
||||
))
|
||||
})
|
||||
})
|
||||
describe("exportPluginSettings", function() {
|
||||
it("exports plugin settings - default false", function() {
|
||||
plugins.init({ "a-plugin": { a: 123, b:234, c: 345} });
|
||||
plugins.registerPlugin("test-module/test-set","a-plugin",{
|
||||
settings: {
|
||||
a: { exportable: true },
|
||||
b: {exportable: false },
|
||||
d: { exportable: true, value: 456}
|
||||
|
||||
}
|
||||
});
|
||||
var exportedSet = {};
|
||||
plugins.exportPluginSettings(exportedSet);
|
||||
exportedSet.should.have.property("a-plugin");
|
||||
// a is exportable
|
||||
exportedSet["a-plugin"].should.have.property("a",123);
|
||||
// b is explicitly not exportable
|
||||
exportedSet["a-plugin"].should.not.have.property("b");
|
||||
// c isn't listed and default false
|
||||
exportedSet["a-plugin"].should.not.have.property("c");
|
||||
// d has a default value
|
||||
exportedSet["a-plugin"].should.have.property("d",456);
|
||||
})
|
||||
it("exports plugin settings - default true", function() {
|
||||
plugins.init({ "a-plugin": { a: 123, b:234, c: 345} });
|
||||
plugins.registerPlugin("test-module/test-set","a-plugin",{
|
||||
settings: {
|
||||
'*': { exportable: true },
|
||||
a: { exportable: true },
|
||||
b: {exportable: false },
|
||||
d: { exportable: true, value: 456}
|
||||
|
||||
}
|
||||
});
|
||||
var exportedSet = {};
|
||||
plugins.exportPluginSettings(exportedSet);
|
||||
exportedSet.should.have.property("a-plugin");
|
||||
// a is exportable
|
||||
exportedSet["a-plugin"].should.have.property("a",123);
|
||||
// b is explicitly not exportable
|
||||
exportedSet["a-plugin"].should.not.have.property("b");
|
||||
// c isn't listed, but default true
|
||||
exportedSet["a-plugin"].should.have.property("c");
|
||||
// d has a default value
|
||||
exportedSet["a-plugin"].should.have.property("d",456);
|
||||
})
|
||||
});
|
||||
});
|
||||
@@ -1,614 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var should = require("should");
|
||||
var sinon = require("sinon");
|
||||
var path = require("path");
|
||||
|
||||
var NR_TEST_UTILS = require("nr-test-utils");
|
||||
|
||||
var typeRegistry = NR_TEST_UTILS.require("@node-red/registry/lib/registry");
|
||||
const { events } = NR_TEST_UTILS.require("@node-red/util");
|
||||
|
||||
describe("red/nodes/registry/registry",function() {
|
||||
|
||||
afterEach(function() {
|
||||
typeRegistry.clear();
|
||||
});
|
||||
|
||||
function stubSettings(s,available,initialConfig) {
|
||||
s.available = function() {return available;};
|
||||
s.set = sinon.spy(function(s,v) { return Promise.resolve();});
|
||||
s.get = function(s) { return initialConfig;};
|
||||
return s;
|
||||
}
|
||||
|
||||
var settings = stubSettings({},false,null);
|
||||
var settingsWithStorageAndInitialConfig = stubSettings({},true,{"node-red":{module:"testModule",name:"testName",version:"testVersion",nodes:{"node":{id:"node-red/testName",name:"test",types:["a","b"],enabled:true}}}});
|
||||
|
||||
var testNodeSet1 = {
|
||||
id: "test-module/test-name",
|
||||
module: "test-module",
|
||||
name: "test-name",
|
||||
enabled: true,
|
||||
loaded: false,
|
||||
config: "configA",
|
||||
types: [ "test-a","test-b"]
|
||||
};
|
||||
|
||||
var testNodeSet2 = {
|
||||
id: "test-module/test-name-2",
|
||||
module: "test-module",
|
||||
name: "test-name-2",
|
||||
enabled: true,
|
||||
loaded: false,
|
||||
config: "configB",
|
||||
types: [ "test-c","test-d"]
|
||||
};
|
||||
var testNodeSet2WithError = {
|
||||
id: "test-module/test-name-2",
|
||||
module: "test-module",
|
||||
name: "test-name-2",
|
||||
enabled: true,
|
||||
loaded: false,
|
||||
err: "I have an error",
|
||||
config: "configC",
|
||||
types: [ "test-c","test-d"]
|
||||
};
|
||||
var testNodeSet3 = {
|
||||
id: "test-module-2/test-name-3",
|
||||
module: "test-module-2",
|
||||
name: "test-name-3",
|
||||
enabled: true,
|
||||
loaded: false,
|
||||
config: "configB",
|
||||
types: [ "test-a","test-e"]
|
||||
};
|
||||
|
||||
|
||||
|
||||
describe('#init/load', function() {
|
||||
it('loads initial config', function(done) {
|
||||
typeRegistry.init(settingsWithStorageAndInitialConfig,null);
|
||||
typeRegistry.getNodeList().should.have.lengthOf(0);
|
||||
typeRegistry.load();
|
||||
typeRegistry.getNodeList().should.have.lengthOf(1);
|
||||
done();
|
||||
});
|
||||
|
||||
it('migrates legacy format', function(done) {
|
||||
var legacySettings = {
|
||||
available: function() { return true; },
|
||||
set: sinon.stub().returns(Promise.resolve()),
|
||||
get: function() { return {
|
||||
"123": {
|
||||
"name": "72-sentiment.js",
|
||||
"types": [
|
||||
"sentiment"
|
||||
],
|
||||
"enabled": true
|
||||
},
|
||||
"456": {
|
||||
"name": "20-inject.js",
|
||||
"types": [
|
||||
"inject"
|
||||
],
|
||||
"enabled": true
|
||||
},
|
||||
"789": {
|
||||
"name": "testModule:a-module.js",
|
||||
"types": [
|
||||
"example"
|
||||
],
|
||||
"enabled":true,
|
||||
"module":"testModule"
|
||||
}
|
||||
}}
|
||||
};
|
||||
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,null);
|
||||
typeRegistry.load();
|
||||
legacySettings.set.calledOnce.should.be.true();
|
||||
legacySettings.set.args[0][1].should.eql(expected);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe.skip('#addNodeSet', function() {
|
||||
it('adds a node set for an unknown module', function() {
|
||||
|
||||
typeRegistry.init(settings,null);
|
||||
|
||||
typeRegistry.getNodeList().should.have.lengthOf(0);
|
||||
typeRegistry.getModuleList().should.eql({});
|
||||
|
||||
typeRegistry.addNodeSet("test-module/test-name",testNodeSet1, "0.0.1");
|
||||
|
||||
typeRegistry.getNodeList().should.have.lengthOf(1);
|
||||
var moduleList = typeRegistry.getModuleList();
|
||||
moduleList.should.have.a.property("test-module");
|
||||
moduleList["test-module"].should.have.a.property("name","test-module");
|
||||
moduleList["test-module"].should.have.a.property("version","0.0.1");
|
||||
moduleList["test-module"].should.have.a.property("nodes");
|
||||
moduleList["test-module"].nodes.should.have.a.property("test-name");
|
||||
|
||||
moduleList["test-module"].nodes["test-name"].should.eql({
|
||||
config: 'configA',
|
||||
id: 'test-module/test-name',
|
||||
module: 'test-module',
|
||||
name: 'test-name',
|
||||
enabled: true,
|
||||
loaded: false,
|
||||
types: [ 'test-a', 'test-b' ]
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('adds a node set to an existing module', function() {
|
||||
|
||||
typeRegistry.init(settings,null);
|
||||
typeRegistry.getNodeList().should.have.lengthOf(0);
|
||||
typeRegistry.getModuleList().should.eql({});
|
||||
|
||||
typeRegistry.addNodeSet("test-module/test-name",testNodeSet1, "0.0.1");
|
||||
|
||||
typeRegistry.getNodeList().should.have.lengthOf(1);
|
||||
var moduleList = typeRegistry.getModuleList();
|
||||
Object.keys(moduleList).should.have.a.lengthOf(1);
|
||||
moduleList.should.have.a.property("test-module");
|
||||
moduleList["test-module"].should.have.a.property("name","test-module");
|
||||
moduleList["test-module"].should.have.a.property("version","0.0.1");
|
||||
moduleList["test-module"].should.have.a.property("nodes");
|
||||
|
||||
Object.keys(moduleList["test-module"].nodes).should.have.a.lengthOf(1);
|
||||
moduleList["test-module"].nodes.should.have.a.property("test-name");
|
||||
|
||||
|
||||
typeRegistry.addNodeSet("test-module/test-name-2",testNodeSet2);
|
||||
|
||||
typeRegistry.getNodeList().should.have.lengthOf(2);
|
||||
moduleList = typeRegistry.getModuleList();
|
||||
Object.keys(moduleList).should.have.a.lengthOf(1);
|
||||
Object.keys(moduleList["test-module"].nodes).should.have.a.lengthOf(2);
|
||||
moduleList["test-module"].nodes.should.have.a.property("test-name");
|
||||
moduleList["test-module"].nodes.should.have.a.property("test-name-2");
|
||||
});
|
||||
|
||||
it('doesnt add node set types if node set has an error', function() {
|
||||
typeRegistry.init(settings,null);
|
||||
typeRegistry.getNodeList().should.have.lengthOf(0);
|
||||
typeRegistry.getModuleList().should.eql({});
|
||||
|
||||
typeRegistry.addNodeSet("test-module/test-name",testNodeSet1, "0.0.1");
|
||||
|
||||
typeRegistry.getTypeId("test-a").should.eql("test-module/test-name");
|
||||
|
||||
should.not.exist(typeRegistry.getTypeId("test-c"));
|
||||
|
||||
typeRegistry.addNodeSet("test-module/test-name-2",testNodeSet2WithError, "0.0.1");
|
||||
|
||||
should.not.exist(typeRegistry.getTypeId("test-c"));
|
||||
});
|
||||
|
||||
it('doesnt add node set if type already exists', function() {
|
||||
typeRegistry.init(settings,null);
|
||||
typeRegistry.getNodeList().should.have.lengthOf(0);
|
||||
typeRegistry.getModuleList().should.eql({});
|
||||
|
||||
should.not.exist(typeRegistry.getTypeId("test-e"));
|
||||
|
||||
typeRegistry.addNodeSet("test-module/test-name",testNodeSet1, "0.0.1");
|
||||
typeRegistry.getNodeList().should.have.lengthOf(1);
|
||||
should.exist(typeRegistry.getTypeId("test-a"));
|
||||
typeRegistry.addNodeSet(testNodeSet3.id,testNodeSet3, "0.0.1");
|
||||
typeRegistry.getNodeList().should.have.lengthOf(2);
|
||||
|
||||
// testNodeSet3 registers a duplicate test-a and unique test-e
|
||||
// as test-a is a duplicate, test-e should not get registered
|
||||
should.not.exist(typeRegistry.getTypeId("test-e"));
|
||||
|
||||
var testNodeSet3Result = typeRegistry.getNodeList()[1];
|
||||
should.exist(testNodeSet3Result.err);
|
||||
testNodeSet3Result.err.code.should.equal("type_already_registered");
|
||||
testNodeSet3Result.err.details.type.should.equal("test-a");
|
||||
testNodeSet3Result.err.details.moduleA.should.equal("test-module");
|
||||
testNodeSet3Result.err.details.moduleB.should.equal("test-module-2");
|
||||
|
||||
//
|
||||
// typeRegistry.addNodeSet("test-module/test-name-2",testNodeSet2WithError, "0.0.1");
|
||||
//
|
||||
// should.not.exist(typeRegistry.getTypeId("test-c"));
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
describe("#enableNodeSet", function() {
|
||||
it('throws error if settings unavailable', function() {
|
||||
typeRegistry.init(settings,null);
|
||||
/*jshint immed: false */
|
||||
(function(){
|
||||
typeRegistry.enableNodeSet("test-module/test-name");
|
||||
}).should.throw("Settings unavailable");
|
||||
});
|
||||
|
||||
it('throws error if module unknown', function() {
|
||||
typeRegistry.init(settingsWithStorageAndInitialConfig,null);
|
||||
/*jshint immed: false */
|
||||
(function(){
|
||||
typeRegistry.enableNodeSet("test-module/unknown");
|
||||
}).should.throw("Unrecognised id: test-module/unknown");
|
||||
});
|
||||
it.skip('enables the node',function(){})
|
||||
|
||||
});
|
||||
describe("#disableNodeSet", function() {
|
||||
it('throws error if settings unavailable', function() {
|
||||
typeRegistry.init(settings,null);
|
||||
/*jshint immed: false */
|
||||
(function(){
|
||||
typeRegistry.disableNodeSet("test-module/test-name");
|
||||
}).should.throw("Settings unavailable");
|
||||
});
|
||||
|
||||
it('throws error if module unknown', function() {
|
||||
typeRegistry.init(settingsWithStorageAndInitialConfig,null);
|
||||
/*jshint immed: false */
|
||||
(function(){
|
||||
typeRegistry.disableNodeSet("test-module/unknown");
|
||||
}).should.throw("Unrecognised id: test-module/unknown");
|
||||
});
|
||||
it.skip('disables the node',function(){})
|
||||
});
|
||||
|
||||
describe('#getNodeConfig', function() {
|
||||
it('returns nothing for an unregistered type config', function(done) {
|
||||
typeRegistry.init(settings,null);
|
||||
var config = typeRegistry.getNodeConfig("imaginary-shark");
|
||||
(config === null).should.be.true();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#saveNodeList',function() {
|
||||
it('rejects when settings unavailable',function(done) {
|
||||
typeRegistry.init(stubSettings({},false,{}),null);
|
||||
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,null);
|
||||
|
||||
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) {
|
||||
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) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#removeModule',function() {
|
||||
it('throws error for unknown module', function() {
|
||||
var s = stubSettings({},true,{});
|
||||
typeRegistry.init(s,null);
|
||||
/*jshint immed: false */
|
||||
(function(){
|
||||
typeRegistry.removeModule("test-module/unknown");
|
||||
}).should.throw("Unrecognised module: test-module/unknown");
|
||||
});
|
||||
it('throws error for unavaiable settings', function() {
|
||||
var s = stubSettings({},false,{});
|
||||
typeRegistry.init(s,null);
|
||||
/*jshint immed: false */
|
||||
(function(){
|
||||
typeRegistry.removeModule("test-module/unknown");
|
||||
}).should.throw("Settings unavailable");
|
||||
});
|
||||
it('removes a known module', function() {
|
||||
var s = stubSettings({},true,{});
|
||||
typeRegistry.init(s,null);
|
||||
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);
|
||||
|
||||
var info = typeRegistry.removeModule('test-module');
|
||||
moduleList = typeRegistry.getModuleList();
|
||||
moduleList.should.not.have.a.property("test-module");
|
||||
typeRegistry.getNodeList().should.have.lengthOf(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#get[All]NodeConfigs', function() {
|
||||
it('returns node config', function() {
|
||||
typeRegistry.init(settings,{
|
||||
getNodeHelp: function(config) { return "HE"+config.name+"LP" }
|
||||
});
|
||||
|
||||
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('<!-- --- [red-module:test-module/test-name] --- -->\nconfigAHEtest-nameLP');
|
||||
typeRegistry.getNodeConfig("test-module/test-name-2").should.eql('<!-- --- [red-module:test-module/test-name-2] --- -->\nconfigBHEtest-name-2LP');
|
||||
typeRegistry.getAllNodeConfigs().should.eql('\n<!-- --- [red-module:test-module/test-name] --- -->\nconfigAHEtest-nameLP\n<!-- --- [red-module:test-module/test-name-2] --- -->\nconfigBHEtest-name-2LP');
|
||||
});
|
||||
});
|
||||
describe('#getModuleInfo', function() {
|
||||
it('returns module info', function() {
|
||||
typeRegistry.init(settings,{});
|
||||
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');
|
||||
moduleInfo.should.have.a.property('nodes');
|
||||
moduleInfo.nodes.should.have.a.lengthOf(1);
|
||||
moduleInfo.nodes[0].should.have.a.property('id','test-module/test-name');
|
||||
moduleInfo.nodes[0].should.not.have.a.property('file');
|
||||
});
|
||||
});
|
||||
describe('#getNodeInfo', function() {
|
||||
it('returns node info', function() {
|
||||
typeRegistry.init(settings,{});
|
||||
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');
|
||||
nodeSetInfo.should.not.have.a.property('file');
|
||||
});
|
||||
});
|
||||
describe('#getFullNodeInfo', function() {
|
||||
it('returns node info', function() {
|
||||
typeRegistry.init(settings,{});
|
||||
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.getFullNodeInfo("test-module/test-name");
|
||||
nodeSetInfo.should.have.a.property('id',"test-module/test-name");
|
||||
nodeSetInfo.should.have.a.property('config');
|
||||
nodeSetInfo.should.have.a.property('file');
|
||||
});
|
||||
});
|
||||
describe('#cleanModuleList', function() {
|
||||
it.skip("cleans the module list");
|
||||
});
|
||||
describe('#getNodeList', function() {
|
||||
it("returns a filtered list", function() {
|
||||
typeRegistry.init(settings,{});
|
||||
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);
|
||||
filteredList.should.have.a.lengthOf(1);
|
||||
filteredList[0].should.have.a.property('id',"test-module/test-name-2");
|
||||
});
|
||||
});
|
||||
|
||||
describe('#registerNodeConstructor', function() {
|
||||
var TestNodeConstructor;
|
||||
beforeEach(function() {
|
||||
TestNodeConstructor = function TestNodeConstructor() {};
|
||||
sinon.stub(events,'emit');
|
||||
});
|
||||
afterEach(function() {
|
||||
events.emit.restore();
|
||||
});
|
||||
it('registers a node constructor', function() {
|
||||
typeRegistry.registerNodeConstructor('node-set','node-type',TestNodeConstructor);
|
||||
events.emit.calledOnce.should.be.true();
|
||||
events.emit.lastCall.args[0].should.eql('type-registered');
|
||||
events.emit.lastCall.args[1].should.eql('node-type');
|
||||
})
|
||||
it('throws error on duplicate node registration', function() {
|
||||
typeRegistry.registerNodeConstructor('node-set','node-type',TestNodeConstructor);
|
||||
events.emit.calledOnce.should.be.true();
|
||||
events.emit.lastCall.args[0].should.eql('type-registered');
|
||||
events.emit.lastCall.args[1].should.eql('node-type');
|
||||
/*jshint immed: false */
|
||||
(function(){
|
||||
typeRegistry.registerNodeConstructor('node-set','node-type',TestNodeConstructor);
|
||||
}).should.throw("node-type already registered");
|
||||
events.emit.calledOnce.should.be.true();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getNodeIconPath', function() {
|
||||
it('returns the null when getting an unknown icon', function() {
|
||||
var iconPath = typeRegistry.getNodeIconPath('random-module','youwonthaveme.png');
|
||||
should.not.exist(iconPath);
|
||||
});
|
||||
|
||||
it('returns a registered icon' , function() {
|
||||
var testIcon = path.resolve(__dirname+'/resources/userDir/lib/icons/');
|
||||
typeRegistry.init(settings,{});
|
||||
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(path.resolve(testIcon+"/test_icon.png"));
|
||||
});
|
||||
|
||||
it('returns null when getting an unknown module', function() {
|
||||
var debugIcon = path.resolve(__dirname+'/../../../public/icons/debug.png');
|
||||
var iconPath = typeRegistry.getNodeIconPath('unknown-module', 'debug.png');
|
||||
should.not.exist(iconPath);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getNodeIcons', function() {
|
||||
it('returns empty icon list when no modules are registered', function() {
|
||||
var iconList = typeRegistry.getNodeIcons();
|
||||
iconList.should.eql({});
|
||||
});
|
||||
|
||||
it('returns an icon list of registered node module', function() {
|
||||
var testIcon = path.resolve(__dirname+'/resources/userDir/lib/icons/');
|
||||
typeRegistry.init(settings,{});
|
||||
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_icon.png"]});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getModuleResource', function() {
|
||||
beforeEach(function() {
|
||||
typeRegistry.init(settings,{});
|
||||
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"
|
||||
}
|
||||
},
|
||||
resources: {
|
||||
path: path.join(__dirname, "resources","examples")
|
||||
}
|
||||
});
|
||||
});
|
||||
it('Returns valid resource path', function() {
|
||||
const result = typeRegistry.getModuleResource("test-module","one.json");
|
||||
should.exist(result);
|
||||
result.should.eql(path.join(__dirname, "resources","examples","one.json"))
|
||||
});
|
||||
it('Returns null for path that tries to break out', function() {
|
||||
// Note - this path exists, but we don't allow .. in the resolved path to
|
||||
// avoid breaking out of the resources dir
|
||||
const result = typeRegistry.getModuleResource("test-module","../../index_spec.js");
|
||||
should.not.exist(result);
|
||||
});
|
||||
it('Returns null for path that does not exist', function() {
|
||||
const result = typeRegistry.getModuleResource("test-module","two.json");
|
||||
should.not.exist(result);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,5 +0,0 @@
|
||||
// A test node that exports a function
|
||||
module.exports = function(RED) {
|
||||
function DuffNode(n) {}
|
||||
RED.nodes.registerType("duff-node",DuffNode);
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
<script type="text/x-red" data-template-name="test-node-1"></script>
|
||||
<script type="text/x-red" data-help-name="test-node-1"></script>
|
||||
<script type="text/javascript">RED.nodes.registerType('test-node-1',{});</script>
|
||||
@@ -1,5 +0,0 @@
|
||||
// A test node that exports a function
|
||||
module.exports = function(RED) {
|
||||
function DuplicateTestNode(n) {}
|
||||
RED.nodes.registerType("test-node-1",DuplicateTestNode);
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
<script type="text/x-red" data-template-name="test-node-multiple-1a"></script>
|
||||
<script type="text/x-red" data-help-name="test-node-multiple-1a"></script>
|
||||
<script type="text/javascript">RED.nodes.registerType('test-node-multiple-1a',{});</script>
|
||||
<script type="text/x-red" data-template-name="test-node-multiple-1b"></script>
|
||||
<script type="text/x-red" data-help-name="test-node-multiple-1b"></script>
|
||||
<script type="text/javascript">RED.nodes.registerType('test-node-multiple-1b',{});</script>
|
||||
@@ -1,7 +0,0 @@
|
||||
// A test node that exports a function
|
||||
module.exports = function(RED) {
|
||||
function TestNode1(n) {}
|
||||
RED.nodes.registerType("test-node-multiple-1a",TestNode1);
|
||||
function TestNode2(n) {}
|
||||
RED.nodes.registerType("test-node-multiple-1b",TestNode2);
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
<script type="text/x-red" data-template-name="nested-node-1"></script>
|
||||
<script type="text/x-red" data-help-name="nested-node-1"></script>
|
||||
<script type="text/javascript">RED.nodes.registerType('nested-node-1',{});</script>
|
||||
<style></style>
|
||||
@@ -1,5 +0,0 @@
|
||||
// A test node that exports a function
|
||||
module.exports = function(RED) {
|
||||
function TestNode(n) {}
|
||||
RED.nodes.registerType("nested-node-1",TestNode);
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 393 B |
@@ -1,4 +0,0 @@
|
||||
<script type="text/x-red" data-template-name="should-not-load-1"></script>
|
||||
<script type="text/x-red" data-help-name="should-not-load-1"></script>
|
||||
<script type="text/javascript">RED.nodes.registerType('should-not-load-1',{});</script>
|
||||
<style></style>
|
||||
@@ -1,5 +0,0 @@
|
||||
// A test node that exports a function
|
||||
module.exports = function(RED) {
|
||||
function TestNode(n) {}
|
||||
RED.nodes.registerType("should-not-load-1",TestNode);
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
<script type="text/x-red" data-template-name="should-not-load-2"></script>
|
||||
<script type="text/x-red" data-help-name="should-not-load-2"></script>
|
||||
<script type="text/javascript">RED.nodes.registerType('should-not-load-2',{});</script>
|
||||
<style></style>
|
||||
@@ -1,5 +0,0 @@
|
||||
// A test node that exports a function
|
||||
module.exports = function(RED) {
|
||||
function TestNode(n) {}
|
||||
RED.nodes.registerType("should-not-load-2",TestNode);
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
<script type="text/x-red" data-template-name="should-not-load-3"></script>
|
||||
<script type="text/x-red" data-help-name="should-not-load-3"></script>
|
||||
<script type="text/javascript">RED.nodes.registerType('should-not-load-3',{});</script>
|
||||
<style></style>
|
||||
@@ -1,5 +0,0 @@
|
||||
// A test node that exports a function
|
||||
module.exports = function(RED) {
|
||||
function TestNode(n) {}
|
||||
RED.nodes.registerType("should-not-load-3",TestNode);
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
<script type="text/x-red" data-template-name="test-node-1"></script>
|
||||
<script type="text/x-red" data-help-name="test-node-1"></script>
|
||||
<script type="text/javascript">RED.nodes.registerType('test-node-1',{});</script>
|
||||
<style></style>
|
||||
<p>this should be filtered out</p>
|
||||
@@ -1,5 +0,0 @@
|
||||
// A test node that exports a function
|
||||
module.exports = function(RED) {
|
||||
function TestNode(n) {}
|
||||
RED.nodes.registerType("test-node-1",TestNode);
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
<script type="text/x-red" data-template-name="test-node-2"></script>
|
||||
<script type="text/x-red" data-help-name="test-node-2"></script>
|
||||
<script type="text/javascript">RED.nodes.registerType('test-node-2',{});</script>
|
||||
<style></style>
|
||||
@@ -1,9 +0,0 @@
|
||||
// A test node that exports a function which returns a resolving promise
|
||||
|
||||
module.exports = function(RED) {
|
||||
return new Promise(function(resolve,reject) {
|
||||
function TestNode(n) {}
|
||||
RED.nodes.registerType("test-node-2",TestNode);
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
<script type="text/x-red" data-template-name="test-node-3"></script>
|
||||
<script type="text/x-red" data-help-name="test-node-3"></script>
|
||||
<script type="text/javascript">RED.nodes.registerType('test-node-3',{});</script>
|
||||
@@ -1,7 +0,0 @@
|
||||
// A test node that exports a function which returns a rejecting promise
|
||||
|
||||
module.exports = function(RED) {
|
||||
return new Promise(function(resolve,reject) {
|
||||
reject("fail");
|
||||
});
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
<script type="text/x-red" data-template-name="test-node-3"></script>
|
||||
<script type="text/x-red" data-help-name="test-node-3"></script>
|
||||
<script type="text/javascript">RED.nodes.registerType('test-node-3',{});</script>
|
||||
@@ -1 +0,0 @@
|
||||
throw new Error("fail to require");
|
||||
@@ -1 +0,0 @@
|
||||
This file exists just to ensure the parent directory is in the repository.
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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>
|
||||
@@ -1,4 +0,0 @@
|
||||
// A test node that exports a function
|
||||
module.exports = function(RED) {
|
||||
throw new Error("fail to load");
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 393 B |
@@ -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
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"name" : "TestNodeModule",
|
||||
"version" : "0.0.1",
|
||||
"description" : "A test node module",
|
||||
"node-red" : {
|
||||
"nodes": {
|
||||
"TestNodeMod1": "TestNodeModule.js",
|
||||
"TestNodeMod2": "TestNodeModule2.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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>
|
||||
@@ -1,4 +0,0 @@
|
||||
// A test node that exports a function
|
||||
module.exports = function(RED) {
|
||||
throw new Error("fail to load");
|
||||
}
|
||||
@@ -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
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 163 B |
@@ -1,5 +0,0 @@
|
||||
<script type="text/x-red" data-template-name="test-node-5"></script>
|
||||
<script type="text/x-red" data-help-name="test-node-5"></script>
|
||||
<script type="text/javascript">RED.nodes.registerType('test-node-5',{});</script>
|
||||
<style></style>
|
||||
<p>this should be filtered out</p>
|
||||
@@ -1 +0,0 @@
|
||||
throw new Error("fail to require");
|
||||
@@ -1,3 +0,0 @@
|
||||
describe("red/nodes/registry/subflow",function() {
|
||||
it.skip("NEEDS TESTS");
|
||||
});
|
||||
@@ -1,115 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
const should = require("should");
|
||||
const sinon = require("sinon");
|
||||
|
||||
const NR_TEST_UTILS = require("nr-test-utils");
|
||||
const registryUtil = NR_TEST_UTILS.require("@node-red/registry/lib/util");
|
||||
|
||||
// Get the internal runtime api
|
||||
const runtime = NR_TEST_UTILS.require("@node-red/runtime")._;
|
||||
|
||||
const i18n = NR_TEST_UTILS.require("@node-red/util").i18n;
|
||||
|
||||
describe("red/nodes/registry/util",function() {
|
||||
describe("createNodeApi", function() {
|
||||
let i18n_;
|
||||
let registerType;
|
||||
let registerSubflow;
|
||||
|
||||
before(function() {
|
||||
i18n_ = sinon.stub(i18n,"_").callsFake(function() {
|
||||
return Array.prototype.slice.call(arguments,0);
|
||||
})
|
||||
registerType = sinon.stub(runtime.nodes,"registerType");
|
||||
registerSubflow = sinon.stub(runtime.nodes,"registerSubflow");
|
||||
});
|
||||
after(function() {
|
||||
i18n_.restore();
|
||||
registerType.restore();
|
||||
registerSubflow.restore();
|
||||
})
|
||||
|
||||
it("builds node-specific view of runtime api", function() {
|
||||
registryUtil.init(runtime);
|
||||
var result = registryUtil.createNodeApi({id: "my-node", namespace: "my-namespace"})
|
||||
// Need a better strategy here.
|
||||
// For now, validate the node-custom functions
|
||||
|
||||
var message = result._("message");
|
||||
// This should prepend the node's namespace to the message
|
||||
message.should.eql([ 'my-namespace:message' ]);
|
||||
|
||||
var nodeConstructor = () => {};
|
||||
var nodeOpts = {};
|
||||
result.nodes.registerType("type",nodeConstructor, nodeOpts);
|
||||
registerType.called.should.be.true();
|
||||
registerType.lastCall.args[0].should.eql("my-node")
|
||||
registerType.lastCall.args[1].should.eql("type")
|
||||
registerType.lastCall.args[2].should.eql(nodeConstructor)
|
||||
registerType.lastCall.args[3].should.eql(nodeOpts)
|
||||
|
||||
var subflowDef = {};
|
||||
result.nodes.registerSubflow(subflowDef);
|
||||
registerSubflow.called.should.be.true();
|
||||
registerSubflow.lastCall.args[0].should.eql("my-node")
|
||||
registerSubflow.lastCall.args[1].should.eql(subflowDef)
|
||||
|
||||
});
|
||||
});
|
||||
describe("checkModuleAllowed", function() {
|
||||
function checkList(module, version, allowList, denyList) {
|
||||
return registryUtil.checkModuleAllowed(
|
||||
module,
|
||||
version,
|
||||
registryUtil.parseModuleList(allowList),
|
||||
registryUtil.parseModuleList(denyList)
|
||||
)
|
||||
}
|
||||
|
||||
it("allows module with no allow/deny list provided", function() {
|
||||
checkList("abc","1.2.3",[],[]).should.be.true();
|
||||
})
|
||||
it("defaults allow to * when only deny list is provided", function() {
|
||||
checkList("abc","1.2.3",["*"],["def"]).should.be.true();
|
||||
checkList("def","1.2.3",["*"],["def"]).should.be.false();
|
||||
})
|
||||
it("uses most specific matching rule", function() {
|
||||
checkList("abc","1.2.3",["ab*"],["a*"]).should.be.true();
|
||||
checkList("def","1.2.3",["d*"],["de*"]).should.be.false();
|
||||
})
|
||||
it("checks version string using semver rules", function() {
|
||||
// Deny
|
||||
checkList("abc","1.2.3",["abc@1.2.2"],["*"]).should.be.false();
|
||||
checkList("abc","1.2.3",["abc@1.2.4"],["*"]).should.be.false();
|
||||
checkList("abc","1.2.3",["abc@>1.2.3"],["*"]).should.be.false();
|
||||
checkList("abc","1.2.3",["abc@>=1.2.3"],["abc"]).should.be.false();
|
||||
|
||||
|
||||
checkList("node-red-contrib-foo","1.2.3",["*"],["*contrib*"]).should.be.false();
|
||||
|
||||
|
||||
// Allow
|
||||
checkList("abc","1.2.3",["abc@1.2.3"],["*"]).should.be.true();
|
||||
checkList("abc","1.2.3",["abc@<1.2.4"],["*"]).should.be.true();
|
||||
checkList("abc","1.2.3",["abc"],["abc@>1.2.3"]).should.be.true();
|
||||
checkList("abc","1.2.3",["abc"],["abc@<1.2.3||>1.2.3"]).should.be.true();
|
||||
checkList("node-red-contrib-foo","1.2.3",["*contrib*"],["*"]).should.be.true();
|
||||
})
|
||||
|
||||
})
|
||||
});
|
||||
Reference in New Issue
Block a user