Skip to content

Commit fa408e7

Browse files
msonnbcodex
andcommitted
test(browser): retain static browser tracing counterparts
Co-Authored-By: GPT-6 <codex@openai.com>
1 parent d0d6847 commit fa408e7

87 files changed

Lines changed: 2707 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import * as Sentry from '@sentry/browser';
2+
3+
window.Sentry = Sentry;
4+
5+
Sentry.init({
6+
traceLifecycle: 'static',
7+
dsn: 'https://public@dsn.ingest.sentry.io/1337',
8+
integrations: [Sentry.browserTracingIntegration()],
9+
tracesSampleRate: 1,
10+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
document.getElementById('go-background').addEventListener('click', () => {
2+
setTimeout(() => {
3+
Object.defineProperty(document, 'hidden', { value: true, writable: true });
4+
const ev = document.createEvent('Event');
5+
ev.initEvent('visibilitychange');
6+
document.dispatchEvent(ev);
7+
}, 250);
8+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
</head>
6+
<body>
7+
<button id="go-background">New Tab</button>
8+
</body>
9+
</html>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { expect } from '@playwright/test';
2+
import type { Event } from '@sentry/core';
3+
import { sentryTest } from '../../../../utils/fixtures';
4+
import { getFirstSentryEnvelopeRequest, shouldSkipTracingTest } from '../../../../utils/helpers';
5+
6+
sentryTest('should finish pageload transaction when the page goes background', async ({ getLocalTestUrl, page }) => {
7+
if (shouldSkipTracingTest()) {
8+
sentryTest.skip();
9+
}
10+
const url = await getLocalTestUrl({ testDir: __dirname });
11+
12+
await page.goto(url);
13+
await page.locator('#go-background').click();
14+
15+
const pageloadTransaction = await getFirstSentryEnvelopeRequest<Event>(page);
16+
17+
expect(pageloadTransaction.contexts?.trace?.op).toBe('pageload');
18+
expect(pageloadTransaction.contexts?.trace?.status).toBe('cancelled');
19+
expect(pageloadTransaction.contexts?.trace?.data?.['sentry.cancellation_reason']).toBe('document.hidden');
20+
});
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import * as Sentry from '@sentry/browser';
2+
3+
window.Sentry = Sentry;
4+
5+
Sentry.init({
6+
traceLifecycle: 'static',
7+
dsn: 'https://public@dsn.ingest.sentry.io/1337',
8+
integrations: [
9+
Sentry.browserTracingIntegration({
10+
_experiments: {
11+
enableHTTPTimings: true,
12+
},
13+
}),
14+
],
15+
tracesSampleRate: 1,
16+
});
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fetch('http://sentry-test-site.example/0').then(
2+
fetch('http://sentry-test-site.example/1').then(fetch('http://sentry-test-site.example/2')),
3+
);
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { expect } from '@playwright/test';
2+
import type { Event } from '@sentry/core';
3+
import { sentryTest } from '../../../../utils/fixtures';
4+
import { getMultipleSentryEnvelopeRequests, shouldSkipTracingTest } from '../../../../utils/helpers';
5+
6+
sentryTest('creates fetch spans with http timing', async ({ browserName, getLocalTestUrl, page }) => {
7+
const supportedBrowsers = ['chromium', 'firefox'];
8+
9+
if (shouldSkipTracingTest() || !supportedBrowsers.includes(browserName)) {
10+
sentryTest.skip();
11+
}
12+
await page.route('http://sentry-test-site.example/*', async route => {
13+
const request = route.request();
14+
const postData = await request.postDataJSON();
15+
16+
await route.fulfill({
17+
status: 200,
18+
contentType: 'application/json',
19+
body: JSON.stringify(Object.assign({ id: 1 }, postData)),
20+
});
21+
});
22+
23+
const url = await getLocalTestUrl({ testDir: __dirname });
24+
25+
const envelopes = await getMultipleSentryEnvelopeRequests<Event>(page, 2, { url, timeout: 10000 });
26+
const tracingEvent = envelopes[envelopes.length - 1]; // last envelope contains tracing data on all browsers
27+
28+
const requestSpans = tracingEvent.spans?.filter(({ op }) => op === 'http.client');
29+
30+
expect(requestSpans).toHaveLength(3);
31+
32+
await page.pause();
33+
requestSpans?.forEach((span, index) =>
34+
expect(span).toMatchObject({
35+
description: `GET http://sentry-test-site.example/${index}`,
36+
parent_span_id: tracingEvent.contexts?.trace?.span_id,
37+
span_id: expect.stringMatching(/[a-f\d]{16}/),
38+
start_timestamp: expect.any(Number),
39+
timestamp: expect.any(Number),
40+
trace_id: tracingEvent.contexts?.trace?.trace_id,
41+
data: expect.objectContaining({
42+
'http.request.redirect_start': expect.any(Number),
43+
'http.request.redirect_end': expect.any(Number),
44+
'http.request.worker_start': expect.any(Number),
45+
'http.request.fetch_start': expect.any(Number),
46+
'http.request.domain_lookup_start': expect.any(Number),
47+
'http.request.domain_lookup_end': expect.any(Number),
48+
'http.request.connect_start': expect.any(Number),
49+
'http.request.secure_connection_start': expect.any(Number),
50+
'http.request.connection_end': expect.any(Number),
51+
'http.request.request_start': expect.any(Number),
52+
'http.request.response_start': expect.any(Number),
53+
'http.request.response_end': expect.any(Number),
54+
'http.request.time_to_first_byte': expect.any(Number),
55+
'network.protocol.version': expect.any(String),
56+
}),
57+
}),
58+
);
59+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import * as Sentry from '@sentry/browser';
2+
3+
window.Sentry = Sentry;
4+
5+
Sentry.init({
6+
traceLifecycle: 'static',
7+
dsn: 'https://public@dsn.ingest.sentry.io/1337',
8+
integrations: [
9+
Sentry.browserTracingIntegration({
10+
linkPreviousTrace: 'in-memory',
11+
consistentTraceSampling: true,
12+
}),
13+
],
14+
tracePropagationTargets: ['sentry-test-external.io'],
15+
tracesSampler: ctx => {
16+
if (ctx.attributes && ctx.attributes['sentry.origin'] === 'auto.pageload.browser') {
17+
return 1;
18+
}
19+
return ctx.inheritOrSampleWith(0);
20+
},
21+
debug: true,
22+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const btn1 = document.getElementById('btn1');
2+
3+
const btn2 = document.getElementById('btn2');
4+
5+
btn1.addEventListener('click', () => {
6+
Sentry.startNewTrace(() => {
7+
Sentry.startSpan({ name: 'custom root span 1', op: 'custom' }, () => {});
8+
});
9+
});
10+
11+
btn2.addEventListener('click', () => {
12+
Sentry.startNewTrace(() => {
13+
Sentry.startSpan({ name: 'custom root span 2', op: 'custom' }, async () => {
14+
await fetch('http://sentry-test-external.io');
15+
});
16+
});
17+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
</head>
6+
<button id="btn1"></button>
7+
<button id="btn2"></button>
8+
</html>

0 commit comments

Comments
 (0)