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