diff --git a/docs/02-execution-context.md b/docs/02-execution-context.md index 65200eed0..ae398fa2c 100644 --- a/docs/02-execution-context.md +++ b/docs/02-execution-context.md @@ -45,3 +45,5 @@ You cannot use `t.teardown()` in hooks either. ## `t.timeout(ms)` Set a timeout for the test, in milliseconds. The test will fail if this timeout is exceeded. The timeout is reset each time an assertion is made. + +Use `t.timeout.clear()` to clear the timeout and restore the default behavior. diff --git a/lib/test.js b/lib/test.js index 1e6922532..40782171f 100644 --- a/lib/test.js +++ b/lib/test.js @@ -79,6 +79,10 @@ class ExecutionContext extends Assertions { test.timeout(ms, message); }; + this.timeout.clear = () => { + test.clearTimeout(); + }; + this.teardown = callback => { test.addTeardown(callback); }; @@ -289,7 +293,6 @@ export default class Test { this.pendingAttemptCount = 0; this.planCount = null; this.startedAt = 0; - this.timeoutMs = 0; this.timeoutTimer = null; } @@ -418,7 +421,6 @@ export default class Test { } this.clearTimeout(); - this.timeoutMs = ms; this.timeoutTimer = nowAndTimers.setCappedTimeout(() => { this.saveFirstError(new Error(message ?? 'Test timeout exceeded')); @@ -427,19 +429,11 @@ export default class Test { } }, ms); - this.notifyTimeoutUpdate(this.timeoutMs); + this.notifyTimeoutUpdate(ms); } refreshTimeout() { - if (!this.timeoutTimer) { - return; - } - - if (this.timeoutTimer.refresh) { - this.timeoutTimer.refresh(); - } else { - this.timeout(this.timeoutMs); - } + this.timeoutTimer?.refresh(); } clearTimeout() { diff --git a/test-tap/test.js b/test-tap/test.js index 4a8e41938..261e108e2 100644 --- a/test-tap/test.js +++ b/test-tap/test.js @@ -589,6 +589,18 @@ test('timeout is refreshed on assert', {skip: ciInfo.isCI}, t => ava(async a => t.equal(result.passed, true); })); +test('timeout can be cleared', {skip: ciInfo.isCI}, t => ava(async a => { + a.timeout(100); + a.plan(2); + await Promise.all([ + delay(50).then(() => a.pass()), + delay(100).then(() => a.timeout.clear()), + delay(350).then(() => a.pass()), + ]); +}).run().then(result => { + t.equal(result.passed, true); +})); + test('teardown passing test', t => { const teardown = sinon.spy(); return ava(a => { diff --git a/test-types/import-in-cts/timeout.cts b/test-types/import-in-cts/timeout.cts new file mode 100644 index 000000000..40770e9dc --- /dev/null +++ b/test-types/import-in-cts/timeout.cts @@ -0,0 +1,6 @@ +import test from '../../entrypoints/main.cjs'; + +test('test', t => { + t.timeout(100); + t.timeout.clear(); +}); diff --git a/test-types/module/timeout.ts b/test-types/module/timeout.ts new file mode 100644 index 000000000..c96a5b647 --- /dev/null +++ b/test-types/module/timeout.ts @@ -0,0 +1,6 @@ +import test from '../../entrypoints/main.mjs'; + +test('test', t => { + t.timeout(100); + t.timeout.clear(); +}); diff --git a/test/watch-mode/helpers/watch.js b/test/watch-mode/helpers/watch.js index bd7cd21d6..ab553cdae 100644 --- a/test/watch-mode/helpers/watch.js +++ b/test/watch-mode/helpers/watch.js @@ -88,7 +88,7 @@ export const withFixture = fixture => async (t, task) => { idlePromise = new Promise(() => {}); assertingIdle = false; // TODO: When testing using AVA 6, enable for better managed timeouts. - // t.timeout(0); + // t.timeout.clear(); if (failedIdleAssertion) { failedIdleAssertion = false; t.fail('Watcher performed a test run while it should have been idle'); diff --git a/types/test-fn.d.cts b/types/test-fn.d.cts index 8eb16785d..e64e4ffee 100644 --- a/types/test-fn.d.cts +++ b/types/test-fn.d.cts @@ -39,11 +39,16 @@ export type PlanFn = { skip(count: number): void; }; -/** - * Set a timeout for the test, in milliseconds. The test will fail if the timeout is exceeded. - * The timeout is reset each time an assertion is made. - */ -export type TimeoutFn = (ms: number, message?: string) => void; +export type TimeoutFn = { + /** + * Set a timeout for the test, in milliseconds. The test will fail if the timeout is exceeded. + * The timeout is reset each time an assertion is made. + */ + (ms: number, message?: string): void; + + /** Clear the timeout and restore the default behavior. */ + clear(): void; +} /** Declare a function to be run after the test has ended. */ export type TeardownFn = (fn: (() => Promise) | (() => void)) => void;