diff --git a/oxlint-suppressions.json b/oxlint-suppressions.json index 06b2fb3c82..9315e29b97 100644 --- a/oxlint-suppressions.json +++ b/oxlint-suppressions.json @@ -549,11 +549,6 @@ "count": 2 } }, - "src/lib/async/until.ts": { - "typescript/no-explicit-any": { - "count": 2 - } - }, "src/lib/broadcast/stub.ts": { "typescript/no-explicit-any": { "count": 1 diff --git a/src/lib/async/until.test.ts b/src/lib/async/until.test.ts new file mode 100644 index 0000000000..e5b810df48 --- /dev/null +++ b/src/lib/async/until.test.ts @@ -0,0 +1,29 @@ +import {describe, expect, it, jest} from '@jest/globals' + +import {until} from './until' + +describe('until', () => { + it('does not invoke the condition when an attempt rejects', async () => { + const fn = jest + .fn<() => Promise>() + .mockRejectedValueOnce(new Error('failed')) + .mockResolvedValue('ready') + const cond = jest.fn((value: string) => value === 'ready') + + await expect(until(2, 0, cond, fn)).resolves.toBe(true) + expect(fn).toHaveBeenCalledTimes(2) + expect(cond).toHaveBeenCalledTimes(1) + expect(cond).toHaveBeenCalledWith('ready') + }) + + it('returns false when every attempt rejects', async () => { + const fn = jest + .fn<() => Promise>() + .mockRejectedValue(new Error('failed')) + const cond = jest.fn((_value: string) => true) + + await expect(until(2, 0, cond, fn)).resolves.toBe(false) + expect(fn).toHaveBeenCalledTimes(2) + expect(cond).not.toHaveBeenCalled() + }) +}) diff --git a/src/lib/async/until.ts b/src/lib/async/until.ts index 1b7a576334..970f303f2e 100644 --- a/src/lib/async/until.ts +++ b/src/lib/async/until.ts @@ -3,21 +3,20 @@ import {timeout} from './timeout' export async function until( retries: number, delay: number, - cond: (v: T, err: any) => boolean, + cond: (v: T) => boolean, fn: () => Promise, ): Promise { while (retries > 0) { + let v: T try { - const v = await fn() - if (cond(v, undefined)) { - return true - } - } catch (e: any) { - // TODO: change the type signature of cond to accept undefined - // however this breaks every existing usage of until -sfn - if (cond(undefined as unknown as T, e)) { - return true - } + v = await fn() + } catch { + await timeout(delay) + retries-- + continue + } + if (cond(v)) { + return true } await timeout(delay) retries--