noflo
Version:
Flow-Based Programming environment for JavaScript
327 lines (324 loc) • 9.6 kB
JavaScript
var chai, noflo, path, root, urlPrefix;
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 = '/';
}
describe('asCallback interface', function() {
var loader, neverSend, processAsync, processError, streamify;
loader = null;
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);
}, 1);
});
};
processError = function() {
var c;
c = new noflo.Component;
c.inPorts.add('in', {
datatype: 'string'
});
c.outPorts.add('out', {
datatype: 'string'
});
c.outPorts.add('error');
return c.process(function(input, output) {
var data;
data = input.getData('in');
return output.done(new Error("Received " + data));
});
};
neverSend = 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;
return data = input.getData('in');
});
};
streamify = 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 char, chars, data, i, idx, j, len, len1, word, words;
data = input.getData('in');
words = data.split(' ');
for (idx = i = 0, len = words.length; i < len; idx = ++i) {
word = words[idx];
output.send(new noflo.IP('openBracket', idx));
chars = word.split('');
for (j = 0, len1 = chars.length; j < len1; j++) {
char = chars[j];
output.send(new noflo.IP('data', char));
}
output.send(new noflo.IP('closeBracket', idx));
}
return output.done();
});
};
before(function(done) {
loader = new noflo.ComponentLoader(root);
return loader.listComponents(function(err) {
if (err) {
return done(err);
}
loader.registerComponent('process', 'Async', processAsync);
loader.registerComponent('process', 'Error', processError);
loader.registerComponent('process', 'NeverSend', neverSend);
loader.registerComponent('process', 'Streamify', streamify);
return done();
});
});
describe('with a non-existing component', function() {
var wrapped;
wrapped = null;
before(function() {
return wrapped = noflo.asCallback('foo/Bar', {
loader: loader
});
});
it('should be able to wrap it', function(done) {
chai.expect(wrapped).to.be.a('function');
chai.expect(wrapped.length).to.equal(2);
return done();
});
return it('should fail execution', function(done) {
return wrapped(1, function(err) {
chai.expect(err).to.be.an('error');
return done();
});
});
});
describe('with simple asynchronous component', function() {
var wrapped;
wrapped = null;
before(function() {
return wrapped = noflo.asCallback('process/Async', {
loader: loader
});
});
it('should be able to wrap it', function(done) {
chai.expect(wrapped).to.be.a('function');
chai.expect(wrapped.length).to.equal(2);
return done();
});
it('should execute network with input map and provide output map', function(done) {
var expected;
expected = {
hello: 'world'
};
return wrapped({
"in": expected
}, function(err, out) {
if (err) {
return done(err);
}
chai.expect(out.out).to.eql(expected);
return done();
});
});
it('should execute network with simple input and provide simple output', function(done) {
var expected;
expected = {
hello: 'world'
};
return wrapped(expected, function(err, out) {
if (err) {
return done(err);
}
chai.expect(out).to.eql(expected);
return done();
});
});
it('should not mix up simultaneous runs', function(done) {
var i, received, results;
received = 0;
return (function() {
results = [];
for (i = 0; i <= 100; i++){ results.push(i); }
return results;
}).apply(this).forEach(function(idx) {
return wrapped(idx, function(err, out) {
if (err) {
return done(err);
}
chai.expect(out).to.equal(idx);
received++;
if (received !== 101) {
return;
}
return done();
});
});
});
it('should execute a network with a sequence and provide output sequence', function(done) {
var expected, sent;
sent = [
{
"in": 'hello'
}, {
"in": 'world'
}, {
"in": 'foo'
}, {
"in": 'bar'
}
];
expected = sent.map(function(portmap) {
var res;
return res = {
out: portmap["in"]
};
});
return wrapped(sent, function(err, out) {
if (err) {
return done(err);
}
chai.expect(out).to.eql(expected);
return done();
});
});
return describe('with the raw option', function() {
return it('should execute a network with a sequence and provide output sequence', function(done) {
var sent, wrappedRaw;
wrappedRaw = noflo.asCallback('process/Async', {
loader: loader,
raw: true
});
sent = [
{
"in": new noflo.IP('openBracket', 'a')
}, {
"in": 'hello'
}, {
"in": 'world'
}, {
"in": new noflo.IP('closeBracket', 'a')
}, {
"in": new noflo.IP('openBracket', 'b')
}, {
"in": 'foo'
}, {
"in": 'bar'
}, {
"in": new noflo.IP('closeBracket', 'b')
}
];
return wrappedRaw(sent, function(err, out) {
var types;
if (err) {
return done(err);
}
types = out.map(function(map) {
return map.out.type + " " + map.out.data;
});
chai.expect(types).to.eql(['openBracket a', 'data hello', 'data world', 'closeBracket a', 'openBracket b', 'data foo', 'data bar', 'closeBracket b']);
return done();
});
});
});
});
describe('with a component sending an error', function() {
var wrapped;
wrapped = null;
before(function() {
return wrapped = noflo.asCallback('process/Error', {
loader: loader
});
});
it('should execute network with input map and provide error', function(done) {
var expected;
expected = 'hello there';
return wrapped({
"in": expected
}, function(err) {
chai.expect(err).to.be.an('error');
chai.expect(err.message).to.contain(expected);
return done();
});
});
return it('should execute network with simple input and provide error', function(done) {
var expected;
expected = 'hello world';
return wrapped(expected, function(err) {
chai.expect(err).to.be.an('error');
chai.expect(err.message).to.contain(expected);
return done();
});
});
});
return describe('with a component sending streams', function() {
var wrapped;
wrapped = null;
before(function() {
return wrapped = noflo.asCallback('process/Streamify', {
loader: loader
});
});
it('should execute network with input map and provide output map with streams as arrays', function(done) {
return wrapped({
"in": 'hello world'
}, function(err, out) {
chai.expect(out.out).to.eql([['h', 'e', 'l', 'l', 'o'], ['w', 'o', 'r', 'l', 'd']]);
return done();
});
});
it('should execute network with simple input and and provide simple output with streams as arrays', function(done) {
return wrapped('hello there', function(err, out) {
chai.expect(out).to.eql([['h', 'e', 'l', 'l', 'o'], ['t', 'h', 'e', 'r', 'e']]);
return done();
});
});
return describe('with the raw option', function() {
return it('should execute network with input map and provide output map with IP objects', function(done) {
var wrappedRaw;
wrappedRaw = noflo.asCallback('process/Streamify', {
loader: loader,
raw: true
});
return wrappedRaw({
"in": 'hello world'
}, function(err, out) {
var types;
types = out.out.map(function(ip) {
return ip.type + " " + ip.data;
});
chai.expect(types).to.eql(['openBracket 0', 'data h', 'data e', 'data l', 'data l', 'data o', 'closeBracket 0', 'openBracket 1', 'data w', 'data o', 'data r', 'data l', 'data d', 'closeBracket 1']);
return done();
});
});
});
});
});