Skip to content

Commit 2be6891

Browse files
committed
add tests for requests and spans after initial pageload span ended
1 parent efcaaf8 commit 2be6891

File tree

4 files changed

+153
-1
lines changed

4 files changed

+153
-1
lines changed

dev-packages/browser-integration-tests/suites/tracing/dsc-txn-name-update/test.ts

+1
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ async function makeRequestAndGetBaggageItems(page: Page): Promise<string[]> {
166166
const request = await requestPromise;
167167

168168
const baggage = await request.headerValue('baggage');
169+
169170
return baggage?.split(',').sort() ?? [];
170171
}
171172

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

+144-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { expect } from '@playwright/test';
1+
import { expect, request } from '@playwright/test';
22
import type { Event } from '@sentry/types';
33
import { sentryTest } from '../../../../utils/fixtures';
44
import type { EventAndTraceHeader } from '../../../../utils/helpers';
@@ -294,6 +294,149 @@ sentryTest(
294294
},
295295
);
296296

297+
sentryTest(
298+
'outgoing fetch request after pageload has pageload traceId in headers',
299+
async ({ getLocalTestUrl, page }) => {
300+
if (shouldSkipTracingTest()) {
301+
sentryTest.skip();
302+
}
303+
304+
const url = await getLocalTestUrl({ testDir: __dirname });
305+
306+
await page.route('http://example.com/**', route => {
307+
return route.fulfill({
308+
status: 200,
309+
contentType: 'application/json',
310+
body: JSON.stringify({}),
311+
});
312+
});
313+
314+
const pageloadEventPromise = getFirstSentryEnvelopeRequest<EventAndTraceHeader>(
315+
page,
316+
undefined,
317+
eventAndTraceHeaderRequestParser,
318+
);
319+
await page.goto(url);
320+
const [pageloadEvent, pageloadTraceHeader] = await pageloadEventPromise;
321+
322+
const pageloadTraceContext = pageloadEvent.contexts?.trace;
323+
const pageloadTraceId = pageloadTraceContext?.trace_id;
324+
325+
expect(pageloadEvent.type).toEqual('transaction');
326+
expect(pageloadTraceContext).toMatchObject({
327+
op: 'pageload',
328+
trace_id: expect.stringMatching(/^[0-9a-f]{32}$/),
329+
span_id: expect.stringMatching(/^[0-9a-f]{16}$/),
330+
});
331+
expect(pageloadTraceContext).not.toHaveProperty('parent_span_id');
332+
333+
expect(pageloadTraceHeader).toEqual({
334+
environment: 'production',
335+
public_key: 'public',
336+
sample_rate: '1',
337+
sampled: 'true',
338+
trace_id: pageloadTraceId,
339+
});
340+
341+
const requestPromise = page.waitForRequest('http://example.com/*');
342+
await page.locator('#xhrBtn').click();
343+
const request = await requestPromise;
344+
345+
const headers = request.headers();
346+
347+
// sampling decision is propagated from active span sampling decision
348+
expect(headers['sentry-trace']).toMatch(new RegExp(`^${pageloadTraceId}-[0-9a-f]{16}-1$`));
349+
expect(headers['baggage']).toEqual(
350+
`sentry-environment=production,sentry-public_key=public,sentry-trace_id=${pageloadTraceId},sentry-sample_rate=1,sentry-sampled=true`,
351+
);
352+
},
353+
);
354+
355+
sentryTest(
356+
'custom span and request headers after pageload have pageload traceId ',
357+
async ({ getLocalTestUrl, page }) => {
358+
if (shouldSkipTracingTest()) {
359+
sentryTest.skip();
360+
}
361+
362+
const url = await getLocalTestUrl({ testDir: __dirname });
363+
364+
await page.route('http://example.com/**', route => {
365+
return route.fulfill({
366+
status: 200,
367+
contentType: 'application/json',
368+
body: JSON.stringify({}),
369+
});
370+
});
371+
372+
const pageloadEventPromise = getFirstSentryEnvelopeRequest<EventAndTraceHeader>(
373+
page,
374+
undefined,
375+
eventAndTraceHeaderRequestParser,
376+
);
377+
378+
await page.goto(url);
379+
380+
const [pageloadEvent, pageloadTraceHeader] = await pageloadEventPromise;
381+
382+
const pageloadTraceContext = pageloadEvent.contexts?.trace;
383+
const pageloadTraceId = pageloadTraceContext?.trace_id;
384+
385+
expect(pageloadEvent.type).toEqual('transaction');
386+
expect(pageloadTraceContext).toMatchObject({
387+
op: 'pageload',
388+
trace_id: expect.stringMatching(/^[0-9a-f]{32}$/),
389+
span_id: expect.stringMatching(/^[0-9a-f]{16}$/),
390+
});
391+
expect(pageloadTraceContext).not.toHaveProperty('parent_span_id');
392+
393+
expect(pageloadTraceHeader).toEqual({
394+
environment: 'production',
395+
public_key: 'public',
396+
sample_rate: '1',
397+
sampled: 'true',
398+
trace_id: pageloadTraceId,
399+
});
400+
401+
const requestPromise = page.waitForRequest('http://example.com/**');
402+
const customTransactionEventPromise = getFirstSentryEnvelopeRequest<EventAndTraceHeader>(
403+
page,
404+
undefined,
405+
eventAndTraceHeaderRequestParser,
406+
);
407+
408+
await page.locator('#spanAndFetchBtn').click();
409+
410+
const [[customTransactionEvent, customTransactionTraceHeader], request] = await Promise.all([
411+
customTransactionEventPromise,
412+
requestPromise,
413+
]);
414+
415+
const customTransactionTraceContext = customTransactionEvent.contexts?.trace;
416+
417+
expect(customTransactionEvent.type).toEqual('transaction');
418+
expect(customTransactionTraceContext).toMatchObject({
419+
trace_id: pageloadTraceId,
420+
});
421+
422+
expect(customTransactionTraceHeader).toEqual({
423+
environment: 'production',
424+
public_key: 'public',
425+
sample_rate: '1',
426+
sampled: 'true',
427+
trace_id: pageloadTraceId,
428+
});
429+
430+
const headers = request.headers();
431+
432+
// sampling decision is propagated from active span sampling decision
433+
expect(headers['sentry-trace']).toMatch(new RegExp(`^${pageloadTraceId}-[0-9a-f]{16}-1$`));
434+
expect(headers['baggage']).toEqual(
435+
`sentry-environment=production,sentry-public_key=public,sentry-trace_id=${pageloadTraceId},sentry-sample_rate=1,sentry-sampled=true`,
436+
);
437+
},
438+
);
439+
297440
sentryTest('user feedback event after pageload has pageload traceId in headers', async ({ getLocalTestUrl, page }) => {
298441
if (shouldSkipTracingTest() || shouldSkipFeedbackTest()) {
299442
sentryTest.skip();

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

+7
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,10 @@ xhrBtn.addEventListener('click', () => {
1414
xhr.open('GET', 'http://example.com');
1515
xhr.send();
1616
});
17+
18+
const spanAndFetchBtn = document.getElementById('spanAndFetchBtn');
19+
spanAndFetchBtn.addEventListener('click', () => {
20+
Sentry.startSpan({ name: 'custom-root-span' }, async () => {
21+
await fetch('http://example.com');
22+
});
23+
});

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

+1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@
77
<button id="errorBtn">Throw Error</button>
88
<button id="fetchBtn">Fetch Request</button>
99
<button id="xhrBtn">XHR Request</button>
10+
<button id="spanAndFetchBtn">Start Span and Fetch Request</button>
1011
</body>
1112
</html>

0 commit comments

Comments
 (0)