1
1
import { expect } from '@playwright/test' ;
2
2
3
3
import { sentryTest } from '../../../../utils/fixtures' ;
4
- import { envelopeRequestParser } from '../../../../utils/helpers' ;
4
+ import { envelopeRequestParser , waitForErrorRequest } from '../../../../utils/helpers' ;
5
5
import {
6
6
expectedClickBreadcrumb ,
7
7
expectedConsoleBreadcrumb ,
@@ -10,124 +10,133 @@ import {
10
10
import {
11
11
getReplayEvent ,
12
12
getReplayRecordingContent ,
13
+ isReplayEvent ,
13
14
shouldSkipReplayTest ,
14
15
waitForReplayRequest ,
15
16
} from '../../../../utils/replayHelpers' ;
16
17
17
- sentryTest (
18
- '[error-mode] should start recording and switch to session mode once an error is thrown' ,
19
- async ( { getLocalTestPath, page } ) => {
20
- if ( shouldSkipReplayTest ( ) ) {
21
- sentryTest . skip ( ) ;
22
- }
23
-
24
- let callsToSentry = 0 ;
25
- let errorEventId : string | undefined ;
26
- const reqPromise0 = waitForReplayRequest ( page , 0 ) ;
27
- const reqPromise1 = waitForReplayRequest ( page , 1 ) ;
28
- const reqPromise2 = waitForReplayRequest ( page , 2 ) ;
29
-
30
- await page . route ( 'https://dsn.ingest.sentry.io/**/*' , route => {
31
- const event = envelopeRequestParser ( route . request ( ) ) ;
32
- // error events have no type field
33
- if ( event && ! event . type && event . event_id ) {
34
- errorEventId = event . event_id ;
18
+ // TODO: Try to run this many times to identify flakes
19
+ for ( let i = 0 ; i < 100 ; i ++ ) {
20
+ sentryTest (
21
+ `[error-mode] should start recording and switch to session mode once an error is thrown RUN ${ i } ` ,
22
+ async ( { getLocalTestPath, page } ) => {
23
+ if ( shouldSkipReplayTest ( ) ) {
24
+ sentryTest . skip ( ) ;
35
25
}
36
- callsToSentry ++ ;
37
26
38
- return route . fulfill ( {
39
- status : 200 ,
40
- contentType : 'application/json' ,
41
- body : JSON . stringify ( { id : 'test-id' } ) ,
27
+ let callsToSentry = 0 ;
28
+ let errorEventId : string | undefined ;
29
+ const reqPromise0 = waitForReplayRequest ( page , 0 ) ;
30
+ const reqPromise1 = waitForReplayRequest ( page , 1 ) ;
31
+ const reqPromise2 = waitForReplayRequest ( page , 2 ) ;
32
+ const reqErrorPromise = waitForErrorRequest ( page ) ;
33
+
34
+ await page . route ( 'https://dsn.ingest.sentry.io/**/*' , route => {
35
+ const event = envelopeRequestParser ( route . request ( ) ) ;
36
+ // error events have no type field
37
+ if ( event && ! event . type && event . event_id ) {
38
+ errorEventId = event . event_id ;
39
+ }
40
+ // We only want to count errors & replays here
41
+ if ( event && ( ! event . type || isReplayEvent ( event ) ) ) {
42
+ callsToSentry ++ ;
43
+ }
44
+
45
+ return route . fulfill ( {
46
+ status : 200 ,
47
+ contentType : 'application/json' ,
48
+ body : JSON . stringify ( { id : 'test-id' } ) ,
49
+ } ) ;
42
50
} ) ;
43
- } ) ;
44
-
45
- const url = await getLocalTestPath ( { testDir : __dirname } ) ;
46
-
47
- await page . goto ( url ) ;
48
- await page . click ( '#go-background' ) ;
49
- expect ( callsToSentry ) . toEqual ( 0 ) ;
50
-
51
- await page . click ( '#error' ) ;
52
- const req0 = await reqPromise0 ;
53
-
54
- await page . click ( '#go-background' ) ;
55
- const req1 = await reqPromise1 ;
56
-
57
- expect ( callsToSentry ) . toEqual ( 3 ) ; // 1 error, 2 replay events
58
-
59
- await page . click ( '#log' ) ;
60
- await page . click ( '#go-background' ) ;
61
- const req2 = await reqPromise2 ;
62
-
63
- const event0 = getReplayEvent ( req0 ) ;
64
- const content0 = getReplayRecordingContent ( req0 ) ;
65
-
66
- const event1 = getReplayEvent ( req1 ) ;
67
- const content1 = getReplayRecordingContent ( req1 ) ;
68
-
69
- const event2 = getReplayEvent ( req2 ) ;
70
- const content2 = getReplayRecordingContent ( req2 ) ;
71
-
72
- expect ( event0 ) . toEqual (
73
- getExpectedReplayEvent ( {
74
- contexts : { replay : { error_sample_rate : 1 , session_sample_rate : 0 } } ,
75
- // @ts -ignore this is fine
76
- error_ids : [ errorEventId ] ,
77
- replay_type : 'error' ,
78
- } ) ,
79
- ) ;
80
-
81
- // The first event should have both, full and incremental snapshots,
82
- // as we recorded and kept all events in the buffer
83
- expect ( content0 . fullSnapshots ) . toHaveLength ( 1 ) ;
84
- // We don't know how many incremental snapshots we'll have (also browser-dependent),
85
- // but we know that we have at least 5
86
- expect ( content0 . incrementalSnapshots . length ) . toBeGreaterThan ( 5 ) ;
87
- // We want to make sure that the event that triggered the error was recorded.
88
- expect ( content0 . breadcrumbs ) . toEqual (
89
- expect . arrayContaining ( [
90
- {
91
- ...expectedClickBreadcrumb ,
92
- message : 'body > button#error' ,
93
- } ,
94
- ] ) ,
95
- ) ;
96
-
97
- expect ( event1 ) . toEqual (
98
- getExpectedReplayEvent ( {
99
- contexts : { replay : { error_sample_rate : 1 , session_sample_rate : 0 } } ,
100
- // @ts -ignore this is fine
101
- replay_type : 'error' , // although we're in session mode, we still send 'error' as replay_type
102
- replay_start_timestamp : undefined ,
103
- segment_id : 1 ,
104
- urls : [ ] ,
105
- } ) ,
106
- ) ;
107
-
108
- // Also the second snapshot should have a full snapshot, as we switched from error to session
109
- // mode which triggers another checkout
110
- expect ( content1 . fullSnapshots ) . toHaveLength ( 1 ) ;
111
- expect ( content1 . incrementalSnapshots ) . toHaveLength ( 0 ) ;
112
-
113
- // The next event should just be a normal replay event as we're now in session mode and
114
- // we continue recording everything
115
- expect ( event2 ) . toEqual (
116
- getExpectedReplayEvent ( {
117
- contexts : { replay : { error_sample_rate : 1 , session_sample_rate : 0 } } ,
118
- // @ts -ignore this is fine
119
- replay_type : 'error' ,
120
- replay_start_timestamp : undefined ,
121
- segment_id : 2 ,
122
- urls : [ ] ,
123
- } ) ,
124
- ) ;
125
-
126
- expect ( content2 . breadcrumbs ) . toEqual (
127
- expect . arrayContaining ( [
128
- { ...expectedClickBreadcrumb , message : 'body > button#log' } ,
129
- { ...expectedConsoleBreadcrumb , level : 'log' , message : 'Some message' } ,
130
- ] ) ,
131
- ) ;
132
- } ,
133
- ) ;
51
+
52
+ const url = await getLocalTestPath ( { testDir : __dirname } ) ;
53
+
54
+ await page . goto ( url ) ;
55
+ await page . click ( '#go-background' ) ;
56
+ expect ( callsToSentry ) . toEqual ( 0 ) ;
57
+
58
+ await page . click ( '#error' ) ;
59
+ const req0 = await reqPromise0 ;
60
+
61
+ void page . click ( '#go-background' ) ;
62
+ const req1 = await reqPromise1 ;
63
+ await reqErrorPromise ;
64
+
65
+ expect ( callsToSentry ) . toEqual ( 3 ) ; // 1 error, 2 replay events
66
+
67
+ void page . click ( '#log' ) ;
68
+ void page . click ( '#go-background' ) ;
69
+ const req2 = await reqPromise2 ;
70
+
71
+ const event0 = getReplayEvent ( req0 ) ;
72
+ const content0 = getReplayRecordingContent ( req0 ) ;
73
+
74
+ const event1 = getReplayEvent ( req1 ) ;
75
+ const content1 = getReplayRecordingContent ( req1 ) ;
76
+
77
+ const event2 = getReplayEvent ( req2 ) ;
78
+ const content2 = getReplayRecordingContent ( req2 ) ;
79
+
80
+ expect ( event0 ) . toEqual (
81
+ getExpectedReplayEvent ( {
82
+ contexts : { replay : { error_sample_rate : 1 , session_sample_rate : 0 } } ,
83
+ // @ts -ignore this is fine
84
+ error_ids : [ errorEventId ] ,
85
+ replay_type : 'error' ,
86
+ } ) ,
87
+ ) ;
88
+
89
+ // The first event should have both, full and incremental snapshots,
90
+ // as we recorded and kept all events in the buffer
91
+ expect ( content0 . fullSnapshots ) . toHaveLength ( 1 ) ;
92
+ // We don't know how many incremental snapshots we'll have (also browser-dependent),
93
+ // but we know that we have at least 5
94
+ expect ( content0 . incrementalSnapshots . length ) . toBeGreaterThan ( 5 ) ;
95
+ // We want to make sure that the event that triggered the error was recorded.
96
+ expect ( content0 . breadcrumbs ) . toEqual (
97
+ expect . arrayContaining ( [
98
+ {
99
+ ...expectedClickBreadcrumb ,
100
+ message : 'body > button#error' ,
101
+ } ,
102
+ ] ) ,
103
+ ) ;
104
+
105
+ expect ( event1 ) . toEqual (
106
+ getExpectedReplayEvent ( {
107
+ contexts : { replay : { error_sample_rate : 1 , session_sample_rate : 0 } } ,
108
+ // @ts -ignore this is fine
109
+ replay_type : 'error' , // although we're in session mode, we still send 'error' as replay_type
110
+ replay_start_timestamp : undefined ,
111
+ segment_id : 1 ,
112
+ urls : [ ] ,
113
+ } ) ,
114
+ ) ;
115
+
116
+ // Also the second snapshot should have a full snapshot, as we switched from error to session
117
+ // mode which triggers another checkout
118
+ expect ( content1 . fullSnapshots ) . toHaveLength ( 1 ) ;
119
+ expect ( content1 . incrementalSnapshots ) . toHaveLength ( 0 ) ;
120
+
121
+ // The next event should just be a normal replay event as we're now in session mode and
122
+ // we continue recording everything
123
+ expect ( event2 ) . toEqual (
124
+ getExpectedReplayEvent ( {
125
+ contexts : { replay : { error_sample_rate : 1 , session_sample_rate : 0 } } ,
126
+ // @ts -ignore this is fine
127
+ replay_type : 'error' ,
128
+ replay_start_timestamp : undefined ,
129
+ segment_id : 2 ,
130
+ urls : [ ] ,
131
+ } ) ,
132
+ ) ;
133
+
134
+ expect ( content2 . breadcrumbs ) . toEqual (
135
+ expect . arrayContaining ( [
136
+ { ...expectedClickBreadcrumb , message : 'body > button#log' } ,
137
+ { ...expectedConsoleBreadcrumb , level : 'log' , message : 'Some message' } ,
138
+ ] ) ,
139
+ ) ;
140
+ } ,
141
+ ) ;
142
+ }
0 commit comments