@@ -969,6 +969,93 @@ class ReplayIntegrationTest {
969969 assertFalse(replay.isDebugMaskingOverlayEnabled)
970970 }
971971
972+ @Test
973+ fun `snapshot observer is invoked with bitmap and metadata` () {
974+ var callbackInvoked = false
975+ var receivedTimestamp = 0L
976+ var receivedScreen: String? = null
977+ var receivedBitmap: Bitmap ? = null
978+
979+ val captureStrategy =
980+ mock<CaptureStrategy > {
981+ doAnswer {
982+ ((it.arguments[1 ] as ReplayCache .(frameTimestamp: Long ) -> Unit )).invoke(
983+ fixture.replayCache,
984+ 1720693523997 ,
985+ )
986+ }
987+ .whenever(mock)
988+ .onScreenshotRecorded(anyOrNull<Bitmap >(), any())
989+ }
990+ val replay = fixture.getSut(context, replayCaptureStrategyProvider = { captureStrategy })
991+
992+ fixture.scopes.configureScope { it.screen = " MainActivity" }
993+ replay.register(fixture.scopes, fixture.options)
994+ replay.start()
995+
996+ replay.snapshotObserver = ReplaySnapshotObserver { bitmap, frameTimestamp, screenName ->
997+ callbackInvoked = true
998+ receivedTimestamp = frameTimestamp
999+ receivedScreen = screenName
1000+ receivedBitmap = bitmap
1001+ }
1002+
1003+ replay.onScreenshotRecorded(mock<Bitmap >())
1004+
1005+ assertTrue(callbackInvoked)
1006+ assertEquals(1720693523997 , receivedTimestamp)
1007+ assertEquals(" MainActivity" , receivedScreen)
1008+ assertTrue(receivedBitmap is Bitmap )
1009+ }
1010+
1011+ @Test
1012+ fun `snapshot observer exception does not prevent frame storage` () {
1013+ val captureStrategy =
1014+ mock<CaptureStrategy > {
1015+ doAnswer {
1016+ ((it.arguments[1 ] as ReplayCache .(frameTimestamp: Long ) -> Unit )).invoke(
1017+ fixture.replayCache,
1018+ 1720693523997 ,
1019+ )
1020+ }
1021+ .whenever(mock)
1022+ .onScreenshotRecorded(anyOrNull<Bitmap >(), any())
1023+ }
1024+ val replay = fixture.getSut(context, replayCaptureStrategyProvider = { captureStrategy })
1025+
1026+ replay.register(fixture.scopes, fixture.options)
1027+ replay.start()
1028+
1029+ replay.snapshotObserver = ReplaySnapshotObserver { _, _, _ -> throw RuntimeException (" test" ) }
1030+
1031+ replay.onScreenshotRecorded(mock<Bitmap >())
1032+
1033+ verify(fixture.replayCache).addFrame(any<Bitmap >(), any(), anyOrNull())
1034+ }
1035+
1036+ @Test
1037+ fun `snapshot observer is not invoked when null` () {
1038+ val captureStrategy =
1039+ mock<CaptureStrategy > {
1040+ doAnswer {
1041+ ((it.arguments[1 ] as ReplayCache .(frameTimestamp: Long ) -> Unit )).invoke(
1042+ fixture.replayCache,
1043+ 1720693523997 ,
1044+ )
1045+ }
1046+ .whenever(mock)
1047+ .onScreenshotRecorded(anyOrNull<Bitmap >(), any())
1048+ }
1049+ val replay = fixture.getSut(context, replayCaptureStrategyProvider = { captureStrategy })
1050+
1051+ replay.register(fixture.scopes, fixture.options)
1052+ replay.start()
1053+
1054+ replay.onScreenshotRecorded(mock<Bitmap >())
1055+
1056+ verify(fixture.replayCache).addFrame(any<Bitmap >(), any(), anyOrNull())
1057+ }
1058+
9721059 private fun getSessionCaptureStrategy (options : SentryOptions ): SessionCaptureStrategy =
9731060 SessionCaptureStrategy (
9741061 options,
0 commit comments