Skip to content

Commit 0d7b2c0

Browse files
committed
Replace argThat with eager failures
argThat is not descriptive enough for composite conditions.
1 parent 1d9ad7f commit 0d7b2c0

File tree

3 files changed

+208
-184
lines changed

3 files changed

+208
-184
lines changed

player/src/androidTest/kotlin/com/tidal/sdk/player/playlog/Extensions.kt

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,46 @@ package com.tidal.sdk.player.playlog
22

33
import assertk.Assert
44
import assertk.assertions.isCloseTo
5-
import kotlin.math.absoluteValue
5+
import junit.framework.AssertionFailedError
66

77
internal fun Assert<Double>.isAssetPositionEqualTo(targetPosition: Double) =
88
isCloseTo(targetPosition, 0.5)
99

10-
internal fun Double.isAssetPositionEqualTo(targetPosition: Double) =
11-
(this - targetPosition).absoluteValue < 0.5
10+
@Suppress("ThrowsCount")
11+
internal fun <T> Iterable<T>.combinedPassAllOf(
12+
vararg checks: Pair<Int, T.() -> Unit>,
13+
) {
14+
val passesLeft = checks.map { it.first }.toMutableList()
15+
val throwableMessageMap = mutableMapOf<Int, MutableList<String>>()
16+
forEachIndexed { subjectIndex, subject ->
17+
var checkIndex = -1
18+
while (checkIndex < checks.size) {
19+
try {
20+
val check = checks[++checkIndex].second
21+
subject.check()
22+
if (passesLeft[checkIndex] <= 0) {
23+
throw AssertionFailedError(
24+
"Check at index $checkIndex passed more than desired amount of times (${checks[checkIndex].first})" // ktlint-disable max-line-length
25+
)
26+
}
27+
passesLeft[checkIndex]--
28+
throwableMessageMap.remove(subjectIndex)
29+
checkIndex = checks.size
30+
} catch (throwable: Throwable) {
31+
if (!throwableMessageMap.containsKey(subjectIndex)) {
32+
throwableMessageMap[subjectIndex] = mutableListOf()
33+
}
34+
throwableMessageMap.getValue(subjectIndex).add(throwable.message!!)
35+
}
36+
}
37+
}
38+
if (throwableMessageMap.isNotEmpty()) {
39+
throw AssertionFailedError("Failed check(s): $throwableMessageMap")
40+
}
41+
val index = passesLeft.indexOfFirst { it != 0 }
42+
if (index != -1) {
43+
throw AssertionFailedError(
44+
"Missed check: index $index, wanted ${checks[index].first}, missed ${passesLeft[index]}"
45+
)
46+
}
47+
}

player/src/androidTest/kotlin/com/tidal/sdk/player/playlog/SingleMediaProductPlayLogTest.kt

Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ import org.mockito.Mockito.times
6060
import org.mockito.Mockito.verifyNoMoreInteractions
6161
import org.mockito.kotlin.anyOrNull
6262
import org.mockito.kotlin.argThat
63+
import org.mockito.kotlin.argumentCaptor
6364
import org.mockito.kotlin.eq
6465
import org.mockito.kotlin.verify
6566

