257 lines
7.3 KiB
JavaScript
257 lines
7.3 KiB
JavaScript
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)
|
|
})
|
|
})
|
|
]
|
|
|