noflo
Version:
Flow-Based Programming environment for JavaScript
1,633 lines (1,631 loc) • 74.7 kB
JavaScript
var chai, noflo;
if (typeof process !== 'undefined' && process.execPath && process.execPath.match(/node|iojs/)) {
if (!chai) {
chai = require('chai');
}
noflo = require('../src/lib/NoFlo.coffee');
} else {
noflo = require('noflo');
}
describe('Component traits', function() {
describe('MapComponent', function() {
var c;
c = null;
it('should pass data to the callback', function() {
var s;
c = new noflo.Component;
c.inPorts.add('in');
c.outPorts.add('out', {
required: false
});
noflo.helpers.MapComponent(c, function(data) {
return chai.expect(data).to.equal(1);
});
s = new noflo.internalSocket.createSocket();
c.inPorts["in"].attach(s);
return s.send(1);
});
it('should pass groups to the callback', function() {
var s;
c = new noflo.Component;
c.inPorts.add('in');
c.outPorts.add('out', {
required: false
});
noflo.helpers.MapComponent(c, function(data, groups) {
chai.expect(groups).to.eql(['one', 'two']);
return chai.expect(data).to.equal(1);
});
s = new noflo.internalSocket.createSocket();
c.inPorts["in"].attach(s);
s.beginGroup('one');
s.beginGroup('two');
return s.send(1);
});
return it('should send groups and disconnect through', function(done) {
var groups, s, s2;
c = new noflo.Component;
c.inPorts.add('in');
c.outPorts.add('out', {
required: false
});
noflo.helpers.MapComponent(c, function(data, groups, out) {
return out.send(data * 2);
});
s = new noflo.internalSocket.createSocket();
c.inPorts["in"].attach(s);
s2 = new noflo.internalSocket.createSocket();
c.outPorts.out.attach(s2);
groups = [];
s2.on('begingroup', function(group) {
return groups.push(group);
});
s2.on('data', function(data) {
chai.expect(groups.length).to.equal(2);
return chai.expect(data).to.equal(6);
});
s2.on('endgroup', function() {
return groups.pop();
});
s2.on('disconnect', function() {
chai.expect(groups.length).to.equal(0);
return done();
});
s.beginGroup('one');
s.beginGroup('two');
s.send(3);
s.endGroup();
s.endGroup();
return s.disconnect();
});
});
describe('WirePattern', function() {
describe('when grouping by packet groups', function() {
var c, p, x, y, z;
c = null;
x = null;
y = null;
z = null;
p = null;
beforeEach(function(done) {
c = new noflo.Component;
c.inPorts.add('x', {
required: true,
datatype: 'int'
}).add('y', {
required: true,
datatype: 'int'
}).add('z', {
required: true,
datatype: 'int'
});
c.outPorts.add('point');
x = new noflo.internalSocket.createSocket();
y = new noflo.internalSocket.createSocket();
z = new noflo.internalSocket.createSocket();
p = new noflo.internalSocket.createSocket();
c.inPorts.x.attach(x);
c.inPorts.y.attach(y);
c.inPorts.z.attach(z);
c.outPorts.point.attach(p);
return done();
});
afterEach(function() {
return c.outPorts.point.detach(p);
});
it('should pass data and groups to the callback', function(done) {
var count, groups, grp, key, results, src;
src = {
111: {
x: 1,
y: 2,
z: 3
},
222: {
x: 4,
y: 5,
z: 6
},
333: {
x: 7,
y: 8,
z: 9
}
};
noflo.helpers.WirePattern(c, {
"in": ['x', 'y', 'z'],
out: 'point',
group: true,
forwardGroups: true
}, function(data, groups, out) {
chai.expect(groups.length).to.be.above(0);
chai.expect(data).to.deep.equal(src[groups[0]]);
return out.send(data);
});
groups = [];
count = 0;
p.on('begingroup', function(grp) {
return groups.push(grp);
});
p.on('endgroup', function() {
return groups.pop();
});
p.on('data', function(data) {
return count++;
});
p.on('disconnect', function() {
if (count === 3 && groups.length === 0) {
return done();
}
});
results = [];
for (key in src) {
grp = src[key];
x.beginGroup(key);
y.beginGroup(key);
z.beginGroup(key);
x.send(grp.x);
y.send(grp.y);
z.send(grp.z);
x.endGroup();
y.endGroup();
z.endGroup();
x.disconnect();
y.disconnect();
results.push(z.disconnect());
}
return results;
});
it('should work without a group provided', function(done) {
noflo.helpers.WirePattern(c, {
"in": ['x', 'y', 'z'],
out: 'point'
}, function(data, groups, out) {
chai.expect(groups.length).to.equal(0);
return out.send({
x: data.x,
y: data.y,
z: data.z
});
});
p.once('data', function(data) {
chai.expect(data).to.deep.equal({
x: 123,
y: 456,
z: 789
});
return done();
});
x.send(123);
x.disconnect();
y.send(456);
y.disconnect();
z.send(789);
return z.disconnect();
});
it('should process inputs for different groups independently with group: true', function(done) {
var groups, inOrder, input, j, len, outOrder, results, src, tuple;
src = {
1: {
x: 1,
y: 2,
z: 3
},
2: {
x: 4,
y: 5,
z: 6
},
3: {
x: 7,
y: 8,
z: 9
}
};
inOrder = [[1, 'x'], [3, 'z'], [2, 'y'], [2, 'x'], [1, 'z'], [2, 'z'], [3, 'x'], [1, 'y'], [3, 'y']];
outOrder = [2, 1, 3];
noflo.helpers.WirePattern(c, {
"in": ['x', 'y', 'z'],
out: 'point',
group: true,
forwardGroups: true
}, function(data, groups, out) {
return out.send({
x: data.x,
y: data.y,
z: data.z
});
});
groups = [];
p.on('begingroup', function(grp) {
return groups.push(grp);
});
p.on('endgroup', function(grp) {
return groups.pop();
});
p.on('data', function(data) {
chai.expect(groups.length).to.equal(1);
chai.expect(groups[0]).to.equal(outOrder[0]);
chai.expect(data).to.deep.equal(src[outOrder[0]]);
outOrder.shift();
if (!outOrder.length) {
return done();
}
});
results = [];
for (j = 0, len = inOrder.length; j < len; j++) {
tuple = inOrder[j];
input = null;
switch (tuple[1]) {
case 'x':
input = x;
break;
case 'y':
input = y;
break;
case 'z':
input = z;
}
input.beginGroup(tuple[0]);
input.send(src[tuple[0]][tuple[1]]);
input.endGroup();
results.push(input.disconnect());
}
return results;
});
it('should support asynchronous handlers', function(done) {
var counter, hadData, point;
point = {
x: 123,
y: 456,
z: 789
};
noflo.helpers.WirePattern(c, {
"in": ['x', 'y', 'z'],
out: 'point',
async: true,
group: true,
forwardGroups: true
}, function(data, groups, out, callback) {
return setTimeout(function() {
out.send({
x: data.x,
y: data.y,
z: data.z
});
return callback();
}, 100);
});
counter = 0;
hadData = false;
p.on('begingroup', function(grp) {
return counter++;
});
p.on('endgroup', function() {
return counter--;
});
p.once('data', function(data) {
chai.expect(data).to.deep.equal(point);
return hadData = true;
});
p.once('disconnect', function() {
chai.expect(counter).to.equal(0);
chai.expect(hadData).to.be["true"];
return done();
});
x.beginGroup('async');
y.beginGroup('async');
z.beginGroup('async');
x.send(point.x);
y.send(point.y);
z.send(point.z);
x.endGroup();
y.endGroup();
z.endGroup();
x.disconnect();
y.disconnect();
return z.disconnect();
});
it('should support asynchronous handlers in legacy mode', function(done) {
var counter, hadData, point;
point = {
x: 123,
y: 456,
z: 789
};
noflo.helpers.WirePattern(c, {
"in": ['x', 'y', 'z'],
out: 'point',
async: true,
group: true,
forwardGroups: true,
legacy: true
}, function(data, groups, out, callback) {
return setTimeout(function() {
out.send({
x: data.x,
y: data.y,
z: data.z
});
return callback();
}, 100);
});
counter = 0;
hadData = false;
p.on('begingroup', function(grp) {
return counter++;
});
p.on('endgroup', function() {
return counter--;
});
p.once('data', function(data) {
chai.expect(data).to.deep.equal(point);
return hadData = true;
});
p.once('disconnect', function() {
chai.expect(counter).to.equal(0);
chai.expect(hadData).to.be["true"];
return done();
});
x.beginGroup('async');
y.beginGroup('async');
z.beginGroup('async');
x.send(point.x);
y.send(point.y);
z.send(point.z);
x.endGroup();
y.endGroup();
z.endGroup();
x.disconnect();
y.disconnect();
return z.disconnect();
});
it('should not forward groups if forwarding is off', function(done) {
var counter, hadData, point;
point = {
x: 123,
y: 456
};
noflo.helpers.WirePattern(c, {
"in": ['x', 'y'],
out: 'point'
}, function(data, groups, out) {
return out.send({
x: data.x,
y: data.y
});
});
counter = 0;
hadData = false;
p.on('begingroup', function(grp) {
return counter++;
});
p.on('data', function(data) {
chai.expect(data).to.deep.equal(point);
return hadData = true;
});
p.once('disconnect', function() {
chai.expect(counter).to.equal(0);
chai.expect(hadData).to.be["true"];
return done();
});
x.beginGroup('doNotForwardMe');
y.beginGroup('doNotForwardMe');
x.send(point.x);
y.send(point.y);
x.endGroup();
y.endGroup();
x.disconnect();
return y.disconnect();
});
it('should forward groups from a specific port only', function(done) {
var groups, point, refGroups;
point = {
x: 123,
y: 456,
z: 789
};
refGroups = ['boo'];
noflo.helpers.WirePattern(c, {
"in": ['x', 'y', 'z'],
out: 'point',
forwardGroups: 'y'
}, function(data, groups, out) {
return out.send({
x: data.x,
y: data.y,
z: data.z
});
});
groups = [];
p.on('begingroup', function(grp) {
return groups.push(grp);
});
p.on('data', function(data) {
return chai.expect(data).to.deep.equal(point);
});
p.once('disconnect', function() {
chai.expect(groups).to.deep.equal(refGroups);
return done();
});
x.beginGroup('foo');
y.beginGroup('boo');
z.beginGroup('bar');
x.send(point.x);
y.send(point.y);
z.send(point.z);
x.endGroup();
y.endGroup();
z.endGroup();
x.disconnect();
y.disconnect();
return z.disconnect();
});
return it('should forward groups from selected ports only', function(done) {
var groups, point, refGroups;
point = {
x: 123,
y: 456,
z: 789
};
refGroups = ['foo', 'bar'];
noflo.helpers.WirePattern(c, {
"in": ['x', 'y', 'z'],
out: 'point',
forwardGroups: ['x', 'z']
}, function(data, groups, out) {
return out.send({
x: data.x,
y: data.y,
z: data.z
});
});
groups = [];
p.on('begingroup', function(grp) {
return groups.push(grp);
});
p.on('data', function(data) {
return chai.expect(data).to.deep.equal(point);
});
p.once('disconnect', function() {
chai.expect(groups).to.deep.equal(refGroups);
return done();
});
x.beginGroup('foo');
y.beginGroup('boo');
z.beginGroup('bar');
x.send(point.x);
y.send(point.y);
z.send(point.z);
x.endGroup();
y.endGroup();
z.endGroup();
x.disconnect();
y.disconnect();
return z.disconnect();
});
});
describe('when `this` context is important', function() {
var c, p, x, y, z;
c = new noflo.Component;
c.inPorts.add('x', {
required: true,
datatype: 'int'
}).add('y', {
required: true,
datatype: 'int'
}).add('z', {
required: true,
datatype: 'int'
});
c.outPorts.add('point');
x = new noflo.internalSocket.createSocket();
y = new noflo.internalSocket.createSocket();
z = new noflo.internalSocket.createSocket();
p = new noflo.internalSocket.createSocket();
c.inPorts.x.attach(x);
c.inPorts.y.attach(y);
c.inPorts.z.attach(z);
c.outPorts.point.attach(p);
it('should correctly bind component to `this` context', function(done) {
noflo.helpers.WirePattern(c, {
"in": ['x', 'y', 'z'],
out: 'point'
}, function(data, groups, out) {
chai.expect(this).to.deep.equal(c);
return out.send({
x: data.x,
y: data.y,
z: data.z
});
});
p.once('data', function(data) {
chai.expect(data).to.deep.equal({
x: 123,
y: 456,
z: 789
});
return done();
});
x.send(123);
x.disconnect();
y.send(456);
y.disconnect();
z.send(789);
return z.disconnect();
});
return it('should correctly bind component to `this` context in async mode', function(done) {
noflo.helpers.WirePattern(c, {
"in": ['x', 'y', 'z'],
async: true,
out: 'point'
}, function(data, groups, out, callback) {
chai.expect(this).to.deep.equal(c);
out.send({
x: data.x,
y: data.y,
z: data.z
});
return callback();
});
p.once('data', function(data) {
return done();
});
x.send(123);
x.disconnect();
y.send(456);
y.disconnect();
z.send(789);
return z.disconnect();
});
});
describe('when in async mode and packet order matters', function() {
var c, delay, load, msg, out;
c = new noflo.Component;
c.inPorts.add('delay', {
datatype: 'int'
}).add('msg', {
datatype: 'string'
});
c.outPorts.add('out', {
datatype: 'object'
}).add('load', {
datatype: 'int'
});
delay = new noflo.internalSocket.createSocket();
msg = new noflo.internalSocket.createSocket();
out = new noflo.internalSocket.createSocket();
load = new noflo.internalSocket.createSocket();
c.inPorts.delay.attach(delay);
c.inPorts.msg.attach(msg);
c.outPorts.out.attach(out);
c.outPorts.load.attach(load);
it('should preserve input order at the output', function(done) {
var expected, idx, ip, j, len, results, sample;
noflo.helpers.WirePattern(c, {
"in": ['delay', 'msg'],
async: true,
ordered: true,
group: false
}, function(data, groups, res, callback) {
return setTimeout(function() {
res.send({
delay: data.delay,
msg: data.msg
});
return callback();
}, data.delay);
});
sample = [
{
delay: 30,
msg: "one"
}, {
delay: 0,
msg: "two"
}, {
delay: 20,
msg: "three"
}, {
delay: 10,
msg: "four"
}
];
out.on('data', function(data) {
return chai.expect(data).to.deep.equal(sample.shift());
});
out.on('disconnect', function() {
if (sample.length === 0) {
return done();
}
});
expected = [1, 2, 3, 4, 3, 2, 1, 0];
load.on('data', function(data) {
return chai.expect(data).to.equal(expected.shift());
});
idx = 0;
results = [];
for (j = 0, len = sample.length; j < len; j++) {
ip = sample[j];
delay.beginGroup(idx);
delay.send(ip.delay);
delay.endGroup();
msg.beginGroup(idx);
msg.send(ip.msg);
msg.endGroup();
delay.disconnect();
msg.disconnect();
results.push(idx++);
}
return results;
});
it('should throw if receiveStreams is used', function(done) {
var f;
f = function() {
return noflo.helpers.WirePattern(c, {
"in": ['delay', 'msg'],
async: true,
ordered: true,
group: false,
receiveStreams: ['delay', 'msg']
}, function(data, groups, res, callback) {
return callback();
});
};
chai.expect(f).to["throw"](Error);
return done();
});
return it('should throw if sendStreams is used', function(done) {
var f;
f = function() {
return noflo.helpers.WirePattern(c, {
"in": ['delay', 'msg'],
async: true,
ordered: true,
group: false,
sendStreams: ['out']
}, function(data, groups, res, callback) {
return callback();
});
};
chai.expect(f).to["throw"](Error);
return done();
});
});
describe('when grouping by field', function() {
var c, msg, umsg, usr;
c = new noflo.Component;
c.inPorts.add('user', {
datatype: 'object'
}).add('message', {
datatype: 'object'
});
c.outPorts.add('signedmessage');
usr = new noflo.internalSocket.createSocket();
msg = new noflo.internalSocket.createSocket();
umsg = new noflo.internalSocket.createSocket();
c.inPorts.user.attach(usr);
c.inPorts.message.attach(msg);
c.outPorts.signedmessage.attach(umsg);
return it('should match objects by specific field', function(done) {
var counter, fn, mesg, messages, req, results, user, users;
noflo.helpers.WirePattern(c, {
"in": ['user', 'message'],
out: 'signedmessage',
async: true,
field: 'request'
}, function(data, groups, out, callback) {
return setTimeout(function() {
out.send({
request: data.request,
user: data.user.name,
text: data.message.text
});
return callback();
}, 10);
});
users = {
14: {
request: 14,
id: 21,
name: 'Josh'
},
12: {
request: 12,
id: 25,
name: 'Leo'
},
34: {
request: 34,
id: 84,
name: 'Anica'
}
};
messages = {
34: {
request: 34,
id: 234,
text: 'Hello world'
},
12: {
request: 12,
id: 82,
text: 'Aloha amigos'
},
14: {
request: 14,
id: 249,
text: 'Node.js ftw'
}
};
counter = 0;
umsg.on('data', function(data) {
chai.expect(data).to.be.an('object');
chai.expect(data.request).to.be.ok;
chai.expect(data.user).to.equal(users[data.request].name);
chai.expect(data.text).to.equal(messages[data.request].text);
counter++;
if (counter === 3) {
return done();
}
});
fn = function(req, user) {
return setTimeout(function() {
usr.send(user);
return usr.disconnect();
}, req);
};
for (req in users) {
user = users[req];
fn(req, user);
}
results = [];
for (req in messages) {
mesg = messages[req];
results.push((function(req, mesg) {
return setTimeout(function() {
msg.send(mesg);
return msg.disconnect();
}, req);
})(req, mesg));
}
return results;
});
});
describe('when there are multiple output routes', function() {
it('should send output to one or more of them', function(done) {
var c, even, expected, i, j, num, numbers, odd, received, results, str;
numbers = ['cero', 'uno', 'dos', 'tres', 'cuatro', 'cinco', 'seis', 'siete', 'ocho', 'nueve'];
c = new noflo.Component;
c.inPorts.add('num', {
datatype: 'int'
}).add('str', {
datatype: 'string'
});
c.outPorts.add('odd', {
datatype: 'object'
}).add('even', {
datatype: 'object'
});
num = new noflo.internalSocket.createSocket();
str = new noflo.internalSocket.createSocket();
odd = new noflo.internalSocket.createSocket();
even = new noflo.internalSocket.createSocket();
c.inPorts.num.attach(num);
c.inPorts.str.attach(str);
c.outPorts.odd.attach(odd);
c.outPorts.even.attach(even);
noflo.helpers.WirePattern(c, {
"in": ['num', 'str'],
out: ['odd', 'even'],
async: true,
ordered: true,
forwardGroups: true
}, function(data, groups, outs, callback) {
return setTimeout(function() {
if (data.num % 2 === 1) {
outs.odd.send(data);
} else {
outs.even.send(data);
}
return callback();
}, 0);
});
expected = [];
numbers.forEach(function(n, idx) {
var port;
if (idx % 2 === 1) {
port = 'odd';
} else {
port = 'even';
}
expected.push(port + " < " + idx);
expected.push(port + " DATA " + n);
return expected.push(port + " > " + idx);
});
received = [];
odd.on('begingroup', function(grp) {
return received.push("odd < " + grp);
});
odd.on('data', function(data) {
return received.push("odd DATA " + data.str);
});
odd.on('endgroup', function(grp) {
return received.push("odd > " + grp);
});
odd.on('disconnect', function() {
if (received.length !== expected.length) {
return;
}
chai.expect(received).to.eql(expected);
return done();
});
even.on('begingroup', function(grp) {
return received.push("even < " + grp);
});
even.on('data', function(data) {
return received.push("even DATA " + data.str);
});
even.on('endgroup', function(grp) {
return received.push("even > " + grp);
});
even.on('disconnect', function() {
if (!(received.length >= expected.length)) {
return;
}
chai.expect(received).to.eql(expected);
return done();
});
results = [];
for (i = j = 0; j < 10; i = ++j) {
num.beginGroup(i);
num.send(i);
num.endGroup(i);
num.disconnect();
str.beginGroup(i);
str.send(numbers[i]);
str.endGroup(i);
results.push(str.disconnect());
}
return results;
});
return it('should send output to one or more of indexes', function(done) {
var c, even, expected, i, j, num, numbers, odd, received, results, str;
c = new noflo.Component;
c.inPorts.add('num', {
datatype: 'int'
}).add('str', {
datatype: 'string'
});
c.outPorts.add('out', {
datatype: 'object',
addressable: true
});
num = new noflo.internalSocket.createSocket();
str = new noflo.internalSocket.createSocket();
odd = new noflo.internalSocket.createSocket();
even = new noflo.internalSocket.createSocket();
c.inPorts.num.attach(num);
c.inPorts.str.attach(str);
c.outPorts.out.attach(odd);
c.outPorts.out.attach(even);
numbers = ['cero', 'uno', 'dos', 'tres', 'cuatro', 'cinco', 'seis', 'siete', 'ocho', 'nueve'];
noflo.helpers.WirePattern(c, {
"in": ['num', 'str'],
out: 'out',
async: true,
ordered: true,
forwardGroups: true
}, function(data, groups, outs, callback) {
return setTimeout(function() {
if (data.num % 2 === 1) {
outs.send(data, 0);
} else {
outs.send(data, 1);
}
return callback();
}, 0);
});
expected = [];
numbers.forEach(function(n, idx) {
var port;
if (idx % 2 === 1) {
port = 'odd';
} else {
port = 'even';
}
expected.push(port + " < " + idx);
expected.push(port + " DATA " + n);
return expected.push(port + " > " + idx);
});
received = [];
odd.on('begingroup', function(grp) {
return received.push("odd < " + grp);
});
odd.on('data', function(data) {
return received.push("odd DATA " + data.str);
});
odd.on('endgroup', function(grp) {
return received.push("odd > " + grp);
});
odd.on('disconnect', function() {
if (received.length !== expected.length) {
return;
}
chai.expect(received).to.eql(expected);
return done();
});
even.on('begingroup', function(grp) {
return received.push("even < " + grp);
});
even.on('data', function(data) {
return received.push("even DATA " + data.str);
});
even.on('endgroup', function(grp) {
return received.push("even > " + grp);
});
even.on('disconnect', function() {
if (!(received.length >= expected.length)) {
return;
}
chai.expect(received).to.eql(expected);
return done();
});
results = [];
for (i = j = 0; j < 10; i = ++j) {
num.beginGroup(i);
num.send(i);
num.endGroup(i);
num.disconnect();
str.beginGroup(i);
str.send(numbers[i]);
str.endGroup(i);
results.push(str.disconnect());
}
return results;
});
});
describe('when there are parameter ports', function() {
var c, d1, d2, err, out, p1, p2, p3;
c = null;
p1 = p2 = p3 = d1 = d2 = out = err = 0;
beforeEach(function() {
c = new noflo.Component;
c.inPorts.add('param1', {
datatype: 'string',
required: true
}).add('param2', {
datatype: 'int',
required: false
}).add('param3', {
datatype: 'int',
required: true,
"default": 0
}).add('data1', {
datatype: 'string'
}).add('data2', {
datatype: 'int'
});
c.outPorts.add('out', {
datatype: 'object'
}).add('error', {
datatype: 'object'
});
p1 = new noflo.internalSocket.createSocket();
p2 = new noflo.internalSocket.createSocket();
p3 = new noflo.internalSocket.createSocket();
d1 = new noflo.internalSocket.createSocket();
d2 = new noflo.internalSocket.createSocket();
out = new noflo.internalSocket.createSocket();
err = new noflo.internalSocket.createSocket();
c.inPorts.param1.attach(p1);
c.inPorts.param2.attach(p2);
c.inPorts.param3.attach(p3);
c.inPorts.data1.attach(d1);
c.inPorts.data2.attach(d2);
c.outPorts.out.attach(out);
return c.outPorts.error.attach(err);
});
it('should wait for required params without default value', function(done) {
noflo.helpers.WirePattern(c, {
"in": ['data1', 'data2'],
out: 'out',
params: ['param1', 'param2', 'param3']
}, function(input, groups, out) {
var res;
res = {
p1: c.params.param1,
p2: c.params.param2,
p3: c.params.param3,
d1: input.data1,
d2: input.data2
};
return out.send(res);
});
err.on('data', function(data) {
return done(data);
});
out.once('data', function(data) {
chai.expect(data).to.be.an('object');
chai.expect(data.p1).to.equal('req');
chai.expect(data.p2).to.be.undefined;
chai.expect(data.p3).to.equal(0);
chai.expect(data.d1).to.equal('foo');
chai.expect(data.d2).to.equal(123);
return out.once('data', function(data) {
chai.expect(data).to.be.an('object');
chai.expect(data.p1).to.equal('req');
chai.expect(data.p2).to.equal(568);
chai.expect(data.p3).to.equal(800);
chai.expect(data.d1).to.equal('bar');
chai.expect(data.d2).to.equal(456);
return done();
});
});
d1.send('foo');
d1.disconnect();
d2.send(123);
d2.disconnect();
c.sendDefaults();
p1.send('req');
p1.disconnect();
return setTimeout(function() {
p2.send(568);
p2.disconnect();
p3.send(800);
p3.disconnect();
d1.send('bar');
d1.disconnect();
d2.send(456);
return d2.disconnect();
}, 10);
});
it('should work for async procs too', function(done) {
noflo.helpers.WirePattern(c, {
"in": ['data1', 'data2'],
out: 'out',
params: ['param1', 'param2', 'param3'],
async: true
}, function(input, groups, out, callback) {
var delay;
delay = c.params.param2 ? c.params.param2 : 10;
return setTimeout(function() {
var res;
res = {
p1: c.params.param1,
p2: c.params.param2,
p3: c.params.param3,
d1: input.data1,
d2: input.data2
};
out.send(res);
return callback();
}, delay);
});
err.on('data', function(data) {
return done(data);
});
out.once('data', function(data) {
chai.expect(data).to.be.an('object');
chai.expect(data.p1).to.equal('req');
chai.expect(data.p2).to.equal(56);
chai.expect(data.p3).to.equal(0);
chai.expect(data.d1).to.equal('foo');
chai.expect(data.d2).to.equal(123);
return done();
});
p2.send(56);
p2.disconnect();
d1.send('foo');
d1.disconnect();
d2.send(123);
d2.disconnect();
c.sendDefaults();
p1.send('req');
return p1.disconnect();
});
it('should reset state if shutdown() is called', function(done) {
noflo.helpers.WirePattern(c, {
"in": ['data1', 'data2'],
out: 'out',
params: ['param1', 'param2', 'param3']
}, function(input, groups, out) {
return out.send({
p1: c.params.param1,
p2: c.params.param2,
p3: c.params.param3,
d1: input.data1,
d2: input.data2
});
});
d1.send('boo');
d1.disconnect();
p2.send(73);
p2.disconnect();
chai.expect(c.inPorts.data1.getBuffer().length, 'data1 should have a packet').to.be.above(0);
chai.expect(c.inPorts.param2.getBuffer().length, 'param2 should have a packet').to.be.above(0);
return c.shutdown(function(err) {
var j, len, port, portName, ref;
if (err) {
return done(err);
}
ref = c.inPorts.ports;
for (port = j = 0, len = ref.length; j < len; port = ++j) {
portName = ref[port];
chai.expect(port.getBuffer()).to.eql([]);
chai.expect(c.load).to.equal(0);
}
return done();
});
});
return it('should drop premature data if configured to do so', function(done) {
noflo.helpers.WirePattern(c, {
"in": ['data1', 'data2'],
out: 'out',
params: ['param1', 'param2', 'param3'],
dropInput: true
}, function(input, groups, out) {
var res;
res = {
p1: c.params.param1,
p2: c.params.param2,
p3: c.params.param3,
d1: input.data1,
d2: input.data2
};
return out.send(res);
});
err.on('data', function(data) {
return done(data);
});
out.once('data', function(data) {
chai.expect(data).to.be.an('object');
chai.expect(data.p1).to.equal('req');
chai.expect(data.p2).to.equal(568);
chai.expect(data.p3).to.equal(800);
chai.expect(data.d1).to.equal('bar');
chai.expect(data.d2).to.equal(456);
return done();
});
c.sendDefaults();
p2.send(568);
p2.disconnect();
p3.send(800);
p3.disconnect();
d1.send('foo');
d1.disconnect();
d2.send(123);
d2.disconnect();
return setTimeout(function() {
p1.send('req');
p1.disconnect();
d1.send('bar');
d1.disconnect();
d2.send(456);
return d2.disconnect();
}, 10);
});
});
describe('without output ports', function() {
var foo, sig;
foo = null;
sig = null;
before(function() {
var c;
c = new noflo.Component;
c.inPorts.add('foo');
foo = noflo.internalSocket.createSocket();
sig = noflo.internalSocket.createSocket();
c.inPorts.foo.attach(foo);
return noflo.helpers.WirePattern(c, {
"in": 'foo',
out: [],
async: true
}, function(foo, grp, out, callback) {
return setTimeout(function() {
sig.send(foo);
return callback();
}, 20);
});
});
return it('should be fine still', function(done) {
sig.on('data', function(data) {
chai.expect(data).to.equal('foo');
return done();
});
foo.send('foo');
return foo.disconnect();
});
});
describe('with many inputs and groups in async mode', function() {
var err, ins, msg, out, pth, rep, tkn;
ins = noflo.internalSocket.createSocket();
msg = noflo.internalSocket.createSocket();
rep = noflo.internalSocket.createSocket();
pth = noflo.internalSocket.createSocket();
tkn = noflo.internalSocket.createSocket();
out = noflo.internalSocket.createSocket();
err = noflo.internalSocket.createSocket();
before(function() {
var c;
c = new noflo.Component;
c.token = null;
c.inPorts.add('in', {
datatype: 'string'
}).add('message', {
datatype: 'string'
}).add('repository', {
datatype: 'string'
}).add('path', {
datatype: 'string'
}).add('token', {
datatype: 'string'
}, function(event, payload) {
if (event === 'data') {
return c.token = payload;
}
});
c.outPorts.add('out', {
datatype: 'string'
}).add('error', {
datatype: 'object'
});
noflo.helpers.WirePattern(c, {
"in": ['in', 'message', 'repository', 'path'],
out: 'out',
async: true,
forwardGroups: true
}, function(data, groups, out, callback) {
return setTimeout(function() {
out.beginGroup(data.path);
out.send(data.message);
out.endGroup();
return callback();
}, 300);
});
c.inPorts["in"].attach(ins);
c.inPorts.message.attach(msg);
c.inPorts.repository.attach(rep);
c.inPorts.path.attach(pth);
c.inPorts.token.attach(tkn);
c.outPorts.out.attach(out);
return c.outPorts.error.attach(err);
});
return it('should handle mixed flow well', function(done) {
var ends, groups, packets, refData, refGroups;
groups = [];
refGroups = ['foo', 'http://techcrunch.com/2013/03/26/embedly-now/', 'path data'];
ends = 0;
packets = [];
refData = ['message data'];
out.on('begingroup', function(grp) {
return groups.push(grp);
});
out.on('endgroup', function() {
return ends++;
});
out.on('data', function(data) {
return packets.push(data);
});
out.on('disconnect', function() {
chai.expect(groups).to.deep.equal(refGroups);
chai.expect(ends).to.equal(3);
chai.expect(packets).to.deep.equal(refData);
return done();
});
err.on('data', function(data) {
return done(data);
});
rep.beginGroup('foo');
rep.beginGroup('http://techcrunch.com/2013/03/26/embedly-now/');
rep.send('repo data');
rep.endGroup();
rep.endGroup();
ins.beginGroup('foo');
ins.beginGroup('http://techcrunch.com/2013/03/26/embedly-now/');
ins.send('ins data');
msg.beginGroup('foo');
msg.beginGroup('http://techcrunch.com/2013/03/26/embedly-now/');
msg.send('message data');
msg.endGroup();
msg.endGroup();
ins.endGroup();
ins.endGroup();
ins.disconnect();
msg.disconnect();
pth.beginGroup('foo');
pth.beginGroup('http://techcrunch.com/2013/03/26/embedly-now/');
pth.send('path data');
pth.endGroup();
pth.endGroup();
pth.disconnect();
return rep.disconnect();
});
});
describe('with many inputs and groups in sync mode', function() {
var err, ins, msg, out, pth, rep, tkn;
ins = noflo.internalSocket.createSocket();
msg = noflo.internalSocket.createSocket();
rep = noflo.internalSocket.createSocket();
pth = noflo.internalSocket.createSocket();
tkn = noflo.internalSocket.createSocket();
out = noflo.internalSocket.createSocket();
err = noflo.internalSocket.createSocket();
before(function() {
var c;
c = new noflo.Component;
c.token = null;
c.inPorts.add('in', {
datatype: 'string'
}).add('message', {
datatype: 'string'
}).add('repository', {
datatype: 'string'
}).add('path', {
datatype: 'string'
}).add('token', {
datatype: 'string'
}, function(event, payload) {
if (event === 'data') {
return c.token = payload;
}
});
c.outPorts.add('out', {
datatype: 'string'
}).add('error', {
datatype: 'object'
});
noflo.helpers.WirePattern(c, {
"in": ['in', 'message', 'repository', 'path'],
out: 'out',
async: false,
forwardGroups: true
}, function(data, groups, out) {
out.beginGroup(data.path);
out.send(data.message);
return out.endGroup();
});
c.inPorts["in"].attach(ins);
c.inPorts.message.attach(msg);
c.inPorts.repository.attach(rep);
c.inPorts.path.attach(pth);
c.inPorts.token.attach(tkn);
c.outPorts.out.attach(out);
return c.outPorts.error.attach(err);
});
return it('should handle mixed flow well', function(done) {
var ends, groups, packets, refData, refGroups;
groups = [];
refGroups = ['foo', 'http://techcrunch.com/2013/03/26/embedly-now/', 'path data'];
ends = 0;
packets = [];
refData = ['message data'];
out.on('begingroup', function(grp) {
return groups.push(grp);
});
out.on('endgroup', function() {
return ends++;
});
out.on('data', function(data) {
return packets.push(data);
});
out.on('disconnect', function() {
chai.expect(groups).to.deep.equal(refGroups);
chai.expect(ends).to.equal(3);
chai.expect(packets).to.deep.equal(refData);
return done();
});
err.on('data', function(data) {
return done(data);
});
rep.beginGroup('foo');
rep.beginGroup('http://techcrunch.com/2013/03/26/embedly-now/');
rep.send('repo data');
rep.endGroup();
rep.endGroup();
ins.beginGroup('foo');
ins.beginGroup('http://techcrunch.com/2013/03/26/embedly-now/');
ins.send('ins data');
msg.beginGroup('foo');
msg.beginGroup('http://techcrunch.com/2013/03/26/embedly-now/');
msg.send('message data');
msg.endGroup();
msg.endGroup();
ins.endGroup();
ins.endGroup();
ins.disconnect();
msg.disconnect();
pth.beginGroup('foo');
pth.beginGroup('http://techcrunch.com/2013/03/26/embedly-now/');
pth.send('path data');
pth.endGroup();
pth.endGroup();
pth.disconnect();
return rep.disconnect();
});
});
describe('for batch processing', function() {
var addr2sum, cntA, cntB, dblA2add, dblB2add, gen2dblA, gen2dblB, newAdder, newDoubler, newGenerator, newSeqsum, sum;
newGenerator = function(name) {
var generator;
generator = new noflo.Component;
generator.inPorts.add('count', {
datatype: 'int'
});
generator.outPorts.add('seq', {
datatype: 'int'
});
return noflo.helpers.WirePattern(generator, {
"in": 'count',
out: 'seq',
async: true,
forwardGroups: true,
ordered: true
}, function(count, groups, seq, callback) {
var i, j, ref, results, sentCount;
sentCount = 0;
results = [];
for (i = j = 1, ref = count; 1 <= ref ? j <= ref : j >= ref; i = 1 <= ref ? ++j : --j) {
results.push((function(i) {
var delay;
delay = i > 10 ? i % 10 : i;
return setTimeout(function() {
seq.send(i);
sentCount++;
if (sentCount === count) {
return callback();
}
}, delay);
})(i));
}
return results;
});
};
newDoubler = function(name) {
var doubler;
doubler = new noflo.Component;
doubler.inPorts.add('num', {
datatype: 'int'
});
doubler.outPorts.add('out', {
datatype: 'int'
});
return noflo.helpers.WirePattern(doubler, {
"in": 'num',
out: 'out',
forwardGroups: true
}, function(num, groups, out) {
var dbl;
dbl = 2 * num;
return out.send(dbl);
});
};
newAdder = function() {
var adder;
adder = new noflo.Component;
adder.inPorts.add('num1', {
datatype: 'int'
});
adder.inPorts.add('num2', {
datatype: 'int'
});
adder.outPorts.add('sum', {
datatype: 'int'
});
return noflo.helpers.WirePattern(adder, {
"in": ['num1', 'num2'],
out: 'sum',
forwardGroups: true,
async: true,
ordered: true
}, function(args, groups, out, callback) {
var sum;
sum = args.num1 + args.num2;
return setTimeout(function() {
out.send(sum);
return callback();
}, sum % 10);
});
};
newSeqsum = function() {
var seqsum;
seqsum = new noflo.Component;
seqsum.sum = 0;
seqsum.inPorts.add('seq', {
datatype: 'int'
}, function(event, payload) {
switch (event) {
case 'data':
return seqsum.sum += payload;
case 'disconnect':
seqsum.outPorts.sum.send(seqsum.sum);
seqsum.sum = 0;
return seqsum.outPorts.sum.disconnect();
}
});
seqsum.outPorts.add('sum', {
datatype: 'int'
});
return seqsum;
};
cntA = noflo.internalSocket.createSocket();
cntB = noflo.internalSocket.createSocket();
gen2dblA = noflo.internalSocket.createSocket();
gen2dblB = noflo.internalSocket.createSocket();
dblA2add = noflo.internalSocket.createSocket();
dblB2add = noflo.internalSocket.createSocket();
addr2sum = noflo.internalSocket.createSocket();
sum = noflo.internalSocket.createSocket();
before(function() {
var addr, dblA, dblB, genA, genB, sumr;
genA = newGenerator('A');
genB = newGenerator('B');
dblA = newDoubler('A');
dblB = newDoubler('B');
addr = newAdder();
sumr = newSeqsum();
genA.inPorts.count.attach(cntA);
genB.inPorts.count.attach(cntB);
genA.outPorts.seq.attach(gen2dblA);
genB.outPorts.seq.attach(gen2dblB);
dblA.inPorts.num.attach(gen2dblA);
dblB.inPorts.num.attach(gen2dblB);
dblA.outPorts.out.attach(dblA2add);
dblB.outPorts.out.attach(dblB2add);
addr.inPorts.num1.attach(dblA2add);
addr.inPorts.num2.attach(dblB2add);
addr.outPorts.sum.attach(addr2sum);
sumr.inPorts.seq.attach(addr2sum);
return sumr.outPorts.sum.attach(sum);
});
return it('should process sequences of packets separated by disconnects', function(done) {
var actual, expected;
return this.skip('WirePattern doesn\'t see disconnects because of IP objects');
expected = [24, 40];
actual = [];
sum.on('data', function(data) {
return actual.push(data);
});
sum.on('disconnect', function() {
var act, exp;
chai.expect(actual).to.have.length.above(0);
chai.expect(expected).to.have.length.above(0);
act = actual.shift();
exp = expected.shift();
chai.expect(act).to.equal(exp);
if (expected.length === 0) {
return done();
}
});
cntA.send(3);
cntA.disconnect();
cntB.send(3);
cntB.disconnect();
cntA.send(4);
cntB.send(4);
cntA.disconnect();
return cntB.disconnect();
});
});
describe('for batch processing with groups', function() {
var c1, c1c2, c2, cnt, out;
c1 = new noflo.Component;
c1.inPorts.add('count', {
datatype: 'int'
});
c1.outPorts.add('seq', {
datatype: 'int'
});
c2 = new noflo.Component;
c2.inPorts.add('num', {
datatype: 'int'
});
c2.outPorts.add('out', {
datatype: 'int'
});
cnt = noflo.internalSocket.createSocket();
c1c2 = noflo.internalSocket.createSocket();
out = noflo.internalSocket.createSocket();
c1.inPorts.count.attach(cnt);
c1.outPorts.seq.attach(c1c2);
c2.inPo