diff --git a/player/src/androidTest/kotlin/com/tidal/sdk/player/playlog/TwoMediaProductsPlayLogTest.kt b/player/src/androidTest/kotlin/com/tidal/sdk/player/playlog/TwoMediaProductsPlayLogTest.kt index f0645335..9ad46b9c 100644 --- a/player/src/androidTest/kotlin/com/tidal/sdk/player/playlog/TwoMediaProductsPlayLogTest.kt +++ b/player/src/androidTest/kotlin/com/tidal/sdk/player/playlog/TwoMediaProductsPlayLogTest.kt @@ -18,16 +18,22 @@ import com.tidal.sdk.player.events.EventReporterModuleRoot import com.tidal.sdk.player.events.di.DefaultEventReporterComponent import com.tidal.sdk.player.events.playlogtest.PlayLogTestDefaultEventReporterComponentFactory import com.tidal.sdk.player.events.reflectionComponentFactoryF +import com.tidal.sdk.player.playbackengine.model.Event import com.tidal.sdk.player.playbackengine.model.Event.MediaProductEnded import com.tidal.sdk.player.playbackengine.model.Event.Release import com.tidal.sdk.player.setBodyFromFile import kotlin.math.absoluteValue +import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.minutes +import kotlin.time.Duration.Companion.seconds import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.take import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.StandardTestDispatcher @@ -49,6 +55,7 @@ import org.junit.Test import org.junit.runners.Parameterized import org.mockito.Mockito.atMost import org.mockito.Mockito.mock +import org.mockito.Mockito.times import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.kotlin.anyOrNull import org.mockito.kotlin.argThat @@ -236,6 +243,65 @@ internal class TwoMediaProductsPlayLogTest { ) } + @Test + fun repeatOneWithNext() = runTest { + val gson = Gson() + + player.playbackEngine.load(mediaProduct1) + player.playbackEngine.setNext(mediaProduct2) + player.playbackEngine.setRepeatOne(true) + player.playbackEngine.play() + withContext(Dispatchers.Default.limitedParallelism(1)) { + withTimeout(8.seconds) { + player.playbackEngine.events.filter { it is Event.MediaProductTransition } + .take(2) + .collect() + } + player.playbackEngine.setRepeatOne(false) + withTimeout(8.seconds) { + player.playbackEngine.events.filter { it is Event.MediaProductTransition }.first() + } + delay(1.seconds) + while (player.playbackEngine.assetPosition < 1) { + delay(10.milliseconds) + } + player.playbackEngine.reset() + } + + eventReporterCoroutineScope.advanceUntilIdle() + verify(eventSender, times(2)).sendEvent( + eq("playback_session"), + eq(ConsentCategory.NECESSARY), + argThat { + with(gson.fromJson(this, JsonObject::class.java)["payload"].asJsonObject) { + get("startAssetPosition").asDouble.isAssetPositionEqualTo(0.0) && + get("endAssetPosition").asDouble + .isAssetPositionEqualTo(MEDIA_PRODUCT_1_DURATION_SECONDS) && + get("actualProductId")?.asString.contentEquals(mediaProduct1.productId) && + get("sourceType")?.asString.contentEquals(mediaProduct1.sourceType) && + get("sourceId")?.asString.contentEquals(mediaProduct1.sourceId) && + get("actions").asJsonArray.isEmpty + } + }, + eq(emptyMap()), + ) + verify(eventSender).sendEvent( + eq("playback_session"), + eq(ConsentCategory.NECESSARY), + argThat { + with(gson.fromJson(this, JsonObject::class.java)["payload"].asJsonObject) { + get("startAssetPosition").asDouble.isAssetPositionEqualTo(0.0) && + get("endAssetPosition").asDouble.isAssetPositionEqualTo(1.0) && + get("actualProductId")?.asString.contentEquals(mediaProduct2.productId) && + get("sourceType")?.asString.contentEquals(mediaProduct2.sourceType) && + get("sourceId")?.asString.contentEquals(mediaProduct2.sourceId) && + get("actions").asJsonArray.isEmpty + } + }, + eq(emptyMap()), + ) + } + private fun Double.isAssetPositionEqualTo(targetPosition: Double) = (this - targetPosition).absoluteValue < 0.5 }