11import type { Route } from '@playwright/test' ;
22import { expect } from '@playwright/test' ;
3- import type { Event } from '@sentry/core' ;
3+ import { type Event , SEMANTIC_ATTRIBUTE_SENTRY_OP , SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core' ;
44
55import { sentryTest } from '../../../../utils/fixtures' ;
66import { getFirstSentryEnvelopeRequest , shouldSkipTracingTest } from '../../../../utils/helpers' ;
77
8- sentryTest ( 'should add resource spans to pageload transaction' , async ( { getLocalTestUrl, page } ) => {
8+ sentryTest ( 'should add resource spans to pageload transaction' , async ( { getLocalTestUrl, page, browserName } ) => {
99 if ( shouldSkipTracingTest ( ) ) {
1010 sentryTest . skip ( ) ;
1111 }
1212
13+ const isWebkitRun = browserName === 'webkit' ;
14+
1315 // Intercepting asset requests to avoid network-related flakiness and random retries (on Firefox).
1416 await page . route ( 'https://example.com/path/to/image.svg' , ( route : Route ) =>
15- route . fulfill ( { path : `${ __dirname } /assets/image.svg` } ) ,
17+ route . fulfill ( {
18+ path : `${ __dirname } /assets/image.svg` ,
19+ headers : {
20+ 'Timing-Allow-Origin' : '*' ,
21+ 'Content-Type' : 'image/svg+xml' ,
22+ } ,
23+ } ) ,
1624 ) ;
1725 await page . route ( 'https://example.com/path/to/script.js' , ( route : Route ) =>
18- route . fulfill ( { path : `${ __dirname } /assets/script.js` } ) ,
26+ route . fulfill ( {
27+ path : `${ __dirname } /assets/script.js` ,
28+ headers : {
29+ 'Timing-Allow-Origin' : '*' ,
30+ 'Content-Type' : 'application/javascript' ,
31+ } ,
32+ } ) ,
1933 ) ;
2034 await page . route ( 'https://example.com/path/to/style.css' , ( route : Route ) =>
21- route . fulfill ( { path : `${ __dirname } /assets/style.css` } ) ,
35+ route . fulfill ( {
36+ path : `${ __dirname } /assets/style.css` ,
37+ headers : {
38+ 'Timing-Allow-Origin' : '*' ,
39+ 'Content-Type' : 'text/css' ,
40+ } ,
41+ } ) ,
2242 ) ;
2343
2444 const url = await getLocalTestUrl ( { testDir : __dirname } ) ;
@@ -27,11 +47,14 @@ sentryTest('should add resource spans to pageload transaction', async ({ getLoca
2747 const resourceSpans = eventData . spans ?. filter ( ( { op } ) => op ?. startsWith ( 'resource' ) ) ;
2848
2949 const scriptSpans = resourceSpans ?. filter ( ( { op } ) => op === 'resource.script' ) ;
30- const linkSpans = resourceSpans ?. filter ( ( { op } ) => op === 'resource.link' ) ;
31- const imgSpans = resourceSpans ?. filter ( ( { op } ) => op === 'resource.img' ) ;
50+ const linkSpan = resourceSpans ?. filter ( ( { op } ) => op === 'resource.link' ) [ 0 ] ;
51+ const imgSpan = resourceSpans ?. filter ( ( { op } ) => op === 'resource.img' ) [ 0 ] ;
52+
53+ const spanId = eventData . contexts ?. trace ?. span_id ;
54+ const traceId = eventData . contexts ?. trace ?. trace_id ;
3255
33- expect ( imgSpans ) . toHaveLength ( 1 ) ;
34- expect ( linkSpans ) . toHaveLength ( 1 ) ;
56+ expect ( spanId ) . toBeDefined ( ) ;
57+ expect ( traceId ) . toBeDefined ( ) ;
3558
3659 const hasCdnBundle = ( process . env . PW_BUNDLE || '' ) . startsWith ( 'bundle' ) ;
3760
@@ -41,11 +64,90 @@ sentryTest('should add resource spans to pageload transaction', async ({ getLoca
4164 }
4265
4366 expect ( scriptSpans ?. map ( ( { description } ) => description ) . sort ( ) ) . toEqual ( expectedScripts ) ;
67+ expect ( scriptSpans ?. map ( ( { parent_span_id } ) => parent_span_id ) ) . toEqual ( expectedScripts . map ( ( ) => spanId ) ) ;
4468
45- const spanId = eventData . contexts ?. trace ?. span_id ;
69+ const customScriptSpan = scriptSpans ?. find (
70+ ( { description } ) => description === 'https://example.com/path/to/script.js' ,
71+ ) ;
4672
47- expect ( spanId ) . toBeDefined ( ) ;
48- expect ( imgSpans ?. [ 0 ] . parent_span_id ) . toBe ( spanId ) ;
49- expect ( linkSpans ?. [ 0 ] . parent_span_id ) . toBe ( spanId ) ;
50- expect ( scriptSpans ?. map ( ( { parent_span_id } ) => parent_span_id ) ) . toEqual ( expectedScripts . map ( ( ) => spanId ) ) ;
73+ expect ( imgSpan ) . toEqual ( {
74+ data : {
75+ 'http.decoded_response_content_length' : expect . any ( Number ) ,
76+ 'http.response_content_length' : expect . any ( Number ) ,
77+ 'http.response_transfer_size' : expect . any ( Number ) ,
78+ 'network.protocol.name' : '' ,
79+ 'network.protocol.version' : 'unknown' ,
80+ [ SEMANTIC_ATTRIBUTE_SENTRY_OP ] : 'resource.img' ,
81+ [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] : 'auto.resource.browser.metrics' ,
82+ 'server.address' : 'example.com' ,
83+ 'url.same_origin' : false ,
84+ 'url.scheme' : 'https' ,
85+ ...( ! isWebkitRun && {
86+ 'resource.render_blocking_status' : 'non-blocking' ,
87+ 'http.response_delivery_type' : '' ,
88+ } ) ,
89+ } ,
90+ description : 'https://example.com/path/to/image.svg' ,
91+ op : 'resource.img' ,
92+ origin : 'auto.resource.browser.metrics' ,
93+ parent_span_id : spanId ,
94+ span_id : expect . stringMatching ( / ^ [ a - f 0 - 9 ] { 16 } $ / ) ,
95+ start_timestamp : expect . any ( Number ) ,
96+ timestamp : expect . any ( Number ) ,
97+ trace_id : traceId ,
98+ } ) ;
99+
100+ expect ( linkSpan ) . toEqual ( {
101+ data : {
102+ 'http.decoded_response_content_length' : expect . any ( Number ) ,
103+ 'http.response_content_length' : expect . any ( Number ) ,
104+ 'http.response_transfer_size' : expect . any ( Number ) ,
105+ 'network.protocol.name' : '' ,
106+ 'network.protocol.version' : 'unknown' ,
107+ [ SEMANTIC_ATTRIBUTE_SENTRY_OP ] : 'resource.link' ,
108+ [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] : 'auto.resource.browser.metrics' ,
109+ 'server.address' : 'example.com' ,
110+ 'url.same_origin' : false ,
111+ 'url.scheme' : 'https' ,
112+ ...( ! isWebkitRun && {
113+ 'resource.render_blocking_status' : 'non-blocking' ,
114+ 'http.response_delivery_type' : '' ,
115+ } ) ,
116+ } ,
117+ description : 'https://example.com/path/to/style.css' ,
118+ op : 'resource.link' ,
119+ origin : 'auto.resource.browser.metrics' ,
120+ parent_span_id : spanId ,
121+ span_id : expect . stringMatching ( / ^ [ a - f 0 - 9 ] { 16 } $ / ) ,
122+ start_timestamp : expect . any ( Number ) ,
123+ timestamp : expect . any ( Number ) ,
124+ trace_id : traceId ,
125+ } ) ;
126+
127+ expect ( customScriptSpan ) . toEqual ( {
128+ data : {
129+ 'http.decoded_response_content_length' : expect . any ( Number ) ,
130+ 'http.response_content_length' : expect . any ( Number ) ,
131+ 'http.response_transfer_size' : expect . any ( Number ) ,
132+ 'network.protocol.name' : '' ,
133+ 'network.protocol.version' : 'unknown' ,
134+ 'sentry.op' : 'resource.script' ,
135+ 'sentry.origin' : 'auto.resource.browser.metrics' ,
136+ 'server.address' : 'example.com' ,
137+ 'url.same_origin' : false ,
138+ 'url.scheme' : 'https' ,
139+ ...( ! isWebkitRun && {
140+ 'resource.render_blocking_status' : 'non-blocking' ,
141+ 'http.response_delivery_type' : '' ,
142+ } ) ,
143+ } ,
144+ description : 'https://example.com/path/to/script.js' ,
145+ op : 'resource.script' ,
146+ origin : 'auto.resource.browser.metrics' ,
147+ parent_span_id : spanId ,
148+ span_id : expect . stringMatching ( / ^ [ a - f 0 - 9 ] { 16 } $ / ) ,
149+ start_timestamp : expect . any ( Number ) ,
150+ timestamp : expect . any ( Number ) ,
151+ trace_id : traceId ,
152+ } ) ;
51153} ) ;
0 commit comments