import { it, assert, assertEq, assertErr } from 'folktest' import { ArrayEnumerator, CachedIteratorEnumerator, DropEnumerator, Enumerable, Enumerator, FilterEnumerator, FlatMapEnumerator, FusedEnumerator, IterableEnumerator, IteratorEnumerator, MapEnumerator, TakeEnumerator } from '../../dist/index.js' const createIterator = (arr = []) => { let index = 0 return { next() { return index < arr.length ? { value: arr[index++], done: false } : { done: true } } } } const createIterable = arr => ({ [Symbol.iterator]() { return createIterator(arr) } }) const createEnumerator = arr => Enumerator.fromIterable(createIterable(arr)) const createEnumerable = arr => Enumerable.from(createIterator(arr)) const helpers = { concat: { prepare: () => { const e1 = createEnumerable([1, 2, 3]) const e2 = createEnumerable([10, 20, 30]) return e1.concat(e2)._enumerator }, expected: FusedEnumerator }, drop: { prepare: () => createEnumerable().drop(0)._enumerator, expected: DropEnumerator }, filter: { prepare: () => createEnumerable().filter(x => x)._enumerator, expected: FilterEnumerator }, flatMap: { prepare: () => { const e = createEnumerable() return e.flatMap(() => createEnumerator([1]))._enumerator }, expected: FlatMapEnumerator }, map: { prepare: () => createEnumerable().map(x => x)._enumerator, expected: MapEnumerator }, take: { prepare: () => createEnumerable().take(0)._enumerator, expected: TakeEnumerator } } export const EnumerableFrom = [ it('from iterator', () => { const iterator = createIterator() const enumerator = Enumerable.from(iterator)._enumerator assert(enumerator instanceof CachedIteratorEnumerator, `${enumerator.constructor.name} is not an instance of 'CachedIterableEnumerator'`) }), it('from iterable', () => { const iterable = createIterable() const enumerator = Enumerable.from(iterable)._enumerator._enumerator assert(enumerator instanceof IterableEnumerator, `${enumerator.constructor.name} is not an instance of 'IterableEnumerator'`) }), it('from array', () => { const arr = [1, 2, 3] const enumerator = Enumerable.from(arr)._enumerator assert(enumerator instanceof ArrayEnumerator, `${enumerator.constructor.name} is not an instance of 'ArrayBuffer'`) }), it('from arraybuffer', () => { const ab = new Uint8Array(1) const enumerator = Enumerable.from(ab)._enumerator assert(enumerator instanceof ArrayEnumerator, `${enumerator.constructor.name} is not an instance of 'ArrayBuffer'`) }), it('from enumerator', () => { const iterable = createIterable() const enumerator1 = Enumerator.fromIterable(iterable) const enumerable1 = Enumerable.from(enumerator1) assert(enumerable1._enumerator._enumerator instanceof IterableEnumerator, `${enumerable1._enumerator._enumerator.constructor.name} is not an instance of IterableEnumerator`) const iterator = createIterator() const enumerator2 = Enumerator.fromIterator(iterator, false) const enumerable2 = Enumerable.from(enumerator2) assert(enumerable2._enumerator instanceof IteratorEnumerator, `${enumerable2._enumerator.constructor.name} is not an instance of IteratorEnumerator`) const enumerator3 = Enumerator.fromIterator(iterator, true) const enumerable3 = Enumerable.from(enumerator3) assert(enumerable3._enumerator instanceof CachedIteratorEnumerator, `${enumerable3._enumerator.constructor.name} is not an instance of CachedIteratorEnumerator`) }), it('from enumerable', () => { const enumerator = { get current() { return undefined }, moveNext() { return false }, reset() { }, } const enumerable1 = new Enumerable(enumerator) const enumerable2 = Enumerable.from(enumerable1) assertEq(enumerable1, enumerable2) }), it('from invalid should error', () => { const expected = /is not enumerable/g assertErr(() => { Enumerable.from(1) }, expected) assertErr(() => { Enumerable.from(Symbol()) }, expected) }) ] export const EnumerableMethod = [ it('at', () => { const arr = [3, 2, 1] const e1 = Enumerable.from(arr) const iterator = createIterator(arr) const e2 = Enumerable.from(iterator) const iterable = createIterator(arr) const e3 = Enumerable.from(iterable) const enums = [e1, e2, e3] enums.forEach(e => { arr.forEach((value, index) => { assertEq(e.at(index), value) }) }) }), it('atOrDefault', () => { const arr = [3] const e = Enumerable.from(arr) assertEq(e.atOrDefault(0, 12), 3) assertEq(e.atOrDefault(1, 12), 12) }), it('atOrElse', () => { const arr = [3] const e = Enumerable.from(arr) const orElse = () => 12 assertEq(e.atOrElse(0, orElse), 3) assertEq(e.atOrElse(1, orElse), 12) }), it('enumerator', () => { assert( Enumerable.from([]).enumerator() instanceof ArrayEnumerator ) }), it('every', () => { const e = Enumerable.from([1, 1, 1]) assert(e.every(n => Number.isInteger(n)), `${e.toString()}.every failed`) assert(!e.every(n => n > 1), `${e.toString()}.every passed when it should have failed`) }), it('enumerator helpers', () => { Object.entries(helpers).forEach(([name, { prepare, expected }]) => { const enumerator = prepare() assert(enumerator instanceof expected, `Enumerable.${name}(): ${enumerator.constructor.name} is not an instance of ${expected.name}`) }) }), it('some', () => { const e = createEnumerable([1, 2, 3]) assert(e.some(n => n === 1), `${e.toString()}.some failed`) assert(!e.some(n => n === 4), `${e.toString()}.some passed when it should have failed`) }) ] export const EnumerableHelpers = [ it('FusedEnumerator', () => { const expected = [1, 2, 3, 10, 20, 30] const e1 = createEnumerator([1, 2, 3]) const e2 = createEnumerator([10, 20, 30]) const fe = new FusedEnumerator([e1, e2]) expected.forEach(n => { fe.moveNext() assertEq(fe.current, n) }) }), it('DropEnumerator', () => { const expected = [4, 5, 6] const e = new DropEnumerator(createEnumerator([1, 2, 3, 4, 5, 6]), 3) expected.forEach(n => { e.moveNext() assertEq(e.current, n) }) }), it('FilterEnumerator', () => { const expected = [1, 3, 5] const e = new FilterEnumerator(createEnumerator([1, 2, 3, 4, 5, 6]), x => x % 2 !== 0) expected.forEach(n => { e.moveNext() assertEq(e.current, n) }) }), it('FlatMapEnumerator', () => { const expected = [1, 2, 2, 3, 3, 3] const e = new FlatMapEnumerator( createEnumerator([1, 2, 3]), n => { const arr = Array.from({ length: n }).fill(n) return createEnumerator(arr) } ) expected.forEach(n => { e.moveNext() assertEq(e.current, n) }) }), it('MapEnumerator', () => { const expected = [1, 4, 9] const e = new MapEnumerator(createEnumerator([1, 2, 3]), n => n * n) expected.forEach(n => { e.moveNext() assertEq(e.current, n) }) }), it('TakeEnumerator', () => { const expected = [1, 2, 3] const e = new TakeEnumerator(createEnumerator([1, 2, 3, 4, 5, 6]), 3) expected.forEach(n => { e.moveNext() assertEq(e.current, n) }) }) ]