mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 12:07:55 +00:00
Permalink Tweaks (#2768)
* Revert back to creating a new flow when re-selecting the same room. Fix the composer bug by adding IDs to the all of the module AnyViews. * Don't show the live timeline when starting with a focussed event.
This commit is contained in:
@@ -22,6 +22,7 @@ import Combine
|
||||
@MainActor
|
||||
class RoomFlowCoordinatorTests: XCTestCase {
|
||||
var clientProxy: ClientProxyMock!
|
||||
var timelineControllerFactory: RoomTimelineControllerFactoryMock!
|
||||
var roomFlowCoordinator: RoomFlowCoordinator!
|
||||
var navigationStackCoordinator: NavigationStackCoordinator!
|
||||
var cancellables = Set<AnyCancellable>()
|
||||
@@ -216,7 +217,7 @@ class RoomFlowCoordinatorTests: XCTestCase {
|
||||
XCTAssert(navigationStackCoordinator.rootCoordinator is RoomScreenCoordinator)
|
||||
XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 0)
|
||||
|
||||
try await process(route: .event(roomID: "1", eventID: "2"))
|
||||
try await process(route: .childEvent(roomID: "1", eventID: "2"))
|
||||
XCTAssert(navigationStackCoordinator.rootCoordinator is RoomScreenCoordinator)
|
||||
XCTAssertEqual(navigationStackCoordinator.stackCoordinators.count, 0)
|
||||
|
||||
@@ -269,6 +270,7 @@ class RoomFlowCoordinatorTests: XCTestCase {
|
||||
private func setupRoomFlowCoordinator(asChildFlow: Bool = false, roomType: RoomType? = nil) async {
|
||||
cancellables.removeAll()
|
||||
clientProxy = ClientProxyMock(.init(userID: "hi@bob", roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms)))))
|
||||
timelineControllerFactory = RoomTimelineControllerFactoryMock(configuration: .init())
|
||||
|
||||
clientProxy.roomPreviewForIdentifierClosure = { [roomType] roomID in
|
||||
switch roomType {
|
||||
@@ -309,7 +311,7 @@ class RoomFlowCoordinatorTests: XCTestCase {
|
||||
roomFlowCoordinator = await RoomFlowCoordinator(roomID: roomID,
|
||||
userSession: userSession,
|
||||
isChildFlow: asChildFlow,
|
||||
roomTimelineControllerFactory: MockRoomTimelineControllerFactory(),
|
||||
roomTimelineControllerFactory: timelineControllerFactory,
|
||||
navigationStackCoordinator: navigationStackCoordinator,
|
||||
emojiProvider: EmojiProvider(),
|
||||
appMediator: AppMediatorMock.default,
|
||||
|
||||
@@ -172,6 +172,7 @@ class RoomScreenViewModelTests: XCTestCase {
|
||||
XCTAssertEqual(timelineController.focusOnEventCallCount, 0)
|
||||
XCTAssertTrue(viewModel.context.viewState.timelineViewState.isLive)
|
||||
XCTAssertNil(viewModel.context.viewState.timelineViewState.focussedEventID)
|
||||
XCTAssertFalse(viewModel.context.viewState.timelineViewState.focussedEventNeedsDisplay)
|
||||
|
||||
// When focussing on an item that isn't loaded.
|
||||
let deferred = deferFulfillment(viewModel.context.$viewState) { !$0.timelineViewState.isLive }
|
||||
@@ -182,6 +183,7 @@ class RoomScreenViewModelTests: XCTestCase {
|
||||
XCTAssertEqual(timelineController.focusOnEventCallCount, 1)
|
||||
XCTAssertFalse(viewModel.context.viewState.timelineViewState.isLive)
|
||||
XCTAssertEqual(viewModel.context.viewState.timelineViewState.focussedEventID, "t4")
|
||||
XCTAssertTrue(viewModel.context.viewState.timelineViewState.focussedEventNeedsDisplay)
|
||||
}
|
||||
|
||||
func testFocusLoadedItem() async throws {
|
||||
@@ -196,6 +198,7 @@ class RoomScreenViewModelTests: XCTestCase {
|
||||
XCTAssertEqual(timelineController.focusOnEventCallCount, 0)
|
||||
XCTAssertTrue(viewModel.context.viewState.timelineViewState.isLive)
|
||||
XCTAssertNil(viewModel.context.viewState.timelineViewState.focussedEventID)
|
||||
XCTAssertFalse(viewModel.context.viewState.timelineViewState.focussedEventNeedsDisplay)
|
||||
|
||||
// When focussing on a loaded item.
|
||||
let deferred = deferFailure(viewModel.context.$viewState, timeout: 1) { !$0.timelineViewState.isLive }
|
||||
@@ -206,6 +209,7 @@ class RoomScreenViewModelTests: XCTestCase {
|
||||
XCTAssertEqual(timelineController.focusOnEventCallCount, 0)
|
||||
XCTAssertTrue(viewModel.context.viewState.timelineViewState.isLive)
|
||||
XCTAssertEqual(viewModel.context.viewState.timelineViewState.focussedEventID, "t1")
|
||||
XCTAssertTrue(viewModel.context.viewState.timelineViewState.focussedEventNeedsDisplay)
|
||||
}
|
||||
|
||||
func testFocusLive() async throws {
|
||||
@@ -225,6 +229,7 @@ class RoomScreenViewModelTests: XCTestCase {
|
||||
XCTAssertEqual(timelineController.focusLiveCallCount, 0)
|
||||
XCTAssertFalse(viewModel.context.viewState.timelineViewState.isLive)
|
||||
XCTAssertEqual(viewModel.context.viewState.timelineViewState.focussedEventID, "t4")
|
||||
XCTAssertTrue(viewModel.context.viewState.timelineViewState.focussedEventNeedsDisplay)
|
||||
|
||||
// When switching back to a live timeline.
|
||||
deferred = deferFulfillment(viewModel.context.$viewState) { $0.timelineViewState.isLive }
|
||||
@@ -235,6 +240,15 @@ class RoomScreenViewModelTests: XCTestCase {
|
||||
XCTAssertEqual(timelineController.focusLiveCallCount, 1)
|
||||
XCTAssertTrue(viewModel.context.viewState.timelineViewState.isLive)
|
||||
XCTAssertNil(viewModel.context.viewState.timelineViewState.focussedEventID)
|
||||
XCTAssertFalse(viewModel.context.viewState.timelineViewState.focussedEventNeedsDisplay)
|
||||
}
|
||||
|
||||
func testInitialFocusViewState() async throws {
|
||||
let timelineController = MockRoomTimelineController()
|
||||
|
||||
let viewModel = makeViewModel(focussedEventID: "t10", timelineController: timelineController)
|
||||
XCTAssertEqual(viewModel.context.viewState.timelineViewState.focussedEventID, "t10")
|
||||
XCTAssertTrue(viewModel.context.viewState.timelineViewState.focussedEventNeedsDisplay)
|
||||
}
|
||||
|
||||
// MARK: - Sending
|
||||
@@ -464,8 +478,11 @@ class RoomScreenViewModelTests: XCTestCase {
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
private func makeViewModel(roomProxy: RoomProxyProtocol? = nil, timelineController: RoomTimelineControllerProtocol) -> RoomScreenViewModel {
|
||||
private func makeViewModel(roomProxy: RoomProxyProtocol? = nil,
|
||||
focussedEventID: String? = nil,
|
||||
timelineController: RoomTimelineControllerProtocol) -> RoomScreenViewModel {
|
||||
RoomScreenViewModel(roomProxy: roomProxy ?? RoomProxyMock(with: .init(name: "")),
|
||||
focussedEventID: focussedEventID,
|
||||
timelineController: timelineController,
|
||||
mediaProvider: MockMediaProvider(),
|
||||
mediaPlayerProvider: MediaPlayerProviderMock(),
|
||||
|
||||
@@ -22,6 +22,7 @@ import Combine
|
||||
@MainActor
|
||||
class UserSessionFlowCoordinatorTests: XCTestCase {
|
||||
var clientProxy: ClientProxyMock!
|
||||
var timelineControllerFactory: RoomTimelineControllerFactoryMock!
|
||||
var userSessionFlowCoordinator: UserSessionFlowCoordinator!
|
||||
var navigationRootCoordinator: NavigationRootCoordinator!
|
||||
var notificationManager: NotificationManagerMock!
|
||||
@@ -35,6 +36,7 @@ class UserSessionFlowCoordinatorTests: XCTestCase {
|
||||
override func setUp() async throws {
|
||||
cancellables.removeAll()
|
||||
clientProxy = ClientProxyMock(.init(userID: "hi@bob", roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms)))))
|
||||
timelineControllerFactory = RoomTimelineControllerFactoryMock(configuration: .init())
|
||||
let mediaProvider = MockMediaProvider()
|
||||
let voiceMessageMediaManager = VoiceMessageMediaManagerMock()
|
||||
let userSession = MockUserSession(clientProxy: clientProxy,
|
||||
@@ -49,7 +51,7 @@ class UserSessionFlowCoordinatorTests: XCTestCase {
|
||||
navigationRootCoordinator: navigationRootCoordinator,
|
||||
appLockService: AppLockServiceMock(),
|
||||
bugReportService: BugReportServiceMock(),
|
||||
roomTimelineControllerFactory: MockRoomTimelineControllerFactory(),
|
||||
roomTimelineControllerFactory: timelineControllerFactory,
|
||||
appMediator: AppMediatorMock.default,
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
@@ -216,22 +218,40 @@ class UserSessionFlowCoordinatorTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testEventRoutes() async throws {
|
||||
// A regular event route should set its room as the root of the stack and focus on the event.
|
||||
try await process(route: .event(roomID: "1", eventID: "1"), expectedState: .roomList(selectedRoomID: "1"))
|
||||
XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator)
|
||||
XCTAssertEqual(detailNavigationStack?.stackCoordinators.count, 0)
|
||||
XCTAssertNotNil(detailCoordinator)
|
||||
XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryCallsCount, 1)
|
||||
XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryReceivedArguments?.initialFocussedEventID, "1")
|
||||
|
||||
// A child event route should push a new room screen onto the stack and focus on the event.
|
||||
userSessionFlowCoordinator.handleAppRoute(.childEvent(roomID: "2", eventID: "2"), animated: true)
|
||||
try await Task.sleep(for: .milliseconds(100))
|
||||
XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator)
|
||||
XCTAssertEqual(detailNavigationStack?.stackCoordinators.count, 1)
|
||||
XCTAssertTrue(detailNavigationStack?.stackCoordinators.first is RoomScreenCoordinator)
|
||||
XCTAssertNotNil(detailCoordinator)
|
||||
XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryCallsCount, 2)
|
||||
XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryReceivedArguments?.initialFocussedEventID, "2")
|
||||
|
||||
// A subsequent regular event route should clear the stack and set the new room as the root of the stack.
|
||||
try await process(route: .event(roomID: "3", eventID: "3"), expectedState: .roomList(selectedRoomID: "3"))
|
||||
XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator)
|
||||
XCTAssertEqual(detailNavigationStack?.stackCoordinators.count, 0)
|
||||
XCTAssertNotNil(detailCoordinator)
|
||||
XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryCallsCount, 3)
|
||||
XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryReceivedArguments?.initialFocussedEventID, "3")
|
||||
|
||||
// A regular event route for the same room should set a new instance of the room as the root of the stack.
|
||||
try await process(route: .event(roomID: "3", eventID: "4"), expectedState: .roomList(selectedRoomID: "3"))
|
||||
XCTAssertTrue(detailNavigationStack?.rootCoordinator is RoomScreenCoordinator)
|
||||
XCTAssertEqual(detailNavigationStack?.stackCoordinators.count, 0)
|
||||
XCTAssertNotNil(detailCoordinator)
|
||||
XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryCallsCount, 4)
|
||||
XCTAssertEqual(timelineControllerFactory.buildRoomTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryReceivedArguments?.initialFocussedEventID, "4",
|
||||
"A new timeline should be created for the same room ID, so that the screen isn't stale while loading.")
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
Reference in New Issue
Block a user