@@ -25,6 +25,7 @@ import kotlin.time.Duration.Companion.milliseconds
2525import kotlin.time.Duration.Companion.minutes
2626import kotlin.time.Duration.Companion.seconds
2727import kotlinx.coroutines.Dispatchers
28+ import kotlinx.coroutines.async
2829import kotlinx.coroutines.delay
2930import kotlinx.coroutines.flow.Flow
3031import kotlinx.coroutines.flow.collect
@@ -522,4 +523,141 @@ internal class TwoMediaProductsPlayLogTest {
522523 eq(emptyMap()),
523524 )
524525 }
526+
527+ @Suppress(" CyclomaticComplexMethod" , " LongMethod" )
528+ @Test
529+ fun playAndDoALot () = runTest {
530+ val gson = Gson ()
531+
532+ player.playbackEngine.load(mediaProduct1)
533+ player.playbackEngine.play()
534+ withContext(Dispatchers .Default .limitedParallelism(1 )) {
535+ withTimeout(4 .seconds) {
536+ player.playbackEngine.events.filter { it is Event .MediaProductTransition }.first()
537+ }
538+ delay(2 .seconds)
539+ while (player.playbackEngine.assetPosition < 2 ) {
540+ delay(10 .milliseconds)
541+ }
542+ player.playbackEngine.pause()
543+ player.playbackEngine.seek(3_000F )
544+ player.playbackEngine.play()
545+ player.playbackEngine.setNext(mediaProduct2)
546+ player.playbackEngine.pause()
547+ player.playbackEngine.play()
548+ delay(2 .seconds)
549+ while (player.playbackEngine.assetPosition < 4 ) {
550+ delay(10 .milliseconds)
551+ }
552+ withTimeout(4 .seconds) {
553+ val waitJob = async {
554+ player.playbackEngine.events
555+ .filter { it is Event .MediaProductTransition }
556+ .first()
557+ }
558+ player.playbackEngine.skipToNext()
559+ waitJob.await()
560+ }
561+ player.playbackEngine.seek(58_000F )
562+ player.playbackEngine.setRepeatOne(true )
563+ withTimeout(4 .seconds) {
564+ player.playbackEngine.events.filter { it is Event .MediaProductTransition }.first()
565+ }
566+ delay(1 .seconds)
567+ while (player.playbackEngine.assetPosition < 1 ) {
568+ delay(10 .milliseconds)
569+ }
570+ player.playbackEngine.reset()
571+ }
572+
573+ eventReporterCoroutineScope.advanceUntilIdle()
574+ verify(eventSender).sendEvent(
575+ eq(" playback_session" ),
576+ eq(ConsentCategory .NECESSARY ),
577+ argThat {
578+ with (gson.fromJson(this , JsonObject ::class .java)[" payload" ].asJsonObject) {
579+ get(" startAssetPosition" ).asDouble.isAssetPositionEqualTo(0.0 ) &&
580+ get(" endAssetPosition" ).asDouble.isAssetPositionEqualTo(4.0 ) &&
581+ get(" actualProductId" )?.asString.contentEquals(mediaProduct1.productId) &&
582+ get(" sourceType" )?.asString.contentEquals(mediaProduct1.sourceType) &&
583+ get(" sourceId" )?.asString.contentEquals(mediaProduct1.sourceId) &&
584+ get(" actions" ).asJsonArray.run {
585+ val firstStopAction =
586+ gson.fromJson(this [0 ], PlaybackSession .Payload .Action ::class .java)
587+ val firstStartAction =
588+ gson.fromJson(this [1 ], PlaybackSession .Payload .Action ::class .java)
589+ val perfectFirstResumeTimestamp = firstStopAction.timestamp
590+ val secondStopAction =
591+ gson.fromJson(this [2 ], PlaybackSession .Payload .Action ::class .java)
592+ val secondStartAction =
593+ gson.fromJson(this [3 ], PlaybackSession .Payload .Action ::class .java)
594+ val perfectSecondResumeTimestamp = secondStopAction.timestamp
595+ firstStopAction.actionType ==
596+ PlaybackSession .Payload .Action .Type .PLAYBACK_STOP &&
597+ firstStopAction.assetPositionSeconds.isAssetPositionEqualTo(2.0 ) &&
598+ firstStartAction.actionType ==
599+ PlaybackSession .Payload .Action .Type .PLAYBACK_START &&
600+ firstStartAction.assetPositionSeconds.isAssetPositionEqualTo(3.0 ) &&
601+ firstStartAction.timestamp in
602+ (perfectFirstResumeTimestamp - 500 ).. (perfectFirstResumeTimestamp + 500 ) &&
603+ secondStopAction.actionType ==
604+ PlaybackSession .Payload .Action .Type .PLAYBACK_STOP &&
605+ secondStopAction.assetPositionSeconds.isAssetPositionEqualTo(3.0 ) &&
606+ secondStartAction.actionType ==
607+ PlaybackSession .Payload .Action .Type .PLAYBACK_START &&
608+ secondStartAction.assetPositionSeconds
609+ .isAssetPositionEqualTo(3.0 ) &&
610+ secondStartAction.timestamp in
611+ (perfectSecondResumeTimestamp - 500 ).. (perfectSecondResumeTimestamp + 500 )
612+ }
613+ }
614+ },
615+ eq(emptyMap()),
616+ )
617+ verify(eventSender).sendEvent(
618+ eq(" playback_session" ),
619+ eq(ConsentCategory .NECESSARY ),
620+ argThat {
621+ with (gson.fromJson(this , JsonObject ::class .java)[" payload" ].asJsonObject) {
622+ get(" startAssetPosition" ).asDouble.isAssetPositionEqualTo(0.0 ) &&
623+ get(" endAssetPosition" ).asDouble
624+ .isAssetPositionEqualTo(MEDIA_PRODUCT_2_DURATION_SECONDS ) &&
625+ get(" actualProductId" )?.asString.contentEquals(mediaProduct2.productId) &&
626+ get(" sourceType" )?.asString.contentEquals(mediaProduct2.sourceType) &&
627+ get(" sourceId" )?.asString.contentEquals(mediaProduct2.sourceId) &&
628+ get(" actions" ).asJsonArray.run {
629+ val stopAction =
630+ gson.fromJson(this [0 ], PlaybackSession .Payload .Action ::class .java)
631+ val startAction =
632+ gson.fromJson(this [1 ], PlaybackSession .Payload .Action ::class .java)
633+ val perfectResumeTimestamp = stopAction.timestamp
634+ stopAction.actionType ==
635+ PlaybackSession .Payload .Action .Type .PLAYBACK_STOP &&
636+ stopAction.assetPositionSeconds.isAssetPositionEqualTo(0.0 ) &&
637+ startAction.actionType ==
638+ PlaybackSession .Payload .Action .Type .PLAYBACK_START &&
639+ startAction.assetPositionSeconds.isAssetPositionEqualTo(58.0 ) &&
640+ startAction.timestamp in
641+ (perfectResumeTimestamp - 500 ).. (perfectResumeTimestamp + 500 )
642+ }
643+ }
644+ },
645+ eq(emptyMap()),
646+ )
647+ verify(eventSender).sendEvent(
648+ eq(" playback_session" ),
649+ eq(ConsentCategory .NECESSARY ),
650+ argThat {
651+ with (gson.fromJson(this , JsonObject ::class .java)[" payload" ].asJsonObject) {
652+ get(" startAssetPosition" ).asDouble.isAssetPositionEqualTo(0.0 ) &&
653+ get(" endAssetPosition" ).asDouble.isAssetPositionEqualTo(1.0 ) &&
654+ get(" actualProductId" )?.asString.contentEquals(mediaProduct2.productId) &&
655+ get(" sourceType" )?.asString.contentEquals(mediaProduct2.sourceType) &&
656+ get(" sourceId" )?.asString.contentEquals(mediaProduct2.sourceId) &&
657+ get(" actions" ).asJsonArray.isEmpty
658+ }
659+ },
660+ eq(emptyMap()),
661+ )
662+ }
525663}
0 commit comments