mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
update from upstream
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
"use strict";
|
||||
const should = require("should");
|
||||
const helper = require("node-red-node-test-helper");
|
||||
const { doesNotThrow } = require("should");
|
||||
const mqttNodes = require("nr-test-utils").require("@node-red/nodes/core/network/10-mqtt.js");
|
||||
const BROKER_HOST = process.env.MQTT_BROKER_SERVER || "localhost";
|
||||
const BROKER_PORT = process.env.MQTT_BROKER_PORT || 1883;
|
||||
@@ -72,8 +73,7 @@ describe('MQTT Nodes', function () {
|
||||
done();
|
||||
});
|
||||
}
|
||||
|
||||
/** Conditional test runner (only run if skipTests=false) */
|
||||
// Conditional test runner (only run if skipTests=false)
|
||||
function itConditional(title, test) {
|
||||
return !skipTests ? it(title, test) : it.skip(title, test);
|
||||
}
|
||||
@@ -92,7 +92,8 @@ describe('MQTT Nodes', function () {
|
||||
options.expectMsg = Object.assign({}, options.sendMsg);
|
||||
testSendRecv({}, { datatype: "auto", topicType: "static" }, {}, options, { done: done });
|
||||
});
|
||||
itConditional('should send JSON and receive string (auto)', function (done) {
|
||||
//Prior to V3, "auto" mode would only parse to string or buffer.
|
||||
itConditional('should send JSON and receive string (auto mode)', function (done) {
|
||||
if (skipTests) { return this.skip() }
|
||||
this.timeout = 2000;
|
||||
const options = {}
|
||||
@@ -104,7 +105,44 @@ describe('MQTT Nodes', function () {
|
||||
options.expectMsg = Object.assign({}, options.sendMsg);
|
||||
testSendRecv({}, { datatype: "auto", topicType: "static" }, {}, options, { done: done });
|
||||
})
|
||||
itConditional('should send JSON and receive string (utf8)', function (done) {
|
||||
//In V3, "auto" mode should try to parse JSON, then string and fall back to buffer
|
||||
itConditional('should send JSON and receive object (auto-detect mode)', function (done) {
|
||||
if (skipTests) { return this.skip() }
|
||||
this.timeout = 2000;
|
||||
const options = {}
|
||||
options.sendMsg = {
|
||||
topic: nextTopic(),
|
||||
payload: '{"prop":"value1", "num":1}',
|
||||
qos: 1
|
||||
}
|
||||
options.expectMsg = Object.assign({}, options.sendMsg);
|
||||
options.expectMsg.payload = JSON.parse(options.sendMsg.payload);
|
||||
testSendRecv({}, { datatype: "auto-detect", topicType: "static" }, {}, options, { done: done });
|
||||
})
|
||||
itConditional('should send invalid JSON and receive string (auto mode)', function (done) {
|
||||
if (skipTests) { return this.skip() }
|
||||
this.timeout = 2000;
|
||||
const options = {}
|
||||
options.sendMsg = {
|
||||
topic: nextTopic(),
|
||||
payload: '{prop:"value3", "num":3}'// send invalid JSON ...
|
||||
}
|
||||
options.expectMsg = Object.assign({}, options.sendMsg);//expect same payload
|
||||
testSendRecv({}, { datatype: "auto", topicType: "static" }, {}, options, { done: done });
|
||||
});
|
||||
itConditional('should send invalid JSON and receive string (auto-detect mode)', function (done) {
|
||||
if (skipTests) { return this.skip() }
|
||||
this.timeout = 2000;
|
||||
const options = {}
|
||||
options.sendMsg = {
|
||||
topic: nextTopic(),
|
||||
payload: '{prop:"value3", "num":3}'// send invalid JSON ...
|
||||
}
|
||||
options.expectMsg = Object.assign({}, options.sendMsg);//expect same payload
|
||||
testSendRecv({}, { datatype: "auto-detect", topicType: "static" }, {}, options, { done: done });
|
||||
});
|
||||
|
||||
itConditional('should send JSON and receive string (utf8 mode)', function (done) {
|
||||
if (skipTests) { return this.skip() }
|
||||
this.timeout = 2000;
|
||||
const options = {}
|
||||
@@ -116,7 +154,7 @@ describe('MQTT Nodes', function () {
|
||||
options.expectMsg = Object.assign({}, options.sendMsg);
|
||||
testSendRecv({}, { datatype: "utf8", topicType: "static" }, {}, options, { done: done });
|
||||
});
|
||||
itConditional('should send JSON and receive Object (json)', function (done) {
|
||||
itConditional('should send JSON and receive Object (json mode)', function (done) {
|
||||
if (skipTests) { return this.skip() }
|
||||
this.timeout = 2000;
|
||||
const options = {}
|
||||
@@ -127,7 +165,31 @@ describe('MQTT Nodes', function () {
|
||||
options.expectMsg = Object.assign({}, options.sendMsg, { payload: { "prop": "value3", "num": 3 } });//expect an object
|
||||
testSendRecv({}, { datatype: "json", topicType: "static" }, {}, options, { done: done });
|
||||
});
|
||||
itConditional('should send String and receive Buffer (buffer)', function (done) {
|
||||
itConditional('should send invalid JSON and raise error (json mode)', function (done) {
|
||||
if (skipTests) { return this.skip() }
|
||||
this.timeout = 2000;
|
||||
const options = {}
|
||||
options.sendMsg = {
|
||||
topic: nextTopic(),
|
||||
payload: '{prop:"value3", "num":3}', // send invalid JSON ...
|
||||
}
|
||||
const hooks = { done: done, beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
hooks.afterLoad = (helperNode, mqttBroker, mqttIn, mqttOut) => {
|
||||
helperNode.on("input", function (msg) {
|
||||
try {
|
||||
msg.should.have.a.property("error").type("object");
|
||||
msg.error.should.have.a.property("source").type("object");
|
||||
msg.error.source.should.have.a.property("id", mqttIn.id);
|
||||
done();
|
||||
} catch (err) {
|
||||
done(err)
|
||||
}
|
||||
});
|
||||
return true; //handled
|
||||
}
|
||||
testSendRecv({}, { datatype: "json", topicType: "static" }, {}, options, hooks);
|
||||
});
|
||||
itConditional('should send String and receive Buffer (buffer mode)', function (done) {
|
||||
if (skipTests) { return this.skip() }
|
||||
this.timeout = 2000;
|
||||
const options = {}
|
||||
@@ -138,7 +200,7 @@ describe('MQTT Nodes', function () {
|
||||
options.expectMsg = Object.assign({}, options.sendMsg, { payload: Buffer.from(options.sendMsg.payload) });//expect Buffer.from(msg.payload)
|
||||
testSendRecv({}, { datatype: "buffer", topicType: "static" }, {}, options, { done: done });
|
||||
});
|
||||
itConditional('should send utf8 Buffer and receive String (auto)', function (done) {
|
||||
itConditional('should send utf8 Buffer and receive String (auto mode)', function (done) {
|
||||
if (skipTests) { return this.skip() }
|
||||
this.timeout = 2000;
|
||||
const options = {}
|
||||
@@ -149,7 +211,7 @@ describe('MQTT Nodes', function () {
|
||||
options.expectMsg = Object.assign({}, options.sendMsg, { payload: "x y z" });//set expected payload to "x y z"
|
||||
testSendRecv({}, { datatype: "auto", topicType: "static" }, {}, options, { done: done });
|
||||
});
|
||||
itConditional('should send non utf8 Buffer and receive Buffer (auto)', function (done) {
|
||||
itConditional('should send non utf8 Buffer and receive Buffer (auto mode)', function (done) {
|
||||
if (skipTests) { return this.skip() }
|
||||
this.timeout = 2000;
|
||||
const options = {}
|
||||
@@ -158,7 +220,7 @@ describe('MQTT Nodes', function () {
|
||||
topic: nextTopic(),
|
||||
payload: Buffer.from([0xC0, 0xC1, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF]) //non valid UTF8
|
||||
}
|
||||
options.expectMsg = Object.assign({}, options.sendMsg);
|
||||
options.expectMsg = Object.assign({}, options.sendMsg, {payload: Buffer.from([0xC0, 0xC1, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF])});
|
||||
testSendRecv({}, { datatype: "auto", topicType: "static" }, {}, options, hooks);
|
||||
});
|
||||
itConditional('should send/receive all v5 flags and settings', function (done) {
|
||||
@@ -168,16 +230,16 @@ describe('MQTT Nodes', function () {
|
||||
const options = {}
|
||||
const hooks = { done: done, beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
options.sendMsg = {
|
||||
topic: t + "/command", payload: Buffer.from("v5"), qos: 1, retain: true,
|
||||
topic: t + "/command", payload: Buffer.from('{"version":"v5"}'), qos: 1, retain: true,
|
||||
responseTopic: t + "/response",
|
||||
userProperties: { prop1: "val1" },
|
||||
contentType: "application/json",
|
||||
contentType: "text/plain",
|
||||
correlationData: Buffer.from([1, 2, 3]),
|
||||
payloadFormatIndicator: true,
|
||||
messageExpiryInterval: 2000,
|
||||
}
|
||||
options.expectMsg = Object.assign({}, options.sendMsg);
|
||||
options.expectMsg.payload = options.expectMsg.payload.toString(); //auto mode + payloadFormatIndicator should make a string
|
||||
options.expectMsg.payload = options.expectMsg.payload.toString(); //auto mode + payloadFormatIndicator + contentType: "text/plain" should make a string
|
||||
delete options.expectMsg.payloadFormatIndicator; //Seems mqtt.js only publishes payloadFormatIndicator the will msg
|
||||
const inOptions = {
|
||||
datatype: "auto", topicType: "static",
|
||||
@@ -185,6 +247,109 @@ describe('MQTT Nodes', function () {
|
||||
}
|
||||
testSendRecv({ protocolVersion: 5 }, inOptions, {}, options, hooks);
|
||||
});
|
||||
itConditional('should send regular string with v5 media type "text/plain" and receive a string (auto mode)', function (done) {
|
||||
if (skipTests) { return this.skip() }
|
||||
this.timeout = 2000;
|
||||
const options = {}
|
||||
const hooks = { done: done, beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
options.sendMsg = {
|
||||
topic: nextTopic(), payload: "abc", contentType: "text/plain"
|
||||
}
|
||||
options.expectMsg = Object.assign({}, options.sendMsg);
|
||||
testSendRecv({ protocolVersion: 5 }, { datatype: "auto", topicType: "static" }, {}, options, hooks);
|
||||
});
|
||||
itConditional('should send JSON with v5 media type "text/plain" and receive a string (auto mode)', function (done) {
|
||||
if (skipTests) { return this.skip() }
|
||||
this.timeout = 2000;
|
||||
const options = {}
|
||||
const hooks = { done: done, beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
options.sendMsg = {
|
||||
topic: nextTopic(), payload: '{"prop":"val"}', contentType: "text/plain"
|
||||
}
|
||||
options.expectMsg = Object.assign({}, options.sendMsg);
|
||||
testSendRecv({ protocolVersion: 5 }, { datatype: "auto", topicType: "static" }, {}, options, hooks);
|
||||
});
|
||||
itConditional('should send JSON with v5 media type "text/plain" and receive a string (auto-detect mode)', function (done) {
|
||||
if (skipTests) { return this.skip() }
|
||||
this.timeout = 2000;
|
||||
const options = {}
|
||||
const hooks = { done: done, beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
options.sendMsg = {
|
||||
topic: nextTopic(), payload: '{"prop":"val"}', contentType: "text/plain"
|
||||
}
|
||||
options.expectMsg = Object.assign({}, options.sendMsg);
|
||||
testSendRecv({ protocolVersion: 5 }, { datatype: "auto-detect", topicType: "static" }, {}, options, hooks);
|
||||
});
|
||||
itConditional('should send JSON with v5 media type "application/json" and receive an object (auto-detect mode)', function (done) {
|
||||
if (skipTests) { return this.skip() }
|
||||
this.timeout = 2000;
|
||||
const options = {}
|
||||
const hooks = { done: done, beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
options.sendMsg = {
|
||||
topic: nextTopic(), payload: '{"prop":"val"}', contentType: "application/json",
|
||||
}
|
||||
options.expectMsg = Object.assign({}, options.sendMsg, { payload: JSON.parse(options.sendMsg.payload)});
|
||||
testSendRecv({ protocolVersion: 5 }, { datatype: "auto-detect", topicType: "static" }, {}, options, hooks);
|
||||
});
|
||||
itConditional('should send invalid JSON with v5 media type "application/json" and raise an error (auto mode)', function (done) {
|
||||
if (skipTests) { return this.skip() }
|
||||
this.timeout = 2000;
|
||||
const options = {}
|
||||
options.sendMsg = {
|
||||
topic: nextTopic(),
|
||||
payload: '{prop:"value3", "num":3}', contentType: "application/json", // send invalid JSON ...
|
||||
}
|
||||
const hooks = { done: done, beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
hooks.afterLoad = (helperNode, mqttBroker, mqttIn, mqttOut) => {
|
||||
helperNode.on("input", function (msg) {
|
||||
try {
|
||||
msg.should.have.a.property("error").type("object");
|
||||
msg.error.should.have.a.property("source").type("object");
|
||||
msg.error.source.should.have.a.property("id", mqttIn.id);
|
||||
done();
|
||||
} catch (err) {
|
||||
done(err)
|
||||
}
|
||||
});
|
||||
return true; //handled
|
||||
}
|
||||
testSendRecv({ protocolVersion: 5 }, { datatype: "auto", topicType: "static" }, {}, options, hooks);
|
||||
});
|
||||
|
||||
itConditional('should send buffer with v5 media type "application/json" and receive an object (auto-detect mode)', function (done) {
|
||||
if (skipTests) { return this.skip() }
|
||||
this.timeout = 2000;
|
||||
const options = {}
|
||||
const hooks = { done: done, beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
options.sendMsg = {
|
||||
topic: nextTopic(), payload: Buffer.from([0x7b,0x22,0x70,0x72,0x6f,0x70,0x22,0x3a,0x22,0x76,0x61,0x6c,0x22,0x7d]), contentType: "application/json",
|
||||
}
|
||||
options.expectMsg = Object.assign({}, options.sendMsg, { payload: {"prop":"val"}});
|
||||
testSendRecv({ protocolVersion: 5 }, { datatype: "auto-detect", topicType: "static" }, {}, options, hooks);
|
||||
});
|
||||
itConditional('should send buffer with v5 media type "text/plain" and receive a string (auto mode)', function (done) {
|
||||
if (skipTests) { return this.skip() }
|
||||
this.timeout = 2000;
|
||||
const options = {}
|
||||
const hooks = { done: done, beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
options.sendMsg = {
|
||||
topic: nextTopic(), payload: Buffer.from([0x7b,0x22,0x70,0x72,0x6f,0x70,0x22,0x3a,0x22,0x76,0x61,0x6c,0x22,0x7d]), contentType: "text/plain",
|
||||
}
|
||||
options.expectMsg = Object.assign({}, options.sendMsg, { payload: '{"prop":"val"}'});
|
||||
testSendRecv({ protocolVersion: 5 }, { datatype: "auto", topicType: "static" }, {}, options, hooks);
|
||||
});
|
||||
itConditional('should send buffer with v5 media type "application/zip" and receive a buffer (auto mode)', function (done) {
|
||||
if (skipTests) { return this.skip() }
|
||||
this.timeout = 2000;
|
||||
const options = {}
|
||||
const hooks = { done: done, beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
options.sendMsg = {
|
||||
topic: nextTopic(), payload: Buffer.from([0x7b,0x22,0x70,0x72,0x6f,0x70,0x22,0x3a,0x22,0x76,0x61,0x6c,0x22,0x7d]), contentType: "application/zip",
|
||||
}
|
||||
options.expectMsg = Object.assign({}, options.sendMsg, { payload: Buffer.from([0x7b,0x22,0x70,0x72,0x6f,0x70,0x22,0x3a,0x22,0x76,0x61,0x6c,0x22,0x7d])});
|
||||
testSendRecv({ protocolVersion: 5 }, { datatype: "auto", topicType: "static" }, {}, options, hooks);
|
||||
});
|
||||
|
||||
itConditional('should subscribe dynamically via action', function (done) {
|
||||
if (skipTests) { return this.skip() }
|
||||
this.timeout = 2000;
|
||||
@@ -278,7 +443,8 @@ describe('MQTT Nodes', function () {
|
||||
const mqttOut = helper.getNode("mqtt.out");
|
||||
const mqttBroker1 = helper.getNode("mqtt.broker1");
|
||||
const mqttBroker2 = helper.getNode("mqtt.broker2");
|
||||
waitBrokerConnect([mqttBroker1, mqttBroker2], function connected() {
|
||||
waitBrokerConnect([mqttBroker1, mqttBroker2])
|
||||
.then(() => {
|
||||
//connected - add the on handler and call to disconnect
|
||||
helperNode.on("input", function (msg) {
|
||||
try {
|
||||
@@ -292,6 +458,7 @@ describe('MQTT Nodes', function () {
|
||||
})
|
||||
mqttOut.receive({ "action": "disconnect" });//close broker2
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
});
|
||||
itConditional('should publish will message', function (done) {
|
||||
@@ -307,7 +474,8 @@ describe('MQTT Nodes', function () {
|
||||
const helperNode = helper.getNode("helper.node");
|
||||
const mqttBroker1 = helper.getNode("mqtt.broker1");
|
||||
const mqttBroker2 = helper.getNode("mqtt.broker2");
|
||||
waitBrokerConnect([mqttBroker1, mqttBroker2], function connected() {
|
||||
waitBrokerConnect([mqttBroker1, mqttBroker2])
|
||||
.then(() => {
|
||||
//connected - add the on handler and call to disconnect
|
||||
helperNode.on("input", function (msg) {
|
||||
try {
|
||||
@@ -321,6 +489,7 @@ describe('MQTT Nodes', function () {
|
||||
});
|
||||
mqttBroker2.client.end(true); //force closure
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
});
|
||||
itConditional('should publish will message with V5 properties', function (done) {
|
||||
@@ -362,7 +531,8 @@ describe('MQTT Nodes', function () {
|
||||
const helperNode = helper.getNode("helper.node");
|
||||
const mqttBroker1 = helper.getNode("mqtt.broker1");
|
||||
const mqttBroker2 = helper.getNode("mqtt.broker2");
|
||||
waitBrokerConnect([mqttBroker1, mqttBroker2], function connected() {
|
||||
waitBrokerConnect([mqttBroker1, mqttBroker2])
|
||||
.then(() => {
|
||||
//connected - add the on handler and call to disconnect
|
||||
helperNode.on("input", function (msg) {
|
||||
try {
|
||||
@@ -374,6 +544,7 @@ describe('MQTT Nodes', function () {
|
||||
});
|
||||
mqttBroker2.client.end(true); //force closure
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
});
|
||||
//#endregion ADVANCED TESTS
|
||||
@@ -431,17 +602,24 @@ function testSendRecv(brokerOptions, inNodeOptions, outNodeOptions, options, hoo
|
||||
}
|
||||
});
|
||||
}
|
||||
waitBrokerConnect(mqttBroker, function () {
|
||||
waitBrokerConnect(mqttBroker)
|
||||
.then(() => {
|
||||
//finally, connected!
|
||||
if (hooks.afterConnect) {
|
||||
let handled = hooks.afterConnect(helperNode, mqttBroker, mqttIn, mqttOut);
|
||||
if (handled) { return }
|
||||
}
|
||||
if (mqttIn.isDynamic) {
|
||||
mqttIn.receive({ "action": "subscribe", "topic": sendMsg.topic })
|
||||
if(sendMsg.topic) {
|
||||
if (mqttIn.isDynamic) {
|
||||
mqttIn.receive({ "action": "subscribe", "topic": sendMsg.topic })
|
||||
}
|
||||
mqttOut.receive(sendMsg);
|
||||
}
|
||||
mqttOut.receive(sendMsg);
|
||||
})
|
||||
.catch((e) => {
|
||||
if (hooks.done) { hooks.done(e); }
|
||||
else { throw e; }
|
||||
});
|
||||
} catch (err) {
|
||||
if (hooks.done) { hooks.done(err); }
|
||||
else { throw err; }
|
||||
@@ -463,14 +641,16 @@ function buildBasicMQTTSendRecvFlow(brokerOptions, inOptions, outOptions) {
|
||||
const inNode = buildMQTTInNode(inOptions.id, inOptions.name, inOptions.broker || broker.id, inOptions.topic, inOptions, ["helper.node"]);
|
||||
const outNode = buildMQTTOutNode(outOptions.id, outOptions.name, outOptions.broker || broker.id, outOptions.topic, outOptions);
|
||||
const helper = buildNode("helper", "helper.node", "helper_node", {});
|
||||
const catchNode = buildNode("catch", "catch.node", "catch_node", {"scope": ["mqtt.in"]}, ["helper.node"]);
|
||||
return {
|
||||
nodes: {
|
||||
[broker.name]: broker,
|
||||
[inNode.name]: inNode,
|
||||
[outNode.name]: outNode,
|
||||
[helper.name]: helper,
|
||||
[catchNode.name]: catchNode,
|
||||
},
|
||||
flow: [broker, inNode, outNode, helper]
|
||||
flow: [broker, inNode, outNode, helper, catchNode]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -575,22 +755,33 @@ function compareMsgToExpected(msg, expectMsg) {
|
||||
if (hasProperty(expectMsg, "messageExpiryInterval")) { msg.should.have.property("messageExpiryInterval", expectMsg.messageExpiryInterval); }
|
||||
}
|
||||
|
||||
function waitBrokerConnect(broker, callback, timeLimit) {
|
||||
timeLimit = timeLimit || 2000;
|
||||
const brokers = Array.isArray(broker) ? broker : [broker];
|
||||
wait();
|
||||
function wait() {
|
||||
if (brokers.every(e => e.connected == true)) {
|
||||
callback(); //yey - connected!
|
||||
} else {
|
||||
timeLimit = timeLimit - 15;
|
||||
if (timeLimit <= 0) {
|
||||
throw new Error("Timeout waiting broker connect")
|
||||
function waitBrokerConnect(broker, timeLimit) {
|
||||
|
||||
let waitConnected = (broker, timeLimit) => {
|
||||
const brokers = Array.isArray(broker) ? broker : [broker];
|
||||
timeLimit = timeLimit || 1000;
|
||||
let timer, resolved = false;
|
||||
return new Promise( (resolve, reject) => {
|
||||
timer = wait();
|
||||
function wait() {
|
||||
if (brokers.every(e => e.connected == true)) {
|
||||
resolved = true;
|
||||
clearTimeout(timer);
|
||||
resolve();
|
||||
} else {
|
||||
timeLimit = timeLimit - 15;
|
||||
if (timeLimit <= 0) {
|
||||
if(!resolved) {
|
||||
reject("Timeout waiting broker connect")
|
||||
}
|
||||
}
|
||||
timer = setTimeout(wait, 15);
|
||||
return timer;
|
||||
}
|
||||
}
|
||||
setTimeout(wait, 15);
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
return waitConnected(broker, timeLimit);
|
||||
}
|
||||
|
||||
function hasProperty(obj, propName) {
|
||||
|
119
test/unit/@node-red/editor-api/lib/admin/diagnostics_spec.js
Normal file
119
test/unit/@node-red/editor-api/lib/admin/diagnostics_spec.js
Normal file
@@ -0,0 +1,119 @@
|
||||
const should = require("should");
|
||||
const request = require('supertest');
|
||||
const express = require('express');
|
||||
const bodyParser = require("body-parser");
|
||||
const sinon = require('sinon');
|
||||
|
||||
let app;
|
||||
|
||||
const NR_TEST_UTILS = require("nr-test-utils");
|
||||
const diagnostics = NR_TEST_UTILS.require("@node-red/editor-api/lib/admin/diagnostics");
|
||||
|
||||
describe("api/editor/diagnostics", function() {
|
||||
before(function() {
|
||||
app = express();
|
||||
app.use(bodyParser.json());
|
||||
app.get("/diagnostics",diagnostics.getReport);
|
||||
});
|
||||
|
||||
it('returns the diagnostics report when explicitly enabled', function(done) {
|
||||
const settings = { diagnostics: { ui: true, enabled: true } }
|
||||
const runtimeAPI = {
|
||||
diagnostics: {
|
||||
get: async function (opts) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
opts = opts || {}
|
||||
try {
|
||||
resolve({ opts: opts, a:1, b:2});
|
||||
} catch (error) {
|
||||
error.status = 500;
|
||||
reject(error);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
diagnostics.init(settings, runtimeAPI);
|
||||
|
||||
request(app)
|
||||
.get("/diagnostics")
|
||||
.expect(200)
|
||||
.end(function(err,res) {
|
||||
if (err || typeof res.error === "object") {
|
||||
return done(err || res.error);
|
||||
}
|
||||
res.should.have.property("statusCode",200);
|
||||
res.body.should.have.property("a",1);
|
||||
res.body.should.have.property("b",2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('returns the diagnostics report when not explicitly enabled (implicitly enabled)', function(done) {
|
||||
const settings = { diagnostics: { enabled: undefined } }
|
||||
const runtimeAPI = {
|
||||
diagnostics: {
|
||||
get: async function (opts) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
opts = opts || {}
|
||||
try {
|
||||
resolve({ opts: opts, a:3, b:4});
|
||||
} catch (error) {
|
||||
error.status = 500;
|
||||
reject(error);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
diagnostics.init(settings, runtimeAPI);
|
||||
|
||||
request(app)
|
||||
.get("/diagnostics")
|
||||
.expect(200)
|
||||
.end(function(err,res) {
|
||||
if (err || typeof res.error === "object") {
|
||||
return done(err || res.error);
|
||||
}
|
||||
res.should.have.property("statusCode",200);
|
||||
res.body.should.have.property("a",3);
|
||||
res.body.should.have.property("b",4);
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should error when setting is disabled', function(done) {
|
||||
const settings = { diagnostics: { ui: true, enabled: false } }
|
||||
const runtimeAPI = {
|
||||
diagnostics: {
|
||||
get: async function (opts) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
opts = opts || {}
|
||||
try {
|
||||
resolve({ opts: opts});
|
||||
} catch (error) {
|
||||
error.status = 500;
|
||||
reject(error);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
diagnostics.init(settings, runtimeAPI);
|
||||
|
||||
request(app)
|
||||
.get("/diagnostics")
|
||||
.expect(403)
|
||||
.end(function(err,res) {
|
||||
if (!err && typeof res.error !== "object") {
|
||||
return done(new Error("accessing diagnostics endpoint while disabled should raise error"));
|
||||
}
|
||||
res.should.have.property("statusCode",403);
|
||||
res.body.should.have.property("message","diagnostics are disabled");
|
||||
res.body.should.have.property("code","diagnostics.disabled");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
@@ -0,0 +1 @@
|
||||
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><path d="M10.004 14.499h20M10.004 46.503h20M10.004 22.5h20M10.004 30.501h20M10.004 38.502h20" stroke="#fff" stroke-width="2.9997000000000003"/></svg>
|
After Width: | Height: | Size: 236 B |
@@ -0,0 +1,5 @@
|
||||
<script>
|
||||
(function() {
|
||||
console.log("hello from loose1.html")
|
||||
})()
|
||||
</script>
|
@@ -0,0 +1,4 @@
|
||||
|
||||
(function() {
|
||||
console.log("hello from loose1.js")
|
||||
})()
|
@@ -0,0 +1 @@
|
||||
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><path d="M30.999 31.005v-3h-6.762s.812-12.397 1.162-14 .597-3.35 2.628-3.103 1.971 3.103 1.971 3.103l4.862-.016s-.783-3.984-2.783-5.984-7.946-1.7-9.633.03c-1.687 1.73-2.302 5.065-2.597 6.422-.588 4.5-.854 9.027-1.248 13.547h-8.6v3H18.1s-.812 12.398-1.162 14-.597 3.35-2.628 3.103-1.972-3.102-1.972-3.102l-4.862.015s.783 3.985 2.783 5.985c2 2 7.946 1.699 9.634-.031 1.687-1.73 2.302-5.065 2.597-6.422.587-4.5.854-9.027 1.248-13.547z" fill="#fff"/></svg>
|
After Width: | Height: | Size: 539 B |
@@ -0,0 +1 @@
|
||||
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><path d="M7 38.98v3.983h11v12l13-23H19l-.463.017c-1.28 4.048-5.066 6.983-9.537 6.983zm12-11.017h12l-13-23v12H7V20.9l2 .064c4.467 0 8.25 2.93 9.534 6.972zM6.95 24.22a6 6 0 1 1-.083 11.456" fill="#fff" style="isolation:auto;mix-blend-mode:normal"/></svg>
|
After Width: | Height: | Size: 339 B |
@@ -0,0 +1,5 @@
|
||||
<script>
|
||||
(function() {
|
||||
console.log("hello from loose2.html")
|
||||
})()
|
||||
</script>
|
@@ -0,0 +1,4 @@
|
||||
|
||||
(function() {
|
||||
console.log("hello from loose2.js")
|
||||
})()
|
@@ -0,0 +1 @@
|
||||
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><path d="M30.999 31.005v-3h-6.762s.812-12.397 1.162-14 .597-3.35 2.628-3.103 1.971 3.103 1.971 3.103l4.862-.016s-.783-3.984-2.783-5.984-7.946-1.7-9.633.03c-1.687 1.73-2.302 5.065-2.597 6.422-.588 4.5-.854 9.027-1.248 13.547h-8.6v3H18.1s-.812 12.398-1.162 14-.597 3.35-2.628 3.103-1.972-3.102-1.972-3.102l-4.862.015s.783 3.985 2.783 5.985c2 2 7.946 1.699 9.634-.031 1.687-1.73 2.302-5.065 2.597-6.422.587-4.5.854-9.027 1.248-13.547z" fill="#fff"/></svg>
|
After Width: | Height: | Size: 539 B |
@@ -0,0 +1,4 @@
|
||||
|
||||
(function() {
|
||||
console.log("hello from regular module main.js")
|
||||
})()
|
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "node-red-node-testnode",
|
||||
"version": "1.0.0",
|
||||
"description": "A node-red node that does nothing other than exist",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [
|
||||
"node-red"
|
||||
],
|
||||
"node-red": {
|
||||
"nodes": {
|
||||
"testnode": "index.js"
|
||||
}
|
||||
},
|
||||
"author": "@testyMcTersterson",
|
||||
"license": "MIT"
|
||||
}
|
@@ -0,0 +1 @@
|
||||
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><path d="M30.999 31.005v-3h-6.762s.812-12.397 1.162-14 .597-3.35 2.628-3.103 1.971 3.103 1.971 3.103l4.862-.016s-.783-3.984-2.783-5.984-7.946-1.7-9.633.03c-1.687 1.73-2.302 5.065-2.597 6.422-.588 4.5-.854 9.027-1.248 13.547h-8.6v3H18.1s-.812 12.398-1.162 14-.597 3.35-2.628 3.103-1.972-3.102-1.972-3.102l-4.862.015s.783 3.985 2.783 5.985c2 2 7.946 1.699 9.634-.031 1.687-1.73 2.302-5.065 2.597-6.422.587-4.5.854-9.027 1.248-13.547z" fill="#fff"/></svg>
|
After Width: | Height: | Size: 539 B |
@@ -0,0 +1,4 @@
|
||||
|
||||
(function() {
|
||||
console.log("hello from regular module main.js")
|
||||
})()
|
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "regular_node",
|
||||
"version": "1.0.0",
|
||||
"description": "A regular node that does nothing other than exist",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [
|
||||
"test"
|
||||
],
|
||||
"author": "@testyMcTersterson",
|
||||
"license": "MIT"
|
||||
}
|
@@ -0,0 +1,5 @@
|
||||
<script>
|
||||
(function() {
|
||||
console.log("hello from @test/testnode index.html")
|
||||
})()
|
||||
</script>
|
@@ -0,0 +1,4 @@
|
||||
|
||||
(function() {
|
||||
console.log("hello from @test/testnode index.js")
|
||||
})()
|
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "@test/testnode",
|
||||
"version": "1.0.0",
|
||||
"description": "A test node that does nothing other than exist",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [
|
||||
"node-red",
|
||||
"test"
|
||||
],
|
||||
"node-red": {
|
||||
"nodes": {
|
||||
"testnode": "index.js"
|
||||
}
|
||||
},
|
||||
"author": "@testyMcTersterson",
|
||||
"license": "MIT"
|
||||
}
|
@@ -0,0 +1,5 @@
|
||||
<script>
|
||||
(function() {
|
||||
console.log("hello from testnode2 index.js")
|
||||
})()
|
||||
</script>
|
@@ -0,0 +1,4 @@
|
||||
|
||||
(function() {
|
||||
console.log("hello from testnode2 index.js")
|
||||
})()
|
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "testnode2",
|
||||
"version": "1.0.0",
|
||||
"description": "A test node that does nothing other than exist",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [
|
||||
"node-red",
|
||||
"test"
|
||||
],
|
||||
"node-red": {
|
||||
"nodes": {
|
||||
"testnode2": "index.js"
|
||||
}
|
||||
},
|
||||
"author": "@testyMcTersterson",
|
||||
"license": "MIT"
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
(function() {
|
||||
console.log("Hi from test plugin client side")
|
||||
})()
|
@@ -0,0 +1,14 @@
|
||||
module.exports = function (RED) {
|
||||
RED.plugins.registerPlugin('test-theme', {
|
||||
type: 'node-red-theme',
|
||||
scripts: [
|
||||
'files/clientside.js'
|
||||
],
|
||||
css: [
|
||||
'files/theme.css',
|
||||
],
|
||||
monacoOptions: {
|
||||
theme: "vs"
|
||||
}
|
||||
})
|
||||
}
|
@@ -0,0 +1 @@
|
||||
:root{--red-ui-primary-background: #f2f3fb;}
|
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "test-theme2",
|
||||
"version": "0.0.1",
|
||||
"description": "test theme for Node-RED",
|
||||
|
||||
"keywords": [
|
||||
"node-red",
|
||||
"plugin",
|
||||
"theme"
|
||||
],
|
||||
"author": {
|
||||
"name": "testy-McTesterson"
|
||||
},
|
||||
"license": "MIT",
|
||||
"node-red": {
|
||||
"version": ">=2.2.0",
|
||||
"plugins": {
|
||||
"test-theme2": "files/plugin.js"
|
||||
}
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.x"
|
||||
}
|
||||
}
|
5
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.html
generated
vendored
Normal file
5
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.html
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
<script>
|
||||
(function() {
|
||||
console.log("hello from @test/testnode index.html")
|
||||
})()
|
||||
</script>
|
4
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.js
generated
vendored
Normal file
4
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.js
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
(function() {
|
||||
console.log("hello from @test/testnode index.js")
|
||||
})()
|
20
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/package.json
generated
vendored
Normal file
20
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/package.json
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "@test/testnode",
|
||||
"version": "1.0.0",
|
||||
"description": "A test node that does nothing other than exist",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [
|
||||
"node-red",
|
||||
"test"
|
||||
],
|
||||
"node-red": {
|
||||
"nodes": {
|
||||
"testnode": "index.js"
|
||||
}
|
||||
},
|
||||
"author": "@testyMcTersterson",
|
||||
"license": "MIT"
|
||||
}
|
3
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/clientside.js
generated
vendored
Normal file
3
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/clientside.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
(function() {
|
||||
console.log("Hi from test plugin client side")
|
||||
})()
|
14
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/plugin.js
generated
vendored
Normal file
14
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/plugin.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
module.exports = function (RED) {
|
||||
RED.plugins.registerPlugin('test-theme', {
|
||||
type: 'node-red-theme',
|
||||
scripts: [
|
||||
'files/clientside.js'
|
||||
],
|
||||
css: [
|
||||
'files/theme.css',
|
||||
],
|
||||
monacoOptions: {
|
||||
theme: "vs"
|
||||
}
|
||||
})
|
||||
}
|
1
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/theme.css
generated
vendored
Normal file
1
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/theme.css
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
:root{--red-ui-primary-background: #f2f3fb;}
|
24
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/package.json
generated
vendored
Normal file
24
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/package.json
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "@test/test-theme3",
|
||||
"version": "0.0.1",
|
||||
"description": "test theme for Node-RED",
|
||||
|
||||
"keywords": [
|
||||
"node-red",
|
||||
"plugin",
|
||||
"theme"
|
||||
],
|
||||
"author": {
|
||||
"name": "testy-McTesterson"
|
||||
},
|
||||
"license": "MIT",
|
||||
"node-red": {
|
||||
"version": ">=2.2.0",
|
||||
"plugins": {
|
||||
"test-theme3": "files/plugin.js"
|
||||
}
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.x"
|
||||
}
|
||||
}
|
5
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.html
generated
vendored
Normal file
5
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.html
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
<script>
|
||||
(function() {
|
||||
console.log("hello from testnode3 index.js")
|
||||
})()
|
||||
</script>
|
4
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.js
generated
vendored
Normal file
4
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.js
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
(function() {
|
||||
console.log("hello from testnode3 index.js")
|
||||
})()
|
20
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/package.json
generated
vendored
Normal file
20
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/package.json
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "testnode3",
|
||||
"version": "1.0.0",
|
||||
"description": "A test node that does nothing other than exist",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [
|
||||
"node-red",
|
||||
"test"
|
||||
],
|
||||
"node-red": {
|
||||
"nodes": {
|
||||
"testnode3": "index.js"
|
||||
}
|
||||
},
|
||||
"author": "@testyMcTersterson",
|
||||
"license": "MIT"
|
||||
}
|
139
test/unit/@node-red/runtime/lib/api/diagnostics_spec.js
Normal file
139
test/unit/@node-red/runtime/lib/api/diagnostics_spec.js
Normal file
@@ -0,0 +1,139 @@
|
||||
|
||||
var should = require("should");
|
||||
var sinon = require("sinon");
|
||||
var NR_TEST_UTILS = require("nr-test-utils");
|
||||
var diagnostics = NR_TEST_UTILS.require("@node-red/runtime/lib/api/diagnostics")
|
||||
|
||||
var 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/diagnostics", function() {
|
||||
|
||||
describe("get", function() {
|
||||
before(function() {
|
||||
diagnostics.init({
|
||||
isStarted: () => true,
|
||||
nodes: {
|
||||
getNodeList: () => [{module:"node-red", version:"9.9.9"},{module:"node-red-node-inject", version:"8.8.8"}]
|
||||
},
|
||||
settings: {
|
||||
version: "7.7.7",
|
||||
available: () => true,
|
||||
//apiMaxLength: xxx, deliberately left blank. Should arrive in report as "UNSET"
|
||||
debugMaxLength: 1111,
|
||||
disableEditor: false,
|
||||
flowFile: "flows.json",
|
||||
mqttReconnectTime: 321,
|
||||
serialReconnectTime: 432,
|
||||
socketReconnectTime: 2222,
|
||||
socketTimeout: 3333,
|
||||
tcpMsgQueueSize: 4444,
|
||||
inboundWebSocketTimeout: 5555,
|
||||
runtimeState: {enabled: true, ui: false},
|
||||
adminAuth: {},//should be sanitised to "SET"
|
||||
httpAdminRoot: "/admin/root/",
|
||||
httpAdminCors: {},//should be sanitised to "SET"
|
||||
httpNodeAuth: {},//should be sanitised to "SET"
|
||||
httpNodeRoot: "/node/root/",
|
||||
httpNodeCors: {},//should be sanitised to "SET"
|
||||
httpStatic: "/var/static/",//should be sanitised to "SET"
|
||||
httpStaticRoot: "/static/root/",
|
||||
httpStaticCors: {},//should be sanitised to "SET"
|
||||
uiHost: "something.secret.com",//should be sanitised to "SET"
|
||||
uiPort: 1337,//should be sanitised to "SET"
|
||||
userDir: "/var/super/secret/",//should be sanitised to "SET",
|
||||
nodesDir: "/var/super/secret/",//should be sanitised to "SET",
|
||||
contextStorage: {
|
||||
default : { module: "memory" },
|
||||
file: { module: "localfilesystem" },
|
||||
secured: { module: "secure_store", user: "fred", pass: "super-duper-secret" },
|
||||
},
|
||||
editorTheme: {}
|
||||
},
|
||||
log: mockLog()
|
||||
});
|
||||
})
|
||||
it("returns basic user settings", function() {
|
||||
return diagnostics.get({scope:"fake_scope"}).then(result => {
|
||||
should(result).be.type("object");
|
||||
|
||||
//result.xxxxx
|
||||
Object.keys(result)
|
||||
const reportPropCount = Object.keys(result).length;
|
||||
reportPropCount.should.eql(7);//ensure no more than 7 keys are present in the report (avoid leakage of extra info)
|
||||
result.should.have.property("report","diagnostics");
|
||||
result.should.have.property("scope","fake_scope");
|
||||
result.should.have.property("time").type("object");
|
||||
result.should.have.property("intl").type("object");
|
||||
result.should.have.property("nodejs").type("object");
|
||||
result.should.have.property("os").type("object");
|
||||
result.should.have.property("runtime").type("object");
|
||||
|
||||
//result.runtime.xxxxx
|
||||
const runtimeCount = Object.keys(result.runtime).length;
|
||||
runtimeCount.should.eql(5);//ensure 5 keys are present in runtime
|
||||
result.runtime.should.have.property('isStarted',true)
|
||||
result.runtime.should.have.property('flows')
|
||||
result.runtime.should.have.property('modules').type("object");
|
||||
result.runtime.should.have.property('settings').type("object");
|
||||
result.runtime.should.have.property('version','7.7.7');
|
||||
|
||||
//result.runtime.modules.xxxxx
|
||||
const moduleCount = Object.keys(result.runtime.modules).length;
|
||||
moduleCount.should.eql(2);//ensure no more than the 2 modules specified are present
|
||||
result.runtime.modules.should.have.property('node-red','9.9.9');
|
||||
result.runtime.modules.should.have.property('node-red-node-inject','8.8.8');
|
||||
|
||||
//result.runtime.settings.xxxxx
|
||||
const settingsCount = Object.keys(result.runtime.settings).length;
|
||||
settingsCount.should.eql(27);//ensure no more than the 21 settings listed below are present in the settings object
|
||||
result.runtime.settings.should.have.property('available',true);
|
||||
result.runtime.settings.should.have.property('apiMaxLength', "UNSET");//deliberately disabled to ensure UNSET is returned
|
||||
result.runtime.settings.should.have.property('debugMaxLength', 1111);
|
||||
result.runtime.settings.should.have.property('disableEditor', false);
|
||||
result.runtime.settings.should.have.property('editorTheme', {});
|
||||
result.runtime.settings.should.have.property('flowFile', "flows.json");
|
||||
result.runtime.settings.should.have.property('mqttReconnectTime', 321);
|
||||
result.runtime.settings.should.have.property('serialReconnectTime', 432);
|
||||
result.runtime.settings.should.have.property('socketReconnectTime', 2222);
|
||||
result.runtime.settings.should.have.property('socketTimeout', 3333);
|
||||
result.runtime.settings.should.have.property('tcpMsgQueueSize', 4444);
|
||||
result.runtime.settings.should.have.property('inboundWebSocketTimeout', 5555);
|
||||
result.runtime.settings.should.have.property('runtimeState', {enabled: true, ui: false});
|
||||
result.runtime.settings.should.have.property("adminAuth", "SET"); //should be sanitised to "SET"
|
||||
result.runtime.settings.should.have.property("httpAdminCors", "SET"); //should be sanitised to "SET"
|
||||
result.runtime.settings.should.have.property('httpAdminRoot', "/admin/root/");
|
||||
result.runtime.settings.should.have.property("httpNodeAuth", "SET"); //should be sanitised to "SET"
|
||||
result.runtime.settings.should.have.property("httpNodeCors", "SET"); //should be sanitised to "SET"
|
||||
result.runtime.settings.should.have.property('httpNodeRoot', "/node/root/");
|
||||
result.runtime.settings.should.have.property("httpStatic", "SET"); //should be sanitised to "SET"
|
||||
result.runtime.settings.should.have.property('httpStaticRoot', "/static/root/");
|
||||
result.runtime.settings.should.have.property("httpStaticCors", "SET"); //should be sanitised to "SET"
|
||||
result.runtime.settings.should.have.property("uiHost", "SET"); //should be sanitised to "SET"
|
||||
result.runtime.settings.should.have.property("uiPort", "SET"); //should be sanitised to "SET"
|
||||
result.runtime.settings.should.have.property("userDir", "SET"); //should be sanitised to "SET"
|
||||
result.runtime.settings.should.have.property('contextStorage').type("object");
|
||||
result.runtime.settings.should.have.property('nodesDir', "SET")
|
||||
|
||||
//result.runtime.settings.contextStorage.xxxxx
|
||||
const contextCount = Object.keys(result.runtime.settings.contextStorage).length;
|
||||
contextCount.should.eql(3);//ensure no more than the 3 settings listed below are present in the contextStorage object
|
||||
result.runtime.settings.contextStorage.should.have.property('default', {module:"memory"});
|
||||
result.runtime.settings.contextStorage.should.have.property('file', {module:"localfilesystem"});
|
||||
result.runtime.settings.contextStorage.should.have.property('secured', {module:"secure_store"}); //only module should be present, other fields are dropped for security
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
|
||||
});
|
Reference in New Issue
Block a user