diff --git a/packages/playwright/src/matchers/expect.ts b/packages/playwright/src/matchers/expect.ts index 102ec98d9a..2bf73ef3ac 100644 --- a/packages/playwright/src/matchers/expect.ts +++ b/packages/playwright/src/matchers/expect.ts @@ -243,6 +243,8 @@ class ExpectMetaInfoProxyHandler implements ProxyHandler { } return (...args: any[]) => { const testInfo = currentTestInfo(); + // We assume that the matcher will read the current expect timeout the first thing. + setCurrentExpectConfigureTimeout(this._info.timeout); if (!testInfo) return matcher.call(target, ...args); @@ -282,8 +284,7 @@ class ExpectMetaInfoProxyHandler implements ProxyHandler { }; const expectZone: ExpectZone = { title, wallTime }; - // We assume that the matcher will read the current expect timeout the first thing. - setCurrentExpectConfigureTimeout(this._info.timeout); + try { const result = zones.run('expectZone', expectZone, () => matcher.call(target, ...args)); if (result instanceof Promise) diff --git a/tests/playwright-test/expect.spec.ts b/tests/playwright-test/expect.spec.ts index e56034c886..d5d4b338fa 100644 --- a/tests/playwright-test/expect.spec.ts +++ b/tests/playwright-test/expect.spec.ts @@ -16,6 +16,7 @@ import path from 'path'; import { test, expect, parseTestRunnerOutput, stripAnsi } from './playwright-test-fixtures'; +const { spawnAsync } = require('../../packages/playwright-core/lib/utils'); test('should be able to call expect.extend in config', async ({ runInlineTest }) => { const result = await runInlineTest({ @@ -964,3 +965,38 @@ test('should support mergeExpects', async ({ runInlineTest }) => { expect(result.passed).toBe(1); expect(result.exitCode).toBe(0); }); + +test('should respect timeout from configured expect when used outside of the test runner', async ({ runInlineTest, writeFiles, runTSC }) => { + + const files = { + 'script.mjs': ` + import { test, expect as baseExpect, chromium } from '@playwright/test'; + + const configuredExpect = baseExpect.configure({ + timeout: 10, + }); + + let browser; + try { + browser = await chromium.launch(); + const context = await browser.newContext(); + const page = await context.newPage(); + await configuredExpect(page.getByTestId("does-not-exist")).toBeAttached(); + } catch(e) { + console.error(e); + process.exit(1); + } + finally { + await browser?.close(); + } + + ` + }; + const baseDir = await writeFiles(files); + const { code, stdout, stderr } = await spawnAsync('node', ['script.mjs'], { stdio: 'pipe', cwd: baseDir }); + + + expect(code).toBe(1); + expect(stdout).toBe(''); + expect(stripAnsi(stderr)).toContain('Timed out 10ms waiting for expect(locator).toBeAttached()'); +});