@@ -36,19 +36,25 @@ afterEach(() => {
36
36
( client . getTransport ( ) ?. send as MockTransport ) . mockClear ( ) ;
37
37
} ) ;
38
38
39
- type SentReplayExpected = {
40
- envelopeHeader ?: {
41
- event_id : string ;
42
- sent_at : string ;
43
- sdk : {
44
- name : string ;
45
- version ?: string ;
46
- } ;
39
+ type EnvelopeHeader = {
40
+ event_id : string ;
41
+ sent_at : string ;
42
+ sdk : {
43
+ name : string ;
44
+ version ?: string ;
47
45
} ;
48
- replayEventHeader ?: { type : 'replay_event' } ;
49
- replayEventPayload ?: Record < string , unknown > ;
50
- recordingHeader ?: { type : 'replay_recording' ; length : number } ;
51
- recordingPayloadHeader ?: Record < string , unknown > ;
46
+ } ;
47
+
48
+ type ReplayEventHeader = { type : 'replay_event' } ;
49
+ type ReplayEventPayload = Record < string , unknown > ;
50
+ type RecordingHeader = { type : 'replay_recording' ; length : number } ;
51
+ type RecordingPayloadHeader = Record < string , unknown > ;
52
+ type SentReplayExpected = {
53
+ envelopeHeader ?: EnvelopeHeader ;
54
+ replayEventHeader ?: ReplayEventHeader ;
55
+ replayEventPayload ?: ReplayEventPayload ;
56
+ recordingHeader ?: RecordingHeader ;
57
+ recordingPayloadHeader ?: RecordingPayloadHeader ;
52
58
events ?: string | Uint8Array ;
53
59
} ;
54
60
@@ -70,20 +76,27 @@ const toHaveSameSession = function (received: jest.Mocked<ReplayContainer>, expe
70
76
} ;
71
77
} ;
72
78
73
- /**
74
- * Checks the last call to `fetch` and ensures a replay was uploaded by
75
- * checking the `fetch()` request's body.
76
- */
77
- // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
78
- const toHaveSentReplay = function (
79
- _received : jest . Mocked < ReplayContainer > ,
79
+ type Result = {
80
+ passed : boolean ;
81
+ key : string ;
82
+ expectedVal : SentReplayExpected [ keyof SentReplayExpected ] ;
83
+ actualVal : SentReplayExpected [ keyof SentReplayExpected ] ;
84
+ } ;
85
+ type Call = [
86
+ EnvelopeHeader ,
87
+ [
88
+ [ ReplayEventHeader | undefined , ReplayEventPayload | undefined ] ,
89
+ [ RecordingHeader | undefined , RecordingPayloadHeader | undefined ] ,
90
+ ] ,
91
+ ] ;
92
+ type CheckCallForSentReplayResult = { pass : boolean ; call : Call | undefined ; results : Result [ ] } ;
93
+
94
+ function checkCallForSentReplay (
95
+ call : Call | undefined ,
80
96
expected ?: SentReplayExpected | { sample : SentReplayExpected ; inverse : boolean } ,
81
- ) {
82
- const { calls } = ( getCurrentHub ( ) . getClient ( ) ?. getTransport ( ) ?. send as MockTransport ) . mock ;
83
- const lastCall = calls [ calls . length - 1 ] ?. [ 0 ] ;
84
-
85
- const envelopeHeader = lastCall ?. [ 0 ] ;
86
- const envelopeItems = lastCall ?. [ 1 ] || [ [ ] , [ ] ] ;
97
+ ) : CheckCallForSentReplayResult {
98
+ const envelopeHeader = call ?. [ 0 ] ;
99
+ const envelopeItems = call ?. [ 1 ] || [ [ ] , [ ] ] ;
87
100
const [ [ replayEventHeader , replayEventPayload ] , [ recordingHeader , recordingPayload ] = [ ] ] = envelopeItems ;
88
101
89
102
// @ts -ignore recordingPayload is always a string in our tests
@@ -116,34 +129,98 @@ const toHaveSentReplay = function (
116
129
. map ( key => {
117
130
const actualVal = actualObj [ key as keyof SentReplayExpected ] ;
118
131
const expectedVal = expectedObj [ key as keyof SentReplayExpected ] ;
119
- const matches = ! expectedVal || this . equals ( actualVal , expectedVal ) ;
132
+ const passed = ! expectedVal || this . equals ( actualVal , expectedVal ) ;
120
133
121
- return [ matches , key , expectedVal , actualVal ] ;
134
+ return { passed , key, expectedVal, actualVal } ;
122
135
} )
123
- . filter ( ( [ passed ] ) => ! passed )
136
+ . filter ( ( { passed } ) => ! passed )
124
137
: [ ] ;
125
138
126
- const payloadPassed = Boolean ( lastCall && ( ! expected || results . length === 0 ) ) ;
139
+ const pass = Boolean ( call && ( ! expected || results . length === 0 ) ) ;
140
+
141
+ return {
142
+ pass,
143
+ call,
144
+ results,
145
+ } ;
146
+ }
147
+
148
+ /**
149
+ * Checks all calls to `fetch` and ensures a replay was uploaded by
150
+ * checking the `fetch()` request's body.
151
+ */
152
+ // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
153
+ const toHaveSentReplay = function (
154
+ _received : jest . Mocked < ReplayContainer > ,
155
+ expected ?: SentReplayExpected | { sample : SentReplayExpected ; inverse : boolean } ,
156
+ ) {
157
+ const { calls } = ( getCurrentHub ( ) . getClient ( ) ?. getTransport ( ) ?. send as MockTransport ) . mock ;
158
+
159
+ let result : CheckCallForSentReplayResult ;
160
+
161
+ for ( const currentCall of calls ) {
162
+ result = checkCallForSentReplay . call ( this , currentCall [ 0 ] , expected ) ;
163
+ if ( result . pass ) {
164
+ break ;
165
+ }
166
+ }
167
+
168
+ // @ts -ignore use before assigned
169
+ const { results, call, pass } = result ;
127
170
128
171
const options = {
129
172
isNot : this . isNot ,
130
173
promise : this . promise ,
131
174
} ;
132
175
133
- const allPass = payloadPassed ;
134
-
135
176
return {
136
- pass : allPass ,
177
+ pass,
137
178
message : ( ) =>
138
- ! lastCall
139
- ? allPass
179
+ ! call
180
+ ? pass
140
181
? 'Expected Replay to not have been sent, but a request was attempted'
141
182
: 'Expected Replay to have been sent, but a request was not attempted'
142
183
: `${ this . utils . matcherHint ( 'toHaveSentReplay' , undefined , undefined , options ) } \n\n${ results
143
184
. map (
144
- ( [ , key , expected , actual ] ) =>
145
- `Expected (key: ${ key } ): ${ payloadPassed ? 'not ' : '' } ${ this . utils . printExpected ( expected ) } \n` +
146
- `Received (key: ${ key } ): ${ this . utils . printReceived ( actual ) } ` ,
185
+ ( { key, expectedVal, actualVal } : Result ) =>
186
+ `Expected (key: ${ key } ): ${ pass ? 'not ' : '' } ${ this . utils . printExpected ( expectedVal ) } \n` +
187
+ `Received (key: ${ key } ): ${ this . utils . printReceived ( actualVal ) } ` ,
188
+ )
189
+ . join ( '\n' ) } `,
190
+ } ;
191
+ } ;
192
+
193
+ /**
194
+ * Checks the last call to `fetch` and ensures a replay was uploaded by
195
+ * checking the `fetch()` request's body.
196
+ */
197
+ // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
198
+ const toHaveLastSentReplay = function (
199
+ _received : jest . Mocked < ReplayContainer > ,
200
+ expected ?: SentReplayExpected | { sample : SentReplayExpected ; inverse : boolean } ,
201
+ ) {
202
+ const { calls } = ( getCurrentHub ( ) . getClient ( ) ?. getTransport ( ) ?. send as MockTransport ) . mock ;
203
+ const lastCall = calls [ calls . length - 1 ] ?. [ 0 ] ;
204
+
205
+ const { results, call, pass } = checkCallForSentReplay . call ( this , lastCall , expected ) ;
206
+
207
+ const options = {
208
+ isNot : this . isNot ,
209
+ promise : this . promise ,
210
+ } ;
211
+
212
+ return {
213
+ pass,
214
+ message : ( ) =>
215
+ ! call
216
+ ? pass
217
+ ? 'Expected Replay to not have been sent, but a request was attempted'
218
+ : 'Expected Replay to have last been sent, but a request was not attempted'
219
+ : `${ this . utils . matcherHint ( 'toHaveSentReplay' , undefined , undefined , options ) } \n\n${ results
220
+ . map (
221
+ ( { key, expectedVal, actualVal } : Result ) =>
222
+ `Expected (key: ${ key } ): ${ pass ? 'not ' : '' } ${ this . utils . printExpected ( expectedVal ) } \n` +
223
+ `Received (key: ${ key } ): ${ this . utils . printReceived ( actualVal ) } ` ,
147
224
)
148
225
. join ( '\n' ) } `,
149
226
} ;
@@ -152,17 +229,20 @@ const toHaveSentReplay = function (
152
229
expect . extend ( {
153
230
toHaveSameSession,
154
231
toHaveSentReplay,
232
+ toHaveLastSentReplay,
155
233
} ) ;
156
234
157
235
declare global {
158
236
// eslint-disable-next-line @typescript-eslint/no-namespace
159
237
namespace jest {
160
238
interface AsymmetricMatchers {
161
239
toHaveSentReplay ( expected ?: SentReplayExpected ) : void ;
240
+ toHaveLastSentReplay ( expected ?: SentReplayExpected ) : void ;
162
241
toHaveSameSession ( expected : undefined | Session ) : void ;
163
242
}
164
243
interface Matchers < R > {
165
244
toHaveSentReplay ( expected ?: SentReplayExpected ) : R ;
245
+ toHaveLastSentReplay ( expected ?: SentReplayExpected ) : R ;
166
246
toHaveSameSession ( expected : undefined | Session ) : R ;
167
247
}
168
248
}
0 commit comments