From 8bd072f0f62e9bd09f79e772e2ab9e0f7b1257d0 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Wed, 8 Jul 2026 11:23:00 +0200 Subject: [PATCH] test(e2e): Gate hydrogen-react-router-7 client clicks on hydration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hydrogen-react-router-7 E2E client tests that click an element right after `page.goto()` are flaky: Playwright's `click()` waits for actionability but not React hydration, so the click can land before the element's onClick handler is attached. The exception/ErrorBoundary clicks then capture nothing, and the `` click falls back to a full page navigation (a pageload instead of a client-side navigation). Await the pageload transaction — which only completes once the client SDK and router have hydrated — before clicking, in the exception, ErrorBoundary and navigation tests. This mirrors the mitigation already used by the remix-hydrogen navigation test. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../tests/client-errors.test.ts | 18 +++++++++++++++++- .../tests/client-transactions.test.ts | 10 ++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/dev-packages/e2e-tests/test-applications/hydrogen-react-router-7/tests/client-errors.test.ts b/dev-packages/e2e-tests/test-applications/hydrogen-react-router-7/tests/client-errors.test.ts index a14347cdc519..db87e3c0b11b 100644 --- a/dev-packages/e2e-tests/test-applications/hydrogen-react-router-7/tests/client-errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/hydrogen-react-router-7/tests/client-errors.test.ts @@ -1,13 +1,22 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/test-utils'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; test('Sends a client-side exception to Sentry', async ({ page }) => { + // The pageload transaction only completes once the client SDK and the router have hydrated. + // Awaiting it before clicking guarantees the button's onClick handler is attached — a click that + // lands before hydration would do nothing, and the exception would never be captured. + const pageloadTransactionPromise = waitForTransaction('hydrogen-react-router-7', transactionEvent => { + return transactionEvent.contexts?.trace?.op === 'pageload' && transactionEvent.transaction === '/'; + }); + const errorPromise = waitForError('hydrogen-react-router-7', errorEvent => { return errorEvent.exception?.values?.[0].value === 'I am an error!'; }); await page.goto('/'); + await pageloadTransactionPromise; + const exceptionButton = page.locator('id=exception-button'); await exceptionButton.click(); @@ -17,12 +26,19 @@ test('Sends a client-side exception to Sentry', async ({ page }) => { }); test('Sends a client-side ErrorBoundary exception to Sentry', async ({ page }) => { + // Wait for hydration (see above) before clicking, so the button's onClick handler is attached. + const pageloadTransactionPromise = waitForTransaction('hydrogen-react-router-7', transactionEvent => { + return transactionEvent.contexts?.trace?.op === 'pageload' && transactionEvent.transaction === '/client-error'; + }); + const errorPromise = waitForError('hydrogen-react-router-7', errorEvent => { return errorEvent.exception?.values?.[0].value === 'Sentry React Component Error'; }); await page.goto('/client-error'); + await pageloadTransactionPromise; + const throwButton = page.locator('id=throw-on-click'); await throwButton.click(); diff --git a/dev-packages/e2e-tests/test-applications/hydrogen-react-router-7/tests/client-transactions.test.ts b/dev-packages/e2e-tests/test-applications/hydrogen-react-router-7/tests/client-transactions.test.ts index 1adb44011d07..a23e49338f2c 100644 --- a/dev-packages/e2e-tests/test-applications/hydrogen-react-router-7/tests/client-transactions.test.ts +++ b/dev-packages/e2e-tests/test-applications/hydrogen-react-router-7/tests/client-transactions.test.ts @@ -14,12 +14,22 @@ test('Sends a pageload transaction to Sentry', async ({ page }) => { }); test('Sends a navigation transaction to Sentry', async ({ page }) => { + // Wait for the initial pageload transaction first. This ensures the client SDK and router are fully + // hydrated before we click the link. Clicking before hydration completes makes the `` behave + // like a plain anchor, triggering a full page navigation (a `pageload` transaction) instead of a + // client-side `navigation` one, which makes this test flaky. + const pageloadTransactionPromise = waitForTransaction('hydrogen-react-router-7', transactionEvent => { + return transactionEvent.contexts?.trace?.op === 'pageload' && transactionEvent.transaction === '/'; + }); + const transactionPromise = waitForTransaction('hydrogen-react-router-7', transactionEvent => { return transactionEvent.contexts?.trace?.op === 'navigation' && transactionEvent.transaction === '/user/:id'; }); await page.goto('/'); + await pageloadTransactionPromise; + const linkElement = page.locator('id=navigation'); await linkElement.click();