@@ -3,7 +3,12 @@ import type * as Sentry from '@sentry/browser';
33import type { EventEnvelopeHeaders } from '@sentry/types' ;
44
55import { sentryTest } from '../../../utils/fixtures' ;
6- import { envelopeRequestParser , shouldSkipTracingTest , waitForTransactionRequest } from '../../../utils/helpers' ;
6+ import {
7+ envelopeRequestParser ,
8+ shouldSkipTracingTest ,
9+ waitForErrorRequest ,
10+ waitForTransactionRequest ,
11+ } from '../../../utils/helpers' ;
712import { getReplaySnapshot , shouldSkipReplayTest , waitForReplayRunning } from '../../../utils/replayHelpers' ;
813
914type TestWindow = Window & {
@@ -216,3 +221,67 @@ sentryTest(
216221 } ) ;
217222 } ,
218223) ;
224+
225+ sentryTest ( 'should add replay_id to error DSC while replay is active' , async ( { getLocalTestPath, page } ) => {
226+ if ( shouldSkipReplayTest ( ) ) {
227+ sentryTest . skip ( ) ;
228+ }
229+
230+ await page . route ( 'https://dsn.ingest.sentry.io/**/*' , route => {
231+ return route . fulfill ( {
232+ status : 200 ,
233+ contentType : 'application/json' ,
234+ body : JSON . stringify ( { id : 'test-id' } ) ,
235+ } ) ;
236+ } ) ;
237+
238+ const url = await getLocalTestPath ( { testDir : __dirname } ) ;
239+ await page . goto ( url ) ;
240+
241+ const error1Req = waitForErrorRequest ( page , event => event . exception ?. values ?. [ 0 ] . value === 'This is error #1' ) ;
242+ const error2Req = waitForErrorRequest ( page , event => event . exception ?. values ?. [ 0 ] . value === 'This is error #2' ) ;
243+
244+ // We want to wait for the transaction to be done, to ensure we have a consistent test
245+ const transactionReq = shouldSkipTracingTest ( ) ? Promise . resolve ( ) : waitForTransactionRequest ( page ) ;
246+
247+ // Wait for this to be available
248+ await page . waitForFunction ( '!!window.Replay' ) ;
249+
250+ // We have to start replay before we finish the transaction, otherwise the DSC will not be frozen with the Replay ID
251+ await page . evaluate ( 'window.Replay.start();' ) ;
252+ await waitForReplayRunning ( page ) ;
253+ await transactionReq ;
254+
255+ await page . evaluate ( 'window._triggerError(1)' ) ;
256+
257+ const error1Header = envelopeRequestParser ( await error1Req , 0 ) as EventEnvelopeHeaders ;
258+ const replay = await getReplaySnapshot ( page ) ;
259+
260+ expect ( replay . session ?. id ) . toBeDefined ( ) ;
261+
262+ expect ( error1Header . trace ) . toBeDefined ( ) ;
263+ expect ( error1Header . trace ) . toEqual ( {
264+ environment : 'production' ,
265+ sample_rate : '1' ,
266+ trace_id : expect . any ( String ) ,
267+ public_key : 'public' ,
268+ replay_id : replay . session ?. id ,
269+ sampled : 'true' ,
270+ } ) ;
271+
272+ // Now end replay and trigger another error, it should not have a replay_id in DSC anymore
273+ await page . evaluate ( 'window.Replay.stop();' ) ;
274+ await page . waitForFunction ( '!window.Replay.getReplayId();' ) ;
275+ await page . evaluate ( 'window._triggerError(2)' ) ;
276+
277+ const error2Header = envelopeRequestParser ( await error2Req , 0 ) as EventEnvelopeHeaders ;
278+
279+ expect ( error2Header . trace ) . toBeDefined ( ) ;
280+ expect ( error2Header . trace ) . toEqual ( {
281+ environment : 'production' ,
282+ sample_rate : '1' ,
283+ trace_id : expect . any ( String ) ,
284+ public_key : 'public' ,
285+ sampled : 'true' ,
286+ } ) ;
287+ } ) ;
0 commit comments