Move more MockTimelineController configuration to the constructor

This commit is contained in:
Stefan Ceriu
2026-05-29 12:35:50 +03:00
parent 4830424427
commit 423bd8073f
11 changed files with 73 additions and 105 deletions
@@ -17,18 +17,19 @@ extension TimelineControllerFactoryMock {
convenience init(_ configuration: Configuration) {
self.init()
buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderReturnValue = configuration.timelineController ?? {
let timelineController = MockTimelineController()
timelineController.timelineItems = RoomTimelineItemFixtures.largeChunk
return timelineController
}()
buildTimelineControllerRoomProxyInitialFocussedEventIDTimelineItemFactoryMediaProviderClosure = { _, _, _, _ in
if let timelineController = configuration.threadTimelineController {
return timelineController
} else {
return MockTimelineController(timelineItems: RoomTimelineItemFixtures.largeChunk)
}
}
buildThreadTimelineControllerThreadRootEventIDInitialFocussedEventIDRoomProxyTimelineItemFactoryMediaProviderClosure = { threadRootEventID, _, _, _, _ in
if let threadTimelineController = configuration.threadTimelineController {
return .success(threadTimelineController)
if let timelineController = configuration.threadTimelineController {
return .success(timelineController)
} else {
let timelineController = MockTimelineController(timelineKind: .thread(rootEventID: threadRootEventID))
timelineController.timelineItems = RoomTimelineItemFixtures.largeChunk
let timelineController = MockTimelineController(timelineKind: .thread(rootEventID: threadRootEventID), timelineItems: RoomTimelineItemFixtures.largeChunk)
return .success(timelineController)
}
}
@@ -163,8 +163,7 @@ struct TimelineMediaPreviewModifier_Previews: PreviewProvider {
thumbnailSource: nil,
contentType: .pdf))
let timelineController = MockTimelineController(timelineKind: .media(.mediaFilesScreen))
timelineController.timelineItems = [item]
let timelineController = MockTimelineController(timelineKind: .media(.mediaFilesScreen), timelineItems: [item])
let mediaProvider = MediaProviderMock(.init())
@@ -224,8 +224,7 @@ struct TimelineMediaPreviewDetailsView_Previews: PreviewProvider, TestablePrevie
contentType: contentType))
let timelineKind = TimelineKind.media(isPresentedOnRoomScreen ? .roomScreenLive : .mediaFilesScreen)
let timelineController = MockTimelineController(timelineKind: timelineKind)
timelineController.timelineItems = [item]
let timelineController = MockTimelineController(timelineKind: timelineKind, timelineItems: [item])
let viewModel = TimelineMediaPreviewViewModel(initialItem: item,
timelineViewModel: TimelineViewModel.mock(timelineKind: timelineKind,
@@ -142,8 +142,7 @@ struct TimelineMediaPreviewRedactConfirmationView_Previews: PreviewProvider, Tes
thumbnailInfo: .mockThumbnail,
contentType: contentType))
let timelineController = MockTimelineController(timelineKind: .media(.mediaFilesScreen))
timelineController.timelineItems = [item]
let timelineController = MockTimelineController(timelineKind: .media(.mediaFilesScreen), timelineItems: [item])
return TimelineMediaPreviewViewModel(initialItem: item,
timelineViewModel: TimelineViewModel.mock(timelineKind: timelineController.timelineKind,
timelineController: timelineController),
@@ -72,8 +72,7 @@ struct PinnedEventsTimelineScreen_Previews: PreviewProvider, TestablePreview {
analyticsService: AnalyticsServiceMock(.init()))
static let emptyTimelineViewModel: TimelineViewModel = {
let timelineController = MockTimelineController(timelineKind: .pinned)
timelineController.timelineItems = []
let timelineController = MockTimelineController(timelineKind: .pinned, timelineItems: [])
let appSettings = AppSettings.volatile()
@@ -115,8 +115,7 @@ private extension DateFormatter {
struct RoomPollsHistoryScreen_Previews: PreviewProvider, TestablePreview {
static let viewModelEmpty: RoomPollsHistoryScreenViewModel = {
let timelineController = MockTimelineController()
timelineController.timelineItems = []
let timelineController = MockTimelineController(timelineItems: [])
let roomProxyMockConfiguration = JoinedRoomProxyMockConfiguration(name: "Polls")
return RoomPollsHistoryScreenViewModel(pollInteractionHandler: PollInteractionHandlerMock(),
timelineController: timelineController,
@@ -124,20 +123,20 @@ struct RoomPollsHistoryScreen_Previews: PreviewProvider, TestablePreview {
}()
static let viewModel: RoomPollsHistoryScreenViewModel = {
let timelineController = MockTimelineController()
let polls = [PollRoomTimelineItem.mock(poll: .disclosed(createdByAccountOwner: false)),
PollRoomTimelineItem.mock(poll: .disclosed(createdByAccountOwner: true)),
PollRoomTimelineItem.mock(poll: .emptyDisclosed, isEditable: true)]
timelineController.timelineItems = polls
var timelineItemsTimestamps = [TimelineItemIdentifier: Date]()
for i in 0..<polls.count {
let item = polls[i]
let date: Date! = DateComponents(calendar: .current, timeZone: .gmt, year: 2023, month: 12, day: 1 + i, hour: 12).date
timelineController.timelineItemsTimestamp[item.id] = date
timelineItemsTimestamps[item.id] = date
}
let timelineController = MockTimelineController(timelineItems: polls,
timelineItemsTimestamps: timelineItemsTimestamps)
let roomProxyMockConfiguration = JoinedRoomProxyMockConfiguration(name: "Polls", timelineStartReached: true)
return RoomPollsHistoryScreenViewModel(pollInteractionHandler: PollInteractionHandlerMock(),
timelineController: timelineController,
@@ -16,34 +16,34 @@ class MockTimelineController: TimelineControllerProtocol {
private let lastInsertedMessageID: TimelineItemIdentifier = .event(uniqueID: .init("last_message"),
eventOrTransactionID: .eventID("last_message"))
/// An array of timeline item arrays that will be inserted in order for each back pagination request.
var backPaginationResponses: [[RoomTimelineItemProtocol]] = []
var roomProxy: JoinedRoomProxyProtocol?
var timelineProxy: TimelineProxyProtocol?
private var roomProxy: JoinedRoomProxyProtocol?
private var timelineProxy: TimelineProxyProtocol?
var roomID: String {
roomProxy?.id ?? "MockRoomIdentifier"
}
var timelineKind: TimelineKind
private(set) var timelineKind: TimelineKind
let callbacks = PassthroughSubject<TimelineControllerCallback, Never>()
private(set) var timelineItems: [RoomTimelineItemProtocol] = RoomTimelineItemFixtures.default {
didSet {
callbacks.send(.updatedTimelineItems(timelineItems: timelineItems, isSwitchingTimelines: false))
}
}
private let timelineItemsTimestamps: [TimelineItemIdentifier: Date]
/// An array of timeline item arrays that will be inserted in order for each back pagination request.
var backPaginationResponses: [[RoomTimelineItemProtocol]] = []
var paginationState: TimelinePaginationState = .initial {
didSet {
callbacks.send(.paginationState(paginationState))
}
}
var timelineItems: [RoomTimelineItemProtocol] = RoomTimelineItemFixtures.default {
didSet {
callbacks.send(.updatedTimelineItems(timelineItems: timelineItems, isSwitchingTimelines: false))
}
}
var timelineItemsTimestamp: [TimelineItemIdentifier: Date] = [:]
static var mediaGallery: MockTimelineController {
MockTimelineController(timelineKind: .media(.mediaFilesScreen), timelineItems: (0..<5).reduce([]) { partialResult, _ in
partialResult + [RoomTimelineItemFixtures.separator] + RoomTimelineItemFixtures.mediaChunk
@@ -56,12 +56,16 @@ class MockTimelineController: TimelineControllerProtocol {
return mock
}
init(timelineKind: TimelineKind = .live,
init(roomProxy: JoinedRoomProxyProtocol? = nil,
timelineKind: TimelineKind = .live,
timelineItems: [RoomTimelineItemProtocol] = RoomTimelineItemFixtures.default,
timelineProxy: TimelineProxyProtocol? = nil) {
timelineProxy: TimelineProxyProtocol? = nil,
timelineItemsTimestamps: [TimelineItemIdentifier: Date] = [TimelineItemIdentifier: Date]()) {
self.roomProxy = roomProxy
self.timelineKind = timelineKind
self.timelineItems = timelineItems
self.timelineProxy = timelineProxy
self.timelineItemsTimestamps = timelineItemsTimestamps
callbacks.send(.paginationState(paginationState))
callbacks.send(.isLive(true))
@@ -169,7 +173,7 @@ class MockTimelineController: TimelineControllerProtocol {
}
func eventTimestamp(for itemID: TimelineItemIdentifier) -> Date? {
timelineItemsTimestamp[itemID] ?? .now
timelineItemsTimestamps[itemID] ?? .now
}
// MARK: - Sending
@@ -308,8 +308,7 @@ class MockScreen: Identifiable {
return navigationStackCoordinator
case .roomSmallTimeline:
let navigationStackCoordinator = NavigationStackCoordinator()
let timelineController = MockTimelineController()
timelineController.timelineItems = RoomTimelineItemFixtures.smallChunk
let timelineController = MockTimelineController(timelineItems: RoomTimelineItemFixtures.smallChunk)
let parameters = RoomScreenCoordinatorParameters(userSession: UserSessionMock(.init()),
roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: .mockMXCAvatar)),
timelineController: timelineController,
@@ -330,8 +329,7 @@ class MockScreen: Identifiable {
return navigationStackCoordinator
case .roomSmallTimelineWithReactions:
let navigationStackCoordinator = NavigationStackCoordinator()
let timelineController = MockTimelineController()
timelineController.timelineItems = RoomTimelineItemFixtures.default
let timelineController = MockTimelineController(timelineItems: RoomTimelineItemFixtures.default)
let parameters = RoomScreenCoordinatorParameters(userSession: UserSessionMock(.init()),
roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: .mockMXCAvatar)),
timelineController: timelineController,
@@ -351,8 +349,7 @@ class MockScreen: Identifiable {
return navigationStackCoordinator
case .roomSmallTimelineWithReadReceipts:
let navigationStackCoordinator = NavigationStackCoordinator()
let timelineController = MockTimelineController()
timelineController.timelineItems = RoomTimelineItemFixtures.smallChunkWithReadReceipts
let timelineController = MockTimelineController(timelineItems: RoomTimelineItemFixtures.smallChunkWithReadReceipts)
let parameters = RoomScreenCoordinatorParameters(userSession: UserSessionMock(.init()),
roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: .mockMXCAvatar)),
timelineController: timelineController,
@@ -504,8 +501,7 @@ class MockScreen: Identifiable {
case .roomLayoutHighlight:
let navigationStackCoordinator = NavigationStackCoordinator()
let timelineController = MockTimelineController()
timelineController.timelineItems = RoomTimelineItemFixtures.permalinkChunk
let timelineController = MockTimelineController(timelineItems: RoomTimelineItemFixtures.permalinkChunk)
let parameters = RoomScreenCoordinatorParameters(userSession: UserSessionMock(.init()),
roomProxy: JoinedRoomProxyMock(.init(name: "Timeline highlight", avatarURL: .mockMXCAvatar)),
timelineController: timelineController,
@@ -540,8 +536,7 @@ class MockScreen: Identifiable {
case .roomWithDisclosedPolls:
let navigationStackCoordinator = NavigationStackCoordinator()
let timelineController = MockTimelineController()
timelineController.timelineItems = RoomTimelineItemFixtures.disclosedPolls
let timelineController = MockTimelineController(timelineItems: RoomTimelineItemFixtures.disclosedPolls)
let parameters = RoomScreenCoordinatorParameters(userSession: UserSessionMock(.init()),
roomProxy: JoinedRoomProxyMock(.init(name: "Polls timeline", avatarURL: .mockMXCAvatar)),
timelineController: timelineController,
@@ -563,8 +558,7 @@ class MockScreen: Identifiable {
case .roomWithUndisclosedPolls:
let navigationStackCoordinator = NavigationStackCoordinator()
let timelineController = MockTimelineController()
timelineController.timelineItems = RoomTimelineItemFixtures.undisclosedPolls
let timelineController = MockTimelineController(timelineItems: RoomTimelineItemFixtures.undisclosedPolls)
let parameters = RoomScreenCoordinatorParameters(userSession: UserSessionMock(.init()),
roomProxy: JoinedRoomProxyMock(.init(name: "Polls timeline", avatarURL: .mockMXCAvatar)),
timelineController: timelineController,
@@ -586,8 +580,7 @@ class MockScreen: Identifiable {
case .roomWithOutgoingPolls:
let navigationStackCoordinator = NavigationStackCoordinator()
let timelineController = MockTimelineController()
timelineController.timelineItems = RoomTimelineItemFixtures.outgoingPolls
let timelineController = MockTimelineController(timelineItems: RoomTimelineItemFixtures.outgoingPolls)
let parameters = RoomScreenCoordinatorParameters(userSession: UserSessionMock(.init()),
roomProxy: JoinedRoomProxyMock(.init(name: "Polls timeline", avatarURL: .mockMXCAvatar)),
timelineController: timelineController,
+9 -18
View File
@@ -81,8 +81,7 @@ struct PillContextTests {
let id = "test_room"
let displayName = "Test"
let proxyMock = JoinedRoomProxyMock(.init(id: id, name: displayName, avatarURL: avatarURL))
let mockController = MockTimelineController()
mockController.roomProxy = proxyMock
let mockController = MockTimelineController(roomProxy: proxyMock)
let mock = TimelineViewModel(roomProxy: proxyMock,
timelineController: mockController,
userSession: UserSessionMock(.init()),
@@ -106,10 +105,9 @@ struct PillContextTests {
let userIndicatorController = UserIndicatorControllerMock()
let proxyMock = JoinedRoomProxyMock(.init())
let mockController = MockTimelineController()
let mockController = MockTimelineController(roomProxy: proxyMock)
let clientMock = ClientProxyMock(.init())
clientMock.roomSummaryForIdentifierReturnValue = .mock(id: "1", name: "Foundation 🔭🪐🌌")
mockController.roomProxy = proxyMock
let mock = TimelineViewModel(roomProxy: proxyMock,
timelineController: mockController,
userSession: UserSessionMock(.init(clientProxy: clientMock)),
@@ -134,8 +132,7 @@ struct PillContextTests {
let userIndicatorController = UserIndicatorControllerMock()
let proxyMock = JoinedRoomProxyMock(.init())
let mockController = MockTimelineController()
mockController.roomProxy = proxyMock
let mockController = MockTimelineController(roomProxy: proxyMock)
let mock = TimelineViewModel(roomProxy: proxyMock,
timelineController: mockController,
userSession: UserSessionMock(.init()),
@@ -160,8 +157,7 @@ struct PillContextTests {
let userIndicatorController = UserIndicatorControllerMock()
let proxyMock = JoinedRoomProxyMock(.init())
let mockController = MockTimelineController()
mockController.roomProxy = proxyMock
let mockController = MockTimelineController(roomProxy: proxyMock)
let clientMock = ClientProxyMock(.init())
clientMock.roomSummaryForAliasReturnValue = .mock(id: "2",
name: "Foundation and Empire",
@@ -190,8 +186,7 @@ struct PillContextTests {
let userIndicatorController = UserIndicatorControllerMock()
let proxyMock = JoinedRoomProxyMock(.init())
let mockController = MockTimelineController()
mockController.roomProxy = proxyMock
let mockController = MockTimelineController(roomProxy: proxyMock)
let mock = TimelineViewModel(roomProxy: proxyMock,
timelineController: mockController,
userSession: UserSessionMock(.init()),
@@ -216,8 +211,7 @@ struct PillContextTests {
let userIndicatorController = UserIndicatorControllerMock()
let proxyMock = JoinedRoomProxyMock(.init())
let mockController = MockTimelineController()
mockController.roomProxy = proxyMock
let mockController = MockTimelineController(roomProxy: proxyMock)
let clientMock = ClientProxyMock(.init())
clientMock.roomSummaryForIdentifierReturnValue = .mock(id: "1", name: "Foundation 🔭🪐🌌")
let mock = TimelineViewModel(roomProxy: proxyMock,
@@ -244,8 +238,7 @@ struct PillContextTests {
let userIndicatorController = UserIndicatorControllerMock()
let proxyMock = JoinedRoomProxyMock(.init())
let mockController = MockTimelineController()
mockController.roomProxy = proxyMock
let mockController = MockTimelineController(roomProxy: proxyMock)
let mock = TimelineViewModel(roomProxy: proxyMock,
timelineController: mockController,
userSession: UserSessionMock(.init()),
@@ -270,8 +263,7 @@ struct PillContextTests {
let userIndicatorController = UserIndicatorControllerMock()
let proxyMock = JoinedRoomProxyMock(.init())
let mockController = MockTimelineController()
mockController.roomProxy = proxyMock
let mockController = MockTimelineController(roomProxy: proxyMock)
let clientMock = ClientProxyMock(.init())
clientMock.roomSummaryForAliasReturnValue = .mock(id: "2",
name: "Foundation and Empire",
@@ -300,8 +292,7 @@ struct PillContextTests {
let userIndicatorController = UserIndicatorControllerMock()
let proxyMock = JoinedRoomProxyMock(.init())
let mockController = MockTimelineController()
mockController.roomProxy = proxyMock
let mockController = MockTimelineController(roomProxy: proxyMock)
let mock = TimelineViewModel(roomProxy: proxyMock,
timelineController: mockController,
userSession: UserSessionMock(.init()),
@@ -292,8 +292,7 @@ struct TimelineMediaPreviewViewModelTests {
private mutating func setupViewModel(initialItemIndex: Int = 0, photoLibraryAuthorizationDenied: Bool = false) {
let initialItems = makeItems()
timelineController = MockTimelineController(timelineKind: .media(.mediaFilesScreen))
timelineController.timelineItems = initialItems
timelineController = MockTimelineController(timelineKind: .media(.mediaFilesScreen), timelineItems: initialItems)
mediaProvider = MediaProviderMock(.init())
photoLibraryManager = PhotoLibraryManagerMock(.init(authorizationDenied: photoLibraryAuthorizationDenied))
+15 -30
View File
@@ -35,8 +35,7 @@ final class TimelineViewModelTests {
]
// When showing them in a timeline.
let timelineController = MockTimelineController()
timelineController.timelineItems = items
let timelineController = MockTimelineController(timelineItems: items)
let viewModel = makeViewModel(timelineController: timelineController)
// Then the messages should be grouped together.
@@ -64,8 +63,7 @@ final class TimelineViewModelTests {
]
// When showing them in a timeline.
let timelineController = MockTimelineController()
timelineController.timelineItems = items
let timelineController = MockTimelineController(timelineItems: items)
let viewModel = makeViewModel(timelineController: timelineController)
// Then the messages should be grouped by sender.
@@ -91,8 +89,7 @@ final class TimelineViewModelTests {
]
// When showing them in a timeline.
let timelineController = MockTimelineController()
timelineController.timelineItems = items
let timelineController = MockTimelineController(timelineItems: items)
let viewModel = makeViewModel(timelineController: timelineController)
// Then the first message should not be grouped but the other two should.
@@ -115,8 +112,7 @@ final class TimelineViewModelTests {
]
// When showing them in a timeline.
let timelineController = MockTimelineController()
timelineController.timelineItems = items
let timelineController = MockTimelineController(timelineItems: items)
let viewModel = makeViewModel(timelineController: timelineController)
// Then the first and second messages should be grouped and the last one should not.
@@ -139,8 +135,7 @@ final class TimelineViewModelTests {
]
// When showing them in a timeline.
let timelineController = MockTimelineController()
timelineController.timelineItems = items
let timelineController = MockTimelineController(timelineItems: items)
let viewModel = makeViewModel(timelineController: timelineController)
// Then the messages should be grouped together.
@@ -157,8 +152,7 @@ final class TimelineViewModelTests {
let items = [TextRoomTimelineItem(eventID: "t1"),
TextRoomTimelineItem(eventID: "t2"),
TextRoomTimelineItem(eventID: "t3")]
let timelineController = MockTimelineController()
timelineController.timelineItems = items
let timelineController = MockTimelineController(timelineItems: items)
let viewModel = makeViewModel(timelineController: timelineController)
#expect(timelineController.focusOnEventCallCount == 0)
@@ -182,8 +176,7 @@ final class TimelineViewModelTests {
let items = [TextRoomTimelineItem(eventID: "t1"),
TextRoomTimelineItem(eventID: "t2"),
TextRoomTimelineItem(eventID: "t3")]
let timelineController = MockTimelineController()
timelineController.timelineItems = items
let timelineController = MockTimelineController(timelineItems: items)
let viewModel = makeViewModel(timelineController: timelineController)
#expect(timelineController.focusOnEventCallCount == 0)
@@ -207,8 +200,7 @@ final class TimelineViewModelTests {
let items = [TextRoomTimelineItem(eventID: "t1"),
TextRoomTimelineItem(eventID: "t2"),
TextRoomTimelineItem(eventID: "t3")]
let timelineController = MockTimelineController()
timelineController.timelineItems = items
let timelineController = MockTimelineController(timelineItems: items)
let viewModel = makeViewModel(timelineController: timelineController)
@@ -294,17 +286,13 @@ final class TimelineViewModelTests {
JoinedRoomProxyMock,
TimelineProxyMock,
MockTimelineController) {
let roomProxy = JoinedRoomProxyMock(.init(name: ""))
let timelineProxy = TimelineProxyMock()
roomProxy.timeline = timelineProxy
let timelineController = MockTimelineController()
timelineProxy.sendReadReceiptForTypeReturnValue = .success(())
timelineController.timelineItems = items
timelineController.roomProxy = roomProxy
let roomProxy = JoinedRoomProxyMock(.init(name: ""))
roomProxy.timeline = timelineProxy
let timelineController = MockTimelineController(roomProxy: roomProxy, timelineItems: items)
let appSettings = AppSettings.volatile()
@@ -335,8 +323,7 @@ final class TimelineViewModelTests {
let appSettings = AppSettings.volatile()
// When showing them in a timeline.
let timelineController = MockTimelineController()
timelineController.timelineItems = [message]
let timelineController = MockTimelineController(timelineItems: [message])
let viewModel = TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "", members: [RoomMemberProxyMock.mockAlice, RoomMemberProxyMock.mockCharlie])),
timelineController: timelineController,
userSession: UserSessionMock(.init()),
@@ -556,8 +543,7 @@ final class TimelineViewModelTests {
func tapSendInfoEncryptionAuthentictyDisplaysAlert() {
// Given a room with an event whose authenticity could not be verified
let items = [TextRoomTimelineItem(eventID: "t1", encryptionAuthenticity: .verificationViolation(color: .red))]
let timelineController = MockTimelineController()
timelineController.timelineItems = items
let timelineController = MockTimelineController(timelineItems: items)
let viewModel = makeViewModel(timelineController: timelineController)
#expect(viewModel.state.bindings.alertInfo == nil)
@@ -571,8 +557,7 @@ final class TimelineViewModelTests {
func tapSendInfoEncryptionForwarderDisplaysAlert() {
// Given a room with an event whose key was forwarded
let items = [TextRoomTimelineItem(eventID: "t1", keyForwarder: .test)]
let timelineController = MockTimelineController()
timelineController.timelineItems = items
let timelineController = MockTimelineController(timelineItems: items)
let viewModel = makeViewModel(timelineController: timelineController)
#expect(viewModel.state.bindings.alertInfo == nil)