UNPKG

noflo

Version:

Flow-Based Programming environment for JavaScript

293 lines (280 loc) 9.15 kB
describe('Outport Port', () => { describe('with addressable ports', () => { let s1 = null; let s2 = null; let s3 = null; beforeEach(() => { s1 = new noflo.internalSocket.InternalSocket(); s2 = new noflo.internalSocket.InternalSocket(); s3 = new noflo.internalSocket.InternalSocket(); }); it('should be able to send to a specific port', () => { const p = new noflo.OutPort({ addressable: true }); p.attach(s1); p.attach(s2); p.attach(s3); chai.expect(p.listAttached()).to.eql([0, 1, 2]); s1.on('data', () => { chai.expect(true).to.equal(false); }); s2.on('data', (data) => { chai.expect(data).to.equal('some-data'); }); s3.on('data', () => { chai.expect(true).to.equal(false); }); p.send('some-data', 1); }); it('should be able to send to index 0', (done) => { const p = new noflo.OutPort({ addressable: true }); p.attach(s1); s1.on('data', (data) => { chai.expect(data).to.equal('my-data'); done(); }); p.send('my-data', 0); }); it('should throw an error when sent data without address', () => { chai.expect(() => p.send('some-data')).to.throw; }); it('should throw an error when a specific port is requested with non-addressable port', () => { const p = new noflo.OutPort(); p.attach(s1); p.attach(s2); p.attach(s3); chai.expect(() => p.send('some-data', 1)).to.throw; }); it('should give correct port index when detaching a connection', (done) => { const p = new noflo.OutPort({ addressable: true }); p.attach(s1, 3); p.attach(s2, 1); p.attach(s3, 5); const expectedSockets = [s2, s3]; const expected = [1, 5]; const expectedAttached = [ [3, 5], [3], ]; p.on('detach', (socket, index) => { chai.expect(socket).to.equal(expectedSockets.shift()); chai.expect(index).to.equal(expected.shift()); chai.expect(p.isAttached(index)).to.equal(false); const atts = expectedAttached.shift(); chai.expect(p.listAttached()).to.eql(atts); for (const att of atts) { chai.expect(p.isAttached(att)).to.equal(true); } if (!expected.length) { done(); } }); p.detach(s2); p.detach(s3); }); }); describe('with caching ports', () => { let s1 = null; let s2 = null; let s3 = null; beforeEach(() => { s1 = new noflo.internalSocket.InternalSocket(); s2 = new noflo.internalSocket.InternalSocket(); s3 = new noflo.internalSocket.InternalSocket(); }); it('should repeat the previously sent value on attach event', (done) => { const p = new noflo.OutPort({ caching: true }); s1.once('data', (data) => { chai.expect(data).to.equal('foo'); }); s2.once('data', (data) => { chai.expect(data).to.equal('foo'); // Next value should be different s2.once('data', (data) => { chai.expect(data).to.equal('bar'); done(); }); }); p.attach(s1); p.send('foo'); p.disconnect(); p.attach(s2); p.send('bar'); p.disconnect(); }); it('should support addressable ports', (done) => { const p = new noflo.OutPort({ addressable: true, caching: true, }); p.attach(s1); p.attach(s2); s1.on('data', () => { chai.expect(true).to.equal(false); }); s2.on('data', (data) => { chai.expect(data).to.equal('some-data'); }); s3.on('data', (data) => { chai.expect(data).to.equal('some-data'); done(); }); p.send('some-data', 1); p.disconnect(1); p.detach(s2); p.attach(s3, 1); }); }); describe('with IP objects', () => { let s1 = null; let s2 = null; let s3 = null; beforeEach(() => { s1 = new noflo.internalSocket.InternalSocket(); s2 = new noflo.internalSocket.InternalSocket(); s3 = new noflo.internalSocket.InternalSocket(); }); it('should send data IPs and substreams', (done) => { const p = new noflo.OutPort(); p.attach(s1); const expectedEvents = [ 'data', 'openBracket', 'data', 'closeBracket', ]; let count = 0; s1.on('ip', (data) => { count++; chai.expect(data).to.be.an('object'); chai.expect(data.type).to.equal(expectedEvents.shift()); if (data.type === 'data') { chai.expect(data.data).to.equal('my-data'); } if (count === 4) { done(); } }); p.data('my-data'); p.openBracket() .data('my-data') .closeBracket(); }); it('should send non-clonable objects by reference', (done) => { const p = new noflo.OutPort(); p.attach(s1); p.attach(s2); p.attach(s3); const obj = { foo: 123, bar: { boo: 'baz', }, func() { return this.foo = 456; }, }; s1.on('ip', (data) => { chai.expect(data).to.be.an('object'); chai.expect(data.data).to.equal(obj); chai.expect(data.data.func).to.be.a('function'); s2.on('ip', (data) => { chai.expect(data).to.be.an('object'); chai.expect(data.data).to.equal(obj); chai.expect(data.data.func).to.be.a('function'); s3.on('ip', (data) => { chai.expect(data).to.be.an('object'); chai.expect(data.data).to.equal(obj); chai.expect(data.data.func).to.be.a('function'); done(); }); }); }); p.data(obj, { clonable: false }); // default }); it('should clone clonable objects on fan-out', (done) => { const p = new noflo.OutPort(); p.attach(s1); p.attach(s2); p.attach(s3); const obj = { foo: 123, bar: { boo: 'baz', }, func() { this.foo = 456; }, }; s1.on('ip', (data) => { chai.expect(data).to.be.an('object'); // First send is non-cloning chai.expect(data.data).to.equal(obj); chai.expect(data.data.func).to.be.a('function'); s2.on('ip', (data) => { chai.expect(data).to.be.an('object'); chai.expect(data.data).to.not.equal(obj); chai.expect(data.data.foo).to.equal(obj.foo); chai.expect(data.data.bar).to.eql(obj.bar); chai.expect(data.data.func).to.be.undefined; s3.on('ip', (data) => { chai.expect(data).to.be.an('object'); chai.expect(data.data).to.not.equal(obj); chai.expect(data.data.foo).to.equal(obj.foo); chai.expect(data.data.bar).to.eql(obj.bar); chai.expect(data.data.func).to.be.undefined; done(); }); }); }); p.data(obj, { clonable: true }); }); it('should stamp an IP object with the port\'s datatype', (done) => { const p = new noflo.OutPort({ datatype: 'string' }); p.attach(s1); s1.on('ip', (data) => { chai.expect(data).to.be.an('object'); chai.expect(data.type).to.equal('data'); chai.expect(data.data).to.equal('Hello'); chai.expect(data.datatype).to.equal('string'); done(); }); p.data('Hello'); }); it('should keep an IP object\'s datatype as-is if already set', (done) => { const p = new noflo.OutPort({ datatype: 'string' }); p.attach(s1); s1.on('ip', (data) => { chai.expect(data).to.be.an('object'); chai.expect(data.type).to.equal('data'); chai.expect(data.data).to.equal(123); chai.expect(data.datatype).to.equal('integer'); done(); }); p.sendIP(new noflo.IP('data', 123, { datatype: 'integer' })); }); it('should stamp an IP object with the port\'s schema', (done) => { const p = new noflo.OutPort({ datatype: 'string', schema: 'text/markdown', }); p.attach(s1); s1.on('ip', (data) => { chai.expect(data).to.be.an('object'); chai.expect(data.type).to.equal('data'); chai.expect(data.data).to.equal('Hello'); chai.expect(data.datatype).to.equal('string'); chai.expect(data.schema).to.equal('text/markdown'); done(); }); p.data('Hello'); }); it('should keep an IP object\'s schema as-is if already set', (done) => { const p = new noflo.OutPort({ datatype: 'string', schema: 'text/markdown', }); p.attach(s1); s1.on('ip', (data) => { chai.expect(data).to.be.an('object'); chai.expect(data.type).to.equal('data'); chai.expect(data.data).to.equal('Hello'); chai.expect(data.datatype).to.equal('string'); chai.expect(data.schema).to.equal('text/plain'); done(); }); p.sendIP(new noflo.IP('data', 'Hello', { datatype: 'string', schema: 'text/plain', })); }); }); });