@@ -16,6 +16,7 @@ import com.tidal.sdk.player.common.model.MediaProduct
1616import com.tidal.sdk.player.common.model.ProductType
1717import com.tidal.sdk.player.events.EventReporterModuleRoot
1818import com.tidal.sdk.player.events.di.DefaultEventReporterComponent
19+ import com.tidal.sdk.player.events.model.PlaybackSession
1920import com.tidal.sdk.player.events.playlogtest.PlayLogTestDefaultEventReporterComponentFactory
2021import com.tidal.sdk.player.events.reflectionComponentFactoryF
2122import com.tidal.sdk.player.playbackengine.model.Event
@@ -300,4 +301,74 @@ internal class TwoMediaProductsPlayLogTest {
300301 eq(emptyMap()),
301302 )
302303 }
304+
305+ @Suppress(" CyclomaticComplexMethod" , " LongMethod" )
306+ @Test
307+ fun seekBeyondBoundsWithNext () = runTest {
308+ val gson = Gson ()
309+
310+ player.playbackEngine.load(mediaProduct1)
311+ player.playbackEngine.setNext(mediaProduct2)
312+ player.playbackEngine.play()
313+ withContext(Dispatchers .Default .limitedParallelism(1 )) {
314+ delay(2 .seconds)
315+ while (player.playbackEngine.assetPosition < 2 ) {
316+ delay(10 .milliseconds)
317+ }
318+ player.playbackEngine.seek(10_000F )
319+ delay(1 .seconds)
320+ while (player.playbackEngine.assetPosition < 1 ) {
321+ delay(10 .milliseconds)
322+ }
323+ player.playbackEngine.reset()
324+ }
325+
326+ eventReporterCoroutineScope.advanceUntilIdle()
327+ verify(eventSender).sendEvent(
328+ eq(" playback_session" ),
329+ eq(ConsentCategory .NECESSARY ),
330+ argThat {
331+ with (gson.fromJson(this , JsonObject ::class .java)[" payload" ].asJsonObject) {
332+ get(" startAssetPosition" ).asDouble.isAssetPositionEqualTo(0.0 ) &&
333+ get(" endAssetPosition" ).asDouble
334+ .isAssetPositionEqualTo(MEDIA_PRODUCT_1_DURATION_SECONDS ) &&
335+ get(" actualProductId" )?.asString.contentEquals(mediaProduct1.productId) &&
336+ get(" sourceType" )?.asString.contentEquals(mediaProduct1.sourceType) &&
337+ get(" sourceId" )?.asString.contentEquals(mediaProduct1.sourceId) &&
338+ get(" actions" ).asJsonArray.run {
339+ val stopAction =
340+ gson.fromJson(this [0 ], PlaybackSession .Payload .Action ::class .java)
341+ val startAction =
342+ gson.fromJson(this [1 ], PlaybackSession .Payload .Action ::class .java)
343+ val perfectResumeTimestamp = stopAction.timestamp
344+ stopAction.actionType ==
345+ PlaybackSession .Payload .Action .Type .PLAYBACK_STOP &&
346+ stopAction.assetPositionSeconds.isAssetPositionEqualTo(2.0 ) &&
347+ startAction.actionType ==
348+ PlaybackSession .Payload .Action .Type .PLAYBACK_START &&
349+ startAction.assetPositionSeconds
350+ .isAssetPositionEqualTo(MEDIA_PRODUCT_1_DURATION_SECONDS ) &&
351+ startAction.timestamp in
352+ (perfectResumeTimestamp - 500 ).. (perfectResumeTimestamp + 500 )
353+ }
354+ }
355+ },
356+ eq(emptyMap()),
357+ )
358+ verify(eventSender).sendEvent(
359+ eq(" playback_session" ),
360+ eq(ConsentCategory .NECESSARY ),
361+ argThat {
362+ with (gson.fromJson(this , JsonObject ::class .java)[" payload" ].asJsonObject) {
363+ get(" startAssetPosition" ).asDouble.isAssetPositionEqualTo(0.0 ) &&
364+ get(" endAssetPosition" ).asDouble.isAssetPositionEqualTo(1.0 ) &&
365+ get(" actualProductId" )?.asString.contentEquals(mediaProduct2.productId) &&
366+ get(" sourceType" )?.asString.contentEquals(mediaProduct2.sourceType) &&
367+ get(" sourceId" )?.asString.contentEquals(mediaProduct2.sourceId) &&
368+ get(" actions" ).asJsonArray.isEmpty
369+ }
370+ },
371+ eq(emptyMap()),
372+ )
373+ }
303374}
0 commit comments