Add the JoinRoomScreen into the SpaceFlowCoordinator. (#4513)

* Add the JoinRoomScreen into the SpaceFlowCoordinator.

The screen needs further work to make the join work.

* Fix the tests completing the join flow with the right action.
This commit is contained in:
Doug
2025-09-17 15:12:45 +01:00
committed by GitHub
parent c4de609ad7
commit 27f4c25194
22 changed files with 260 additions and 92 deletions
@@ -47,7 +47,7 @@ class JoinRoomScreenViewModelTests: XCTestCase {
XCTAssertTrue(appSettings.seenInvites.isEmpty, "Only an invited room should register the room ID as a seen invite.")
let deferred = deferFulfillment(viewModel.actionsPublisher) { $0 == .joined }
let deferred = deferFulfillment(viewModel.actionsPublisher) { $0 == .joined(.roomID("1")) }
context.send(viewAction: .join)
try await deferred.fulfill()
}
@@ -60,7 +60,7 @@ class JoinRoomScreenViewModelTests: XCTestCase {
XCTAssertEqual(appSettings.seenInvites, ["1"], "The invited room's ID should be registered as a seen invite.")
let deferred = deferFulfillment(viewModel.actionsPublisher) { $0 == .joined }
let deferred = deferFulfillment(viewModel.actionsPublisher) { $0 == .joined(.roomID("1")) }
context.send(viewAction: .acceptInvite)
try await deferred.fulfill()
@@ -156,6 +156,8 @@ class JoinRoomScreenViewModelTests: XCTestCase {
try await deferred.fulfill()
}
// MARK: - Helpers
private func setupViewModel(throwing: Bool = false, mode: TestMode = .joined) {
ServiceLocator.shared.settings.knockingEnabled = true
@@ -199,3 +201,21 @@ class JoinRoomScreenViewModelTests: XCTestCase {
userIndicatorController: ServiceLocator.shared.userIndicatorController)
}
}
extension JoinRoomScreenViewModelAction: @retroactive Equatable {
// A close enough approximation for tests.
public static func == (lhs: JoinRoomScreenViewModelAction, rhs: JoinRoomScreenViewModelAction) -> Bool {
switch (lhs, rhs) {
case (.joined(.roomID(let lhsRoomID)), .joined(.roomID(let rhsRoomID))):
lhsRoomID == rhsRoomID
case (.joined(.space(let lhsSpace)), .joined(.space(let rhsSpace))):
lhsSpace.spaceRoomProxy.id == rhsSpace.spaceRoomProxy.id
case (.dismiss, .dismiss):
true
case (.presentDeclineAndBlock(let lhsUserID), .presentDeclineAndBlock(let rhsUserID)):
lhsUserID == rhsUserID
default:
false
}
}
}
@@ -72,7 +72,10 @@ class SpaceListScreenViewModelTests: XCTestCase {
])
spaceServiceProxy = SpaceServiceProxyMock(.init())
spaceServiceProxy.joinedSpacesPublisher = joinedSpacesSubject.asCurrentValuePublisher()
spaceServiceProxy.spaceRoomListForClosure = { .success(SpaceRoomListProxyMock(.init(spaceRoomProxy: $0))) }
spaceServiceProxy.spaceRoomListSpaceIDClosure = { [joinedSpacesSubject] spaceID in
guard let spaceRoomProxy = joinedSpacesSubject?.value.first(where: { $0.id == spaceID }) else { return .failure(.missingSpace) }
return .success(SpaceRoomListProxyMock(.init(spaceRoomProxy: spaceRoomProxy)))
}
clientProxy.spaceService = spaceServiceProxy
viewModel = SpaceListScreenViewModel(userSession: userSession,
@@ -93,7 +93,7 @@ class SpaceScreenViewModelTests: XCTestCase {
func testSelectingSpace() async throws {
setupViewModel()
let selectedSpace = try XCTUnwrap(mockSpaceRooms.first { $0.isSpace }, "There should be a space to select.")
let selectedSpace = try XCTUnwrap(mockSpaceRooms.first { $0.isSpace && $0.state == .joined }, "There should be a space to select.")
let deferred = deferFulfillment(viewModel.actionsPublisher) { _ in true }
viewModel.context.send(viewAction: .spaceAction(.select(selectedSpace)))
let action = try await deferred.fulfill()
@@ -106,6 +106,22 @@ class SpaceScreenViewModelTests: XCTestCase {
}
}
func testSelectingUnjoinedSpace() async throws {
setupViewModel()
let selectedSpace = try XCTUnwrap(mockSpaceRooms.first { $0.isSpace && $0.state != .joined }, "There should be a space to select.")
let deferred = deferFulfillment(viewModel.actionsPublisher) { _ in true }
viewModel.context.send(viewAction: .spaceAction(.select(selectedSpace)))
let action = try await deferred.fulfill()
switch action {
case .selectUnjoinedSpace(let spaceRoomProxy) where spaceRoomProxy.id == selectedSpace.id:
break
default:
XCTFail("The action should select the space.")
}
}
func testSelectingRoom() async throws {
setupViewModel()
@@ -125,7 +141,7 @@ class SpaceScreenViewModelTests: XCTestCase {
func testJoiningSpace() async throws {
setupViewModel()
let selectedSpace = try XCTUnwrap(mockSpaceRooms.first { $0.isSpace }, "There should be a space to select.")
let selectedSpace = try XCTUnwrap(mockSpaceRooms.first { $0.isSpace && $0.state != .joined }, "There should be a space to select.")
let expectation = XCTestExpectation(description: "Join room")
clientProxy.joinRoomViaClosure = { _, _ in
@@ -184,7 +200,10 @@ class SpaceScreenViewModelTests: XCTestCase {
paginationResponses: paginationResponses))
let spaceServiceProxy = SpaceServiceProxyMock(.init())
spaceServiceProxy.spaceRoomListForClosure = { .success(SpaceRoomListProxyMock(.init(spaceRoomProxy: $0))) }
spaceServiceProxy.spaceRoomListSpaceIDClosure = { [mockSpaceRooms] spaceID in
guard let spaceRoomProxy = mockSpaceRooms.first(where: { $0.id == spaceID }) else { return .failure(.missingSpace) }
return .success(SpaceRoomListProxyMock(.init(spaceRoomProxy: spaceRoomProxy)))
}
clientProxy = ClientProxyMock(.init())