UNPKG

noflo

Version:

Flow-Based Programming environment for JavaScript

553 lines (545 loc) 16.2 kB
var chai, noflo, path, processAsync, processMerge, processMergeA, root, urlPrefix, wirePatternAsync, wirePatternMerge; if (typeof process !== 'undefined' && process.execPath && process.execPath.match(/node|iojs/)) { if (!chai) { chai = require('chai'); } noflo = require('../src/lib/NoFlo.coffee'); path = require('path'); root = path.resolve(__dirname, '../'); urlPrefix = './'; } else { noflo = require('noflo'); root = 'noflo'; urlPrefix = '/'; } wirePatternAsync = function() { var c; c = new noflo.Component; c.inPorts.add('in', { datatype: 'string' }); c.outPorts.add('out', { datatype: 'string' }); return noflo.helpers.WirePattern(c, { "in": 'in', out: 'out', async: true, forwardGroups: true }, function(data, groups, out, callback) { return setTimeout(function() { out.send(data + c.nodeId); return callback(); }, 1); }); }; wirePatternMerge = function() { var c; c = new noflo.Component; c.inPorts.add('in1', { datatype: 'string' }); c.inPorts.add('in2', { datatype: 'string' }); c.outPorts.add('out', { datatype: 'string' }); return noflo.helpers.WirePattern(c, { "in": ['in1', 'in2'], out: 'out', async: true, forwardGroups: true }, function(data, groups, out, callback) { out.send("1" + data['in1'] + c.nodeId + "2" + data['in2'] + c.nodeId); return callback(); }); }; processAsync = function() { var c; c = new noflo.Component; c.inPorts.add('in', { datatype: 'string' }); c.outPorts.add('out', { datatype: 'string' }); return c.process(function(input, output) { var data; data = input.getData('in'); return setTimeout(function() { return output.sendDone(data + c.nodeId); }, 1); }); }; processMerge = function() { var c; c = new noflo.Component; c.inPorts.add('in1', { datatype: 'string' }); c.inPorts.add('in2', { datatype: 'string' }); c.outPorts.add('out', { datatype: 'string' }); c.forwardBrackets = { 'in1': ['out'] }; return c.process(function(input, output) { var first, second; if (!input.has('in1', 'in2', function(ip) { return ip.type === 'data'; })) { return; } first = input.getData('in1'); second = input.getData('in2'); return output.sendDone({ out: "1" + first + ":2" + second + ":" + c.nodeId }); }); }; processMergeA = function() { var c; c = new noflo.Component; c.inPorts.add('in1', { datatype: 'string' }); c.inPorts.add('in2', { datatype: 'string', addressable: true }); c.outPorts.add('out', { datatype: 'string' }); c.forwardBrackets = { 'in1': ['out'] }; return c.process(function(input, output) { var first, second0, second1; if (!input.hasData('in1', ['in2', 0], ['in2', 1])) { return; } first = input.getData('in1'); second0 = input.getData(['in2', 0]); second1 = input.getData(['in2', 1]); return output.sendDone({ out: "1" + first + ":2" + second0 + ":2" + second1 + ":" + c.nodeId }); }); }; describe('Scope isolation', function() { var loader; loader = null; before(function(done) { loader = new noflo.ComponentLoader(root); return loader.listComponents(function(err) { if (err) { return done(err); } loader.registerComponent('wirepattern', 'Async', wirePatternAsync); loader.registerComponent('wirepattern', 'Merge', wirePatternMerge); loader.registerComponent('process', 'Async', processAsync); loader.registerComponent('process', 'Merge', processMerge); loader.registerComponent('process', 'MergeA', processMergeA); return done(); }); }); describe('with WirePattern sending to Process API', function() { var c, ins, out; c = null; ins = null; out = null; before(function(done) { var fbpData; fbpData = "INPORT=Wp.IN:IN OUTPORT=Pc.OUT:OUT Wp(wirepattern/Async) OUT -> IN Pc(process/Async)"; return noflo.graph.loadFBP(fbpData, function(err, g) { if (err) { return done(err); } loader.registerComponent('scope', 'Connected', g); return loader.load('scope/Connected', function(err, instance) { if (err) { return done(err); } c = instance; ins = noflo.internalSocket.createSocket(); c.inPorts["in"].attach(ins); return done(); }); }); }); beforeEach(function() { out = noflo.internalSocket.createSocket(); return c.outPorts.out.attach(out); }); afterEach(function() { c.outPorts.out.detach(out); return out = null; }); it('should forward old-style groups as expected', function(done) { var expected, received; expected = ['CONN', '< 1', '< a', 'DATA bazWpPc', '>', '>', 'DISC']; received = []; out.on('connect', function() { return received.push('CONN'); }); out.on('begingroup', function(group) { return received.push("< " + group); }); out.on('data', function(data) { return received.push("DATA " + data); }); out.on('endgroup', function() { return received.push('>'); }); out.on('disconnect', function() { received.push('DISC'); chai.expect(received).to.eql(expected); return done(); }); ins.connect(); ins.beginGroup(1); ins.beginGroup('a'); ins.send('baz'); ins.endGroup(); ins.endGroup(); return ins.disconnect(); }); it('should forward new-style brackets as expected', function(done) { var brackets, expected, received; expected = ['< 1', '< a', 'DATA fooWpPc', '>', '>']; received = []; brackets = []; out.on('ip', function(ip) { switch (ip.type) { case 'openBracket': received.push("< " + ip.data); return brackets.push(ip.data); case 'data': return received.push("DATA " + ip.data); case 'closeBracket': received.push('>'); brackets.pop(); if (brackets.length) { return; } chai.expect(received).to.eql(expected); return done(); } }); ins.post(new noflo.IP('openBracket', 1)); ins.post(new noflo.IP('openBracket', 'a')); ins.post(new noflo.IP('data', 'foo')); ins.post(new noflo.IP('closeBracket', 'a')); return ins.post(new noflo.IP('closeBracket', 1)); }); return it('should forward scopes as expected', function(done) { var brackets, expected, received; expected = ['x < 1', 'x < a', 'x DATA barWpPc', 'x >', 'x >']; received = []; brackets = []; out.on('ip', function(ip) { switch (ip.type) { case 'openBracket': received.push(ip.scope + " < " + ip.data); return brackets.push(ip.data); case 'data': return received.push(ip.scope + " DATA " + ip.data); case 'closeBracket': received.push(ip.scope + " >"); brackets.pop(); if (brackets.length) { return; } chai.expect(received).to.eql(expected); return done(); } }); ins.post(new noflo.IP('openBracket', 1, { scope: 'x' })); ins.post(new noflo.IP('openBracket', 'a', { scope: 'x' })); ins.post(new noflo.IP('data', 'bar', { scope: 'x' })); ins.post(new noflo.IP('closeBracket', 'a', { scope: 'x' })); return ins.post(new noflo.IP('closeBracket', 1, { scope: 'x' })); }); }); describe('pure Process API merging two inputs', function() { var c, in1, in2, out; c = null; in1 = null; in2 = null; out = null; before(function(done) { var fbpData; fbpData = "INPORT=Pc1.IN:IN1 INPORT=Pc2.IN:IN2 OUTPORT=PcMerge.OUT:OUT Pc1(process/Async) OUT -> IN1 PcMerge(process/Merge) Pc2(process/Async) OUT -> IN2 PcMerge(process/Merge)"; return noflo.graph.loadFBP(fbpData, function(err, g) { if (err) { return done(err); } loader.registerComponent('scope', 'Merge', g); return loader.load('scope/Merge', function(err, instance) { if (err) { return done(err); } c = instance; in1 = noflo.internalSocket.createSocket(); c.inPorts.in1.attach(in1); in2 = noflo.internalSocket.createSocket(); c.inPorts.in2.attach(in2); return done(); }); }); }); beforeEach(function() { out = noflo.internalSocket.createSocket(); return c.outPorts.out.attach(out); }); afterEach(function() { c.outPorts.out.detach(out); return out = null; }); it('should forward new-style brackets as expected', function(done) { var expected, received; expected = ['CONN', '< 1', '< a', 'DATA 1bazPc1:2fooPc2:PcMerge', '>', '>', 'DISC']; received = []; out.on('connect', function() { return received.push('CONN'); }); out.on('begingroup', function(group) { return received.push("< " + group); }); out.on('data', function(data) { return received.push("DATA " + data); }); out.on('endgroup', function() { return received.push('>'); }); out.on('disconnect', function() { received.push('DISC'); chai.expect(received).to.eql(expected); return done(); }); in2.connect(); in2.send('foo'); in2.disconnect(); in1.connect(); in1.beginGroup(1); in1.beginGroup('a'); in1.send('baz'); in1.endGroup(); in1.endGroup(); return in1.disconnect(); }); it('should forward new-style brackets as expected regardless of sending order', function(done) { var expected, received; expected = ['CONN', '< 1', '< a', 'DATA 1bazPc1:2fooPc2:PcMerge', '>', '>', 'DISC']; received = []; out.on('connect', function() { return received.push('CONN'); }); out.on('begingroup', function(group) { return received.push("< " + group); }); out.on('data', function(data) { return received.push("DATA " + data); }); out.on('endgroup', function() { return received.push('>'); }); out.on('disconnect', function() { received.push('DISC'); chai.expect(received).to.eql(expected); return done(); }); in1.connect(); in1.beginGroup(1); in1.beginGroup('a'); in1.send('baz'); in1.endGroup(); in1.endGroup(); in1.disconnect(); in2.connect(); in2.send('foo'); return in2.disconnect(); }); return it('should forward scopes as expected', function(done) { var brackets, expected, received; expected = ['x < 1', 'x DATA 1onePc1:2twoPc2:PcMerge', 'x >']; received = []; brackets = []; out.on('ip', function(ip) { switch (ip.type) { case 'openBracket': received.push(ip.scope + " < " + ip.data); return brackets.push(ip.data); case 'data': return received.push(ip.scope + " DATA " + ip.data); case 'closeBracket': received.push(ip.scope + " >"); brackets.pop(); if (brackets.length) { return; } chai.expect(received).to.eql(expected); return done(); } }); in2.post(new noflo.IP('data', 'two', { scope: 'x' })); in1.post(new noflo.IP('openBracket', 1, { scope: 'x' })); in1.post(new noflo.IP('data', 'one', { scope: 'x' })); return in1.post(new noflo.IP('closeBracket', 1, { scope: 'x' })); }); }); describe('Process API with IIPs and scopes', function() { var c, in1, in2, out; c = null; in1 = null; in2 = null; out = null; before(function(done) { var fbpData; fbpData = "INPORT=Pc1.IN:IN1 OUTPORT=PcMerge.OUT:OUT Pc1(process/Async) -> IN1 PcMerge(process/Merge) 'twoIIP' -> IN2 PcMerge(process/Merge)"; return noflo.graph.loadFBP(fbpData, function(err, g) { if (err) { return done(err); } loader.registerComponent('scope', 'MergeIIP', g); return loader.load('scope/MergeIIP', function(err, instance) { if (err) { return done(err); } c = instance; in1 = noflo.internalSocket.createSocket(); c.inPorts.in1.attach(in1); return done(); }); }); }); beforeEach(function() { out = noflo.internalSocket.createSocket(); return c.outPorts.out.attach(out); }); afterEach(function() { c.outPorts.out.detach(out); return out = null; }); return it('should forward scopes as expected', function(done) { var brackets, expected, received; expected = ['x < 1', 'x DATA 1onePc1:2twoIIP:PcMerge', 'x >']; received = []; brackets = []; out.on('ip', function(ip) { switch (ip.type) { case 'openBracket': received.push(ip.scope + " < " + ip.data); return brackets.push(ip.data); case 'data': return received.push(ip.scope + " DATA " + ip.data); case 'closeBracket': received.push(ip.scope + " >"); brackets.pop(); if (brackets.length) { return; } chai.expect(received).to.eql(expected); return done(); } }); in1.post(new noflo.IP('openBracket', 1, { scope: 'x' })); in1.post(new noflo.IP('data', 'one', { scope: 'x' })); return in1.post(new noflo.IP('closeBracket', 1, { scope: 'x' })); }); }); return describe('Process API with IIPs to addressable ports and scopes', function() { var c, in1, in2, out; c = null; in1 = null; in2 = null; out = null; before(function(done) { var fbpData; fbpData = "INPORT=Pc1.IN:IN1 OUTPORT=PcMergeA.OUT:OUT Pc1(process/Async) -> IN1 PcMergeA(process/MergeA) 'twoIIP0' -> IN2[0] PcMergeA 'twoIIP1' -> IN2[1] PcMergeA"; return noflo.graph.loadFBP(fbpData, function(err, g) { if (err) { return done(err); } loader.registerComponent('scope', 'MergeIIPA', g); return loader.load('scope/MergeIIPA', function(err, instance) { if (err) { return done(err); } c = instance; in1 = noflo.internalSocket.createSocket(); c.inPorts.in1.attach(in1); return done(); }); }); }); beforeEach(function() { out = noflo.internalSocket.createSocket(); return c.outPorts.out.attach(out); }); afterEach(function() { c.outPorts.out.detach(out); return out = null; }); return it('should forward scopes as expected', function(done) { var brackets, expected, received; expected = ['x < 1', 'x DATA 1onePc1:2twoIIP0:2twoIIP1:PcMergeA', 'x >']; received = []; brackets = []; out.on('ip', function(ip) { switch (ip.type) { case 'openBracket': received.push(ip.scope + " < " + ip.data); return brackets.push(ip.data); case 'data': return received.push(ip.scope + " DATA " + ip.data); case 'closeBracket': received.push(ip.scope + " >"); brackets.pop(); if (brackets.length) { return; } chai.expect(received).to.eql(expected); return done(); } }); in1.post(new noflo.IP('openBracket', 1, { scope: 'x' })); in1.post(new noflo.IP('data', 'one', { scope: 'x' })); return in1.post(new noflo.IP('closeBracket', 1, { scope: 'x' })); }); }); });