UNPKG

rubico

Version:

[a]synchronous functional programming

280 lines (273 loc) 11.5 kB
const Mux = require('../monad/Mux') const assert = require('assert') const unionWith = require('./unionWith') const { isSequence } = Mux describe('unionWith', () => { describe('<T any>unionWith(predicate (T, T)=>Promise<boolean>|boolean)(values Array<Sequence<T>|T>|T) -> result Promise<Array<T>>|Array<T>', () => { const variadicAsyncPluckStrictEqual = (a, b) => a.a === b.a ? Promise.resolve(true) : false const variadicAsyncPluckStrictEqual2 = (a, b) => a.a === b.a ? true : Promise.resolve(false) it('create a flattened unique array with uniques given by a binary predicate', async () => { assert.deepEqual( unionWith((a, b) => a.a === b.a)([ [{ a: 1 }, { a: 2 }], [{ a: 2 }, { a: 3 }], [{ b: 5 }, { a: 5 }], ]), [{ a: 1 }, { a: 2 }, { a: 3 }, { b: 5 }, { a: 5 }] ) assert.deepEqual( unionWith((a, b) => a.a === b.a)([ [{ a: 1 }, { a: 1 }], [{ a: 1 }, { a: 1 }], [{ a: 1 }, { a: 2 }], ]), [{ a: 1 }, { a: 2 }] ) }) it('binary predicate can be async', async () => { assert.deepEqual( await unionWith(async (a, b) => a.a === b.a)([ [{ a: 1 }, { a: 2 }], [{ a: 2 }, { a: 3 }], [{ b: 5 }, { a: 5 }], ]), [{ a: 1 }, { a: 2 }, { a: 3 }, { b: 5 }, { a: 5 }] ) assert.deepEqual( await unionWith(variadicAsyncPluckStrictEqual)([ [{ a: 1 }, { a: 2 }], [{ a: 2 }, { a: 3 }], [{ b: 5 }, { a: 5 }], ]), [{ a: 1 }, { a: 2 }, { a: 3 }, { b: 5 }, { a: 5 }] ) assert.deepEqual( await unionWith(variadicAsyncPluckStrictEqual2)([ [{ a: 1 }, { a: 2 }], [{ a: 2 }, { a: 3 }], [{ b: 5 }, { a: 5 }], ]), [{ a: 1 }, { a: 2 }, { a: 3 }, { b: 5 }, { a: 5 }] ) }) it('empty', async () => { assert.deepEqual( unionWith((a, b) => a === b)([]), [], ) }) it('behavior on varying types', async () => { assert.deepEqual( unionWith((a, b) => a.a === b.a)([ [{ a: 1 }, { a: 2 }], [{ a: 2 }, { a: 3 }], [5, 6], // 6.a === undefined === 5.a ]), [{ a: 1 }, { a: 2 }, { a: 3 }, 5] ) }) it('throws TypeError on unionWith(nonFunction)', async () => { assert.throws( () => unionWith('hey')([1, 2, 3]), new TypeError('comparator is not a function') ) }) it('throws TypeError on unionWith(...)(nonArray)', async () => { assert.throws( () => unionWith(() => {})(new Set([1, 2, 3])), new TypeError('[object Set] is not an Array') ) }) }) describe.skip('<T any>unionWith(predicate (T, T)=>Promise<boolean>|boolean)(values Set<Sequence<T>|T>|T) -> result Promise<Set<T>>|Set<T>', () => { it('predicate () => false; values Set<[1, 2, 3]>; result Set<[1, 2, 3]>', async () => { assert.deepEqual( unionWith(() => false)(new Set([1, 2, 3])), new Set([1, 2, 3]), ) }) it('predicate () => true; values Set<[1, 2, 3]>; result Set<[1]>', async () => { assert.deepEqual( unionWith(() => true)(new Set([1, 2, 3])), new Set([1]), ) }) it('predicate async () => false; values Set<[1, 2, 3]>; result Promise<Set<[1, 2, 3]>>', async () => { const p = unionWith(async () => false)(new Set([1, 2, 3])) assert(p instanceof Promise) const result = await p assert.deepEqual(result, new Set([1, 2, 3])) }) it('predicate item => item.name; values Set<[{...}, {...}, {...}]>; result Promise|<Set<[{...}, {...}]>>', async () => { const people = new Set([{ name: 'George' }, { name: 'George' }, { name: 'Jim' }]) const result = unionWith((personA, personB) => personA.name === personB.name)(people) assert.deepEqual(result, new Set([{ name: 'George' }, { name: 'Jim' }])) { const p = unionWith(async (personA, personB) => personA.name === personB.name)(people) assert(p instanceof Promise) const result = await p assert.deepEqual(result, new Set([{ name: 'George' }, { name: 'Jim' }])) } }) it('predicate () => false; values Set<[[1], 2, [3]]>; result Set<[1, 2, 3]>', async () => { assert.deepEqual( unionWith(() => false)(new Set([[1], 2, [3]])), new Set([1, 2, 3]), ) }) it('predicate () => false; values Set<[1, [2], 3]>; result Set<[1, 2, 3]>', async () => { assert.deepEqual( unionWith(() => false)(new Set([1, [2], 3])), new Set([1, 2, 3]), ) }) xit('predicate () => false; values Set<[asyncGeneratorFunc, asyncGeneratorFunc, asyncGeneratorFunc]>; result Set<[1, 2, 3, 1, 2, 3, 1, 2, 3]>', async () => { const asyncNumbers = async function*(){ yield 1; yield 2; yield 3 } assert( unionWith(() => false)([asyncNumbers, asyncNumbers, asyncNumbers]) instanceof Promise ) assert.deepEqual( await unionWith(() => false)([asyncNumbers, asyncNumbers, asyncNumbers]), [1, 2, 3, 1, 2, 3, 1, 2, 3], ) assert.deepEqual( await unionWith(() => false)(new Set([asyncNumbers, asyncNumbers, asyncNumbers])), new Set([1, 2, 3]), ) }) }) describe.skip('<T any>unionWith(predicate (T, T)=>boolean)(values SyncSequence<SyncSequence<T>|T>|T) -> result Iterator<T>', () => { it('predicate () => false; values [GeneratorFunction, GeneratorFunction, 5, 5, 5]; result [1, 2, 3, 1, 2, 3, 5, 5, 5]', async () => { const numbersGeneratorFunc = function*() { yield 1; yield 2; yield 3 } const subject = unionWith(() => false)([numbersGeneratorFunc, numbersGeneratorFunc, 5, 5, 5]) assert.deepEqual(subject, [1, 2, 3, 1, 2, 3, 5, 5, 5]) }) it('predicate () => false; values GeneratorFunction<>; result Iterator<>', async () => { const numbersGeneratorFunc = function*() { yield 1; yield 2; yield 3 } const subject = unionWith(() => false)(function*(){}) const arr = [...subject] assert.deepEqual(arr, []) }) it('predicate () => false; values GeneratorFunction<[1, 2, 3]>; result Iterator<[1, 2, 3]>', async () => { const oneGeneratorFunc = function*() { yield 1; yield 1; yield 1 } const subject = unionWith((a, b) => a == b)(oneGeneratorFunc) const arr = [...subject] assert.deepEqual(arr, [1]) }) it('predicate () => false; values GeneratorFunction<[GeneratorFunction, GeneratorFunction, 5, 5, 5]>; result [1, 2, 3, 1, 2, 3, 5, 5, 5]', async () => { const numbersGeneratorFunc = function*() { yield 1; yield 2; yield 3 } const gen = function*() { yield numbersGeneratorFunc; yield numbersGeneratorFunc; yield* [5, 5, 5] } const subject = unionWith(() => false)(gen) assert(isSequence(subject)) const arr = [...subject] assert.deepEqual(arr, [1, 2, 3, 1, 2, 3, 5, 5, 5]) }) }) describe.skip('<T any>unionWith(predicate (T, T)=>Promise<boolean>|boolean)(values Sequence<Sequence<T>|T>|T) -> result AsyncIterator<T>', () => { it('predicate () => false; values [AsyncGeneratorFunction, GeneratorFunction, 5, 5, 5]; result Promise<[1, 2, 3, 1, 2, 3, 5, 5, 5]>', async () => { const numbersGeneratorFunc = function*() { yield 1; yield 2; yield 3 } const numbersAsyncGeneratorFunc = async function*() { yield 1; yield 2; yield 3 } const gen = async function*() { yield numbersAsyncGeneratorFunc; yield numbersGeneratorFunc; yield* [5, 5, 5] } { const p = unionWith(() => false)([numbersAsyncGeneratorFunc, numbersGeneratorFunc, 5, [5, 5]]) assert(p instanceof Promise) const subject = await p const arr = [...subject] assert.deepEqual(arr, [1, 2, 3, 1, 2, 3, 5, 5, 5]) } { const p = unionWith(() => Promise.resolve(false))([numbersAsyncGeneratorFunc, numbersGeneratorFunc, 5, [5, 5]]) assert(p instanceof Promise) const subject = await p const arr = [...subject] assert.deepEqual(arr, [1, 2, 3, 1, 2, 3, 5, 5, 5]) } { const subject = unionWith(() => Promise.resolve(false))(gen) const arr = [] for await (const item of subject) arr.push(item) assert.deepEqual(arr, [1, 2, 3, 1, 2, 3, 5, 5, 5]) } { const p = unionWith(() => Promise.resolve(false))([async function*(){}]) assert(p instanceof Promise) const subject = await p assert.deepEqual(subject, []) } }) it('predicate () => false; values AsyncGeneratorFunction<[AsyncGeneratorFunction, GeneratorFunction, 5, 5, 5]>; result AsyncIterator<[1, 2, 3, 1, 2, 3, 5, 5, 5]>', async () => { const numbersGeneratorFunc = function*() { yield 1; yield 2; yield 3 } const numbersAsyncGeneratorFunc = async function*() { yield 1; yield 2; yield 3 } const gen = async function*() { yield numbersAsyncGeneratorFunc; yield numbersGeneratorFunc; yield* [5, 5, 5] } const subject = unionWith(() => false)(gen) const arr = [] for await (const item of subject) arr.push(item) assert.deepEqual(arr, [1, 2, 3, 1, 2, 3, 5, 5, 5]) { const subject = unionWith(async () => true)(gen) const arr = [] for await (const item of subject) arr.push(item) assert.deepEqual(arr, [1]) } }) it('unionWith(() => false)(emptyAsyncIterator)', async () => { const gen = async function*() {} const subject = unionWith(() => false)(gen) const arr = [] for await (const item of subject) arr.push(item) assert.deepEqual(arr, []) }) }) describe.skip('misc', () => { it('unionWith(NaN)', async () => { assert(typeof unionWith(NaN) == 'function') }) it('unionWith([])', async () => { assert(typeof unionWith([]) == 'function') }) it('unionWith({})', async () => { assert(typeof unionWith({}) == 'function') }) it('unionWith(undefined)', async () => { assert(typeof unionWith(undefined) == 'function') }) it('unionWith(null)', async () => { assert(typeof unionWith(null) == 'function') }) it('unionWith(predicate)(NaN)', async () => { const subject = unionWith(() => true)(NaN) assert(isSequence(subject)) const arr = [...subject] assert.equal(arr.length, 1) assert(isNaN(arr[0])) }) it('unionWith(predicate)([]); []', async () => { const subject = unionWith(() => true)([]) assert.deepEqual(subject, []) }) it('unionWith(predicate)({}); Iterator<{}>', async () => { const subject = unionWith(() => true)({}) assert(isSequence(subject)) const arr = [...subject] assert.deepEqual(arr, [{}]) }) it('unionWith(predicate)(undefined); []', async () => { const subject = unionWith(() => true)(undefined) assert(isSequence(subject)) const arr = [...subject] assert.deepEqual(arr, []) }) it('unionWith(predicate)(null); []', async () => { const subject = unionWith(() => true)(null) assert(isSequence(subject)) const arr = [...subject] assert.deepEqual(arr, []) }) xit('unionWith(asyncPredicate)([emptyAsyncGeneratorFunction])', async () => { const p = unionWith(() => Promise.resolve(false))([async function*(){}]) assert(p instanceof Promise) const subject = await p assert.deepEqual(subject, []) }) }) })