polyflow
Version:
A flow-based programming framework
485 lines (385 loc) • 13.6 kB
JavaScript
;
var path = require('path');
describe('PolyFlow', function () {
var polyflow = require('../../src/polyflow');
polyflow.nano('nano', {
outputs: {
'out': []
}
}, function ($outputs) {
$outputs.out();
});
polyflow.nano('nano.io', {
inputs: ['in1'],
outputs: {
out: ['out1'],
out2: ['out2']
}
}, function ($inputs, $outputs) {
if ($inputs.in1 === true) {
$outputs.out(true);
} else {
$outputs.out2(false);
}
});
describe('basic functionalities', function () {
it('should allow to create/retreive nano and graph', function () {
polyflow.nano('nano1', function () {});
polyflow.graph('graph1');
expect(polyflow.getComponent('nano1')).toBeDefined();
expect(polyflow.getComponent('graph1')).toBeDefined();
expect(function () {
polyflow.getComponent('__nano1');
}).toThrow();
expect(function () {
polyflow.getComponent('__graph1');
}).toThrow();
});
});
describe('dependency injection system', function () {
polyflow.service('service1', function () {
return {
run: function (arg) {
return arg;
}
};
});
polyflow.service('service2', function (service1) {
return {
run: function (arg) {
return service1.run(arg);
}
};
});
polyflow.service('service3', function (service2) {
return {
run: function (arg) {
return service2.run(arg);
}
};
});
polyflow.service('service4', function (service1, service2, service3) {
return {
run: function (arg) {
return service1.run(arg) && service2.run(arg) && service3.run(arg);
}
};
});
polyflow.service('badService', function (service1, service2, service3, unexistingService) {
return null;
});
polyflow.service('badService2', function (service1, badService) {
return null;
});
it('should allow to create/retreive services', function () {
expect(polyflow.$injector.getService('service1')).toBeDefined();
expect(polyflow.$injector.getService('service1').run(true)).toBe(true);
expect(function () {
polyflow.$injector.getService('__service1');
}).toThrow();
});
it('should inject services in service', function () {
var service3 = polyflow.$injector.getService('service3');
var service4 = polyflow.$injector.getService('service4');
expect(service3.run(true)).toBe(true);
expect(service4.run(true)).toBe(true);
});
it('should throw when trying to inject unexisting service', function () {
expect(function () {
polyflow.getService('badService');
}).toThrow();
expect(function () {
polyflow.getService('badService2');
}).toThrow();
});
it('should inject services and special services in nano', function (done) {
var s1 = polyflow.$injector.getService('service1');
var s2 = polyflow.$injector.getService('service2');
var s3 = polyflow.$injector.getService('service3');
polyflow.nano('nano.injects', {
inputs: ['in1'],
outputs: {
out: ['out'],
}
}, function (service1, $inputs, service2, $outputs, service3, $flow) {
expect(service1).toBe(s1);
expect(service2).toBe(s2);
expect(service3).toBe(s3);
expect($flow instanceof polyflow.Flow).toBe(true);
expect($inputs.in1).toBeDefined();
expect($outputs.out).toBeDefined();
done();
});
var graph = polyflow.graph('graph');
graph.begin()
.then('nano.injects');
var network = graph.compile();
network.digest({
in1: true
});
});
it('should load services in folder', function () {
polyflow.loadServices(path.join(__dirname, '../fixtures/services/'));
expect(polyflow.getService('folderService1')).toBeDefined();
expect(polyflow.getService('folderService2')).toBeDefined();
});
});
describe('binder', function () {
var Binder = require('../../src/Binder.js');
/* TODO */
});
describe('graph', function () {
it('should be chainable using then', function (done) {
var graph = polyflow.graph('graph');
graph.begin()
.then('nano')
.then('nano')
.then(function () {
done();
});
var network = graph.compile();
network.digest();
});
it('should has a select methode', function () {
var graph = polyflow.graph('graph');
var a = false,
b = false,
c = false;
graph.addNode('nano', 'C')
.then(function () {
expect(a).toBe(true);
expect(b).toBe(true);
c = true;
});
graph.begin()
.then('nano')
.then('nano', 'A')
.then('nano', 'B')
.then('C');
graph.select('A')
.then(function () {
a = true;
expect(b).toBe(false);
expect(c).toBe(false);
});
graph.select('B')
.then(function () {
expect(a).toBe(true);
b = true;
expect(c).toBe(false);
});
var network = graph.compile();
runs(function () {
network.digest();
});
waitsFor(function () {
return a && b && c;
}, 'all branches to finilize', 200);
});
it('should has an on methode to select an ouput', function () {
var graph = polyflow.graph('graph');
var a = false,
b = false;
graph.begin()
.then('nano')
.then('nano.io', 'A');
graph.select('A')
.then(function () {
a = true;
});
graph.select('A').on('out2')
.then(function () {
b = true;
});
var network = graph.compile();
runs(function () {
network.digest({
in1: true
});
});
waitsFor(function () {
return a;
}, 'digest 1 to finalize', 200);
runs(function () {
expect(a).toBe(true);
expect(b).toBe(false);
a = false;
b = false;
});
runs(function () {
network.digest({
in1: false
});
});
waitsFor(function () {
return b;
}, 'digest 2 to finalize', 200);
runs(function () {
expect(a).toBe(false);
expect(b).toBe(true);
});
});
it('should be connectable', function () {
var a = false,
b = false,
graph1 = polyflow.graph('graph1'),
graph2 = polyflow.graph('graph2');
graph1.begin()
.then('nano.io', 'io')
.output('out');
graph1.select('io').on('out2')
.output('out2');
graph2.begin()
.then('graph1', 'g1')
.then(function () {
a = true;
});
graph2.select('g1').on('out2')
.then(function () {
b = true;
});
var network = graph2.compile();
runs(function () {
network.digest({
in1: true
});
network.digest({
in1: false
});
});
waitsFor(function () {
return a && b;
}, 'all branches to finilize', 200);
});
it('should allow to bind inputs/outputs', function () {
var a = false,
b = false,
graph = polyflow.graph('graph');
graph.begin()
.then('nano.io', 'io')
.then(function ($flow) {
expect($flow.out11).toBe(true);
a = true;
});
graph.select('io').on('out2')
.then(function ($flow) {
expect($flow.out22).toBe(false);
b = true;
});
graph.select('io')
.bind.input('in1').to('in11')
.bind.output('out', 'out1').to('out11')
.bind.output('out2', 'out2').to('out22');
var network = graph.compile();
runs(function () {
network.digest({
in11: true
});
network.digest({
in11: false
});
});
waitsFor(function () {
return a && b;
}, 'all branches to finilize', 200);
});
it('should allow to ignore an output', function (done) {
var graph = polyflow.graph('graph');
graph.begin()
.then('nano.io', 'io')
.bind.output('out', 'out1').to(null)
.then(function ($flow) {
expect($flow.out1).toBeUndefined();
done();
});
var network = graph.compile();
network.digest({
in1: true
});
});
});
describe('flow', function () {
it('should die when the number of instances is 0', function (done) {
var graph = polyflow.graph('graph');
var a = false,
b = false;
graph.begin()
.then('nano', 'A')
.then('nano')
.then(function () {
a = true;
});
graph.select('A')
.then('nano')
.then(function () {
b = true;
});
var flow = new polyflow.Flow();
flow.$on('die', function () {
expect(a).toBe(true);
expect(b).toBe(true);
done();
});
var network = graph.compile();
network.digest(flow);
});
it('should die only if all subflows are died', function () {
var flow = new polyflow.Flow();
flow.$increase();
var subflow = flow.$createSubflow();
subflow.$increase();
flow.$decrease();
expect(flow.$died).toBe(false);
subflow.$decrease();
expect(subflow.$died).toBe(true);
expect(flow.$died).toBe(true);
});
it('should manage data inheritance', function () {
var flow = new polyflow.Flow();
var subflow = flow.$createSubflow();
var a = {},
b = {},
bb = {};
flow.a = a;
flow.b = b;
subflow.b = bb;
expect(flow.$get('a')).toBe(a);
expect(flow.$get('b')).toBe(b);
expect(subflow.$get('a')).toBe(a);
expect(subflow.$get('b')).toBe(bb);
});
});
describe('network', function () {
it('should managed inputs/outputs parameters', function (done) {
var graph = polyflow.graph('graph');
polyflow.nano('nano1', {
inputs: ['in1', 'in2'],
outputs: {
out: ['out1', 'out2']
}
}, function ($inputs, $outputs) {
expect($inputs.in1).toBe('in1');
expect($inputs.in2).toBe('in2');
expect($inputs.in3).toBeUndefined();
$outputs.out('out1', 'out2');
});
graph.begin()
.then('nano')
.then('nano1')
.then(function ($flow) {
expect($flow.in1).toBe('in1');
expect($flow.in2).toBe('in2');
expect($flow.in3).toBe('in3');
expect($flow.out1).toBe('out1');
expect($flow.out2).toBe('out2');
done();
});
var network = graph.compile();
network.digest({
in1: 'in1',
in2: 'in2',
in3: 'in3'
});
});
});
});