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(`
-
-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);
- })
- });
-});
diff --git a/test/unit/@node-red/registry/lib/registry_spec.js b/test/unit/@node-red/registry/lib/registry_spec.js
deleted file mode 100644
index 5501264a7..000000000
--- a/test/unit/@node-red/registry/lib/registry_spec.js
+++ /dev/null
@@ -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('\nconfigAHEtest-nameLP');
- typeRegistry.getNodeConfig("test-module/test-name-2").should.eql('\nconfigBHEtest-name-2LP');
- typeRegistry.getAllNodeConfigs().should.eql('\n\nconfigAHEtest-nameLP\n\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);
- });
- });
-});
diff --git a/test/unit/@node-red/registry/lib/resources/examples/one.json b/test/unit/@node-red/registry/lib/resources/examples/one.json
deleted file mode 100644
index e69de29bb..000000000
diff --git a/test/unit/@node-red/registry/lib/resources/local/DuffNode/DuffNode.js b/test/unit/@node-red/registry/lib/resources/local/DuffNode/DuffNode.js
deleted file mode 100644
index 41e2a0059..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/DuffNode/DuffNode.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// A test node that exports a function
-module.exports = function(RED) {
- function DuffNode(n) {}
- RED.nodes.registerType("duff-node",DuffNode);
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/DuplicateTestNode/TestNode1.html b/test/unit/@node-red/registry/lib/resources/local/DuplicateTestNode/TestNode1.html
deleted file mode 100644
index b637ede21..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/DuplicateTestNode/TestNode1.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/test/unit/@node-red/registry/lib/resources/local/DuplicateTestNode/TestNode1.js b/test/unit/@node-red/registry/lib/resources/local/DuplicateTestNode/TestNode1.js
deleted file mode 100644
index e81214169..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/DuplicateTestNode/TestNode1.js
+++ /dev/null
@@ -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);
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/MultipleNodes1/MultipleNodes1.html b/test/unit/@node-red/registry/lib/resources/local/MultipleNodes1/MultipleNodes1.html
deleted file mode 100644
index 5359644e5..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/MultipleNodes1/MultipleNodes1.html
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/test/unit/@node-red/registry/lib/resources/local/MultipleNodes1/MultipleNodes1.js b/test/unit/@node-red/registry/lib/resources/local/MultipleNodes1/MultipleNodes1.js
deleted file mode 100644
index 55747c0b3..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/MultipleNodes1/MultipleNodes1.js
+++ /dev/null
@@ -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);
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/NestedNode.html b/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/NestedNode.html
deleted file mode 100644
index abc823e8f..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/NestedNode.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
diff --git a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/NestedNode.js b/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/NestedNode.js
deleted file mode 100644
index cd3148a58..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/NestedNode.js
+++ /dev/null
@@ -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);
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/icons/arrow-in.png b/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/icons/arrow-in.png
deleted file mode 100644
index e38f3914600901b736f5fa18786ee11be6d41c28..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 393
zcmeAS@N?(olHy`uVBq!ia0vp^B0wz1!3HFCgzU0`6icy_X9x!n)NrJ90QsB+9+AZi
z3~X;em{G3O!W1YdS>hT|5}cn_Ql40p%1~Zju9umYU7Va)kgAtols@~NjT8d|Bb%p-
zV~9uR+N-+$hZ97Oeyp#Y$RU!&XX#m>@|$agvYL9Jz$O6}72y^gZVi>ZMeaH^t*Q|!
zLhVk<0xdko8zYVo#8M-LBBd8b>1kw|i?FO)bWqsy_rwQg27N4y
zeX6pqO$_Cex^^A7_NsS@+=bOASA^wN0&GKN(hlAguRU&q-
jTBY?`*L>xN+|S&+7B*edvmQhOgN?z{)z4*}Q$iB}+9!`i
diff --git a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/lib/ShouldNotLoad.html b/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/lib/ShouldNotLoad.html
deleted file mode 100644
index ac9235d26..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/lib/ShouldNotLoad.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
diff --git a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/lib/ShouldNotLoad.js b/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/lib/ShouldNotLoad.js
deleted file mode 100644
index 8af249b14..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/lib/ShouldNotLoad.js
+++ /dev/null
@@ -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);
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/node_modules/ShouldNotLoad.html b/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/node_modules/ShouldNotLoad.html
deleted file mode 100644
index eb7c8a3f9..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/node_modules/ShouldNotLoad.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
diff --git a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/node_modules/ShouldNotLoad.js b/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/node_modules/ShouldNotLoad.js
deleted file mode 100644
index 623e299b2..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/node_modules/ShouldNotLoad.js
+++ /dev/null
@@ -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);
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/test/ShouldNotLoad.html b/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/test/ShouldNotLoad.html
deleted file mode 100644
index 4212fd589..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/test/ShouldNotLoad.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
diff --git a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/test/ShouldNotLoad.js b/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/test/ShouldNotLoad.js
deleted file mode 100644
index 5856adada..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/test/ShouldNotLoad.js
+++ /dev/null
@@ -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);
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNode1/TestNode1.html b/test/unit/@node-red/registry/lib/resources/local/TestNode1/TestNode1.html
deleted file mode 100644
index 97dbf1710..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNode1/TestNode1.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-this should be filtered out
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNode1/TestNode1.js b/test/unit/@node-red/registry/lib/resources/local/TestNode1/TestNode1.js
deleted file mode 100644
index bfa3b65bd..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNode1/TestNode1.js
+++ /dev/null
@@ -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);
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNode2/TestNode2.html b/test/unit/@node-red/registry/lib/resources/local/TestNode2/TestNode2.html
deleted file mode 100644
index 66b65909e..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNode2/TestNode2.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNode2/TestNode2.js b/test/unit/@node-red/registry/lib/resources/local/TestNode2/TestNode2.js
deleted file mode 100644
index 1bf2fa6c9..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNode2/TestNode2.js
+++ /dev/null
@@ -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();
- });
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNode3/TestNode3.html b/test/unit/@node-red/registry/lib/resources/local/TestNode3/TestNode3.html
deleted file mode 100644
index 9a0f6f7ea..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNode3/TestNode3.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNode3/TestNode3.js b/test/unit/@node-red/registry/lib/resources/local/TestNode3/TestNode3.js
deleted file mode 100644
index b9ee6a624..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNode3/TestNode3.js
+++ /dev/null
@@ -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");
- });
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNode4/TestNode4.html b/test/unit/@node-red/registry/lib/resources/local/TestNode4/TestNode4.html
deleted file mode 100644
index 9a0f6f7ea..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNode4/TestNode4.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNode4/TestNode4.js b/test/unit/@node-red/registry/lib/resources/local/TestNode4/TestNode4.js
deleted file mode 100644
index c31255852..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNode4/TestNode4.js
+++ /dev/null
@@ -1 +0,0 @@
-throw new Error("fail to require");
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/EmptyModule/file.txt b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/EmptyModule/file.txt
deleted file mode 100644
index 0ce8dcaed..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/EmptyModule/file.txt
+++ /dev/null
@@ -1 +0,0 @@
-This file exists just to ensure the parent directory is in the repository.
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule.html b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule.html
deleted file mode 100644
index 17483f7ca..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-this should be filtered out
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule.js b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule.js
deleted file mode 100644
index c79c2ceb6..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule.js
+++ /dev/null
@@ -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);
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule2.html b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule2.html
deleted file mode 100644
index a1f1b6c79..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule2.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-this should be filtered out
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule2.js b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule2.js
deleted file mode 100644
index d359fb3f2..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule2.js
+++ /dev/null
@@ -1,4 +0,0 @@
-// A test node that exports a function
-module.exports = function(RED) {
- throw new Error("fail to load");
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/arrow-in.png b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/arrow-in.png
deleted file mode 100644
index e38f3914600901b736f5fa18786ee11be6d41c28..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 393
zcmeAS@N?(olHy`uVBq!ia0vp^B0wz1!3HFCgzU0`6icy_X9x!n)NrJ90QsB+9+AZi
z3~X;em{G3O!W1YdS>hT|5}cn_Ql40p%1~Zju9umYU7Va)kgAtols@~NjT8d|Bb%p-
zV~9uR+N-+$hZ97Oeyp#Y$RU!&XX#m>@|$agvYL9Jz$O6}72y^gZVi>ZMeaH^t*Q|!
zLhVk<0xdko8zYVo#8M-LBBd8b>1kw|i?FO)bWqsy_rwQg27N4y
zeX6pqO$_Cex^^A7_NsS@+=bOASA^wN0&GKN(hlAguRU&q-
jTBY?`*L>xN+|S&+7B*edvmQhOgN?z{)z4*}Q$iB}+9!`i
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/file.txt b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/file.txt
deleted file mode 100644
index 59a29af14..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/file.txt
+++ /dev/null
@@ -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
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/package.json b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/package.json
deleted file mode 100644
index 8eba5b04b..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/package.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "name" : "TestNodeModule",
- "version" : "0.0.1",
- "description" : "A test node module",
- "node-red" : {
- "nodes": {
- "TestNodeMod1": "TestNodeModule.js",
- "TestNodeMod2": "TestNodeModule2.js"
- }
- }
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule.html b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule.html
deleted file mode 100644
index 17483f7ca..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-this should be filtered out
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule.js b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule.js
deleted file mode 100644
index c79c2ceb6..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule.js
+++ /dev/null
@@ -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);
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule2.html b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule2.html
deleted file mode 100644
index a1f1b6c79..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule2.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-this should be filtered out
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule2.js b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule2.js
deleted file mode 100644
index d359fb3f2..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule2.js
+++ /dev/null
@@ -1,4 +0,0 @@
-// A test node that exports a function
-module.exports = function(RED) {
- throw new Error("fail to load");
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/icons/file.txt b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/icons/file.txt
deleted file mode 100644
index 59a29af14..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/icons/file.txt
+++ /dev/null
@@ -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
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/package.json b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/package.json
deleted file mode 100644
index 4f9e46518..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/package.json
+++ /dev/null
@@ -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"
- }
- }
-}
diff --git a/test/unit/@node-red/registry/lib/resources/userDir/lib/icons/file.txt b/test/unit/@node-red/registry/lib/resources/userDir/lib/icons/file.txt
deleted file mode 100644
index e69de29bb..000000000
diff --git a/test/unit/@node-red/registry/lib/resources/userDir/lib/icons/test_icon.png b/test/unit/@node-red/registry/lib/resources/userDir/lib/icons/test_icon.png
deleted file mode 100644
index 4b6b7b5e9b10ec790348eb59f73bdac596e2f3b8..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 163
zcmeAS@N?(olHy`uVBq!ia0vp^B0wz1$P6UK?yS)OQjEnx?oJHr&dIz4a@YcVLR^9L
z|NsA&-kg6IB%S2#?!wT)D(eB{a29w(76Vni0bxeDQVUa{AbW|YuPggKZdPtVo=;b%
zu>pm|JY5_^IIbrr*#Br`l>NUU`M`mYFm{Gnm$g4<{K@tLs$lSR^>bP0l+XkK5O^!s
diff --git a/test/unit/@node-red/registry/lib/resources/userDir/nodes/TestNode5/TestNode5.html b/test/unit/@node-red/registry/lib/resources/userDir/nodes/TestNode5/TestNode5.html
deleted file mode 100644
index f38a3a24d..000000000
--- a/test/unit/@node-red/registry/lib/resources/userDir/nodes/TestNode5/TestNode5.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-this should be filtered out
diff --git a/test/unit/@node-red/registry/lib/resources/userDir/nodes/TestNode5/TestNode5.js b/test/unit/@node-red/registry/lib/resources/userDir/nodes/TestNode5/TestNode5.js
deleted file mode 100644
index c31255852..000000000
--- a/test/unit/@node-red/registry/lib/resources/userDir/nodes/TestNode5/TestNode5.js
+++ /dev/null
@@ -1 +0,0 @@
-throw new Error("fail to require");
diff --git a/test/unit/@node-red/registry/lib/subflow_spec.js b/test/unit/@node-red/registry/lib/subflow_spec.js
deleted file mode 100644
index 2aa7db203..000000000
--- a/test/unit/@node-red/registry/lib/subflow_spec.js
+++ /dev/null
@@ -1,3 +0,0 @@
-describe("red/nodes/registry/subflow",function() {
- it.skip("NEEDS TESTS");
-});
diff --git a/test/unit/@node-red/registry/lib/util_spec.js b/test/unit/@node-red/registry/lib/util_spec.js
deleted file mode 100644
index 7e94d4fe5..000000000
--- a/test/unit/@node-red/registry/lib/util_spec.js
+++ /dev/null
@@ -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();
- })
-
- })
-});
diff --git a/test/unit/@node-red/runtime/lib/api/comms_spec.js b/test/unit/@node-red/runtime/lib/api/comms_spec.js
deleted file mode 100644
index 0097f5ce8..000000000
--- a/test/unit/@node-red/runtime/lib/api/comms_spec.js
+++ /dev/null
@@ -1,321 +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 NR_TEST_UTILS = require("nr-test-utils");
-var comms = NR_TEST_UTILS.require("@node-red/runtime/lib/api/comms");
-var events = NR_TEST_UTILS.require("@node-red/util/lib/events");
-
-describe("runtime-api/comms", function() {
- describe("listens for events", function() {
- var messages = [];
- var clientConnection = {
- send: function(topic,data) {
- messages.push({topic,data})
- }
- }
- var eventHandlers = {};
- before(function(done) {
- sinon.stub(events,"removeListener").callsFake(function() {})
- sinon.stub(events,"on").callsFake(function(evt,handler) { eventHandlers[evt] = handler })
- comms.init({
- log: {
- trace: function(){}
- }
- })
- comms.addConnection({client: clientConnection}).then(done);
- })
- after(function(done) {
- comms.removeConnection({client: clientConnection}).then(done);
- events.removeListener.restore();
- events.on.restore();
- })
- afterEach(function() {
- messages = [];
- })
-
- it('runtime events',function(){
- eventHandlers.should.have.property('runtime-event');
- eventHandlers['runtime-event']({
- id: "my-event",
- payload: "my-payload"
- })
- messages.should.have.length(1);
- messages[0].should.have.property("topic","notification/my-event");
- messages[0].should.have.property("data","my-payload")
- })
- it('status events',function(){
- eventHandlers.should.have.property('node-status');
- eventHandlers['node-status']({
- id: "my-event",
- status: {text:"my-status",badProperty:"should be filtered"}
- })
- messages.should.have.length(1);
- messages[0].should.have.property("topic","status/my-event");
- messages[0].should.have.property("data");
- messages[0].data.should.have.property("text","my-status");
- messages[0].data.should.not.have.property("badProperty");
-
- })
- it('comms events',function(){
- eventHandlers.should.have.property('runtime-event');
- eventHandlers['comms']({
- topic: "my-topic",
- data: "my-payload"
- })
- messages.should.have.length(1);
- messages[0].should.have.property("topic","my-topic");
- messages[0].should.have.property("data","my-payload")
- })
- });
- describe("manages connections", function() {
- var eventHandlers = {};
- var messages = [];
- var clientConnection1 = {
- send: function(topic,data) {
- messages.push({topic,data})
- }
- }
- var clientConnection2 = {
- send: function(topic,data) {
- messages.push({topic,data})
- }
- }
- before(function() {
- sinon.stub(events,"removeListener").callsFake(function() {})
- sinon.stub(events,"on").callsFake(function(evt,handler) { eventHandlers[evt] = handler })
- comms.init({
- log: {
- trace: function(){}
- }
- })
- })
- after(function() {
- events.removeListener.restore();
- events.on.restore();
- })
- afterEach(function(done) {
- comms.removeConnection({client: clientConnection1}).then(function() {
- comms.removeConnection({client: clientConnection2}).then(done);
- });
- messages = [];
- })
- it('adds new connections',function(done){
- eventHandlers['comms']({
- topic: "my-topic",
- data: "my-payload"
- })
- messages.should.have.length(0);
- comms.addConnection({client: clientConnection1}).then(function() {
- eventHandlers['comms']({
- topic: "my-topic",
- data: "my-payload"
- })
- messages.should.have.length(1);
- comms.addConnection({client: clientConnection2}).then(function() {
- eventHandlers['comms']({
- topic: "my-topic",
- data: "my-payload"
- })
- messages.should.have.length(3);
- done();
- }).catch(done);
- });
- });
- it('removes connections',function(done){
- eventHandlers['comms']({
- topic: "my-topic",
- data: "my-payload"
- })
- messages.should.have.length(0);
- comms.addConnection({client: clientConnection1}).then(function() {
- comms.addConnection({client: clientConnection2}).then(function() {
- eventHandlers['comms']({
- topic: "my-topic",
- data: "my-payload"
- })
- messages.should.have.length(2);
- comms.removeConnection({client: clientConnection1}).then(function() {
- eventHandlers['comms']({
- topic: "my-topic",
- data: "my-payload"
- })
- messages.should.have.length(3);
- done();
- });
- }).catch(done);
- });
- })
- })
-
- describe("subscriptions", function() {
- var messages = [];
- var clientConnection = {
- send: function(topic,data) {
- messages.push({topic,data})
- }
- }
- var clientConnection2 = {
- send: function(topic,data) {
- messages.push({topic,data})
- }
- }
- var eventHandlers = {};
- before(function() {
- sinon.stub(events,"removeListener").callsFake(function() {})
- sinon.stub(events,"on").callsFake(function(evt,handler) { eventHandlers[evt] = handler })
- comms.init({
- log: {
- trace: function(){}
- }
- })
- })
- after(function() {
- events.removeListener.restore();
- events.on.restore();
- })
- afterEach(function(done) {
- messages = [];
- comms.removeConnection({client: clientConnection}).then(done);
- })
-
- it('subscribe triggers retained messages',function(done){
- eventHandlers['comms']({
- topic: "my-event",
- data: "my-payload",
- retain: true
- })
- messages.should.have.length(0);
- comms.addConnection({client: clientConnection}).then(function() {
- return comms.subscribe({client: clientConnection, topic: "my-event"}).then(function() {
- messages.should.have.length(1);
- messages[0].should.have.property("topic","my-event");
- messages[0].should.have.property("data","my-payload");
- done();
- });
- }).catch(done);
- })
- it('retains non-blank status message',function(done){
- eventHandlers['node-status']({
- id: "node1234",
- status: {text:"hello"}
- })
- messages.should.have.length(0);
- comms.addConnection({client: clientConnection}).then(function() {
- return comms.subscribe({client: clientConnection, topic: "status/#"}).then(function() {
- messages.should.have.length(1);
- messages[0].should.have.property("topic","status/node1234");
- messages[0].should.have.property("data",{text:"hello", fill: undefined, shape: undefined});
- done();
- });
- }).catch(done);
- })
- it('does not retain blank status message',function(done){
- eventHandlers['node-status']({
- id: "node1234",
- status: {}
- })
- messages.should.have.length(0);
- comms.addConnection({client: clientConnection}).then(function() {
- return comms.subscribe({client: clientConnection, topic: "status/#"}).then(function() {
- messages.should.have.length(0);
- done();
- });
- }).catch(done);
- })
- it('does not send blank status if first status',function(done){
- messages.should.have.length(0);
- comms.addConnection({client: clientConnection}).then(function() {
- return comms.subscribe({client: clientConnection, topic: "status/#"}).then(function() {
- eventHandlers['node-status']({
- id: "node5678",
- status: {}
- })
- messages.should.have.length(0);
- done()
- })
- }).catch(done);
- });
- it('sends blank status if replacing retained',function(done){
- eventHandlers['node-status']({
- id: "node5678",
- status: {text:"hello"}
- })
- messages.should.have.length(0);
- comms.addConnection({client: clientConnection}).then(function() {
- return comms.subscribe({client: clientConnection, topic: "status/#"}).then(function() {
- messages.should.have.length(1);
- eventHandlers['node-status']({
- id: "node5678",
- status: {}
- })
- messages.should.have.length(2);
- done()
- })
- }).catch(done);
- });
-
- it('does not retain initial status blank message',function(done){
- eventHandlers['node-status']({
- id: "my-event",
- status: {}
- })
- messages.should.have.length(0);
- comms.addConnection({client: clientConnection}).then(function() {
- return comms.subscribe({client: clientConnection, topic: "my-event"}).then(function() {
- messages.should.have.length(1);
- messages[0].should.have.property("topic","my-event");
- messages[0].should.have.property("data","my-payload");
- done();
- });
- }).catch(done);
- })
-
- it('retained messages get cleared',function(done) {
- eventHandlers['comms']({
- topic: "my-event",
- data: "my-payload",
- retain: true
- })
- messages.should.have.length(0);
- comms.addConnection({client: clientConnection}).then(function() {
- return comms.subscribe({client: clientConnection, topic: "my-event"}).then(function() {
- messages.should.have.length(1);
- messages[0].should.have.property("topic","my-event");
- messages[0].should.have.property("data","my-payload");
- // Now we have a retained message, clear it
- eventHandlers['comms']({
- topic: "my-event",
- data: "my-payload-cleared"
- });
- messages.should.have.length(2);
- messages[1].should.have.property("topic","my-event");
- messages[1].should.have.property("data","my-payload-cleared");
- // Now add a second client and subscribe - no message should arrive
- return comms.addConnection({client: clientConnection2}).then(function() {
- return comms.subscribe({client: clientConnection2, topic: "my-event"}).then(function() {
- messages.should.have.length(2);
- done();
- });
- });
- });
- }).catch(done);
- });
- })
-
-});
diff --git a/test/unit/@node-red/runtime/lib/api/context_spec.js b/test/unit/@node-red/runtime/lib/api/context_spec.js
deleted file mode 100644
index bf23e9cc6..000000000
--- a/test/unit/@node-red/runtime/lib/api/context_spec.js
+++ /dev/null
@@ -1,353 +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 NR_TEST_UTILS = require("nr-test-utils");
-var context = NR_TEST_UTILS.require("@node-red/runtime/lib/api/context");
-
-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";}
-});
-
-var mockContext = function(contents) {
- return {
- get: function(key,store,callback) {
- if (contents.hasOwnProperty(store) && contents[store].hasOwnProperty(key)) {
- callback(null,contents[store][key]);
- } else {
- callback(null,undefined);
- }
- },
- set: function (key, value, store, callback) {
- if (contents.hasOwnProperty(store)) {
- if (!value) {
- delete contents[store][key];
- callback(null);
- }
- } else {
- callback("err store");
- }
- },
- keys: function (store, callback) {
- if (contents.hasOwnProperty(store)) {
- callback(null, Object.keys(contents[store]));
- } else {
- callback("err store");
- }
- }
- };
-};
-
-describe("runtime-api/context", function() {
- var globalContext, flowContext, nodeContext, contexts;
-
- beforeEach(function() {
- globalContext = { default: { abc: 111 }, file: { abc: 222 } };
- flowContext = { default: { abc: 333 }, file: { abc: 444 } };
- nodeContext = { default: { abc: 555 }, file: { abc: 666 } };
- contexts = {
- global: mockContext(globalContext),
- flow1: mockContext(flowContext)
- };
- context.init({
- nodes: {
- listContextStores: function() {
- return { default: 'default', stores: [ 'default', 'file' ] };
- },
- getContext: function(id) {
- return contexts[id];
- },
- getNode: function(id) {
- if (id === 'known') {
- return {
- context: function() { return mockContext(nodeContext); }
- };
- } else {
- return null;
- }
- }
- },
- settings: {
- functionGlobalContext: {
- fgc:1234
- }
- },
- log: mockLog()
- });
- });
-
- describe("getValue", function() {
- it('gets global value of default store', function() {
- return context.getValue({
- scope: 'global',
- id: undefined,
- store: undefined, // use default
- key: 'abc'
- }).then(function(result) {
- result.should.have.property('msg','111');
- result.should.have.property('format','number');
- });
- });
-
- it('gets global value of specified store', function() {
- return context.getValue({
- scope: 'global',
- id: undefined,
- store: 'file',
- key: 'abc'
- }).then(function(result) {
- result.should.have.property('msg','222');
- result.should.have.property('format','number');
- });
- });
-
- it('gets flow value of default store', function() {
- return context.getValue({
- scope: 'flow',
- id: 'flow1',
- store: undefined, // use default
- key: 'abc'
- }).then(function(result) {
- result.should.have.property('msg','333');
- result.should.have.property('format','number');
- });
- });
-
- it('gets flow value of specified store', function() {
- return context.getValue({
- scope: 'flow',
- id: 'flow1',
- store: 'file',
- key: 'abc'
- }).then(function(result) {
- result.should.have.property('msg','444');
- result.should.have.property('format','number');
- });
- });
-
- it('gets node value of default store', function() {
- return context.getValue({
- scope: 'node',
- id: 'known',
- store: undefined, // use default
- key: 'abc'
- }).then(function(result) {
- result.should.have.property('msg','555');
- result.should.have.property('format','number');
- });
- });
-
- it('gets node value of specified store', function() {
- return context.getValue({
- scope: 'node',
- id: 'known',
- store: 'file',
- key: 'abc'
- }).then(function(result) {
- result.should.have.property('msg','666');
- result.should.have.property('format','number');
- });
- });
-
- it('404s for unknown store', function(done) {
- context.getValue({
- scope: 'global',
- id: undefined,
- store: 'unknown',
- key: 'abc'
- }).then(function(result) {
- done("getValue for unknown store should not resolve");
- }).catch(function(err) {
- err.should.have.property('code','not_found');
- err.should.have.property('status',404);
- done();
- });
- });
-
- it('gets all global value properties', function() {
- return context.getValue({
- scope: 'global',
- id: undefined,
- store: undefined, // use default
- key: undefined, //
- }).then(function(result) {
- result.should.eql({
- default: { abc: { msg: '111', format: 'number' } },
- file: { abc: { msg: '222', format: 'number' } }
- });
- });
- });
-
- it('gets all flow value properties', function() {
- return context.getValue({
- scope: 'flow',
- id: 'flow1',
- store: undefined, // use default
- key: undefined, //
- }).then(function(result) {
- result.should.eql({
- default: { abc: { msg: '333', format: 'number' } },
- file: { abc: { msg: '444', format: 'number' } }
- });
- });
- });
-
- it('gets all node value properties', function() {
- return context.getValue({
- scope: 'node',
- id: 'known',
- store: undefined, // use default
- key: undefined, //
- }).then(function(result) {
- result.should.eql({
- default: { abc: { msg: '555', format: 'number' } },
- file: { abc: { msg: '666', format: 'number' } }
- });
- });
- });
-
- it('gets empty object when specified context doesn\'t exist', function() {
- return context.getValue({
- scope: 'node',
- id: 'non-existent',
- store: 'file',
- key: 'abc'
- }).then(function(result) {
- result.should.be.an.Object();
- result.should.be.empty();
- });
- });
- });
-
- describe("delete", function () {
- it('deletes global value of default store', function () {
- return context.delete({
- scope: 'global',
- id: undefined,
- store: undefined, // use default
- key: 'abc'
- }).then(function () {
- globalContext.should.eql({
- default: {}, file: { abc: 222 }
- });
- });
- });
-
- it('deletes global value of specified store', function () {
- return context.delete({
- scope: 'global',
- id: undefined,
- store: 'file',
- key: 'abc'
- }).then(function () {
- globalContext.should.eql({
- default: { abc: 111 }, file: {}
- });
- });
- });
-
- it('deletes flow value of default store', function () {
- return context.delete({
- scope: 'flow',
- id: 'flow1',
- store: undefined, // use default
- key: 'abc'
- }).then(function () {
- flowContext.should.eql({
- default: {}, file: { abc: 444 }
- });
- });
- });
-
- it('deletes flow value of specified store', function () {
- return context.delete({
- scope: 'flow',
- id: 'flow1',
- store: 'file',
- key: 'abc'
- }).then(function () {
- flowContext.should.eql({
- default: { abc: 333 }, file: {}
- });
- });
- });
-
- it('deletes node value of default store', function () {
- return context.delete({
- scope: 'node',
- id: 'known',
- store: undefined, // use default
- key: 'abc'
- }).then(function () {
- nodeContext.should.eql({
- default: {}, file: { abc: 666 }
- });
- });
- });
-
- it('deletes node value of specified store', function () {
- return context.delete({
- scope: 'node',
- id: 'known',
- store: 'file',
- key: 'abc'
- }).then(function () {
- nodeContext.should.eql({
- default: { abc: 555 }, file: {}
- });
- });
- });
-
- it('does nothing when specified context doesn\'t exist', function() {
- return context.delete({
- scope: 'node',
- id: 'non-existent',
- store: 'file',
- key: 'abc'
- }).then(function(result) {
- should.not.exist(result);
- nodeContext.should.eql({
- default: { abc: 555 }, file: { abc: 666 }
- });
- });
- });
-
- it('404s for unknown store', function (done) {
- context.delete({
- scope: 'global',
- id: undefined,
- store: 'unknown',
- key: 'abc'
- }).then(function () {
- done("delete for unknown store should not resolve");
- }).catch(function (err) {
- err.should.have.property('code', 'not_found');
- err.should.have.property('status', 404);
- done();
- });
- });
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/api/flows_spec.js b/test/unit/@node-red/runtime/lib/api/flows_spec.js
deleted file mode 100644
index 9062ef52f..000000000
--- a/test/unit/@node-red/runtime/lib/api/flows_spec.js
+++ /dev/null
@@ -1,430 +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 NR_TEST_UTILS = require("nr-test-utils");
-var flows = NR_TEST_UTILS.require("@node-red/runtime/lib/api/flows")
-
-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/flows", function() {
- describe("getFlows", function() {
- it("returns the current flow configuration", function(done) {
- flows.init({
- log: mockLog(),
- flows: {
- getFlows: function() { return [1,2,3] }
- }
- });
- flows.getFlows({}).then(function(result) {
- result.should.eql([1,2,3]);
- done();
- }).catch(done);
- });
- });
-
- describe("setFlows", function() {
- var setFlows;
- var loadFlows;
- var reloadError = false;
- beforeEach(function() {
- setFlows = sinon.spy(function(flows,credentials,type) {
- if (flows[0] === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- }
- return Promise.resolve("newRev");
- });
- loadFlows = sinon.spy(function() {
- if (!reloadError) {
- return Promise.resolve("newLoadRev");
- } else {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- }
- })
- flows.init({
- log: mockLog(),
- flows: {
- getFlows: function() { return {rev:"currentRev",flows:[]} },
- setFlows: setFlows,
- loadFlows: loadFlows
- }
- })
-
- })
- it("defaults to full deploy", function(done) {
- flows.setFlows({
- flows: {flows:[4,5,6]}
- }).then(function(result) {
- result.should.eql({rev:"newRev"});
- setFlows.called.should.be.true();
- setFlows.lastCall.args[0].should.eql([4,5,6]);
- setFlows.lastCall.args[2].should.eql("full");
- done();
- }).catch(done);
- });
- it("includes credentials when part of the request", function(done) {
- flows.setFlows({
- flows: {flows:[4,5,6], credentials: {$:"creds"}},
- }).then(function(result) {
- result.should.eql({rev:"newRev"});
- setFlows.called.should.be.true();
- setFlows.lastCall.args[0].should.eql([4,5,6]);
- setFlows.lastCall.args[1].should.eql({$:"creds"});
- setFlows.lastCall.args[2].should.eql("full");
- done();
- }).catch(done);
- });
- it("passes through other deploy types", function(done) {
- flows.setFlows({
- deploymentType: "nodes",
- flows: {flows:[4,5,6]}
- }).then(function(result) {
- result.should.eql({rev:"newRev"});
- setFlows.called.should.be.true();
- setFlows.lastCall.args[0].should.eql([4,5,6]);
- setFlows.lastCall.args[2].should.eql("nodes");
- done();
- }).catch(done);
- });
- it("triggers a flow reload", function(done) {
- flows.setFlows({
- deploymentType: "reload"
- }).then(function(result) {
- result.should.eql({rev:"newLoadRev"});
- setFlows.called.should.be.false();
- loadFlows.called.should.be.true();
- done();
- }).catch(done);
- });
- it("allows update when revision matches", function(done) {
- flows.setFlows({
- deploymentType: "nodes",
- flows: {flows:[4,5,6],rev:"currentRev"}
- }).then(function(result) {
- result.should.eql({rev:"newRev"});
- setFlows.called.should.be.true();
- setFlows.lastCall.args[0].should.eql([4,5,6]);
- setFlows.lastCall.args[2].should.eql("nodes");
- done();
- }).catch(done);
- });
- it("rejects update when revision does not match", function(done) {
- flows.setFlows({
- deploymentType: "nodes",
- flows: {flows:[4,5,6],rev:"notTheCurrentRev"}
- }).then(function(result) {
- done(new Error("Did not reject rev mismatch"));
- }).catch(function(err) {
- err.should.have.property('code','version_mismatch');
- err.should.have.property('status',409);
- done();
- }).catch(done);
- });
- it("rejects when reload fails",function(done) {
- reloadError = true;
- flows.setFlows({
- deploymentType: "reload"
- }).then(function(result) {
- done(new Error("Did not return internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- done();
- }).catch(done);
- });
- it("rejects when update fails",function(done) {
- flows.setFlows({
- deploymentType: "full",
- flows: {flows:["error",5,6]}
- }).then(function(result) {
- done(new Error("Did not return internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- done();
- }).catch(done);
- });
- });
-
- describe("addFlow", function() {
- var addFlow;
- beforeEach(function() {
- addFlow = sinon.spy(function(flow) {
- if (flow === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- }
- return Promise.resolve("newId");
- });
- flows.init({
- log: mockLog(),
- flows: {
- addFlow: addFlow
- }
- });
- })
- it("adds a flow", function(done) {
- flows.addFlow({flow:{a:"123"}}).then(function(id) {
- addFlow.called.should.be.true();
- addFlow.lastCall.args[0].should.eql({a:"123"});
- id.should.eql("newId");
- done()
- }).catch(done);
- });
- it("rejects when add fails", function(done) {
- flows.addFlow({flow:"error"}).then(function(id) {
- done(new Error("Did not return internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- done();
- }).catch(done);
- });
- });
- describe("getFlow", function() {
- var getFlow;
- beforeEach(function() {
- getFlow = sinon.spy(function(flow) {
- if (flow === "unknown") {
- return null;
- }
- return [1,2,3];
- });
- flows.init({
- log: mockLog(),
- flows: {
- getFlow: getFlow
- }
- });
- })
- it("gets a flow", function(done) {
- flows.getFlow({id:"123"}).then(function(flow) {
- flow.should.eql([1,2,3]);
- done()
- }).catch(done);
- });
- it("rejects when flow not found", function(done) {
- flows.getFlow({id:"unknown"}).then(function(flow) {
- done(new Error("Did not return internal error"));
- }).catch(function(err) {
- err.should.have.property('code','not_found');
- err.should.have.property('status',404);
- done();
- }).catch(done);
- });
- });
-
- describe("updateFlow", function() {
- var updateFlow;
- beforeEach(function() {
- updateFlow = sinon.spy(function(id,flow) {
- if (id === "unknown") {
- var err = new Error();
- // TODO: quirk of internal api - uses .code for .status
- err.code = 404;
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else if (id === "error") {
- var err = new Error();
- // TODO: quirk of internal api - uses .code for .status
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- }
- return Promise.resolve();
- });
- flows.init({
- log: mockLog(),
- flows: {
- updateFlow: updateFlow
- }
- });
- })
- it("updates a flow", function(done) {
- flows.updateFlow({id:"123",flow:[1,2,3]}).then(function(id) {
- id.should.eql("123");
- updateFlow.called.should.be.true();
- updateFlow.lastCall.args[0].should.eql("123");
- updateFlow.lastCall.args[1].should.eql([1,2,3]);
- done()
- }).catch(done);
- });
- it("rejects when flow not found", function(done) {
- flows.updateFlow({id:"unknown"}).then(function(flow) {
- done(new Error("Did not return internal error"));
- }).catch(function(err) {
- err.should.have.property('code','not_found');
- err.should.have.property('status',404);
- done();
- }).catch(done);
- });
- it("rejects when update fails", function(done) {
- flows.updateFlow({id:"error"}).then(function(flow) {
- done(new Error("Did not return internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
-
- describe("deleteFlow", function() {
- var removeFlow;
- beforeEach(function() {
- removeFlow = sinon.spy(function(flow) {
- if (flow === "unknown") {
- var err = new Error();
- // TODO: quirk of internal api - uses .code for .status
- err.code = 404;
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else if (flow === "error") {
- var err = new Error();
- // TODO: quirk of internal api - uses .code for .status
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- }
- return Promise.resolve();
- });
- flows.init({
- log: mockLog(),
- flows: {
- removeFlow: removeFlow
- }
- });
- })
- it("deletes a flow", function(done) {
- flows.deleteFlow({id:"123"}).then(function() {
- removeFlow.called.should.be.true();
- removeFlow.lastCall.args[0].should.eql("123");
- done()
- }).catch(done);
- });
- it("rejects when flow not found", function(done) {
- flows.deleteFlow({id:"unknown"}).then(function(flow) {
- done(new Error("Did not return internal error"));
- }).catch(function(err) {
- err.should.have.property('code','not_found');
- err.should.have.property('status',404);
- done();
- }).catch(done);
- });
- it("rejects when delete fails", function(done) {
- flows.deleteFlow({id:"error"}).then(function(flow) {
- done(new Error("Did not return internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("getNodeCredentials", function() {
- beforeEach(function() {
- flows.init({
- log: mockLog(),
- nodes: {
- getCredentials: function(id) {
- if (id === "unknown") {
- return undefined;
- } else if (id === "known") {
- return {
- username: "abc",
- password: "123"
- }
- } else if (id === "known2") {
- return {
- username: "abc",
- password: ""
- }
- } else {
- return {};
- }
- },
- getCredentialDefinition: function(type) {
- if (type === "node") {
- return {
- username: {type:"text"},
- password: {type:"password"}
- }
- } else {
- return null;
- }
- }
- }
- });
- })
- it("returns an empty object for an unknown node", function(done) {
- flows.getNodeCredentials({id:"unknown", type:"node"}).then(function(result) {
- result.should.eql({});
- done();
- }).catch(done);
- });
- it("gets the filtered credentials for a known node with password", function(done) {
- flows.getNodeCredentials({id:"known", type:"node"}).then(function(result) {
- result.should.eql({
- username: "abc",
- has_password: true
- });
- done();
- }).catch(done);
- });
- it("gets the filtered credentials for a known node without password", function(done) {
- flows.getNodeCredentials({id:"known2", type:"node"}).then(function(result) {
- result.should.eql({
- username: "abc",
- has_password: false
- });
- done();
- }).catch(done);
- });
- it("gets the empty credentials for a known node without a registered definition", function(done) {
- flows.getNodeCredentials({id:"known2", type:"unknown-type"}).then(function(result) {
- result.should.eql({});
- done();
- }).catch(done);
- });
- });
-
-});
diff --git a/test/unit/@node-red/runtime/lib/api/index_spec.js b/test/unit/@node-red/runtime/lib/api/index_spec.js
deleted file mode 100644
index ecedf22ef..000000000
--- a/test/unit/@node-red/runtime/lib/api/index_spec.js
+++ /dev/null
@@ -1,55 +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 NR_TEST_UTILS = require("nr-test-utils");
-var index = NR_TEST_UTILS.require("@node-red/runtime/lib/api/index");
-
-
-describe("runtime-api/index", function() {
- before(function() {
- ["comms","flows","nodes","settings","library","projects"].forEach(n => {
- sinon.stub(NR_TEST_UTILS.require(`@node-red/runtime/lib/api/${n}`),"init").callsFake(()=>{});
- })
- });
- after(function() {
- ["comms","flows","nodes","settings","library","projects"].forEach(n => {
- NR_TEST_UTILS.require(`@node-red/runtime/lib/api/${n}`).init.restore()
- })
- })
- it('isStarted', function(done) {
- index.init({
- isStarted: ()=>true
- });
- index.isStarted({}).then(function(started) {
- started.should.be.true();
- done();
- }).catch(done);
- })
-
- it('isStarted', function(done) {
- index.init({
- version: ()=>"1.2.3.4"
- });
- index.version({}).then(function(version) {
- version.should.eql("1.2.3.4");
- done();
- }).catch(done);
- })
-
-});
diff --git a/test/unit/@node-red/runtime/lib/api/library_spec.js b/test/unit/@node-red/runtime/lib/api/library_spec.js
deleted file mode 100644
index 3fa5291d2..000000000
--- a/test/unit/@node-red/runtime/lib/api/library_spec.js
+++ /dev/null
@@ -1,167 +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 NR_TEST_UTILS = require("nr-test-utils");
-var library = NR_TEST_UTILS.require("@node-red/runtime/lib/api/library")
-
-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/library", function() {
- describe("getEntry", function() {
- before(function() {
- library.init({
- log: mockLog,
- library: {
- getEntry: function(library, type,path) {
- if (type === "known") {
- return Promise.resolve("known");
- } else if (type === "forbidden") {
- var err = new Error("forbidden");
- err.code = "forbidden";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else if (type === "not_found") {
- var err = new Error("forbidden");
- err.code = "not_found";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else if (type === "error") {
- var err = new Error("error");
- err.code = "unknown_error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else if (type === "blank") {
- return Promise.reject();
- }
- }
- }
- })
- })
- it("returns a known entry", function(done) {
- library.getEntry({library: "local",type: "known", path: "/abc"}).then(function(result) {
- result.should.eql("known")
- done();
- }).catch(done)
- })
- it("rejects a forbidden entry", function(done) {
- library.getEntry({library: "local",type: "forbidden", path: "/abc"}).then(function(result) {
- done(new Error("did not reject"));
- }).catch(function(err) {
- err.should.have.property("code","forbidden");
- err.should.have.property("status",403);
- done();
- }).catch(done)
- })
- it("rejects an unknown entry", function(done) {
- library.getEntry({library: "local",type: "not_found", path: "/abc"}).then(function(result) {
- done(new Error("did not reject"));
- }).catch(function(err) {
- err.should.have.property("code","not_found");
- err.should.have.property("status",404);
- done();
- }).catch(done)
- })
- it("rejects a blank (unknown) entry", function(done) {
- library.getEntry({library: "local",type: "blank", path: "/abc"}).then(function(result) {
- done(new Error("did not reject"));
- }).catch(function(err) {
- err.should.have.property("code","not_found");
- err.should.have.property("status",404);
- done();
- }).catch(done)
- })
- it("rejects unexpected error", function(done) {
- library.getEntry({library: "local",type: "error", path: "/abc"}).then(function(result) {
- done(new Error("did not reject"));
- }).catch(function(err) {
- err.should.have.property("status",400);
- done();
- }).catch(done)
- })
- })
- describe("saveEntry", function() {
- var opts;
- before(function() {
- library.init({
- log: mockLog,
- library: {
- saveEntry: function(library,type,path,meta,body) {
- opts = {type,path,meta,body};
- if (type === "known") {
- return Promise.resolve();
- } else if (type === "forbidden") {
- var err = new Error("forbidden");
- err.code = "forbidden";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else if (type === "not_found") {
- var err = new Error("forbidden");
- err.code = "not_found";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- }
- }
- }
- })
- })
-
- it("saves an entry", function(done) {
- library.saveEntry({library: "local",type: "known", path: "/abc", meta: {a:1}, body:"123"}).then(function() {
- opts.should.have.property("type","known");
- opts.should.have.property("path","/abc");
- opts.should.have.property("meta",{a:1});
- opts.should.have.property("body","123");
- done();
- }).catch(done)
- })
- it("rejects a forbidden entry", function(done) {
- library.saveEntry({library: "local",type: "forbidden", path: "/abc", meta: {a:1}, body:"123"}).then(function() {
- done(new Error("did not reject"));
- }).catch(function(err) {
- err.should.have.property("code","forbidden");
- err.should.have.property("status",403);
- done();
- }).catch(done)
- })
- it("rejects an unknown entry", function(done) {
- library.saveEntry({library: "local",type: "not_found", path: "/abc", meta: {a:1}, body:"123"}).then(function() {
- done(new Error("did not reject"));
- }).catch(function(err) {
- err.should.have.property("status",400);
- done();
- }).catch(done)
- })
- })
-
-});
diff --git a/test/unit/@node-red/runtime/lib/api/nodes_spec.js b/test/unit/@node-red/runtime/lib/api/nodes_spec.js
deleted file mode 100644
index 60c6d9edd..000000000
--- a/test/unit/@node-red/runtime/lib/api/nodes_spec.js
+++ /dev/null
@@ -1,1005 +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 NR_TEST_UTILS = require("nr-test-utils");
-var nodes = NR_TEST_UTILS.require("@node-red/runtime/lib/api/nodes")
-
-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/nodes", function() {
- describe("getNodeInfo", function() {
- beforeEach(function() {
- nodes.init({
- log: mockLog(),
- nodes: {
- getNodeInfo: function(id) {
- if (id === "known") {
- return {id:"known"};
- } else {
- return null;
- }
- }
- }
- });
- })
- it("returns node info", function(done) {
- nodes.getNodeInfo({id:"known"}).then(function(result) {
- result.should.eql({id:"known"});
- done();
- }).catch(done);
- });
- it("returns 404 if node not known", function(done) {
- nodes.getNodeInfo({id:"unknown"}).then(function(result) {
- done(new Error("Did not return internal error"));
- }).catch(function(err) {
- err.should.have.property('code','not_found');
- err.should.have.property('status',404);
- done();
- }).catch(done);
- });
- });
- describe("getNodeList", function() {
- beforeEach(function() {
- nodes.init({
- log: mockLog(),
- nodes: {
- getNodeList: function() {
- return [1,2,3];
- }
- }
- });
- })
- it("returns node list", function(done) {
- nodes.getNodeList({}).then(function(result) {
- result.should.eql([1,2,3]);
- done();
- }).catch(done);
- });
- });
-
- describe("getNodeConfig", function() {
- beforeEach(function() {
- nodes.init({
- log: mockLog(),
- nodes: {
- getNodeConfig: function(id,lang) {
- if (id === "known") {
- return id+lang;
- } else {
- return null;
- }
- }
- }
- });
- })
- it("returns node config", function(done) {
- nodes.getNodeConfig({id:"known",lang:'lang'}).then(function(result) {
- result.should.eql("knownlang");
- done();
- }).catch(done);
- });
- it("returns 404 if node not known", function(done) {
- nodes.getNodeConfig({id:"unknown",lang:'lang'}).then(function(result) {
- done(new Error("Did not return internal error"));
- }).catch(function(err) {
- err.should.have.property('code','not_found');
- err.should.have.property('status',404);
- done();
- }).catch(done);
- });
- });
-
- describe("getNodeConfigs", function() {
- beforeEach(function() {
- nodes.init({
- log: mockLog(),
- nodes: {
- getNodeConfigs: function(lang) {
- return lang;
- }
- }
- });
- })
- it("returns all node configs", function(done) {
- nodes.getNodeConfigs({lang:'lang'}).then(function(result) {
- result.should.eql("lang");
- done();
- }).catch(done);
- });
- });
-
- describe("getModuleInfo", function() {
- beforeEach(function() {
- nodes.init({
- log: mockLog(),
- nodes: {
- getModuleInfo: function(id) {
- if (id === "known") {
- return {module:"known"};
- } else {
- return null;
- }
- }
- }
- });
- })
- it("returns node info", function(done) {
- nodes.getModuleInfo({module:"known"}).then(function(result) {
- result.should.eql({module:"known"});
- done();
- }).catch(done);
- });
- it("returns 404 if node not known", function(done) {
- nodes.getModuleInfo({module:"unknown"}).then(function(result) {
- done(new Error("Did not return internal error"));
- }).catch(function(err) {
- err.should.have.property('code','not_found');
- err.should.have.property('status',404);
- done();
- }).catch(done);
- });
- });
-
- describe.skip("addModule", function() {});
- describe.skip("removeModule", function() {});
- describe.skip("setModuleState", function() {});
- describe.skip("setNodeSetState", function() {});
-
- describe.skip("getModuleCatalogs", function() {});
- describe.skip("getModuleCatalog", function() {});
-
- describe.skip("getIconList", function() {});
- describe.skip("getIcon", function() {});
-
-
-});
-
-/*
-var should = require("should");
-var request = require('supertest');
-var express = require('express');
-var bodyParser = require('body-parser');
-var sinon = require('sinon');
-
-var nodes = require("../../../../red/api/admin/nodes");
-var apiUtil = require("../../../../red/api/util");
-
-describe("api/admin/nodes", function() {
-
- var app;
- function initNodes(runtime) {
- runtime.log = {
- audit:function(e){},//console.log(e)},
- _:function(){},
- info: function(){},
- warn: function(){}
- }
- runtime.events = {
- emit: function(){}
- }
- nodes.init(runtime);
-
- }
-
- before(function() {
- app = express();
- app.use(bodyParser.json());
- app.get("/nodes",nodes.getAll);
- app.post("/nodes",nodes.post);
- app.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,nodes.getModule);
- app.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,nodes.getSet);
- app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,nodes.putModule);
- app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,nodes.putSet);
- app.get("/getIcons",nodes.getIcons);
- app.delete("/nodes/:id",nodes.delete);
- sinon.stub(apiUtil,"determineLangFromHeaders").callsFake(function() {
- return "en-US";
- });
- });
- after(function() {
- apiUtil.determineLangFromHeaders.restore();
- })
-
- describe('get nodes', function() {
- it('returns node list', function(done) {
- initNodes({
- nodes:{
- getNodeList: function() {
- return [1,2,3];
- }
- }
- });
- request(app)
- .get('/nodes')
- .set('Accept', 'application/json')
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.be.an.Array();
- res.body.should.have.lengthOf(3);
- done();
- });
- });
-
- it('returns node configs', function(done) {
- initNodes({
- nodes:{
- getNodeConfigs: function() {
- return "";
- }
- },
- i18n: {
- determineLangFromHeaders: function(){}
- }
- });
- request(app)
- .get('/nodes')
- .set('Accept', 'text/html')
- .expect(200)
- .expect("")
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- it('returns node module info', function(done) {
- initNodes({
- nodes:{
- getModuleInfo: function(id) {
- return {"node-red":{name:"node-red"}}[id];
- }
- }
- });
- request(app)
- .get('/nodes/node-red')
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("name","node-red");
- done();
- });
- });
-
- it('returns 404 for unknown module', function(done) {
- initNodes({
- nodes:{
- getModuleInfo: function(id) {
- return {"node-red":{name:"node-red"}}[id];
- }
- }
- });
- request(app)
- .get('/nodes/node-blue')
- .expect(404)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- it('returns individual node info', function(done) {
- initNodes({
- nodes:{
- getNodeInfo: function(id) {
- return {"node-red/123":{id:"node-red/123"}}[id];
- }
- }
- });
- request(app)
- .get('/nodes/node-red/123')
- .set('Accept', 'application/json')
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("id","node-red/123");
- done();
- });
- });
-
- it('returns individual node configs', function(done) {
- initNodes({
- nodes:{
- getNodeConfig: function(id) {
- return {"node-red/123":""}[id];
- }
- },
- i18n: {
- determineLangFromHeaders: function(){}
- }
- });
- request(app)
- .get('/nodes/node-red/123')
- .set('Accept', 'text/html')
- .expect(200)
- .expect("")
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- it('returns 404 for unknown node', function(done) {
- initNodes({
- nodes:{
- getNodeInfo: function(id) {
- return {"node-red/123":{id:"node-red/123"}}[id];
- }
- }
- });
- request(app)
- .get('/nodes/node-red/456')
- .set('Accept', 'application/json')
- .expect(404)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
- });
-
- describe('install', function() {
-
- it('returns 400 if settings are unavailable', function(done) {
- initNodes({
- settings:{available:function(){return false}}
- });
- request(app)
- .post('/nodes')
- .expect(400)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- it('returns 400 if request is invalid', function(done) {
- initNodes({
- settings:{available:function(){return true}}
- });
- request(app)
- .post('/nodes')
- .send({})
- .expect(400)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- describe('by module', function() {
- it('installs the module and returns module info', function(done) {
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getModuleInfo: function(id) { return null; },
- installModule: function() {
- return Promise.resolve({
- name:"foo",
- nodes:[{id:"123"}]
- });
- }
- }
- });
- request(app)
- .post('/nodes')
- .send({module: 'foo'})
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("name","foo");
- res.body.should.have.property("nodes");
- res.body.nodes[0].should.have.property("id","123");
- done();
- });
- });
-
- it('fails the install if already installed', function(done) {
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getModuleInfo: function(id) { return {nodes:{id:"123"}}; },
- installModule: function() {
- return Promise.resolve({id:"123"});
- }
- }
- });
- request(app)
- .post('/nodes')
- .send({module: 'foo'})
- .expect(400)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- it('fails the install if module error', function(done) {
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getModuleInfo: function(id) { return null },
- installModule: function() {
- return Promise.reject(new Error("test error"));
- }
- }
- });
- request(app)
- .post('/nodes')
- .send({module: 'foo'})
- .expect(400)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("message","Error: test error");
- done();
- });
- });
- it('fails the install if module not found', function(done) {
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getModuleInfo: function(id) { return null },
- installModule: function() {
- var err = new Error("test error");
- err.code = 404;
- return Promise.reject(err);
- }
- }
- });
- request(app)
- .post('/nodes')
- .send({module: 'foo'})
- .expect(404)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
- });
- });
- describe('delete', function() {
- it('returns 400 if settings are unavailable', function(done) {
- initNodes({
- settings:{available:function(){return false}}
- });
-
- request(app)
- .del('/nodes/123')
- .expect(400)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- describe('by module', function() {
- it('uninstalls the module', function(done) {
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getModuleInfo: function(id) { return {nodes:[{id:"123"}]} },
- getNodeInfo: function() { return null },
- uninstallModule: function() { return Promise.resolve({id:"123"});}
- }
- });
- request(app)
- .del('/nodes/foo')
- .expect(204)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- it('fails the uninstall if the module is not installed', function(done) {
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getModuleInfo: function(id) { return null },
- getNodeInfo: function() { return null }
- }
- });
- request(app)
- .del('/nodes/foo')
- .expect(404)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- it('fails the uninstall if the module is not installed', function(done) {
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getModuleInfo: function(id) { return {nodes:[{id:"123"}]} },
- getNodeInfo: function() { return null },
- uninstallModule: function() { return Promise.reject(new Error("test error"));}
- }
- });
- request(app)
- .del('/nodes/foo')
- .expect(400)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("message","Error: test error");
- done();
- });
- });
- });
-
- });
-
- describe('enable/disable', function() {
- it('returns 400 if settings are unavailable', function(done) {
- initNodes({
- settings:{available:function(){return false}}
- });
- request(app)
- .put('/nodes/123')
- .expect(400)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- it('returns 400 for invalid node payload', function(done) {
- initNodes({
- settings:{available:function(){return true}}
- });
- request(app)
- .put('/nodes/node-red/foo')
- .send({})
- .expect(400)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("message","Invalid request");
- done();
- });
- });
-
- it('returns 400 for invalid module payload', function(done) {
- initNodes({
- settings:{available:function(){return true}}
- });
- request(app)
- .put('/nodes/foo')
- .send({})
- .expect(400)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("message","Invalid request");
-
- done();
- });
- });
-
- it('returns 404 for unknown node', function(done) {
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getNodeInfo: function() { return null }
- }
- });
-
- request(app)
- .put('/nodes/node-red/foo')
- .send({enabled:false})
- .expect(404)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- it('returns 404 for unknown module', function(done) {
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getModuleInfo: function(id) { return null }
- }
- });
-
- request(app)
- .put('/nodes/node-blue')
- .send({enabled:false})
- .expect(404)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- it('enables disabled node', function(done) {
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getNodeInfo: function() { return {id:"123",enabled: false} },
- enableNode: function() { return Promise.resolve({id:"123",enabled: true,types:['a']}); }
- }
- });
- request(app)
- .put('/nodes/node-red/foo')
- .send({enabled:true})
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("id","123");
- res.body.should.have.property("enabled",true);
-
- done();
- });
- });
-
- it('disables enabled node', function(done) {
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getNodeInfo: function() { return {id:"123",enabled: true} },
- disableNode: function() { return Promise.resolve({id:"123",enabled: false,types:['a']}); }
- }
- });
- request(app)
- .put('/nodes/node-red/foo')
- .send({enabled:false})
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("id","123");
- res.body.should.have.property("enabled",false);
-
- done();
- });
- });
-
- describe('no-ops if already in the right state', function() {
- function run(state,done) {
- var enableNode = sinon.spy(function() { return Promise.resolve({id:"123",enabled: true,types:['a']}) });
- var disableNode = sinon.spy(function() { return Promise.resolve({id:"123",enabled: false,types:['a']}) });
-
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getNodeInfo: function() { return {id:"123",enabled: state} },
- enableNode: enableNode,
- disableNode: disableNode
- }
- });
- request(app)
- .put('/nodes/node-red/foo')
- .send({enabled:state})
- .expect(200)
- .end(function(err,res) {
- var enableNodeCalled = enableNode.called;
- var disableNodeCalled = disableNode.called;
- if (err) {
- throw err;
- }
- enableNodeCalled.should.be.false();
- disableNodeCalled.should.be.false();
- res.body.should.have.property("id","123");
- res.body.should.have.property("enabled",state);
-
- done();
- });
- }
- it('already enabled', function(done) {
- run(true,done);
- });
- it('already disabled', function(done) {
- run(false,done);
- });
- });
-
- describe('does not no-op if err on node', function() {
- function run(state,done) {
- var enableNode = sinon.spy(function() { return Promise.resolve({id:"123",enabled: true,types:['a']}) });
- var disableNode = sinon.spy(function() { return Promise.resolve({id:"123",enabled: false,types:['a']}) });
-
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getNodeInfo: function() { return {id:"123",enabled: state, err:"foo"} },
- enableNode: enableNode,
- disableNode: disableNode
- }
- });
- request(app)
- .put('/nodes/node-red/foo')
- .send({enabled:state})
- .expect(200)
- .end(function(err,res) {
- var enableNodeCalled = enableNode.called;
- var disableNodeCalled = disableNode.called;
- if (err) {
- throw err;
- }
- enableNodeCalled.should.be.equal(state);
- disableNodeCalled.should.be.equal(!state);
- res.body.should.have.property("id","123");
- res.body.should.have.property("enabled",state);
-
- done();
- });
- }
- it('already enabled', function(done) {
- run(true,done);
- });
- it('already disabled', function(done) {
- run(false,done);
- });
- });
-
- it('enables disabled module', function(done) {
- var n1 = {id:"123",enabled:false,types:['a']};
- var n2 = {id:"456",enabled:false,types:['b']};
- var enableNode = sinon.stub();
- enableNode.onFirstCall().returns((function() {
- n1.enabled = true;
- return Promise.resolve(n1);
- })());
- enableNode.onSecondCall().returns((function() {
- n2.enabled = true;
- return Promise.resolve(n2);
- })());
- enableNode.returns(null);
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getModuleInfo: function() { return {name:"node-red", nodes:[n1, n2]} },
- enableNode: enableNode
- }
- });
-
- request(app)
- .put('/nodes/node-red')
- .send({enabled:true})
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("name","node-red");
- res.body.should.have.property("nodes");
- res.body.nodes[0].should.have.property("enabled",true);
- res.body.nodes[1].should.have.property("enabled",true);
-
- done();
- });
- });
-
- it('disables enabled module', function(done) {
- var n1 = {id:"123",enabled:true,types:['a']};
- var n2 = {id:"456",enabled:true,types:['b']};
- var disableNode = sinon.stub();
- disableNode.onFirstCall().returns((function() {
- n1.enabled = false;
- return Promise.resolve(n1);
- })());
- disableNode.onSecondCall().returns((function() {
- n2.enabled = false;
- return Promise.resolve(n2);
- })());
- disableNode.returns(null);
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getModuleInfo: function() { return {name:"node-red", nodes:[n1, n2]} },
- disableNode: disableNode
- }
- });
-
- request(app)
- .put('/nodes/node-red')
- .send({enabled:false})
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("name","node-red");
- res.body.should.have.property("nodes");
- res.body.nodes[0].should.have.property("enabled",false);
- res.body.nodes[1].should.have.property("enabled",false);
-
- done();
- });
- });
-
- describe('no-ops if a node in module already in the right state', function() {
- function run(state,done) {
- var node = {id:"123",enabled:state,types:['a']};
- var enableNode = sinon.spy(function(id) {
- node.enabled = true;
- return Promise.resolve(node);
- });
- var disableNode = sinon.spy(function(id) {
- node.enabled = false;
- return Promise.resolve(node);
- });
-
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getModuleInfo: function() { return {name:"node-red", nodes:[node]}; },
- enableNode: enableNode,
- disableNode: disableNode
- }
- });
- request(app)
- .put('/nodes/node-red')
- .send({enabled:state})
- .expect(200)
- .end(function(err,res) {
- var enableNodeCalled = enableNode.called;
- var disableNodeCalled = disableNode.called;
- if (err) {
- throw err;
- }
- enableNodeCalled.should.be.false();
- disableNodeCalled.should.be.false();
- res.body.should.have.property("name","node-red");
- res.body.should.have.property("nodes");
- res.body.nodes[0].should.have.property("enabled",state);
-
- done();
- });
- }
- it('already enabled', function(done) {
- run(true,done);
- });
- it('already disabled', function(done) {
- run(false,done);
- });
- });
-
- describe('does not no-op if err on a node in module', function() {
- function run(state,done) {
- var node = {id:"123",enabled:state,types:['a'],err:"foo"};
- var enableNode = sinon.spy(function(id) {
- node.enabled = true;
- return Promise.resolve(node);
- });
- var disableNode = sinon.spy(function(id) {
- node.enabled = false;
- return Promise.resolve(node);
- });
-
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getModuleInfo: function() { return {name:"node-red", nodes:[node]}; },
- enableNode: enableNode,
- disableNode: disableNode
- }
- });
-
- request(app)
- .put('/nodes/node-red')
- .send({enabled:state})
- .expect(200)
- .end(function(err,res) {
- var enableNodeCalled = enableNode.called;
- var disableNodeCalled = disableNode.called;
- if (err) {
- throw err;
- }
- enableNodeCalled.should.be.equal(state);
- disableNodeCalled.should.be.equal(!state);
- res.body.should.have.property("name","node-red");
- res.body.should.have.property("nodes");
- res.body.nodes[0].should.have.property("enabled",state);
-
- done();
- });
- }
- it('already enabled', function(done) {
- run(true,done);
- });
- it('already disabled', function(done) {
- run(false,done);
- });
- });
- });
-
- describe('get icons', function() {
- it('returns icon list', function(done) {
- initNodes({
- nodes:{
- getNodeIcons: function() {
- return {"module":["1.png","2.png","3.png"]};
- }
- }
- });
- request(app)
- .get('/getIcons')
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- console.log(res.body);
- res.body.should.have.property("module");
- res.body.module.should.be.an.Array();
- res.body.module.should.have.lengthOf(3);
- done();
- });
- });
- });
-});
-
-*/
diff --git a/test/unit/@node-red/runtime/lib/api/plugins_spec.js b/test/unit/@node-red/runtime/lib/api/plugins_spec.js
deleted file mode 100644
index 7ae6d8286..000000000
--- a/test/unit/@node-red/runtime/lib/api/plugins_spec.js
+++ /dev/null
@@ -1,68 +0,0 @@
-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" } }))
- })
- });
- });
-
-});
\ No newline at end of file
diff --git a/test/unit/@node-red/runtime/lib/api/projects_spec.js b/test/unit/@node-red/runtime/lib/api/projects_spec.js
deleted file mode 100644
index 2fe7ca221..000000000
--- a/test/unit/@node-red/runtime/lib/api/projects_spec.js
+++ /dev/null
@@ -1,1170 +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 NR_TEST_UTILS = require("nr-test-utils");
-var projects = NR_TEST_UTILS.require("@node-red/runtime/lib/api/projects")
-
-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/settings", function() {
- describe("available", function() {
- it("resolves true if projects available", function(done) {
- projects.init({
- storage: {
- projects: {}
- }
- });
- projects.available().then(function(result) {
- result.should.be.true();
- done();
- }).catch(done);
- })
- it("resolves false if projects unavailable", function(done) {
- projects.init({
- storage: {
- }
- });
- projects.available().then(function(result) {
- result.should.be.false();
- done();
- }).catch(done);
- })
-
- });
- describe("listProjects", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- listProjects: sinon.spy(function(user) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve([1,2,3]);
- }
- }),
- getActiveProject: function(user) {
- if (user === "noActive") {
- return null;
- }
- return {name:"aProject"};
- }
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("lists the projects, without an active project", function(done) {
- projects.listProjects({user:"noActive"}).then(function(result) {
- result.should.have.property('projects',[1,2,3]);
- result.should.not.have.property('active');
- done();
- }).catch(done);
- });
- it("lists the projects, with an active project", function(done) {
- projects.listProjects({user:"foo"}).then(function(result) {
- result.should.have.property('projects',[1,2,3]);
- result.should.have.property('active','aProject');
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.listProjects({user:"error"}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- err.should.have.property('status',400);
- done();
- }).catch(done);
- });
-
- });
- describe("createProject", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- createProject: sinon.spy(function(user,project) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve(project);
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("create project", function(done) {
- projects.createProject({user:"known",project:{a:1}}).then(function(result) {
- result.should.eql({a:1});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.createProject({user:"error"}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
- describe("initialiseProject", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- initialiseProject: sinon.spy(function(user,id,project) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({id,project});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("intialise project", function(done) {
- projects.initialiseProject({user:"known",id:123, project:{a:1}}).then(function(result) {
- result.should.eql({id:123, project:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.initialiseProject({user:"error"}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("getActiveProject", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- getActiveProject: sinon.spy(function(user) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve("123");
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("returns active project", function(done) {
- projects.getActiveProject({user:"known"}).then(function(result) {
- result.should.eql("123");
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.getActiveProject({user:"error"}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("setActiveProject", function() {
- var activeProject;
- var runtime;
- beforeEach(function() {
- runtime = {
- log: mockLog(),
- storage: {projects: {
- getActiveProject: sinon.spy(function() { return activeProject;}),
- setActiveProject: sinon.spy(function(user,id) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id});
- }
- })
- }}};
- projects.init(runtime);
- })
- it("sets project if current project is unset", function(done) {
- activeProject = null;
- projects.setActiveProject({user:"known",id:123}).then(function(result) {
- result.should.eql({user:"known",id:123});
- done();
- }).catch(done);
- });
- it("sets project if current project is different", function(done) {
- activeProject = {name:456};
- projects.setActiveProject({user:"known",id:123}).then(function(result) {
- result.should.eql({user:"known",id:123});
- done();
- }).catch(done);
- });
- it("no-ops if current project is same", function(done) {
- activeProject = {name:123};
- projects.setActiveProject({user:"known",id:123}).then(function(result) {
- (result === undefined).should.be.true();
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.setActiveProject({user:"error"}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("getProject", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- getProject: sinon.spy(function(user,id) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("returns project", function(done) {
- projects.getProject({user:"known",id:123}).then(function(result) {
- result.should.eql({user:"known",id:123});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.getProject({user:"error"}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
- describe("updateProject", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- updateProject: sinon.spy(function(user,id,project) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,project});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("updates project", function(done) {
- projects.updateProject({user:"known",id:123,project:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,project:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.updateProject({user:"error",id:123,project:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("deleteProject", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- deleteProject: sinon.spy(function(user,id) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("deletes project", function(done) {
- projects.deleteProject({user:"known",id:123}).then(function(result) {
- result.should.eql({user:"known",id:123});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.deleteProject({user:"error",id:123}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("getStatus", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- getStatus: sinon.spy(function(user,id,remote) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,remote});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("gets status", function(done) {
- projects.getStatus({user:"known",id:123,remote:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,remote:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.getStatus({user:"error",id:123,project:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
- describe("getBranches", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- getBranches: sinon.spy(function(user,id,remote) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,remote});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("gets branches", function(done) {
- projects.getBranches({user:"known",id:123,remote:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,remote:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.getBranches({user:"error",id:123,remote:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
- describe("getBranchStatus", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- getBranchStatus: sinon.spy(function(user,id,branch) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,branch});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("gets branch status", function(done) {
- projects.getBranchStatus({user:"known",id:123,branch:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,branch:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.getBranchStatus({user:"error",id:123,branch:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("setBranch", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- setBranch: sinon.spy(function(user,id,branch,create) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,branch,create});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("commits", function(done) {
- projects.setBranch({user:"known",id:123,branch:{a:1},create:true}).then(function(result) {
- result.should.eql({user:"known",id:123,branch:{a:1},create:true});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.setBranch({user:"error",id:123,branch:{a:1},create:true}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("deleteBranch", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- deleteBranch: sinon.spy(function(user,id,branch,something,force) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,branch,force});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("commits", function(done) {
- projects.deleteBranch({user:"known",id:123,branch:{a:1},force:true}).then(function(result) {
- result.should.eql({user:"known",id:123,branch:{a:1},force:true});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.deleteBranch({user:"error",id:123,branch:{a:1},force:true}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("commit", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- commit: sinon.spy(function(user,id,message) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,message});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("commits", function(done) {
- projects.commit({user:"known",id:123,message:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,message:{message:{a:1}}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.commit({user:"error",id:123,message:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
- describe("getCommit", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- getCommit: sinon.spy(function(user,id,sha) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,sha});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("gets commit", function(done) {
- projects.getCommit({user:"known",id:123,sha:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,sha:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.getCommit({user:"error",id:123,sha:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("getCommits", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- getCommits: sinon.spy(function(user,id,options) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,options});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("gets commits with default limit/before", function(done) {
- projects.getCommits({user:"known",id:123}).then(function(result) {
- result.should.eql({user:"known",id:123,options:{limit:20,before:undefined}});
- done();
- }).catch(done);
- });
- it("gets commits with provided limit/before", function(done) {
- projects.getCommits({user:"known",id:123,limit:10,before:456}).then(function(result) {
- result.should.eql({user:"known",id:123,options:{limit:10,before:456}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.getCommits({user:"error"}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("abortMerge", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- abortMerge: sinon.spy(function(user,id) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("aborts merge", function(done) {
- projects.abortMerge({user:"known",id:123}).then(function(result) {
- result.should.eql({user:"known",id:123});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.abortMerge({user:"error"}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("resolveMerge", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- resolveMerge: sinon.spy(function(user,id,path,resolution) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,path,resolution});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("resolves merge", function(done) {
- projects.resolveMerge({user:"known",id:123,path:"/abc",resolution:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,path:"/abc",resolution:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.resolveMerge({user:"error",id:123,path:"/abc",resolution:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("getFiles", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- getFiles: sinon.spy(function(user,id) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("gets files", function(done) {
- projects.getFiles({user:"known",id:123}).then(function(result) {
- result.should.eql({user:"known",id:123});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.getFiles({user:"error"}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("getFile", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- getFile: sinon.spy(function(user,id,path,tree) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,path,tree});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("gets file", function(done) {
- projects.getFile({user:"known",id:123,path:"/abc",tree:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,path:"/abc",tree:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.getFile({user:"error",id:123,path:"/abc",tree:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("stageFile", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- stageFile: sinon.spy(function(user,id,path) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,path});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("stages a file", function(done) {
- projects.stageFile({user:"known",id:123,path:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,path:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.stageFile({user:"error",id:123,path:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
- describe("unstageFile", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- unstageFile: sinon.spy(function(user,id,path) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,path});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("unstages a file", function(done) {
- projects.unstageFile({user:"known",id:123,path:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,path:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.unstageFile({user:"error",id:123,path:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("revertFile", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- revertFile: sinon.spy(function(user,id,path) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,path});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("reverts a file", function(done) {
- projects.revertFile({user:"known",id:123,path:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,path:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.revertFile({user:"error",id:123,path:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("getFileDiff", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- getFileDiff: sinon.spy(function(user,id,path,type) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,path,type});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("gets file diff", function(done) {
- projects.getFileDiff({user:"known",id:123,path:{a:1},type:"abc"}).then(function(result) {
- result.should.eql({user:"known",id:123,path:{a:1},type:"abc"});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.getFileDiff({user:"error",id:123,path:{a:1},type:"abc"}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("getRemotes", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- getRemotes: sinon.spy(function(user,id) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("gets remotes", function(done) {
- projects.getRemotes({user:"known",id:123}).then(function(result) {
- result.should.eql({user:"known",id:123});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.getRemotes({user:"error"}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("addRemote", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- addRemote: sinon.spy(function(user,id,remote) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,remote});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("adds a remote", function(done) {
- projects.addRemote({user:"known",id:123,remote:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,remote:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.addRemote({user:"error",id:123,remote:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("removeRemote", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- removeRemote: sinon.spy(function(user,id,remote) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,remote});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("removes a remote", function(done) {
- projects.removeRemote({user:"known",id:123,remote:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,remote:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.removeRemote({user:"error",id:123,remote:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("updateRemote", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- updateRemote: sinon.spy(function(user,id,name,remote) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,name,remote});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("updates a remote", function(done) {
- projects.updateRemote({user:"known",id:123,remote:{name:"abc",a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,name:"abc",remote:{name:"abc",a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.updateRemote({user:"error",id:123,remote:{name:"abc",a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
- describe("pull", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- pull: sinon.spy(function(user,id,remote,track,allowUnrelatedHistories) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,remote,track,allowUnrelatedHistories});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("pulls", function(done) {
- projects.pull({user:"known",id:123,remote:"abc",track:false,allowUnrelatedHistories:true}).then(function(result) {
- result.should.eql({user:"known",id:123,remote:"abc",track:false,allowUnrelatedHistories:true});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.pull({user:"error",id:123,remote:"abc",track:false,allowUnrelatedHistories:true}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
- describe("push", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- push: sinon.spy(function(user,id,remote,track) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,remote,track});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("pulls", function(done) {
- projects.push({user:"known",id:123,remote:"abc",track:false}).then(function(result) {
- result.should.eql({user:"known",id:123,remote:"abc",track:false});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.push({user:"error",id:123,remote:"abc",track:false}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
-
-});
diff --git a/test/unit/@node-red/runtime/lib/api/settings_spec.js b/test/unit/@node-red/runtime/lib/api/settings_spec.js
deleted file mode 100644
index 9b3b94229..000000000
--- a/test/unit/@node-red/runtime/lib/api/settings_spec.js
+++ /dev/null
@@ -1,988 +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 clone = require("clone");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-var settings = NR_TEST_UTILS.require("@node-red/runtime/lib/api/settings")
-
-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/settings", function() {
- describe("getRuntimeSettings", function() {
- it("gets the runtime settings", function() {
- settings.init({
- settings: {
- foo: 123,
- httpNodeRoot: "testHttpNodeRoot",
- version: "testVersion",
- paletteCategories :["red","blue","green"],
- exportNodeSettings: (obj) => {
- obj.testNodeSetting = "helloWorld";
- },
- },
- plugins: {
- exportPluginSettings: (obj) => {
- obj.testPluginSettings = "helloPluginWorld";
- }
- },
- nodes: {
- listContextStores: () => { return {stores:["file","memory"], default: "file"} },
- installerEnabled: () => false,
- getCredentialKeyType: () => "test-key-type"
- },
- library: {getLibraries: () => ["lib1"] },
- storage: {}
- })
- return settings.getRuntimeSettings({}).then(result => {
- result.should.have.property("httpNodeRoot","testHttpNodeRoot");
- result.should.have.property("version","testVersion");
- result.should.have.property("paletteCategories",["red","blue","green"]);
- result.should.have.property("libraries",["lib1"]);
- result.should.have.property("testNodeSetting","helloWorld");
- result.should.have.property("testPluginSettings","helloPluginWorld");
- result.should.not.have.property("foo",123);
- result.should.have.property("flowEncryptionType","test-key-type");
- result.should.not.have.property("user");
- result.should.have.property("externalModules");
- result.externalModules.should.eql({palette:{allowInstall:false, allowUpload: false}});
-
- })
- });
- it("gets the filtered user settings", function() {
- settings.init({
- settings: {
- foo: 123,
- httpNodeRoot: "testHttpNodeRoot",
- version: "testVersion",
- paletteCategories :["red","blue","green"],
- exportNodeSettings: (obj) => {
- obj.testNodeSetting = "helloWorld";
- },
- },
- plugins: {
- exportPluginSettings: (obj) => {
- obj.testPluginSettings = "helloPluginWorld";
- }
- },
- nodes: {
- listContextStores: () => { return {stores:["file","memory"], default: "file"} },
- installerEnabled: () => false,
- getCredentialKeyType: () => "test-key-type"
- },
- library: {getLibraries: () => { ["lib1"]} },
- storage: {}
- })
- return settings.getRuntimeSettings({
- user: {
- username: "nick",
- anonymous: false,
- image: "http://example.com",
- permissions: "*",
- private: "secret"
- }
- }).then(result => {
- result.should.have.property("user");
- result.user.should.have.property("username","nick");
- result.user.should.have.property("permissions","*");
- result.user.should.have.property("image","http://example.com");
- result.user.should.have.property("anonymous",false);
- result.user.should.not.have.property("private");
- })
- });
- it("gets the filtered settings when editor disabled ", function() {
- settings.init({
- settings: {
- disableEditor: true,
- foo: 123,
- httpNodeRoot: "testHttpNodeRoot",
- version: "testVersion",
- paletteCategories :["red","blue","green"],
- exportNodeSettings: (obj) => {
- obj.testNodeSetting = "helloWorld";
- },
- },
- plugins: {
- exportPluginSettings: (obj) => {
- obj.testPluginSettings = "helloPluginWorld";
- }
- },
- nodes: {
- listContextStores: () => { return {stores:["file","memory"], default: "file"} },
- installerEnabled: () => false,
- getCredentialKeyType: () => "test-key-type"
- },
- library: {getLibraries: () => { ["lib1"]} },
- storage: {
- projects: {
- getActiveProject: () => 'test-active-project',
- getFlowFilename: () => 'test-flow-file',
- getCredentialsFilename: () => 'test-creds-file',
- getGlobalGitUser: () => {return {name:'foo',email:'foo@example.com'}}
- }
- }
- })
- return settings.getRuntimeSettings({
- user: {
- username: "nick",
- anonymous: false,
- image: "http://example.com",
- permissions: "*",
- private: "secret"
- }
- }).then(result => {
- result.should.have.property("user");
- result.user.should.have.property("username","nick");
- result.user.should.have.property("permissions","*");
- result.user.should.have.property("image","http://example.com");
- result.user.should.have.property("anonymous",false);
- result.user.should.not.have.property("private");
-
- // Filtered out when disableEditor is true
- result.should.not.have.property("paletteCategories",["red","blue","green"]);
- result.should.not.have.property("testNodeSetting","helloWorld");
- result.should.not.have.property("foo",123);
- result.should.not.have.property("flowEncryptionType","test-key-type");
- result.should.not.have.property("project");
- result.should.not.have.property("git");
-
- })
- });
- it('includes project settings if projects available', function() {
- settings.init({
- settings: {
- foo: 123,
- httpNodeRoot: "testHttpNodeRoot",
- version: "testVersion",
- paletteCategories :["red","blue","green"],
- exportNodeSettings: (obj) => {
- obj.testNodeSetting = "helloWorld";
- },
- },
- plugins: {
- exportPluginSettings: (obj) => {
- obj.testPluginSettings = "helloPluginWorld";
- }
- },
- nodes: {
- listContextStores: () => { return {stores:["file","memory"], default: "file"} },
- installerEnabled: () => false,
- getCredentialKeyType: () => "test-key-type"
- },
- library: {getLibraries: () => { ["lib1"]} },
- storage: {
- projects: {
- getActiveProject: () => 'test-active-project',
- getFlowFilename: () => 'test-flow-file',
- getCredentialsFilename: () => 'test-creds-file',
- getGlobalGitUser: () => {return {name:'foo',email:'foo@example.com'}}
- }
- }
- })
- return settings.getRuntimeSettings({
- user: {
- username: "nick",
- anonymous: false,
- image: "http://example.com",
- permissions: "*",
- private: "secret"
- }
- }).then(result => {
- result.should.have.property("project","test-active-project");
- result.should.not.have.property("files");
- result.should.have.property("git");
- result.git.should.have.property("globalUser",{name:'foo',email:'foo@example.com'});
- });
- });
-
- it('includes existing files details if projects enabled but no active project and files exist', function() {
- settings.init({
- settings: {
- foo: 123,
- httpNodeRoot: "testHttpNodeRoot",
- version: "testVersion",
- paletteCategories :["red","blue","green"],
- exportNodeSettings: (obj) => {
- obj.testNodeSetting = "helloWorld";
- },
- },
- plugins: {
- exportPluginSettings: (obj) => {
- obj.testPluginSettings = "helloPluginWorld";
- }
- },
- nodes: {
- listContextStores: () => { return {stores:["file","memory"], default: "file"} },
- installerEnabled: () => false,
- getCredentialKeyType: () => "test-key-type"
- },
- library: {getLibraries: () => { ["lib1"]} },
- storage: {
- projects: {
- flowFileExists: () => true,
- getActiveProject: () => false,
- getFlowFilename: () => 'test-flow-file',
- getCredentialsFilename: () => 'test-creds-file',
- getGlobalGitUser: () => {return {name:'foo',email:'foo@example.com'}}
- }
- }
- })
- return settings.getRuntimeSettings({
- user: {
- username: "nick",
- anonymous: false,
- image: "http://example.com",
- permissions: "*",
- private: "secret"
- }
- }).then(result => {
- result.git.should.have.property("globalUser",{name:'foo',email:'foo@example.com'});
- result.should.not.have.property("project");
- result.should.have.property("files");
- result.files.should.have.property("flow",'test-flow-file');
- result.files.should.have.property("credentials",'test-creds-file');
- result.should.have.property("git");
- result.git.should.have.property("globalUser",{name:'foo',email:'foo@example.com'});
- });
- });
-
- it('does not include file details if projects enabled but no active project and files do not exist', function() {
- settings.init({
- settings: {
- foo: 123,
- httpNodeRoot: "testHttpNodeRoot",
- version: "testVersion",
- paletteCategories :["red","blue","green"],
- exportNodeSettings: (obj) => {
- obj.testNodeSetting = "helloWorld";
- },
- },
- plugins: {
- exportPluginSettings: (obj) => {
- obj.testPluginSettings = "helloPluginWorld";
- }
- },
- nodes: {
- listContextStores: () => { return {stores:["file","memory"], default: "file"} },
- installerEnabled: () => false,
- getCredentialKeyType: () => "test-key-type"
- },
- library: {getLibraries: () => { ["lib1"]} },
- storage: {
- projects: {
- flowFileExists: () => false,
- getActiveProject: () => false,
- getFlowFilename: () => 'test-flow-file',
- getCredentialsFilename: () => 'test-creds-file',
- getGlobalGitUser: () => {return {name:'foo',email:'foo@example.com'}}
- }
- }
- })
- return settings.getRuntimeSettings({
- user: {
- username: "nick",
- anonymous: false,
- image: "http://example.com",
- permissions: "*",
- private: "secret"
- }
- }).then(result => {
- result.should.not.have.property("project");
- result.should.not.have.property("files");
- result.should.have.property("git");
- result.git.should.have.property("globalUser",{name:'foo',email:'foo@example.com'});
- });
- });
- });
- describe("getUserSettings", function() {
- before(function() {
- settings.init({
- settings: {
- getUserSettings: username => username
- }
- });
- })
- it("returns default user settings", function() {
- return settings.getUserSettings({}).then(result => {
- result.should.eql("_");
- })
- })
- it("returns default user settings for anonymous", function() {
- return settings.getUserSettings({user:{anonymous:true}}).then(result => {
- result.should.eql("_");
- })
- })
- it("returns user settings", function() {
- return settings.getUserSettings({user:{username:'nick'}}).then(result => {
- result.should.eql("nick");
- })
- })
- });
-
- describe("updateUserSettings", function() {
- var userSettings;
- before(function() {
- settings.init({
- settings: {
- getUserSettings: username => clone(userSettings[username]),
- setUserSettings: (username, settings) => {
- if (username === 'error') {
- var p = Promise.reject(new Error("unknown user"));
- p.catch(()=>{});
- return p;
- } else if (username === 'throw') {
- throw new Error("thrown error");
- }
- userSettings[username] = clone(settings);
- return Promise.resolve();
- }
- },
- log: mockLog()
- });
- })
- beforeEach(function() {
- userSettings = {
- "_": { abc: 123 },
- "nick": {abc: 456}
- }
- })
- it('sets default user settings', function() {
- return settings.updateUserSettings({settings:{abc:789}}).then(function() {
- userSettings._.abc.should.eql(789)
- })
- })
- it('merges user settings', function() {
- return settings.updateUserSettings({settings:{def:789}}).then(function() {
- userSettings._.abc.should.eql(123)
- userSettings._.def.should.eql(789)
- })
- })
- it('sets default user settings for anonymous user', function() {
- return settings.updateUserSettings({user:{anonymous:true},settings:{def:789}}).then(function() {
- userSettings._.abc.should.eql(123)
- userSettings._.def.should.eql(789)
- })
- })
- it('sets named user settings', function() {
- return settings.updateUserSettings({user:{username:'nick'},settings:{def:789}}).then(function() {
- userSettings.nick.abc.should.eql(456)
- userSettings.nick.def.should.eql(789)
- })
- })
- it('rejects with suitable error', function(done) {
- settings.updateUserSettings({user:{username:'error'},settings:{def:789}}).then(result => {
- done("Unexpected resolve for error case");
- }).catch(err => {
- err.should.have.property('status', 400);
- done();
- }).catch(done);
- })
- it('rejects with suitable error - thrown', function(done) {
- settings.updateUserSettings({user:{username:'throw'},settings:{def:789}}).then(result => {
- done("Unexpected resolve for error case");
- }).catch(err => {
- err.should.have.property('status', 400);
- done();
- }).catch(done);
- })
- });
- describe("getUserKeys", function() {
- before(function() {
- settings.init({
- storage: {
- projects: {
- ssh: {
- listSSHKeys: username => {
- if (username === 'error') {
- var p = Promise.reject(new Error("unknown user"));
- p.catch(()=>{});
- return p;
- }
- return Promise.resolve([username])
- }
- }
- }
- }
- })
- })
- it('returns the default users keys', function() {
- return settings.getUserKeys({}).then(result => {
- result.should.eql(['__default']);
- })
- })
- it('returns the default users keys for anonymous', function() {
- return settings.getUserKeys({user:{anonymous:true}}).then(result => {
- result.should.eql(['__default']);
- })
- })
- it('returns the users keys', function() {
- return settings.getUserKeys({user:{username:'nick'}}).then(result => {
- result.should.eql(['nick']);
- })
- })
- it('rejects with suitable error', function(done) {
- settings.getUserKeys({user:{username:'error'}}).then(result => {
- done("Unexpected resolve for error case");
- }).catch(err => {
- err.should.have.property('status', 400);
- done();
- }).catch(done);
- })
- });
-
- describe("getUserKey", function() {
- before(function() {
- settings.init({
- storage: {
- projects: {
- ssh: {
- getSSHKey: (username, id) => {
- if (username === 'error') {
- var p = Promise.reject(new Error("unknown user"));
- p.catch(()=>{});
- return p;
- } else if (username === '404') {
- return Promise.resolve(null);
- }
- return Promise.resolve({username,id})
- }
- }
- }
- }
- })
- })
- it('returns the default user key', function() {
- return settings.getUserKey({id:'keyid'}).then(result => {
- result.should.eql({id:'keyid',username:"__default"});
- })
- })
- it('returns the default user key - anonymous', function() {
- return settings.getUserKey({user:{anonymous:true},id:'keyid'}).then(result => {
- result.should.eql({id:'keyid',username:"__default"});
- })
- })
- it('returns the user key', function() {
- return settings.getUserKey({user:{username:'nick'},id:'keyid'}).then(result => {
- result.should.eql({id:'keyid',username:"nick"});
- })
- })
- it('404s for unknown key', function(done) {
- settings.getUserKey({user:{username:'404'},id:'keyid'}).then(result => {
- done("Unexpected resolve for error case");
- }).catch(err => {
- err.should.have.property('status', 404);
- err.should.have.property('code', 'not_found');
- done();
- }).catch(done);
- })
- it('rejects with suitable error', function(done) {
- settings.getUserKey({user:{username:'error'}}).then(result => {
- done("Unexpected resolve for error case");
- }).catch(err => {
- err.should.have.property('status', 400);
- done();
- }).catch(done);
- })
- });
- describe("generateUserKey", function() {
- before(function() {
- settings.init({
- storage: {
- projects: {
- ssh: {
- generateSSHKey: (username, opts) => {
- if (username === 'error') {
- var p = Promise.reject(new Error("unknown user"));
- p.catch(()=>{});
- return p;
- }
- return Promise.resolve(JSON.stringify({username,opts}))
- }
- }
- }
- }
- })
- })
- it('generates for the default user', function() {
- return settings.generateUserKey({id:'keyid'}).then(result => {
- var data = JSON.parse(result);
- data.should.eql({opts:{id:'keyid'},username:"__default"});
- })
- })
- it('generates for the default user - anonymous', function() {
- return settings.generateUserKey({user:{anonymous:true},id:'keyid'}).then(result => {
- var data = JSON.parse(result);
- data.should.eql({opts:{user:{anonymous:true},id:'keyid'},username:"__default"});
- })
- })
- it('generates for the user', function() {
- return settings.generateUserKey({user:{username:'nick'},id:'keyid'}).then(result => {
- var data = JSON.parse(result);
- data.should.eql({opts:{user:{username:'nick'},id:'keyid'},username:"nick"});
- })
- })
- it('rejects with suitable error', function(done) {
- settings.generateUserKey({user:{username:'error'}}).then(result => {
- done("Unexpected resolve for error case");
- }).catch(err => {
- err.should.have.property('status', 400);
- done();
- }).catch(done);
- })
-
- });
- describe("removeUserKey", function() {
- var received = {};
- before(function() {
- settings.init({
- storage: {
- projects: {
- ssh: {
- deleteSSHKey: (username, id) => {
- if (username === 'error') {
- var p = Promise.reject(new Error("unknown user"));
- p.catch(()=>{});
- return p;
- }
- received.username = username;
- received.id = id;
- return Promise.resolve();
- }
- }
- }
- }
- })
- });
- beforeEach(function() {
- received.username = "";
- received.id = "";
- })
- it('removes for the default user', function() {
- return settings.removeUserKey({id:'keyid'}).then(() => {
- received.username.should.eql("__default");
- received.id.should.eql("keyid");
- })
- })
- it('removes for the default user key - anonymous', function() {
- return settings.removeUserKey({user:{anonymous:true},id:'keyid'}).then(() => {
- received.username.should.eql("__default");
- received.id.should.eql("keyid");
- })
- })
- it('returns the user key', function() {
- return settings.removeUserKey({user:{username:'nick'},id:'keyid'}).then(() => {
- received.username.should.eql("nick");
- received.id.should.eql("keyid");
- })
- })
- it('rejects with suitable error', function(done) {
- settings.removeUserKey({user:{username:'error'}}).then(result => {
- done("Unexpected resolve for error case");
- }).catch(err => {
- err.should.have.property('status', 400);
- done();
- }).catch(done);
- })
- });
-
-});
-
-
-
-/*
-
-
-var should = require("should");
-var sinon = require("sinon");
-var request = require("supertest");
-var express = require("express");
-var editorApi = require("../../../../red/api/editor");
-var comms = require("../../../../red/api/editor/comms");
-var info = require("../../../../red/api/editor/settings");
-var auth = require("../../../../red/api/auth");
-var sshkeys = require("../../../../red/api/editor/sshkeys");
-var bodyParser = require("body-parser");
-var fs = require("fs-extra");
-var fspath = require("path");
-
-
-describe("api/editor/sshkeys", function() {
- var app;
- var mockList = [
- 'library','theme','locales','credentials','comms'
- ]
- var isStarted = true;
- var errors = [];
- var session_data = {};
-
- var mockRuntime = {
- settings:{
- httpNodeRoot: true,
- httpAdminRoot: true,
- disableEditor: false,
- exportNodeSettings:function(){},
- storage: {
- getSessions: function(){
- return Promise.resolve(session_data);
- },
- setSessions: function(_session) {
- session_data = _session;
- return Promise.resolve();
- }
- }
- },
- log:{audit:function(){},error:function(msg){errors.push(msg)},trace:function(){}},
- storage: {
- projects: {
- ssh: {
- init: function(){},
- listSSHKeys: function(){},
- getSSHKey: function(){},
- generateSSHKey: function(){},
- deleteSSHKey: function(){}
- }
- }
- },
- events:{on:function(){},removeListener:function(){}},
- isStarted: function() { return isStarted; },
- nodes: {installerEnabled: function() { return false }}
- };
-
- before(function() {
- auth.init(mockRuntime);
- app = express();
- app.use(bodyParser.json());
- app.use(editorApi.init({},mockRuntime));
- });
- after(function() {
- })
-
- beforeEach(function() {
- sinon.stub(mockRuntime.storage.projects.ssh, "listSSHKeys");
- sinon.stub(mockRuntime.storage.projects.ssh, "getSSHKey");
- sinon.stub(mockRuntime.storage.projects.ssh, "generateSSHKey");
- sinon.stub(mockRuntime.storage.projects.ssh, "deleteSSHKey");
- })
- afterEach(function() {
- mockRuntime.storage.projects.ssh.listSSHKeys.restore();
- mockRuntime.storage.projects.ssh.getSSHKey.restore();
- mockRuntime.storage.projects.ssh.generateSSHKey.restore();
- mockRuntime.storage.projects.ssh.deleteSSHKey.restore();
- })
-
- it('GET /settings/user/keys --- return empty list', function(done) {
- mockRuntime.storage.projects.ssh.listSSHKeys.returns(Promise.resolve([]));
- request(app)
- .get("/settings/user/keys")
- .expect(200)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('keys');
- res.body.keys.should.be.empty();
- done();
- });
- });
-
- it('GET /settings/user/keys --- return normal list', function(done) {
- var fileList = [
- 'test_key01',
- 'test_key02'
- ];
- var retList = fileList.map(function(elem) {
- return {
- name: elem
- };
- });
- mockRuntime.storage.projects.ssh.listSSHKeys.returns(Promise.resolve(retList));
- request(app)
- .get("/settings/user/keys")
- .expect(200)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('keys');
- for (var item of retList) {
- res.body.keys.should.containEql(item);
- }
- done();
- });
- });
-
- it('GET /settings/user/keys --- return Error', function(done) {
- var errInstance = new Error("Messages here.....");
- errInstance.code = "test_code";
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- mockRuntime.storage.projects.ssh.listSSHKeys.returns(p);
- request(app)
- .get("/settings/user/keys")
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('error');
- res.body.error.should.be.equal(errInstance.code);
- res.body.should.have.property('message');
- res.body.message.should.be.equal(errInstance.message);
- done();
- });
- });
-
- it('GET /settings/user/keys/ --- return 404', function(done) {
- mockRuntime.storage.projects.ssh.getSSHKey.returns(Promise.resolve(null));
- request(app)
- .get("/settings/user/keys/NOT_REAL")
- .expect(404)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- done();
- });
- });
- it('GET /settings/user/keys --- return Unexpected Error', function(done) {
- var errInstance = new Error("Messages.....");
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- mockRuntime.storage.projects.ssh.listSSHKeys.returns(p);
- request(app)
- .get("/settings/user/keys")
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('error');
- res.body.error.should.be.equal("unexpected_error");
- res.body.should.have.property('message');
- res.body.message.should.be.equal(errInstance.toString());
- done();
- });
- });
-
- it('GET /settings/user/keys/ --- return content', function(done) {
- var key_file_name = "test_key";
- var fileContent = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQD3a+sgtgzSbbliWxmOq5p6+H/mE+0gjWfLWrkIVmHENd1mifV4uCmIHAR2NfuadUYMQ3+bQ90kpmmEKTMYPsyentsKpHQZxTzG7wOCAIpJnbPTHDMxEJhVTaAwEjbVyMSIzTTPfnhoavWIBu0+uMgKDDlBm+RjlgkFlyhXyCN6UwFrIUUMH6Gw+eQHLiooKIl8ce7uDxIlt+9b7hFCU+sQ3kvuse239DZluu6+8buMWqJvrEHgzS9adRFKku8nSPAEPYn85vDi7OgVAcLQufknNgs47KHBAx9h04LeSrFJ/P5J1b//ItRpMOIme+O9d1BR46puzhvUaCHLdvO9czj+OmW+dIm+QIk6lZIOOMnppG72kZxtLfeKT16ur+2FbwAdL9ItBp4BI/YTlBPoa5mLMxpuWfmX1qHntvtGc9wEwS1P7YFfmF3XiK5apxalzrn0Qlr5UmDNbVIqJb1OlbC0w03Z0oktti1xT+R2DGOLWM4lBbpXDHV1BhQ7oYOvbUD8Cnof55lTP0WHHsOHlQc/BGDti1XA9aBX/OzVyzBUYEf0pkimsD0RYo6aqt7QwehJYdlz9x1NBguBffT0s4NhNb9IWr+ASnFPvNl2sw4XH/8U0J0q8ZkMpKkbLM1Zdp1Fv00GF0f5UNRokai6uM3w/ccantJ3WvZ6GtctqytWrw== \n";
- mockRuntime.storage.projects.ssh.getSSHKey.returns(Promise.resolve(fileContent));
- request(app)
- .get("/settings/user/keys/" + key_file_name)
- .expect(200)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- mockRuntime.storage.projects.ssh.getSSHKey.called.should.be.true();
- res.body.should.be.deepEqual({ publickey: fileContent });
- done();
- });
- });
-
- it('GET /settings/user/keys/ --- return Error', function(done) {
- var key_file_name = "test_key";
- var errInstance = new Error("Messages.....");
- errInstance.code = "test_code";
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- mockRuntime.storage.projects.ssh.getSSHKey.returns(p);
- request(app)
- .get("/settings/user/keys/" + key_file_name)
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('error');
- res.body.error.should.be.equal(errInstance.code);
- res.body.should.have.property('message');
- res.body.message.should.be.equal(errInstance.message);
- done();
- });
- });
-
- it('GET /settings/user/keys/ --- return Unexpected Error', function(done) {
- var key_file_name = "test_key";
- var errInstance = new Error("Messages.....");
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- mockRuntime.storage.projects.ssh.getSSHKey.returns(p);
- request(app)
- .get("/settings/user/keys/" + key_file_name)
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('error');
- res.body.error.should.be.equal("unexpected_error");
- res.body.should.have.property('message');
- res.body.message.should.be.equal(errInstance.toString());
- done();
- });
- });
-
- it('POST /settings/user/keys --- success', function(done) {
- var key_file_name = "test_key";
- mockRuntime.storage.projects.ssh.generateSSHKey.returns(Promise.resolve(key_file_name));
- request(app)
- .post("/settings/user/keys")
- .send({ name: key_file_name })
- .expect(200)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- done();
- });
- });
-
- it('POST /settings/user/keys --- return parameter error', function(done) {
- var key_file_name = "test_key";
- mockRuntime.storage.projects.ssh.generateSSHKey.returns(Promise.resolve(key_file_name));
- request(app)
- .post("/settings/user/keys")
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('error');
- res.body.error.should.be.equal("unexpected_error");
- res.body.should.have.property('message');
- res.body.message.should.be.equal("You need to have body or body.name");
- done();
- });
- });
-
- it('POST /settings/user/keys --- return Error', function(done) {
- var key_file_name = "test_key";
- var errInstance = new Error("Messages.....");
- errInstance.code = "test_code";
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- mockRuntime.storage.projects.ssh.generateSSHKey.returns(p);
- request(app)
- .post("/settings/user/keys")
- .send({ name: key_file_name })
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('error');
- res.body.error.should.be.equal("test_code");
- res.body.should.have.property('message');
- res.body.message.should.be.equal(errInstance.message);
- done();
- });
- });
-
- it('POST /settings/user/keys --- return Unexpected error', function(done) {
- var key_file_name = "test_key";
- var errInstance = new Error("Messages.....");
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- mockRuntime.storage.projects.ssh.generateSSHKey.returns(p);
- request(app)
- .post("/settings/user/keys")
- .send({ name: key_file_name })
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('error');
- res.body.error.should.be.equal("unexpected_error");
- res.body.should.have.property('message');
- res.body.message.should.be.equal(errInstance.toString());
- done();
- });
- });
-
- it('DELETE /settings/user/keys/ --- success', function(done) {
- var key_file_name = "test_key";
- mockRuntime.storage.projects.ssh.deleteSSHKey.returns(Promise.resolve(true));
- request(app)
- .delete("/settings/user/keys/" + key_file_name)
- .expect(204)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.be.deepEqual({});
- done();
- });
- });
-
- it('DELETE /settings/user/keys/ --- return Error', function(done) {
- var key_file_name = "test_key";
- var errInstance = new Error("Messages.....");
- errInstance.code = "test_code";
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- mockRuntime.storage.projects.ssh.deleteSSHKey.returns(p);
- request(app)
- .delete("/settings/user/keys/" + key_file_name)
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('error');
- res.body.error.should.be.equal("test_code");
- res.body.should.have.property('message');
- res.body.message.should.be.equal(errInstance.message);
- done();
- });
- });
-
- it('DELETE /settings/user/keys/ --- return Unexpected Error', function(done) {
- var key_file_name = "test_key";
- var errInstance = new Error("Messages.....");
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- mockRuntime.storage.projects.ssh.deleteSSHKey.returns(p);
- request(app)
- .delete("/settings/user/keys/" + key_file_name)
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('error');
- res.body.error.should.be.equal("unexpected_error");
- res.body.should.have.property('message');
- res.body.message.should.be.equal(errInstance.toString());
- done();
- });
- });
-});
-*/
diff --git a/test/unit/@node-red/runtime/lib/flows/Flow_spec.js b/test/unit/@node-red/runtime/lib/flows/Flow_spec.js
deleted file mode 100644
index eed4810c4..000000000
--- a/test/unit/@node-red/runtime/lib/flows/Flow_spec.js
+++ /dev/null
@@ -1,1327 +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 clone = require('clone');
-var util = require("util");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var flowUtils = NR_TEST_UTILS.require("@node-red/runtime/lib/flows/util");
-var Flow = NR_TEST_UTILS.require("@node-red/runtime/lib/flows/Flow");
-var flows = NR_TEST_UTILS.require("@node-red/runtime/lib/flows");
-var Node = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/Node");
-var hooks = NR_TEST_UTILS.require("@node-red/util/lib/hooks");
-var typeRegistry = NR_TEST_UTILS.require("@node-red/registry");
-
-
-describe('Flow', function() {
- var getType;
-
- var stoppedNodes = {};
- var stoppedOrder = [];
- var currentNodes = {};
- var rewiredNodes = {};
- var createCount = 0;
-
- beforeEach(function() {
- currentNodes = {};
- stoppedNodes = {};
- stoppedOrder =[];
- rewiredNodes = {};
- createCount = 0;
- Flow.init({settings:{},log:{
- log: sinon.stub(), // function() { console.log("l",[...arguments].map(a => JSON.stringify(a)).join(" ")) },//
- debug: sinon.stub(), // function() { console.log("d",[...arguments].map(a => JSON.stringify(a)).join(" ")) },//sinon.stub(),
- trace: sinon.stub(), // function() { console.log("t",[...arguments].map(a => JSON.stringify(a)).join(" ")) },//sinon.stub(),
- warn: sinon.stub(), // function() { console.log("w",[...arguments].map(a => JSON.stringify(a)).join(" ")) },//sinon.stub(),
- info: sinon.stub(), // function() { console.log("i",[...arguments].map(a => JSON.stringify(a)).join(" ")) },//sinon.stub(),
- metric: sinon.stub(),
- _: function() { return "abc"}
- }});
- });
-
- var TestNode = function(n) {
- Node.call(this,n);
- this._index = createCount++;
- this.scope = n.scope;
- var node = this;
- this.foo = n.foo;
- this.handled = 0;
- this.stopped = false;
- currentNodes[node.id] = node;
- this.on('input',function(msg) {
- // console.log(this.id,msg.payload);
- node.handled++;
- node.send(msg);
- });
- this.on('close',function() {
- node.stopped = true;
- stoppedNodes[node.id] = node;
- stoppedOrder.push(node.id)
- delete currentNodes[node.id];
- });
- this.__updateWires = this.updateWires;
- this.updateWires = function(newWires) {
- rewiredNodes[node.id] = node;
- node.newWires = newWires;
- node.__updateWires(newWires);
- };
- }
- util.inherits(TestNode,Node);
-
- var TestErrorNode = function(n) {
- Node.call(this,n);
- this._index = createCount++;
- this.scope = n.scope;
- this.name = n.name;
- var node = this;
- this.foo = n.foo;
- this.handled = 0;
- this.stopped = false;
- currentNodes[node.id] = node;
- this.on('input',function(msg) {
- node.handled++;
- node.error("test error",msg);
- });
- this.on('close',function() {
- node.stopped = true;
- stoppedNodes[node.id] = node;
- stoppedOrder.push(node.id)
- delete currentNodes[node.id];
- });
- this.__updateWires = this.updateWires;
- this.updateWires = function(newWires) {
- rewiredNodes[node.id] = node;
- node.newWires = newWires;
- node.__updateWires(newWires);
- };
- }
- util.inherits(TestErrorNode,Node);
-
- var TestAsyncNode = function(n) {
- Node.call(this,n);
- var node = this;
- this.scope = n.scope;
- this.uncaught = n.uncaught;
- this.foo = n.foo;
- this.handled = 0;
- this.messages = [];
- this.stopped = false;
- this.closeDelay = n.closeDelay || 50;
- currentNodes[node.id] = node;
- this.on('input',function(msg) {
- node.handled++;
- msg.handled = node.handled;
- node.messages.push(msg);
- node.send(msg);
- });
- this.on('close',function(done) {
- setTimeout(function() {
- node.stopped = true;
- stoppedNodes[node.id] = node;
- stoppedOrder.push(node.id)
- delete currentNodes[node.id];
- done();
- },node.closeDelay);
- });
- }
- util.inherits(TestAsyncNode,Node);
-
- var TestDoneNode = function(n) {
- Node.call(this,n);
- var node = this;
- this.scope = n.scope;
- this.uncaught = n.uncaught;
- this.foo = n.foo;
- this.handled = 0;
- this.messages = [];
- this.stopped = false;
- this.closeDelay = n.closeDelay || 50;
- currentNodes[node.id] = node;
- this.on('input',function(msg, send, done) {
- node.handled++;
- node.messages.push(msg);
- send(msg);
- done();
- });
- this.on('close',function(done) {
- setTimeout(function() {
- node.stopped = true;
- stoppedNodes[node.id] = node;
- stoppedOrder.push(node.id)
- delete currentNodes[node.id];
- done();
- },node.closeDelay);
- });
- }
- util.inherits(TestDoneNode,Node);
-
- before(function() {
- getType = sinon.stub(typeRegistry,"get").callsFake(function(type) {
- if (type=="test") {
- return TestNode;
- } else if (type=="testError"){
- return TestErrorNode;
- } else if (type=="testDone"){
- return TestDoneNode;
- } else {
- return TestAsyncNode;
- }
- });
- });
- after(function() {
- getType.restore();
- });
-
- describe('#constructor',function() {
- it('called with an empty flow',function() {
- var config = flowUtils.parseConfig([]);
- var flow = Flow.create({},config);
-
- var nodeCount = 0;
- Object.keys(flow.getActiveNodes()).length.should.equal(0);
- });
- });
-
- describe('#start',function() {
- it("instantiates an initial configuration and stops it",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"4",z:"t1",type:"test",foo:"a"}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
-
- Object.keys(flow.getActiveNodes()).should.have.length(4);
-
- flow.getNode('1').should.have.a.property('id','1');
- flow.getNode('2').should.have.a.property('id','2');
- flow.getNode('3').should.have.a.property('id','3');
- flow.getNode('4').should.have.a.property('id','4');
-
- currentNodes.should.have.a.property("1");
- currentNodes.should.have.a.property("2");
- currentNodes.should.have.a.property("3");
- currentNodes.should.have.a.property("4");
-
- currentNodes["1"].should.have.a.property("handled",0);
- currentNodes["2"].should.have.a.property("handled",0);
- currentNodes["3"].should.have.a.property("handled",0);
-
- currentNodes["3"].on("input", function() {
- currentNodes["1"].should.have.a.property("handled",1);
- currentNodes["2"].should.have.a.property("handled",1);
- currentNodes["3"].should.have.a.property("handled",1);
-
- flow.stop().then(function() {
- try {
- currentNodes.should.not.have.a.property("1");
- currentNodes.should.not.have.a.property("2");
- currentNodes.should.not.have.a.property("3");
- currentNodes.should.not.have.a.property("4");
- stoppedNodes.should.have.a.property("1");
- stoppedNodes.should.have.a.property("2");
- stoppedNodes.should.have.a.property("3");
- stoppedNodes.should.have.a.property("4");
- done();
- } catch(err) {
- done(err);
- }
- });
- });
- currentNodes["1"].receive({payload:"test"});
- });
-
- it("instantiates config nodes in the right order",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"4",z:"t1",type:"test",foo:"5"}, // This node depends on #5
- {id:"5",z:"t1",type:"test"}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
-
- Object.keys(flow.getActiveNodes()).should.have.length(5);
-
-
- currentNodes.should.have.a.property("1");
- currentNodes.should.have.a.property("2");
- currentNodes.should.have.a.property("3");
- currentNodes.should.have.a.property("4");
- currentNodes.should.have.a.property("5");
-
- currentNodes["1"].should.have.a.property("_index",2);
- currentNodes["2"].should.have.a.property("_index",3);
- currentNodes["3"].should.have.a.property("_index",4);
- currentNodes["4"].should.have.a.property("_index",1);
- currentNodes["5"].should.have.a.property("_index",0);
-
- flow.stop().then(function() {
- currentNodes.should.not.have.a.property("1");
- currentNodes.should.not.have.a.property("2");
- currentNodes.should.not.have.a.property("3");
- currentNodes.should.not.have.a.property("4");
- currentNodes.should.not.have.a.property("5");
- stoppedNodes.should.have.a.property("1");
- stoppedNodes.should.have.a.property("2");
- stoppedNodes.should.have.a.property("3");
- stoppedNodes.should.have.a.property("4");
- stoppedNodes.should.have.a.property("5");
- done();
- });
- });
-
-
- it("detects dependency loops in config nodes",function() {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"node1",z:"t1",type:"test",foo:"node2"}, // This node depends on #5
- {id:"node2",z:"t1",type:"test",foo:"node1"}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- /*jshint immed: false */
- (function(){
- flow.start();
- }).should.throw("Circular config node dependency detected: node1");
- });
-
- it("rewires nodes specified by diff",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]}
- ]);
-
- var flow = Flow.create({},config,config.flows["t1"]);
- createCount.should.equal(0);
- flow.start();
- //TODO: use update to pass in new wiring and verify the change
- createCount.should.equal(3);
- flow.start({rewired:["2"]});
- createCount.should.equal(3);
- rewiredNodes.should.have.a.property("2");
- done();
- });
-
- it("instantiates a node with environment variable property values",function(done) {
- after(function() {
- delete process.env.NODE_RED_TEST_VALUE;
- })
- process.env.NODE_RED_TEST_VALUE = "a-value";
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"$(NODE_RED_TEST_VALUE)",wires:[]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:{a:"$(NODE_RED_TEST_VALUE)"},wires:[]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:" $(NODE_RED_TEST_VALUE)",wires:[]},
- {id:"4",x:10,y:10,z:"t1",type:"test",foo:"$(NODE_RED_TEST_VALUE) ",wires:[]},
- {id:"5",x:10,y:10,z:"t1",type:"test",foo:"$(NODE_RED_TEST_VALUE_NONE)",wires:[]},
- {id:"6",x:10,y:10,z:"t1",type:"test",foo:["$(NODE_RED_TEST_VALUE)"],wires:[]}
- ]);
- var flow = Flow.create({getSetting:v=>process.env[v]},config,config.flows["t1"]);
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
-
- activeNodes["1"].foo.should.equal("a-value");
- activeNodes["2"].foo.a.should.equal("a-value");
- activeNodes["3"].foo.should.equal(" $(NODE_RED_TEST_VALUE)");
- activeNodes["4"].foo.should.equal("$(NODE_RED_TEST_VALUE) ");
- activeNodes["5"].foo.should.equal("$(NODE_RED_TEST_VALUE_NONE)");
- activeNodes["6"].foo[0].should.equal("a-value");
-
- flow.stop().then(function() {
- done();
- });
- });
-
- it("ignores disabled nodes",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",d:true,type:"test",foo:"a",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"4",z:"t1",type:"test",foo:"a"},
- {id:"5",z:"t1",type:"test",d:true,foo:"a"}
-
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
-
- Object.keys(flow.getActiveNodes()).should.have.length(3);
-
- flow.getNode('1').should.have.a.property('id','1');
- should.not.exist(flow.getNode('2'));
- flow.getNode('3').should.have.a.property('id','3');
- flow.getNode('4').should.have.a.property('id','4');
- should.not.exist(flow.getNode('5'));
-
- currentNodes.should.have.a.property("1");
- currentNodes.should.not.have.a.property("2");
- currentNodes.should.have.a.property("3");
- currentNodes.should.have.a.property("4");
-
- currentNodes["1"].should.have.a.property("handled",0);
- currentNodes["3"].should.have.a.property("handled",0);
-
- currentNodes["1"].receive({payload:"test"});
-
- setTimeout(function() {
- currentNodes["1"].should.have.a.property("handled",1);
- // Message doesn't reach 3 as 2 is disabled
- currentNodes["3"].should.have.a.property("handled",0);
-
- flow.stop().then(function() {
- try {
- currentNodes.should.not.have.a.property("1");
- currentNodes.should.not.have.a.property("2");
- currentNodes.should.not.have.a.property("3");
- currentNodes.should.not.have.a.property("4");
- stoppedNodes.should.have.a.property("1");
- stoppedNodes.should.not.have.a.property("2");
- stoppedNodes.should.have.a.property("3");
- stoppedNodes.should.have.a.property("4");
- done();
- } catch(err) {
- done(err);
- }
- });
- },50);
- });
-
- });
-
- describe('#stop', function() {
-
-
- it("stops all nodes",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"asyncTest",foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
-
-
- currentNodes.should.have.a.property("1");
- currentNodes.should.have.a.property("2");
- currentNodes.should.have.a.property("3");
-
- flow.stop().then(function() {
- currentNodes.should.not.have.a.property("1");
- currentNodes.should.not.have.a.property("2");
- currentNodes.should.not.have.a.property("3");
- stoppedNodes.should.have.a.property("1");
- stoppedNodes.should.have.a.property("2");
- stoppedNodes.should.have.a.property("3");
- done();
- }).catch(done);
- });
-
- it("stops specified nodes",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
-
- currentNodes.should.have.a.property("1");
- currentNodes.should.have.a.property("2");
- currentNodes.should.have.a.property("3");
-
- flow.stop(["2"]).then(function() {
- currentNodes.should.have.a.property("1");
- currentNodes.should.not.have.a.property("2");
- currentNodes.should.have.a.property("3");
- stoppedNodes.should.not.have.a.property("1");
- stoppedNodes.should.have.a.property("2");
- stoppedNodes.should.not.have.a.property("3");
- done();
- });
- });
-
- it("stops config nodes last",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"c1",z:"t1",type:"test"},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]},
- {id:"c2",z:"t1",type:"test"},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"c3",z:"t1",type:"test"}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
-
- currentNodes.should.have.a.property("1");
- currentNodes.should.have.a.property("2");
- currentNodes.should.have.a.property("3");
- currentNodes.should.have.a.property("c1");
- currentNodes.should.have.a.property("c2");
- currentNodes.should.have.a.property("c3");
- stoppedOrder.should.have.a.length(0);
-
- flow.stop().then(function() {
- stoppedOrder.should.eql([ '1', '2', '3', 'c1', 'c2', 'c3' ]);
- done();
- }).catch(done);
- });
-
-
- it("Times out a node that fails to close", function(done) {
- Flow.init({settings:{nodeCloseTimeout:50},log:{
- log: sinon.stub(),
- debug: sinon.stub(),
- trace: sinon.stub(),
- warn: sinon.stub(),
- info: sinon.stub(),
- metric: sinon.stub(),
- _: function() { return "abc"}
- }});
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"testAsync",closeDelay: 80, foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
-
- currentNodes.should.have.a.property("1");
- currentNodes.should.have.a.property("2");
- currentNodes.should.have.a.property("3");
-
- flow.stop().then(function() {
- currentNodes.should.have.a.property("1");
- currentNodes.should.not.have.a.property("2");
- currentNodes.should.not.have.a.property("3");
- stoppedNodes.should.not.have.a.property("1");
- stoppedNodes.should.have.a.property("2");
- stoppedNodes.should.have.a.property("3");
- setTimeout(function() {
- currentNodes.should.not.have.a.property("1");
- stoppedNodes.should.have.a.property("1");
- done();
- },40)
- });
- });
-
- });
-
- describe('#getNode',function() {
- it("gets a node known to the flow",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"4",z:"t1",type:"test",foo:"a"}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
-
- Object.keys(flow.getActiveNodes()).should.have.length(4);
-
- flow.getNode('1').should.have.a.property('id','1');
-
- flow.stop().then(() => { done() });
- });
-
- it("passes to parent if node not known locally",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"4",z:"t1",type:"test",foo:"a"}
- ]);
- var flow = Flow.create({
- getNode: id => { return {id:id}}
- },config,config.flows["t1"]);
- flow.start();
-
- Object.keys(flow.getActiveNodes()).should.have.length(4);
-
- flow.getNode('1').should.have.a.property('id','1');
-
- flow.getNode('parentNode').should.have.a.property('id','parentNode');
-
-
- flow.stop().then(() => { done() });
- });
-
- it("does not pass to parent if cancelBubble set",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"4",z:"t1",type:"test",foo:"a"}
- ]);
- var flow = Flow.create({
- getNode: id => { return {id:id}}
- },config,config.flows["t1"]);
- flow.start();
-
- Object.keys(flow.getActiveNodes()).should.have.length(4);
-
- flow.getNode('1').should.have.a.property('id','1');
-
- should.not.exist(flow.getNode('parentNode',true));
- flow.stop().then(() => { done() });
- });
- });
-
- describe("#handleStatus",function() {
- it("passes a status event to the adjacent status node",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sn",x:10,y:10,z:"t1",type:"status",foo:"a",wires:[]},
- {id:"sn2",x:10,y:10,z:"t1",type:"status",foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
- Object.keys(activeNodes).should.have.length(5);
-
-
- flow.handleStatus(config.flows["t1"].nodes["1"],{text:"my-status",random:"otherProperty"});
-
- setTimeout(function() {
-
- currentNodes["sn"].should.have.a.property("handled",1);
- var statusMessage = currentNodes["sn"].messages[0];
-
- statusMessage.should.have.a.property("status");
- statusMessage.status.should.have.a.property("text","my-status");
- statusMessage.status.should.have.a.property("source");
- statusMessage.status.source.should.have.a.property("id","1");
- statusMessage.status.source.should.have.a.property("type","test");
- statusMessage.status.source.should.have.a.property("name","a");
-
- currentNodes["sn2"].should.have.a.property("handled",1);
- statusMessage = currentNodes["sn2"].messages[0];
-
- statusMessage.should.have.a.property("status");
- statusMessage.status.should.have.a.property("text","my-status");
- statusMessage.status.should.have.a.property("random","otherProperty");
- statusMessage.status.should.have.a.property("source");
- statusMessage.status.source.should.have.a.property("id","1");
- statusMessage.status.source.should.have.a.property("type","test");
- statusMessage.status.source.should.have.a.property("name","a");
-
-
- flow.stop().then(function() {
- done();
- });
- },50)
- });
- it("passes a status event to the adjacent scoped status node ",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sn",x:10,y:10,z:"t1",type:"status",scope:["2"],foo:"a",wires:[]},
- {id:"sn2",x:10,y:10,z:"t1",type:"status",scope:["1"],foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
- Object.keys(activeNodes).should.have.length(5);
-
-
- flow.handleStatus(config.flows["t1"].nodes["1"],{text:"my-status"});
-
- setTimeout(function() {
- currentNodes["sn"].should.have.a.property("handled",0);
- currentNodes["sn2"].should.have.a.property("handled",1);
- var statusMessage = currentNodes["sn2"].messages[0];
-
- statusMessage.should.have.a.property("status");
- statusMessage.status.should.have.a.property("text","my-status");
- statusMessage.status.should.have.a.property("source");
- statusMessage.status.source.should.have.a.property("id","1");
- statusMessage.status.source.should.have.a.property("type","test");
- statusMessage.status.source.should.have.a.property("name","a");
-
-
- flow.stop().then(function() {
- done();
- });
- },50);
- });
-
- });
-
- describe("#handleError",function() {
- it("passes an error event to the adjacent catch node",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sn",x:10,y:10,z:"t1",type:"catch",foo:"a",wires:[]},
- {id:"sn2",x:10,y:10,z:"t1",type:"catch",foo:"a",wires:[]},
- {id:"sn3",x:10,y:10,z:"t1",type:"catch",uncaught:true,wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
- Object.keys(activeNodes).should.have.length(6);
-
-
- flow.handleError(config.flows["t1"].nodes["1"],"my-error",{a:"foo"});
-
- setTimeout(function() {
- currentNodes["sn"].should.have.a.property("handled",1);
- var statusMessage = currentNodes["sn"].messages[0];
-
- statusMessage.should.have.a.property("error");
- statusMessage.error.should.have.a.property("message","my-error");
- statusMessage.error.should.have.a.property("source");
- statusMessage.error.source.should.have.a.property("id","1");
- statusMessage.error.source.should.have.a.property("type","test");
- statusMessage.error.source.should.have.a.property("name","a");
-
- currentNodes["sn2"].should.have.a.property("handled",1);
- statusMessage = currentNodes["sn2"].messages[0];
-
- statusMessage.should.have.a.property("error");
- statusMessage.error.should.have.a.property("message","my-error");
- statusMessage.error.should.have.a.property("source");
- statusMessage.error.source.should.have.a.property("id","1");
- statusMessage.error.source.should.have.a.property("type","test");
- statusMessage.error.source.should.have.a.property("name","a");
-
- // Node sn3 has uncaught:true - so should not get called
- currentNodes["sn3"].should.have.a.property("handled",0);
-
-
- flow.stop().then(function() {
- done();
- });
- },50);
- });
- it("passes an error event to the adjacent scoped catch node ",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sn",x:10,y:10,z:"t1",type:"catch",scope:["2"],foo:"a",wires:[]},
- {id:"sn2",x:10,y:10,z:"t1",type:"catch",scope:["1"],foo:"a",wires:[]},
- {id:"sn3",x:10,y:10,z:"t1",type:"catch",uncaught:true,wires:[]},
- {id:"sn4",x:10,y:10,z:"t1",type:"catch",uncaught:true,wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
- Object.keys(activeNodes).should.have.length(7);
-
- flow.handleError(config.flows["t1"].nodes["1"],"my-error",{a:"foo"});
-
- setTimeout(function() {
- currentNodes["sn"].should.have.a.property("handled",0);
- currentNodes["sn2"].should.have.a.property("handled",1);
- var statusMessage = currentNodes["sn2"].messages[0];
-
- statusMessage.should.have.a.property("error");
- statusMessage.error.should.have.a.property("message","my-error");
- statusMessage.error.should.have.a.property("source");
- statusMessage.error.source.should.have.a.property("id","1");
- statusMessage.error.source.should.have.a.property("type","test");
- statusMessage.error.source.should.have.a.property("name","a");
-
- // Node sn3/4 have uncaught:true - so should not get called
- currentNodes["sn3"].should.have.a.property("handled",0);
- currentNodes["sn4"].should.have.a.property("handled",0);
-
- // Inject error that sn1/2 will ignore - so should get picked up by sn3
- flow.handleError(config.flows["t1"].nodes["3"],"my-error-2",{a:"foo-2"});
- setTimeout(function() {
- currentNodes["sn"].should.have.a.property("handled",0);
- currentNodes["sn2"].should.have.a.property("handled",1);
- currentNodes["sn3"].should.have.a.property("handled",1);
- currentNodes["sn4"].should.have.a.property("handled",1);
-
- statusMessage = currentNodes["sn3"].messages[0];
- statusMessage.should.have.a.property("error");
- statusMessage.error.should.have.a.property("message","my-error-2");
- statusMessage.error.should.have.a.property("source");
- statusMessage.error.source.should.have.a.property("id","3");
- statusMessage.error.source.should.have.a.property("type","test");
-
- flow.stop().then(function() {
- done();
- });
- },50);
- },50);
- });
- it("moves any existing error object sideways",function(done){
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sn",x:10,y:10,z:"t1",type:"catch",foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
-
- flow.handleError(config.flows["t1"].nodes["1"],"my-error",{a:"foo",error:"existing"});
- setTimeout(function() {
- currentNodes["sn"].should.have.a.property("handled",1);
- var statusMessage = currentNodes["sn"].messages[0];
-
- statusMessage.should.have.a.property("_error","existing");
- statusMessage.should.have.a.property("error");
- statusMessage.error.should.have.a.property("message","my-error");
- statusMessage.error.should.have.a.property("source");
- statusMessage.error.source.should.have.a.property("id","1");
- statusMessage.error.source.should.have.a.property("type","test");
- statusMessage.error.source.should.have.a.property("name","a");
-
- flow.stop().then(function() {
- done();
- });
- },50);
- });
- it("prevents an error looping more than 10 times",function(){});
- });
-
- describe("#handleComplete",function() {
- it("passes a complete event to the adjacent Complete node",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"testDone",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"testDone",foo:"a",wires:[]},
- {id:"cn",x:10,y:10,z:"t1",type:"complete",scope:["1","3"],foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
- Object.keys(activeNodes).should.have.length(4);
-
- var msg = {payload: "hello world"}
- var n1 = currentNodes["1"].receive(msg);
- setTimeout(function() {
- currentNodes["cn"].should.have.a.property("handled",2);
- currentNodes["cn"].messages[0].should.have.a.property("handled",1);
- currentNodes["cn"].messages[1].should.have.a.property("handled",2);
- flow.stop().then(function() {
- done();
- });
- },50);
- });
- });
-
-
- describe("#send", function() {
- it("sends a message - no cloning", function(done) {
- var shutdownTest = function(err) {
- hooks.clear();
- flow.stop().then(() => { done(err) });
- }
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
-
- Object.keys(flow.getActiveNodes()).should.have.length(2);
-
- var n1 = flow.getNode('1');
- var n2 = flow.getNode('2');
- var messageReceived = false;
- n2.receive = function(msg) {
- messageReceived = true;
- try {
- msg.should.be.exactly(message);
- shutdownTest();
- } catch(err) {
- shutdownTest(err);
- }
- }
-
- var message = {payload:"hello"}
- flow.send([{
- msg: message,
- source: { id:"1", node: n1 },
- destination: { id:"2", node: undefined },
- cloneMessage: false
- }])
- messageReceived.should.be.false()
- })
- it("sends a message - cloning", function(done) {
- var shutdownTest = function(err) {
- hooks.clear();
- flow.stop().then(() => { done(err) });
- }
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
-
- Object.keys(flow.getActiveNodes()).should.have.length(2);
-
- var n1 = flow.getNode('1');
- var n2 = flow.getNode('2');
-
- n2.receive = function(msg) {
- try {
- // Message should be cloned
- msg.should.be.eql(message);
- msg.should.not.be.exactly(message);
- shutdownTest();
- } catch(err) {
- shutdownTest(err);
- }
- }
-
- var message = {payload:"hello"}
- flow.send([{
- msg: message,
- source: { id:"1", node: n1 },
- destination: { id:"2", node: undefined },
- cloneMessage: true
- }])
- })
- it("sends multiple messages", function(done) {
- var shutdownTest = function(err) {
- hooks.clear();
- flow.stop().then(() => { done(err) });
- }
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
-
- Object.keys(flow.getActiveNodes()).should.have.length(2);
-
- var n1 = flow.getNode('1');
- var n2 = flow.getNode('2');
-
- var messageCount = 0;
- n2.receive = function(msg) {
- try {
- msg.should.be.exactly(messages[messageCount++]);
- if (messageCount === 2) {
- shutdownTest();
- }
- } catch(err) {
- shutdownTest(err);
- }
- }
-
- var messages = [{payload:"hello"},{payload:"world"}];
-
- flow.send([{
- msg: messages[0],
- source: { id:"1", node: n1 },
- destination: { id:"2", node: undefined }
- },{
- msg: messages[1],
- source: { id:"1", node: n1 },
- destination: { id:"2", node: undefined }
- }])
- })
- it("sends a message - triggers hooks", function(done) {
- var hookErrors = [];
- var messageReceived = false;
- var hooksCalled = [];
- hooks.add("onSend", function(sendEvents) {
- hooksCalled.push("onSend")
- try {
- messageReceived.should.be.false()
- sendEvents.should.have.length(1);
- sendEvents[0].msg.should.be.exactly(message);
- } catch(err) {
- hookErrors.push(err);
- }
- })
- hooks.add("preRoute", function(sendEvent) {
- hooksCalled.push("preRoute")
- try {
- messageReceived.should.be.false()
- sendEvent.msg.should.be.exactly(message);
- should.not.exist(sendEvent.destination.node)
- } catch(err) {
- hookErrors.push(err);
- }
-
- })
- hooks.add("preDeliver", function(sendEvent) {
- hooksCalled.push("preDeliver")
- try {
- messageReceived.should.be.false()
- // Cloning should have happened
- sendEvent.msg.should.not.be.exactly(message);
- // Destinatino node populated
- should.exist(sendEvent.destination.node)
- } catch(err) {
- hookErrors.push(err);
- }
-
- })
- hooks.add("postDeliver", function(sendEvent) {
- hooksCalled.push("postDeliver")
- try {
- messageReceived.should.be.false()
-
- } catch(err) {
- hookErrors.push(err);
- }
-
- })
- var shutdownTest = function(err) {
- hooks.clear();
- flow.stop().then(() => { done(err) });
- }
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
-
- Object.keys(flow.getActiveNodes()).should.have.length(2);
-
- var n1 = flow.getNode('1');
- var n2 = flow.getNode('2');
- n2.receive = function(msg) {
- messageReceived = true;
- try {
- msg.should.be.eql(message);
- msg.should.not.be.exactly(message);
- hooksCalled.should.eql(["onSend","preRoute","preDeliver","postDeliver"])
- if (hookErrors.length > 0) {
- shutdownTest(hookErrors[0])
- } else {
- shutdownTest();
- }
- } catch(err) {
- shutdownTest(err);
- }
- }
-
- var message = {payload:"hello"}
- flow.send([{
- msg: message,
- source: { id:"1", node: n1 },
- destination: { id:"2", node: undefined },
- cloneMessage: true
- }])
- })
-
- describe("errors thrown by hooks are reported to the sending node", function() {
- var flow;
- var n1,n2;
- var messageReceived = false;
- var errorReceived = null;
- before(function() {
- hooks.add("onSend", function(sendEvents) {
- if (sendEvents[0].msg.payload === "trigger-onSend") {
- throw new Error("onSend Error");
- }
- })
- hooks.add("preRoute", function(sendEvent) {
- if (sendEvent.msg.payload === "trigger-preRoute") {
- throw new Error("preRoute Error");
- }
- })
- hooks.add("preDeliver", function(sendEvent) {
- if (sendEvent.msg.payload === "trigger-preDeliver") {
- throw new Error("preDeliver Error");
- }
- })
- hooks.add("postDeliver", function(sendEvent) {
- if (sendEvent.msg.payload === "trigger-postDeliver") {
- throw new Error("postDeliver Error");
- }
- })
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]}
- ]);
- flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
- n1 = flow.getNode('1');
- n2 = flow.getNode('2');
- n2.receive = function(msg) {
- messageReceived = true;
- }
- n1.error = function(err) {
- errorReceived = err;
- }
-
- })
- after(function(done) {
- hooks.clear();
- flow.stop().then(() => { done() });
- })
- beforeEach(function() {
- messageReceived = false;
- errorReceived = null;
- })
- function testHook(hook, msgExpected, done) {
- var message = {payload:"trigger-"+hook}
- flow.send([{
- msg: message,
- source: { id:"1", node: n1 },
- destination: { id:"2", node: undefined },
- cloneMessage: true
- }])
- setTimeout(function() {
- try {
- messageReceived.should.equal(msgExpected);
- should.exist(errorReceived)
- errorReceived.toString().should.containEql(hook);
- done();
- } catch(err) {
- done(err);
- }
- },10)
- }
-
- it("onSend", function(done) { testHook("onSend", false, done) })
- it("preRoute", function(done) { testHook("preRoute", false, done) })
- it("preDeliver", function(done) { testHook("preDeliver", false, done) })
- it("postDeliver", function(done) { testHook("postDeliver", true, done) })
- })
-
- describe("hooks can stop the sending of messages", function() {
- var flow;
- var n1,n2;
- var messageReceived = false;
- var errorReceived = false;
- before(function() {
- hooks.add("onSend", function(sendEvents) {
- if (sendEvents[0].msg.payload === "trigger-onSend") {
- return false
- }
- })
- hooks.add("preRoute", function(sendEvent) {
- if (sendEvent.msg.payload === "trigger-preRoute") {
- return false
- }
- })
- hooks.add("preDeliver", function(sendEvent) {
- if (sendEvent.msg.payload === "trigger-preDeliver") {
- return false
- }
- })
- hooks.add("postDeliver", function(sendEvent) {
- if (sendEvent.msg.payload === "trigger-postDeliver") {
- return false
- }
- })
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]}
- ]);
- flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
- n1 = flow.getNode('1');
- n2 = flow.getNode('2');
- n2.receive = function(msg) {
- messageReceived = true;
- }
- n1.error = function(err) {
- errorReceived = true;
- }
-
- })
- after(function(done) {
- hooks.clear();
- flow.stop().then(() => { done() });
- })
- function testSend(payload,messageReceivedExpected,errorReceivedExpected,done) {
- messageReceived = false;
- errorReceived = false;
- flow.send([{
- msg: {payload: payload},
- source: { id:"1", node: n1 },
- destination: { id:"2", node: undefined },
- cloneMessage: true
- }])
- setTimeout(function() {
- try {
- messageReceived.should.eql(messageReceivedExpected)
- errorReceived.should.eql(errorReceivedExpected)
- done();
- } catch(err) {
- done(err);
- }
- },10)
- }
- function testHook(hook, done) {
- testSend("pass",true,false,err => {
- if (err) {
- done(err)
- } else {
- testSend("trigger-"+hook,false,false,done);
- }
- })
- }
-
- it("onSend", function(done) { testHook("onSend", done) })
- it("preRoute", function(done) { testHook("preRoute", done) })
- it("preDeliver", function(done) { testHook("preDeliver", done) })
- // postDeliver happens after delivery is scheduled so cannot stop it
- // it("postDeliver", function(done) { testHook("postDeliver", done) })
- })
- })
-
- describe("#env", function () {
- it("can instantiate a node with environment variable property values of group and tab", function (done) {
- try {
- after(function() {
- delete process.env.V0;
- delete process.env.V1;
- })
- process.env.V0 = "gv0";
- process.env.V1 = "gv1";
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab",env:[
- {"name": "V0", value: "v0", type: "str"}
- ]},
- {id:"g1",type:"group",z:"t1",env:[
- {"name": "V0", value: "v1", type: "str"},
- {"name": "V1", value: "v2", type: "str"}
- ]},
- {id:"g2",type:"group",z:"t1",g:"g1",env:[
- {"name": "V1", value: "v3", type: "str"}
- ]},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"$(V0)",wires:[]},
- {id:"2",x:10,y:10,z:"t1",g:"g1",type:"test",foo:"$(V0)",wires:[]},
- {id:"3",x:10,y:10,z:"t1",g:"g1",type:"test",foo:"$(V1)",wires:[]},
- {id:"4",x:10,y:10,z:"t1",g:"g2",type:"test",foo:"$(V1)",wires:[]},
- {id:"5",x:10,y:10,z:"t1",type:"test",foo:"$(V1)",wires:[]},
- ]);
- var flow = Flow.create({getSetting:v=>process.env[v]},config,config.flows["t1"]);
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
-
- activeNodes["1"].foo.should.equal("v0");
- activeNodes["2"].foo.should.equal("v1");
- activeNodes["3"].foo.should.equal("v2");
- activeNodes["4"].foo.should.equal("v3");
- activeNodes["5"].foo.should.equal("gv1");
-
- flow.stop().then(function() {
- done();
- });
- }
- catch (e) {
- console.log(e.stack);
- done(e);
- }
-
- });
- it("can access environment variable property using $parent", function (done) {
- try {
- after(function() {
- delete process.env.V0;
- delete process.env.V1;
- })
- process.env.V0 = "gv0";
- process.env.V1 = "gv1";
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab",env:[
- {"name": "V0", value: "v0", type: "str"}
- ]},
- {id:"g1",type:"group",z:"t1",env:[
- {"name": "V0", value: "v1", type: "str"},
- {"name": "V1", value: "v2", type: "str"}
- ]},
- {id:"g2",type:"group",z:"t1",g:"g1",env:[
- {"name": "V1", value: "v3", type: "str"}
- ]},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"${$parent.V0}",wires:[]},
- {id:"2",x:10,y:10,z:"t1",g:"g1",type:"test",foo:"${$parent.V0}",wires:[]},
- {id:"3",x:10,y:10,z:"t1",g:"g1",type:"test",foo:"${$parent.V1}",wires:[]},
- {id:"4",x:10,y:10,z:"t1",g:"g2",type:"test",foo:"${$parent.V1}",wires:[]},
- {id:"5",x:10,y:10,z:"t1",type:"test",foo:"${$parent.V1}",wires:[]},
- ]);
- var flow = Flow.create({getSetting:v=>process.env[v]},config,config.flows["t1"]);
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
-
- activeNodes["1"].foo.should.equal("gv0");
- activeNodes["2"].foo.should.equal("v0");
- activeNodes["3"].foo.should.equal("gv1");
- activeNodes["4"].foo.should.equal("v2");
- activeNodes["5"].foo.should.equal("gv1");
-
- flow.stop().then(function() {
- done();
- });
- }
- catch (e) {
- console.log(e.stack);
- done(e);
- }
-
- });
-
- });
-
-});
diff --git a/test/unit/@node-red/runtime/lib/flows/Subflow_spec.js b/test/unit/@node-red/runtime/lib/flows/Subflow_spec.js
deleted file mode 100644
index 0479b5117..000000000
--- a/test/unit/@node-red/runtime/lib/flows/Subflow_spec.js
+++ /dev/null
@@ -1,885 +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 clone = require('clone');
-var util = require("util");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var Subflow = NR_TEST_UTILS.require("@node-red/runtime/lib/flows/Subflow");
-var Flow = NR_TEST_UTILS.require("@node-red/runtime/lib/flows/Flow");
-
-var flowUtils = NR_TEST_UTILS.require("@node-red/runtime/lib/flows/util");
-var flows = NR_TEST_UTILS.require("@node-red/runtime/lib/flows");
-var Node = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/Node");
-var typeRegistry = NR_TEST_UTILS.require("@node-red/registry");
-
-describe('Subflow', function() {
- var getType;
-
- var stoppedNodes = {};
- var currentNodes = {};
- var rewiredNodes = {};
- var createCount = 0;
-
- beforeEach(function() {
- currentNodes = {};
- stoppedNodes = {};
- rewiredNodes = {};
- createCount = 0;
- var runtime = {
- settings:{},
- log:{
- log: sinon.stub(), // function() { console.log("l",[...arguments].map(a => JSON.stringify(a)).join(" ")) },//
- debug: sinon.stub(), // function() { console.log("d",[...arguments].map(a => JSON.stringify(a)).join(" ")) },//sinon.stub(),
- trace: sinon.stub(), // function() { console.log("t",[...arguments].map(a => JSON.stringify(a)).join(" ")) },//sinon.stub(),
- warn: sinon.stub(), // function() { console.log("w",[...arguments].map(a => JSON.stringify(a)).join(" ")) },//sinon.stub(),
- info: sinon.stub(), // function() { console.log("i",[...arguments].map(a => JSON.stringify(a)).join(" ")) },//sinon.stub(),
- metric: sinon.stub(),
- _: function() { return "abc"}
- }
- }
- Flow.init(runtime);
- Subflow.init(runtime);
- });
-
- var TestNode = function(n) {
- Node.call(this,n);
- this._index = createCount++;
- this.scope = n.scope;
- var node = this;
- this.foo = n.foo;
- this.handled = 0;
- this.stopped = false;
- this.received = null;
- currentNodes[node.id] = node;
- this.on('input',function(msg) {
- // console.log(this.id,msg.payload);
- node.handled++;
- node.received = msg.payload;
- node.send(msg);
- });
- this.on('close',function() {
- node.stopped = true;
- stoppedNodes[node.id] = node;
- delete currentNodes[node.id];
- });
- this.__updateWires = this.updateWires;
- this.updateWires = function(newWires) {
- rewiredNodes[node.id] = node;
- node.newWires = newWires;
- node.__updateWires(newWires);
- };
- }
- util.inherits(TestNode,Node);
-
- var TestErrorNode = function(n) {
- Node.call(this,n);
- this._index = createCount++;
- this.scope = n.scope;
- this.name = n.name;
- var node = this;
- this.foo = n.foo;
- this.handled = 0;
- this.stopped = false;
- currentNodes[node.id] = node;
- this.on('input',function(msg) {
- node.handled++;
- node.error("test error",msg);
- });
- this.on('close',function() {
- node.stopped = true;
- stoppedNodes[node.id] = node;
- delete currentNodes[node.id];
- });
- this.__updateWires = this.updateWires;
- this.updateWires = function(newWires) {
- rewiredNodes[node.id] = node;
- node.newWires = newWires;
- node.__updateWires(newWires);
- };
- }
- util.inherits(TestErrorNode,Node);
-
-
- var TestStatusNode = function(n) {
- Node.call(this,n);
- this._index = createCount++;
- this.scope = n.scope;
- this.name = n.name;
- var node = this;
- this.foo = n.foo;
- this.handled = 0;
- this.stopped = false;
- currentNodes[node.id] = node;
- this.on('input',function(msg) {
- node.handled++;
- node.status({text:"test status"});
- });
- this.on('close',function() {
- node.stopped = true;
- stoppedNodes[node.id] = node;
- delete currentNodes[node.id];
- });
- this.__updateWires = this.updateWires;
- this.updateWires = function(newWires) {
- rewiredNodes[node.id] = node;
- node.newWires = newWires;
- node.__updateWires(newWires);
- };
- }
- util.inherits(TestStatusNode,Node);
-
- var TestAsyncNode = function(n) {
- Node.call(this,n);
- var node = this;
- this.scope = n.scope;
- this.foo = n.foo;
- this.handled = 0;
- this.messages = [];
- this.stopped = false;
- this.closeDelay = n.closeDelay || 50;
- currentNodes[node.id] = node;
- this.on('input',function(msg) {
- node.handled++;
- node.messages.push(msg);
- node.send(msg);
- });
- this.on('close',function(done) {
- setTimeout(function() {
- node.stopped = true;
- stoppedNodes[node.id] = node;
- delete currentNodes[node.id];
- done();
- },node.closeDelay);
- });
- }
- util.inherits(TestAsyncNode,Node);
-
- var TestEnvNode = function(n) {
- Node.call(this,n);
- this._index = createCount++;
- this.scope = n.scope;
- this.foo = n.foo;
- var node = this;
- this.stopped = false;
- this.received = null;
- currentNodes[node.id] = node;
- this.on('input',function(msg) {
- var flow = node._flow;
- var val = flow.getSetting("__KEY__");
- node.received = val;
- node.send({payload: val});
- });
- this.on('close',function() {
- node.stopped = true;
- stoppedNodes[node.id] = node;
- delete currentNodes[node.id];
- });
- this.__updateWires = this.updateWires;
- this.updateWires = function(newWires) {
- rewiredNodes[node.id] = node;
- node.newWires = newWires;
- node.__updateWires(newWires);
- };
- }
- util.inherits(TestEnvNode,Node);
-
- before(function() {
- getType = sinon.stub(typeRegistry,"get").callsFake(function(type) {
- if (type=="test") {
- return TestNode;
- } else if (type=="testError"){
- return TestErrorNode;
- } else if (type=="testStatus"){
- return TestStatusNode;
- } else if (type=="testEnv"){
- return TestEnvNode;
- } else {
- return TestAsyncNode;
- }
- });
- });
- after(function() {
- getType.restore();
- });
- describe('#start',function() {
- it("instantiates a subflow and stops it",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3","4"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"4",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sf1",type:"subflow","name":"Subflow 2","info":"",
- "in":[{"wires":[{"id":"sf1-1"}]}],"out":[{"wires":[{"id":"sf1-2","port":0}]},{"wires":[{"id":"sf1","port":0}]}]},
- {id:"sf1-1",type:"test","z":"sf1",x:166,y:99,"wires":[["sf1-2"]]},
- {id:"sf1-2",type:"test","z":"sf1",foo:"sf1-cn",x:166,y:99,"wires":[[]]},
- {id:"sf1-cn",type:"test","z":"sf1"}
- ]);
- var flow = Flow.create({handleError: (a,b,c) => { console.log(a,b,c); }},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
- Object.keys(activeNodes).should.have.length(4);
- // var sfInstanceId = Object.keys(activeNodes)[5];
- // var sfInstanceId2 = Object.keys(activeNodes)[6];
- var sfConfigId = Object.keys(activeNodes)[4];
-
- flow.getNode('1').should.have.a.property('id','1');
- flow.getNode('2').should.have.a.property('id','2');
- flow.getNode('3').should.have.a.property('id','3');
- flow.getNode('4').should.have.a.property('id','4');
- // flow.getNode(sfInstanceId).should.have.a.property('id',sfInstanceId);
- // flow.getNode(sfInstanceId2).should.have.a.property('id',sfInstanceId2);
- // flow.getNode(sfConfigId).should.have.a.property('id',sfConfigId);
-
- // flow.getNode(sfInstanceId2).should.have.a.property('foo',sfConfigId);
-
- Object.keys(currentNodes).should.have.length(6);
-
- currentNodes.should.have.a.property("1");
- currentNodes.should.not.have.a.property("2");
- currentNodes.should.have.a.property("3");
- currentNodes.should.have.a.property("4");
- // currentNodes.should.have.a.property(sfInstanceId);
- // currentNodes.should.have.a.property(sfInstanceId2);
- // currentNodes.should.have.a.property(sfConfigId);
-
- currentNodes["1"].should.have.a.property("handled",0);
- currentNodes["3"].should.have.a.property("handled",0);
- currentNodes["4"].should.have.a.property("handled",0);
- // currentNodes[sfInstanceId].should.have.a.property("handled",0);
- // currentNodes[sfInstanceId2].should.have.a.property("handled",0);
-
- currentNodes["1"].receive({payload:"test"});
-
- setTimeout(function() {
- currentNodes["1"].should.have.a.property("handled",1);
- // currentNodes[sfInstanceId].should.have.a.property("handled",1);
- // currentNodes[sfInstanceId2].should.have.a.property("handled",1);
- currentNodes["3"].should.have.a.property("handled",1);
- currentNodes["4"].should.have.a.property("handled",1);
-
-
-
- flow.stop().then(function() {
- Object.keys(currentNodes).should.have.length(0);
- Object.keys(stoppedNodes).should.have.length(6);
-
- // currentNodes.should.not.have.a.property("1");
- // currentNodes.should.not.have.a.property("3");
- // currentNodes.should.not.have.a.property("4");
- // // currentNodes.should.not.have.a.property(sfInstanceId);
- // // currentNodes.should.not.have.a.property(sfInstanceId2);
- // // currentNodes.should.not.have.a.property(sfConfigId);
- // stoppedNodes.should.have.a.property("1");
- // stoppedNodes.should.have.a.property("3");
- // stoppedNodes.should.have.a.property("4");
- // // stoppedNodes.should.have.a.property(sfInstanceId);
- // // stoppedNodes.should.have.a.property(sfInstanceId2);
- // // stoppedNodes.should.have.a.property(sfConfigId);
- done();
- });
- },150);
- });
- it("instantiates a subflow inside a subflow and stops it",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3","4"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"4",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sf1",type:"subflow","name":"Subflow 1","info":"",
- "in":[{"wires":[{"id":"sf1-1"}]}],"out":[{"wires":[{"id":"sf1-2","port":0}]}]},
- {id:"sf2",type:"subflow","name":"Subflow 2","info":"",
- "in":[{wires:[]}],"out":[{"wires":[{"id":"sf2","port":0}]}]},
- {id:"sf1-1",type:"test","z":"sf1",x:166,y:99,"wires":[["sf1-2"]]},
- {id:"sf1-2",type:"subflow:sf2","z":"sf1",x:166,y:99,"wires":[[]]}
-
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- currentNodes["1"].should.have.a.property("handled",0);
- currentNodes["3"].should.have.a.property("handled",0);
-
- currentNodes["1"].receive({payload:"test"});
-
- setTimeout(function() {
- currentNodes["1"].should.have.a.property("handled",1);
- currentNodes["3"].should.have.a.property("handled",1);
- flow.stop().then(function() {
- Object.keys(currentNodes).should.have.length(0);
- done();
- });
- },150);
- });
- it("rewires a subflow node on update/start",function(done){
-
- var rawConfig = [
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"4",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sf1",type:"subflow","name":"Subflow 2","info":"",
- "in":[{"wires":[{"id":"sf1-1"}]}],"out":[{"wires":[{"id":"sf1-2","port":0}]}]},
- {id:"sf1-1",type:"test1","z":"sf1",x:166,y:99,"wires":[["sf1-2"]]},
- {id:"sf1-2",type:"test2","z":"sf1",x:166,y:99,"wires":[[]]}
- ];
-
- var config = flowUtils.parseConfig(clone(rawConfig));
-
- rawConfig[2].wires = [["4"]];
-
- var newConfig = flowUtils.parseConfig(rawConfig);
- var diff = flowUtils.diffConfigs(config,newConfig);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
- Object.keys(activeNodes).should.have.length(4);
- // var sfInstanceId = Object.keys(activeNodes)[4];
- // var sfInstanceId2 = Object.keys(activeNodes)[5];
-
- currentNodes["1"].should.have.a.property("handled",0);
- currentNodes["3"].should.have.a.property("handled",0);
- currentNodes["4"].should.have.a.property("handled",0);
-
- currentNodes["1"].receive({payload:"test"});
-
- setTimeout(function() {
- currentNodes["1"].should.have.a.property("handled",1);
- // currentNodes[sfInstanceId].should.have.a.property("handled",1);
- // currentNodes[sfInstanceId2].should.have.a.property("handled",1);
- currentNodes["3"].should.have.a.property("handled",1);
- currentNodes["4"].should.have.a.property("handled",0);
-
- flow.update(newConfig,newConfig.flows["t1"]);
- flow.start(diff)
-
- currentNodes["1"].receive({payload:"test2"});
- setTimeout(function() {
-
- currentNodes["1"].should.have.a.property("handled",2);
- // currentNodes[sfInstanceId].should.have.a.property("handled",2);
- // currentNodes[sfInstanceId2].should.have.a.property("handled",2);
- currentNodes["3"].should.have.a.property("handled",1);
- currentNodes["4"].should.have.a.property("handled",1);
-
-
- flow.stop().then(function() {
- done();
- });
- },150);
- },150);
- });
- });
- describe('#stop', function() {
- it("stops subflow instance nodes",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sf1",type:"subflow","name":"Subflow 2","info":"",
- "in":[{"wires":[{"id":"sf1-1"}]}],"out":[{"wires":[{"id":"sf1-1","port":0}]}]},
- {id:"sf1-1",type:"test","z":"sf1",x:166,y:99,"wires":[[]]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
- Object.keys(activeNodes).should.have.length(3);
- Object.keys(stoppedNodes).should.have.length(0);
- flow.stop(["2"]).then(function() {
- Object.keys(currentNodes).should.have.length(2);
- Object.keys(stoppedNodes).should.have.length(1);
- done();
- }).catch(done);
- });
- });
- describe("#handleStatus",function() {
- it("passes a status event to the subflow's parent tab status node - all scope",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sf1",type:"subflow","name":"Subflow 2","info":"",
- "in":[{"wires":[{"id":"sf1-1"}]}],"out":[{"wires":[{"id":"sf1-1","port":0}]}]},
- {id:"sf1-1",type:"testStatus",name:"test-status-node","z":"sf1",x:166,y:99,"wires":[[]]},
- {id:"sn",x:10,y:10,z:"t1",type:"status",foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
-
- activeNodes["1"].receive({payload:"test"});
- setTimeout(function() {
- currentNodes["sn"].should.have.a.property("handled",1);
- var statusMessage = currentNodes["sn"].messages[0];
-
- statusMessage.should.have.a.property("status");
- statusMessage.status.should.have.a.property("text","test status");
- statusMessage.status.should.have.a.property("source");
- statusMessage.status.source.should.have.a.property("type","testStatus");
- statusMessage.status.source.should.have.a.property("name","test-status-node");
-
- flow.stop().then(function() {
- done();
- });
- },150);
- });
- it("passes a status event to the subflow's parent tab status node - targetted scope",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sf1",type:"subflow","name":"Subflow 2","info":"",
- "in":[{"wires":[{"id":"sf1-1"}]}],"out":[{"wires":[{"id":"sf1-1","port":0}]}]},
- {id:"sf1-1",type:"testStatus",name:"test-status-node","z":"sf1",x:166,y:99,"wires":[[]]},
- {id:"sn",x:10,y:10,z:"t1",type:"status",scope:["2"],wires:[]}
- ]);
- var parentFlowStatusCalled = false;
-
- var flow = Flow.create({handleStatus:() => { parentFlowStatusCalled = true} },config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
-
- activeNodes["1"].receive({payload:"test"});
-
- setTimeout(function() {
- parentFlowStatusCalled.should.be.false();
-
- currentNodes["sn"].should.have.a.property("handled",1);
- var statusMessage = currentNodes["sn"].messages[0];
-
- statusMessage.should.have.a.property("status");
- statusMessage.status.should.have.a.property("text","test status");
- statusMessage.status.should.have.a.property("source");
- statusMessage.status.source.should.have.a.property("type","testStatus");
- statusMessage.status.source.should.have.a.property("name","test-status-node");
-
- flow.stop().then(function() {
-
- done();
- });
- },150);
- });
- });
-
- describe("status node", function() {
- it("emits a status event when a message is passed to a subflow-status node - msg.payload as string", function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {
- id:"sf1",
- type:"subflow",
- name:"Subflow 2",
- info:"",
- in:[{wires:[{id:"sf1-1"}]}],
- out:[{wires:[{id:"sf1-1",port:0}]}],
- status:{wires:[{id:"sf1-1", port:0}]}
- },
- {id:"sf1-1",type:"test",name:"test","z":"sf1",x:166,y:99,"wires":[[]]},
- {id:"sn",x:10,y:10,z:"t1",type:"status",foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
-
- activeNodes["1"].receive({payload:"test-payload"});
-
- setTimeout(function() {
- currentNodes["sn"].should.have.a.property("handled",1);
- var statusMessage = currentNodes["sn"].messages[0];
-
- statusMessage.should.have.a.property("status");
- statusMessage.status.should.have.a.property("text","test-payload");
- statusMessage.status.should.have.a.property("source");
- statusMessage.status.source.should.have.a.property("id","2");
- statusMessage.status.source.should.have.a.property("type","subflow:sf1");
-
- flow.stop().then(function() {
-
- done();
- });
- },150);
- });
- it("emits a status event when a message is passed to a subflow-status node - msg.payload as status obj", function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {
- id:"sf1",
- type:"subflow",
- name:"Subflow 2",
- info:"",
- in:[{wires:[{id:"sf1-1"}]}],
- out:[{wires:[{id:"sf1-1",port:0}]}],
- status:{wires:[{id:"sf1-1", port:0}]}
- },
- {id:"sf1-1",type:"test",name:"test","z":"sf1",x:166,y:99,"wires":[[]]},
- {id:"sn",x:10,y:10,z:"t1",type:"status",foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
-
- activeNodes["1"].receive({payload:{text:"payload-obj"}});
-
- setTimeout(function() {
- currentNodes["sn"].should.have.a.property("handled",1);
- var statusMessage = currentNodes["sn"].messages[0];
-
- statusMessage.should.have.a.property("status");
- statusMessage.status.should.have.a.property("text","payload-obj");
- statusMessage.status.should.have.a.property("source");
- statusMessage.status.source.should.have.a.property("id","2");
- statusMessage.status.source.should.have.a.property("type","subflow:sf1");
-
- flow.stop().then(function() {
-
- done();
- });
- },150);
- });
- it("emits a status event when a message is passed to a subflow-status node - msg.status", function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {
- id:"sf1",
- type:"subflow",
- name:"Subflow 2",
- info:"",
- in:[{wires:[{id:"sf1-1"}]}],
- out:[{wires:[{id:"sf1-1",port:0}]}],
- status:{wires:[{id:"sf1-1", port:0}]}
- },
- {id:"sf1-1",type:"test",name:"test","z":"sf1",x:166,y:99,"wires":[[]]},
- {id:"sn",x:10,y:10,z:"t1",type:"status",foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
-
- activeNodes["1"].receive({status:{text:"status-obj"}});
-
- setTimeout(function() {
- currentNodes["sn"].should.have.a.property("handled",1);
- var statusMessage = currentNodes["sn"].messages[0];
-
- statusMessage.should.have.a.property("status");
- statusMessage.status.should.have.a.property("text","status-obj");
- statusMessage.status.should.have.a.property("source");
- statusMessage.status.source.should.have.a.property("id","2");
- statusMessage.status.source.should.have.a.property("type","subflow:sf1");
-
- flow.stop().then(function() {
-
- done();
- });
- },150);
- });
- it("does not emit a regular status event if it contains a subflow-status node", function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {
- id:"sf1",
- type:"subflow",
- name:"Subflow 2",
- info:"",
- in:[{wires:[{id:"sf1-1"}]}],
- out:[{wires:[{id:"sf1-1",port:0}]}],
- status:{wires:[]}
- },
- {id:"sf1-1",type:"testStatus",name:"test-status-node","z":"sf1",x:166,y:99,"wires":[[]]},
- {id:"sn",x:10,y:10,z:"t1",type:"status",foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
-
- activeNodes["1"].receive({payload:"test-payload"});
-
- currentNodes["sn"].should.have.a.property("handled",0);
-
- flow.stop().then(function() {
-
- done();
- });
- });
- })
-
- describe("#handleError",function() {
- it("passes an error event to the subflow's parent tab catch node - all scope",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sf1",type:"subflow","name":"Subflow 2","info":"",
- "in":[{"wires":[{"id":"sf1-1"}]}],"out":[{"wires":[{"id":"sf1-1","port":0}]}]},
- {id:"sf1-1",name:"test-error-node",type:"testError","z":"sf1",x:166,y:99,"wires":[[]]},
- {id:"sn",x:10,y:10,z:"t1",type:"catch",foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
-
- activeNodes["1"].receive({payload:"test"});
-
- setTimeout(function() {
- currentNodes["sn"].should.have.a.property("handled",1);
- var statusMessage = currentNodes["sn"].messages[0];
-
- statusMessage.should.have.a.property("error");
- statusMessage.error.should.have.a.property("message","test error");
- statusMessage.error.should.have.a.property("source");
- statusMessage.error.source.should.have.a.property("type","testError");
- statusMessage.error.source.should.have.a.property("name","test-error-node");
-
- flow.stop().then(function() {
- done();
- });
- },150);
- });
- it("passes an error event to the subflow's parent tab catch node - targetted scope",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sf1",type:"subflow","name":"Subflow 2","info":"",
- "in":[{"wires":[{"id":"sf1-1"}]}],"out":[{"wires":[{"id":"sf1-1","port":0}]}]},
- {id:"sf1-1",name:"test-error-node",type:"testError","z":"sf1",x:166,y:99,"wires":[[]]},
- {id:"sn",x:10,y:10,z:"t1",type:"catch",scope:["2"],wires:[]}
- ]);
- var parentFlowErrorCalled = false;
- var flow = Flow.create({handleError:() => { parentFlowErrorCalled = true} },config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
-
- activeNodes["1"].receive({payload:"test"});
-
- setTimeout(function() {
- parentFlowErrorCalled.should.be.false();
-
- currentNodes["sn"].should.have.a.property("handled",1);
- var statusMessage = currentNodes["sn"].messages[0];
-
- statusMessage.should.have.a.property("error");
- statusMessage.error.should.have.a.property("message","test error");
- statusMessage.error.should.have.a.property("source");
- statusMessage.error.source.should.have.a.property("type","testError");
- statusMessage.error.source.should.have.a.property("name","test-error-node");
-
- flow.stop().then(function() {
- done();
- });
- },150);
-
- });
- });
-
- describe("#env var", function() {
- // should be changed according to internal env var representation
- function setEnv(node, key, val) {
- var flow = node._flow;
- if (flow) {
- var env = flow.env;
- if (!env) {
- env = flow.env = {};
- }
- env[key] = {
- name: key,
- type: "str",
- value: val
- };
- }
- }
-
- it("can access process env var", function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"t1.1",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"t1.3",wires:[]},
- {id:"sf1",type:"subflow",name:"Subflow 2",info:"",
- "in":[ {wires:[{id:"sf1-1"}]} ],
- "out":[ {wires:[{id:"sf1-2",port:0}]} ]},
- {id:"sf1-1",type:"test",z:"sf1",foo:"sf1.1",x:166,y:99,wires:[["sf1-2"]]},
- {id:"sf1-2",type:"testEnv",z:"sf1",foo:"sf1-cn",x:166,y:99,wires:[[]]}
- ]);
- var flow = Flow.create({
- getSetting: k=> process.env[k],
- handleError: (a,b,c) => { console.log(a,b,c); }
- },config,config.flows["t1"]);
-
- flow.start();
-
- process.env["__KEY__"] = "__VAL__";
-
- currentNodes["1"].receive({payload: "test"});
- setTimeout(function() {
- currentNodes["3"].should.have.a.property("received", "__VAL__");
-
- flow.stop().then(function() {
- done();
- });
- },150);
- });
-
- it("can access subflow env var", function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"t1.1",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"t1.3",wires:[]},
- {id:"sf1",type:"subflow",name:"Subflow 2",info:"",
- "in":[ {wires:[{id:"sf1-1"}]} ],
- "out":[ {wires:[{id:"sf1-2",port:0}]} ]},
- {id:"sf1-1",type:"test",z:"sf1",foo:"sf1.1",x:166,y:99,wires:[["sf1-2"]]},
- {id:"sf1-2",type:"testEnv",z:"sf1",foo:"sf1.2",x:166,y:99,wires:[[]]}
- ]);
- var flow = Flow.create({
- getSetting: k=> process.env[k],
- handleError: (a,b,c) => { console.log(a,b,c); }
- },config,config.flows["t1"]);
-
- flow.start();
-
- var testenv_node = null;
- for (var n in currentNodes) {
- var node = currentNodes[n];
- if (node.type === "testEnv") {
- testenv_node = node;
- break;
- }
- }
- process.env["__KEY__"] = "__VAL0__";
- setEnv(testenv_node, "__KEY__", "__VAL1__");
-
- currentNodes["1"].receive({payload: "test"});
- setTimeout(function() {
- currentNodes["3"].should.have.a.property("received", "__VAL1__");
-
- flow.stop().then(function() {
- done();
- });
- },150);
- });
-
- it("can access nested subflow env var", function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"t1.1",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"t1.3",wires:[]},
- {id:"sf1",type:"subflow",name:"Subflow 1",info:"",
- in:[{wires:[{id:"sf1-1"}]}],
- out:[{wires:[{id:"sf1-2",port:0}]}]},
- {id:"sf2",type:"subflow",name:"Subflow 2",info:"",
- in:[{wires:[{id:"sf2-1"}]}],
- out:[{wires:[{id:"sf2-2",port:0}]}]},
- {id:"sf1-1",type:"test",z:"sf1",foo:"sf1.1",x:166,y:99,wires:[["sf1-2"]]},
- {id:"sf1-2",type:"subflow:sf2",z:"sf1",x:166,y:99,wires:[[]]},
- {id:"sf2-1",type:"test",z:"sf2",foo:"sf2.1",x:166,y:99,wires:[["sf2-2"]]},
- {id:"sf2-2",type:"testEnv",z:"sf2",foo:"sf2.2",x:166,y:99,wires:[[]]},
- ]);
- var flow = Flow.create({
- getSetting: k=> process.env[k],
- handleError: (a,b,c) => { console.log(a,b,c); }
- },config,config.flows["t1"]);
-
- flow.start();
-
- var node_sf1_1 = null;
- var node_sf2_1 = null;
- var testenv_node = null;
- for (var n in currentNodes) {
- var node = currentNodes[n];
- if (node.foo === "sf1.1") {
- node_sf1_1 = node;
- }
- if (node.foo === "sf2.1") {
- node_sf2_1 = node;
- }
- }
-
- process.env["__KEY__"] = "__VAL0__";
- currentNodes["1"].receive({payload: "test"});
- setTimeout(function() {
- currentNodes["3"].should.have.a.property("received", "__VAL0__");
-
- setEnv(node_sf1_1, "__KEY__", "__VAL1__");
- currentNodes["1"].receive({payload: "test"});
- setTimeout(function() {
- currentNodes["3"].should.have.a.property("received", "__VAL1__");
-
- setEnv(node_sf2_1, "__KEY__", "__VAL2__");
- currentNodes["1"].receive({payload: "test"});
- setTimeout(function() {
- currentNodes["3"].should.have.a.property("received", "__VAL2__");
-
- flow.stop().then(function() {
- done();
- });
- },150);
- },150);
- },150);
- });
-
- });
-
-});
diff --git a/test/unit/@node-red/runtime/lib/flows/index_spec.js b/test/unit/@node-red/runtime/lib/flows/index_spec.js
deleted file mode 100644
index 737846100..000000000
--- a/test/unit/@node-red/runtime/lib/flows/index_spec.js
+++ /dev/null
@@ -1,669 +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 clone = require("clone");
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var flows = NR_TEST_UTILS.require("@node-red/runtime/lib/flows");
-var RedNode = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/Node");
-var RED = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes");
-var events = NR_TEST_UTILS.require("@node-red/util/lib/events");
-var credentials = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/credentials");
-var typeRegistry = NR_TEST_UTILS.require("@node-red/registry")
-var Flow = NR_TEST_UTILS.require("@node-red/runtime/lib/flows/Flow");
-
-describe('flows/index', function() {
-
- var storage;
- var eventsOn;
- var credentialsClean;
- var credentialsLoad;
- var credentialsAdd;
-
- var flowCreate;
- var getType;
- var checkFlowDependencies;
-
- var mockLog = {
- log: sinon.stub(),
- debug: sinon.stub(),
- trace: sinon.stub(),
- warn: sinon.stub(),
- info: sinon.stub(),
- metric: sinon.stub(),
- _: function() { return "abc"}
- }
-
-
- before(function() {
- getType = sinon.stub(typeRegistry,"get").callsFake(function(type) {
- return type.indexOf('missing') === -1;
- });
- checkFlowDependencies = sinon.stub(typeRegistry, "checkFlowDependencies").callsFake(async function(flow) {
- if (flow[0].id === "node-with-missing-modules") {
- throw new Error("Missing module");
- }
- });
- });
-
- after(function() {
- getType.restore();
- checkFlowDependencies.restore();
- });
-
-
- beforeEach(function() {
- eventsOn = sinon.spy(events,"on");
- credentialsClean = sinon.stub(credentials,"clean").callsFake(function(conf) {
- conf.forEach(function(n) {
- delete n.credentials;
- });
- return Promise.resolve();
- });
- credentialsLoad = sinon.stub(credentials,"load").callsFake(function(creds) {
- if (creds && creds.hasOwnProperty("$") && creds['$'] === "fail") {
- return Promise.reject("creds error");
- }
- return Promise.resolve();
- });
- credentialsAdd = sinon.stub(credentials,"add").callsFake(async function(id, conf){})
- flowCreate = sinon.stub(Flow,"create").callsFake(function(parent, global, flow) {
- var id;
- if (typeof flow === 'undefined') {
- flow = global;
- id = '_GLOBAL_';
- } else {
- id = flow.id;
- }
- flowCreate.flows[id] = {
- flow: flow,
- global: global,
- start: sinon.spy(),
- update: sinon.spy(),
- stop: sinon.spy(),
- getActiveNodes: function() {
- return flow.nodes||{};
- },
- handleError: sinon.spy(),
- handleStatus: sinon.spy()
-
- }
- return flowCreate.flows[id];
- });
- flowCreate.flows = {};
-
- storage = {
- saveFlows: function(conf) {
- storage.conf = conf;
- return Promise.resolve();
- }
- }
- });
-
- afterEach(function(done) {
- eventsOn.restore();
- credentialsClean.restore();
- credentialsLoad.restore();
- credentialsAdd.restore();
- flowCreate.restore();
-
- flows.stopFlows().then(done);
-
- });
- // describe('#init',function() {
- // it('registers the type-registered handler', function() {
- // flows.init({},{});
- // eventsOn.calledOnce.should.be.true();
- // });
- // });
-
- describe('#setFlows', function() {
- it('sets the full flow', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.setFlows(originalConfig).then(function() {
- credentialsClean.called.should.be.true();
- storage.hasOwnProperty('conf').should.be.true();
- flows.getFlows().flows.should.eql(originalConfig);
- done();
- });
-
- });
- it('loads the full flow for type load', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- var loadStorage = {
- saveFlows: function(conf) {
- loadStorage.conf = conf;
- return Promise.resolve(456);
- },
- getFlows: function() {
- return Promise.resolve({flows:originalConfig,rev:123})
- }
- }
- flows.init({log:mockLog, settings:{},storage:loadStorage});
- flows.setFlows(originalConfig,"load").then(function() {
- credentialsClean.called.should.be.false();
- // 'load' type does not trigger a save
- loadStorage.hasOwnProperty('conf').should.be.false();
- flows.getFlows().flows.should.eql(originalConfig);
- done();
- });
-
- });
-
- it('extracts credentials from the full flow', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[],credentials:{"a":1}},
- {id:"t1",type:"tab"}
- ];
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.setFlows(originalConfig).then(function() {
- credentialsClean.called.should.be.true();
- storage.hasOwnProperty('conf').should.be.true();
- var cleanedFlows = flows.getFlows();
- storage.conf.flows.should.eql(cleanedFlows.flows);
- cleanedFlows.flows.should.not.eql(originalConfig);
- cleanedFlows.flows[0].credentials = {"a":1};
- cleanedFlows.flows.should.eql(originalConfig);
- done();
- });
- });
-
- it('sets the full flow including credentials', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- var credentials = {"t1-1":{"a":1}};
-
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.setFlows(originalConfig,credentials).then(function() {
- credentialsClean.called.should.be.true();
- credentialsAdd.called.should.be.true();
- credentialsAdd.lastCall.args[0].should.eql("t1-1");
- credentialsAdd.lastCall.args[1].should.eql({"a":1});
- flows.getFlows().flows.should.eql(originalConfig);
- done();
- });
- });
-
- it('updates existing flows with partial deployment - nodes', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- var newConfig = clone(originalConfig);
- newConfig.push({id:"t1-2",x:10,y:10,z:"t1",type:"test",wires:[]});
- newConfig.push({id:"t2",type:"tab"});
- newConfig.push({id:"t2-1",x:10,y:10,z:"t2",type:"test",wires:[]});
- storage.getFlows = function() {
- return Promise.resolve({flows:originalConfig});
- }
- events.once('flows:started',function() {
- flows.setFlows(newConfig,"nodes").then(function() {
- flows.getFlows().flows.should.eql(newConfig);
- flowCreate.flows['t1'].update.called.should.be.true();
- flowCreate.flows['t2'].start.called.should.be.true();
- flowCreate.flows['_GLOBAL_'].update.called.should.be.true();
- done();
- })
- });
-
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.load().then(function() {
- flows.startFlows();
- });
- });
-
- it('updates existing flows with partial deployment - flows', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- var newConfig = clone(originalConfig);
- newConfig.push({id:"t1-2",x:10,y:10,z:"t1",type:"test",wires:[]});
- newConfig.push({id:"t2",type:"tab"});
- newConfig.push({id:"t2-1",x:10,y:10,z:"t2",type:"test",wires:[]});
- storage.getFlows = function() {
- return Promise.resolve({flows:originalConfig});
- }
-
- events.once('flows:started',function() {
- flows.setFlows(newConfig,"nodes").then(function() {
- flows.getFlows().flows.should.eql(newConfig);
- flowCreate.flows['t1'].update.called.should.be.true();
- flowCreate.flows['t2'].start.called.should.be.true();
- flowCreate.flows['_GLOBAL_'].update.called.should.be.true();
- flows.stopFlows().then(done);
- })
- });
-
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.load().then(function() {
- flows.startFlows();
- });
- });
-
- it('returns error if it cannot decrypt credentials', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- var credentials = {"$":"fail"};
-
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.setFlows(originalConfig,credentials).then(function() {
- done("Unexpected success when credentials couldn't be decrypted")
- }).catch(function(err) {
- done();
- });
- });
- });
-
- describe('#load', function() {
- it('loads the flow config', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- storage.getFlows = function() {
- return Promise.resolve({flows:originalConfig});
- }
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.load().then(function() {
- credentialsLoad.called.should.be.true();
- // 'load' type does not trigger a save
- storage.hasOwnProperty('conf').should.be.false();
- flows.getFlows().flows.should.eql(originalConfig);
- done();
- });
- });
- });
-
- describe('#startFlows', function() {
- it('starts the loaded config', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- storage.getFlows = function() {
- return Promise.resolve({flows:originalConfig});
- }
-
- events.once('flows:started',function() {
- Object.keys(flowCreate.flows).should.eql(['_GLOBAL_','t1']);
- done();
- });
-
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.load().then(function() {
- return flows.startFlows();
- });
- });
- it('does not start if nodes missing', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1-2",x:10,y:10,z:"t1",type:"missing",wires:[]},
- {id:"t1",type:"tab"}
- ];
- storage.getFlows = function() {
- return Promise.resolve({flows:originalConfig});
- }
-
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.load().then(function() {
- return flows.startFlows();
- }).then(() => {
- try {
- flowCreate.called.should.be.false();
- done();
- } catch(err) {
- done(err);
- }
- });
- });
-
- it('starts when missing nodes registered', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1-2",x:10,y:10,z:"t1",type:"missing",wires:[]},
- {id:"t1-3",x:10,y:10,z:"t1",type:"missing2",wires:[]},
- {id:"t1",type:"tab"}
- ];
- storage.getFlows = function() {
- return Promise.resolve({flows:originalConfig});
- }
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.load().then(function() {
- return flows.startFlows();
- }).then(() => {
- flowCreate.called.should.be.false();
- events.emit("type-registered","missing");
- setTimeout(function() {
- flowCreate.called.should.be.false();
- events.emit("type-registered","missing2");
- setTimeout(function() {
- flowCreate.called.should.be.true();
- done();
- },10);
- },10);
- });
- });
-
- it('does not start if external modules missing', function(done) {
- var originalConfig = [
- {id:"node-with-missing-modules",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
-
- storage.getFlows = function() {
- return Promise.resolve({flows:originalConfig});
- }
- var receivedEvent = null;
- var handleEvent = function(payload) {
- receivedEvent = payload;
- }
-
- events.on("runtime-event",handleEvent);
-
- //{id:"runtime-state",payload:{error:"missing-modules", type:"warning",text:"notification.warnings.missing-modules",modules:missingModules},retain:true});"
-
-
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.load().then(flows.startFlows).then(() => {
- events.removeListener("runtime-event",handleEvent);
- try {
- flowCreate.called.should.be.false();
- receivedEvent.should.have.property('id','runtime-state');
- receivedEvent.should.have.property('payload',
- { error: 'missing-modules',
- type: 'warning',
- text: 'notification.warnings.missing-modules',
- modules: [] }
- );
-
- done();
- }catch(err) {
- done(err)
- }
- });
- });
-
- });
-
- describe.skip('#get',function() {
-
- });
-
- describe('#eachNode', function() {
- it('iterates the flow nodes', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- storage.getFlows = function() {
- return Promise.resolve({flows:originalConfig});
- }
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.load().then(function() {
- var c = 0;
- flows.eachNode(function(node) {
- c++
- })
- c.should.equal(2);
- done();
- });
- });
- });
-
- describe('#stopFlows', function() {
-
- });
- // describe('#handleError', function() {
- // it('passes error to correct flow', function(done) {
- // var originalConfig = [
- // {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- // {id:"t1",type:"tab"}
- // ];
- // storage.getFlows = function() {
- // return Promise.resolve({flows:originalConfig});
- // }
- //
- // events.once('flows:started',function() {
- // flows.handleError(originalConfig[0],"message",{});
- // flowCreate.flows['t1'].handleError.called.should.be.true();
- // done();
- // });
- //
- // flows.init({log:mockLog, settings:{},storage:storage});
- // flows.load().then(function() {
- // flows.startFlows();
- // });
- // });
- // it('passes error to flows that use the originating global config', function(done) {
- // var originalConfig = [
- // {id:"configNode",type:"test"},
- // {id:"t1",type:"tab"},
- // {id:"t1-1",x:10,y:10,z:"t1",type:"test",config:"configNode",wires:[]},
- // {id:"t2",type:"tab"},
- // {id:"t2-1",x:10,y:10,z:"t2",type:"test",wires:[]},
- // {id:"t3",type:"tab"},
- // {id:"t3-1",x:10,y:10,z:"t3",type:"test",config:"configNode",wires:[]}
- // ];
- // storage.getFlows = function() {
- // return Promise.resolve({flows:originalConfig});
- // }
- //
- // events.once('flows:started',function() {
- // flows.handleError(originalConfig[0],"message",{});
- // try {
- // flowCreate.flows['t1'].handleError.called.should.be.true();
- // flowCreate.flows['t2'].handleError.called.should.be.false();
- // flowCreate.flows['t3'].handleError.called.should.be.true();
- // done();
- // } catch(err) {
- // done(err);
- // }
- // });
- //
- // flows.init({log:mockLog, settings:{},storage:storage});
- // flows.load().then(function() {
- // flows.startFlows();
- // });
- // });
- // });
- // describe('#handleStatus', function() {
- // it('passes status to correct flow', function(done) {
- // var originalConfig = [
- // {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- // {id:"t1",type:"tab"}
- // ];
- // storage.getFlows = function() {
- // return Promise.resolve({flows:originalConfig});
- // }
- //
- // events.once('flows:started',function() {
- // flows.handleStatus(originalConfig[0],"message");
- // flowCreate.flows['t1'].handleStatus.called.should.be.true();
- // done();
- // });
- //
- // flows.init({log:mockLog, settings:{},storage:storage});
- // flows.load().then(function() {
- // flows.startFlows();
- // });
- // });
- //
- // it('passes status to flows that use the originating global config', function(done) {
- // var originalConfig = [
- // {id:"configNode",type:"test"},
- // {id:"t1",type:"tab"},
- // {id:"t1-1",x:10,y:10,z:"t1",type:"test",config:"configNode",wires:[]},
- // {id:"t2",type:"tab"},
- // {id:"t2-1",x:10,y:10,z:"t2",type:"test",wires:[]},
- // {id:"t3",type:"tab"},
- // {id:"t3-1",x:10,y:10,z:"t3",type:"test",config:"configNode",wires:[]}
- // ];
- // storage.getFlows = function() {
- // return Promise.resolve({flows:originalConfig});
- // }
- //
- // events.once('flows:started',function() {
- // flows.handleStatus(originalConfig[0],"message");
- // try {
- // flowCreate.flows['t1'].handleStatus.called.should.be.true();
- // flowCreate.flows['t2'].handleStatus.called.should.be.false();
- // flowCreate.flows['t3'].handleStatus.called.should.be.true();
- // done();
- // } catch(err) {
- // done(err);
- // }
- // });
- //
- // flows.init({log:mockLog, settings:{},storage:storage});
- // flows.load().then(function() {
- // flows.startFlows();
- // });
- // });
- // });
-
- describe('#checkTypeInUse', function() {
-
- before(function() {
- sinon.stub(typeRegistry,"getNodeInfo").callsFake(function(id) {
- if (id === 'unused-module') {
- return {types:['one','two','three']}
- } else {
- return {types:['one','test','three']}
- }
- });
- });
-
- after(function() {
- typeRegistry.getNodeInfo.restore();
- });
-
- it('returns cleanly if type not is use', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.setFlows(originalConfig).then(function() {
- flows.checkTypeInUse("unused-module");
- done();
- });
- });
- it('throws error if type is in use', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.setFlows(originalConfig).then(function() {
- /*jshint immed: false */
- try {
- flows.checkTypeInUse("used-module");
- done("type_in_use error not thrown");
- } catch(err) {
- err.code.should.eql("type_in_use");
- done();
- }
- });
- });
- });
-
- describe('#addFlow', function() {
- it("rejects duplicate node id",function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- storage.getFlows = function() {
- return Promise.resolve({flows:originalConfig});
- }
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.load().then(function() {
- flows.addFlow({
- label:'new flow',
- nodes:[
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]}
- ]
- }).then(function() {
- done(new Error('failed to reject duplicate node id'));
- }).catch(function(err) {
- done();
- })
- });
-
- });
-
- it("addFlow",function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- storage.getFlows = function() {
- return Promise.resolve({flows:originalConfig});
- }
- storage.setFlows = function() {
- return Promise.resolve();
- }
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.load().then(function() {
- return flows.startFlows();
- }).then(function() {
- flows.addFlow({
- label:'new flow',
- nodes:[
- {id:"t2-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t2-2",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t2-3",z:"t1",type:"test"}
- ]
- }).then(function(id) {
- flows.getFlows().flows.should.have.lengthOf(6);
- var createdFlows = Object.keys(flowCreate.flows);
- createdFlows.should.have.lengthOf(3);
- createdFlows[2].should.eql(id);
- done();
- }).catch(function(err) {
- done(err);
- })
- });
-
- });
- })
- describe('#updateFlow', function() {
- it.skip("updateFlow");
- })
- describe('#removeFlow', function() {
- it.skip("removeFlow");
- })
- describe('#disableFlow', function() {
- it.skip("disableFlow");
- })
- describe('#enableFlow', function() {
- it.skip("enableFlow");
- })
-});
diff --git a/test/unit/@node-red/runtime/lib/flows/util_spec.js b/test/unit/@node-red/runtime/lib/flows/util_spec.js
deleted file mode 100644
index 6a4571e87..000000000
--- a/test/unit/@node-red/runtime/lib/flows/util_spec.js
+++ /dev/null
@@ -1,801 +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 clone = require("clone");
-var NR_TEST_UTILS = require("nr-test-utils");
-var flowUtil = NR_TEST_UTILS.require("@node-red/runtime/lib/flows/util");
-var typeRegistry = NR_TEST_UTILS.require("@node-red/registry");
-var redUtil = NR_TEST_UTILS.require("@node-red/util").util;
-
-describe('flows/util', function() {
- var getType;
-
- before(function() {
- getType = sinon.stub(typeRegistry,"get").callsFake(function(type) {
- return type!=='missing';
- });
- });
- after(function() {
- getType.restore();
- });
-
- describe('#mapEnvVarProperties',function() {
- before(function() {
- process.env.foo1 = "bar1";
- process.env.foo2 = "bar2";
- process.env.foo3 = "bar3";
- })
- after(function() {
- delete process.env.foo1;
- delete process.env.foo2;
- delete process.env.foo3;
- })
- it('handles ENV substitutions in an object - $()', function() {
- var foo = {a:"$(foo1)",b:"$(foo2)",c:{d:"$(foo3)"}};
- for (var p in foo) {
- if (foo.hasOwnProperty(p)) {
- flowUtil.mapEnvVarProperties(foo,p,{getSetting: p => process.env[p]});
- }
- }
- foo.should.eql({ a: 'bar1', b: 'bar2', c: { d: 'bar3' } } );
- });
- it('handles ENV substitutions in an object - ${}', function() {
- var foo = {a:"${foo1}",b:"${foo2}",c:{d:"${foo3}"}};
- for (var p in foo) {
- if (foo.hasOwnProperty(p)) {
- flowUtil.mapEnvVarProperties(foo,p,{getSetting: p => process.env[p]});
- }
- }
- foo.should.eql({ a: 'bar1', b: 'bar2', c: { d: 'bar3' } } );
- });
-
- it('gets ENV from parent flow', function() {
- var foo = {a:"$(unknown)",b:"$(foo2)",c:{d:"$(foo3)"}};
- for (var p in foo) {
- if (foo.hasOwnProperty(p)) {
- flowUtil.mapEnvVarProperties(foo,p,{
- getSetting: name => name[0]==='f'?name.toUpperCase():undefined
- });
- }
- }
- foo.should.eql({ a: '$(unknown)', b: 'FOO2', c: { d: 'FOO3' } } );
- });
- });
- describe('#getEnvVar',function() {
- before(function() {
- process.env.foo1 = "bar1";
- })
- after(function() {
- delete process.env.foo1;
- })
- it('returns a known env var', function() {
- flowUtil.init({settings:{}});
- flowUtil.getEnvVar("foo1").should.equal("bar1")
- })
- it('returns undefined for an unknown env var', function() {
- flowUtil.init({settings:{}});
- (flowUtil.getEnvVar("foo2") === undefined).should.be.true()
- })
- it('returns undefined for an excluded env var', function() {
- flowUtil.init({settings:{envVarExcludes:['foo1']}});
- (flowUtil.getEnvVar("foo1") === undefined).should.be.true()
- })
-
- });
-
- describe('#diffNodes',function() {
- it('handles a null old node', function() {
- flowUtil.diffNodes(null,{}).should.be.true();
- });
- it('ignores x/y changes', function() {
- flowUtil.diffNodes({x:10,y:10},{x:20,y:10}).should.be.false();
- flowUtil.diffNodes({x:10,y:10},{x:10,y:20}).should.be.false();
- });
- it('ignores wiring changes', function() {
- flowUtil.diffNodes({wires:[]},{wires:[1,2,3]}).should.be.false();
- });
- it('spots existing property change - string', function() {
- flowUtil.diffNodes({a:"foo"},{a:"bar"}).should.be.true();
- });
- it('spots existing property change - number', function() {
- flowUtil.diffNodes({a:0},{a:1}).should.be.true();
- });
- it('spots existing property change - boolean', function() {
- flowUtil.diffNodes({a:true},{a:false}).should.be.true();
- });
- it('spots existing property change - truthy', function() {
- flowUtil.diffNodes({a:true},{a:1}).should.be.true();
- });
- it('spots existing property change - falsey', function() {
- flowUtil.diffNodes({a:false},{a:0}).should.be.true();
- });
- it('spots existing property change - array', function() {
- flowUtil.diffNodes({a:[0,1,2]},{a:[0,2,3]}).should.be.true();
- });
- it('spots existing property change - object', function() {
- flowUtil.diffNodes({a:{a:[0,1,2]}},{a:{a:[0,2,3]}}).should.be.true();
- flowUtil.diffNodes({a:{a:[0,1,2]}},{a:{b:[0,1,2]}}).should.be.true();
- });
- it('spots added property', function() {
- flowUtil.diffNodes({a:"foo"},{a:"foo",b:"bar"}).should.be.true();
- });
- it('spots removed property', function() {
- flowUtil.diffNodes({a:"foo",b:"bar"},{a:"foo"}).should.be.true();
- });
-
-
- });
-
- describe('#parseConfig',function() {
-
- it('parses a single-tab flow', function() {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- var parsedConfig = flowUtil.parseConfig(originalConfig);
- var expectedConfig = {"allNodes":{"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"test","wires":[]},"t1":{"id":"t1","type":"tab"}},"subflows":{},"configs":{},"flows":{"t1":{"id":"t1","type":"tab","subflows":{},"configs":{},"nodes":{"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"test","wires":[]}}}},"groups":{},"missingTypes":[]};
- parsedConfig.should.eql(expectedConfig);
- });
-
- it('parses a single-tab flow with global config node', function() {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",foo:"cn", wires:[]},
- {id:"cn",type:"test"},
- {id:"t1",type:"tab"}
- ];
- var parsedConfig = flowUtil.parseConfig(originalConfig);
- var expectedConfig = {"allNodes":{"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"test","foo":"cn","wires":[]},"cn":{"id":"cn","type":"test"},"t1":{"id":"t1","type":"tab"}},"subflows":{},"configs":{"cn":{"id":"cn","type":"test","_users":["t1-1"]}},"flows":{"t1":{"id":"t1","type":"tab","subflows":{},"configs":{},"nodes":{"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"test","foo":"cn","wires":[]}}}},"groups":{},"missingTypes":[]};
- parsedConfig.should.eql(expectedConfig);
- });
-
- it('parses a multi-tab flow', function() {
- var originalConfig = [
- {id:"t1",type:"tab"},
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t2",type:"tab"},
- {id:"t2-1",x:10,y:10,z:"t2",type:"test",wires:[]}
- ];
- var parsedConfig = flowUtil.parseConfig(originalConfig);
- var expectedConfig = {"allNodes":{"t1":{"id":"t1","type":"tab"},"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"test","wires":[]},"t2":{"id":"t2","type":"tab"},"t2-1":{"id":"t2-1","x":10,"y":10,"z":"t2","type":"test","wires":[]}},"subflows":{},"configs":{},"flows":{"t1":{"id":"t1","type":"tab","subflows":{},"configs":{},"nodes":{"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"test","wires":[]}}},"t2":{"id":"t2","type":"tab","subflows":{},"configs":{},"nodes":{"t2-1":{"id":"t2-1","x":10,"y":10,"z":"t2","type":"test","wires":[]}}}},"groups":{},"missingTypes":[]};
- parsedConfig.should.eql(expectedConfig);
- });
-
- it('parses a subflow flow', function() {
- var originalConfig = [
- {id:"t1",type:"tab"},
- {id:"t1-1",x:10,y:10,z:"t1",type:"subflow:sf1",wires:[]},
- {id:"sf1",type:"subflow"},
- {id:"sf1-1",x:10,y:10,z:"sf1",type:"test",wires:[]}
- ];
- var parsedConfig = flowUtil.parseConfig(originalConfig);
- var expectedConfig = {"allNodes":{"t1":{"id":"t1","type":"tab"},"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"subflow:sf1","wires":[]},"sf1":{"id":"sf1","type":"subflow"},"sf1-1":{"id":"sf1-1","x":10,"y":10,"z":"sf1","type":"test","wires":[]}},"subflows":{"sf1":{"id":"sf1","type":"subflow","configs":{},"nodes":{"sf1-1":{"id":"sf1-1","x":10,"y":10,"z":"sf1","type":"test","wires":[]}},"instances":[{"id":"t1-1","x":10,"y":10,"z":"t1","type":"subflow:sf1","wires":[],"subflow":"sf1"}]}},"configs":{},"flows":{"t1":{"id":"t1","type":"tab","subflows":{},"configs":{},"nodes":{"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"subflow:sf1","wires":[],"subflow":"sf1"}}}},"groups":{},"missingTypes":[]};
- parsedConfig.should.eql(expectedConfig);
- });
-
- it('parses a flow with a missing type', function() {
- var originalConfig = [
- {id:"t1",type:"tab"},
- {id:"t1-1",x:10,y:10,z:"t1",type:"sf1",wires:[]},
- {id:"t1-2",x:10,y:10,z:"t1",type:"missing",wires:[]},
- ];
- var parsedConfig = flowUtil.parseConfig(originalConfig);
- parsedConfig.missingTypes.should.eql(['missing']);
- var expectedConfig = {"allNodes":{"t1":{"id":"t1","type":"tab"},"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"sf1","wires":[]},"t1-2":{"id":"t1-2","x":10,"y":10,"z":"t1","type":"missing","wires":[]}},"subflows":{},"configs":{},"flows":{"t1":{"id":"t1","type":"tab","subflows":{},"configs":{},"nodes":{"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"sf1","wires":[]},'t1-2': { id: 't1-2', x: 10, y: 10, z: 't1', type: 'missing', wires: [] }}}},"groups":{},"missingTypes":["missing"]};
- redUtil.compareObjects(parsedConfig,expectedConfig).should.be.true();
- });
-
- it('parses a flow with a missing flow', function() {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",foo:"cn", wires:[]},
- {id:"cn",type:"test"},
- ];
- var parsedConfig = flowUtil.parseConfig(originalConfig);
- var expectedConfig = {"allNodes":{"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"test","foo":"cn","wires":[]},"cn":{"id":"cn","type":"test"}},"subflows":{},"configs":{"cn":{"id":"cn","type":"test","_users":["t1-1"]}},"flows":{"t1":{"id":"t1","type":"tab","subflows":{},"configs":{},"nodes":{"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"test","foo":"cn","wires":[]}}}},"groups":{},"missingTypes":[]};
- parsedConfig.should.eql(expectedConfig);
- });
-
- it('parses a flow including a group', function() {
- var originalConfig = [
- {id:"t1",type:"tab"},
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"g1",type:"group",z:"t1"}
- ];
- var parsedConfig = flowUtil.parseConfig(originalConfig);
- var expectedConfig = {"allNodes":{"t1":{"id":"t1","type":"tab"},"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"test","wires":[]},"g1":{"id":"g1","type":"group","z":"t1"}},"subflows":{},"configs":{},"flows":{"t1":{"id":"t1","type":"tab","subflows":{},"configs":{},"nodes":{"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"test","wires":[]}}}},"groups":{"g1":{"id":"g1","type":"group","z":"t1"}},"missingTypes":[]}
- parsedConfig.should.eql(expectedConfig);
- });
-
- });
-
- describe('#diffConfigs', function() {
-
- it('handles an identical configuration', function() {
- var config = [{id:"123",type:"test",foo:"a",wires:[]}];
-
- var originalConfig = flowUtil.parseConfig(clone(config));
- var changedConfig = flowUtil.parseConfig(clone(config));
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
-
- diffResult.added.should.have.length(0);
- diffResult.changed.should.have.length(0);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.should.have.length(0);
- });
-
- it('identifies nodes with changed properties, including downstream linked', function() {
- var config = [{id:"1",type:"test",foo:"a",wires:[]},{id:"2",type:"test",bar:"b",wires:[[1]]},{id:"3",type:"test",foo:"a",wires:[]}];
- var newConfig = clone(config);
- newConfig[0].foo = "b";
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.should.eql(["1"]);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.should.eql(["2"]);
-
- });
- it('identifies nodes with changed properties, including upstream linked', function() {
- var config = [{id:"1",type:"test",foo:"a",wires:[]},{id:"2",type:"test",bar:"b",wires:[["1"]]},{id:"3",type:"test",foo:"a",wires:[]}];
- var newConfig = clone(config);
- newConfig[1].bar = "c";
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.should.eql(["2"]);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.should.eql(["1"]);
- });
-
- it('identifies nodes with changed credentials, including downstream linked', function() {
- var config = [{id:"1",type:"test",wires:[]},{id:"2",type:"test",bar:"b",wires:[["1"]]},{id:"3",type:"test",foo:"a",wires:[]}];
- var newConfig = clone(config);
- newConfig[0].credentials = {};
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.should.eql(["1"]);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.should.eql(["2"]);
- });
-
- it('identifies nodes with changed wiring', function() {
- var config = [{id:"1",type:"test",foo:"a",wires:[]},{id:"2",type:"test",bar:"b",wires:[["1"]]},{id:"3",type:"test",foo:"a",wires:[]}];
- var newConfig = clone(config);
- newConfig[1].wires[0][0] = "3";
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.should.have.length(0);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.eql(["2"]);
- diffResult.linked.sort().should.eql(["1","3"]);
- });
-
- it('identifies nodes with changed wiring - second connection added', function() {
- var config = [{id:"1",type:"test",foo:"a",wires:[]},{id:"2",type:"test",bar:"b",wires:[["1"]]},{id:"3",type:"test",foo:"a",wires:[]}];
- var newConfig = clone(config);
- newConfig[1].wires[0].push("1");
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.should.have.length(0);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.eql(["2"]);
- diffResult.linked.sort().should.eql(["1"]);
- });
-
- it('identifies nodes with changed wiring - node connected', function() {
- var config = [{id:"1",type:"test",foo:"a",wires:[["2"]]},{id:"2",type:"test",bar:"b",wires:[[]]},{id:"3",type:"test",foo:"a",wires:[]}];
- var newConfig = clone(config);
- newConfig[1].wires.push("3");
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.should.have.length(0);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.eql(["2"]);
- diffResult.linked.sort().should.eql(["1","3"]);
- });
-
- it('identifies new nodes', function() {
- var config = [{id:"1",type:"test",foo:"a",wires:[]},{id:"3",type:"test",foo:"a",wires:[]}];
- var newConfig = clone(config);
- newConfig.push({id:"2",type:"test",bar:"b",wires:[["1"]]});
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.eql(["2"]);
- diffResult.changed.should.have.length(0);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["1"]);
- });
-
- it('identifies deleted nodes', function() {
- var config = [{id:"1",type:"test",foo:"a",wires:[["2"]]},{id:"2",type:"test",bar:"b",wires:[["3"]]},{id:"3",type:"test",foo:"a",wires:[]}];
- var newConfig = clone(config);
- newConfig.splice(1,1);
- newConfig[0].wires = [];
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.should.have.length(0);
- diffResult.removed.should.eql(["2"]);
- diffResult.rewired.should.eql(["1"]);
- diffResult.linked.sort().should.eql(["3"]);
- });
-
- it('identifies config nodes changes, node->config', function() {
- var config = [
- {id:"1",type:"test",foo:"configNode",wires:[["2"]]},
- {id:"2",type:"test",bar:"b",wires:[["3"]]},
- {id:"3",type:"test",foo:"a",wires:[]},
- {id:"configNode",type:"testConfig"}
- ];
- var newConfig = clone(config);
- newConfig[3].foo = "bar";
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.sort().should.eql(["1","configNode"]);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["2","3"]);
- });
-
- it('identifies config nodes changes, node->config->config', function() {
- var config = [
- {id:"1",type:"test",foo:"configNode1",wires:[["2"]]},
- {id:"2",type:"test",bar:"b",wires:[["3"]]},
- {id:"3",type:"test",foo:"a",wires:[]},
- {id:"configNode1",foo:"configNode2",type:"testConfig"},
- {id:"configNode2",type:"testConfig"}
- ];
- var newConfig = clone(config);
- newConfig[4].foo = "bar";
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.sort().should.eql(["1","configNode1","configNode2"]);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["2","3"]);
- });
-
- it('marks a parent subflow as changed for an internal property change', function() {
- var config = [
- {id:"1",type:"test",wires:[["2"]]},
- {id:"2",type:"subflow:sf1",wires:[["3"]]},
- {id:"3",type:"test",wires:[]},
- {id:"sf1",type:"subflow"},
- {id:"sf1-1",z:"sf1",type:"test",foo:"a",wires:[]},
- {id:"4",type:"subflow:sf1",wires:[]}
- ];
-
- var newConfig = clone(config);
- newConfig[4].foo = "b";
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.sort().should.eql(['2', '4', 'sf1']);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["1","3"]);
-
-
- });
-
- it('marks a parent subflow as changed for an internal wiring change', function() {
- var config = [
- {id:"1",type:"test",wires:[["2"]]},
- {id:"2",type:"subflow:sf1",wires:[["3"]]},
- {id:"3",type:"test",wires:[]},
- {id:"sf1",type:"subflow"},
- {id:"sf1-1",z:"sf1",type:"test",wires:[]},
- {id:"sf1-2",z:"sf1",type:"test",wires:[]}
- ];
-
- var newConfig = clone(config);
- newConfig[4].wires = [["sf1-2"]];
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.sort().should.eql(['2', 'sf1']);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["1","3"]);
- });
-
- it('marks a parent subflow as changed for an internal node add', function() {
- var config = [
- {id:"1",type:"test",wires:[["2"]]},
- {id:"2",type:"subflow:sf1",wires:[["3"]]},
- {id:"3",type:"test",wires:[]},
- {id:"sf1",type:"subflow"},
- {id:"sf1-1",z:"sf1",type:"test",wires:[]},
- {id:"sf1-2",z:"sf1",type:"test",wires:[]}
- ];
-
- var newConfig = clone(config);
- newConfig.push({id:"sf1-3",z:"sf1",type:"test",wires:[]});
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.sort().should.eql(['2', 'sf1']);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["1","3"]);
-
- });
-
- it('marks a parent subflow as changed for an internal node delete', function() {
- var config = [
- {id:"1",type:"test",wires:[["2"]]},
- {id:"2",type:"subflow:sf1",wires:[["3"]]},
- {id:"3",type:"test",wires:[]},
- {id:"sf1",type:"subflow"},
- {id:"sf1-1",z:"sf1",type:"test",wires:[]},
- {id:"sf1-2",z:"sf1",type:"test",wires:[]}
- ];
-
- var newConfig = clone(config);
- newConfig.splice(5,1);
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.sort().should.eql(['2', 'sf1']);
- diffResult.removed.should.have.length(1);
- diffResult.removed.sort().should.eql(['sf1-2']);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["1","3"]);
-
- });
-
- it('marks a parent subflow as changed for an internal subflow wiring change - input removed', function() {
- var config = [
- {id:"1",type:"test",wires:[["2"]]},
- {id:"2",type:"subflow:sf1",wires:[["3"]]},
- {id:"3",type:"test",wires:[]},
- {id:"sf1",type:"subflow","in": [{"wires": [{"id": "sf1-1"}]}],"out": [{"wires": [{"id": "sf1-2","port": 0}]}]},
- {id:"sf1-1",z:"sf1",type:"test",wires:[]},
- {id:"sf1-2",z:"sf1",type:"test",wires:[]}
- ];
-
- var newConfig = clone(config);
- newConfig[3].in[0].wires = [];
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.sort().should.eql(['2', 'sf1']);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["1","3"]);
- });
-
- it('marks a parent subflow as changed for an internal subflow wiring change - input added', function() {
- var config = [
- {id:"1",type:"test",wires:[["2"]]},
- {id:"2",type:"subflow:sf1",wires:[["3"]]},
- {id:"3",type:"test",wires:[]},
- {id:"sf1",type:"subflow","in": [{"wires": [{"id": "sf1-1"}]}],"out": [{"wires": [{"id": "sf1-2","port": 0}]}]},
- {id:"sf1-1",z:"sf1",type:"test",wires:[]},
- {id:"sf1-2",z:"sf1",type:"test",wires:[]}
- ];
-
- var newConfig = clone(config);
- newConfig[3].in[0].wires.push({"id":"sf1-2"});
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.sort().should.eql(['2', 'sf1']);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["1","3"]);
- });
-
- it('marks a parent subflow as changed for an internal subflow wiring change - output added', function() {
- var config = [
- {id:"1",type:"test",wires:[["2"]]},
- {id:"2",type:"subflow:sf1",wires:[["3"]]},
- {id:"3",type:"test",wires:[]},
- {id:"sf1",type:"subflow","in": [{"wires": [{"id": "sf1-1"}]}],"out": [{"wires": [{"id": "sf1-2","port": 0}]}]},
- {id:"sf1-1",z:"sf1",type:"test",wires:[]},
- {id:"sf1-2",z:"sf1",type:"test",wires:[]}
- ];
-
- var newConfig = clone(config);
- newConfig[3].out[0].wires.push({"id":"sf1-2","port":0});
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.sort().should.eql(['2', 'sf1']);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["1","3"]);
- });
-
- it('marks a parent subflow as changed for an internal subflow wiring change - output removed', function() {
- var config = [
- {id:"1",type:"test",wires:[["2"]]},
- {id:"2",type:"subflow:sf1",wires:[["3"]]},
- {id:"3",type:"test",wires:[]},
- {id:"sf1",type:"subflow","in": [{"wires": [{"id": "sf1-1"}]}],"out": [{"wires": [{"id": "sf1-2","port": 0}]}]},
- {id:"sf1-1",z:"sf1",type:"test",wires:[]},
- {id:"sf1-2",z:"sf1",type:"test",wires:[]}
- ];
-
- var newConfig = clone(config);
- newConfig[3].out[0].wires = [];
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.sort().should.eql(['2', 'sf1']);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["1","3"]);
- });
-
- it('marks a parent subflow as changed for a global config node change', function() {
- var config = [
- {id:"1",type:"test",wires:[["2"]]},
- {id:"2",type:"subflow:sf1",wires:[["3"]]},
- {id:"3",type:"test",wires:[]},
- {id:"sf1",type:"subflow"},
- {id:"sf1-1",z:"sf1",prop:"configNode",type:"test",wires:[]},
- {id:"sf1-2",z:"sf1",type:"test",wires:[]},
- {id:"configNode",a:"foo",type:"test",wires:[]}
- ];
-
- var newConfig = clone(config);
- newConfig[6].a = "bar";
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.sort().should.eql(['2', "configNode", 'sf1']);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["1","3"]);
- });
-
- it('marks a parent subflow as changed for an internal subflow instance change', function() {
- var config = [
- {id:"1",type:"test",wires:[["2"]]},
- {id:"2",type:"subflow:sf1",wires:[["3"]]},
- {id:"3",type:"test",wires:[]},
- {id:"sf1",type:"subflow"},
- {id:"sf2",type:"subflow"},
- {id:"sf1-1",z:"sf1",type:"test",wires:[]},
- {id:"sf1-2",z:"sf1",type:"subflow:sf2",wires:[]},
- {id:"sf2-1",z:"sf2",type:"test",wires:[]},
- {id:"sf2-2",z:"sf2",type:"test",wires:[]},
- ];
-
- var newConfig = clone(config);
- newConfig[8].a = "bar";
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.sort().should.eql(['2', 'sf1', 'sf2']);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["1","3"]);
- });
-
-
- it('ignores tab changes that are immaterial', function() {
- var config = [{id:"1",type:"tab",label:"fred"},{id:"2",type:"test",bar:"b",wires:[["1"]],z:"1"}];
- var newConfig = clone(config);
- newConfig[0].label = "barney";
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.should.have.length(0);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- });
-
-
- it('marks a deleted tab as removed', function() {
- var config = [{id:"f1",type:"tab",label:"fred"},{id:"n1",type:"test",bar:"b",wires:[["1"]],z:"f1"},
- {id:"f2",type:"tab",label:"fred"},{id:"n2",type:"test",bar:"b",wires:[["1"]],z:"f2"}];
- var newConfig = clone(config);
- newConfig = newConfig.slice(0,2);
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.should.have.length(0);
- diffResult.removed.sort().should.eql(['f2', 'n2']);
- diffResult.rewired.should.have.length(0);
- });
-
- it('marks all nodes as added when tab state changes disabled to enabled', function() {
- var config = [{id:"1",type:"tab",disabled:true,label:"fred"},{id:"2",type:"test",bar:"b",wires:[["1"]],z:"1"},{id:"3",type:"test"}];
- var newConfig = clone(config);
- newConfig[0].disabled = false;
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
-
- diffResult.added.should.have.length(2);
- diffResult.added.sort().should.eql(["1","2"]);
- diffResult.changed.should.have.length(0);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- });
- it('marks all nodes as removed when tab state changes enabled to disabled', function() {
- var config = [{id:"1",type:"tab",disabled:false,label:"fred"},{id:"2",type:"test",bar:"b",wires:[["1"]],z:"1"},{id:"3",type:"test"}];
- var newConfig = clone(config);
- newConfig[0].disabled = true;
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
-
- diffResult.added.should.have.length(0);
- diffResult.changed.should.have.length(0);
- diffResult.removed.should.have.length(2);
- diffResult.removed.sort().should.eql(["1","2"]);
- diffResult.rewired.should.have.length(0);
- });
-
- it('marks a node as removed when its state changes enabled to disabled', function() {
- var config = [{id:"1",type:"tab",disabled:false,label:"fred"},{id:"2",type:"test",bar:"b",wires:[["1"]],z:"1"},{id:"3",type:"test"}];
- var newConfig = clone(config);
- newConfig[1].d = true;
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
-
- diffResult.added.should.have.length(0);
- diffResult.changed.should.have.length(2);
- diffResult.changed.sort().should.eql(["1","2"]);
- diffResult.removed.should.have.length(1);
- diffResult.removed.sort().should.eql(["2"]);
- diffResult.rewired.should.have.length(0);
- });
-
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/index_spec.js b/test/unit/@node-red/runtime/lib/index_spec.js
deleted file mode 100644
index 9041ba66e..000000000
--- a/test/unit/@node-red/runtime/lib/index_spec.js
+++ /dev/null
@@ -1,250 +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 api = NR_TEST_UTILS.require("@node-red/runtime/lib/api");
-var runtime = NR_TEST_UTILS.require("@node-red/runtime");
-
-var redNodes = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes");
-var storage = NR_TEST_UTILS.require("@node-red/runtime/lib/storage");
-var settings = NR_TEST_UTILS.require("@node-red/runtime/lib/settings");
-var util = NR_TEST_UTILS.require("@node-red/util");
-
-var log = NR_TEST_UTILS.require("@node-red/util").log;
-var i18n = NR_TEST_UTILS.require("@node-red/util").i18n;
-
-describe("runtime", function() {
- afterEach(function() {
- if (console.log.restore) {
- console.log.restore();
- }
- })
-
- before(function() {
- process.env.NODE_RED_HOME = NR_TEST_UTILS.resolve("node-red");
- });
- after(function() {
- delete process.env.NODE_RED_HOME;
- });
- function mockUtil(metrics) {
- sinon.stub(log,"log").callsFake(function(){})
- sinon.stub(log,"warn").callsFake(function(){})
- sinon.stub(log,"info").callsFake(function(){})
- sinon.stub(log,"trace").callsFake(function(){})
- sinon.stub(log,"metric").callsFake(function(){ return !!metrics })
- sinon.stub(log,"_").callsFake(function(){ return "abc"})
- sinon.stub(i18n,"registerMessageCatalog").callsFake(function(){ return Promise.resolve()})
- }
- function unmockUtil() {
- log.log.restore && log.log.restore();
- log.warn.restore && log.warn.restore();
- log.info.restore && log.info.restore();
- log.trace.restore && log.trace.restore();
- log.metric.restore && log.metric.restore();
- log._.restore && log._.restore();
- i18n.registerMessageCatalog.restore && i18n.registerMessageCatalog.restore();
- }
- describe("init", function() {
- beforeEach(function() {
- sinon.stub(log,"init").callsFake(function() {});
- sinon.stub(settings,"init").callsFake(function() {});
- sinon.stub(redNodes,"init").callsFake(function() {})
- mockUtil();
- });
- afterEach(function() {
- log.init.restore();
- settings.init.restore();
- redNodes.init.restore();
- unmockUtil();
- })
-
- it("initialises components", function() {
- runtime.init({testSettings: true, httpAdminRoot:"/"});
- settings.init.called.should.be.true();
- redNodes.init.called.should.be.true();
- });
-
- it("returns version", function() {
- runtime.init({testSettings: true, httpAdminRoot:"/"});
- return runtime.version().then(version => {
- /^\d+\.\d+\.\d+(-.*)?$/.test(version).should.be.true();
- });
-
-
- })
- });
-
- describe("start",function() {
- var storageInit;
- var settingsLoad;
- var redNodesInit;
- var redNodesLoad;
- var redNodesCleanModuleList;
- var redNodesGetNodeList;
- var redNodesLoadFlows;
- var redNodesStartFlows;
- var redNodesLoadContextsPlugin;
-
- beforeEach(function() {
- storageInit = sinon.stub(storage,"init").callsFake(function(settings) {return Promise.resolve();});
- redNodesInit = sinon.stub(redNodes,"init").callsFake(function() {});
- redNodesLoad = sinon.stub(redNodes,"load").callsFake(function() {return Promise.resolve()});
- redNodesCleanModuleList = sinon.stub(redNodes,"cleanModuleList").callsFake(function(){});
- redNodesLoadFlows = sinon.stub(redNodes,"loadFlows").callsFake(function() {return Promise.resolve()});
- redNodesStartFlows = sinon.stub(redNodes,"startFlows").callsFake(function() {});
- redNodesLoadContextsPlugin = sinon.stub(redNodes,"loadContextsPlugin").callsFake(function() {return Promise.resolve()});
- mockUtil();
- });
- afterEach(function() {
- storageInit.restore();
- redNodesInit.restore();
- redNodesLoad.restore();
- redNodesGetNodeList.restore();
- redNodesCleanModuleList.restore();
- redNodesLoadFlows.restore();
- redNodesStartFlows.restore();
- redNodesLoadContextsPlugin.restore();
- unmockUtil();
- });
- it("reports errored/missing modules",function(done) {
- redNodesGetNodeList = sinon.stub(redNodes,"getNodeList").callsFake(function(cb) {
- return [
- { err:"errored",name:"errName" }, // error
- { module:"module",enabled:true,loaded:false,types:["typeA","typeB"]} // missing
- ].filter(cb);
- });
- runtime.init({testSettings: true, httpAdminRoot:"/", load:function() { return Promise.resolve();}});
- // sinon.stub(console,"log");
- runtime.start().then(function() {
- // console.log.restore();
- try {
- storageInit.calledOnce.should.be.true();
- redNodesInit.calledOnce.should.be.true();
- redNodesLoad.calledOnce.should.be.true();
- redNodesLoadFlows.calledOnce.should.be.true();
-
- log.warn.calledWithMatch("Failed to register 1 node type");
- log.warn.calledWithMatch("Missing node modules");
- log.warn.calledWithMatch(" - module: typeA, typeB");
- redNodesCleanModuleList.calledOnce.should.be.true();
- done();
- } catch(err) {
- done(err);
- }
- }).catch(err=>{done(err)});
- });
- it("initiates load of missing modules",function(done) {
- redNodesGetNodeList = sinon.stub(redNodes,"getNodeList").callsFake(function(cb) {
- return [
- { err:"errored",name:"errName" }, // error
- { err:"errored",name:"errName" }, // error
- { module:"module",enabled:true,loaded:false,types:["typeA","typeB"]}, // missing
- { module:"node-red",enabled:true,loaded:false,types:["typeC","typeD"]} // missing
- ].filter(cb);
- });
- var serverInstallModule = sinon.stub(redNodes,"installModule").callsFake(function(name) { return Promise.resolve({nodes:[]});});
- runtime.init({testSettings: true, autoInstallModules:true, httpAdminRoot:"/", load:function() { return Promise.resolve();}});
- sinon.stub(console,"log");
- runtime.start().then(function() {
- console.log.restore();
- try {
- log.warn.calledWithMatch("Failed to register 2 node types");
- log.warn.calledWithMatch("Missing node modules");
- log.warn.calledWithMatch(" - module: typeA, typeB");
- log.warn.calledWithMatch(" - node-red: typeC, typeD");
- redNodesCleanModuleList.calledOnce.should.be.false();
- serverInstallModule.calledOnce.should.be.true();
- serverInstallModule.calledWithMatch("module");
- done();
- } catch(err) {
- done(err);
- } finally {
- serverInstallModule.restore();
- }
- }).catch(err=>{done(err)});
- });
- it("reports errored modules when verbose is enabled",function(done) {
- redNodesGetNodeList = sinon.stub(redNodes,"getNodeList").callsFake(function(cb) {
- return [
- { err:"errored",name:"errName" } // error
- ].filter(cb);
- });
- runtime.init({testSettings: true, verbose:true, httpAdminRoot:"/", load:function() { return Promise.resolve();}});
- sinon.stub(console,"log");
- runtime.start().then(function() {
- console.log.restore();
- try {
- log.warn.neverCalledWithMatch("Failed to register 1 node type");
- log.warn.calledWithMatch("[errName] errored");
- done();
- } catch(err) {
- done(err);
- }
- }).catch(err=>{done(err)});
- });
-
- it("reports runtime metrics",function(done) {
- var stopFlows = sinon.stub(redNodes,"stopFlows").callsFake(function() { return Promise.resolve();} );
- redNodesGetNodeList = sinon.stub(redNodes,"getNodeList").callsFake(function() {return []});
- unmockUtil();
- mockUtil(true);
- runtime.init(
- {testSettings: true, runtimeMetricInterval:200, httpAdminRoot:"/", load:function() { return Promise.resolve();}},
- {},
- undefined);
- // sinon.stub(console,"log");
- runtime.start().then(function() {
- // console.log.restore();
- setTimeout(function() {
- try {
- log.log.args.should.have.lengthOf(3);
- log.log.args[0][0].should.have.property("event","runtime.memory.rss");
- log.log.args[1][0].should.have.property("event","runtime.memory.heapTotal");
- log.log.args[2][0].should.have.property("event","runtime.memory.heapUsed");
- done();
- } catch(err) {
- done(err);
- } finally {
- runtime.stop();
- stopFlows.restore();
- }
- },300);
- }).catch(err=>{done(err)});
- });
-
-
- });
-
- it("stops components", function(done) {
- var stopFlows = sinon.stub(redNodes,"stopFlows").callsFake(function() { return Promise.resolve();} );
- var closeContextsPlugin = sinon.stub(redNodes,"closeContextsPlugin").callsFake(function() { return Promise.resolve();} );
- runtime.stop().then(function(){
- stopFlows.called.should.be.true();
- closeContextsPlugin.called.should.be.true();
- stopFlows.restore();
- closeContextsPlugin.restore();
- done();
- }).catch(function(err){
- stopFlows.restore();
- closeContextsPlugin.restore();
- return done(err)
- });
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/library/examples_spec.js b/test/unit/@node-red/runtime/lib/library/examples_spec.js
deleted file mode 100644
index d7f466d83..000000000
--- a/test/unit/@node-red/runtime/lib/library/examples_spec.js
+++ /dev/null
@@ -1,138 +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 fs = require("fs");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-var examplesLibrary = NR_TEST_UTILS.require("@node-red/runtime/lib/library/examples")
-
-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/library/examples", function() {
- describe("getEntry", function() {
- before(function() {
- examplesLibrary.init({
- log: mockLog,
- storage: {
- getLibraryEntry: function(type,path) {
- return Promise.resolve({type,path});
- },
- getFlow: function(path) {
- return Promise.resolve({path});
- }
- },
- nodes: {
- getNodeExampleFlows: function() {
- return {
- "test-module": {
- f: ["abc"]
- },
- "@scope/test-module": {
- f: ["abc","throw"]
- }
-
- }
- },
- getNodeExampleFlowPath: function(module,entryPath) {
- if (module === "unknown") {
- return null;
- }
- return "/tmp/"+module+"/"+entryPath;
- }
- }
- });
- sinon.stub(fs,"readFile").callsFake(function(path,opts,callback) {
- if (path === "/tmp/test-module/abc") {
- callback(null,"Example flow result");
- } else if (path === "/tmp/@scope/test-module/abc") {
- callback(null,"Example scope flow result");
- } else if (path === "/tmp/test-module/throw") {
- throw new Error("Instant error")
- } else {
- callback(new Error("Unexpected path:"+path))
- }
- })
- });
- after(function() {
- fs.readFile.restore();
- })
-
- it ('returns a flow example entry', function(done) {
- examplesLibrary.getEntry("flows","test-module/abc").then(function(result) {
- result.should.eql("Example flow result");
- done();
- }).catch(done);
- });
-
- it ('returns a flow example listing - top level', function(done) {
- examplesLibrary.getEntry("flows","").then(function(result) {
- result.should.eql([ 'test-module', '@scope/test-module' ])
- done();
- }).catch(done);
- });
- it ('returns a flow example listing - in module', function(done) {
- examplesLibrary.getEntry("flows","test-module").then(function(result) {
- result.should.eql([{ fn: 'abc' }])
- done();
- }).catch(done);
- });
- it ('returns a flow example listing - in scoped module', function(done) {
- examplesLibrary.getEntry("flows","@scope/test-module").then(function(result) {
- result.should.eql([{ fn: 'abc' }, {fn: 'throw'}])
- done();
- }).catch(done);
- });
- it ('returns a flow example entry from scoped module', function(done) {
- examplesLibrary.getEntry("flows","@scope/test-module/abc").then(function(result) {
- result.should.eql("Example scope flow result");
- done();
- }).catch(done);
- });
- it ('returns an error for unknown flow example entry', function(done) {
- examplesLibrary.getEntry("flows","unknown/abc").then(function(result) {
- done(new Error("No error thrown"))
- }).catch(function(err) {
- err.should.have.property("code","not_found");
- done();
- });
- });
- it ('returns an error for file load error - async', function(done) {
- examplesLibrary.getEntry("flows","test-module/unknown").then(function(result) {
- done(new Error("No error thrown"))
- }).catch(function(err) {
- done();
- });
- });
- it ('returns an error for file load error - sync', function(done) {
- examplesLibrary.getEntry("flows","test-module/throw").then(function(result) {
- done(new Error("No error thrown"))
- }).catch(function(err) {
- done();
- });
- });
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/library/index_spec.js b/test/unit/@node-red/runtime/lib/library/index_spec.js
deleted file mode 100644
index 2499124c7..000000000
--- a/test/unit/@node-red/runtime/lib/library/index_spec.js
+++ /dev/null
@@ -1,199 +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 library = NR_TEST_UTILS.require("@node-red/runtime/lib/library/index")
-const localLibrary = NR_TEST_UTILS.require("@node-red/runtime/lib/library/local")
-const examplesLibrary = NR_TEST_UTILS.require("@node-red/runtime/lib/library/examples")
-const events = NR_TEST_UTILS.require("@node-red/util/lib/events")
-
-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/library", function() {
- before(function() {
- sinon.stub(localLibrary,"getEntry").callsFake(function(type,path) {
- return Promise.resolve({
- library: "local",
- type:type,
- path:path
- })
- });
- sinon.stub(localLibrary,"saveEntry").callsFake(function(type, path, meta, body) {
- return Promise.resolve({
- library: "local",
- type:type,
- path:path,
- meta:meta,
- body:body
- })
- });
- sinon.stub(examplesLibrary,"getEntry").callsFake(function(type,path) {
- return Promise.resolve({
- library: "_examples_",
- type:type,
- path:path
- })
- });
- });
- after(function() {
- localLibrary.getEntry.restore();
- localLibrary.saveEntry.restore();
- examplesLibrary.getEntry.restore();
- })
- describe("register", function() {
- // it("throws error for duplicate type", function() {
- // library.init({});
- // library.register("unknown","/abc");
- // should(()=>{library.register("unknown","/abc")} ).throw();
- // })
- })
-
- describe("getLibraries", function() {
- before(function() {
- library.init({});
- });
- it('returns the default and examples libraries', function() {
- const libs = library.getLibraries();
- libs.should.have.length(2);
- libs[0].should.have.property('id', 'local');
- libs[0].should.have.property('label','editor:library.types.local');
- libs[0].should.have.property("user", false);
- libs[0].should.have.property('icon', 'font-awesome/fa-hdd-o');
-
- libs[1].should.have.property('id', 'examples');
- libs[1].should.have.property('label','editor:library.types.examples');
- libs[1].should.have.property("user", false);
- libs[1].should.have.property('icon', 'font-awesome/fa-life-ring');
- libs[1].should.have.property('readOnly', true);
- libs[1].should.have.property('types', ['flows']);
- });
-
- it('returns the libraries from settings', function() {
- library.init({
- plugins: {
- getPlugin: id => { return {
- id: "test-library-plugin",
- type: "node-red-library-source",
- class: function() {}
- }
- }
- },
- settings: {
- editorTheme: {
- library: {
- sources: [
- {id: "test-plugin-id", type:"test-library-plugin"}
- ]
- }
- }
- }
- });
- let libs = library.getLibraries();
- libs.should.have.length(2);
-
- events.emit("registry:plugin-added","test-library-plugin" )
-
- libs = library.getLibraries();
- libs.should.have.length(3);
- libs[2].should.have.property('id', 'test-plugin-id');
- libs[2].should.have.property("user", false);
- });
- })
-
- describe("getEntry", function() {
- before(function() {
- library.init({});
- });
- it('throws error for unregistered type', function() {
- should(()=>{library.getEntry("local","unknown","/abc")} ).throw();
- });
- it('throws error for unknown library', function() {
- should(()=>{library.getEntry("unknown","unknown","/abc")} ).throw();
- });
-
- it('returns a registered non-flow entry', function(done) {
- library.register("test-module","test-type");
- library.getEntry("local","test-type","/abc").then(function(result) {
- result.should.have.property("library","local")
- result.should.have.property("type","test-type")
- result.should.have.property("path","/abc")
- done();
- }).catch(done);
- });
-
- it ('returns a flow entry', function(done) {
- library.getEntry("local","flows","/abc").then(function(result) {
- result.should.have.property("library","local")
- result.should.have.property("path","/abc")
- done();
- }).catch(done);
- });
-
- it ('returns a flow example entry', function(done) {
- library.getEntry("examples","flows","/test-module/abc").then(function(result) {
- result.should.have.property("library","_examples_")
- result.should.have.property("path","/test-module/abc")
- done();
- }).catch(done);
- });
- });
-
- describe("saveEntry", function() {
- before(function() {
- library.init({});
- });
- it('throws error for unknown library', function() {
- should(()=>{library.saveEntry("unknown","unknown","/abc",{id:"meta"},{id:"body"})} ).throw();
- });
- it('throws error for unregistered type', function() {
- should(()=>{library.saveEntry("local","unknown","/abc",{id:"meta"},{id:"body"})} ).throw();
- });
- it('throws error for save to readonly library', function() {
- should(()=>{library.saveEntry("_examples_","unknown","/abc",{id:"meta"},{id:"body"})} ).throw();
- });
- it('saves a flow entry', function(done) {
- library.saveEntry('local','flows','/abc',{id:"meta"},{id:"body"}).then(function(result) {
- result.should.have.property("path","/abc");
- result.should.have.property("body",{id:"body"});
- done();
- }).catch(done);
- })
- it('saves a non-flow entry', function(done) {
- library.register("test-module","test-type");
- library.saveEntry('local','test-type','/abc',{id:"meta"},{id:"body"}).then(function(result) {
- result.should.have.property("type","test-type");
- result.should.have.property("path","/abc");
- result.should.have.property("meta",{id:"meta"});
- result.should.have.property("body",{id:"body"});
- done();
- }).catch(done);
- })
-
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/library/local_spec.js b/test/unit/@node-red/runtime/lib/library/local_spec.js
deleted file mode 100644
index 965e5c87a..000000000
--- a/test/unit/@node-red/runtime/lib/library/local_spec.js
+++ /dev/null
@@ -1,93 +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 NR_TEST_UTILS = require("nr-test-utils");
-var localLibrary = NR_TEST_UTILS.require("@node-red/runtime/lib/library/local")
-
-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/library/local", function() {
-
- describe("getEntry", function() {
- before(function() {
- localLibrary.init({
- log: mockLog,
- storage: {
- getLibraryEntry: function(type,path) {
- return Promise.resolve({type,path});
- }
- }
- });
- });
-
- it('returns a registered non-flow entry', function(done) {
- localLibrary.getEntry("test-type","/abc").then(function(result) {
- result.should.have.property("type","test-type")
- result.should.have.property("path","/abc")
- done();
- }).catch(done);
- });
-
- it ('returns a flow entry', function(done) {
- localLibrary.getEntry("flows","/abc").then(function(result) {
- result.should.have.property("path","/abc")
- done();
- }).catch(done);
- });
- });
-
- describe("saveEntry", function() {
- before(function() {
- localLibrary.init({
- log: mockLog,
- storage: {
- saveLibraryEntry: function(type, path, meta, body) {
- return Promise.resolve({type,path,meta,body})
- }
- }
- });
- });
- it('saves a flow entry', function(done) {
- localLibrary.saveEntry('flows','/abc',{id:"meta"},{id:"body"}).then(function(result) {
- result.should.have.property("path","/abc");
- result.should.have.property("body",{id:"body"});
- done();
- }).catch(done);
- })
- it('saves a non-flow entry', function(done) {
- localLibrary.saveEntry('test-type','/abc',{id:"meta"},{id:"body"}).then(function(result) {
- result.should.have.property("type","test-type");
- result.should.have.property("path","/abc");
- result.should.have.property("meta",{id:"meta"});
- result.should.have.property("body",{id:"body"});
- done();
- }).catch(done);
- })
-
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/nodes/Node_spec.js b/test/unit/@node-red/runtime/lib/nodes/Node_spec.js
deleted file mode 100644
index 3fe676f1e..000000000
--- a/test/unit/@node-red/runtime/lib/nodes/Node_spec.js
+++ /dev/null
@@ -1,809 +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 NR_TEST_UTILS = require("nr-test-utils");
-var RedNode = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/Node");
-var Log = NR_TEST_UTILS.require("@node-red/util").log;
-var hooks = NR_TEST_UTILS.require("@node-red/util/lib/hooks");
-var flows = NR_TEST_UTILS.require("@node-red/runtime/lib/flows");
-
-describe('Node', function() {
- describe('#constructor',function() {
- it('is called with an id and a type',function() {
- var n = new RedNode({id:'123',type:'abc'});
- n.should.have.property('id','123');
- n.should.have.property('type','abc');
- n.should.not.have.property('name');
- n.wires.should.be.empty();
- });
-
- it('is called with an id, a type and a name',function() {
- var n = new RedNode({id:'123',type:'abc',name:'barney'});
- n.should.have.property('id','123');
- n.should.have.property('type','abc');
- n.should.have.property('name','barney');
- n.wires.should.be.empty();
- });
-
- it('is called with an id, a type and some wires',function() {
- var n = new RedNode({id:'123',type:'abc',wires:['123','456']});
- n.should.have.property('id','123');
- n.should.have.property('type','abc');
- n.should.not.have.property('name');
- n.wires.should.have.length(2);
- });
-
- });
-
- describe('#close', function() {
- it('emits close event when closed',function(done) {
- var n = new RedNode({id:'123',type:'abc'});
- n.on('close',function() {
- done();
- });
- n.close();
- });
-
- it('returns a promise when provided a callback with a done parameter',function(testdone) {
- var n = new RedNode({id:'123',type:'abc'});
- n.on('close',function(done) {
- setTimeout(function() {
- done();
- },50);
- });
- var p = n.close();
- should.exist(p);
- p.then(function() {
- testdone();
- });
- });
- it('accepts a callback with "removed" and "done" parameters', function(testdone) {
- var n = new RedNode({id:'123',type:'abc'});
- var receivedRemoved;
- n.on('close',function(removed,done) {
- receivedRemoved = removed;
- setTimeout(function() {
- done();
- },50);
- });
- var p = n.close(true);
- should.exist(p);
- (receivedRemoved).should.be.true();
- p.then(function() {
- testdone();
- });
- })
- it('allows multiple close handlers to be registered',function(testdone) {
- var n = new RedNode({id:'123',type:'abc'});
- var callbacksClosed = 0;
- n.on('close',function(done) {
- setTimeout(function() {
- callbacksClosed++;
- done();
- },50);
- });
- n.on('close',function(done) {
- setTimeout(function() {
- callbacksClosed++;
- done();
- },75);
- });
- n.on('close',function() {
- callbacksClosed++;
- });
- var p = n.close();
- should.exist(p);
- p.then(function() {
- callbacksClosed.should.eql(3);
- testdone();
- }).catch(function(e) {
- testdone(e);
- });
- });
- });
-
-
- describe('#receive', function() {
- it('emits input event when called', function(done) {
- var n = new RedNode({id:'123',type:'abc'});
- var message = {payload:"hello world"};
- n.on('input',function(msg) {
- should.deepEqual(msg,message);
- done();
- });
- n.receive(message);
- });
-
- it('writes metric info with undefined msg', function(done){
- var n = new RedNode({id:'123',type:'abc'});
- n.on('input',function(msg) {
- (typeof msg).should.not.be.equal("undefined");
- (typeof msg._msgid).should.not.be.equal("undefined");
- done();
- });
- n.receive();
- });
-
- it('writes metric info with null msg', function(done){
- var n = new RedNode({id:'123',type:'abc'});
- n.on('input',function(msg) {
- (typeof msg).should.not.be.equal("undefined");
- (typeof msg._msgid).should.not.be.equal("undefined");
- done();
- });
- n.receive(null);
- });
-
- it('handles thrown errors', function(done) {
- var n = new RedNode({id:'123',type:'abc'});
- sinon.stub(n,"error").callsFake(function(err,msg) {});
- var message = {payload:"hello world"};
- n.on('input',function(msg) {
- throw new Error("test error");
- });
- n.receive(message);
- setTimeout(function() {
- n.error.called.should.be.true();
- n.error.firstCall.args[1].should.equal(message);
- done();
- },50);
- });
-
- it('calls parent flow handleComplete when callback provided', function(done) {
- var n = new RedNode({id:'123',type:'abc', _flow: {
- handleComplete: function(node,msg) {
- try {
- msg.should.deepEqual(message);
- done();
- } catch(err) {
- done(err);
- }
- }
- }});
-
- var message = {payload:"hello world"};
- n.on('input',function(msg, nodeSend, nodeDone) {
- nodeDone();
- });
- n.receive(message);
- });
-
- it('triggers onComplete hook when done callback provided', function(done) {
- var handleCompleteCalled = false;
- var hookCalled = false;
- var n = new RedNode({id:'123',type:'abc', _flow: {
- handleComplete: function(node,msg) {
- handleCompleteCalled = true;
- }
- }});
- var hookError;
- hooks.add("onComplete",function(completeEvent) {
- hookCalled = true;
- try {
- handleCompleteCalled.should.be.false("onComplete should be called before handleComplete")
- should.not.exist(completeEvent.error);
- completeEvent.msg.should.deepEqual(message);
- completeEvent.node.id.should.eql("123");
- completeEvent.node.node.should.equal(n);
- } catch(err) {
- hookError = err;
- }
- })
- var message = {payload:"hello world"};
- n.on('input',function(msg, nodeSend, nodeDone) {
- nodeDone();
- });
- n.receive(message);
- setTimeout(function() {
- if (hookError) {
- done(hookError);
- return
- }
- try {
- hookCalled.should.be.true("onComplete hook should be called");
- handleCompleteCalled.should.be.true("handleComplete should be called");
- done();
- } catch(err) {
- done(err);
- }
- })
- });
-
- it('triggers onComplete hook when done callback provided - with error', function(done) {
- var handleCompleteCalled = false;
- var hookCalled = false;
- var errorReported = false;
- var n = new RedNode({id:'123',type:'abc', _flow: {
- handleComplete: function(node,msg) {
- handleCompleteCalled = true;
- }
- }});
- var hookError;
- hooks.add("onComplete",function(completeEvent) {
- hookCalled = true;
- try {
- handleCompleteCalled.should.be.false("onComplete should be called before handleComplete")
- should.exist(completeEvent.error);
- completeEvent.error.toString().should.equal("Error: test error")
- completeEvent.msg.should.deepEqual(message);
- completeEvent.node.id.should.eql("123");
- completeEvent.node.node.should.equal(n);
- } catch(err) {
- hookError = err;
- }
- })
- var message = {payload:"hello world"};
- n.on('input',function(msg, nodeSend, nodeDone) {
- nodeDone(new Error("test error"));
- });
- n.error = function(err,msg) {
- errorReported = true;
- }
- n.receive(message);
- setTimeout(function() {
- if (hookError) {
- done(hookError);
- return
- }
- try {
- hookCalled.should.be.true("onComplete hook should be called");
- handleCompleteCalled.should.be.false("handleComplete should not be called");
- done();
- } catch(err) {
- done(err);
- }
- })
- });
- it('logs error if callback provides error', function(done) {
- var n = new RedNode({id:'123',type:'abc'});
- sinon.stub(n,"error").callsFake(function(err,msg) {});
-
- var message = {payload:"hello world"};
- n.on('input',function(msg, nodeSend, nodeDone) {
- nodeDone(new Error("test error"));
- setTimeout(function() {
- try {
- n.error.called.should.be.true();
- n.error.firstCall.args[0].toString().should.equal("Error: test error");
- n.error.firstCall.args[1].should.equal(message);
- done();
- } catch(err) {
- done(err);
- }
- },50);
- });
- n.receive(message);
- });
- it("triggers hooks when receiving a message", function(done) {
- var hookErrors = [];
- var messageReceived = false;
- var hooksCalled = [];
- hooks.add("onReceive", function(receiveEvent) {
- hooksCalled.push("onReceive")
- try {
- messageReceived.should.be.false("Message should not have been received before onReceive")
- receiveEvent.msg.should.be.exactly(message);
- receiveEvent.destination.id.should.equal("123")
- receiveEvent.destination.node.should.equal(n)
- } catch(err) {
- hookErrors.push(err);
- }
- })
- hooks.add("postReceive", function(receiveEvent) {
- hooksCalled.push("postReceive")
- try {
- messageReceived.should.be.true("Message should have been received before postReceive")
- receiveEvent.msg.should.be.exactly(message);
- receiveEvent.destination.id.should.equal("123")
- receiveEvent.destination.node.should.equal(n)
- } catch(err) {
- hookErrors.push(err);
- }
-
- })
- var n = new RedNode({id:'123',type:'abc'});
- var message = {payload:"hello world"};
- n.on('input',function(msg) {
- messageReceived = true;
- try {
- should.strictEqual(this,n);
- hooksCalled.should.eql(["onReceive"])
- should.deepEqual(msg,message);
- } catch(err) {
- hookErrors.push(err)
- }
- });
- n.receive(message);
- setTimeout(function() {
- hooks.clear();
- if (hookErrors.length > 0) {
- done(hookErrors[0])
- } else {
- done();
- }
- },10);
- });
- describe("errors thrown by hooks are reported", function() {
- before(function() {
- hooks.add("onReceive",function(recEvent) {
- if (recEvent.msg.payload === "trigger-onReceive") {
- throw new Error("onReceive Error")
- }
- })
- hooks.add("postReceive",function(recEvent) {
- if (recEvent.msg.payload === "trigger-postReceive") {
- throw new Error("postReceive Error")
- }
- })
- })
- after(function() {
- hooks.clear();
- })
- function testHook(hook, msgExpected, done) {
- var messageReceived = false;
- var errorReceived;
- var n = new RedNode({id:'123',type:'abc'});
- var message = {payload:"trigger-"+hook};
- n.on('input',function(msg) {
- messageReceived = true;
- });
- n.error = function (err) {
- errorReceived = err;
- }
-
- n.receive(message);
-
- setTimeout(function() {
- try {
- messageReceived.should.equal(msgExpected,`Hook ${hook} messageReceived expected ${msgExpected} actual ${messageReceived}`);
- should.exist(errorReceived);
- errorReceived.toString().should.containEql(hook)
- done()
- } catch(err) {
- done(err);
- }
- },10);
- }
- it("onReceive", function(done) { testHook("onReceive", false, done)})
- it("postReceive", function(done) { testHook("postReceive", true, done)})
- })
- });
-
- describe("hooks can halt receive", function() {
- before(function() {
- hooks.add("onReceive",function(recEvent) {
- if (recEvent.msg.payload === "trigger-onReceive") {
- return false;
- }
- })
- })
- after(function() {
- hooks.clear();
- })
-
- function testHook(hook, msgExpected, done) {
- var messageReceived = false;
- var errorReceived;
- var n = new RedNode({id:'123',type:'abc'});
- var message = {payload:"trigger-"+hook};
- n.on('input',function(msg) {
- messageReceived = true;
- });
- n.error = function (err) {
- errorReceived = err;
- }
-
- n.receive(message);
-
- setTimeout(function() {
- try {
- messageReceived.should.equal(msgExpected,`Hook ${hook} messageReceived expected ${msgExpected} actual ${messageReceived}`);
- should.not.exist(errorReceived);
- done()
- } catch(err) {
- done(err);
- }
- },10);
- }
- it("onReceive", function(done) { testHook("onReceive", false, done)})
- })
-
-
- describe('#send', function() {
-
- it('emits a single message', function(done) {
- var flow = {
- send: (sendEvents) => {
- try {
- sendEvents.should.have.length(1);
- sendEvents[0].msg.should.equal(message);
- sendEvents[0].destination.should.eql({id:"n2", node: undefined});
- sendEvents[0].source.should.eql({id:"n1", node: n1, port: 0})
- done();
- } catch(err) {
- done(err);
- }
- },
- };
- var n1 = new RedNode({_flow:flow,id:'n1',type:'abc',wires:[['n2']]});
- var message = {payload:"hello world"};
- n1.send(message);
- });
-
- it('emits a message with callback provided send', function(done) {
- var flow = {
- handleError: (node,logMessage,msg,reportingNode) => {done(logMessage)},
- handleComplete: (node,msg) => {},
- send: (sendEvents) => {
- try {
- sendEvents.should.have.length(1);
- sendEvents[0].msg.should.equal(message);
- sendEvents[0].destination.should.eql({id:"n2", node: undefined});
- sendEvents[0].source.should.eql({id:"n1", node: n1, port: 0});
- sendEvents[0].cloneMessage.should.be.false();
- done();
- } catch(err) {
- done(err);
- }
- },
- };
- var n1 = new RedNode({_flow:flow,id:'n1',type:'abc',wires:[['n2']]});
- var message = {payload:"hello world"};
- n1.on('input',function(msg,nodeSend,nodeDone) {
- nodeSend(msg);
- nodeDone();
- });
- n1.receive(message);
- });
-
- it('emits multiple messages on a single output', function(done) {
- var flow = {
- handleError: (node,logMessage,msg,reportingNode) => {done(logMessage)},
- send: (sendEvents) => {
- try {
- sendEvents.should.have.length(2);
- sendEvents[0].msg.should.equal(messages[0]);
- sendEvents[0].destination.should.eql({id:"n2", node: undefined});
- sendEvents[0].source.should.eql({id:"n1", node: n1, port: 0});
- sendEvents[0].cloneMessage.should.be.false();
-
- sendEvents[1].msg.should.equal(messages[1]);
- sendEvents[1].destination.should.eql({id:"n2", node: undefined});
- sendEvents[1].source.should.eql({id:"n1", node: n1, port: 0});
- sendEvents[1].cloneMessage.should.be.true();
-
- done();
- } catch(err) {
- done(err);
- }
- },
- };
- var n1 = new RedNode({_flow:flow,id:'n1',type:'abc',wires:[['n2']]});
-
- var messages = [
- {payload:"hello world"},
- {payload:"hello world again"}
- ];
-
- n1.send([messages]);
- });
-
- it('emits messages to multiple outputs', function(done) {
- var flow = {
- handleError: (node,logMessage,msg,reportingNode) => {done(logMessage)},
- send: (sendEvents) => {
- try {
- sendEvents.should.have.length(3);
- sendEvents[0].msg.should.equal(messages[0]);
- sendEvents[0].destination.should.eql({id:"n2", node: undefined});
- sendEvents[0].source.should.eql({id:"n1", node: n1, port: 0});
- sendEvents[0].cloneMessage.should.be.false();
- should.exist(sendEvents[0].msg._msgid);
- sendEvents[1].msg.should.equal(messages[2]);
- sendEvents[1].destination.should.eql({id:"n4", node: undefined});
- sendEvents[1].source.should.eql({id:"n1", node: n1, port: 2})
- sendEvents[1].cloneMessage.should.be.true();
- should.exist(sendEvents[1].msg._msgid);
- sendEvents[2].msg.should.equal(messages[2]);
- sendEvents[2].destination.should.eql({id:"n5", node: undefined});
- sendEvents[2].source.should.eql({id:"n1", node: n1, port: 2})
- sendEvents[2].cloneMessage.should.be.true();
- should.exist(sendEvents[2].msg._msgid);
-
- sendEvents[0].msg._msgid.should.eql(sendEvents[1].msg._msgid)
- sendEvents[1].msg._msgid.should.eql(sendEvents[2].msg._msgid)
-
- done();
- } catch(err) {
- done(err);
- }
- }
- };
- var n1 = new RedNode({_flow:flow, id:'n1',type:'abc',wires:[['n2'],['n3'],['n4','n5']]});
- var n2 = new RedNode({_flow:flow, id:'n2',type:'abc'});
- var n3 = new RedNode({_flow:flow, id:'n3',type:'abc'});
- var n4 = new RedNode({_flow:flow, id:'n4',type:'abc'});
- var n5 = new RedNode({_flow:flow, id:'n5',type:'abc'});
- var messages = [
- {payload:"hello world"},
- null,
- {payload:"hello world again"}
- ];
-
- var rcvdCount = 0;
-
- n1.send(messages);
- });
-
- it('emits no messages', function(done) {
- var flow = {
- handleError: (node,logMessage,msg,reportingNode) => {done(logMessage)},
- getNode: (id) => { return {'n1':n1,'n2':n2}[id]},
- };
- var n1 = new RedNode({_flow:flow,id:'n1',type:'abc',wires:[['n2']]});
- var n2 = new RedNode({_flow:flow,id:'n2',type:'abc'});
-
- n2.on('input',function(msg) {
- should.fail(null,null,"unexpected message");
- });
-
- setTimeout(function() {
- done();
- }, 200);
-
- n1.send();
- });
-
- // it('emits messages without cloning req or res', function(done) {
- // var flow = {
- // getNode: (id) => { return {'n1':n1,'n2':n2,'n3':n3}[id]},
- // send: (node,dst,msg) => { setImmediate(function() { flow.getNode(dst).receive(msg) })}
- // };
- // var n1 = new RedNode({_flow:flow,id:'n1',type:'abc',wires:[[['n2'],['n3']]]});
- // var n2 = new RedNode({_flow:flow,id:'n2',type:'abc'});
- // var n3 = new RedNode({_flow:flow,id:'n3',type:'abc'});
- //
- // var req = {};
- // var res = {};
- // var cloned = {};
- // var message = {payload: "foo", cloned: cloned, req: req, res: res};
- //
- // var rcvdCount = 0;
- //
- // // first message to be sent, so should not be cloned
- // n2.on('input',function(msg) {
- // should.deepEqual(msg, message);
- // msg.cloned.should.be.exactly(message.cloned);
- // msg.req.should.be.exactly(message.req);
- // msg.res.should.be.exactly(message.res);
- // rcvdCount += 1;
- // if (rcvdCount == 2) {
- // done();
- // }
- // });
- //
- // // second message to be sent, so should be cloned
- // // message uuids wont match since we've cloned
- // n3.on('input',function(msg) {
- // msg.payload.should.equal(message.payload);
- // msg.cloned.should.not.be.exactly(message.cloned);
- // msg.req.should.be.exactly(message.req);
- // msg.res.should.be.exactly(message.res);
- // rcvdCount += 1;
- // if (rcvdCount == 2) {
- // done();
- // }
- // });
- //
- // n1.send(message);
- // });
-
- // it("logs the uuid for all messages sent", function(done) {
- // var logHandler = {
- // msgIds:[],
- // messagesSent: 0,
- // emit: function(event, msg) {
- // if (msg.event == "node.abc.send" && msg.level == Log.METRIC) {
- // this.messagesSent++;
- // this.msgIds.push(msg.msgid);
- // (typeof msg.msgid).should.not.be.equal("undefined");
- // }
- // }
- // };
- //
- // Log.addHandler(logHandler);
- // var flow = {
- // getNode: (id) => { return {'n1':sender,'n2':receiver1,'n3':receiver2}[id]},
- // send: (node,dst,msg) => { setImmediate(function() { flow.getNode(dst).receive(msg) })}
- // };
- //
- // var sender = new RedNode({_flow:flow,id:'n1',type:'abc', wires:[['n2', 'n3']]});
- // var receiver1 = new RedNode({_flow:flow,id:'n2',type:'abc'});
- // var receiver2 = new RedNode({_flow:flow,id:'n3',type:'abc'});
- // sender.send({"some": "message"});
- // setTimeout(function() {
- // try {
- // logHandler.messagesSent.should.equal(1);
- // should.exist(logHandler.msgIds[0])
- // Log.removeHandler(logHandler);
- // done();
- // } catch(err) {
- // Log.removeHandler(logHandler);
- // done(err);
- // }
- // },50)
- // })
- });
-
-
- describe('#log', function() {
- it('produces a log message', function(done) {
- var n = new RedNode({id:'123',type:'abc',z:'789', _flow: {log:function(msg) { loginfo = msg;}}});
- var loginfo = {};
- n.log("a log message");
- should.deepEqual({level:Log.INFO, id:n.id,
- type:n.type, msg:"a log message",z:'789'}, loginfo);
- done();
- });
- it('produces a log message with a name', function(done) {
- var n = new RedNode({id:'123', type:'abc', name:"barney", z:'789', _flow: {log:function(msg) { loginfo = msg;}}});
- var loginfo = {};
- n.log("a log message");
- should.deepEqual({level:Log.INFO, id:n.id, name: "barney",
- type:n.type, msg:"a log message",z:'789'}, loginfo);
- done();
- });
- });
-
- describe('#warn', function() {
- it('produces a warning message', function(done) {
- var n = new RedNode({id:'123',type:'abc',z:'789', _flow: {log:function(msg) { loginfo = msg;}}});
- var loginfo = {};
- n.warn("a warning");
- should.deepEqual({level:Log.WARN, id:n.id,
- type:n.type, msg:"a warning",z:'789'}, loginfo);
- done();
- });
- });
-
- describe('#error', function() {
- it('handles a null error message', function(done) {
- var flow = {
- handleError: sinon.stub(),
- log:sinon.stub()
- }
- var n = new RedNode({_flow:flow, id:'123',type:'abc',z:'789'});
- var message = {a:1};
- n.error(null,message);
-
- flow.handleError.called.should.be.true();
- flow.handleError.args[0][0].should.eql(n);
- flow.handleError.args[0][1].should.eql("");
- flow.handleError.args[0][2].should.eql(message);
-
- done();
- });
-
- it('produces an error message', function(done) {
- var flow = {
- handleError: sinon.stub(),
- log:sinon.stub()
- }
- var n = new RedNode({_flow:flow, id:'123',type:'abc',z:'789'});
- var message = {a:2};
-
- n.error("This is an error",message);
-
- flow.handleError.called.should.be.true();
- flow.handleError.args[0][0].should.eql(n);
- flow.handleError.args[0][1].should.eql("This is an error");
- flow.handleError.args[0][2].should.eql(message);
-
- done();
- });
-
- });
-
- describe('#metric', function() {
- it('produces a metric message', function(done) {
- var n = new RedNode({id:'123',type:'abc'});
- var loginfo = {};
- sinon.stub(Log, 'log').callsFake(function(msg) {
- loginfo = msg;
- });
- var msg = {payload:"foo", _msgid:"987654321"};
- n.metric("test.metric",msg,"15mb");
- should.deepEqual({value:"15mb", level:Log.METRIC, nodeid:n.id,
- event:"node.abc.test.metric",msgid:"987654321"}, loginfo);
- Log.log.restore();
- done();
- });
- });
-
- describe('#metric', function() {
- it('returns metric value if eventname undefined', function(done) {
- var n = new RedNode({id:'123',type:'abc'});
- var loginfo = {};
- sinon.stub(Log, 'log').callsFake(function(msg) {
- loginfo = msg;
- });
- var msg = {payload:"foo", _msgid:"987654321"};
- var m = n.metric(undefined,msg,"15mb");
- m.should.be.a.Boolean();
- Log.log.restore();
- done();
- });
- it('returns not defined if eventname defined', function(done) {
- var n = new RedNode({id:'123',type:'abc'});
- var loginfo = {};
- sinon.stub(Log, 'log').callsFake(function(msg) {
- loginfo = msg;
- });
- var msg = {payload:"foo", _msgid:"987654321"};
- var m = n.metric("info",msg,"15mb");
- should(m).be.undefined;
- Log.log.restore();
- done();
- });
- });
-
- describe('#status', function() {
- it('publishes status', function(done) {
- var flow = {
- handleStatus: sinon.stub()
- }
- var n = new RedNode({_flow:flow,id:'123',type:'abc'});
- var status = {fill:"green",shape:"dot",text:"connected"};
-
- n.status(status);
-
- flow.handleStatus.called.should.be.true();
- flow.handleStatus.args[0][0].should.eql(n);
- flow.handleStatus.args[0][1].should.eql(status);
- done();
- });
- it('publishes status for plain string', function(done) {
- var flow = { handleStatus: sinon.stub() }
- var n = new RedNode({_flow:flow,id:'123',type:'abc'});
- n.status("text status");
- flow.handleStatus.called.should.be.true();
- flow.handleStatus.args[0][0].should.eql(n);
- flow.handleStatus.args[0][1].should.eql({text:"text status"});
- done();
- });
- it('publishes status for plain boolean', function(done) {
- var flow = { handleStatus: sinon.stub() }
- var n = new RedNode({_flow:flow,id:'123',type:'abc'});
- n.status(false);
- flow.handleStatus.called.should.be.true();
- flow.handleStatus.args[0][0].should.eql(n);
- flow.handleStatus.args[0][1].should.eql({text:"false"});
- done();
- });
- it('publishes status for plain number', function(done) {
- var flow = { handleStatus: sinon.stub() }
- var n = new RedNode({_flow:flow,id:'123',type:'abc'});
- n.status(123);
- flow.handleStatus.called.should.be.true();
- flow.handleStatus.args[0][0].should.eql(n);
- flow.handleStatus.args[0][1].should.eql({text:"123"});
- done();
- });
- });
-
-});
diff --git a/test/unit/@node-red/runtime/lib/nodes/context/index_spec.js b/test/unit/@node-red/runtime/lib/nodes/context/index_spec.js
deleted file mode 100644
index 7e05eba8f..000000000
--- a/test/unit/@node-red/runtime/lib/nodes/context/index_spec.js
+++ /dev/null
@@ -1,1209 +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 Context = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/context/index");
-
-describe('context', function() {
- describe('local memory',function() {
- beforeEach(function() {
- Context.init({});
- Context.load();
- });
- afterEach(function() {
- Context.clean({allNodes:{}});
- return Context.close();
- });
- it('stores local property',function() {
- var flowContext = Context.getFlowContext("flowA")
- var context1 = Context.get("1","flowA");
- should.not.exist(context1.get("foo"));
- context1.set("foo","test");
- context1.get("foo").should.equal("test");
- });
- it('stores local property - creates parent properties',function() {
- var flowContext = Context.getFlowContext("flowA")
- var context1 = Context.get("1","flowA");
- context1.set("foo.bar","test");
- context1.get("foo").should.eql({bar:"test"});
- });
- it('deletes local property',function() {
- var flowContext = Context.getFlowContext("flowA")
- var context1 = Context.get("1","flowA");
- context1.set("foo.abc.bar1","test1");
- context1.set("foo.abc.bar2","test2");
- context1.get("foo.abc").should.eql({bar1:"test1",bar2:"test2"});
- context1.set("foo.abc.bar1",undefined);
- context1.get("foo.abc").should.eql({bar2:"test2"});
- context1.set("foo.abc",undefined);
- should.not.exist(context1.get("foo.abc"));
- context1.set("foo",undefined);
- should.not.exist(context1.get("foo"));
- });
- it('stores flow property',function() {
- var flowContext = Context.getFlowContext("flowA")
- var context1 = Context.get("1","flowA");
- should.not.exist(context1.flow.get("foo"));
- context1.flow.set("foo","test");
- context1.flow.get("foo").should.equal("test");
- });
- it('stores global property',function() {
- var flowContext = Context.getFlowContext("flowA")
- var context1 = Context.get("1","flowA");
- should.not.exist(context1.global.get("foo"));
- context1.global.set("foo","test");
- context1.global.get("foo").should.equal("test");
- });
-
- it('keeps local context local', function() {
- var flowContext = Context.getFlowContext("flowA")
- var context1 = Context.get("1","flowA");
- var context2 = Context.get("2","flowA");
-
- should.not.exist(context1.get("foo"));
- should.not.exist(context2.get("foo"));
- context1.set("foo","test");
-
- context1.get("foo").should.equal("test");
- should.not.exist(context2.get("foo"));
- });
- it('flow context accessible to all flow nodes', function() {
- var flowContext = Context.getFlowContext("flowA")
- var context1 = Context.get("1","flowA");
- var context2 = Context.get("2","flowA");
-
- should.not.exist(context1.flow.get("foo"));
- should.not.exist(context2.flow.get("foo"));
-
- context1.flow.set("foo","test");
- context1.flow.get("foo").should.equal("test");
- context2.flow.get("foo").should.equal("test");
- });
-
- it('flow context not shared to nodes on other flows', function() {
- var flowContextA = Context.getFlowContext("flowA")
- var flowContextB = Context.getFlowContext("flowB")
- var context1 = Context.get("1","flowA");
- var context2 = Context.get("2","flowB");
-
- should.not.exist(context1.flow.get("foo"));
- should.not.exist(context2.flow.get("foo"));
-
- context1.flow.set("foo","test");
- context1.flow.get("foo").should.equal("test");
- should.not.exist(context2.flow.get("foo"));
- });
-
- it('global context shared to all nodes', function() {
- var flowContextA = Context.getFlowContext("flowA")
- var flowContextB = Context.getFlowContext("flowB")
-
- var context1 = Context.get("1","flowA");
- var context2 = Context.get("2","flowB");
-
- should.not.exist(context1.global.get("foo"));
- should.not.exist(context2.global.get("foo"));
-
- context1.global.set("foo","test");
- context1.global.get("foo").should.equal("test");
- context2.global.get("foo").should.equal("test");
- });
-
- it('context.flow/global are not enumerable', function() {
- var flowContextA = Context.getFlowContext("flowA")
- var context1 = Context.get("1","flowA");
- Object.keys(context1).length.should.equal(0);
- Object.keys(context1.flow).length.should.equal(0);
- Object.keys(context1.global).length.should.equal(0);
- })
-
- it('context.flow/global cannot be deleted', function() {
- var flowContextA = Context.getFlowContext("flowA")
- var context1 = Context.get("1","flowA");
- delete context1.flow;
- should.exist(context1.flow);
- delete context1.global;
- should.exist(context1.global);
- })
-
- it('deletes context',function() {
- var flowContextA = Context.getFlowContext("flowA")
- var context = Context.get("1","flowA");
- should.not.exist(context.get("foo"));
- context.set("foo","abc");
- context.get("foo").should.equal("abc");
-
- return Context.delete("1","flowA").then(function(){
- context = Context.get("1","flowA");
- should.not.exist(context.get("foo"));
- });
- });
-
- it('enumerates context keys - sync', function() {
- var flowContextA = Context.getFlowContext("flowA")
- var context = Context.get("1","flowA");
-
- var keys = context.keys();
- keys.should.be.an.Array();
- keys.should.be.empty();
-
- context.set("foo","bar");
- keys = context.keys();
- keys.should.have.length(1);
- keys[0].should.equal("foo");
-
- context.set("abc.def","bar");
- keys = context.keys();
- keys.should.have.length(2);
- keys[1].should.equal("abc");
- });
-
- it('enumerates context keys - async', function(done) {
- var flowContextA = Context.getFlowContext("flowA")
- var context = Context.get("1","flowA");
-
- var keys = context.keys(function(err,keys) {
- keys.should.be.an.Array();
- keys.should.be.empty();
- context.set("foo","bar");
- keys = context.keys(function(err,keys) {
- keys.should.have.length(1);
- keys[0].should.equal("foo");
-
- context.set("abc.def","bar");
- keys = context.keys(function(err,keys) {
- keys.should.have.length(2);
- keys[1].should.equal("abc");
- done();
- });
- });
- });
- });
-
- it('should enumerate only context keys when GlobalContext was given - sync', function() {
- Context.init({functionGlobalContext: {foo:"bar"}});
- Context.load().then(function(){
- var flowContextA = Context.getFlowContext("flowA")
- var context = Context.get("1","flowA");
- context.global.set("foo2","bar2");
- var keys = context.global.keys();
- keys.should.have.length(2);
- keys[0].should.equal("foo");
- keys[1].should.equal("foo2");
- });
- });
-
- it('should enumerate only context keys when GlobalContext was given - async', function(done) {
- Context.init({functionGlobalContext: {foo:"bar"}});
- Context.load().then(function(){
- var flowContextA = Context.getFlowContext("flowA")
- var context = Context.get("1","flowA");
- context.global.set("foo2","bar2");
- context.global.keys(function(err,keys) {
- keys.should.have.length(2);
- keys[0].should.equal("foo");
- keys[1].should.equal("foo2");
- done();
- });
- }).catch(done);
- });
-
-
- it('returns functionGlobalContext value if store value undefined', function() {
- Context.init({functionGlobalContext: {foo:"bar"}});
- return Context.load().then(function(){
- var flowContextA = Context.getFlowContext("flowA")
- var context = Context.get("1","flowA");
- var v = context.global.get('foo');
- v.should.equal('bar');
- });
- })
-
- it('returns functionGlobalContext sub-value if store value undefined', function() {
- Context.init({functionGlobalContext: {foo:{bar:123}}});
- return Context.load().then(function(){
- var flowContextA = Context.getFlowContext("flowA")
- var context = Context.get("1","flowA");
- var v = context.global.get('foo.bar');
- should.equal(v,123);
- });
- })
-
- describe("$parent", function() {
- it('should get undefined for $parent without key', function() {
- var flowContextA = Context.getFlowContext("flowA")
- var flowContextB = Context.getFlowContext("flowB","flowA")
- var context0 = Context.get("0","flowA");
- var context1 = Context.get("1","flowB");
- var parent = context1.get("$parent");
- should.equal(parent, undefined);
- });
-
- it('should get undefined for $parent of root', function() {
- var flowContextA = Context.getFlowContext("flowA")
- var flowContextB = Context.getFlowContext("flowB","flowA")
- var context0 = Context.get("0","flowA");
- var context1 = Context.get("1","flowB");
- var parent = context1.flow.get("$parent.$parent.K");
- should.equal(parent, undefined);
- });
-
- it('should get undefined for $parent of root - callback', function(done) {
- var flowContextA = Context.getFlowContext("flowA")
- var flowContextB = Context.getFlowContext("flowB","flowA")
- var context0 = Context.get("0","flowA");
- var context1 = Context.get("1","flowB");
- context1.flow.get("$parent.$parent.K", function(err, result) {
- try {
- should.equal(err, undefined);
- should.equal(result, undefined);
- done();
- } catch(err) {
- done(err);
- }
- });
-
- });
-
- it('should get value in $parent', function() {
- var flowContextA = Context.getFlowContext("flowA")
- var flowContextB = Context.getFlowContext("flowB","flowA")
- var context0 = Context.get("0","flowA");
- var context1 = Context.get("1","flowB");
- flowContextA.set("K", "v");
- var v = context1.flow.get("$parent.K");
- should.equal(v, "v");
- });
-
- it('should set value in $parent', function() {
- var flowContextA = Context.getFlowContext("flowA")
- var flowContextB = Context.getFlowContext("flowB","flowA")
- var context0 = Context.get("0","flowA");
- var context1 = Context.get("1","flowB");
- context1.flow.set("$parent.K", "v");
- var v = flowContextA.get("K");
- should.equal(v, "v");
- });
-
- it('should not contain $parent in keys', function() {
- var flowContextA = Context.getFlowContext("flowA")
- var flowContextB = Context.getFlowContext("flowB","flowA")
- var context0 = Context.get("0","flowA");
- var context1 = Context.get("1","flowB");
- var parent = context1.get("$parent");
- flowContextA.set("K0", "v0");
- context1.set("K1", "v1");
- var keys = context1.keys();
- keys.should.have.length(1);
- keys[0].should.equal("K1");
- });
- });
-
- });
-
- describe('external context storage',function() {
- var resourcesDir = path.resolve(path.join(__dirname,"..","resources","context"));
- var sandbox = sinon.createSandbox();
- var stubGet = sandbox.stub();
- var stubSet = sandbox.stub();
- var stubKeys = sandbox.stub();
- var stubDelete = sandbox.stub().returns(Promise.resolve());
- var stubClean = sandbox.stub().returns(Promise.resolve());
- var stubOpen = sandbox.stub().returns(Promise.resolve());
- var stubClose = sandbox.stub().returns(Promise.resolve());
- var stubGet2 = sandbox.stub();
- var stubSet2 = sandbox.stub();
- var stubKeys2 = sandbox.stub();
- var stubDelete2 = sandbox.stub().returns(Promise.resolve());
- var stubClean2 = sandbox.stub().returns(Promise.resolve());
- var stubOpen2 = sandbox.stub().returns(Promise.resolve());
- var stubClose2 = sandbox.stub().returns(Promise.resolve());
- var testPlugin = function(config){
- function Test(){}
- Test.prototype.get = stubGet;
- Test.prototype.set = stubSet;
- Test.prototype.keys = stubKeys;
- Test.prototype.delete = stubDelete;
- Test.prototype.clean = stubClean;
- Test.prototype.open = stubOpen;
- Test.prototype.close = stubClose;
- return new Test(config);
- };
- var testPlugin2 = function(config){
- function Test2(){}
- Test2.prototype.get = stubGet2;
- Test2.prototype.set = stubSet2;
- Test2.prototype.keys = stubKeys2;
- Test2.prototype.delete = stubDelete2;
- Test2.prototype.clean = stubClean2;
- Test2.prototype.open = stubOpen2;
- Test2.prototype.close = stubClose2;
- return new Test2(config);
- };
- var contextStorage={
- test:{
- module: testPlugin,
- config:{}
- }
- };
- var contextDefaultStorage={
- default: {
- module: testPlugin2,
- config:{}
- },
- test:{
- module: testPlugin,
- config:{}
- }
- };
- var contextAlias={
- default: "test",
- test:{
- module: testPlugin,
- config:{}
- }
- };
- var memoryStorage ={
- memory:{
- module: "memory"
- }
- };
-
- afterEach(function() {
- sandbox.reset();
- return Context.clean({allNodes:{}}).then(function(){
- return Context.close();
- }).then(function(){
- return fs.remove(resourcesDir);
- });
- });
-
- describe('load modules',function(){
- it('should call open()', function() {
- Context.init({contextStorage:contextDefaultStorage});
- Context.load().then(function(){
- stubOpen.called.should.be.true();
- stubOpen2.called.should.be.true();
- });
- });
- it('should load memory module', function() {
- Context.init({contextStorage:{memory:{module:"memory"}}});
- return Context.load();
- });
- it('should load localfilesystem module', function() {
- Context.init({contextStorage:{file:{module:"localfilesystem",config:{dir:resourcesDir}}}});
- return Context.load();
- });
- it('should ignore reserved storage name `_`', function(done) {
- Context.init({contextStorage:{_:{module:testPlugin}}});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow")
- var context = Context.get("1","flow");
- var cb = function(){}
- context.set("foo","bar","_",cb);
- context.get("foo","_",cb);
- context.keys("_",cb);
- stubSet.called.should.be.false();
- stubGet.called.should.be.false();
- stubKeys.called.should.be.false();
- done();
- }).catch(done);
- });
-
- it('should fail when using invalid store name', function(done) {
- Context.init({contextStorage:{'Invalid name':{module:testPlugin}}});
- Context.load().then(function(){
- done("An error was not thrown");
- }).catch(function(){
- done();
- });
- });
- it('should fail when using invalid sign character', function (done) {
- Context.init({ contextStorage:{'abc-123':{module:testPlugin}}});
- Context.load().then(function () {
- done("An error was not thrown");
- }).catch(function () {
- done();
- });
- });
- it('should fail when using invalid default context', function(done) {
- Context.init({contextStorage:{default:"noexist"}});
- Context.load().then(function(){
- done("An error was not thrown");
- }).catch(function(){
- done();
- });
- });
- it('should fail for the storage with no module', function(done) {
- Context.init({ contextStorage: { test: {}}});
- Context.load().then(function(){
- done("An error was not thrown");
- }).catch(function(){
- done();
- });
- });
- it('should fail to load non-existent module', function(done) {
- Context.init({contextStorage:{ file:{module:"nonexistent"} }});
- Context.load().then(function(){
- done("An error was not thrown");
- }).catch(function(){
- done();
- });
- });
- it('should fail to load invalid module', function (done) {
- Context.init({contextStorage: {
- test: {
- module: function (config) {
- throw new Error("invalid plugin was loaded.");
- }
- }
- }});
- Context.load().then(function () {
- done("An error was not thrown");
- }).catch(function () {
- done();
- });
- });
- });
-
- describe('close modules',function(){
- it('should call close()', function(done) {
- Context.init({contextStorage:contextDefaultStorage});
- Context.load().then(function(){
- return Context.close().then(function(){
- stubClose.called.should.be.true();
- stubClose2.called.should.be.true();
- done();
- });
- }).catch(done);
- });
- });
-
- describe('store context',function() {
- it('should store local property to external context storage',function(done) {
- Context.init({contextStorage:contextStorage});
- var cb = function(){done("An error occurred")}
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- context.set("foo","bar","test",cb);
- context.get("foo","test",cb);
- context.keys("test",cb);
- stubSet.calledWithExactly("1:flow","foo","bar",cb).should.be.true();
- stubGet.calledWith("1:flow","foo").should.be.true();
- stubKeys.calledWithExactly("1:flow",cb).should.be.true();
- done();
- }).catch(done);
- });
- it('should store flow property to external context storage',function(done) {
- Context.init({contextStorage:contextStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- var cb = function(){done("An error occurred")}
- context.flow.set("foo","bar","test",cb);
- context.flow.get("foo","test",cb);
- context.flow.keys("test",cb);
- stubSet.calledWithExactly("flow","foo","bar",cb).should.be.true();
- stubGet.calledWith("flow","foo").should.be.true();
- stubKeys.calledWithExactly("flow",cb).should.be.true();
- done();
- }).catch(done);
- });
- it('should store global property to external context storage',function(done) {
- Context.init({contextStorage:contextStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- var cb = function(){done("An error occurred")}
- context.global.set("foo","bar","test",cb);
- context.global.get("foo","test",cb);
- context.global.keys("test",cb);
- stubSet.calledWithExactly("global","foo","bar",cb).should.be.true();
- stubGet.calledWith("global","foo").should.be.true();
- stubKeys.calledWith("global").should.be.true();
- done();
- }).catch(done);
- });
- it('should store data to the default context when non-existent context storage was specified', function(done) {
- Context.init({contextStorage:contextDefaultStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- var cb = function(){done("An error occurred")}
- context.set("foo","bar","nonexist",cb);
- context.get("foo","nonexist",cb);
- context.keys("nonexist",cb);
- stubGet.called.should.be.false();
- stubSet.called.should.be.false();
- stubKeys.called.should.be.false();
- stubSet2.calledWithExactly("1:flow","foo","bar",cb).should.be.true();
- stubGet2.calledWith("1:flow","foo").should.be.true();
- stubKeys2.calledWithExactly("1:flow",cb).should.be.true();
- done();
- }).catch(done);
- });
- it('should use the default context', function(done) {
- Context.init({contextStorage:contextDefaultStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- var cb = function(){done("An error occurred")}
- context.set("foo","bar","default",cb);
- context.get("foo","default",cb);
- context.keys("default",cb);
- stubGet.called.should.be.false();
- stubSet.called.should.be.false();
- stubKeys.called.should.be.false();
- stubSet2.calledWithExactly("1:flow","foo","bar",cb).should.be.true();
- stubGet2.calledWith("1:flow","foo").should.be.true();
- stubKeys2.calledWithExactly("1:flow",cb).should.be.true();
- done();
- }).catch(done);
- });
- it('should use the alias of default context', function(done) {
- Context.init({contextStorage:contextDefaultStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- var cb = function(){done("An error occurred")}
- context.set("foo","alias",cb);
- context.get("foo",cb);
- context.keys(cb);
- stubGet.called.should.be.false();
- stubSet.called.should.be.false();
- stubKeys.called.should.be.false();
- stubSet2.calledWithExactly("1:flow","foo","alias",cb).should.be.true();
- stubGet2.calledWith("1:flow","foo").should.be.true();
- stubKeys2.calledWithExactly("1:flow",cb).should.be.true();
- done();
- }).catch(done);
- });
-
- it('should allow the store name to be provide in the key', function(done) {
- Context.init({contextStorage:contextDefaultStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- var cb = function(){done("An error occurred")}
- context.set("#:(test)::foo","bar");
- context.get("#:(test)::foo");
- stubGet2.called.should.be.false();
- stubSet2.called.should.be.false();
- stubSet.calledWithExactly("1:flow","foo","bar",undefined).should.be.true();
- stubGet.calledWith("1:flow","foo").should.be.true();
- done();
- }).catch(done);
- });
-
-
- it('should use default as the alias of other context', function(done) {
- Context.init({contextStorage:contextAlias});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- var cb = function(){done("An error occurred")}
- context.set("foo","alias",cb);
- context.get("foo",cb);
- context.keys(cb);
- stubSet.calledWithExactly("1:flow","foo","alias",cb).should.be.true();
- stubGet.calledWith("1:flow","foo").should.be.true();
- stubKeys.calledWithExactly("1:flow",cb).should.be.true();
- done();
- }).catch(done);
- });
- it('should not throw an error using undefined storage for local context', function(done) {
- Context.init({contextStorage:contextStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- var cb = function(){done("An error occurred")}
- context.get("local","nonexist",cb);
- done()
- }).catch(done);
- });
- it('should throw an error using undefined storage for flow context', function(done) {
- Context.init({contextStorage:contextStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- var cb = function(){done("An error occurred")}
- context.flow.get("flow","nonexist",cb);
- done();
- }).catch(done);
- });
-
- it('should return functionGlobalContext value as a default - synchronous', function(done) {
- var fGC = { "foo": 456 };
- Context.init({contextStorage:memoryStorage, functionGlobalContext:fGC });
- Context.load().then(function() {
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- // Get foo - should be value from fGC
- var v = context.global.get("foo");
- v.should.equal(456);
-
- // Update foo - should not touch fGC object
- context.global.set("foo","new value");
- fGC.foo.should.equal(456);
-
- // Get foo - should be the updated value
- v = context.global.get("foo");
- v.should.equal("new value");
- done();
- }).catch(done);
- })
-
- it('should return functionGlobalContext value as a default - async', function(done) {
- var fGC = { "foo": 456 };
- Context.init({contextStorage:memoryStorage, functionGlobalContext:fGC });
- Context.load().then(function() {
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- // Get foo - should be value from fGC
- context.global.get("foo", function(err, v) {
- if (err) {
- done(err)
- } else {
- v.should.equal(456);
- // Update foo - should not touch fGC object
- context.global.set("foo","new value", function(err) {
- if (err) {
- done(err)
- } else {
- fGC.foo.should.equal(456);
- // Get foo - should be the updated value
- context.global.get("foo", function(err, v) {
- if (err) {
- done(err)
- } else {
- v.should.equal("new value");
- done();
- }
- });
- }
- });
- }
- });
- }).catch(done);
- })
-
- it('should return multiple values if key is an array', function(done) {
- Context.init({contextStorage:memoryStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- context.set("foo1","bar1","memory");
- context.set("foo2","bar2","memory");
- context.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
- if (err) {
- done(err);
- } else {
- foo1.should.be.equal("bar1");
- foo2.should.be.equal("bar2");
- should.not.exist(foo3);
- done();
- }
- });
- }).catch(function(err){ done(err); });
- });
-
- it('should return multiple functionGlobalContext values if key is an array', function(done) {
- var fGC = { "foo1": 456, "foo2": {"bar":789} };
- Context.init({contextStorage:memoryStorage, functionGlobalContext:fGC });
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- context.global.get(["foo1","foo2.bar","foo3"], "memory", function(err,foo1,foo2,foo3){
- if (err) {
- done(err);
- } else {
- should.equal(foo1, 456);
- should.equal(foo2, 789);
- should.not.exist(foo3);
- done();
- }
- });
- }).catch(function(err){ done(err); });
- });
-
- it('should return an error if an error occurs in getting multiple store values', function(done) {
- Context.init({contextStorage:contextStorage});
- stubGet.onFirstCall().callsArgWith(2, "error2", "bar1");
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow")
- var context = Context.get("1","flow");
- context.global.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
- if (err === "error2") {
- done();
- } else {
- done("An error occurred");
- }
- });
- }).catch(function(err){ done(err); });
- });
-
- it('should return a first error if some errors occur in getting multiple store values', function(done) {
- Context.init({contextStorage:contextStorage});
- stubGet.onFirstCall().callsArgWith(2, "error1");
- stubGet.onSecondCall().callsArgWith(2, null, "bar2");
- stubGet.onThirdCall().callsArgWith(2, "error3");
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- context.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
- if (err === "error1") {
- done();
- } else {
- done("An error occurred");
- }
- });
- }).catch(function(err){ done(err); });
- });
-
- it('should store multiple properties if key and value are arrays', function(done) {
- Context.init({contextStorage:memoryStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- context.set(["foo1","foo2","foo3"], ["bar1","bar2","bar3"], "memory", function(err){
- if (err) {
- done(err);
- } else {
- context.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
- if (err) {
- done(err);
- } else {
- foo1.should.be.equal("bar1");
- foo2.should.be.equal("bar2");
- foo3.should.be.equal("bar3");
- done();
- }
- });
- }
- });
- });
- });
-
- it('should deletes multiple properties', function(done) {
- Context.init({contextStorage:memoryStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- context.set(["foo1","foo2","foo3"], ["bar1","bar2","bar3"], "memory", function(err){
- if (err) {
- done(err);
- } else {
- context.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
- if (err) {
- done(err);
- } else {
- foo1.should.be.equal("bar1");
- foo2.should.be.equal("bar2");
- foo3.should.be.equal("bar3");
- context.set(["foo1","foo2","foo3"], new Array(3), "memory", function(err){
- if (err) {
- done(err);
- } else {
- context.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
- if (err) {
- done(err);
- } else {
- should.not.exist(foo1);
- should.not.exist(foo2);
- should.not.exist(foo3);
- done();
- }
- });
- }
- });
- }
- });
- }
- });
- });
- });
-
- it('should use null for missing values if the value array is shorter than the key array', function(done) {
- Context.init({contextStorage:memoryStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- context.set(["foo1","foo2","foo3"], ["bar1","bar2"], "memory", function(err){
- if (err) {
- done(err);
- } else {
- context.keys(function(err, keys){
- keys.should.have.length(3);
- keys.should.eql(["foo1","foo2","foo3"]);
- context.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
- if (err) {
- done(err);
- } else {
- foo1.should.be.equal("bar1");
- foo2.should.be.equal("bar2");
- should(foo3).be.null();
- done();
- }
- });
- });
- }
- });
- });
- });
-
- it('should use null for missing values if the value is not array', function(done) {
- Context.init({contextStorage:memoryStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- context.set(["foo1","foo2","foo3"], "bar1", "memory", function(err){
- if (err) {
- done(err);
- } else {
- context.keys(function(err, keys){
- keys.should.have.length(3);
- keys.should.eql(["foo1","foo2","foo3"]);
- context.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
- if (err) {
- done(err);
- } else {
- foo1.should.be.equal("bar1");
- should(foo2).be.null();
- should(foo3).be.null();
- done();
- }
- });
- });
- }
- });
- });
- });
-
- it('should ignore the extra values if the value array is longer than the key array', function(done) {
- Context.init({contextStorage:memoryStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- context.set(["foo1","foo2","foo3"], ["bar1","bar2","bar3","ignored"], "memory", function(err){
- if (err) {
- done(err);
- } else {
- context.keys(function(err, keys){
- keys.should.have.length(3);
- keys.should.eql(["foo1","foo2","foo3"]);
- context.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
- if (err) {
- done(err);
- } else {
- foo1.should.be.equal("bar1");
- foo2.should.be.equal("bar2");
- foo3.should.be.equal("bar3");
- done();
- }
- });
- });
- }
- });
- });
- });
-
- it('should return an error if an error occurs in storing multiple values', function(done) {
- Context.init({contextStorage:contextStorage});
- stubSet.onFirstCall().callsArgWith(3, "error2");
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- context.set(["foo1","foo2","foo3"], ["bar1","bar2","bar3"], "memory", function(err){
- if (err === "error2") {
- done();
- } else {
- done("An error occurred");
- }
- });
- }).catch(function(err){ done(err); });
- });
-
- it('should throw an error if callback of context.get is not a function', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1", "flow");
- context.get("foo", "memory", "callback");
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
-
- it('should not throw an error if callback of context.get is not specified', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1", "flow");
- context.get("foo", "memory");
- done();
- }).catch(done);
- });
-
- it('should throw an error if callback of context.set is not a function', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1", "flow");
- context.set("foo", "bar", "memory", "callback");
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
-
- it('should not throw an error if callback of context.set is not specified', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1", "flow");
- context.set("foo", "bar", "memory");
- done();
- }).catch(done);
- });
-
- it('should throw an error if callback of context.keys is not a function', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1", "flow");
- context.keys("memory", "callback");
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
-
- it('should not throw an error if callback of context.keys is not specified', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1", "flow");
- context.keys("memory");
- done();
- }).catch(done);
- });
- it('should throw an error in context.get if key is empty string', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.get("");
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
- it('should throw an error in context.get if key is an object', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.get({});
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
- it('should throw an error in context.get if key is a number', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.get(1);
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
- it('should throw an error in context.get if key array contains an empty string', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.get(["ok1", "", "ok2"]);
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
- it('should throw an error in context.get if key array contains an object', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.get(["ok1", {}, "ok2"]);
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
- it('should throw an error in context.get if key array contains a number', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.get(["ok1", 1, "ok2"]);
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
-
- it('should throw an error in context.set if key is empty string', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.set("", 1);
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
- it('should throw an error in context.set if key is an object', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.set({}, 1);
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
- it('should throw an error in context.set if key is a number', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.set(1, 1);
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
- it('should throw an error in context.set if key array contains an empty string', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.set(["ok1", "", "ok2"], 1);
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
- it('should throw an error in context.set if key array contains an object', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.set(["ok1", {}, "ok2"], 1);
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
- it('should throw an error in context.set if key array contains a number', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.set(["ok1", 1, "ok2"], 1);
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
-
- it('should have an err set in callback for invalid key in context.get', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.get("", function(err) {
- if(err) {
- done();
- } else {
- done("should throw an error.");
- }
- });
- }).catch(done);
- });
-
- it('should have an err set in callback for invalid key in context.set', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.set("", "value", function(err) {
- if(err) {
- done();
- } else {
- done("should throw an error.");
- }
- });
- }).catch(done);
- });
- });
-
- describe('listStores', function () {
- it('should list context storages', function (done) {
- Context.init({ contextStorage: contextDefaultStorage });
- Context.load().then(function () {
- var list = Context.listStores();
- list.default.should.equal("default");
- list.stores.should.eql(["default", "test"]);
- done();
- }).catch(done);
- });
-
- it('should list context storages without default storage', function (done) {
- Context.init({ contextStorage: contextStorage });
- Context.load().then(function () {
- var list = Context.listStores();
- list.default.should.equal("test");
- list.stores.should.eql(["test"]);
- done();
- }).catch(done);
- });
- });
- describe('delete context',function(){
- it('should not call delete() when external context storage is used', function(done) {
- Context.init({contextStorage:contextDefaultStorage});
- Context.load().then(function(){
- Context.get("flowA");
- return Context.delete("flowA").then(function(){
- stubDelete.called.should.be.false();
- stubDelete2.called.should.be.false();
- done();
- });
- }).catch(done);
- });
- });
-
- describe('clean context',function(){
- it('should call clean()', function(done) {
- Context.init({contextStorage:contextDefaultStorage});
- Context.load().then(function(){
- return Context.clean({allNodes:{}}).then(function(){
- stubClean.calledWithExactly([]).should.be.true();
- stubClean2.calledWithExactly([]).should.be.true();
- done();
- });
- }).catch(done);
- });
- });
- });
-
-});
diff --git a/test/unit/@node-red/runtime/lib/nodes/context/localfilesystem_spec.js b/test/unit/@node-red/runtime/lib/nodes/context/localfilesystem_spec.js
deleted file mode 100644
index 26f9789f4..000000000
--- a/test/unit/@node-red/runtime/lib/nodes/context/localfilesystem_spec.js
+++ /dev/null
@@ -1,883 +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-extra');
-var path = require("path");
-var NR_TEST_UTILS = require("nr-test-utils");
-var LocalFileSystem = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/context/localfilesystem");
-
-var resourcesDir = path.resolve(path.join(__dirname,"..","resources","context"));
-
-var defaultContextBase = "context";
-
-describe('localfilesystem',function() {
-
- before(function() {
- return fs.remove(resourcesDir);
- });
-
- describe('#get/set',function() {
- var context;
- beforeEach(function() {
- context = LocalFileSystem({dir: resourcesDir, cache: false});
- return context.open();
- });
-
- afterEach(function() {
- return context.clean([]).then(function(){
- return context.close();
- }).then(function(){
- return fs.remove(resourcesDir);
- });
- });
-
- it('should store property',function(done) {
- context.get("nodeX","foo",function(err, value){
- if (err) { return done(err); }
- should.not.exist(value);
- context.set("nodeX","foo","test",function(err){
- if (err) { return done(err); }
- context.get("nodeX","foo",function(err, value){
- if (err) { return done(err); }
- value.should.be.equal("test");
- done();
- });
- });
- });
- });
-
- it('should store property - creates parent properties',function(done) {
- context.set("nodeX","foo.bar","test",function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.be.eql({bar:"test"});
- done();
- });
- });
- });
-
- it('should store local scope property', function (done) {
- context.set("abc:def", "foo.bar", "test", function (err) {
- context.get("abc:def", "foo", function (err, value) {
- value.should.be.eql({ bar: "test" });
- done();
- });
- });
- });
-
- it('should delete property',function(done) {
- context.set("nodeX","foo.abc.bar1","test1",function(err){
- context.set("nodeX","foo.abc.bar2","test2",function(err){
- context.get("nodeX","foo.abc",function(err, value){
- value.should.be.eql({bar1:"test1",bar2:"test2"});
- context.set("nodeX","foo.abc.bar1",undefined,function(err){
- context.get("nodeX","foo.abc",function(err, value){
- value.should.be.eql({bar2:"test2"});
- context.set("nodeX","foo.abc",undefined,function(err){
- context.get("nodeX","foo.abc",function(err, value){
- should.not.exist(value);
- context.set("nodeX","foo",undefined,function(err){
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- done();
- });
- });
- });
- });
- });
- });
- });
- });
- });
- });
-
- it('should not shared context with other scope', function(done) {
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- context.get("nodeY","foo",function(err, value){
- should.not.exist(value);
- context.set("nodeX","foo","testX",function(err){
- context.set("nodeY","foo","testY",function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.be.equal("testX");
- context.get("nodeY","foo",function(err, value){
- value.should.be.equal("testY");
- done();
- });
- });
- });
- });
- });
- });
- });
-
- it('should store string',function(done) {
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- context.set("nodeX","foo","bar",function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.be.String();
- value.should.be.equal("bar");
- context.set("nodeX","foo","1",function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.be.String();
- value.should.be.equal("1");
- done();
- });
- });
- });
- });
- });
- });
-
- it('should store number',function(done) {
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- context.set("nodeX","foo",1,function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.be.Number();
- value.should.be.equal(1);
- done();
- });
- });
- });
- });
-
- it('should store null',function(done) {
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- context.set("nodeX","foo",null,function(err){
- context.get("nodeX","foo",function(err, value){
- should(value).be.null();
- done();
- });
- });
- });
- });
-
- it('should store boolean',function(done) {
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- context.set("nodeX","foo",true,function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.be.Boolean().and.true();
- context.set("nodeX","foo",false,function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.be.Boolean().and.false();
- done();
- });
- });
- });
- });
- });
- });
-
- it('should store object',function(done) {
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- context.set("nodeX","foo",{obj:"bar"},function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.be.Object();
- value.should.eql({obj:"bar"});
- done();
- });
- });
- });
- });
-
- it('should store array',function(done) {
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- context.set("nodeX","foo",["a","b","c"],function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.be.Array();
- value.should.eql(["a","b","c"]);
- context.get("nodeX","foo[1]",function(err, value){
- value.should.be.String();
- value.should.equal("b");
- done();
- });
- });
- });
- });
- });
-
- it('should store array of arrays',function(done) {
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- context.set("nodeX","foo",[["a","b","c"],[1,2,3,4],[true,false]],function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.be.Array();
- value.should.have.length(3);
- value[0].should.have.length(3);
- value[1].should.have.length(4);
- value[2].should.have.length(2);
- context.get("nodeX","foo[1]",function(err, value){
- value.should.be.Array();
- value.should.have.length(4);
- value.should.be.eql([1,2,3,4]);
- done();
- });
- });
- });
- });
- });
-
- it('should store array of objects',function(done) {
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- context.set("nodeX","foo",[{obj:"bar1"},{obj:"bar2"},{obj:"bar3"}],function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.be.Array();
- value.should.have.length(3);
- value[0].should.be.Object();
- value[1].should.be.Object();
- value[2].should.be.Object();
- context.get("nodeX","foo[1]",function(err, value){
- value.should.be.Object();
- value.should.be.eql({obj:"bar2"});
- done();
- });
- });
- });
- });
- });
-
- it('should set/get multiple values', function(done) {
- context.set("nodeX",["one","two","three"],["test1","test2","test3"], function(err) {
- context.get("nodeX",["one","two"], function() {
- Array.prototype.slice.apply(arguments).should.eql([undefined,"test1","test2"])
- done();
- });
- });
- })
- it('should set/get multiple values - get unknown', function(done) {
- context.set("nodeX",["one","two","three"],["test1","test2","test3"], function(err) {
- context.get("nodeX",["one","two","unknown"], function() {
- Array.prototype.slice.apply(arguments).should.eql([undefined,"test1","test2",undefined])
- done();
- });
- });
- })
- it('should set/get multiple values - single value providd', function(done) {
- context.set("nodeX",["one","two","three"],"test1", function(err) {
- context.get("nodeX",["one","two"], function() {
- Array.prototype.slice.apply(arguments).should.eql([undefined,"test1",null])
- done();
- });
- });
- })
-
- it('should throw error if bad key included in multiple keys - get', function(done) {
- context.set("nodeX",["one","two","three"],["test1","test2","test3"], function(err) {
- context.get("nodeX",["one",".foo","three"], function(err) {
- should.exist(err);
- done();
- });
- });
- })
-
- it('should throw error if bad key included in multiple keys - set', function(done) {
- context.set("nodeX",["one",".foo","three"],["test1","test2","test3"], function(err) {
- should.exist(err);
- // Check 'one' didn't get set as a result
- context.get("nodeX","one",function(err,one) {
- should.not.exist(one);
- done();
- })
- });
- })
-
- it('should throw an error when getting a value with invalid key', function (done) {
- context.set("nodeX","foo","bar",function(err) {
- context.get("nodeX"," ",function(err,value) {
- should.exist(err);
- done();
- });
- });
- });
-
- it('should throw an error when setting a value with invalid key',function (done) {
- context.set("nodeX"," ","bar",function (err) {
- should.exist(err);
- done();
- });
- });
-
- it('should throw an error when callback of get() is not a function',function (done) {
- try {
- context.get("nodeX","foo","callback");
- done("should throw an error.");
- } catch (err) {
- done();
- }
- });
-
- it('should throw an error when callback of get() is not specified',function (done) {
- try {
- context.get("nodeX","foo");
- done("should throw an error.");
- } catch (err) {
- done();
- }
- });
-
- it('should throw an error when callback of set() is not a function',function (done) {
- try {
- context.set("nodeX","foo","bar","callback");
- done("should throw an error.");
- } catch (err) {
- done();
- }
- });
-
- it('should not throw an error when callback of set() is not specified', function (done) {
- try {
- context.set("nodeX"," ","bar");
- done();
- } catch (err) {
- done("should not throw an error.");
- }
- });
-
- it('should handle empty context file', function (done) {
- fs.outputFile(path.join(resourcesDir,defaultContextBase,"nodeX","flow.json"),"",function(){
- context.get("nodeX", "foo", function (err, value) {
- should.not.exist(value);
- context.set("nodeX", "foo", "test", function (err) {
- context.get("nodeX", "foo", function (err, value) {
- value.should.be.equal("test");
- done();
- });
- });
- });
- });
- });
-
- it('should throw an error when reading corrupt context file', function (done) {
- fs.outputFile(path.join(resourcesDir, defaultContextBase, "nodeX", "flow.json"),"{abc",function(){
- context.get("nodeX", "foo", function (err, value) {
- should.exist(err);
- done();
- });
- });
- });
- });
-
- describe('#keys',function() {
- var context;
- beforeEach(function() {
- context = LocalFileSystem({dir: resourcesDir, cache: false});
- return context.open();
- });
-
- afterEach(function() {
- return context.clean([]).then(function(){
- return context.close();
- }).then(function(){
- return fs.remove(resourcesDir);
- });
- });
-
- it('should enumerate context keys', function(done) {
- context.keys("nodeX",function(err, value){
- value.should.be.an.Array();
- value.should.be.empty();
- context.set("nodeX","foo","bar",function(err){
- context.keys("nodeX",function(err, value){
- value.should.have.length(1);
- value[0].should.equal("foo");
- context.set("nodeX","abc.def","bar",function(err){
- context.keys("nodeX",function(err, value){
- value.should.have.length(2);
- value[1].should.equal("abc");
- done();
- });
- });
- });
- });
- });
- });
-
- it('should enumerate context keys in each scopes', function(done) {
- context.keys("nodeX",function(err, value){
- value.should.be.an.Array();
- value.should.be.empty();
- context.keys("nodeY",function(err, value){
- value.should.be.an.Array();
- value.should.be.empty();
- context.set("nodeX","foo","bar",function(err){
- context.set("nodeY","hoge","piyo",function(err){
- context.keys("nodeX",function(err, value){
- value.should.have.length(1);
- value[0].should.equal("foo");
- context.keys("nodeY",function(err, value){
- value.should.have.length(1);
- value[0].should.equal("hoge");
- done();
- });
- });
- });
- });
- });
- });
- });
-
- it('should throw an error when callback of keys() is not a function', function (done) {
- try {
- context.keys("nodeX", "callback");
- done("should throw an error.");
- } catch (err) {
- done();
- }
- });
-
- it('should throw an error when callback of keys() is not specified', function (done) {
- try {
- context.keys("nodeX");
- done("should throw an error.");
- } catch (err) {
- done();
- }
- });
- });
-
- describe('#delete',function() {
- var context;
- beforeEach(function() {
- context = LocalFileSystem({dir: resourcesDir, cache: false});
- return context.open();
- });
-
- afterEach(function() {
- return context.clean([]).then(function(){
- return context.close();
- }).then(function(){
- return fs.remove(resourcesDir);
- });
- });
-
- it('should delete context',function(done) {
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- context.get("nodeY","foo",function(err, value){
- should.not.exist(value);
- context.set("nodeX","foo","testX",function(err){
- context.set("nodeY","foo","testY",function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.be.equal("testX");
- context.get("nodeY","foo",function(err, value){
- value.should.be.equal("testY");
- context.delete("nodeX").then(function(){
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- context.get("nodeY","foo",function(err, value){
- value.should.be.equal("testY");
- done();
- });
- });
- }).catch(done);
- });
- });
- });
- });
- });
- });
- });
- });
-
- describe('#clean',function() {
- var context;
- var contextGet;
- var contextSet;
- beforeEach(function() {
- context = LocalFileSystem({dir: resourcesDir, cache: false});
- contextGet = function(scope,key) {
- return new Promise((res,rej) => {
- context.get(scope,key, function(err,value) {
- if (err) {
- rej(err);
- } else {
- res(value);
- }
- })
- });
- }
- contextSet = function(scope,key,value) {
- return new Promise((res,rej) => {
- context.set(scope,key,value, function(err) {
- if (err) {
- rej(err);
- } else {
- res();
- }
- })
- });
- }
- return context.open();
- });
-
- afterEach(function() {
- return context.clean([]).then(function(){
- return context.close().then(function(){
- return fs.remove(resourcesDir);
- });
- });
- });
- it('should clean unnecessary context',function(done) {
- contextSet("global","foo","testGlobal").then(function() {
- return contextSet("nodeX:flow1","foo","testX");
- }).then(function() {
- return contextSet("nodeY:flow2","foo","testY");
- }).then(function() {
- return contextGet("nodeX:flow1","foo");
- }).then(function(value) {
- value.should.be.equal("testX");
- }).then(function() {
- return contextGet("nodeY:flow2","foo");
- }).then(function(value) {
- value.should.be.equal("testY");
- }).then(function() {
- return context.clean([])
- }).then(function() {
- return contextGet("nodeX:flow1","foo");
- }).then(function(value) {
- should.not.exist(value);
- }).then(function() {
- return contextGet("nodeY:flow2","foo");
- }).then(function(value) {
- should.not.exist(value);
- }).then(function() {
- return contextGet("global","foo");
- }).then(function(value) {
- value.should.eql("testGlobal");
- }).then(done).catch(done);
- });
-
- it('should not clean active context',function(done) {
- contextSet("global","foo","testGlobal").then(function() {
- return contextSet("nodeX:flow1","foo","testX");
- }).then(function() {
- return contextSet("nodeY:flow2","foo","testY");
- }).then(function() {
- return contextGet("nodeX:flow1","foo");
- }).then(function(value) {
- value.should.be.equal("testX");
- }).then(function() {
- return contextGet("nodeY:flow2","foo");
- }).then(function(value) {
- value.should.be.equal("testY");
- }).then(function() {
- return context.clean(["flow1","nodeX"])
- }).then(function() {
- return contextGet("nodeX:flow1","foo");
- }).then(function(value) {
- value.should.be.equal("testX");
- }).then(function() {
- return contextGet("nodeY:flow2","foo");
- }).then(function(value) {
- should.not.exist(value);
- }).then(function() {
- return contextGet("global","foo");
- }).then(function(value) {
- value.should.eql("testGlobal");
- }).then(done).catch(done);
- });
- });
-
- describe('#if cache is enabled',function() {
-
- var context;
- beforeEach(function() {
- context = LocalFileSystem({dir: resourcesDir, cache: false});
- return context.open();
- });
-
- afterEach(function() {
- return context.clean([]).then(function(){
- return context.close();
- }).then(function(){
- return fs.remove(resourcesDir);
- });
- });
-
-
-
- it('should load contexts into the cache',function() {
- var globalData = {key:"global"};
- var flowData = {key:"flow"};
- var nodeData = {key:"node"};
- return Promise.all([
- fs.outputFile(path.join(resourcesDir,defaultContextBase,"global","global.json"), JSON.stringify(globalData,null,4), "utf8"),
- fs.outputFile(path.join(resourcesDir,defaultContextBase,"flow","flow.json"), JSON.stringify(flowData,null,4), "utf8"),
- fs.outputFile(path.join(resourcesDir,defaultContextBase,"flow","node.json"), JSON.stringify(nodeData,null,4), "utf8")
- ]).then(function(){
- context = LocalFileSystem({dir: resourcesDir, cache: true});
- return context.open();
- }).then(function(){
- return Promise.all([
- fs.remove(path.join(resourcesDir,defaultContextBase,"global","global.json")),
- fs.remove(path.join(resourcesDir,defaultContextBase,"flow","flow.json")),
- fs.remove(path.join(resourcesDir,defaultContextBase,"flow","node.json"))
- ]);
- }).then(function(){
- context.get("global","key").should.be.equal("global");
- context.get("flow","key").should.be.equal("flow");
- context.get("node:flow","key").should.be.equal("node");
- });
- });
-
- it('should store property to the cache',function() {
- context = LocalFileSystem({dir: resourcesDir, cache: true, flushInterval: 1});
- return context.open().then(function(){
- return new Promise(function(resolve, reject){
- context.set("global","foo","bar",function(err){
- if(err){
- reject(err);
- } else {
- fs.readJson(path.join(resourcesDir,defaultContextBase,"global","global.json")).then(function(data) {
- // File should not exist as flush hasn't happened
- reject("File global/global.json should not exist");
- }).catch(function(err) {
- setTimeout(function() {
- fs.readJson(path.join(resourcesDir,defaultContextBase,"global","global.json")).then(function(data) {
- data.should.eql({foo:'bar'});
- resolve();
- }).catch(function(err) {
- reject(err);
- });
- },1100)
- })
- }
- });
- });
- }).then(function(){
- return fs.remove(path.join(resourcesDir,defaultContextBase,"global","global.json"));
- }).then(function(){
- context.get("global","foo").should.be.equal("bar");
- })
- });
-
- it('should enumerate context keys in the cache',function() {
- var globalData = {foo:"bar"};
- return fs.outputFile(path.join(resourcesDir,defaultContextBase,"global","global.json"), JSON.stringify(globalData,null,4), "utf8").then(function(){
- context = LocalFileSystem({dir: resourcesDir, cache: true, flushInterval: 2});
- return context.open()
- }).then(function(){
- return fs.remove(path.join(resourcesDir,defaultContextBase,"global","global.json"));
- }).then(function(){
- var keys = context.keys("global");
- keys.should.have.length(1);
- keys[0].should.equal("foo");
- return new Promise(function(resolve, reject){
- context.set("global","foo2","bar2",function(err){
- if(err){
- reject(err);
- } else {
- resolve();
- }
- });
- });
- }).then(function(){
- return fs.remove(path.join(resourcesDir,defaultContextBase,"global","global.json"));
- }).then(function(){
- var keys = context.keys("global");
- keys.should.have.length(2);
- keys[1].should.equal("foo2");
- })
- });
-
- it('should delete context in the cache',function() {
- context = LocalFileSystem({dir: resourcesDir, cache: true, flushInterval: 2});
- return context.open().then(function(){
- return new Promise(function(resolve, reject){
- context.set("global","foo","bar",function(err){
- if(err){
- reject(err);
- } else {
- resolve();
- }
- });
- });
- }).then(function(){
- context.get("global","foo").should.be.equal("bar");
- return context.delete("global");
- }).then(function(){
- should.not.exist(context.get("global","foo"))
- })
- });
-
- it('should clean unnecessary context in the cache',function() {
- var flowAData = {key:"flowA"};
- var flowBData = {key:"flowB"};
- return Promise.all([
- fs.outputFile(path.join(resourcesDir,defaultContextBase,"flowA","flow.json"), JSON.stringify(flowAData,null,4), "utf8"),
- fs.outputFile(path.join(resourcesDir,defaultContextBase,"flowB","flow.json"), JSON.stringify(flowBData,null,4), "utf8")
- ]).then(function(){
- context = LocalFileSystem({dir: resourcesDir, cache: true, flushInterval: 2});
- return context.open();
- }).then(function(){
- context.get("flowA","key").should.be.equal("flowA");
- context.get("flowB","key").should.be.equal("flowB");
- return context.clean(["flowA"]);
- }).then(function(){
- context.get("flowA","key").should.be.equal("flowA");
- should.not.exist(context.get("flowB","key"));
- });
- });
- });
-
- describe('Configuration', function () {
- var context;
- beforeEach(function() {
- context = LocalFileSystem({dir: resourcesDir, cache: false});
- return context.open();
- });
-
- afterEach(function() {
- return context.clean([]).then(function(){
- return context.close();
- }).then(function(){
- return fs.remove(resourcesDir);
- });
- });
- it('should change a base directory', function (done) {
- var differentBaseContext = LocalFileSystem({
- base: "contexts2",
- dir: resourcesDir,
- cache: false
- });
- differentBaseContext.open().then(function () {
- differentBaseContext.set("node2", "foo2", "bar2", function (err) {
- differentBaseContext.get("node2", "foo2", function (err, value) {
- value.should.be.equal("bar2");
- context.get("node2", "foo2", function(err, value) {
- should.not.exist(value);
- done();
- });
- });
- });
- });
- });
-
- it('should use userDir', function (done) {
- var userDirContext = LocalFileSystem({
- base: "contexts2",
- cache: false,
- settings: {
- userDir: resourcesDir
- }
- });
- userDirContext.open().then(function () {
- userDirContext.set("node2", "foo2", "bar2", function (err) {
- userDirContext.get("node2", "foo2", function (err, value) {
- value.should.be.equal("bar2");
- context.get("node2", "foo2", function (err, value) {
- should.not.exist(value);
- done();
- });
- });
- });
- });
- });
-
- it('should use NODE_RED_HOME', function (done) {
- var oldNRH = process.env.NODE_RED_HOME;
- process.env.NODE_RED_HOME = resourcesDir;
- fs.ensureDirSync(resourcesDir);
- fs.writeFileSync(path.join(resourcesDir,".config.json"),"");
- var nrHomeContext = LocalFileSystem({
- base: "contexts2",
- cache: false
- });
- try {
- nrHomeContext.open().then(function () {
- nrHomeContext.set("node2", "foo2", "bar2", function (err) {
- nrHomeContext.get("node2", "foo2", function (err, value) {
- value.should.be.equal("bar2");
- context.get("node2", "foo2", function (err, value) {
- should.not.exist(value);
- done();
- });
- });
- });
- });
- } finally {
- process.env.NODE_RED_HOME = oldNRH;
- }
- });
-
- it('should use HOME_PATH', function (done) {
- var oldNRH = process.env.NODE_RED_HOME;
- var oldHOMEPATH = process.env.HOMEPATH;
- process.env.NODE_RED_HOME = resourcesDir;
- process.env.HOMEPATH = resourcesDir;
- var homePath = path.join(resourcesDir, ".node-red");
- fs.outputFile(path.join(homePath, ".config.json"),"",function(){
- var homeContext = LocalFileSystem({
- base: "contexts2",
- cache: false
- });
- try {
- homeContext.open().then(function () {
- homeContext.set("node2", "foo2", "bar2", function (err) {
- homeContext.get("node2", "foo2", function (err, value) {
- value.should.be.equal("bar2");
- context.get("node2", "foo2", function (err, value) {
- should.not.exist(value);
- done();
- });
- });
- });
- });
- } finally {
- process.env.NODE_RED_HOME = oldNRH;
- process.env.HOMEPATH = oldHOMEPATH;
- }
- });
- });
-
- it('should use HOME_PATH', function (done) {
- var oldNRH = process.env.NODE_RED_HOME;
- var oldHOMEPATH = process.env.HOMEPATH;
- var oldHOME = process.env.HOME;
- process.env.NODE_RED_HOME = resourcesDir;
- process.env.HOMEPATH = resourcesDir;
- process.env.HOME = resourcesDir;
- var homeContext = LocalFileSystem({
- base: "contexts2",
- cache: false
- });
- try {
- homeContext.open().then(function () {
- homeContext.set("node2", "foo2", "bar2", function (err) {
- homeContext.get("node2", "foo2", function (err, value) {
- value.should.be.equal("bar2");
- context.get("node2", "foo2", function (err, value) {
- should.not.exist(value);
- done();
- });
- });
- });
- });
- } finally {
- process.env.NODE_RED_HOME = oldNRH;
- process.env.HOMEPATH = oldHOMEPATH;
- process.env.HOME = oldHOME;
- }
- });
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/nodes/context/memory_spec.js b/test/unit/@node-red/runtime/lib/nodes/context/memory_spec.js
deleted file mode 100644
index 663ee46b7..000000000
--- a/test/unit/@node-red/runtime/lib/nodes/context/memory_spec.js
+++ /dev/null
@@ -1,321 +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 Memory = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/context/memory");
-
-describe('memory',function() {
- var context;
-
- beforeEach(function() {
- context = Memory({});
- return context.open();
- });
-
- afterEach(function() {
- return context.clean([]).then(function(){
- return context.close();
- });
- });
-
- describe('#get/set',function() {
- describe('sync',function() {
- it('should store property',function() {
- should.not.exist(context.get("nodeX","foo"));
- context.set("nodeX","foo","test");
- context.get("nodeX","foo").should.equal("test");
- });
-
- it('should store property - creates parent properties',function() {
- context.set("nodeX","foo.bar","test");
- context.get("nodeX","foo").should.eql({bar:"test"});
- });
-
- it('should delete property',function() {
- context.set("nodeX","foo.abc.bar1","test1");
- context.set("nodeX","foo.abc.bar2","test2");
- context.get("nodeX","foo.abc").should.eql({bar1:"test1",bar2:"test2"});
- context.set("nodeX","foo.abc.bar1",undefined);
- context.get("nodeX","foo.abc").should.eql({bar2:"test2"});
- context.set("nodeX","foo.abc",undefined);
- should.not.exist(context.get("nodeX","foo.abc"));
- context.set("nodeX","foo",undefined);
- should.not.exist(context.get("nodeX","foo"));
- });
-
- it('should not shared context with other scope', function() {
- should.not.exist(context.get("nodeX","foo"));
- should.not.exist(context.get("nodeY","foo"));
- context.set("nodeX","foo","testX");
- context.set("nodeY","foo","testY");
-
- context.get("nodeX","foo").should.equal("testX");
- context.get("nodeY","foo").should.equal("testY");
- });
-
- it('should throw the error if the error occurs', function() {
- try{
- context.set("nodeX",".foo","test");
- should.fail("Error was not thrown");
- }catch(err){
- should.exist(err);
- try{
- context.get("nodeX",".foo");
- should.fail("Error was not thrown");
- }catch(err){
- should.exist(err);
- }
- }
- });
-
- it('should get multiple values - all known', function() {
- context.set("nodeX","one","test1");
- context.set("nodeX","two","test2");
- context.set("nodeX","three","test3");
- context.set("nodeX","four","test4");
-
- var values = context.get("nodeX",["one","two","four"]);
- values.should.eql(["test1","test2","test4"])
- })
- it('should get multiple values - include unknown', function() {
- context.set("nodeX","one","test1");
- context.set("nodeX","two","test2");
- context.set("nodeX","three","test3");
- context.set("nodeX","four","test4");
-
- var values = context.get("nodeX",["one","unknown.with.multiple.levels"]);
- values.should.eql(["test1",undefined])
- })
- it('should throw error if bad key included in multiple keys', function() {
- context.set("nodeX","one","test1");
- context.set("nodeX","two","test2");
- context.set("nodeX","three","test3");
- context.set("nodeX","four","test4");
-
- try{
- var values = context.get("nodeX",["one",".foo","three"]);
- should.fail("Error was not thrown");
- }catch(err){
- should.exist(err);
- }
- })
-
-
- });
-
- describe('async',function() {
- it('should store property',function(done) {
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- context.set("nodeX","foo","test",function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.equal("test");
- done();
- });
- });
- });
- });
-
- it('should pass the error to callback if the error occurs',function(done) {
- context.set("nodeX",".foo","test",function(err, value){
- should.exist(err);
- context.get("nodeX",".foo",function(err){
- should.exist(err);
- done();
- });
- });
- });
-
- it('should get multiple values - all known', function(done) {
- context.set("nodeX","one","test1");
- context.set("nodeX","two","test2");
- context.set("nodeX","three","test3");
- context.set("nodeX","four","test4");
-
- context.get("nodeX",["one","two","four"],function() {
- Array.prototype.slice.apply(arguments).should.eql([undefined,"test1","test2","test4"])
- done();
- });
- })
- it('should get multiple values - include unknown', function(done) {
- context.set("nodeX","one","test1");
- context.set("nodeX","two","test2");
- context.set("nodeX","three","test3");
- context.set("nodeX","four","test4");
-
- context.get("nodeX",["one","unknown"],function() {
- Array.prototype.slice.apply(arguments).should.eql([undefined,"test1",undefined])
- done();
- });
- })
- it('should throw error if bad key included in multiple keys', function(done) {
- context.set("nodeX","one","test1");
- context.set("nodeX","two","test2");
- context.set("nodeX","three","test3");
- context.set("nodeX","four","test4");
-
- context.get("nodeX",["one",".foo","three"], function(err) {
- should.exist(err);
- done();
- });
- })
- });
- });
-
- describe('#keys',function() {
- describe('sync',function() {
- it('should enumerate context keys', function() {
- var keys = context.keys("nodeX");
- keys.should.be.an.Array();
- keys.should.be.empty();
-
- context.set("nodeX","foo","bar");
- keys = context.keys("nodeX");
- keys.should.have.length(1);
- keys[0].should.equal("foo");
-
- context.set("nodeX","abc.def","bar");
- keys = context.keys("nodeX");
- keys.should.have.length(2);
- keys[1].should.equal("abc");
- });
-
- it('should enumerate context keys in each scopes', function() {
- var keysX = context.keys("nodeX");
- keysX.should.be.an.Array();
- keysX.should.be.empty();
-
- var keysY = context.keys("nodeY");
- keysY.should.be.an.Array();
- keysY.should.be.empty();
-
- context.set("nodeX","foo","bar");
- context.set("nodeY","hoge","piyo");
- keysX = context.keys("nodeX");
- keysX.should.have.length(1);
- keysX[0].should.equal("foo");
-
- keysY = context.keys("nodeY");
- keysY.should.have.length(1);
- keysY[0].should.equal("hoge");
- });
-
- it('should enumerate global context keys', function () {
- var keys = context.keys("global");
- keys.should.be.an.Array();
- keys.should.be.empty();
-
- context.set("global", "foo", "bar");
- keys = context.keys("global");
- keys.should.have.length(1);
- keys[0].should.equal("foo");
-
- context.set("global", "abc.def", "bar");
- keys = context.keys("global");
- keys.should.have.length(2);
- keys[1].should.equal("abc");
- });
-
- it('should not return specific keys as global context keys', function () {
- var keys = context.keys("global");
-
- context.set("global", "set", "bar");
- context.set("global", "get", "bar");
- context.set("global", "keys", "bar");
- keys = context.keys("global");
- keys.should.have.length(0);
- });
- });
-
- describe('async',function() {
- it('should enumerate context keys', function(done) {
- context.keys("nodeX", function(err, keys) {
- keys.should.be.an.Array();
- keys.should.be.empty();
- context.set("nodeX", "foo", "bar", function(err) {
- context.keys("nodeX", function(err, keys) {
- keys.should.have.length(1);
- keys[0].should.equal("foo");
- context.set("nodeX","abc.def","bar",function(err){
- context.keys("nodeX",function(err, keys){
- keys.should.have.length(2);
- keys[1].should.equal("abc");
- done();
- });
- });
- });
- });
- });
- });
- });
- });
-
- describe('#delete',function() {
- it('should delete context',function() {
- should.not.exist(context.get("nodeX","foo"));
- should.not.exist(context.get("nodeY","foo"));
- context.set("nodeX","foo","abc");
- context.set("nodeY","foo","abc");
- context.get("nodeX","foo").should.equal("abc");
- context.get("nodeY","foo").should.equal("abc");
-
- return context.delete("nodeX").then(function(){
- should.not.exist(context.get("nodeX","foo"));
- should.exist(context.get("nodeY","foo"));
- });
- });
- });
-
- describe('#clean',function() {
- it('should clean unnecessary context',function() {
- should.not.exist(context.get("nodeX","foo"));
- should.not.exist(context.get("nodeY","foo"));
- context.set("nodeX","foo","abc");
- context.set("nodeY","foo","abc");
- context.get("nodeX","foo").should.equal("abc");
- context.get("nodeY","foo").should.equal("abc");
-
- return context.clean([]).then(function(){
- should.not.exist(context.get("nodeX","foo"));
- should.not.exist(context.get("nodeY","foo"));
- });
- });
- it('should not clean active context',function() {
- should.not.exist(context.get("nodeX","foo"));
- should.not.exist(context.get("nodeY","foo"));
- context.set("nodeX","foo","abc");
- context.set("nodeY","foo","abc");
- context.get("nodeX","foo").should.equal("abc");
- context.get("nodeY","foo").should.equal("abc");
-
- return context.clean(["nodeX"]).then(function(){
- should.exist(context.get("nodeX","foo"));
- should.not.exist(context.get("nodeY","foo"));
- });
- });
- it('should not clean global context', function () {
- context.set("global", "foo", "abc");
- context.get("global", "foo").should.equal("abc");
-
- return context.clean(["global"]).then(function () {
- should.exist(context.get("global", "foo"));
- });
- });
- });
-
-});
diff --git a/test/unit/@node-red/runtime/lib/nodes/credentials_spec.js b/test/unit/@node-red/runtime/lib/nodes/credentials_spec.js
deleted file mode 100644
index 6db0b867b..000000000
--- a/test/unit/@node-red/runtime/lib/nodes/credentials_spec.js
+++ /dev/null
@@ -1,474 +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 util = require("util");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-var index = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/index");
-var credentials = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/credentials");
-var log = NR_TEST_UTILS.require("@node-red/util").log;
-
-
-describe('red/runtime/nodes/credentials', function() {
-
- var encryptionDisabledSettings = {
- get: function(key) {
- return false;
- }
- }
-
- afterEach(function() {
- index.clearRegistry();
- });
-
- it('loads provided credentials',function() {
- credentials.init({
- log: log,
- settings: encryptionDisabledSettings
- });
-
- return credentials.load({"a":{"b":1,"c":2}}).then(function() {
- credentials.get("a").should.have.property('b',1);
- credentials.get("a").should.have.property('c',2);
- });
- });
- it('adds a new credential',function() {
- credentials.init({
- log: log,
- settings: encryptionDisabledSettings
- });
- return credentials.load({"a":{"b":1,"c":2}}).then(function() {
- credentials.dirty().should.be.false();
- should.not.exist(credentials.get("b"));
- return credentials.add("b",{"foo":"bar"}).then(function() {
- credentials.get("b").should.have.property("foo","bar");
- credentials.dirty().should.be.true();
- });
- });
- });
- it('deletes an existing credential',function() {
- credentials.init({
- log: log,
- settings: encryptionDisabledSettings
- });
- return credentials.load({"a":{"b":1,"c":2}}).then(function() {
- credentials.dirty().should.be.false();
- credentials.delete("a");
- should.not.exist(credentials.get("a"));
- credentials.dirty().should.be.true();
- });
- });
-
- it('exports the credentials, clearing dirty flag', function() {
- credentials.init({
- log: log,
- settings: encryptionDisabledSettings
- });
- var creds = {"a":{"b":1,"c":2}};
- return credentials.load(creds).then(function() {
- return credentials.add("b",{"foo":"bar"})
- }).then(function() {
- credentials.dirty().should.be.true();
- return credentials.export().then(function(exported) {
- exported.should.eql(creds);
- credentials.dirty().should.be.false();
- })
- });
- })
-
- describe("#clean",function() {
- it("removes credentials of unknown nodes",function() {
- credentials.init({
- log: log,
- settings: encryptionDisabledSettings,
- nodes: { getType: () => function(){} }
- });
- var creds = {"a":{"b":1,"c":2},"b":{"d":3}};
- return credentials.load(creds).then(function() {
- credentials.dirty().should.be.false();
- should.exist(credentials.get("a"));
- should.exist(credentials.get("b"));
- return credentials.clean([{id:"b"}]).then(function() {
- credentials.dirty().should.be.true();
- should.not.exist(credentials.get("a"));
- should.exist(credentials.get("b"));
- });
- });
- });
- it("extracts credentials of known nodes",function() {
- credentials.init({
- log: log,
- settings: encryptionDisabledSettings,
- nodes: { getType: () => function(){} }
- });
- credentials.register("testNode",{"b":"text","c":"password"})
- var creds = {"a":{"b":1,"c":2}};
- var newConfig = [{id:"a",type:"testNode",credentials:{"b":"newBValue","c":"newCValue"}}];
- return credentials.load(creds).then(function() {
- credentials.dirty().should.be.false();
- return credentials.clean(newConfig).then(function() {
- credentials.dirty().should.be.true();
- credentials.get("a").should.have.property('b',"newBValue");
- credentials.get("a").should.have.property('c',"newCValue");
- should.not.exist(newConfig[0].credentials);
- });
- });
- });
-
-
- });
-
- it('warns if a node has no credential definition', function() {
- credentials.init({
- log: log,
- settings: encryptionDisabledSettings,
- nodes: { getType: () => function(){} }
- });
- return credentials.load({}).then(function() {
- var node = {id:"node",type:"test",credentials:{
- user1:"newUser",
- password1:"newPassword"
- }};
- sinon.spy(log,"warn");
- credentials.extract(node);
- log.warn.called.should.be.true();
- should.not.exist(node.credentials);
- log.warn.restore();
- });
- })
-
- it('extract credential updates in the provided node', function(done) {
- credentials.init({
- log: log,
- settings: encryptionDisabledSettings,
- nodes: { getType: () => function(){} }
- });
- var defintion = {
- user1:{type:"text"},
- password1:{type:"password"},
- user2:{type:"text"},
- password2:{type:"password"},
- user3:{type:"text"},
- password3:{type:"password"}
-
- };
- credentials.register("test",defintion);
- var def = credentials.getDefinition("test");
- defintion.should.eql(def);
-
- credentials.load({"node":{user1:"abc",password1:"123",user2:"def",password2:"456",user3:"ghi",password3:"789"}}).then(function() {
- var node = {id:"node",type:"test",credentials:{
- // user1 unchanged
- password1:"__PWRD__",
- user2: "",
- password2:" ",
- user3:"newUser",
- password3:"newPassword"
- }};
- credentials.dirty().should.be.false();
- credentials.extract(node);
-
- node.should.not.have.a.property("credentials");
-
- credentials.dirty().should.be.true();
- var newCreds = credentials.get("node");
- newCreds.should.have.a.property("user1","abc");
- newCreds.should.have.a.property("password1","123");
- newCreds.should.not.have.a.property("user2");
- newCreds.should.not.have.a.property("password2");
- newCreds.should.have.a.property("user3","newUser");
- newCreds.should.have.a.property("password3","newPassword");
-
- done();
- });
- });
- it('extract ignores node without credentials', function(done) {
- credentials.init({
- log: log,
- settings: encryptionDisabledSettings,
- nodes: { getType: () => function(){} }
- });
- credentials.load({"node":{user1:"abc",password1:"123"}}).then(function() {
- var node = {id:"node",type:"test"};
-
- credentials.dirty().should.be.false();
- credentials.extract(node);
- credentials.dirty().should.be.false();
- done();
- });
- });
-
- describe("encryption",function() {
- var settings = {};
- var runtime = {
- log: log,
- settings: {
- get: function(key) {
- return settings[key];
- },
- set: function(key,value) {
- settings[key] = value;
- return Promise.resolve();
- },
- delete: function(key) {
- delete settings[key];
- return Promise.resolve();
- }
- },
- nodes: { getType: () => function(){} }
- }
- it('migrates to encrypted and generates default key', function(done) {
- settings = {};
- credentials.init(runtime);
- credentials.load({"node":{user1:"abc",password1:"123"}}).then(function() {
- settings.should.have.a.property("_credentialSecret");
- settings._credentialSecret.should.have.a.length(64);
- credentials.dirty().should.be.true();
- credentials.export().then(function(result) {
- result.should.have.a.property("$");
- // reset everything - but with _credentialSecret still set
- credentials.init(runtime);
- // load the freshly encrypted version
- credentials.load(result).then(function() {
- should.exist(credentials.get("node"));
- done();
- })
- });
- });
- });
- it('uses default key', function(done) {
- settings = {
- _credentialSecret: "e3a36f47f005bf2aaa51ce3fc6fcaafd79da8d03f2b1a9281f8fb0a285e6255a"
- };
- // {"node":{user1:"abc",password1:"123"}}
- var cryptedFlows = {"$":"5b89d8209b5158a3c313675561b1a5b5phN1gDBe81Zv98KqS/hVDmc9EKvaKqRIvcyXYvBlFNzzzJtvN7qfw06i"};
- credentials.init(runtime);
- credentials.load(cryptedFlows).then(function() {
- should.exist(credentials.get("node"));
- credentials.dirty().should.be.false();
- credentials.add("node",{user1:"def",password1:"456"});
- credentials.export().then(function(result) {
- result.should.have.a.property("$");
- // reset everything - but with _credentialSecret still set
- credentials.init(runtime);
- // load the freshly encrypted version
- credentials.load(result).then(function() {
- should.exist(credentials.get("node"));
- credentials.get("node").should.have.a.property("user1","def");
- credentials.get("node").should.have.a.property("password1","456");
- done();
- })
- });
- });
- });
- it('uses user key', function(done) {
- settings = {
- credentialSecret: "e3a36f47f005bf2aaa51ce3fc6fcaafd79da8d03f2b1a9281f8fb0a285e6255a"
- };
- // {"node":{user1:"abc",password1:"123"}}
- var cryptedFlows = {"$":"5b89d8209b5158a3c313675561b1a5b5phN1gDBe81Zv98KqS/hVDmc9EKvaKqRIvcyXYvBlFNzzzJtvN7qfw06i"};
- credentials.init(runtime);
- credentials.load(cryptedFlows).then(function() {
- credentials.dirty().should.be.false();
- should.exist(credentials.get("node"));
- credentials.add("node",{user1:"def",password1:"456"});
- credentials.export().then(function(result) {
- result.should.have.a.property("$");
-
- // reset everything - but with _credentialSecret still set
- credentials.init(runtime);
- // load the freshly encrypted version
- credentials.load(result).then(function() {
- should.exist(credentials.get("node"));
- credentials.get("node").should.have.a.property("user1","def");
- credentials.get("node").should.have.a.property("password1","456");
- done();
- })
- });
- });
- });
- it('uses user key - when settings are otherwise unavailable', function(done) {
- var runtime = {
- log: log,
- settings: {
- get: function(key) {
- if (key === 'credentialSecret') {
- return "e3a36f47f005bf2aaa51ce3fc6fcaafd79da8d03f2b1a9281f8fb0a285e6255a";
- }
- throw new Error();
- },
- set: function(key,value) {
- throw new Error();
- }
- }
- }
- // {"node":{user1:"abc",password1:"123"}}
- var cryptedFlows = {"$":"5b89d8209b5158a3c313675561b1a5b5phN1gDBe81Zv98KqS/hVDmc9EKvaKqRIvcyXYvBlFNzzzJtvN7qfw06i"};
- credentials.init(runtime);
- credentials.load(cryptedFlows).then(function() {
- should.exist(credentials.get("node"));
- credentials.add("node",{user1:"def",password1:"456"});
- credentials.export().then(function(result) {
- result.should.have.a.property("$");
-
- // reset everything - but with _credentialSecret still set
- credentials.init(runtime);
- // load the freshly encrypted version
- credentials.load(result).then(function() {
- should.exist(credentials.get("node"));
- credentials.get("node").should.have.a.property("user1","def");
- credentials.get("node").should.have.a.property("password1","456");
- done();
- })
- });
- });
- });
- it('migrates from default key to user key', function() {
- settings = {
- _credentialSecret: "e3a36f47f005bf2aaa51ce3fc6fcaafd79da8d03f2b1a9281f8fb0a285e6255a",
- credentialSecret: "aaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbcccccccccccccddddddddddddeeeee"
- };
- // {"node":{user1:"abc",password1:"123"}}
- var cryptedFlows = {"$":"5b89d8209b5158a3c313675561b1a5b5phN1gDBe81Zv98KqS/hVDmc9EKvaKqRIvcyXYvBlFNzzzJtvN7qfw06i"};
- credentials.init(runtime);
- return credentials.load(cryptedFlows).then(function() {
- credentials.dirty().should.be.true();
- should.exist(credentials.get("node"));
- return credentials.export().then(function(result) {
- result.should.have.a.property("$");
- settings.should.not.have.a.property("_credentialSecret");
-
- // reset everything - but with _credentialSecret still set
- credentials.init(runtime);
- // load the freshly encrypted version
- return credentials.load(result).then(function() {
- should.exist(credentials.get("node"));
- credentials.get("node").should.have.a.property("user1","abc");
- credentials.get("node").should.have.a.property("password1","123");
- })
- });
- });
- });
-
- it('migrates from default key to user key - unencrypted original', function(done) {
- settings = {
- _credentialSecret: "e3a36f47f005bf2aaa51ce3fc6fcaafd79da8d03f2b1a9281f8fb0a285e6255a",
- credentialSecret: "aaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbcccccccccccccddddddddddddeeeee"
- };
- // {"node":{user1:"abc",password1:"123"}}
- var unencryptedFlows = {"node":{user1:"abc",password1:"123"}};
- credentials.init(runtime);
- credentials.load(unencryptedFlows).then(function() {
- credentials.dirty().should.be.true();
- should.exist(credentials.get("node"));
- credentials.export().then(function(result) {
- result.should.have.a.property("$");
- settings.should.not.have.a.property("_credentialSecret");
-
- // reset everything - but with _credentialSecret still set
- credentials.init(runtime);
- // load the freshly encrypted version
- credentials.load(result).then(function() {
- should.exist(credentials.get("node"));
- credentials.get("node").should.have.a.property("user1","abc");
- credentials.get("node").should.have.a.property("password1","123");
- done();
- })
- });
- });
- });
-
- it('migrates from default key to unencrypted', function(done) {
- settings = {
- _credentialSecret: "e3a36f47f005bf2aaa51ce3fc6fcaafd79da8d03f2b1a9281f8fb0a285e6255a",
- credentialSecret: false
- };
- // {"node":{user1:"abc",password1:"123"}}
- var cryptedFlows = {"$":"5b89d8209b5158a3c313675561b1a5b5phN1gDBe81Zv98KqS/hVDmc9EKvaKqRIvcyXYvBlFNzzzJtvN7qfw06i"};
- credentials.init(runtime);
- credentials.load(cryptedFlows).then(function() {
- credentials.dirty().should.be.true();
- should.exist(credentials.get("node"));
- credentials.export().then(function(result) {
- result.should.not.have.a.property("$");
- settings.should.not.have.a.property("_credentialSecret");
- result.should.eql({"node":{user1:"abc",password1:"123"}});
- done();
- });
- });
- });
- it('handles bad default key - resets credentials', function(done) {
- settings = {
- _credentialSecret: "badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadb"
- };
- // {"node":{user1:"abc",password1:"123"}}
- var cryptedFlows = {"$":"5b89d8209b5158a3c313675561b1a5b5phN1gDBe81Zv98KqS/hVDmc9EKvaKqRIvcyXYvBlFNzzzJtvN7qfw06i"};
- credentials.init(runtime);
- credentials.load(cryptedFlows).then(function() {
- // credentials.dirty().should.be.true();
- // should.not.exist(credentials.get("node"));
- done();
- }).catch(function(err) {
- err.should.have.property('code','credentials_load_failed');
- done();
- });
- });
- it('handles bad user key - resets credentials', function(done) {
- settings = {
- credentialSecret: "badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadb"
- };
- // {"node":{user1:"abc",password1:"123"}}
- var cryptedFlows = {"$":"5b89d8209b5158a3c313675561b1a5b5phN1gDBe81Zv98KqS/hVDmc9EKvaKqRIvcyXYvBlFNzzzJtvN7qfw06i"};
- credentials.init(runtime);
- credentials.load(cryptedFlows).then(function() {
- // credentials.dirty().should.be.true();
- // should.not.exist(credentials.get("node"));
- done();
- }).catch(function(err) {
- err.should.have.property('code','credentials_load_failed');
- done();
- });
- });
-
- it('handles unavailable settings - leaves creds unencrypted', function(done) {
- var runtime = {
- log: log,
- settings: {
- get: function(key) {
- throw new Error();
- },
- set: function(key,value) {
- throw new Error();
- }
- },
- nodes: { getType: () => function(){} }
- }
- // {"node":{user1:"abc",password1:"123"}}
- credentials.init(runtime);
- credentials.load({"node":{user1:"abc",password1:"123"}}).then(function() {
- credentials.dirty().should.be.false();
- should.exist(credentials.get("node"));
- credentials.export().then(function(result) {
- result.should.not.have.a.property("$");
- result.should.have.a.property("node");
- done();
- });
- });
- });
- })
-})
diff --git a/test/unit/@node-red/runtime/lib/nodes/index_spec.js b/test/unit/@node-red/runtime/lib/nodes/index_spec.js
deleted file mode 100644
index d6017db45..000000000
--- a/test/unit/@node-red/runtime/lib/nodes/index_spec.js
+++ /dev/null
@@ -1,404 +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-extra');
-var path = require('path');
-var sinon = require('sinon');
-var inherits = require("util").inherits;
-
-var NR_TEST_UTILS = require("nr-test-utils");
-var index = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/index");
-var flows = NR_TEST_UTILS.require("@node-red/runtime/lib/flows");
-var registry = NR_TEST_UTILS.require("@node-red/registry")
-var Node = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/Node");
-
-describe("red/nodes/index", function() {
- before(function() {
- sinon.stub(index,"startFlows");
- process.env.NODE_RED_HOME = NR_TEST_UTILS.resolve("node-red");
- process.env.foo="bar";
- });
- after(function() {
- index.startFlows.restore();
- delete process.env.NODE_RED_HOME;
- delete process.env.foo;
- });
-
- afterEach(function() {
- index.clearRegistry();
- });
-
- var testFlows = [{"type":"test","id":"tab1","label":"Sheet 1"}];
- var testCredentials = {"tab1":{"b":1, "c":"2", "d":"$(foo)"}};
- var storage = {
- getFlows: function() {
- return Promise.resolve({red:123,flows:testFlows,credentials:testCredentials});
- },
- saveFlows: function(conf) {
- should.deepEqual(testFlows, conf.flows);
- return Promise.resolve(123);
- }
- };
-
- var settings = {
- available: function() { return false },
- get: function() { return false }
- };
-
- var EventEmitter = require('events').EventEmitter;
- var runtime = {
- settings: settings,
- storage: storage,
- log: {debug:function() {}, warn:function() {}},
- events: new EventEmitter()
- };
-
- function TestNode(n) {
- this._flow = {getSetting: p => process.env[p]};
- index.createNode(this, n);
- this.on("log", function() {
- // do nothing
- });
- }
-
- it('nodes are initialised with credentials',function(done) {
- index.init(runtime);
- index.registerType('test-node-set','test', TestNode);
- index.loadFlows().then(function() {
- var testnode = new TestNode({id:'tab1',type:'test',name:'barney'});
- testnode.credentials.should.have.property('b',1);
- testnode.credentials.should.have.property('c',"2");
- testnode.credentials.should.have.property('d',"bar");
- done();
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('flows should be initialised',function(done) {
- index.init(runtime);
- index.loadFlows().then(function() {
- // console.log(testFlows);
- // console.log(index.getFlows());
- should.deepEqual(testFlows, index.getFlows().flows);
- done();
- }).catch(function(err) {
- done(err);
- });
-
- });
- describe("registerType", function() {
- describe("logs deprecated usage", function() {
- before(function() {
- sinon.stub(registry,"registerType");
- });
- after(function() {
- registry.registerType.restore();
- });
- it("called without node-set name", function() {
- var runtime = {
- settings: settings,
- storage: storage,
- log: {debug:function() {}, warn:sinon.spy()},
- events: new EventEmitter()
- }
- index.init(runtime);
-
- index.registerType(/*'test-node-set',*/'test', TestNode, {});
- runtime.log.warn.called.should.be.true();
- registry.registerType.called.should.be.true();
- registry.registerType.firstCall.args[0].should.eql('');
- registry.registerType.firstCall.args[1].should.eql('test');
- registry.registerType.firstCall.args[2].should.eql(TestNode);
- });
- });
- describe("extends constructor with Node constructor", function() {
- var TestNodeConstructor;
- before(function() {
- sinon.stub(registry,"registerType");
- });
- after(function() {
- registry.registerType.restore();
- });
- beforeEach(function() {
- TestNodeConstructor = function TestNodeConstructor() {};
- var runtime = {
- settings: settings,
- storage: storage,
- log: {debug:function() {}, warn:sinon.spy()},
- events: new EventEmitter()
- }
- index.init(runtime);
- })
- it('extends a constructor with the Node constructor', function() {
- TestNodeConstructor.prototype.should.not.be.an.instanceOf(Node);
- index.registerType('node-set','node-type',TestNodeConstructor);
- TestNodeConstructor.prototype.should.be.an.instanceOf(Node);
- });
- it('does not override a constructor prototype', function() {
- function Foo(){};
- inherits(TestNodeConstructor,Foo);
- TestNodeConstructor.prototype.should.be.an.instanceOf(Foo);
- TestNodeConstructor.prototype.should.not.be.an.instanceOf(Node);
-
- index.registerType('node-set','node-type',TestNodeConstructor);
-
- TestNodeConstructor.prototype.should.be.an.instanceOf(Node);
- TestNodeConstructor.prototype.should.be.an.instanceOf(Foo);
-
- index.registerType('node-set','node-type2',TestNodeConstructor);
- TestNodeConstructor.prototype.should.be.an.instanceOf(Node);
- TestNodeConstructor.prototype.should.be.an.instanceOf(Foo);
- });
- });
- describe("register credentials definition", function() {
- var http = require('http');
- var express = require('express');
- var app = express();
- var runtime = NR_TEST_UTILS.require("@node-red/runtime");
- var credentials = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/credentials");
- var localfilesystem = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/localfilesystem");
- var log = NR_TEST_UTILS.require("@node-red/util").log;
- var RED = NR_TEST_UTILS.require("node-red/lib/red.js");
-
- var userDir = path.join(__dirname,".testUserHome");
- before(function(done) {
- sinon.stub(log,"log").callsFake(function(){});
- fs.remove(userDir,function(err) {
- fs.mkdir(userDir,function() {
- sinon.stub(index, 'load').callsFake(function() {
- return new Promise(function(resolve,reject){
- resolve([]);
- });
- });
- sinon.stub(localfilesystem, 'getCredentials').callsFake(function() {
- return new Promise(function(resolve,reject) {
- resolve({"tab1":{"b":1,"c":2}});
- });
- }) ;
- RED.init(http.createServer(function(req,res){app(req,res)}),
- {userDir: userDir});
- runtime.start().then(function () {
- done();
- });
- });
- });
- });
-
- after(function(done) {
- fs.remove(userDir,function() {
- runtime.stop().then(function() {
- index.load.restore();
- localfilesystem.getCredentials.restore();
- log.log.restore();
- done();
- });
- });
- });
-
- it('definition defined',function() {
- index.registerType('test-node-set','test', TestNode, {
- credentials: {
- foo: {type:"test"}
- }
- });
- var testnode = new TestNode({id:'tab1',type:'test',name:'barney', '_alias':'tab1'});
- index.getCredentialDefinition("test").should.have.property('foo');
- });
- });
-
- describe("register settings definition", function() {
- beforeEach(function() {
- sinon.stub(registry,"registerType");
- })
- afterEach(function() {
- registry.registerType.restore();
- })
- it('registers valid settings',function() {
- var runtime = {
- settings: settings,
- storage: storage,
- log: {debug:function() {}, warn:function() {}},
- events: new EventEmitter()
- }
- runtime.settings.registerNodeSettings = sinon.spy();
- index.init(runtime);
-
- index.registerType('test-node-set','test', TestNode, {
- settings: {
- testOne: {}
- }
- });
- runtime.settings.registerNodeSettings.called.should.be.true();
- runtime.settings.registerNodeSettings.firstCall.args[0].should.eql('test');
- runtime.settings.registerNodeSettings.firstCall.args[1].should.eql({testOne: {}});
- });
- it('logs invalid settings',function() {
- var runtime = {
- settings: settings,
- storage: storage,
- log: {debug:function() {}, warn:sinon.spy()},
- events: new EventEmitter()
- }
- runtime.settings.registerNodeSettings = function() { throw new Error("pass");}
- index.init(runtime);
-
- index.registerType('test-node-set','test', TestNode, {
- settings: {
- testOne: {}
- }
- });
- runtime.log.warn.called.should.be.true();
- });
- });
- });
-
- describe('allows nodes to be added/removed/enabled/disabled from the registry', function() {
- var randomNodeInfo = {id:"5678",types:["random"]};
-
- beforeEach(function() {
- sinon.stub(registry,"getNodeInfo").callsFake(function(id) {
- if (id == "test") {
- return {id:"1234",types:["test"]};
- } else if (id == "doesnotexist") {
- return null;
- } else {
- return randomNodeInfo;
- }
- });
- sinon.stub(registry,"disableNode").callsFake(function(id) {
- return Promise.resolve(randomNodeInfo);
- });
- });
- afterEach(function() {
- registry.getNodeInfo.restore();
- registry.disableNode.restore();
- });
-
- it('allows an unused node type to be disabled',function(done) {
- index.init(runtime);
- index.registerType('test-node-set','test', TestNode);
- index.loadFlows().then(function() {
- return index.disableNode("5678").then(function(info) {
- registry.disableNode.calledOnce.should.be.true();
- registry.disableNode.calledWith("5678").should.be.true();
- info.should.eql(randomNodeInfo);
- done();
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('prevents disabling a node type that is in use',function(done) {
- index.init(runtime);
- index.registerType('test-node-set','test', TestNode);
- index.loadFlows().then(function() {
- /*jshint immed: false */
- (function() {
- index.disabledNode("test");
- }).should.throw();
-
- done();
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('prevents disabling a node type that is unknown',function(done) {
- index.init(runtime);
- index.registerType('test-node-set','test', TestNode);
- index.loadFlows().then(function() {
- /*jshint immed: false */
- (function() {
- index.disableNode("doesnotexist");
- }).should.throw();
-
- done();
- }).catch(function(err) {
- done(err);
- });
- });
- });
-
- describe('allows modules to be removed from the registry', function() {
- var randomNodeInfo = {id:"5678",types:["random"]};
- var randomModuleInfo = {
- name:"random",
- nodes: [randomNodeInfo]
- };
-
- before(function() {
- sinon.stub(registry,"getNodeInfo").callsFake(function(id) {
- if (id == "node-red/foo") {
- return {id:"1234",types:["test"]};
- } else if (id == "doesnotexist") {
- return null;
- } else {
- return randomNodeInfo;
- }
- });
- sinon.stub(registry,"getModuleInfo").callsFake(function(module) {
- if (module == "node-red") {
- return {nodes:[{name:"foo"}]};
- } else if (module == "doesnotexist") {
- return null;
- } else {
- return randomModuleInfo;
- }
- });
- sinon.stub(registry,"removeModule").callsFake(function(id) {
- return randomModuleInfo;
- });
- });
- after(function() {
- registry.getNodeInfo.restore();
- registry.getModuleInfo.restore();
- registry.removeModule.restore();
- });
-
- it('prevents removing a module that is in use',function(done) {
- index.init(runtime);
- index.registerType('test-node-set','test', TestNode);
- index.loadFlows().then(function() {
- /*jshint immed: false */
- (function() {
- index.removeModule("node-red");
- }).should.throw();
-
- done();
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('prevents removing a module that is unknown',function(done) {
- index.init(runtime);
- index.registerType('test-node-set','test', TestNode);
- index.loadFlows().then(function() {
- /*jshint immed: false */
- (function() {
- index.removeModule("doesnotexist");
- }).should.throw();
-
- done();
- }).catch(function(err) {
- done(err);
- });
- });
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/nodes/resources/local/NestedDirectoryNode/NestedNode/icons/arrow-in.png b/test/unit/@node-red/runtime/lib/nodes/resources/local/NestedDirectoryNode/NestedNode/icons/arrow-in.png
deleted file mode 100644
index e38f3914600901b736f5fa18786ee11be6d41c28..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 393
zcmeAS@N?(olHy`uVBq!ia0vp^B0wz1!3HFCgzU0`6icy_X9x!n)NrJ90QsB+9+AZi
z3~X;em{G3O!W1YdS>hT|5}cn_Ql40p%1~Zju9umYU7Va)kgAtols@~NjT8d|Bb%p-
zV~9uR+N-+$hZ97Oeyp#Y$RU!&XX#m>@|$agvYL9Jz$O6}72y^gZVi>ZMeaH^t*Q|!
zLhVk<0xdko8zYVo#8M-LBBd8b>1kw|i?FO)bWqsy_rwQg27N4y
zeX6pqO$_Cex^^A7_NsS@+=bOASA^wN0&GKN(hlAguRU&q-
jTBY?`*L>xN+|S&+7B*edvmQhOgN?z{)z4*}Q$iB}+9!`i
diff --git a/test/unit/@node-red/runtime/lib/nodes/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/arrow-in.png b/test/unit/@node-red/runtime/lib/nodes/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/arrow-in.png
deleted file mode 100644
index 59a29af14..000000000
--- a/test/unit/@node-red/runtime/lib/nodes/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/arrow-in.png
+++ /dev/null
@@ -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
diff --git a/test/unit/@node-red/runtime/lib/plugins_spec.js b/test/unit/@node-red/runtime/lib/plugins_spec.js
deleted file mode 100644
index a78de643c..000000000
--- a/test/unit/@node-red/runtime/lib/plugins_spec.js
+++ /dev/null
@@ -1,13 +0,0 @@
-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
- })
-});
diff --git a/test/unit/@node-red/runtime/lib/settings_spec.js b/test/unit/@node-red/runtime/lib/settings_spec.js
deleted file mode 100644
index 51c190fea..000000000
--- a/test/unit/@node-red/runtime/lib/settings_spec.js
+++ /dev/null
@@ -1,333 +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 settings = NR_TEST_UTILS.require("@node-red/runtime/lib/settings");
-
-
-describe("runtime/settings", function() {
-
- afterEach(function() {
- settings.reset();
- });
-
- it('wraps the user settings as read-only properties', function() {
- var userSettings = {
- a: 123,
- b: "test",
- c: [1,2,3]
- }
- settings.init(userSettings);
-
- settings.available().should.be.false();
-
- settings.a.should.equal(123);
- settings.b.should.equal("test");
- settings.c.should.be.an.Array();
- settings.c.should.have.lengthOf(3);
-
- settings.get("a").should.equal(123);
- settings.get("b").should.equal("test");
- settings.get("c").should.be.an.Array();
- settings.get("c").should.have.lengthOf(3);
-
- /*jshint immed: false */
- (function() {
- settings.a = 456;
- }).should.throw();
-
- settings.c.push(5);
- settings.c.should.be.an.Array();
- settings.c.should.have.lengthOf(4);
-
- /*jshint immed: false */
- (function() {
- settings.set("a",456);
- }).should.throw();
-
- /*jshint immed: false */
- (function() {
- settings.set("a",456);
- }).should.throw();
-
- /*jshint immed: false */
- (function() {
- settings.get("unknown");
- }).should.throw();
-
- /*jshint immed: false */
- (function() {
- settings.set("unknown",456);
- }).should.throw();
-
- });
-
- it('loads global settings from storage', function(done) {
- var userSettings = {
- a: 123,
- b: "test",
- c: [1,2,3]
- }
- var savedSettings = null;
- var saveCount = 0;
- var storage = {
- getSettings: function() {
- return Promise.resolve({globalA:789});
- },
- saveSettings: function(settings) {
- saveCount++;
- savedSettings = settings;
- return Promise.resolve();
- }
- }
- settings.init(userSettings);
-
- settings.available().should.be.false();
-
- /*jshint immed: false */
- (function() {
- settings.get("unknown");
- }).should.throw();
- settings.load(storage).then(function() {
- settings.available().should.be.true();
- settings.get("globalA").should.equal(789);
- settings.set("globalA","abc").then(function() {
- savedSettings.globalA.should.equal("abc");
- saveCount.should.equal(1);
- settings.set("globalA","abc").then(function() {
- savedSettings.globalA.should.equal("abc");
- // setting to existing value should not trigger save
- saveCount.should.equal(1);
- done();
- });
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('removes persistent settings when reset', function() {
- var userSettings = {
- a: 123,
- b: "test",
- c: [1,2,3]
- }
- settings.init(userSettings);
-
- settings.available().should.be.false();
-
- settings.should.have.property("a",123);
- settings.should.have.property("b","test");
- settings.c.should.be.an.Array();
- settings.c.should.have.lengthOf(3);
-
- settings.reset();
-
- settings.should.not.have.property("a");
- settings.should.not.have.property("d");
- settings.should.not.have.property("c");
-
- });
-
- it('registers node settings and exports them', function() {
- var userSettings = {};
- settings.init(userSettings);
- settings.registerNodeSettings("inject", {injectColor:{value:"red", exportable:true}, injectSize:{value:"100", exportable:true}} );
- settings.registerNodeSettings("mqtt", {mqttColor:{value:"purple", exportable:false}, mqttSize:{value:"50", exportable:true}} );
- settings.registerNodeSettings("http request", {httpRequest1:{value:"a1", exportable:true}} );
- settings.registerNodeSettings(" http--request<> ", {httpRequest2:{value:"a2", exportable:true}} );
- settings.registerNodeSettings("_http_request_", {httpRequest3:{value:"a3", exportable:true}} );
- settings.registerNodeSettings("mQtT", {mQtTColor:{value:"purple", exportable:true}} );
- settings.registerNodeSettings("abc123", {abc123:{value:"def456", exportable:true}} );
- settings.registerNodeSettings("noValue", {noValueHasValue:{value:"123", exportable:true}, noValueNoValue:{exportable:true}} );
-
- var safeSettings = {};
- settings.exportNodeSettings(safeSettings);
- safeSettings.should.have.property("injectColor", "red");
- safeSettings.should.have.property("injectSize", "100");
- safeSettings.should.not.have.property("mqttColor");
- safeSettings.should.have.property("mqttSize", "50");
- safeSettings.should.have.property("httpRequest1", "a1");
- safeSettings.should.have.property("httpRequest2", "a2");
- safeSettings.should.have.property("httpRequest3", "a3");
- safeSettings.should.have.property("mQtTColor", "purple");
- safeSettings.should.have.property("abc123", "def456");
-
- safeSettings.should.have.property("noValueHasValue", "123");
- safeSettings.should.not.have.property("noValueNoValue");
- });
-
- it('prohibits registering the property whose name do not start with type name', function() {
- var userSettings = {};
- settings.init(userSettings);
- (function() {
- settings.registerNodeSettings("inject", {color:{value:"red", exportable:true}} );
- }).should.throw();
- (function() {
- settings.registerNodeSettings("_a_b_1_", {ab1Color:{value:"red", exportable:true}} );
- }).should.throw();
- (function() {
- settings.registerNodeSettings("AB2", {AB2Color:{value:"red", exportable:true}} );
- }).should.throw();
- (function() {
- settings.registerNodeSettings("abcDef", {abcColor:{value:"red", exportable:true}} );
- }).should.throw();
- var safeSettings = {};
- settings.exportNodeSettings(safeSettings);
- safeSettings.should.not.have.property("color");
- safeSettings.should.not.have.property("ab1Color", "blue");
- safeSettings.should.not.have.property("AB2Color");
- safeSettings.should.not.have.property("abcColor");
- });
-
- it('overwrites node settings with user settings', function() {
- var userSettings = {
- injectColor: "green",
- mqttColor: "yellow",
- abColor: [1,2,3]
- }
- settings.init(userSettings);
- settings.registerNodeSettings("inject", {injectColor:{value:"red", exportable:true}} );
- settings.registerNodeSettings("ab", {abColor:{value:"red", exportable:false}} );
- var safeSettings = {};
- settings.exportNodeSettings(safeSettings);
- safeSettings.should.have.property("injectColor", "green");
- safeSettings.should.not.have.property("mqttColor");
- safeSettings.should.not.have.property("abColor");
- });
-
- it('disables/enables node settings', function() {
- var userSettings = {};
- settings.init(userSettings);
-
- var safeSettings = {};
- settings.registerNodeSettings("inject", {injectColor:{value:"red", exportable:true}} );
- settings.registerNodeSettings("mqtt", {mqttColor:{value:"purple", exportable:true}} );
- settings.registerNodeSettings("http request", {httpRequestColor:{value:"yellow", exportable:true}} );
- settings.exportNodeSettings(safeSettings);
- safeSettings.should.have.property("injectColor", "red");
- safeSettings.should.have.property("mqttColor", "purple");
- safeSettings.should.have.property("httpRequestColor", "yellow");
-
- safeSettings = {};
- var types = ["inject", "mqtt"];
- settings.disableNodeSettings(types);
- settings.exportNodeSettings(safeSettings);
- safeSettings.should.not.have.property("injectColor");
- safeSettings.should.not.have.property("mqttColor");
- safeSettings.should.have.property("httpRequestColor", "yellow");
-
- safeSettings = {};
- types = ["inject"];
- settings.enableNodeSettings(types);
- settings.exportNodeSettings(safeSettings);
- safeSettings.should.have.property("injectColor", "red");
- safeSettings.should.not.have.property("mqttColor");
- safeSettings.should.have.property("httpRequestColor", "yellow");
- });
-
-
- it('delete global setting', function() {
- // read-only
- var localSettings = {a:1};
- // read-write
- var globalSettings = {b:2};
- var storage = {
- getSettings: function() {
- return Promise.resolve(globalSettings);
- },
- saveSettings: function() {
- return Promise.resolve();
- }
- }
- settings.init(localSettings);
- return settings.load(storage).then(function() {
- settings.get('a').should.eql(1);
- settings.get('b').should.eql(2);
- return settings.delete('b')
- }).then(function() {
- should.not.exist(settings.get('b'));
- })
- });
-
- it('refused to delete local setting', function(done) {
- // read-only
- var localSettings = {a:1};
- // read-write
- var globalSettings = {b:2};
- var storage = {
- getSettings: function() {
- return Promise.resolve(globalSettings);
- }
- }
- settings.init(localSettings);
- settings.load(storage).then(function() {
- settings.get('a').should.eql(1);
- settings.get('b').should.eql(2);
- try {
- settings.delete('a');
- return done("Did not throw error");
- } catch(err) {
- // expected
- }
- done();
- }).catch(done)
- });
-
-
- it('get user settings', function() {
- var userSettings = {
- admin: {a:1}
- }
- var storage = {
- getSettings: function() {
- return Promise.resolve({a:1,users:userSettings});
- }
- }
- settings.init(userSettings);
- return settings.load(storage).then(function() {
- var result = settings.getUserSettings('admin');
- result.should.eql(userSettings.admin);
- // Check it has been cloned
- result.should.not.equal(userSettings.admin);
- })
- })
- it('set user settings', function() {
- var userSettings = {
- admin: {a:1}
- }
- var savedSettings;
- var storage = {
- getSettings: function() {
- return Promise.resolve({c:3,users:userSettings});
- },
- saveSettings: function(s) {
- savedSettings = s;
- return Promise.resolve();
- }
- }
- settings.init(userSettings);
- return settings.load(storage).then(function() {
- return settings.setUserSettings('admin',{b:2})
- }).then(function() {
- savedSettings.should.have.property("c",3);
- savedSettings.should.have.property('users');
- savedSettings.users.should.eql({admin:{b:2}})
- })
- })
-
-});
diff --git a/test/unit/@node-red/runtime/lib/storage/index_spec.js b/test/unit/@node-red/runtime/lib/storage/index_spec.js
deleted file mode 100644
index dd9fa6e9b..000000000
--- a/test/unit/@node-red/runtime/lib/storage/index_spec.js
+++ /dev/null
@@ -1,271 +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 paff = require('path');
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var storage = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/index");
-
-describe("red/storage/index", function() {
-
- it('rejects the promise when settings suggest loading a bad module', function(done) {
-
- var wrongModule = {
- settings:{
- storageModule : "thisaintloading"
- }
- };
-
- storage.init(wrongModule).then( function() {
- var one = 1;
- var zero = 0;
- try {
- zero.should.equal(one, "The initialization promise should never get resolved");
- } catch(err) {
- done(err);
- }
- }).catch(function(e) {
- done(); //successfully rejected promise
- });
- });
-
- it('non-string storage module', function(done) {
- var initSetsMeToTrue = false;
-
- var moduleWithBooleanSettingInit = {
- init : function() {
- initSetsMeToTrue = true;
- }
- };
-
- var setsBooleanModule = {
- settings: {
- storageModule : moduleWithBooleanSettingInit
- }
- };
-
- storage.init(setsBooleanModule);
- initSetsMeToTrue.should.be.true();
- done();
- });
-
- it('respects storage interface', function(done) {
- var calledFlagGetFlows = false;
- var calledFlagGetCredentials = false;
- var calledFlagGetAllFlows = false;
- var calledInit = false;
- var calledFlagGetSettings = false;
- var calledFlagGetSessions = false;
-
- var interfaceCheckerModule = {
- init : function (settings) {
- settings.should.be.an.Object();
- calledInit = true;
- },
- getFlows : function() {
- calledFlagGetFlows = true;
- return Promise.resolve([]);
- },
- saveFlows : function (flows) {
- flows.should.be.an.Array();
- flows.should.have.lengthOf(0);
- return Promise.resolve("");
- },
- getCredentials : function() {
- calledFlagGetCredentials = true;
- return Promise.resolve({});
- },
- saveCredentials : function(credentials) {
- credentials.should.be.true();
- },
- getSettings : function() {
- calledFlagGetSettings = true;
- },
- saveSettings : function(settings) {
- settings.should.be.true();
- },
- getSessions : function() {
- calledFlagGetSessions = true;
- },
- saveSessions : function(sessions) {
- sessions.should.be.true();
- },
- getAllFlows : function() {
- calledFlagGetAllFlows = true;
- },
- getFlow : function(fn) {
- fn.should.equal("name");
- },
- saveFlow : function(fn, data) {
- fn.should.equal("name");
- data.should.be.true();
- },
- getLibraryEntry : function(type, path) {
- type.should.be.true();
- path.should.equal("name");
- },
- saveLibraryEntry : function(type, path, meta, body) {
- type.should.be.true();
- path.should.equal("name");
- meta.should.be.true();
- body.should.be.true();
- }
- };
-
- var moduleToLoad = {
- settings: {
- storageModule : interfaceCheckerModule
- }
- };
-
- var promises = [];
- storage.init(moduleToLoad);
- promises.push(storage.getFlows());
- promises.push(storage.saveFlows({flows:[],credentials:{}}));
- storage.getSettings();
- storage.saveSettings(true);
- storage.getSessions();
- storage.saveSessions(true);
- storage.getAllFlows();
- storage.getFlow("name");
- storage.saveFlow("name", true);
- storage.getLibraryEntry(true, "name");
- storage.saveLibraryEntry(true, "name", true, true);
-
- Promise.all(promises).then(function() {
- try {
- calledInit.should.be.true();
- calledFlagGetFlows.should.be.true();
- calledFlagGetCredentials.should.be.true();
- calledFlagGetAllFlows.should.be.true();
- done();
- } catch(err) {
- done(err);
- }
- });
- });
-
- describe('respects deprecated flow library functions', function() {
-
- var savePath;
- var saveContent;
- var saveMeta;
- var saveType;
-
- var interfaceCheckerModule = {
- init : function (settings) {
- settings.should.be.an.Object();
- },
- getLibraryEntry : function(type, path) {
- if (type === "flows") {
- if (path === "/" || path === "\\") {
- return Promise.resolve(["a",{fn:"test.json"}]);
- } else if (path == "/a" || path == "\\a") {
- return Promise.resolve([{fn:"test2.json"}]);
- } else if (path == paff.join("","a","test2.json")) {
- return Promise.resolve("test content");
- }
- }
- },
- saveLibraryEntry : function(type, path, meta, body) {
- saveType = type;
- savePath = path;
- saveContent = body;
- saveMeta = meta;
- return Promise.resolve();
- }
- };
-
- var moduleToLoad = {
- settings: {
- storageModule : interfaceCheckerModule
- }
- };
- before(function() {
- storage.init(moduleToLoad);
- });
- it('getAllFlows',function(done) {
- storage.getAllFlows().then(function (res) {
- try {
- res.should.eql({ d: { a: { f: ['test2'] } }, f: [ 'test' ] });
- done();
- } catch(err) {
- done(err);
- }
- });
- });
-
- it('getFlow',function(done) {
- storage.getFlow(paff.join("a","test2.json")).then(function(res) {
- try {
- res.should.eql("test content");
- done();
- } catch(err) {
- done(err);
- }
- });
- });
-
- it ('saveFlow', function (done) {
- storage.saveFlow(paff.join("a","test2.json"),"new content").then(function(res) {
- try {
- savePath.should.eql(paff.join("a","test2.json"));
- saveContent.should.eql("new content");
- saveMeta.should.eql({});
- saveType.should.eql("flows");
- done();
- } catch(err) {
- done(err);
- }
- });
-
- });
- });
-
- describe('handles missing settings/sessions interface', function() {
- before(function() {
- var interfaceCheckerModule = {
- init : function () {}
- };
- storage.init({settings:{storageModule: interfaceCheckerModule}});
- });
-
- it('defaults missing getSettings',function(done) {
- storage.getSettings().then(function(settings) {
- should.not.exist(settings);
- done();
- });
- });
- it('defaults missing saveSettings',function(done) {
- storage.saveSettings({}).then(function() {
- done();
- });
- });
- it('defaults missing getSessions',function(done) {
- storage.getSessions().then(function(settings) {
- should.not.exist(settings);
- done();
- });
- });
- it('defaults missing saveSessions',function(done) {
- storage.saveSessions({}).then(function() {
- done();
- });
- });
- });
-
-});
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/index_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/index_spec.js
deleted file mode 100644
index 65826c9f4..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/index_spec.js
+++ /dev/null
@@ -1,518 +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-extra');
-var path = require('path');
-var sinon = require('sinon');
-var NR_TEST_UTILS = require("nr-test-utils");
-var process = require("process");
-
-var localfilesystem = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/localfilesystem");
-var log = NR_TEST_UTILS.require("@node-red/util").log;
-
-describe('storage/localfilesystem', function() {
- var mockRuntime = {
- log:{
- _:function() { return "placeholder message"},
- info: function() { },
- warn: function() { },
- trace: function() {}
- }
- };
- var userDir = path.join(__dirname,".testUserHome");
- var testFlow = [{"type":"tab","id":"d8be2a6d.2741d8","label":"Sheet 1"}];
- beforeEach(function(done) {
- fs.remove(userDir,function(err) {
- fs.mkdir(userDir,done);
- });
- });
- afterEach(function(done) {
- fs.remove(userDir,done);
- });
-
- it('should initialise the user directory',function(done) {
- localfilesystem.init({userDir:userDir,getUserSettings: () => {{}}}, mockRuntime).then(function() {
- fs.existsSync(path.join(userDir,"lib")).should.be.true();
- fs.existsSync(path.join(userDir,"lib",'flows')).should.be.true();
- done();
- }).catch(function(err) {
- done(err);
- });
- });
-
-
- it('should set userDir to NRH if .config.json presents',function(done) {
- var oldNRH = process.env.NODE_RED_HOME;
- process.env.NODE_RED_HOME = path.join(userDir,"NRH");
- fs.mkdirSync(process.env.NODE_RED_HOME);
- fs.writeFileSync(path.join(process.env.NODE_RED_HOME,".config.json"),"{}","utf8");
- var settings = {getUserSettings: () => {{}}};
- localfilesystem.init(settings, mockRuntime).then(function() {
- try {
- fs.existsSync(path.join(process.env.NODE_RED_HOME,"lib")).should.be.true();
- fs.existsSync(path.join(process.env.NODE_RED_HOME,"lib",'flows')).should.be.true();
- settings.userDir.should.equal(process.env.NODE_RED_HOME);
- done();
- } catch(err) {
- done(err);
- } finally {
- process.env.NODE_RED_HOME = oldNRH;
- }
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should set userDir to HOMEPATH/.node-red if .config.json presents',function(done) {
- var oldNRH = process.env.NODE_RED_HOME;
- process.env.NODE_RED_HOME = path.join(userDir,"NRH");
- var oldHOMEPATH = process.env.HOMEPATH;
- process.env.HOMEPATH = path.join(userDir,"HOMEPATH");
- fs.mkdirSync(process.env.HOMEPATH);
- fs.mkdirSync(path.join(process.env.HOMEPATH,".node-red"));
- fs.writeFileSync(path.join(process.env.HOMEPATH,".node-red",".config.json"),"{}","utf8");
- var settings = {getUserSettings: () => {{}}};
- localfilesystem.init(settings, mockRuntime).then(function() {
- try {
- fs.existsSync(path.join(process.env.HOMEPATH,".node-red","lib")).should.be.true();
- fs.existsSync(path.join(process.env.HOMEPATH,".node-red","lib",'flows')).should.be.true();
- settings.userDir.should.equal(path.join(process.env.HOMEPATH,".node-red"));
- done();
- } catch(err) {
- done(err);
- } finally {
- process.env.NODE_RED_HOME = oldNRH;
- process.env.NODE_HOMEPATH = oldHOMEPATH;
- }
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should set userDir to HOME/.node-red',function(done) {
- var oldNRH = process.env.NODE_RED_HOME;
- process.env.NODE_RED_HOME = path.join(userDir,"NRH");
- var oldHOME = process.env.HOME;
- process.env.HOME = path.join(userDir,"HOME");
- var oldHOMEPATH = process.env.HOMEPATH;
- process.env.HOMEPATH = path.join(userDir,"HOMEPATH");
-
- fs.mkdirSync(process.env.HOME);
- var settings = {getUserSettings: () => {{}}};
- localfilesystem.init(settings, mockRuntime).then(function() {
- try {
- fs.existsSync(path.join(process.env.HOME,".node-red","lib")).should.be.true();
- fs.existsSync(path.join(process.env.HOME,".node-red","lib",'flows')).should.be.true();
- settings.userDir.should.equal(path.join(process.env.HOME,".node-red"));
- done();
- } catch(err) {
- done(err);
- } finally {
- process.env.NODE_RED_HOME = oldNRH;
- process.env.HOME = oldHOME;
- process.env.HOMEPATH = oldHOMEPATH;
- }
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should set userDir to USERPROFILE/.node-red',function(done) {
- var oldNRH = process.env.NODE_RED_HOME;
- process.env.NODE_RED_HOME = path.join(userDir,"NRH");
- var oldHOME = process.env.HOME;
- process.env.HOME = "";
- var oldHOMEPATH = process.env.HOMEPATH;
- process.env.HOMEPATH = path.join(userDir,"HOMEPATH");
- var oldUSERPROFILE = process.env.USERPROFILE;
- process.env.USERPROFILE = path.join(userDir,"USERPROFILE");
-
- fs.mkdirSync(process.env.USERPROFILE);
- var settings = {getUserSettings: () => {{}}};
- localfilesystem.init(settings, mockRuntime).then(function() {
- try {
- fs.existsSync(path.join(process.env.USERPROFILE,".node-red","lib")).should.be.true();
- fs.existsSync(path.join(process.env.USERPROFILE,".node-red","lib",'flows')).should.be.true();
- settings.userDir.should.equal(path.join(process.env.USERPROFILE,".node-red"));
- done();
- } catch(err) {
- done(err);
- } finally {
- process.env.NODE_RED_HOME = oldNRH;
- process.env.HOME = oldHOME;
- process.env.HOMEPATH = oldHOMEPATH;
- process.env.USERPROFILE = oldUSERPROFILE;
- }
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should handle missing flow file',function(done) {
- localfilesystem.init({userDir:userDir,getUserSettings: () => {{}}}, mockRuntime).then(function() {
- var flowFile = 'flows_'+require('os').hostname()+'.json';
- var flowFilePath = path.join(userDir,flowFile);
- fs.existsSync(flowFilePath).should.be.false();
- localfilesystem.getFlows().then(function(flows) {
- flows.should.eql([]);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should handle empty flow file, no backup',function(done) {
- localfilesystem.init({userDir:userDir,getUserSettings: () => {{}}}, mockRuntime).then(function() {
- var flowFile = 'flows_'+require('os').hostname()+'.json';
- var flowFilePath = path.join(userDir,flowFile);
- var flowFileBackupPath = path.join(userDir,"."+flowFile+".backup");
- fs.closeSync(fs.openSync(flowFilePath, 'w'));
- fs.existsSync(flowFilePath).should.be.true();
- localfilesystem.getFlows().then(function(flows) {
- flows.should.eql([]);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should handle empty flow file, restores backup',function(done) {
- localfilesystem.init({userDir:userDir,getUserSettings: () => {{}}}, mockRuntime).then(function() {
- var flowFile = 'flows_'+require('os').hostname()+'.json';
- var flowFilePath = path.join(userDir,flowFile);
- var flowFileBackupPath = path.join(userDir,"."+flowFile+".backup");
- fs.closeSync(fs.openSync(flowFilePath, 'w'));
- fs.existsSync(flowFilePath).should.be.true();
- fs.existsSync(flowFileBackupPath).should.be.false();
- fs.writeFileSync(flowFileBackupPath,JSON.stringify(testFlow));
- fs.existsSync(flowFileBackupPath).should.be.true();
- setTimeout(function() {
- localfilesystem.getFlows().then(function(flows) {
- flows.should.eql(testFlow);
- done();
- }).catch(function(err) {
- done(err);
- });
- },50);
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should save flows to the default file',function(done) {
- localfilesystem.init({userDir:userDir,getUserSettings: () => {{}}}, mockRuntime).then(function() {
- var flowFile = 'flows_'+require('os').hostname()+'.json';
- var flowFilePath = path.join(userDir,flowFile);
- var flowFileBackupPath = path.join(userDir,"."+flowFile+".backup");
- fs.existsSync(flowFilePath).should.be.false();
- fs.existsSync(flowFileBackupPath).should.be.false();
- localfilesystem.saveFlows(testFlow).then(function() {
- fs.existsSync(flowFilePath).should.be.true();
- fs.existsSync(flowFileBackupPath).should.be.false();
- localfilesystem.getFlows().then(function(flows) {
- flows.should.eql(testFlow);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should save flows to the specified file',function(done) {
- var defaultFlowFile = 'flows_'+require('os').hostname()+'.json';
- var defaultFlowFilePath = path.join(userDir,defaultFlowFile);
- var flowFile = 'test.json';
- var flowFilePath = path.join(userDir,flowFile);
-
- localfilesystem.init({userDir:userDir, flowFile:flowFilePath,getUserSettings: () => {{}}}, mockRuntime).then(function() {
- fs.existsSync(defaultFlowFilePath).should.be.false();
- fs.existsSync(flowFilePath).should.be.false();
-
- localfilesystem.saveFlows(testFlow).then(function() {
- fs.existsSync(defaultFlowFilePath).should.be.false();
- fs.existsSync(flowFilePath).should.be.true();
- localfilesystem.getFlows().then(function(flows) {
- flows.should.eql(testFlow);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should format the flows file when flowFilePretty specified',function(done) {
- var flowFile = 'test.json';
- var flowFilePath = path.join(userDir,flowFile);
- localfilesystem.init({userDir:userDir, flowFile:flowFilePath,flowFilePretty:true,getUserSettings: () => {{}}}, mockRuntime).then(function() {
- localfilesystem.saveFlows(testFlow).then(function() {
- var content = fs.readFileSync(flowFilePath,"utf8");
- content.split("\n").length.should.be.above(1);
- localfilesystem.getFlows().then(function(flows) {
- flows.should.eql(testFlow);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should fsync the flows file',function(done) {
- var flowFile = 'test.json';
- var flowFilePath = path.join(userDir,flowFile);
- localfilesystem.init({editorTheme:{projects:{enabled:false}},userDir:userDir, flowFile:flowFilePath,getUserSettings: () => {{}}}, mockRuntime).then(function() {
- sinon.spy(fs,"fsync");
- localfilesystem.saveFlows(testFlow).then(function() {
- fs.fsync.callCount.should.be.greaterThan(0);
- fs.fsync.restore();
- done();
- }).catch(function(err) {
- fs.fsync.restore();
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should log fsync errors and continue',function(done) {
- var flowFile = 'test.json';
- var flowFilePath = path.join(userDir,flowFile);
- localfilesystem.init({userDir:userDir, flowFile:flowFilePath,getUserSettings: () => {{}}}, mockRuntime).then(function() {
- sinon.stub(fs,"fsync").callsFake(function(fd, cb) {
- cb(new Error());
- });
- sinon.spy(log,"warn");
- localfilesystem.saveFlows(testFlow).then(function() {
- fs.fsync.callCount.should.be.greaterThan(0);
- log.warn.restore();
- fs.fsync.callCount.should.be.greaterThan(0);
- fs.fsync.restore();
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should backup the flows file', function(done) {
- var defaultFlowFile = 'flows_'+require('os').hostname()+'.json';
- var defaultFlowFilePath = path.join(userDir,defaultFlowFile);
- var flowFile = 'test.json';
- var flowFilePath = path.join(userDir,flowFile);
- var flowFileBackupPath = path.join(userDir,"."+flowFile+".backup");
-
- localfilesystem.init({userDir:userDir, flowFile:flowFilePath,getUserSettings: () => {{}}}, mockRuntime).then(function() {
- fs.existsSync(defaultFlowFilePath).should.be.false();
- fs.existsSync(flowFilePath).should.be.false();
- fs.existsSync(flowFileBackupPath).should.be.false();
-
- localfilesystem.saveFlows(testFlow).then(function() {
- fs.existsSync(flowFileBackupPath).should.be.false();
- fs.existsSync(defaultFlowFilePath).should.be.false();
- fs.existsSync(flowFilePath).should.be.true();
- var content = fs.readFileSync(flowFilePath,'utf8');
- var testFlow2 = [{"type":"tab","id":"bc5672ad.2741d8","label":"Sheet 2"}];
-
- localfilesystem.saveFlows(testFlow2).then(function() {
- fs.existsSync(flowFileBackupPath).should.be.true();
- fs.existsSync(defaultFlowFilePath).should.be.false();
- fs.existsSync(flowFilePath).should.be.true();
- var backupContent = fs.readFileSync(flowFileBackupPath,'utf8');
- content.should.equal(backupContent);
- var content2 = fs.readFileSync(flowFilePath,'utf8');
- content2.should.not.equal(backupContent);
- done();
-
- }).catch(function(err) {
- done(err);
- });
-
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
-
-
- });
-
- it('should handle missing credentials', function(done) {
- var flowFile = 'test.json';
- var flowFilePath = path.join(userDir,flowFile);
- var credFile = path.join(userDir,"test_cred.json");
- localfilesystem.init({userDir:userDir, flowFile:flowFilePath,getUserSettings: () => {{}}}, mockRuntime).then(function() {
- fs.existsSync(credFile).should.be.false();
-
- localfilesystem.getCredentials().then(function(creds) {
- creds.should.eql({});
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should handle credentials', function(done) {
- var flowFile = 'test.json';
- var flowFilePath = path.join(userDir,flowFile);
- var credFile = path.join(userDir,"test_cred.json");
-
- localfilesystem.init({userDir:userDir, flowFile:flowFilePath,getUserSettings: () => {{}}}, mockRuntime).then(function() {
-
- fs.existsSync(credFile).should.be.false();
-
- var credentials = {"abc":{"type":"creds"}};
-
- localfilesystem.saveCredentials(credentials).then(function() {
- fs.existsSync(credFile).should.be.true();
- localfilesystem.getCredentials().then(function(creds) {
- creds.should.eql(credentials);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
-
- it('should backup existing credentials', function(done) {
- var flowFile = 'test.json';
- var flowFilePath = path.join(userDir,flowFile);
- var credFile = path.join(userDir,"test_cred.json");
- var credFileBackup = path.join(userDir,".test_cred.json.backup");
-
- localfilesystem.init({userDir:userDir, flowFile:flowFilePath,getUserSettings: () => {{}}}, mockRuntime).then(function() {
-
- fs.writeFileSync(credFile,"{}","utf8");
-
- fs.existsSync(credFile).should.be.true();
- fs.existsSync(credFileBackup).should.be.false();
-
- var credentials = {"abc":{"type":"creds"}};
-
- localfilesystem.saveCredentials(credentials).then(function() {
- fs.existsSync(credFile).should.be.true();
- fs.existsSync(credFileBackup).should.be.true();
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should format the creds file when flowFilePretty specified',function(done) {
- var flowFile = 'test.json';
- var flowFilePath = path.join(userDir,flowFile);
- var credFile = path.join(userDir,"test_cred.json");
-
- localfilesystem.init({userDir:userDir, flowFile:flowFilePath, flowFilePretty:true,getUserSettings: () => {{}}}, mockRuntime).then(function() {
-
- fs.existsSync(credFile).should.be.false();
-
- var credentials = {"abc":{"type":"creds"}};
-
- localfilesystem.saveCredentials(credentials).then(function() {
- fs.existsSync(credFile).should.be.true();
- var content = fs.readFileSync(credFile,"utf8");
- content.split("\n").length.should.be.above(1);
- localfilesystem.getCredentials().then(function(creds) {
- creds.should.eql(credentials);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should handle flow file in random unc path and non-existent subfolder',function(done) {
- // only test on win32
- if (process.platform !== 'win32') {
- console.log('skipped test as not win32');
- done();
- return;
- }
-
- // get a real windows path
- var flowFile = path.win32.resolve(userDir+'/some/random/path');
- var rootdir = path.win32.resolve(userDir+'/some');
- // make it into a local UNC path
- flowFile = flowFile.replace('C:\\', '\\\\localhost\\c$\\');
- localfilesystem.init({userDir:userDir, flowFile:flowFile}, mockRuntime).then(function() {
- fs.existsSync(flowFile).should.be.false();
- localfilesystem.saveFlows(testFlow).then(function() {
- fs.existsSync(flowFile).should.be.true();
- localfilesystem.getFlows().then(function(flows) {
- flows.should.eql(testFlow);
- // cleanup
- fs.removeSync(rootdir);
- done();
- }).catch(function(err) {
- // cleanup
- fs.removeSync(rootdir);
- done(err);
- });
- }).catch(function(err) {
- // cleanup
- fs.removeSync(rootdir);
- done(err);
- });
- }).catch(function(err) {
- // cleanup
- fs.removeSync(rootdir);
- done(err);
- });
- });
-
-});
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/library_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/library_spec.js
deleted file mode 100644
index 69b6e3da6..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/library_spec.js
+++ /dev/null
@@ -1,244 +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-extra');
-var path = require('path');
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var localfilesystemLibrary = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/localfilesystem/library");
-
-describe('storage/localfilesystem/library', function() {
- var userDir = path.join(__dirname,".testUserHome");
- beforeEach(function(done) {
- fs.remove(userDir,function(err) {
- fs.mkdir(userDir,done);
- });
- });
- afterEach(function(done) {
- fs.remove(userDir,done);
- });
-
- it('should return an empty list of library objects',function(done) {
- localfilesystemLibrary.init({userDir:userDir}).then(function() {
- localfilesystemLibrary.getLibraryEntry('object','').then(function(flows) {
- flows.should.eql([]);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should return an empty list of library objects (path=/)',function(done) {
- localfilesystemLibrary.init({userDir:userDir}).then(function() {
- localfilesystemLibrary.getLibraryEntry('object','/').then(function(flows) {
- flows.should.eql([]);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should return an error for a non-existent library object',function(done) {
- localfilesystemLibrary.init({userDir:userDir}).then(function() {
- localfilesystemLibrary.getLibraryEntry('object','A/B').then(function(flows) {
- should.fail(null,null,"non-existent flow");
- }).catch(function(err) {
- should.exist(err);
- done();
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- function createObjectLibrary(type) {
- type = type || "object";
- var objLib = path.join(userDir, "lib", type);
- try {
- fs.mkdirSync(objLib);
- } catch (err) {
- }
- fs.mkdirSync(path.join(objLib, "A"));
- fs.mkdirSync(path.join(objLib, "B"));
- fs.mkdirSync(path.join(objLib, "B", "C"));
- fs.mkdirSync(path.join(objLib, "D"));
- if (type === "functions" || type === "object") {
- fs.writeFileSync(path.join(objLib, "file1.js"), "// abc: def\n// not a metaline \n\n Hi", 'utf8');
- fs.writeFileSync(path.join(objLib, "B", "file2.js"), "// ghi: jkl\n// not a metaline \n\n Hi", 'utf8');
- fs.writeFileSync(path.join(objLib, "D", "file3.js"), "// mno: 日本語テスト\n\nこんにちわ", 'utf8');
- }
- if (type === "flows" || type === "object") {
- fs.writeFileSync(path.join(objLib, "B", "flow.json"), "Hi", 'utf8');
- }
- }
-
- it('should return a directory listing of library objects', function (done) {
- localfilesystemLibrary.init({userDir: userDir}).then(function () {
- createObjectLibrary();
-
- localfilesystemLibrary.getLibraryEntry('object', '').then(function (flows) {
- flows.should.eql([ 'A', 'B', 'D', { abc: 'def', fn: 'file1.js' }]);
- localfilesystemLibrary.getLibraryEntry('object', 'B').then(function (flows) {
- flows.should.eql([ 'C', { ghi: 'jkl', fn: 'file2.js' }, { fn: 'flow.json' }]);
- localfilesystemLibrary.getLibraryEntry('object', 'B/C').then(function (flows) {
- flows.should.eql([]);
- localfilesystemLibrary.getLibraryEntry('object', 'D').then(function (flows) {
- flows.should.eql([{ mno: '日本語テスト', fn: 'file3.js' }]);
- done();
- }).catch(function (err) {
- done(err);
- });
- }).catch(function (err) {
- done(err);
- });
- }).catch(function (err) {
- done(err);
- });
- }).catch(function (err) {
- done(err);
- });
- }).catch(function (err) {
- done(err);
- });
- });
-
- it('should load a flow library object with .json unspecified', function(done) {
- localfilesystemLibrary.init({userDir:userDir}).then(function() {
- createObjectLibrary("flows");
- localfilesystemLibrary.getLibraryEntry('flows','B/flow').then(function(flows) {
- flows.should.eql("Hi");
- done();
- }).catch(function(err) {
- done(err);
- });
- });
-
- });
-
- it('should return a library object',function(done) {
- localfilesystemLibrary.init({userDir:userDir}).then(function() {
- createObjectLibrary();
- localfilesystemLibrary.getLibraryEntry('object','B/file2.js').then(function(body) {
- body.should.eql("// not a metaline \n\n Hi");
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should return a newly saved library function',function(done) {
- localfilesystemLibrary.init({userDir:userDir}).then(function() {
- createObjectLibrary("functions");
- localfilesystemLibrary.getLibraryEntry('functions','B').then(function(flows) {
- flows.should.eql([ 'C', { ghi: 'jkl', fn: 'file2.js' } ]);
- var ft = path.join("B","D","file3.js");
- localfilesystemLibrary.saveLibraryEntry('functions',ft,{mno:'pqr'},"// another non meta line\n\n Hi There").then(function() {
- setTimeout(function() {
- localfilesystemLibrary.getLibraryEntry('functions',path.join("B","D")).then(function(flows) {
- flows.should.eql([ { mno: 'pqr', fn: 'file3.js' } ]);
- localfilesystemLibrary.getLibraryEntry('functions',ft).then(function(body) {
- body.should.eql("// another non meta line\n\n Hi There");
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- })
- }, 50);
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should return a newly saved library flow',function(done) {
- localfilesystemLibrary.init({userDir:userDir}).then(function() {
- createObjectLibrary("flows");
- localfilesystemLibrary.getLibraryEntry('flows','B').then(function(flows) {
- flows.should.eql([ 'C', {fn:'flow.json'} ]);
- var ft = path.join("B","D","file3");
- localfilesystemLibrary.saveLibraryEntry('flows',ft,{mno:'pqr'},"Hi").then(function() {
- setTimeout(function() {
- localfilesystemLibrary.getLibraryEntry('flows',path.join("B","D")).then(function(flows) {
- flows.should.eql([ { mno: 'pqr', fn: 'file3.json' } ]);
- localfilesystemLibrary.getLibraryEntry('flows',ft+".json").then(function(body) {
- body.should.eql("Hi");
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- })
- }, 50);
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should return a newly saved library flow (multi-byte character)',function(done) {
- localfilesystemLibrary.init({userDir:userDir}).then(function() {
- createObjectLibrary("flows");
- localfilesystemLibrary.getLibraryEntry('flows','B').then(function(flows) {
- flows.should.eql([ 'C', {fn:'flow.json'} ]);
- var ft = path.join("B","D","file4");
- localfilesystemLibrary.saveLibraryEntry('flows',ft,{mno:'pqr'},"こんにちわこんにちわこんにちわ").then(function() {
- setTimeout(function() {
- localfilesystemLibrary.getLibraryEntry('flows',path.join("B","D")).then(function(flows) {
- flows.should.eql([ { mno: 'pqr', fn: 'file4.json' } ]);
- localfilesystemLibrary.getLibraryEntry('flows',ft+".json").then(function(body) {
- body.should.eql("こんにちわこんにちわこんにちわ");
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- })
- }, 50);
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/Project_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/Project_spec.js
deleted file mode 100644
index ecf24cf40..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/Project_spec.js
+++ /dev/null
@@ -1,21 +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 NR_TEST_UTILS = require("nr-test-utils");
-
-describe("storage/localfilesystem/projects/Project", function() {
- it.skip("NEEDS TESTS WRITING",function() {});
-})
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/defaultFileSet_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/defaultFileSet_spec.js
deleted file mode 100644
index 3fab5a45c..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/defaultFileSet_spec.js
+++ /dev/null
@@ -1,64 +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 defaultFileSet = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/localfilesystem/projects/defaultFileSet");
-
-describe('storage/localfilesystem/projects/defaultFileSet', function() {
- var runtime = {
- i18n: {
- "_": function(name) {
- return name;
- }
- }
- };
- it('generates package.json for a project', function() {
- var generated = defaultFileSet["package.json"]({
- name: "A TEST NAME",
- summary: "A TEST SUMMARY",
- files: {
- flow: "MY FLOW FILE",
- credentials: "MY CREDENTIALS FILE"
- }
- }, runtime);
-
- var parsed = JSON.parse(generated);
- parsed.should.have.property('name',"A TEST NAME");
- parsed.should.have.property('description',"A TEST SUMMARY");
- parsed.should.have.property('node-red');
- parsed['node-red'].should.have.property('settings');
- parsed['node-red'].settings.should.have.property('flowFile',"MY FLOW FILE");
- parsed['node-red'].settings.should.have.property('credentialsFile',"MY CREDENTIALS FILE");
- });
-
- it('generates README.md for a project', function() {
- var generated = defaultFileSet["README.md"]({
- name: "A TEST NAME",
- summary: "A TEST SUMMARY"
- }, runtime);
- generated.should.match(/A TEST NAME/);
- generated.should.match(/A TEST SUMMARY/);
- });
- it('generates .gitignore for a project', function() {
- var generated = defaultFileSet[".gitignore"]({
- name: "A TEST NAME",
- summary: "A TEST SUMMARY"
- }, runtime);
- generated.length.should.be.greaterThan(0);
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/authCache_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/authCache_spec.js
deleted file mode 100644
index c1617bf90..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/authCache_spec.js
+++ /dev/null
@@ -1,84 +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 NR_TEST_UTILS = require("nr-test-utils");
-var authCache = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/localfilesystem/projects/git/authCache")
-
-describe("localfilesystem/projects/git/authCache", function() {
-
- beforeEach(function() {
- authCache.init();
- });
- afterEach(function() {
- authCache.init();
- });
-
- it('sets/clears auth details for a given project/remote/user', function() {
- should.not.exist(authCache.get("project","remote1","user1"));
- should.not.exist(authCache.get("project","remote1","user2"));
-
- authCache.set("project","remote1","user1",{foo1:"bar1"});
- authCache.set("project","remote1","user2",{foo2:"bar2"});
-
- var result = authCache.get("project","remote1","user1");
- result.should.have.property("foo1","bar1");
-
- result = authCache.get("project","remote1","user2");
- result.should.have.property("foo2","bar2");
-
- authCache.clear("project","remote1","user1");
- should.not.exist(authCache.get("project","remote1","user1"));
- should.exist(authCache.get("project","remote1","user2"));
-
- });
-
-
- it('clears auth details for all users on a given project/remote', function() {
-
- authCache.set("project","remote1","user1",{foo1:"bar1"});
- authCache.set("project","remote1","user2",{foo2:"bar2"});
- authCache.set("project","remote2","user1",{foo3:"bar3"});
-
- should.exist(authCache.get("project","remote1","user1"));
- should.exist(authCache.get("project","remote1","user2"));
- should.exist(authCache.get("project","remote2","user1"));
-
- authCache.clear("project","remote1");
- should.not.exist(authCache.get("project","remote1","user1"));
- should.not.exist(authCache.get("project","remote1","user2"));
- should.exist(authCache.get("project","remote2","user1"));
- });
-
- it('clears auth details for all remotes/users on a given project', function() {
-
- authCache.set("project1","remote1","user1",{foo1:"bar1"});
- authCache.set("project1","remote1","user2",{foo2:"bar2"});
- authCache.set("project2","remote2","user1",{foo3:"bar3"});
-
- should.exist(authCache.get("project1","remote1","user1"));
- should.exist(authCache.get("project1","remote1","user2"));
- should.exist(authCache.get("project2","remote2","user1"));
-
- authCache.clear("project2");
- should.exist(authCache.get("project1","remote1","user1"));
- should.exist(authCache.get("project1","remote1","user2"));
- should.not.exist(authCache.get("project2","remote2","user1"));
- });
-
-});
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/authServer_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/authServer_spec.js
deleted file mode 100644
index 9b789a66b..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/authServer_spec.js
+++ /dev/null
@@ -1,83 +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 net = require("net");
-var path = require("path");
-var os = require("os");
-var should = require("should");
-var sinon = require("sinon");
-var child_process = require("child_process");
-var fs = require("fs-extra");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var authServer = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/localfilesystem/projects/git/authServer");
-
-
-var sendPrompt = function(localPath, prompt) {
- return new Promise(function(resolve,reject) {
- var response;
- var socket = net.connect(localPath, function() {
- socket.on('data', function(data) { response = data; socket.end() });
- socket.on('end', function() {
- resolve(response);
- });
- socket.on('error',reject);
- socket.write(prompt+"\n", 'utf8');
- });
- socket.setEncoding('utf8');
- });
-}
-
-
-describe("localfilesystem/projects/git/authServer", function() {
- it("listens for user/pass prompts and returns provided auth", function(done) {
- authServer.ResponseServer({username: "TEST_USER", password: "TEST_PASS"}).then(function(rs) {
- sendPrompt(rs.path,"Username").then(function(response) {
- response.should.eql("TEST_USER");
- return sendPrompt(rs.path,"Password");
- }).then(function(response) {
- response.should.eql("TEST_PASS");
- }).then(() => {
- rs.close();
- done();
- }).catch(function(err) {
- rs.close();
- done(err);
- })
-
- })
- });
-
- it("listens for ssh prompts and returns provided auth", function(done) {
- authServer.ResponseSSHServer({passphrase: "TEST_PASSPHRASE"}).then(function(rs) {
- sendPrompt(rs.path,"The").then(function(response) {
- // TODO:
- response.should.eql("yes");
- return sendPrompt(rs.path,"Enter");
- }).then(function(response) {
- response.should.eql("TEST_PASSPHRASE");
- }).then(() => {
- rs.close();
- done();
- }).catch(function(err) {
- rs.close();
- done(err);
- })
-
- })
- })
-});
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/authWriter_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/authWriter_spec.js
deleted file mode 100644
index c80cb8ad1..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/authWriter_spec.js
+++ /dev/null
@@ -1,83 +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 net = require("net");
-var path = require("path");
-var os = require("os");
-var should = require("should");
-var sinon = require("sinon");
-var child_process = require("child_process");
-var fs = require("fs-extra");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var authWriter = NR_TEST_UTILS.resolve("@node-red/runtime/lib/storage/localfilesystem/projects/git/authWriter");
-
-function getListenPath() {
- var seed = (0x100000+Math.random()*0x999999).toString(16);
- var fn = 'node-red-git-askpass-'+seed+'-sock';
- var listenPath;
- if (process.platform === 'win32') {
- listenPath = '\\\\.\\pipe\\'+fn;
- } else {
- listenPath = path.join(process.env['XDG_RUNTIME_DIR'] || os.tmpdir(), fn);
- }
- // console.log(listenPath);
- return listenPath;
-}
-
-
-describe("localfilesystem/projects/git/authWriter", function() {
- it("connects to port and sends passphrase", function(done) {
- var receivedData = "";
- var server = net.createServer(function(connection) {
- connection.setEncoding('utf8');
- connection.on('data', function(data) {
- receivedData += data;
- var m = data.indexOf("\n");
- if (m !== -1) {
- connection.end();
- }
- });
- });
-
- var listenPath = getListenPath();
-
- server.listen(listenPath, function(ready) {
- child_process.exec('"'+process.execPath+'" "'+authWriter+'" "'+listenPath+'" TEST_PHRASE_FOO',{cwd:__dirname}, (error,stdout,stderr) => {
- server.close();
- try {
- should.not.exist(error);
- receivedData.should.eql("TEST_PHRASE_FOO\n");
- done();
- } catch(err) {
- done(err);
- }
- });
- });
- server.on('close', function() {
- // console.log("Closing response server");
- fs.removeSync(listenPath);
- });
- server.on('error',function(err) {
- console.log("ResponseServer unexpectedError:",err.toString());
- server.close();
- done(err);
- });
-
-
- })
-});
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/index_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/index_spec.js
deleted file mode 100644
index 773342fa6..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/index_spec.js
+++ /dev/null
@@ -1,21 +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 NR_TEST_UTILS = require("nr-test-utils");
-
-describe("storage/localfilesystem/projects/git/index", function() {
- it.skip("NEEDS TESTS WRITING",function() {});
-})
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/index_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/index_spec.js
deleted file mode 100644
index f63a20522..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/index_spec.js
+++ /dev/null
@@ -1,21 +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 NR_TEST_UTILS = require("nr-test-utils");
-
-describe("storage/localfilesystem/projects/index", function() {
- it.skip("NEEDS TESTS WRITING",function() {});
-})
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/ssh/index_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/ssh/index_spec.js
deleted file mode 100644
index c6d0c533e..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/ssh/index_spec.js
+++ /dev/null
@@ -1,433 +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-extra');
-var path = require('path');
-
-var NR_TEST_UTILS = require("nr-test-utils");
-var sshkeys = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/localfilesystem/projects/ssh");
-
-describe("storage/localfilesystem/projects/ssh", function() {
- var userDir = path.join(__dirname,".testSSHKeyUserHome");
- var mockSettings = {
- userDir: userDir
- };
- var mockRuntime = {
- log:{
- _:function() { return "placeholder message"},
- info: function() { },
- log: function() { },
- trace: function() { }
- }
- };
- var oldHOME;
-
- beforeEach(function(done) {
- oldHOME = process.env.HOME;
- process.env.HOME = "/tmp/doesnt/exist";
- fs.remove(userDir,function(err) {
- fs.mkdir(userDir,done);
- });
- });
- afterEach(function(done) {
- process.env.HOME = oldHOME;
- fs.remove(userDir,done);
- });
-
- it('should create sshkey directory when sshkey initializes', function(done) {
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- var ret = fs.existsSync(sshkeyDirPath);
- ret.should.be.true();
- done();
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should get sshkey empty list if there is no sshkey file', function(done) {
- var username = 'test';
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- sshkeys.listSSHKeys(username).then(function(retObj) {
- retObj.should.be.instanceOf(Array).and.have.lengthOf(0);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should get sshkey list', function(done) {
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var filenameList = ['test-key01', 'test-key02'];
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- for(var filename of filenameList) {
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename),"","utf8");
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename+".pub"),"","utf8");
- }
- sshkeys.listSSHKeys(username).then(function(retObj) {
- retObj.should.be.instanceOf(Array).and.have.lengthOf(filenameList.length);
- for(var filename of filenameList) {
- retObj.should.containEql({ name: filename });
- }
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should not get sshkey file if there is only private key', function(done) {
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var filenameList = ['test-key01', 'test-key02'];
- var onlyPrivateKeyFilenameList = ['test-key03', 'test-key04'];
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- for(var filename of filenameList) {
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename),"","utf8");
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename+".pub"),"","utf8");
- }
- for(var filename of onlyPrivateKeyFilenameList) {
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename),"","utf8");
- }
- sshkeys.listSSHKeys(username).then(function(retObj) {
- retObj.should.be.instanceOf(Array).and.have.lengthOf(filenameList.length);
- for(var filename of filenameList) {
- retObj.should.containEql({ name: filename });
- }
- for(var filename of onlyPrivateKeyFilenameList) {
- retObj.should.not.containEql({ name: filename });
- }
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should not get sshkey file if there is only public key', function(done) {
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var filenameList = ['test-key01', 'test-key02'];
- var directoryList = ['test-key03', '.test-key04'];
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- for(var filename of filenameList) {
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename),"","utf8");
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename+".pub"),"","utf8");
- }
- for(var filename of directoryList) {
- fs.ensureDirSync(path.join(sshkeyDirPath,filename));
- }
- sshkeys.listSSHKeys(username).then(function(retObj) {
- retObj.should.be.instanceOf(Array).and.have.lengthOf(filenameList.length);
- for(var filename of filenameList) {
- retObj.should.containEql({ name: filename });
- }
- for(var directoryname of directoryList) {
- retObj.should.not.containEql({ name: directoryname });
- }
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should get sshkey list that does not have directory', function(done) {
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var otherUsername = 'other';
- var filenameList = ['test-key01', 'test-key02'];
- var otherUserFilenameList = ['test-key03', 'test-key04'];
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- for(var filename of filenameList) {
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename),"","utf8");
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename+".pub"),"","utf8");
- }
- for(var filename of otherUserFilenameList) {
- fs.writeFileSync(path.join(sshkeyDirPath,otherUsername+"_"+filename),"","utf8");
- fs.writeFileSync(path.join(sshkeyDirPath,otherUsername+"_"+filename+".pub"),"","utf8");
- }
- sshkeys.listSSHKeys(username).then(function(retObj) {
- retObj.should.be.instanceOf(Array).and.have.lengthOf(filenameList.length);
- for(var filename of filenameList) {
- retObj.should.containEql({ name: filename });
- }
- for(var filename of otherUserFilenameList) {
- retObj.should.not.containEql({ name: filename });
- }
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should get sshkey list that have keys of specified user', function(done) {
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var otherUsername = 'other';
- var filenameList = ['test-key01', 'test-key02'];
- var otherUserFilenameList = ['test-key03', 'test-key04'];
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- for(var filename of filenameList) {
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename),"","utf8");
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename+".pub"),"","utf8");
- }
- for(var filename of otherUserFilenameList) {
- fs.writeFileSync(path.join(sshkeyDirPath,otherUsername+"_"+filename),"","utf8");
- fs.writeFileSync(path.join(sshkeyDirPath,otherUsername+"_"+filename+".pub"),"","utf8");
- }
- sshkeys.listSSHKeys(username).then(function(retObj) {
- retObj.should.be.instanceOf(Array).and.have.lengthOf(filenameList.length);
- for(var filename of filenameList) {
- retObj.should.containEql({ name: filename });
- }
- for(var filename of otherUserFilenameList) {
- retObj.should.not.containEql({ name: filename });
- }
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should generate sshkey file with empty data', function(done) {
- this.timeout(10000);
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var options = {
- name: 'test-key01'
- };
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- sshkeys.generateSSHKey(username, options).then(function(retObj) {
- retObj.should.be.equal(options.name);
- fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name)).should.be.true();
- fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name+'.pub')).should.be.true();
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should generate sshkey file with only comment data', function(done) {
- this.timeout(10000);
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var options = {
- comment: 'test@test.com',
- name: 'test-key01'
- };
-
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- sshkeys.generateSSHKey(username, options).then(function(retObj) {
- retObj.should.be.equal(options.name);
- fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name)).should.be.true();
- fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name+'.pub')).should.be.true();
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should generate sshkey file with password data', function(done) {
- this.timeout(10000);
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var options = {
- comment: 'test@test.com',
- name: 'test-key01',
- password: 'testtest'
- };
-
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- sshkeys.generateSSHKey(username, options).then(function(retObj) {
- retObj.should.be.equal(options.name);
- fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name)).should.be.true();
- fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name+'.pub')).should.be.true();
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should generate sshkey file with size data', function(done) {
- this.timeout(20000);
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var options = {
- comment: 'test@test.com',
- name: 'test-key01',
- size: 4096
- };
-
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- sshkeys.generateSSHKey(username, options).then(function(retObj) {
- retObj.should.be.equal(options.name);
- fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name)).should.be.true();
- fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name+'.pub')).should.be.true();
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should generate sshkey file with password & size data', function(done) {
- this.timeout(20000);
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var options = {
- comment: 'test@test.com',
- name: 'test-key01',
- password: 'testtest',
- size: 4096
- };
-
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- sshkeys.generateSSHKey(username, options).then(function(retObj) {
- retObj.should.be.equal(options.name);
- fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name)).should.be.true();
- fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name+'.pub')).should.be.true();
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should not generate sshkey file with illegal size data', function(done) {
- this.timeout(10000);
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var options = {
- comment: 'test@test.com',
- name: 'test-key01',
- size: 1023
- };
-
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- sshkeys.generateSSHKey(username, options).then(function(retObj) {
- done(new Error('Does NOT throw error!'));
- }).catch(function(err) {
- try {
- err.should.have.property('code', 'key_length_too_short');
- done();
- }
- catch (error) {
- done(error);
- }
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should not generate sshkey file with illegal password', function(done) {
- this.timeout(10000);
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var options = {
- comment: 'test@test.com',
- name: 'test-key01',
- password: 'aa'
- };
-
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- sshkeys.generateSSHKey(username, options).then(function(retObj) {
- done(new Error('Does NOT throw error!'));
- }).catch(function(err) {
- try {
- err.should.have.property('code', 'key_passphrase_too_short');
- done();
- }
- catch (error) {
- done(error);
- }
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should get sshkey file content', function(done) {
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var filename = 'test-key01';
- var fileContent = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQD3a+sgtgzSbbliWxmOq5p6+H/mE+0gjWfLWrkIVmHENd1mifV4uCmIHAR2NfuadUYMQ3+bQ90kpmmEKTMYPsyentsKpHQZxTzG7wOCAIpJnbPTHDMxEJhVTaAwEjbVyMSIzTTPfnhoavWIBu0+uMgKDDlBm+RjlgkFlyhXyCN6UwFrIUUMH6Gw+eQHLiooKIl8ce7uDxIlt+9b7hFCU+sQ3kvuse239DZluu6+8buMWqJvrEHgzS9adRFKku8nSPAEPYn85vDi7OgVAcLQufknNgs47KHBAx9h04LeSrFJ/P5J1b//ItRpMOIme+O9d1BR46puzhvUaCHLdvO9czj+OmW+dIm+QIk6lZIOOMnppG72kZxtLfeKT16ur+2FbwAdL9ItBp4BI/YTlBPoa5mLMxpuWfmX1qHntvtGc9wEwS1P7YFfmF3XiK5apxalzrn0Qlr5UmDNbVIqJb1OlbC0w03Z0oktti1xT+R2DGOLWM4lBbpXDHV1BhQ7oYOvbUD8Cnof55lTP0WHHsOHlQc/BGDti1XA9aBX/OzVyzBUYEf0pkimsD0RYo6aqt7QwehJYdlz9x1NBguBffT0s4NhNb9IWr+ASnFPvNl2sw4XH/8U0J0q8ZkMpKkbLM1Zdp1Fv00GF0f5UNRokai6uM3w/ccantJ3WvZ6GtctqytWrw== \n";
-
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename),"","utf8");
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename+".pub"),fileContent,"utf8");
- sshkeys.getSSHKey(username, filename).then(function(retObj) {
- retObj.should.be.equal(fileContent);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should delete sshkey files', function(done) {
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var filename = 'test-key01';
- var fileContent = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQD3a+sgtgzSbbliWxmOq5p6+H/mE+0gjWfLWrkIVmHENd1mifV4uCmIHAR2NfuadUYMQ3+bQ90kpmmEKTMYPsyentsKpHQZxTzG7wOCAIpJnbPTHDMxEJhVTaAwEjbVyMSIzTTPfnhoavWIBu0+uMgKDDlBm+RjlgkFlyhXyCN6UwFrIUUMH6Gw+eQHLiooKIl8ce7uDxIlt+9b7hFCU+sQ3kvuse239DZluu6+8buMWqJvrEHgzS9adRFKku8nSPAEPYn85vDi7OgVAcLQufknNgs47KHBAx9h04LeSrFJ/P5J1b//ItRpMOIme+O9d1BR46puzhvUaCHLdvO9czj+OmW+dIm+QIk6lZIOOMnppG72kZxtLfeKT16ur+2FbwAdL9ItBp4BI/YTlBPoa5mLMxpuWfmX1qHntvtGc9wEwS1P7YFfmF3XiK5apxalzrn0Qlr5UmDNbVIqJb1OlbC0w03Z0oktti1xT+R2DGOLWM4lBbpXDHV1BhQ7oYOvbUD8Cnof55lTP0WHHsOHlQc/BGDti1XA9aBX/OzVyzBUYEf0pkimsD0RYo6aqt7QwehJYdlz9x1NBguBffT0s4NhNb9IWr+ASnFPvNl2sw4XH/8U0J0q8ZkMpKkbLM1Zdp1Fv00GF0f5UNRokai6uM3w/ccantJ3WvZ6GtctqytWrw== \n";
-
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename),"","utf8");
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename+".pub"),fileContent,"utf8");
- sshkeys.deleteSSHKey(username, filename).then(function() {
- fs.existsSync(path.join(sshkeyDirPath,username+'_'+filename)).should.be.false();
- fs.existsSync(path.join(sshkeyDirPath,username+'_'+filename+'.pub')).should.be.false();
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/ssh/keygen_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/ssh/keygen_spec.js
deleted file mode 100644
index f3487277b..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/ssh/keygen_spec.js
+++ /dev/null
@@ -1,110 +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 child_process = require('child_process');
-var EventEmitter = require("events");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-var keygen = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/localfilesystem/projects/ssh/keygen")
-
-describe("localfilesystem/projects/ssh/keygen", function() {
-
- afterEach(function() {
- if (child_process.spawn.restore) {
- child_process.spawn.restore();
- }
- })
-
- it("invokes sshkeygen", function(done) {
- var command;
- var args;
- var opts;
- sinon.stub(child_process,"spawn").callsFake(function(_command,_args,_opts) {
- _command = command;
- _args = args;
- _opts = opts;
-
- var e = new EventEmitter();
- e.stdout = new EventEmitter();
- e.stderr = new EventEmitter();
- setTimeout(function() {
- e.stdout.emit("data","result");
- e.emit("close",0);
- },50)
- return e;
- });
-
- keygen.generateKey({
- size: 1024,
- location: 'location',
- comment: 'comment',
- password: 'password'
- }).then(function(output) {
- output.should.equal("result");
- done();
- }).catch(function(err) {
- done(err);
- })
- })
-
- it("reports passphrase too short", function(done) {
- var command;
- var args;
- var opts;
-
- try {
- keygen.generateKey({
- size: 1024,
- location: 'location',
- comment: 'comment',
- password: '123'
- }).then(function(output) {
- done(new Error("Error not thrown"));
- }).catch(function(err) {
- done(new Error("Error not thrown"));
- })
- } catch(err) {
- err.should.have.property("code","key_passphrase_too_short");
- done();
- }
- });
-
- it("reports key length too short", function(done) {
- var command;
- var args;
- var opts;
- try {
- keygen.generateKey({
- size: 123,
- location: 'location',
- comment: 'comment',
- password: 'password'
- }).then(function(output) {
- done(new Error("Error not thrown"));
- }).catch(function(err) {
- done(new Error("Error not thrown"));
- })
- } catch(err) {
- err.should.have.property("code","key_length_too_short");
- done();
-
- }
- });
-
-
-});
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/sessions_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/sessions_spec.js
deleted file mode 100644
index 685886d67..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/sessions_spec.js
+++ /dev/null
@@ -1,80 +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-extra');
-var path = require('path');
-
-var NR_TEST_UTILS = require("nr-test-utils");
-var localfilesystemSessions = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/localfilesystem/sessions");
-
-describe('storage/localfilesystem/sessions', function() {
- var userDir = path.join(__dirname,".testUserHome");
- beforeEach(function(done) {
- fs.remove(userDir,function(err) {
- fs.mkdir(userDir,done);
- });
- });
- afterEach(function(done) {
- fs.remove(userDir,done);
- });
- it('should handle non-existent sessions', function(done) {
- var sessionsFile = path.join(userDir,".sessions.json");
-
- localfilesystemSessions.init({userDir:userDir});
- fs.existsSync(sessionsFile).should.be.false();
- localfilesystemSessions.getSessions().then(function(sessions) {
- sessions.should.eql({});
- done();
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should handle corrupt sessions', function(done) {
- var sessionsFile = path.join(userDir,".sessions.json");
- fs.writeFileSync(sessionsFile,"[This is not json","utf8");
- localfilesystemSessions.init({userDir:userDir});
- fs.existsSync(sessionsFile).should.be.true();
- localfilesystemSessions.getSessions().then(function(sessions) {
- sessions.should.eql({});
- done();
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should handle sessions', function(done) {
- var sessionsFile = path.join(userDir,".sessions.json");
-
- localfilesystemSessions.init({userDir:userDir});
- fs.existsSync(sessionsFile).should.be.false();
-
- var sessions = {"abc":{"type":"creds"}};
-
- localfilesystemSessions.saveSessions(sessions).then(function() {
- fs.existsSync(sessionsFile).should.be.true();
- localfilesystemSessions.getSessions().then(function(_sessions) {
- _sessions.should.eql(sessions);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/settings_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/settings_spec.js
deleted file mode 100644
index bd07ca27f..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/settings_spec.js
+++ /dev/null
@@ -1,134 +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 fs = require('fs-extra');
-const path = require('path');
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var localfilesystemSettings = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/localfilesystem/settings");
-
-describe('storage/localfilesystem/settings', function() {
- var userDir = path.join(__dirname,".testUserHome");
- beforeEach(function(done) {
- fs.remove(userDir,function(err) {
- fs.mkdir(userDir,done);
- });
- });
- afterEach(function(done) {
- fs.remove(userDir,done);
- });
-
- it('should handle non-existent settings', function(done) {
- var settingsFile = path.join(userDir,".config.json");
- localfilesystemSettings.init({userDir:userDir}).then(function() {
- fs.existsSync(settingsFile).should.be.false();
- return localfilesystemSettings.getSettings();
- }).then(function(settings) {
- settings.should.eql({});
- done();
- }).catch(err => { done(err)});
- });
-
- it('should migrate single config.json to multiple files', function(done) {
- var settingsFile = path.join(userDir,".config.json");
- fs.writeFileSync(settingsFile,JSON.stringify({
- nodes:{a:1},
- _credentialSecret: "foo",
- users:{b:2},
- projects: {c:3}
- }),"utf8");
-
- async function checkFile(sectionName, expectedContents) {
- const file = path.join(userDir,".config."+sectionName+".json");
- fs.existsSync(file).should.be.true();
- var contents = await fs.readFile(file,'utf8');
- var data = JSON.parse(contents);
- data.should.eql(expectedContents)
- }
-
- localfilesystemSettings.init({userDir:userDir}).then(async function() {
- // (For now) leave the old settings file in place
- fs.existsSync(settingsFile).should.be.true();
- await checkFile("nodes",{a:1})
- await checkFile("users",{b:2})
- await checkFile("projects",{c:3})
- await checkFile("runtime",{_credentialSecret:"foo"})
- done();
- }).catch(err => { done(err)});
- });
-
- it('should load separate settings file', async function() {
- await fs.writeFile( path.join(userDir,".config.nodes.json"),JSON.stringify({a:1}),"utf8");
- await fs.writeFile( path.join(userDir,".config.users.json"),JSON.stringify({b:2}),"utf8");
- await fs.writeFile( path.join(userDir,".config.projects.json"),JSON.stringify({c:3}),"utf8");
- await fs.writeFile( path.join(userDir,".config.runtime.json"),JSON.stringify({_credentialSecret:"foo"}),"utf8");
-
- return localfilesystemSettings.init({userDir:userDir})
- .then(localfilesystemSettings.getSettings)
- .then(settings => {
- settings.should.eql({
- nodes:{a:1},
- _credentialSecret: "foo",
- users:{b:2},
- projects: {c:3}
- })
- })
- });
-
- it('should write only the files that need writing', async function() {
- await fs.writeFile( path.join(userDir,".config.nodes.json"),JSON.stringify({a:1}),"utf8");
- await fs.writeFile( path.join(userDir,".config.users.json"),JSON.stringify({b:2}),"utf8");
- await fs.writeFile( path.join(userDir,".config.projects.json"),JSON.stringify({c:3}),"utf8");
- await fs.writeFile( path.join(userDir,".config.runtime.json"),JSON.stringify({_credentialSecret:"foo"}),"utf8");
-
- const fsStatNodes = await fs.stat(path.join(userDir,".config.nodes.json"))
- const fsStatUsers = await fs.stat(path.join(userDir,".config.users.json"))
- const fsStatProjects = await fs.stat(path.join(userDir,".config.projects.json"))
- const fsStatRuntime = await fs.stat(path.join(userDir,".config.runtime.json"))
-
- return localfilesystemSettings.init({userDir:userDir}).then(function() {
- return new Promise(res => {
- setTimeout(function() {
- res();
- },10)
- });
- }).then(() => {
- return localfilesystemSettings.saveSettings({
- nodes:{d:4},
- _credentialSecret: "bar",
- users:{b:2},
- projects: {c:3}
- })
- }).then(async function() {
-
- const newFsStatNodes = await fs.stat(path.join(userDir,".config.nodes.json"))
- const newFsStatUsers = await fs.stat(path.join(userDir,".config.users.json"))
- const newFsStatProjects = await fs.stat(path.join(userDir,".config.projects.json"))
- const newFsStatRuntime = await fs.stat(path.join(userDir,".config.runtime.json"))
-
- // Not changed
- newFsStatUsers.mtimeMs.should.eql(fsStatUsers.mtimeMs);
- newFsStatProjects.mtimeMs.should.eql(fsStatProjects.mtimeMs);
-
- // Changed
- newFsStatNodes.mtimeMs.should.not.eql(fsStatNodes.mtimeMs);
- newFsStatRuntime.mtimeMs.should.not.eql(fsStatRuntime.mtimeMs);
-
- })
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/util_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/util_spec.js
deleted file mode 100644
index fa1e4bdb7..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/util_spec.js
+++ /dev/null
@@ -1,32 +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 util = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/localfilesystem/util");
-
-describe('storage/localfilesystem/util', function() {
- describe('parseJSON', function() {
- it('returns parsed JSON', function() {
- var result = util.parseJSON('{"a":123}');
- result.should.eql({a:123});
- })
- it('ignores BOM character', function() {
- var result = util.parseJSON('\uFEFF{"a":123}');
- result.should.eql({a:123});
- })
- })
-});
diff --git a/test/unit/@node-red/util/index_spec.js b/test/unit/@node-red/util/index_spec.js
deleted file mode 100644
index ee46fc504..000000000
--- a/test/unit/@node-red/util/index_spec.js
+++ /dev/null
@@ -1,21 +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 NR_TEST_UTILS = require("nr-test-utils");
-
-describe("node-red/red", function() {
- it.skip("NEEDS TESTS WRITING",function() {});
-});
diff --git a/test/unit/@node-red/util/lib/events_spec.js b/test/unit/@node-red/util/lib/events_spec.js
deleted file mode 100644
index 09f5d2ae0..000000000
--- a/test/unit/@node-red/util/lib/events_spec.js
+++ /dev/null
@@ -1,25 +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");
-
-describe("@node-red/util/events", function() {
- it('can be required without errors', function() {
- NR_TEST_UTILS.require("@node-red/util/lib/events");
- });
- it.skip('more tests needed', function(){})
-});
diff --git a/test/unit/@node-red/util/lib/exec_spec.js b/test/unit/@node-red/util/lib/exec_spec.js
deleted file mode 100644
index 9b02fb3f1..000000000
--- a/test/unit/@node-red/util/lib/exec_spec.js
+++ /dev/null
@@ -1,140 +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 EventEmitter = require("events").EventEmitter;
-
-
-var child_process = require('child_process');
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var events = NR_TEST_UTILS.require("@node-red/util/lib/events");
-var exec = NR_TEST_UTILS.require("@node-red/util/lib/exec");
-
-describe("runtime/exec", function() {
- var logEvents;
- var mockProcess;
- const eventLogHandler = function(ev) {
- logEvents.push(ev);
- }
-
- beforeEach(function() {
-
- logEvents = [];
- events.on("event-log", eventLogHandler);
-
- mockProcess = new EventEmitter();
- mockProcess.stdout = new EventEmitter();
- mockProcess.stderr = new EventEmitter();
- sinon.stub(child_process,'spawn').callsFake(function(command,args,options) {
- mockProcess._args = {command,args,options};
- return mockProcess;
- });
- });
-
- afterEach(function() {
- events.removeListener("event-log", eventLogHandler);
- if (child_process.spawn.restore) {
- child_process.spawn.restore();
- }
- });
-
- it("runs command and resolves on success - no emit", function(done) {
- var command = "cmd";
- var args = [1,2,3];
- var opts = { a: true };
- exec.run(command,args,opts).then(function(result) {
- command.should.eql(mockProcess._args.command);
- args.should.eql(mockProcess._args.args);
- opts.should.eql(mockProcess._args.options);
- logEvents.length.should.eql(0);
- result.code.should.eql(0);
- result.stdout.should.eql("123");
- result.stderr.should.eql("abc");
- done();
- }).catch(done);
-
- mockProcess.stdout.emit('data',"1");
- mockProcess.stderr.emit('data',"a");
- mockProcess.stderr.emit('data',"b");
- mockProcess.stdout.emit('data',"2");
- mockProcess.stdout.emit('data',"3");
- mockProcess.stderr.emit('data',"c");
- mockProcess.emit('close',0);
- });
-
- it("runs command and resolves on success - emit", function(done) {
- var command = "cmd";
- var args = [1,2,3];
- var opts = { a: true };
- exec.run(command,args,opts,true).then(function(result) {
- logEvents.length.should.eql(8);
- done();
- }).catch(done);
-
- mockProcess.stdout.emit('data',"1");
- mockProcess.stderr.emit('data',"a");
- mockProcess.stderr.emit('data',"b");
- mockProcess.stdout.emit('data',"2");
- mockProcess.stdout.emit('data',"3");
- mockProcess.stderr.emit('data',"c");
- mockProcess.emit('close',0);
- })
-
- it("runs command and rejects on error - close", function(done) {
- var command = "cmd";
- var args = [1,2,3];
- var opts = { a: true };
- exec.run(command,args,opts).then(function() {
- done("Command should have rejected");
- }).catch(function(result) {
- result
- result.code.should.eql(123);
- result.stdout.should.eql("123");
- result.stderr.should.eql("abc");
- done();
- }).catch(done);
-
- mockProcess.stdout.emit('data',"1");
- mockProcess.stderr.emit('data',"a");
- mockProcess.stderr.emit('data',"b");
- mockProcess.stdout.emit('data',"2");
- mockProcess.stdout.emit('data',"3");
- mockProcess.stderr.emit('data',"c");
- mockProcess.emit('close',123);
- })
-
- it("runs command and rejects on error - error", function(done) {
- var command = "cmd";
- var args = [1,2,3];
- var opts = { a: true };
- exec.run(command,args,opts).then(function() {
- done("Command should have rejected");
- }).catch(function(result) {
- result
- result.code.should.eql(456);
- result.stdout.should.eql("");
- result.stderr.should.eql("test-error");
- done();
- }).catch(done);
-
- mockProcess.emit('error',"test-error");
- mockProcess.emit('close',456);
- })
-
-});
diff --git a/test/unit/@node-red/util/lib/hooks_spec.js b/test/unit/@node-red/util/lib/hooks_spec.js
deleted file mode 100644
index 4b25f33d2..000000000
--- a/test/unit/@node-red/util/lib/hooks_spec.js
+++ /dev/null
@@ -1,338 +0,0 @@
-const should = require("should");
-const NR_TEST_UTILS = require("nr-test-utils");
-
-const hooks = NR_TEST_UTILS.require("@node-red/util/lib/hooks");
-
-describe("util/hooks", function() {
- afterEach(function() {
- hooks.clear();
- })
- it("allows a hook to be registered", function(done) {
- let calledWith = null;
- hooks.has("onSend").should.be.false();
- hooks.add("onSend", function(payload) { calledWith = payload } )
- hooks.has("onSend").should.be.true();
- let data = { a: 1 };
- hooks.trigger("onSend",data,err => {
- calledWith.should.equal(data);
- done(err);
- })
- })
- it("rejects invalid hook id", function(done) {
- try {
- hooks.add("foo", function(payload) {})
- done(new Error("Invalid hook accepted"))
- } catch(err) {
- done();
- }
- })
- it("calls hooks in the order they were registered", function(done) {
- hooks.add("onSend", function(payload) { payload.order.push("A") } )
- hooks.add("onSend", function(payload) { payload.order.push("B") } )
- let data = { order:[] };
- hooks.trigger("onSend",data,err => {
- data.order.should.eql(["A","B"])
- done(err);
- })
- })
-
- it("does not allow multiple hooks with same id.label", function() {
- hooks.has("onSend.one").should.be.false();
- hooks.has("onSend").should.be.false();
- hooks.add("onSend.one", function(payload) { payload.order.push("A") } );
- hooks.has("onSend.one").should.be.true();
- hooks.has("onSend").should.be.true();
- (function() {
- hooks.add("onSend.one", function(payload) { payload.order.push("B") } )
- }).should.throw();
- })
-
- it("removes labelled hook", function(done) {
- hooks.has("onSend.A").should.be.false();
- hooks.has("onSend.B").should.be.false();
- hooks.has("onSend").should.be.false();
-
- hooks.add("onSend.A", function(payload) { payload.order.push("A") } )
-
- hooks.has("onSend.A").should.be.true();
- hooks.has("onSend.B").should.be.false();
- hooks.has("onSend").should.be.true();
-
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
-
- hooks.has("onSend.A").should.be.true();
- hooks.has("onSend.B").should.be.true();
- hooks.has("onSend").should.be.true();
-
- hooks.remove("onSend.A");
-
- hooks.has("onSend.A").should.be.false();
- hooks.has("onSend.B").should.be.true();
- hooks.has("onSend").should.be.true();
-
-
- let data = { order:[] };
- hooks.trigger("onSend",data,err => {
- try {
- data.order.should.eql(["B"])
-
- hooks.remove("onSend.B");
-
- hooks.has("onSend.A").should.be.false();
- hooks.has("onSend.B").should.be.false();
- hooks.has("onSend").should.be.false();
-
- done(err);
- } catch(err2) {
- done(err2);
- }
- })
- })
-
- it("cannot remove unlabelled hook", function() {
- hooks.add("onSend", function(payload) { payload.order.push("A") } );
- (function() {
- hooks.remove("onSend")
- }).should.throw();
- })
- it("removes all hooks with same label", function(done) {
- hooks.add("onSend.A", function(payload) { payload.order.push("A") } )
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
- hooks.add("preRoute.A", function(payload) { payload.order.push("C") } )
- hooks.add("preRoute.B", function(payload) { payload.order.push("D") } )
-
- let data = { order:[] };
- hooks.trigger("onSend",data,err => {
- data.order.should.eql(["A","B"])
- hooks.trigger("preRoute", data, err => {
- data.order.should.eql(["A","B","C","D"])
-
- data.order = [];
-
- hooks.remove("*.A");
-
- hooks.trigger("onSend",data,err => {
- data.order.should.eql(["B"])
- hooks.trigger("preRoute", data, err => {
- data.order.should.eql(["B","D"])
- })
- done(err);
- })
- })
- })
- })
- it("allows a hook to remove itself whilst being called", function(done) {
- let data = { order: [] }
- hooks.add("onSend.A", function(payload) { payload.order.push("A") } )
- hooks.add("onSend.B", function(payload) {
- hooks.remove("*.B");
- })
- hooks.add("onSend.C", function(payload) { payload.order.push("C") } )
- hooks.add("onSend.D", function(payload) { payload.order.push("D") } )
-
- hooks.trigger("onSend", data, err => {
- try {
- should.not.exist(err);
- data.order.should.eql(["A","C","D"])
- done();
- } catch(e) {
- done(e);
- }
- })
- });
-
- it("allows a hook to remove itself and others whilst being called", function(done) {
- let data = { order: [] }
- hooks.add("onSend.A", function(payload) { payload.order.push("A") } )
- hooks.add("onSend.B", function(payload) {
- hooks.remove("*.B");
- hooks.remove("*.C");
- })
- hooks.add("onSend.C", function(payload) { payload.order.push("C") } )
- hooks.add("onSend.D", function(payload) { payload.order.push("D") } )
-
- hooks.trigger("onSend", data, err => {
- try {
- should.not.exist(err);
- data.order.should.eql(["A","D"])
- done();
- } catch(e) {
- done(e);
- }
- })
- });
-
- it("halts execution on return false", function(done) {
- hooks.add("onSend.A", function(payload) { payload.order.push("A"); return false } )
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
-
- let data = { order:[] };
- hooks.trigger("onSend",data,err => {
- data.order.should.eql(["A"])
- err.should.be.false();
- done();
- })
- })
- it("halts execution on thrown error", function(done) {
- hooks.add("onSend.A", function(payload) { payload.order.push("A"); throw new Error("error") } )
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
-
- let data = { order:[] };
- hooks.trigger("onSend",data,err => {
- data.order.should.eql(["A"])
- should.exist(err);
- err.should.not.be.false()
- done();
- })
- })
-
- it("handler can use callback function", function(done) {
- hooks.add("onSend.A", function(payload, done) {
- setTimeout(function() {
- payload.order.push("A")
- done()
- },30)
- })
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
-
- let data = { order:[] };
- hooks.trigger("onSend",data,err => {
- data.order.should.eql(["A","B"])
- done(err);
- })
- })
-
- it("handler can use callback function - halt execution", function(done) {
- hooks.add("onSend.A", function(payload, done) {
- setTimeout(function() {
- payload.order.push("A")
- done(false)
- },30)
- })
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
-
- let data = { order:[] };
- hooks.trigger("onSend",data,err => {
- data.order.should.eql(["A"])
- err.should.be.false()
- done();
- })
- })
- it("handler can use callback function - halt on error", function(done) {
- hooks.add("onSend.A", function(payload, done) {
- setTimeout(function() {
- done(new Error("test error"))
- },30)
- })
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
-
- let data = { order:[] };
- hooks.trigger("onSend",data,err => {
- data.order.should.eql([])
- should.exist(err);
- err.should.not.be.false()
- done();
- })
- })
-
- it("handler be an async function", function(done) {
- hooks.add("onSend.A", async function(payload) {
- return new Promise(resolve => {
- setTimeout(function() {
- payload.order.push("A")
- resolve()
- },30)
- });
- })
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
-
- let data = { order:[] };
- hooks.trigger("onSend",data,err => {
- data.order.should.eql(["A","B"])
- done(err);
- })
- })
-
- it("handler be an async function - halt execution", function(done) {
- hooks.add("onSend.A", async function(payload) {
- return new Promise(resolve => {
- setTimeout(function() {
- payload.order.push("A")
- resolve(false)
- },30)
- });
- })
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
-
- let data = { order:[] };
- hooks.trigger("onSend",data,err => {
- data.order.should.eql(["A"])
- done(err);
- })
- })
- it("handler be an async function - halt on error", function(done) {
- hooks.add("onSend.A", async function(payload) {
- return new Promise((resolve,reject) => {
- setTimeout(function() {
- reject(new Error("test error"))
- },30)
- });
- })
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
-
- let data = { order:[] };
- hooks.trigger("onSend",data,err => {
- data.order.should.eql([])
- should.exist(err);
- err.should.not.be.false()
- done();
- })
- })
-
-
- it("handler can use callback function - promise API", function(done) {
- hooks.add("onSend.A", function(payload, done) {
- setTimeout(function() {
- payload.order.push("A")
- done()
- },30)
- })
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
-
- let data = { order:[] };
- hooks.trigger("onSend",data).then(() => {
- data.order.should.eql(["A","B"])
- done()
- }).catch(done)
- })
-
- it("handler can halt execution - promise API", function(done) {
- hooks.add("onSend.A", function(payload, done) {
- setTimeout(function() {
- payload.order.push("A")
- done(false)
- },30)
- })
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
-
- let data = { order:[] };
- hooks.trigger("onSend",data).then(() => {
- data.order.should.eql(["A"])
- done()
- }).catch(done)
- })
-
- it("handler can halt execution on error - promise API", function(done) {
- hooks.add("onSend.A", function(payload, done) {
- throw new Error("error");
- })
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
-
- let data = { order:[] };
- hooks.trigger("onSend",data).then(() => {
- done("hooks.trigger resolved unexpectedly")
- }).catch(err => {
- done();
- })
- })
-});
diff --git a/test/unit/@node-red/util/lib/i18n_spec.js b/test/unit/@node-red/util/lib/i18n_spec.js
deleted file mode 100644
index 5deaba032..000000000
--- a/test/unit/@node-red/util/lib/i18n_spec.js
+++ /dev/null
@@ -1,26 +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 NR_TEST_UTILS = require("nr-test-utils");
-
- var i18n = NR_TEST_UTILS.require("@node-red/util").i18n;
-
-
-describe("@node-red/util/i18n", function() {
- it.skip('more tests needed', function(){})
-});
diff --git a/test/unit/@node-red/util/lib/index_spec.js b/test/unit/@node-red/util/lib/index_spec.js
deleted file mode 100644
index 3cf2347c1..000000000
--- a/test/unit/@node-red/util/lib/index_spec.js
+++ /dev/null
@@ -1,19 +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.
- **/
-
-describe("@node-red/util", function() {
- it.skip('more tests needed', function(){})
-});
diff --git a/test/unit/@node-red/util/lib/log_spec.js b/test/unit/@node-red/util/lib/log_spec.js
deleted file mode 100644
index 056f37672..000000000
--- a/test/unit/@node-red/util/lib/log_spec.js
+++ /dev/null
@@ -1,252 +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 util = require("util");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var log = NR_TEST_UTILS.require("@node-red/util").log;
-
-
-describe("@node-red/util/log", function() {
- beforeEach(function () {
- var spy = sinon.stub(util, 'log').callsFake(function(arg){});
- var settings = {logging: { console: { level: 'metric', metrics: true } } };
- log.init(settings);
- });
-
- afterEach(function() {
- util.log.restore();
- });
-
- it('it can raise an error', function() {
- var ret = log.error("This is an error");
- sinon.assert.calledWithMatch(util.log,"[error] This is an error");
- });
-
- it('it can raise a trace', function() {
- var ret = log.trace("This is a trace");
- sinon.assert.calledWithMatch(util.log,"[trace] This is a trace");
- });
-
- it('it can raise a debug', function() {
- var ret = log.debug("This is a debug");
- sinon.assert.calledWithMatch(util.log,"[debug] This is a debug");
- });
-
- it('it can raise a info', function() {
- var ret = log.info("This is an info");
- sinon.assert.calledWithMatch(util.log,"[info] This is an info");
- });
-
- it('it can raise a warn', function() {
- var ret = log.warn("This is a warn");
- sinon.assert.calledWithMatch(util.log,"[warn] This is a warn");
- });
-
- it('it can raise a metric', function() {
- var metrics = {};
- metrics.level = log.METRIC;
- metrics.nodeid = "testid";
- metrics.event = "node.test.testevent";
- metrics.msgid = "12345";
- metrics.value = "the metric payload";
- var ret = log.log(metrics);
- util.log.calledOnce.should.be.true();
- util.log.firstCall.args[0].indexOf("[metric] ").should.equal(0);
- var body = JSON.parse(util.log.firstCall.args[0].substring(9));
- body.should.have.a.property("nodeid","testid");
- body.should.have.a.property("event","node.test.testevent");
- body.should.have.a.property("msgid","12345");
- body.should.have.a.property("value","the metric payload");
- body.should.have.a.property("timestamp");
- body.should.have.a.property("level",log.METRIC);
- });
-
- it('it checks metrics are enabled', function() {
- log.metric().should.equal(true);
- var sett = {logging: { console: { level: 'info', metrics: false } } };
- log.init(sett);
- log.metric().should.equal(false);
- });
-
- it('it logs node type and name if provided',function() {
- log.log({level:log.INFO,type:"nodeType",msg:"test",name:"nodeName",id:"nodeId"});
- util.log.calledOnce.should.be.true();
- util.log.firstCall.args[0].indexOf("[nodeType:nodeName]").should.not.equal(-1);
- });
- it('it logs node type and id if no name provided',function() {
- log.log({level:log.INFO,type:"nodeType",msg:"test",id:"nodeId"});
- util.log.calledOnce.should.be.true();
- util.log.firstCall.args[0].indexOf("[nodeType:nodeId]").should.not.equal(-1);
- });
-
- it('ignores lower level messages and metrics', function() {
- var settings = {logging: { console: { level: 'warn', metrics: false } } };
- log.init(settings);
- log.error("This is an error");
- log.warn("This is a warn");
- log.info("This is an info");
- log.debug("This is a debug");
- log.trace("This is a trace");
- log.log({level:log.METRIC,msg:"testMetric"});
- sinon.assert.calledWithMatch(util.log,"[error] This is an error");
- sinon.assert.calledWithMatch(util.log,"[warn] This is a warn");
- sinon.assert.neverCalledWithMatch(util.log,"[info] This is an info");
- sinon.assert.neverCalledWithMatch(util.log,"[debug] This is a debug");
- sinon.assert.neverCalledWithMatch(util.log,"[trace] This is a trace");
- sinon.assert.neverCalledWithMatch(util.log,"[metric] ");
- });
- it('ignores lower level messages but accepts metrics', function() {
- var settings = {logging: { console: { level: 'log', metrics: true } } };
- log.init(settings);
- log.error("This is an error");
- log.warn("This is a warn");
- log.info("This is an info");
- log.debug("This is a debug");
- log.trace("This is a trace");
- log.log({level:log.METRIC,msg:"testMetric"});
- sinon.assert.calledWithMatch(util.log,"[error] This is an error");
- sinon.assert.calledWithMatch(util.log,"[warn] This is a warn");
- sinon.assert.calledWithMatch(util.log,"[info] This is an info");
- sinon.assert.neverCalledWithMatch(util.log,"[debug] This is a debug");
- sinon.assert.neverCalledWithMatch(util.log,"[trace] This is a trace");
- sinon.assert.calledWithMatch(util.log,"[metric] ");
- });
-
- it('default settings set to INFO and metrics off', function() {
- log.init({logging:{}});
- log.error("This is an error");
- log.warn("This is a warn");
- log.info("This is an info");
- log.debug("This is a debug");
- log.trace("This is a trace");
- log.log({level:log.METRIC,msg:"testMetric"});
- sinon.assert.calledWithMatch(util.log,"[error] This is an error");
- sinon.assert.calledWithMatch(util.log,"[warn] This is a warn");
- sinon.assert.calledWithMatch(util.log,"[info] This is an info");
- sinon.assert.neverCalledWithMatch(util.log,"[debug] This is a debug");
- sinon.assert.neverCalledWithMatch(util.log,"[trace] This is a trace");
- sinon.assert.neverCalledWithMatch(util.log,"[metric] ");
- });
- it('no logger used if custom logger handler does not exist', function() {
- var settings = {logging: { customLogger: { level: 'trace', metrics: true } } };
- log.init(settings);
- log.error("This is an error");
- log.warn("This is a warn");
- log.info("This is an info");
- log.debug("This is a debug");
- log.trace("This is a trace");
- log.log({level:log.METRIC,msg:"testMetric"});
- sinon.assert.neverCalledWithMatch(util.log,"[error] This is an error");
- sinon.assert.neverCalledWithMatch(util.log,"[warn] This is a warn");
- sinon.assert.neverCalledWithMatch(util.log,"[info] This is an info");
- sinon.assert.neverCalledWithMatch(util.log,"[debug] This is a debug");
- sinon.assert.neverCalledWithMatch(util.log,"[trace] This is a trace");
- sinon.assert.neverCalledWithMatch(util.log,"[metric] ");
- });
-
- it('add a custom log handler directly', function() {
- var settings = {};
- log.init(settings);
-
- var logEvents = [];
- var loggerOne = {
- emit: function(event,msg) {
- logEvents.push({logger:1,msg:msg});
- }
- };
- var loggerTwo = {
- emit: function(event,msg) {
- logEvents.push({logger:2,msg:msg});
- }
- };
- log.addHandler(loggerOne);
- log.addHandler(loggerTwo);
-
- log.error("This is an error");
- log.warn("This is a warn");
- log.info("This is an info");
- log.debug("This is a debug");
- log.trace("This is a trace");
- log.log({level:log.METRIC,msg:"testMetric"});
-
- logEvents.filter(function(evt) { return evt.logger === 1}).should.have.lengthOf(6);
- logEvents.filter(function(evt) { return evt.logger === 2}).should.have.lengthOf(6);
- });
-
- it('remove a custom log handler directly', function() {
- var settings = {};
- log.init(settings);
-
- var logEvents = [];
- var loggerOne = {
- emit: function(event,msg) {
- logEvents.push({logger:1,msg:msg});
- }
- };
- var loggerTwo = {
- emit: function(event,msg) {
- logEvents.push({logger:2,msg:msg});
- }
- };
- log.addHandler(loggerOne);
- log.addHandler(loggerTwo);
-
- log.info("This is an info");
- logEvents.filter(function(evt) { return evt.logger === 1}).should.have.lengthOf(1);
- logEvents.filter(function(evt) { return evt.logger === 2}).should.have.lengthOf(1);
-
-
- log.removeHandler(loggerTwo);
- log.info("This is an info");
- logEvents.filter(function(evt) { return evt.logger === 1}).should.have.lengthOf(2);
- logEvents.filter(function(evt) { return evt.logger === 2}).should.have.lengthOf(1);
-
- log.removeHandler(loggerOne);
- log.info("This is an info");
- logEvents.filter(function(evt) { return evt.logger === 1}).should.have.lengthOf(2);
- logEvents.filter(function(evt) { return evt.logger === 2}).should.have.lengthOf(1);
-
-
- });
- it('it can log without exception', function() {
- var msg = {
- msg: {
- mystrangeobj:"hello",
- },
- };
- msg.msg.toString = function(){
- throw new Error('Exception in toString - should have been caught');
- }
- msg.msg.constructor = { name: "strangeobj" };
- var ret = log.info(msg.msg);
- });
- it('it can log an object but use .message', function() {
- var msg = {
- msg: {
- message: "my special message",
- mystrangeobj:"hello",
- },
- };
- var ret = log.info(msg.msg);
- sinon.assert.calledWithMatch(util.log,"my special message");
- });
-
-
-
-});
diff --git a/test/unit/@node-red/util/lib/util_spec.js b/test/unit/@node-red/util/lib/util_spec.js
deleted file mode 100644
index 5007fe5c5..000000000
--- a/test/unit/@node-red/util/lib/util_spec.js
+++ /dev/null
@@ -1,1092 +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 util = NR_TEST_UTILS.require("@node-red/util").util;
-
-describe("@node-red/util/util", function() {
- describe('generateId', function() {
- it('generates an id', function() {
- var id = util.generateId();
- var id2 = util.generateId();
- id.should.not.eql(id2);
- });
- });
- describe('compareObjects', function() {
- it('numbers', function() {
- util.compareObjects(0,0).should.equal(true);
- util.compareObjects(0,1).should.equal(false);
- util.compareObjects(1000,1001).should.equal(false);
- util.compareObjects(1000,1000).should.equal(true);
- util.compareObjects(0,"0").should.equal(false);
- util.compareObjects(1,"1").should.equal(false);
- util.compareObjects(0,null).should.equal(false);
- util.compareObjects(0,undefined).should.equal(false);
- });
- it('strings', function() {
- util.compareObjects("","").should.equal(true);
- util.compareObjects("a","a").should.equal(true);
- util.compareObjects("",null).should.equal(false);
- util.compareObjects("",undefined).should.equal(false);
- });
-
- it('arrays', function() {
- util.compareObjects(["a"],["a"]).should.equal(true);
- util.compareObjects(["a"],["a","b"]).should.equal(false);
- util.compareObjects(["a","b"],["b"]).should.equal(false);
- util.compareObjects(["a"],"a").should.equal(false);
- util.compareObjects([[1],["a"]],[[1],["a"]]).should.equal(true);
- util.compareObjects([[1],["a"]],[["a"],[1]]).should.equal(false);
- });
- it('objects', function() {
- util.compareObjects({"a":1},{"a":1,"b":1}).should.equal(false);
- util.compareObjects({"a":1,"b":1},{"a":1,"b":1}).should.equal(true);
- util.compareObjects({"b":1,"a":1},{"a":1,"b":1}).should.equal(true);
- });
- it('Buffer', function() {
- util.compareObjects(Buffer.from("hello"),Buffer.from("hello")).should.equal(true);
- util.compareObjects(Buffer.from("hello"),Buffer.from("hello ")).should.equal(false);
- util.compareObjects(Buffer.from("hello"),"hello").should.equal(false);
- });
-
- });
-
- describe('ensureString', function() {
- it('strings are preserved', function() {
- util.ensureString('string').should.equal('string');
- });
- it('Buffer is converted', function() {
- var s = util.ensureString(Buffer.from('foo'));
- s.should.equal('foo');
- (typeof s).should.equal('string');
- });
- it('Object is converted to JSON', function() {
- var s = util.ensureString({foo: "bar"});
- (typeof s).should.equal('string');
- should.deepEqual(JSON.parse(s), {foo:"bar"});
- });
- it('stringifies other things', function() {
- var s = util.ensureString(123);
- (typeof s).should.equal('string');
- s.should.equal('123');
- });
- });
-
- describe('ensureBuffer', function() {
- it('Buffers are preserved', function() {
- var b = Buffer.from('');
- util.ensureBuffer(b).should.equal(b);
- });
- it('string is converted', function() {
- var b = util.ensureBuffer('foo');
- var expected = Buffer.from('foo');
- for (var i = 0; i < expected.length; i++) {
- b[i].should.equal(expected[i]);
- }
- Buffer.isBuffer(b).should.equal(true);
- });
- it('Object is converted to JSON', function() {
- var obj = {foo: "bar"}
- var b = util.ensureBuffer(obj);
- Buffer.isBuffer(b).should.equal(true);
- should.deepEqual(JSON.parse(b), obj);
- });
- it('stringifies other things', function() {
- var b = util.ensureBuffer(123);
- Buffer.isBuffer(b).should.equal(true);
- var expected = Buffer.from('123');
- for (var i = 0; i < expected.length; i++) {
- b[i].should.equal(expected[i]);
- }
- });
- });
-
- describe('cloneMessage', function() {
- it('clones a simple message', function() {
- var msg = {string:"hi",array:[1,2,3],object:{a:1,subobject:{b:2}}};
-
- var cloned = util.cloneMessage(msg);
-
- cloned.should.eql(msg);
-
- cloned.should.not.equal(msg);
- cloned.array.should.not.equal(msg.string);
- cloned.object.should.not.equal(msg.object);
- cloned.object.subobject.should.not.equal(msg.object.subobject);
-
- cloned.should.not.have.property("req");
- cloned.should.not.have.property("res");
- });
- it('does not clone http req/res properties', function() {
- var msg = {req:{a:1},res:{b:2}};
-
- var cloned = util.cloneMessage(msg);
-
- cloned.should.eql(msg);
- cloned.should.not.equal(msg);
-
- cloned.req.should.equal(msg.req);
- cloned.res.should.equal(msg.res);
- });
- it('handles undefined values without throwing an error', function() {
- var result = util.cloneMessage(undefined);
- should.not.exist(result);
- })
- });
- describe('getObjectProperty', function() {
- it('gets a property beginning with "msg."', function() {
- // getMessageProperty strips off `msg.` prefixes.
- // getObjectProperty does not
- var obj = { msg: { a: "foo"}, a: "bar"};
- var v = util.getObjectProperty(obj,"msg.a");
- v.should.eql("foo");
- })
- });
- describe('getMessageProperty', function() {
- it('retrieves a simple property', function() {
- var v = util.getMessageProperty({a:"foo"},"msg.a");
- v.should.eql("foo");
- 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);
- });
- it('should throw error if property parent does not exist', function() {
- /*jshint immed: false */
- (function() {
- util.getMessageProperty({a:"foo"},"msg.a.b.c");
- }).should.throw();
- });
- it('retrieves a property with array syntax', function() {
- var v = util.getMessageProperty({a:["foo","bar"]},"msg.a[0]");
- v.should.eql("foo");
- var v2 = util.getMessageProperty({a:[null,{b:"foo"}]},"a[1].b");
- v2.should.eql("foo");
- var v3 = util.getMessageProperty({a:[[["foo"]]]},"a[0][0][0]");
- v3.should.eql("foo");
- });
-
- });
- describe('setObjectProperty', function() {
- it('set a property beginning with "msg."', function() {
- // setMessageProperty strips off `msg.` prefixes.
- // setObjectProperty does not
- var obj = {};
- var result = util.setObjectProperty(obj,"msg.a","bar");
- result.should.be.true();
- obj.should.have.property("msg");
- obj.msg.should.have.property("a","bar");
- })
- });
- describe('setMessageProperty', function() {
- it('sets a property', function() {
- var msg = {a:"foo"};
- var result = util.setMessageProperty(msg,"msg.a","bar");
- result.should.be.true();
- msg.a.should.eql('bar');
- });
- it('sets a deep level property', function() {
- var msg = {a:{b:{c:"foo"}}};
- var result = util.setMessageProperty(msg,"msg.a.b.c","bar");
- result.should.be.true();
- msg.a.b.c.should.eql('bar');
- });
- it('creates missing parent properties by default', function() {
- var msg = {a:{}};
- var result = util.setMessageProperty(msg,"msg.a.b.c","bar");
- result.should.be.true();
- msg.a.b.c.should.eql('bar');
- })
- it('does not create missing parent properties', function() {
- var msg = {a:{}};
- var result = util.setMessageProperty(msg,"msg.a.b.c","bar",false);
- result.should.be.false();
- should.not.exist(msg.a.b);
- })
- it('does not create missing parent properties of array', function () {
- var msg = {a:{}};
- var result = util.setMessageProperty(msg, "msg.a.b[1].c", "bar", false);
- result.should.be.false();
- should.not.exist(msg.a.b);
- })
-
- it('does not create missing parent properties of string', function() {
- var msg = {a:"foo"};
- var result = util.setMessageProperty(msg, "msg.a.b.c", "bar", false);
- result.should.be.false();
- should.not.exist(msg.a.b);
- })
- it('does not set property of existing string property', function() {
- var msg = {a:"foo"};
- var result = util.setMessageProperty(msg, "msg.a.b", "bar", false);
- result.should.be.false();
- should.not.exist(msg.a.b);
- })
-
- it('does not set property of existing number property', function() {
- var msg = {a:123};
- var result = util.setMessageProperty(msg, "msg.a.b", "bar", false);
- result.should.be.false();
- should.not.exist(msg.a.b);
- })
- it('does not create missing parent properties of number', function() {
- var msg = {a:123};
- var result = util.setMessageProperty(msg, "msg.a.b.c", "bar", false);
- result.should.be.false();
- should.not.exist(msg.a.b);
- })
-
- it('does not set property of existing boolean property', function() {
- var msg = {a:true};
- var result = util.setMessageProperty(msg, "msg.a.b", "bar", false);
- result.should.be.false();
- should.not.exist(msg.a.b);
- })
- it('does not create missing parent properties of boolean', function() {
- var msg = {a:true};
- var result = util.setMessageProperty(msg, "msg.a.b.c", "bar", false);
- result.should.be.false();
- should.not.exist(msg.a.b);
- })
-
-
- it('deletes property if value is undefined', function() {
- var msg = {a:{b:{c:"foo"}}};
- var result = util.setMessageProperty(msg,"msg.a.b.c",undefined);
- result.should.be.true();
- should.not.exist(msg.a.b.c);
- })
- it('does not create missing parent properties if value is undefined', function() {
- var msg = {a:{}};
- var result = util.setMessageProperty(msg,"msg.a.b.c",undefined);
- result.should.be.false();
- should.not.exist(msg.a.b);
- });
- it('sets a property with array syntax', function() {
- var msg = {a:{b:["foo",{c:["",""]}]}};
- var result = util.setMessageProperty(msg,"msg.a.b[1].c[1]","bar");
- result.should.be.true();
- msg.a.b[1].c[1].should.eql('bar');
- });
- it('creates missing array elements - final property', function() {
- var msg = {a:[]};
- var result = util.setMessageProperty(msg,"msg.a[2]","bar");
- result.should.be.true();
- msg.a.should.have.length(3);
- msg.a[2].should.eql("bar");
- });
- it('creates missing array elements - mid property', function() {
- var msg = {};
- var result = util.setMessageProperty(msg,"msg.a[2].b","bar");
- result.should.be.true();
- msg.a.should.have.length(3);
- msg.a[2].b.should.eql("bar");
- });
- it('creates missing array elements - multi-arrays', function() {
- var msg = {};
- var result = util.setMessageProperty(msg,"msg.a[2][2]","bar");
- result.should.be.true();
- msg.a.should.have.length(3);
- msg.a.should.be.instanceOf(Array);
- msg.a[2].should.have.length(3);
- msg.a[2].should.be.instanceOf(Array);
- msg.a[2][2].should.eql("bar");
- });
- it('does not create missing array elements - mid property', function () {
- var msg = {a:[]};
- var result = util.setMessageProperty(msg, "msg.a[1][1]", "bar", false);
- result.should.be.false();
- msg.a.should.empty();
- });
- it('does not create missing array elements - final property', function() {
- var msg = {a:{}};
- var result = util.setMessageProperty(msg,"msg.a.b[2]","bar",false);
- result.should.be.false();
- should.not.exist(msg.a.b);
- // check it has not been misinterpreted
- msg.a.should.not.have.property("b[2]");
- });
- it('deletes property inside array if value is undefined', function() {
- var msg = {a:[1,2,3]};
- var result = util.setMessageProperty(msg,"msg.a[1]",undefined);
- result.should.be.true();
- msg.a.should.have.length(2);
- 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() {
- it('returns string',function() {
- var result = util.evaluateNodeProperty('hello','str');
- result.should.eql('hello');
- });
- it('returns number',function() {
- var result = util.evaluateNodeProperty('0123','num');
- result.should.eql(123);
- });
- it('returns evaluated json',function() {
- var result = util.evaluateNodeProperty('{"a":123}','json');
- result.should.eql({a:123});
- });
- it('returns regex',function() {
- var result = util.evaluateNodeProperty('^abc$','re');
- result.toString().should.eql("/^abc$/");
- });
- it('returns boolean',function() {
- var result = util.evaluateNodeProperty('true','bool');
- result.should.be.true();
- result = util.evaluateNodeProperty('TrUe','bool');
- result.should.be.true();
- result = util.evaluateNodeProperty('false','bool');
- result.should.be.false();
- result = util.evaluateNodeProperty('','bool');
- result.should.be.false();
- });
- it('returns date',function() {
- var result = util.evaluateNodeProperty('','date');
- (Date.now() - result).should.be.approximately(0,50);
- });
- it('returns bin', function () {
- var result = util.evaluateNodeProperty('[1, 2]','bin');
- result[0].should.eql(1);
- result[1].should.eql(2);
- });
- it('returns msg property',function() {
- var result = util.evaluateNodeProperty('foo.bar','msg',{},{foo:{bar:"123"}});
- result.should.eql("123");
- });
- it('throws an error if callback is not defined', function (done) {
- try {
- util.evaluateNodeProperty(' ','msg',{},{foo:{bar:"123"}});
- done("should throw an error");
- } catch (err) {
- done();
- }
- });
- it('returns flow property',function() {
- var result = util.evaluateNodeProperty('foo.bar','flow',{
- context:function() { return {
- flow: { get: function(k) {
- if (k === 'foo.bar') {
- return '123';
- } else {
- return null;
- }
- }}
- }}
- },{});
- result.should.eql("123");
- });
- it('returns global property',function() {
- var result = util.evaluateNodeProperty('foo.bar','global',{
- context:function() { return {
- global: { get: function(k) {
- if (k === 'foo.bar') {
- return '123';
- } else {
- return null;
- }
- }}
- }}
- },{});
- result.should.eql("123");
- });
- it('returns jsonata result', function () {
- var result = util.evaluateNodeProperty('$abs(-1)','jsonata',{},{});
- result.should.eql(1);
- });
- it('returns null', function() {
- var result = util.evaluateNodeProperty(null,'null');
- (result === null).should.be.true();
- })
- describe('environment variable', function() {
- before(function() {
- process.env.NR_TEST_A = "foo";
- process.env.NR_TEST_B = "${NR_TEST_A}";
- })
- after(function() {
- delete process.env.NR_TEST_A;
- delete process.env.NR_TEST_B;
- })
-
- it('returns an environment variable - NR_TEST_A', function() {
- var result = util.evaluateNodeProperty('NR_TEST_A','env');
- result.should.eql('foo');
- });
- it('returns an environment variable - ${NR_TEST_A}', function() {
- var result = util.evaluateNodeProperty('${NR_TEST_A}','env');
- result.should.eql('foo');
- });
- it('returns an environment variable - ${NR_TEST_A', function() {
- var result = util.evaluateNodeProperty('${NR_TEST_A','env');
- result.should.eql('');
- });
- it('returns an environment variable - foo${NR_TEST_A}bar', function() {
- var result = util.evaluateNodeProperty('123${NR_TEST_A}456','env');
- result.should.eql('123foo456');
- });
- it('returns an environment variable - foo${NR_TEST_B}bar', function() {
- var result = util.evaluateNodeProperty('123${NR_TEST_B}456','env');
- result.should.eql('123${NR_TEST_A}456');
- });
-
- });
- });
-
- describe('normalisePropertyExpression', function() {
- function testABC(input,expected) {
- var result = util.normalisePropertyExpression(input);
- // console.log("+",input);
- // console.log(result);
- result.should.eql(expected);
- }
- 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,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']); })
- it("pass a['b'].c",function() { testABC("a['b'].c",['a','b','c']); })
-
- it("pass a[0].c",function() { testABC("a[0].c",['a',0,'c']); })
- it("pass a.0.c",function() { testABC("a.0.c",['a',0,'c']); })
- it("pass a['a.b[0]'].c",function() { testABC("a['a.b[0]'].c",['a','a.b[0]','c']); })
- it("pass a[0][0][0]",function() { testABC("a[0][0][0]",['a',0,0,0]); })
- it("pass '1.2.3.4'",function() { testABC("'1.2.3.4'",['1.2.3.4']); })
- 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[]"); })
- it("fail a]",function() { testInvalid("a]"); })
- it("fail a[",function() { testInvalid("a["); })
- it("fail a[0d]",function() { testInvalid("a[0d]"); })
- it("fail a['",function() { testInvalid("a['"); })
- it("fail a[']",function() { testInvalid("a[']"); })
- it("fail a[0']",function() { testInvalid("a[0']"); })
- it("fail a.[0]",function() { testInvalid("a.[0]"); })
- it("fail [0]",function() { testInvalid("[0]"); })
- it("fail a[0",function() { testInvalid("a[0"); })
- it("fail a.",function() { testInvalid("a."); })
- it("fail .a",function() { testInvalid(".a"); })
- it("fail a. b",function() { testInvalid("a. b"); })
- it("fail a.b",function() { testInvalid(" a.b"); })
- it("fail a[0].[1]",function() { testInvalid("a[0].[1]"); })
- it("fail a['']",function() { testInvalid("a['']"); })
- it("fail 'a.b'c",function() { testInvalid("'a.b'c"); })
- it("fail ",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]",{})})
-
- });
-
- describe('normaliseNodeTypeName', function() {
- function normalise(input, expected) {
- var result = util.normaliseNodeTypeName(input);
- result.should.eql(expected);
- }
-
- it('pass blank',function() { normalise("", "") });
- it('pass ab1',function() { normalise("ab1", "ab1") });
- it('pass AB1',function() { normalise("AB1", "aB1") });
- it('pass a b 1',function() { normalise("a b 1", "aB1") });
- it('pass a-b-1',function() { normalise("a-b-1", "aB1") });
- it('pass ab1 ',function() { normalise(" ab1 ", "ab1") });
- it('pass _a_b_1_',function() { normalise("_a_b_1_", "aB1") });
- it('pass http request',function() { normalise("http request", "httpRequest") });
- it('pass HttpRequest',function() { normalise("HttpRequest", "httpRequest") });
- });
-
- describe('prepareJSONataExpression', function() {
- it('prepares an expression', function() {
- var result = util.prepareJSONataExpression('payload',{});
- result.should.have.property('evaluate');
- result.should.have.property('assign');
- result.should.have.property('_legacyMode', false);
- });
- it('prepares a legacyMode expression', function() {
- var result = util.prepareJSONataExpression('msg.payload',{});
- result.should.have.property('evaluate');
- result.should.have.property('assign');
- result.should.have.property('_legacyMode', true);
- });
- });
- describe('evaluateJSONataExpression', function() {
- it('evaluates an expression', function() {
- var expr = util.prepareJSONataExpression('payload',{});
- var result = util.evaluateJSONataExpression(expr,{payload:"hello"});
- result.should.eql("hello");
- });
- it('evaluates a legacyMode expression', function() {
- var expr = util.prepareJSONataExpression('msg.payload',{});
- var result = util.evaluateJSONataExpression(expr,{payload:"hello"});
- result.should.eql("hello");
- });
- it('accesses flow context from an expression', function() {
- var expr = util.prepareJSONataExpression('$flowContext("foo")',{context:function() { return {flow:{get: function(key) { return {'foo':'bar'}[key]}}}}});
- var result = util.evaluateJSONataExpression(expr,{payload:"hello"});
- result.should.eql("bar");
- });
- it('accesses undefined environment variable from an expression', function() {
- var expr = util.prepareJSONataExpression('$env("UTIL_ENV")',{});
- var result = util.evaluateJSONataExpression(expr,{});
- result.should.eql('');
- });
- it('accesses environment variable from an expression', function() {
- process.env.UTIL_ENV = 'foo';
- var expr = util.prepareJSONataExpression('$env("UTIL_ENV")',{});
- var result = util.evaluateJSONataExpression(expr,{});
- result.should.eql('foo');
- });
- it('accesses moment from an expression', function() {
- var expr = util.prepareJSONataExpression('$moment("2020-05-27", "YYYY-MM-DD").add(7, "days").add(1, "months").format("YYYY-MM-DD")',{});
- var result = util.evaluateJSONataExpression(expr,{});
- result.should.eql('2020-07-03');
- });
- it('accesses moment-timezone from an expression', function() {
- var expr = util.prepareJSONataExpression('$moment("2013-11-18 11:55Z").tz("Asia/Taipei").format()',{});
- var result = util.evaluateJSONataExpression(expr,{});
- result.should.eql('2013-11-18T19:55:00+08:00');
- });
- it('handles non-existant flow context variable', function() {
- var expr = util.prepareJSONataExpression('$flowContext("nonExistant")',{context:function() { return {flow:{get: function(key) { return {'foo':'bar'}[key]}}}}});
- var result = util.evaluateJSONataExpression(expr,{payload:"hello"});
- should.not.exist(result);
- });
- it('handles non-existant global context variable', function() {
- var expr = util.prepareJSONataExpression('$globalContext("nonExistant")',{context:function() { return {global:{get: function(key) { return {'foo':'bar'}[key]}}}}});
- var result = util.evaluateJSONataExpression(expr,{payload:"hello"});
- should.not.exist(result);
- });
- it('handles async flow context access', function(done) {
- var expr = util.prepareJSONataExpression('$flowContext("foo")',{context:function() { return {flow:{get: function(key,store,callback) { setTimeout(()=>{callback(null,{'foo':'bar'}[key])},10)}}}}});
- util.evaluateJSONataExpression(expr,{payload:"hello"},function(err,value) {
- try {
- should.not.exist(err);
- value.should.eql("bar");
- done();
- } catch(err2) {
- done(err2);
- }
- });
- })
- it('handles async global context access', function(done) {
- var expr = util.prepareJSONataExpression('$globalContext("foo")',{context:function() { return {global:{get: function(key,store,callback) { setTimeout(()=>{callback(null,{'foo':'bar'}[key])},10)}}}}});
- util.evaluateJSONataExpression(expr,{payload:"hello"},function(err,value) {
- try {
- should.not.exist(err);
- value.should.eql("bar");
- done();
- } catch(err2) {
- done(err2);
- }
- });
- })
- it('handles persistable store in flow context access', function(done) {
- var storeName;
- var expr = util.prepareJSONataExpression('$flowContext("foo", "flowStoreName")',{context:function() { return {flow:{get: function(key,store,callback) { storeName = store;setTimeout(()=>{callback(null,{'foo':'bar'}[key])},10)}}}}});
- util.evaluateJSONataExpression(expr,{payload:"hello"},function(err,value) {
- try {
- should.not.exist(err);
- value.should.eql("bar");
- storeName.should.equal("flowStoreName");
- done();
- } catch(err2) {
- done(err2);
- }
- });
- })
- it('handles persistable store in global context access', function(done) {
- var storeName;
- var expr = util.prepareJSONataExpression('$globalContext("foo", "globalStoreName")',{context:function() { return {global:{get: function(key,store,callback) { storeName = store;setTimeout(()=>{callback(null,{'foo':'bar'}[key])},10)}}}}});
- util.evaluateJSONataExpression(expr,{payload:"hello"},function(err,value) {
- try {
- should.not.exist(err);
- value.should.eql("bar");
- storeName.should.equal("globalStoreName");
- done();
- } catch(err2) {
- done(err2);
- }
- });
- })
- it('callbacks with error when invalid expression was specified', function (done) {
- var expr = util.prepareJSONataExpression('$abc(1)',{});
- var result = util.evaluateJSONataExpression(expr,{payload:"hello"},function(err,value){
- should.exist(err);
- done();
- });
- });
- });
-
- describe('encodeObject', function () {
- it('encodes Error with message', function() {
- var err = new Error("encode error");
- err.name = 'encodeError';
- var msg = {msg:err};
- var result = util.encodeObject(msg);
- result.format.should.eql("error");
- var resultJson = JSON.parse(result.msg);
- resultJson.name.should.eql('encodeError');
- resultJson.message.should.eql('encode error');
- });
- it('encodes Error without message', function() {
- var err = new Error();
- err.name = 'encodeError';
- err.toString = function(){return 'error message';}
- var msg = {msg:err};
- var result = util.encodeObject(msg);
- result.format.should.eql("error");
- var resultJson = JSON.parse(result.msg);
- resultJson.name.should.eql('encodeError');
- resultJson.message.should.eql('error message');
- });
- it('encodes Buffer', function() {
- var msg = {msg:Buffer.from("abc")};
- var result = util.encodeObject(msg,{maxLength:4});
- result.format.should.eql("buffer[3]");
- result.msg[0].should.eql('6');
- result.msg[1].should.eql('1');
- result.msg[2].should.eql('6');
- result.msg[3].should.eql('2');
- });
- it('encodes function', function() {
- var msg = {msg:function(){}};
- var result = util.encodeObject(msg);
- result.format.should.eql("function");
- result.msg.should.eql('[function]');
- });
- it('encodes boolean', function() {
- var msg = {msg:true};
- var result = util.encodeObject(msg);
- result.format.should.eql("boolean");
- result.msg.should.eql('true');
- });
- it('encodes number', function() {
- var msg = {msg:123};
- var result = util.encodeObject(msg);
- result.format.should.eql("number");
- result.msg.should.eql('123');
- });
- it('encodes 0', function() {
- var msg = {msg:0};
- var result = util.encodeObject(msg);
- result.format.should.eql("number");
- result.msg.should.eql('0');
- });
- it('encodes null', function() {
- var msg = {msg:null};
- var result = util.encodeObject(msg);
- result.format.should.eql("null");
- result.msg.should.eql('(undefined)');
- });
- it('encodes undefined', function() {
- var msg = {msg:undefined};
- var result = util.encodeObject(msg);
- result.format.should.eql("undefined");
- result.msg.should.eql('(undefined)');
- });
- it('encodes string', function() {
- var msg = {msg:'1234567890'};
- var result = util.encodeObject(msg,{maxLength:6});
- result.format.should.eql("string[10]");
- result.msg.should.eql('123456...');
- });
-
- it('encodes Map', function() {
- const m = new Map();
- m.set("a",1);
- m.set("b",2);
- var msg = {msg:m};
- var result = util.encodeObject(msg);
- result.format.should.eql("map");
- var resultJson = JSON.parse(result.msg);
- resultJson.should.have.property("__enc__",true);
- resultJson.should.have.property("type","map");
- resultJson.should.have.property("data",{"a":1,"b":2});
- resultJson.should.have.property("length",2)
- });
-
- it('encodes Set', function() {
- const m = new Set();
- m.add("a");
- m.add("b");
- var msg = {msg:m};
- var result = util.encodeObject(msg);
- result.format.should.eql("set[2]");
- var resultJson = JSON.parse(result.msg);
- resultJson.should.have.property("__enc__",true);
- resultJson.should.have.property("type","set");
- resultJson.should.have.property("data",["a","b"]);
- resultJson.should.have.property("length",2)
- });
-
-
- describe('encode object', function() {
- it('object', function() {
- var msg = { msg:{"foo":"bar"} };
- var result = util.encodeObject(msg);
- result.format.should.eql("Object");
- var resultJson = JSON.parse(result.msg);
- resultJson.foo.should.eql('bar');
- });
- it('object whose name includes error', function() {
- function MyErrorObj(){
- this.name = 'my error obj';
- this.message = 'my error message';
- };
- var msg = { msg:new MyErrorObj() };
- var result = util.encodeObject(msg);
- result.format.should.eql("MyErrorObj");
- var resultJson = JSON.parse(result.msg);
- resultJson.name.should.eql('my error obj');
- resultJson.message.should.eql('my error message');
- });
-
- it('object with undefined property', function() {
- var msg = { msg:{a:1,b:undefined,c:3 } };
- var result = util.encodeObject(msg);
- result.format.should.eql("Object");
- var resultJson = JSON.parse(result.msg);
- resultJson.should.have.property("a",1);
- resultJson.should.have.property("c",3);
- resultJson.should.have.property("b");
- resultJson.b.should.have.property("__enc__", true);
- resultJson.b.should.have.property("type", "undefined");
- });
- it('object with Map property', function() {
- const m = new Map();
- m.set("a",1);
- m.set("b",2);
- var msg = {msg:{"aMap":m}};
- var result = util.encodeObject(msg);
- result.format.should.eql("Object");
- var resultJson = JSON.parse(result.msg);
- resultJson.should.have.property("aMap");
- resultJson.aMap.should.have.property("__enc__",true);
- resultJson.aMap.should.have.property("type","map");
- resultJson.aMap.should.have.property("data",{"a":1,"b":2});
- resultJson.aMap.should.have.property("length",2)
- });
- it('object with Set property', function() {
- const m = new Set();
- m.add("a");
- m.add("b");
- var msg = {msg:{"aSet":m}};
- var result = util.encodeObject(msg);
- result.format.should.eql("Object");
- var resultJson = JSON.parse(result.msg);
- resultJson.should.have.property("aSet");
- resultJson.aSet.should.have.property("__enc__",true);
- resultJson.aSet.should.have.property("type","set");
- resultJson.aSet.should.have.property("data",["a","b"]);
- resultJson.aSet.should.have.property("length",2)
- });
- it('constructor of IncomingMessage', function() {
- function IncomingMessage(){};
- var msg = { msg:new IncomingMessage() };
- var result = util.encodeObject(msg);
- result.format.should.eql("Object");
- var resultJson = JSON.parse(result.msg);
- resultJson.should.empty();
- });
- it('_req key in msg', function() {
- function Socket(){};
- var msg = { msg:{"_req":123} };
- var result = util.encodeObject(msg);
- result.format.should.eql("Object");
- var resultJson = JSON.parse(result.msg);
- resultJson._req.__enc__.should.eql(true);
- resultJson._req.type.should.eql('internal');
- });
- it('_res key in msg', function() {
- function Socket(){};
- var msg = { msg:{"_res":123} };
- var result = util.encodeObject(msg);
- result.format.should.eql("Object");
- var resultJson = JSON.parse(result.msg);
- resultJson._res.__enc__.should.eql(true);
- resultJson._res.type.should.eql('internal');
- });
- it('array of error', function() {
- var msg = { msg:[new Error("encode error")] };
- var result = util.encodeObject(msg);
- result.format.should.eql("array[1]");
- var resultJson = JSON.parse(result.msg);
- resultJson[0].should.eql('Error: encode error');
- });
- it('long array in msg', function() {
- var msg = {msg:{array:[1,2,3,4]}};
- var result = util.encodeObject(msg,{maxLength:2});
- result.format.should.eql("Object");
- var resultJson = JSON.parse(result.msg);
- resultJson.array.__enc__.should.eql(true);
- resultJson.array.data[0].should.eql(1);
- resultJson.array.data[1].should.eql(2);
- resultJson.array.length.should.eql(4);
- });
- it('array of string', function() {
- var msg = { msg:["abcde","12345"] };
- var result = util.encodeObject(msg,{maxLength:3});
- result.format.should.eql("array[2]");
- var resultJson = JSON.parse(result.msg);
- resultJson[0].should.eql('abc...');
- resultJson[1].should.eql('123...');
- });
- it('array containing undefined', function() {
- var msg = { msg:[1,undefined,3]};
- var result = util.encodeObject(msg);
- result.format.should.eql("array[3]");
- var resultJson = JSON.parse(result.msg);
- resultJson[0].should.eql(1);
- resultJson[2].should.eql(3);
- resultJson[1].__enc__.should.be.true();
- resultJson[1].type.should.eql("undefined");
- });
- it('array of function', function() {
- var msg = { msg:[function(){}] };
- var result = util.encodeObject(msg);
- result.format.should.eql("array[1]");
- var resultJson = JSON.parse(result.msg);
- resultJson[0].__enc__.should.eql(true);
- resultJson[0].type.should.eql('function');
- });
- it('array of number', function() {
- var msg = { msg:[1,2,3] };
- var result = util.encodeObject(msg,{maxLength:2});
- result.format.should.eql("array[3]");
- var resultJson = JSON.parse(result.msg);
- resultJson.__enc__.should.eql(true);
- resultJson.data[0].should.eql(1);
- resultJson.data[1].should.eql(2);
- resultJson.data.length.should.eql(2);
- resultJson.length.should.eql(3);
- });
- it('array of special number', function() {
- var msg = { msg:[NaN,Infinity,-Infinity] };
- var result = util.encodeObject(msg);
- result.format.should.eql("array[3]");
- var resultJson = JSON.parse(result.msg);
- resultJson[0].__enc__.should.eql(true);
- resultJson[0].type.should.eql('number');
- resultJson[0].data.should.eql('NaN');
- resultJson[1].data.should.eql('Infinity');
- resultJson[2].data.should.eql('-Infinity');
- });
- it('constructor of Buffer in msg', function() {
- var msg = { msg:{buffer:Buffer.from([1,2,3,4])} };
- var result = util.encodeObject(msg,{maxLength:2});
- result.format.should.eql("Object");
- var resultJson = JSON.parse(result.msg);
- resultJson.buffer.__enc__.should.eql(true);
- resultJson.buffer.length.should.eql(4);
- resultJson.buffer.data[0].should.eql(1);
- resultJson.buffer.data[1].should.eql(2);
- });
- it('constructor of ServerResponse', function() {
- function ServerResponse(){};
- var msg = { msg: new ServerResponse() };
- var result = util.encodeObject(msg);
- result.format.should.eql("Object");
- var resultJson = JSON.parse(result.msg);
- resultJson.should.eql('[internal]');
- });
- it('constructor of Socket in msg', function() {
- function Socket(){};
- var msg = { msg: { socket: new Socket() } };
- var result = util.encodeObject(msg);
- result.format.should.eql("Object");
- var resultJson = JSON.parse(result.msg);
- resultJson.socket.should.eql('[internal]');
- });
- it('object which fails to serialise', function(done) {
- var msg = {
- msg: {
- obj:{
- cantserialise:{
- message:'this will not be displayed',
- toJSON: function(val) {
- throw 'this exception should have been caught';
- return 'should not display because we threw first';
- },
- },
- canserialise:{
- message:'this should be displayed',
- }
- },
- }
- };
- var result = util.encodeObject(msg);
- result.format.should.eql("error");
- var success = (result.msg.indexOf('cantserialise') > 0);
- success &= (result.msg.indexOf('this exception should have been caught') > 0);
- success &= (result.msg.indexOf('canserialise') > 0);
- success.should.eql(1);
- done();
- });
- it('object which fails to serialise - different error type', function(done) {
- var msg = {
- msg: {
- obj:{
- cantserialise:{
- message:'this will not be displayed',
- toJSON: function(val) {
- throw new Error('this exception should have been caught');
- return 'should not display because we threw first';
- },
- },
- canserialise:{
- message:'this should be displayed',
- }
- },
- }
- };
- var result = util.encodeObject(msg);
- result.format.should.eql("error");
- var success = (result.msg.indexOf('cantserialise') > 0);
- success &= (result.msg.indexOf('this exception should have been caught') > 0);
- success &= (result.msg.indexOf('canserialise') > 0);
- success.should.eql(1);
- done();
- });
- it('very large object which fails to serialise should be truncated', function(done) {
- var msg = {
- msg: {
- obj:{
- big:"",
- cantserialise:{
- message:'this will not be displayed',
- toJSON: function(val) {
- throw new Error('this exception should have been caught');
- return 'should not display because we threw first';
- },
- },
- canserialise:{
- message:'this should be displayed',
- }
- },
- }
- };
-
- for (var i = 0; i < 1000; i++) {
- msg.msg.obj.big += 'some more string ';
- }
-
- var result = util.encodeObject(msg);
- result.format.should.eql("error");
- var resultJson = JSON.parse(result.msg);
- var success = (resultJson.message.length <= 1000);
- success.should.eql(true);
- done();
- });
- it('test bad toString', function(done) {
- var msg = {
- msg: {
- mystrangeobj:"hello",
- },
- };
- msg.msg.toString = function(){
- throw new Error('Exception in toString - should have been caught');
- }
- msg.msg.constructor = { name: "strangeobj" };
-
- var result = util.encodeObject(msg);
- var success = (result.msg.indexOf('[Type not printable]') >= 0);
- success.should.eql(true);
- done();
- });
- it('test bad object constructor', function(done) {
- var msg = {
- msg: {
- mystrangeobj:"hello",
- constructor: {
- get name(){
- throw new Error('Exception in constructor name');
- }
- }
- },
- };
- var result = util.encodeObject(msg);
- done();
- });
-
- });
- });
-
-});
diff --git a/test/unit/_spec.js b/test/unit/_spec.js
deleted file mode 100644
index d099836f3..000000000
--- a/test/unit/_spec.js
+++ /dev/null
@@ -1,87 +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.
- **/
-
-/**
- * This test simply checks that for every .js file there exists
- * a *_spec.js file under ./test correspondingly.
- */
-
-/**
- * Currently we're only checking the core components under ./red
- * TODO: Increase the scope of this check
- */
-
-var fs = require("fs-extra");
-var should = require("should");
-var path = require('path');
-
-// Directories to check with .js files and _spec.js files respectively
-var rootdir = path.resolve(__dirname, "../..");
-var jsdir = path.resolve(__dirname, "../../packages/node_modules/");
-var testdir = path.resolve(__dirname);
-
-var walkDirectory = function(dir) {
- var p = fs.readdir(dir);
- var errors = [];
- return p.then(function(list) {
- var promises = [];
- list.forEach(function(file) {
- var filePath = path.join(dir,file);
-
- if (!/@node-red\/(editor-client|nodes)/.test(filePath) && !/node-red\/settings\.js/.test(filePath) && !/\/docs\//.test(filePath)) {
- promises.push(fs.stat(filePath).then(function(stat){
- if (stat.isDirectory()) {
- return walkDirectory(filePath).then(function(results) {
- if (results) {
- errors = errors.concat(results);
- }
- });
- } else if (/\.js$/.test(filePath)) {
- var testFile = filePath.replace(jsdir, testdir).replace(".js", "_spec.js");
- return fs.exists(testFile).then(function(exists) {
- if (!exists) {
- errors.push(testFile.substring(rootdir.length+1));
- } else {
- return fs.stat(testFile).then(function(stat) {
- if (stat.size === 0) {
- errors.push("[empty] "+testFile.substring(rootdir.length+1));
- }
- })
- }
- });
- }
- }));
- }
- });
- return Promise.all(promises).then(function() {
- return errors;
- })
- });
-}
-
-describe('_spec.js', function() {
- this.timeout(50000); // we might not finish within the Mocha default timeout limit, project will also grow
- it('is checking if all .js files have a corresponding _spec.js test file.', function(done) {
- walkDirectory(jsdir).then(function(errors) {
- if (errors.length > 0) {
- var error = new Error("Missing/empty _spec files:\n\t"+errors.join("\n\t"));
- done(error);
- } else {
- done();
- }
- });
- });
-});
diff --git a/test/unit/node-red/lib/red_spec.js b/test/unit/node-red/lib/red_spec.js
deleted file mode 100644
index 4cd430822..000000000
--- a/test/unit/node-red/lib/red_spec.js
+++ /dev/null
@@ -1,76 +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 fs = require("fs");
-var path = require("path");
-
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var api = NR_TEST_UTILS.require("@node-red/runtime/lib/api");
-
-var RED = NR_TEST_UTILS.require("node-red");
-
-var runtime = NR_TEST_UTILS.require("@node-red/runtime");
-var api = NR_TEST_UTILS.require("@node-red/runtime/lib/api");
-
-
-describe("red/red", function() {
-
- // describe("check build", function() {
- // beforeEach(function() {
- // sinon.stub(runtime,"init").callsFake(function() {});
- // sinon.stub(api,"init").callsFake(function() {});
- // // sinon.stub(RED,"version").callsFake(function() { return "version";});
- // });
- // afterEach(function() {
- // runtime.init.restore();
- // api.init.restore();
- // fs.statSync.restore();
- // // RED.version.restore();
- // });
- // it.skip('warns if build has not been run',function() {
- // sinon.stub(fs,"statSync").callsFake(function() { throw new Error();});
- //
- // /*jshint immed: false */
- // (function() {
- // RED.init({},{});
- // }).should.throw("Node-RED not built");
- // });
- // it('passed if build has been run',function() {
- // sinon.stub(fs,"statSync").callsFake(function() { });
- // RED.init({},{});
- // });
- // });
-
- describe("externals", function() {
- it('reports version', function() {
- /\d+\.\d+\.\d+(-git)?/.test(RED.version()).should.be.true();
- });
- it.skip('access server externals', function() {
- // TODO: unstubable accessors - need to make this testable
- // RED.app;
- // RED.httpAdmin;
- // RED.httpNode;
- // RED.server;
- });
- it.skip('only initialises api component if httpAdmin enabled');
- it.skip('stubs httpAdmin if httpAdmin disabled');
- it.skip('stubs httpNode if httpNode disabled');
- });
-
-});
diff --git a/test/unit/node-red/red_spec.js b/test/unit/node-red/red_spec.js
deleted file mode 100644
index ee46fc504..000000000
--- a/test/unit/node-red/red_spec.js
+++ /dev/null
@@ -1,21 +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 NR_TEST_UTILS = require("nr-test-utils");
-
-describe("node-red/red", function() {
- it.skip("NEEDS TESTS WRITING",function() {});
-});
From d63e5da60cb50e916fd79757d39d1132d71243ca Mon Sep 17 00:00:00 2001
From: "andrew.greene"
Date: Wed, 8 Dec 2021 18:08:01 -0700
Subject: [PATCH 38/48] Add input/output to comment node
---
.../@node-red/nodes/core/common/90-comment.html | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/packages/node_modules/@node-red/nodes/core/common/90-comment.html b/packages/node_modules/@node-red/nodes/core/common/90-comment.html
index cca7cd51d..579a92cc7 100644
--- a/packages/node_modules/@node-red/nodes/core/common/90-comment.html
+++ b/packages/node_modules/@node-red/nodes/core/common/90-comment.html
@@ -1,4 +1,4 @@
-
+