import chai = require('chai'); import Promise = require('bluebird'); import async = require('../src/async/index'); import await = require('../src/await/index'); var expect = chai.expect; describe('async.iterable(...)', () => { var foo = async.iterable ((yield_, count: number, accum?: any[]) => { if (count < 1 || count > 9) throw new Error('out of range'); for (var i = 1; i <= count; ++i) { if (accum) accum.push(111 * i); yield_ (111 * i); } return 'done'; }); describe('returns a function', () => { it('which returns an async iterator with next() and forEach() methods', () => { var syncResult = foo(); expect(syncResult).is.an('object'); expect(syncResult.next).is.a('function'); expect(syncResult.forEach).is.a('function'); }); }); describe('provides an iterator whose next() method', () => { it('synchronously returns a promise', () => { var iter = foo(3); expect(iter.next()).instanceOf(Promise); }); it('begins executing synchronously and completes asynchronously', done => { var arr = [], iter = foo(3, arr); (> iter.next()) .then(() => expect(arr).to.deep.equal([111, '***'])) .then(() => done()) .catch(done); expect(arr).to.deep.equal([111]); arr.push('***'); }); it("preserves the 'this' context of the call", async.cps (() => { var foo = { bar: async.iterable (function (yield_) { yield_ (this); return 'done'; }) }, baz = {x:7}; var iter = foo.bar(); expect(await (iter.next())).to.deep.equal({ done: false, value: foo }); expect(await (iter.next())).to.deep.equal({ done: true }); iter = foo.bar.call(baz); expect(await (iter.next())).to.deep.equal({ done: false, value: baz }); expect(await (iter.next())).to.deep.equal({ done: true }); })); it('eventually resolves with the definition\'s yielded value', async.cps (() => { var iter = foo(3); expect(await (iter.next())).to.deep.equal({ done: false, value: 111 }); expect(await (iter.next())).to.deep.equal({ done: false, value: 222 }); expect(await (iter.next())).to.deep.equal({ done: false, value: 333 }); expect(await (iter.next())).to.deep.equal({ done: true }); })); it('eventually rejects with the definition\'s thrown value', async.cps (() => { var err, iter = foo(20); expect(() => await (iter.next())).to.throw(Error, 'out of range'); })); it('eventually rejects if the iteration is already finished', async.cps(() => { var err, iter = foo(1); expect(await (iter.next())).to.deep.equal({ done: false, value: 111 }); expect(await (iter.next())).to.deep.equal({ done: true }); expect(() => await (iter.next())).to.throw(Error); })); it('works with await', done => { var foo = async.iterable ((yield_) => { yield_ (await (Promise.delay(20).then(() => 'blah'))); }); foo().next() .then(result => expect(result).to.deep.equal({ done:false, value:'blah' })) .then(() => done()) .catch(done); }); }); describe('provides an iterator whose forEach() method', () => { function nullFunc() { } //it('expects a single callback as its argument', () => { // expect(() => ( foo(3)).forEach()).to.throw(Error); // expect(() => ( foo(3)).forEach(1)).to.throw(Error); // expect(() => ( foo(3)).forEach(1, nullFunc)).to.throw(Error); //}); it('synchronously returns a promise', () => { var iter = foo(3); expect(iter.forEach(nullFunc)).instanceOf(Promise); }); it('begins executing synchronously and completes asynchronously', done => { var arr = [], iter = foo(3, arr); (> iter.forEach(nullFunc)) .then(() => expect(arr).to.deep.equal([111, '***', 222, 333])) .then(() => done()) .catch(done); expect(arr).to.deep.equal([111]); arr.push('***'); }); it('iterates over all yielded values', async.cps(() => { var arr = [], iter = foo(4); await (iter.forEach(val => arr.push(val))); expect(arr).to.deep.equal([111, 222, 333, 444]); })); //it('eventually resolves with the definition\'s returned value', async.cps(() => { // var arr = [], iter = foo(7, arr); // var result = await (iter.forEach(nullFunc)); // expect(result).to.equal('done'); // expect(arr.length).to.equal(7); //})); it('eventually rejects with the definition\'s thrown value', async.cps(() => { var err, iter = foo(20); expect(() => await (iter.forEach(nullFunc))).to.throw(Error, 'out of range'); })); it('eventually rejects if the iteration is already finished', async.cps(() => { var err, iter = foo(1); await (iter.forEach(nullFunc)); expect (() => await (iter.forEach(nullFunc))).to.throw(Error); })); it('works with await', done => { var foo = async.iterable ((yield_) => { yield_ (await (Promise.delay(20).then(() => 'blah'))); }), arr = []; foo().forEach(val => arr.push(val)) .then(result => expect(result).to.not.exist) .then(() => expect(arr).to.deep.equal(['blah'])) .then(() => done()) .catch(done); }); }); });