mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 12:07:55 +00:00
Remove the dynamic member lookup from UserSettings in favour of nested access. (#6294)
* Remove the dynamic member lookup from UserSettings in favour of nested access. * Remove forwarding methods from UserSettings. * Update the Enterprise submodule.
This commit is contained in:
@@ -18,7 +18,7 @@ final class BugReportServiceTests {
|
||||
|
||||
init() throws {
|
||||
userSettings = UserSettings.mock()
|
||||
userSettings.bugReportRageshakeURL.reset()
|
||||
userSettings.app.bugReportRageshakeURL.reset()
|
||||
|
||||
let bugReportServiceMock = BugReportServiceMock()
|
||||
bugReportServiceMock.lastCrashEventIDSubject = .init(nil)
|
||||
@@ -27,7 +27,7 @@ final class BugReportServiceTests {
|
||||
}
|
||||
|
||||
deinit {
|
||||
userSettings.bugReportRageshakeURL.reset()
|
||||
userSettings.app.bugReportRageshakeURL.reset()
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -104,22 +104,22 @@ final class BugReportServiceTests {
|
||||
@Test
|
||||
@MainActor
|
||||
func configurations() async throws {
|
||||
guard case let .url(initialURL) = userSettings.bugReportRageshakeURL.publisher.value else {
|
||||
guard case let .url(initialURL) = userSettings.app.bugReportRageshakeURL.publisher.value else {
|
||||
Issue.record("Unexpected initial configuration.")
|
||||
return
|
||||
}
|
||||
|
||||
let service = BugReportService(rageshakeURLPublisher: userSettings.bugReportRageshakeURL.publisher,
|
||||
let service = BugReportService(rageshakeURLPublisher: userSettings.app.bugReportRageshakeURL.publisher,
|
||||
applicationID: "mock_app_id",
|
||||
sdkGitSHA: "1234",
|
||||
session: .mock,
|
||||
appHooks: AppHooks())
|
||||
#expect(service.isEnabled)
|
||||
|
||||
userSettings.bugReportRageshakeURL.applyRemoteValue(.disabled)
|
||||
userSettings.app.bugReportRageshakeURL.applyRemoteValue(.disabled)
|
||||
#expect(!service.isEnabled)
|
||||
|
||||
userSettings.bugReportRageshakeURL.applyRemoteValue(.url("https://bugs.server.net/submit"))
|
||||
userSettings.app.bugReportRageshakeURL.applyRemoteValue(.url("https://bugs.server.net/submit"))
|
||||
#expect(service.isEnabled)
|
||||
|
||||
let bugReport = BugReport(userID: "@mock:client.com",
|
||||
@@ -136,7 +136,7 @@ final class BugReportServiceTests {
|
||||
|
||||
#expect(customConfigurationResponse.reportURL == "https://bugs.server.net/123")
|
||||
|
||||
userSettings.bugReportRageshakeURL.reset()
|
||||
userSettings.app.bugReportRageshakeURL.reset()
|
||||
#expect(service.isEnabled)
|
||||
|
||||
let defaultConfigurationResponse = try await service.submitBugReport(bugReport, progressListener: progressSubject).get()
|
||||
|
||||
@@ -85,7 +85,7 @@ final class CreateRoomScreenViewModelTests {
|
||||
spaceServiceConfiguration: .init(spaceRoomLists: ["1": .init()])))
|
||||
clientProxy.roomForIdentifierClosure = { roomID in .joined(JoinedRoomProxyMock(.init(id: roomID))) }
|
||||
userSession = UserSessionMock(.init(clientProxy: clientProxy))
|
||||
userSettings.knockingEnabled = true
|
||||
userSettings.app.knockingEnabled = true
|
||||
let viewModel = CreateRoomScreenViewModel(isSpace: true,
|
||||
spaceSelectionMode: .none,
|
||||
shouldShowCancelButton: false,
|
||||
@@ -336,7 +336,7 @@ final class CreateRoomScreenViewModelTests {
|
||||
clientProxy.spaceService = spaceService
|
||||
clientProxy.roomForIdentifierClosure = { roomID in .joined(JoinedRoomProxyMock(.init(id: roomID))) }
|
||||
userSession = UserSessionMock(.init(clientProxy: clientProxy))
|
||||
userSettings.knockingEnabled = true
|
||||
userSettings.app.knockingEnabled = true
|
||||
let viewModel = CreateRoomScreenViewModel(isSpace: isSpace,
|
||||
spaceSelectionMode: spacesSelectionMode,
|
||||
shouldShowCancelButton: false,
|
||||
|
||||
@@ -275,7 +275,7 @@ final class HomeScreenViewModelTests {
|
||||
room.roomID == invites[0].roomID && room.badges.isDotShown == false
|
||||
}
|
||||
}
|
||||
userSettings.seenInvites = Set(invites.compactMap(\.roomID))
|
||||
userSettings.app.seenInvites = Set(invites.compactMap(\.roomID))
|
||||
try await deferred.fulfill()
|
||||
invites = context.viewState.rooms.invites
|
||||
|
||||
@@ -289,14 +289,14 @@ final class HomeScreenViewModelTests {
|
||||
setupViewModel(invites: .rooms)
|
||||
|
||||
let invitedRoomIDs = context.viewState.rooms.invites.compactMap(\.roomID)
|
||||
userSettings.seenInvites = Set(invitedRoomIDs)
|
||||
userSettings.app.seenInvites = Set(invitedRoomIDs)
|
||||
#expect(invitedRoomIDs.count == 2)
|
||||
|
||||
let deferred = deferFulfillment(viewModel.actions) { $0 == .presentRoom(roomIdentifier: invitedRoomIDs[0]) }
|
||||
context.send(viewAction: .acceptInvite(roomIdentifier: invitedRoomIDs[0]))
|
||||
try await deferred.fulfill()
|
||||
|
||||
#expect(userSettings.seenInvites == [invitedRoomIDs[1]])
|
||||
#expect(userSettings.app.seenInvites == [invitedRoomIDs[1]])
|
||||
#expect(!notificationManager.removeDeliveredMessageNotificationsForCalled, "The notification will be dismissed when opening the room.")
|
||||
}
|
||||
|
||||
@@ -305,7 +305,7 @@ final class HomeScreenViewModelTests {
|
||||
setupViewModel(invites: .spaces)
|
||||
|
||||
let invitedRoomIDs = context.viewState.rooms.invites.compactMap(\.roomID)
|
||||
userSettings.seenInvites = Set(invitedRoomIDs)
|
||||
userSettings.app.seenInvites = Set(invitedRoomIDs)
|
||||
#expect(invitedRoomIDs.count == 2)
|
||||
|
||||
let deferred = deferFulfillment(viewModel.actions) {
|
||||
@@ -314,7 +314,7 @@ final class HomeScreenViewModelTests {
|
||||
context.send(viewAction: .acceptInvite(roomIdentifier: invitedRoomIDs[0]))
|
||||
try await deferred.fulfill()
|
||||
|
||||
#expect(userSettings.seenInvites == [invitedRoomIDs[1]])
|
||||
#expect(userSettings.app.seenInvites == [invitedRoomIDs[1]])
|
||||
#expect(!notificationManager.removeDeliveredMessageNotificationsForCalled, "The notification will be dismissed when opening the room.")
|
||||
}
|
||||
|
||||
@@ -322,7 +322,7 @@ final class HomeScreenViewModelTests {
|
||||
func declineInvite() async throws {
|
||||
setupViewModel(invites: .rooms)
|
||||
let invitedRoomIDs = context.viewState.rooms.invites.compactMap(\.roomID)
|
||||
userSettings.seenInvites = Set(invitedRoomIDs)
|
||||
userSettings.app.seenInvites = Set(invitedRoomIDs)
|
||||
#expect(invitedRoomIDs.count == 2)
|
||||
|
||||
let deferred = deferFulfillment(context.$viewState) { $0.bindings.alertInfo != nil }
|
||||
@@ -345,7 +345,7 @@ final class HomeScreenViewModelTests {
|
||||
try await Task.sleep(for: .milliseconds(100))
|
||||
#expect(rejectCalled)
|
||||
|
||||
#expect(userSettings.seenInvites == [invitedRoomIDs[1]])
|
||||
#expect(userSettings.app.seenInvites == [invitedRoomIDs[1]])
|
||||
#expect(notificationManager.removeDeliveredMessageNotificationsForCalled)
|
||||
#expect(notificationManager.removeDeliveredMessageNotificationsForReceivedInvocations == [invitedRoomIDs[0]])
|
||||
}
|
||||
@@ -354,7 +354,7 @@ final class HomeScreenViewModelTests {
|
||||
func declineAndBlockInvite() async throws {
|
||||
setupViewModel(invites: .rooms)
|
||||
let invitedRoomIDs = context.viewState.rooms.invites.compactMap(\.roomID)
|
||||
userSettings.seenInvites = Set(invitedRoomIDs)
|
||||
userSettings.app.seenInvites = Set(invitedRoomIDs)
|
||||
#expect(invitedRoomIDs.count == 2)
|
||||
|
||||
let deferred = deferFulfillment(context.$viewState) { $0.bindings.alertInfo != nil }
|
||||
@@ -368,7 +368,7 @@ final class HomeScreenViewModelTests {
|
||||
|
||||
@Test
|
||||
func newSoundBanner() {
|
||||
userSettings.hasSeenNewSoundBanner = false
|
||||
userSettings.app.hasSeenNewSoundBanner = false
|
||||
|
||||
setupViewModel()
|
||||
#expect(context.viewState.shouldShowBanner)
|
||||
@@ -377,26 +377,26 @@ final class HomeScreenViewModelTests {
|
||||
context.send(viewAction: .dismissNewSoundBanner)
|
||||
#expect(!context.viewState.shouldShowBanner)
|
||||
#expect(!context.viewState.shouldShowNewSoundBanner)
|
||||
#expect(userSettings.hasSeenNewSoundBanner)
|
||||
#expect(userSettings.app.hasSeenNewSoundBanner)
|
||||
}
|
||||
|
||||
@Test
|
||||
func multiAccountAnnouncement() async throws {
|
||||
userSettings.multiAccountEnabled = true
|
||||
userSettings.app.multiAccountEnabled = true
|
||||
setupViewModel()
|
||||
|
||||
// Arming it after the view model exists (Developer options) doesn't present it on its own.
|
||||
userSettings.hasSeenMultiAccountAnnouncement = false
|
||||
userSettings.app.hasSeenMultiAccountAnnouncement = false
|
||||
let deferredFailure = deferFailure(context.$viewState, timeout: .seconds(1)) { $0.bindings.isPresentingMultiAccountAnnouncement }
|
||||
try await deferredFailure.fulfill()
|
||||
|
||||
let deferred = deferFulfillment(context.$viewState) { $0.bindings.isPresentingMultiAccountAnnouncement }
|
||||
context.send(viewAction: .screenAppeared)
|
||||
try await deferred.fulfill()
|
||||
#expect(!userSettings.hasSeenMultiAccountAnnouncement)
|
||||
#expect(!userSettings.app.hasSeenMultiAccountAnnouncement)
|
||||
|
||||
context.send(viewAction: .multiAccountAnnouncementAppeared)
|
||||
#expect(userSettings.hasSeenMultiAccountAnnouncement)
|
||||
#expect(userSettings.app.hasSeenMultiAccountAnnouncement)
|
||||
#expect(context.viewState.bindings.isPresentingMultiAccountAnnouncement)
|
||||
|
||||
// A swipe down dismisses it without any of the announcement's actions.
|
||||
@@ -408,8 +408,8 @@ final class HomeScreenViewModelTests {
|
||||
|
||||
@Test(arguments: [HomeScreenViewAction.dismissMultiAccountAnnouncement, .addAccount])
|
||||
func multiAccountAnnouncementActionsDismissIt(_ action: HomeScreenViewAction) async throws {
|
||||
userSettings.multiAccountEnabled = true
|
||||
userSettings.hasSeenMultiAccountAnnouncement = false
|
||||
userSettings.app.multiAccountEnabled = true
|
||||
userSettings.app.hasSeenMultiAccountAnnouncement = false
|
||||
setupViewModel()
|
||||
|
||||
let deferred = deferFulfillment(context.$viewState) { $0.bindings.isPresentingMultiAccountAnnouncement }
|
||||
@@ -422,8 +422,8 @@ final class HomeScreenViewModelTests {
|
||||
|
||||
@Test(arguments: MultiAccountAnnouncementHiddenCase.allCases)
|
||||
func multiAccountAnnouncementHidden(_ hiddenCase: MultiAccountAnnouncementHiddenCase) async throws {
|
||||
userSettings.multiAccountEnabled = hiddenCase != .flagOff
|
||||
userSettings.hasSeenMultiAccountAnnouncement = hiddenCase == .alreadySeen
|
||||
userSettings.app.multiAccountEnabled = hiddenCase != .flagOff
|
||||
userSettings.app.hasSeenMultiAccountAnnouncement = hiddenCase == .alreadySeen
|
||||
let verificationState: SessionVerificationState = switch hiddenCase {
|
||||
case .unverified: .unverified
|
||||
case .unknownVerificationState: .unknown
|
||||
@@ -435,13 +435,13 @@ final class HomeScreenViewModelTests {
|
||||
let deferred = deferFailure(context.$viewState, timeout: .seconds(1)) { $0.bindings.isPresentingMultiAccountAnnouncement }
|
||||
context.send(viewAction: .screenAppeared)
|
||||
try await deferred.fulfill()
|
||||
#expect(userSettings.hasSeenMultiAccountAnnouncement == (hiddenCase == .alreadySeen))
|
||||
#expect(userSettings.app.hasSeenMultiAccountAnnouncement == (hiddenCase == .alreadySeen))
|
||||
}
|
||||
|
||||
@Test
|
||||
func multiAccountAnnouncementPresentsOnTheNextAppearanceOnceVerified() async throws {
|
||||
userSettings.multiAccountEnabled = true
|
||||
userSettings.hasSeenMultiAccountAnnouncement = false
|
||||
userSettings.app.multiAccountEnabled = true
|
||||
userSettings.app.hasSeenMultiAccountAnnouncement = false
|
||||
let securityStateSubject = CurrentValueSubject<SessionSecurityState, Never>(.init(verificationState: .unverified, recoveryState: .enabled))
|
||||
setupViewModel(securityStatePublisher: securityStateSubject.asCurrentValuePublisher())
|
||||
|
||||
|
||||
@@ -45,12 +45,12 @@ final class JoinRoomScreenViewModelTests {
|
||||
|
||||
@Test
|
||||
func interaction() async throws {
|
||||
#expect(userSettings.seenInvites.isEmpty, "There shouldn't be any seen invites before running the tests.")
|
||||
#expect(userSettings.app.seenInvites.isEmpty, "There shouldn't be any seen invites before running the tests.")
|
||||
|
||||
setupViewModel()
|
||||
try await deferFulfillment(viewModel.context.$viewState) { $0.mode == .joinable }.fulfill()
|
||||
|
||||
#expect(userSettings.seenInvites.isEmpty, "Only an invited room should register the room ID as a seen invite.")
|
||||
#expect(userSettings.app.seenInvites.isEmpty, "Only an invited room should register the room ID as a seen invite.")
|
||||
|
||||
let deferred = deferFulfillment(viewModel.actionsPublisher) { $0 == .joined(.roomID("1")) }
|
||||
context.send(viewAction: .join)
|
||||
@@ -59,28 +59,28 @@ final class JoinRoomScreenViewModelTests {
|
||||
|
||||
@Test
|
||||
func acceptInviteInteraction() async throws {
|
||||
#expect(userSettings.seenInvites.isEmpty, "There shouldn't be any seen invites before running the tests.")
|
||||
#expect(userSettings.app.seenInvites.isEmpty, "There shouldn't be any seen invites before running the tests.")
|
||||
|
||||
setupViewModel(mode: .invited)
|
||||
try await deferFulfillment(viewModel.context.$viewState) { $0.mode == .invited(isDM: false) }.fulfill()
|
||||
|
||||
#expect(userSettings.seenInvites == ["1"], "The invited room's ID should be registered as a seen invite.")
|
||||
#expect(userSettings.app.seenInvites == ["1"], "The invited room's ID should be registered as a seen invite.")
|
||||
|
||||
let deferred = deferFulfillment(viewModel.actionsPublisher) { $0 == .joined(.roomID("1")) }
|
||||
context.send(viewAction: .acceptInvite)
|
||||
try await deferred.fulfill()
|
||||
|
||||
#expect(userSettings.seenInvites.isEmpty, "The after accepting an invite the invite should be forgotten in case the user leaves.")
|
||||
#expect(userSettings.app.seenInvites.isEmpty, "The after accepting an invite the invite should be forgotten in case the user leaves.")
|
||||
}
|
||||
|
||||
@Test
|
||||
func declineInviteInteraction() async throws {
|
||||
#expect(userSettings.seenInvites.isEmpty, "There shouldn't be any seen invites before running the tests.")
|
||||
#expect(userSettings.app.seenInvites.isEmpty, "There shouldn't be any seen invites before running the tests.")
|
||||
|
||||
setupViewModel(mode: .invited)
|
||||
|
||||
try await deferFulfillment(viewModel.context.$viewState) { $0.mode == .invited(isDM: false) }.fulfill()
|
||||
#expect(userSettings.seenInvites == ["1"], "The invited room's ID should be registered as a seen invite.")
|
||||
#expect(userSettings.app.seenInvites == ["1"], "The invited room's ID should be registered as a seen invite.")
|
||||
|
||||
context.send(viewAction: .declineInvite)
|
||||
|
||||
@@ -89,17 +89,17 @@ final class JoinRoomScreenViewModelTests {
|
||||
context.alertInfo?.secondaryButton?.action?()
|
||||
try await deferred.fulfill()
|
||||
|
||||
#expect(userSettings.seenInvites.isEmpty, "The after declining an invite the invite should be forgotten in case another invite is received.")
|
||||
#expect(userSettings.app.seenInvites.isEmpty, "The after declining an invite the invite should be forgotten in case another invite is received.")
|
||||
}
|
||||
|
||||
@Test
|
||||
func knockedState() async throws {
|
||||
#expect(userSettings.seenInvites.isEmpty, "There shouldn't be any seen invites before running the tests.")
|
||||
#expect(userSettings.app.seenInvites.isEmpty, "There shouldn't be any seen invites before running the tests.")
|
||||
setupViewModel(mode: .knocked)
|
||||
|
||||
try await deferFulfillment(viewModel.context.$viewState) { $0.mode == .knocked }.fulfill()
|
||||
|
||||
#expect(userSettings.seenInvites.isEmpty, "Only an invited room should register the room ID as a seen invite.")
|
||||
#expect(userSettings.app.seenInvites.isEmpty, "Only an invited room should register the room ID as a seen invite.")
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -41,11 +41,11 @@ final class LiveLocationManagerTests {
|
||||
|
||||
try result.get()
|
||||
#expect(callOrder == ["stop", "start"])
|
||||
#expect(userSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] == nil)
|
||||
#expect(userSettings.app.liveLocationSharingSessionsByRoomID["!room:matrix.org"] == nil)
|
||||
|
||||
try await simulateBeaconEcho(roomID: "!room:matrix.org", eventID: "$event:matrix.org")
|
||||
|
||||
#expect(userSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] != nil)
|
||||
#expect(userSettings.app.liveLocationSharingSessionsByRoomID["!room:matrix.org"] != nil)
|
||||
#expect(locationManagerMock.startUpdatingLocationCalled)
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ final class LiveLocationManagerTests {
|
||||
setUp()
|
||||
let roomProxy = makeRoomProxy(roomID: "!room:matrix.org")
|
||||
clientProxy.roomForIdentifierClosure = { _ in .joined(roomProxy) }
|
||||
userSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] = LiveLocationSession(eventID: "$old_event:matrix.org", expirationDate: Date().addingTimeInterval(300))
|
||||
userSettings.app.liveLocationSharingSessionsByRoomID["!room:matrix.org"] = LiveLocationSession(eventID: "$old_event:matrix.org", expirationDate: Date().addingTimeInterval(300))
|
||||
|
||||
var callOrder: [String] = []
|
||||
roomProxy.stopLiveLocationShareClosure = {
|
||||
@@ -73,7 +73,7 @@ final class LiveLocationManagerTests {
|
||||
|
||||
try await simulateBeaconEcho(roomID: "!room:matrix.org", eventID: "$event:matrix.org")
|
||||
|
||||
#expect(userSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] != nil)
|
||||
#expect(userSettings.app.liveLocationSharingSessionsByRoomID["!room:matrix.org"] != nil)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -82,12 +82,12 @@ final class LiveLocationManagerTests {
|
||||
let roomProxy = makeRoomProxy(roomID: "!room1:matrix.org")
|
||||
clientProxy.roomForIdentifierClosure = { _ in .joined(roomProxy) }
|
||||
|
||||
userSettings.liveLocationSharingSessionsByRoomID["!room2:matrix.org"] = LiveLocationSession(eventID: "$event:matrix.org", expirationDate: Date().addingTimeInterval(300))
|
||||
userSettings.app.liveLocationSharingSessionsByRoomID["!room2:matrix.org"] = LiveLocationSession(eventID: "$event:matrix.org", expirationDate: Date().addingTimeInterval(300))
|
||||
|
||||
_ = await manager.startLiveLocation(roomID: "!room1:matrix.org", duration: .seconds(300))
|
||||
|
||||
#expect(roomProxy.stopLiveLocationShareCalled)
|
||||
#expect(userSettings.liveLocationSharingSessionsByRoomID["!room2:matrix.org"] != nil)
|
||||
#expect(userSettings.app.liveLocationSharingSessionsByRoomID["!room2:matrix.org"] != nil)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -98,7 +98,7 @@ final class LiveLocationManagerTests {
|
||||
let result = await manager.startLiveLocation(roomID: "!room:matrix.org", duration: .seconds(300))
|
||||
|
||||
#expect(throws: LiveLocationManagerError.roomNotJoined) { try result.get() }
|
||||
#expect(userSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] == nil)
|
||||
#expect(userSettings.app.liveLocationSharingSessionsByRoomID["!room:matrix.org"] == nil)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -111,7 +111,7 @@ final class LiveLocationManagerTests {
|
||||
let result = await manager.startLiveLocation(roomID: "!room:matrix.org", duration: .seconds(300))
|
||||
|
||||
#expect(throws: LiveLocationManagerError.startFailed) { try result.get() }
|
||||
#expect(userSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] == nil)
|
||||
#expect(userSettings.app.liveLocationSharingSessionsByRoomID["!room:matrix.org"] == nil)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -127,7 +127,7 @@ final class LiveLocationManagerTests {
|
||||
|
||||
try await simulateBeaconEcho(roomID: "!room:matrix.org", eventID: "$event:matrix.org")
|
||||
|
||||
let storedSession = try #require(userSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"])
|
||||
let storedSession = try #require(userSettings.app.liveLocationSharingSessionsByRoomID["!room:matrix.org"])
|
||||
let expectedMinTimeout = beforeStart.addingTimeInterval(TimeInterval(duration.seconds))
|
||||
let expectedMaxTimeout = afterStart.addingTimeInterval(TimeInterval(duration.seconds))
|
||||
|
||||
@@ -142,12 +142,12 @@ final class LiveLocationManagerTests {
|
||||
setUp()
|
||||
let roomProxy = makeRoomProxy(roomID: "!room:matrix.org")
|
||||
clientProxy.roomForIdentifierClosure = { _ in .joined(roomProxy) }
|
||||
userSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] = LiveLocationSession(eventID: "$event:matrix.org", expirationDate: Date().addingTimeInterval(300))
|
||||
userSettings.app.liveLocationSharingSessionsByRoomID["!room:matrix.org"] = LiveLocationSession(eventID: "$event:matrix.org", expirationDate: Date().addingTimeInterval(300))
|
||||
|
||||
await manager.stopLiveLocation(roomID: "!room:matrix.org")
|
||||
|
||||
#expect(roomProxy.stopLiveLocationShareCalled)
|
||||
#expect(userSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] == nil)
|
||||
#expect(userSettings.app.liveLocationSharingSessionsByRoomID["!room:matrix.org"] == nil)
|
||||
// Setting the timeout date above starts tracking; removing it stops tracking.
|
||||
#expect(locationManagerMock.startUpdatingLocationCalled)
|
||||
#expect(locationManagerMock.stopUpdatingLocationCalled)
|
||||
@@ -169,13 +169,13 @@ final class LiveLocationManagerTests {
|
||||
setUp()
|
||||
let roomProxy = makeRoomProxy(roomID: "!room1:matrix.org")
|
||||
clientProxy.roomForIdentifierClosure = { _ in .joined(roomProxy) }
|
||||
userSettings.liveLocationSharingSessionsByRoomID["!room1: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))
|
||||
userSettings.app.liveLocationSharingSessionsByRoomID["!room1:matrix.org"] = LiveLocationSession(eventID: "$event:matrix.org", expirationDate: Date().addingTimeInterval(300))
|
||||
userSettings.app.liveLocationSharingSessionsByRoomID["!room2:matrix.org"] = LiveLocationSession(eventID: "$event:matrix.org", expirationDate: Date().addingTimeInterval(300))
|
||||
|
||||
await manager.stopLiveLocation(roomID: "!room1:matrix.org")
|
||||
|
||||
#expect(userSettings.liveLocationSharingSessionsByRoomID["!room1:matrix.org"] == nil)
|
||||
#expect(userSettings.liveLocationSharingSessionsByRoomID["!room2:matrix.org"] != nil)
|
||||
#expect(userSettings.app.liveLocationSharingSessionsByRoomID["!room1:matrix.org"] == nil)
|
||||
#expect(userSettings.app.liveLocationSharingSessionsByRoomID["!room2:matrix.org"] != nil)
|
||||
}
|
||||
|
||||
// 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 simulateBeaconEcho(roomID: "!room:matrix.org", eventID: "$event:matrix.org")
|
||||
#expect(userSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] != nil)
|
||||
#expect(userSettings.app.liveLocationSharingSessionsByRoomID["!room:matrix.org"] != nil)
|
||||
|
||||
let deferred = deferFulfillment(userSettings.liveLocationSharingSessionsByRoomIDPublisher) { $0["!room:matrix.org"] == nil }
|
||||
let deferred = deferFulfillment(userSettings.app.liveLocationSharingSessionsByRoomIDPublisher) { $0["!room:matrix.org"] == nil }
|
||||
beaconInfoSubject.send(LiveLocationOwnInfoUpdate(roomID: "!room:matrix.org", eventID: "$external_event:matrix.org", isLive: true))
|
||||
try await deferred.fulfill()
|
||||
|
||||
#expect(userSettings.liveLocationSharingSessionsByRoomID["!room:matrix.org"] == nil)
|
||||
#expect(userSettings.app.liveLocationSharingSessionsByRoomID["!room:matrix.org"] == nil)
|
||||
}
|
||||
|
||||
// MARK: - Reduced accuracy
|
||||
@@ -237,7 +237,7 @@ final class LiveLocationManagerTests {
|
||||
}
|
||||
|
||||
private func simulateBeaconEcho(roomID: String, eventID: String) async throws {
|
||||
let deferred = deferFulfillment(userSettings.liveLocationSharingSessionsByRoomIDPublisher) { $0[roomID] != nil }
|
||||
let deferred = deferFulfillment(userSettings.app.liveLocationSharingSessionsByRoomIDPublisher) { $0[roomID] != nil }
|
||||
beaconInfoSubject.send(LiveLocationOwnInfoUpdate(roomID: roomID, eventID: eventID, isLive: true))
|
||||
try await deferred.fulfill()
|
||||
}
|
||||
|
||||
@@ -420,7 +420,7 @@ struct LocationSharingScreenViewModelTests {
|
||||
let userSettings = UserSettings.mock()
|
||||
|
||||
viewModel = LocationSharingScreenViewModel(interactionMode: .viewLive(sender: nil, initialLiveLocationShare: nil),
|
||||
mapURLBuilder: userSettings.mapTilerConfiguration.publisher.value,
|
||||
mapURLBuilder: userSettings.app.mapTilerConfiguration.publisher.value,
|
||||
roomProxy: roomProxyMock,
|
||||
timelineController: TimelineControllerMock(.init(timelineProxy: TimelineProxyMock(.init()))),
|
||||
liveLocationManager: LiveLocationManagerMock(.init()),
|
||||
@@ -546,7 +546,7 @@ struct LocationSharingScreenViewModelTests {
|
||||
#expect(context.showsUserLocationMode == .hide)
|
||||
|
||||
// Another device takes over: this device's session is removed and a new own share arrives.
|
||||
userSettings.liveLocationSharingSessionsByRoomID.removeValue(forKey: Self.roomID)
|
||||
userSettings.app.liveLocationSharingSessionsByRoomID.removeValue(forKey: Self.roomID)
|
||||
let newOwnShare = makeLiveLocationShare(userID: RoomMemberProxyMock.mockMe.userID, latitude: 48.8, longitude: 2.3)
|
||||
|
||||
let deferred = deferFulfillment(context.observe(\.showsUserLocationMode)) { $0 == .show }
|
||||
@@ -633,7 +633,7 @@ struct LocationSharingScreenViewModelTests {
|
||||
userSettings = UserSettings.mock()
|
||||
timelineProxy = TimelineProxyMock(.init())
|
||||
viewModel = LocationSharingScreenViewModel(interactionMode: .picker(shouldShowLiveLocationOption: true),
|
||||
mapURLBuilder: userSettings.mapTilerConfiguration.publisher.value,
|
||||
mapURLBuilder: userSettings.app.mapTilerConfiguration.publisher.value,
|
||||
roomProxy: JoinedRoomProxyMock(.init(members: members)),
|
||||
timelineController: TimelineControllerMock(.init(timelineProxy: timelineProxy)),
|
||||
liveLocationManager: liveLocationManagerMock,
|
||||
@@ -651,7 +651,7 @@ struct LocationSharingScreenViewModelTests {
|
||||
isSharingLiveLocationFromThisDevice: Bool = false) {
|
||||
userSettings = UserSettings.mock()
|
||||
if isSharingLiveLocationFromThisDevice {
|
||||
userSettings.liveLocationSharingSessionsByRoomID[Self.roomID] = .init(eventID: "$event:matrix.org", expirationDate: .distantFuture)
|
||||
userSettings.app.liveLocationSharingSessionsByRoomID[Self.roomID] = .init(eventID: "$event:matrix.org", expirationDate: .distantFuture)
|
||||
}
|
||||
|
||||
let liveLocationServiceMock = RoomLiveLocationServiceMock()
|
||||
@@ -661,7 +661,7 @@ struct LocationSharingScreenViewModelTests {
|
||||
roomProxyMock.makeLiveLocationServiceReturnValue = liveLocationServiceMock
|
||||
|
||||
viewModel = LocationSharingScreenViewModel(interactionMode: .viewLive(sender: sender, initialLiveLocationShare: initialShare),
|
||||
mapURLBuilder: userSettings.mapTilerConfiguration.publisher.value,
|
||||
mapURLBuilder: userSettings.app.mapTilerConfiguration.publisher.value,
|
||||
roomProxy: roomProxyMock,
|
||||
timelineController: TimelineControllerMock(.init(timelineProxy: TimelineProxyMock(.init()))),
|
||||
liveLocationManager: LiveLocationManagerMock(.init()),
|
||||
|
||||
@@ -29,7 +29,7 @@ final class MediaUploadPreviewScreenViewModelTests {
|
||||
|
||||
init() {
|
||||
userSettings = UserSettings.mock()
|
||||
userSettings.optimizeMediaUploads = false
|
||||
userSettings.app.optimizeMediaUploads = false
|
||||
|
||||
userIndicatorController = UserIndicatorControllerMock()
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ final class MediaUploadingPreprocessorTests {
|
||||
|
||||
init() {
|
||||
userSettings = UserSettings.mock()
|
||||
userSettings.optimizeMediaUploads = false
|
||||
userSettings.app.optimizeMediaUploads = false
|
||||
mediaUploadingPreprocessor = MediaUploadingPreprocessor(userSettings: userSettings)
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ final class MediaUploadingPreprocessorTests {
|
||||
func landscapeMovVideoOptimizedProcessing() async throws {
|
||||
let url = try #require(Bundle(for: Self.self).url(forResource: "landscape_test_video.mov", withExtension: nil), "Failed retrieving test asset")
|
||||
|
||||
userSettings.optimizeMediaUploads = true
|
||||
userSettings.app.optimizeMediaUploads = true
|
||||
|
||||
guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
|
||||
case let .video(optimizedVideoURL, _, optimizedVideoInfo) = optimizedResult else {
|
||||
@@ -139,7 +139,7 @@ final class MediaUploadingPreprocessorTests {
|
||||
func portraitMp4VideoOptimizedProcessing() async throws {
|
||||
let url = try #require(Bundle(for: Self.self).url(forResource: "portrait_test_video.mp4", withExtension: nil), "Failed retrieving test asset")
|
||||
|
||||
userSettings.optimizeMediaUploads = true
|
||||
userSettings.app.optimizeMediaUploads = true
|
||||
|
||||
guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
|
||||
case let .video(optimizedVideoURL, _, optimizedVideoInfo) = optimizedResult else {
|
||||
@@ -184,7 +184,7 @@ final class MediaUploadingPreprocessorTests {
|
||||
#expect(imageInfo.thumbnailInfo?.height == 344)
|
||||
|
||||
// Repeat with optimised media setting
|
||||
userSettings.optimizeMediaUploads = true
|
||||
userSettings.app.optimizeMediaUploads = true
|
||||
|
||||
guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
|
||||
case let .image(optimizedImageURL, thumbnailURL, optimizedImageInfo) = optimizedResult else {
|
||||
@@ -228,7 +228,7 @@ final class MediaUploadingPreprocessorTests {
|
||||
#expect(imageInfo.thumbnailInfo?.height == 800)
|
||||
|
||||
// Repeat with optimised media setting
|
||||
userSettings.optimizeMediaUploads = true
|
||||
userSettings.app.optimizeMediaUploads = true
|
||||
|
||||
guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
|
||||
case let .image(optimizedImageURL, thumbnailURL, optimizedImageInfo) = optimizedResult else {
|
||||
@@ -274,7 +274,7 @@ final class MediaUploadingPreprocessorTests {
|
||||
#expect(imageInfo.thumbnailInfo?.height == 240)
|
||||
|
||||
// Repeat with optimised media setting
|
||||
userSettings.optimizeMediaUploads = true
|
||||
userSettings.app.optimizeMediaUploads = true
|
||||
|
||||
guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
|
||||
case let .image(optimizedImageURL, _, optimizedImageInfo) = optimizedResult else {
|
||||
@@ -325,7 +325,7 @@ final class MediaUploadingPreprocessorTests {
|
||||
#expect(imageInfo.thumbnailInfo?.height == 800)
|
||||
|
||||
// Repeat with optimised media setting
|
||||
userSettings.optimizeMediaUploads = true
|
||||
userSettings.app.optimizeMediaUploads = true
|
||||
|
||||
guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
|
||||
case let .image(optimizedImageURL, thumbnailURL, optimizedImageInfo) = optimizedResult else {
|
||||
@@ -377,7 +377,7 @@ final class MediaUploadingPreprocessorTests {
|
||||
#expect(imageInfo.thumbnailInfo?.height == 472)
|
||||
|
||||
// Repeat with optimised media setting
|
||||
userSettings.optimizeMediaUploads = true
|
||||
userSettings.app.optimizeMediaUploads = true
|
||||
|
||||
guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
|
||||
case let .image(optimizedImageURL, _, optimizedImageInfo) = optimizedResult else {
|
||||
@@ -419,7 +419,7 @@ final class MediaUploadingPreprocessorTests {
|
||||
#expect(imageInfo.thumbnailInfo?.height == 800)
|
||||
|
||||
// Repeat with optimised media setting
|
||||
userSettings.optimizeMediaUploads = true
|
||||
userSettings.app.optimizeMediaUploads = true
|
||||
|
||||
guard case let .success(optimizedResult) = await mediaUploadingPreprocessor.processMedia(at: url, maxUploadSize: maxUploadSize),
|
||||
case let .image(optimizedImageURL, thumbnailURL, optimizedImageInfo) = optimizedResult else {
|
||||
@@ -453,7 +453,7 @@ final class MediaUploadingPreprocessorTests {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
if userSettings.optimizeMediaUploads {
|
||||
if userSettings.app.optimizeMediaUploads {
|
||||
// Check that new image has been scaled within the requirements for an optimised image
|
||||
#expect(convertedImage.size.width <= MediaUploadingPreprocessor.Constants.optimizedMaxPixelSize)
|
||||
#expect(convertedImage.size.height <= MediaUploadingPreprocessor.Constants.optimizedMaxPixelSize)
|
||||
|
||||
@@ -42,16 +42,16 @@ struct NotificationSettingsScreenViewModelTests {
|
||||
|
||||
@Test
|
||||
func enableNotifications() {
|
||||
userSettings.enableNotifications = false
|
||||
userSettings.app.enableNotifications = false
|
||||
context.send(viewAction: .changedEnableNotifications)
|
||||
#expect(userSettings.enableNotifications)
|
||||
#expect(userSettings.app.enableNotifications)
|
||||
}
|
||||
|
||||
@Test
|
||||
func disableNotifications() {
|
||||
userSettings.enableNotifications = true
|
||||
userSettings.app.enableNotifications = true
|
||||
context.send(viewAction: .changedEnableNotifications)
|
||||
#expect(!userSettings.enableNotifications)
|
||||
#expect(!userSettings.app.enableNotifications)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -411,7 +411,7 @@ struct NotificationSettingsScreenViewModelTests {
|
||||
// Given a tone and a manager that persists the selection to app settings
|
||||
let tone = NotificationTone.createBundledSound(label: "Test", filename: "test.caf")
|
||||
toneManager.setSelectedToneClosure = { [userSettings] selectedTone in
|
||||
userSettings.selectedNotificationTone = selectedTone
|
||||
userSettings.app.selectedNotificationTone = selectedTone
|
||||
return NotificationToneManager.libraryLocation
|
||||
}
|
||||
|
||||
@@ -419,21 +419,21 @@ struct NotificationSettingsScreenViewModelTests {
|
||||
context.send(viewAction: .selectAlertTone(tone))
|
||||
|
||||
// Then it is reflected in app settings
|
||||
#expect(userSettings.selectedNotificationTone == tone)
|
||||
#expect(userSettings.app.selectedNotificationTone == tone)
|
||||
}
|
||||
|
||||
@Test
|
||||
func deletingActiveToneResetsSelection() {
|
||||
// Given the active tone is a custom tone
|
||||
let customTone = NotificationTone.createCustomUserSound(filename: "custom.caf")
|
||||
userSettings.selectedNotificationTone = customTone
|
||||
userSettings.app.selectedNotificationTone = customTone
|
||||
toneManager.customTonesReturnValue = [customTone]
|
||||
|
||||
// When that tone is deleted
|
||||
context.send(viewAction: .deleteCustomAlertTones([customTone]))
|
||||
|
||||
// Then the selection is cleared, falling back to the default
|
||||
#expect(userSettings.selectedNotificationTone == nil)
|
||||
#expect(userSettings.app.selectedNotificationTone == nil)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -441,14 +441,14 @@ struct NotificationSettingsScreenViewModelTests {
|
||||
// Given a custom tone is active and a different custom tone also exists
|
||||
let activeTone = NotificationTone.createCustomUserSound(filename: "active.caf")
|
||||
let otherTone = NotificationTone.createCustomUserSound(filename: "other.caf")
|
||||
userSettings.selectedNotificationTone = activeTone
|
||||
userSettings.app.selectedNotificationTone = activeTone
|
||||
toneManager.customTonesReturnValue = [activeTone, otherTone]
|
||||
|
||||
// When the non-active tone is deleted
|
||||
context.send(viewAction: .deleteCustomAlertTones([otherTone]))
|
||||
|
||||
// Then the active selection is unchanged
|
||||
#expect(userSettings.selectedNotificationTone == activeTone)
|
||||
#expect(userSettings.app.selectedNotificationTone == activeTone)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -476,7 +476,7 @@ struct NotificationSettingsScreenViewModelTests {
|
||||
func deleteCustomToneFailurePreservesSelection() {
|
||||
// Given the active tone is a custom tone and deletion will fail
|
||||
let customTone = NotificationTone.createCustomUserSound(filename: "custom.caf")
|
||||
userSettings.selectedNotificationTone = customTone
|
||||
userSettings.app.selectedNotificationTone = customTone
|
||||
toneManager.deleteCustomToneThrowableError = NSError(domain: "test", code: 1)
|
||||
toneManager.customTonesReturnValue = [customTone]
|
||||
|
||||
@@ -484,7 +484,7 @@ struct NotificationSettingsScreenViewModelTests {
|
||||
context.send(viewAction: .deleteCustomAlertTones([customTone]))
|
||||
|
||||
// Then the selection is unchanged
|
||||
#expect(userSettings.selectedNotificationTone == customTone)
|
||||
#expect(userSettings.app.selectedNotificationTone == customTone)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -39,7 +39,7 @@ struct PresenceServiceTests {
|
||||
|
||||
@Test
|
||||
func serviceSeededActiveWhileSharingReportsOnline() async throws {
|
||||
userSettings.sharePresence = true
|
||||
userSettings.app.sharePresence = true
|
||||
|
||||
let deferred = deferFulfillment(sendsSubject) { $0.presence == .online }
|
||||
let service = makeService(initialApplicationState: .active)
|
||||
@@ -53,7 +53,7 @@ struct PresenceServiceTests {
|
||||
|
||||
@Test
|
||||
func serviceSeededBackgroundedWhileSharingReportsUnavailable() async throws {
|
||||
userSettings.sharePresence = true
|
||||
userSettings.app.sharePresence = true
|
||||
|
||||
let deferred = deferFulfillment(sendsSubject) { $0.presence == .unavailable }
|
||||
let service = makeService(initialApplicationState: .background)
|
||||
@@ -66,7 +66,7 @@ struct PresenceServiceTests {
|
||||
|
||||
@Test
|
||||
func serviceSeededActiveWhileNotSharingReportsOffline() async throws {
|
||||
userSettings.sharePresence = false
|
||||
userSettings.app.sharePresence = false
|
||||
|
||||
let deferred = deferFulfillment(sendsSubject) { $0.presence == .offline }
|
||||
let service = makeService(initialApplicationState: .active)
|
||||
@@ -79,7 +79,7 @@ struct PresenceServiceTests {
|
||||
|
||||
@Test
|
||||
func becomingActiveNotificationWhileSharingReportsOnlineImmediately() async throws {
|
||||
userSettings.sharePresence = true
|
||||
userSettings.app.sharePresence = true
|
||||
let service = makeService(initialApplicationState: .inactive)
|
||||
|
||||
let deferred = deferFulfillment(sendsSubject) { $0.presence == .online }
|
||||
@@ -93,7 +93,7 @@ struct PresenceServiceTests {
|
||||
|
||||
@Test
|
||||
func resigningActiveNotificationWhileSharingReportsUnavailableImmediately() async throws {
|
||||
userSettings.sharePresence = true
|
||||
userSettings.app.sharePresence = true
|
||||
let initialDeferred = deferFulfillment(sendsSubject) { $0.presence == .online }
|
||||
let service = makeService(initialApplicationState: .active)
|
||||
_ = try await initialDeferred.fulfill()
|
||||
@@ -109,19 +109,19 @@ struct PresenceServiceTests {
|
||||
|
||||
@Test
|
||||
func togglingSharingWhileActiveDrivesOnlineAndOffline() async throws {
|
||||
userSettings.sharePresence = false
|
||||
userSettings.app.sharePresence = false
|
||||
let initialDeferred = deferFulfillment(sendsSubject) { $0.presence == .offline }
|
||||
let service = makeService(initialApplicationState: .active)
|
||||
_ = try await initialDeferred.fulfill()
|
||||
|
||||
let onlineDeferred = deferFulfillment(sendsSubject) { $0.presence == .online }
|
||||
userSettings.sharePresence = true
|
||||
userSettings.app.sharePresence = true
|
||||
let online = try await onlineDeferred.fulfill()
|
||||
#expect(online.presence == .online)
|
||||
#expect(online.sendImmediately)
|
||||
|
||||
let offlineDeferred = deferFulfillment(sendsSubject) { $0.presence == .offline }
|
||||
userSettings.sharePresence = false
|
||||
userSettings.app.sharePresence = false
|
||||
let offline = try await offlineDeferred.fulfill()
|
||||
#expect(offline.presence == .offline)
|
||||
#expect(offline.sendImmediately)
|
||||
@@ -131,7 +131,7 @@ struct PresenceServiceTests {
|
||||
|
||||
@Test
|
||||
func repeatingTheSameStateSendsOnlyOnce() async throws {
|
||||
userSettings.sharePresence = true
|
||||
userSettings.app.sharePresence = true
|
||||
|
||||
let initialDeferred = deferFulfillment(sendsSubject) { $0.presence == .online }
|
||||
let service = makeService(initialApplicationState: .active)
|
||||
@@ -148,7 +148,7 @@ struct PresenceServiceTests {
|
||||
|
||||
@Test
|
||||
func failedImmediateSendIsNotRetriedUntilTheDesiredPresenceChanges() async throws {
|
||||
userSettings.sharePresence = true
|
||||
userSettings.app.sharePresence = true
|
||||
clientProxy.configurePresenceSendImmediatelyClosure = { [sendsSubject] presence, sendImmediately in
|
||||
sendsSubject.send((presence, sendImmediately))
|
||||
return presence == .online ? .failure(.forbiddenAccess) : .success(())
|
||||
@@ -173,7 +173,7 @@ struct PresenceServiceTests {
|
||||
|
||||
@Test
|
||||
func newerTransitionWinsWhenAnEarlierSendIsInFlight() async throws {
|
||||
userSettings.sharePresence = true
|
||||
userSettings.app.sharePresence = true
|
||||
|
||||
let (onlineStartedStream, onlineStartedContinuation) = AsyncStream<Void>.makeStream()
|
||||
let (resumeOnlineSendStream, resumeOnlineSendContinuation) = AsyncStream<Void>.makeStream()
|
||||
@@ -206,7 +206,7 @@ struct PresenceServiceTests {
|
||||
|
||||
@Test
|
||||
func deinitCancelsPendingSend() async throws {
|
||||
userSettings.sharePresence = true
|
||||
userSettings.app.sharePresence = true
|
||||
|
||||
let (onlineStartedStream, onlineStartedContinuation) = AsyncStream.makeStream(of: Void.self)
|
||||
let (onlineFinishedStream, onlineFinishedContinuation) = AsyncStream.makeStream(of: Void.self)
|
||||
|
||||
@@ -230,7 +230,7 @@ final class RoomFlowCoordinatorTests {
|
||||
|
||||
@Test
|
||||
func threadedEventRoutes() async throws {
|
||||
userSettings.threadsEnabled = true
|
||||
userSettings.app.threadsEnabled = true
|
||||
setupRoomFlowCoordinator()
|
||||
|
||||
// Navigate directly to the threaded event
|
||||
|
||||
@@ -148,12 +148,12 @@ final class RoomListFiltersStateTests {
|
||||
// MARK: - Helpers
|
||||
|
||||
private func enableLowPriorityFeature() {
|
||||
userSettings.lowPriorityFilterEnabled = true
|
||||
userSettings.app.lowPriorityFilterEnabled = true
|
||||
state = RoomListFiltersState(userSettings: userSettings)
|
||||
}
|
||||
|
||||
private func enableMentionsFeature() {
|
||||
userSettings.mentionsFilterEnabled = true
|
||||
userSettings.app.mentionsFilterEnabled = true
|
||||
state = RoomListFiltersState(userSettings: userSettings)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ final class RoomScreenViewModelTests {
|
||||
@Test
|
||||
func pinnedEventsBannerThreadedSelection() async throws {
|
||||
let userSettings = UserSettings.mock()
|
||||
userSettings.threadsEnabled = true
|
||||
userSettings.app.threadsEnabled = true
|
||||
let userSession = UserSessionMock(.init(userSettings: userSettings))
|
||||
|
||||
let roomProxyMock = JoinedRoomProxyMock(.init())
|
||||
|
||||
@@ -123,7 +123,7 @@ final class RoomSummaryProviderTests {
|
||||
|
||||
private func setup(isLowPriorityFilterEnabled: Bool = false, includesOnlyJoinedRooms: Bool = false, setsRoomList: Bool = true) {
|
||||
userSettings = UserSettings.mock()
|
||||
userSettings.lowPriorityFilterEnabled = isLowPriorityFilterEnabled
|
||||
userSettings.app.lowPriorityFilterEnabled = isLowPriorityFilterEnabled
|
||||
|
||||
let stateEventStringBuilder = RoomStateEventStringBuilder(userID: "@me:matrix.org")
|
||||
let attributedStringBuilder = AttributedStringBuilder(mentionBuilder: MentionBuilder())
|
||||
|
||||
@@ -124,44 +124,44 @@ struct SearchScreenViewModelTests {
|
||||
context.searchQuery = "Second"
|
||||
context.send(viewAction: .selectRoom(roomID: "2"))
|
||||
|
||||
#expect(userSettings.searchBreadcrumbs == [.room(roomID: "2")])
|
||||
#expect(userSettings.account.searchBreadcrumbs == [.room(roomID: "2")])
|
||||
|
||||
context.send(viewAction: .submitQuery)
|
||||
|
||||
#expect(userSettings.searchBreadcrumbs == [.query("Second"), .room(roomID: "2")])
|
||||
#expect(userSettings.account.searchBreadcrumbs == [.query("Second"), .room(roomID: "2")])
|
||||
|
||||
// Selecting the same room again from the empty state only bumps it back to the top.
|
||||
context.searchQuery = ""
|
||||
context.send(viewAction: .selectRoom(roomID: "2"))
|
||||
|
||||
#expect(userSettings.searchBreadcrumbs == [.room(roomID: "2"), .query("Second")])
|
||||
#expect(userSettings.account.searchBreadcrumbs == [.room(roomID: "2"), .query("Second")])
|
||||
|
||||
// Submitting an empty query records nothing.
|
||||
context.send(viewAction: .submitQuery)
|
||||
|
||||
#expect(userSettings.searchBreadcrumbs == [.room(roomID: "2"), .query("Second")])
|
||||
#expect(userSettings.account.searchBreadcrumbs == [.room(roomID: "2"), .query("Second")])
|
||||
}
|
||||
|
||||
@Test
|
||||
func removingBreadcrumbs() {
|
||||
userSettings.searchBreadcrumbs = [.query("Second"), .room(roomID: "2")]
|
||||
userSettings.account.searchBreadcrumbs = [.query("Second"), .room(roomID: "2")]
|
||||
|
||||
context.send(viewAction: .removeBreadcrumb(.query("Second")))
|
||||
|
||||
#expect(userSettings.searchBreadcrumbs == [.room(roomID: "2")])
|
||||
#expect(userSettings.account.searchBreadcrumbs == [.room(roomID: "2")])
|
||||
|
||||
context.send(viewAction: .removeBreadcrumb(.room(SearchScreenRoom(.mock(id: "2", name: "Second")))))
|
||||
|
||||
#expect(userSettings.searchBreadcrumbs.isEmpty)
|
||||
#expect(userSettings.account.searchBreadcrumbs.isEmpty)
|
||||
}
|
||||
|
||||
@Test
|
||||
func clearingBreadcrumbs() {
|
||||
userSettings.searchBreadcrumbs = [.query("Second"), .room(roomID: "2")]
|
||||
userSettings.account.searchBreadcrumbs = [.query("Second"), .room(roomID: "2")]
|
||||
|
||||
context.send(viewAction: .clearBreadcrumbs)
|
||||
|
||||
#expect(userSettings.searchBreadcrumbs.isEmpty)
|
||||
#expect(userSettings.account.searchBreadcrumbs.isEmpty)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -169,7 +169,7 @@ struct SearchScreenViewModelTests {
|
||||
staticRoomListSubject.send([.mock(id: "2", name: "Second")])
|
||||
|
||||
let deferred = deferFulfillment(context.observe(\.viewState.breadcrumbs)) { $0.count == 2 }
|
||||
userSettings.searchBreadcrumbs = [.query("Second"), .room(roomID: "2")]
|
||||
userSettings.account.searchBreadcrumbs = [.query("Second"), .room(roomID: "2")]
|
||||
try await deferred.fulfill()
|
||||
|
||||
#expect(context.viewState.breadcrumbs.map(\.id) == ["query-Second", "room-2"])
|
||||
@@ -180,7 +180,7 @@ struct SearchScreenViewModelTests {
|
||||
staticRoomListSubject.send([.mock(id: "2", name: "Second"), .mock(id: "left", name: "Left", isJoined: false)])
|
||||
|
||||
let deferred = deferFulfillment(context.observe(\.viewState.breadcrumbs)) { !$0.isEmpty }
|
||||
userSettings.searchBreadcrumbs = [.room(roomID: "left"), .room(roomID: "2")]
|
||||
userSettings.account.searchBreadcrumbs = [.room(roomID: "left"), .room(roomID: "2")]
|
||||
try await deferred.fulfill()
|
||||
|
||||
#expect(context.viewState.breadcrumbs.map(\.id) == ["room-2"])
|
||||
@@ -190,7 +190,7 @@ struct SearchScreenViewModelTests {
|
||||
@Test
|
||||
func roomBreadcrumbsAreDisplayedAfterTheRoomListLoads() async throws {
|
||||
var deferred = deferFulfillment(context.observe(\.viewState.breadcrumbs)) { $0.count == 1 }
|
||||
userSettings.searchBreadcrumbs = [.query("Second"), .room(roomID: "2")]
|
||||
userSettings.account.searchBreadcrumbs = [.query("Second"), .room(roomID: "2")]
|
||||
try await deferred.fulfill()
|
||||
|
||||
#expect(context.viewState.breadcrumbs.map(\.id) == ["query-Second"])
|
||||
|
||||
@@ -458,8 +458,8 @@ final class SecurityAndPrivacyScreenViewModelTests {
|
||||
joinRule: ElementX.JoinRule,
|
||||
forceDisableE2EE: Bool = false) {
|
||||
let userSettings = UserSettings.mock()
|
||||
userSettings.knockingEnabled = true
|
||||
userSettings.forceDisableE2EE.applyRemoteValue(forceDisableE2EE)
|
||||
userSettings.app.knockingEnabled = true
|
||||
userSettings.app.forceDisableE2EE.applyRemoteValue(forceDisableE2EE)
|
||||
roomProxy = JoinedRoomProxyMock(.init(isEncrypted: false,
|
||||
canonicalAlias: "#room:matrix.org",
|
||||
members: .allMembersAsCreator,
|
||||
|
||||
@@ -181,11 +181,11 @@ struct SettingsScreenViewModelTests {
|
||||
#expect(!context.viewState.showAddAccountButton)
|
||||
|
||||
var deferred = deferFulfillment(context.observe(\.viewState.showAddAccountButton)) { $0 }
|
||||
userSettings.multiAccountEnabled = true
|
||||
userSettings.app.multiAccountEnabled = true
|
||||
try await deferred.fulfill()
|
||||
|
||||
deferred = deferFulfillment(context.observe(\.viewState.showAddAccountButton)) { !$0 }
|
||||
userSettings.multiAccountEnabled = false
|
||||
userSettings.app.multiAccountEnabled = false
|
||||
try await deferred.fulfill()
|
||||
}
|
||||
|
||||
|
||||
@@ -900,14 +900,14 @@ final class TimelineViewModelTests {
|
||||
func disablingTheFlagClearsTheSelection() async throws {
|
||||
let items = [TextRoomTimelineItem(eventID: "$1")]
|
||||
let userSettings = UserSettings.mock()
|
||||
userSettings.messageMultiSelectEnabled = true
|
||||
userSettings.app.messageMultiSelectEnabled = true
|
||||
let viewModel = makeViewModel(timelineController: TimelineControllerMock(.init(timelineItems: items)), userSettings: userSettings)
|
||||
|
||||
startSelection(items[0].id, in: viewModel)
|
||||
#expect(viewModel.state.messageSelection.isActive)
|
||||
|
||||
let deferred = deferFulfillment(viewModel.context.$viewState) { !$0.messageSelection.isEnabled && !$0.messageSelection.isActive }
|
||||
userSettings.messageMultiSelectEnabled = false
|
||||
userSettings.app.messageMultiSelectEnabled = false
|
||||
try await deferred.fulfill()
|
||||
}
|
||||
|
||||
@@ -945,7 +945,7 @@ final class TimelineViewModelTests {
|
||||
private func makeSelectionViewModel(timelineController: TimelineControllerProtocol,
|
||||
userIndicatorController: UserIndicatorControllerProtocol = UserIndicatorControllerMock()) -> TimelineViewModel {
|
||||
let userSettings = UserSettings.mock()
|
||||
userSettings.messageMultiSelectEnabled = true
|
||||
userSettings.app.messageMultiSelectEnabled = true
|
||||
return makeViewModel(timelineController: timelineController,
|
||||
userIndicatorController: userIndicatorController,
|
||||
userSettings: userSettings)
|
||||
|
||||
@@ -24,31 +24,31 @@ struct UserSettingsTests {
|
||||
@Test
|
||||
func accountSettingsAreScopedToAccount() {
|
||||
// Given settings for two different accounts.
|
||||
#expect(aliceSettings.searchBreadcrumbs.isEmpty)
|
||||
#expect(bobSettings.searchBreadcrumbs.isEmpty)
|
||||
#expect(aliceSettings.account.searchBreadcrumbs.isEmpty)
|
||||
#expect(bobSettings.account.searchBreadcrumbs.isEmpty)
|
||||
|
||||
// When updating an account setting for Alice.
|
||||
aliceSettings.searchBreadcrumbs = [.query("Alice")]
|
||||
aliceSettings.account.searchBreadcrumbs = [.query("Alice")]
|
||||
|
||||
// Then only Alice should see the change.
|
||||
#expect(aliceSettings.searchBreadcrumbs == [.query("Alice")])
|
||||
#expect(bobSettings.searchBreadcrumbs.isEmpty)
|
||||
#expect(aliceSettings.account.searchBreadcrumbs == [.query("Alice")])
|
||||
#expect(bobSettings.account.searchBreadcrumbs.isEmpty)
|
||||
}
|
||||
|
||||
@Test
|
||||
func appSettingsAreShared() {
|
||||
// Given settings for two different accounts.
|
||||
#expect(!appSettings.hasSignedInBefore)
|
||||
#expect(!aliceSettings.hasSignedInBefore)
|
||||
#expect(!bobSettings.hasSignedInBefore)
|
||||
#expect(!aliceSettings.app.hasSignedInBefore)
|
||||
#expect(!bobSettings.app.hasSignedInBefore)
|
||||
|
||||
// When updating an app setting through Alice's settings.
|
||||
aliceSettings.hasSignedInBefore = true
|
||||
aliceSettings.app.hasSignedInBefore = true
|
||||
|
||||
// Then the change should be seen by the app and every account.
|
||||
#expect(appSettings.hasSignedInBefore)
|
||||
#expect(aliceSettings.hasSignedInBefore)
|
||||
#expect(bobSettings.hasSignedInBefore)
|
||||
#expect(aliceSettings.app.hasSignedInBefore)
|
||||
#expect(bobSettings.app.hasSignedInBefore)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -59,18 +59,18 @@ struct UserSettingsTests {
|
||||
try store.set(JSONEncoder().encode([SearchBreadcrumb.query("Alice")]), forKey: "searchBreadcrumbs")
|
||||
#expect(store.object(forKey: "hasRunIdentityConfirmationOnboarding") != nil)
|
||||
#expect(store.object(forKey: "searchBreadcrumbs") != nil)
|
||||
#expect(!aliceSettings.hasRunIdentityConfirmationOnboarding)
|
||||
#expect(aliceSettings.searchBreadcrumbs.isEmpty)
|
||||
#expect(!aliceSettings.account.hasRunIdentityConfirmationOnboarding)
|
||||
#expect(aliceSettings.account.searchBreadcrumbs.isEmpty)
|
||||
|
||||
// When migrating those values into Alice's account settings.
|
||||
aliceSettings.migrateAppSettingsValueToAccountSettings(\.hasRunIdentityConfirmationOnboardingKey)
|
||||
aliceSettings.migrateAppSettingsValueToAccountSettings(\.searchBreadcrumbsKey)
|
||||
aliceSettings.account.migrateAppSettingsValue(\.hasRunIdentityConfirmationOnboardingKey)
|
||||
aliceSettings.account.migrateAppSettingsValue(\.searchBreadcrumbsKey)
|
||||
|
||||
// Then the values should belong to Alice only.
|
||||
#expect(aliceSettings.hasRunIdentityConfirmationOnboarding)
|
||||
#expect(aliceSettings.searchBreadcrumbs == [.query("Alice")])
|
||||
#expect(!bobSettings.hasRunIdentityConfirmationOnboarding)
|
||||
#expect(bobSettings.searchBreadcrumbs.isEmpty)
|
||||
#expect(aliceSettings.account.hasRunIdentityConfirmationOnboarding)
|
||||
#expect(aliceSettings.account.searchBreadcrumbs == [.query("Alice")])
|
||||
#expect(!bobSettings.account.hasRunIdentityConfirmationOnboarding)
|
||||
#expect(bobSettings.account.searchBreadcrumbs.isEmpty)
|
||||
#expect(store.object(forKey: "hasRunIdentityConfirmationOnboarding") == nil)
|
||||
#expect(store.object(forKey: "searchBreadcrumbs") == nil)
|
||||
}
|
||||
@@ -79,24 +79,24 @@ struct UserSettingsTests {
|
||||
func resetSessionSpecificSettings() {
|
||||
// Given app settings and account settings for two different accounts.
|
||||
appSettings.hasSignedInBefore = true
|
||||
aliceSettings.hasRunIdentityConfirmationOnboarding = true
|
||||
aliceSettings.searchBreadcrumbs = [.query("Alice")]
|
||||
bobSettings.hasRunIdentityConfirmationOnboarding = true
|
||||
bobSettings.searchBreadcrumbs = [.query("Bob")]
|
||||
aliceSettings.account.hasRunIdentityConfirmationOnboarding = true
|
||||
aliceSettings.account.searchBreadcrumbs = [.query("Alice")]
|
||||
bobSettings.account.hasRunIdentityConfirmationOnboarding = true
|
||||
bobSettings.account.searchBreadcrumbs = [.query("Bob")]
|
||||
#expect(appSettings.hasSignedInBefore)
|
||||
#expect(aliceSettings.hasRunIdentityConfirmationOnboarding)
|
||||
#expect(aliceSettings.searchBreadcrumbs == [.query("Alice")])
|
||||
#expect(bobSettings.hasRunIdentityConfirmationOnboarding)
|
||||
#expect(bobSettings.searchBreadcrumbs == [.query("Bob")])
|
||||
#expect(aliceSettings.account.hasRunIdentityConfirmationOnboarding)
|
||||
#expect(aliceSettings.account.searchBreadcrumbs == [.query("Alice")])
|
||||
#expect(bobSettings.account.hasRunIdentityConfirmationOnboarding)
|
||||
#expect(bobSettings.account.searchBreadcrumbs == [.query("Bob")])
|
||||
|
||||
// When resetting Alice's session specific settings.
|
||||
aliceSettings.resetSessionSpecificSettings()
|
||||
aliceSettings.account.reset()
|
||||
|
||||
// Then only Alice's account settings should be reset.
|
||||
#expect(!aliceSettings.hasRunIdentityConfirmationOnboarding)
|
||||
#expect(aliceSettings.searchBreadcrumbs.isEmpty)
|
||||
#expect(bobSettings.hasRunIdentityConfirmationOnboarding)
|
||||
#expect(bobSettings.searchBreadcrumbs == [.query("Bob")])
|
||||
#expect(!aliceSettings.account.hasRunIdentityConfirmationOnboarding)
|
||||
#expect(aliceSettings.account.searchBreadcrumbs.isEmpty)
|
||||
#expect(bobSettings.account.hasRunIdentityConfirmationOnboarding)
|
||||
#expect(bobSettings.account.searchBreadcrumbs == [.query("Bob")])
|
||||
#expect(appSettings.hasSignedInBefore)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user