@@ -5,7 +5,14 @@ import type { Event } from '@sentry/types';
5
5
import { sentryTest } from '../../../../utils/fixtures' ;
6
6
import { getFirstSentryEnvelopeRequest , shouldSkipTracingTest } from '../../../../utils/helpers' ;
7
7
8
- sentryTest ( 'should capture a LCP vital with element details.' , async ( { browserName, getLocalTestUrl, page } ) => {
8
+ /*
9
+ Because we "serve" the html test page as a static file, all requests for the image
10
+ are considered 3rd party requests. So the LCP value we obtain for the image is also
11
+ considered a 3rd party LCP value, meaning `renderTime` is only set if we also
12
+ return the `Timing-Allow-Origin` header.
13
+ */
14
+
15
+ sentryTest ( 'captures LCP vitals with element details.' , async ( { browserName, getLocalTestUrl, page } ) => {
9
16
if ( shouldSkipTracingTest ( ) || browserName !== 'chromium' ) {
10
17
sentryTest . skip ( ) ;
11
18
}
@@ -16,17 +23,50 @@ sentryTest('should capture a LCP vital with element details.', async ({ browserN
16
23
} ) ;
17
24
18
25
const url = await getLocalTestUrl ( { testDir : __dirname } ) ;
19
- const [ eventData ] = await Promise . all ( [
20
- getFirstSentryEnvelopeRequest < Event > ( page ) ,
21
- page . goto ( url ) ,
22
- page . locator ( 'button' ) . click ( ) ,
23
- ] ) ;
26
+ const [ eventData ] = await Promise . all ( [ getFirstSentryEnvelopeRequest < Event > ( page ) , page . goto ( url ) ] ) ;
24
27
25
28
expect ( eventData . measurements ) . toBeDefined ( ) ;
26
29
expect ( eventData . measurements ?. lcp ?. value ) . toBeDefined ( ) ;
27
30
28
- // XXX: This should be body > img, but it can be flakey as sometimes it will report
29
- // the button as LCP.
30
31
expect ( eventData . contexts ?. trace ?. data ?. [ 'lcp.element' ] . startsWith ( 'body >' ) ) . toBe ( true ) ;
31
32
expect ( eventData . contexts ?. trace ?. data ?. [ 'lcp.size' ] ) . toBeGreaterThan ( 0 ) ;
33
+ expect ( eventData . contexts ?. trace ?. data ?. [ 'lcp.loadTime' ] ) . toBeGreaterThan ( 0 ) ;
34
+
35
+ // renderTime is 0 because we don't return the `Timing-Allow-Origin` header
36
+ // and the image is loaded from a 3rd party origin
37
+ expect ( eventData . contexts ?. trace ?. data ?. [ 'lcp.renderTime' ] ) . toBe ( 0 ) ;
38
+
39
+ // The LCP value should be the loadTime because the renderTime is not set
40
+ expect ( eventData . measurements ?. lcp ?. value ) . toBeCloseTo ( eventData . contexts ?. trace ?. data ?. [ 'lcp.loadTime' ] ) ;
32
41
} ) ;
42
+
43
+ sentryTest (
44
+ 'captures LCP renderTime when returning Timing-Allow-Origin header.' ,
45
+ async ( { browserName, getLocalTestUrl, page } ) => {
46
+ if ( shouldSkipTracingTest ( ) || browserName !== 'chromium' ) {
47
+ sentryTest . skip ( ) ;
48
+ }
49
+
50
+ page . route ( '**' , route => route . continue ( ) ) ;
51
+ page . route ( '**/my/image.png' , async ( route : Route ) => {
52
+ return route . fulfill ( {
53
+ path : `${ __dirname } /assets/sentry-logo-600x179.png` ,
54
+ headers : { 'Timing-Allow-Origin' : '*' } ,
55
+ } ) ;
56
+ } ) ;
57
+
58
+ const url = await getLocalTestUrl ( { testDir : __dirname } ) ;
59
+ const [ eventData ] = await Promise . all ( [ getFirstSentryEnvelopeRequest < Event > ( page ) , page . goto ( url ) ] ) ;
60
+
61
+ expect ( eventData . measurements ) . toBeDefined ( ) ;
62
+ expect ( eventData . measurements ?. lcp ?. value ) . toBeDefined ( ) ;
63
+
64
+ expect ( eventData . contexts ?. trace ?. data ?. [ 'lcp.element' ] . startsWith ( 'body >' ) ) . toBe ( true ) ;
65
+ expect ( eventData . contexts ?. trace ?. data ?. [ 'lcp.size' ] ) . toBeGreaterThan ( 0 ) ;
66
+ expect ( eventData . contexts ?. trace ?. data ?. [ 'lcp.loadTime' ] ) . toBeGreaterThan ( 0 ) ;
67
+ expect ( eventData . contexts ?. trace ?. data ?. [ 'lcp.renderTime' ] ) . toBeGreaterThan ( 0 ) ;
68
+
69
+ // The LCP value should be the renderTime because the renderTime is set
70
+ expect ( eventData . measurements ?. lcp ?. value ) . toBeCloseTo ( eventData . contexts ?. trace ?. data ?. [ 'lcp.renderTime' ] ) ;
71
+ } ,
72
+ ) ;
0 commit comments