Skip to content

Commit bb5ee63

Browse files
committed
feat(react-19-e2e): add SENTRY_LIGHTHOUSE_MODE instrumentation
Mirrors the dynamic-import pattern from default-browser/src/index.js so the react-19 E2E test app can serve as a third (CRA) cell in the Lighthouse matrix alongside default-browser (webpack) and nextjs-16 (Next.js SSR). CRA exposes only env vars prefixed REACT_APP_*, so the gate is process.env.REACT_APP_SENTRY_LIGHTHOUSE_MODE. Three branches: - 'no-sentry': sync render with no Sentry import; CRA dead-code-eliminates the @sentry/react chunk entirely (the dynamic import in the else branch becomes unreachable when the env var inlines to 'no-sentry'). - 'tracing-replay': Sentry.init + browserTracingIntegration + replayIntegration. - 'init-only' / unset: Sentry.init with no integrations, error handlers attached to createRoot (preserves the existing E2E behavior when the env var is unset). The createRoot call moves inside the async IIFE in the else branch because the onUncaughtError / onCaughtError options need the dynamically-imported Sentry.reactErrorHandler. React handles its own scheduling so the extra microtask before render is invisible to Playwright tests.
1 parent 06f87a5 commit bb5ee63

1 file changed

Lines changed: 52 additions & 20 deletions

File tree

  • dev-packages/e2e-tests/test-applications/react-19/src
Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,58 @@
1-
import * as Sentry from '@sentry/react';
21
import React from 'react';
32
import ReactDOM from 'react-dom/client';
43
import Index from './pages/Index';
54

6-
Sentry.init({
7-
environment: 'qa', // dynamic sampling bias to keep transactions
8-
dsn: process.env.REACT_APP_E2E_TEST_DSN,
9-
release: 'e2e-test',
10-
tunnel: 'http://localhost:3031/', // proxy server
11-
});
5+
const lighthouseMode = process.env.REACT_APP_SENTRY_LIGHTHOUSE_MODE;
126

13-
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement, {
14-
onUncaughtError: Sentry.reactErrorHandler((error, errorInfo) => {
15-
console.warn(error, errorInfo);
16-
}),
17-
onCaughtError: Sentry.reactErrorHandler((error, errorInfo) => {
18-
console.warn(error, errorInfo);
19-
}),
20-
});
7+
if (lighthouseMode === 'no-sentry') {
8+
// No Sentry at all — sync render so webpack/CRA can fully dead-code-eliminate the
9+
// @sentry/react import below. CRA inlines `process.env.REACT_APP_*` at build time,
10+
// so this branch becomes the only one in the bundle when the env var is set.
11+
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
12+
root.render(
13+
<div>
14+
<Index />
15+
</div>,
16+
);
17+
} else {
18+
// Dynamic-import Sentry so it lives in a separate chunk that webpack/CRA drops
19+
// entirely from the no-sentry build above. Preserves existing E2E behavior when
20+
// the env var is unset (init + error handlers, no tracing/replay).
21+
void (async () => {
22+
const Sentry = await import('@sentry/react');
2123

22-
root.render(
23-
<div>
24-
<Index />
25-
</div>,
26-
);
24+
const integrations: unknown[] = [];
25+
if (lighthouseMode === 'tracing-replay') {
26+
integrations.push(Sentry.browserTracingIntegration());
27+
integrations.push(Sentry.replayIntegration());
28+
}
29+
30+
Sentry.init({
31+
environment: 'qa', // dynamic sampling bias to keep transactions
32+
dsn: process.env.REACT_APP_E2E_TEST_DSN,
33+
release: 'e2e-test',
34+
tunnel: 'http://localhost:3031/', // proxy server
35+
integrations: integrations as Parameters<typeof Sentry.init>[0]['integrations'],
36+
tracesSampleRate: lighthouseMode === 'tracing-replay' ? 1.0 : undefined,
37+
replaysSessionSampleRate: lighthouseMode === 'tracing-replay' ? 1.0 : 0,
38+
replaysOnErrorSampleRate: lighthouseMode === 'tracing-replay' ? 1.0 : 0,
39+
});
40+
41+
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement, {
42+
onUncaughtError: Sentry.reactErrorHandler((error, errorInfo) => {
43+
// oxlint-disable-next-line no-console
44+
console.warn(error, errorInfo);
45+
}),
46+
onCaughtError: Sentry.reactErrorHandler((error, errorInfo) => {
47+
// oxlint-disable-next-line no-console
48+
console.warn(error, errorInfo);
49+
}),
50+
});
51+
52+
root.render(
53+
<div>
54+
<Index />
55+
</div>,
56+
);
57+
})();
58+
}

0 commit comments

Comments
 (0)