mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 21:33:26 +00:00
Always open manage member sheet (#4110)
* always open manage member sheet * Update ElementX/Sources/Screens/ManageRoomMemberSheet/ManageRoomMemberSheetModels.swift Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com> * Update ElementX/Sources/Screens/ManageRoomMemberSheet/ManageRoomMemberSheetModels.swift Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com> * pr suggestions and handled the buttons actions correctly * Update ElementX/Sources/Screens/ManageRoomMemberSheet/View/ManageRoomMemberSheetView.swift Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com> * fixed some compilation errors * added some documentation * using a struct instead of a protocol * using arguments instead of a struct --------- Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com>
This commit is contained in:
@@ -27,9 +27,8 @@ class ManageRoomMemberSheetViewModelTests: XCTestCase {
|
||||
return .success(())
|
||||
}
|
||||
|
||||
viewModel = ManageRoomMemberSheetViewModel(member: RoomMemberDetails(withProxy: RoomMemberProxyMock.mockAlice),
|
||||
canKick: true,
|
||||
canBan: true,
|
||||
viewModel = ManageRoomMemberSheetViewModel(memberDetails: .memberDetails(roomMember: .init(withProxy: RoomMemberProxyMock.mockAlice)),
|
||||
permissions: .init(canKick: true, canBan: true, ownPowerLevel: RoomMemberProxyMock.mockAdmin.powerLevel),
|
||||
roomProxy: roomProxy,
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
analyticsService: ServiceLocator.shared.analytics,
|
||||
@@ -59,9 +58,8 @@ class ManageRoomMemberSheetViewModelTests: XCTestCase {
|
||||
return .success(())
|
||||
}
|
||||
|
||||
viewModel = ManageRoomMemberSheetViewModel(member: RoomMemberDetails(withProxy: RoomMemberProxyMock.mockAlice),
|
||||
canKick: true,
|
||||
canBan: true,
|
||||
viewModel = ManageRoomMemberSheetViewModel(memberDetails: .memberDetails(roomMember: .init(withProxy: RoomMemberProxyMock.mockAlice)),
|
||||
permissions: .init(canKick: true, canBan: true, ownPowerLevel: RoomMemberProxyMock.mockAdmin.powerLevel),
|
||||
roomProxy: roomProxy,
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
analyticsService: ServiceLocator.shared.analytics,
|
||||
@@ -82,9 +80,8 @@ class ManageRoomMemberSheetViewModelTests: XCTestCase {
|
||||
|
||||
func testDisplayDetails() async throws {
|
||||
let roomProxy = JoinedRoomProxyMock(.init(members: [RoomMemberProxyMock.mockAdmin, RoomMemberProxyMock.mockAlice]))
|
||||
viewModel = ManageRoomMemberSheetViewModel(member: RoomMemberDetails(withProxy: RoomMemberProxyMock.mockAlice),
|
||||
canKick: true,
|
||||
canBan: true,
|
||||
viewModel = ManageRoomMemberSheetViewModel(memberDetails: .memberDetails(roomMember: .init(withProxy: RoomMemberProxyMock.mockAlice)),
|
||||
permissions: .init(canKick: true, canBan: true, ownPowerLevel: RoomMemberProxyMock.mockAdmin.powerLevel),
|
||||
roomProxy: roomProxy,
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
analyticsService: ServiceLocator.shared.analytics,
|
||||
|
||||
@@ -18,6 +18,11 @@ class RoomMembersListScreenViewModelTests: XCTestCase {
|
||||
viewModel.context
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
viewModel = nil
|
||||
roomProxy = nil
|
||||
}
|
||||
|
||||
func testJoinedMembers() async throws {
|
||||
setup(with: [.mockAlice, .mockBob])
|
||||
|
||||
@@ -130,11 +135,11 @@ class RoomMembersListScreenViewModelTests: XCTestCase {
|
||||
func testSelectUserAsUser() async throws {
|
||||
// Given the room list viewed as a regular user.
|
||||
setup(with: .allMembers)
|
||||
let deferred = deferFulfillment(context.$viewState) { !$0.visibleInvitedMembers.isEmpty }
|
||||
var deferred = deferFulfillment(context.$viewState) { !$0.visibleInvitedMembers.isEmpty }
|
||||
try await deferred.fulfill()
|
||||
|
||||
// When tapping on another user in the list.
|
||||
let memberDetailsAction = deferFulfillment(viewModel.actions) { $0.isSelectMember }
|
||||
deferred = deferFulfillment(context.$viewState) { $0.bindings.manageMemeberViewModel != nil }
|
||||
guard let user = viewModel.state.visibleJoinedMembers.first(where: { $0.member.role == .user && $0.member.id != RoomMemberProxyMock.mockMe.userID })?.member else {
|
||||
XCTFail("Expected to find a regular user.")
|
||||
return
|
||||
@@ -142,8 +147,11 @@ class RoomMembersListScreenViewModelTests: XCTestCase {
|
||||
context.send(viewAction: .selectMember(user))
|
||||
|
||||
// Then the member's details should be shown.
|
||||
try await memberDetailsAction.fulfill()
|
||||
XCTAssertNil(context.manageMemeberViewModel)
|
||||
try await deferred.fulfill()
|
||||
XCTAssertNotNil(context.manageMemeberViewModel)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.memberDetails.id, user.id)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.permissions.canKick, false)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.permissions.canBan, false)
|
||||
}
|
||||
|
||||
func testSelectUserAsAdmin() async throws {
|
||||
@@ -163,9 +171,12 @@ class RoomMembersListScreenViewModelTests: XCTestCase {
|
||||
try await deferred.fulfill()
|
||||
|
||||
// Then member management should be shown for that user.
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.member, user)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.canKick, true)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.canBan, true)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.memberDetails.id, user.id)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.permissions.canKick, true)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.permissions.canBan, true)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.isKickDisabled, false)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.isBanUnbanDisabled, false)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.isMemberBanned, false)
|
||||
}
|
||||
|
||||
func testSelectModeratorAsAdmin() async throws {
|
||||
@@ -185,19 +196,22 @@ class RoomMembersListScreenViewModelTests: XCTestCase {
|
||||
try await deferred.fulfill()
|
||||
|
||||
// Then member management should be shown for the moderator.
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.member, moderator)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.canKick, true)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.canBan, true)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.memberDetails.id, moderator.id)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.permissions.canKick, true)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.permissions.canBan, true)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.isMemberBanned, false)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.isKickDisabled, false)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.isBanUnbanDisabled, false)
|
||||
}
|
||||
|
||||
func testSelectAdminAsAdmin() async throws {
|
||||
// Given the room list viewed as an admin.
|
||||
setup(with: .allMembersAsAdmin)
|
||||
let deferred = deferFulfillment(context.$viewState) { !$0.visibleInvitedMembers.isEmpty }
|
||||
var deferred = deferFulfillment(context.$viewState) { !$0.visibleInvitedMembers.isEmpty && $0.canKickUsers && $0.canBanUsers }
|
||||
try await deferred.fulfill()
|
||||
|
||||
// When tapping on another administrator in the list.
|
||||
let memberDetailsAction = deferFulfillment(viewModel.actions) { $0.isSelectMember }
|
||||
deferred = deferFulfillment(context.$viewState) { $0.bindings.manageMemeberViewModel != nil }
|
||||
guard let admin = viewModel.state.visibleJoinedMembers.first(where: { $0.member.role == .administrator && $0.member.id != RoomMemberProxyMock.mockMe.userID })?.member else {
|
||||
XCTFail("Expected to find another admin.")
|
||||
return
|
||||
@@ -205,8 +219,13 @@ class RoomMembersListScreenViewModelTests: XCTestCase {
|
||||
context.send(viewAction: .selectMember(admin))
|
||||
|
||||
// Then the administrator's details should be shown.
|
||||
try await memberDetailsAction.fulfill()
|
||||
XCTAssertNil(context.manageMemeberViewModel)
|
||||
try await deferred.fulfill()
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.memberDetails.id, admin.id)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.permissions.canKick, true)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.permissions.canBan, true)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.isKickDisabled, true)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.isBanUnbanDisabled, true)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.isMemberBanned, false)
|
||||
}
|
||||
|
||||
func testSelectOwnMemberAsAdmin() async throws {
|
||||
@@ -231,12 +250,12 @@ class RoomMembersListScreenViewModelTests: XCTestCase {
|
||||
func testSelectBannedMember() async throws {
|
||||
// Given the room list viewed as an admin.
|
||||
setup(with: .allMembersAsAdmin + RoomMemberProxyMock.mockBanned)
|
||||
var deferred = deferFulfillment(context.$viewState) { !$0.visibleInvitedMembers.isEmpty }
|
||||
var deferred = deferFulfillment(context.$viewState) { !$0.visibleInvitedMembers.isEmpty && $0.canKickUsers && $0.canBanUsers }
|
||||
try await deferred.fulfill()
|
||||
XCTAssertNil(context.alertInfo)
|
||||
|
||||
// When tapping on a banned member in the list.
|
||||
deferred = deferFulfillment(context.$viewState) { $0.bindings.alertInfo != nil }
|
||||
deferred = deferFulfillment(context.$viewState) { $0.bindings.manageMemeberViewModel != nil }
|
||||
guard let bannedMember = viewModel.state.visibleBannedMembers.first?.member else {
|
||||
XCTFail("Expected to find a banned user.")
|
||||
return
|
||||
@@ -245,21 +264,12 @@ class RoomMembersListScreenViewModelTests: XCTestCase {
|
||||
|
||||
// Then an alert should be shown to unban the user.
|
||||
try await deferred.fulfill()
|
||||
XCTAssertNil(context.manageMemeberViewModel)
|
||||
XCTAssertNotNil(context.alertInfo)
|
||||
}
|
||||
|
||||
func testUnbanMember() async throws {
|
||||
setup(with: .allMembersAsAdmin)
|
||||
let deferred = deferFulfillment(context.$viewState) { !$0.visibleJoinedMembers.isEmpty }
|
||||
try await deferred.fulfill()
|
||||
|
||||
context.send(viewAction: .unbanMember(viewModel.state.visibleJoinedMembers[0].member))
|
||||
|
||||
// Calling the mock won't actually change any view state, so sleep instead.
|
||||
try await Task.sleep(for: .milliseconds(100))
|
||||
|
||||
XCTAssert(roomProxy.unbanUserCalled)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.memberDetails.id, bannedMember.id)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.permissions.canKick, true)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.permissions.canBan, true)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.isKickDisabled, true)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.isBanUnbanDisabled, false)
|
||||
XCTAssertEqual(context.manageMemeberViewModel?.state.isMemberBanned, true)
|
||||
}
|
||||
|
||||
private func setup(with members: [RoomMemberProxyMock]) {
|
||||
|
||||
@@ -377,12 +377,14 @@ class TimelineViewModelTests: XCTestCase {
|
||||
value.bindings.manageMemberViewModel != nil
|
||||
}
|
||||
|
||||
viewModel.context.send(viewAction: .tappedOnSenderDetails(userID: RoomMemberProxyMock.mockAlice.userID))
|
||||
viewModel.context.send(viewAction: .tappedOnSenderDetails(sender: .init(with: RoomMemberProxyMock.mockAlice)))
|
||||
try await deferred.fulfill()
|
||||
|
||||
XCTAssertEqual(viewModel.context.manageMemberViewModel?.state.member.id, RoomMemberProxyMock.mockAlice.userID)
|
||||
XCTAssertEqual(viewModel.context.manageMemberViewModel?.state.canBan, true)
|
||||
XCTAssertEqual(viewModel.context.manageMemberViewModel?.state.canKick, true)
|
||||
XCTAssertEqual(viewModel.context.manageMemberViewModel?.id, RoomMemberProxyMock.mockAlice.userID)
|
||||
XCTAssertEqual(viewModel.context.manageMemberViewModel?.state.permissions.canBan, true)
|
||||
XCTAssertEqual(viewModel.context.manageMemberViewModel?.state.permissions.canKick, true)
|
||||
XCTAssertEqual(viewModel.context.manageMemberViewModel?.state.isKickDisabled, false)
|
||||
XCTAssertEqual(viewModel.context.manageMemberViewModel?.state.isBanUnbanDisabled, false)
|
||||
}
|
||||
|
||||
func testShowDetailsForAnAdmin() async throws {
|
||||
@@ -402,25 +404,24 @@ class TimelineViewModelTests: XCTestCase {
|
||||
timelineControllerFactory: TimelineControllerFactoryMock(.init()),
|
||||
clientProxy: ClientProxyMock(.init()))
|
||||
|
||||
let deferredState = deferFulfillment(viewModel.context.$viewState) { value in
|
||||
var deferredState = deferFulfillment(viewModel.context.$viewState) { value in
|
||||
!value.canCurrentUserKick && !value.canCurrentUserBan
|
||||
}
|
||||
|
||||
try await deferredState.fulfill()
|
||||
|
||||
let deferredAction = deferFulfillment(viewModel.actions) { action in
|
||||
switch action {
|
||||
case .displaySenderDetails(let userID):
|
||||
return userID == RoomMemberProxyMock.mockAdmin.userID
|
||||
default:
|
||||
return false
|
||||
}
|
||||
deferredState = deferFulfillment(viewModel.context.$viewState) { value in
|
||||
value.bindings.manageMemberViewModel != nil
|
||||
}
|
||||
|
||||
viewModel.context.send(viewAction: .tappedOnSenderDetails(userID: RoomMemberProxyMock.mockAdmin.userID))
|
||||
try await deferredAction.fulfill()
|
||||
viewModel.context.send(viewAction: .tappedOnSenderDetails(sender: .init(with: RoomMemberProxyMock.mockAdmin)))
|
||||
try await deferredState.fulfill()
|
||||
|
||||
XCTAssertNil(viewModel.context.manageMemberViewModel)
|
||||
XCTAssertEqual(viewModel.context.manageMemberViewModel?.state.permissions.canBan, false)
|
||||
XCTAssertEqual(viewModel.context.manageMemberViewModel?.state.permissions.canKick, false)
|
||||
XCTAssertEqual(viewModel.context.manageMemberViewModel?.state.isKickDisabled, true)
|
||||
XCTAssertEqual(viewModel.context.manageMemberViewModel?.state.isBanUnbanDisabled, true)
|
||||
XCTAssertEqual(viewModel.context.manageMemberViewModel?.id, RoomMemberProxyMock.mockAdmin.userID)
|
||||
}
|
||||
|
||||
func testShowDetailsForABannedUser() async throws {
|
||||
@@ -440,25 +441,25 @@ class TimelineViewModelTests: XCTestCase {
|
||||
timelineControllerFactory: TimelineControllerFactoryMock(.init()),
|
||||
clientProxy: ClientProxyMock(.init()))
|
||||
|
||||
let deferredState = deferFulfillment(viewModel.context.$viewState) { value in
|
||||
var deferredState = deferFulfillment(viewModel.context.$viewState) { value in
|
||||
value.canCurrentUserKick && value.canCurrentUserBan
|
||||
}
|
||||
|
||||
try await deferredState.fulfill()
|
||||
|
||||
let deferredAction = deferFulfillment(viewModel.actions) { action in
|
||||
switch action {
|
||||
case .displaySenderDetails(let userID):
|
||||
return userID == RoomMemberProxyMock.mockBanned[0].userID
|
||||
default:
|
||||
return false
|
||||
}
|
||||
deferredState = deferFulfillment(viewModel.context.$viewState) { value in
|
||||
value.bindings.manageMemberViewModel != nil
|
||||
}
|
||||
|
||||
viewModel.context.send(viewAction: .tappedOnSenderDetails(userID: RoomMemberProxyMock.mockBanned[0].userID))
|
||||
try await deferredAction.fulfill()
|
||||
viewModel.context.send(viewAction: .tappedOnSenderDetails(sender: .init(with: RoomMemberProxyMock.mockBanned[0])))
|
||||
try await deferredState.fulfill()
|
||||
|
||||
XCTAssertNil(viewModel.context.manageMemberViewModel)
|
||||
XCTAssertEqual(viewModel.context.manageMemberViewModel?.state.permissions.canBan, true)
|
||||
XCTAssertEqual(viewModel.context.manageMemberViewModel?.state.permissions.canKick, true)
|
||||
XCTAssertEqual(viewModel.context.manageMemberViewModel?.state.isKickDisabled, true)
|
||||
XCTAssertEqual(viewModel.context.manageMemberViewModel?.state.isBanUnbanDisabled, false)
|
||||
XCTAssertEqual(viewModel.context.manageMemberViewModel?.state.isMemberBanned, true)
|
||||
XCTAssertEqual(viewModel.context.manageMemberViewModel?.id, RoomMemberProxyMock.mockBanned[0].userID)
|
||||
}
|
||||
|
||||
// MARK: - Pins
|
||||
@@ -576,3 +577,12 @@ private extension TextRoomTimelineItem {
|
||||
content: .init(body: "Hello, World!"))
|
||||
}
|
||||
}
|
||||
|
||||
private extension TimelineItemSender {
|
||||
init(with proxy: RoomMemberProxyMock) {
|
||||
self.init(id: proxy.userID,
|
||||
displayName: proxy.displayName ?? "",
|
||||
isDisplayNameAmbiguous: false,
|
||||
avatarURL: proxy.avatarURL)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user