From 7d86ba2e278ff8fc17fedca591ff2c9d1a40f0ad Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Thu, 2 Jul 2026 14:49:57 +0200 Subject: [PATCH 1/3] test(browser): Fix web worker route-registration race in debug ID test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The webWorker integration tests registered the `**/worker.js` mock route after navigation was already triggered by `getFirstSentryEnvelopeRequest`, and never awaited the route. Since `init.js` creates the worker at page-load time (`new Worker('/worker.js')`), the worker request could win the race, load the real worker without an injected debug ID, and the expected error envelope would never arrive — causing a 30s test timeout flake. Register and await the route before navigation, matching the convention used across the rest of the browser integration suite. Co-Authored-By: Cursor --- .../suites/integrations/webWorker/test.ts | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/integrations/webWorker/test.ts b/dev-packages/browser-integration-tests/suites/integrations/webWorker/test.ts index 8133a24253f9..c6f5199ef0aa 100644 --- a/dev-packages/browser-integration-tests/suites/integrations/webWorker/test.ts +++ b/dev-packages/browser-integration-tests/suites/integrations/webWorker/test.ts @@ -11,14 +11,18 @@ sentryTest('Assigns web worker debug IDs when using webWorkerIntegration', async const url = await getLocalTestUrl({ testDir: __dirname }); - const errorEventPromise = getFirstSentryEnvelopeRequest(page, url); - - page.route('**/worker.js', route => { - route.fulfill({ + // `init.js` creates the worker (`new Worker('/worker.js')`) during page load, so the + // route must be registered (and awaited) before navigation is triggered. Otherwise the + // worker request can race the route setup, load the real worker without a debug ID, and + // the expected error envelope never arrives. + await page.route('**/worker.js', route => { + return route.fulfill({ path: `${__dirname}/assets/worker.js`, }); }); + const errorEventPromise = getFirstSentryEnvelopeRequest(page, url); + const button = page.locator('#errWorker'); await button.click(); @@ -45,14 +49,18 @@ sentryTest('Captures unhandled rejections from web workers', async ({ getLocalTe const url = await getLocalTestUrl({ testDir: __dirname }); - const errorEventPromise = getFirstSentryEnvelopeRequest(page, url); - - page.route('**/worker.js', route => { - route.fulfill({ + // `init.js` creates the worker (`new Worker('/worker.js')`) during page load, so the + // route must be registered (and awaited) before navigation is triggered. Otherwise the + // worker request can race the route setup, load the real worker without a debug ID, and + // the expected error envelope never arrives. + await page.route('**/worker.js', route => { + return route.fulfill({ path: `${__dirname}/assets/worker.js`, }); }); + const errorEventPromise = getFirstSentryEnvelopeRequest(page, url); + const button = page.locator('#rejectionWorker'); await button.click(); From 3a7114caca30aa772e6fd4becff6d5fc8007b7b0 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Mon, 6 Jul 2026 10:22:40 +0200 Subject: [PATCH 2/3] fix another flake --- .../suites/integrations/webWorker/test.ts | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/integrations/webWorker/test.ts b/dev-packages/browser-integration-tests/suites/integrations/webWorker/test.ts index c6f5199ef0aa..930739f76fd3 100644 --- a/dev-packages/browser-integration-tests/suites/integrations/webWorker/test.ts +++ b/dev-packages/browser-integration-tests/suites/integrations/webWorker/test.ts @@ -1,7 +1,7 @@ import { expect } from '@playwright/test'; import type { Event } from '@sentry/core'; import { sentryTest } from '../../../utils/fixtures'; -import { getFirstSentryEnvelopeRequest } from '../../../utils/helpers'; +import { envelopeRequestParser, waitForErrorRequest } from '../../../utils/helpers'; sentryTest('Assigns web worker debug IDs when using webWorkerIntegration', async ({ getLocalTestUrl, page }) => { const bundle = process.env.PW_BUNDLE; @@ -21,12 +21,16 @@ sentryTest('Assigns web worker debug IDs when using webWorkerIntegration', async }); }); - const errorEventPromise = getFirstSentryEnvelopeRequest(page, url); + const errorEventPromise = waitForErrorRequest( + page, + event => !!event.exception?.values?.[0]?.value?.includes('Worker error for testing'), + ); - const button = page.locator('#errWorker'); - await button.click(); + await page.goto(url); - const errorEvent = await errorEventPromise; + await page.locator('#errWorker').click(); + + const errorEvent = envelopeRequestParser(await errorEventPromise); expect(errorEvent.debug_meta?.images).toBeDefined(); @@ -59,12 +63,16 @@ sentryTest('Captures unhandled rejections from web workers', async ({ getLocalTe }); }); - const errorEventPromise = getFirstSentryEnvelopeRequest(page, url); + const errorEventPromise = waitForErrorRequest( + page, + event => !!event.exception?.values?.[0]?.value?.includes('Worker unhandled rejection'), + ); + + await page.goto(url); - const button = page.locator('#rejectionWorker'); - await button.click(); + await page.locator('#rejectionWorker').click(); - const errorEvent = await errorEventPromise; + const errorEvent = envelopeRequestParser(await errorEventPromise); // Verify the unhandled rejection was captured expect(errorEvent.exception?.values?.[0]?.value).toContain('Worker unhandled rejection'); From 752b0c5ccbbab7bac890dfe7804a50c2edc210c5 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Mon, 6 Jul 2026 11:36:50 +0200 Subject: [PATCH 3/3] deslop comments --- .../suites/integrations/webWorker/test.ts | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/integrations/webWorker/test.ts b/dev-packages/browser-integration-tests/suites/integrations/webWorker/test.ts index 930739f76fd3..b98bc1376d03 100644 --- a/dev-packages/browser-integration-tests/suites/integrations/webWorker/test.ts +++ b/dev-packages/browser-integration-tests/suites/integrations/webWorker/test.ts @@ -11,10 +11,7 @@ sentryTest('Assigns web worker debug IDs when using webWorkerIntegration', async const url = await getLocalTestUrl({ testDir: __dirname }); - // `init.js` creates the worker (`new Worker('/worker.js')`) during page load, so the - // route must be registered (and awaited) before navigation is triggered. Otherwise the - // worker request can race the route setup, load the real worker without a debug ID, and - // the expected error envelope never arrives. + // `init.js` creates the worker at page load, so the route must be registered before navigating. await page.route('**/worker.js', route => { return route.fulfill({ path: `${__dirname}/assets/worker.js`, @@ -53,10 +50,7 @@ sentryTest('Captures unhandled rejections from web workers', async ({ getLocalTe const url = await getLocalTestUrl({ testDir: __dirname }); - // `init.js` creates the worker (`new Worker('/worker.js')`) during page load, so the - // route must be registered (and awaited) before navigation is triggered. Otherwise the - // worker request can race the route setup, load the real worker without a debug ID, and - // the expected error envelope never arrives. + // `init.js` creates the worker at page load, so the route must be registered before navigating. await page.route('**/worker.js', route => { return route.fulfill({ path: `${__dirname}/assets/worker.js`, @@ -74,7 +68,6 @@ sentryTest('Captures unhandled rejections from web workers', async ({ getLocalTe const errorEvent = envelopeRequestParser(await errorEventPromise); - // Verify the unhandled rejection was captured expect(errorEvent.exception?.values?.[0]?.value).toContain('Worker unhandled rejection'); expect(errorEvent.exception?.values?.[0]?.mechanism?.type).toBe('auto.browser.web_worker.onunhandledrejection'); expect(errorEvent.exception?.values?.[0]?.mechanism?.handled).toBe(false);