@@ -830,6 +831,7 @@ internal class SingleMediaProductPlayLogTest {
830831
@Test
831832
fun seekBeyondBoundsWithRepeatOne() = runTest {
832833
val gson = Gson()
834+
val payloadCaptor = argumentCaptor<String>()
833835

834836
player.playbackEngine.load(mediaProduct)
835837
player.playbackEngine.setRepeatOne(true)
@@ -848,51 +850,48 @@ internal class SingleMediaProductPlayLogTest {
848850
}
849851

850852
eventReporterCoroutineScope.advanceUntilIdle()
851-
verify(eventSender).sendEvent(
853+
verify(eventSender, times(2)).sendEvent(
852854
eq("playback_session"),
853855
eq(ConsentCategory.NECESSARY),
854-
argThat {
855-
with(gson.fromJson(this, JsonObject::class.java)["payload"].asJsonObject) {
856-
get("startAssetPosition").asDouble.isAssetPositionEqualTo(0.0) &&
857-
get("endAssetPosition").asDouble
858-
.isAssetPositionEqualTo(MEDIA_PRODUCT_DURATION_SECONDS) &&
859-
get("actualProductId")?.asString.contentEquals(mediaProduct.productId) &&
860-
get("sourceType")?.asString.contentEquals(mediaProduct.sourceType) &&
861-
get("sourceId")?.asString.contentEquals(mediaProduct.sourceId) &&
862-
get("actions").asJsonArray.run {
863-
val stopAction =
864-
gson.fromJson(this[0], PlaybackSession.Payload.Action::class.java)
865-
val startAction =
866-
gson.fromJson(this[1], PlaybackSession.Payload.Action::class.java)
867-
val perfectResumeTimestamp = stopAction.timestamp
868-
stopAction.actionType ==
869-
PlaybackSession.Payload.Action.Type.PLAYBACK_STOP &&
870-
stopAction.assetPositionSeconds.isAssetPositionEqualTo(2.0) &&
871-
startAction.actionType ==
872-
PlaybackSession.Payload.Action.Type.PLAYBACK_START &&
873-
startAction.assetPositionSeconds
874-
.isAssetPositionEqualTo(MEDIA_PRODUCT_DURATION_SECONDS) &&
875-
startAction.timestamp in
876-
(perfectResumeTimestamp - 500)..(perfectResumeTimestamp + 500)
877-
}
878-
}
879-
},
856+
payloadCaptor.capture(),
880857
eq(emptyMap()),
881858
)
882-
verify(eventSender).sendEvent(
883-
eq("playback_session"),
884-
eq(ConsentCategory.NECESSARY),
885-
argThat {
886-
with(gson.fromJson(this, JsonObject::class.java)["payload"].asJsonObject) {
887-
get("startAssetPosition").asDouble.isAssetPositionEqualTo(0.0) &&
888-
get("endAssetPosition").asDouble.isAssetPositionEqualTo(1.0) &&
889-
get("actualProductId")?.asString.contentEquals(mediaProduct.productId) &&
890-
get("sourceType")?.asString.contentEquals(mediaProduct.sourceType) &&
891-
get("sourceId")?.asString.contentEquals(mediaProduct.sourceId) &&
892-
get("actions").asJsonArray.isEmpty
859+
payloadCaptor.allValues.map {
860+
gson.fromJson(it, JsonObject::class.java)["payload"].asJsonObject
861+
}.combinedPassAllOf(
862+
1 to {
863+
assertThat(get("startAssetPosition").asDouble).isAssetPositionEqualTo(0.0)
864+
assertThat(get("endAssetPosition").asDouble)
865+
.isAssetPositionEqualTo(MEDIA_PRODUCT_DURATION_SECONDS)
866+
assertThat(get("actualProductId")?.asString)
867+
.isEqualTo(mediaProduct.productId)
868+
assertThat(get("sourceType")?.asString).isEqualTo(mediaProduct.sourceType)
869+
assertThat(get("sourceId")?.asString).isEqualTo(mediaProduct.sourceId)
870+
with(get("actions").asJsonArray) {
871+
val stopAction =
872+
gson.fromJson(this[0], PlaybackSession.Payload.Action::class.java)
873+
val startAction =
874+
gson.fromJson(this[1], PlaybackSession.Payload.Action::class.java)
875+
val perfectResumeTimestamp = stopAction.timestamp
876+
assertThat(stopAction.actionType)
877+
.isEqualTo(PlaybackSession.Payload.Action.Type.PLAYBACK_STOP)
878+
assertThat(stopAction.assetPositionSeconds).isAssetPositionEqualTo(2.0)
879+
assertThat(startAction.actionType)
880+
.isEqualTo(PlaybackSession.Payload.Action.Type.PLAYBACK_START)
881+
assertThat(startAction.assetPositionSeconds)
882+
.isAssetPositionEqualTo(MEDIA_PRODUCT_DURATION_SECONDS)
883+
assertThat(startAction.timestamp)
884+
.isBetween(perfectResumeTimestamp - 500, perfectResumeTimestamp + 500)
893885
}
894886
},
895-
eq(emptyMap()),
887+
1 to {
888+
assertThat(get("startAssetPosition").asDouble).isAssetPositionEqualTo(0.0)
889+
assertThat(get("endAssetPosition").asDouble).isAssetPositionEqualTo(1.0)
890+
assertThat(get("actualProductId")?.asString).isEqualTo(mediaProduct.productId)
891+
assertThat(get("sourceType")?.asString).isEqualTo(mediaProduct.sourceType)
892+
assertThat(get("sourceId")?.asString).isEqualTo(mediaProduct.sourceId)
893+
assertThat(get("actions").asJsonArray).isEmpty()
894+
},
896895
)
897896
}
898897
}

0 commit comments

Comments
 (0)