Merge pull request #5906 from element-hq/feature/fga/fix_edit_moderator

fix: edit moderators not working
This commit is contained in:
ganfra 2025-12-15 20:57:01 +01:00 committed by GitHub
commit 3b1b923743
2 changed files with 48 additions and 36 deletions

View file

@ -44,7 +44,7 @@ import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
@ -81,7 +81,7 @@ class ChangeRolesPresenter(
val owners = if (role == RoomMember.Role.Admin) { val owners = if (role == RoomMember.Role.Admin) {
room.usersWithRole { role -> role is RoomMember.Role.Owner } room.usersWithRole { role -> role is RoomMember.Role.Owner }
} else { } else {
emptyFlow() flowOf(persistentListOf())
} }
combine( combine(
owners, owners,

View file

@ -256,44 +256,48 @@ class ChangeRolesPresenterTest {
@Test @Test
fun `present - UserSelectionToggle adds and removes users from the selected user list`() = runTest { fun `present - UserSelectionToggle adds and removes users from the selected user list`() = runTest {
val roomMemberList = aRoomMemberList()
val room = FakeJoinedRoom().apply { val room = FakeJoinedRoom().apply {
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList())) givenRoomMembersState(RoomMembersState.Ready(roomMemberList))
givenRoomInfo(aRoomInfo(roomPowerLevels = roomPowerLevelsWithRole(RoomMember.Role.Admin))) givenRoomInfo(aRoomInfo(roomPowerLevels = roomPowerLevelsFromRoomMemberList(roomMemberList)))
} }
val presenter = createChangeRolesPresenter(room = room) val presenter = createChangeRolesPresenter(room = room)
val userMember = roomMemberList.first { it.role == RoomMember.Role.User }
presenter.test { presenter.test {
skipItems(1) skipItems(1)
val initialState = awaitItem() val initialState = awaitItem()
assertThat(initialState.selectedUsers).hasSize(1) assertThat(initialState.selectedUsers).hasSize(1)
initialState.eventSink(ChangeRolesEvent.UserSelectionToggled(MatrixUser(A_USER_ID_2))) initialState.eventSink(ChangeRolesEvent.UserSelectionToggled(userMember.toMatrixUser()))
assertThat(awaitItem().selectedUsers).hasSize(2) assertThat(awaitItem().selectedUsers).hasSize(2)
initialState.eventSink(ChangeRolesEvent.UserSelectionToggled(MatrixUser(A_USER_ID_2))) initialState.eventSink(ChangeRolesEvent.UserSelectionToggled(userMember.toMatrixUser()))
assertThat(awaitItem().selectedUsers).hasSize(1) assertThat(awaitItem().selectedUsers).hasSize(1)
} }
} }
@Test @Test
fun `present - hasPendingChanges is true when the initial selected users don't match the new ones`() = runTest { fun `present - hasPendingChanges is true when the initial selected users don't match the new ones`() = runTest {
val roomMemberList = aRoomMemberList()
val room = FakeJoinedRoom().apply { val room = FakeJoinedRoom().apply {
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList())) givenRoomMembersState(RoomMembersState.Ready(roomMemberList))
givenRoomInfo(aRoomInfo(roomPowerLevels = roomPowerLevelsWithRole(RoomMember.Role.Admin))) givenRoomInfo(aRoomInfo(roomPowerLevels = roomPowerLevelsFromRoomMemberList(roomMemberList)))
} }
val presenter = createChangeRolesPresenter(room = room) val presenter = createChangeRolesPresenter(room = room)
val userMember = roomMemberList.first { it.role == RoomMember.Role.User }
presenter.test { presenter.test {
skipItems(1) skipItems(1)
val initialState = awaitItem() val initialState = awaitItem()
assertThat(initialState.hasPendingChanges).isFalse() assertThat(initialState.hasPendingChanges).isFalse()
assertThat(initialState.selectedUsers).hasSize(1) assertThat(initialState.selectedUsers).hasSize(1)
initialState.eventSink(ChangeRolesEvent.UserSelectionToggled(MatrixUser(A_USER_ID_2))) initialState.eventSink(ChangeRolesEvent.UserSelectionToggled(userMember.toMatrixUser()))
with(awaitItem()) { with(awaitItem()) {
assertThat(selectedUsers).hasSize(2) assertThat(selectedUsers).hasSize(2)
assertThat(hasPendingChanges).isTrue() assertThat(hasPendingChanges).isTrue()
} }
initialState.eventSink(ChangeRolesEvent.UserSelectionToggled(MatrixUser(A_USER_ID_2))) initialState.eventSink(ChangeRolesEvent.UserSelectionToggled(userMember.toMatrixUser()))
with(awaitItem()) { with(awaitItem()) {
assertThat(selectedUsers).hasSize(1) assertThat(selectedUsers).hasSize(1)
assertThat(hasPendingChanges).isFalse() assertThat(hasPendingChanges).isFalse()
@ -303,9 +307,10 @@ class ChangeRolesPresenterTest {
@Test @Test
fun `present - Exit will display success false if no pending changes`() = runTest { fun `present - Exit will display success false if no pending changes`() = runTest {
val roomMemberList = aRoomMemberList()
val room = FakeJoinedRoom().apply { val room = FakeJoinedRoom().apply {
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList())) givenRoomMembersState(RoomMembersState.Ready(roomMemberList))
givenRoomInfo(aRoomInfo(roomPowerLevels = roomPowerLevelsWithRole(RoomMember.Role.Admin))) givenRoomInfo(aRoomInfo(roomPowerLevels = roomPowerLevelsFromRoomMemberList(roomMemberList)))
} }
val presenter = createChangeRolesPresenter(room = room) val presenter = createChangeRolesPresenter(room = room)
presenter.test { presenter.test {
@ -321,9 +326,10 @@ class ChangeRolesPresenterTest {
@Test @Test
fun `present - CloseDialog will remove exit confirmation`() = runTest { fun `present - CloseDialog will remove exit confirmation`() = runTest {
val roomMemberList = aRoomMemberList()
val room = FakeJoinedRoom().apply { val room = FakeJoinedRoom().apply {
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList())) givenRoomMembersState(RoomMembersState.Ready(roomMemberList))
givenRoomInfo(aRoomInfo(roomPowerLevels = roomPowerLevelsWithRole(RoomMember.Role.Admin))) givenRoomInfo(aRoomInfo(roomPowerLevels = roomPowerLevelsFromRoomMemberList(roomMemberList)))
} }
val presenter = createChangeRolesPresenter(room = room) val presenter = createChangeRolesPresenter(room = room)
presenter.test { presenter.test {
@ -345,9 +351,10 @@ class ChangeRolesPresenterTest {
@Test @Test
fun `present - Exit will display a confirmation dialog if there are pending changes, calling it again will actually exit`() = runTest { fun `present - Exit will display a confirmation dialog if there are pending changes, calling it again will actually exit`() = runTest {
val roomMemberList = aRoomMemberList()
val room = FakeJoinedRoom().apply { val room = FakeJoinedRoom().apply {
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList())) givenRoomMembersState(RoomMembersState.Ready(roomMemberList))
givenRoomInfo(aRoomInfo(roomPowerLevels = roomPowerLevelsWithRole(RoomMember.Role.Admin))) givenRoomInfo(aRoomInfo(roomPowerLevels = roomPowerLevelsFromRoomMemberList(roomMemberList)))
} }
val presenter = createChangeRolesPresenter(room = room) val presenter = createChangeRolesPresenter(room = room)
presenter.test { presenter.test {
@ -371,12 +378,13 @@ class ChangeRolesPresenterTest {
@Test @Test
fun `present - Save will display a confirmation when adding admins`() = runTest { fun `present - Save will display a confirmation when adding admins`() = runTest {
val roomMemberList = aRoomMemberList()
val room = FakeJoinedRoom( val room = FakeJoinedRoom(
updateUserRoleResult = { Result.success(Unit) }, updateUserRoleResult = { Result.success(Unit) },
baseRoom = FakeBaseRoom(updateMembersResult = { Result.success(Unit) }), baseRoom = FakeBaseRoom(updateMembersResult = { Result.success(Unit) }),
).apply { ).apply {
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList())) givenRoomMembersState(RoomMembersState.Ready(roomMemberList))
givenRoomInfo(aRoomInfo(roomPowerLevels = roomPowerLevelsWithRole(RoomMember.Role.Admin))) givenRoomInfo(aRoomInfo(roomPowerLevels = roomPowerLevelsFromRoomMemberList(roomMemberList)))
} }
val presenter = createChangeRolesPresenter(role = RoomMember.Role.Admin, room = room) val presenter = createChangeRolesPresenter(role = RoomMember.Role.Admin, room = room)
presenter.test { presenter.test {
@ -395,9 +403,10 @@ class ChangeRolesPresenterTest {
@Test @Test
fun `present - CloseDialog will remove the confirmation dialog`() = runTest { fun `present - CloseDialog will remove the confirmation dialog`() = runTest {
val roomMemberList = aRoomMemberList()
val room = FakeJoinedRoom().apply { val room = FakeJoinedRoom().apply {
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList())) givenRoomMembersState(RoomMembersState.Ready(roomMemberList))
givenRoomInfo(aRoomInfo(roomPowerLevels = roomPowerLevelsWithRole(RoomMember.Role.Admin))) givenRoomInfo(aRoomInfo(roomPowerLevels = roomPowerLevelsFromRoomMemberList(roomMemberList)))
} }
val presenter = createChangeRolesPresenter(role = RoomMember.Role.Admin, room = room) val presenter = createChangeRolesPresenter(role = RoomMember.Role.Admin, room = room)
presenter.test { presenter.test {
@ -419,25 +428,27 @@ class ChangeRolesPresenterTest {
@Test @Test
fun `present - Save will just save the data for moderators`() = runTest { fun `present - Save will just save the data for moderators`() = runTest {
val analyticsService = FakeAnalyticsService() val analyticsService = FakeAnalyticsService()
val roomMemberList = aRoomMemberList()
val room = FakeJoinedRoom( val room = FakeJoinedRoom(
updateUserRoleResult = { Result.success(Unit) }, updateUserRoleResult = { Result.success(Unit) },
baseRoom = FakeBaseRoom(updateMembersResult = { Result.success(Unit) }), baseRoom = FakeBaseRoom(updateMembersResult = { Result.success(Unit) }),
).apply { ).apply {
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList())) givenRoomMembersState(RoomMembersState.Ready(roomMemberList))
givenRoomInfo(aRoomInfo(roomPowerLevels = roomPowerLevelsWithRole(RoomMember.Role.Moderator))) givenRoomInfo(aRoomInfo(roomPowerLevels = roomPowerLevelsFromRoomMemberList(roomMemberList)))
} }
val presenter = createChangeRolesPresenter( val presenter = createChangeRolesPresenter(
role = RoomMember.Role.Moderator, role = RoomMember.Role.Moderator,
room = room, room = room,
analyticsService = analyticsService analyticsService = analyticsService
) )
val userMember = roomMemberList.first { it.role == RoomMember.Role.User }
presenter.test { presenter.test {
skipItems(1) skipItems(2)
val initialState = awaitItem() val initialState = awaitItem()
assertThat(initialState.selectedUsers).isEmpty() assertThat(initialState.selectedUsers).hasSize(1)
initialState.eventSink(ChangeRolesEvent.UserSelectionToggled(MatrixUser(A_USER_ID_2))) initialState.eventSink(ChangeRolesEvent.UserSelectionToggled(userMember.toMatrixUser()))
awaitItem().also { awaitItem().also {
assertThat(it.selectedUsers).hasSize(1) assertThat(it.selectedUsers).hasSize(2)
it.eventSink(ChangeRolesEvent.Save) it.eventSink(ChangeRolesEvent.Save)
} }
assertThat(awaitItem().savingState).isInstanceOf(AsyncAction.Loading::class.java) assertThat(awaitItem().savingState).isInstanceOf(AsyncAction.Loading::class.java)
@ -516,20 +527,22 @@ class ChangeRolesPresenterTest {
@Test @Test
fun `present - Save can handle failures and CloseDialog clears them`() = runTest { fun `present - Save can handle failures and CloseDialog clears them`() = runTest {
val roomMemberList = aRoomMemberList()
val room = FakeJoinedRoom( val room = FakeJoinedRoom(
updateUserRoleResult = { Result.failure(IllegalStateException("Failed")) } updateUserRoleResult = { Result.failure(IllegalStateException("Failed")) }
).apply { ).apply {
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList())) givenRoomMembersState(RoomMembersState.Ready(roomMemberList))
givenRoomInfo(aRoomInfo(roomPowerLevels = roomPowerLevelsWithRole(role = RoomMember.Role.Moderator, userId = A_USER_ID))) givenRoomInfo(aRoomInfo(roomPowerLevels = roomPowerLevelsFromRoomMemberList(roomMemberList)))
} }
val presenter = createChangeRolesPresenter(role = RoomMember.Role.Moderator, room = room) val presenter = createChangeRolesPresenter(role = RoomMember.Role.Moderator, room = room)
val userMember = roomMemberList.first { it.role == RoomMember.Role.User }
presenter.test { presenter.test {
skipItems(1) skipItems(2)
val initialState = awaitItem() val initialState = awaitItem()
assertThat(initialState.selectedUsers).isEmpty() assertThat(initialState.selectedUsers).hasSize(1)
initialState.eventSink(ChangeRolesEvent.UserSelectionToggled(MatrixUser(A_USER_ID_2))) initialState.eventSink(ChangeRolesEvent.UserSelectionToggled(userMember.toMatrixUser()))
awaitItem().also { awaitItem().also {
assertThat(it.selectedUsers).hasSize(1) assertThat(it.selectedUsers).hasSize(2)
it.eventSink(ChangeRolesEvent.Save) it.eventSink(ChangeRolesEvent.Save)
} }
val loadingState = awaitItem() val loadingState = awaitItem()
@ -553,13 +566,12 @@ class ChangeRolesPresenterTest {
} }
} }
private fun roomPowerLevelsWithRole( private fun roomPowerLevelsFromRoomMemberList(
role: RoomMember.Role, roomMemberList: List<RoomMember>,
userId: UserId = A_USER_ID,
): RoomPowerLevels { ): RoomPowerLevels {
return RoomPowerLevels( return RoomPowerLevels(
values = defaultRoomPowerLevelValues(), values = defaultRoomPowerLevelValues(),
users = persistentMapOf(userId to role.powerLevel) users = roomMemberList.associate { it.userId to it.role.powerLevel }.toImmutableMap()
) )
} }