Merge pull request #5394 from element-hq/feature/bma/testIgnoredUser
Add troubleshhot notification test about blocked users
This commit is contained in:
commit
6dc99d415e
46 changed files with 529 additions and 216 deletions
|
|
@ -93,6 +93,8 @@ allprojects {
|
||||||
// Fix compilation warning for annotations
|
// Fix compilation warning for annotations
|
||||||
// See https://youtrack.jetbrains.com/issue/KT-73255/Change-defaulting-rule-for-annotations for more details
|
// See https://youtrack.jetbrains.com/issue/KT-73255/Change-defaulting-rule-for-annotations for more details
|
||||||
freeCompilerArgs.add("-Xannotation-default-target=first-only")
|
freeCompilerArgs.add("-Xannotation-default-target=first-only")
|
||||||
|
// Opt-in to context receivers
|
||||||
|
freeCompilerArgs.add("-Xcontext-parameters")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -208,6 +208,10 @@ class PreferencesFlowNode(
|
||||||
navigateUp()
|
navigateUp()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun openIgnoredUsers() {
|
||||||
|
backstack.push(NavTarget.BlockedUsers)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,5 +43,6 @@ dependencies {
|
||||||
testCommonDependencies(libs)
|
testCommonDependencies(libs)
|
||||||
testImplementation(projects.libraries.matrix.test)
|
testImplementation(projects.libraries.matrix.test)
|
||||||
testImplementation(projects.libraries.permissions.test)
|
testImplementation(projects.libraries.permissions.test)
|
||||||
|
testImplementation(projects.libraries.troubleshoot.test)
|
||||||
testImplementation(projects.services.toolbox.test)
|
testImplementation(projects.services.toolbox.test)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import dev.zacsweers.metro.Inject
|
||||||
import io.element.android.libraries.permissions.api.PermissionStateProvider
|
import io.element.android.libraries.permissions.api.PermissionStateProvider
|
||||||
import io.element.android.libraries.permissions.impl.R
|
import io.element.android.libraries.permissions.impl.R
|
||||||
import io.element.android.libraries.permissions.impl.action.PermissionActions
|
import io.element.android.libraries.permissions.impl.action.PermissionActions
|
||||||
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator
|
||||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTest
|
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.NotificationTroubleshootTestDelegate
|
||||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
||||||
|
|
@ -54,7 +55,10 @@ class NotificationTroubleshootCheckPermissionTest(
|
||||||
|
|
||||||
override suspend fun reset() = delegate.reset()
|
override suspend fun reset() = delegate.reset()
|
||||||
|
|
||||||
override suspend fun quickFix(coroutineScope: CoroutineScope) {
|
override suspend fun quickFix(
|
||||||
|
coroutineScope: CoroutineScope,
|
||||||
|
navigator: NotificationTroubleshootNavigator,
|
||||||
|
) {
|
||||||
// Do not bother about asking the permission inline, just lead the user to the settings
|
// Do not bother about asking the permission inline, just lead the user to the settings
|
||||||
permissionActions.openSettings()
|
permissionActions.openSettings()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,12 @@
|
||||||
package io.element.android.libraries.permissions.impl.troubleshoot
|
package io.element.android.libraries.permissions.impl.troubleshoot
|
||||||
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import app.cash.turbine.test
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import io.element.android.libraries.permissions.impl.action.FakePermissionActions
|
import io.element.android.libraries.permissions.impl.action.FakePermissionActions
|
||||||
import io.element.android.libraries.permissions.test.FakePermissionStateProvider
|
import io.element.android.libraries.permissions.test.FakePermissionStateProvider
|
||||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
||||||
|
import io.element.android.libraries.troubleshoot.test.FakeNotificationTroubleshootNavigator
|
||||||
|
import io.element.android.libraries.troubleshoot.test.runAndTestState
|
||||||
import io.element.android.services.toolbox.test.sdk.FakeBuildVersionSdkIntProvider
|
import io.element.android.services.toolbox.test.sdk.FakeBuildVersionSdkIntProvider
|
||||||
import io.element.android.services.toolbox.test.strings.FakeStringProvider
|
import io.element.android.services.toolbox.test.strings.FakeStringProvider
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
@ -28,10 +29,7 @@ class NotificationTroubleshootCheckPermissionTestTest {
|
||||||
permissionActions = FakePermissionActions(),
|
permissionActions = FakePermissionActions(),
|
||||||
stringProvider = FakeStringProvider(),
|
stringProvider = FakeStringProvider(),
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
val lastItem = awaitItem()
|
val lastItem = awaitItem()
|
||||||
|
|
@ -47,10 +45,7 @@ class NotificationTroubleshootCheckPermissionTestTest {
|
||||||
permissionActions = FakePermissionActions(),
|
permissionActions = FakePermissionActions(),
|
||||||
stringProvider = FakeStringProvider(),
|
stringProvider = FakeStringProvider(),
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
val lastItem = awaitItem()
|
val lastItem = awaitItem()
|
||||||
|
|
@ -74,17 +69,14 @@ class NotificationTroubleshootCheckPermissionTestTest {
|
||||||
permissionActions = actions,
|
permissionActions = actions,
|
||||||
stringProvider = FakeStringProvider(),
|
stringProvider = FakeStringProvider(),
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
val lastItem = awaitItem()
|
val lastItem = awaitItem()
|
||||||
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true))
|
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(hasQuickFix = true))
|
||||||
// Quick fix
|
// Quick fix
|
||||||
launch {
|
backgroundScope.launch {
|
||||||
sut.quickFix(this)
|
sut.quickFix(this, FakeNotificationTroubleshootNavigator())
|
||||||
// Run the test again (IRL it will be done thanks to the resuming of the application)
|
// Run the test again (IRL it will be done thanks to the resuming of the application)
|
||||||
sut.run(this)
|
sut.run(this)
|
||||||
}
|
}
|
||||||
|
|
@ -109,13 +101,10 @@ class NotificationTroubleshootCheckPermissionTestTest {
|
||||||
permissionActions = actions,
|
permissionActions = actions,
|
||||||
stringProvider = FakeStringProvider(),
|
stringProvider = FakeStringProvider(),
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(hasQuickFix = true))
|
||||||
sut.reset()
|
sut.reset()
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,7 @@ dependencies {
|
||||||
testImplementation(projects.libraries.push.test)
|
testImplementation(projects.libraries.push.test)
|
||||||
testImplementation(projects.libraries.pushproviders.test)
|
testImplementation(projects.libraries.pushproviders.test)
|
||||||
testImplementation(projects.libraries.pushstore.test)
|
testImplementation(projects.libraries.pushstore.test)
|
||||||
|
testImplementation(projects.libraries.troubleshoot.test)
|
||||||
testImplementation(projects.features.call.test)
|
testImplementation(projects.features.call.test)
|
||||||
testImplementation(projects.features.lockscreen.test)
|
testImplementation(projects.features.lockscreen.test)
|
||||||
testImplementation(projects.services.appnavstate.test)
|
testImplementation(projects.services.appnavstate.test)
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ class CurrentPushProviderTest(
|
||||||
} else {
|
} else {
|
||||||
delegate.updateState(
|
delegate.updateState(
|
||||||
description = stringProvider.getString(R.string.troubleshoot_notifications_test_current_push_provider_failure),
|
description = stringProvider.getString(R.string.troubleshoot_notifications_test_current_push_provider_failure),
|
||||||
status = NotificationTroubleshootTestState.Status.Failure(false)
|
status = NotificationTroubleshootTestState.Status.Failure()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 New Vector Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
|
* Please see LICENSE files in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.push.impl.troubleshoot
|
||||||
|
|
||||||
|
import dev.zacsweers.metro.ContributesIntoSet
|
||||||
|
import dev.zacsweers.metro.Inject
|
||||||
|
import io.element.android.libraries.di.SessionScope
|
||||||
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
|
import io.element.android.libraries.push.impl.R
|
||||||
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator
|
||||||
|
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.services.toolbox.api.strings.StringProvider
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
||||||
|
@ContributesIntoSet(SessionScope::class)
|
||||||
|
@Inject
|
||||||
|
class IgnoredUsersTest(
|
||||||
|
private val matrixClient: MatrixClient,
|
||||||
|
private val stringProvider: StringProvider,
|
||||||
|
) : NotificationTroubleshootTest {
|
||||||
|
override val order = 80
|
||||||
|
private val delegate = NotificationTroubleshootTestDelegate(
|
||||||
|
defaultName = stringProvider.getString(R.string.troubleshoot_notifications_test_blocked_users_title),
|
||||||
|
defaultDescription = stringProvider.getString(R.string.troubleshoot_notifications_test_blocked_users_description),
|
||||||
|
fakeDelay = NotificationTroubleshootTestDelegate.SHORT_DELAY,
|
||||||
|
)
|
||||||
|
override val state: StateFlow<NotificationTroubleshootTestState> = delegate.state
|
||||||
|
|
||||||
|
override suspend fun run(coroutineScope: CoroutineScope) {
|
||||||
|
delegate.start()
|
||||||
|
val ignorerUsers = matrixClient.ignoredUsersFlow.value
|
||||||
|
if (ignorerUsers.isEmpty()) {
|
||||||
|
delegate.updateState(
|
||||||
|
description = stringProvider.getString(R.string.troubleshoot_notifications_test_blocked_users_result_none),
|
||||||
|
status = NotificationTroubleshootTestState.Status.Success,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
delegate.updateState(
|
||||||
|
description = stringProvider.getQuantityString(
|
||||||
|
R.plurals.troubleshoot_notifications_test_blocked_users_result_some,
|
||||||
|
ignorerUsers.size,
|
||||||
|
ignorerUsers.size
|
||||||
|
),
|
||||||
|
status = NotificationTroubleshootTestState.Status.Failure(
|
||||||
|
hasQuickFix = true,
|
||||||
|
isCritical = false,
|
||||||
|
quickFixButtonString = stringProvider.getString(R.string.troubleshoot_notifications_test_blocked_users_quick_fix),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun quickFix(
|
||||||
|
coroutineScope: CoroutineScope,
|
||||||
|
navigator: NotificationTroubleshootNavigator,
|
||||||
|
) {
|
||||||
|
navigator.openIgnoredUsers()
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun reset() = delegate.reset()
|
||||||
|
}
|
||||||
|
|
@ -54,7 +54,7 @@ class NotificationTest(
|
||||||
} else {
|
} else {
|
||||||
delegate.updateState(
|
delegate.updateState(
|
||||||
description = stringProvider.getString(R.string.troubleshoot_notifications_test_display_notification_permission_failure),
|
description = stringProvider.getString(R.string.troubleshoot_notifications_test_display_notification_permission_failure),
|
||||||
status = NotificationTroubleshootTestState.Status.Failure(false)
|
status = NotificationTroubleshootTestState.Status.Failure()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -81,7 +81,7 @@ class NotificationTest(
|
||||||
notificationDisplayer.dismissDiagnosticNotification()
|
notificationDisplayer.dismissDiagnosticNotification()
|
||||||
delegate.updateState(
|
delegate.updateState(
|
||||||
description = stringProvider.getString(R.string.troubleshoot_notifications_test_display_notification_failure),
|
description = stringProvider.getString(R.string.troubleshoot_notifications_test_display_notification_failure),
|
||||||
status = NotificationTroubleshootTestState.Status.Failure(false)
|
status = NotificationTroubleshootTestState.Status.Failure()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import dev.zacsweers.metro.Inject
|
||||||
import io.element.android.libraries.push.api.PushService
|
import io.element.android.libraries.push.api.PushService
|
||||||
import io.element.android.libraries.push.api.gateway.PushGatewayFailure
|
import io.element.android.libraries.push.api.gateway.PushGatewayFailure
|
||||||
import io.element.android.libraries.push.impl.R
|
import io.element.android.libraries.push.impl.R
|
||||||
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator
|
||||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTest
|
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.NotificationTroubleshootTestDelegate
|
||||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
||||||
|
|
@ -56,7 +57,7 @@ class PushLoopbackTest(
|
||||||
val hasQuickFix = pushService.getCurrentPushProvider()?.canRotateToken() == true
|
val hasQuickFix = pushService.getCurrentPushProvider()?.canRotateToken() == true
|
||||||
delegate.updateState(
|
delegate.updateState(
|
||||||
description = stringProvider.getString(R.string.troubleshoot_notifications_test_push_loop_back_failure_1),
|
description = stringProvider.getString(R.string.troubleshoot_notifications_test_push_loop_back_failure_1),
|
||||||
status = NotificationTroubleshootTestState.Status.Failure(hasQuickFix)
|
status = NotificationTroubleshootTestState.Status.Failure(hasQuickFix = hasQuickFix)
|
||||||
)
|
)
|
||||||
job.cancel()
|
job.cancel()
|
||||||
return
|
return
|
||||||
|
|
@ -64,7 +65,7 @@ class PushLoopbackTest(
|
||||||
Timber.e(e, "Failed to test push")
|
Timber.e(e, "Failed to test push")
|
||||||
delegate.updateState(
|
delegate.updateState(
|
||||||
description = stringProvider.getString(R.string.troubleshoot_notifications_test_push_loop_back_failure_2, e.message),
|
description = stringProvider.getString(R.string.troubleshoot_notifications_test_push_loop_back_failure_2, e.message),
|
||||||
status = NotificationTroubleshootTestState.Status.Failure(false)
|
status = NotificationTroubleshootTestState.Status.Failure()
|
||||||
)
|
)
|
||||||
job.cancel()
|
job.cancel()
|
||||||
return
|
return
|
||||||
|
|
@ -72,7 +73,7 @@ class PushLoopbackTest(
|
||||||
if (!testPushResult) {
|
if (!testPushResult) {
|
||||||
delegate.updateState(
|
delegate.updateState(
|
||||||
description = stringProvider.getString(R.string.troubleshoot_notifications_test_push_loop_back_failure_3),
|
description = stringProvider.getString(R.string.troubleshoot_notifications_test_push_loop_back_failure_3),
|
||||||
status = NotificationTroubleshootTestState.Status.Failure(false)
|
status = NotificationTroubleshootTestState.Status.Failure()
|
||||||
)
|
)
|
||||||
job.cancel()
|
job.cancel()
|
||||||
return
|
return
|
||||||
|
|
@ -93,13 +94,16 @@ class PushLoopbackTest(
|
||||||
job.cancel()
|
job.cancel()
|
||||||
delegate.updateState(
|
delegate.updateState(
|
||||||
description = stringProvider.getString(R.string.troubleshoot_notifications_test_push_loop_back_failure_4),
|
description = stringProvider.getString(R.string.troubleshoot_notifications_test_push_loop_back_failure_4),
|
||||||
status = NotificationTroubleshootTestState.Status.Failure(false)
|
status = NotificationTroubleshootTestState.Status.Failure()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun quickFix(coroutineScope: CoroutineScope) {
|
override suspend fun quickFix(
|
||||||
|
coroutineScope: CoroutineScope,
|
||||||
|
navigator: NotificationTroubleshootNavigator,
|
||||||
|
) {
|
||||||
delegate.start()
|
delegate.start()
|
||||||
pushService.getCurrentPushProvider()?.rotateToken()
|
pushService.getCurrentPushProvider()?.rotateToken()
|
||||||
run(coroutineScope)
|
run(coroutineScope)
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ class PushProvidersTest(
|
||||||
} else {
|
} else {
|
||||||
delegate.updateState(
|
delegate.updateState(
|
||||||
description = stringProvider.getString(R.string.troubleshoot_notifications_test_detect_push_provider_failure),
|
description = stringProvider.getString(R.string.troubleshoot_notifications_test_detect_push_provider_failure),
|
||||||
status = NotificationTroubleshootTestState.Status.Failure(false)
|
status = NotificationTroubleshootTestState.Status.Failure()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,14 @@
|
||||||
<string name="push_distributor_background_sync_android">"Background synchronization"</string>
|
<string name="push_distributor_background_sync_android">"Background synchronization"</string>
|
||||||
<string name="push_distributor_firebase_android">"Google Services"</string>
|
<string name="push_distributor_firebase_android">"Google Services"</string>
|
||||||
<string name="push_no_valid_google_play_services_apk_android">"No valid Google Play Services found. Notifications may not work properly."</string>
|
<string name="push_no_valid_google_play_services_apk_android">"No valid Google Play Services found. Notifications may not work properly."</string>
|
||||||
|
<string name="troubleshoot_notifications_test_blocked_users_description">"Checking blocked users"</string>
|
||||||
|
<string name="troubleshoot_notifications_test_blocked_users_quick_fix">"View blocked users"</string>
|
||||||
|
<string name="troubleshoot_notifications_test_blocked_users_result_none">"No users are blocked."</string>
|
||||||
|
<plurals name="troubleshoot_notifications_test_blocked_users_result_some">
|
||||||
|
<item quantity="one">"You blocked %1$d user. You will not receive notifications for this user."</item>
|
||||||
|
<item quantity="other">"You blocked %1$d users. You will not receive notifications for these users."</item>
|
||||||
|
</plurals>
|
||||||
|
<string name="troubleshoot_notifications_test_blocked_users_title">"Blocked users"</string>
|
||||||
<string name="troubleshoot_notifications_test_current_push_provider_description">"Get the name of the current provider."</string>
|
<string name="troubleshoot_notifications_test_current_push_provider_description">"Get the name of the current provider."</string>
|
||||||
<string name="troubleshoot_notifications_test_current_push_provider_failure">"No push providers selected."</string>
|
<string name="troubleshoot_notifications_test_current_push_provider_failure">"No push providers selected."</string>
|
||||||
<string name="troubleshoot_notifications_test_current_push_provider_success">"Current push provider: %1$s."</string>
|
<string name="troubleshoot_notifications_test_current_push_provider_success">"Current push provider: %1$s."</string>
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,11 @@
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.troubleshoot
|
package io.element.android.libraries.push.impl.troubleshoot
|
||||||
|
|
||||||
import app.cash.turbine.test
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import io.element.android.libraries.push.test.FakeGetCurrentPushProvider
|
import io.element.android.libraries.push.test.FakeGetCurrentPushProvider
|
||||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
||||||
|
import io.element.android.libraries.troubleshoot.test.runAndTestState
|
||||||
import io.element.android.services.toolbox.test.strings.FakeStringProvider
|
import io.element.android.services.toolbox.test.strings.FakeStringProvider
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
|
|
@ -23,10 +22,7 @@ class CurrentPushProviderTestTest {
|
||||||
getCurrentPushProvider = FakeGetCurrentPushProvider("foo"),
|
getCurrentPushProvider = FakeGetCurrentPushProvider("foo"),
|
||||||
stringProvider = FakeStringProvider(),
|
stringProvider = FakeStringProvider(),
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
val lastItem = awaitItem()
|
val lastItem = awaitItem()
|
||||||
|
|
@ -41,14 +37,11 @@ class CurrentPushProviderTestTest {
|
||||||
getCurrentPushProvider = FakeGetCurrentPushProvider(null),
|
getCurrentPushProvider = FakeGetCurrentPushProvider(null),
|
||||||
stringProvider = FakeStringProvider(),
|
stringProvider = FakeStringProvider(),
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
val lastItem = awaitItem()
|
val lastItem = awaitItem()
|
||||||
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false))
|
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure())
|
||||||
sut.reset()
|
sut.reset()
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 New Vector Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
|
* Please see LICENSE files in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.push.impl.troubleshoot
|
||||||
|
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import io.element.android.libraries.matrix.test.A_USER_ID
|
||||||
|
import io.element.android.libraries.matrix.test.A_USER_ID_2
|
||||||
|
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||||
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator
|
||||||
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
||||||
|
import io.element.android.libraries.troubleshoot.test.runAndTestState
|
||||||
|
import io.element.android.services.toolbox.test.strings.FakeStringProvider
|
||||||
|
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||||
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class IgnoredUsersTestTest {
|
||||||
|
@Test
|
||||||
|
fun `test IgnoredUsersTest order`() = runTest {
|
||||||
|
val sut = IgnoredUsersTest(
|
||||||
|
matrixClient = FakeMatrixClient(),
|
||||||
|
stringProvider = FakeStringProvider(),
|
||||||
|
)
|
||||||
|
assertThat(sut.order).isEqualTo(80)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test IgnoredUsersTest quick fix`() = runTest {
|
||||||
|
val sut = IgnoredUsersTest(
|
||||||
|
matrixClient = FakeMatrixClient(),
|
||||||
|
stringProvider = FakeStringProvider(),
|
||||||
|
)
|
||||||
|
val openIgnoredUsersResult = lambdaRecorder<Unit> {}
|
||||||
|
val navigator = object : NotificationTroubleshootNavigator {
|
||||||
|
override fun openIgnoredUsers() = openIgnoredUsersResult()
|
||||||
|
}
|
||||||
|
sut.quickFix(
|
||||||
|
coroutineScope = backgroundScope,
|
||||||
|
navigator = navigator,
|
||||||
|
)
|
||||||
|
openIgnoredUsersResult.assertions().isCalledOnce()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test IgnoredUsersTest with no blocked users`() = runTest {
|
||||||
|
val sut = IgnoredUsersTest(
|
||||||
|
matrixClient = FakeMatrixClient(
|
||||||
|
ignoredUsersFlow = MutableStateFlow(persistentListOf())
|
||||||
|
),
|
||||||
|
stringProvider = FakeStringProvider(),
|
||||||
|
)
|
||||||
|
sut.runAndTestState {
|
||||||
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||||
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
|
val lastItem = awaitItem()
|
||||||
|
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Success)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test IgnoredUsersTest with blocked users`() = runTest {
|
||||||
|
val sut = IgnoredUsersTest(
|
||||||
|
matrixClient = FakeMatrixClient(
|
||||||
|
ignoredUsersFlow = MutableStateFlow(persistentListOf(A_USER_ID, A_USER_ID_2))
|
||||||
|
),
|
||||||
|
stringProvider = FakeStringProvider(),
|
||||||
|
)
|
||||||
|
sut.runAndTestState {
|
||||||
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||||
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
|
val lastItem = awaitItem()
|
||||||
|
val lastStatus = lastItem.status as NotificationTroubleshootTestState.Status.Failure
|
||||||
|
assertThat(lastStatus.hasQuickFix).isTrue()
|
||||||
|
assertThat(lastStatus.isCritical).isFalse()
|
||||||
|
assertThat(lastStatus.quickFixButtonString).isNotNull()
|
||||||
|
assertThat(lastItem.description).contains("2")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,14 +7,13 @@
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.troubleshoot
|
package io.element.android.libraries.push.impl.troubleshoot
|
||||||
|
|
||||||
import app.cash.turbine.test
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationCreator
|
import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationCreator
|
||||||
import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationDisplayer
|
import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationDisplayer
|
||||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
||||||
|
import io.element.android.libraries.troubleshoot.test.runAndTestState
|
||||||
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.lambdaRecorder
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
|
|
@ -31,10 +30,7 @@ class NotificationTestTest {
|
||||||
fun `test NotificationTest notification cannot be displayed`() = runTest {
|
fun `test NotificationTest notification cannot be displayed`() = runTest {
|
||||||
fakeNotificationDisplayer.displayDiagnosticNotificationResult = lambdaRecorder { _ -> false }
|
fakeNotificationDisplayer.displayDiagnosticNotificationResult = lambdaRecorder { _ -> false }
|
||||||
val sut = createNotificationTest()
|
val sut = createNotificationTest()
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
assertThat(awaitItem().status).isInstanceOf(NotificationTroubleshootTestState.Status.Failure::class.java)
|
assertThat(awaitItem().status).isInstanceOf(NotificationTroubleshootTestState.Status.Failure::class.java)
|
||||||
|
|
@ -44,10 +40,7 @@ class NotificationTestTest {
|
||||||
@Test
|
@Test
|
||||||
fun `test NotificationTest user does not click on notification`() = runTest {
|
fun `test NotificationTest user does not click on notification`() = runTest {
|
||||||
val sut = createNotificationTest()
|
val sut = createNotificationTest()
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.WaitingForUser)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.WaitingForUser)
|
||||||
|
|
@ -60,10 +53,7 @@ class NotificationTestTest {
|
||||||
@Test
|
@Test
|
||||||
fun `test NotificationTest user clicks on notification`() = runTest {
|
fun `test NotificationTest user clicks on notification`() = runTest {
|
||||||
val sut = createNotificationTest()
|
val sut = createNotificationTest()
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.WaitingForUser)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.WaitingForUser)
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.troubleshoot
|
package io.element.android.libraries.push.impl.troubleshoot
|
||||||
|
|
||||||
import app.cash.turbine.test
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||||
import io.element.android.libraries.matrix.test.A_FAILURE_REASON
|
import io.element.android.libraries.matrix.test.A_FAILURE_REASON
|
||||||
|
|
@ -15,10 +14,11 @@ import io.element.android.libraries.push.api.gateway.PushGatewayFailure
|
||||||
import io.element.android.libraries.push.test.FakePushService
|
import io.element.android.libraries.push.test.FakePushService
|
||||||
import io.element.android.libraries.pushproviders.test.FakePushProvider
|
import io.element.android.libraries.pushproviders.test.FakePushProvider
|
||||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
||||||
|
import io.element.android.libraries.troubleshoot.test.FakeNotificationTroubleshootNavigator
|
||||||
|
import io.element.android.libraries.troubleshoot.test.runAndTestState
|
||||||
import io.element.android.services.toolbox.test.strings.FakeStringProvider
|
import io.element.android.services.toolbox.test.strings.FakeStringProvider
|
||||||
import io.element.android.services.toolbox.test.systemclock.FakeSystemClock
|
import io.element.android.services.toolbox.test.systemclock.FakeSystemClock
|
||||||
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
|
|
@ -32,14 +32,11 @@ class PushLoopbackTestTest {
|
||||||
clock = FakeSystemClock(),
|
clock = FakeSystemClock(),
|
||||||
stringProvider = FakeStringProvider(),
|
stringProvider = FakeStringProvider(),
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
val lastItem = awaitItem()
|
val lastItem = awaitItem()
|
||||||
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false))
|
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -56,14 +53,11 @@ class PushLoopbackTestTest {
|
||||||
clock = FakeSystemClock(),
|
clock = FakeSystemClock(),
|
||||||
stringProvider = FakeStringProvider(),
|
stringProvider = FakeStringProvider(),
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
val lastItem = awaitItem()
|
val lastItem = awaitItem()
|
||||||
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false))
|
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure())
|
||||||
sut.reset()
|
sut.reset()
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||||
}
|
}
|
||||||
|
|
@ -89,17 +83,14 @@ class PushLoopbackTestTest {
|
||||||
clock = FakeSystemClock(),
|
clock = FakeSystemClock(),
|
||||||
stringProvider = FakeStringProvider(),
|
stringProvider = FakeStringProvider(),
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
val lastItem = awaitItem()
|
val lastItem = awaitItem()
|
||||||
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true))
|
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(hasQuickFix = true))
|
||||||
sut.quickFix(this)
|
sut.quickFix(this, FakeNotificationTroubleshootNavigator())
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(hasQuickFix = true))
|
||||||
rotateTokenLambda.assertions().isCalledOnce()
|
rotateTokenLambda.assertions().isCalledOnce()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -115,14 +106,11 @@ class PushLoopbackTestTest {
|
||||||
clock = FakeSystemClock(),
|
clock = FakeSystemClock(),
|
||||||
stringProvider = FakeStringProvider(),
|
stringProvider = FakeStringProvider(),
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
val lastItem = awaitItem()
|
val lastItem = awaitItem()
|
||||||
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false))
|
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -139,14 +127,11 @@ class PushLoopbackTestTest {
|
||||||
clock = FakeSystemClock(),
|
clock = FakeSystemClock(),
|
||||||
stringProvider = FakeStringProvider(),
|
stringProvider = FakeStringProvider(),
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
val lastItem = awaitItem()
|
val lastItem = awaitItem()
|
||||||
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false))
|
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure())
|
||||||
assertThat(lastItem.description).contains(A_FAILURE_REASON)
|
assertThat(lastItem.description).contains(A_FAILURE_REASON)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -163,10 +148,7 @@ class PushLoopbackTestTest {
|
||||||
clock = FakeSystemClock(),
|
clock = FakeSystemClock(),
|
||||||
stringProvider = FakeStringProvider(),
|
stringProvider = FakeStringProvider(),
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
val lastItem = awaitItem()
|
val lastItem = awaitItem()
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,11 @@
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.troubleshoot
|
package io.element.android.libraries.push.impl.troubleshoot
|
||||||
|
|
||||||
import app.cash.turbine.test
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import io.element.android.libraries.pushproviders.test.FakePushProvider
|
import io.element.android.libraries.pushproviders.test.FakePushProvider
|
||||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
||||||
|
import io.element.android.libraries.troubleshoot.test.runAndTestState
|
||||||
import io.element.android.services.toolbox.test.strings.FakeStringProvider
|
import io.element.android.services.toolbox.test.strings.FakeStringProvider
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
|
|
@ -23,14 +22,11 @@ class PushProvidersTestTest {
|
||||||
pushProviders = emptySet(),
|
pushProviders = emptySet(),
|
||||||
stringProvider = FakeStringProvider(),
|
stringProvider = FakeStringProvider(),
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
val lastItem = awaitItem()
|
val lastItem = awaitItem()
|
||||||
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false))
|
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure())
|
||||||
sut.reset()
|
sut.reset()
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||||
}
|
}
|
||||||
|
|
@ -45,10 +41,7 @@ class PushProvidersTestTest {
|
||||||
),
|
),
|
||||||
stringProvider = FakeStringProvider(),
|
stringProvider = FakeStringProvider(),
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
val lastItem = awaitItem()
|
val lastItem = awaitItem()
|
||||||
|
|
|
||||||
|
|
@ -76,5 +76,6 @@ dependencies {
|
||||||
testImplementation(projects.libraries.push.test)
|
testImplementation(projects.libraries.push.test)
|
||||||
testImplementation(projects.libraries.pushstore.test)
|
testImplementation(projects.libraries.pushstore.test)
|
||||||
testImplementation(projects.libraries.sessionStorage.test)
|
testImplementation(projects.libraries.sessionStorage.test)
|
||||||
|
testImplementation(projects.libraries.troubleshoot.test)
|
||||||
testImplementation(projects.services.toolbox.test)
|
testImplementation(projects.services.toolbox.test)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ class FirebaseAvailabilityTest(
|
||||||
} else {
|
} else {
|
||||||
delegate.updateState(
|
delegate.updateState(
|
||||||
description = stringProvider.getString(R.string.troubleshoot_notifications_test_firebase_availability_failure),
|
description = stringProvider.getString(R.string.troubleshoot_notifications_test_firebase_availability_failure),
|
||||||
status = NotificationTroubleshootTestState.Status.Failure(false)
|
status = NotificationTroubleshootTestState.Status.Failure()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import io.element.android.libraries.pushproviders.firebase.FirebaseConfig
|
||||||
import io.element.android.libraries.pushproviders.firebase.FirebaseStore
|
import io.element.android.libraries.pushproviders.firebase.FirebaseStore
|
||||||
import io.element.android.libraries.pushproviders.firebase.FirebaseTroubleshooter
|
import io.element.android.libraries.pushproviders.firebase.FirebaseTroubleshooter
|
||||||
import io.element.android.libraries.pushproviders.firebase.R
|
import io.element.android.libraries.pushproviders.firebase.R
|
||||||
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator
|
||||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTest
|
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.NotificationTroubleshootTestDelegate
|
||||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
||||||
|
|
@ -62,7 +63,7 @@ class FirebaseTokenTest(
|
||||||
} else {
|
} else {
|
||||||
delegate.updateState(
|
delegate.updateState(
|
||||||
description = stringProvider.getString(R.string.troubleshoot_notifications_test_firebase_token_failure),
|
description = stringProvider.getString(R.string.troubleshoot_notifications_test_firebase_token_failure),
|
||||||
status = NotificationTroubleshootTestState.Status.Failure(true)
|
status = NotificationTroubleshootTestState.Status.Failure(hasQuickFix = true)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -71,7 +72,10 @@ class FirebaseTokenTest(
|
||||||
|
|
||||||
override suspend fun reset() = delegate.reset()
|
override suspend fun reset() = delegate.reset()
|
||||||
|
|
||||||
override suspend fun quickFix(coroutineScope: CoroutineScope) {
|
override suspend fun quickFix(
|
||||||
|
coroutineScope: CoroutineScope,
|
||||||
|
navigator: NotificationTroubleshootNavigator,
|
||||||
|
) {
|
||||||
delegate.start()
|
delegate.start()
|
||||||
firebaseTroubleshooter.troubleshoot()
|
firebaseTroubleshooter.troubleshoot()
|
||||||
run(coroutineScope)
|
run(coroutineScope)
|
||||||
|
|
|
||||||
|
|
@ -7,14 +7,13 @@
|
||||||
|
|
||||||
package io.element.android.libraries.pushproviders.firebase.troubleshoot
|
package io.element.android.libraries.pushproviders.firebase.troubleshoot
|
||||||
|
|
||||||
import app.cash.turbine.test
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import io.element.android.libraries.pushproviders.firebase.FakeIsPlayServiceAvailable
|
import io.element.android.libraries.pushproviders.firebase.FakeIsPlayServiceAvailable
|
||||||
import io.element.android.libraries.pushproviders.firebase.FirebaseConfig
|
import io.element.android.libraries.pushproviders.firebase.FirebaseConfig
|
||||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
||||||
import io.element.android.libraries.troubleshoot.api.test.TestFilterData
|
import io.element.android.libraries.troubleshoot.api.test.TestFilterData
|
||||||
|
import io.element.android.libraries.troubleshoot.test.runAndTestState
|
||||||
import io.element.android.services.toolbox.test.strings.FakeStringProvider
|
import io.element.android.services.toolbox.test.strings.FakeStringProvider
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
|
|
@ -25,10 +24,7 @@ class FirebaseAvailabilityTestTest {
|
||||||
isPlayServiceAvailable = FakeIsPlayServiceAvailable(true),
|
isPlayServiceAvailable = FakeIsPlayServiceAvailable(true),
|
||||||
stringProvider = FakeStringProvider(),
|
stringProvider = FakeStringProvider(),
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
val lastItem = awaitItem()
|
val lastItem = awaitItem()
|
||||||
|
|
@ -42,14 +38,11 @@ class FirebaseAvailabilityTestTest {
|
||||||
isPlayServiceAvailable = FakeIsPlayServiceAvailable(false),
|
isPlayServiceAvailable = FakeIsPlayServiceAvailable(false),
|
||||||
stringProvider = FakeStringProvider(),
|
stringProvider = FakeStringProvider(),
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
val lastItem = awaitItem()
|
val lastItem = awaitItem()
|
||||||
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false))
|
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure())
|
||||||
sut.reset()
|
sut.reset()
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,15 @@
|
||||||
|
|
||||||
package io.element.android.libraries.pushproviders.firebase.troubleshoot
|
package io.element.android.libraries.pushproviders.firebase.troubleshoot
|
||||||
|
|
||||||
import app.cash.turbine.test
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import io.element.android.libraries.pushproviders.firebase.FakeFirebaseTroubleshooter
|
import io.element.android.libraries.pushproviders.firebase.FakeFirebaseTroubleshooter
|
||||||
import io.element.android.libraries.pushproviders.firebase.FirebaseConfig
|
import io.element.android.libraries.pushproviders.firebase.FirebaseConfig
|
||||||
import io.element.android.libraries.pushproviders.firebase.InMemoryFirebaseStore
|
import io.element.android.libraries.pushproviders.firebase.InMemoryFirebaseStore
|
||||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
||||||
import io.element.android.libraries.troubleshoot.api.test.TestFilterData
|
import io.element.android.libraries.troubleshoot.api.test.TestFilterData
|
||||||
|
import io.element.android.libraries.troubleshoot.test.FakeNotificationTroubleshootNavigator
|
||||||
|
import io.element.android.libraries.troubleshoot.test.runAndTestState
|
||||||
import io.element.android.services.toolbox.test.strings.FakeStringProvider
|
import io.element.android.services.toolbox.test.strings.FakeStringProvider
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
|
|
@ -27,10 +27,7 @@ class FirebaseTokenTestTest {
|
||||||
firebaseTroubleshooter = FakeFirebaseTroubleshooter(),
|
firebaseTroubleshooter = FakeFirebaseTroubleshooter(),
|
||||||
stringProvider = FakeStringProvider(),
|
stringProvider = FakeStringProvider(),
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
val lastItem = awaitItem()
|
val lastItem = awaitItem()
|
||||||
|
|
@ -53,16 +50,13 @@ class FirebaseTokenTestTest {
|
||||||
),
|
),
|
||||||
stringProvider = FakeStringProvider(),
|
stringProvider = FakeStringProvider(),
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
val lastItem = awaitItem()
|
val lastItem = awaitItem()
|
||||||
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true))
|
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(hasQuickFix = true))
|
||||||
// Quick fix
|
// Quick fix
|
||||||
sut.quickFix(this)
|
sut.quickFix(this, FakeNotificationTroubleshootNavigator())
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Success)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Success)
|
||||||
}
|
}
|
||||||
|
|
@ -81,13 +75,10 @@ class FirebaseTokenTestTest {
|
||||||
),
|
),
|
||||||
stringProvider = FakeStringProvider(),
|
stringProvider = FakeStringProvider(),
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(hasQuickFix = true))
|
||||||
sut.reset()
|
sut.reset()
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ dependencies {
|
||||||
testImplementation(projects.libraries.push.test)
|
testImplementation(projects.libraries.push.test)
|
||||||
testImplementation(projects.libraries.pushproviders.test)
|
testImplementation(projects.libraries.pushproviders.test)
|
||||||
testImplementation(projects.libraries.pushstore.test)
|
testImplementation(projects.libraries.pushstore.test)
|
||||||
|
testImplementation(projects.libraries.troubleshoot.test)
|
||||||
testImplementation(projects.services.toolbox.test)
|
testImplementation(projects.services.toolbox.test)
|
||||||
testImplementation(projects.services.appnavstate.test)
|
testImplementation(projects.services.appnavstate.test)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ class UnifiedPushMatrixGatewayTest(
|
||||||
if (config == null) {
|
if (config == null) {
|
||||||
delegate.updateState(
|
delegate.updateState(
|
||||||
description = "No current push provider",
|
description = "No current push provider",
|
||||||
status = NotificationTroubleshootTestState.Status.Failure(false)
|
status = NotificationTroubleshootTestState.Status.Failure()
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
val gatewayBaseUrl = config.url.removeSuffix("/_matrix/push/v1/notify")
|
val gatewayBaseUrl = config.url.removeSuffix("/_matrix/push/v1/notify")
|
||||||
|
|
@ -65,13 +65,13 @@ class UnifiedPushMatrixGatewayTest(
|
||||||
} else {
|
} else {
|
||||||
delegate.updateState(
|
delegate.updateState(
|
||||||
description = "${config.url} is not a Matrix gateway.",
|
description = "${config.url} is not a Matrix gateway.",
|
||||||
status = NotificationTroubleshootTestState.Status.Failure(false)
|
status = NotificationTroubleshootTestState.Status.Failure()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} catch (throwable: Throwable) {
|
} catch (throwable: Throwable) {
|
||||||
delegate.updateState(
|
delegate.updateState(
|
||||||
description = "Fail to check the gateway ${config.url}: ${throwable.localizedMessage}",
|
description = "Fail to check the gateway ${config.url}: ${throwable.localizedMessage}",
|
||||||
status = NotificationTroubleshootTestState.Status.Failure(false)
|
status = NotificationTroubleshootTestState.Status.Failure()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import dev.zacsweers.metro.Inject
|
||||||
import io.element.android.libraries.pushproviders.unifiedpush.R
|
import io.element.android.libraries.pushproviders.unifiedpush.R
|
||||||
import io.element.android.libraries.pushproviders.unifiedpush.UnifiedPushConfig
|
import io.element.android.libraries.pushproviders.unifiedpush.UnifiedPushConfig
|
||||||
import io.element.android.libraries.pushproviders.unifiedpush.UnifiedPushDistributorProvider
|
import io.element.android.libraries.pushproviders.unifiedpush.UnifiedPushDistributorProvider
|
||||||
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator
|
||||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTest
|
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.NotificationTroubleshootTestDelegate
|
||||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
||||||
|
|
@ -57,14 +58,17 @@ class UnifiedPushTest(
|
||||||
} else {
|
} else {
|
||||||
delegate.updateState(
|
delegate.updateState(
|
||||||
description = stringProvider.getString(R.string.troubleshoot_notifications_test_unified_push_failure),
|
description = stringProvider.getString(R.string.troubleshoot_notifications_test_unified_push_failure),
|
||||||
status = NotificationTroubleshootTestState.Status.Failure(true)
|
status = NotificationTroubleshootTestState.Status.Failure(hasQuickFix = true)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun reset() = delegate.reset()
|
override suspend fun reset() = delegate.reset()
|
||||||
|
|
||||||
override suspend fun quickFix(coroutineScope: CoroutineScope) {
|
override suspend fun quickFix(
|
||||||
|
coroutineScope: CoroutineScope,
|
||||||
|
navigator: NotificationTroubleshootNavigator,
|
||||||
|
) {
|
||||||
openDistributorWebPageAction.execute()
|
openDistributorWebPageAction.execute()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
|
|
||||||
package io.element.android.libraries.pushproviders.unifiedpush.troubleshoot
|
package io.element.android.libraries.pushproviders.unifiedpush.troubleshoot
|
||||||
|
|
||||||
import app.cash.turbine.test
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import io.element.android.libraries.pushproviders.api.CurrentUserPushConfig
|
import io.element.android.libraries.pushproviders.api.CurrentUserPushConfig
|
||||||
import io.element.android.libraries.pushproviders.test.aCurrentUserPushConfig
|
import io.element.android.libraries.pushproviders.test.aCurrentUserPushConfig
|
||||||
|
|
@ -18,8 +17,8 @@ import io.element.android.libraries.pushproviders.unifiedpush.matrixDiscoveryRes
|
||||||
import io.element.android.libraries.pushproviders.unifiedpush.network.DiscoveryResponse
|
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.NotificationTroubleshootTestState
|
||||||
import io.element.android.libraries.troubleshoot.api.test.TestFilterData
|
import io.element.android.libraries.troubleshoot.api.test.TestFilterData
|
||||||
|
import io.element.android.libraries.troubleshoot.test.runAndTestState
|
||||||
import io.element.android.tests.testutils.testCoroutineDispatchers
|
import io.element.android.tests.testutils.testCoroutineDispatchers
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.test.TestScope
|
import kotlinx.coroutines.test.TestScope
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
@ -31,10 +30,7 @@ class UnifiedPushMatrixGatewayTestTest {
|
||||||
currentUserPushConfig = aCurrentUserPushConfig(),
|
currentUserPushConfig = aCurrentUserPushConfig(),
|
||||||
discoveryResponse = matrixDiscoveryResponse,
|
discoveryResponse = matrixDiscoveryResponse,
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
val lastItem = awaitItem()
|
val lastItem = awaitItem()
|
||||||
|
|
@ -48,14 +44,11 @@ class UnifiedPushMatrixGatewayTestTest {
|
||||||
currentUserPushConfig = null,
|
currentUserPushConfig = null,
|
||||||
discoveryResponse = matrixDiscoveryResponse,
|
discoveryResponse = matrixDiscoveryResponse,
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
val lastItem = awaitItem()
|
val lastItem = awaitItem()
|
||||||
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false))
|
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -65,14 +58,11 @@ class UnifiedPushMatrixGatewayTestTest {
|
||||||
currentUserPushConfig = aCurrentUserPushConfig(),
|
currentUserPushConfig = aCurrentUserPushConfig(),
|
||||||
discoveryResponse = invalidDiscoveryResponse,
|
discoveryResponse = invalidDiscoveryResponse,
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
val lastItem = awaitItem()
|
val lastItem = awaitItem()
|
||||||
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false))
|
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure())
|
||||||
// Reset the error
|
// Reset the error
|
||||||
sut.reset()
|
sut.reset()
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||||
|
|
@ -85,14 +75,11 @@ class UnifiedPushMatrixGatewayTestTest {
|
||||||
currentUserPushConfig = aCurrentUserPushConfig(),
|
currentUserPushConfig = aCurrentUserPushConfig(),
|
||||||
discoveryResponse = { error("Network error") },
|
discoveryResponse = { error("Network error") },
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
val lastItem = awaitItem()
|
val lastItem = awaitItem()
|
||||||
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(false))
|
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,13 @@
|
||||||
|
|
||||||
package io.element.android.libraries.pushproviders.unifiedpush.troubleshoot
|
package io.element.android.libraries.pushproviders.unifiedpush.troubleshoot
|
||||||
|
|
||||||
import app.cash.turbine.test
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import io.element.android.libraries.pushproviders.api.Distributor
|
import io.element.android.libraries.pushproviders.api.Distributor
|
||||||
import io.element.android.libraries.pushproviders.unifiedpush.UnifiedPushConfig
|
import io.element.android.libraries.pushproviders.unifiedpush.UnifiedPushConfig
|
||||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
||||||
import io.element.android.libraries.troubleshoot.api.test.TestFilterData
|
import io.element.android.libraries.troubleshoot.api.test.TestFilterData
|
||||||
|
import io.element.android.libraries.troubleshoot.test.FakeNotificationTroubleshootNavigator
|
||||||
|
import io.element.android.libraries.troubleshoot.test.runAndTestState
|
||||||
import io.element.android.services.toolbox.test.strings.FakeStringProvider
|
import io.element.android.services.toolbox.test.strings.FakeStringProvider
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
|
|
@ -30,10 +31,7 @@ class UnifiedPushTestTest {
|
||||||
openDistributorWebPageAction = FakeOpenDistributorWebPageAction(),
|
openDistributorWebPageAction = FakeOpenDistributorWebPageAction(),
|
||||||
stringProvider = FakeStringProvider(),
|
stringProvider = FakeStringProvider(),
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
val lastItem = awaitItem()
|
val lastItem = awaitItem()
|
||||||
|
|
@ -57,17 +55,14 @@ class UnifiedPushTestTest {
|
||||||
),
|
),
|
||||||
stringProvider = FakeStringProvider(),
|
stringProvider = FakeStringProvider(),
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
val lastItem = awaitItem()
|
val lastItem = awaitItem()
|
||||||
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true))
|
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(hasQuickFix = true))
|
||||||
// Quick fix
|
// Quick fix
|
||||||
launch {
|
backgroundScope.launch {
|
||||||
sut.quickFix(this)
|
sut.quickFix(this, FakeNotificationTroubleshootNavigator())
|
||||||
sut.run(this)
|
sut.run(this)
|
||||||
}
|
}
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
|
|
@ -91,14 +86,11 @@ class UnifiedPushTestTest {
|
||||||
),
|
),
|
||||||
stringProvider = FakeStringProvider(),
|
stringProvider = FakeStringProvider(),
|
||||||
)
|
)
|
||||||
launch {
|
sut.runAndTestState {
|
||||||
sut.run(this)
|
|
||||||
}
|
|
||||||
sut.state.test {
|
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
val lastItem = awaitItem()
|
val lastItem = awaitItem()
|
||||||
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true))
|
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(hasQuickFix = true))
|
||||||
sut.reset()
|
sut.reset()
|
||||||
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(false))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,5 +22,6 @@ interface NotificationTroubleShootEntryPoint : FeatureEntryPoint {
|
||||||
|
|
||||||
interface Callback : Plugin {
|
interface Callback : Plugin {
|
||||||
fun onDone()
|
fun onDone()
|
||||||
|
fun openIgnoredUsers()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 New Vector Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
|
* Please see LICENSE files in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.troubleshoot.api.test
|
||||||
|
|
||||||
|
interface NotificationTroubleshootNavigator {
|
||||||
|
fun openIgnoredUsers()
|
||||||
|
}
|
||||||
|
|
@ -16,7 +16,10 @@ interface NotificationTroubleshootTest {
|
||||||
fun isRelevant(data: TestFilterData): Boolean = true
|
fun isRelevant(data: TestFilterData): Boolean = true
|
||||||
suspend fun run(coroutineScope: CoroutineScope)
|
suspend fun run(coroutineScope: CoroutineScope)
|
||||||
suspend fun reset()
|
suspend fun reset()
|
||||||
suspend fun quickFix(coroutineScope: CoroutineScope) {
|
suspend fun quickFix(
|
||||||
|
coroutineScope: CoroutineScope,
|
||||||
|
navigator: NotificationTroubleshootNavigator,
|
||||||
|
) {
|
||||||
error("Quick fix not implemented, you need to override this method in your test")
|
error("Quick fix not implemented, you need to override this method in your test")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ class NotificationTroubleshootTestDelegate(
|
||||||
if (isSuccess) {
|
if (isSuccess) {
|
||||||
NotificationTroubleshootTestState.Status.Success
|
NotificationTroubleshootTestState.Status.Success
|
||||||
} else {
|
} else {
|
||||||
NotificationTroubleshootTestState.Status.Failure(hasQuickFix)
|
NotificationTroubleshootTestState.Status.Failure(hasQuickFix = hasQuickFix)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,10 @@ data class NotificationTroubleshootTestState(
|
||||||
data object InProgress : Status
|
data object InProgress : Status
|
||||||
data object WaitingForUser : Status
|
data object WaitingForUser : Status
|
||||||
data object Success : Status
|
data object Success : Status
|
||||||
data class Failure(val hasQuickFix: Boolean) : Status
|
data class Failure(
|
||||||
|
val hasQuickFix: Boolean = false,
|
||||||
|
val isCritical: Boolean = true,
|
||||||
|
val quickFixButtonString: String? = null,
|
||||||
|
) : Status
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import im.vector.app.features.analytics.plan.MobileScreen
|
||||||
import io.element.android.annotations.ContributesNode
|
import io.element.android.annotations.ContributesNode
|
||||||
import io.element.android.libraries.di.SessionScope
|
import io.element.android.libraries.di.SessionScope
|
||||||
import io.element.android.libraries.troubleshoot.api.NotificationTroubleShootEntryPoint
|
import io.element.android.libraries.troubleshoot.api.NotificationTroubleShootEntryPoint
|
||||||
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator
|
||||||
import io.element.android.services.analytics.api.ScreenTracker
|
import io.element.android.services.analytics.api.ScreenTracker
|
||||||
|
|
||||||
@ContributesNode(SessionScope::class)
|
@ContributesNode(SessionScope::class)
|
||||||
|
|
@ -26,15 +27,26 @@ import io.element.android.services.analytics.api.ScreenTracker
|
||||||
class TroubleshootNotificationsNode(
|
class TroubleshootNotificationsNode(
|
||||||
@Assisted buildContext: BuildContext,
|
@Assisted buildContext: BuildContext,
|
||||||
@Assisted plugins: List<Plugin>,
|
@Assisted plugins: List<Plugin>,
|
||||||
private val presenter: TroubleshootNotificationsPresenter,
|
|
||||||
private val screenTracker: ScreenTracker,
|
private val screenTracker: ScreenTracker,
|
||||||
) : Node(buildContext, plugins = plugins) {
|
factory: TroubleshootNotificationsPresenter.Factory,
|
||||||
|
) : Node(buildContext, plugins = plugins),
|
||||||
|
NotificationTroubleshootNavigator {
|
||||||
|
private val presenter = factory.create(
|
||||||
|
navigator = this,
|
||||||
|
)
|
||||||
|
|
||||||
private fun onDone() {
|
private fun onDone() {
|
||||||
plugins<NotificationTroubleShootEntryPoint.Callback>().forEach {
|
plugins<NotificationTroubleShootEntryPoint.Callback>().forEach {
|
||||||
it.onDone()
|
it.onDone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun openIgnoredUsers() {
|
||||||
|
plugins<NotificationTroubleShootEntryPoint.Callback>().forEach {
|
||||||
|
it.openIgnoredUsers()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun View(modifier: Modifier) {
|
override fun View(modifier: Modifier) {
|
||||||
screenTracker.TrackScreen(MobileScreen.ScreenName.NotificationTroubleshoot)
|
screenTracker.TrackScreen(MobileScreen.ScreenName.NotificationTroubleshoot)
|
||||||
|
|
|
||||||
|
|
@ -12,14 +12,23 @@ import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import dev.zacsweers.metro.Assisted
|
||||||
|
import dev.zacsweers.metro.AssistedFactory
|
||||||
import dev.zacsweers.metro.Inject
|
import dev.zacsweers.metro.Inject
|
||||||
import io.element.android.libraries.architecture.Presenter
|
import io.element.android.libraries.architecture.Presenter
|
||||||
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
class TroubleshootNotificationsPresenter(
|
class TroubleshootNotificationsPresenter(
|
||||||
|
@Assisted private val navigator: NotificationTroubleshootNavigator,
|
||||||
private val troubleshootTestSuite: TroubleshootTestSuite,
|
private val troubleshootTestSuite: TroubleshootTestSuite,
|
||||||
) : Presenter<TroubleshootNotificationsState> {
|
) : Presenter<TroubleshootNotificationsState> {
|
||||||
|
@AssistedFactory
|
||||||
|
fun interface Factory {
|
||||||
|
fun create(navigator: NotificationTroubleshootNavigator): TroubleshootNotificationsPresenter
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun present(): TroubleshootNotificationsState {
|
override fun present(): TroubleshootNotificationsState {
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
|
@ -34,7 +43,11 @@ class TroubleshootNotificationsPresenter(
|
||||||
troubleshootTestSuite.runTestSuite(this)
|
troubleshootTestSuite.runTestSuite(this)
|
||||||
}
|
}
|
||||||
is TroubleshootNotificationsEvents.QuickFix -> coroutineScope.launch {
|
is TroubleshootNotificationsEvents.QuickFix -> coroutineScope.launch {
|
||||||
troubleshootTestSuite.quickFix(event.testIndex, this)
|
troubleshootTestSuite.quickFix(
|
||||||
|
testIndex = event.testIndex,
|
||||||
|
coroutineScope = this,
|
||||||
|
navigator = navigator,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
TroubleshootNotificationsEvents.RetryFailedTests -> coroutineScope.launch {
|
TroubleshootNotificationsEvents.RetryFailedTests -> coroutineScope.launch {
|
||||||
troubleshootTestSuite.retryFailedTest(this)
|
troubleshootTestSuite.retryFailedTest(this)
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,12 @@ open class TroubleshootNotificationsStateProvider : PreviewParameterProvider<Tro
|
||||||
aTroubleshootNotificationsState(
|
aTroubleshootNotificationsState(
|
||||||
listOf(
|
listOf(
|
||||||
aTroubleshootTestStateSuccess(),
|
aTroubleshootTestStateSuccess(),
|
||||||
|
aTroubleshootTestStateFailure(
|
||||||
|
isCritical = false,
|
||||||
|
hasQuickFix = true,
|
||||||
|
quickFixButtonString = "Custom quick fix",
|
||||||
|
),
|
||||||
aTroubleshootTestStateInProgress(),
|
aTroubleshootTestStateInProgress(),
|
||||||
aTroubleshootTestStateIdle(),
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
aTroubleshootNotificationsState(
|
aTroubleshootNotificationsState(
|
||||||
|
|
@ -106,5 +110,14 @@ fun aTroubleshootTestStateWaitingForUser() =
|
||||||
fun aTroubleshootTestStateSuccess() =
|
fun aTroubleshootTestStateSuccess() =
|
||||||
aTroubleshootTestState(status = NotificationTroubleshootTestState.Status.Success)
|
aTroubleshootTestState(status = NotificationTroubleshootTestState.Status.Success)
|
||||||
|
|
||||||
fun aTroubleshootTestStateFailure(hasQuickFix: Boolean) =
|
fun aTroubleshootTestStateFailure(
|
||||||
aTroubleshootTestState(status = NotificationTroubleshootTestState.Status.Failure(hasQuickFix = hasQuickFix))
|
hasQuickFix: Boolean = false,
|
||||||
|
isCritical: Boolean = true,
|
||||||
|
quickFixButtonString: String? = null,
|
||||||
|
) = aTroubleshootTestState(
|
||||||
|
status = NotificationTroubleshootTestState.Status.Failure(
|
||||||
|
hasQuickFix = hasQuickFix,
|
||||||
|
isCritical = isCritical,
|
||||||
|
quickFixButtonString = quickFixButtonString,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -64,11 +64,12 @@ private fun ColumnScope.TroubleshootTestView(
|
||||||
testState: NotificationTroubleshootTestState,
|
testState: NotificationTroubleshootTestState,
|
||||||
onQuickFixClick: () -> Unit,
|
onQuickFixClick: () -> Unit,
|
||||||
) {
|
) {
|
||||||
if ((testState.status as? Status.Idle)?.visible == false) return
|
val status = testState.status
|
||||||
|
if ((status as? Status.Idle)?.visible == false) return
|
||||||
ListItem(
|
ListItem(
|
||||||
headlineContent = { Text(text = testState.name) },
|
headlineContent = { Text(text = testState.name) },
|
||||||
supportingContent = { Text(text = testState.description) },
|
supportingContent = { Text(text = testState.description) },
|
||||||
trailingContent = when (testState.status) {
|
trailingContent = when (status) {
|
||||||
is Status.Idle -> null
|
is Status.Idle -> null
|
||||||
Status.InProgress -> ListItemContent.Custom {
|
Status.InProgress -> ListItemContent.Custom {
|
||||||
CircularProgressIndicator(
|
CircularProgressIndicator(
|
||||||
|
|
@ -98,20 +99,19 @@ private fun ColumnScope.TroubleshootTestView(
|
||||||
Icon(
|
Icon(
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
modifier = Modifier.size(24.dp),
|
modifier = Modifier.size(24.dp),
|
||||||
imageVector = CompoundIcons.ErrorSolid(),
|
imageVector = if (status.isCritical) CompoundIcons.ErrorSolid() else CompoundIcons.Warning(),
|
||||||
tint = ElementTheme.colors.textCriticalPrimary
|
tint = ElementTheme.colors.iconCriticalPrimary,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if ((testState.status as? Status.Failure)?.hasQuickFix == true) {
|
if (status is Status.Failure && status.hasQuickFix) {
|
||||||
ListItem(
|
ListItem(
|
||||||
headlineContent = {
|
headlineContent = { },
|
||||||
},
|
|
||||||
trailingContent = ListItemContent.Custom {
|
trailingContent = ListItemContent.Custom {
|
||||||
Button(
|
Button(
|
||||||
text = stringResource(id = R.string.troubleshoot_notifications_screen_quick_fix_action),
|
text = status.quickFixButtonString ?: stringResource(id = R.string.troubleshoot_notifications_screen_quick_fix_action),
|
||||||
onClick = onQuickFixClick
|
onClick = onQuickFixClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import dev.zacsweers.metro.Inject
|
||||||
import im.vector.app.features.analytics.plan.NotificationTroubleshoot
|
import im.vector.app.features.analytics.plan.NotificationTroubleshoot
|
||||||
import io.element.android.libraries.architecture.AsyncAction
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
import io.element.android.libraries.push.api.GetCurrentPushProvider
|
import io.element.android.libraries.push.api.GetCurrentPushProvider
|
||||||
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator
|
||||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTest
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTest
|
||||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
||||||
import io.element.android.libraries.troubleshoot.api.test.TestFilterData
|
import io.element.android.libraries.troubleshoot.api.test.TestFilterData
|
||||||
|
|
@ -90,8 +91,12 @@ class TroubleshootTestSuite(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun quickFix(testIndex: Int, coroutineScope: CoroutineScope) {
|
suspend fun quickFix(
|
||||||
tests[testIndex].quickFix(coroutineScope)
|
testIndex: Int,
|
||||||
|
coroutineScope: CoroutineScope,
|
||||||
|
navigator: NotificationTroubleshootNavigator,
|
||||||
|
) {
|
||||||
|
tests[testIndex].quickFix(coroutineScope, navigator)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -104,7 +109,7 @@ fun List<NotificationTroubleshootTestState>.computeMainState(): AsyncAction<Unit
|
||||||
else -> {
|
else -> {
|
||||||
if (any { it.status is NotificationTroubleshootTestState.Status.WaitingForUser }) {
|
if (any { it.status is NotificationTroubleshootTestState.Status.WaitingForUser }) {
|
||||||
AsyncAction.ConfirmingNoParams
|
AsyncAction.ConfirmingNoParams
|
||||||
} else if (any { it.status is NotificationTroubleshootTestState.Status.Failure }) {
|
} else if (any { it.status.let { status -> status is NotificationTroubleshootTestState.Status.Failure && status.isCritical } }) {
|
||||||
AsyncAction.Failure(Exception("Some tests failed"))
|
AsyncAction.Failure(Exception("Some tests failed"))
|
||||||
} else {
|
} else {
|
||||||
AsyncAction.Success(Unit)
|
AsyncAction.Success(Unit)
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,13 @@ class DefaultNotificationTroubleShootEntryPointTest {
|
||||||
TroubleshootNotificationsNode(
|
TroubleshootNotificationsNode(
|
||||||
buildContext = buildContext,
|
buildContext = buildContext,
|
||||||
plugins = plugins,
|
plugins = plugins,
|
||||||
presenter = createTroubleshootNotificationsPresenter(),
|
factory = { createTroubleshootNotificationsPresenter() },
|
||||||
screenTracker = FakeScreenTracker(),
|
screenTracker = FakeScreenTracker(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val callback = object : NotificationTroubleShootEntryPoint.Callback {
|
val callback = object : NotificationTroubleShootEntryPoint.Callback {
|
||||||
override fun onDone() = lambdaError()
|
override fun onDone() = lambdaError()
|
||||||
|
override fun openIgnoredUsers() = lambdaError()
|
||||||
}
|
}
|
||||||
val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null))
|
val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null))
|
||||||
.callback(callback)
|
.callback(callback)
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
package io.element.android.libraries.troubleshoot.impl
|
package io.element.android.libraries.troubleshoot.impl
|
||||||
|
|
||||||
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator
|
||||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTest
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTest
|
||||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
|
@ -50,7 +51,10 @@ class FakeNotificationTroubleshootTest(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun quickFix(coroutineScope: CoroutineScope) {
|
override suspend fun quickFix(
|
||||||
|
coroutineScope: CoroutineScope,
|
||||||
|
navigator: NotificationTroubleshootNavigator,
|
||||||
|
) {
|
||||||
updateState(NotificationTroubleshootTestState.Status.InProgress)
|
updateState(NotificationTroubleshootTestState.Status.InProgress)
|
||||||
quickFixAction()?.let {
|
quickFixAction()?.let {
|
||||||
_state.emit(it)
|
_state.emit(it)
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,15 @@
|
||||||
|
|
||||||
package io.element.android.libraries.troubleshoot.impl
|
package io.element.android.libraries.troubleshoot.impl
|
||||||
|
|
||||||
import app.cash.molecule.RecompositionMode
|
|
||||||
import app.cash.molecule.moleculeFlow
|
|
||||||
import app.cash.turbine.test
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import io.element.android.libraries.architecture.AsyncAction
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
import io.element.android.libraries.push.test.FakeGetCurrentPushProvider
|
import io.element.android.libraries.push.test.FakeGetCurrentPushProvider
|
||||||
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator
|
||||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTest
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTest
|
||||||
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
||||||
import io.element.android.services.analytics.test.FakeAnalyticsService
|
import io.element.android.services.analytics.test.FakeAnalyticsService
|
||||||
|
import io.element.android.tests.testutils.lambda.lambdaError
|
||||||
|
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
|
||||||
|
|
||||||
|
|
@ -23,9 +23,7 @@ class TroubleshootNotificationsPresenterTest {
|
||||||
@Test
|
@Test
|
||||||
fun `present - initial state`() = runTest {
|
fun `present - initial state`() = runTest {
|
||||||
val presenter = createTroubleshootNotificationsPresenter()
|
val presenter = createTroubleshootNotificationsPresenter()
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
presenter.test {
|
||||||
presenter.present()
|
|
||||||
}.test {
|
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
assertThat(initialState.testSuiteState.tests).isEmpty()
|
assertThat(initialState.testSuiteState.tests).isEmpty()
|
||||||
assertThat(initialState.testSuiteState.mainState).isEqualTo(AsyncAction.Uninitialized)
|
assertThat(initialState.testSuiteState.mainState).isEqualTo(AsyncAction.Uninitialized)
|
||||||
|
|
@ -40,9 +38,7 @@ class TroubleshootNotificationsPresenterTest {
|
||||||
val presenter = createTroubleshootNotificationsPresenter(
|
val presenter = createTroubleshootNotificationsPresenter(
|
||||||
troubleshootTestSuite = troubleshootTestSuite,
|
troubleshootTestSuite = troubleshootTestSuite,
|
||||||
)
|
)
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
presenter.test {
|
||||||
presenter.present()
|
|
||||||
}.test {
|
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
initialState.eventSink(TroubleshootNotificationsEvents.StartTests)
|
initialState.eventSink(TroubleshootNotificationsEvents.StartTests)
|
||||||
skipItems(1)
|
skipItems(1)
|
||||||
|
|
@ -63,9 +59,7 @@ class TroubleshootNotificationsPresenterTest {
|
||||||
val presenter = createTroubleshootNotificationsPresenter(
|
val presenter = createTroubleshootNotificationsPresenter(
|
||||||
troubleshootTestSuite = troubleshootTestSuite,
|
troubleshootTestSuite = troubleshootTestSuite,
|
||||||
)
|
)
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
presenter.test {
|
||||||
presenter.present()
|
|
||||||
}.test {
|
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
initialState.eventSink(TroubleshootNotificationsEvents.RetryFailedTests)
|
initialState.eventSink(TroubleshootNotificationsEvents.RetryFailedTests)
|
||||||
skipItems(1)
|
skipItems(1)
|
||||||
|
|
@ -74,6 +68,80 @@ class TroubleshootNotificationsPresenterTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `present - critical failed test`() {
|
||||||
|
`present - check main state`(
|
||||||
|
tests = setOf(
|
||||||
|
FakeNotificationTroubleshootTest(
|
||||||
|
firstStatus = NotificationTroubleshootTestState.Status.Failure(isCritical = true)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
expectedIsCritical = true,
|
||||||
|
expectedMainState = AsyncAction.Failure::class.java,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `present - success and critical failed test`() {
|
||||||
|
`present - check main state`(
|
||||||
|
tests = setOf(
|
||||||
|
FakeNotificationTroubleshootTest(
|
||||||
|
firstStatus = NotificationTroubleshootTestState.Status.Success
|
||||||
|
),
|
||||||
|
FakeNotificationTroubleshootTest(
|
||||||
|
firstStatus = NotificationTroubleshootTestState.Status.Failure(isCritical = true)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
expectedIsCritical = true,
|
||||||
|
expectedMainState = AsyncAction.Failure::class.java,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `present - non critical failed test`() {
|
||||||
|
`present - check main state`(
|
||||||
|
tests = setOf(
|
||||||
|
FakeNotificationTroubleshootTest(
|
||||||
|
firstStatus = NotificationTroubleshootTestState.Status.Failure(isCritical = false)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
expectedIsCritical = false,
|
||||||
|
expectedMainState = AsyncAction.Success::class.java,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `present - waiting for user`() {
|
||||||
|
`present - check main state`(
|
||||||
|
tests = setOf(
|
||||||
|
FakeNotificationTroubleshootTest(
|
||||||
|
firstStatus = NotificationTroubleshootTestState.Status.WaitingForUser
|
||||||
|
)
|
||||||
|
),
|
||||||
|
expectedIsCritical = false,
|
||||||
|
expectedMainState = AsyncAction.ConfirmingNoParams::class.java,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun `present - check main state`(
|
||||||
|
tests: Set<NotificationTroubleshootTest>,
|
||||||
|
expectedIsCritical: Boolean,
|
||||||
|
expectedMainState: Class<out AsyncAction<*>>,
|
||||||
|
) = runTest {
|
||||||
|
val troubleshootTestSuite = createTroubleshootTestSuite(
|
||||||
|
tests = tests
|
||||||
|
)
|
||||||
|
val presenter = createTroubleshootNotificationsPresenter(
|
||||||
|
troubleshootTestSuite = troubleshootTestSuite,
|
||||||
|
)
|
||||||
|
presenter.test {
|
||||||
|
skipItems(1)
|
||||||
|
val initialState = awaitItem()
|
||||||
|
assertThat(initialState.hasFailedTests).isEqualTo(expectedIsCritical)
|
||||||
|
assertThat(initialState.testSuiteState.mainState).isInstanceOf(expectedMainState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - quick fix test`() = runTest {
|
fun `present - quick fix test`() = runTest {
|
||||||
val troubleshootTestSuite = createTroubleshootTestSuite(
|
val troubleshootTestSuite = createTroubleshootTestSuite(
|
||||||
|
|
@ -86,9 +154,7 @@ class TroubleshootNotificationsPresenterTest {
|
||||||
val presenter = createTroubleshootNotificationsPresenter(
|
val presenter = createTroubleshootNotificationsPresenter(
|
||||||
troubleshootTestSuite = troubleshootTestSuite,
|
troubleshootTestSuite = troubleshootTestSuite,
|
||||||
)
|
)
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
presenter.test {
|
||||||
presenter.present()
|
|
||||||
}.test {
|
|
||||||
skipItems(1)
|
skipItems(1)
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
assertThat(initialState.testSuiteState.mainState).isInstanceOf(AsyncAction.Failure::class.java)
|
assertThat(initialState.testSuiteState.mainState).isInstanceOf(AsyncAction.Failure::class.java)
|
||||||
|
|
@ -111,9 +177,13 @@ private fun createTroubleshootTestSuite(
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun createTroubleshootNotificationsPresenter(
|
internal fun createTroubleshootNotificationsPresenter(
|
||||||
|
navigator: NotificationTroubleshootNavigator = object : NotificationTroubleshootNavigator {
|
||||||
|
override fun openIgnoredUsers() = lambdaError()
|
||||||
|
},
|
||||||
troubleshootTestSuite: TroubleshootTestSuite = createTroubleshootTestSuite(),
|
troubleshootTestSuite: TroubleshootTestSuite = createTroubleshootTestSuite(),
|
||||||
): TroubleshootNotificationsPresenter {
|
): TroubleshootNotificationsPresenter {
|
||||||
return TroubleshootNotificationsPresenter(
|
return TroubleshootNotificationsPresenter(
|
||||||
|
navigator = navigator,
|
||||||
troubleshootTestSuite = troubleshootTestSuite,
|
troubleshootTestSuite = troubleshootTestSuite,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
31
libraries/troubleshoot/test/build.gradle.kts
Normal file
31
libraries/troubleshoot/test/build.gradle.kts
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 New Vector Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
|
* Please see LICENSE files in the repository root for full details.
|
||||||
|
*/
|
||||||
|
plugins {
|
||||||
|
id("io.element.android-library")
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "io.element.android.libraries.troubleshoot.test"
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(projects.libraries.troubleshoot.api)
|
||||||
|
implementation(projects.tests.testutils)
|
||||||
|
implementation(libs.coroutines.test)
|
||||||
|
implementation(libs.test.core)
|
||||||
|
implementation(libs.test.turbine)
|
||||||
|
}
|
||||||
|
|
||||||
|
ktlint {
|
||||||
|
filter {
|
||||||
|
exclude { element ->
|
||||||
|
val path = element.file.path
|
||||||
|
// Exclude this file, that ktlint cannot parse.
|
||||||
|
path.contains("libraries/troubleshoot/test/src/main/kotlin/io/element/android/libraries/troubleshoot/test/Utils.kt")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 New Vector Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
|
* Please see LICENSE files in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.troubleshoot.test
|
||||||
|
|
||||||
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator
|
||||||
|
import io.element.android.tests.testutils.lambda.lambdaError
|
||||||
|
|
||||||
|
class FakeNotificationTroubleshootNavigator(
|
||||||
|
private val openIgnoredUsersResult: () -> Unit = { lambdaError() },
|
||||||
|
) : NotificationTroubleshootNavigator {
|
||||||
|
override fun openIgnoredUsers() = openIgnoredUsersResult()
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 New Vector Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
|
* Please see LICENSE files in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@file:Suppress("UnusedImports")
|
||||||
|
|
||||||
|
package io.element.android.libraries.troubleshoot.test
|
||||||
|
|
||||||
|
import app.cash.turbine.TurbineTestContext
|
||||||
|
import app.cash.turbine.test
|
||||||
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTest
|
||||||
|
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.test.TestScope
|
||||||
|
|
||||||
|
context(testScope: TestScope)
|
||||||
|
suspend fun NotificationTroubleshootTest.runAndTestState(
|
||||||
|
validate: suspend TurbineTestContext<NotificationTroubleshootTestState>.() -> Unit,
|
||||||
|
) {
|
||||||
|
testScope.backgroundScope.launch {
|
||||||
|
run(this)
|
||||||
|
}
|
||||||
|
state.test(validate = validate)
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:642e972ecba4cf6af7961066a67b556047d0ab3c35a4ce66e043ba185d93b528
|
oid sha256:9051334b3879fe2a6fb56a3c573ecb49eca7700a94184d828e2c0329cbb82b4b
|
||||||
size 20101
|
size 25070
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:26e11efbeec28f03e9b8d0df822e886b9e420fc523286cc0aa69760f8d5b639c
|
oid sha256:50fb2b753bdad6a9df4ce2f55a552464e229c7b81be16e0d4f5c8e4e4b3d129b
|
||||||
size 19562
|
size 24312
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,7 @@
|
||||||
"includeRegex" : [
|
"includeRegex" : [
|
||||||
"push_.*",
|
"push_.*",
|
||||||
"notification_.*",
|
"notification_.*",
|
||||||
|
"troubleshoot_notifications\\.test_blocked_users\\..*",
|
||||||
"troubleshoot_notifications_test_current_push_provider.*",
|
"troubleshoot_notifications_test_current_push_provider.*",
|
||||||
"troubleshoot_notifications_test_detect_push_provider.*",
|
"troubleshoot_notifications_test_detect_push_provider.*",
|
||||||
"troubleshoot_notifications_test_display_notification_.*",
|
"troubleshoot_notifications_test_display_notification_.*",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue