diff --git a/docs/src/test-api/class-testconfig.md b/docs/src/test-api/class-testconfig.md index 09d0558d33..926b3eca6d 100644 --- a/docs/src/test-api/class-testconfig.md +++ b/docs/src/test-api/class-testconfig.md @@ -52,6 +52,8 @@ export default defineConfig({ - `threshold` ?<[float]> an acceptable perceived color difference between the same pixel in compared images, ranging from `0` (strict) and `1` (lax). `"pixelmatch"` comparator computes color difference in [YIQ color space](https://en.wikipedia.org/wiki/YIQ) and defaults `threshold` value to `0.2`. - `maxDiffPixels` ?<[int]> an acceptable amount of pixels that could be different, unset by default. - `maxDiffPixelRatio` ?<[float]> an acceptable ratio of pixels that are different to the total amount of pixels, between `0` and `1` , unset by default. + - `toPass` ?<[Object]> Configuration for the [expect(value).toPass()](../test-assertions.md#expecttopass) method. + - `timeout` ?<[int]> timeout for toPass method in milliseconds. Configuration for the `expect` assertion library. Learn more about [various timeouts](../test-timeouts.md). diff --git a/docs/src/test-api/class-testproject.md b/docs/src/test-api/class-testproject.md index 338910db71..61a1cc5b5c 100644 --- a/docs/src/test-api/class-testproject.md +++ b/docs/src/test-api/class-testproject.md @@ -102,6 +102,8 @@ export default defineConfig({ - `threshold` ?<[float]> an acceptable perceived color difference between the same pixel in compared images, ranging from `0` (strict) and `1` (lax). `"pixelmatch"` comparator computes color difference in [YIQ color space](https://en.wikipedia.org/wiki/YIQ) and defaults `threshold` value to `0.2`. - `maxDiffPixels` ?<[int]> an acceptable amount of pixels that could be different, unset by default. - `maxDiffPixelRatio` ?<[float]> an acceptable ratio of pixels that are different to the total amount of pixels, between `0` and `1` , unset by default. + - `toPass` ?<[Object]> Configuration for the [expect(value).toPass()](../test-assertions.md) method. + - `timeout` ?<[int]> timeout for toPass method in milliseconds. Configuration for the `expect` assertion library. diff --git a/packages/playwright/src/matchers/matchers.ts b/packages/playwright/src/matchers/matchers.ts index 91bdc3701b..3dc08ba223 100644 --- a/packages/playwright/src/matchers/matchers.ts +++ b/packages/playwright/src/matchers/matchers.ts @@ -25,6 +25,7 @@ import { constructURLBasedOnBaseURL, isRegExp, isTextualMimeType, pollAgainstDea import { currentTestInfo } from '../common/globals'; import { TestInfoImpl } from '../worker/testInfo'; import type { ExpectMatcherContext } from './expect'; +import { takeFirst } from '../common/config'; interface LocatorEx extends Locator { _expect(expression: string, options: Omit & { expectedValue?: any }): Promise<{ matches: boolean, received?: any, log?: string[], timedOut?: boolean }>; @@ -367,7 +368,7 @@ export async function toPass( } = {}, ) { const testInfo = currentTestInfo(); - const timeout = options.timeout !== undefined ? options.timeout : 0; + const timeout = takeFirst(options.timeout, testInfo?._projectInternal.expect?.toPass?.timeout, 0); const { deadline, timeoutMessage } = testInfo ? testInfo._deadlineForMatcher(timeout) : TestInfoImpl._defaultDeadlineForMatcher(timeout); const result = await pollAgainstDeadline(async () => { diff --git a/packages/playwright/types/test.d.ts b/packages/playwright/types/test.d.ts index bbbcdb4c53..f2bc93ad3c 100644 --- a/packages/playwright/types/test.d.ts +++ b/packages/playwright/types/test.d.ts @@ -693,6 +693,16 @@ interface TestConfig { */ maxDiffPixelRatio?: number; }; + + /** + * Configuration for the [expect(value).toPass()](https://playwright.dev/docs/test-assertions#expecttopass) method. + */ + toPass?: { + /** + * timeout for toPass method in milliseconds. + */ + timeout?: number; + }; }; /** @@ -6827,6 +6837,16 @@ interface TestProject { */ maxDiffPixelRatio?: number; }; + + /** + * Configuration for the [expect(value).toPass()](https://playwright.dev/docs/test-assertions) method. + */ + toPass?: { + /** + * timeout for toPass method in milliseconds. + */ + timeout?: number; + }; }; /** diff --git a/tests/playwright-test/expect-to-pass.spec.ts b/tests/playwright-test/expect-to-pass.spec.ts index 2c73283930..2ad00e0ce7 100644 --- a/tests/playwright-test/expect-to-pass.spec.ts +++ b/tests/playwright-test/expect-to-pass.spec.ts @@ -220,3 +220,43 @@ test('should show intermediate result for toPass that spills over test time', as expect(result.output).toContain('Expected: 2'); expect(result.output).toContain('Received: 3'); }); + +test('should respect timeout in config file when timeout parameter is not passed', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'playwright.config.js': `module.exports = { expect: { toPass: { timeout: 100 } } }`, + 'a.spec.ts': ` + import { test, expect } from '@playwright/test'; + test('should fail', async () => { + await test.expect(() => { + expect(1).toBe(2); + }).toPass(); + }); + ` + }); + expect(result.exitCode).toBe(1); + expect(result.output).toContain('Timeout 100ms exceeded while waiting on the predicate'); + expect(result.output).toContain('Received: 1'); + expect(result.output).toContain(` + 4 | await test.expect(() => { + `.trim()); +}); + +test('should give priority to timeout parameter over timeout in config file', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'playwright.config.js': `module.exports = { expect: { toPass: { timeout: 100 } } }`, + 'a.spec.ts': ` + import { test, expect } from '@playwright/test'; + test('should fail', async () => { + await test.expect(() => { + expect(1).toBe(2); + }).toPass({ timeout: 200 }); + }); + ` + }); + expect(result.exitCode).toBe(1); + expect(result.output).toContain('Timeout 200ms exceeded while waiting on the predicate'); + expect(result.output).toContain('Received: 1'); + expect(result.output).toContain(` + 4 | await test.expect(() => { + `.trim()); +});