mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
add unit tests
This commit is contained in:
parent
76c0e140cf
commit
39f303fcd6
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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
126
test/unit/@node-red/runtime/lib/api/diagnostics_spec.js
Normal file
126
test/unit/@node-red/runtime/lib/api/diagnostics_spec.js
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
|
||||||
|
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,
|
||||||
|
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",
|
||||||
|
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(4);//ensure no more than 4 keys are present in runtime
|
||||||
|
result.runtime.should.have.property('isStarted',true)
|
||||||
|
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(21);//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("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.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
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user