UNPKG

iterates

Version:

Iterator and AsyncIterator helper functions with typings

778 lines (776 loc) 23.6 kB
import * as subject from './sync.js'; import { tuple } from './utils.js'; describe('sync', () => { describe('asArray', () => { it('should collect all values of an iterable in an array', () => { const array = subject.asArray(subject.range({ start: 1, end: 4 })); expect(array).toEqual([1, 2, 3]); }); it('should collect all values of an iterator in an array', () => { const array = subject.asArray([1, 2, 3][Symbol.iterator]()); expect(array).toEqual([1, 2, 3]); }); }); describe('range', () => { it('should count from start to end', () => { const iterator = subject.range({ start: 0, end: 3 })[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: 0 }); expect(iterator.next()).toEqual({ done: false, value: 1 }); expect(iterator.next()).toEqual({ done: false, value: 2 }); expect(iterator.next()).toEqual({ done: true, value: 3 }); }); it('should count from start to end with negative step value', () => { const iterator = subject.range({ start: 3, end: 0, step: -1 })[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: 3 }); expect(iterator.next()).toEqual({ done: false, value: 2 }); expect(iterator.next()).toEqual({ done: false, value: 1 }); expect(iterator.next()).toEqual({ done: true, value: 0 }); }); it('should stop on overshooting step values', () => { const positiveIterator = subject.range({ start: 0, end: 3, step: 2 })[Symbol.iterator](); const negativeIterator = subject.range({ start: 3, end: 0, step: -2 })[Symbol.iterator](); expect(positiveIterator.next()).toEqual({ done: false, value: 0 }); expect(positiveIterator.next()).toEqual({ done: false, value: 2 }); expect(positiveIterator.next()).toEqual({ done: true, value: 4 }); expect(negativeIterator.next()).toEqual({ done: false, value: 3 }); expect(negativeIterator.next()).toEqual({ done: false, value: 1 }); expect(negativeIterator.next()).toEqual({ done: true, value: -1 }); }); it('should support infinite ranges', () => { const iterator = subject.range({ start: 3 })[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: 3 }); expect(iterator.next()).toEqual({ done: false, value: 4 }); expect(iterator.next()).toEqual({ done: false, value: 5 }); expect(iterator.next()).toEqual({ done: false, value: 6 }); expect(iterator.next()).toEqual({ done: false, value: 7 }); expect(iterator.next()).toEqual({ done: false, value: 8 }); }); it('should emit no values if start === end', () => { const iterator = subject.range({ start: 0, end: 0 })[Symbol.iterator](); expect(iterator.next()).toEqual({ done: true, value: 0 }); }); }); describe('enumerate', () => { it('should add the index to each element', () => { const iterator = subject.enumerate(['one', 'two', 'three'])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: { index: 0, item: 'one' } }); expect(iterator.next()).toEqual({ done: false, value: { index: 1, item: 'two' } }); expect(iterator.next()).toEqual({ done: false, value: { index: 2, item: 'three' } }); expect(iterator.next()).toEqual({ done: true, value: undefined }); }); }); describe('map', () => { it('should apply the provided function over each item', () => { const iterator = subject.map(item => item.toUpperCase(), ['one', 'two', 'three'])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: 'ONE' }); expect(iterator.next()).toEqual({ done: false, value: 'TWO' }); expect(iterator.next()).toEqual({ done: false, value: 'THREE' }); expect(iterator.next()).toEqual({ done: true, value: undefined }); }); it('should be auto curried', () => { const iterator = subject.map(item => item.toUpperCase())(['one', 'two', 'three'])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: 'ONE' }); }); }); describe('filterMap', () => { it('should apply the provided function over each item and flatten it', () => { const iterator = subject.filterMap(item => item.length === 3 ? item.toUpperCase() : undefined, ['one', 'two', 'three'])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: 'ONE' }); expect(iterator.next()).toEqual({ done: false, value: 'TWO' }); expect(iterator.next()).toEqual({ done: true, value: undefined }); }); it('should be auto curried', () => { const iterator = subject.filterMap(item => item.length === 3 ? item.toUpperCase() : undefined)(['one', 'two', 'three'])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: 'ONE' }); }); }); describe('flatMap', () => { it('should apply the provided function over each item and flatten it', () => { const iterator = subject.flatMap(item => [item, item.toUpperCase()], ['one', 'two', 'three'])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: 'one' }); expect(iterator.next()).toEqual({ done: false, value: 'ONE' }); expect(iterator.next()).toEqual({ done: false, value: 'two' }); expect(iterator.next()).toEqual({ done: false, value: 'TWO' }); expect(iterator.next()).toEqual({ done: false, value: 'three' }); expect(iterator.next()).toEqual({ done: false, value: 'THREE' }); expect(iterator.next()).toEqual({ done: true, value: undefined }); }); it('should be auto curried', () => { const iterator = subject.flatMap(item => [item, item.toUpperCase()])(['one', 'two', 'three'])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: 'one' }); }); }); describe('flatten', () => { it('should apply flatten the items', () => { const iterator = subject.flatten([[1, 'one'], [2, 'two'], [3, 'three']])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: 1 }); expect(iterator.next()).toEqual({ done: false, value: 'one' }); expect(iterator.next()).toEqual({ done: false, value: 2 }); expect(iterator.next()).toEqual({ done: false, value: 'two' }); expect(iterator.next()).toEqual({ done: false, value: 3 }); expect(iterator.next()).toEqual({ done: false, value: 'three' }); expect(iterator.next()).toEqual({ done: true, value: undefined }); }); }); describe('filter', () => { it('should only pass through items that pass the test', () => { const iterator = subject.filter(item => item !== 'two', ['one', 'two', 'three'])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: 'one' }); expect(iterator.next()).toEqual({ done: false, value: 'three' }); expect(iterator.next()).toEqual({ done: true, value: undefined }); }); it('should be auto curried', () => { const iterator = subject.filter(item => item !== 'two')(['one', 'two', 'three'])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: 'one' }); }); }); describe('fold', () => { it('should return the accumulated value', () => { const item = subject.fold(0, (sum, item) => sum + item, [1, 2, 3]); expect(item).toEqual(6); }); it('should return the initial value if there are no items', () => { const item = subject.fold(0, (sum, item) => sum + item, []); expect(item).toEqual(0); }); it('should be auto curried', () => { const item = subject.fold(0, (sum, item) => sum + item)([1, 2, 3]); expect(item).toEqual(6); }); }); describe('scan', () => { it('should return the accumulated value', () => { const iterator = subject.scan(0, (sum, item) => sum + item, [1, 2, 3])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: 1 }); expect(iterator.next()).toEqual({ done: false, value: 3 }); expect(iterator.next()).toEqual({ done: false, value: 6 }); expect(iterator.next()).toEqual({ done: true, value: 6 }); }); it('should return the initial value if there are no items', () => { const iterator = subject.scan(0, (sum, item) => sum + item, [])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: true, value: 0 }); }); it('should be auto curried', () => { const iterator = subject.scan(0, (sum, item) => sum + item)([1, 2, 3]); expect(iterator.next()).toEqual({ done: false, value: 1 }); }); }); describe('collect', () => { it('should collect the values of the iterator in a map', () => { const map = subject.collect(item => [item, item ** 2], [1, 2, 3]); expect(map).toEqual(new Map([[1, 1], [2, 4], [3, 9]])); }); it('should overwrite duplicate keys', () => { const map = subject.collect(item => [item ** 2, item], [1, 2, 3, -2]); expect(map).toEqual(new Map([[1, 1], [4, -2], [9, 3]])); }); it('should support a custom merge function', () => { const map = subject.collect(item => [item ** 2, item], [1, 2, 3, -2], { merge: (a, b) => a + b }); expect(map).toEqual(new Map([[1, 1], [4, 0], [9, 3]])); }); it('should be auto curried', () => { const collectFn = item => tuple([item ** 2, item]); const values = [1, 2, 3, -2]; const options = { merge: (a, b) => a + b }; const result = new Map([[1, 1], [4, 0], [9, 3]]); const map1 = subject.collect(collectFn, values, options); expect(map1).toEqual(result); const map2 = subject.collect(collectFn)(values, options); expect(map2).toEqual(result); const map3 = subject.collect(collectFn, options)(values); expect(map3).toEqual(result); }); }); describe('collectRecord', () => { it('should collect the values of the iterator in a map', () => { const map = subject.collectRecord(item => [`${item}`, item ** 2], [1, 2, 3]); expect(map).toEqual({ 1: 1, 2: 4, 3: 9 }); }); it('should overwrite duplicate keys', () => { const map = subject.collectRecord(item => [`${item ** 2}`, item], [1, 2, 3, -2]); expect(map).toEqual({ 1: 1, 4: -2, 9: 3 }); }); it('should support a custom merge function', () => { const map = subject.collectRecord(item => [`${item ** 2}`, item], [1, 2, 3, -2], { merge: (a, b) => a + b }); expect(map).toEqual({ 1: 1, 4: 0, 9: 3 }); }); it('should be auto curried', () => { const collectFn = item => tuple([`${item ** 2}`, item]); const values = [1, 2, 3, -2]; const options = { merge: (a, b) => a + b }; const result = { 1: 1, 4: 0, 9: 3 }; const map1 = subject.collectRecord(collectFn, values, options); expect(map1).toEqual(result); const map2 = subject.collectRecord(collectFn)(values, options); expect(map2).toEqual(result); const map3 = subject.collectRecord(collectFn, options)(values); expect(map3).toEqual(result); }); }); describe('zip', () => { it('should zip two iterators', () => { const iterator = subject.zip([1, 2, 3], ['one', 'two', 'three'])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: [1, 'one'] }); expect(iterator.next()).toEqual({ done: false, value: [2, 'two'] }); expect(iterator.next()).toEqual({ done: false, value: [3, 'three'] }); expect(iterator.next()).toEqual({ done: true, value: undefined }); }); it('should return the continuing iterator', () => { const longA = [1, 2, 3, 4]; const longB = ['one', 'two', 'three', 'four']; const iteratorA = subject.zip(longA, ['one', 'two', 'three'])[Symbol.iterator](); const iteratorB = subject.zip([1, 2, 3], longB)[Symbol.iterator](); expect(iteratorA.next()).toEqual({ done: false, value: [1, 'one'] }); expect(iteratorA.next()).toEqual({ done: false, value: [2, 'two'] }); expect(iteratorA.next()).toEqual({ done: false, value: [3, 'three'] }); const doneA = iteratorA.next(); expect(doneA).toEqual({ done: true, value: longA }); expect(iteratorB.next()).toEqual({ done: false, value: [1, 'one'] }); expect(iteratorB.next()).toEqual({ done: false, value: [2, 'two'] }); expect(iteratorB.next()).toEqual({ done: false, value: [3, 'three'] }); const doneB = iteratorB.next(); expect(doneB).toEqual({ done: true, value: longB }); }); }); describe('all', () => { it('should return false if any item fails the test', () => { const test1 = subject.all(item => item.length === 3, ['one', 'two', 'three']); const test2 = subject.all(item => item.length === 5, ['one', 'two', 'three']); expect(test1).toBe(false); expect(test2).toBe(false); }); it('should return true if all items pass the test', () => { const test = subject.all(item => item.length !== 4, ['one', 'two', 'three']); expect(test).toBe(true); }); it('should return true if the iterator is empty', () => { const test = subject.all(item => item === 4, []); expect(test).toBe(true); }); it('should be auto curried', () => { const test = subject.all(item => item.length === 3)(['one', 'two', 'three']); expect(test).toBe(false); }); }); describe('any', () => { it('should return true if any item pass the test', () => { const test1 = subject.any(item => item.length === 3, ['one', 'two', 'three']); const test2 = subject.any(item => item.length === 5, ['one', 'two', 'three']); expect(test1).toBe(true); expect(test2).toBe(true); }); it('should return true if all items fails the test', () => { const test = subject.any(item => item.length === 4, ['one', 'two', 'three']); expect(test).toBe(false); }); it('should return false if the iterator is empty', () => { const test = subject.any(item => item === 4, []); expect(test).toBe(false); }); it('should be auto curried', () => { const test = subject.any(item => item.length === 3)(['one', 'two', 'three']); expect(test).toBe(true); }); }); describe('find', () => { it('should return the first item that pass the test', () => { const item = subject.find(item => item.length === 3, ['one', 'two', 'three']); const item2 = subject.find(item => item.length === 5, ['one', 'two', 'three']); expect(item).toEqual('one'); expect(item2).toEqual('three'); }); it('should return undefined if no item pass the test', () => { const item = subject.find(item => item.length === 4, ['one', 'two', 'three']); expect(item).toEqual(undefined); }); it('should be auto curried', () => { const item = subject.find(item => item.length === 3)(['one', 'two', 'three']); expect(item).toEqual('one'); }); }); describe('partition', () => { it('should return a tuple of passing and failing elements', () => { const [even, odd] = subject.partition(item => item % 2 === 0, [1, 2, 3, 4, 5]); expect(even).toEqual([2, 4]); expect(odd).toEqual([1, 3, 5]); }); it('should be auto curried', () => { const [even, odd] = subject.partition(item => item % 2 === 0)([1, 2, 3]); expect(even).toEqual([2]); expect(odd).toEqual([1, 3]); }); }); describe('first', () => { it('should return the first item', () => { const item = subject.first(['one', 'two', 'three']); expect(item).toEqual('one'); }); it('should return undefined if there are no items', () => { const item = subject.first([]); expect(item).toEqual(undefined); }); }); describe('skip', () => { it('should skip the first n items', () => { const iterator = subject.skip(2, ['one', 'two', 'three'])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: 'three' }); expect(iterator.next()).toEqual({ done: true, value: undefined }); }); it('should return all items if skip is zero', () => { const iterator = subject.skip(0, ['one', 'two', 'three'])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: 'one' }); expect(iterator.next()).toEqual({ done: false, value: 'two' }); expect(iterator.next()).toEqual({ done: false, value: 'three' }); expect(iterator.next()).toEqual({ done: true, value: undefined }); }); it('should no items if n is greater than the size of the iterable', () => { const iterator = subject.skip(4, ['one', 'two', 'three'])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: true, value: undefined }); }); it('should be auto curried', () => { const iterator = subject.skip(1)(['one', 'two', 'three'])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: 'two' }); }); }); describe('skipWhile', () => { it('should skip the first items test returns true for', () => { const iterator = subject.skipWhile(item => item.length === 3, ['one', 'two', 'three'])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: 'three' }); expect(iterator.next()).toEqual({ done: true, value: undefined }); }); it('should return all items if test directly returns false', () => { const iterator = subject.skipWhile(() => false, ['one', 'two', 'three'])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: 'one' }); expect(iterator.next()).toEqual({ done: false, value: 'two' }); expect(iterator.next()).toEqual({ done: false, value: 'three' }); expect(iterator.next()).toEqual({ done: true, value: undefined }); }); it('should no items if test always return true', () => { const iterator = subject.skipWhile(() => true, ['one', 'two', 'three'])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: true, value: undefined }); }); it('should be auto curried', () => { const iterator = subject.skipWhile(item => item === 'one')(['one', 'two', 'three'])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: 'two' }); }); }); describe('take', () => { it('should return the first n items', () => { const iterator = subject.take(2, ['one', 'two', 'three'])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: 'one' }); expect(iterator.next()).toEqual({ done: false, value: 'two' }); expect(iterator.next()).toEqual({ done: true, value: undefined }); }); it('should return avalible items if n is greater than the size of the iterable', () => { const iterator = subject.take(4, ['one', 'two', 'three'])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: 'one' }); expect(iterator.next()).toEqual({ done: false, value: 'two' }); expect(iterator.next()).toEqual({ done: false, value: 'three' }); expect(iterator.next()).toEqual({ done: true, value: undefined }); }); it('should be auto curried', () => { const iterator = subject.take(2)(['one', 'two', 'three'])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: 'one' }); }); }); describe('takeWhile', () => { it('should return the first items test returns true for', () => { const iterator = subject.takeWhile(item => item.length === 3, ['one', 'two', 'three'])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: 'one' }); expect(iterator.next()).toEqual({ done: false, value: 'two' }); expect(iterator.next()).toEqual({ done: true, value: undefined }); }); it('should return all items if test always return true', () => { const iterator = subject.takeWhile(() => true, ['one', 'two', 'three'])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: 'one' }); expect(iterator.next()).toEqual({ done: false, value: 'two' }); expect(iterator.next()).toEqual({ done: false, value: 'three' }); expect(iterator.next()).toEqual({ done: true, value: undefined }); }); it('should be auto curried', () => { const iterator = subject.takeWhile(item => item === 'one')(['one', 'two', 'three'])[Symbol.iterator](); expect(iterator.next()).toEqual({ done: false, value: 'one' }); }); }); describe('last', () => { it('should return the last item', () => { const item = subject.last(['one', 'two', 'three']); expect(item).toEqual('three'); }); it('should return undefined if there are no items', () => { const item = subject.last([]); expect(item).toEqual(undefined); }); }); describe('sort', () => { it('should return a sorted array', () => { const items = subject.sort((a, b) => a - b, [2, 1, 3]); expect(items).toEqual([1, 2, 3]); }); }); });