mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-10-31 08:15:24 +00:00
Move any visible account settings into AccountSettings. (#6308)
* Remove the now unused setting to disable in-app notifications. * Move visible account settings into AccountSettings. Have ignored enableNotifications for now as that will require reworking the NotificationManager. * Allow different sounds to be selected for each account. * Move defaultNotificationTone into AccountSettings.
This commit is contained in:
@@ -23,7 +23,6 @@ nonisolated struct NotificationContentBuilderTests {
|
||||
style: .plain)
|
||||
mediaProvider = MediaProviderMock(.init())
|
||||
notificationContentBuilder = await NotificationContentBuilder(messageEventStringBuilder: stringBuilder,
|
||||
notificationSoundName: UNNotificationSoundName("message.caf"),
|
||||
userSession: NSEUserSessionMock(.init()))
|
||||
}
|
||||
|
||||
|
||||
@@ -411,29 +411,29 @@ 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.app.selectedNotificationTone = selectedTone
|
||||
return NotificationToneManager.libraryLocation
|
||||
userSettings.account.selectedNotificationTone = selectedTone
|
||||
return URL.customTonesDirectory
|
||||
}
|
||||
|
||||
// When the user selects that tone
|
||||
context.send(viewAction: .selectAlertTone(tone))
|
||||
|
||||
// Then it is reflected in app settings
|
||||
#expect(userSettings.app.selectedNotificationTone == tone)
|
||||
#expect(userSettings.account.selectedNotificationTone == tone)
|
||||
}
|
||||
|
||||
@Test
|
||||
func deletingActiveToneResetsSelection() {
|
||||
// Given the active tone is a custom tone
|
||||
let customTone = NotificationTone.createCustomUserSound(filename: "custom.caf")
|
||||
userSettings.app.selectedNotificationTone = customTone
|
||||
userSettings.account.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.app.selectedNotificationTone == nil)
|
||||
#expect(userSettings.account.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.app.selectedNotificationTone = activeTone
|
||||
userSettings.account.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.app.selectedNotificationTone == activeTone)
|
||||
#expect(userSettings.account.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.app.selectedNotificationTone = customTone
|
||||
userSettings.account.selectedNotificationTone = customTone
|
||||
toneManager.deleteCustomToneThrowableError = NSError(domain: "test", code: 1)
|
||||
toneManager.customTonesReturnValue = [customTone]
|
||||
|
||||
@@ -484,14 +484,14 @@ struct NotificationSettingsScreenViewModelTests {
|
||||
context.send(viewAction: .deleteCustomAlertTones([customTone]))
|
||||
|
||||
// Then the selection is unchanged
|
||||
#expect(userSettings.app.selectedNotificationTone == customTone)
|
||||
#expect(userSettings.account.selectedNotificationTone == customTone)
|
||||
}
|
||||
|
||||
@Test
|
||||
func importingCustomToneRefreshesAvailableList() async throws {
|
||||
// Given a tone file ready to import
|
||||
let importedTone = NotificationTone.createCustomUserSound(filename: "imported.caf")
|
||||
let location = NotificationToneManager.libraryLocation.appending(component: importedTone.filename)
|
||||
let location = URL.customTonesDirectory.appending(component: importedTone.filename)
|
||||
toneManager.addNewToneToLibraryFromReturnValue = location
|
||||
toneManager.customTonesReturnValue = [importedTone]
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import Foundation
|
||||
import Testing
|
||||
|
||||
/// These tests exercise `NotificationToneManager` against the real app sandbox filesystem.
|
||||
/// Because all tests share a single `libraryLocation` directory on disk, they are inherently
|
||||
/// Because all tests share a single `customTonesDirectory` on disk, they are inherently
|
||||
/// incapable of running in parallel — files written by one test would corrupt the state of
|
||||
/// another. This project runs test in serial regardless, but this is just to document this is a specific case
|
||||
/// relying on that behavior.
|
||||
@@ -56,8 +56,8 @@ struct NotificationToneManagerTests {
|
||||
@Test
|
||||
func customTonesFiltersToCAFOnly() throws {
|
||||
// Given both CAF and non-CAF files written to the library directory
|
||||
let cafURL = NotificationToneManager.libraryLocation.appending(component: "\(UUID().uuidString).caf")
|
||||
let mp3URL = NotificationToneManager.libraryLocation.appending(component: "\(UUID().uuidString).mp3")
|
||||
let cafURL = URL.customTonesDirectory.appending(component: "\(UUID().uuidString).caf")
|
||||
let mp3URL = URL.customTonesDirectory.appending(component: "\(UUID().uuidString).mp3")
|
||||
defer {
|
||||
try? FileManager.default.removeItem(at: cafURL)
|
||||
try? FileManager.default.removeItem(at: mp3URL)
|
||||
@@ -79,7 +79,7 @@ struct NotificationToneManagerTests {
|
||||
func addingDuplicateToneThrowsFileAlreadyExists() async throws {
|
||||
// Given a CAF file that has already been imported into the library
|
||||
let sourceURL = URL.temporaryDirectory.appending(component: "\(UUID().uuidString).caf")
|
||||
let importedURL = NotificationToneManager.libraryLocation
|
||||
let importedURL = URL.customTonesDirectory
|
||||
.appending(component: sourceURL.deletingPathExtension().lastPathComponent)
|
||||
.appendingPathExtension("caf")
|
||||
defer {
|
||||
|
||||
@@ -39,7 +39,7 @@ struct PresenceServiceTests {
|
||||
|
||||
@Test
|
||||
func serviceSeededActiveWhileSharingReportsOnline() async throws {
|
||||
userSettings.app.sharePresence = true
|
||||
userSettings.account.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.app.sharePresence = true
|
||||
userSettings.account.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.app.sharePresence = false
|
||||
userSettings.account.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.app.sharePresence = true
|
||||
userSettings.account.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.app.sharePresence = true
|
||||
userSettings.account.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.app.sharePresence = false
|
||||
userSettings.account.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.app.sharePresence = true
|
||||
userSettings.account.sharePresence = true
|
||||
let online = try await onlineDeferred.fulfill()
|
||||
#expect(online.presence == .online)
|
||||
#expect(online.sendImmediately)
|
||||
|
||||
let offlineDeferred = deferFulfillment(sendsSubject) { $0.presence == .offline }
|
||||
userSettings.app.sharePresence = false
|
||||
userSettings.account.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.app.sharePresence = true
|
||||
userSettings.account.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.app.sharePresence = true
|
||||
userSettings.account.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.app.sharePresence = true
|
||||
userSettings.account.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.app.sharePresence = true
|
||||
userSettings.account.sharePresence = true
|
||||
|
||||
let (onlineStartedStream, onlineStartedContinuation) = AsyncStream.makeStream(of: Void.self)
|
||||
let (onlineFinishedStream, onlineFinishedContinuation) = AsyncStream.makeStream(of: Void.self)
|
||||
|
||||
Reference in New Issue
Block a user