Merge pull request #3388 from element-hq/feature/bma/pushEndpoint
Unified push endpoint: do not fallback to default endpoint in case of failure and add troubleshoot test.
This commit is contained in:
@@ -37,7 +37,7 @@ class NotificationTroubleshootCheckPermissionTest @Inject constructor(
|
||||
private val permissionStateProvider: PermissionStateProvider,
|
||||
private val sdkVersionProvider: BuildVersionSdkIntProvider,
|
||||
private val permissionActions: PermissionActions,
|
||||
private val stringProvider: StringProvider,
|
||||
stringProvider: StringProvider,
|
||||
) : NotificationTroubleshootTest {
|
||||
override val order: Int = 0
|
||||
|
||||
|
||||
@@ -101,4 +101,32 @@ class NotificationTroubleshootCheckPermissionTestTest {
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Success)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test NotificationTroubleshootCheckPermissionTest error and reset`() = runTest {
|
||||
val permissionStateProvider = FakePermissionStateProvider(
|
||||
permissionGranted = false
|
||||
)
|
||||
val actions = FakePermissionActions(
|
||||
openSettingsAction = {
|
||||
permissionStateProvider.setPermissionGranted()
|
||||
}
|
||||
)
|
||||
val sut = NotificationTroubleshootCheckPermissionTest(
|
||||
permissionStateProvider = permissionStateProvider,
|
||||
sdkVersionProvider = FakeBuildVersionSdkIntProvider(sdkInt = Build.VERSION_CODES.TIRAMISU),
|
||||
permissionActions = actions,
|
||||
stringProvider = FakeStringProvider(),
|
||||
)
|
||||
launch {
|
||||
sut.run(this)
|
||||
}
|
||||
sut.state.test {
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true))
|
||||
sut.reset()
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import io.element.android.libraries.pushproviders.api.CurrentUserPushConfig
|
||||
import io.element.android.libraries.pushproviders.api.Distributor
|
||||
import io.element.android.libraries.pushproviders.api.PushProvider
|
||||
import io.element.android.libraries.pushproviders.test.FakePushProvider
|
||||
import io.element.android.libraries.pushproviders.test.aCurrentUserPushConfig
|
||||
import io.element.android.libraries.pushstore.api.UserPushStoreFactory
|
||||
import io.element.android.libraries.pushstore.test.userpushstore.FakeUserPushStore
|
||||
import io.element.android.libraries.pushstore.test.userpushstore.FakeUserPushStoreFactory
|
||||
@@ -57,10 +58,7 @@ class DefaultPushServiceTest {
|
||||
|
||||
@Test
|
||||
fun `test push ok`() = runTest {
|
||||
val aConfig = CurrentUserPushConfig(
|
||||
url = "aUrl",
|
||||
pushKey = "aPushKey",
|
||||
)
|
||||
val aConfig = aCurrentUserPushConfig()
|
||||
val testPushResult = lambdaRecorder<CurrentUserPushConfig, Unit> { }
|
||||
val aPushProvider = FakePushProvider(
|
||||
currentUserPushConfig = aConfig
|
||||
|
||||
@@ -18,7 +18,7 @@ package io.element.android.libraries.push.impl.test
|
||||
|
||||
import io.element.android.appconfig.PushConfig
|
||||
import io.element.android.libraries.push.impl.pushgateway.PushGatewayNotifyRequest
|
||||
import io.element.android.libraries.pushproviders.api.CurrentUserPushConfig
|
||||
import io.element.android.libraries.pushproviders.test.aCurrentUserPushConfig
|
||||
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||
import io.element.android.tests.testutils.lambda.value
|
||||
import kotlinx.coroutines.test.runTest
|
||||
@@ -33,10 +33,7 @@ class DefaultTestPushTest {
|
||||
executeResult = executeResult,
|
||||
)
|
||||
)
|
||||
val aConfig = CurrentUserPushConfig(
|
||||
url = "aUrl",
|
||||
pushKey = "aPushKey",
|
||||
)
|
||||
val aConfig = aCurrentUserPushConfig()
|
||||
defaultTestPush.execute(aConfig)
|
||||
executeResult.assertions()
|
||||
.isCalledOnce()
|
||||
|
||||
@@ -58,6 +58,8 @@ class CurrentPushProviderTestTest {
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||
val lastItem = awaitItem()
|
||||
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false))
|
||||
sut.reset()
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,8 @@ class NotificationTestTest {
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.WaitingForUser)
|
||||
assertThat(awaitItem().status).isInstanceOf(NotificationTroubleshootTestState.Status.Failure::class.java)
|
||||
sut.reset()
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,8 @@ class PushLoopbackTestTest {
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||
val lastItem = awaitItem()
|
||||
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false))
|
||||
sut.reset()
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ class PushProvidersTestTest {
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||
val lastItem = awaitItem()
|
||||
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false))
|
||||
sut.reset()
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,8 @@ class FirebaseAvailabilityTestTest {
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||
val lastItem = awaitItem()
|
||||
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false))
|
||||
sut.reset()
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,6 +77,31 @@ class FirebaseTokenTestTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test FirebaseTokenTest error and reset`() = runTest {
|
||||
val firebaseStore = InMemoryFirebaseStore(null)
|
||||
val sut = FirebaseTokenTest(
|
||||
firebaseStore = firebaseStore,
|
||||
firebaseTroubleshooter = FakeFirebaseTroubleshooter(
|
||||
troubleShootResult = {
|
||||
firebaseStore.storeFcmToken(FAKE_TOKEN)
|
||||
Result.success(Unit)
|
||||
}
|
||||
),
|
||||
stringProvider = FakeStringProvider(),
|
||||
)
|
||||
launch {
|
||||
sut.run(this)
|
||||
}
|
||||
sut.state.test {
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true))
|
||||
sut.reset()
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test FirebaseTokenTest isRelevant`() {
|
||||
val sut = FirebaseTokenTest(
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2024 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.pushproviders.test
|
||||
|
||||
import io.element.android.libraries.pushproviders.api.CurrentUserPushConfig
|
||||
|
||||
fun aCurrentUserPushConfig(
|
||||
url: String = "aUrl",
|
||||
pushKey: String = "aPushKey",
|
||||
) = CurrentUserPushConfig(
|
||||
url = url,
|
||||
pushKey = pushKey,
|
||||
)
|
||||
@@ -60,6 +60,7 @@ dependencies {
|
||||
testImplementation(libs.test.turbine)
|
||||
testImplementation(projects.libraries.matrix.test)
|
||||
testImplementation(projects.libraries.push.test)
|
||||
testImplementation(projects.libraries.pushproviders.test)
|
||||
testImplementation(projects.libraries.pushstore.test)
|
||||
testImplementation(projects.tests.testutils)
|
||||
testImplementation(projects.services.toolbox.test)
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2024 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.pushproviders.unifiedpush
|
||||
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.pushproviders.api.CurrentUserPushConfig
|
||||
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret
|
||||
import io.element.android.services.appnavstate.api.AppNavigationStateService
|
||||
import io.element.android.services.appnavstate.api.currentSessionId
|
||||
import javax.inject.Inject
|
||||
|
||||
interface UnifiedPushCurrentUserPushConfigProvider {
|
||||
suspend fun provide(): CurrentUserPushConfig?
|
||||
}
|
||||
|
||||
@ContributesBinding(AppScope::class)
|
||||
class DefaultUnifiedPushCurrentUserPushConfigProvider @Inject constructor(
|
||||
private val pushClientSecret: PushClientSecret,
|
||||
private val unifiedPushStore: UnifiedPushStore,
|
||||
private val appNavigationStateService: AppNavigationStateService,
|
||||
) : UnifiedPushCurrentUserPushConfigProvider {
|
||||
override suspend fun provide(): CurrentUserPushConfig? {
|
||||
val currentSession = appNavigationStateService.appNavigationState.value.navigationState.currentSessionId() ?: return null
|
||||
val clientSecret = pushClientSecret.getSecretForUser(currentSession)
|
||||
val url = unifiedPushStore.getPushGateway(clientSecret) ?: return null
|
||||
val pushKey = unifiedPushStore.getEndpoint(clientSecret) ?: return null
|
||||
return CurrentUserPushConfig(
|
||||
url = url,
|
||||
pushKey = pushKey,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package io.element.android.libraries.pushproviders.unifiedpush
|
||||
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.core.data.tryOrNull
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
@@ -33,30 +34,37 @@ class DefaultUnifiedPushGatewayResolver @Inject constructor(
|
||||
private val unifiedPushApiFactory: UnifiedPushApiFactory,
|
||||
private val coroutineDispatchers: CoroutineDispatchers,
|
||||
) : UnifiedPushGatewayResolver {
|
||||
private val logger = Timber.tag("DefaultUnifiedPushGatewayResolver")
|
||||
|
||||
override suspend fun getGateway(endpoint: String): String {
|
||||
val gateway = UnifiedPushConfig.DEFAULT_PUSH_GATEWAY_HTTP_URL
|
||||
try {
|
||||
val url = URL(endpoint)
|
||||
val url = tryOrNull(
|
||||
onError = { logger.d(it, "Cannot parse endpoint as an URL") }
|
||||
) {
|
||||
URL(endpoint)
|
||||
}
|
||||
return if (url == null) {
|
||||
logger.d("Using default gateway")
|
||||
UnifiedPushConfig.DEFAULT_PUSH_GATEWAY_HTTP_URL
|
||||
} else {
|
||||
val port = if (url.port != -1) ":${url.port}" else ""
|
||||
val customBase = "${url.protocol}://${url.host}$port"
|
||||
val customUrl = "$customBase/_matrix/push/v1/notify"
|
||||
Timber.i("Testing $customUrl")
|
||||
logger.i("Testing $customUrl")
|
||||
return withContext(coroutineDispatchers.io) {
|
||||
val api = unifiedPushApiFactory.create(customBase)
|
||||
try {
|
||||
val discoveryResponse = api.discover()
|
||||
if (discoveryResponse.unifiedpush.gateway == "matrix") {
|
||||
Timber.d("Using custom gateway")
|
||||
return@withContext customUrl
|
||||
logger.d("The endpoint seems to be a valid UnifiedPush gateway")
|
||||
} else {
|
||||
logger.e("The endpoint does not seem to be a valid UnifiedPush gateway")
|
||||
}
|
||||
} catch (throwable: Throwable) {
|
||||
Timber.tag("UnifiedPushHelper").e(throwable)
|
||||
logger.e(throwable, "Error checking for UnifiedPush endpoint")
|
||||
}
|
||||
return@withContext gateway
|
||||
// Always return the custom url.
|
||||
customUrl
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
Timber.d(e, "Cannot try custom gateway")
|
||||
}
|
||||
return gateway
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,6 @@ import io.element.android.libraries.pushproviders.api.CurrentUserPushConfig
|
||||
import io.element.android.libraries.pushproviders.api.Distributor
|
||||
import io.element.android.libraries.pushproviders.api.PushProvider
|
||||
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret
|
||||
import io.element.android.services.appnavstate.api.AppNavigationStateService
|
||||
import io.element.android.services.appnavstate.api.currentSessionId
|
||||
import javax.inject.Inject
|
||||
|
||||
@ContributesMultibinding(AppScope::class)
|
||||
@@ -34,7 +32,7 @@ class UnifiedPushProvider @Inject constructor(
|
||||
private val unRegisterUnifiedPushUseCase: UnregisterUnifiedPushUseCase,
|
||||
private val pushClientSecret: PushClientSecret,
|
||||
private val unifiedPushStore: UnifiedPushStore,
|
||||
private val appNavigationStateService: AppNavigationStateService,
|
||||
private val unifiedPushCurrentUserPushConfigProvider: UnifiedPushCurrentUserPushConfigProvider,
|
||||
) : PushProvider {
|
||||
override val index = UnifiedPushConfig.INDEX
|
||||
override val name = UnifiedPushConfig.NAME
|
||||
@@ -62,13 +60,6 @@ class UnifiedPushProvider @Inject constructor(
|
||||
}
|
||||
|
||||
override suspend fun getCurrentUserPushConfig(): CurrentUserPushConfig? {
|
||||
val currentSession = appNavigationStateService.appNavigationState.value.navigationState.currentSessionId() ?: return null
|
||||
val clientSecret = pushClientSecret.getSecretForUser(currentSession)
|
||||
val url = unifiedPushStore.getPushGateway(clientSecret) ?: return null
|
||||
val pushKey = unifiedPushStore.getEndpoint(clientSecret) ?: return null
|
||||
return CurrentUserPushConfig(
|
||||
url = url,
|
||||
pushKey = pushKey,
|
||||
)
|
||||
return unifiedPushCurrentUserPushConfigProvider.provide()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2024 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.pushproviders.unifiedpush.troubleshoot
|
||||
|
||||
import com.squareup.anvil.annotations.ContributesMultibinding
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.pushproviders.unifiedpush.UnifiedPushApiFactory
|
||||
import io.element.android.libraries.pushproviders.unifiedpush.UnifiedPushConfig
|
||||
import io.element.android.libraries.pushproviders.unifiedpush.UnifiedPushCurrentUserPushConfigProvider
|
||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTest
|
||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestDelegate
|
||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
||||
import io.element.android.libraries.troubleshoot.api.test.TestFilterData
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@ContributesMultibinding(AppScope::class)
|
||||
class UnifiedPushMatrixGatewayTest @Inject constructor(
|
||||
private val unifiedPushApiFactory: UnifiedPushApiFactory,
|
||||
private val coroutineDispatchers: CoroutineDispatchers,
|
||||
private val unifiedPushCurrentUserPushConfigProvider: UnifiedPushCurrentUserPushConfigProvider,
|
||||
) : NotificationTroubleshootTest {
|
||||
override val order = 450
|
||||
private val delegate = NotificationTroubleshootTestDelegate(
|
||||
defaultName = "Test push gateway",
|
||||
defaultDescription = "Ensure that the push gateway is valid.",
|
||||
visibleWhenIdle = false,
|
||||
fakeDelay = NotificationTroubleshootTestDelegate.SHORT_DELAY,
|
||||
)
|
||||
override val state: StateFlow<NotificationTroubleshootTestState> = delegate.state
|
||||
|
||||
override fun isRelevant(data: TestFilterData): Boolean {
|
||||
return data.currentPushProviderName == UnifiedPushConfig.NAME
|
||||
}
|
||||
|
||||
override suspend fun run(coroutineScope: CoroutineScope) {
|
||||
delegate.start()
|
||||
val config = unifiedPushCurrentUserPushConfigProvider.provide()
|
||||
if (config == null) {
|
||||
delegate.updateState(
|
||||
description = "No current push provider",
|
||||
status = NotificationTroubleshootTestState.Status.Failure(false)
|
||||
)
|
||||
} else {
|
||||
val gatewayBaseUrl = config.url.removeSuffix("/_matrix/push/v1/notify")
|
||||
// Checking if the gateway is a Matrix gateway
|
||||
coroutineScope.launch(coroutineDispatchers.io) {
|
||||
val api = unifiedPushApiFactory.create(gatewayBaseUrl)
|
||||
try {
|
||||
val discoveryResponse = api.discover()
|
||||
if (discoveryResponse.unifiedpush.gateway == "matrix") {
|
||||
delegate.updateState(
|
||||
description = "${config.url} is a Matrix gateway.",
|
||||
status = NotificationTroubleshootTestState.Status.Success
|
||||
)
|
||||
} else {
|
||||
delegate.updateState(
|
||||
description = "${config.url} is not a Matrix gateway.",
|
||||
status = NotificationTroubleshootTestState.Status.Failure(false)
|
||||
)
|
||||
}
|
||||
} catch (throwable: Throwable) {
|
||||
delegate.updateState(
|
||||
description = "Fail to check the gateway ${config.url}: ${throwable.localizedMessage}",
|
||||
status = NotificationTroubleshootTestState.Status.Failure(false)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun reset() = delegate.reset()
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (c) 2024 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.pushproviders.unifiedpush
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.matrix.test.A_SECRET
|
||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||
import io.element.android.libraries.pushproviders.api.CurrentUserPushConfig
|
||||
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret
|
||||
import io.element.android.libraries.pushstore.test.userpushstore.clientsecret.FakePushClientSecret
|
||||
import io.element.android.services.appnavstate.api.AppNavigationState
|
||||
import io.element.android.services.appnavstate.api.AppNavigationStateService
|
||||
import io.element.android.services.appnavstate.api.NavigationState
|
||||
import io.element.android.services.appnavstate.test.FakeAppNavigationStateService
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
class DefaultUnifiedPushCurrentUserPushConfigProviderTest {
|
||||
@Test
|
||||
fun `getCurrentUserPushConfig no session`() = runTest {
|
||||
val sut = createDefaultUnifiedPushCurrentUserPushConfigProvider()
|
||||
val result = sut.provide()
|
||||
assertThat(result).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getCurrentUserPushConfig no push gateway`() = runTest {
|
||||
val sut = createDefaultUnifiedPushCurrentUserPushConfigProvider(
|
||||
appNavigationStateService = FakeAppNavigationStateService(
|
||||
appNavigationState = MutableStateFlow(
|
||||
AppNavigationState(
|
||||
navigationState = NavigationState.Session(owner = "owner", sessionId = A_SESSION_ID),
|
||||
isInForeground = true
|
||||
)
|
||||
)
|
||||
),
|
||||
pushClientSecret = FakePushClientSecret(
|
||||
getSecretForUserResult = { A_SECRET }
|
||||
),
|
||||
unifiedPushStore = FakeUnifiedPushStore(
|
||||
getPushGatewayResult = { null }
|
||||
),
|
||||
)
|
||||
val result = sut.provide()
|
||||
assertThat(result).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getCurrentUserPushConfig no push key`() = runTest {
|
||||
val sut = createDefaultUnifiedPushCurrentUserPushConfigProvider(
|
||||
appNavigationStateService = FakeAppNavigationStateService(
|
||||
appNavigationState = MutableStateFlow(
|
||||
AppNavigationState(
|
||||
navigationState = NavigationState.Session(owner = "owner", sessionId = A_SESSION_ID),
|
||||
isInForeground = true
|
||||
)
|
||||
)
|
||||
),
|
||||
pushClientSecret = FakePushClientSecret(
|
||||
getSecretForUserResult = { A_SECRET }
|
||||
),
|
||||
unifiedPushStore = FakeUnifiedPushStore(
|
||||
getPushGatewayResult = { "aPushGateway" },
|
||||
getEndpointResult = { null }
|
||||
),
|
||||
)
|
||||
val result = sut.provide()
|
||||
assertThat(result).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getCurrentUserPushConfig ok`() = runTest {
|
||||
val sut = createDefaultUnifiedPushCurrentUserPushConfigProvider(
|
||||
appNavigationStateService = FakeAppNavigationStateService(
|
||||
appNavigationState = MutableStateFlow(
|
||||
AppNavigationState(
|
||||
navigationState = NavigationState.Session(owner = "owner", sessionId = A_SESSION_ID),
|
||||
isInForeground = true
|
||||
)
|
||||
)
|
||||
),
|
||||
pushClientSecret = FakePushClientSecret(
|
||||
getSecretForUserResult = { A_SECRET }
|
||||
),
|
||||
unifiedPushStore = FakeUnifiedPushStore(
|
||||
getPushGatewayResult = { "aPushGateway" },
|
||||
getEndpointResult = { "aEndpoint" }
|
||||
),
|
||||
)
|
||||
val result = sut.provide()
|
||||
assertThat(result).isEqualTo(CurrentUserPushConfig("aPushGateway", "aEndpoint"))
|
||||
}
|
||||
|
||||
private fun createDefaultUnifiedPushCurrentUserPushConfigProvider(
|
||||
pushClientSecret: PushClientSecret = FakePushClientSecret(),
|
||||
unifiedPushStore: UnifiedPushStore = FakeUnifiedPushStore(),
|
||||
appNavigationStateService: AppNavigationStateService = FakeAppNavigationStateService(),
|
||||
): DefaultUnifiedPushCurrentUserPushConfigProvider {
|
||||
return DefaultUnifiedPushCurrentUserPushConfigProvider(
|
||||
pushClientSecret = pushClientSecret,
|
||||
unifiedPushStore = unifiedPushStore,
|
||||
appNavigationStateService = appNavigationStateService,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -25,23 +25,23 @@ import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
internal val matrixDiscoveryResponse = {
|
||||
DiscoveryResponse(
|
||||
unifiedpush = DiscoveryUnifiedPush(
|
||||
gateway = "matrix"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
internal val invalidDiscoveryResponse = {
|
||||
DiscoveryResponse(
|
||||
unifiedpush = DiscoveryUnifiedPush(
|
||||
gateway = ""
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
class DefaultUnifiedPushGatewayResolverTest {
|
||||
private val matrixDiscoveryResponse = {
|
||||
DiscoveryResponse(
|
||||
unifiedpush = DiscoveryUnifiedPush(
|
||||
gateway = "matrix"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private val invalidDiscoveryResponse = {
|
||||
DiscoveryResponse(
|
||||
unifiedpush = DiscoveryUnifiedPush(
|
||||
gateway = ""
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when a custom url provide a correct matrix gateway, the custom url is returned`() = runTest {
|
||||
val unifiedPushApiFactory = FakeUnifiedPushApiFactory(
|
||||
@@ -95,7 +95,7 @@ class DefaultUnifiedPushGatewayResolverTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when a custom url is not reachable, the default url is returned`() = runTest {
|
||||
fun `when a custom url is not reachable, the custom url is still returned`() = runTest {
|
||||
val unifiedPushApiFactory = FakeUnifiedPushApiFactory(
|
||||
discoveryResponse = { throw AN_EXCEPTION }
|
||||
)
|
||||
@@ -104,7 +104,7 @@ class DefaultUnifiedPushGatewayResolverTest {
|
||||
)
|
||||
val result = sut.getGateway("http://custom.url")
|
||||
assertThat(unifiedPushApiFactory.baseUrlParameter).isEqualTo("http://custom.url")
|
||||
assertThat(result).isEqualTo(UnifiedPushConfig.DEFAULT_PUSH_GATEWAY_HTTP_URL)
|
||||
assertThat(result).isEqualTo("http://custom.url/_matrix/push/v1/notify")
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -121,7 +121,7 @@ class DefaultUnifiedPushGatewayResolverTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when a custom url provides a invalid matrix gateway, the default url is returned`() = runTest {
|
||||
fun `when a custom url provides a invalid matrix gateway, the custom url is still returned`() = runTest {
|
||||
val unifiedPushApiFactory = FakeUnifiedPushApiFactory(
|
||||
discoveryResponse = invalidDiscoveryResponse
|
||||
)
|
||||
@@ -130,7 +130,7 @@ class DefaultUnifiedPushGatewayResolverTest {
|
||||
)
|
||||
val result = sut.getGateway("https://custom.url")
|
||||
assertThat(unifiedPushApiFactory.baseUrlParameter).isEqualTo("https://custom.url")
|
||||
assertThat(result).isEqualTo(UnifiedPushConfig.DEFAULT_PUSH_GATEWAY_HTTP_URL)
|
||||
assertThat(result).isEqualTo("https://custom.url/_matrix/push/v1/notify")
|
||||
}
|
||||
|
||||
private fun TestScope.createDefaultUnifiedPushGatewayResolver(
|
||||
|
||||
@@ -24,18 +24,14 @@ import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||
import io.element.android.libraries.matrix.test.A_SECRET
|
||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.libraries.pushproviders.api.CurrentUserPushConfig
|
||||
import io.element.android.libraries.pushproviders.api.Distributor
|
||||
import io.element.android.libraries.pushproviders.test.aCurrentUserPushConfig
|
||||
import io.element.android.libraries.pushproviders.unifiedpush.troubleshoot.FakeUnifiedPushCurrentUserPushConfigProvider
|
||||
import io.element.android.libraries.pushproviders.unifiedpush.troubleshoot.FakeUnifiedPushDistributorProvider
|
||||
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret
|
||||
import io.element.android.libraries.pushstore.test.userpushstore.clientsecret.FakePushClientSecret
|
||||
import io.element.android.services.appnavstate.api.AppNavigationState
|
||||
import io.element.android.services.appnavstate.api.AppNavigationStateService
|
||||
import io.element.android.services.appnavstate.api.NavigationState
|
||||
import io.element.android.services.appnavstate.test.FakeAppNavigationStateService
|
||||
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||
import io.element.android.tests.testutils.lambda.value
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
@@ -226,78 +222,15 @@ class UnifiedPushProviderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getCurrentUserPushConfig no session`() = runTest {
|
||||
val unifiedPushProvider = createUnifiedPushProvider()
|
||||
val result = unifiedPushProvider.getCurrentUserPushConfig()
|
||||
assertThat(result).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getCurrentUserPushConfig no push gateway`() = runTest {
|
||||
fun `getCurrentUserPushConfig invokes the provider methods`() = runTest {
|
||||
val currentUserPushConfig = aCurrentUserPushConfig()
|
||||
val unifiedPushProvider = createUnifiedPushProvider(
|
||||
appNavigationStateService = FakeAppNavigationStateService(
|
||||
appNavigationState = MutableStateFlow(
|
||||
AppNavigationState(
|
||||
navigationState = NavigationState.Session(owner = "owner", sessionId = A_SESSION_ID),
|
||||
isInForeground = true
|
||||
)
|
||||
)
|
||||
),
|
||||
pushClientSecret = FakePushClientSecret(
|
||||
getSecretForUserResult = { A_SECRET }
|
||||
),
|
||||
unifiedPushStore = FakeUnifiedPushStore(
|
||||
getPushGatewayResult = { null }
|
||||
),
|
||||
unifiedPushCurrentUserPushConfigProvider = FakeUnifiedPushCurrentUserPushConfigProvider(
|
||||
currentUserPushConfig = { currentUserPushConfig }
|
||||
)
|
||||
)
|
||||
val result = unifiedPushProvider.getCurrentUserPushConfig()
|
||||
assertThat(result).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getCurrentUserPushConfig no push key`() = runTest {
|
||||
val unifiedPushProvider = createUnifiedPushProvider(
|
||||
appNavigationStateService = FakeAppNavigationStateService(
|
||||
appNavigationState = MutableStateFlow(
|
||||
AppNavigationState(
|
||||
navigationState = NavigationState.Session(owner = "owner", sessionId = A_SESSION_ID),
|
||||
isInForeground = true
|
||||
)
|
||||
)
|
||||
),
|
||||
pushClientSecret = FakePushClientSecret(
|
||||
getSecretForUserResult = { A_SECRET }
|
||||
),
|
||||
unifiedPushStore = FakeUnifiedPushStore(
|
||||
getPushGatewayResult = { "aPushGateway" },
|
||||
getEndpointResult = { null }
|
||||
),
|
||||
)
|
||||
val result = unifiedPushProvider.getCurrentUserPushConfig()
|
||||
assertThat(result).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getCurrentUserPushConfig ok`() = runTest {
|
||||
val unifiedPushProvider = createUnifiedPushProvider(
|
||||
appNavigationStateService = FakeAppNavigationStateService(
|
||||
appNavigationState = MutableStateFlow(
|
||||
AppNavigationState(
|
||||
navigationState = NavigationState.Session(owner = "owner", sessionId = A_SESSION_ID),
|
||||
isInForeground = true
|
||||
)
|
||||
)
|
||||
),
|
||||
pushClientSecret = FakePushClientSecret(
|
||||
getSecretForUserResult = { A_SECRET }
|
||||
),
|
||||
unifiedPushStore = FakeUnifiedPushStore(
|
||||
getPushGatewayResult = { "aPushGateway" },
|
||||
getEndpointResult = { "aEndpoint" }
|
||||
),
|
||||
)
|
||||
val result = unifiedPushProvider.getCurrentUserPushConfig()
|
||||
assertThat(result).isEqualTo(CurrentUserPushConfig("aPushGateway", "aEndpoint"))
|
||||
assertThat(result).isEqualTo(currentUserPushConfig)
|
||||
}
|
||||
|
||||
private fun createUnifiedPushProvider(
|
||||
@@ -306,7 +239,7 @@ class UnifiedPushProviderTest {
|
||||
unRegisterUnifiedPushUseCase: UnregisterUnifiedPushUseCase = FakeUnregisterUnifiedPushUseCase(),
|
||||
pushClientSecret: PushClientSecret = FakePushClientSecret(),
|
||||
unifiedPushStore: UnifiedPushStore = FakeUnifiedPushStore(),
|
||||
appNavigationStateService: AppNavigationStateService = FakeAppNavigationStateService(),
|
||||
unifiedPushCurrentUserPushConfigProvider: UnifiedPushCurrentUserPushConfigProvider = FakeUnifiedPushCurrentUserPushConfigProvider(),
|
||||
): UnifiedPushProvider {
|
||||
return UnifiedPushProvider(
|
||||
unifiedPushDistributorProvider = unifiedPushDistributorProvider,
|
||||
@@ -314,7 +247,7 @@ class UnifiedPushProviderTest {
|
||||
unRegisterUnifiedPushUseCase = unRegisterUnifiedPushUseCase,
|
||||
pushClientSecret = pushClientSecret,
|
||||
unifiedPushStore = unifiedPushStore,
|
||||
appNavigationStateService = appNavigationStateService
|
||||
unifiedPushCurrentUserPushConfigProvider = unifiedPushCurrentUserPushConfigProvider,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2024 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.pushproviders.unifiedpush.troubleshoot
|
||||
|
||||
import io.element.android.libraries.pushproviders.api.CurrentUserPushConfig
|
||||
import io.element.android.libraries.pushproviders.unifiedpush.UnifiedPushCurrentUserPushConfigProvider
|
||||
import io.element.android.tests.testutils.lambda.lambdaError
|
||||
|
||||
class FakeUnifiedPushCurrentUserPushConfigProvider(
|
||||
private val currentUserPushConfig: () -> CurrentUserPushConfig? = { lambdaError() },
|
||||
) : UnifiedPushCurrentUserPushConfigProvider {
|
||||
override suspend fun provide(): CurrentUserPushConfig? {
|
||||
return currentUserPushConfig()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 2024 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.pushproviders.unifiedpush.troubleshoot
|
||||
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.pushproviders.api.CurrentUserPushConfig
|
||||
import io.element.android.libraries.pushproviders.test.aCurrentUserPushConfig
|
||||
import io.element.android.libraries.pushproviders.unifiedpush.FakeUnifiedPushApiFactory
|
||||
import io.element.android.libraries.pushproviders.unifiedpush.UnifiedPushConfig
|
||||
import io.element.android.libraries.pushproviders.unifiedpush.invalidDiscoveryResponse
|
||||
import io.element.android.libraries.pushproviders.unifiedpush.matrixDiscoveryResponse
|
||||
import io.element.android.libraries.pushproviders.unifiedpush.network.DiscoveryResponse
|
||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
||||
import io.element.android.libraries.troubleshoot.api.test.TestFilterData
|
||||
import io.element.android.tests.testutils.testCoroutineDispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
class UnifiedPushMatrixGatewayTestTest {
|
||||
@Test
|
||||
fun `test UnifiedPushMatrixGatewayTest success`() = runTest {
|
||||
val sut = createUnifiedPushMatrixGatewayTest(
|
||||
currentUserPushConfig = aCurrentUserPushConfig(),
|
||||
discoveryResponse = matrixDiscoveryResponse,
|
||||
)
|
||||
launch {
|
||||
sut.run(this)
|
||||
}
|
||||
sut.state.test {
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||
val lastItem = awaitItem()
|
||||
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Success)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test UnifiedPushMatrixGatewayTest no config found`() = runTest {
|
||||
val sut = createUnifiedPushMatrixGatewayTest(
|
||||
currentUserPushConfig = null,
|
||||
discoveryResponse = matrixDiscoveryResponse,
|
||||
)
|
||||
launch {
|
||||
sut.run(this)
|
||||
}
|
||||
sut.state.test {
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||
val lastItem = awaitItem()
|
||||
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test UnifiedPushMatrixGatewayTest not valid gateway`() = runTest {
|
||||
val sut = createUnifiedPushMatrixGatewayTest(
|
||||
currentUserPushConfig = aCurrentUserPushConfig(),
|
||||
discoveryResponse = invalidDiscoveryResponse,
|
||||
)
|
||||
launch {
|
||||
sut.run(this)
|
||||
}
|
||||
sut.state.test {
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||
val lastItem = awaitItem()
|
||||
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false))
|
||||
// Reset the error
|
||||
sut.reset()
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test UnifiedPushMatrixGatewayTest network error`() = runTest {
|
||||
val sut = createUnifiedPushMatrixGatewayTest(
|
||||
currentUserPushConfig = aCurrentUserPushConfig(),
|
||||
discoveryResponse = { error("Network error") },
|
||||
)
|
||||
launch {
|
||||
sut.run(this)
|
||||
}
|
||||
sut.state.test {
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||
val lastItem = awaitItem()
|
||||
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test isRelevant`() = runTest {
|
||||
val sut = createUnifiedPushMatrixGatewayTest()
|
||||
assertThat(sut.isRelevant(TestFilterData(currentPushProviderName = UnifiedPushConfig.NAME))).isTrue()
|
||||
assertThat(sut.isRelevant(TestFilterData(currentPushProviderName = "other"))).isFalse()
|
||||
}
|
||||
|
||||
private fun TestScope.createUnifiedPushMatrixGatewayTest(
|
||||
currentUserPushConfig: CurrentUserPushConfig? = null,
|
||||
discoveryResponse: () -> DiscoveryResponse = matrixDiscoveryResponse,
|
||||
): UnifiedPushMatrixGatewayTest {
|
||||
return UnifiedPushMatrixGatewayTest(
|
||||
unifiedPushApiFactory = FakeUnifiedPushApiFactory(discoveryResponse),
|
||||
coroutineDispatchers = testCoroutineDispatchers(),
|
||||
unifiedPushCurrentUserPushConfigProvider = FakeUnifiedPushCurrentUserPushConfigProvider(
|
||||
currentUserPushConfig = { currentUserPushConfig }
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -84,6 +84,35 @@ class UnifiedPushTestTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test UnifiedPushTest error and reset`() = runTest {
|
||||
val providers = FakeUnifiedPushDistributorProvider()
|
||||
val sut = UnifiedPushTest(
|
||||
unifiedPushDistributorProvider = providers,
|
||||
openDistributorWebPageAction = FakeOpenDistributorWebPageAction(
|
||||
executeAction = {
|
||||
providers.setDistributorsResult(
|
||||
listOf(
|
||||
Distributor("value", "Name"),
|
||||
)
|
||||
)
|
||||
}
|
||||
),
|
||||
stringProvider = FakeStringProvider(),
|
||||
)
|
||||
launch {
|
||||
sut.run(this)
|
||||
}
|
||||
sut.state.test {
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||
val lastItem = awaitItem()
|
||||
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true))
|
||||
sut.reset()
|
||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test isRelevant`() {
|
||||
val sut = UnifiedPushTest(
|
||||
|
||||
Reference in New Issue
Block a user