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