11import { expect } from '@playwright/test' ;
2+ import type { replayIntegration as actualReplayIntegration } from '@sentry-internal/replay' ;
23import { sentryTest } from '../../../utils/fixtures' ;
34import { getExpectedReplayEvent } from '../../../utils/replayEventTemplates' ;
45import {
@@ -13,55 +14,122 @@ import {
1314// Session should expire after 2s - keep in sync with init.js
1415const SESSION_TIMEOUT = 2000 ;
1516
16- sentryTest ( 'handles an expired session' , async ( { browserName, forceFlushReplay, getLocalTestUrl, page } ) => {
17- if ( shouldSkipReplayTest ( ) || browserName !== 'chromium' ) {
18- sentryTest . skip ( ) ;
19- }
17+ sentryTest (
18+ 'handles an expired session that re-samples to session' ,
19+ async ( { browserName, forceFlushReplay, getLocalTestUrl, page } ) => {
20+ if ( shouldSkipReplayTest ( ) || browserName !== 'chromium' ) {
21+ sentryTest . skip ( ) ;
22+ }
2023
21- const reqPromise0 = waitForReplayRequest ( page , 0 ) ;
22- const reqPromise1 = waitForReplayRequest ( page , 1 ) ;
24+ const reqPromise0 = waitForReplayRequest ( page , 0 ) ;
25+ const reqPromise1 = waitForReplayRequest ( page , 1 ) ;
2326
24- const url = await getLocalTestUrl ( { testDir : __dirname } ) ;
27+ const url = await getLocalTestUrl ( { testDir : __dirname } ) ;
2528
26- await page . goto ( url ) ;
27- const req0 = await reqPromise0 ;
29+ await page . goto ( url ) ;
30+ const req0 = await reqPromise0 ;
2831
29- const replayEvent0 = getReplayEvent ( req0 ) ;
30- expect ( replayEvent0 ) . toEqual ( getExpectedReplayEvent ( { } ) ) ;
32+ const replayEvent0 = getReplayEvent ( req0 ) ;
33+ expect ( replayEvent0 ) . toEqual ( getExpectedReplayEvent ( { } ) ) ;
3134
32- const fullSnapshots0 = getFullRecordingSnapshots ( req0 ) ;
33- expect ( fullSnapshots0 . length ) . toEqual ( 1 ) ;
34- const stringifiedSnapshot = normalize ( fullSnapshots0 [ 0 ] ) ;
35- expect ( stringifiedSnapshot ) . toMatchSnapshot ( 'snapshot-0.json' ) ;
35+ const fullSnapshots0 = getFullRecordingSnapshots ( req0 ) ;
36+ expect ( fullSnapshots0 . length ) . toEqual ( 1 ) ;
37+ const stringifiedSnapshot = normalize ( fullSnapshots0 [ 0 ] ) ;
38+ expect ( stringifiedSnapshot ) . toMatchSnapshot ( 'snapshot-0.json' ) ;
3639
37- // We wait for another segment 0
38- const reqPromise2 = waitForReplayRequest ( page , 0 ) ;
40+ // We wait for another segment 0
41+ const reqPromise2 = waitForReplayRequest ( page , 0 ) ;
3942
40- await page . locator ( '#button1' ) . click ( ) ;
41- await forceFlushReplay ( ) ;
42- const req1 = await reqPromise1 ;
43+ await page . locator ( '#button1' ) . click ( ) ;
44+ await forceFlushReplay ( ) ;
45+ const req1 = await reqPromise1 ;
4346
44- const replayEvent1 = getReplayEvent ( req1 ) ;
45- expect ( replayEvent1 ) . toEqual ( getExpectedReplayEvent ( { segment_id : 1 , urls : [ ] } ) ) ;
47+ const replayEvent1 = getReplayEvent ( req1 ) ;
48+ expect ( replayEvent1 ) . toEqual ( getExpectedReplayEvent ( { segment_id : 1 , urls : [ ] } ) ) ;
4649
47- const replay = await getReplaySnapshot ( page ) ;
48- const oldSessionId = replay . session ?. id ;
50+ const replay = await getReplaySnapshot ( page ) ;
51+ const oldSessionId = replay . session ?. id ;
4952
50- await new Promise ( resolve => setTimeout ( resolve , SESSION_TIMEOUT ) ) ;
53+ await new Promise ( resolve => setTimeout ( resolve , SESSION_TIMEOUT ) ) ;
5154
52- await page . locator ( '#button2' ) . click ( ) ;
53- await forceFlushReplay ( ) ;
54- const req2 = await reqPromise2 ;
55+ await page . locator ( '#button2' ) . click ( ) ;
56+ await forceFlushReplay ( ) ;
57+ const req2 = await reqPromise2 ;
5558
56- const replay2 = await getReplaySnapshot ( page ) ;
59+ const replay2 = await getReplaySnapshot ( page ) ;
5760
58- expect ( replay2 . session ?. id ) . not . toEqual ( oldSessionId ) ;
61+ expect ( replay2 . session ?. id ) . not . toEqual ( oldSessionId ) ;
5962
60- const replayEvent2 = getReplayEvent ( req2 ) ;
61- expect ( replayEvent2 ) . toEqual ( getExpectedReplayEvent ( { } ) ) ;
63+ const replayEvent2 = getReplayEvent ( req2 ) ;
64+ expect ( replayEvent2 ) . toEqual ( getExpectedReplayEvent ( { } ) ) ;
6265
63- const fullSnapshots2 = getFullRecordingSnapshots ( req2 ) ;
64- expect ( fullSnapshots2 . length ) . toEqual ( 1 ) ;
65- const stringifiedSnapshot2 = normalize ( fullSnapshots2 [ 0 ] ) ;
66- expect ( stringifiedSnapshot2 ) . toMatchSnapshot ( 'snapshot-2.json' ) ;
67- } ) ;
66+ const fullSnapshots2 = getFullRecordingSnapshots ( req2 ) ;
67+ expect ( fullSnapshots2 . length ) . toEqual ( 1 ) ;
68+ const stringifiedSnapshot2 = normalize ( fullSnapshots2 [ 0 ] ) ;
69+ expect ( stringifiedSnapshot2 ) . toMatchSnapshot ( 'snapshot-2.json' ) ;
70+ } ,
71+ ) ;
72+
73+ sentryTest (
74+ 'handles an expired session that re-samples to buffer' ,
75+ async ( { browserName, forceFlushReplay, getLocalTestUrl, page } ) => {
76+ if ( shouldSkipReplayTest ( ) || browserName !== 'chromium' ) {
77+ sentryTest . skip ( ) ;
78+ }
79+
80+ const reqPromise0 = waitForReplayRequest ( page , 0 ) ;
81+ const reqPromise1 = waitForReplayRequest ( page , 1 ) ;
82+
83+ const url = await getLocalTestUrl ( { testDir : __dirname } ) ;
84+
85+ await page . goto ( url ) ;
86+ const req0 = await reqPromise0 ;
87+
88+ const replayEvent0 = getReplayEvent ( req0 ) ;
89+ expect ( replayEvent0 ) . toEqual ( getExpectedReplayEvent ( { } ) ) ;
90+
91+ const fullSnapshots0 = getFullRecordingSnapshots ( req0 ) ;
92+ expect ( fullSnapshots0 . length ) . toEqual ( 1 ) ;
93+ const stringifiedSnapshot = normalize ( fullSnapshots0 [ 0 ] ) ;
94+ expect ( stringifiedSnapshot ) . toMatchSnapshot ( 'snapshot-0.json' ) ;
95+
96+ await page . locator ( '#button1' ) . click ( ) ;
97+ await forceFlushReplay ( ) ;
98+ const req1 = await reqPromise1 ;
99+
100+ const replayEvent1 = getReplayEvent ( req1 ) ;
101+ expect ( replayEvent1 ) . toEqual ( getExpectedReplayEvent ( { segment_id : 1 , urls : [ ] } ) ) ;
102+
103+ const replay = await getReplaySnapshot ( page ) ;
104+ const oldSessionId = replay . session ?. id ;
105+
106+ await new Promise ( resolve => setTimeout ( resolve , SESSION_TIMEOUT ) ) ;
107+ await page . evaluate ( ( ) => {
108+ const replayIntegration = ( window as unknown as Window & { Replay : ReturnType < typeof actualReplayIntegration > } )
109+ . Replay ;
110+ replayIntegration [ '_replay' ] . getOptions ( ) . errorSampleRate = 1.0 ;
111+ replayIntegration [ '_replay' ] . getOptions ( ) . sessionSampleRate = 0.0 ;
112+ } ) ;
113+
114+ let wasReplayFlushed = false ;
115+ page . on ( 'request' , request => {
116+ if ( request . url ( ) . includes ( '/api/1337/envelope/' ) ) {
117+ wasReplayFlushed = true ;
118+ }
119+ } ) ;
120+ await page . locator ( '#button2' ) . click ( ) ;
121+ await forceFlushReplay ( ) ;
122+
123+ // This timeout is not ideal, but not sure of a better way to ensure replay is not flushed
124+ await new Promise ( resolve => setTimeout ( resolve , SESSION_TIMEOUT ) ) ;
125+
126+ expect ( wasReplayFlushed ) . toBe ( false ) ;
127+
128+ const currentSessionId = await page . evaluate ( ( ) => {
129+ // @ts -expect-error - Replay is not typed
130+ return window . Replay . _replay . session ?. id ;
131+ } ) ;
132+
133+ expect ( currentSessionId ) . not . toEqual ( oldSessionId ) ;
134+ } ,
135+ ) ;
0 commit comments