diff --git a/README.md b/README.md index bfb989f..08cc99d 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ This library is written in TypeScript but is exposed as ES7 (if imported as `alr * [once](#once) * [retry](#retry) * [defer](#defer) + * [deferSet](#deferset) * [reflect](#reflect) * [inspect](#inspect) * [Try](#try) @@ -422,6 +423,50 @@ deferred.resolve( ); // This is now legal, typewise ``` +## deferSet + +Instead of creating a lot of defer objects, e.g. in unit tests to trigger asynchrony in a certain order, `deferSet` is a cleaner way. + +A *"defer set"* is a dynamically growable set of indexes (numbers) which can be awaited, resolved or rejected at any time. + +`deferSet( )` returns an object (of a class `OrderedAsynchrony`). This has the helper functions: + + * `wait( index | [indices...] ) -> Promise< void >` + * `resolve( index | [indices...] ) -> Promise< void >` + * `reject( index | [indices...] ) -> Promise< void >` + +```ts +import { deferSet } from 'already' + +const order = deferSet( ); + +order.resolve( 0 ); // Resolve index 0 +await order.wait( 0 ); // Wait for promise 0 (which was resolved above) +``` + +The above will work fine, it's basically creating a `defer`, resolving it and then awaiting its promise. This will deadlock: + +```ts +await order.wait( 0 ); // Will wait forever +order.resolve( 0 ); +``` + +It's possible to wait, resolve and reject multiple indices at once, by specifying an array instead. And `wait` can take an optional index (or array of indices) to resolve, as well as an optional index (or array of indices) to reject. + +The return value of `wait( )`, `resolve( )` and `reject( )` is a promise *and* the defer set itself. + +```ts +// Do stuff, and eventually trigger certain index resolutions. +doFoo( ).then( ( ) => { order.resolve( 0 ); } ); // Eventually resolves index 0 +doBar( ).then( ( ) => { order.resolve( [ 1, 3 ] ); } ); // Eventually resolves index 1 and 3 +// etc. + +await order.wait( [ 0, 1, 3 ], 2 ); // Await index 0, 1 and 3, resolve index 2. +order.reject( 4 ); // Will reject index 4 with an error. +await order.wait( 4 ); // Will (asynchronously) throw. +``` + + ## reflect A promise can be either resolved or rejected, but sometimes it's convenient to have a shared flow for either occasion. That's when `reflect` comes in handy. It takes a promise as argument, and returns a promise to a `Reflection` object which contains the *value* **or** *error*, and the booleans `isResolved` and `isRejected`. diff --git a/jest.config.js b/jest.config.js index d76e14b..66e2b26 100644 --- a/jest.config.js +++ b/jest.config.js @@ -9,9 +9,10 @@ module.exports = { modulePathIgnorePatterns: [ ".*\.d\.ts" ], - collectCoverageFrom: ["/lib/**", "index.ts"], + collectCoverageFrom: ["/dist/**/*.js"], coverageReporters: ["lcov", "text", "html"], setupFiles: [ "trace-unhandled/register", ], + maxConcurrency: Infinity, }; diff --git a/lib/index.ts b/lib/index.ts index 31a98d1..e0e1e90 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -4,6 +4,7 @@ export default { Finally, Try, defer, + deferSet, delay, delayChain, each, @@ -1172,3 +1173,118 @@ export function funnel< T, U extends Promise< T > = Promise< T > >( return runner( fn, [ ] ); }; } + + +export class OrderedAsynchrony +{ + private deferrals: Array< EmptyDeferred > = [ ]; + + public wait( + waitForIndex: number | ConcatArray< number >, + resolveIndex?: number | ConcatArray< number > | undefined | null, + rejectIndex?: number | ConcatArray< number > | undefined | null + ) + : Promise< void > & this + { + this.ensureDeferral( [ + ...( ( < Array< number > >[ ] ).concat( waitForIndex ) ), + ...( + resolveIndex == null ? [ ] : + ( < Array< number > >[ ] ).concat( resolveIndex ) + ), + ...( + rejectIndex == null ? [ ] : + ( < Array< number > >[ ] ).concat( rejectIndex ) + ), + ] ); + + return this.decorate( + Promise.all( + ( < Array< number > >[ ] ).concat( waitForIndex ) + .map( index => this.deferrals[ index ].promise ) + ) + .then( ( ) => + Promise.all( [ + resolveIndex == null + ? void 0 + : this.resolve( resolveIndex ), + rejectIndex == null + ? void 0 + : this.reject( rejectIndex ), + ] ) + .then( ( ) => { } ) + ) + ); + } + + public resolve( index: number | ConcatArray< number > ) + : Promise< void > & this + { + this.ensureDeferral( index ); + + return this.decorate( delay( 0 ).then( ( ) => + { + ( < Array< number > >[ ] ).concat( index ) + .forEach( index => + { + this.deferrals[ index ].resolve( ); + } ); + } ) ); + } + + public reject( + index: number | ConcatArray< number >, + error = new Error( "OrderedAsynchrony rejection" ) + ) + : Promise< void > & this + { + this.ensureDeferral( index ); + + return this.decorate( delay( 0 ).then( ( ) => + { + ( < Array< number > >[ ] ).concat( index ) + .forEach( index => + { + this.deferrals[ index ].reject( error ); + } ); + } ) ); + } + + private ensureDeferral( index: number | ConcatArray< number > ): this + { + const indices = ( < Array< number > >[ ] ) + .concat( index ) + .sort( ( a, b ) => b - a ); + + const highest = indices[ 0 ]; + + for ( let i = this.deferrals.length; i <= highest; ++i ) + this.deferrals.push( defer( void 0 ) ); + + return this; + } + + private decorate( promise: Promise< void > ) + : Promise< void > & this + { + // tslint:disable-next-line:variable-name + const This = { + decorate: this.decorate.bind( this ), + deferrals: this.deferrals, + ensureDeferral: this.ensureDeferral.bind( this ), + reject: this.reject.bind( this ), + resolve: this.resolve.bind( this ), + wait: this.wait.bind( this ), + } as unknown as this; + + return Object.assign( + promise, + This + ); + } +} + +export function deferSet( ) +{ + return new OrderedAsynchrony( ); +} diff --git a/test/defer-set.ts b/test/defer-set.ts new file mode 100644 index 0000000..b93f7e5 --- /dev/null +++ b/test/defer-set.ts @@ -0,0 +1,51 @@ +import { + deferSet, + reflect, +} from "../"; + + +describe( "deferSet", ( ) => +{ + it.concurrent( "resolve, wait", async ( ) => + { + const order = deferSet( ); + + await order.resolve( 0 ); + await order.wait( 0 ); + } ); + + it.concurrent( "wait+resolve+reject all-in-one", async ( ) => + { + const order = deferSet( ); + + await order.resolve( 0 ); + + await order.wait( 0, 1, 2 ); + + await order.wait( 1 ); + const reflection = await reflect( order.wait( 2 ) ); + expect( reflection.isRejected ).toBe( true ); + expect( ( < Error >reflection.error ).message ).toMatch( /rejection/ ); + } ); + + it.concurrent( "wait+resolve+reject all-in-one, arrays", async ( ) => + { + const order = deferSet( ); + + await order.resolve( [ 0, 1 ] ); + + await order.wait( [ 0, 1 ], [ 2, 3 ], [ 4, 5 ] ); + + await order.wait( [ 2, 3 ] ); + const reflection = await reflect( order.wait( [ 4, 5 ] ) ); + expect( reflection.isRejected ).toBe( true ); + expect( ( < Error >reflection.error ).message ).toMatch( /rejection/ ); + } ); + + it.concurrent( "wait+resolve+reject all-in-one, empty arrays", async ( ) => + { + const order = deferSet( ); + + await order.wait( [ ], [ ], [ ] ); + } ); +} ); diff --git a/test/funnel.ts b/test/funnel.ts index 32f6e4a..5b799d3 100644 --- a/test/funnel.ts +++ b/test/funnel.ts @@ -1,5 +1,6 @@ import { defer, + deferSet, delay, funnel, Funnel, @@ -36,11 +37,14 @@ const makePredicate = < T >( const maker = ( reporter: ( val: string ) => void, val: string, - millis: number = 0 + millis: number | ( ( ) => Promise< void > ) = 0 ) => async ( ) => { - await delay( millis ); + if ( typeof millis === "number" || typeof millis === "bigint" ) + await delay( millis ); + else + await millis( ); reporter( val ); }; @@ -50,7 +54,7 @@ describe( "funnel", ( ) => { [ true, false ].forEach( fifo => describe( `fifo = ${fifo}`, ( ) => { - it( "only one job", async ( ) => + it.concurrent( "only one job", async ( ) => { const onComplete = jest.fn( ); const fun: Funnel< number > = @@ -71,27 +75,32 @@ describe( "funnel", ( ) => expect( onComplete.mock.calls.length ).toBe( 1 ); } ); - it( "two jobs", async ( ) => + it.concurrent( "two jobs", async ( ) => { const deferred = defer( void 0 ); const onComplete = jest.fn( deferred.resolve ); const parts = jest.fn( ); const fun = funnel< number >( { fifo, onComplete } ); + const order = deferSet( ); const eventualValue1 = fun( makePredicate< number >( - maker( parts, "1 a", 0 ), - maker( parts, "1 b", 5 ), + maker( parts, "1 a", ( ) => order.wait( 0 ) ), + maker( parts, "1 b", ( ) => order.wait( 1 ) ), 1 ) ); const eventualValue2 = fun( makePredicate< number >( - maker( parts, "2 a", 0 ), - maker( parts, "2 b", 5 ), + maker( parts, "2 a", ( ) => order.wait( 0 ) ), + maker( parts, "2 b", ( ) => order.wait( 1 ) ), 2 ) ); + order.resolve( 0 ) + .then( ( ) => delay( 10 ) ) + .then( ( ) => order.resolve( 1 ) ); + const value1 = await eventualValue1; const value2 = await eventualValue2; await deferred.promise; @@ -107,27 +116,30 @@ describe( "funnel", ( ) => expect( onComplete.mock.calls.length ).toBe( 1 ); } ); - it( "two jobs, first slower", async ( ) => + it.concurrent( "two jobs, first slower", async ( ) => { const deferred = defer( void 0 ); const onComplete = jest.fn( deferred.resolve ); const parts = jest.fn( ); const fun = funnel< number >( { fifo, onComplete } ); + const order = deferSet( ); const eventualValue1 = fun( makePredicate< number >( - maker( parts, "1 a", 10 ), - maker( parts, "1 b", 5 ), + maker( parts, "1 a", ( ) => order.wait( 0 ).wait( 1 ) ), + maker( parts, "1 b", ( ) => order.wait( 0 ) ), 1 ) ); const eventualValue2 = fun( makePredicate< number >( - maker( parts, "2 a", 0 ), - maker( parts, "2 b", 5 ), + maker( parts, "2 a", ( ) => order.resolve( 0 ) ), + maker( parts, "2 b", ( ) => order.resolve( 0 ) ), 2 ) ); + await delay( 20 ); order.resolve( 1 ); + const value1 = await eventualValue1; const value2 = await eventualValue2; await deferred.promise; @@ -146,25 +158,31 @@ describe( "funnel", ( ) => } ); } ) ); - it( "two jobs, first slower, no arg", async ( ) => + it.concurrent( "two jobs, first slower, no arg", async ( ) => { const parts = jest.fn( ); const fun = funnel< number >( ); + const order = deferSet( ); const eventualValue1 = fun( makePredicate< number >( - maker( parts, "1 a", 10 ), - maker( parts, "1 b", 5 ), + maker( parts, "1 a", ( ) => order.wait( 1 ) ), + maker( parts, "1 b", ( ) => order.wait( 2 ) ), 1 ) ); const eventualValue2 = fun( makePredicate< number >( - maker( parts, "2 a", 0 ), - maker( parts, "2 b", 5 ), + maker( parts, "2 a", ( ) => order.wait( 0 ) ), + maker( parts, "2 b", ( ) => order.wait( 3 ) ), 2 ) ); + order.resolve( 0 ); await delay( 1 ); + order.resolve( 1 ); await delay( 1 ); + order.resolve( 2 ); await delay( 1 ); + order.resolve( 3 ); await delay( 1 ); + const value1 = await eventualValue1; const value2 = await eventualValue2; @@ -177,25 +195,31 @@ describe( "funnel", ( ) => ); } ); - it( "two jobs, first slower, arg = null", async ( ) => + it.concurrent( "two jobs, first slower, arg = null", async ( ) => { const parts = jest.fn( ); const fun = funnel< number >( < any >null ); + const order = deferSet( ); const eventualValue1 = fun( makePredicate< number >( - maker( parts, "1 a", 10 ), - maker( parts, "1 b", 5 ), + maker( parts, "1 a", ( ) => order.wait( 1 ) ), + maker( parts, "1 b", ( ) => order.wait( 2 ) ), 1 ) ); const eventualValue2 = fun( makePredicate< number >( - maker( parts, "2 a", 0 ), - maker( parts, "2 b", 5 ), + maker( parts, "2 a", ( ) => order.wait( 0 ) ), + maker( parts, "2 b", ( ) => order.wait( 3 ) ), 2 ) ); + order.resolve( 0 ); await delay( 1 ); + order.resolve( 1 ); await delay( 1 ); + order.resolve( 2 ); await delay( 1 ); + order.resolve( 3 ); await delay( 1 ); + const value1 = await eventualValue1; const value2 = await eventualValue2; @@ -208,25 +232,31 @@ describe( "funnel", ( ) => ); } ); - it( "two jobs, first slower, onComplete = null", async ( ) => + it.concurrent( "two jobs, first slower, onComplete = null", async ( ) => { const parts = jest.fn( ); const fun = funnel< number >( { onComplete: < any >null } ); + const order = deferSet( ); const eventualValue1 = fun( makePredicate< number >( - maker( parts, "1 a", 10 ), - maker( parts, "1 b", 5 ), + maker( parts, "1 a", ( ) => order.wait( 1 ) ), + maker( parts, "1 b", ( ) => order.wait( 2 ) ), 1 ) ); const eventualValue2 = fun( makePredicate< number >( - maker( parts, "2 a", 0 ), - maker( parts, "2 b", 5 ), + maker( parts, "2 a", ( ) => order.wait( 0 ) ), + maker( parts, "2 b", ( ) => order.wait( 3 ) ), 2 ) ); + order.resolve( 0 ); await delay( 1 ); + order.resolve( 1 ); await delay( 1 ); + order.resolve( 2 ); await delay( 1 ); + order.resolve( 3 ); await delay( 1 ); + const value1 = await eventualValue1; const value2 = await eventualValue2; @@ -239,30 +269,32 @@ describe( "funnel", ( ) => ); } ); - it( "two jobs, shortcut", async ( ) => + it.concurrent( "two jobs, shortcut", async ( ) => { const parts = jest.fn( ); const fun = funnel< number >( { onComplete: < any >null, fifo: false } ); + const order = deferSet( ); const eventualValue1 = fun( makePredicate< number >( - maker( parts, "1 a", 10 ), - maker( parts, "1 b", 5 ), + maker( parts, "1 a", ( ) => order.wait( 0 ) ), + maker( parts, "1 b", ( ) => order.wait( 0 ).resolve( 1 ) ), 1 ) ); const eventualValue2 = fun( async ( shouldRetry, retry, shortcut ) => { - await delay( 1 ); parts( "2 a" ); + await order.resolve( 0 ); + if ( shouldRetry( ) ) return retry( ); parts( "2 b" ); shortcut( ); - await delay( 50 ); + await order.wait( 1 ); parts( "2 c" ); return 2; @@ -278,15 +310,16 @@ describe( "funnel", ( ) => expect( args ).toEqual( [ "2 a", "2 b", "1 a", "1 b", "2 c" ] ); } ); - it( "two jobs, shortcut before retry", async ( ) => + it.concurrent( "two jobs, shortcut before retry", async ( ) => { const parts = jest.fn( ); const fun = funnel< number >( { onComplete: < any >null, fifo: false } ); + const order = deferSet( ); const eventualValue1 = fun( makePredicate< number >( - maker( parts, "1 a", 10 ), - maker( parts, "1 b", 5 ), + maker( parts, "1 a", ( ) => order.wait( 0 ) ), + maker( parts, "1 b", 0 ), 1 ) ); @@ -305,6 +338,8 @@ describe( "funnel", ( ) => await delay( 1 ); parts( "2 c" ); + order.resolve( 0 ); + return 2; } ); @@ -318,15 +353,16 @@ describe( "funnel", ( ) => expect( args ).toEqual( [ "2 a", "2 b", "2 c", "1 a", "1 b" ] ); } ); - it( "two jobs, retry in sync", async ( ) => + it.concurrent( "two jobs, retry in sync", async ( ) => { const parts = jest.fn( ); const fun = funnel< number >( { onComplete: < any >null, fifo: false } ); + const order = deferSet( ); const eventualValue1 = fun( makePredicate< number >( - maker( parts, "1 a", 10 ), - maker( parts, "1 b", 5 ), + maker( parts, "1 a", ( ) => order.wait( 0 ) ), + maker( parts, "1 b", 0 ), 1 ) ); @@ -337,6 +373,7 @@ describe( "funnel", ( ) => return retry( ); parts( "2 a" ); + order.resolve( 0 ); return 2; } ); @@ -363,7 +400,7 @@ describe( "funnel", ( ) => runs.forEach( ( { type, name, predicate } ) => { - it( `should be able to ${type} before shouldRetry (${name})`, + it.concurrent( `should be able to ${type} before shouldRetry (${name})`, async ( ) => { const fun = funnel< number >( ); @@ -383,7 +420,7 @@ describe( "funnel", ( ) => .toBe( "foo" ); } ); - it( `should be able to ${type} after shouldRetry (${name})`, + it.concurrent( `should be able to ${type} after shouldRetry (${name})`, async ( ) => { const fun = funnel< number >( ); diff --git a/test/index.ts b/test/index.ts index 611746d..969802d 100644 --- a/test/index.ts +++ b/test/index.ts @@ -30,7 +30,7 @@ const barValue = 17; describe( "finally", ( ) => { - it( "should be called on a resolved promise", ( ) => + it.concurrent( "should be called on a resolved promise", ( ) => { let called = false; @@ -45,7 +45,7 @@ describe( "finally", ( ) => } ); } ); - it( "should be called on a rejected promise", ( ) => + it.concurrent( "should be called on a rejected promise", ( ) => { let called = false; @@ -68,7 +68,7 @@ describe( "finally", ( ) => describe( "finallyDelay", ( ) => { - it( "should be called on a resolved promise", ( ) => + it.concurrent( "should be called on a resolved promise", ( ) => { let value = 0; @@ -84,7 +84,7 @@ describe( "finallyDelay", ( ) => } ); } ); - it( "should be called on a rejected promise", ( ) => + it.concurrent( "should be called on a rejected promise", ( ) => { let value = 0; @@ -108,7 +108,7 @@ describe( "finallyDelay", ( ) => describe( "tap", ( ) => { - it( "should be called on a resolved promise", ( ) => + it.concurrent( "should be called on a resolved promise", ( ) => { let called = false; @@ -128,7 +128,7 @@ describe( "tap", ( ) => } ); } ); - it( "should not be called on a rejected promise", ( ) => + it.concurrent( "should not be called on a rejected promise", ( ) => { let called = false; @@ -159,14 +159,15 @@ describe( "tap", ( ) => describe( "props", ( ) => { - it( "should work as standalone call", async ( ) => + it.concurrent( "should work as standalone call", async ( ) => { const val = await props( { a: 1, b: delay( 10 ).then( ( ) => 2 ) } ); expect( val ).toEqual( { a: 1, b: 2 } ); } ); - it( "should work in a promise chain as function reference", async ( ) => + it.concurrent( "should work in a promise chain as function reference", + async ( ) => { const val = await Promise.resolve( { a: 1, b: delay( 10 ).then( ( ) => 2 ) } ) @@ -204,7 +205,7 @@ describe( "filter", ( ) => .then( values => ( { values, concurrencies } ) ); } - it( "unspecified concurrency should be correct", async ( ) => + it.concurrent( "unspecified concurrency should be correct", async ( ) => { const { concurrencies, values } = await filterConcurrency( < number >< any >void 0, @@ -216,7 +217,7 @@ describe( "filter", ( ) => expect( concurrencies ).toEqual( [ 1, 2, 3, 4, 5, 4, 3, 2, 1, 0 ] ); } ); - it( "concurrency 1 should be correct", async ( ) => + it.concurrent( "concurrency 1 should be correct", async ( ) => { const { concurrencies, values } = await filterConcurrency( 1, @@ -228,7 +229,7 @@ describe( "filter", ( ) => expect( concurrencies ).toEqual( [ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 ] ); } ); - it( "concurrency 2 should be correct", async ( ) => + it.concurrent( "concurrency 2 should be correct", async ( ) => { const { concurrencies, values } = await filterConcurrency( 2, @@ -243,7 +244,7 @@ describe( "filter", ( ) => expect( concurrencies ).toContain( 2 ); } ); - it( "concurrency 3 should be correct", async ( ) => + it.concurrent( "concurrency 3 should be correct", async ( ) => { const { concurrencies, values } = await filterConcurrency( 3, @@ -258,7 +259,7 @@ describe( "filter", ( ) => expect( concurrencies ).toContain( 3 ); } ); - it( "should work without options", async ( ) => + it.concurrent( "should work without options", async ( ) => { const arr = [ 1, 2, Promise.resolve( 3 ), delayChain( 50 )( 4 ), 5 ]; const arr2 = await Promise.all( arr ) @@ -272,7 +273,7 @@ describe( "filter", ( ) => expect( arr2 ).toEqual( [ 2, 4 ] ); } ); - it( "should work as a free function", async ( ) => + it.concurrent( "should work as a free function", async ( ) => { const arr = [ 1, 2, Promise.resolve( 3 ), delayChain( 50 )( 4 ), 5 ]; const arr2 = await filter( @@ -287,7 +288,8 @@ describe( "filter", ( ) => expect( arr2 ).toEqual( [ 2, 4 ] ); } ); - it( "should work as a free function without options", async ( ) => + it.concurrent( "should work as a free function without options", + async ( ) => { const arr = [ 1, 2, Promise.resolve( 3 ), delayChain( 50 )( 4 ), 5 ]; const arr2 = await filter( @@ -330,7 +332,7 @@ describe( "map", ( ) => .then( values => ( { values, concurrencies } ) ); } - it( "unspecified concurrency should be correct", async ( ) => + it.concurrent( "unspecified concurrency should be correct", async ( ) => { const { concurrencies, values } = await mapConcurrency( < number >< any >void 0, @@ -343,7 +345,7 @@ describe( "map", ( ) => expect( concurrencies ).toEqual( [ 1, 2, 3, 4, 5, 4, 3, 2, 1, 0 ] ); } ); - it( "concurrency 1 should be correct", async ( ) => + it.concurrent( "concurrency 1 should be correct", async ( ) => { const { concurrencies, values } = await mapConcurrency( 1, @@ -356,7 +358,7 @@ describe( "map", ( ) => expect( concurrencies ).toEqual( [ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 ] ); } ); - it( "concurrency 2 should be correct", async ( ) => + it.concurrent( "concurrency 2 should be correct", async ( ) => { const { concurrencies, values } = await mapConcurrency( 2, @@ -373,7 +375,7 @@ describe( "map", ( ) => expect( concurrencies ).toContain( 2 ); } ); - it( "concurrency 3 should be correct", async ( ) => + it.concurrent( "concurrency 3 should be correct", async ( ) => { const { concurrencies, values } = await mapConcurrency( 3, @@ -390,7 +392,7 @@ describe( "map", ( ) => expect( concurrencies ).toContain( 3 ); } ); - it( "should work without options", async ( ) => + it.concurrent( "should work without options", async ( ) => { const arr = [ 1, 2, Promise.resolve( 3 ), delayChain( 50 )( 4 ), 5 ]; const arr2 = await Promise.all( arr ) @@ -405,7 +407,7 @@ describe( "map", ( ) => expect( arr3 ).toEqual( [ 1, 2, 3, 4, 5 ] ); } ); - it( "should work as a free function", async ( ) => + it.concurrent( "should work as a free function", async ( ) => { const arr = [ 1, 2, Promise.resolve( 3 ), delayChain( 50 )( 4 ), 5 ]; const arr2 = await map( @@ -421,7 +423,8 @@ describe( "map", ( ) => expect( arr3 ).toEqual( [ 1, 2, 3, 4, 5 ] ); } ); - it( "should work as a free function without options", async ( ) => + it.concurrent( "should work as a free function without options", + async ( ) => { const arr = [ 1, 2, Promise.resolve( 3 ), delayChain( 50 )( 4 ), 5 ]; const arr2 = await map( @@ -445,7 +448,7 @@ describe( "reduce", ( ) => return acc + cur; } - it( "should reduce initialValue if empty array", async ( ) => + it.concurrent( "should reduce initialValue if empty array", async ( ) => { const input: Array< number > = [ ]; const initialValue = fooValue; @@ -455,7 +458,8 @@ describe( "reduce", ( ) => expect( reduced ).toBe( fooValue ); } ); - it( "should reduce single-value array without initialValue", async ( ) => + it.concurrent( "should reduce single-value array without initialValue", + async ( ) => { const input = [ fooValue ]; @@ -464,7 +468,8 @@ describe( "reduce", ( ) => expect( reduced ).toBe( fooValue ); } ); - it( "should reduce single-value array with initialValue", async ( ) => + it.concurrent( "should reduce single-value array with initialValue", + async ( ) => { const input = [ fooValue ]; const initialValue = fooValue; @@ -474,7 +479,8 @@ describe( "reduce", ( ) => expect( reduced ).toBe( fooValue + fooValue ); } ); - it( "should reduce multi-value array without initialValue", async ( ) => + it.concurrent( "should reduce multi-value array without initialValue", + async ( ) => { const input = [ fooValue, fooValue ]; @@ -483,7 +489,8 @@ describe( "reduce", ( ) => expect( reduced ).toBe( fooValue + fooValue ); } ); - it( "should reduce multi-value array with initialValue", async ( ) => + it.concurrent( "should reduce multi-value array with initialValue", + async ( ) => { const input = [ fooValue, fooValue ]; const initialValue = fooValue; @@ -493,7 +500,7 @@ describe( "reduce", ( ) => expect( reduced ).toBe( fooValue + fooValue + fooValue ); } ); - it( "should handle future array and future values", async ( ) => + it.concurrent( "should handle future array and future values", async ( ) => { const input = Promise.resolve( [ Promise.resolve( fooValue ), fooValue ] ); const initialValue = Promise.resolve( fooValue ); @@ -503,7 +510,8 @@ describe( "reduce", ( ) => expect( reduced ).toBe( fooValue + fooValue + fooValue ); } ); - it( "should work in a promise chain without initialValue", async ( ) => + it.concurrent( "should work in a promise chain without initialValue", + async ( ) => { const input = Promise.resolve( [ Promise.resolve( fooValue ), fooValue ] ); @@ -512,7 +520,8 @@ describe( "reduce", ( ) => expect( reduced ).toBe( fooValue + fooValue ); } ); - it( "should work in a promise chain with initialValue", async ( ) => + it.concurrent( "should work in a promise chain with initialValue", + async ( ) => { const input = Promise.resolve( [ Promise.resolve( fooValue ), fooValue ] ); const initialValue = Promise.resolve( fooValue ); @@ -522,7 +531,8 @@ describe( "reduce", ( ) => expect( reduced ).toBe( fooValue + fooValue + fooValue ); } ); - it( "should handle reduce with different aggregate type", async ( ) => + it.concurrent( "should handle reduce with different aggregate type", + async ( ) => { const makeLessThan = async ( than: number ) => { @@ -556,7 +566,7 @@ describe( "each", ( ) => { describe( "with array", ( ) => { - it( "should iterate empty array", async ( ) => + it.concurrent( "should iterate empty array", async ( ) => { const input: Array< number > = [ ]; const spy = jest.fn( ); @@ -568,7 +578,8 @@ describe( "each", ( ) => expect( spy.mock.calls.length ).toBe( 0 ); } ); - it( "should iterate single-value array (inferred type)", async ( ) => + it.concurrent( "should iterate single-value array (inferred type)", + async ( ) => { const input = [ fooValue ]; const spy = jest.fn( ); @@ -582,7 +593,7 @@ describe( "each", ( ) => expect( spy.mock.calls ).toEqual( [ [ fooValue, 0, 1 ] ] ); } ); - it( "should iterate single-value array", async ( ) => + it.concurrent( "should iterate single-value array", async ( ) => { const input = [ fooValue ]; const spy = jest.fn( ); @@ -594,7 +605,7 @@ describe( "each", ( ) => expect( spy.mock.calls ).toEqual( [ [ fooValue, 0, 1 ] ] ); } ); - it( "should iterate multi-value array", async ( ) => + it.concurrent( "should iterate multi-value array", async ( ) => { const input = [ fooValue, barValue, fooValue ]; const spy = jest.fn( ); @@ -610,7 +621,8 @@ describe( "each", ( ) => ] ); } ); - it( "should iterate empty array asynchronously", async ( ) => + it.concurrent( "should iterate empty array asynchronously", + async ( ) => { const order: Array< number > = [ ]; const input: Array< number > = [ ]; @@ -631,7 +643,8 @@ describe( "each", ( ) => expect( order ).toEqual( [ ] ); } ); - it( "should iterate single-value array asynchronously", async ( ) => + it.concurrent( "should iterate single-value array asynchronously", + async ( ) => { const order: Array< number > = [ ]; const input = [ fooValue ]; @@ -652,7 +665,8 @@ describe( "each", ( ) => expect( order ).toEqual( [ 0, 0 ] ); } ); - it( "should iterate multi-value array asynchronously", async ( ) => + it.concurrent( "should iterate multi-value array asynchronously", + async ( ) => { const order: Array< number > = [ ]; const input = [ fooValue, barValue, fooValue ]; @@ -680,7 +694,7 @@ describe( "each", ( ) => describe( "in promise chain", ( ) => { - it( "should iterate empty array", async ( ) => + it.concurrent( "should iterate empty array", async ( ) => { const input = Promise.resolve( [ ] ); const spy = jest.fn( ); @@ -692,7 +706,7 @@ describe( "each", ( ) => expect( spy.mock.calls.length ).toBe( 0 ); } ); - it( "should iterate single-value array", async ( ) => + it.concurrent( "should iterate single-value array", async ( ) => { const input = Promise.resolve( [ fooValue ] ); const spy = jest.fn( ); @@ -704,7 +718,7 @@ describe( "each", ( ) => expect( spy.mock.calls ).toEqual( [ [ fooValue, 0, 1 ] ] ); } ); - it( "should iterate multi-value array", async ( ) => + it.concurrent( "should iterate multi-value array", async ( ) => { const input = Promise.resolve( [ fooValue, barValue, fooValue ] ); const spy = jest.fn( ); @@ -720,7 +734,8 @@ describe( "each", ( ) => ] ); } ); - it( "should iterate empty array asynchronously", async ( ) => + it.concurrent( "should iterate empty array asynchronously", + async ( ) => { const order: Array< number > = [ ]; const input = Promise.resolve( [ ] ); @@ -741,7 +756,8 @@ describe( "each", ( ) => expect( order ).toEqual( [ ] ); } ); - it( "should iterate single-value array asynchronously", async ( ) => + it.concurrent( "should iterate single-value array asynchronously", + async ( ) => { const order: Array< number > = [ ]; const input = Promise.resolve( [ fooValue ] ); @@ -762,7 +778,8 @@ describe( "each", ( ) => expect( order ).toEqual( [ 0, 0 ] ); } ); - it( "should iterate multi-value array asynchronously", async ( ) => + it.concurrent( "should iterate multi-value array asynchronously", + async ( ) => { const order: Array< number > = [ ]; const input = Promise.resolve( [ fooValue, barValue, fooValue ] ); @@ -830,7 +847,7 @@ describe( "some", ( ) => describe( "sync flat", ( ) => { - it( "should be false on empty array", async ( ) => + it.concurrent( "should be false on empty array", async ( ) => { const input: Array< number > = [ ]; @@ -839,7 +856,8 @@ describe( "some", ( ) => expect( res ).toBe( false ); } ); - it( "should return false on unmatching single-value array", async ( ) => + it.concurrent( "should return false on unmatching single-value array", + async ( ) => { const input = [ fooValue ]; @@ -848,7 +866,8 @@ describe( "some", ( ) => expect( res ).toBe( false ); } ); - it( "should return value on matching single-value array", async ( ) => + it.concurrent( "should return value on matching single-value array", + async ( ) => { const input = [ fooValue ]; @@ -857,7 +876,8 @@ describe( "some", ( ) => expect( res ).toEqual( { val: fooValue } ); } ); - it( "should return false on unmatching multi-value array", async ( ) => + it.concurrent( "should return false on unmatching multi-value array", + async ( ) => { const input = [ fooValue, fooValue + 1, fooValue + 2 ]; @@ -866,7 +886,8 @@ describe( "some", ( ) => expect( res ).toBe( false ); } ); - it( "should return first match in multi-value array", async ( ) => + it.concurrent( "should return first match in multi-value array", + async ( ) => { const input = [ fooValue, fooValue + 1, fooValue + 2 ]; @@ -878,7 +899,7 @@ describe( "some", ( ) => describe( "sync in promise chain", ( ) => { - it( "should be false on empty array", async ( ) => + it.concurrent( "should be false on empty array", async ( ) => { const res = await Promise.resolve( [ ] ) @@ -887,7 +908,8 @@ describe( "some", ( ) => expect( res ).toBe( false ); } ); - it( "should return false on unmatching single-value array", async ( ) => + it.concurrent( "should return false on unmatching single-value array", + async ( ) => { const res = await Promise.resolve( [ fooValue ] ) @@ -896,7 +918,8 @@ describe( "some", ( ) => expect( res ).toBe( false ); } ); - it( "should return value on matching single-value array", async ( ) => + it.concurrent( "should return value on matching single-value array", + async ( ) => { const res = await Promise.resolve( [ fooValue ] ) @@ -905,7 +928,8 @@ describe( "some", ( ) => expect( res ).toEqual( { val: fooValue } ); } ); - it( "should return false on unmatching multi-value array", async ( ) => + it.concurrent( "should return false on unmatching multi-value array", + async ( ) => { const res = await Promise.resolve( [ fooValue, fooValue + 1, fooValue + 2 ] ) @@ -914,7 +938,8 @@ describe( "some", ( ) => expect( res ).toBe( false ); } ); - it( "should return first match in multi-value array", async ( ) => + it.concurrent( "should return first match in multi-value array", + async ( ) => { const res = await Promise.resolve( [ fooValue, fooValue + 1, fooValue + 2 ] ) @@ -926,7 +951,7 @@ describe( "some", ( ) => describe( "async flat", ( ) => { - it( "should be false on empty array", async ( ) => + it.concurrent( "should be false on empty array", async ( ) => { const input: Array< number > = [ ]; @@ -935,7 +960,8 @@ describe( "some", ( ) => expect( res ).toBe( false ); } ); - it( "should return false on unmatching single-value array", async ( ) => + it.concurrent( "should return false on unmatching single-value array", + async ( ) => { const input = [ fooValue ]; @@ -944,7 +970,8 @@ describe( "some", ( ) => expect( res ).toBe( false ); } ); - it( "should return value on matching single-value array", async ( ) => + it.concurrent( "should return value on matching single-value array", + async ( ) => { const input = [ fooValue ]; @@ -953,7 +980,8 @@ describe( "some", ( ) => expect( res ).toEqual( { val: fooValue } ); } ); - it( "should return false on unmatching multi-value array", async ( ) => + it.concurrent( "should return false on unmatching multi-value array", + async ( ) => { const input = [ fooValue, fooValue + 1, fooValue + 2 ]; @@ -962,7 +990,8 @@ describe( "some", ( ) => expect( res ).toBe( false ); } ); - it( "should return first match in multi-value array", async ( ) => + it.concurrent( "should return first match in multi-value array", + async ( ) => { const input = [ fooValue, fooValue + 1, fooValue + 2 ]; @@ -974,7 +1003,7 @@ describe( "some", ( ) => describe( "async in promise chain", ( ) => { - it( "should be false on empty array", async ( ) => + it.concurrent( "should be false on empty array", async ( ) => { const res = await Promise.resolve( [ ] ) @@ -983,7 +1012,8 @@ describe( "some", ( ) => expect( res ).toBe( false ); } ); - it( "should return false on unmatching single-value array", async ( ) => + it.concurrent( "should return false on unmatching single-value array", + async ( ) => { const res = await Promise.resolve( [ fooValue ] ) @@ -992,7 +1022,8 @@ describe( "some", ( ) => expect( res ).toBe( false ); } ); - it( "should return value on matching single-value array", async ( ) => + it.concurrent( "should return value on matching single-value array", + async ( ) => { const res = await Promise.resolve( [ fooValue ] ) @@ -1001,7 +1032,8 @@ describe( "some", ( ) => expect( res ).toEqual( { val: fooValue } ); } ); - it( "should return false on unmatching multi-value array", async ( ) => + it.concurrent( "should return false on unmatching multi-value array", + async ( ) => { const res = await Promise.resolve( [ fooValue, fooValue + 1, fooValue + 2 ] ) @@ -1010,7 +1042,8 @@ describe( "some", ( ) => expect( res ).toBe( false ); } ); - it( "should return first match in multi-value array", async ( ) => + it.concurrent( "should return first match in multi-value array", + async ( ) => { const res = await Promise.resolve( [ fooValue, fooValue + 1, fooValue + 2 ] ) @@ -1029,14 +1062,15 @@ describe( "some", ( ) => ); } - it( "should be false on empty array", async ( ) => + it.concurrent( "should be false on empty array", async ( ) => { const res = await some( Promise.resolve( [ ] ), asyncSomePred ); expect( res ).toBe( false ); } ); - it( "should return false on unmatching single-value array", async ( ) => + it.concurrent( "should return false on unmatching single-value array", + async ( ) => { const input = promisifyList( [ fooValue ] ); @@ -1045,7 +1079,8 @@ describe( "some", ( ) => expect( res ).toBe( false ); } ); - it( "should return value on matching single-value array", async ( ) => + it.concurrent( "should return value on matching single-value array", + async ( ) => { const input = promisifyList( [ fooValue ] ); @@ -1054,7 +1089,8 @@ describe( "some", ( ) => expect( res ).toEqual( { val: fooValue } ); } ); - it( "should return false on unmatching multi-value array", async ( ) => + it.concurrent( "should return false on unmatching multi-value array", + async ( ) => { const input = promisifyList( [ fooValue, fooValue + 1, fooValue + 2 ] ); @@ -1064,7 +1100,8 @@ describe( "some", ( ) => expect( res ).toBe( false ); } ); - it( "should return first match in multi-value array", async ( ) => + it.concurrent( "should return first match in multi-value array", + async ( ) => { const input = promisifyList( [ fooValue, fooValue + 1, fooValue + 2 ] ); @@ -1097,7 +1134,7 @@ describe( "once", ( ) => expect( spy.mock.calls.length ).toBe( 1 ); } ); - it( "should call asynchronously once", async ( ) => + it.concurrent( "should call asynchronously once", async ( ) => { const spy = jest.fn( delayedFunction( ) ); @@ -1121,7 +1158,8 @@ describe( "once", ( ) => expect( spy.mock.calls.length ).toBe( 1 ); } ); - it( "should call asynchronously once with value", async ( ) => + it.concurrent( "should call asynchronously once with value", + async ( ) => { const spy = jest.fn( delayedFunction( ) ); @@ -1158,7 +1196,7 @@ describe( "once", ( ) => expect( spy1.mock.calls.length ).toBe( 1 ); } ); - it( "should call asynchronously once", async ( ) => + it.concurrent( "should call asynchronously once", async ( ) => { const _once = once( ); @@ -1180,7 +1218,8 @@ describe( "once", ( ) => expect( spy1.mock.calls.length ).toBe( 1 ); } ); - it( "should call asynchronously once (stressed)", async ( ) => + it.concurrent( "should call asynchronously once (stressed)", + async ( ) => { const _once = once( ); @@ -1298,7 +1337,7 @@ describe( "retry", ( ) => `after ${retryTimes} retries ` + `when returning after ${returnAfter} times`; - it( msg, async ( ) => + it.concurrent( msg, async ( ) => { if ( shouldThrow ) { @@ -1318,7 +1357,8 @@ describe( "retry", ( ) => } ); } ); - it( "should rethrow on immediately false predicate", async ( ) => + it.concurrent( "should rethrow on immediately false predicate", + async ( ) => { const thrower = throwFirst( 5, 42 ); @@ -1329,7 +1369,8 @@ describe( "retry", ( ) => expect( result.error ).toBe( testError ); } ); - it( "should rethrow on eventually false predicate", async ( ) => + it.concurrent( "should rethrow on eventually false predicate", + async ( ) => { const thrower = throwFirst( 5, 42 ); @@ -1347,7 +1388,8 @@ describe( "retry", ( ) => describe( "defer", ( ) => { - it( "should work with undefined and no resolve argument", async ( ) => + it.concurrent( "should work with undefined and no resolve argument", + async ( ) => { const deferred = defer( void 0 ); @@ -1357,7 +1399,8 @@ describe( "defer", ( ) => expect( val ).toBe( void 0 ); } ); - it( "should work with undefined and one resolve argument", async ( ) => + it.concurrent( "should work with undefined and one resolve argument", + async ( ) => { const deferred = defer( void 0 ); @@ -1367,7 +1410,7 @@ describe( "defer", ( ) => expect( val ).toBe( void 0 ); } ); - it( "should work with resolving", async ( ) => + it.concurrent( "should work with resolving", async ( ) => { const deferred = defer< number >( ); @@ -1377,7 +1420,7 @@ describe( "defer", ( ) => expect( val ).toBe( fooValue ); } ); - it( "should work with rejecting", async ( ) => + it.concurrent( "should work with rejecting", async ( ) => { const deferred = defer< number >( ); @@ -1399,7 +1442,7 @@ describe( "defer", ( ) => describe( "reflect", ( ) => { - it( "should work with resolved promises", async ( ) => + it.concurrent( "should work with resolved promises", async ( ) => { const p = Promise.resolve( fooValue ); @@ -1413,7 +1456,7 @@ describe( "reflect", ( ) => expect( error ).toBe( void 0 ); } ); - it( "should work with not yet resolved promises", async ( ) => + it.concurrent( "should work with not yet resolved promises", async ( ) => { const p = delay( 1, fooValue ); @@ -1427,7 +1470,7 @@ describe( "reflect", ( ) => expect( error ).toBe( void 0 ); } ); - it( "should work with rejected promises", async ( ) => + it.concurrent( "should work with rejected promises", async ( ) => { const p = Promise.reject( fooError ); @@ -1441,7 +1484,7 @@ describe( "reflect", ( ) => expect( error ).toBe( fooError ); } ); - it( "should work with not yet rejected promises", async ( ) => + it.concurrent( "should work with not yet rejected promises", async ( ) => { const p = delay( 1 ).then( ( ) => { throw fooError; } ); @@ -1459,7 +1502,7 @@ describe( "reflect", ( ) => describe( "inspect", ( ) => { - it( "should work with pending", async ( ) => + it.concurrent( "should work with pending", async ( ) => { const deferred = defer< string >( ); @@ -1476,7 +1519,7 @@ describe( "inspect", ( ) => return inspectable.promise; } ); - it( "should work with resolving", async ( ) => + it.concurrent( "should work with resolving", async ( ) => { const deferred = defer< string >( ); @@ -1493,7 +1536,7 @@ describe( "inspect", ( ) => return inspectable.promise; } ); - it( "should work with rejecting", async ( ) => + it.concurrent( "should work with rejecting", async ( ) => { const deferred = defer< string >( ); @@ -1514,7 +1557,7 @@ describe( "inspect", ( ) => return inspectable.promise.catch( err => { } ); } ); - it( "should be settled after {await}", async ( ) => + it.concurrent( "should be settled after {await}", async ( ) => { const deferred = defer< string >( ); @@ -1533,7 +1576,7 @@ describe( "inspect", ( ) => describe( "deferInspectable", ( ) => { - it( "should resolve and reject", async ( ) => + it.concurrent( "should resolve and reject", async ( ) => { const deferredRes = deferInspectable< string >( ); const deferredRej = deferInspectable< string >( ); @@ -1560,7 +1603,7 @@ describe( "deferInspectable", ( ) => .toBe( "err" ); } ); - it( "should not double-resolve or double-reject", async ( ) => + it.concurrent( "should not double-resolve or double-reject", async ( ) => { const deferredRes = deferInspectable< string >( ); const deferredRej = deferInspectable< string >( ); @@ -2056,7 +2099,7 @@ describe( "wrapFunction", ( ) => } ); - it( "async sync sync noarg noreturn", async ( ) => + it.concurrent( "async sync sync noarg noreturn", async ( ) => { const after = makeSpy( ( ) => { } ); const before = makeSpy0( ( ) => Promise.resolve( after ) ); @@ -2069,7 +2112,7 @@ describe( "wrapFunction", ( ) => expect( after.mock.calls.length ).toBe( 1 ); } ); - it( "async sync sync noarg", async ( ) => + it.concurrent( "async sync sync noarg", async ( ) => { const after = makeSpy( ( ) => { } ); const before = makeSpy0( ( ) => Promise.resolve( after ) ); @@ -2080,7 +2123,7 @@ describe( "wrapFunction", ( ) => expect( after.mock.calls.length ).toBe( 1 ); } ); - it( "async sync sync arg noreturn", async ( ) => + it.concurrent( "async sync sync arg noreturn", async ( ) => { const after = makeSpy( ( ) => { } ); const before = makeSpy( ( s: string ) => Promise.resolve( after ) ); @@ -2093,7 +2136,7 @@ describe( "wrapFunction", ( ) => expect( after.mock.calls.length ).toBe( 1 ); } ); - it( "async sync sync arg", async ( ) => + it.concurrent( "async sync sync arg", async ( ) => { const after = makeSpy( ( ) => { } ); const before = makeSpy( ( s: string ) => Promise.resolve( after ) ); @@ -2105,7 +2148,7 @@ describe( "wrapFunction", ( ) => expect( after.mock.calls.length ).toBe( 1 ); } ); - it( "sync async sync noarg noreturn", async ( ) => + it.concurrent( "sync async sync noarg noreturn", async ( ) => { const after = makeSpy( ( ) => { } ); const before = makeSpy0( ( ) => after ); @@ -2118,7 +2161,7 @@ describe( "wrapFunction", ( ) => expect( after.mock.calls.length ).toBe( 1 ); } ); - it( "sync async sync noarg", async ( ) => + it.concurrent( "sync async sync noarg", async ( ) => { const after = makeSpy( ( ) => { } ); const before = makeSpy0( ( ) => after ); @@ -2131,7 +2174,7 @@ describe( "wrapFunction", ( ) => expect( after.mock.calls.length ).toBe( 1 ); } ); - it( "sync async sync arg noreturn", async ( ) => + it.concurrent( "sync async sync arg noreturn", async ( ) => { const after = makeSpy( ( ) => { } ); const before = makeSpy( ( s: string ) => after ); @@ -2144,7 +2187,7 @@ describe( "wrapFunction", ( ) => expect( after.mock.calls.length ).toBe( 1 ); } ); - it( "sync async sync arg", async ( ) => + it.concurrent( "sync async sync arg", async ( ) => { const after = makeSpy( ( ) => { } ); const before = makeSpy( ( s: string ) => after ); @@ -2158,7 +2201,7 @@ describe( "wrapFunction", ( ) => } ); - it( "async async sync noarg", async ( ) => + it.concurrent( "async async sync noarg", async ( ) => { const after = makeSpy( ( ) => { } ); const before = makeSpy0( ( ) => Promise.resolve( after ) ); @@ -2171,7 +2214,7 @@ describe( "wrapFunction", ( ) => expect( after.mock.calls.length ).toBe( 1 ); } ); - it( "async async sync arg", async ( ) => + it.concurrent( "async async sync arg", async ( ) => { const after = makeSpy( ( ) => { } ); const before = makeSpy( ( s: string ) => Promise.resolve( after ) ); @@ -2186,7 +2229,7 @@ describe( "wrapFunction", ( ) => expect( after.mock.calls.length ).toBe( 1 ); } ); - it( "sync sync async noarg", async ( ) => + it.concurrent( "sync sync async noarg", async ( ) => { const after = makeSpy( ( ) => Promise.resolve( ) ); const before = makeSpy0( ( ) => after ); @@ -2197,7 +2240,7 @@ describe( "wrapFunction", ( ) => expect( after.mock.calls.length ).toBe( 1 ); } ); - it( "sync sync async arg", async ( ) => + it.concurrent( "sync sync async arg", async ( ) => { const after = makeSpy( ( ) => Promise.resolve( ) ); const before = makeSpy( ( s: string ) => after ); @@ -2211,7 +2254,7 @@ describe( "wrapFunction", ( ) => } ); - it( "async sync async noarg noreturn", async ( ) => + it.concurrent( "async sync async noarg noreturn", async ( ) => { const after = makeSpy( ( ) => Promise.resolve( ) ); const before = makeSpy0( ( ) => Promise.resolve( after ) ); @@ -2224,7 +2267,7 @@ describe( "wrapFunction", ( ) => expect( after.mock.calls.length ).toBe( 1 ); } ); - it( "async sync async noarg", async ( ) => + it.concurrent( "async sync async noarg", async ( ) => { const after = makeSpy( ( ) => Promise.resolve( ) ); const before = makeSpy0( ( ) => Promise.resolve( after ) ); @@ -2235,7 +2278,7 @@ describe( "wrapFunction", ( ) => expect( after.mock.calls.length ).toBe( 1 ); } ); - it( "async sync async arg noreturn", async ( ) => + it.concurrent( "async sync async arg noreturn", async ( ) => { const after = makeSpy( ( ) => Promise.resolve( ) ); const before = makeSpy( ( s: string ) => Promise.resolve( after ) ); @@ -2248,7 +2291,7 @@ describe( "wrapFunction", ( ) => expect( after.mock.calls.length ).toBe( 1 ); } ); - it( "async sync async arg", async ( ) => + it.concurrent( "async sync async arg", async ( ) => { const after = makeSpy( ( ) => Promise.resolve( ) ); const before = makeSpy( ( s: string ) => Promise.resolve( after ) ); @@ -2261,7 +2304,7 @@ describe( "wrapFunction", ( ) => expect( after.mock.calls.length ).toBe( 1 ); } ); - it( "sync async async noarg", async ( ) => + it.concurrent( "sync async async noarg", async ( ) => { const after = makeSpy( ( ) => Promise.resolve( ) ); const before = makeSpy0( ( ) => after ); @@ -2274,7 +2317,7 @@ describe( "wrapFunction", ( ) => expect( after.mock.calls.length ).toBe( 1 ); } ); - it( "sync async async noarg timing", async ( ) => + it.concurrent( "sync async async noarg timing", async ( ) => { const after = makeSpy( ( ) => delay( 10 ) ); const before = makeSpy0( ( ) => after ); @@ -2292,7 +2335,7 @@ describe( "wrapFunction", ( ) => expect( after.mock.calls.length ).toBe( 1 ); } ); - it( "sync async async arg", async ( ) => + it.concurrent( "sync async async arg", async ( ) => { const after = makeSpy( ( ) => Promise.resolve( ) ); const before = makeSpy( ( s: string ) => after ); @@ -2308,7 +2351,7 @@ describe( "wrapFunction", ( ) => } ); - it( "async async async noarg", async ( ) => + it.concurrent( "async async async noarg", async ( ) => { const after = makeSpy( ( ) => Promise.resolve( ) ); const before = makeSpy0( ( ) => Promise.resolve( after ) ); @@ -2321,7 +2364,7 @@ describe( "wrapFunction", ( ) => expect( after.mock.calls.length ).toBe( 1 ); } ); - it( "async async async arg", async ( ) => + it.concurrent( "async async async arg", async ( ) => { const after = makeSpy( ( ) => Promise.resolve( ) ); const before = makeSpy( ( s: string ) => Promise.resolve( after ) ); @@ -2337,7 +2380,7 @@ describe( "wrapFunction", ( ) => } ); } ); - it( "Invalid (missing) argument", async ( ) => + it.concurrent( "Invalid (missing) argument", async ( ) => { const after = makeSpy( ( ) => Promise.resolve( ) ); const before = makeSpy( ( s: string ) => Promise.resolve( after ) ); @@ -2362,7 +2405,7 @@ describe( "wrapFunction", ( ) => expect( after.mock.calls.length ).toBe( 0 ); } ); - it( 'Empty return from "before"', async ( ) => + it.concurrent( 'Empty return from "before"', async ( ) => { const before = makeSpy( ( s: string ) => < ( ) => { } >< any >null ); @@ -2373,7 +2416,7 @@ describe( "wrapFunction", ( ) => expect( before.mock.calls ).toEqual( [ [ "foo" ] ] ); } ); - it( 'Illegal return value from "before"', async ( ) => + it.concurrent( 'Illegal return value from "before"', async ( ) => { const before = makeSpy( ( s: string ) => < ( ) => { } >< any >"bad" ); @@ -2396,7 +2439,7 @@ describe( "wrapFunction", ( ) => expect( before.mock.calls ).toEqual( [ [ "foo" ] ] ); } ); - it( 'Async throw in "before"', async ( ) => + it.concurrent( 'Async throw in "before"', async ( ) => { const before = makeSpy( ( s: string ) => Promise.reject( new Error( "foobar" ) )