/* eslint-disable vitest/no-conditional-expect */ import {TimeoutError} from '../../errors/TimeoutError'; import {eventually} from '../eventually'; describe('eventually', () => { describe('Pass', () => { it('should with async function', async () => { // eslint-disable-next-line @typescript-eslint/no-confusing-void-expression const result = await eventually(async () => undefined); expect(result).toBe(undefined); }); it('should with sync function', async () => { // eslint-disable-next-line @typescript-eslint/no-confusing-void-expression const result = await eventually(() => undefined); expect(result).toBe(undefined); }); it('should with sync function returning string', async () => { // eslint-disable-next-line @typescript-eslint/no-confusing-void-expression const result = await eventually(() => 'SOME_STRING'); expect(result).toBe(undefined); }); it('should pass from 2-nd time', async () => { let tryCounter = 1; // eslint-disable-next-line @typescript-eslint/no-confusing-void-expression const result = await eventually(async () => { if (tryCounter === 2) { return; } tryCounter++; throw new Error('TEST_ERROR'); }); expect(result).toBe(undefined); expect(tryCounter).toBe(2); }); }); describe('Not pass', () => { it('should retry for 1 second with 30 ms delay by default and fail', async () => { const before = Date.now(); try { await eventually(() => { throw new Error('error_message'); }); } catch (e) { expect((e as Error).message).toMatch('[timeout=1_000]'); expect((e as Error).message).toMatch('error_message'); const timeElapsed = Date.now() - before; expect(timeElapsed).toBeGreaterThan(900); expect(timeElapsed).toBeLessThan(1_100); } }); it('should allow to set custom timeout', async () => { const before = Date.now(); try { await eventually( () => { throw new Error('error_message'); }, {timeout: 2_000}, ); } catch (e) { expect((e as Error).message).toMatch('[timeout=2_000]'); expect((e as Error).message).toMatch('error_message'); expect(Date.now() - before).toBeGreaterThan(1_900); expect(Date.now() - before).toBeLessThan(2_600); } }); it('should be able to work with shorthand timeout param', async () => { try { await eventually(async () => { throw new Error('error'); }, 10); } catch (e) { expect(e).toBeInstanceOf(TimeoutError); expect((e as Error).message).toContain('eventually [timeout=10]'); } }); it('should not pass if error thrown', async () => { try { await eventually( async () => { throw new Error('error'); }, {timeout: 10}, ); } catch (e) { expect(e).toBeInstanceOf(TimeoutError); expect((e as Error).message).toContain('eventually [timeout=10]'); } }); it('should show id if defined and error is thrown', async () => { try { await eventually( async function someTest() { throw new Error('error'); }, { timeout: 10, id: 'SOME_ID_FOR_DEBUG', }, ); } catch (e) { expect(e).toBeInstanceOf(Error); expect((e as Error).message).toContain('eventually [id=SOME_ID_FOR_DEBUG] [timeout=10]'); expect((e as Error).message).toContain(`\nasync function someTest() {\n throw new Error("error");\n}`); } }); }); });