UNPKG

noflo

Version:

Flow-Based Programming environment for JavaScript

616 lines (610 loc) 19.9 kB
var chai, graph, noflo, path, root, subgraph, 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'); } subgraph = require('../src/components/Graph.coffee'); graph = require('../src/lib/Graph.coffee'); noflo = require('../src/lib/NoFlo.coffee'); path = require('path'); root = path.resolve(__dirname, '../'); urlPrefix = './'; } else { subgraph = require('noflo/src/components/Graph.js'); graph = require('noflo/src/lib/Graph.js'); noflo = require('noflo/src/lib/NoFlo.js'); root = 'noflo'; urlPrefix = '/'; } describe('Graph component', function() { var Split, SubgraphMerge, c, g; c = null; g = null; beforeEach(function() { c = subgraph.getComponent(); g = noflo.internalSocket.createSocket(); return c.inPorts.graph.attach(g); }); 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; })(noflo.Component); Split.getComponent = function() { return new Split; }; SubgraphMerge = function() { var inst; inst = new noflo.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('initially', function() { it('should be ready', function() { return chai.expect(c.ready).to.be["true"]; }); it('should not contain a network', function() { return chai.expect(c.network).to.be["null"]; }); it('should not have a baseDir', function() { return chai.expect(c.baseDir).to.be["null"]; }); return it('should only have the graph inport', function() { chai.expect(c.inPorts.ports).to.have.keys(['graph']); return chai.expect(c.outPorts.ports).to.be.empty; }); }); describe('with JSON graph definition', function() { it('should emit a ready event after network has been loaded', function(done) { this.timeout(6000); c.baseDir = root; c.once('ready', function() { chai.expect(c.network).not.to.be["null"]; chai.expect(c.ready).to.be["true"]; return done(); }); c.once('network', function(network) { network.loader.components.Split = Split; network.loader.registerComponent('', 'Merge', SubgraphMerge); chai.expect(c.ready).to.be["false"]; chai.expect(c.network).not.to.be["null"]; return c.start(); }); return g.send({ processes: { Split: { component: 'Split' }, Merge: { component: 'Merge' } } }); }); it('should expose available ports', function(done) { this.timeout(6000); c.baseDir = root; c.once('ready', function() { chai.expect(c.inPorts.ports).to.have.keys(['graph']); chai.expect(c.outPorts.ports).to.be.empty; return done(); }); c.once('network', function() { chai.expect(c.ready).to.be["false"]; chai.expect(c.network).not.to.be["null"]; c.network.loader.components.Split = Split; c.network.loader.components.Merge = SubgraphMerge; return c.start(); }); return g.send({ processes: { Split: { component: 'Split' }, Merge: { component: 'Merge' } }, connections: [ { src: { process: 'Merge', port: 'out' }, tgt: { process: 'Split', port: 'in' } } ] }); }); it('should update description from the graph', function(done) { c.baseDir = root; this.timeout(6000); c.once('ready', function() { chai.expect(c.network).not.to.be["null"]; chai.expect(c.ready).to.be["true"]; chai.expect(c.description).to.equal('Hello, World!'); return done(); }); c.once('network', function(network) { network.loader.components.Split = Split; chai.expect(c.ready).to.be["false"]; chai.expect(c.network).not.to.be["null"]; chai.expect(c.description).to.equal('Hello, World!'); return c.start(); }); return g.send({ properties: { description: 'Hello, World!' }, processes: { Split: { component: 'Split' } } }); }); it('should expose only exported ports when they exist', function(done) { c.baseDir = root; this.timeout(6000); c.once('ready', function() { chai.expect(c.inPorts.ports).to.have.keys(['graph']); chai.expect(c.outPorts.ports).to.have.keys(['out']); return done(); }); c.once('network', function() { chai.expect(c.ready).to.be["false"]; chai.expect(c.network).not.to.be["null"]; c.network.loader.components.Split = Split; c.network.loader.components.Merge = SubgraphMerge; return c.start(); }); return g.send({ exports: [ { "public": 'out', "private": 'split.out' } ], processes: { Split: { component: 'Split' }, Merge: { component: 'Merge' } }, connections: [ { src: { process: 'Merge', port: 'out' }, tgt: { process: 'Split', port: 'in' } } ] }); }); return it('should be able to run the graph', function(done) { c.baseDir = root; this.timeout(6000); c.once('ready', function() { var ins, out; ins = noflo.internalSocket.createSocket(); out = noflo.internalSocket.createSocket(); c.inPorts['in'].attach(ins); c.outPorts['out'].attach(out); out.on('data', function(data) { chai.expect(data).to.equal('Foo'); return done(); }); return ins.send('Foo'); }); c.once('network', function() { chai.expect(c.ready).to.be["false"]; chai.expect(c.network).not.to.be["null"]; c.network.loader.components.Split = Split; c.network.loader.components.Merge = SubgraphMerge; return c.start(); }); return g.send({ exports: [ { "public": 'in', "private": 'merge.in' }, { "public": 'out', "private": 'split.out' } ], processes: { Split: { component: 'Split' }, Merge: { component: 'Merge' } }, connections: [ { src: { process: 'Merge', port: 'out' }, tgt: { process: 'Split', port: 'in' } } ] }); }); }); describe('with a Graph instance', function() { var gr; gr = new graph.Graph('Hello, world'); gr.baseDir = root; gr.addNode('Split', 'Split'); gr.addNode('Merge', 'Merge'); gr.addEdge('Merge', 'out', 'Split', 'in'); gr.addInport('in', 'Merge', 'in'); gr.addOutport('out', 'Split', 'out'); it('should emit a ready event after network has been loaded', function(done) { this.timeout(6000); c.once('ready', function() { chai.expect(c.network).not.to.be["null"]; chai.expect(c.ready).to.be["true"]; return done(); }); c.once('network', function() { chai.expect(c.ready).to.be["false"]; chai.expect(c.network).not.to.be["null"]; c.network.loader.components.Split = Split; c.network.loader.components.Merge = SubgraphMerge; return c.start(); }); g.send(gr); return chai.expect(c.ready).to.be["false"]; }); it('should expose available ports', function(done) { c.baseDir = root; this.timeout(6000); c.once('ready', function() { chai.expect(c.inPorts.ports).to.have.keys(['graph', 'in']); chai.expect(c.outPorts.ports).to.have.keys(['out']); return done(); }); c.once('network', function() { chai.expect(c.ready).to.be["false"]; chai.expect(c.network).not.to.be["null"]; c.network.loader.components.Split = Split; c.network.loader.components.Merge = SubgraphMerge; return c.start(); }); return g.send(gr); }); return it('should be able to run the graph', function(done) { c.baseDir = root; this.timeout(6000); c.once('ready', function() { var ins, out; ins = noflo.internalSocket.createSocket(); out = noflo.internalSocket.createSocket(); c.inPorts['in'].attach(ins); c.outPorts['out'].attach(out); out.on('data', function(data) { chai.expect(data).to.equal('Foo'); return done(); }); return ins.send('Foo'); }); c.once('network', function() { chai.expect(c.ready).to.be["false"]; chai.expect(c.network).not.to.be["null"]; c.network.loader.components.Split = Split; c.network.loader.components.Merge = SubgraphMerge; return c.start(); }); return g.send(gr); }); }); describe('with a FBP file with INPORTs and OUTPORTs', function() { var file; file = "" + urlPrefix + "spec/fixtures/subgraph.fbp"; it('should emit a ready event after network has been loaded', function(done) { this.timeout(6000); c.once('ready', function() { chai.expect(c.network).not.to.be["null"]; chai.expect(c.ready).to.be["true"]; return done(); }); c.once('network', function() { chai.expect(c.ready).to.be["false"]; chai.expect(c.network).not.to.be["null"]; c.network.loader.components.Split = Split; c.network.loader.components.Merge = SubgraphMerge; return c.start(); }); g.send(file); return chai.expect(c.ready).to.be["false"]; }); it('should expose available ports', function(done) { c.baseDir = root; this.timeout(6000); c.once('ready', function() { chai.expect(c.inPorts.ports).to.have.keys(['graph', 'in']); chai.expect(c.outPorts.ports).to.have.keys(['out']); return done(); }); c.once('network', function() { chai.expect(c.ready).to.be["false"]; chai.expect(c.network).not.to.be["null"]; c.network.loader.components.Split = Split; c.network.loader.components.Merge = SubgraphMerge; return c.start(); }); return g.send(file); }); return it('should be able to run the graph', function(done) { c.baseDir = root; this.timeout(6000); c.once('ready', function() { var ins, out; ins = noflo.internalSocket.createSocket(); out = noflo.internalSocket.createSocket(); c.inPorts['in'].attach(ins); c.outPorts['out'].attach(out); out.on('connect', function() { return ins.send('Foo'); }); out.on('data', function(data) { chai.expect(data).to.equal('Foo'); return ins.disconnect(); }); out.on('disconnect', function() { return done(); }); return ins.connect(); }); c.once('network', function() { chai.expect(c.ready).to.be["false"]; chai.expect(c.network).not.to.be["null"]; c.network.loader.components.Split = Split; c.network.loader.components.Merge = SubgraphMerge; return c.start(); }); return g.send(file); }); }); describe('with a FBP file with legacy EXPORTS', function() { var file; file = "" + urlPrefix + "spec/fixtures/subgraph_legacy.fbp"; it('should emit a ready event after network has been loaded', function(done) { this.timeout(6000); c.once('ready', function() { chai.expect(c.network).not.to.be["null"]; chai.expect(c.ready).to.be["true"]; return done(); }); c.once('network', function() { chai.expect(c.ready).to.be["false"]; chai.expect(c.network).not.to.be["null"]; c.network.loader.components.Split = Split; c.network.loader.components.Merge = SubgraphMerge; return c.start(); }); g.send(file); return chai.expect(c.ready).to.be["false"]; }); it('should expose available ports', function(done) { c.baseDir = root; this.timeout(6000); c.once('ready', function() { chai.expect(c.inPorts.ports).to.have.keys(['graph', 'in']); chai.expect(c.outPorts.ports).to.have.keys(['out']); return done(); }); c.once('network', function() { chai.expect(c.ready).to.be["false"]; chai.expect(c.network).not.to.be["null"]; c.network.loader.components.Split = Split; c.network.loader.components.Merge = SubgraphMerge; return c.start(); }); return g.send(file); }); it('should have disambiguated the exported ports', function(done) { c.baseDir = root; this.timeout(6000); c.once('ready', function() { chai.expect(c.network.graph.exports).to.be.empty; chai.expect(c.network.graph.inports).to.be.not.empty; chai.expect(c.network.graph.inports["in"]).to.be.an('object'); chai.expect(c.network.graph.outports).to.be.not.empty; chai.expect(c.network.graph.outports.out).to.be.an('object'); return done(); }); c.once('network', function() { c.network.loader.components.Split = Split; return c.network.loader.components.Merge = SubgraphMerge; }); return g.send(file); }); return it('should be able to run the graph', function(done) { c.baseDir = root; this.timeout(6000); c.once('ready', function() { var ins, out; ins = noflo.internalSocket.createSocket(); out = noflo.internalSocket.createSocket(); c.inPorts['in'].attach(ins); c.outPorts['out'].attach(out); out.on('connect', function() { return ins.send('Foo'); }); out.on('data', function(data) { chai.expect(data).to.equal('Foo'); return ins.disconnect(); }); out.on('disconnect', function() { return done(); }); return ins.connect(); }); c.once('network', function() { chai.expect(c.ready).to.be["false"]; chai.expect(c.network).not.to.be["null"]; c.network.loader.components.Split = Split; c.network.loader.components.Merge = SubgraphMerge; return c.start(); }); return g.send(file); }); }); return describe('when a subgraph is used as a component', function() { var createSplit, grDefaults, grInitials; createSplit = function() { c = new noflo.Component; c.inPorts.add('in', { required: true, datatype: 'string', "default": 'default-value' }, (function(_this) { return function(e, data) { switch (e) { case 'connect': return c.outPorts.out.connect(); case 'data': return c.outPorts.out.send(data); case 'disconnect': return c.outPorts.out.disconnect(); } }; })(this)); c.outPorts.add('out'); return c; }; grDefaults = new noflo.Graph('Child Graph Using Defaults'); grDefaults.addNode('SplitIn', 'Split'); grDefaults.addNode('SplitOut', 'Split'); grDefaults.addInport('in', 'SplitIn', 'in'); grDefaults.addOutport('out', 'SplitOut', 'out'); grDefaults.addEdge('SplitIn', 'out', 'SplitOut', 'in'); grInitials = new noflo.Graph('Child Graph Using Initials'); grInitials.addNode('SplitIn', 'Split'); grInitials.addNode('SplitOut', 'Split'); grInitials.addInport('in', 'SplitIn', 'in'); grInitials.addOutport('out', 'SplitOut', 'out'); grInitials.addInitial('initial-value', 'SplitIn', 'in'); grInitials.addEdge('SplitIn', 'out', 'SplitOut', 'in'); it('should send defaults', function(done) { var cl; this.timeout(6000); cl = new noflo.ComponentLoader(root); return cl.listComponents(function(err, components) { if (err) { return done(err); } cl.components.Split = createSplit; cl.components.Defaults = grDefaults; cl.components.Initials = grInitials; return cl.load('Defaults', function(err, inst) { var o; o = noflo.internalSocket.createSocket(); inst.outPorts.out.attach(o); o.once('data', function(data) { chai.expect(data).to.equal('default-value'); return done(); }); return inst.start(); }); }); }); it('should send initials', function(done) { var cl; this.timeout(6000); cl = new noflo.ComponentLoader(root); return cl.listComponents(function(err, components) { if (err) { return done(err); } cl.components.Split = createSplit; cl.components.Defaults = grDefaults; cl.components.Initials = grInitials; return cl.load('Initials', function(err, inst) { var o; o = noflo.internalSocket.createSocket(); inst.outPorts.out.attach(o); o.once('data', function(data) { chai.expect(data).to.equal('initial-value'); return done(); }); return inst.start(); }); }); }); return it('should not send defaults when an inport is attached externally', function(done) { var cl; this.timeout(6000); cl = new noflo.ComponentLoader(root); return cl.listComponents(function(err, components) { if (err) { return done(err); } cl.components.Split = createSplit; cl.components.Defaults = grDefaults; cl.components.Initials = grInitials; return cl.load('Defaults', function(err, inst) { var i, o; i = noflo.internalSocket.createSocket(); o = noflo.internalSocket.createSocket(); inst.inPorts["in"].attach(i); inst.outPorts.out.attach(o); o.once('data', function(data) { chai.expect(data).to.equal('Foo'); return done(); }); inst.start(); return i.send('Foo'); }); }); }); }); });