2 * Copyright 2014 IBM Corp.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 var should = require("should");
18 var sinon = require("sinon");
19 var path = require("path");
20 var when = require("when");
22 var RedNodes = require("../../../red/nodes");
23 var RedNode = require("../../../red/nodes/Node");
24 var typeRegistry = require("../../../red/nodes/registry");
25 var events = require("../../../red/events");
27 afterEach(function() {
31 describe('NodeRegistry', function() {
33 var resourcesDir = __dirname+ path.sep + "resources" + path.sep;
35 function stubSettings(s,available) {
36 s.available = function() {return available;}
37 s.set = function(s,v) { return when.resolve()},
38 s.get = function(s) { return null;}
41 var settings = stubSettings({},false);
42 var settingsWithStorage = stubSettings({},true);
44 it('automatically registers new nodes',function() {
45 var testNode = RedNodes.getNode('123');
47 var n = new RedNode({id:'123',type:'abc'});
49 var newNode = RedNodes.getNode('123');
51 should.strictEqual(n,newNode);
54 it('handles nodes that export a function', function(done) {
55 typeRegistry.init(settings);
56 typeRegistry.load(resourcesDir + "TestNode1",true).then(function() {
57 var list = typeRegistry.getNodeList();
58 list.should.be.an.Array.and.have.lengthOf(1);
59 list[0].should.have.property("id");
60 list[0].should.have.property("name","TestNode1.js");
61 list[0].should.have.property("types",["test-node-1"]);
62 list[0].should.have.property("enabled",true);
63 list[0].should.not.have.property("err");
65 var nodeConstructor = typeRegistry.get("test-node-1");
66 nodeConstructor.should.be.type("function");
69 }).catch(function(e) {
76 it('handles nodes that export a function returning a resolving promise', function(done) {
77 typeRegistry.init(settings);
78 typeRegistry.load(resourcesDir + "TestNode2",true).then(function() {
79 var list = typeRegistry.getNodeList();
80 list.should.be.an.Array.and.have.lengthOf(1);
81 list[0].should.have.property("id");
82 list[0].should.have.property("name","TestNode2.js");
83 list[0].should.have.property("types",["test-node-2"]);
84 list[0].should.have.property("enabled",true);
85 list[0].should.not.have.property("err");
86 var nodeConstructor = typeRegistry.get("test-node-2");
87 nodeConstructor.should.be.type("function");
90 }).catch(function(e) {
96 it('handles nodes that export a function returning a rejecting promise', function(done) {
97 typeRegistry.init(settings);
98 typeRegistry.load(resourcesDir + "TestNode3",true).then(function() {
99 var list = typeRegistry.getNodeList();
100 list.should.be.an.Array.and.have.lengthOf(1);
101 list[0].should.have.property("id");
102 list[0].should.have.property("name","TestNode3.js");
103 list[0].should.have.property("types",["test-node-3"]);
104 list[0].should.have.property("enabled",true);
105 list[0].should.have.property("err","fail");
107 var nodeConstructor = typeRegistry.get("test-node-3");
108 (nodeConstructor === null).should.be.true;
111 }).catch(function(e) {
117 it('handles files containing multiple nodes', function(done) {
118 typeRegistry.init(settings);
119 typeRegistry.load(resourcesDir + "MultipleNodes1",true).then(function() {
120 var list = typeRegistry.getNodeList();
121 list.should.be.an.Array.and.have.lengthOf(1);
122 list[0].should.have.property("id");
123 list[0].should.have.property("name","MultipleNodes1.js");
124 list[0].should.have.property("types",["test-node-multiple-1a","test-node-multiple-1b"]);
125 list[0].should.have.property("enabled",true);
126 list[0].should.not.have.property("err");
128 var nodeConstructor = typeRegistry.get("test-node-multiple-1a");
129 nodeConstructor.should.be.type("function");
131 nodeConstructor = typeRegistry.get("test-node-multiple-1b");
132 nodeConstructor.should.be.type("function");
135 }).catch(function(e) {
140 it('handles nested directories', function(done) {
141 typeRegistry.init(settings);
142 typeRegistry.load(resourcesDir + "NestedDirectoryNode",true).then(function() {
143 var list = typeRegistry.getNodeList();
144 list.should.be.an.Array.and.have.lengthOf(1);
145 list[0].should.have.property("id");
146 list[0].should.have.property("name","NestedNode.js");
147 list[0].should.have.property("types",["nested-node-1"]);
148 list[0].should.have.property("enabled",true);
149 list[0].should.not.have.property("err");
151 }).catch(function(e) {
156 it('emits type-registered and node-icon-dir events', function(done) {
157 var eventEmitSpy = sinon.spy(events,"emit");
158 typeRegistry.init(settings);
159 typeRegistry.load(resourcesDir + "NestedDirectoryNode",true).then(function() {
160 var list = typeRegistry.getNodeList();
161 list.should.be.an.Array.and.have.lengthOf(1);
162 list[0].should.have.property("name","NestedNode.js");
163 list[0].should.have.property("types",["nested-node-1"]);
164 list[0].should.have.property("enabled",true);
165 list[0].should.not.have.property("err");
167 eventEmitSpy.callCount.should.equal(2);
169 eventEmitSpy.firstCall.args[0].should.be.equal("node-icon-dir");
170 eventEmitSpy.firstCall.args[1].should.be.equal(
171 resourcesDir + "NestedDirectoryNode" + path.sep + "NestedNode" + path.sep + "icons");
173 eventEmitSpy.secondCall.args[0].should.be.equal("type-registered");
174 eventEmitSpy.secondCall.args[1].should.be.equal("nested-node-1");
177 }).catch(function(e) {
179 }).finally(function() {
180 eventEmitSpy.restore();
184 it('rejects a duplicate node type registration', function(done) {
186 typeRegistry.init(stubSettings({
187 nodesDir:[resourcesDir + "TestNode1",resourcesDir + "DuplicateTestNode"]
189 typeRegistry.load("wontexist",true).then(function() {
190 var list = typeRegistry.getNodeList();
192 list.should.be.an.Array.and.have.lengthOf(2);
193 list[0].should.have.property("id");
194 list[0].should.have.property("name","TestNode1.js");
195 list[0].should.have.property("types",["test-node-1"]);
196 list[0].should.have.property("enabled",true);
197 list[0].should.not.have.property("err");
199 list[1].should.have.property("id");
200 list[1].id.should.not.equal(list[0].id);
202 list[1].should.have.property("name","TestNode1.js");
203 list[1].should.have.property("types",["test-node-1"]);
204 list[1].should.have.property("enabled",true);
205 list[1].should.have.property("err");
206 /already registered/.test(list[1].err).should.be.true;
208 var nodeConstructor = typeRegistry.get("test-node-1");
209 // Verify the duplicate node hasn't replaced the original one
210 nodeConstructor.name.should.be.equal("TestNode");
213 }).catch(function(e) {
218 it('handles nodesDir as a string', function(done) {
220 typeRegistry.init(stubSettings({
221 nodesDir :resourcesDir + "TestNode1"
223 typeRegistry.load("wontexist",true).then(function(){
224 var list = typeRegistry.getNodeList();
225 list.should.be.an.Array.and.have.lengthOf(1);
226 list[0].should.have.property("types",["test-node-1"]);
228 }).catch(function(e) {
229 done("Loading of non-existing nodesDir should succeed");
234 it('handles invalid nodesDir',function(done) {
236 typeRegistry.init(stubSettings({
237 nodesDir : "wontexist"
239 typeRegistry.load("wontexist",true).then(function(){
240 var list = typeRegistry.getNodeList();
241 list.should.be.an.Array.and.be.empty;
243 }).catch(function(e) {
244 done("Loading of non-existing nodesDir should succeed");
248 it('returns nothing for an unregistered type config', function() {
249 typeRegistry.init(settings);
250 typeRegistry.load("wontexist",true).then(function(){
251 var config = typeRegistry.getNodeConfig("imaginary-shark");
252 (config === null).should.be.true;
253 }).catch(function(e) {
258 it('excludes node files listed in nodesExcludes',function(done) {
259 typeRegistry.init(stubSettings({
260 nodesExcludes: [ "TestNode1.js" ],
261 nodesDir:[resourcesDir + "TestNode1",resourcesDir + "TestNode2"]
263 typeRegistry.load("wontexist",true).then(function() {
264 var list = typeRegistry.getNodeList();
265 list.should.be.an.Array.and.have.lengthOf(1);
266 list[0].should.have.property("types",["test-node-2"]);
268 }).catch(function(e) {
273 it('returns the node configurations', function(done) {
274 typeRegistry.init(stubSettings({
275 nodesDir:[resourcesDir + "TestNode1",resourcesDir + "TestNode2"]
277 typeRegistry.load("wontexist",true).then(function() {
278 var list = typeRegistry.getNodeList();
280 var nodeConfigs = typeRegistry.getNodeConfigs();
282 // TODO: this is brittle...
283 nodeConfigs.should.equal("<script type=\"text/x-red\" data-template-name=\"test-node-1\"></script>\n<script type=\"text/x-red\" data-help-name=\"test-node-1\"></script>\n<script type=\"text/javascript\">RED.nodes.registerType('test-node-1',{});</script>\n<style></style>\n<p>this should be filtered out</p>\n<script type=\"text/x-red\" data-template-name=\"test-node-2\"></script>\n<script type=\"text/x-red\" data-help-name=\"test-node-2\"></script>\n<script type=\"text/javascript\">RED.nodes.registerType('test-node-2',{});</script>\n<style></style>\n");
285 var nodeId = list[0].id;
286 var nodeConfig = typeRegistry.getNodeConfig(nodeId);
287 nodeConfig.should.equal("<script type=\"text/x-red\" data-template-name=\"test-node-1\"></script>\n<script type=\"text/x-red\" data-help-name=\"test-node-1\"></script>\n<script type=\"text/javascript\">RED.nodes.registerType('test-node-1',{});</script>\n<style></style>\n<p>this should be filtered out</p>\n");
289 }).catch(function(e) {
294 it('stores the node list', function(done) {
296 nodesDir:[resourcesDir + "TestNode1",resourcesDir + "TestNode2",resourcesDir + "TestNode3"],
297 available: function() { return true; },
298 set: function(s,v) {return when.resolve();},
299 get: function(s) { return null;}
301 var settingsSave = sinon.spy(settings,"set");
302 typeRegistry.init(settings);
303 typeRegistry.load("wontexist",true).then(function() {
304 var list = typeRegistry.getNodeList();
305 list.should.be.Array.and.have.length(3);
307 settingsSave.callCount.should.equal(1);
308 settingsSave.firstCall.args[0].should.be.equal("nodes");
309 var savedList = settingsSave.firstCall.args[1];
311 savedList[list[0].id].name == list[0].name;
312 savedList[list[1].id].name == list[1].name;
313 savedList[list[2].id].name == list[2].name;
315 savedList[list[0].id].should.not.have.property("err");
316 savedList[list[1].id].should.not.have.property("err");
317 savedList[list[2].id].should.not.have.property("err");
320 }).catch(function(e) {
322 }).finally(function() {
323 settingsSave.restore();
328 it('allows nodes to be added by filename', function(done) {
330 available: function() { return true; },
331 set: function(s,v) {return when.resolve();},
332 get: function(s) { return null;}
334 typeRegistry.init(settings);
335 typeRegistry.load("wontexist",true).then(function(){
336 var list = typeRegistry.getNodeList();
337 list.should.be.an.Array.and.be.empty;
339 typeRegistry.addNode(resourcesDir + "TestNode1/TestNode1.js").then(function(node) {
340 list = typeRegistry.getNodeList();
341 list[0].should.have.property("id");
342 list[0].should.have.property("name","TestNode1.js");
343 list[0].should.have.property("types",["test-node-1"]);
344 list[0].should.have.property("enabled",true);
345 list[0].should.not.have.property("err");
347 node.should.be.an.Array.and.have.lengthOf(1);
348 node.should.eql(list);
351 }).catch(function(e) {
355 }).catch(function(e) {
360 it('fails to add non-existent filename', function(done) {
361 typeRegistry.init(settingsWithStorage);
362 typeRegistry.load("wontexist",true).then(function(){
363 var list = typeRegistry.getNodeList();
364 list.should.be.an.Array.and.be.empty;
365 typeRegistry.addNode(resourcesDir + "DoesNotExist/DoesNotExist.js").then(function(nodes) {
366 nodes.should.be.an.Array.and.have.lengthOf(1);
367 nodes[0].should.have.property("id");
368 nodes[0].should.have.property("types",[]);
369 nodes[0].should.have.property("err");
371 }).otherwise(function(e) {
375 }).catch(function(e) {
380 it('returns node info by type or id', function(done) {
381 typeRegistry.init(settings);
382 typeRegistry.load(resourcesDir + "TestNode1",true).then(function() {
383 var list = typeRegistry.getNodeList();
384 list.should.be.an.Array.and.have.lengthOf(1);
387 var type = list[0].types[0];
389 list[0].should.have.property("id");
390 list[0].should.have.property("name","TestNode1.js");
391 list[0].should.have.property("types",["test-node-1"]);
392 list[0].should.have.property("enabled",true);
393 list[0].should.not.have.property("err");
395 var info = typeRegistry.getNodeInfo(id);
396 list[0].should.eql(info);
398 var info2 = typeRegistry.getNodeInfo(type);
399 list[0].should.eql(info2);
402 }).catch(function(e) {
409 it('rejects adding duplicate nodes', function(done) {
410 typeRegistry.init(settingsWithStorage);
411 typeRegistry.load(resourcesDir + "TestNode1",true).then(function(){
412 var list = typeRegistry.getNodeList();
413 list.should.be.an.Array.and.have.lengthOf(1);
415 typeRegistry.addNode({file:resourcesDir + "TestNode1" + path.sep + "TestNode1.js"}).then(function(node) {
416 done(new Error("duplicate node loaded"));
417 }).otherwise(function(e) {
418 var list = typeRegistry.getNodeList();
419 list.should.be.an.Array.and.have.lengthOf(1);
423 }).catch(function(e) {
428 it('removes nodes from the registry', function(done) {
429 typeRegistry.init(settingsWithStorage);
430 typeRegistry.load(resourcesDir + "TestNode1",true).then(function() {
431 var list = typeRegistry.getNodeList();
432 list.should.be.an.Array.and.have.lengthOf(1);
433 list[0].should.have.property("id");
434 list[0].should.have.property("name","TestNode1.js");
435 list[0].should.have.property("types",["test-node-1"]);
436 list[0].should.have.property("enabled",true);
437 list[0].should.have.property("loaded",true);
439 typeRegistry.getNodeConfigs().length.should.be.greaterThan(0);
441 var info = typeRegistry.removeNode(list[0].id);
443 info.should.have.property("id",list[0].id);
444 info.should.have.property("enabled",false);
445 info.should.have.property("loaded",false);
447 typeRegistry.getNodeList().should.be.an.Array.and.be.empty;
448 typeRegistry.getNodeConfigs().length.should.equal(0);
450 var nodeConstructor = typeRegistry.get("test-node-1");
451 (typeof nodeConstructor).should.be.equal("undefined");
455 }).catch(function(e) {
460 it('rejects removing unknown nodes from the registry', function(done) {
461 typeRegistry.init(settings);
462 typeRegistry.load("wontexist",true).then(function() {
463 var list = typeRegistry.getNodeList();
464 list.should.be.an.Array.and.be.empty;
467 /*jshint immed: false */
469 typeRegistry.removeNode("1234");
473 }).catch(function(e) {
478 it('scans the node_modules path for node files', function(done) {
479 var fs = require("fs");
480 var path = require("path");
482 var eventEmitSpy = sinon.spy(events,"emit");
483 var pathJoin = (function() {
484 var _join = path.join;
485 return sinon.stub(path,"join",function() {
486 if (arguments.length == 3 && arguments[2] == "package.json") {
487 return _join(resourcesDir,"TestNodeModule" + path.sep + "node_modules" + path.sep,arguments[1],arguments[2]);
489 if (arguments.length == 2 && arguments[1] == "TestNodeModule") {
490 return _join(resourcesDir,"TestNodeModule" + path.sep + "node_modules" + path.sep,arguments[1]);
492 return _join.apply(this,arguments);
496 var readdirSync = (function() {
497 var originalReaddirSync = fs.readdirSync;
499 return sinon.stub(fs,"readdirSync",function(dir) {
501 if (callCount == 1) {
502 result = originalReaddirSync(resourcesDir + "TestNodeModule" + path.sep + "node_modules");
509 typeRegistry.init(settings);
510 typeRegistry.load("wontexist",false).then(function(){
511 var list = typeRegistry.getNodeList();
512 list.should.be.an.Array.and.have.lengthOf(2);
513 list[0].should.have.property("id");
514 list[0].should.have.property("name","TestNodeModule:TestNodeMod1");
515 list[0].should.have.property("types",["test-node-mod-1"]);
516 list[0].should.have.property("enabled",true);
517 list[0].should.not.have.property("err");
519 list[1].should.have.property("id");
520 list[1].should.have.property("name","TestNodeModule:TestNodeMod2");
521 list[1].should.have.property("types",["test-node-mod-2"]);
522 list[1].should.have.property("enabled",true);
523 list[1].should.have.property("err");
526 eventEmitSpy.callCount.should.equal(2);
528 eventEmitSpy.firstCall.args[0].should.be.equal("node-icon-dir");
529 eventEmitSpy.firstCall.args[1].should.be.equal(
530 resourcesDir + "TestNodeModule" + path.sep+ "node_modules" + path.sep + "TestNodeModule" + path.sep + "icons");
532 eventEmitSpy.secondCall.args[0].should.be.equal("type-registered");
533 eventEmitSpy.secondCall.args[1].should.be.equal("test-node-mod-1");
536 }).catch(function(e) {
538 }).finally(function() {
539 readdirSync.restore();
541 eventEmitSpy.restore();
545 it('allows nodes to be added by module name', function(done) {
546 var fs = require("fs");
547 var path = require("path");
549 var pathJoin = (function() {
550 var _join = path.join;
551 return sinon.stub(path,"join",function() {
552 if (arguments.length == 3 && arguments[2] == "package.json") {
553 return _join(resourcesDir,"TestNodeModule" + path.sep + "node_modules" + path.sep,arguments[1],arguments[2]);
555 if (arguments.length == 2 && arguments[1] == "TestNodeModule") {
556 return _join(resourcesDir,"TestNodeModule" + path.sep + "node_modules" + path.sep,arguments[1]);
558 return _join.apply(this,arguments);
562 var readdirSync = (function() {
563 var originalReaddirSync = fs.readdirSync;
565 return sinon.stub(fs,"readdirSync",function(dir) {
567 if (callCount == 1) {
568 result = originalReaddirSync(resourcesDir + "TestNodeModule" + path.sep + "node_modules");
574 typeRegistry.init(settingsWithStorage);
575 typeRegistry.load("wontexist",true).then(function(){
576 var list = typeRegistry.getNodeList();
577 list.should.be.an.Array.and.be.empty;
579 typeRegistry.addModule("TestNodeModule").then(function(node) {
580 list = typeRegistry.getNodeList();
581 list.should.be.an.Array.and.have.lengthOf(2);
582 list[0].should.have.property("id");
583 list[0].should.have.property("name","TestNodeModule:TestNodeMod1");
584 list[0].should.have.property("types",["test-node-mod-1"]);
585 list[0].should.have.property("enabled",true);
586 list[0].should.not.have.property("err");
588 list[1].should.have.property("id");
589 list[1].should.have.property("name","TestNodeModule:TestNodeMod2");
590 list[1].should.have.property("types",["test-node-mod-2"]);
591 list[1].should.have.property("enabled",true);
592 list[1].should.have.property("err");
594 node.should.eql(list);
597 }).catch(function(e) {
601 }).catch(function(e) {
603 }).finally(function() {
604 readdirSync.restore();
610 it('rejects adding duplicate node modules', function(done) {
611 var fs = require("fs");
612 var path = require("path");
614 var pathJoin = (function() {
615 var _join = path.join;
616 return sinon.stub(path,"join",function() {
617 if (arguments.length == 3 && arguments[2] == "package.json") {
618 return _join(resourcesDir,"TestNodeModule" + path.sep + "node_modules" + path.sep,arguments[1],arguments[2]);
620 if (arguments.length == 2 && arguments[1] == "TestNodeModule") {
621 return _join(resourcesDir,"TestNodeModule" + path.sep + "node_modules" + path.sep,arguments[1]);
623 return _join.apply(this,arguments);
627 var readdirSync = (function() {
628 var originalReaddirSync = fs.readdirSync;
630 return sinon.stub(fs,"readdirSync",function(dir) {
632 if (callCount == 1) {
633 result = originalReaddirSync(resourcesDir + "TestNodeModule" + path.sep + "node_modules");
640 typeRegistry.init(settingsWithStorage);
641 typeRegistry.load('wontexist',false).then(function(){
642 var list = typeRegistry.getNodeList();
643 list.should.be.an.Array.and.have.lengthOf(2);
644 typeRegistry.addModule("TestNodeModule").then(function(node) {
645 done(new Error("addModule resolved"));
646 }).otherwise(function(err) {
649 }).catch(function(e) {
651 }).finally(function() {
652 readdirSync.restore();
658 it('fails to add non-existent module name', function(done) {
659 typeRegistry.init(settingsWithStorage);
660 typeRegistry.load("wontexist",true).then(function(){
661 var list = typeRegistry.getNodeList();
662 list.should.be.an.Array.and.be.empty;
664 typeRegistry.addModule("DoesNotExistModule").then(function(node) {
665 done(new Error("ENOENT not thrown"));
666 }).otherwise(function(e) {
667 e.code.should.eql("MODULE_NOT_FOUND");
671 }).catch(function(e) {
676 it('removes nodes from the registry by module', function(done) {
677 var fs = require("fs");
678 var path = require("path");
680 var pathJoin = (function() {
681 var _join = path.join;
682 return sinon.stub(path,"join",function() {
683 if (arguments.length == 3 && arguments[2] == "package.json") {
684 return _join(resourcesDir,"TestNodeModule" + path.sep + "node_modules" + path.sep,arguments[1],arguments[2]);
686 if (arguments.length == 2 && arguments[1] == "TestNodeModule") {
687 return _join(resourcesDir,"TestNodeModule" + path.sep + "node_modules" + path.sep,arguments[1]);
689 return _join.apply(this,arguments);
693 var readdirSync = (function() {
694 var originalReaddirSync = fs.readdirSync;
696 return sinon.stub(fs,"readdirSync",function(dir) {
698 if (callCount == 1) {
699 result = originalReaddirSync(resourcesDir + "TestNodeModule" + path.sep + "node_modules");
706 typeRegistry.init(settingsWithStorage);
707 typeRegistry.load('wontexist',false).then(function(){
708 var list = typeRegistry.getNodeList();
709 list.should.be.an.Array.and.have.lengthOf(2);
710 var res = typeRegistry.removeModule("TestNodeModule");
712 res.should.be.an.Array.and.have.lengthOf(2);
713 res[0].should.have.a.property("id",list[0].id);
714 res[1].should.have.a.property("id",list[1].id);
716 list = typeRegistry.getNodeList();
717 list.should.be.an.Array.and.be.empty;
720 }).catch(function(e) {
722 }).finally(function() {
723 readdirSync.restore();
729 it('fails to remove non-existent module name', function(done) {
730 typeRegistry.init(settings);
731 typeRegistry.load("wontexist",true).then(function(){
732 var list = typeRegistry.getNodeList();
733 list.should.be.an.Array.and.be.empty;
735 /*jshint immed: false */
737 typeRegistry.removeModule("DoesNotExistModule");
742 }).catch(function(e) {
748 it('allows nodes to be enabled and disabled', function(done) {
749 typeRegistry.init(settingsWithStorage);
750 typeRegistry.load(resourcesDir+path.sep+"TestNode1",true).then(function() {
751 var list = typeRegistry.getNodeList();
752 list.should.be.an.Array.and.have.lengthOf(1);
753 list[0].should.have.property("id");
754 list[0].should.have.property("name","TestNode1.js");
755 list[0].should.have.property("enabled",true);
757 var nodeConfig = typeRegistry.getNodeConfigs();
758 nodeConfig.length.should.be.greaterThan(0);
760 var info = typeRegistry.disableNode(list[0].id);
761 info.should.have.property("id",list[0].id);
762 info.should.have.property("enabled",false);
764 var list2 = typeRegistry.getNodeList();
765 list2.should.be.an.Array.and.have.lengthOf(1);
766 list2[0].should.have.property("enabled",false);
768 typeRegistry.getNodeConfigs().length.should.equal(0);
770 var info2 = typeRegistry.enableNode(list[0].id);
771 info2.should.have.property("id",list[0].id);
772 info2.should.have.property("enabled",true);
774 var list3 = typeRegistry.getNodeList();
775 list3.should.be.an.Array.and.have.lengthOf(1);
776 list3[0].should.have.property("enabled",true);
778 var nodeConfig2 = typeRegistry.getNodeConfigs();
779 nodeConfig2.should.eql(nodeConfig);
782 }).catch(function(e) {
787 it('fails to enable/disable non-existent nodes', function(done) {
788 typeRegistry.init(settings);
789 typeRegistry.load("wontexist",true).then(function() {
790 var list = typeRegistry.getNodeList();
791 list.should.be.an.Array.and.be.empty;
793 /*jshint immed: false */
795 typeRegistry.disableNode("123");
798 /*jshint immed: false */
800 typeRegistry.enableNode("123");
804 }).catch(function(e) {