diff --git a/packages/browser/src/client/tester/tester-utils.ts b/packages/browser/src/client/tester/tester-utils.ts index 8acd995fc..60044062a 100644 --- a/packages/browser/src/client/tester/tester-utils.ts +++ b/packages/browser/src/client/tester/tester-utils.ts @@ -245,11 +245,10 @@ export function processTimeoutOptions(options_: const currentTime = now() const endTime = startTime + timeout const remainingTime = Math.floor(endTime - currentTime) - if (remainingTime <= 0) { - return options_ - } - // give us some time to process the timeout - options_.timeout = remainingTime - 100 + // keep some buffer to process the timeout, but always hand the provider a + // positive value so it surfaces a descriptive, source-mapped locator error + // instead of letting the task timer win the race with a generic timeout + options_.timeout = Math.max(remainingTime - 100, 1) return options_ } diff --git a/test/browser/fixtures/timeout-hooks/hooks-timeout.test.ts b/test/browser/fixtures/timeout-hooks/hooks-timeout.test.ts index dddb7a101..5cc0e0b71 100644 --- a/test/browser/fixtures/timeout-hooks/hooks-timeout.test.ts +++ b/test/browser/fixtures/timeout-hooks/hooks-timeout.test.ts @@ -4,16 +4,16 @@ import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, onTes describe.runIf(server.provider === 'playwright')('timeouts are failing correctly', () => { it('click on non-existing element fails', async () => { await page.getByRole('code').click() - }, 150) + }, 500) it('expect.element on non-existing element fails', async () => { await expect.element(page.getByRole('code')).toBeVisible() - }, 150) + }, 1000) describe('beforeEach', () => { beforeEach(async () => { await page.getByTestId('non-existing').click() - }, 150) + }, 500) it('skipped', () => {}) }) @@ -21,7 +21,7 @@ describe.runIf(server.provider === 'playwright')('timeouts are failing correctly describe('afterEach', () => { afterEach(async () => { await page.getByTestId('non-existing').click() - }, 150) + }, 500) it('skipped', () => {}) }) @@ -29,7 +29,7 @@ describe.runIf(server.provider === 'playwright')('timeouts are failing correctly describe('beforeAll', () => { beforeAll(async () => { await page.getByTestId('non-existing').click() - }, 150) + }, 500) it('skipped', () => {}) }) @@ -37,7 +37,7 @@ describe.runIf(server.provider === 'playwright')('timeouts are failing correctly describe('afterAll', () => { afterAll(async () => { await page.getByTestId('non-existing').click() - }, 150) + }, 500) it('skipped', () => {}) }) @@ -46,13 +46,13 @@ describe.runIf(server.provider === 'playwright')('timeouts are failing correctly it('fails', ({ onTestFinished }) => { onTestFinished(async () => { await page.getByTestId('non-existing').click() - }, 150) + }, 500) }) it('fails global', () => { onTestFinished(async () => { await page.getByTestId('non-existing').click() - }, 150) + }, 500) }) }) @@ -60,7 +60,7 @@ describe.runIf(server.provider === 'playwright')('timeouts are failing correctly it('fails', ({ onTestFailed }) => { onTestFailed(async () => { await page.getByTestId('non-existing').click() - }, 150) + }, 500) expect.unreachable() }) @@ -68,7 +68,7 @@ describe.runIf(server.provider === 'playwright')('timeouts are failing correctly it('fails global', () => { onTestFailed(async () => { await page.getByTestId('non-existing').click() - }, 150) + }, 500) expect.unreachable() })