Created
June 1, 2022 13:41
-
-
Save felipepodesta/11a2e9aa83e992258e5e0eed89e3d20c to your computer and use it in GitHub Desktop.
Revisions
-
VinceOPS revised this gist
Apr 29, 2019 . 2 changed files with 24 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -51,4 +51,26 @@ describe('waitForAssertion', () => { expect(e).toBeInstanceOf(TimeoutError); } }); it('throws forward instances of TypeError', async () => { try { await waitForAssertion(() => { const failedInjectionService: any = {}; failedInjectionService.foo(); }); } catch (e) { expect(e).toBeInstanceOf(TypeError); } }); it('throws forward instances of ReferenceError', async () => { try { await waitForAssertion(() => { // @ts-ignore b.foo(); }); } catch (e) { expect(e).toBeInstanceOf(ReferenceError); } }); }); This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,4 +1,4 @@ import { from, interval, throwError } from 'rxjs'; import { catchError, first, switchMap, timeout } from 'rxjs/operators'; /** @@ -24,7 +24,7 @@ export function waitForAssertion(assertion: () => any, timeoutDelay: number = 10 return interval(intervalDelay) .pipe( switchMap(() => from(Promise.resolve(assertion()))), catchError((err, o) => (err instanceof ReferenceError || err instanceof TypeError ? throwError(err) : o)), first(), timeout(timeoutDelay), ) -
VinceOPS created this gist
Dec 10, 2018 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,54 @@ import { TimeoutError } from 'rxjs'; import { waitForAssertion } from './wait-for-assertion'; describe('waitForAssertion', () => { let mockWitness: jest.Mock; beforeEach(() => { mockWitness = jest.fn().mockReturnValue(false); }); describe('Waits both synchronous and asynchronous callbacks', () => { let intervalsCount: number; let intervalDelay: number; let delayBeforeSuccessTrigger: number; let timeoutDelay: number; beforeEach(() => { intervalsCount = 4; intervalDelay = 20; delayBeforeSuccessTrigger = (intervalsCount + 1) * intervalDelay; // safety margin: use more than the expected execution time as timeout delay timeoutDelay = 3 * intervalsCount * intervalDelay; }); it('waits for an asynchronous assertion to succeed', async () => { setTimeout(() => mockWitness.mockReturnValue(true), delayBeforeSuccessTrigger); await waitForAssertion(() => expect(mockWitness()).toBe(true), timeoutDelay, intervalDelay); // "success" is triggered after `intervalsCount` + 1 cycles, so expect at least `intervalCount` calls expect(mockWitness.mock.calls.length).toBeGreaterThanOrEqual(intervalsCount); }); it('also works with async closures', async () => { setTimeout(() => mockWitness.mockResolvedValue(true), delayBeforeSuccessTrigger); await waitForAssertion(() => expect(mockWitness()).resolves.toEqual(true), timeoutDelay, intervalDelay); expect(mockWitness.mock.calls.length).toBeGreaterThanOrEqual(intervalsCount); }); }); it('throws a TimeoutError if the assertion did not succeed', async () => { const expectedCyclesCount = 4; const intervalDelay = 100; const timeoutDelay = (expectedCyclesCount + 1) * intervalDelay; expect.assertions(expectedCyclesCount + 1); try { await waitForAssertion(() => expect(mockWitness()).toBe(true), timeoutDelay, intervalDelay); } catch (e) { expect(e).toBeInstanceOf(TimeoutError); } }); }); This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,32 @@ import { from, interval } from 'rxjs'; import { catchError, first, switchMap, timeout } from 'rxjs/operators'; /** * Wait for any assertion or group of assertions to succeed, or timeout. * * Run (through a promise) the given function `assertion` every `intervalDelay` milliseconds * until it stops throwing or until `timeoutDelay` is passed (timeout). * * @param assertion Closure containing all assertions to be made (calls of `expect()`). * @param timeoutDelay How long should the assertion be repeated until it passes (or times out). * @param intervalDelay How often should the assertion be repeated during `timeoutDelay`. * * @return Resolve on success, or reject with a `TimeoutError`. * * @example * // in a test, where we need to ensure a value is asynchronously updated in elasticsearch * await waitForAssertion(async () => { * const { document } = await elasticsearchService.get(UserIndex, userId); * return expect(document.firstName).toBe(updatedUser.firstName); * }); */ export function waitForAssertion(assertion: () => any, timeoutDelay: number = 1000, intervalDelay: number = 100) { return interval(intervalDelay) .pipe( switchMap(() => from(Promise.resolve(assertion()))), catchError((err, o) => o), first(), timeout(timeoutDelay), ) .toPromise(); }