UNPKG

pipe-iterators

Version:

Like underscore for Node streams. Map, reduce, filter, fork, pipeline and other utility functions for iterating over object mode streams.

280 lines (251 loc) 7.33 kB
var assert = require('assert'), pi = require('../index.js'), isReadable = require('../lib/is-stream').isReadable, isWritable = require('../lib/is-stream').isWritable, isDuplex = require('../lib/is-stream').isDuplex; describe('forEach', function() { var stream, calls, contexts; beforeEach(function() { calls = []; contexts = []; stream = pi.fromArray(['a', 'b', 'c']); }); it('iterates over every element with expected arguments', function(done) { stream.pipe(pi.forEach(function(obj, index) { contexts.push(this); calls.push([ obj, index]); })) .pipe(pi.toArray(function(results) { assert.deepEqual(calls, [ [ 'a', 0 ], [ 'b', 1 ], [ 'c', 2 ] ]); assert.deepEqual(results, [ 'a', 'b', 'c' ]); done(); })); }); it('uses the provided thisArg', function(done) { var context = { foo: 'bar' }; stream.pipe(pi.forEach(function(obj, index) { contexts.push(this); calls.push([ obj, index]); }, context)) .pipe(pi.toArray(function(results) { assert.ok(contexts.every(function(item) { return item === context; })); assert.deepEqual(calls, [ [ 'a', 0 ], [ 'b', 1 ], [ 'c', 2 ] ]); assert.deepEqual(results, [ 'a', 'b', 'c' ]); done(); })); }); }); describe('map', function() { var stream, calls, contexts; beforeEach(function() { calls = []; contexts = []; stream = pi.fromArray(['a', 'b', 'c']); }); it('should apply a mapper', function(done) { stream.pipe(pi.map(function(obj, index) { contexts.push(this); calls.push([ obj, index]); return obj.toString().toUpperCase(); })) .pipe(pi.toArray(function(results) { assert.deepEqual(calls, [ [ 'a', 0 ], [ 'b', 1 ], [ 'c', 2 ] ]); assert.deepEqual(results, [ 'A', 'B', 'C' ]); done(); })); }); it('uses the provided thisArg', function(done) { var context = { foo: 'bar' }; stream.pipe(pi.map(function(obj, index) { contexts.push(this); calls.push([ obj, index]); return obj.toString().toUpperCase(); }, context)) .pipe(pi.toArray(function(results) { assert.ok(contexts.every(function(item) { return item === context; })); assert.deepEqual(calls, [ [ 'a', 0 ], [ 'b', 1 ], [ 'c', 2 ] ]); assert.deepEqual(results, [ 'A', 'B', 'C' ]); done(); })); }); }); describe('reduce', function() { var stream, calls; beforeEach(function() { calls = []; stream = pi.fromArray([1, 2, 3]); }); it('accumulates results', function(done) { stream.pipe(pi.reduce(function(prev, curr, index) { calls.push([ prev, curr, index ]); return prev + curr; }, 4)) .pipe(pi.toArray(function(results) { assert.deepEqual(calls, [ [ 4, 1, 0 ], [ 5, 2, 1 ], [ 7, 3, 2 ] ]); assert.deepEqual(results, [ 10 ]); done(); })); }); // If the stream has only one element and no `initialValue` was provided, // or if `initialValue` is provided but the stream is empty, the solo // value would be returned without calling callback. it('works when initial is not set', function(done) { stream.pipe(pi.reduce(function(prev, curr, index) { calls.push([ prev, curr, index]); return prev + curr; })) .pipe(pi.toArray(function(results) { assert.deepEqual(calls, [ [ 1, 2, 1 ], [ 3, 3, 2 ] ]); assert.deepEqual(results, [ 6 ]); done(); })); }); }); describe('filter', function() { var stream, calls, contexts; beforeEach(function() { calls = []; contexts = []; stream = pi.fromArray([1, 2, 3]); }); it('filters out non-matching values', function(done) { stream.pipe(pi.filter(function(obj, index) { contexts.push(this); calls.push([ obj, index]); return obj % 2 == 0; })) .pipe(pi.toArray(function(results) { assert.deepEqual(calls, [ [ 1, 0 ], [ 2, 1 ], [ 3, 2 ] ]); assert.deepEqual(results, [ 2 ]); done(); })); }); it('uses the provided thisArg', function(done) { var context = { foo: 'bar' }; stream.pipe(pi.filter(function(obj, index) { contexts.push(this); calls.push([ obj, index]); return obj % 2 == 0; }, context)) .pipe(pi.toArray(function(results) { assert.ok(contexts.every(function(item) { return item === context; })); assert.deepEqual(calls, [ [ 1, 0 ], [ 2, 1 ], [ 3, 2 ] ]); assert.deepEqual(results, [ 2 ]); done(); })); }); }); describe('mapKey', function() { var stream, calls, contexts, context = { foo: 'bar' }; beforeEach(function() { calls = []; contexts = []; stream = pi.fromArray([ { a: 'aBc', b: 'dEf' }, { a: 'gHi', b: 'jKl' }, {} ]); }); it('maps with a string and a function', function(done) { var objs = []; stream.pipe(pi.mapKey('a', function(value, obj, index) { contexts.push(this); objs.push(obj); calls.push([ value, index]); return ('' + value).toUpperCase(); }, context)) .pipe(pi.toArray(function(results) { assert.ok(contexts.every(function(item) { return item === context; })); assert.ok(objs.every(function(item, index) { return item === results[index]; })); assert.deepEqual(calls, [ [ 'aBc', 0 ], [ 'gHi', 1 ], [ undefined, 2 ] ]); assert.deepEqual(results, [ { a: 'ABC', b: 'dEf' }, { a: 'GHI', b: 'jKl' }, { a: 'UNDEFINED' } ]); done(); })); }); it('maps with a hash of functions and non-functions', function(done) { var objs = []; stream.pipe(pi.mapKey({ a: function(value, obj, index) { contexts.push(this); objs.push(obj); calls.push([ value, index]); return ('' + value).toUpperCase(); }, // bool, str, obj, arr, null, undefined b: true, c: 'str', d: { foo: 'bar' }, e: [ 'a' ], f: null, e: undefined }, context)) .pipe(pi.toArray(function(results) { assert.ok(contexts.every(function(item) { return item === context; })); assert.ok(objs.every(function(item, index) { return item === results[index]; })); assert.deepEqual(calls, [ [ 'aBc', 0 ], [ 'gHi', 1 ], [ undefined, 2 ] ]); assert.deepEqual(results, [ { a: 'ABC', b: true, c: 'str', d: { foo: 'bar' }, e: [ 'a' ], f: null, e: undefined }, { a: 'GHI', b: true, c: 'str', d: { foo: 'bar' }, e: [ 'a' ], f: null, e: undefined }, { a: 'UNDEFINED', b: true, c: 'str', d: { foo: 'bar' }, e: [ 'a' ], f: null, e: undefined } ]); done(); })); }); });