Skip to content

Commit 52e9455

Browse files
msonnbcodex
andcommitted
test(browser): wait for LCP candidates and use attribute constants
Co-Authored-By: GPT-6 <codex@openai.com>
1 parent 468b4a6 commit 52e9455

36 files changed

Lines changed: 685 additions & 445 deletions

File tree

‎dev-packages/browser-integration-tests/suites/tracing/interactions/disabled/test.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { SENTRY_ORIGIN } from '@sentry/conventions/attributes';
12
import { expect } from '@playwright/test';
23
import { sentryTest } from '../../../../utils/fixtures';
34
import { hidePage, shouldSkipTracingTest } from '../../../../utils/helpers';
@@ -14,5 +15,5 @@ sentryTest('does not capture interaction spans without the integration', async (
1415
await hidePage(page);
1516
await page.evaluate(() => (window as any).Sentry.flush());
1617

17-
expect(spans.filter(span => span.attributes['sentry.origin']?.value === 'auto.browser.interactions')).toHaveLength(0);
18+
expect(spans.filter(span => span.attributes[SENTRY_ORIGIN]?.value === 'auto.browser.interactions')).toHaveLength(0);
1819
});

‎dev-packages/browser-integration-tests/suites/tracing/interactions/spans/test.ts‎

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import { expect } from '@playwright/test';
22
import { SDK_VERSION } from '@sentry/core';
33
import {
4+
SENTRY_IS_LOCALHOST,
5+
CULTURE_CALENDAR,
6+
CULTURE_LOCALE,
7+
CULTURE_TIMEZONE,
8+
URL_FULL,
9+
BROWSER_WEB_VITAL_INP_TARGET,
410
SENTRY_IDLE_SPAN_FINISH_REASON,
511
SENTRY_SEGMENT_ID,
612
SENTRY_SEGMENT_NAME,
@@ -51,28 +57,28 @@ sentryTest('captures streamed interaction span tree. @firefox', async ({ browser
5157

5258
expect(interactionSegmentSpan).toEqual({
5359
attributes: {
54-
'sentry.is_localhost': { value: false, type: 'boolean' },
60+
[SENTRY_IS_LOCALHOST]: { value: false, type: 'boolean' },
5561
[SENTRY_TRACE_LIFECYCLE]: {
5662
type: 'string',
5763
value: 'stream',
5864
},
59-
'culture.calendar': {
65+
[CULTURE_CALENDAR]: {
6066
type: 'string',
6167
value: expect.any(String),
6268
},
63-
'culture.locale': {
69+
[CULTURE_LOCALE]: {
6470
type: 'string',
6571
value: expect.any(String),
6672
},
67-
'culture.timezone': {
73+
[CULTURE_TIMEZONE]: {
6874
type: 'string',
6975
value: expect.any(String),
7076
},
7177
[USER_AGENT_ORIGINAL]: {
7278
type: 'string',
7379
value: expect.any(String),
7480
},
75-
'url.full': {
81+
[URL_FULL]: {
7682
type: 'string',
7783
value: expect.any(String),
7884
},
@@ -136,7 +142,7 @@ sentryTest('captures streamed interaction span tree. @firefox', async ({ browser
136142
const interactionSpan = interactionSpanTree.find(span => getSpanOp(span) === 'ui.interaction.click');
137143
expect(interactionSpan).toEqual({
138144
attributes: {
139-
'sentry.is_localhost': { value: false, type: 'boolean' },
145+
[SENTRY_IS_LOCALHOST]: { value: false, type: 'boolean' },
140146
[SENTRY_TRACE_LIFECYCLE]: {
141147
type: 'string',
142148
value: 'stream',
@@ -173,7 +179,7 @@ sentryTest('captures streamed interaction span tree. @firefox', async ({ browser
173179
type: 'string',
174180
value: 'production',
175181
},
176-
'browser.web_vital.inp.target': {
182+
[BROWSER_WEB_VITAL_INP_TARGET]: {
177183
type: 'string',
178184
value: 'body > button.clicked',
179185
},

‎dev-packages/browser-integration-tests/suites/tracing/metrics/connection-rtt-navigation/test.ts‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ import { expect } from '@playwright/test';
22
import { sentryTest } from '../../../../utils/fixtures';
33
import { shouldSkipTracingTest } from '../../../../utils/helpers';
44
import { waitForStreamedSpanAndTraceHeaderOnUrl } from '../../../../utils/spanUtils';
5-
import { NETWORK_CONNECTION_RTT } from '@sentry/conventions/attributes';
5+
import {
6+
BROWSER_WEB_VITAL_FCP_VALUE,
7+
BROWSER_WEB_VITAL_TTFB_VALUE,
8+
NETWORK_CONNECTION_RTT,
9+
} from '@sentry/conventions/attributes';
610

711
sentryTest(
812
'records connection RTT on pageload and navigation spans',
@@ -14,7 +18,7 @@ sentryTest(
1418

1519
expect(pageload.attributes[NETWORK_CONNECTION_RTT]).toEqual({ type: 'integer', value: 0 });
1620
expect(navigation.attributes[NETWORK_CONNECTION_RTT]).toEqual(pageload.attributes[NETWORK_CONNECTION_RTT]);
17-
expect(navigation.attributes['browser.web_vital.fcp.value']).toBeUndefined();
18-
expect(navigation.attributes['browser.web_vital.ttfb.value']).toBeUndefined();
21+
expect(navigation.attributes[BROWSER_WEB_VITAL_FCP_VALUE]).toBeUndefined();
22+
expect(navigation.attributes[BROWSER_WEB_VITAL_TTFB_VALUE]).toBeUndefined();
1923
},
2024
);

‎dev-packages/browser-integration-tests/suites/tracing/metrics/handlers-lcp/test.ts‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
import {
2+
BROWSER_WEB_VITAL_LCP_VALUE,
3+
BROWSER_WEB_VITAL_LCP_ELEMENT,
4+
BROWSER_WEB_VITAL_LCP_SIZE,
5+
} from '@sentry/conventions/attributes';
16
import type { Route } from '@playwright/test';
27
import { expect } from '@playwright/test';
38
import { sentryTest } from '../../../../utils/fixtures';
@@ -26,9 +31,9 @@ sentryTest(
2631
await page.locator('button').click();
2732
const lcpSpan = await lcpPromise;
2833

29-
expect(lcpSpan.attributes['browser.web_vital.lcp.value']?.value).toBeGreaterThan(0);
30-
expect(lcpSpan.attributes['browser.web_vital.lcp.element']).toEqual({ type: 'string', value: 'body > img' });
31-
expect(lcpSpan.attributes['browser.web_vital.lcp.size']).toEqual({ type: 'integer', value: 107400 });
34+
expect(lcpSpan.attributes[BROWSER_WEB_VITAL_LCP_VALUE]?.value).toBeGreaterThan(0);
35+
expect(lcpSpan.attributes[BROWSER_WEB_VITAL_LCP_ELEMENT]).toEqual({ type: 'string', value: 'body > img' });
36+
expect(lcpSpan.attributes[BROWSER_WEB_VITAL_LCP_SIZE]).toEqual({ type: 'integer', value: 107400 });
3237
expect(await page.evaluate('window._LCP')).toBe(107400);
3338
expect(await page.evaluate('window._LCP2')).toBe(107400);
3439
expect(await page.evaluate('window._LCP3')).toBeUndefined();

‎dev-packages/browser-integration-tests/suites/tracing/metrics/pageload-browser-spans/test.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { URL_FULL } from '@sentry/conventions/attributes';
12
import { expect } from '@playwright/test';
23
import { sentryTest } from '../../../../utils/fixtures';
34
import { shouldSkipTracingTest } from '../../../../utils/helpers';
@@ -22,7 +23,7 @@ sentryTest('adds browser performance spans to the pageload segment', async ({ ge
2223
const matches = browserSpans.filter(span => getSpanOp(span) === op);
2324
expect(matches).toHaveLength(1);
2425
expect(matches[0].name).toBe(name);
25-
expect(matches[0].attributes['url.full']).toEqual({ type: 'string', value: page.url() });
26+
expect(matches[0].attributes[URL_FULL]).toEqual({ type: 'string', value: page.url() });
2627
expect(matches[0].parent_span_id).toBe(pageload.span_id);
2728
expect(matches[0].trace_id).toBe(pageload.trace_id);
2829
});

‎dev-packages/browser-integration-tests/suites/tracing/metrics/pageload-resource-spans-static/test.ts‎

Lines changed: 109 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,32 @@
1-
import { SENTRY_OP, SENTRY_ORIGIN } from '@sentry/conventions/attributes';
1+
import {
2+
HTTP_REQUEST_SAME_ORIGIN,
3+
URL_FULL,
4+
HTTP_RESPONSE_BODY_DECODED_SIZE,
5+
HTTP_RESPONSE_BODY_SIZE,
6+
HTTP_RESPONSE_SIZE,
7+
HTTP_REQUEST_CONNECT_START,
8+
HTTP_REQUEST_CONNECTION_END,
9+
HTTP_REQUEST_DOMAIN_LOOKUP_END,
10+
HTTP_REQUEST_DOMAIN_LOOKUP_START,
11+
HTTP_REQUEST_FETCH_START,
12+
HTTP_REQUEST_REDIRECT_END,
13+
HTTP_REQUEST_REDIRECT_START,
14+
HTTP_REQUEST_REQUEST_START,
15+
HTTP_REQUEST_SECURE_CONNECTION_START,
16+
HTTP_REQUEST_WORKER_START,
17+
HTTP_REQUEST_RESPONSE_END,
18+
HTTP_REQUEST_RESPONSE_START,
19+
HTTP_REQUEST_TIME_TO_FIRST_BYTE,
20+
NETWORK_PROTOCOL_NAME,
21+
NETWORK_PROTOCOL_VERSION,
22+
SERVER_ADDRESS,
23+
URL_DOMAIN,
24+
URL_SCHEME,
25+
HTTP_RESPONSE_STATUS_CODE,
26+
RESOURCE_RENDER_BLOCKING_STATUS,
27+
SENTRY_OP,
28+
SENTRY_ORIGIN,
29+
} from '@sentry/conventions/attributes';
230
import type { Route } from '@playwright/test';
331
import { expect } from '@playwright/test';
432
import { type Event } from '@sentry/core';
@@ -69,46 +97,46 @@ sentryTest('adds resource spans to pageload transaction', async ({ getLocalTestU
6997
// The init bundle script is served from the test origin: its description is origin-relative,
7098
// but `url.full` retains the full absolute URL (needed for span description inference).
7199
const sameOriginScriptSpan = scriptSpans?.find(({ description }) => description === '/init.bundle.js');
72-
expect(sameOriginScriptSpan?.data?.['http.request.same_origin']).toBe(true);
73-
expect(sameOriginScriptSpan?.data?.['url.full']).toMatch(/^https?:\/\/.+\/init\.bundle\.js$/);
100+
expect(sameOriginScriptSpan?.data?.[HTTP_REQUEST_SAME_ORIGIN]).toBe(true);
101+
expect(sameOriginScriptSpan?.data?.[URL_FULL]).toMatch(/^https?:\/\/.+\/init\.bundle\.js$/);
74102

75103
const customScriptSpan = scriptSpans?.find(
76104
({ description }) => description === 'https://sentry-test-site.example/path/to/script.js',
77105
);
78106

79107
expect(imgSpan).toEqual({
80108
data: {
81-
'http.response.body.decoded_size': expect.any(Number),
82-
'http.response.body.size': expect.any(Number),
83-
'http.response.size': expect.any(Number),
84-
'http.request.connect_start': expect.any(Number),
85-
'http.request.connection_end': expect.any(Number),
86-
'http.request.domain_lookup_end': expect.any(Number),
87-
'http.request.domain_lookup_start': expect.any(Number),
88-
'http.request.fetch_start': expect.any(Number),
89-
'http.request.redirect_end': expect.any(Number),
90-
'http.request.redirect_start': expect.any(Number),
91-
'http.request.request_start': expect.any(Number),
92-
'http.request.secure_connection_start': expect.any(Number),
93-
'http.request.worker_start': expect.any(Number),
94-
'http.request.response_end': expect.any(Number),
95-
'http.request.response_start': expect.any(Number),
96-
'http.request.time_to_first_byte': expect.any(Number),
97-
'network.protocol.name': '',
98-
'network.protocol.version': 'unknown',
109+
[HTTP_RESPONSE_BODY_DECODED_SIZE]: expect.any(Number),
110+
[HTTP_RESPONSE_BODY_SIZE]: expect.any(Number),
111+
[HTTP_RESPONSE_SIZE]: expect.any(Number),
112+
[HTTP_REQUEST_CONNECT_START]: expect.any(Number),
113+
[HTTP_REQUEST_CONNECTION_END]: expect.any(Number),
114+
[HTTP_REQUEST_DOMAIN_LOOKUP_END]: expect.any(Number),
115+
[HTTP_REQUEST_DOMAIN_LOOKUP_START]: expect.any(Number),
116+
[HTTP_REQUEST_FETCH_START]: expect.any(Number),
117+
[HTTP_REQUEST_REDIRECT_END]: expect.any(Number),
118+
[HTTP_REQUEST_REDIRECT_START]: expect.any(Number),
119+
[HTTP_REQUEST_REQUEST_START]: expect.any(Number),
120+
[HTTP_REQUEST_SECURE_CONNECTION_START]: expect.any(Number),
121+
[HTTP_REQUEST_WORKER_START]: expect.any(Number),
122+
[HTTP_REQUEST_RESPONSE_END]: expect.any(Number),
123+
[HTTP_REQUEST_RESPONSE_START]: expect.any(Number),
124+
[HTTP_REQUEST_TIME_TO_FIRST_BYTE]: expect.any(Number),
125+
[NETWORK_PROTOCOL_NAME]: '',
126+
[NETWORK_PROTOCOL_VERSION]: 'unknown',
99127
[SENTRY_OP]: 'resource.img',
100128
[SENTRY_ORIGIN]: 'auto.resource.browser.metrics',
101-
'server.address': 'sentry-test-site.example',
102-
'url.domain': 'sentry-test-site.example',
103-
'http.request.same_origin': false,
104-
'url.scheme': 'https',
105-
'url.full': 'https://sentry-test-site.example/path/to/image.svg',
129+
[SERVER_ADDRESS]: 'sentry-test-site.example',
130+
[URL_DOMAIN]: 'sentry-test-site.example',
131+
[HTTP_REQUEST_SAME_ORIGIN]: false,
132+
[URL_SCHEME]: 'https',
133+
[URL_FULL]: 'https://sentry-test-site.example/path/to/image.svg',
106134
// WebKit reports `deliveryType` as of Playwright 1.63's build, but still no response status
107135
// or render blocking status.
108136
'http.response_delivery_type': '',
109137
...(!isWebkitRun && {
110-
'http.response.status_code': expect.any(Number),
111-
'resource.render_blocking_status': 'non-blocking',
138+
[HTTP_RESPONSE_STATUS_CODE]: expect.any(Number),
139+
[RESOURCE_RENDER_BLOCKING_STATUS]: 'non-blocking',
112140
}),
113141
},
114142
description: 'https://sentry-test-site.example/path/to/image.svg',
@@ -125,43 +153,43 @@ sentryTest('adds resource spans to pageload transaction', async ({ getLocalTestU
125153
// range check: TTFB is reasonably <10 seconds, which is really a check that we report it in
126154
// seconds rather than milliseconds. WebKit resolves these intercepted routes without measurable
127155
// delay, so only the other engines are held to a non-zero value.
128-
const imgSpanTtfb = imgSpan?.data['http.request.time_to_first_byte'];
156+
const imgSpanTtfb = imgSpan?.data[HTTP_REQUEST_TIME_TO_FIRST_BYTE];
129157
expect(imgSpanTtfb).toBeGreaterThan(isWebkitRun ? -1 : 0);
130158
expect(imgSpanTtfb).toBeLessThan(10);
131159

132160
expect(linkSpan).toEqual({
133161
data: {
134-
'http.response.body.decoded_size': expect.any(Number),
135-
'http.response.body.size': expect.any(Number),
136-
'http.response.size': expect.any(Number),
137-
'http.request.connect_start': expect.any(Number),
138-
'http.request.connection_end': expect.any(Number),
139-
'http.request.domain_lookup_end': expect.any(Number),
140-
'http.request.domain_lookup_start': expect.any(Number),
141-
'http.request.fetch_start': expect.any(Number),
142-
'http.request.redirect_end': expect.any(Number),
143-
'http.request.redirect_start': expect.any(Number),
144-
'http.request.request_start': expect.any(Number),
145-
'http.request.secure_connection_start': expect.any(Number),
146-
'http.request.worker_start': expect.any(Number),
147-
'http.request.response_end': expect.any(Number),
148-
'http.request.response_start': expect.any(Number),
149-
'http.request.time_to_first_byte': expect.any(Number),
150-
'network.protocol.name': '',
151-
'network.protocol.version': 'unknown',
162+
[HTTP_RESPONSE_BODY_DECODED_SIZE]: expect.any(Number),
163+
[HTTP_RESPONSE_BODY_SIZE]: expect.any(Number),
164+
[HTTP_RESPONSE_SIZE]: expect.any(Number),
165+
[HTTP_REQUEST_CONNECT_START]: expect.any(Number),
166+
[HTTP_REQUEST_CONNECTION_END]: expect.any(Number),
167+
[HTTP_REQUEST_DOMAIN_LOOKUP_END]: expect.any(Number),
168+
[HTTP_REQUEST_DOMAIN_LOOKUP_START]: expect.any(Number),
169+
[HTTP_REQUEST_FETCH_START]: expect.any(Number),
170+
[HTTP_REQUEST_REDIRECT_END]: expect.any(Number),
171+
[HTTP_REQUEST_REDIRECT_START]: expect.any(Number),
172+
[HTTP_REQUEST_REQUEST_START]: expect.any(Number),
173+
[HTTP_REQUEST_SECURE_CONNECTION_START]: expect.any(Number),
174+
[HTTP_REQUEST_WORKER_START]: expect.any(Number),
175+
[HTTP_REQUEST_RESPONSE_END]: expect.any(Number),
176+
[HTTP_REQUEST_RESPONSE_START]: expect.any(Number),
177+
[HTTP_REQUEST_TIME_TO_FIRST_BYTE]: expect.any(Number),
178+
[NETWORK_PROTOCOL_NAME]: '',
179+
[NETWORK_PROTOCOL_VERSION]: 'unknown',
152180
[SENTRY_OP]: 'resource.link',
153181
[SENTRY_ORIGIN]: 'auto.resource.browser.metrics',
154-
'server.address': 'sentry-test-site.example',
155-
'url.domain': 'sentry-test-site.example',
156-
'http.request.same_origin': false,
157-
'url.scheme': 'https',
158-
'url.full': 'https://sentry-test-site.example/path/to/style.css',
182+
[SERVER_ADDRESS]: 'sentry-test-site.example',
183+
[URL_DOMAIN]: 'sentry-test-site.example',
184+
[HTTP_REQUEST_SAME_ORIGIN]: false,
185+
[URL_SCHEME]: 'https',
186+
[URL_FULL]: 'https://sentry-test-site.example/path/to/style.css',
159187
// WebKit reports `deliveryType` as of Playwright 1.63's build, but still no response status
160188
// or render blocking status.
161189
'http.response_delivery_type': '',
162190
...(!isWebkitRun && {
163-
'http.response.status_code': expect.any(Number),
164-
'resource.render_blocking_status': 'non-blocking',
191+
[HTTP_RESPONSE_STATUS_CODE]: expect.any(Number),
192+
[RESOURCE_RENDER_BLOCKING_STATUS]: 'non-blocking',
165193
}),
166194
},
167195
description: 'https://sentry-test-site.example/path/to/style.css',
@@ -177,37 +205,37 @@ sentryTest('adds resource spans to pageload transaction', async ({ getLocalTestU
177205

178206
expect(customScriptSpan).toEqual({
179207
data: {
180-
'http.response.body.decoded_size': expect.any(Number),
181-
'http.response.body.size': expect.any(Number),
182-
'http.response.size': expect.any(Number),
183-
'http.request.connection_end': expect.any(Number),
184-
'http.request.connect_start': expect.any(Number),
185-
'http.request.domain_lookup_end': expect.any(Number),
186-
'http.request.domain_lookup_start': expect.any(Number),
187-
'http.request.fetch_start': expect.any(Number),
188-
'http.request.redirect_end': expect.any(Number),
189-
'http.request.redirect_start': expect.any(Number),
190-
'http.request.request_start': expect.any(Number),
191-
'http.request.secure_connection_start': expect.any(Number),
192-
'http.request.worker_start': expect.any(Number),
193-
'http.request.response_end': expect.any(Number),
194-
'http.request.response_start': expect.any(Number),
195-
'http.request.time_to_first_byte': expect.any(Number),
196-
'network.protocol.name': '',
197-
'network.protocol.version': 'unknown',
198-
'sentry.op': 'resource.script',
199-
'sentry.origin': 'auto.resource.browser.metrics',
200-
'server.address': 'sentry-test-site.example',
201-
'url.domain': 'sentry-test-site.example',
202-
'http.request.same_origin': false,
203-
'url.scheme': 'https',
204-
'url.full': 'https://sentry-test-site.example/path/to/script.js',
208+
[HTTP_RESPONSE_BODY_DECODED_SIZE]: expect.any(Number),
209+
[HTTP_RESPONSE_BODY_SIZE]: expect.any(Number),
210+
[HTTP_RESPONSE_SIZE]: expect.any(Number),
211+
[HTTP_REQUEST_CONNECTION_END]: expect.any(Number),
212+
[HTTP_REQUEST_CONNECT_START]: expect.any(Number),
213+
[HTTP_REQUEST_DOMAIN_LOOKUP_END]: expect.any(Number),
214+
[HTTP_REQUEST_DOMAIN_LOOKUP_START]: expect.any(Number),
215+
[HTTP_REQUEST_FETCH_START]: expect.any(Number),
216+
[HTTP_REQUEST_REDIRECT_END]: expect.any(Number),
217+
[HTTP_REQUEST_REDIRECT_START]: expect.any(Number),
218+
[HTTP_REQUEST_REQUEST_START]: expect.any(Number),
219+
[HTTP_REQUEST_SECURE_CONNECTION_START]: expect.any(Number),
220+
[HTTP_REQUEST_WORKER_START]: expect.any(Number),
221+
[HTTP_REQUEST_RESPONSE_END]: expect.any(Number),
222+
[HTTP_REQUEST_RESPONSE_START]: expect.any(Number),
223+
[HTTP_REQUEST_TIME_TO_FIRST_BYTE]: expect.any(Number),
224+
[NETWORK_PROTOCOL_NAME]: '',
225+
[NETWORK_PROTOCOL_VERSION]: 'unknown',
226+
[SENTRY_OP]: 'resource.script',
227+
[SENTRY_ORIGIN]: 'auto.resource.browser.metrics',
228+
[SERVER_ADDRESS]: 'sentry-test-site.example',
229+
[URL_DOMAIN]: 'sentry-test-site.example',
230+
[HTTP_REQUEST_SAME_ORIGIN]: false,
231+
[URL_SCHEME]: 'https',
232+
[URL_FULL]: 'https://sentry-test-site.example/path/to/script.js',
205233
// WebKit reports `deliveryType` as of Playwright 1.63's build, but still no response status
206234
// or render blocking status.
207235
'http.response_delivery_type': '',
208236
...(!isWebkitRun && {
209-
'http.response.status_code': expect.any(Number),
210-
'resource.render_blocking_status': 'non-blocking',
237+
[HTTP_RESPONSE_STATUS_CODE]: expect.any(Number),
238+
[RESOURCE_RENDER_BLOCKING_STATUS]: 'non-blocking',
211239
}),
212240
},
213241
description: 'https://sentry-test-site.example/path/to/script.js',

0 commit comments

Comments
 (0)