Improve and fix tests.

This commit is contained in:
Benoit Marty 2025-10-17 12:04:18 +02:00 committed by Benoit Marty
parent b6ec06ebc6
commit 09a6ffc081
4 changed files with 52 additions and 69 deletions

View file

@ -21,6 +21,7 @@ import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.core.meta.BuildType import io.element.android.libraries.core.meta.BuildType
import io.element.android.libraries.featureflag.api.Feature
import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.featureflag.test.FakeFeature import io.element.android.libraries.featureflag.test.FakeFeature
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
@ -41,15 +42,17 @@ class DeveloperSettingsPresenterTest {
@Test @Test
fun `present - ensures initial states are correct`() = runTest { fun `present - ensures initial states are correct`() = runTest {
val availableFeatures = listOf( val getAvailableFeaturesResult = lambdaRecorder<Boolean, Boolean, List<Feature>> { _, _ ->
FakeFeature( listOf(
key = "feature_1", FakeFeature(
title = "Feature 1", key = "feature_1",
isInLabs = false, title = "Feature 1",
isInLabs = false,
)
) )
) }
val presenter = createDeveloperSettingsPresenter( val presenter = createDeveloperSettingsPresenter(
featureFlagService = FakeFeatureFlagService(providedAvailableFeatures = availableFeatures) featureFlagService = FakeFeatureFlagService(getAvailableFeaturesResult = getAvailableFeaturesResult)
) )
presenter.test { presenter.test {
awaitItem().also { state -> awaitItem().also { state ->
@ -73,6 +76,8 @@ class DeveloperSettingsPresenterTest {
awaitItem().also { state -> awaitItem().also { state ->
assertThat(state.cacheSize).isInstanceOf(AsyncData.Success::class.java) assertThat(state.cacheSize).isInstanceOf(AsyncData.Success::class.java)
} }
getAvailableFeaturesResult.assertions().isCalledOnce()
.with(value(false), value(false))
} }
} }
@ -203,50 +208,17 @@ class DeveloperSettingsPresenterTest {
} }
} }
@Test
fun `present - won't display features in labs or finished`() = runTest {
val availableFeatures = listOf(
// Only this feature should be displayed
FakeFeature(
key = "feature_1",
title = "Feature 1",
isInLabs = false,
),
FakeFeature(
key = "feature_2",
title = "Feature 2",
isInLabs = true,
),
FakeFeature(
key = "feature_3",
title = "Feature 3",
isInLabs = false,
isFinished = true,
)
)
val presenter = createDeveloperSettingsPresenter(
featureFlagService = FakeFeatureFlagService(
providedAvailableFeatures = availableFeatures,
)
)
presenter.test {
skipItems(2)
awaitItem().also { state ->
assertThat(state.features).hasSize(1)
}
}
}
private fun createDeveloperSettingsPresenter( private fun createDeveloperSettingsPresenter(
featureFlagService: FakeFeatureFlagService = FakeFeatureFlagService( featureFlagService: FakeFeatureFlagService = FakeFeatureFlagService(
providedAvailableFeatures = listOf( getAvailableFeaturesResult = { _, _ ->
FakeFeature( listOf(
key = "feature_1", FakeFeature(
title = "Feature 1", key = "feature_1",
isInLabs = false, title = "Feature 1",
isInLabs = false,
)
) )
) }
), ),
cacheSizeUseCase: FakeComputeCacheSizeUseCase = FakeComputeCacheSizeUseCase(), cacheSizeUseCase: FakeComputeCacheSizeUseCase = FakeComputeCacheSizeUseCase(),
clearCacheUseCase: FakeClearCacheUseCase = FakeClearCacheUseCase(), clearCacheUseCase: FakeClearCacheUseCase = FakeClearCacheUseCase(),

View file

@ -15,6 +15,8 @@ import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.featureflag.test.FakeFeature import io.element.android.libraries.featureflag.test.FakeFeature
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.services.toolbox.test.strings.FakeStringProvider import io.element.android.services.toolbox.test.strings.FakeStringProvider
import io.element.android.tests.testutils.lambda.lambdaRecorder
import io.element.android.tests.testutils.lambda.value
import io.element.android.tests.testutils.test import io.element.android.tests.testutils.test
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.Test import org.junit.Test
@ -34,14 +36,19 @@ class LabsPresenterTest {
isInLabs = true, isInLabs = true,
) )
) )
val getAvailableFeaturesResult = lambdaRecorder<Boolean, Boolean, List<Feature>> { _, _ ->
availableFeatures
}
createLabsPresenter( createLabsPresenter(
availableFeatures = availableFeatures, getAvailableFeaturesResult = getAvailableFeaturesResult,
).test { ).test {
skipItems(1) skipItems(1)
val receivedFeatures = awaitItem().features val receivedFeatures = awaitItem().features
assertThat(receivedFeatures).hasSize(2) assertThat(receivedFeatures).hasSize(2)
assertThat(receivedFeatures[0].key).isEqualTo(availableFeatures[0].key) assertThat(receivedFeatures[0].key).isEqualTo(availableFeatures[0].key)
assertThat(receivedFeatures[1].key).isEqualTo(availableFeatures[1].key) assertThat(receivedFeatures[1].key).isEqualTo(availableFeatures[1].key)
getAvailableFeaturesResult.assertions().isCalledOnce()
.with(value(false), value(true))
} }
} }
@ -55,7 +62,7 @@ class LabsPresenterTest {
), ),
) )
createLabsPresenter( createLabsPresenter(
availableFeatures = availableFeatures, getAvailableFeaturesResult = { _, _ -> availableFeatures },
).test { ).test {
skipItems(1) skipItems(1)
val initialItem = awaitItem() val initialItem = awaitItem()
@ -82,7 +89,7 @@ class LabsPresenterTest {
val clearCacheUseCase = FakeClearCacheUseCase() val clearCacheUseCase = FakeClearCacheUseCase()
createLabsPresenter( createLabsPresenter(
availableFeatures = availableFeatures, getAvailableFeaturesResult = { _, _ -> availableFeatures },
clearCacheUseCase = clearCacheUseCase, clearCacheUseCase = clearCacheUseCase,
).test { ).test {
skipItems(1) skipItems(1)
@ -100,12 +107,12 @@ class LabsPresenterTest {
} }
private fun createLabsPresenter( private fun createLabsPresenter(
availableFeatures: List<Feature> = emptyList(), getAvailableFeaturesResult: (Boolean, Boolean) -> List<Feature> = { _, _ -> emptyList() },
clearCacheUseCase: ClearCacheUseCase = FakeClearCacheUseCase(), clearCacheUseCase: ClearCacheUseCase = FakeClearCacheUseCase(),
): LabsPresenter { ): LabsPresenter {
return LabsPresenter( return LabsPresenter(
stringProvider = FakeStringProvider(), stringProvider = FakeStringProvider(),
featureFlagService = FakeFeatureFlagService(providedAvailableFeatures = availableFeatures), featureFlagService = FakeFeatureFlagService(getAvailableFeaturesResult = getAvailableFeaturesResult),
clearCacheUseCase = clearCacheUseCase, clearCacheUseCase = clearCacheUseCase,
) )
} }

View file

@ -189,14 +189,16 @@ class PreferencesRootPresenterTest {
fun `present - labs can be shown if any feature flag is in labs and not finished`() = runTest { fun `present - labs can be shown if any feature flag is in labs and not finished`() = runTest {
createPresenter( createPresenter(
featureFlagService = FakeFeatureFlagService( featureFlagService = FakeFeatureFlagService(
providedAvailableFeatures = listOf( getAvailableFeaturesResult = { _, _ ->
FakeFeature( listOf(
key = "feature_1", FakeFeature(
title = "Feature 1", key = "feature_1",
isInLabs = true, title = "Feature 1",
isFinished = false, isInLabs = true,
isFinished = false,
)
) )
) }
), ),
matrixClient = FakeMatrixClient( matrixClient = FakeMatrixClient(
canDeactivateAccountResult = { true }, canDeactivateAccountResult = { true },
@ -212,14 +214,16 @@ class PreferencesRootPresenterTest {
fun `present - labs can't be shown if all feature flags in labs are finished`() = runTest { fun `present - labs can't be shown if all feature flags in labs are finished`() = runTest {
createPresenter( createPresenter(
featureFlagService = FakeFeatureFlagService( featureFlagService = FakeFeatureFlagService(
providedAvailableFeatures = listOf( getAvailableFeaturesResult = { _, _ ->
FakeFeature( listOf(
key = "feature_1", FakeFeature(
title = "Feature 1", key = "feature_1",
isInLabs = true, title = "Feature 1",
isFinished = true, isInLabs = true,
isFinished = true,
)
) )
) }
), ),
matrixClient = FakeMatrixClient( matrixClient = FakeMatrixClient(
canDeactivateAccountResult = { true }, canDeactivateAccountResult = { true },

View file

@ -17,7 +17,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
class FakeFeatureFlagService( class FakeFeatureFlagService(
initialState: Map<String, Boolean> = emptyMap(), initialState: Map<String, Boolean> = emptyMap(),
private val buildMeta: BuildMeta = aBuildMeta(), private val buildMeta: BuildMeta = aBuildMeta(),
var providedAvailableFeatures: List<Feature> = emptyList(), private val getAvailableFeaturesResult: (Boolean, Boolean) -> List<Feature> = { _, _ -> emptyList() },
) : FeatureFlagService { ) : FeatureFlagService {
private val enabledFeatures = initialState private val enabledFeatures = initialState
.mapValues { MutableStateFlow(it.value) } .mapValues { MutableStateFlow(it.value) }
@ -37,6 +37,6 @@ class FakeFeatureFlagService(
includeFinishFeatures: Boolean, includeFinishFeatures: Boolean,
isInLabs: Boolean, isInLabs: Boolean,
): List<Feature> { ): List<Feature> {
return providedAvailableFeatures return getAvailableFeaturesResult(includeFinishFeatures, isInLabs)
} }
} }