UNPKG

noflo

Version:

Flow-Based Programming environment for JavaScript

436 lines (423 loc) 15.9 kB
var Merge, Split, chai, component, loader, path, platform, port, root, shippingLanguage, urlPrefix, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; if (typeof process !== 'undefined' && process.execPath && process.execPath.match(/node|iojs/)) { if (!chai) { chai = require('chai'); } loader = require('../src/lib/nodejs/ComponentLoader.coffee'); component = require('../src/lib/Component.coffee'); port = require('../src/lib/Port.coffee'); platform = require('../src/lib/Platform.coffee'); path = require('path'); root = path.resolve(__dirname, '../'); shippingLanguage = 'coffeescript'; urlPrefix = './'; } else { loader = require('noflo/src/lib/ComponentLoader.js'); component = require('noflo/src/lib/Component.js'); platform = require('noflo/src/lib/Platform.js'); root = 'noflo'; shippingLanguage = 'javascript'; urlPrefix = '/'; } Split = (function(_super) { __extends(Split, _super); function Split() { this.inPorts = { "in": new noflo.Port }; this.outPorts = { out: new noflo.ArrayPort }; this.inPorts["in"].on('connect', (function(_this) { return function(data) { return _this.outPorts.out.connect(); }; })(this)); this.inPorts["in"].on('data', (function(_this) { return function(data) { return _this.outPorts.out.send(data); }; })(this)); this.inPorts["in"].on('disconnect', (function(_this) { return function() { return _this.outPorts.out.disconnect(); }; })(this)); } return Split; })(component.Component); Split.getComponent = function() { return new Split; }; Merge = function() { var inst; inst = new component.Component; inst.inPorts.add('in', function(event, payload, instance) { var method; method = event; if (event === 'data') { method = 'send'; } return instance.outPorts[method]('out', payload); }); inst.outPorts.add('out'); return inst; }; describe('ComponentLoader with no external packages installed', function() { var l; l = new loader.ComponentLoader(root); it('should initially know of no components', function() { return chai.expect(l.components).to.be["null"]; }); it('should not initially require revalidation', function() { return chai.expect(l.revalidate).to.be["false"]; }); it('should not initially be ready', function() { return chai.expect(l.ready).to.be["false"]; }); it('should not initially be processing', function() { return chai.expect(l.processing).to.be["false"]; }); it('should not have any packages in the checked list', function() { return chai.expect(l.checked).to.be.empty; }); describe('normalizing names', function() { it('should return simple module names as-is', function() { var normalized; normalized = l.getModulePrefix('foo'); return chai.expect(normalized).to.equal('foo'); }); it('should return empty for NoFlo core', function() { var normalized; normalized = l.getModulePrefix('noflo'); return chai.expect(normalized).to.equal(''); }); it('should strip noflo-', function() { var normalized; normalized = l.getModulePrefix('noflo-image'); return chai.expect(normalized).to.equal('image'); }); it('should strip NPM scopes', function() { var normalized; normalized = l.getModulePrefix('@noflo/foo'); return chai.expect(normalized).to.equal('foo'); }); return it('should strip NPM scopes and noflo-', function() { var normalized; normalized = l.getModulePrefix('@noflo/noflo-image'); return chai.expect(normalized).to.equal('image'); }); }); it('should be able to read a list of components', function(done) { var ready; this.timeout(60 * 1000); ready = false; l.once('ready', function() { ready = true; return chai.expect(l.ready).to.equal(true); }); l.listComponents(function(err, components) { if (err) { return done(err); } chai.expect(l.processing).to.equal(false); chai.expect(l.components).not.to.be.empty; chai.expect(components).to.equal(l.components); chai.expect(l.ready).to.equal(true); chai.expect(ready).to.equal(true); return done(); }); return chai.expect(l.processing).to.equal(true); }); describe('after listing components', function() { return it('should have the Graph component registered', function() { return chai.expect(l.components.Graph).not.to.be.empty; }); }); describe('loading the Graph component', function() { var instance; instance = null; it('should be able to load the component', function(done) { return l.load('Graph', function(err, inst) { if (err) { return done(err); } chai.expect(inst).to.be.an('object'); chai.expect(inst.componentName).to.equal('Graph'); instance = inst; return done(); }); }); it('should contain input ports', function() { chai.expect(instance.inPorts).to.be.an('object'); return chai.expect(instance.inPorts.graph).to.be.an('object'); }); it('should have "on" method on the input port', function() { return chai.expect(instance.inPorts.graph.on).to.be.a('function'); }); it('it should know that Graph is a subgraph', function() { return chai.expect(instance.isSubgraph()).to.equal(true); }); it('should know the description for the Graph', function() { return chai.expect(instance.description).to.be.a('string'); }); return it('should be able to provide an icon for the Graph', function() { chai.expect(instance.getIcon()).to.be.a('string'); return chai.expect(instance.getIcon()).to.equal('sitemap'); }); }); describe('loading the Graph component', function() { var instance; instance = null; it('should be able to load the component', function(done) { return l.load('Graph', function(err, graph) { if (err) { return done(err); } chai.expect(graph).to.be.an('object'); instance = graph; return done(); }); }); return it('should have a reference to the Component Loader\'s baseDir', function() { return chai.expect(instance.baseDir).to.equal(l.baseDir); }); }); describe('loading a component', function() { return it('should return an error on an invalid component type', function(done) { l.components['InvalidComponent'] = true; return l.load('InvalidComponent', function(err, c) { chai.expect(err).to.be.instanceOf(Error); chai.expect(err.message).to.equal('Invalid type boolean for component InvalidComponent.'); return done(); }); }); }); describe('register a component at runtime', function() { var instance; Split = (function(_super) { __extends(Split, _super); function Split() { this.inPorts = { "in": new port.Port }; this.outPorts = { out: new port.Port }; } return Split; })(component.Component); Split.getComponent = function() { return new Split; }; instance = null; l.libraryIcons.foo = 'star'; it('should be available in the components list', function() { l.registerComponent('foo', 'Split', Split); return chai.expect(l.components).to.contain.keys(['foo/Split', 'Graph']); }); it('should be able to load the component', function(done) { return l.load('foo/Split', function(err, split) { if (err) { return done(err); } chai.expect(split).to.be.an('object'); instance = split; return done(); }); }); it('should have the correct ports', function() { chai.expect(instance.inPorts).to.have.keys(['in']); return chai.expect(instance.outPorts).to.have.keys(['out']); }); it('should have inherited its icon from the library', function() { return chai.expect(instance.getIcon()).to.equal('star'); }); it('should emit an event on icon change', function(done) { instance.once('icon', function(newIcon) { chai.expect(newIcon).to.equal('smile'); return done(); }); return instance.setIcon('smile'); }); it('new instances should still contain the original icon', function(done) { return l.load('foo/Split', function(err, split) { if (err) { return done(err); } chai.expect(split).to.be.an('object'); chai.expect(split.getIcon()).to.equal('star'); return done(); }); }); it('after setting an icon for the Component class, new instances should have that', function(done) { Split.prototype.icon = 'trophy'; return l.load('foo/Split', function(err, split) { if (err) { return done(err); } chai.expect(split).to.be.an('object'); chai.expect(split.getIcon()).to.equal('trophy'); return done(); }); }); return it('should not affect the original instance', function() { return chai.expect(instance.getIcon()).to.equal('smile'); }); }); describe('reading sources', function() { it('should be able to provide source code for a component', function(done) { return l.getSource('Graph', function(err, component) { if (err) { return done(err); } chai.expect(component).to.be.an('object'); chai.expect(component.code).to.be.a('string'); chai.expect(component.code.indexOf('noflo.Component')).to.not.equal(-1); chai.expect(component.code.indexOf('exports.getComponent')).to.not.equal(-1); chai.expect(component.name).to.equal('Graph'); chai.expect(component.library).to.equal(''); chai.expect(component.language).to.equal(shippingLanguage); return done(); }); }); it('should return an error for missing components', function(done) { return l.getSource('foo/BarBaz', function(err, src) { chai.expect(err).to.be.an('error'); return done(); }); }); return it('should return an error for non-file components', function(done) { return l.getSource('foo/Split', function(err, src) { chai.expect(err).to.be.an('error'); return done(); }); }); }); return describe('writing sources', function() { describe('with working code', function() { var workingSource; workingSource = "var noflo = require('noflo');\n\nexports.getComponent = function() {\n var c = new noflo.Component();\n\n c.inPorts.add('in', function(packet, outPorts) {\n if (packet.event !== 'data') {\n return;\n }\n // Do something with the packet, then\n c.outPorts.out.send(packet.data);\n });\n\n c.outPorts.add('out');\n\n return c;\n};"; it('should be able to set the source', function(done) { this.timeout(10000); if (!platform.isBrowser()) { workingSource = workingSource.replace("'noflo'", "'../src/lib/NoFlo'"); } return l.setSource('foo', 'RepeatData', workingSource, 'js', function(err) { if (err) { return done(err); } return done(); }); }); return it('should be a loadable component', function(done) { return l.load('foo/RepeatData', function(err, inst) { if (err) { return done(err); } chai.expect(inst).to.be.an('object'); chai.expect(inst.inPorts).to.contain.keys(['in']); chai.expect(inst.outPorts).to.contain.keys(['out']); return done(); }); }); }); return describe('with non-working code', function() { var nonWorkingSource; nonWorkingSource = "var noflo = require('noflo');\nvar notFound = require('./this_file_does_not_exist.js');\n\nexports.getComponent = function() {\n var c = new noflo.Component();\n\n c.inPorts.add('in', function(packet, outPorts) {\n if (packet.event !== 'data') {\n return;\n }\n // Do something with the packet, then\n c.outPorts.out.send(packet.data);\n });\n\n c.outPorts.add('out');\n\n return c;\n};"; it('should be able to set the source', function(done) { if (!platform.isBrowser()) { nonWorkingSource = nonWorkingSource.replace("'noflo'", "'../src/lib/NoFlo'"); } return l.setSource('foo', 'NotWorking', nonWorkingSource, 'js', function(err) { chai.expect(err).to.be.an('error'); return done(); }); }); return it('should not be a loadable component', function(done) { return l.load('foo/NotWorking', function(err, inst) { chai.expect(err).to.be.an('error'); chai.expect(inst).to.be.an('undefined'); return done(); }); }); }); }); }); describe('ComponentLoader with a fixture project', function() { var l; l = null; before(function() { if (platform.isBrowser()) { return this.skip(); } }); it('should be possible to instantiate', function() { return l = new loader.ComponentLoader(path.resolve(__dirname, 'fixtures/componentloader')); }); it('should initially know of no components', function() { return chai.expect(l.components).to.be.a('null'); }); it('should not initially be ready', function() { return chai.expect(l.ready).to.be["false"]; }); it('should be able to read a list of components', function(done) { var ready; ready = false; l.once('ready', function() { chai.expect(l.ready).to.equal(true); return ready = l.ready; }); l.listComponents(function(err, components) { if (err) { return done(err); } chai.expect(l.processing).to.equal(false); chai.expect(l.components).not.to.be.empty; chai.expect(components).to.equal(l.components); chai.expect(l.ready).to.equal(true); chai.expect(ready).to.equal(true); return done(); }); return chai.expect(l.processing).to.equal(true); }); it('should be able to load a local component', function(done) { return l.load('componentloader/Output', function(err, instance) { chai.expect(err).to.be.a('null'); chai.expect(instance.description).to.equal('Output stuff'); chai.expect(instance.icon).to.equal('cloud'); return done(); }); }); it('should be able to load a component from a dependency', function(done) { return l.load('example/Forward', function(err, instance) { chai.expect(err).to.be.a('null'); chai.expect(instance.description).to.equal('Forward stuff'); chai.expect(instance.icon).to.equal('car'); return done(); }); }); it('should be able to load a dynamically registered component from a dependency', function(done) { return l.load('example/Hello', function(err, instance) { chai.expect(err).to.be.a('null'); chai.expect(instance.description).to.equal('Hello stuff'); chai.expect(instance.icon).to.equal('bicycle'); return done(); }); }); it('should be able to load core Graph component', function(done) { return l.load('Graph', function(err, instance) { chai.expect(err).to.be.a('null'); chai.expect(instance.icon).to.equal('sitemap'); return done(); }); }); return it('should fail loading a missing component', function(done) { return l.load('componentloader/Missing', function(err, instance) { chai.expect(err).to.be.an('error'); return done(); }); }); });