mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Merge branch 'dev' into function-modules
This commit is contained in:
111
test/unit/@node-red/editor-api/lib/admin/plugins_spec.js
Normal file
111
test/unit/@node-red/editor-api/lib/admin/plugins_spec.js
Normal file
@@ -0,0 +1,111 @@
|
||||
const should = require("should");
|
||||
const request = require('supertest');
|
||||
const express = require('express');
|
||||
const bodyParser = require("body-parser");
|
||||
|
||||
var app;
|
||||
|
||||
var NR_TEST_UTILS = require("nr-test-utils");
|
||||
|
||||
var plugins = NR_TEST_UTILS.require("@node-red/editor-api/lib/admin/plugins");
|
||||
|
||||
describe("api/editor/plugins", function() {
|
||||
const pluginList = [
|
||||
{
|
||||
"id": "test-module/test-set",
|
||||
"enabled": true,
|
||||
"local": 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,
|
||||
"plugins": []
|
||||
}
|
||||
];
|
||||
const pluginConfigs = `
|
||||
<!-- --- [red-plugin:test-module/test-set] --- -->
|
||||
test-module-config`;
|
||||
|
||||
const pluginCatalogs = { "test-module": {"foo": "bar"}};
|
||||
|
||||
before(function() {
|
||||
app = express();
|
||||
app.use(bodyParser.json());
|
||||
app.get("/plugins",plugins.getAll);
|
||||
app.get("/plugins/messages",plugins.getCatalogs);
|
||||
|
||||
plugins.init({
|
||||
plugins: {
|
||||
getPluginList: async function() { return pluginList },
|
||||
getPluginConfigs: async function() { return pluginConfigs },
|
||||
getPluginCatalogs: async function() { return pluginCatalogs }
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
it('returns the list of plugins', function(done) {
|
||||
request(app)
|
||||
.get("/plugins")
|
||||
.set('Accept', 'application/json')
|
||||
.expect(200)
|
||||
.end(function(err,res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
try {
|
||||
JSON.stringify(res.body).should.eql(JSON.stringify(pluginList));
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err)
|
||||
}
|
||||
});
|
||||
});
|
||||
it('returns the plugin configs', function(done) {
|
||||
request(app)
|
||||
.get("/plugins")
|
||||
.set('Accept', 'text/html')
|
||||
.expect(200)
|
||||
.expect(pluginConfigs)
|
||||
.end(function(err,res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('returns the plugin catalogs', function(done) {
|
||||
request(app)
|
||||
.get("/plugins/messages")
|
||||
.set('Accept', 'application/json')
|
||||
.expect(200)
|
||||
.end(function(err,res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
try {
|
||||
JSON.stringify(res.body).should.eql(JSON.stringify(pluginCatalogs));
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err)
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
@@ -33,11 +33,11 @@ describe("api/editor/theme", function () {
|
||||
theme.init({settings: {}});
|
||||
fs.statSync.restore();
|
||||
});
|
||||
it("applies the default theme", function () {
|
||||
it("applies the default theme", async function () {
|
||||
var result = theme.init({});
|
||||
should.not.exist(result);
|
||||
|
||||
var context = theme.context();
|
||||
var context = await theme.context();
|
||||
context.should.have.a.property("page");
|
||||
context.page.should.have.a.property("title", "Node-RED");
|
||||
context.page.should.have.a.property("favicon", "favicon.ico");
|
||||
@@ -52,7 +52,7 @@ describe("api/editor/theme", function () {
|
||||
should.not.exist(theme.settings());
|
||||
});
|
||||
|
||||
it("picks up custom theme", function () {
|
||||
it("picks up custom theme", async function () {
|
||||
theme.init({
|
||||
editorTheme: {
|
||||
page: {
|
||||
@@ -104,7 +104,7 @@ describe("api/editor/theme", function () {
|
||||
|
||||
theme.app();
|
||||
|
||||
var context = theme.context();
|
||||
var context = await theme.context();
|
||||
context.should.have.a.property("page");
|
||||
context.page.should.have.a.property("title", "Test Page Title");
|
||||
context.page.should.have.a.property("favicon", "theme/favicon/favicon");
|
||||
|
155
test/unit/@node-red/registry/lib/plugins_spec.js
Normal file
155
test/unit/@node-red/registry/lib/plugins_spec.js
Normal file
@@ -0,0 +1,155 @@
|
||||
|
||||
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", moduleId => modules[moduleId]);
|
||||
sinon.stub(registry,"getModuleList", () => 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": []
|
||||
}
|
||||
]
|
||||
))
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
});
|
68
test/unit/@node-red/runtime/lib/api/plugins_spec.js
Normal file
68
test/unit/@node-red/runtime/lib/api/plugins_spec.js
Normal file
@@ -0,0 +1,68 @@
|
||||
const should = require("should");
|
||||
const sinon = require("sinon");
|
||||
|
||||
const NR_TEST_UTILS = require("nr-test-utils");
|
||||
const plugins = NR_TEST_UTILS.require("@node-red/runtime/lib/api/plugins")
|
||||
|
||||
const mockLog = () => ({
|
||||
log: sinon.stub(),
|
||||
debug: sinon.stub(),
|
||||
trace: sinon.stub(),
|
||||
warn: sinon.stub(),
|
||||
info: sinon.stub(),
|
||||
metric: sinon.stub(),
|
||||
audit: sinon.stub(),
|
||||
_: function() { return "abc"}
|
||||
})
|
||||
|
||||
describe("runtime-api/plugins", function() {
|
||||
const pluginList = [{id:"one",module:'test-module'},{id:"two",module:"node-red"}];
|
||||
const pluginConfigs = "123";
|
||||
|
||||
describe("getPluginList", function() {
|
||||
it("gets the plugin list", function() {
|
||||
plugins.init({
|
||||
log: mockLog(),
|
||||
plugins: {
|
||||
getPluginList: function() { return pluginList}
|
||||
}
|
||||
});
|
||||
return plugins.getPluginList({}).then(function(result) {
|
||||
result.should.eql(pluginList);
|
||||
})
|
||||
});
|
||||
});
|
||||
describe("getPluginConfigs", function() {
|
||||
it("gets the plugin configs", function() {
|
||||
plugins.init({
|
||||
log: mockLog(),
|
||||
plugins: {
|
||||
getPluginConfigs: function() { return pluginConfigs}
|
||||
}
|
||||
});
|
||||
return plugins.getPluginConfigs({}).then(function(result) {
|
||||
result.should.eql(pluginConfigs);
|
||||
})
|
||||
});
|
||||
});
|
||||
describe("getPluginCatalogs", function() {
|
||||
it("gets the plugin catalogs", function() {
|
||||
plugins.init({
|
||||
log: mockLog(),
|
||||
plugins: {
|
||||
getPluginList: function() { return pluginList}
|
||||
},
|
||||
i18n: {
|
||||
i: {
|
||||
changeLanguage: function(lang,done) { done && done() },
|
||||
getResourceBundle: function(lang, id) { return {lang,id}}
|
||||
}
|
||||
}
|
||||
});
|
||||
return plugins.getPluginCatalogs({lang: "en-US"}).then(function(result) {
|
||||
JSON.stringify(result).should.eql(JSON.stringify({ one: { lang: "en-US", id: "one" } }))
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
});
|
13
test/unit/@node-red/runtime/lib/plugins_spec.js
Normal file
13
test/unit/@node-red/runtime/lib/plugins_spec.js
Normal file
@@ -0,0 +1,13 @@
|
||||
const should = require("should");
|
||||
const sinon = require("sinon");
|
||||
const NR_TEST_UTILS = require("nr-test-utils");
|
||||
|
||||
const plugins = NR_TEST_UTILS.require("@node-red/runtime/lib/plugins");
|
||||
|
||||
describe("runtime/plugins",function() {
|
||||
|
||||
it.skip("delegates all functions to registry module", function() {
|
||||
// There's no easy way to test this as we can't stub the registry functions
|
||||
// before the plugin module gets a reference to them
|
||||
})
|
||||
});
|
@@ -164,6 +164,13 @@ describe("@node-red/util/util", function() {
|
||||
var v2 = util.getMessageProperty({a:"foo"},"a");
|
||||
v2.should.eql("foo");
|
||||
});
|
||||
it('retrieves a nested property', function() {
|
||||
var v = util.getMessageProperty({a:"foo",b:{foo:1,bar:2}},"msg.b[msg.a]");
|
||||
v.should.eql(1);
|
||||
var v2 = util.getMessageProperty({a:"bar",b:{foo:1,bar:2}},"b[msg.a]");
|
||||
v2.should.eql(2);
|
||||
});
|
||||
|
||||
it('should return undefined if property does not exist', function() {
|
||||
var v = util.getMessageProperty({a:"foo"},"msg.b");
|
||||
should.not.exist(v);
|
||||
@@ -331,7 +338,18 @@ describe("@node-red/util/util", function() {
|
||||
msg.a[0].should.eql(1);
|
||||
msg.a[1].should.eql(3);
|
||||
})
|
||||
|
||||
it('handles nested message property references', function() {
|
||||
var obj = {a:"foo",b:{}};
|
||||
var result = util.setObjectProperty(obj,"b[msg.a]","bar");
|
||||
result.should.be.true();
|
||||
obj.b.should.have.property("foo","bar");
|
||||
});
|
||||
it('handles nested message property references', function() {
|
||||
var obj = {a:"foo",b:{"foo":[0,0,0]}};
|
||||
var result = util.setObjectProperty(obj,"b[msg.a][2]","bar");
|
||||
result.should.be.true();
|
||||
obj.b.foo.should.eql([0,0,"bar"])
|
||||
});
|
||||
});
|
||||
|
||||
describe('evaluateNodeProperty', function() {
|
||||
@@ -459,13 +477,24 @@ describe("@node-red/util/util", function() {
|
||||
// console.log(result);
|
||||
result.should.eql(expected);
|
||||
}
|
||||
|
||||
function testInvalid(input) {
|
||||
function testABCWithMessage(input,msg,expected) {
|
||||
var result = util.normalisePropertyExpression(input,msg);
|
||||
// console.log("+",input);
|
||||
// console.log(result);
|
||||
result.should.eql(expected);
|
||||
}
|
||||
function testInvalid(input,msg) {
|
||||
/*jshint immed: false */
|
||||
(function() {
|
||||
util.normalisePropertyExpression(input);
|
||||
util.normalisePropertyExpression(input,msg);
|
||||
}).should.throw();
|
||||
}
|
||||
function testToString(input,msg,expected) {
|
||||
var result = util.normalisePropertyExpression(input,msg,true);
|
||||
console.log("+",input);
|
||||
console.log(result);
|
||||
result.should.eql(expected);
|
||||
}
|
||||
it('pass a.b.c',function() { testABC('a.b.c',['a','b','c']); })
|
||||
it('pass a["b"]["c"]',function() { testABC('a["b"]["c"]',['a','b','c']); })
|
||||
it('pass a["b"].c',function() { testABC('a["b"].c',['a','b','c']); })
|
||||
@@ -479,12 +508,25 @@ describe("@node-red/util/util", function() {
|
||||
it("pass 'a.b'[1]",function() { testABC("'a.b'[1]",['a.b',1]); })
|
||||
it("pass 'a.b'.c",function() { testABC("'a.b'.c",['a.b','c']); })
|
||||
|
||||
it("pass a[msg.b]",function() { testABC("a[msg.b]",["a",["msg","b"]]); })
|
||||
it("pass a[msg[msg.b]]",function() { testABC("a[msg[msg.b]]",["a",["msg",["msg","b"]]]); })
|
||||
it("pass a[msg.b]",function() { testABC("a[msg.b]",["a",["msg","b"]]); })
|
||||
it("pass a[msg.b]",function() { testABC("a[msg.b]",["a",["msg","b"]]); })
|
||||
it("pass a[msg['b]\"[']]",function() { testABC("a[msg['b]\"[']]",["a",["msg","b]\"["]]); })
|
||||
it("pass a[msg['b][']]",function() { testABC("a[msg['b][']]",["a",["msg","b]["]]); })
|
||||
it("pass b[msg.a][2]",function() { testABC("b[msg.a][2]",["b",["msg","a"],2])})
|
||||
|
||||
it("pass b[msg.a][2] (with message)",function() { testABCWithMessage("b[msg.a][2]",{a: "foo"},["b","foo",2])})
|
||||
|
||||
it('pass a.$b.c',function() { testABC('a.$b.c',['a','$b','c']); })
|
||||
it('pass a["$b"].c',function() { testABC('a["$b"].c',['a','$b','c']); })
|
||||
it('pass a._b.c',function() { testABC('a._b.c',['a','_b','c']); })
|
||||
it('pass a["_b"].c',function() { testABC('a["_b"].c',['a','_b','c']); })
|
||||
|
||||
it("pass a['a.b[0]'].c",function() { testToString("a['a.b[0]'].c",null,'a["a.b[0]"]["c"]'); })
|
||||
it("pass a.b.c",function() { testToString("a.b.c",null,'a["b"]["c"]'); })
|
||||
it('pass a[msg.c][0]["fred"]',function() { testToString('a[msg.c][0]["fred"]',{c:"123"},'a["123"][0]["fred"]'); })
|
||||
|
||||
it("fail a'b'.c",function() { testInvalid("a'b'.c"); })
|
||||
it("fail a['b'.c",function() { testInvalid("a['b'.c"); })
|
||||
it("fail a[]",function() { testInvalid("a[]"); })
|
||||
@@ -505,6 +547,12 @@ describe("@node-red/util/util", function() {
|
||||
it("fail a['']",function() { testInvalid("a['']"); })
|
||||
it("fail 'a.b'c",function() { testInvalid("'a.b'c"); })
|
||||
it("fail <blank>",function() { testInvalid("");})
|
||||
it("fail a[b]",function() { testInvalid("a[b]"); })
|
||||
it("fail a[msg.]",function() { testInvalid("a[msg.]"); })
|
||||
it("fail a[msg[]",function() { testInvalid("a[msg[]"); })
|
||||
it("fail a[msg.[]]",function() { testInvalid("a[msg.[]]"); })
|
||||
it("fail a[msg['af]]",function() { testInvalid("a[msg['af]]"); })
|
||||
it("fail b[msg.undefined][2] (with message)",function() { testInvalid("b[msg.undefined][2]",{})})
|
||||
|
||||
});
|
||||
|
||||
@@ -983,4 +1031,5 @@ describe("@node-red/util/util", function() {
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
Reference in New Issue
Block a user