Tapping on user avatar/name in the timeline opens the room member details (#1020)

* Implementation completed

* changelog

* code improvement

* Apply suggestions from code review

Co-authored-by: Stefan Ceriu <stefanc@matrix.org>

* pr suggestions

---------

Co-authored-by: Stefan Ceriu <stefanc@matrix.org>
This commit is contained in:
Mauro
2023-06-06 10:46:04 +02:00
committed by GitHub
parent ea4aa943e0
commit 4b2aba9367
24 changed files with 371 additions and 61 deletions
@@ -61,7 +61,7 @@ class InviteUsersScreenViewModelTests: XCTestCase {
func testInviteButton() async {
let mockedMembers: [RoomMemberProxyMock] = [.mockAlice, .mockBob]
setupWithRoomType(roomType: .room(members: mockedMembers, userIndicatorController: MockUserIndicatorController()))
setupWithRoomType(roomType: .room(members: mockedMembers, userIndicatorController: UserIndicatorControllerMock.default))
_ = await viewModel.context.$viewState.values.first(where: { $0.membershipState.isEmpty == false })
context.send(viewAction: .toggleUser(.mockAlice))
@@ -23,7 +23,7 @@ import XCTest
class RoomDetailsEditScreenViewModelTests: XCTestCase {
var viewModel: RoomDetailsEditScreenViewModel!
var userIndicatorController: MockUserIndicatorController!
var userIndicatorController: UserIndicatorControllerMock!
var context: RoomDetailsEditScreenViewModelType.Context {
viewModel.context
@@ -104,19 +104,14 @@ class RoomDetailsEditScreenViewModelTests: XCTestCase {
setupViewModel(accountOwner: .mockOwner(allowedStateEvents: [.roomAvatar, .roomName, .roomTopic]),
roomProxyConfiguration: .init(name: "Some room", displayName: "Some room"))
viewModel.didSelectMediaUrl(url: .picturesDirectory)
let alertInfo = await userIndicatorController.alertInfoPublisher
.compactMap { $0 }
.values
.first()
XCTAssertNotNil(alertInfo)
try? await Task.sleep(for: .milliseconds(100))
XCTAssertNotNil(userIndicatorController.alertInfo)
}
// MARK: - Private
private func setupViewModel(accountOwner: RoomMemberProxyMock, roomProxyConfiguration: RoomProxyMockConfiguration) {
userIndicatorController = MockUserIndicatorController()
userIndicatorController = UserIndicatorControllerMock.default
viewModel = .init(accountOwner: accountOwner,
mediaProvider: MockMediaProvider(),
roomProxy: RoomProxyMock(with: roomProxyConfiguration),
@@ -150,6 +150,94 @@ class RoomScreenViewModelTests: XCTestCase {
XCTAssertEqual(viewModel.state.items[1].timelineGroupStyle, .middle, "Nothing should prevent the second message from being grouped.")
XCTAssertEqual(viewModel.state.items[2].timelineGroupStyle, .last, "Reactions on the last message should not prevent it from being grouped.")
}
func testGoToUserDetailsSuccessNoDelay() async {
// Setup
let timelineController = MockRoomTimelineController()
let roomProxyMock = RoomProxyMock(with: .init(displayName: ""))
let roomMemberMock = RoomMemberProxyMock()
roomMemberMock.userID = "bob"
roomProxyMock.getMemberUserIDReturnValue = .success(roomMemberMock)
let userIndicatorControllerMock = UserIndicatorControllerMock.default
let viewModel = RoomScreenViewModel(timelineController: timelineController,
mediaProvider: MockMediaProvider(),
roomProxy: roomProxyMock,
userIndicatorController: userIndicatorControllerMock)
viewModel.callback = { action in
switch action {
case .displayRoomMemberDetails(let member):
XCTAssert(member === roomMemberMock)
default:
XCTFail("Did not received the expected action")
}
}
// Test
viewModel.context.send(viewAction: .tappedOnUser(userID: "bob"))
await Task.yield()
XCTAssertFalse(userIndicatorControllerMock.submitIndicatorCalled)
XCTAssert(roomProxyMock.getMemberUserIDCallsCount == 1)
XCTAssertEqual(roomProxyMock.getMemberUserIDReceivedUserID, "bob")
}
func testGoToUserDetailsSuccessWithDelay() async {
// Setup
let timelineController = MockRoomTimelineController()
let roomProxyMock = RoomProxyMock(with: .init(displayName: ""))
let roomMemberMock = RoomMemberProxyMock()
roomMemberMock.userID = "bob"
roomProxyMock.getMemberUserIDClosure = { _ in
try? await Task.sleep(for: .milliseconds(200))
return .success(roomMemberMock)
}
let userIndicatorControllerMock = UserIndicatorControllerMock.default
let viewModel = RoomScreenViewModel(timelineController: timelineController,
mediaProvider: MockMediaProvider(),
roomProxy: roomProxyMock,
userIndicatorController: userIndicatorControllerMock)
viewModel.callback = { action in
switch action {
case .displayRoomMemberDetails(let member):
XCTAssert(member === roomMemberMock)
default:
XCTFail("Did not received the expected action")
}
}
// Test
viewModel.context.send(viewAction: .tappedOnUser(userID: "bob"))
try? await Task.sleep(for: .milliseconds(300))
XCTAssert(userIndicatorControllerMock.submitIndicatorCallsCount == 1)
XCTAssert(userIndicatorControllerMock.retractIndicatorWithIdCallsCount == 1)
XCTAssert(roomProxyMock.getMemberUserIDCallsCount == 1)
XCTAssertEqual(roomProxyMock.getMemberUserIDReceivedUserID, "bob")
}
func testGoToUserDetailsFailure() async {
// Setup
let timelineController = MockRoomTimelineController()
let roomProxyMock = RoomProxyMock(with: .init(displayName: ""))
let roomMemberMock = RoomMemberProxyMock()
roomMemberMock.userID = "bob"
roomProxyMock.getMemberUserIDClosure = { _ in
.failure(.failedRetrievingMember)
}
let userIndicatorControllerMock = UserIndicatorControllerMock.default
let viewModel = RoomScreenViewModel(timelineController: timelineController,
mediaProvider: MockMediaProvider(),
roomProxy: roomProxyMock,
userIndicatorController: userIndicatorControllerMock)
viewModel.callback = { _ in
XCTFail("Should not receive any action")
}
// Test
viewModel.context.send(viewAction: .tappedOnUser(userID: "bob"))
await viewModel.context.nextViewState()
XCTAssertFalse(viewModel.state.bindings.alertInfo.isNil)
XCTAssert(roomProxyMock.getMemberUserIDCallsCount == 1)
XCTAssertEqual(roomProxyMock.getMemberUserIDReceivedUserID, "bob")
}
}
private extension TextRoomTimelineItem {