diff --git a/src/__tests__/utils/polling.test.ts b/src/__tests__/utils/polling.test.ts index c62d325..90cb20e 100644 --- a/src/__tests__/utils/polling.test.ts +++ b/src/__tests__/utils/polling.test.ts @@ -58,16 +58,25 @@ describe('utils/polling.poll_until', ()=>{ expect(result.last_status).toBe('ready'); }); - it('throws timeout error when status never completes', async()=>{ - const fetch_once = vi.fn<() => Promise>() - .mockResolvedValue({status: 'running'}); - await expect(poll_until({ - timeout_seconds: 2, - fetch_once, - get_status: (r: Poll_item)=>r.status, - running_statuses: ['running'], - interval_ms: 0, - timeout_label: 'data', - })).rejects.toThrow('Timeout after 2 seconds waiting for data.'); + it('throws timeout error when the wall-clock budget passes', async()=>{ + vi.useFakeTimers(); + try { + const fetch_once = vi.fn<() => Promise>() + .mockResolvedValue({status: 'running'}); + const promise = poll_until({ + timeout_seconds: 2, + fetch_once, + get_status: (r: Poll_item)=>r.status, + running_statuses: ['running'], + interval_ms: 1000, + timeout_label: 'data', + }); + const assertion = expect(promise).rejects.toThrow( + 'Timeout after 2 seconds waiting for data.'); + await vi.advanceTimersByTimeAsync(2000); + await assertion; + } finally { + vi.useRealTimers(); + } }); }); diff --git a/src/utils/polling.ts b/src/utils/polling.ts index a19b483..505130a 100644 --- a/src/utils/polling.ts +++ b/src/utils/polling.ts @@ -46,27 +46,38 @@ const parse_timeout = ( const poll_until = async(opts: Poll_opts): Promise>=>{ const interval_ms = opts.interval_ms ?? DEFAULT_POLL_INTERVAL_MS; const timeout_label = opts.timeout_label ?? 'completion'; - for (let attempt=0; attempt= deadline) + break; await sleep(interval_ms); } throw new Error(