Skip to content

Commit 0a14ed6

Browse files
committed
Add UI test on ChangeRolesView
1 parent 2cb0567 commit 0a14ed6

File tree

2 files changed

+300
-1
lines changed
  • features/roomdetails/impl/src

2 files changed

+300
-1
lines changed

features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/rolesandpermissions/changeroles/ChangeRolesStateProvider.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ internal fun aChangeRolesState(
6262
exitState: AsyncAction<Unit> = AsyncAction.Uninitialized,
6363
savingState: AsyncAction<Unit> = AsyncAction.Uninitialized,
6464
canRemoveMember: (UserId) -> Boolean = { true },
65+
eventSink: (ChangeRolesEvent) -> Unit = {},
6566
) = ChangeRolesState(
6667
role = role,
6768
query = query,
@@ -72,7 +73,7 @@ internal fun aChangeRolesState(
7273
exitState = exitState,
7374
savingState = savingState,
7475
canChangeMemberRole = canRemoveMember,
75-
eventSink = {},
76+
eventSink = eventSink,
7677
)
7778

7879
internal fun aChangeRolesStateWithSelectedUsers() = aChangeRolesState(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,298 @@
1+
/*
2+
* Copyright (c) 2024 New Vector Ltd
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.element.android.features.roomdetails.rolesandpermissions.changeroles
18+
19+
import androidx.activity.ComponentActivity
20+
import androidx.compose.runtime.CompositionLocalProvider
21+
import androidx.compose.ui.platform.LocalInspectionMode
22+
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
23+
import androidx.compose.ui.test.junit4.createAndroidComposeRule
24+
import androidx.compose.ui.test.onAllNodesWithText
25+
import androidx.compose.ui.test.onNodeWithContentDescription
26+
import androidx.compose.ui.test.onNodeWithText
27+
import androidx.compose.ui.test.performClick
28+
import androidx.test.ext.junit.runners.AndroidJUnit4
29+
import com.google.common.truth.Truth.assertThat
30+
import io.element.android.features.roomdetails.impl.rolesandpermissions.changeroles.ChangeRolesEvent
31+
import io.element.android.features.roomdetails.impl.rolesandpermissions.changeroles.ChangeRolesState
32+
import io.element.android.features.roomdetails.impl.rolesandpermissions.changeroles.ChangeRolesView
33+
import io.element.android.features.roomdetails.impl.rolesandpermissions.changeroles.aChangeRolesState
34+
import io.element.android.features.roomdetails.impl.rolesandpermissions.changeroles.aChangeRolesStateWithSelectedUsers
35+
import io.element.android.libraries.architecture.AsyncAction
36+
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
37+
import io.element.android.libraries.matrix.api.room.RoomMember
38+
import io.element.android.libraries.matrix.api.room.toMatrixUser
39+
import io.element.android.libraries.matrix.ui.components.aMatrixUserList
40+
import io.element.android.libraries.ui.strings.CommonStrings
41+
import io.element.android.tests.testutils.EnsureNeverCalled
42+
import io.element.android.tests.testutils.EventsRecorder
43+
import io.element.android.tests.testutils.clickOn
44+
import io.element.android.tests.testutils.pressBack
45+
import kotlinx.collections.immutable.toImmutableList
46+
import org.junit.Rule
47+
import org.junit.Test
48+
import org.junit.rules.TestRule
49+
import org.junit.runner.RunWith
50+
51+
@RunWith(AndroidJUnit4::class)
52+
class ChangeRolesViewTest {
53+
@get:Rule val rule = createAndroidComposeRule<ComponentActivity>()
54+
55+
@Test
56+
fun `click on back icon search not active emits the expected event`() {
57+
val eventsRecorder = EventsRecorder<ChangeRolesEvent>()
58+
rule.setChangeRolesView(
59+
state = aChangeRolesState(
60+
eventSink = eventsRecorder,
61+
),
62+
)
63+
rule.pressBack()
64+
eventsRecorder.assertList(
65+
listOf(
66+
ChangeRolesEvent.QueryChanged(""),
67+
ChangeRolesEvent.Exit,
68+
)
69+
)
70+
}
71+
72+
@Test
73+
fun `click on back icon search active emits the expected event`() {
74+
val eventsRecorder = EventsRecorder<ChangeRolesEvent>()
75+
rule.setChangeRolesView(
76+
state = aChangeRolesState(
77+
isSearchActive = true,
78+
eventSink = eventsRecorder,
79+
),
80+
)
81+
rule.pressBack()
82+
// This event should be there, maybe a problem with the SearchBar
83+
// It's working fine in the app, so let's ignore it for now
84+
// eventsRecorder.assertSingle(ChangeRolesEvent.ToggleSearchActive)
85+
}
86+
87+
@Test
88+
fun `click on search bar emits the expected event`() {
89+
val eventsRecorder = EventsRecorder<ChangeRolesEvent>()
90+
rule.setChangeRolesView(
91+
state = aChangeRolesState(
92+
eventSink = eventsRecorder,
93+
),
94+
)
95+
rule.clickOn(CommonStrings.common_search_for_someone)
96+
eventsRecorder.assertList(
97+
listOf(
98+
ChangeRolesEvent.QueryChanged(""),
99+
// This event should be there, maybe a problem with the SearchBar
100+
// It's working fine in the app, so let's ignore it for now
101+
// ChangeRolesEvent.ToggleSearchActive,
102+
)
103+
)
104+
}
105+
106+
@Test
107+
fun `click on save button emits the expected event`() {
108+
val eventsRecorder = EventsRecorder<ChangeRolesEvent>()
109+
rule.setChangeRolesView(
110+
state = aChangeRolesState(
111+
hasPendingChanges = true,
112+
eventSink = eventsRecorder,
113+
),
114+
)
115+
rule.clickOn(CommonStrings.action_save)
116+
eventsRecorder.assertList(
117+
listOf(
118+
ChangeRolesEvent.QueryChanged(""),
119+
ChangeRolesEvent.Save,
120+
)
121+
)
122+
}
123+
124+
@Test
125+
fun `testing exit confirmation dialog ok emits the expected event`() {
126+
val eventsRecorder = EventsRecorder<ChangeRolesEvent>()
127+
rule.setChangeRolesView(
128+
state = aChangeRolesState(
129+
exitState = AsyncAction.Confirming,
130+
eventSink = eventsRecorder,
131+
),
132+
)
133+
rule.clickOn(CommonStrings.action_ok)
134+
eventsRecorder.assertList(
135+
listOf(
136+
ChangeRolesEvent.QueryChanged(""),
137+
ChangeRolesEvent.Exit,
138+
)
139+
)
140+
}
141+
142+
@Test
143+
fun `testing exit confirmation dialog cancel emits the expected event`() {
144+
val eventsRecorder = EventsRecorder<ChangeRolesEvent>()
145+
rule.setChangeRolesView(
146+
state = aChangeRolesState(
147+
exitState = AsyncAction.Confirming,
148+
eventSink = eventsRecorder,
149+
),
150+
)
151+
rule.clickOn(CommonStrings.action_cancel)
152+
eventsRecorder.assertList(
153+
listOf(
154+
ChangeRolesEvent.QueryChanged(""),
155+
ChangeRolesEvent.CancelExit
156+
)
157+
)
158+
}
159+
160+
@Test
161+
fun `testing saving dialog failure OK emits the expected event`() {
162+
val eventsRecorder = EventsRecorder<ChangeRolesEvent>()
163+
rule.setChangeRolesView(
164+
state = aChangeRolesState(
165+
savingState = AsyncAction.Failure(Exception("boom")),
166+
eventSink = eventsRecorder,
167+
),
168+
)
169+
rule.clickOn(CommonStrings.action_ok)
170+
eventsRecorder.assertList(
171+
listOf(
172+
ChangeRolesEvent.QueryChanged(""),
173+
ChangeRolesEvent.ClearError,
174+
)
175+
)
176+
}
177+
178+
@Test
179+
fun `testing saving confirmation dialog for admin OK emits the expected event`() {
180+
val eventsRecorder = EventsRecorder<ChangeRolesEvent>()
181+
rule.setChangeRolesView(
182+
state = aChangeRolesState(
183+
role = RoomMember.Role.ADMIN,
184+
savingState = AsyncAction.Confirming,
185+
eventSink = eventsRecorder,
186+
),
187+
)
188+
rule.clickOn(CommonStrings.action_ok)
189+
eventsRecorder.assertList(
190+
listOf(
191+
ChangeRolesEvent.QueryChanged(""),
192+
ChangeRolesEvent.Save,
193+
)
194+
)
195+
}
196+
197+
@Test
198+
fun `testing saving confirmation dialog for admin cancel emits the expected event`() {
199+
val eventsRecorder = EventsRecorder<ChangeRolesEvent>()
200+
rule.setChangeRolesView(
201+
state = aChangeRolesState(
202+
role = RoomMember.Role.ADMIN,
203+
savingState = AsyncAction.Confirming,
204+
eventSink = eventsRecorder,
205+
),
206+
)
207+
rule.clickOn(CommonStrings.action_cancel)
208+
eventsRecorder.assertList(
209+
listOf(
210+
ChangeRolesEvent.QueryChanged(""),
211+
ChangeRolesEvent.ClearError,
212+
)
213+
)
214+
}
215+
216+
@Test
217+
fun `testing removing user from selected list emits the expected event`() {
218+
val eventsRecorder = EventsRecorder<ChangeRolesEvent>()
219+
val selectedUsers = aMatrixUserList().take(2)
220+
val userToDeselect = selectedUsers[1]
221+
assertThat(userToDeselect.displayName).isEqualTo("Bob")
222+
rule.setChangeRolesView(
223+
state = aChangeRolesStateWithSelectedUsers().copy(
224+
selectedUsers = selectedUsers.toImmutableList(),
225+
eventSink = eventsRecorder,
226+
),
227+
)
228+
// Unselect the user from the row list
229+
val contentDescription = rule.activity.getString(CommonStrings.action_remove)
230+
rule.onNodeWithContentDescription(contentDescription).performClick()
231+
eventsRecorder.assertList(
232+
listOf(
233+
ChangeRolesEvent.QueryChanged(""),
234+
ChangeRolesEvent.UserSelectionToggled(userToDeselect),
235+
)
236+
)
237+
}
238+
239+
@Test
240+
fun `testing adding user to the selected list emits the expected event`() {
241+
val eventsRecorder = EventsRecorder<ChangeRolesEvent>()
242+
val selectedUsers = aMatrixUserList().take(2)
243+
val state = aChangeRolesStateWithSelectedUsers().copy(
244+
selectedUsers = selectedUsers.toImmutableList(),
245+
eventSink = eventsRecorder,
246+
)
247+
val userToSelect = (state.searchResults as SearchBarResultState.Results).results[2].toMatrixUser()
248+
assertThat(userToSelect.displayName).isEqualTo("Carol")
249+
rule.setChangeRolesView(
250+
state = state,
251+
)
252+
// Select the user from the rom list
253+
rule.onNodeWithText("Carol").performClick()
254+
eventsRecorder.assertList(
255+
listOf(
256+
ChangeRolesEvent.QueryChanged(""),
257+
ChangeRolesEvent.UserSelectionToggled(userToSelect),
258+
)
259+
)
260+
}
261+
262+
@Test
263+
fun `testing removing user to the selected list emits the expected event`() {
264+
val eventsRecorder = EventsRecorder<ChangeRolesEvent>()
265+
val selectedUsers = aMatrixUserList().take(2)
266+
val state = aChangeRolesStateWithSelectedUsers().copy(
267+
selectedUsers = selectedUsers.toImmutableList(),
268+
eventSink = eventsRecorder,
269+
)
270+
val userToSelect = (state.searchResults as SearchBarResultState.Results).results[1].toMatrixUser()
271+
assertThat(userToSelect.displayName).isEqualTo("Bob")
272+
rule.setChangeRolesView(
273+
state = state,
274+
)
275+
// Select the user from the rom list
276+
rule.onAllNodesWithText("Bob")[1].performClick()
277+
eventsRecorder.assertList(
278+
listOf(
279+
ChangeRolesEvent.QueryChanged(""),
280+
ChangeRolesEvent.UserSelectionToggled(userToSelect),
281+
)
282+
)
283+
}
284+
}
285+
286+
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setChangeRolesView(
287+
state: ChangeRolesState,
288+
onBackPressed: () -> Unit = EnsureNeverCalled(),
289+
) {
290+
setContent {
291+
CompositionLocalProvider(LocalInspectionMode provides true) {
292+
ChangeRolesView(
293+
state = state,
294+
onBackPressed = onBackPressed,
295+
)
296+
}
297+
}
298+
}

0 commit comments

Comments
 (0)