noflo
Version:
Flow-Based Programming environment for JavaScript
400 lines (397 loc) • 12.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('Inport Port', function() {
describe('with default options', function() {
var p;
p = new noflo.InPort;
it('should be of datatype "all"', function() {
return chai.expect(p.getDataType()).to.equal('all');
});
it('should not be required', function() {
return chai.expect(p.isRequired()).to.equal(false);
});
it('should not be addressable', function() {
return chai.expect(p.isAddressable()).to.equal(false);
});
return it('should not be buffered', function() {
return chai.expect(p.isBuffered()).to.equal(false);
});
});
describe('with custom type', function() {
var p;
p = new noflo.InPort({
datatype: 'string',
type: 'text/url'
});
return it('should retain the type', function() {
chai.expect(p.getDataType()).to.equal('string');
return chai.expect(p.options.type).to.equal('text/url');
});
});
describe('without attached sockets', function() {
var p;
p = new noflo.InPort;
it('should not be attached', function() {
chai.expect(p.isAttached()).to.equal(false);
return chai.expect(p.listAttached()).to.eql([]);
});
it('should allow attaching', function() {
return chai.expect(p.canAttach()).to.equal(true);
});
it('should not be connected initially', function() {
return chai.expect(p.isConnected()).to.equal(false);
});
return it('should not contain a socket initially', function() {
return chai.expect(p.sockets.length).to.equal(0);
});
});
describe('with processing function called with port as context', function() {
return it('should set context to port itself', function(done) {
var p, s;
s = new noflo.internalSocket.InternalSocket;
p = new noflo.InPort;
p.on('data', function(packet, component) {
chai.expect(this).to.equal(p);
chai.expect(packet).to.equal('some-data');
return done();
});
p.attach(s);
return s.send('some-data');
});
});
describe('with default value', function() {
var p, s;
p = s = null;
beforeEach(function() {
p = new noflo.InPort({
"default": 'default-value'
});
s = new noflo.internalSocket.InternalSocket;
return p.attach(s);
});
it('should send the default value as a packet, though on next tick after initialization', function(done) {
p.on('data', function(data) {
chai.expect(data).to.equal('default-value');
return done();
});
return s.send();
});
return it('should send the default value before IIP', function(done) {
var received;
received = ['default-value', 'some-iip'];
p.on('data', function(data) {
chai.expect(data).to.equal(received.shift());
if (received.length === 0) {
return done();
}
});
return setTimeout(function() {
s.send();
return s.send('some-iip');
}, 0);
});
});
describe('with options stored in port', function() {
return it('should store all provided options in port, whether we expect it or not', function() {
var name, option, options, p, results;
options = {
datatype: 'string',
type: 'http://schema.org/Person',
description: 'Person',
required: true,
weNeverExpectThis: 'butWeStoreItAnyway'
};
p = new noflo.InPort(options);
results = [];
for (name in options) {
option = options[name];
results.push(chai.expect(p.options[name]).to.equal(option));
}
return results;
});
});
describe('with data type information', function() {
var f, right, wrong;
right = 'all string number int object array'.split(' ');
wrong = 'not valie data types'.split(' ');
f = function(datatype) {
return new noflo.InPort({
datatype: datatype
});
};
right.forEach(function(r) {
return it("should accept a '" + r + "' data type", (function(_this) {
return function() {
return chai.expect(function() {
return f(r);
}).to.not["throw"]();
};
})(this));
});
return wrong.forEach(function(w) {
return it("should NOT accept a '" + w + "' data type", (function(_this) {
return function() {
return chai.expect(function() {
return f(w);
}).to["throw"]();
};
})(this));
});
});
describe('with TYPE (i.e. ontology) information', function() {
var f;
f = function(type) {
return new noflo.InPort({
type: type
});
};
return it('should be a URL or MIME', function() {
chai.expect(function() {
return f('http://schema.org/Person');
}).to.not["throw"]();
chai.expect(function() {
return f('text/javascript');
}).to.not["throw"]();
return chai.expect(function() {
return f('neither-a-url-nor-mime');
}).to["throw"]();
});
});
describe('with buffering', function() {
it('should buffer incoming packets until `receive()`d', function(done) {
var expectedData, expectedEvents, p, s;
expectedEvents = ['connect', 'data', 'data', 'disconnect', 'connect', 'data', 'disconnect'];
expectedData = ['buffered-data-1', 'buffered-data-2', 'buffered-data-3'];
p = new noflo.InPort({
buffered: true
}, function(eventName) {
var expectedEvent, packet;
expectedEvent = expectedEvents.shift();
chai.expect(eventName).to.equal(expectedEvent);
packet = p.receive();
chai.expect(packet).to.be.an('object');
chai.expect(packet.event).to.equal(expectedEvent);
if (packet.event === 'data') {
chai.expect(packet.payload).to.equal(expectedData.shift());
}
if (expectedEvents.length === 0) {
return done();
}
});
s = new noflo.internalSocket.InternalSocket;
p.attach(s);
s.send('buffered-data-1');
s.send('buffered-data-2');
s.disconnect();
s.send('buffered-data-3');
return s.disconnect();
});
it('should be able to tell the number of contained data packets', function() {
var p, s;
p = new noflo.InPort({
buffered: true
});
s = new noflo.internalSocket.InternalSocket;
p.attach(s);
s.send('buffered-data-1');
s.beginGroup('foo');
s.send('buffered-data-2');
s.endGroup();
s.disconnect();
s.send('buffered-data-3');
s.disconnect();
return chai.expect(p.contains()).to.equal(3);
});
it('should return undefined when buffer is empty', function() {
var p;
p = new noflo.InPort({
buffered: true
});
return chai.expect(p.receive()).to.be.undefined;
});
return it('shouldn\'t expose the receive method without buffering', function() {
var p, s;
p = new noflo.InPort({
buffered: false
});
s = new noflo.internalSocket.InternalSocket;
p.attach(s);
p.once('data', function(data) {
chai.expect(data).to.equal('data');
chai.expect(function() {
return p.receive();
}).to["throw"]();
return chai.expect(function() {
return p.contains();
}).to["throw"]();
});
return s.send('data');
});
});
describe('with accepted enumerated values', function() {
it('should accept certain values', function(done) {
var p, s;
p = new noflo.InPort({
values: 'noflo is awesome'.split(' ')
});
s = new noflo.internalSocket.InternalSocket;
p.attach(s);
p.on('data', function(data) {
chai.expect(data).to.equal('awesome');
return done();
});
return s.send('awesome');
});
return it('should throw an error if value is not accepted', function() {
var p, s;
p = new noflo.InPort({
values: 'noflo is awesome'.split(' ')
});
s = new noflo.internalSocket.InternalSocket;
p.attach(s);
p.on('data', function() {
return chai.expect(true).to.be.equal(false);
});
return chai.expect(function() {
return s.send('terrific');
}).to["throw"];
});
});
describe('with processing shorthand', function() {
it('should create a port with a callback', function() {
var ps, s;
s = new noflo.internalSocket.InternalSocket;
ps = {
outPorts: new noflo.OutPorts({
out: new noflo.OutPort
}),
inPorts: new noflo.InPorts
};
ps.inPorts.add('in', function(event, payload) {
if (event !== 'data') {
return;
}
return chai.expect(payload).to.equal('some-data');
});
chai.assert(ps.inPorts["in"] instanceof noflo.InPort);
ps.inPorts["in"].attach(s);
return s.send('some-data');
});
return it('should also accept metadata (i.e. options) when provided', function(done) {
var expectedEvents, ps, s;
s = new noflo.internalSocket.InternalSocket;
expectedEvents = ['connect', 'data', 'disconnect'];
ps = {
outPorts: new noflo.OutPorts({
out: new noflo.OutPort
}),
inPorts: new noflo.InPorts
};
ps.inPorts.add('in', {
datatype: 'string',
required: true
}, function(event, payload) {
chai.expect(event).to.equal(expectedEvents.shift());
if (event !== 'data') {
return;
}
chai.expect(payload).to.equal('some-data');
return done();
});
ps.inPorts["in"].attach(s);
chai.expect(ps.inPorts["in"].listAttached()).to.eql([0]);
s.send('some-data');
return s.disconnect();
});
});
return describe('with IP handle callback option', function() {
it('should pass IP objects to handler', function(done) {
var ps, s;
s = new noflo.internalSocket.InternalSocket;
ps = {
outPorts: new noflo.OutPorts({
out: new noflo.OutPort
}),
inPorts: new noflo.InPorts
};
ps.inPorts.add('in', {
datatype: 'string',
required: true,
handle: function(ip) {
chai.expect(ip).to.be.an('object');
if (ip.type !== 'data') {
return;
}
chai.expect(ip.data).to.equal('some-data');
return done();
}
});
ps.inPorts["in"].attach(s);
chai.expect(ps.inPorts["in"].listAttached()).to.eql([0]);
return s.send(new noflo.IP('data', 'some-data'));
});
it('should translate legacy events to IP objects', function(done) {
var expectedEvents, ps, s;
s = new noflo.internalSocket.InternalSocket;
expectedEvents = ['openBracket', 'data', 'closeBracket'];
ps = {
outPorts: new noflo.OutPorts({
out: new noflo.OutPort
}),
inPorts: new noflo.InPorts
};
ps.inPorts.add('in', {
datatype: 'string',
required: true,
handle: function(ip) {
chai.expect(ip).to.be.an('object');
chai.expect(ip.type).to.equal(expectedEvents.shift());
if (ip.type === 'data') {
chai.expect(ip.data).to.equal('some-data');
}
if (ip.type === 'closeBracket') {
return done();
}
}
});
ps.inPorts["in"].attach(s);
chai.expect(ps.inPorts["in"].listAttached()).to.eql([0]);
s.beginGroup('foo');
s.send('some-data');
s.endGroup();
return s.disconnect();
});
return it('should translate IP objects to legacy events', function(done) {
var expectedEvents, ps, s;
s = new noflo.internalSocket.InternalSocket;
expectedEvents = ['connect', 'data', 'disconnect'];
ps = {
outPorts: new noflo.OutPorts({
out: new noflo.OutPort
}),
inPorts: new noflo.InPorts
};
ps.inPorts.add('in', {
datatype: 'string',
required: true
}, function(event, payload) {
chai.expect(event).to.equal(expectedEvents.shift());
if (event !== 'data') {
return;
}
chai.expect(payload).to.equal('some-data');
return done();
});
ps.inPorts["in"].attach(s);
chai.expect(ps.inPorts["in"].listAttached()).to.eql([0]);
return s.post(new noflo.IP('data', 'some-data'));
});
});
});