genji
Version:
Writing reusable, modular and flexible node.js applications made easy.
294 lines (262 loc) • 8.13 kB
JavaScript
var genji = require('../index');
var Chain = genji.Chain;
var chain = genji.chain;
var promise = genji.promise;
var defer = genji.defer;
var parallel = genji.parallel;
var fs = require('fs');
var assert = require('assert');
var EventEmitter = require('events').EventEmitter;
describe('Control', function () {
describe('.chain', function () {
it('should executing the same function against different array members', function () {
var res = 0;
var c1 = chain([1, 2, 3], function (item, idx, arr, next, args) {
res += item;
next();
});
c1();
assert.equal(res, 6);
});
it('should call function for specified times in serial', function () {
var count = 0;
var c4 = chain(6, function (item, idx, arr, next) {
assert.equal(item, undefined);
assert.equal(arr, 6);
count++;
next();
});
c4();
assert.equal(count, 6);
try {
chain({}, function () {
});
} catch (e) {
assert.ok(e);
}
});
});
describe('.Chain', function () {
it('should add functions in chain and call with order of FIFC', function () {
var c2 = new Chain, res = 0, order = [];
c2.add('fc', function (n, next) {
res += n;
order.push(0);
next(res);
});
c2.add('fc', function (n) {
res += n;
order.push(1);
return res; // == this.next(1);
});
c2.add('fc', function (n, next) {
res += n;
order.push(2);
next(res);
});
c2.get('fc')(1);
assert.equal(res, 3);
assert.deepEqual(order, [0, 1, 2]);
});
it('should return undefined if chain name not exists', function () {
var c3 = new Chain();
assert.equal(c3.get('aa'), undefined); // should not be called
});
});
describe('.parallel', function () {
it('should iterate items and call done after finish the iteration', function (_done) {
var array = [2, 3, 4];
var finishedOrder = [];
function each(item, idx, arr, callback) {
setTimeout(function () {
assert.equal(array, arr);
finishedOrder.push(idx);
callback(null, idx);
}, (1 / item) * 100);
}
function done(result) {
assert.deepEqual([2, 1, 0], finishedOrder);
// order is reserved for result
assert.deepEqual([0, 1, 2], result);
}
parallel(array, each, done);
var finishedOrder2 = [];
function each2(item, idx, arr, callback) {
setTimeout(function () {
assert.deepEqual(array, arr);
finishedOrder2.push(idx);
callback(null, idx * 10);
}, (1 / item) * 100);
}
parallel(array, each2).done(function (result) {
assert.deepEqual([2, 1, 0], finishedOrder2);
assert.deepEqual([0, 10, 20], result);
});
var finishedOrder3 = [];
function each3(item, idx, arr, callback) {
setTimeout(function () {
assert.deepEqual(array, arr);
finishedOrder3.push(idx);
if (item === 3) {
callback('error');
} else {
callback(null, idx * 10);
}
}, (1 / item) * 100);
}
parallel(array, each3).done(
function (result) {
assert.deepEqual([2, 1, 0], finishedOrder3);
assert.equal(undefined, result[1]);
}).fail(function (err, item, idx) {
assert.equal('error', err);
assert.equal(item, 3);
assert.equal(idx, 1);
});
parallel([1, 2, 3, 4], function (item, idx, arr, callback) {
if (item !== 3) {
callback(null, item * 10);
}
})
.done(function (result) {
// this should never be called
assert.equal(false, true);
})
.timeout(function (result) {
assert.equal(-1, result.indexOf(30));
}, 1);
setTimeout(_done, 1800);
});
});
describe('promise', function () {
it('should convert async function to promise form with identical functionality', function () {
var readFile = promise(fs.readFile);
fs.readFile(__filename, function (err, data1) {
if (err) throw err;
readFile(__filename).when(function (err, data2) {
if (err) throw err;
assert.deepEqual(data1, data2);
});
});
});
});
describe('defer', function () {
it('should create defer form of the async function', function (done) {
var emitter = new EventEmitter;
var readFile = defer(fs.readFile, fs, emitter), finished = 0;
var otherFn = defer(function (delay, callback) {
setTimeout(function () {
callback(null, 'fromOtherFn');
}, delay);
});
fs.readFile(__filename, function (err, data1) {
if (err) throw err;
emitter.on('done', function () {
assert.equal(finished, 1);
finished = 2;
});
readFile(__filename)
.then(function (data2) {
assert.deepEqual(data1, data2);
})
.then(function (data2) {
assert.deepEqual(data1, data2);
})
.and(function (defer, data2) {
assert.deepEqual(data1, data2);
defer.next(10);
})
.and(function (defer, data3) {
assert.equal(data3, 10);
return true;
})
.and(function (defer, data4) {
otherFn(100).then(function (d) {
assert.equal(data4, 10);
}).defer(defer);
})
.and(function (defer, data5) {
otherFn(100).and(function (d, d5) {
assert.equal(d5, 'fromOtherFn');
assert.equal(data5, 'fromOtherFn');
d.next(30);
}).callback(function (err, data6) {
assert.equal(data6, 30);
finished = 1;
err ? defer.error(err) : defer.next(data6);
});
})
.done(function () {
// done is called after second `and` and after the `done` event
assert.equal(finished, 2);
done();
});
emitter.on('fail', function (err) {
assert.equal('ENOENT', err.code);
});
readFile(__filename + '1').fail(function (err) {
assert.equal('ENOENT', err.code);
});
});
});
it('should call deferred callback in order for `and`, `then` callbacks', function (done) {
function asyncFn(x, callback) {
setTimeout(function () {
callback(null, x + 1);
}, 1000);
}
var fn = defer(asyncFn);
var then1 = 0;
var then2 = 0;
fn(10)
.and(function (defer, result) {
assert.equal(11, result);
defer.next(result + 1);
})
.and(function (defer, result) {
assert.equal(12, result);
defer.next(result + 2);
})
.and(function (defer, result) {
assert.equal(14, result);
defer.next(14);
})
.then(function (result) {
then1 = result * 2;
})
.then(function (result) {
assert.equal(14, result);
then2 = then1 * 2;
})
.and(function () {
assert.equal(28, then1);
assert.equal(56, then2);
done();
});
});
it('should be able to register many callbacks at once', function (done) {
function asyncFn(x, callback) {
setTimeout(function () {
callback(null, x + 1);
}, 1000);
}
var fn = defer(asyncFn);
function fn1(defer, result) {
assert.equal(11, result);
defer.next(result + 1);
}
function fn2(defer, result) {
assert.equal(12, result);
defer.next(result + 2);
}
function fn3(result) {
assert.equal(14, result);
}
function fn4(result) {
assert.equal(14, result);
done();
}
fn(10).and(fn1, fn2).then(fn3, fn4);
});
});
});