Skip to content

Commit 5fda759

Browse files
committed
test(browser-integration-tests): Test trace lifetime for outgoing fetch requests
1 parent 6fc1b69 commit 5fda759

File tree

5 files changed

+132
-4
lines changed

5 files changed

+132
-4
lines changed

dev-packages/browser-integration-tests/suites/tracing/trace-lifetime/init.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ window.Sentry = Sentry;
55
Sentry.init({
66
dsn: 'https://public@dsn.ingest.sentry.io/1337',
77
integrations: [Sentry.browserTracingIntegration()],
8+
tracePropagationTargets: ['http://example.com'],
89
tracesSampleRate: 1,
910
});

dev-packages/browser-integration-tests/suites/tracing/trace-lifetime/navigation/test.ts

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,74 @@ sentryTest('error after navigation has navigation traceId', async ({ getLocalTes
4141
const navigationTraceId = navigationEvent1.contexts?.trace?.trace_id;
4242
expect(navigationTraceId).toMatch(/^[0-9a-f]{32}$/);
4343

44-
const [, errorEvent] = await Promise.all([
45-
page.locator('#errorBtn').click(),
46-
getFirstSentryEnvelopeRequest<Event>(page),
47-
]);
44+
const errorEventPromise = getFirstSentryEnvelopeRequest<Event>(page);
45+
await page.locator('#errorBtn').click();
46+
const errorEvent = await errorEventPromise;
4847

4948
const errorTraceId = errorEvent.contexts?.trace?.trace_id;
5049
expect(errorTraceId).toBe(navigationTraceId);
5150
});
51+
52+
sentryTest(
53+
'outgoing fetch request after navigation has navigation traceId in headers',
54+
async ({ getLocalTestPath, page }) => {
55+
if (shouldSkipTracingTest()) {
56+
sentryTest.skip();
57+
}
58+
59+
const url = await getLocalTestPath({ testDir: __dirname });
60+
61+
// ensure navigation transaction is finished
62+
await getFirstSentryEnvelopeRequest<Event>(page, url);
63+
64+
const navigationEvent = await getFirstSentryEnvelopeRequest<Event>(page, `${url}#foo`);
65+
expect(navigationEvent.contexts?.trace?.op).toBe('navigation');
66+
67+
const navigationTraceId = navigationEvent.contexts?.trace?.trace_id;
68+
expect(navigationTraceId).toMatch(/^[0-9a-f]{32}$/);
69+
70+
const requestPromise = page.waitForRequest('http://example.com/*');
71+
await page.locator('#fetchBtn').click();
72+
const request = await requestPromise;
73+
const headers = request.headers();
74+
75+
// sampling decision is deferred b/c of no active span at the time of request
76+
expect(headers['sentry-trace']).toMatch(new RegExp(`^${navigationTraceId}-[0-9a-f]{16}$`));
77+
expect(headers['baggage']).toEqual(
78+
`sentry-environment=production,sentry-public_key=public,sentry-trace_id=${navigationTraceId}`,
79+
);
80+
},
81+
);
82+
83+
sentryTest(
84+
'outgoing fetch request during navigation has navigation traceId in headers',
85+
async ({ getLocalTestPath, page }) => {
86+
if (shouldSkipTracingTest()) {
87+
sentryTest.skip();
88+
}
89+
90+
const url = await getLocalTestPath({ testDir: __dirname });
91+
92+
// ensure navigation transaction is finished
93+
await getFirstSentryEnvelopeRequest<Event>(page, url);
94+
95+
const navigationEventPromise = getFirstSentryEnvelopeRequest<Event>(page);
96+
const requestPromise = page.waitForRequest('http://example.com/*');
97+
await page.goto(`${url}#foo`);
98+
await page.locator('#fetchBtn').click();
99+
const [navigationEvent, request] = await Promise.all([navigationEventPromise, requestPromise]);
100+
101+
expect(navigationEvent.contexts?.trace?.op).toBe('navigation');
102+
103+
const navigationTraceId = navigationEvent.contexts?.trace?.trace_id;
104+
expect(navigationTraceId).toMatch(/^[0-9a-f]{32}$/);
105+
106+
const headers = request.headers();
107+
108+
// sampling decision is propagated from active span sampling decision
109+
expect(headers['sentry-trace']).toMatch(new RegExp(`^${navigationTraceId}-[0-9a-f]{16}-1$`));
110+
expect(headers['baggage']).toEqual(
111+
`sentry-environment=production,sentry-public_key=public,sentry-trace_id=${navigationTraceId},sentry-sample_rate=1,sentry-sampled=true`,
112+
);
113+
},
114+
);

dev-packages/browser-integration-tests/suites/tracing/trace-lifetime/pageload/test.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,61 @@ sentryTest('error after pageload has pageload traceId', async ({ getLocalTestPat
4848
const errorTraceId = errorEvent.contexts?.trace?.trace_id;
4949
expect(errorTraceId).toBe(pageloadTraceId);
5050
});
51+
52+
sentryTest(
53+
'outgoing fetch request after pageload has pageload traceId in headers',
54+
async ({ getLocalTestPath, page }) => {
55+
if (shouldSkipTracingTest()) {
56+
sentryTest.skip();
57+
}
58+
59+
const url = await getLocalTestPath({ testDir: __dirname });
60+
61+
const pageloadEvent = await getFirstSentryEnvelopeRequest<Event>(page, url);
62+
expect(pageloadEvent.contexts?.trace?.op).toBe('pageload');
63+
64+
const pageloadTraceId = pageloadEvent.contexts?.trace?.trace_id;
65+
expect(pageloadTraceId).toMatch(/^[0-9a-f]{32}$/);
66+
67+
const requestPromise = page.waitForRequest('http://example.com/*');
68+
await page.locator('#fetchBtn').click();
69+
const request = await requestPromise;
70+
const headers = request.headers();
71+
72+
// sampling decision is deferred b/c of no active span at the time of request
73+
expect(headers['sentry-trace']).toMatch(new RegExp(`^${pageloadTraceId}-[0-9a-f]{16}$`));
74+
expect(headers['baggage']).toEqual(
75+
`sentry-environment=production,sentry-public_key=public,sentry-trace_id=${pageloadTraceId}`,
76+
);
77+
},
78+
);
79+
80+
sentryTest(
81+
'outgoing fetch request during pageload has pageload traceId in headers',
82+
async ({ getLocalTestPath, page }) => {
83+
if (shouldSkipTracingTest()) {
84+
sentryTest.skip();
85+
}
86+
87+
const url = await getLocalTestPath({ testDir: __dirname });
88+
89+
const pageloadEventPromise = getFirstSentryEnvelopeRequest<Event>(page);
90+
const requestPromise = page.waitForRequest('http://example.com/*');
91+
await page.goto(url);
92+
await page.locator('#fetchBtn').click();
93+
const [pageloadEvent, request] = await Promise.all([pageloadEventPromise, requestPromise]);
94+
95+
expect(pageloadEvent.contexts?.trace?.op).toBe('pageload');
96+
97+
const navigationTraceId = pageloadEvent.contexts?.trace?.trace_id;
98+
expect(navigationTraceId).toMatch(/^[0-9a-f]{32}$/);
99+
100+
const headers = request.headers();
101+
102+
// sampling decision is propagated from active span sampling decision
103+
expect(headers['sentry-trace']).toMatch(new RegExp(`^${navigationTraceId}-[0-9a-f]{16}-1$`));
104+
expect(headers['baggage']).toEqual(
105+
`sentry-environment=production,sentry-public_key=public,sentry-trace_id=${navigationTraceId},sentry-sample_rate=1,sentry-sampled=true`,
106+
);
107+
},
108+
);

dev-packages/browser-integration-tests/suites/tracing/trace-lifetime/subject.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,8 @@ const errorBtn = document.getElementById('errorBtn');
22
errorBtn.addEventListener('click', () => {
33
throw new Error('Sentry Test Error');
44
});
5+
6+
const fetchBtn = document.getElementById('fetchBtn');
7+
fetchBtn.addEventListener('click', async () => {
8+
await fetch('http://example.com');
9+
});

dev-packages/browser-integration-tests/suites/tracing/trace-lifetime/template.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@
55
</head>
66
<body>
77
<button id="errorBtn">Throw Error</button>
8+
<button id="fetchBtn">Fetch Request</button>
89
</body>
910
</html>

0 commit comments

Comments
 (0)