Initial plugin runtime api implementation

This commit is contained in:
Nick O'Leary
2020-12-10 16:01:55 +00:00
parent bebebaa3dd
commit a006b52052
25 changed files with 1026 additions and 121 deletions

View 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)
}
});
});
});

View File

@@ -0,0 +1,153 @@
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,
"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": []
}
]
))
})
})
});

View 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" } }))
})
});
});
});

View 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
})
});