Skip to content

Commit

Permalink
Add second PlayLog test
Browse files Browse the repository at this point in the history
  • Loading branch information
stoyicker committed May 29, 2024
1 parent c85dd75 commit b253a56
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ sealed class PlaybackSession<T : PlaybackSession.Payload> :
@Keep
@SuppressWarnings("UnusedPrivateMember")
data class Action(
private val timestamp: Long,
val timestamp: Long,
@SerializedName("assetPosition")
private val assetPositionSeconds: Double,
private val actionType: Type,
val assetPositionSeconds: Double,
val actionType: Type,
) {

@Keep
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.app.Application
import androidx.test.platform.app.InstrumentationRegistry
import assertk.Assert
import assertk.assertThat
import assertk.assertions.isBetween
import assertk.assertions.isCloseTo
import assertk.assertions.isEqualTo
import com.google.gson.Gson
Expand All @@ -20,14 +21,18 @@ import com.tidal.sdk.player.common.model.MediaProduct
import com.tidal.sdk.player.common.model.ProductType
import com.tidal.sdk.player.events.EventReporterModuleRoot
import com.tidal.sdk.player.events.di.DefaultEventReporterComponent
import com.tidal.sdk.player.events.model.PlaybackSession
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.repeatableflakytest.RepeatableFlakyTest
import com.tidal.sdk.player.repeatableflakytest.RepeatableFlakyTestRule
import com.tidal.sdk.player.setBodyFromFile
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.filter
Expand Down Expand Up @@ -137,7 +142,7 @@ class PlayLogTest {
argThat { !contentEquals("playback_session") },
anyOrNull(),
anyOrNull(),
anyOrNull()
anyOrNull(),
)
verifyNoMoreInteractions(eventSender)
}
Expand All @@ -163,7 +168,7 @@ class PlayLogTest {
loadAndPlayUntilEnd(MediaProduct(ProductType.TRACK, "1", null, null))

private fun loadAndPlayUntilEnd(mediaProduct: MediaProduct) = runTest {
responseDispatcher [
responseDispatcher[
"https://api.tidal.com/v1/tracks/1/playbackinfo?playbackmode=STREAM&assetpresentation=FULL&audioquality=LOW".toHttpUrl(),
] = {
MockResponse().setBodyFromFile(
Expand Down Expand Up @@ -203,6 +208,87 @@ class PlayLogTest {
)
}

@Test
fun loadAndPlayThenPauseThenPlayNoNulls() =
loadAndPlayThenPauseThenPlay(MediaProduct(ProductType.TRACK, "1", "TESTA", "456"))

@Test
fun loadAndPlayThenPauseThenPlayNullSourceType() =
loadAndPlayThenPauseThenPlay(MediaProduct(ProductType.TRACK, "1", null, "789"))

@Test
fun loadAndPlayThenPauseThenPlayNullSourceId() =
loadAndPlayThenPauseThenPlay(MediaProduct(ProductType.TRACK, "1", "TESTB", null))

@Test
fun loadAndPlayThenPauseThenPlayNullSourceTypeNullSourceId() =
loadAndPlayThenPauseThenPlay(MediaProduct(ProductType.TRACK, "1", null, null))

@Suppress("LongMethod")
private fun loadAndPlayThenPauseThenPlay(mediaProduct: MediaProduct) = runTest {
val gson = Gson()
responseDispatcher[
"https://api.tidal.com/v1/tracks/1/playbackinfo?playbackmode=STREAM&assetpresentation=FULL&audioquality=LOW".toHttpUrl(),
] = {
MockResponse().setBodyFromFile(
"api-responses/playbackinfo/tracks/playlogtest/get_1_bts.json",
)
}
responseDispatcher["https://test.audio.tidal.com/1_bts.m4a".toHttpUrl()] = {
MockResponse().setBodyFromFile("raw/playlogtest/1_bts.m4a")
}

player.playbackEngine.load(mediaProduct)
player.playbackEngine.play()
withContext(Dispatchers.Default.limitedParallelism(1)) {
withTimeout(4.seconds) {
player.playbackEngine.events.filter { it is Event.MediaProductTransition }.first()
}
delay(2.seconds)
while (player.playbackEngine.assetPosition < 2) {
delay(10.milliseconds)
}
player.playbackEngine.pause()
delay(1.seconds)
player.playbackEngine.play()
withTimeout(8000) {
player.playbackEngine.events.filter { it is MediaProductEnded }.first()
}
}

eventReporterCoroutineScope.advanceUntilIdle()
verify(eventSender).sendEvent(
eq("playback_session"),
eq(ConsentCategory.NECESSARY),
argThat {
with(gson.fromJson(this, JsonObject::class.java)["payload"].asJsonObject) {
assertThat(get("startAssetPosition").asDouble).isAssetPositionEqualTo(0.0)
assertThat(get("endAssetPosition").asDouble).isAssetPositionEqualTo(5.065)
assertThat(get("actualProductId").asString).isEqualTo(mediaProduct.productId)
assertThat(get("sourceType")?.asString).isEqualTo(mediaProduct.sourceType)
assertThat(get("sourceId")?.asString).isEqualTo(mediaProduct.sourceId)
with(get("actions").asJsonArray) {
val pauseAction =
gson.fromJson(this[0], PlaybackSession.Payload.Action::class.java)
assertThat(pauseAction.actionType)
.isEqualTo(PlaybackSession.Payload.Action.Type.PLAYBACK_STOP)
val resumeAction =
gson.fromJson(this[1], PlaybackSession.Payload.Action::class.java)
assertThat(resumeAction.actionType)
.isEqualTo(PlaybackSession.Payload.Action.Type.PLAYBACK_START)
assertThat(resumeAction.assetPositionSeconds)
.isAssetPositionEqualTo(pauseAction.assetPositionSeconds)
val perfectResumeTimestamp = pauseAction.timestamp + 1_000
assertThat(resumeAction.timestamp)
.isBetween(perfectResumeTimestamp - 500, perfectResumeTimestamp + 500)
}
}
true
},
eq(emptyMap()),
)
}

private fun Assert<Double>.isAssetPositionEqualTo(targetPosition: Double) = run {
isCloseTo(targetPosition, 0.5)
}
Expand Down

0 comments on commit b253a56

Please sign in to comment.