Skip to content

Commit b24c46c

Browse files
committed
test(e2e): Port React Router v5 and v6 E2E apps to span streaming
Removes the `traceLifecycle: 'static'` pin from `react-router-5`, `react-router-6`, `react-router-6-use-routes` and `react-router-6-descendant-routes`, and rewrites their specs against streamed span v2. The `react-router-6` SSE spec needed more than a helper swap: streamed `http.client` names carry only the domain, so the request is matched on `url.full`, and the abort error is read off the console because spans carry no breadcrumbs. All three SSE tests load the same route, so each one also pins its lookup to a pageload span that started after it navigated.
1 parent 6817d85 commit b24c46c

16 files changed

Lines changed: 533 additions & 674 deletions

File tree

‎dev-packages/e2e-tests/test-applications/react-router-5/src/index.tsx‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ const replay = Sentry.replayIntegration();
1111
const history = createBrowserHistory();
1212

1313
Sentry.init({
14-
traceLifecycle: 'static',
1514
environment: 'qa', // dynamic sampling bias to keep transactions
1615
dsn:
1716
process.env.REACT_APP_E2E_TEST_DSN ||

‎dev-packages/e2e-tests/test-applications/react-router-5/tests/errors.test.ts‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { expect, test } from '@playwright/test';
2-
import { waitForError, waitForTransaction } from '@sentry-internal/test-utils';
2+
import { getSpanOp, waitForError, waitForStreamedSpan } from '@sentry-internal/test-utils';
33

44
test('Sends correct error event', async ({ page }) => {
55
const errorEventPromise = waitForError('react-router-5', event => {
@@ -30,18 +30,18 @@ test('Sends correct error event', async ({ page }) => {
3030
});
3131

3232
test('Sets correct transactionName', async ({ page }) => {
33-
const transactionPromise = waitForTransaction('react-router-5', async transactionEvent => {
34-
return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'pageload';
33+
const pageloadSpanPromise = waitForStreamedSpan('react-router-5', span => {
34+
return getSpanOp(span) === 'pageload' && span.is_segment;
3535
});
3636

3737
const errorEventPromise = waitForError('react-router-5', event => {
3838
return !event.type && event.exception?.values?.[0]?.value === 'I am an error!';
3939
});
4040

4141
await page.goto('/');
42-
const transactionEvent = await transactionPromise;
42+
const pageloadSpan = await pageloadSpanPromise;
4343

44-
// Only capture error once transaction was sent
44+
// Only capture error once the pageload span was sent
4545
const exceptionButton = page.locator('id=exception-button');
4646
await exceptionButton.click();
4747

@@ -53,7 +53,7 @@ test('Sets correct transactionName', async ({ page }) => {
5353
expect(errorEvent.transaction).toEqual('/');
5454

5555
expect(errorEvent.contexts?.trace).toEqual({
56-
trace_id: transactionEvent.contexts?.trace?.trace_id,
57-
span_id: expect.not.stringContaining(transactionEvent.contexts?.trace?.span_id || ''),
56+
trace_id: pageloadSpan.trace_id,
57+
span_id: expect.not.stringContaining(pageloadSpan.span_id),
5858
});
5959
});
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { expect, test } from '@playwright/test';
2+
import { getSpanOp, waitForStreamedSpan } from '@sentry-internal/test-utils';
3+
4+
test('sends a pageload span with a parameterized URL', async ({ page }) => {
5+
const spanPromise = waitForStreamedSpan('react-router-5', span => {
6+
return getSpanOp(span) === 'pageload' && span.is_segment;
7+
});
8+
9+
await page.goto(`/`);
10+
11+
const span = await spanPromise;
12+
13+
expect(span.name).toBe('/');
14+
expect(span.attributes).toMatchObject({
15+
'sentry.op': { value: 'pageload', type: 'string' },
16+
'sentry.origin': { value: 'auto.pageload.react.reactrouter_v5', type: 'string' },
17+
'sentry.segment.name.source': { value: 'route', type: 'string' },
18+
'url.template': { value: '/', type: 'string' },
19+
'url.path': { value: '/', type: 'string' },
20+
'url.full': { value: expect.stringMatching(/^https?:\/\/localhost:\d+\/$/), type: 'string' },
21+
});
22+
});
23+
24+
test('sends a navigation span with a parameterized URL', async ({ page }) => {
25+
page.on('console', msg => console.log(msg.text()));
26+
const pageloadSpanPromise = waitForStreamedSpan('react-router-5', span => {
27+
return getSpanOp(span) === 'pageload' && span.is_segment;
28+
});
29+
30+
const navigationSpanPromise = waitForStreamedSpan('react-router-5', span => {
31+
return getSpanOp(span) === 'navigation' && span.is_segment;
32+
});
33+
34+
await page.goto(`/`);
35+
await pageloadSpanPromise;
36+
37+
const linkElement = page.locator('id=navigation');
38+
39+
const [_, navigationSpan] = await Promise.all([linkElement.click(), navigationSpanPromise]);
40+
41+
expect(navigationSpan.name).toBe('/user/:id');
42+
expect(navigationSpan.attributes).toMatchObject({
43+
'sentry.op': { value: 'navigation', type: 'string' },
44+
'sentry.origin': { value: 'auto.navigation.react.reactrouter_v5', type: 'string' },
45+
'sentry.segment.name.source': { value: 'route', type: 'string' },
46+
'url.template': { value: '/user/:id', type: 'string' },
47+
'url.path': { value: '/user/5', type: 'string' },
48+
'url.full': { value: expect.stringMatching(/^https?:\/\/localhost:\d+\/user\/5$/), type: 'string' },
49+
});
50+
});

‎dev-packages/e2e-tests/test-applications/react-router-5/tests/transactions.test.ts‎

Lines changed: 0 additions & 68 deletions
This file was deleted.

‎dev-packages/e2e-tests/test-applications/react-router-6-descendant-routes/src/index.tsx‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import Index from './pages/Index';
1616
const replay = Sentry.replayIntegration();
1717

1818
Sentry.init({
19-
traceLifecycle: 'static',
2019
environment: 'qa', // dynamic sampling bias to keep transactions
2120
dsn: process.env.REACT_APP_E2E_TEST_DSN,
2221
integrations: [

0 commit comments

Comments
 (0)