Fix unit tests.

This commit is contained in:
Doug
2026-09-25 14:17:15 +01:00
committed by Stefan Ceriu
parent fccad5fc30
commit c0469e681f
34 changed files with 239 additions and 301 deletions
@@ -23,7 +23,7 @@ final class AnalyticsSettingsScreenViewModelTests {
client.isRunning = false client.isRunning = false
analytics = AnalyticsService(client: client, appSettings: appSettings) analytics = AnalyticsService(client: client, appSettings: appSettings)
viewModel = AnalyticsSettingsScreenViewModel(appSettings: appSettings, viewModel = AnalyticsSettingsScreenViewModel(userSettings: UserSettings(appSettings: appSettings, accountSettings: .init()),
analytics: analytics) analytics: analytics)
context = viewModel.context context = viewModel.context
} }
@@ -13,12 +13,12 @@ import Testing
@MainActor @MainActor
final class BugReportServiceTests { final class BugReportServiceTests {
var appSettings: AppSettings! var userSettings: UserSettings!
var bugReportService: BugReportServiceProtocol! var bugReportService: BugReportServiceProtocol!
init() throws { init() throws {
appSettings = AppSettings.volatile() userSettings = UserSettings.volatile()
appSettings.bugReportRageshakeURL.reset() userSettings.bugReportRageshakeURL.reset()
let bugReportServiceMock = BugReportServiceMock() let bugReportServiceMock = BugReportServiceMock()
bugReportServiceMock.lastCrashEventIDSubject = .init(nil) bugReportServiceMock.lastCrashEventIDSubject = .init(nil)
@@ -27,7 +27,7 @@ final class BugReportServiceTests {
} }
deinit { deinit {
appSettings.bugReportRageshakeURL.reset() userSettings.bugReportRageshakeURL.reset()
} }
@Test @Test
@@ -104,22 +104,22 @@ final class BugReportServiceTests {
@Test @Test
@MainActor @MainActor
func configurations() async throws { func configurations() async throws {
guard case let .url(initialURL) = appSettings.bugReportRageshakeURL.publisher.value else { guard case let .url(initialURL) = userSettings.bugReportRageshakeURL.publisher.value else {
Issue.record("Unexpected initial configuration.") Issue.record("Unexpected initial configuration.")
return return
} }
let service = BugReportService(rageshakeURLPublisher: appSettings.bugReportRageshakeURL.publisher, let service = BugReportService(rageshakeURLPublisher: userSettings.bugReportRageshakeURL.publisher,
applicationID: "mock_app_id", applicationID: "mock_app_id",
sdkGitSHA: "1234", sdkGitSHA: "1234",
session: .mock, session: .mock,
appHooks: AppHooks()) appHooks: AppHooks())
#expect(service.isEnabled) #expect(service.isEnabled)
appSettings.bugReportRageshakeURL.applyRemoteValue(.disabled) userSettings.bugReportRageshakeURL.applyRemoteValue(.disabled)
#expect(!service.isEnabled) #expect(!service.isEnabled)
appSettings.bugReportRageshakeURL.applyRemoteValue(.url("https://bugs.server.net/submit")) userSettings.bugReportRageshakeURL.applyRemoteValue(.url("https://bugs.server.net/submit"))
#expect(service.isEnabled) #expect(service.isEnabled)
let bugReport = BugReport(userID: "@mock:client.com", let bugReport = BugReport(userID: "@mock:client.com",
@@ -136,7 +136,7 @@ final class BugReportServiceTests {
#expect(customConfigurationResponse.reportURL == "https://bugs.server.net/123") #expect(customConfigurationResponse.reportURL == "https://bugs.server.net/123")
appSettings.bugReportRageshakeURL.reset() userSettings.bugReportRageshakeURL.reset()
#expect(service.isEnabled) #expect(service.isEnabled)
let defaultConfigurationResponse = try await service.submitBugReport(bugReport, progressListener: progressSubject).get() let defaultConfigurationResponse = try await service.submitBugReport(bugReport, progressListener: progressSubject).get()
@@ -29,7 +29,7 @@ struct ChatsTabFlowCoordinatorTests {
} }
init() async throws { init() async throws {
let appSettings = AppSettings.volatile() let userSettings = UserSettings.volatile()
clientProxy = ClientProxyMock(.init(userID: "hi@bob", roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))))) clientProxy = ClientProxyMock(.init(userID: "hi@bob", roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms)))))
timelineControllerFactory = TimelineControllerFactoryMock(.init()) timelineControllerFactory = TimelineControllerFactoryMock(.init())
@@ -42,10 +42,10 @@ struct ChatsTabFlowCoordinatorTests {
bugReportService: BugReportServiceMock(.init()), bugReportService: BugReportServiceMock(.init()),
elementCallService: ElementCallServiceMock(.init()), elementCallService: ElementCallServiceMock(.init()),
timelineControllerFactory: timelineControllerFactory, timelineControllerFactory: timelineControllerFactory,
emojiProvider: EmojiProvider(appSettings: appSettings), emojiProvider: EmojiProvider(userSettings: userSettings),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
appSettings: appSettings, userSettings: userSettings,
appHooks: AppHooks(), appHooks: AppHooks(),
analytics: AnalyticsServiceMock(.init()), analytics: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -84,14 +84,14 @@ final class ComposerToolbarViewModelTests {
.init(suggestionType: .user(.init(id: "@user_mention_2:matrix.org", displayName: "User 2", avatarURL: nil)), range: .init(), rawSuggestionText: "")] .init(suggestionType: .user(.init(id: "@user_mention_2:matrix.org", displayName: "User 2", avatarURL: nil)), range: .init(), rawSuggestionText: "")]
let mockCompletionSuggestionService = CompletionSuggestionServiceMock(configuration: .init(suggestions: suggestions)) let mockCompletionSuggestionService = CompletionSuggestionServiceMock(configuration: .init(suggestions: suggestions))
let appSettings = AppSettings.volatile() let userSettings = UserSettings.volatile()
viewModel = ComposerToolbarViewModel(roomProxy: JoinedRoomProxyMock(.init()), viewModel = ComposerToolbarViewModel(roomProxy: JoinedRoomProxyMock(.init()),
wysiwygViewModel: wysiwygViewModel, wysiwygViewModel: wysiwygViewModel,
completionSuggestionService: mockCompletionSuggestionService, completionSuggestionService: mockCompletionSuggestionService,
mediaProvider: MediaProviderMock(.init()), mediaProvider: MediaProviderMock(.init()),
mentionDisplayHelper: ComposerMentionDisplayHelper.mock, mentionDisplayHelper: ComposerMentionDisplayHelper.mock,
appSettings: appSettings, userSettings: userSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
composerDraftService: draftServiceMock) composerDraftService: draftServiceMock)
@@ -803,14 +803,14 @@ final class ComposerToolbarViewModelTests {
let mockSubject = CurrentValueSubject<[IdentityStatusChange], Never>([]) let mockSubject = CurrentValueSubject<[IdentityStatusChange], Never>([])
roomProxyMock.identityStatusChangesPublisher = mockSubject.asCurrentValuePublisher() roomProxyMock.identityStatusChangesPublisher = mockSubject.asCurrentValuePublisher()
let appSettings = AppSettings.volatile() let userSettings = UserSettings.volatile()
viewModel = ComposerToolbarViewModel(roomProxy: roomProxyMock, viewModel = ComposerToolbarViewModel(roomProxy: roomProxyMock,
wysiwygViewModel: wysiwygViewModel, wysiwygViewModel: wysiwygViewModel,
completionSuggestionService: mockCompletionSuggestionService, completionSuggestionService: mockCompletionSuggestionService,
mediaProvider: MediaProviderMock(.init()), mediaProvider: MediaProviderMock(.init()),
mentionDisplayHelper: ComposerMentionDisplayHelper.mock, mentionDisplayHelper: ComposerMentionDisplayHelper.mock,
appSettings: appSettings, userSettings: userSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
composerDraftService: draftServiceMock) composerDraftService: draftServiceMock)
@@ -846,14 +846,14 @@ final class ComposerToolbarViewModelTests {
roomProxyMock.identityStatusChangesPublisher = mockSubject.asCurrentValuePublisher() roomProxyMock.identityStatusChangesPublisher = mockSubject.asCurrentValuePublisher()
let appSettings = AppSettings.volatile() let userSettings = UserSettings.volatile()
viewModel = ComposerToolbarViewModel(roomProxy: roomProxyMock, viewModel = ComposerToolbarViewModel(roomProxy: roomProxyMock,
wysiwygViewModel: wysiwygViewModel, wysiwygViewModel: wysiwygViewModel,
completionSuggestionService: mockCompletionSuggestionService, completionSuggestionService: mockCompletionSuggestionService,
mediaProvider: MediaProviderMock(.init()), mediaProvider: MediaProviderMock(.init()),
mentionDisplayHelper: ComposerMentionDisplayHelper.mock, mentionDisplayHelper: ComposerMentionDisplayHelper.mock,
appSettings: appSettings, userSettings: userSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
composerDraftService: draftServiceMock) composerDraftService: draftServiceMock)
@@ -886,14 +886,14 @@ final class ComposerToolbarViewModelTests {
} }
roomProxyMock.identityStatusChangesPublisher = CurrentValueSubject([IdentityStatusChange(userId: "@alice:localhost", changedTo: .pinViolation)]).asCurrentValuePublisher() roomProxyMock.identityStatusChangesPublisher = CurrentValueSubject([IdentityStatusChange(userId: "@alice:localhost", changedTo: .pinViolation)]).asCurrentValuePublisher()
let appSettings = AppSettings.volatile() let userSettings = UserSettings.volatile()
viewModel = ComposerToolbarViewModel(roomProxy: roomProxyMock, viewModel = ComposerToolbarViewModel(roomProxy: roomProxyMock,
wysiwygViewModel: wysiwygViewModel, wysiwygViewModel: wysiwygViewModel,
completionSuggestionService: mockCompletionSuggestionService, completionSuggestionService: mockCompletionSuggestionService,
mediaProvider: MediaProviderMock(.init()), mediaProvider: MediaProviderMock(.init()),
mentionDisplayHelper: ComposerMentionDisplayHelper.mock, mentionDisplayHelper: ComposerMentionDisplayHelper.mock,
appSettings: appSettings, userSettings: userSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
composerDraftService: draftServiceMock) composerDraftService: draftServiceMock)
@@ -923,7 +923,7 @@ final class ComposerToolbarViewModelTests {
draftServiceMock.loadDraftClosure = loadDraftClosure draftServiceMock.loadDraftClosure = loadDraftClosure
} }
let appSettings = AppSettings.volatile() let userSettings = UserSettings.volatile()
viewModel = ComposerToolbarViewModel(initialText: initialText, viewModel = ComposerToolbarViewModel(initialText: initialText,
roomProxy: JoinedRoomProxyMock(.init()), roomProxy: JoinedRoomProxyMock(.init()),
@@ -931,7 +931,7 @@ final class ComposerToolbarViewModelTests {
completionSuggestionService: completionSuggestionServiceMock, completionSuggestionService: completionSuggestionServiceMock,
mediaProvider: MediaProviderMock(.init()), mediaProvider: MediaProviderMock(.init()),
mentionDisplayHelper: ComposerMentionDisplayHelper.mock, mentionDisplayHelper: ComposerMentionDisplayHelper.mock,
appSettings: appSettings, userSettings: userSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
composerDraftService: draftServiceMock) composerDraftService: draftServiceMock)
viewModel.context.composerFormattingEnabled = true viewModel.context.composerFormattingEnabled = true
@@ -17,14 +17,14 @@ final class CreateRoomScreenViewModelTests {
var spaceService: SpaceServiceProxyMock! var spaceService: SpaceServiceProxyMock!
var userSession: UserSessionMock! var userSession: UserSessionMock!
private let appSettings: AppSettings private let userSettings: UserSettings
var context: CreateRoomScreenViewModel.Context { var context: CreateRoomScreenViewModel.Context {
viewModel.context viewModel.context
} }
init() { init() {
appSettings = AppSettings.volatile() userSettings = UserSettings.volatile()
} }
isolated deinit { isolated deinit {
@@ -85,14 +85,14 @@ final class CreateRoomScreenViewModelTests {
spaceServiceConfiguration: .init(spaceRoomLists: ["1": .init()]))) spaceServiceConfiguration: .init(spaceRoomLists: ["1": .init()])))
clientProxy.roomForIdentifierClosure = { roomID in .joined(JoinedRoomProxyMock(.init(id: roomID))) } clientProxy.roomForIdentifierClosure = { roomID in .joined(JoinedRoomProxyMock(.init(id: roomID))) }
userSession = UserSessionMock(.init(clientProxy: clientProxy)) userSession = UserSessionMock(.init(clientProxy: clientProxy))
appSettings.knockingEnabled = true userSettings.knockingEnabled = true
let viewModel = CreateRoomScreenViewModel(isSpace: true, let viewModel = CreateRoomScreenViewModel(isSpace: true,
spaceSelectionMode: .none, spaceSelectionMode: .none,
shouldShowCancelButton: false, shouldShowCancelButton: false,
userSession: userSession, userSession: userSession,
analytics: AnalyticsServiceMock(.init()), analytics: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appSettings: appSettings) userSettings: userSettings)
self.viewModel = viewModel self.viewModel = viewModel
// Given a form with a blank topic. // Given a form with a blank topic.
@@ -335,14 +335,14 @@ final class CreateRoomScreenViewModelTests {
clientProxy.spaceService = spaceService clientProxy.spaceService = spaceService
clientProxy.roomForIdentifierClosure = { roomID in .joined(JoinedRoomProxyMock(.init(id: roomID))) } clientProxy.roomForIdentifierClosure = { roomID in .joined(JoinedRoomProxyMock(.init(id: roomID))) }
userSession = UserSessionMock(.init(clientProxy: clientProxy)) userSession = UserSessionMock(.init(clientProxy: clientProxy))
appSettings.knockingEnabled = true userSettings.knockingEnabled = true
let viewModel = CreateRoomScreenViewModel(isSpace: isSpace, let viewModel = CreateRoomScreenViewModel(isSpace: isSpace,
spaceSelectionMode: spacesSelectionMode, spaceSelectionMode: spacesSelectionMode,
shouldShowCancelButton: false, shouldShowCancelButton: false,
userSession: userSession, userSession: userSession,
analytics: AnalyticsServiceMock(.init()), analytics: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appSettings: appSettings) userSettings: userSettings)
self.viewModel = viewModel self.viewModel = viewModel
} }
} }
@@ -55,7 +55,7 @@ struct EmojiPickerScreenViewModelTests {
emojiPickerStream = stream emojiPickerStream = stream
viewModel = EmojiPickerScreenViewModel(selectedEmojis: selectedEmojis, viewModel = EmojiPickerScreenViewModel(selectedEmojis: selectedEmojis,
emojiProvider: EmojiProvider(appSettings: .volatile()), emojiProvider: EmojiProvider(userSettings: .volatile()),
continuation: continuation) continuation: continuation)
} }
} }
+4 -4
View File
@@ -19,7 +19,7 @@ struct EmojiProviderTests {
let emojiLoaderMock = EmojiLoaderMock() let emojiLoaderMock = EmojiLoaderMock()
emojiLoaderMock.categories = [category] emojiLoaderMock.categories = [category]
let emojiProvider = EmojiProvider(loader: emojiLoaderMock, appSettings: .volatile()) let emojiProvider = EmojiProvider(loader: emojiLoaderMock, userSettings: .volatile())
let categories = await emojiProvider.categories() let categories = await emojiProvider.categories()
#expect(emojiLoaderMock.categories == categories) #expect(emojiLoaderMock.categories == categories)
@@ -33,7 +33,7 @@ struct EmojiProviderTests {
let emojiLoaderMock = EmojiLoaderMock() let emojiLoaderMock = EmojiLoaderMock()
emojiLoaderMock.categories = [category] emojiLoaderMock.categories = [category]
let emojiProvider = EmojiProvider(loader: emojiLoaderMock, appSettings: .volatile()) let emojiProvider = EmojiProvider(loader: emojiLoaderMock, userSettings: .volatile())
let categories = await emojiProvider.categories(searchString: "") let categories = await emojiProvider.categories(searchString: "")
#expect(emojiLoaderMock.categories == categories) #expect(emojiLoaderMock.categories == categories)
@@ -51,7 +51,7 @@ struct EmojiProviderTests {
let emojiLoaderMock = EmojiLoaderMock() let emojiLoaderMock = EmojiLoaderMock()
emojiLoaderMock.categories = categoriesForFirstLoad emojiLoaderMock.categories = categoriesForFirstLoad
let emojiProvider = EmojiProvider(loader: emojiLoaderMock, appSettings: .volatile()) let emojiProvider = EmojiProvider(loader: emojiLoaderMock, userSettings: .volatile())
_ = await emojiProvider.categories() _ = await emojiProvider.categories()
emojiLoaderMock.categories = categoriesForSecondLoad emojiLoaderMock.categories = categoriesForSecondLoad
@@ -82,7 +82,7 @@ struct EmojiProviderTests {
let emojiLoaderMock = EmojiLoaderMock() let emojiLoaderMock = EmojiLoaderMock()
emojiLoaderMock.categories = categories emojiLoaderMock.categories = categories
let emojiProvider = EmojiProvider(loader: emojiLoaderMock, appSettings: .volatile()) let emojiProvider = EmojiProvider(loader: emojiLoaderMock, userSettings: .volatile())
_ = await emojiProvider.categories() _ = await emojiProvider.categories()
let result = await emojiProvider.categories(searchString: searchString) let result = await emojiProvider.categories(searchString: searchString)
@@ -20,12 +20,12 @@ final class HomeScreenViewModelTests {
var clientProxy: ClientProxyMock! var clientProxy: ClientProxyMock!
var roomSummaryProvider: RoomSummaryProviderMock! var roomSummaryProvider: RoomSummaryProviderMock!
var notificationManager: NotificationManagerMock! var notificationManager: NotificationManagerMock!
private let appSettings: AppSettings private let userSettings: UserSettings
var cancellables = Set<AnyCancellable>() var cancellables = Set<AnyCancellable>()
init() { init() {
appSettings = AppSettings.volatile() userSettings = UserSettings.volatile()
} }
@Test @Test
@@ -275,7 +275,7 @@ final class HomeScreenViewModelTests {
room.roomID == invites[0].roomID && room.badges.isDotShown == false room.roomID == invites[0].roomID && room.badges.isDotShown == false
} }
} }
appSettings.seenInvites = Set(invites.compactMap(\.roomID)) userSettings.seenInvites = Set(invites.compactMap(\.roomID))
try await deferred.fulfill() try await deferred.fulfill()
invites = context.viewState.rooms.invites invites = context.viewState.rooms.invites
@@ -289,14 +289,14 @@ final class HomeScreenViewModelTests {
setupViewModel(invites: .rooms) setupViewModel(invites: .rooms)
let invitedRoomIDs = context.viewState.rooms.invites.compactMap(\.roomID) let invitedRoomIDs = context.viewState.rooms.invites.compactMap(\.roomID)
appSettings.seenInvites = Set(invitedRoomIDs) userSettings.seenInvites = Set(invitedRoomIDs)
#expect(invitedRoomIDs.count == 2) #expect(invitedRoomIDs.count == 2)
let deferred = deferFulfillment(viewModel.actions) { $0 == .presentRoom(roomIdentifier: invitedRoomIDs[0]) } let deferred = deferFulfillment(viewModel.actions) { $0 == .presentRoom(roomIdentifier: invitedRoomIDs[0]) }
context.send(viewAction: .acceptInvite(roomIdentifier: invitedRoomIDs[0])) context.send(viewAction: .acceptInvite(roomIdentifier: invitedRoomIDs[0]))
try await deferred.fulfill() try await deferred.fulfill()
#expect(appSettings.seenInvites == [invitedRoomIDs[1]]) #expect(userSettings.seenInvites == [invitedRoomIDs[1]])
#expect(!notificationManager.removeDeliveredMessageNotificationsForCalled, "The notification will be dismissed when opening the room.") #expect(!notificationManager.removeDeliveredMessageNotificationsForCalled, "The notification will be dismissed when opening the room.")
} }
@@ -305,7 +305,7 @@ final class HomeScreenViewModelTests {
setupViewModel(invites: .spaces) setupViewModel(invites: .spaces)
let invitedRoomIDs = context.viewState.rooms.invites.compactMap(\.roomID) let invitedRoomIDs = context.viewState.rooms.invites.compactMap(\.roomID)
appSettings.seenInvites = Set(invitedRoomIDs) userSettings.seenInvites = Set(invitedRoomIDs)
#expect(invitedRoomIDs.count == 2) #expect(invitedRoomIDs.count == 2)
let deferred = deferFulfillment(viewModel.actions) { let deferred = deferFulfillment(viewModel.actions) {
@@ -314,7 +314,7 @@ final class HomeScreenViewModelTests {
context.send(viewAction: .acceptInvite(roomIdentifier: invitedRoomIDs[0])) context.send(viewAction: .acceptInvite(roomIdentifier: invitedRoomIDs[0]))
try await deferred.fulfill() try await deferred.fulfill()
#expect(appSettings.seenInvites == [invitedRoomIDs[1]]) #expect(userSettings.seenInvites == [invitedRoomIDs[1]])
#expect(!notificationManager.removeDeliveredMessageNotificationsForCalled, "The notification will be dismissed when opening the room.") #expect(!notificationManager.removeDeliveredMessageNotificationsForCalled, "The notification will be dismissed when opening the room.")
} }
@@ -322,7 +322,7 @@ final class HomeScreenViewModelTests {
func declineInvite() async throws { func declineInvite() async throws {
setupViewModel(invites: .rooms) setupViewModel(invites: .rooms)
let invitedRoomIDs = context.viewState.rooms.invites.compactMap(\.roomID) let invitedRoomIDs = context.viewState.rooms.invites.compactMap(\.roomID)
appSettings.seenInvites = Set(invitedRoomIDs) userSettings.seenInvites = Set(invitedRoomIDs)
#expect(invitedRoomIDs.count == 2) #expect(invitedRoomIDs.count == 2)
let deferred = deferFulfillment(context.$viewState) { $0.bindings.alertInfo != nil } let deferred = deferFulfillment(context.$viewState) { $0.bindings.alertInfo != nil }
@@ -345,7 +345,7 @@ final class HomeScreenViewModelTests {
try await Task.sleep(for: .milliseconds(100)) try await Task.sleep(for: .milliseconds(100))
#expect(rejectCalled) #expect(rejectCalled)
#expect(appSettings.seenInvites == [invitedRoomIDs[1]]) #expect(userSettings.seenInvites == [invitedRoomIDs[1]])
#expect(notificationManager.removeDeliveredMessageNotificationsForCalled) #expect(notificationManager.removeDeliveredMessageNotificationsForCalled)
#expect(notificationManager.removeDeliveredMessageNotificationsForReceivedInvocations == [invitedRoomIDs[0]]) #expect(notificationManager.removeDeliveredMessageNotificationsForReceivedInvocations == [invitedRoomIDs[0]])
} }
@@ -354,7 +354,7 @@ final class HomeScreenViewModelTests {
func declineAndBlockInvite() async throws { func declineAndBlockInvite() async throws {
setupViewModel(invites: .rooms) setupViewModel(invites: .rooms)
let invitedRoomIDs = context.viewState.rooms.invites.compactMap(\.roomID) let invitedRoomIDs = context.viewState.rooms.invites.compactMap(\.roomID)
appSettings.seenInvites = Set(invitedRoomIDs) userSettings.seenInvites = Set(invitedRoomIDs)
#expect(invitedRoomIDs.count == 2) #expect(invitedRoomIDs.count == 2)
let deferred = deferFulfillment(context.$viewState) { $0.bindings.alertInfo != nil } let deferred = deferFulfillment(context.$viewState) { $0.bindings.alertInfo != nil }
@@ -368,7 +368,7 @@ final class HomeScreenViewModelTests {
@Test @Test
func newSoundBanner() { func newSoundBanner() {
appSettings.hasSeenNewSoundBanner = false userSettings.hasSeenNewSoundBanner = false
setupViewModel() setupViewModel()
#expect(context.viewState.shouldShowBanner) #expect(context.viewState.shouldShowBanner)
@@ -377,7 +377,7 @@ final class HomeScreenViewModelTests {
context.send(viewAction: .dismissNewSoundBanner) context.send(viewAction: .dismissNewSoundBanner)
#expect(!context.viewState.shouldShowBanner) #expect(!context.viewState.shouldShowBanner)
#expect(!context.viewState.shouldShowNewSoundBanner) #expect(!context.viewState.shouldShowNewSoundBanner)
#expect(appSettings.hasSeenNewSoundBanner) #expect(userSettings.hasSeenNewSoundBanner)
} }
// MARK: - Helpers // MARK: - Helpers
@@ -483,7 +483,7 @@ final class HomeScreenViewModelTests {
viewModel = HomeScreenViewModel(userSession: userSession, viewModel = HomeScreenViewModel(userSession: userSession,
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(), selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
appSettings: appSettings, userSettings: userSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
bugReportService: BugReportServiceMock(.init()), bugReportService: BugReportServiceMock(.init()),
notificationManager: notificationManager, notificationManager: notificationManager,
@@ -109,7 +109,7 @@ struct IdentityConfirmationScreenViewModelTests {
userSession.sessionSecurityStatePublisher = securityStateSubject.asCurrentValuePublisher() userSession.sessionSecurityStatePublisher = securityStateSubject.asCurrentValuePublisher()
viewModel = IdentityConfirmationScreenViewModel(userSession: userSession, viewModel = IdentityConfirmationScreenViewModel(userSession: userSession,
appSettings: .volatile(), userSettings: .volatile(),
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
} }
} }
@@ -31,10 +31,10 @@ final class JoinRoomScreenViewModelTests {
viewModel.context viewModel.context
} }
private let appSettings: AppSettings private let userSettings: UserSettings
init() { init() {
appSettings = AppSettings.volatile() userSettings = UserSettings.volatile()
} }
isolated deinit { isolated deinit {
@@ -45,12 +45,12 @@ final class JoinRoomScreenViewModelTests {
@Test @Test
func interaction() async throws { func interaction() async throws {
#expect(appSettings.seenInvites.isEmpty, "There shouldn't be any seen invites before running the tests.") #expect(userSettings.seenInvites.isEmpty, "There shouldn't be any seen invites before running the tests.")
setupViewModel() setupViewModel()
try await deferFulfillment(viewModel.context.$viewState) { $0.mode == .joinable }.fulfill() try await deferFulfillment(viewModel.context.$viewState) { $0.mode == .joinable }.fulfill()
#expect(appSettings.seenInvites.isEmpty, "Only an invited room should register the room ID as a seen invite.") #expect(userSettings.seenInvites.isEmpty, "Only an invited room should register the room ID as a seen invite.")
let deferred = deferFulfillment(viewModel.actionsPublisher) { $0 == .joined(.roomID("1")) } let deferred = deferFulfillment(viewModel.actionsPublisher) { $0 == .joined(.roomID("1")) }
context.send(viewAction: .join) context.send(viewAction: .join)
@@ -59,28 +59,28 @@ final class JoinRoomScreenViewModelTests {
@Test @Test
func acceptInviteInteraction() async throws { func acceptInviteInteraction() async throws {
#expect(appSettings.seenInvites.isEmpty, "There shouldn't be any seen invites before running the tests.") #expect(userSettings.seenInvites.isEmpty, "There shouldn't be any seen invites before running the tests.")
setupViewModel(mode: .invited) setupViewModel(mode: .invited)
try await deferFulfillment(viewModel.context.$viewState) { $0.mode == .invited(isDM: false) }.fulfill() try await deferFulfillment(viewModel.context.$viewState) { $0.mode == .invited(isDM: false) }.fulfill()
#expect(appSettings.seenInvites == ["1"], "The invited room's ID should be registered as a seen invite.") #expect(userSettings.seenInvites == ["1"], "The invited room's ID should be registered as a seen invite.")
let deferred = deferFulfillment(viewModel.actionsPublisher) { $0 == .joined(.roomID("1")) } let deferred = deferFulfillment(viewModel.actionsPublisher) { $0 == .joined(.roomID("1")) }
context.send(viewAction: .acceptInvite) context.send(viewAction: .acceptInvite)
try await deferred.fulfill() try await deferred.fulfill()
#expect(appSettings.seenInvites.isEmpty, "The after accepting an invite the invite should be forgotten in case the user leaves.") #expect(userSettings.seenInvites.isEmpty, "The after accepting an invite the invite should be forgotten in case the user leaves.")
} }
@Test @Test
func declineInviteInteraction() async throws { func declineInviteInteraction() async throws {
#expect(appSettings.seenInvites.isEmpty, "There shouldn't be any seen invites before running the tests.") #expect(userSettings.seenInvites.isEmpty, "There shouldn't be any seen invites before running the tests.")
setupViewModel(mode: .invited) setupViewModel(mode: .invited)
try await deferFulfillment(viewModel.context.$viewState) { $0.mode == .invited(isDM: false) }.fulfill() try await deferFulfillment(viewModel.context.$viewState) { $0.mode == .invited(isDM: false) }.fulfill()
#expect(appSettings.seenInvites == ["1"], "The invited room's ID should be registered as a seen invite.") #expect(userSettings.seenInvites == ["1"], "The invited room's ID should be registered as a seen invite.")
context.send(viewAction: .declineInvite) context.send(viewAction: .declineInvite)
@@ -89,17 +89,17 @@ final class JoinRoomScreenViewModelTests {
context.alertInfo?.secondaryButton?.action?() context.alertInfo?.secondaryButton?.action?()
try await deferred.fulfill() try await deferred.fulfill()
#expect(appSettings.seenInvites.isEmpty, "The after declining an invite the invite should be forgotten in case another invite is received.") #expect(userSettings.seenInvites.isEmpty, "The after declining an invite the invite should be forgotten in case another invite is received.")
} }
@Test @Test
func knockedState() async throws { func knockedState() async throws {
#expect(appSettings.seenInvites.isEmpty, "There shouldn't be any seen invites before running the tests.") #expect(userSettings.seenInvites.isEmpty, "There shouldn't be any seen invites before running the tests.")
setupViewModel(mode: .knocked) setupViewModel(mode: .knocked)
try await deferFulfillment(viewModel.context.$viewState) { $0.mode == .knocked }.fulfill() try await deferFulfillment(viewModel.context.$viewState) { $0.mode == .knocked }.fulfill()
#expect(appSettings.seenInvites.isEmpty, "Only an invited room should register the room ID as a seen invite.") #expect(userSettings.seenInvites.isEmpty, "Only an invited room should register the room ID as a seen invite.")
} }
@Test @Test
@@ -237,7 +237,7 @@ final class JoinRoomScreenViewModelTests {
} }
viewModel = JoinRoomScreenViewModel(source: .generic(roomID: "1", via: []), viewModel = JoinRoomScreenViewModel(source: .generic(roomID: "1", via: []),
appSettings: appSettings, userSettings: userSettings,
userSession: UserSessionMock(.init(clientProxy: clientProxy)), userSession: UserSessionMock(.init(clientProxy: clientProxy)),
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
} }
@@ -16,7 +16,7 @@ final class LiveLocationManagerTests {
private var clientProxy: ClientProxyMock! private var clientProxy: ClientProxyMock!
private var locationManagerMock: CLLocationManagerMock! private var locationManagerMock: CLLocationManagerMock!
private var manager: LiveLocationManager! private var manager: LiveLocationManager!
private var appSettings: AppSettings! private var userSettings: UserSettings!
private var beaconInfoSubject: PassthroughSubject<LiveLocationOwnInfoUpdate, Never>! private var beaconInfoSubject: PassthroughSubject<LiveLocationOwnInfoUpdate, Never>!
// MARK: - startLiveLocation // MARK: - startLiveLocation
@@ -41,11 +41,11 @@ final class LiveLocationManagerTests {
try result.get() try result.get()
#expect(callOrder == ["stop", "start"]) #expect(callOrder == ["stop", "start"])
#expect(appSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] == nil) #expect(userSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] == nil)
try await simulateBeaconEcho(roomID: "!room:matrix.org", eventID: "$event:matrix.org") try await simulateBeaconEcho(roomID: "!room:matrix.org", eventID: "$event:matrix.org")
#expect(appSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] != nil) #expect(userSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] != nil)
#expect(locationManagerMock.startUpdatingLocationCalled) #expect(locationManagerMock.startUpdatingLocationCalled)
} }
@@ -54,7 +54,7 @@ final class LiveLocationManagerTests {
setUp() setUp()
let roomProxy = makeRoomProxy(roomID: "!room:matrix.org") let roomProxy = makeRoomProxy(roomID: "!room:matrix.org")
clientProxy.roomForIdentifierClosure = { _ in .joined(roomProxy) } clientProxy.roomForIdentifierClosure = { _ in .joined(roomProxy) }
appSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] = LiveLocationSession(eventID: "$old_event:matrix.org", expirationDate: Date().addingTimeInterval(300)) userSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] = LiveLocationSession(eventID: "$old_event:matrix.org", expirationDate: Date().addingTimeInterval(300))
var callOrder: [String] = [] var callOrder: [String] = []
roomProxy.stopLiveLocationShareClosure = { roomProxy.stopLiveLocationShareClosure = {
@@ -73,7 +73,7 @@ final class LiveLocationManagerTests {
try await simulateBeaconEcho(roomID: "!room:matrix.org", eventID: "$event:matrix.org") try await simulateBeaconEcho(roomID: "!room:matrix.org", eventID: "$event:matrix.org")
#expect(appSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] != nil) #expect(userSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] != nil)
} }
@Test @Test
@@ -82,12 +82,12 @@ final class LiveLocationManagerTests {
let roomProxy = makeRoomProxy(roomID: "!room1:matrix.org") let roomProxy = makeRoomProxy(roomID: "!room1:matrix.org")
clientProxy.roomForIdentifierClosure = { _ in .joined(roomProxy) } clientProxy.roomForIdentifierClosure = { _ in .joined(roomProxy) }
appSettings.liveLocationSharingSessionsByRoomID["!room2:matrix.org"] = LiveLocationSession(eventID: "$event:matrix.org", expirationDate: Date().addingTimeInterval(300)) userSettings.liveLocationSharingSessionsByRoomID["!room2:matrix.org"] = LiveLocationSession(eventID: "$event:matrix.org", expirationDate: Date().addingTimeInterval(300))
_ = await manager.startLiveLocation(roomID: "!room1:matrix.org", duration: .seconds(300)) _ = await manager.startLiveLocation(roomID: "!room1:matrix.org", duration: .seconds(300))
#expect(roomProxy.stopLiveLocationShareCalled) #expect(roomProxy.stopLiveLocationShareCalled)
#expect(appSettings.liveLocationSharingSessionsByRoomID["!room2:matrix.org"] != nil) #expect(userSettings.liveLocationSharingSessionsByRoomID["!room2:matrix.org"] != nil)
} }
@Test @Test
@@ -98,7 +98,7 @@ final class LiveLocationManagerTests {
let result = await manager.startLiveLocation(roomID: "!room:matrix.org", duration: .seconds(300)) let result = await manager.startLiveLocation(roomID: "!room:matrix.org", duration: .seconds(300))
#expect(throws: LiveLocationManagerError.roomNotJoined) { try result.get() } #expect(throws: LiveLocationManagerError.roomNotJoined) { try result.get() }
#expect(appSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] == nil) #expect(userSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] == nil)
} }
@Test @Test
@@ -111,7 +111,7 @@ final class LiveLocationManagerTests {
let result = await manager.startLiveLocation(roomID: "!room:matrix.org", duration: .seconds(300)) let result = await manager.startLiveLocation(roomID: "!room:matrix.org", duration: .seconds(300))
#expect(throws: LiveLocationManagerError.startFailed) { try result.get() } #expect(throws: LiveLocationManagerError.startFailed) { try result.get() }
#expect(appSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] == nil) #expect(userSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] == nil)
} }
@Test @Test
@@ -127,7 +127,7 @@ final class LiveLocationManagerTests {
try await simulateBeaconEcho(roomID: "!room:matrix.org", eventID: "$event:matrix.org") try await simulateBeaconEcho(roomID: "!room:matrix.org", eventID: "$event:matrix.org")
let storedSession = try #require(appSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"]) let storedSession = try #require(userSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"])
let expectedMinTimeout = beforeStart.addingTimeInterval(TimeInterval(duration.seconds)) let expectedMinTimeout = beforeStart.addingTimeInterval(TimeInterval(duration.seconds))
let expectedMaxTimeout = afterStart.addingTimeInterval(TimeInterval(duration.seconds)) let expectedMaxTimeout = afterStart.addingTimeInterval(TimeInterval(duration.seconds))
@@ -142,12 +142,12 @@ final class LiveLocationManagerTests {
setUp() setUp()
let roomProxy = makeRoomProxy(roomID: "!room:matrix.org") let roomProxy = makeRoomProxy(roomID: "!room:matrix.org")
clientProxy.roomForIdentifierClosure = { _ in .joined(roomProxy) } clientProxy.roomForIdentifierClosure = { _ in .joined(roomProxy) }
appSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] = LiveLocationSession(eventID: "$event:matrix.org", expirationDate: Date().addingTimeInterval(300)) userSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] = LiveLocationSession(eventID: "$event:matrix.org", expirationDate: Date().addingTimeInterval(300))
await manager.stopLiveLocation(roomID: "!room:matrix.org") await manager.stopLiveLocation(roomID: "!room:matrix.org")
#expect(roomProxy.stopLiveLocationShareCalled) #expect(roomProxy.stopLiveLocationShareCalled)
#expect(appSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] == nil) #expect(userSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] == nil)
// Setting the timeout date above starts tracking; removing it stops tracking. // Setting the timeout date above starts tracking; removing it stops tracking.
#expect(locationManagerMock.startUpdatingLocationCalled) #expect(locationManagerMock.startUpdatingLocationCalled)
#expect(locationManagerMock.stopUpdatingLocationCalled) #expect(locationManagerMock.stopUpdatingLocationCalled)
@@ -169,13 +169,13 @@ final class LiveLocationManagerTests {
setUp() setUp()
let roomProxy = makeRoomProxy(roomID: "!room1:matrix.org") let roomProxy = makeRoomProxy(roomID: "!room1:matrix.org")
clientProxy.roomForIdentifierClosure = { _ in .joined(roomProxy) } clientProxy.roomForIdentifierClosure = { _ in .joined(roomProxy) }
appSettings.liveLocationSharingSessionsByRoomID["!room1:matrix.org"] = LiveLocationSession(eventID: "$event:matrix.org", expirationDate: Date().addingTimeInterval(300)) userSettings.liveLocationSharingSessionsByRoomID["!room1:matrix.org"] = LiveLocationSession(eventID: "$event:matrix.org", expirationDate: Date().addingTimeInterval(300))
appSettings.liveLocationSharingSessionsByRoomID["!room2:matrix.org"] = LiveLocationSession(eventID: "$event:matrix.org", expirationDate: Date().addingTimeInterval(300)) userSettings.liveLocationSharingSessionsByRoomID["!room2:matrix.org"] = LiveLocationSession(eventID: "$event:matrix.org", expirationDate: Date().addingTimeInterval(300))
await manager.stopLiveLocation(roomID: "!room1:matrix.org") await manager.stopLiveLocation(roomID: "!room1:matrix.org")
#expect(appSettings.liveLocationSharingSessionsByRoomID["!room1:matrix.org"] == nil) #expect(userSettings.liveLocationSharingSessionsByRoomID["!room1:matrix.org"] == nil)
#expect(appSettings.liveLocationSharingSessionsByRoomID["!room2:matrix.org"] != nil) #expect(userSettings.liveLocationSharingSessionsByRoomID["!room2:matrix.org"] != nil)
} }
// MARK: - Beacon info updates // MARK: - Beacon info updates
@@ -188,13 +188,13 @@ final class LiveLocationManagerTests {
try await manager.startLiveLocation(roomID: "!room:matrix.org", duration: .seconds(300)).get() try await manager.startLiveLocation(roomID: "!room:matrix.org", duration: .seconds(300)).get()
try await simulateBeaconEcho(roomID: "!room:matrix.org", eventID: "$event:matrix.org") try await simulateBeaconEcho(roomID: "!room:matrix.org", eventID: "$event:matrix.org")
#expect(appSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] != nil) #expect(userSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] != nil)
let deferred = deferFulfillment(appSettings.liveLocationSharingSessionsByRoomIDPublisher) { $0["!room:matrix.org"] == nil } let deferred = deferFulfillment(userSettings.liveLocationSharingSessionsByRoomIDPublisher) { $0["!room:matrix.org"] == nil }
beaconInfoSubject.send(LiveLocationOwnInfoUpdate(roomID: "!room:matrix.org", eventID: "$external_event:matrix.org", isLive: true)) beaconInfoSubject.send(LiveLocationOwnInfoUpdate(roomID: "!room:matrix.org", eventID: "$external_event:matrix.org", isLive: true))
try await deferred.fulfill() try await deferred.fulfill()
#expect(appSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] == nil) #expect(userSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] == nil)
} }
// MARK: - Reduced accuracy // MARK: - Reduced accuracy
@@ -228,16 +228,16 @@ final class LiveLocationManagerTests {
} }
private func setUp(accuracyAuthorization: CLAccuracyAuthorization = .fullAccuracy) { private func setUp(accuracyAuthorization: CLAccuracyAuthorization = .fullAccuracy) {
appSettings = AppSettings.volatile() userSettings = UserSettings.volatile()
clientProxy = ClientProxyMock(.init()) clientProxy = ClientProxyMock(.init())
beaconInfoSubject = PassthroughSubject<LiveLocationOwnInfoUpdate, Never>() beaconInfoSubject = PassthroughSubject<LiveLocationOwnInfoUpdate, Never>()
clientProxy.liveLocationOwnInfoUpdatesPublisher = beaconInfoSubject.eraseToAnyPublisher() clientProxy.liveLocationOwnInfoUpdatesPublisher = beaconInfoSubject.eraseToAnyPublisher()
locationManagerMock = CLLocationManagerMock(.init(accuracyAuthorization: accuracyAuthorization)) locationManagerMock = CLLocationManagerMock(.init(accuracyAuthorization: accuracyAuthorization))
manager = LiveLocationManager(clientProxy: clientProxy, appSettings: appSettings, locationManager: locationManagerMock) manager = LiveLocationManager(clientProxy: clientProxy, userSettings: userSettings, locationManager: locationManagerMock)
} }
private func simulateBeaconEcho(roomID: String, eventID: String) async throws { private func simulateBeaconEcho(roomID: String, eventID: String) async throws {
let deferred = deferFulfillment(appSettings.liveLocationSharingSessionsByRoomIDPublisher) { $0[roomID] != nil } let deferred = deferFulfillment(userSettings.liveLocationSharingSessionsByRoomIDPublisher) { $0[roomID] != nil }
beaconInfoSubject.send(LiveLocationOwnInfoUpdate(roomID: roomID, eventID: eventID, isLive: true)) beaconInfoSubject.send(LiveLocationOwnInfoUpdate(roomID: roomID, eventID: eventID, isLive: true))
try await deferred.fulfill() try await deferred.fulfill()
} }
@@ -16,7 +16,7 @@ struct LocationSharingScreenViewModelTests {
private static let roomID = "!live-location-room:matrix.org" private static let roomID = "!live-location-room:matrix.org"
private var timelineProxy: TimelineProxyMock! private var timelineProxy: TimelineProxyMock!
private var appSettings: AppSettings! private var userSettings: UserSettings!
private var viewModel: LocationSharingScreenViewModel! private var viewModel: LocationSharingScreenViewModel!
private var context: LocationSharingScreenViewModel.Context { private var context: LocationSharingScreenViewModel.Context {
@@ -417,14 +417,14 @@ struct LocationSharingScreenViewModelTests {
let roomProxyMock = JoinedRoomProxyMock(.init(members: .allMembers)) let roomProxyMock = JoinedRoomProxyMock(.init(members: .allMembers))
roomProxyMock.makeLiveLocationServiceReturnValue = liveLocationServiceMock roomProxyMock.makeLiveLocationServiceReturnValue = liveLocationServiceMock
let appSettings = AppSettings.volatile() let userSettings = UserSettings.volatile()
viewModel = LocationSharingScreenViewModel(interactionMode: .viewLive(sender: nil, initialLiveLocationShare: nil), viewModel = LocationSharingScreenViewModel(interactionMode: .viewLive(sender: nil, initialLiveLocationShare: nil),
mapURLBuilder: appSettings.mapTilerConfiguration.publisher.value, mapURLBuilder: userSettings.mapTilerConfiguration.publisher.value,
roomProxy: roomProxyMock, roomProxy: roomProxyMock,
timelineController: TimelineControllerMock(.init(timelineProxy: TimelineProxyMock(.init()))), timelineController: TimelineControllerMock(.init(timelineProxy: TimelineProxyMock(.init()))),
liveLocationManager: LiveLocationManagerMock(.init()), liveLocationManager: LiveLocationManagerMock(.init()),
appSettings: appSettings, userSettings: userSettings,
analytics: AnalyticsServiceMock(.init()), analytics: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
mediaProvider: MediaProviderMock(.init())) mediaProvider: MediaProviderMock(.init()))
@@ -546,7 +546,7 @@ struct LocationSharingScreenViewModelTests {
#expect(context.showsUserLocationMode == .hide) #expect(context.showsUserLocationMode == .hide)
// Another device takes over: this device's session is removed and a new own share arrives. // Another device takes over: this device's session is removed and a new own share arrives.
appSettings.liveLocationSharingSessionsByRoomID.removeValue(forKey: Self.roomID) userSettings.liveLocationSharingSessionsByRoomID.removeValue(forKey: Self.roomID)
let newOwnShare = makeLiveLocationShare(userID: RoomMemberProxyMock.mockMe.userID, latitude: 48.8, longitude: 2.3) let newOwnShare = makeLiveLocationShare(userID: RoomMemberProxyMock.mockMe.userID, latitude: 48.8, longitude: 2.3)
let deferred = deferFulfillment(context.observe(\.showsUserLocationMode)) { $0 == .show } let deferred = deferFulfillment(context.observe(\.showsUserLocationMode)) { $0 == .show }
@@ -630,14 +630,14 @@ struct LocationSharingScreenViewModelTests {
private mutating func setupViewModel(liveLocationManagerMock: LiveLocationManagerMock, private mutating func setupViewModel(liveLocationManagerMock: LiveLocationManagerMock,
members: [RoomMemberProxyMock] = .allMembersAsAdmin) { members: [RoomMemberProxyMock] = .allMembersAsAdmin) {
appSettings = AppSettings.volatile() userSettings = UserSettings.volatile()
timelineProxy = TimelineProxyMock(.init()) timelineProxy = TimelineProxyMock(.init())
viewModel = LocationSharingScreenViewModel(interactionMode: .picker(shouldShowLiveLocationOption: true), viewModel = LocationSharingScreenViewModel(interactionMode: .picker(shouldShowLiveLocationOption: true),
mapURLBuilder: appSettings.mapTilerConfiguration.publisher.value, mapURLBuilder: userSettings.mapTilerConfiguration.publisher.value,
roomProxy: JoinedRoomProxyMock(.init(members: members)), roomProxy: JoinedRoomProxyMock(.init(members: members)),
timelineController: TimelineControllerMock(.init(timelineProxy: timelineProxy)), timelineController: TimelineControllerMock(.init(timelineProxy: timelineProxy)),
liveLocationManager: liveLocationManagerMock, liveLocationManager: liveLocationManagerMock,
appSettings: appSettings, userSettings: userSettings,
analytics: AnalyticsServiceMock(.init()), analytics: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
mediaProvider: MediaProviderMock(.init())) mediaProvider: MediaProviderMock(.init()))
@@ -649,9 +649,9 @@ struct LocationSharingScreenViewModelTests {
liveLocationsSubject: CurrentValueSubject<[LiveLocationShare], Never>, liveLocationsSubject: CurrentValueSubject<[LiveLocationShare], Never>,
members: [RoomMemberProxyMock] = .allMembers, members: [RoomMemberProxyMock] = .allMembers,
isSharingLiveLocationFromThisDevice: Bool = false) { isSharingLiveLocationFromThisDevice: Bool = false) {
appSettings = AppSettings.volatile() userSettings = UserSettings.volatile()
if isSharingLiveLocationFromThisDevice { if isSharingLiveLocationFromThisDevice {
appSettings.liveLocationSharingSessionsByRoomID[Self.roomID] = .init(eventID: "$event:matrix.org", expirationDate: .distantFuture) userSettings.liveLocationSharingSessionsByRoomID[Self.roomID] = .init(eventID: "$event:matrix.org", expirationDate: .distantFuture)
} }
let liveLocationServiceMock = RoomLiveLocationServiceMock() let liveLocationServiceMock = RoomLiveLocationServiceMock()
@@ -661,11 +661,11 @@ struct LocationSharingScreenViewModelTests {
roomProxyMock.makeLiveLocationServiceReturnValue = liveLocationServiceMock roomProxyMock.makeLiveLocationServiceReturnValue = liveLocationServiceMock
viewModel = LocationSharingScreenViewModel(interactionMode: .viewLive(sender: sender, initialLiveLocationShare: initialShare), viewModel = LocationSharingScreenViewModel(interactionMode: .viewLive(sender: sender, initialLiveLocationShare: initialShare),
mapURLBuilder: appSettings.mapTilerConfiguration.publisher.value, mapURLBuilder: userSettings.mapTilerConfiguration.publisher.value,
roomProxy: roomProxyMock, roomProxy: roomProxyMock,
timelineController: TimelineControllerMock(.init(timelineProxy: TimelineProxyMock(.init()))), timelineController: TimelineControllerMock(.init(timelineProxy: TimelineProxyMock(.init()))),
liveLocationManager: LiveLocationManagerMock(.init()), liveLocationManager: LiveLocationManagerMock(.init()),
appSettings: appSettings, userSettings: userSettings,
analytics: AnalyticsServiceMock(.init()), analytics: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
mediaProvider: MediaProviderMock(.init())) mediaProvider: MediaProviderMock(.init()))
@@ -15,7 +15,7 @@ final class MediaUploadPreviewScreenViewModelTests {
var timelineProxy: TimelineProxyMock! var timelineProxy: TimelineProxyMock!
var clientProxy: ClientProxyMock! var clientProxy: ClientProxyMock!
var userIndicatorController: UserIndicatorControllerMock var userIndicatorController: UserIndicatorControllerMock
private let appSettings: AppSettings private let userSettings: UserSettings
var viewModel: MediaUploadPreviewScreenViewModel! var viewModel: MediaUploadPreviewScreenViewModel!
var context: MediaUploadPreviewScreenViewModel.Context { var context: MediaUploadPreviewScreenViewModel.Context {
@@ -28,8 +28,8 @@ final class MediaUploadPreviewScreenViewModelTests {
} }
init() { init() {
appSettings = AppSettings.volatile() userSettings = UserSettings.volatile()
appSettings.optimizeMediaUploads = false userSettings.optimizeMediaUploads = false
userIndicatorController = UserIndicatorControllerMock() userIndicatorController = UserIndicatorControllerMock()
} }
@@ -322,7 +322,7 @@ final class MediaUploadPreviewScreenViewModelTests {
title: "Some File", title: "Some File",
shouldShowCaptionWarning: true, shouldShowCaptionWarning: true,
galleryEnabled: galleryEnabled, galleryEnabled: galleryEnabled,
mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: appSettings), mediaUploadingPreprocessor: MediaUploadingPreprocessor(userSettings: userSettings),
timelineController: TimelineControllerMock(.init(timelineProxy: timelineProxy)), timelineController: TimelineControllerMock(.init(timelineProxy: timelineProxy)),
clientProxy: clientProxy, clientProxy: clientProxy,
userIndicatorController: userIndicatorController) userIndicatorController: userIndicatorController)
@@ -13,13 +13,13 @@ import UniformTypeIdentifiers
final class MediaUploadingPreprocessorTests { final class MediaUploadingPreprocessorTests {
let maxUploadSize: UInt = 100 * 1024 * 1024 let maxUploadSize: UInt = 100 * 1024 * 1024
var appSettings: AppSettings! var userSettings: UserSettings!
var mediaUploadingPreprocessor: MediaUploadingPreprocessor! var mediaUploadingPreprocessor: MediaUploadingPreprocessor!
init() { init() {
appSettings = AppSettings.volatile() userSettings = UserSettings.volatile()
appSettings.optimizeMediaUploads = false userSettings.optimizeMediaUploads = false
mediaUploadingPreprocessor = MediaUploadingPreprocessor(appSettings: appSettings) mediaUploadingPreprocessor = MediaUploadingPreprocessor(userSettings: userSettings)
} }
@Test @Test
@@ -80,7 +80,7 @@ final class MediaUploadingPreprocessorTests {
func landscapeMovVideoOptimizedProcessing() async throws { func landscapeMovVideoOptimizedProcessing() async throws {
let url = try #require(Bundle(for: Self.self).url(forResource: "landscape_test_video.mov", withExtension: nil), "Failed retrieving test asset") let url = try #require(Bundle(for: Self.self).url(forResource: "landscape_test_video.mov", withExtension: nil), "Failed retrieving test asset")
appSettings.optimizeMediaUploads = true userSettings.optimizeMediaUploads = true
guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize), guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
case let .video(optimizedVideoURL, _, optimizedVideoInfo) = optimizedResult else { case let .video(optimizedVideoURL, _, optimizedVideoInfo) = optimizedResult else {
@@ -139,7 +139,7 @@ final class MediaUploadingPreprocessorTests {
func portraitMp4VideoOptimizedProcessing() async throws { func portraitMp4VideoOptimizedProcessing() async throws {
let url = try #require(Bundle(for: Self.self).url(forResource: "portrait_test_video.mp4", withExtension: nil), "Failed retrieving test asset") let url = try #require(Bundle(for: Self.self).url(forResource: "portrait_test_video.mp4", withExtension: nil), "Failed retrieving test asset")
appSettings.optimizeMediaUploads = true userSettings.optimizeMediaUploads = true
guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize), guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
case let .video(optimizedVideoURL, _, optimizedVideoInfo) = optimizedResult else { case let .video(optimizedVideoURL, _, optimizedVideoInfo) = optimizedResult else {
@@ -184,7 +184,7 @@ final class MediaUploadingPreprocessorTests {
#expect(imageInfo.thumbnailInfo?.height == 344) #expect(imageInfo.thumbnailInfo?.height == 344)
// Repeat with optimised media setting // Repeat with optimised media setting
appSettings.optimizeMediaUploads = true userSettings.optimizeMediaUploads = true
guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize), guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
case let .image(optimizedImageURL, thumbnailURL, optimizedImageInfo) = optimizedResult else { case let .image(optimizedImageURL, thumbnailURL, optimizedImageInfo) = optimizedResult else {
@@ -228,7 +228,7 @@ final class MediaUploadingPreprocessorTests {
#expect(imageInfo.thumbnailInfo?.height == 800) #expect(imageInfo.thumbnailInfo?.height == 800)
// Repeat with optimised media setting // Repeat with optimised media setting
appSettings.optimizeMediaUploads = true userSettings.optimizeMediaUploads = true
guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize), guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
case let .image(optimizedImageURL, thumbnailURL, optimizedImageInfo) = optimizedResult else { case let .image(optimizedImageURL, thumbnailURL, optimizedImageInfo) = optimizedResult else {
@@ -274,7 +274,7 @@ final class MediaUploadingPreprocessorTests {
#expect(imageInfo.thumbnailInfo?.height == 240) #expect(imageInfo.thumbnailInfo?.height == 240)
// Repeat with optimised media setting // Repeat with optimised media setting
appSettings.optimizeMediaUploads = true userSettings.optimizeMediaUploads = true
guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize), guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
case let .image(optimizedImageURL, _, optimizedImageInfo) = optimizedResult else { case let .image(optimizedImageURL, _, optimizedImageInfo) = optimizedResult else {
@@ -325,7 +325,7 @@ final class MediaUploadingPreprocessorTests {
#expect(imageInfo.thumbnailInfo?.height == 800) #expect(imageInfo.thumbnailInfo?.height == 800)
// Repeat with optimised media setting // Repeat with optimised media setting
appSettings.optimizeMediaUploads = true userSettings.optimizeMediaUploads = true
guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize), guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
case let .image(optimizedImageURL, thumbnailURL, optimizedImageInfo) = optimizedResult else { case let .image(optimizedImageURL, thumbnailURL, optimizedImageInfo) = optimizedResult else {
@@ -377,7 +377,7 @@ final class MediaUploadingPreprocessorTests {
#expect(imageInfo.thumbnailInfo?.height == 472) #expect(imageInfo.thumbnailInfo?.height == 472)
// Repeat with optimised media setting // Repeat with optimised media setting
appSettings.optimizeMediaUploads = true userSettings.optimizeMediaUploads = true
guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize), guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
case let .image(optimizedImageURL, _, optimizedImageInfo) = optimizedResult else { case let .image(optimizedImageURL, _, optimizedImageInfo) = optimizedResult else {
@@ -419,7 +419,7 @@ final class MediaUploadingPreprocessorTests {
#expect(imageInfo.thumbnailInfo?.height == 800) #expect(imageInfo.thumbnailInfo?.height == 800)
// Repeat with optimised media setting // Repeat with optimised media setting
appSettings.optimizeMediaUploads = true userSettings.optimizeMediaUploads = true
guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize), guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
case let .image(optimizedImageURL, thumbnailURL, optimizedImageInfo) = optimizedResult else { case let .image(optimizedImageURL, thumbnailURL, optimizedImageInfo) = optimizedResult else {
@@ -453,7 +453,7 @@ final class MediaUploadingPreprocessorTests {
fatalError() fatalError()
} }
if appSettings.optimizeMediaUploads { if userSettings.optimizeMediaUploads {
// Check that new image has been scaled within the requirements for an optimised image // Check that new image has been scaled within the requirements for an optimised image
#expect(convertedImage.size.width <= MediaUploadingPreprocessor.Constants.optimizedMaxPixelSize) #expect(convertedImage.size.width <= MediaUploadingPreprocessor.Constants.optimizedMaxPixelSize)
#expect(convertedImage.size.height <= MediaUploadingPreprocessor.Constants.optimizedMaxPixelSize) #expect(convertedImage.size.height <= MediaUploadingPreprocessor.Constants.optimizedMaxPixelSize)
@@ -15,7 +15,7 @@ import Testing
struct NotificationSettingsScreenViewModelTests { struct NotificationSettingsScreenViewModelTests {
private var viewModel: NotificationSettingsScreenViewModelProtocol private var viewModel: NotificationSettingsScreenViewModelProtocol
private var context: NotificationSettingsScreenViewModelType.Context private var context: NotificationSettingsScreenViewModelType.Context
private var appSettings: AppSettings private var userSettings: UserSettings
private var userNotificationCenter: UserNotificationCenterMock private var userNotificationCenter: UserNotificationCenterMock
private var notificationSettingsProxy: NotificationSettingsProxyMock private var notificationSettingsProxy: NotificationSettingsProxyMock
private var toneManager: NotificationToneManagerMock private var toneManager: NotificationToneManagerMock
@@ -23,7 +23,7 @@ struct NotificationSettingsScreenViewModelTests {
init() throws { init() throws {
userNotificationCenter = UserNotificationCenterMock() userNotificationCenter = UserNotificationCenterMock()
userNotificationCenter.authorizationStatusReturnValue = .authorized userNotificationCenter.authorizationStatusReturnValue = .authorized
appSettings = AppSettings.volatile() userSettings = UserSettings.volatile()
notificationSettingsProxy = NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()) notificationSettingsProxy = NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration())
notificationSettingsProxy.getDefaultRoomNotificationModeIsEncryptedIsOneToOneReturnValue = .allMessages notificationSettingsProxy.getDefaultRoomNotificationModeIsEncryptedIsOneToOneReturnValue = .allMessages
notificationSettingsProxy.isRoomMentionEnabledReturnValue = true notificationSettingsProxy.isRoomMentionEnabledReturnValue = true
@@ -31,7 +31,7 @@ struct NotificationSettingsScreenViewModelTests {
toneManager = NotificationToneManagerMock() toneManager = NotificationToneManagerMock()
toneManager.customTonesReturnValue = [] toneManager.customTonesReturnValue = []
viewModel = NotificationSettingsScreenViewModel(appSettings: appSettings, viewModel = NotificationSettingsScreenViewModel(userSettings: userSettings,
userNotificationCenter: userNotificationCenter, userNotificationCenter: userNotificationCenter,
notificationToneManager: toneManager, notificationToneManager: toneManager,
notificationSettingsProxy: notificationSettingsProxy, notificationSettingsProxy: notificationSettingsProxy,
@@ -42,16 +42,16 @@ struct NotificationSettingsScreenViewModelTests {
@Test @Test
func enableNotifications() { func enableNotifications() {
appSettings.enableNotifications = false userSettings.enableNotifications = false
context.send(viewAction: .changedEnableNotifications) context.send(viewAction: .changedEnableNotifications)
#expect(appSettings.enableNotifications) #expect(userSettings.enableNotifications)
} }
@Test @Test
func disableNotifications() { func disableNotifications() {
appSettings.enableNotifications = true userSettings.enableNotifications = true
context.send(viewAction: .changedEnableNotifications) context.send(viewAction: .changedEnableNotifications)
#expect(!appSettings.enableNotifications) #expect(!userSettings.enableNotifications)
} }
@Test @Test
@@ -410,8 +410,8 @@ struct NotificationSettingsScreenViewModelTests {
func selectingAlertTonePersistsSelection() { func selectingAlertTonePersistsSelection() {
// Given a tone and a manager that persists the selection to app settings // Given a tone and a manager that persists the selection to app settings
let tone = NotificationTone.createBundledSound(label: "Test", filename: "test.caf") let tone = NotificationTone.createBundledSound(label: "Test", filename: "test.caf")
toneManager.setSelectedToneClosure = { [appSettings] selectedTone in toneManager.setSelectedToneClosure = { [userSettings] selectedTone in
appSettings.selectedNotificationTone = selectedTone userSettings.selectedNotificationTone = selectedTone
return NotificationToneManager.libraryLocation return NotificationToneManager.libraryLocation
} }
@@ -419,21 +419,21 @@ struct NotificationSettingsScreenViewModelTests {
context.send(viewAction: .selectAlertTone(tone)) context.send(viewAction: .selectAlertTone(tone))
// Then it is reflected in app settings // Then it is reflected in app settings
#expect(appSettings.selectedNotificationTone == tone) #expect(userSettings.selectedNotificationTone == tone)
} }
@Test @Test
func deletingActiveToneResetsSelection() { func deletingActiveToneResetsSelection() {
// Given the active tone is a custom tone // Given the active tone is a custom tone
let customTone = NotificationTone.createCustomUserSound(filename: "custom.caf") let customTone = NotificationTone.createCustomUserSound(filename: "custom.caf")
appSettings.selectedNotificationTone = customTone userSettings.selectedNotificationTone = customTone
toneManager.customTonesReturnValue = [customTone] toneManager.customTonesReturnValue = [customTone]
// When that tone is deleted // When that tone is deleted
context.send(viewAction: .deleteCustomAlertTones([customTone])) context.send(viewAction: .deleteCustomAlertTones([customTone]))
// Then the selection is cleared, falling back to the default // Then the selection is cleared, falling back to the default
#expect(appSettings.selectedNotificationTone == nil) #expect(userSettings.selectedNotificationTone == nil)
} }
@Test @Test
@@ -441,14 +441,14 @@ struct NotificationSettingsScreenViewModelTests {
// Given a custom tone is active and a different custom tone also exists // Given a custom tone is active and a different custom tone also exists
let activeTone = NotificationTone.createCustomUserSound(filename: "active.caf") let activeTone = NotificationTone.createCustomUserSound(filename: "active.caf")
let otherTone = NotificationTone.createCustomUserSound(filename: "other.caf") let otherTone = NotificationTone.createCustomUserSound(filename: "other.caf")
appSettings.selectedNotificationTone = activeTone userSettings.selectedNotificationTone = activeTone
toneManager.customTonesReturnValue = [activeTone, otherTone] toneManager.customTonesReturnValue = [activeTone, otherTone]
// When the non-active tone is deleted // When the non-active tone is deleted
context.send(viewAction: .deleteCustomAlertTones([otherTone])) context.send(viewAction: .deleteCustomAlertTones([otherTone]))
// Then the active selection is unchanged // Then the active selection is unchanged
#expect(appSettings.selectedNotificationTone == activeTone) #expect(userSettings.selectedNotificationTone == activeTone)
} }
@Test @Test
@@ -457,7 +457,7 @@ struct NotificationSettingsScreenViewModelTests {
let customTone = NotificationTone.createCustomUserSound(filename: "custom.caf") let customTone = NotificationTone.createCustomUserSound(filename: "custom.caf")
var remainingTones = [customTone] var remainingTones = [customTone]
toneManager.customTonesClosure = { remainingTones } toneManager.customTonesClosure = { remainingTones }
let localVM = NotificationSettingsScreenViewModel(appSettings: appSettings, let localVM = NotificationSettingsScreenViewModel(userSettings: userSettings,
userNotificationCenter: userNotificationCenter, userNotificationCenter: userNotificationCenter,
notificationToneManager: toneManager, notificationToneManager: toneManager,
notificationSettingsProxy: notificationSettingsProxy, notificationSettingsProxy: notificationSettingsProxy,
@@ -476,7 +476,7 @@ struct NotificationSettingsScreenViewModelTests {
func deleteCustomToneFailurePreservesSelection() { func deleteCustomToneFailurePreservesSelection() {
// Given the active tone is a custom tone and deletion will fail // Given the active tone is a custom tone and deletion will fail
let customTone = NotificationTone.createCustomUserSound(filename: "custom.caf") let customTone = NotificationTone.createCustomUserSound(filename: "custom.caf")
appSettings.selectedNotificationTone = customTone userSettings.selectedNotificationTone = customTone
toneManager.deleteCustomToneThrowableError = NSError(domain: "test", code: 1) toneManager.deleteCustomToneThrowableError = NSError(domain: "test", code: 1)
toneManager.customTonesReturnValue = [customTone] toneManager.customTonesReturnValue = [customTone]
@@ -484,7 +484,7 @@ struct NotificationSettingsScreenViewModelTests {
context.send(viewAction: .deleteCustomAlertTones([customTone])) context.send(viewAction: .deleteCustomAlertTones([customTone]))
// Then the selection is unchanged // Then the selection is unchanged
#expect(appSettings.selectedNotificationTone == customTone) #expect(userSettings.selectedNotificationTone == customTone)
} }
@Test @Test
@@ -18,7 +18,7 @@ struct NotificationToneManagerTests {
private let manager: NotificationToneManager private let manager: NotificationToneManager
init() { init() {
manager = NotificationToneManager(appSettings: .volatile()) manager = NotificationToneManager(userSettings: .volatile())
} }
// MARK: - Deletion // MARK: - Deletion
+11 -33
View File
@@ -15,7 +15,6 @@ import Testing
struct PillContextTests { struct PillContextTests {
@Test @Test
func user() async { func user() async {
let appSettings = AppSettings.volatile()
let userIndicatorController = UserIndicatorControllerMock() let userIndicatorController = UserIndicatorControllerMock()
let id = "@test:matrix.org" let id = "@test:matrix.org"
@@ -28,9 +27,8 @@ struct PillContextTests {
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
appSettings: appSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(appSettings: appSettings), emojiProvider: EmojiProvider(userSettings: .volatile()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .user(userID: id), font: .preferredFont(forTextStyle: .body))) let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .user(userID: id), font: .preferredFont(forTextStyle: .body)))
@@ -49,7 +47,6 @@ struct PillContextTests {
@Test @Test
func ownUser() { func ownUser() {
let appSettings = AppSettings.volatile()
let userIndicatorController = UserIndicatorControllerMock() let userIndicatorController = UserIndicatorControllerMock()
let id = "@test:matrix.org" let id = "@test:matrix.org"
@@ -62,9 +59,8 @@ struct PillContextTests {
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
appSettings: appSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(appSettings: appSettings), emojiProvider: EmojiProvider(userSettings: .volatile()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .user(userID: id), font: .preferredFont(forTextStyle: .body))) let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .user(userID: id), font: .preferredFont(forTextStyle: .body)))
@@ -74,7 +70,6 @@ struct PillContextTests {
@Test @Test
func allUsers() { func allUsers() {
let appSettings = AppSettings.volatile()
let userIndicatorController = UserIndicatorControllerMock() let userIndicatorController = UserIndicatorControllerMock()
let avatarURL = URL(string: "https://matrix.jpg") let avatarURL = URL(string: "https://matrix.jpg")
@@ -88,9 +83,8 @@ struct PillContextTests {
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
appSettings: appSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(appSettings: appSettings), emojiProvider: EmojiProvider(userSettings: .volatile()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .allUsers, font: .preferredFont(forTextStyle: .body))) let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .allUsers, font: .preferredFont(forTextStyle: .body)))
@@ -101,7 +95,6 @@ struct PillContextTests {
@Test @Test
func roomIDMention() { func roomIDMention() {
let appSettings = AppSettings.volatile()
let userIndicatorController = UserIndicatorControllerMock() let userIndicatorController = UserIndicatorControllerMock()
let proxyMock = JoinedRoomProxyMock(.init()) let proxyMock = JoinedRoomProxyMock(.init())
@@ -114,9 +107,8 @@ struct PillContextTests {
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
appSettings: appSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(appSettings: appSettings), emojiProvider: EmojiProvider(userSettings: .volatile()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .roomID("1"), font: .preferredFont(forTextStyle: .body))) let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .roomID("1"), font: .preferredFont(forTextStyle: .body)))
@@ -128,7 +120,6 @@ struct PillContextTests {
@Test @Test
func roomIDMentionMissingRoom() { func roomIDMentionMissingRoom() {
let appSettings = AppSettings.volatile()
let userIndicatorController = UserIndicatorControllerMock() let userIndicatorController = UserIndicatorControllerMock()
let proxyMock = JoinedRoomProxyMock(.init()) let proxyMock = JoinedRoomProxyMock(.init())
@@ -139,9 +130,8 @@ struct PillContextTests {
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
appSettings: appSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(appSettings: appSettings), emojiProvider: EmojiProvider(userSettings: .volatile()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .roomID("1"), font: .preferredFont(forTextStyle: .body))) let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .roomID("1"), font: .preferredFont(forTextStyle: .body)))
@@ -153,7 +143,6 @@ struct PillContextTests {
@Test @Test
func roomAliasMention() { func roomAliasMention() {
let appSettings = AppSettings.volatile()
let userIndicatorController = UserIndicatorControllerMock() let userIndicatorController = UserIndicatorControllerMock()
let proxyMock = JoinedRoomProxyMock(.init()) let proxyMock = JoinedRoomProxyMock(.init())
@@ -168,9 +157,8 @@ struct PillContextTests {
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
appSettings: appSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(appSettings: appSettings), emojiProvider: EmojiProvider(userSettings: .volatile()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .roomAlias("#foundation-and-empire:matrix.org"), font: .preferredFont(forTextStyle: .body))) let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .roomAlias("#foundation-and-empire:matrix.org"), font: .preferredFont(forTextStyle: .body)))
@@ -182,7 +170,6 @@ struct PillContextTests {
@Test @Test
func roomAliasMentionMissingRoom() { func roomAliasMentionMissingRoom() {
let appSettings = AppSettings.volatile()
let userIndicatorController = UserIndicatorControllerMock() let userIndicatorController = UserIndicatorControllerMock()
let proxyMock = JoinedRoomProxyMock(.init()) let proxyMock = JoinedRoomProxyMock(.init())
@@ -193,9 +180,8 @@ struct PillContextTests {
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
appSettings: appSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(appSettings: appSettings), emojiProvider: EmojiProvider(userSettings: .volatile()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .roomAlias("#foundation-and-empire:matrix.org"), font: .preferredFont(forTextStyle: .body))) let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .roomAlias("#foundation-and-empire:matrix.org"), font: .preferredFont(forTextStyle: .body)))
@@ -207,7 +193,6 @@ struct PillContextTests {
@Test @Test
func eventOnRoomIDMention() { func eventOnRoomIDMention() {
let appSettings = AppSettings.volatile()
let userIndicatorController = UserIndicatorControllerMock() let userIndicatorController = UserIndicatorControllerMock()
let proxyMock = JoinedRoomProxyMock(.init()) let proxyMock = JoinedRoomProxyMock(.init())
@@ -220,9 +205,8 @@ struct PillContextTests {
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
appSettings: appSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(appSettings: appSettings), emojiProvider: EmojiProvider(userSettings: .volatile()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .event(room: .roomID("1")), font: .preferredFont(forTextStyle: .body))) let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .event(room: .roomID("1")), font: .preferredFont(forTextStyle: .body)))
@@ -234,7 +218,6 @@ struct PillContextTests {
@Test @Test
func eventOnRoomIDMentionMissingRoom() { func eventOnRoomIDMentionMissingRoom() {
let appSettings = AppSettings.volatile()
let userIndicatorController = UserIndicatorControllerMock() let userIndicatorController = UserIndicatorControllerMock()
let proxyMock = JoinedRoomProxyMock(.init()) let proxyMock = JoinedRoomProxyMock(.init())
@@ -245,9 +228,8 @@ struct PillContextTests {
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
appSettings: appSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(appSettings: appSettings), emojiProvider: EmojiProvider(userSettings: .volatile()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .event(room: .roomID("1")), font: .preferredFont(forTextStyle: .body))) let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .event(room: .roomID("1")), font: .preferredFont(forTextStyle: .body)))
@@ -259,7 +241,6 @@ struct PillContextTests {
@Test @Test
func eventOnRoomAliasMention() { func eventOnRoomAliasMention() {
let appSettings = AppSettings.volatile()
let userIndicatorController = UserIndicatorControllerMock() let userIndicatorController = UserIndicatorControllerMock()
let proxyMock = JoinedRoomProxyMock(.init()) let proxyMock = JoinedRoomProxyMock(.init())
@@ -274,9 +255,8 @@ struct PillContextTests {
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
appSettings: appSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(appSettings: appSettings), emojiProvider: EmojiProvider(userSettings: .volatile()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .event(room: .roomAlias("#foundation-and-empire:matrix.org")), font: .preferredFont(forTextStyle: .body))) let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .event(room: .roomAlias("#foundation-and-empire:matrix.org")), font: .preferredFont(forTextStyle: .body)))
@@ -288,7 +268,6 @@ struct PillContextTests {
@Test @Test
func eventOnRoomAliasMentionMissingRoom() { func eventOnRoomAliasMentionMissingRoom() {
let appSettings = AppSettings.volatile()
let userIndicatorController = UserIndicatorControllerMock() let userIndicatorController = UserIndicatorControllerMock()
let proxyMock = JoinedRoomProxyMock(.init()) let proxyMock = JoinedRoomProxyMock(.init())
@@ -299,9 +278,8 @@ struct PillContextTests {
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
appSettings: appSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(appSettings: appSettings), emojiProvider: EmojiProvider(userSettings: .volatile()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .event(room: .roomAlias("#foundation-and-empire:matrix.org")), font: .preferredFont(forTextStyle: .body))) let context = PillContext(timelineContext: mock.context, data: PillTextAttachmentData(type: .event(room: .roomAlias("#foundation-and-empire:matrix.org")), font: .preferredFont(forTextStyle: .body)))
+15 -15
View File
@@ -14,14 +14,14 @@ import UIKit
@MainActor @MainActor
struct PresenceServiceTests { struct PresenceServiceTests {
let clientProxy: ClientProxyMock let clientProxy: ClientProxyMock
let appSettings: AppSettings let userSettings: UserSettings
let notificationCenter: NotificationCenter let notificationCenter: NotificationCenter
let sendsSubject = PassthroughSubject<(presence: ClientProxyPresence, sendImmediately: Bool), Never>() let sendsSubject = PassthroughSubject<(presence: ClientProxyPresence, sendImmediately: Bool), Never>()
init() { init() {
clientProxy = ClientProxyMock(.init()) clientProxy = ClientProxyMock(.init())
appSettings = AppSettings.volatile() userSettings = UserSettings.volatile()
notificationCenter = NotificationCenter() notificationCenter = NotificationCenter()
clientProxy.configurePresenceSendImmediatelyClosure = { [sendsSubject] presence, sendImmediately in clientProxy.configurePresenceSendImmediatelyClosure = { [sendsSubject] presence, sendImmediately in
@@ -32,14 +32,14 @@ struct PresenceServiceTests {
private func makeService(initialApplicationState: UIApplication.State) -> PresenceService { private func makeService(initialApplicationState: UIApplication.State) -> PresenceService {
PresenceService(clientProxy: clientProxy, PresenceService(clientProxy: clientProxy,
appSettings: appSettings, userSettings: userSettings,
notificationCenter: notificationCenter, notificationCenter: notificationCenter,
initialApplicationState: initialApplicationState) initialApplicationState: initialApplicationState)
} }
@Test @Test
func serviceSeededActiveWhileSharingReportsOnline() async throws { func serviceSeededActiveWhileSharingReportsOnline() async throws {
appSettings.sharePresence = true userSettings.sharePresence = true
let deferred = deferFulfillment(sendsSubject) { $0.presence == .online } let deferred = deferFulfillment(sendsSubject) { $0.presence == .online }
let service = makeService(initialApplicationState: .active) let service = makeService(initialApplicationState: .active)
@@ -53,7 +53,7 @@ struct PresenceServiceTests {
@Test @Test
func serviceSeededBackgroundedWhileSharingReportsUnavailable() async throws { func serviceSeededBackgroundedWhileSharingReportsUnavailable() async throws {
appSettings.sharePresence = true userSettings.sharePresence = true
let deferred = deferFulfillment(sendsSubject) { $0.presence == .unavailable } let deferred = deferFulfillment(sendsSubject) { $0.presence == .unavailable }
let service = makeService(initialApplicationState: .background) let service = makeService(initialApplicationState: .background)
@@ -66,7 +66,7 @@ struct PresenceServiceTests {
@Test @Test
func serviceSeededActiveWhileNotSharingReportsOffline() async throws { func serviceSeededActiveWhileNotSharingReportsOffline() async throws {
appSettings.sharePresence = false userSettings.sharePresence = false
let deferred = deferFulfillment(sendsSubject) { $0.presence == .offline } let deferred = deferFulfillment(sendsSubject) { $0.presence == .offline }
let service = makeService(initialApplicationState: .active) let service = makeService(initialApplicationState: .active)
@@ -79,7 +79,7 @@ struct PresenceServiceTests {
@Test @Test
func becomingActiveNotificationWhileSharingReportsOnlineImmediately() async throws { func becomingActiveNotificationWhileSharingReportsOnlineImmediately() async throws {
appSettings.sharePresence = true userSettings.sharePresence = true
let service = makeService(initialApplicationState: .inactive) let service = makeService(initialApplicationState: .inactive)
let deferred = deferFulfillment(sendsSubject) { $0.presence == .online } let deferred = deferFulfillment(sendsSubject) { $0.presence == .online }
@@ -93,7 +93,7 @@ struct PresenceServiceTests {
@Test @Test
func resigningActiveNotificationWhileSharingReportsUnavailableImmediately() async throws { func resigningActiveNotificationWhileSharingReportsUnavailableImmediately() async throws {
appSettings.sharePresence = true userSettings.sharePresence = true
let initialDeferred = deferFulfillment(sendsSubject) { $0.presence == .online } let initialDeferred = deferFulfillment(sendsSubject) { $0.presence == .online }
let service = makeService(initialApplicationState: .active) let service = makeService(initialApplicationState: .active)
_ = try await initialDeferred.fulfill() _ = try await initialDeferred.fulfill()
@@ -109,19 +109,19 @@ struct PresenceServiceTests {
@Test @Test
func togglingSharingWhileActiveDrivesOnlineAndOffline() async throws { func togglingSharingWhileActiveDrivesOnlineAndOffline() async throws {
appSettings.sharePresence = false userSettings.sharePresence = false
let initialDeferred = deferFulfillment(sendsSubject) { $0.presence == .offline } let initialDeferred = deferFulfillment(sendsSubject) { $0.presence == .offline }
let service = makeService(initialApplicationState: .active) let service = makeService(initialApplicationState: .active)
_ = try await initialDeferred.fulfill() _ = try await initialDeferred.fulfill()
let onlineDeferred = deferFulfillment(sendsSubject) { $0.presence == .online } let onlineDeferred = deferFulfillment(sendsSubject) { $0.presence == .online }
appSettings.sharePresence = true userSettings.sharePresence = true
let online = try await onlineDeferred.fulfill() let online = try await onlineDeferred.fulfill()
#expect(online.presence == .online) #expect(online.presence == .online)
#expect(online.sendImmediately) #expect(online.sendImmediately)
let offlineDeferred = deferFulfillment(sendsSubject) { $0.presence == .offline } let offlineDeferred = deferFulfillment(sendsSubject) { $0.presence == .offline }
appSettings.sharePresence = false userSettings.sharePresence = false
let offline = try await offlineDeferred.fulfill() let offline = try await offlineDeferred.fulfill()
#expect(offline.presence == .offline) #expect(offline.presence == .offline)
#expect(offline.sendImmediately) #expect(offline.sendImmediately)
@@ -131,7 +131,7 @@ struct PresenceServiceTests {
@Test @Test
func repeatingTheSameStateSendsOnlyOnce() async throws { func repeatingTheSameStateSendsOnlyOnce() async throws {
appSettings.sharePresence = true userSettings.sharePresence = true
let initialDeferred = deferFulfillment(sendsSubject) { $0.presence == .online } let initialDeferred = deferFulfillment(sendsSubject) { $0.presence == .online }
let service = makeService(initialApplicationState: .active) let service = makeService(initialApplicationState: .active)
@@ -148,7 +148,7 @@ struct PresenceServiceTests {
@Test @Test
func failedImmediateSendIsNotRetriedUntilTheDesiredPresenceChanges() async throws { func failedImmediateSendIsNotRetriedUntilTheDesiredPresenceChanges() async throws {
appSettings.sharePresence = true userSettings.sharePresence = true
clientProxy.configurePresenceSendImmediatelyClosure = { [sendsSubject] presence, sendImmediately in clientProxy.configurePresenceSendImmediatelyClosure = { [sendsSubject] presence, sendImmediately in
sendsSubject.send((presence, sendImmediately)) sendsSubject.send((presence, sendImmediately))
return presence == .online ? .failure(.forbiddenAccess) : .success(()) return presence == .online ? .failure(.forbiddenAccess) : .success(())
@@ -173,7 +173,7 @@ struct PresenceServiceTests {
@Test @Test
func newerTransitionWinsWhenAnEarlierSendIsInFlight() async throws { func newerTransitionWinsWhenAnEarlierSendIsInFlight() async throws {
appSettings.sharePresence = true userSettings.sharePresence = true
let (onlineStartedStream, onlineStartedContinuation) = AsyncStream<Void>.makeStream() let (onlineStartedStream, onlineStartedContinuation) = AsyncStream<Void>.makeStream()
let (resumeOnlineSendStream, resumeOnlineSendContinuation) = AsyncStream<Void>.makeStream() let (resumeOnlineSendStream, resumeOnlineSendContinuation) = AsyncStream<Void>.makeStream()
@@ -206,7 +206,7 @@ struct PresenceServiceTests {
@Test @Test
func deinitCancelsPendingSend() async throws { func deinitCancelsPendingSend() async throws {
appSettings.sharePresence = true userSettings.sharePresence = true
let (onlineStartedStream, onlineStartedContinuation) = AsyncStream.makeStream(of: Void.self) let (onlineStartedStream, onlineStartedContinuation) = AsyncStream.makeStream(of: Void.self)
let (onlineFinishedStream, onlineFinishedContinuation) = AsyncStream.makeStream(of: Void.self) let (onlineFinishedStream, onlineFinishedContinuation) = AsyncStream.makeStream(of: Void.self)
@@ -167,7 +167,7 @@ struct RoomDetailsEditScreenViewModelTests {
userIndicatorController = UserIndicatorControllerMock() userIndicatorController = UserIndicatorControllerMock()
viewModel = .init(roomProxy: JoinedRoomProxyMock(roomProxyConfiguration), viewModel = .init(roomProxy: JoinedRoomProxyMock(roomProxyConfiguration),
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: .volatile()), mediaUploadingPreprocessor: MediaUploadingPreprocessor(userSettings: .volatile()),
userIndicatorController: userIndicatorController) userIndicatorController: userIndicatorController)
} }
} }
@@ -30,7 +30,7 @@ struct RoomDetailsScreenViewModelTests {
notificationSettingsProxyMock = NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()) notificationSettingsProxyMock = NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration())
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
appSettings: AppSettings.volatile(), userSettings: UserSettings.volatile(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -44,7 +44,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers, joinRule: .public)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers, joinRule: .public))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
appSettings: AppSettings.volatile(), userSettings: UserSettings.volatile(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -65,7 +65,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
appSettings: AppSettings.volatile(), userSettings: UserSettings.volatile(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -87,7 +87,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
appSettings: AppSettings.volatile(), userSettings: UserSettings.volatile(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -146,7 +146,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
appSettings: AppSettings.volatile(), userSettings: UserSettings.volatile(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -168,7 +168,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
appSettings: AppSettings.volatile(), userSettings: UserSettings.volatile(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -201,7 +201,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init(clientProxy: clientProxy)), userSession: UserSessionMock(.init(clientProxy: clientProxy)),
appSettings: AppSettings.volatile(), userSettings: UserSettings.volatile(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -233,7 +233,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
appSettings: AppSettings.volatile(), userSettings: UserSettings.volatile(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -266,7 +266,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init(clientProxy: clientProxy)), userSession: UserSessionMock(.init(clientProxy: clientProxy)),
appSettings: AppSettings.volatile(), userSettings: UserSettings.volatile(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -300,7 +300,7 @@ struct RoomDetailsScreenViewModelTests {
powerLevelsConfiguration: .init(canUserInvite: false))) powerLevelsConfiguration: .init(canUserInvite: false)))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
appSettings: AppSettings.volatile(), userSettings: UserSettings.volatile(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -318,7 +318,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers, joinRule: .public)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers, joinRule: .public))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
appSettings: AppSettings.volatile(), userSettings: UserSettings.volatile(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -367,7 +367,7 @@ struct RoomDetailsScreenViewModelTests {
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
appSettings: AppSettings.volatile(), userSettings: UserSettings.volatile(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -403,7 +403,7 @@ struct RoomDetailsScreenViewModelTests {
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
appSettings: AppSettings.volatile(), userSettings: UserSettings.volatile(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -439,7 +439,7 @@ struct RoomDetailsScreenViewModelTests {
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
appSettings: AppSettings.volatile(), userSettings: UserSettings.volatile(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -460,7 +460,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
appSettings: AppSettings.volatile(), userSettings: UserSettings.volatile(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -481,7 +481,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, members: mockedMembers)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, members: mockedMembers))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
appSettings: AppSettings.volatile(), userSettings: UserSettings.volatile(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -500,7 +500,7 @@ struct RoomDetailsScreenViewModelTests {
notificationSettingsProxyMock.getNotificationSettingsRoomIdIsEncryptedIsOneToOneThrowableError = NotificationSettingsError.Generic(msg: "error") notificationSettingsProxyMock.getNotificationSettingsRoomIdIsEncryptedIsOneToOneThrowableError = NotificationSettingsError.Generic(msg: "error")
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
appSettings: AppSettings.volatile(), userSettings: UserSettings.volatile(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -709,7 +709,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, knockRequestsState: .loaded(mockedRequests), joinRule: .knock)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, knockRequestsState: .loaded(mockedRequests), joinRule: .knock))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
appSettings: AppSettings.volatile(), userSettings: UserSettings.volatile(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -731,7 +731,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, knockRequestsState: .loading, joinRule: .knock)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, knockRequestsState: .loading, joinRule: .knock))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
appSettings: AppSettings.volatile(), userSettings: UserSettings.volatile(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -755,7 +755,7 @@ struct RoomDetailsScreenViewModelTests {
powerLevelsConfiguration: .init(canUserInvite: false))) powerLevelsConfiguration: .init(canUserInvite: false)))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
appSettings: AppSettings.volatile(), userSettings: UserSettings.volatile(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -779,7 +779,7 @@ struct RoomDetailsScreenViewModelTests {
roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, members: mockedMembers, knockRequestsState: .loaded(mockedRequests), joinRule: .knock)) roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, members: mockedMembers, knockRequestsState: .loaded(mockedRequests), joinRule: .knock))
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
appSettings: AppSettings.volatile(), userSettings: UserSettings.volatile(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -807,7 +807,7 @@ struct RoomDetailsScreenViewModelTests {
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
appSettings: AppSettings.volatile(), userSettings: UserSettings.volatile(),
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -19,10 +19,10 @@ final class RoomFlowCoordinatorTests {
var navigationStackCoordinator: NavigationStackCoordinator! var navigationStackCoordinator: NavigationStackCoordinator!
var cancellables = Set<AnyCancellable>() var cancellables = Set<AnyCancellable>()
private let appSettings: AppSettings private let userSettings: UserSettings
init() { init() {
appSettings = AppSettings.volatile() userSettings = UserSettings.volatile()
} }
@Test @Test
@@ -230,7 +230,7 @@ final class RoomFlowCoordinatorTests {
@Test @Test
func threadedEventRoutes() async throws { func threadedEventRoutes() async throws {
appSettings.threadsEnabled = true userSettings.threadsEnabled = true
setupRoomFlowCoordinator() setupRoomFlowCoordinator()
// Navigate directly to the threaded event // Navigate directly to the threaded event
@@ -526,10 +526,10 @@ final class RoomFlowCoordinatorTests {
bugReportService: BugReportServiceMock(.init()), bugReportService: BugReportServiceMock(.init()),
elementCallService: ElementCallServiceMock(.init()), elementCallService: ElementCallServiceMock(.init()),
timelineControllerFactory: timelineControllerFactory, timelineControllerFactory: timelineControllerFactory,
emojiProvider: EmojiProvider(appSettings: appSettings), emojiProvider: EmojiProvider(userSettings: userSettings),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
appSettings: appSettings, userSettings: userSettings,
appHooks: AppHooks(), appHooks: AppHooks(),
analytics: AnalyticsServiceMock(.init()), analytics: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -11,14 +11,14 @@ import Testing
@MainActor @MainActor
final class RoomListFiltersStateTests { final class RoomListFiltersStateTests {
var appSettings: AppSettings var userSettings: UserSettings
var state: RoomListFiltersState var state: RoomListFiltersState
/// The filters that aren't hidden behind a feature flag. /// The filters that aren't hidden behind a feature flag.
let defaultFilters = RoomListFilter.allCases.filter { $0 != .mentions && $0 != .lowPriority } let defaultFilters = RoomListFilter.allCases.filter { $0 != .mentions && $0 != .lowPriority }
init() { init() {
appSettings = AppSettings.volatile() userSettings = UserSettings.volatile()
state = RoomListFiltersState(appSettings: appSettings) state = RoomListFiltersState(userSettings: userSettings)
} }
@Test @Test
@@ -148,12 +148,12 @@ final class RoomListFiltersStateTests {
// MARK: - Helpers // MARK: - Helpers
private func enableLowPriorityFeature() { private func enableLowPriorityFeature() {
appSettings.lowPriorityFilterEnabled = true userSettings.lowPriorityFilterEnabled = true
state = RoomListFiltersState(appSettings: appSettings) state = RoomListFiltersState(userSettings: userSettings)
} }
private func enableMentionsFeature() { private func enableMentionsFeature() {
appSettings.mentionsFilterEnabled = true userSettings.mentionsFilterEnabled = true
state = RoomListFiltersState(appSettings: appSettings) state = RoomListFiltersState(userSettings: userSettings)
} }
} }
@@ -51,16 +51,16 @@ struct RoomMembersFlowCoordinatorTests {
let clientProxy = ClientProxyMock(.init()) let clientProxy = ClientProxyMock(.init())
clientProxy.directRoomForUserIDReturnValue = .success(nil) clientProxy.directRoomForUserIDReturnValue = .success(nil)
let appSettings = AppSettings.volatile() let userSettings = UserSettings.volatile()
let flowParameters = CommonFlowParameters(userSession: UserSessionMock(.init(clientProxy: clientProxy)), let flowParameters = CommonFlowParameters(userSession: UserSessionMock(.init(clientProxy: clientProxy)),
bugReportService: BugReportServiceMock(.init()), bugReportService: BugReportServiceMock(.init()),
elementCallService: ElementCallServiceMock(.init()), elementCallService: ElementCallServiceMock(.init()),
timelineControllerFactory: TimelineControllerFactoryMock(.init()), timelineControllerFactory: TimelineControllerFactoryMock(.init()),
emojiProvider: EmojiProvider(appSettings: appSettings), emojiProvider: EmojiProvider(userSettings: userSettings),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
appSettings: appSettings, userSettings: userSettings,
appHooks: AppHooks(), appHooks: AppHooks(),
analytics: AnalyticsServiceMock(.init()), analytics: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
@@ -16,12 +16,6 @@ import Testing
@MainActor @MainActor
final class RoomScreenViewModelTests { final class RoomScreenViewModelTests {
private let appSettings: AppSettings
init() async throws {
appSettings = AppSettings.volatile()
}
@Test @Test
func pinnedEventsBanner() async throws { func pinnedEventsBanner() async throws {
var configuration = JoinedRoomProxyMockConfiguration() var configuration = JoinedRoomProxyMockConfiguration()
@@ -42,7 +36,6 @@ final class RoomScreenViewModelTests {
roomProxy: roomProxyMock, roomProxy: roomProxyMock,
initialSelectedPinnedEventID: nil, initialSelectedPinnedEventID: nil,
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
appSettings: appSettings,
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
@@ -122,7 +115,6 @@ final class RoomScreenViewModelTests {
roomProxy: roomProxyMock, roomProxy: roomProxyMock,
initialSelectedPinnedEventID: "test1", initialSelectedPinnedEventID: "test1",
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
appSettings: appSettings,
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
@@ -161,7 +153,9 @@ final class RoomScreenViewModelTests {
@Test @Test
func pinnedEventsBannerThreadedSelection() async throws { func pinnedEventsBannerThreadedSelection() async throws {
appSettings.threadsEnabled = true let userSettings = UserSettings.volatile()
userSettings.threadsEnabled = true
let userSession = UserSessionMock(.init(userSettings: userSettings))
let roomProxyMock = JoinedRoomProxyMock(.init()) let roomProxyMock = JoinedRoomProxyMock(.init())
let eventMock = TimelineEventSDKMock() let eventMock = TimelineEventSDKMock()
@@ -178,11 +172,10 @@ final class RoomScreenViewModelTests {
.event(.init(item: EventTimelineItem(configuration: .init(eventID: "test3")), uniqueID: .init("3")))] .event(.init(item: EventTimelineItem(configuration: .init(eventID: "test3")), uniqueID: .init("3")))]
roomProxyMock.pinnedEventsTimelineReturnValue = .success(pinnedTimelineMock) roomProxyMock.pinnedEventsTimelineReturnValue = .success(pinnedTimelineMock)
let viewModel = RoomScreenViewModel(userSession: UserSessionMock(.init()), let viewModel = RoomScreenViewModel(userSession: userSession,
roomProxy: roomProxyMock, roomProxy: roomProxyMock,
initialSelectedPinnedEventID: "test1", initialSelectedPinnedEventID: "test1",
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
appSettings: appSettings,
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
@@ -238,7 +231,6 @@ final class RoomScreenViewModelTests {
roomProxy: roomProxyMock, roomProxy: roomProxyMock,
initialSelectedPinnedEventID: nil, initialSelectedPinnedEventID: nil,
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
appSettings: appSettings,
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
@@ -273,7 +265,6 @@ final class RoomScreenViewModelTests {
roomProxy: roomProxyMock, roomProxy: roomProxyMock,
initialSelectedPinnedEventID: nil, initialSelectedPinnedEventID: nil,
ongoingCallRoomIDPublisher: ongoingCallRoomIDSubject.asCurrentValuePublisher(), ongoingCallRoomIDPublisher: ongoingCallRoomIDSubject.asCurrentValuePublisher(),
appSettings: appSettings,
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
@@ -320,7 +311,6 @@ final class RoomScreenViewModelTests {
roomProxy: roomProxyMock, roomProxy: roomProxyMock,
initialSelectedPinnedEventID: nil, initialSelectedPinnedEventID: nil,
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
appSettings: appSettings,
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
@@ -342,7 +332,6 @@ final class RoomScreenViewModelTests {
roomProxy: roomProxyMock, roomProxy: roomProxyMock,
initialSelectedPinnedEventID: nil, initialSelectedPinnedEventID: nil,
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
appSettings: appSettings,
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
@@ -375,7 +364,6 @@ final class RoomScreenViewModelTests {
roomProxy: roomProxyMock, roomProxy: roomProxyMock,
initialSelectedPinnedEventID: nil, initialSelectedPinnedEventID: nil,
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
appSettings: appSettings,
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
@@ -403,7 +391,6 @@ final class RoomScreenViewModelTests {
roomProxy: roomProxyMock, roomProxy: roomProxyMock,
initialSelectedPinnedEventID: nil, initialSelectedPinnedEventID: nil,
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
appSettings: appSettings,
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
@@ -422,7 +409,6 @@ final class RoomScreenViewModelTests {
roomProxy: roomProxyMock, roomProxy: roomProxyMock,
initialSelectedPinnedEventID: nil, initialSelectedPinnedEventID: nil,
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
appSettings: appSettings,
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
@@ -448,7 +434,6 @@ final class RoomScreenViewModelTests {
roomProxy: roomProxyMock, roomProxy: roomProxyMock,
initialSelectedPinnedEventID: nil, initialSelectedPinnedEventID: nil,
ongoingCallRoomIDPublisher: .init(.init(nil)), ongoingCallRoomIDPublisher: .init(.init(nil)),
appSettings: appSettings,
appHooks: AppHooks(), appHooks: AppHooks(),
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
@@ -17,7 +17,7 @@ final class RoomSummaryProviderTests {
.all(filters: [.space, .invite])]), .all(filters: [.space, .invite])]),
.deduplicateVersions] .deduplicateVersions]
var appSettings: AppSettings! var userSettings: UserSettings!
var roomList: RoomListSDKMock! var roomList: RoomListSDKMock!
var dynamicEntriesController: RoomListDynamicEntriesControllerSDKMock! var dynamicEntriesController: RoomListDynamicEntriesControllerSDKMock!
var roomSummaryProvider: RoomSummaryProvider! var roomSummaryProvider: RoomSummaryProvider!
@@ -90,8 +90,8 @@ final class RoomSummaryProviderTests {
// MARK: - Helpers // MARK: - Helpers
private func setup(isLowPriorityFilterEnabled: Bool = false) { private func setup(isLowPriorityFilterEnabled: Bool = false) {
appSettings = AppSettings.volatile() userSettings = UserSettings.volatile()
appSettings.lowPriorityFilterEnabled = isLowPriorityFilterEnabled userSettings.lowPriorityFilterEnabled = isLowPriorityFilterEnabled
let stateEventStringBuilder = RoomStateEventStringBuilder(userID: "@me:matrix.org") let stateEventStringBuilder = RoomStateEventStringBuilder(userID: "@me:matrix.org")
let attributedStringBuilder = AttributedStringBuilder(mentionBuilder: MentionBuilder()) let attributedStringBuilder = AttributedStringBuilder(mentionBuilder: MentionBuilder())
@@ -104,7 +104,7 @@ final class RoomSummaryProviderTests {
eventStringBuilder: eventStringBuilder, eventStringBuilder: eventStringBuilder,
name: "Test", name: "Test",
notificationSettings: NotificationSettingsProxyMock(with: .init()), notificationSettings: NotificationSettingsProxyMock(with: .init()),
appSettings: appSettings) userSettings: userSettings)
dynamicEntriesController = RoomListDynamicEntriesControllerSDKMock() dynamicEntriesController = RoomListDynamicEntriesControllerSDKMock()
dynamicEntriesController.setFilterKindReturnValue = true dynamicEntriesController.setFilterKindReturnValue = true
@@ -14,7 +14,7 @@ struct SearchScreenViewModelTests {
let viewModel: SearchScreenViewModelProtocol let viewModel: SearchScreenViewModelProtocol
let searchService: SearchServiceProxyMock let searchService: SearchServiceProxyMock
let userIndicatorController: UserIndicatorControllerMock let userIndicatorController: UserIndicatorControllerMock
let appSettings: AppSettings let userSettings: UserSettings
/// The rooms known to the client, empty until the room list loads. /// The rooms known to the client, empty until the room list loads.
let staticRoomListSubject = CurrentValueSubject<[RoomSummary], Never>([]) let staticRoomListSubject = CurrentValueSubject<[RoomSummary], Never>([])
/// Fires with the query each time the (async, debounced) message search runs. /// Fires with the query each time the (async, debounced) message search runs.
@@ -49,13 +49,13 @@ struct SearchScreenViewModelTests {
staticRoomListSubject.value.first { $0.id == identifier } staticRoomListSubject.value.first { $0.id == identifier }
} }
appSettings = AppSettings.volatile() userSettings = UserSettings.volatile()
viewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))), viewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))),
clientProxy: clientProxy, clientProxy: clientProxy,
mediaProvider: MediaProviderMock(.init()), mediaProvider: MediaProviderMock(.init()),
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appSettings: appSettings) userSettings: userSettings)
} }
@Test @Test
@@ -77,7 +77,7 @@ struct SearchScreenViewModelTests {
clientProxy: clientProxy, clientProxy: clientProxy,
mediaProvider: MediaProviderMock(.init()), mediaProvider: MediaProviderMock(.init()),
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appSettings: appSettings) userSettings: userSettings)
let deferred = deferFulfillment(viewModel.context.observe(\.viewState.rooms)) { !$0.isEmpty } let deferred = deferFulfillment(viewModel.context.observe(\.viewState.rooms)) { !$0.isEmpty }
viewModel.context.searchQuery = "room" viewModel.context.searchQuery = "room"
@@ -130,13 +130,13 @@ struct SearchScreenViewModelTests {
context.searchQuery = "Second" context.searchQuery = "Second"
context.send(viewAction: .selectRoom(roomID: "2")) context.send(viewAction: .selectRoom(roomID: "2"))
#expect(appSettings.searchBreadcrumbs == [.room(roomID: "2"), .query("Second")]) #expect(userSettings.searchBreadcrumbs == [.room(roomID: "2"), .query("Second")])
// Selecting the same room again from the empty state only bumps it back to the top. // Selecting the same room again from the empty state only bumps it back to the top.
context.searchQuery = "" context.searchQuery = ""
context.send(viewAction: .selectRoom(roomID: "2")) context.send(viewAction: .selectRoom(roomID: "2"))
#expect(appSettings.searchBreadcrumbs == [.room(roomID: "2"), .query("Second")]) #expect(userSettings.searchBreadcrumbs == [.room(roomID: "2"), .query("Second")])
} }
@Test @Test
@@ -144,7 +144,7 @@ struct SearchScreenViewModelTests {
staticRoomListSubject.send([.mock(id: "2", name: "Second")]) staticRoomListSubject.send([.mock(id: "2", name: "Second")])
let deferred = deferFulfillment(context.observe(\.viewState.breadcrumbs)) { $0.count == 2 } let deferred = deferFulfillment(context.observe(\.viewState.breadcrumbs)) { $0.count == 2 }
appSettings.searchBreadcrumbs = [.query("Second"), .room(roomID: "2")] userSettings.searchBreadcrumbs = [.query("Second"), .room(roomID: "2")]
try await deferred.fulfill() try await deferred.fulfill()
#expect(context.viewState.breadcrumbs.map(\.id) == ["query-Second", "room-2"]) #expect(context.viewState.breadcrumbs.map(\.id) == ["query-Second", "room-2"])
@@ -154,7 +154,7 @@ struct SearchScreenViewModelTests {
@Test @Test
func roomBreadcrumbsAreDisplayedAfterTheRoomListLoads() async throws { func roomBreadcrumbsAreDisplayedAfterTheRoomListLoads() async throws {
var deferred = deferFulfillment(context.observe(\.viewState.breadcrumbs)) { $0.count == 1 } var deferred = deferFulfillment(context.observe(\.viewState.breadcrumbs)) { $0.count == 1 }
appSettings.searchBreadcrumbs = [.query("Second"), .room(roomID: "2")] userSettings.searchBreadcrumbs = [.query("Second"), .room(roomID: "2")]
try await deferred.fulfill() try await deferred.fulfill()
#expect(context.viewState.breadcrumbs.map(\.id) == ["query-Second"]) #expect(context.viewState.breadcrumbs.map(\.id) == ["query-Second"])
@@ -457,9 +457,9 @@ final class SecurityAndPrivacyScreenViewModelTests {
topLevelSpaces: [SpaceServiceRoom] = [], topLevelSpaces: [SpaceServiceRoom] = [],
joinRule: ElementX.JoinRule, joinRule: ElementX.JoinRule,
forceDisableE2EE: Bool = false) { forceDisableE2EE: Bool = false) {
let appSettings = AppSettings.volatile() let userSettings = UserSettings.volatile()
appSettings.knockingEnabled = true userSettings.knockingEnabled = true
appSettings.forceDisableE2EE.applyRemoteValue(forceDisableE2EE) userSettings.forceDisableE2EE.applyRemoteValue(forceDisableE2EE)
roomProxy = JoinedRoomProxyMock(.init(isEncrypted: false, roomProxy = JoinedRoomProxyMock(.init(isEncrypted: false,
canonicalAlias: "#room:matrix.org", canonicalAlias: "#room:matrix.org",
members: .allMembersAsCreator, members: .allMembersAsCreator,
@@ -473,6 +473,6 @@ final class SecurityAndPrivacyScreenViewModelTests {
spaceServiceConfiguration: .init(topLevelSpaces: topLevelSpaces, spaceServiceConfiguration: .init(topLevelSpaces: topLevelSpaces,
joinedParentSpaces: joinedParentSpaces))), joinedParentSpaces: joinedParentSpaces))),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appSettings: appSettings) userSettings: userSettings)
} }
} }
@@ -21,7 +21,7 @@ struct SessionVerificationViewModelTests {
sessionVerificationController = SessionVerificationControllerProxyMock.configureMock() sessionVerificationController = SessionVerificationControllerProxyMock.configureMock()
viewModel = SessionVerificationScreenViewModel(sessionVerificationControllerProxy: sessionVerificationController, viewModel = SessionVerificationScreenViewModel(sessionVerificationControllerProxy: sessionVerificationController,
flow: .deviceInitiator, flow: .deviceInitiator,
appSettings: .volatile(), userSettings: .volatile(),
mediaProvider: MediaProviderMock(.init())) mediaProvider: MediaProviderMock(.init()))
context = viewModel.context context = viewModel.context
} }
@@ -177,7 +177,7 @@ struct SettingsScreenViewModelTests {
private mutating func setupViewModel(status: UserStatus = .init()) { private mutating func setupViewModel(status: UserStatus = .init()) {
clientProxy = ClientProxyMock(.init(userID: "", status: status)) clientProxy = ClientProxyMock(.init(userID: "", status: status))
viewModel = SettingsScreenViewModel(userSession: UserSessionMock(.init(clientProxy: clientProxy)), viewModel = SettingsScreenViewModel(userSession: UserSessionMock(.init(clientProxy: clientProxy)),
appSettings: AppSettings.volatile(), userSettings: UserSettings.volatile(),
isBugReportServiceEnabled: true, isBugReportServiceEnabled: true,
isInSecondaryWindow: false, isInSecondaryWindow: false,
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
@@ -210,8 +210,6 @@ struct TimelineInteractionHandlerTests {
let userSession = UserSessionMock(.init()) let userSession = UserSessionMock(.init())
userSession.voiceMessageMediaManager = voiceMessageMediaManager userSession.voiceMessageMediaManager = voiceMessageMediaManager
let appSettings = AppSettings.volatile()
return TimelineInteractionHandler(roomProxy: JoinedRoomProxyMock(.init()), return TimelineInteractionHandler(roomProxy: JoinedRoomProxyMock(.init()),
timelineController: TimelineControllerMock(.init(timelineItems: timelineItems)), timelineController: TimelineControllerMock(.init(timelineItems: timelineItems)),
userSession: userSession, userSession: userSession,
@@ -219,9 +217,8 @@ struct TimelineInteractionHandlerTests {
voiceMessageRecorder: voiceMessageRecorder, voiceMessageRecorder: voiceMessageRecorder,
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
appSettings: appSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(appSettings: appSettings), emojiProvider: EmojiProvider(userSettings: .volatile()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
} }
@@ -123,7 +123,7 @@ struct TimelineItemMenuActionProviderTests {
isViewSourceEnabled: true, isViewSourceEnabled: true,
areThreadsEnabled: true, areThreadsEnabled: true,
timelineKind: timelineKind, timelineKind: timelineKind,
emojiProvider: EmojiProvider(appSettings: .volatile())) emojiProvider: EmojiProvider(userSettings: .volatile()))
.makeActions() .makeActions()
} }
} }
+17 -39
View File
@@ -294,17 +294,14 @@ final class TimelineViewModelTests {
let timelineController = TimelineControllerMock(.init(roomProxy: roomProxy, timelineItems: items)) let timelineController = TimelineControllerMock(.init(roomProxy: roomProxy, timelineItems: items))
let appSettings = AppSettings.volatile()
let viewModel = TimelineViewModel(roomProxy: roomProxy, let viewModel = TimelineViewModel(roomProxy: roomProxy,
timelineController: timelineController, timelineController: timelineController,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init()),
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
appSettings: appSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(appSettings: appSettings), emojiProvider: EmojiProvider(userSettings: .volatile()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
return (viewModel, roomProxy, timelineProxy, timelineController) return (viewModel, roomProxy, timelineProxy, timelineController)
@@ -320,8 +317,6 @@ final class TimelineViewModelTests {
addReadReceipts: receipts) addReadReceipts: receipts)
let id = message.id let id = message.id
let appSettings = AppSettings.volatile()
// When showing them in a timeline. // When showing them in a timeline.
let timelineController = TimelineControllerMock(.init(timelineItems: [message])) let timelineController = TimelineControllerMock(.init(timelineItems: [message]))
let viewModel = TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "", members: [RoomMemberProxyMock.mockAlice, RoomMemberProxyMock.mockCharlie])), let viewModel = TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "", members: [RoomMemberProxyMock.mockAlice, RoomMemberProxyMock.mockCharlie])),
@@ -330,9 +325,8 @@ final class TimelineViewModelTests {
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
appSettings: appSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(appSettings: appSettings), emojiProvider: EmojiProvider(userSettings: .volatile()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
@@ -346,8 +340,6 @@ final class TimelineViewModelTests {
@Test @Test
func showManageUserAsAdmin() async throws { func showManageUserAsAdmin() async throws {
let appSettings = AppSettings.volatile()
let viewModel = TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "", let viewModel = TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "",
members: [RoomMemberProxyMock.mockAdmin, members: [RoomMemberProxyMock.mockAdmin,
RoomMemberProxyMock.mockAlice], RoomMemberProxyMock.mockAlice],
@@ -357,9 +349,8 @@ final class TimelineViewModelTests {
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
appSettings: appSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(appSettings: appSettings), emojiProvider: EmojiProvider(userSettings: .volatile()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
@@ -385,8 +376,6 @@ final class TimelineViewModelTests {
@Test @Test
func showDetailsForAnAdmin() async throws { func showDetailsForAnAdmin() async throws {
let appSettings = AppSettings.volatile()
let viewModel = TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "", let viewModel = TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "",
members: [RoomMemberProxyMock.mockAdmin, members: [RoomMemberProxyMock.mockAdmin,
RoomMemberProxyMock.mockAlice], RoomMemberProxyMock.mockAlice],
@@ -396,9 +385,8 @@ final class TimelineViewModelTests {
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
appSettings: appSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(appSettings: appSettings), emojiProvider: EmojiProvider(userSettings: .volatile()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
@@ -424,8 +412,6 @@ final class TimelineViewModelTests {
@Test @Test
func showDetailsForABannedUser() async throws { func showDetailsForABannedUser() async throws {
let appSettings = AppSettings.volatile()
let viewModel = TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "", let viewModel = TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "",
members: [RoomMemberProxyMock.mockAdmin, members: [RoomMemberProxyMock.mockAdmin,
RoomMemberProxyMock.mockBanned[0]], RoomMemberProxyMock.mockBanned[0]],
@@ -435,9 +421,8 @@ final class TimelineViewModelTests {
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
appSettings: appSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(appSettings: appSettings), emojiProvider: EmojiProvider(userSettings: .volatile()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
@@ -466,8 +451,6 @@ final class TimelineViewModelTests {
@Test @Test
func pinnedEvents() async throws { func pinnedEvents() async throws {
let appSettings = AppSettings.volatile()
var configuration = JoinedRoomProxyMockConfiguration(name: "", var configuration = JoinedRoomProxyMockConfiguration(name: "",
pinnedEventIDs: .init(["test1"])) pinnedEventIDs: .init(["test1"]))
let roomProxyMock = JoinedRoomProxyMock(configuration) let roomProxyMock = JoinedRoomProxyMock(configuration)
@@ -480,9 +463,8 @@ final class TimelineViewModelTests {
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
appSettings: appSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(appSettings: appSettings), emojiProvider: EmojiProvider(userSettings: .volatile()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
#expect(configuration.pinnedEventIDs == viewModel.context.viewState.pinnedEventIDs) #expect(configuration.pinnedEventIDs == viewModel.context.viewState.pinnedEventIDs)
@@ -497,8 +479,6 @@ final class TimelineViewModelTests {
@Test @Test
func canUserPinEvents() async throws { func canUserPinEvents() async throws {
let appSettings = AppSettings.volatile()
let configuration = JoinedRoomProxyMockConfiguration(name: "", let configuration = JoinedRoomProxyMockConfiguration(name: "",
powerLevelsConfiguration: .init(canUserPin: true)) powerLevelsConfiguration: .init(canUserPin: true))
let roomProxyMock = JoinedRoomProxyMock(configuration) let roomProxyMock = JoinedRoomProxyMock(configuration)
@@ -511,9 +491,8 @@ final class TimelineViewModelTests {
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
appSettings: appSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(appSettings: appSettings), emojiProvider: EmojiProvider(userSettings: .volatile()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
@@ -915,15 +894,15 @@ final class TimelineViewModelTests {
@Test @Test
func disablingTheFlagClearsTheSelection() async throws { func disablingTheFlagClearsTheSelection() async throws {
let items = [TextRoomTimelineItem(eventID: "$1")] let items = [TextRoomTimelineItem(eventID: "$1")]
let appSettings = AppSettings.volatile() let userSettings = UserSettings.volatile()
appSettings.messageMultiSelectEnabled = true userSettings.messageMultiSelectEnabled = true
let viewModel = makeViewModel(timelineController: TimelineControllerMock(.init(timelineItems: items)), appSettings: appSettings) let viewModel = makeViewModel(timelineController: TimelineControllerMock(.init(timelineItems: items)), userSettings: userSettings)
startSelection(items[0].id, in: viewModel) startSelection(items[0].id, in: viewModel)
#expect(viewModel.state.messageSelection.isActive) #expect(viewModel.state.messageSelection.isActive)
let deferred = deferFulfillment(viewModel.context.$viewState) { !$0.messageSelection.isEnabled && !$0.messageSelection.isActive } let deferred = deferFulfillment(viewModel.context.$viewState) { !$0.messageSelection.isEnabled && !$0.messageSelection.isActive }
appSettings.messageMultiSelectEnabled = false userSettings.messageMultiSelectEnabled = false
try await deferred.fulfill() try await deferred.fulfill()
} }
@@ -933,17 +912,16 @@ final class TimelineViewModelTests {
focussedEventID: String? = nil, focussedEventID: String? = nil,
timelineController: TimelineControllerProtocol, timelineController: TimelineControllerProtocol,
userIndicatorController: UserIndicatorControllerProtocol = UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerProtocol = UserIndicatorControllerMock(),
appSettings: AppSettings = .volatile()) -> TimelineViewModel { userSettings: UserSettings = .volatile()) -> TimelineViewModel {
TimelineViewModel(roomProxy: roomProxy ?? JoinedRoomProxyMock(.init(name: "")), TimelineViewModel(roomProxy: roomProxy ?? JoinedRoomProxyMock(.init(name: "")),
focussedEventID: focussedEventID, focussedEventID: focussedEventID,
timelineController: timelineController, timelineController: timelineController,
userSession: UserSessionMock(.init()), userSession: UserSessionMock(.init(userSettings: userSettings)),
mediaPlayerProvider: MediaPlayerProviderMock(), mediaPlayerProvider: MediaPlayerProviderMock(),
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appMediator: AppMediatorMock(.init()), appMediator: AppMediatorMock(.init()),
appSettings: appSettings,
analyticsService: AnalyticsServiceMock(.init()), analyticsService: AnalyticsServiceMock(.init()),
emojiProvider: EmojiProvider(appSettings: appSettings), emojiProvider: EmojiProvider(userSettings: .volatile()),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init())) timelineControllerFactory: TimelineControllerFactoryMock(.init()))
} }
@@ -961,11 +939,11 @@ final class TimelineViewModelTests {
private func makeSelectionViewModel(timelineController: TimelineControllerProtocol, private func makeSelectionViewModel(timelineController: TimelineControllerProtocol,
userIndicatorController: UserIndicatorControllerProtocol = UserIndicatorControllerMock()) -> TimelineViewModel { userIndicatorController: UserIndicatorControllerProtocol = UserIndicatorControllerMock()) -> TimelineViewModel {
let appSettings = AppSettings.volatile() let userSettings = UserSettings.volatile()
appSettings.messageMultiSelectEnabled = true userSettings.messageMultiSelectEnabled = true
return makeViewModel(timelineController: timelineController, return makeViewModel(timelineController: timelineController,
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,
appSettings: appSettings) userSettings: userSettings)
} }
} }
@@ -20,7 +20,7 @@ struct UserDetailsEditScreenViewModelTests {
init() { init() {
viewModel = .init(userSession: UserSessionMock(.init()), viewModel = .init(userSession: UserSessionMock(.init()),
mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: .volatile()), mediaUploadingPreprocessor: MediaUploadingPreprocessor(userSettings: .volatile()),
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
} }
@@ -48,16 +48,16 @@ struct UserSessionFlowCoordinatorTests {
appMediator.networkMonitor = networkMonitor appMediator.networkMonitor = networkMonitor
userIndicatorController = UserIndicatorControllerMock() userIndicatorController = UserIndicatorControllerMock()
let appSettings = AppSettings.volatile() let userSettings = UserSettings.volatile()
let flowParameters = CommonFlowParameters(userSession: UserSessionMock(.init(clientProxy: clientProxy)), let flowParameters = CommonFlowParameters(userSession: UserSessionMock(.init(clientProxy: clientProxy)),
bugReportService: BugReportServiceMock(.init()), bugReportService: BugReportServiceMock(.init()),
elementCallService: ElementCallServiceMock(.init()), elementCallService: ElementCallServiceMock(.init()),
timelineControllerFactory: TimelineControllerFactoryMock(.init()), timelineControllerFactory: TimelineControllerFactoryMock(.init()),
emojiProvider: EmojiProvider(appSettings: appSettings), emojiProvider: EmojiProvider(userSettings: userSettings),
linkMetadataProvider: LinkMetadataProvider(), linkMetadataProvider: LinkMetadataProvider(),
appMediator: appMediator, appMediator: appMediator,
appSettings: appSettings, userSettings: userSettings,
appHooks: AppHooks(), appHooks: AppHooks(),
analytics: AnalyticsServiceMock(.init()), analytics: AnalyticsServiceMock(.init()),
userIndicatorController: userIndicatorController, userIndicatorController: userIndicatorController,