Skip to content

Commit fa14e4c

Browse files
committed
Add notification troubleshoot test about blocked users.
1 parent 648583c commit fa14e4c

File tree

31 files changed

+338
-30
lines changed

31 files changed

+338
-30
lines changed

features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,10 @@ class PreferencesFlowNode(
208208
navigateUp()
209209
}
210210
}
211+
212+
override fun openIgnoredUsers() {
213+
backstack.push(NavTarget.BlockedUsers)
214+
}
211215
})
212216
.build()
213217
}

libraries/permissions/impl/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,6 @@ dependencies {
4343
testCommonDependencies(libs)
4444
testImplementation(projects.libraries.matrix.test)
4545
testImplementation(projects.libraries.permissions.test)
46+
testImplementation(projects.libraries.troubleshoot.test)
4647
testImplementation(projects.services.toolbox.test)
4748
}

libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/troubleshoot/NotificationTroubleshootCheckPermissionTest.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import dev.zacsweers.metro.Inject
1515
import io.element.android.libraries.permissions.api.PermissionStateProvider
1616
import io.element.android.libraries.permissions.impl.R
1717
import io.element.android.libraries.permissions.impl.action.PermissionActions
18+
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator
1819
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTest
1920
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestDelegate
2021
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
@@ -54,7 +55,10 @@ class NotificationTroubleshootCheckPermissionTest(
5455

5556
override suspend fun reset() = delegate.reset()
5657

57-
override suspend fun quickFix(coroutineScope: CoroutineScope) {
58+
override suspend fun quickFix(
59+
coroutineScope: CoroutineScope,
60+
navigator: NotificationTroubleshootNavigator,
61+
) {
5862
// Do not bother about asking the permission inline, just lead the user to the settings
5963
permissionActions.openSettings()
6064
}

libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/troubleshoot/NotificationTroubleshootCheckPermissionTestTest.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import com.google.common.truth.Truth.assertThat
1313
import io.element.android.libraries.permissions.impl.action.FakePermissionActions
1414
import io.element.android.libraries.permissions.test.FakePermissionStateProvider
1515
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
16+
import io.element.android.libraries.troubleshoot.test.FakeNotificationTroubleshootNavigator
1617
import io.element.android.services.toolbox.test.sdk.FakeBuildVersionSdkIntProvider
1718
import io.element.android.services.toolbox.test.strings.FakeStringProvider
1819
import kotlinx.coroutines.launch
@@ -84,7 +85,7 @@ class NotificationTroubleshootCheckPermissionTestTest {
8485
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true))
8586
// Quick fix
8687
launch {
87-
sut.quickFix(this)
88+
sut.quickFix(this, FakeNotificationTroubleshootNavigator())
8889
// Run the test again (IRL it will be done thanks to the resuming of the application)
8990
sut.run(this)
9091
}

libraries/push/impl/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ dependencies {
7272
testImplementation(projects.libraries.push.test)
7373
testImplementation(projects.libraries.pushproviders.test)
7474
testImplementation(projects.libraries.pushstore.test)
75+
testImplementation(projects.libraries.troubleshoot.test)
7576
testImplementation(projects.features.call.test)
7677
testImplementation(projects.features.lockscreen.test)
7778
testImplementation(projects.services.appnavstate.test)
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright 2025 New Vector Ltd.
3+
*
4+
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
5+
* Please see LICENSE files in the repository root for full details.
6+
*/
7+
8+
package io.element.android.libraries.push.impl.troubleshoot
9+
10+
import dev.zacsweers.metro.ContributesIntoSet
11+
import dev.zacsweers.metro.Inject
12+
import io.element.android.libraries.di.SessionScope
13+
import io.element.android.libraries.matrix.api.MatrixClient
14+
import io.element.android.libraries.push.impl.R
15+
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator
16+
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTest
17+
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestDelegate
18+
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
19+
import io.element.android.services.toolbox.api.strings.StringProvider
20+
import kotlinx.coroutines.CoroutineScope
21+
import kotlinx.coroutines.flow.StateFlow
22+
23+
@ContributesIntoSet(SessionScope::class)
24+
@Inject
25+
class IgnoredUsersTest(
26+
private val matrixClient: MatrixClient,
27+
private val stringProvider: StringProvider,
28+
) : NotificationTroubleshootTest {
29+
override val order = 80
30+
private val delegate = NotificationTroubleshootTestDelegate(
31+
defaultName = stringProvider.getString(R.string.troubleshoot_notifications_test_blocked_users_title),
32+
defaultDescription = stringProvider.getString(R.string.troubleshoot_notifications_test_blocked_users_description),
33+
fakeDelay = NotificationTroubleshootTestDelegate.SHORT_DELAY,
34+
)
35+
override val state: StateFlow<NotificationTroubleshootTestState> = delegate.state
36+
37+
override suspend fun run(coroutineScope: CoroutineScope) {
38+
delegate.start()
39+
val ignorerUsers = matrixClient.ignoredUsersFlow.value
40+
if (ignorerUsers.isEmpty()) {
41+
delegate.updateState(
42+
description = stringProvider.getString(R.string.troubleshoot_notifications_test_blocked_users_result_none),
43+
status = NotificationTroubleshootTestState.Status.Success,
44+
)
45+
} else {
46+
delegate.updateState(
47+
description = stringProvider.getQuantityString(
48+
R.plurals.troubleshoot_notifications_test_blocked_users_result_some,
49+
ignorerUsers.size,
50+
ignorerUsers.size
51+
),
52+
status = NotificationTroubleshootTestState.Status.Failure(
53+
hasQuickFix = true,
54+
isCritical = false,
55+
quickFixButtonString = stringProvider.getString(R.string.troubleshoot_notifications_test_blocked_users_quick_fix),
56+
),
57+
)
58+
}
59+
}
60+
61+
override suspend fun quickFix(
62+
coroutineScope: CoroutineScope,
63+
navigator: NotificationTroubleshootNavigator,
64+
) {
65+
navigator.openIgnoredUsers()
66+
}
67+
68+
override suspend fun reset() = delegate.reset()
69+
}

libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTest.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import dev.zacsweers.metro.Inject
1313
import io.element.android.libraries.push.api.PushService
1414
import io.element.android.libraries.push.api.gateway.PushGatewayFailure
1515
import io.element.android.libraries.push.impl.R
16+
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator
1617
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTest
1718
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestDelegate
1819
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
@@ -99,7 +100,10 @@ class PushLoopbackTest(
99100
)
100101
}
101102

102-
override suspend fun quickFix(coroutineScope: CoroutineScope) {
103+
override suspend fun quickFix(
104+
coroutineScope: CoroutineScope,
105+
navigator: NotificationTroubleshootNavigator,
106+
) {
103107
delegate.start()
104108
pushService.getCurrentPushProvider()?.rotateToken()
105109
run(coroutineScope)

libraries/push/impl/src/main/res/values/localazy.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,14 @@
5454
<string name="push_distributor_background_sync_android">"Background synchronization"</string>
5555
<string name="push_distributor_firebase_android">"Google Services"</string>
5656
<string name="push_no_valid_google_play_services_apk_android">"No valid Google Play Services found. Notifications may not work properly."</string>
57+
<string name="troubleshoot_notifications_test_blocked_users_description">"Checking blocked users"</string>
58+
<string name="troubleshoot_notifications_test_blocked_users_quick_fix">"View blocked users"</string>
59+
<string name="troubleshoot_notifications_test_blocked_users_result_none">"No users are blocked."</string>
60+
<plurals name="troubleshoot_notifications_test_blocked_users_result_some">
61+
<item quantity="one">"You blocked %1$d user. You will not receive notifications for this user."</item>
62+
<item quantity="other">"You blocked %1$d users. You will not receive notifications for these users."</item>
63+
</plurals>
64+
<string name="troubleshoot_notifications_test_blocked_users_title">"Blocked users"</string>
5765
<string name="troubleshoot_notifications_test_current_push_provider_description">"Get the name of the current provider."</string>
5866
<string name="troubleshoot_notifications_test_current_push_provider_failure">"No push providers selected."</string>
5967
<string name="troubleshoot_notifications_test_current_push_provider_success">"Current push provider: %1$s."</string>
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Copyright 2025 New Vector Ltd.
3+
*
4+
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
5+
* Please see LICENSE files in the repository root for full details.
6+
*/
7+
8+
package io.element.android.libraries.push.impl.troubleshoot
9+
10+
import app.cash.turbine.test
11+
import com.google.common.truth.Truth.assertThat
12+
import io.element.android.libraries.matrix.test.A_USER_ID
13+
import io.element.android.libraries.matrix.test.A_USER_ID_2
14+
import io.element.android.libraries.matrix.test.FakeMatrixClient
15+
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootNavigator
16+
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
17+
import io.element.android.services.toolbox.test.strings.FakeStringProvider
18+
import io.element.android.tests.testutils.lambda.lambdaRecorder
19+
import kotlinx.collections.immutable.persistentListOf
20+
import kotlinx.coroutines.flow.MutableStateFlow
21+
import kotlinx.coroutines.launch
22+
import kotlinx.coroutines.test.runTest
23+
import org.junit.Test
24+
25+
class IgnoredUsersTestTest {
26+
@Test
27+
fun `test IgnoredUsersTest order`() = runTest {
28+
val sut = IgnoredUsersTest(
29+
matrixClient = FakeMatrixClient(),
30+
stringProvider = FakeStringProvider(),
31+
)
32+
assertThat(sut.order).isEqualTo(80)
33+
}
34+
35+
@Test
36+
fun `test IgnoredUsersTest quick fix`() = runTest {
37+
val sut = IgnoredUsersTest(
38+
matrixClient = FakeMatrixClient(),
39+
stringProvider = FakeStringProvider(),
40+
)
41+
val openIgnoredUsersResult = lambdaRecorder<Unit> {}
42+
val navigator = object : NotificationTroubleshootNavigator {
43+
override fun openIgnoredUsers() = openIgnoredUsersResult()
44+
}
45+
sut.quickFix(
46+
coroutineScope = backgroundScope,
47+
navigator = navigator,
48+
)
49+
openIgnoredUsersResult.assertions().isCalledOnce()
50+
}
51+
52+
@Test
53+
fun `test IgnoredUsersTest with no blocked users`() = runTest {
54+
val sut = IgnoredUsersTest(
55+
matrixClient = FakeMatrixClient(
56+
ignoredUsersFlow = MutableStateFlow(persistentListOf())
57+
),
58+
stringProvider = FakeStringProvider(),
59+
)
60+
backgroundScope.launch {
61+
sut.run(this)
62+
}
63+
sut.state.test {
64+
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
65+
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
66+
val lastItem = awaitItem()
67+
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Success)
68+
}
69+
}
70+
71+
@Test
72+
fun `test IgnoredUsersTest with blocked users`() = runTest {
73+
val sut = IgnoredUsersTest(
74+
matrixClient = FakeMatrixClient(
75+
ignoredUsersFlow = MutableStateFlow(persistentListOf(A_USER_ID, A_USER_ID_2))
76+
),
77+
stringProvider = FakeStringProvider(),
78+
)
79+
backgroundScope.launch {
80+
sut.run(this)
81+
}
82+
sut.state.test {
83+
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Idle(true))
84+
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
85+
val lastItem = awaitItem()
86+
val lastStatus = lastItem.status as NotificationTroubleshootTestState.Status.Failure
87+
assertThat(lastStatus.hasQuickFix).isTrue()
88+
assertThat(lastStatus.isCritical).isFalse()
89+
assertThat(lastStatus.quickFixButtonString).isNotNull()
90+
assertThat(lastItem.description).contains("2")
91+
}
92+
}
93+
}

libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/troubleshoot/PushLoopbackTestTest.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import io.element.android.libraries.push.api.gateway.PushGatewayFailure
1515
import io.element.android.libraries.push.test.FakePushService
1616
import io.element.android.libraries.pushproviders.test.FakePushProvider
1717
import io.element.android.libraries.troubleshoot.api.test.NotificationTroubleshootTestState
18+
import io.element.android.libraries.troubleshoot.test.FakeNotificationTroubleshootNavigator
1819
import io.element.android.services.toolbox.test.strings.FakeStringProvider
1920
import io.element.android.services.toolbox.test.systemclock.FakeSystemClock
2021
import io.element.android.tests.testutils.lambda.lambdaRecorder
@@ -97,7 +98,7 @@ class PushLoopbackTestTest {
9798
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
9899
val lastItem = awaitItem()
99100
assertThat(lastItem.status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true))
100-
sut.quickFix(this)
101+
sut.quickFix(this, FakeNotificationTroubleshootNavigator())
101102
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.InProgress)
102103
assertThat(awaitItem().status).isEqualTo(NotificationTroubleshootTestState.Status.Failure(true))
103104
rotateTokenLambda.assertions().isCalledOnce()

0 commit comments

Comments
 (0)