From 1a6c0d03177b200f458bc53191e50856a39782d6 Mon Sep 17 00:00:00 2001 From: Sabrina Tardio Date: Wed, 18 Oct 2023 16:56:26 +0200 Subject: [PATCH] extract UserText and fix tests --- DuckDuckGo/MainViewController+Segues.swift | 8 - ...cSettingsViewController+SyncDelegate.swift | 1 - DuckDuckGo/SyncSettingsViewController.swift | 2 - DuckDuckGoTests/AppSettingsMock.swift | 4 + .../SyncManagementViewModelTests.swift | 28 ++ .../SyncUI/Views/Internal/UserText.swift | 7 + .../SyncUI/Views/SyncSettingsView.swift | 285 +++++++++--------- 7 files changed, 184 insertions(+), 151 deletions(-) diff --git a/DuckDuckGo/MainViewController+Segues.swift b/DuckDuckGo/MainViewController+Segues.swift index 8fbf104af7..0013ef5ddb 100644 --- a/DuckDuckGo/MainViewController+Segues.swift +++ b/DuckDuckGo/MainViewController+Segues.swift @@ -199,14 +199,6 @@ extension MainViewController { } } - func segueToSettingsLogins() { - os_log(#function, log: .generalLog, type: .debug) - hideAllHighlightsIfNeeded() - launchSettings { - $0.openLogins() - } - } - private func launchSettings(completion: ((SettingsViewController) -> Void)? = nil) { os_log(#function, log: .generalLog, type: .debug) let storyboard = UIStoryboard(name: "Settings", bundle: nil) diff --git a/DuckDuckGo/SyncSettingsViewController+SyncDelegate.swift b/DuckDuckGo/SyncSettingsViewController+SyncDelegate.swift index c5e824613d..75e3f2e990 100644 --- a/DuckDuckGo/SyncSettingsViewController+SyncDelegate.swift +++ b/DuckDuckGo/SyncSettingsViewController+SyncDelegate.swift @@ -37,7 +37,6 @@ extension SyncSettingsViewController: SyncManagementViewModelDelegate { mainVC.segueToBookmarks() } - func updateDeviceName(_ name: String) { Task { @MainActor in rootView.model.devices = [] diff --git a/DuckDuckGo/SyncSettingsViewController.swift b/DuckDuckGo/SyncSettingsViewController.swift index 3f11a60d52..6bba63102b 100644 --- a/DuckDuckGo/SyncSettingsViewController.swift +++ b/DuckDuckGo/SyncSettingsViewController.swift @@ -49,7 +49,6 @@ class SyncSettingsViewController: UIHostingController { var cancellables = Set() - // For some reason, on iOS 14, the viewDidLoad wasn't getting called so do some setup here convenience init(appSettings: AppSettings = AppDependencyProvider.shared.appSettings) { let viewModel = SyncSettingsViewModel() @@ -160,7 +159,6 @@ class SyncSettingsViewController: UIHostingController { lhs.isThisDevice }) } - } diff --git a/DuckDuckGoTests/AppSettingsMock.swift b/DuckDuckGoTests/AppSettingsMock.swift index 00687a6ef4..3725c2ebc9 100644 --- a/DuckDuckGoTests/AppSettingsMock.swift +++ b/DuckDuckGoTests/AppSettingsMock.swift @@ -22,6 +22,10 @@ import Foundation @testable import DuckDuckGo class AppSettingsMock: AppSettings { + + var isSyncBookmarksPaused: Bool = false + + var isSyncCredentialsPaused: Bool = false var autofillCredentialsEnabled: Bool = false diff --git a/DuckDuckGoTests/SyncManagementViewModelTests.swift b/DuckDuckGoTests/SyncManagementViewModelTests.swift index f85a9a79b1..7964c0910c 100644 --- a/DuckDuckGoTests/SyncManagementViewModelTests.swift +++ b/DuckDuckGoTests/SyncManagementViewModelTests.swift @@ -82,6 +82,26 @@ class SyncManagementViewModelTests: XCTestCase, SyncManagementViewModelDelegate ]) } + func testWhenManageBookmarksCalled_BookmarksVCIsLaunched() { + model.manageBookmarks() + + // You can either test one individual call was made x number of times or check for a whole number of calls + monitor.assert(#selector(launchBookmarksViewController).description, calls: 1) + monitor.assertCalls([ + #selector(launchBookmarksViewController).description: 1 + ]) + } + + func testWhenManageLogindCalled_AutofillVCIsLaunched() { + model.manageLogins() + + // You can either test one individual call was made x number of times or check for a whole number of calls + monitor.assert(#selector(launchAutofillViewController).description, calls: 1) + monitor.assertCalls([ + #selector(launchAutofillViewController).description: 1 + ]) + } + // MARK: Delegate functions func showSyncWithAnotherDeviceEnterText() { @@ -148,6 +168,14 @@ class SyncManagementViewModelTests: XCTestCase, SyncManagementViewModelDelegate monitor.incrementCalls(function: #function.cleaningFunctionName()) } + func launchBookmarksViewController() { + monitor.incrementCalls(function: #function.cleaningFunctionName()) + } + + func launchAutofillViewController() { + monitor.incrementCalls(function: #function.cleaningFunctionName()) + } + } // MARK: An idea... can be made more public if works out diff --git a/LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/UserText.swift b/LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/UserText.swift index 387e61c277..1fc5c3535b 100644 --- a/LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/UserText.swift +++ b/LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/UserText.swift @@ -112,5 +112,12 @@ struct UserText { return "\"\(name)\" will no longer be able to access your synced data." } + static let syncLimitExceededTitle = "⚠️ Sync Paused" + static let bookmarksLimitExceededDescription = "Bookmark limit exceeded. Delete some to resume syncing." + static let credentialsLimitExceededDescription = "Logins limit exceeded. Delete some to resume syncing." + static let bookmarksLimitExceededAction = "Manage Bookmarks" + static let credentialsLimitExceededAction = "Manage Logins" + + } // swiftlint:enable line_length diff --git a/LocalPackages/SyncUI/Sources/SyncUI/Views/SyncSettingsView.swift b/LocalPackages/SyncUI/Sources/SyncUI/Views/SyncSettingsView.swift index c5bbee94fe..f2fff4bf6c 100644 --- a/LocalPackages/SyncUI/Sources/SyncUI/Views/SyncSettingsView.swift +++ b/LocalPackages/SyncUI/Sources/SyncUI/Views/SyncSettingsView.swift @@ -40,6 +40,8 @@ public struct SyncSettingsView: View { } } else { List { + workInProgress() + if model.isSyncEnabled { turnOffSync() @@ -66,9 +68,7 @@ public struct SyncSettingsView: View { deleteAllData() } else { - - workInProgress() - + syncWithAnotherDeviceView() singleDeviceSetUpView() @@ -95,54 +95,118 @@ public struct SyncSettingsView: View { @State var selectedDevice: SyncSettingsViewModel.Device? @ViewBuilder - func devices() -> some View { + func workInProgress() -> some View { Section { - if model.devices.isEmpty { - ProgressView() - .padding() + EmptyView() + } footer: { + VStack(alignment: .leading, spacing: 4) { + Text("Work in Progress") + .font(.system(size: 12, weight: .semibold)) + .foregroundColor(.black) + + // swiftlint:disable line_length + Text("This feature is viewable to internal users only and is still being developed and tested. Currently you can create accounts, connect and manage devices, and sync bookmarks, favorites, Autofill logins and Email Protection status. **[More Info](https://app.asana.com/0/1201493110486074/1203756800930481/f)**") + .foregroundColor(.black) + .font(.system(size: 11, weight: .regular)) + // swiftlint:enable line_length } + .padding() + .background(RoundedRectangle(cornerRadius: 8).foregroundColor(.yellow)) + .padding(.bottom, 10) + } - ForEach(model.devices) { device in - Button { - selectedDevice = device - } label: { - HStack { - deviceTypeImage(device) - Text(device.name) - .foregroundColor(.primary) - Spacer() - if device.isThisDevice { - Text(UserText.thisDevice) - .foregroundColor(.secondary) - } - } - } + } + +} + +// Sync Set up Views +extension SyncSettingsView { + @ViewBuilder + func recoverYourDataView() -> some View { + Section { + Button(UserText.recoverYourData) { + model.showRecoverDataView() } - } header: { - Text(UserText.connectedDevicesTitle) } - .sheet(item: $selectedDevice) { device in - Group { - if device.isThisDevice { - EditDeviceView(model: model.createEditDeviceModel(device)) - } else { - RemoveDeviceView(model: model.createRemoveDeviceModel(device)) + } + + @ViewBuilder + func footerView() -> some View { + Section {} footer: { + Text(UserText.syncSettingsFooter) + .daxFootnoteRegular() + .foregroundColor(.secondary) + } + } + + @ViewBuilder + func singleDeviceSetUpView() -> some View { + Section { + HStack { + VStack(alignment: .leading, spacing: 4) { + Text(UserText.singleDeviceSetUpTitle) + .daxBodyBold() + Text(UserText.singleDeviceSetUpInstruction) + .daxBodyRegular() } + Spacer() + Image("Device-Mobile-Upload-96") + } - .modifier { - if #available(iOS 16.0, *) { - $0.presentationDetents([.medium]) - } else { - $0 + if model.isBusy { + SwiftUI.ProgressView() + } else { + Button(UserText.turnSyncOn) { + model.startSyncPressed() } } } - .onReceive(timer) { _ in - if selectedDevice == nil { - model.delegate?.refreshDevices(clearDevices: false) + } + + @ViewBuilder + func syncWithAnotherDeviceView() -> some View { + Section { + HStack { + VStack(alignment: .leading, spacing: 4) { + Text(UserText.syncWithAnotherDeviceTitle) + .daxBodyBold() + Text(UserText.syncWithAnotherDeviceMessage) + .daxBodyRegular() + } + Spacer() + Image("Sync-Pair-96") + + } + Button(UserText.scanQRCode) { + model.scanQRCode() + } + Button(UserText.enterTextCode) { + model.showEnterTextView() } } + } +} +// Sync Enabled Views +extension SyncSettingsView { + @ViewBuilder + func deleteAllData() -> some View { + Section { + Button(UserText.settingsDeleteAllButton) { + model.deleteAllData() + } + } + } + + @ViewBuilder + func saveRecoveryPDF() -> some View { + Section { + Button(UserText.settingsSaveRecoveryPDFButton) { + model.saveRecoveryPDF() + } + } footer: { + Text(UserText.settingsRecoveryPDFWarning) + } } @ViewBuilder @@ -180,69 +244,54 @@ public struct SyncSettingsView: View { } @ViewBuilder - func saveRecoveryPDF() -> some View { - Section { - Button(UserText.settingsSaveRecoveryPDFButton) { - model.saveRecoveryPDF() - } - } footer: { - Text(UserText.settingsRecoveryPDFWarning) - } - } - - @ViewBuilder - func deleteAllData() -> some View { + func devices() -> some View { Section { - Button(UserText.settingsDeleteAllButton) { - model.deleteAllData() + if model.devices.isEmpty { + ProgressView() + .padding() } - } - } - @ViewBuilder - func workInProgress() -> some View { - Section { - EmptyView() - } footer: { - VStack(alignment: .leading, spacing: 4) { - Text("Work in Progress") - .font(.system(size: 12, weight: .semibold)) - .foregroundColor(.black) - - // swiftlint:disable line_length - Text("This feature is viewable to internal users only and is still being developed and tested. Currently you can create accounts, connect and manage devices, and sync bookmarks, favorites, Autofill logins and Email Protection status. **[More Info](https://app.asana.com/0/1201493110486074/1203756800930481/f)**") - .foregroundColor(.black) - .font(.system(size: 11, weight: .regular)) - // swiftlint:enable line_length + ForEach(model.devices) { device in + Button { + selectedDevice = device + } label: { + HStack { + deviceTypeImage(device) + Text(device.name) + .foregroundColor(.primary) + Spacer() + if device.isThisDevice { + Text(UserText.thisDevice) + .foregroundColor(.secondary) + } + } + } } - .padding() - .background(RoundedRectangle(cornerRadius: 8).foregroundColor(.yellow)) - .padding(.bottom, 10) + } header: { + Text(UserText.connectedDevicesTitle) } - - } - - @ViewBuilder - func syncWithAnotherDeviceView() -> some View { - Section { - HStack { - VStack(alignment: .leading, spacing: 4) { - Text(UserText.syncWithAnotherDeviceTitle) - .daxBodyBold() - Text(UserText.syncWithAnotherDeviceMessage) - .daxBodyRegular() + .sheet(item: $selectedDevice) { device in + Group { + if device.isThisDevice { + EditDeviceView(model: model.createEditDeviceModel(device)) + } else { + RemoveDeviceView(model: model.createRemoveDeviceModel(device)) } - Spacer() - Image("Sync-Pair-96") - } - Button(UserText.scanQRCode) { - model.scanQRCode() + .modifier { + if #available(iOS 16.0, *) { + $0.presentationDetents([.medium]) + } else { + $0 + } } - Button(UserText.enterTextCode) { - model.showEnterTextView() + } + .onReceive(timer) { _ in + if selectedDevice == nil { + model.delegate?.refreshDevices(clearDevices: false) } } + } @ViewBuilder @@ -258,70 +307,28 @@ public struct SyncSettingsView: View { } } - @ViewBuilder - func singleDeviceSetUpView() -> some View { - Section { - HStack { - VStack(alignment: .leading, spacing: 4) { - Text(UserText.singleDeviceSetUpTitle) - .daxBodyBold() - Text(UserText.singleDeviceSetUpInstruction) - .daxBodyRegular() - } - Spacer() - Image("Device-Mobile-Upload-96") - - } - if model.isBusy { - SwiftUI.ProgressView() - } else { - Button(UserText.turnSyncOn) { - model.startSyncPressed() - } - } - } - } - - @ViewBuilder - func recoverYourDataView() -> some View { - Section { - Button(UserText.recoverYourData) { - model.showRecoverDataView() - } - } - } - - @ViewBuilder - func footerView() -> some View { - Section {} footer: { - Text(UserText.syncSettingsFooter) - .daxFootnoteRegular() - .foregroundColor(.secondary) - } - } - @ViewBuilder func syncPaused(for itemType: LimitedItemType) -> some View { var explanation: String { switch itemType { case .bookmarks: - return "Bookmark limit exceeded. Delete some to resume syncing." + return UserText.bookmarksLimitExceededDescription case .credentials: - return "Logins limit exceeded. Delete some to resume syncing." + return UserText.credentialsLimitExceededDescription } } var buttonTitle: String { switch itemType { case .bookmarks: - return "Manage Bookmarks" + return UserText.bookmarksLimitExceededAction case .credentials: - return "Manage Logins" + return UserText.credentialsLimitExceededAction } } Section { VStack(alignment: .leading, spacing: 4) { - Text("⚠️ Sync Paused") + Text(UserText.syncLimitExceededTitle) .daxBodyBold() Text(explanation) .daxBodyRegular() @@ -341,7 +348,6 @@ public struct SyncSettingsView: View { case bookmarks case credentials } - } // Extension to apply custom view modifier @@ -368,7 +374,6 @@ public struct OptionsView: View { } } } - } header: { Text(UserText.options) }