@@ -272,24 +272,46 @@ class SentrySessionReplayIntegrationTests: XCTestCase {
272
272
}
273
273
274
274
func testBufferReplayIgnoredBecauseSampleRateForCrash( ) throws {
275
- startSDK ( sessionSampleRate: 1 , errorSampleRate: 1 )
275
+ // -- Arrange --
276
+ // Use deterministic random number to avoid flaky test behavior.
277
+ // CRITICAL: Set random value to 1.0 to ensure shouldReplayFullSession(sessionSampleRate) returns false,
278
+ // preventing the session from starting as a full session. Buffer replay sample rate checks
279
+ // only apply to non-full sessions. The sample rate check uses: random >= errorSampleRate
280
+ // With errorSampleRate=0 and random=1.0: 1.0 >= 0 = true → replay dropped
281
+ SentryDependencyContainer . sharedInstance ( ) . random = TestRandom ( value: 1.0 )
282
+
283
+ // Start current session with 0% session sample rate to ensure it's NOT a full session
284
+ // (shouldReplayFullSession: 1.0 < 0 = false), but 100% error sample rate would normally
285
+ // capture all error replays if this were not a buffer replay from previous session
286
+ startSDK ( sessionSampleRate: 0 , errorSampleRate: 1 )
276
287
277
288
let client = SentryClient ( options: try XCTUnwrap ( SentrySDKInternal . options) )
278
289
let scope = Scope ( )
279
290
let hub = TestHub ( client: client, andScope: scope)
280
291
SentrySDKInternal . setCurrentHub ( hub)
281
292
let expectation = expectation ( description: " Replay to be captured " )
282
- expectation. isInverted = true
283
- hub. onReplayCapture = {
293
+ expectation. isInverted = true // We expect NO replay to be captured
294
+ hub. onReplayCapture = {
284
295
expectation. fulfill ( )
285
296
}
286
-
297
+
298
+ // -- Act --
299
+ // Create a previous session replay file with 0% error sample rate.
300
+ // This simulates a previous session that crashed and had error replay disabled.
301
+ // The key insight: replay capture decision uses the PREVIOUS session's sample rate,
302
+ // not the current session's sample rate, because the replay frames were recorded
303
+ // during the previous session with its own sampling configuration.
287
304
try createLastSessionReplay ( writeSessionInfo: false , errorSampleRate: 0 )
288
305
let crash = Event ( error: NSError ( domain: " Error " , code: 1 ) )
289
306
crash. context = [ : ]
290
307
crash. isFatalEvent = true
291
- globalEventProcessor. reportAll ( crash)
292
-
308
+ globalEventProcessor. reportAll ( crash) // This triggers resumePreviousSessionReplay
309
+
310
+ // -- Assert --
311
+ // The replay should be dropped because:
312
+ // 1. Previous session had errorSampleRate = 0 (no error replays wanted)
313
+ // 2. Sample rate check: 1.0 >= 0 = true → drop replay
314
+ // 3. Current session's errorSampleRate = 1 is irrelevant for previous session data
293
315
wait ( for: [ expectation] , timeout: 1 )
294
316
XCTAssertEqual ( hub. capturedReplayRecordingVideo. count, 0 )
295
317
}
0 commit comments