Skip to content

Commit 372d419

Browse files
authored
chore: step timeout improvements (#34386)
1 parent 9970446 commit 372d419

File tree

3 files changed

+36
-4
lines changed

3 files changed

+36
-4
lines changed

docs/src/test-api/class-test.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1822,7 +1822,7 @@ Maximum time in milliseconds for the step to finish. Defaults to `0` (no timeout
18221822
* since: v1.50
18231823
- `timeout` <[float]>
18241824

1825-
Maximum time in milliseconds for the step to finish. Defaults to `0` (no timeout).
1825+
The maximum time, in milliseconds, allowed for the step to complete. If the step does not complete within the specified timeout, the [`method: Test.step`] method will throw a [TimeoutError]. Defaults to `0` (no timeout).
18261826

18271827
## method: Test.use
18281828
* since: v1.10

packages/playwright/src/common/testType.ts

+13-2
Original file line numberDiff line numberDiff line change
@@ -270,9 +270,20 @@ export class TestTypeImpl {
270270
const step = testInfo._addStep({ category: 'test.step', title, location: options.location, box: options.box });
271271
return await zones.run('stepZone', step, async () => {
272272
try {
273-
const result = await raceAgainstDeadline(async () => body(), options.timeout ? monotonicTime() + options.timeout : 0);
273+
let result: Awaited<ReturnType<typeof raceAgainstDeadline<T>>> | undefined = undefined;
274+
result = await raceAgainstDeadline(async () => {
275+
try {
276+
return await body();
277+
} catch (e) {
278+
// If the step timed out, the test fixtures will tear down, which in turn
279+
// will abort unfinished actions in the step body. Record such errors here.
280+
if (result?.timedOut)
281+
testInfo._failWithError(e);
282+
throw e;
283+
}
284+
}, options.timeout ? monotonicTime() + options.timeout : 0);
274285
if (result.timedOut)
275-
throw new errors.TimeoutError(`Step timeout ${options.timeout}ms exceeded.`);
286+
throw new errors.TimeoutError(`Step timeout of ${options.timeout}ms exceeded.`);
276287
step.complete({});
277288
return result.result;
278289
} catch (error) {

tests/playwright-test/test-step.spec.ts

+22-1
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ test('step timeout option', async ({ runInlineTest }) => {
399399
}, { reporter: '', workers: 1 });
400400
expect(result.exitCode).toBe(1);
401401
expect(result.failed).toBe(1);
402-
expect(result.output).toContain('Error: Step timeout 100ms exceeded.');
402+
expect(result.output).toContain('Error: Step timeout of 100ms exceeded.');
403403
});
404404

405405
test('step timeout longer than test timeout', async ({ runInlineTest }) => {
@@ -422,6 +422,27 @@ test('step timeout longer than test timeout', async ({ runInlineTest }) => {
422422
expect(result.output).toContain('Test timeout of 900ms exceeded.');
423423
});
424424

425+
test('step timeout includes interrupted action errors', async ({ runInlineTest }) => {
426+
const result = await runInlineTest({
427+
'a.test.ts': `
428+
import { test, expect } from '@playwright/test';
429+
test('step with timeout', async ({ page }) => {
430+
await test.step('my step', async () => {
431+
await page.waitForTimeout(100_000);
432+
}, { timeout: 1000 });
433+
});
434+
`
435+
}, { reporter: '', workers: 1 });
436+
expect(result.exitCode).toBe(1);
437+
expect(result.failed).toBe(1);
438+
// Should include 2 errors, one for the step timeout and one for the aborted action.
439+
expect.soft(result.output).toContain('TimeoutError: Step timeout of 1000ms exceeded.');
440+
expect.soft(result.output).toContain(`> 4 | await test.step('my step', async () => {`);
441+
expect.soft(result.output).toContain('Error: page.waitForTimeout: Test ended.');
442+
expect.soft(result.output.split('Error: page.waitForTimeout: Test ended.').length).toBe(2);
443+
expect.soft(result.output).toContain('> 5 | await page.waitForTimeout(100_000);');
444+
});
445+
425446
test('step timeout is errors.TimeoutError', async ({ runInlineTest }) => {
426447
const result = await runInlineTest({
427448
'a.test.ts': `

0 commit comments

Comments
 (0)