From 07176cd3c0d01448d040fee018b2145250e2d833 Mon Sep 17 00:00:00 2001 From: Federico Maccaroni Date: Fri, 10 Oct 2025 14:03:19 -0300 Subject: [PATCH] [PM-14425] [BEEEP] Add test plans (#1106) Co-authored-by: Katherine Bertelsen --- .../Services/TOTP/OTPAuthModelTests.swift | 2 - ...ft => VaultUnlockView+SnapshotTests.swift} | 2 +- .../DebugMenuView+SnapshotTests.swift | 57 ++ ...=> DebugMenuView+ViewInspectorTests.swift} | 17 +- .../Application/AppCoordinatorTests.swift | 39 -- .../Platform/Application/AppModuleTests.swift | 27 - ...ift => StyleGuideFont+SnapshotTests.swift} | 1 + ...=> LoadingOverlayView+SnapshotTests.swift} | 1 + ....swift => SectionView+SnapshotTests.swift} | 1 + .../ExportItemsView+SnapshotTests.swift | 38 ++ ... ExportItemsView+ViewInspectorTests.swift} | 9 +- .../ImportItemsView+SnapshotTests.swift | 38 ++ ... ImportItemsView+ViewInspectorTests.swift} | 9 +- .../SelectLanguageView+SnapshotTests.swift | 43 ++ ...lectLanguageView+ViewInspectorTests.swift} | 12 +- .../Settings/SettingsView+SnapshotTests.swift | 67 +++ ... => SettingsView+ViewInspectorTests.swift} | 30 +- ...swift => TutorialView+SnapshotTests.swift} | 2 +- ...AuthenticatorItemView+SnapshotTests.swift} | 2 +- .../ItemListCardView+SnapshotTests.swift | 27 + ...ItemListCardView+ViewInspectorTests.swift} | 19 +- ...swift => ItemListView+SnapshotTests.swift} | 42 +- .../ItemListView+ViewInspectorTests.swift | 82 +++ ...aptureCoordinator+ViewInspectorTests.swift | 210 ++++++++ ...henticatorKeyCaptureCoordinatorTests.swift | 84 --- .../ManualEntryView+SnapshotTests.swift | 116 +++++ ... ManualEntryView+ViewInspectorTests.swift} | 86 +-- ...swift => ScanCodeView+SnapshotTests.swift} | 12 +- .../ScanCodeView+ViewInspectorTests.swift | 44 ++ .../ActionViewControllerTests.swift | 6 - ...redentialProviderViewControllerTests.swift | 6 - ...ift => StyleGuideFont+SnapshotTests.swift} | 1 + ...swift => ButtonStyles+SnapshotTests.swift} | 1 + ...t => AsyncButton+ViewInspectorTests.swift} | 1 + ...twardenMenuField+ViewInspectorTests.swift} | 1 + ...CircularProgressShape+SnapshotTests.swift} | 1 + ...ettingsMenuField+ViewInspectorTests.swift} | 1 + ...ts.swift => ToastView+SnapshotTests.swift} | 1 + .../ShareViewControllerTests.swift | 6 - ...mpleteRegistrationView+SnapshotTests.swift | 85 +++ ...RegistrationView+ViewInspectorTests.swift} | 51 +- .../ExpiredLinkView+SnapshotTests.swift | 38 ++ ... ExpiredLinkView+ViewInspectorTests.swift} | 8 +- ...rPasswordGeneratorView+SnapshotTests.swift | 50 ++ ...ordGeneratorView+ViewInspectorTests.swift} | 18 +- ...erPasswordGuidanceView+SnapshotTests.swift | 46 ++ ...wordGuidanceView+ViewInspectorTests.swift} | 18 +- ...reventAccountLockView+SnapshotTests.swift} | 12 +- ...ntAccountLockView+ViewInspectorTests.swift | 39 ++ ... => IntroCarouselView+SnapshotTests.swift} | 20 +- ...IntroCarouselView+ViewInspectorTests.swift | 48 ++ .../Landing/LandingView+SnapshotTests.swift | 90 ++++ ...t => LandingView+ViewInspectorTests.swift} | 60 +-- .../SelfHostedView+SnapshotTests.swift | 36 ++ ...> SelfHostedView+ViewInspectorTests.swift} | 9 +- ...nDecryptionOptionsView+SnapshotTests.swift | 52 ++ ...ptionOptionsView+ViewInspectorTests.swift} | 9 +- .../Auth/Login/LoginView+SnapshotTests.swift | 73 +++ ...ift => LoginView+ViewInspectorTests.swift} | 44 +- .../LoginWithDeviceView+SnapshotTests.swift | 42 ++ ...inWithDeviceView+ViewInspectorTests.swift} | 9 +- .../SingleSignOnView+SnapshotTests.swift | 51 ++ ...SingleSignOnView+ViewInspectorTests.swift} | 22 +- ... => TwoFactorAuthView+SnapshotTests.swift} | 67 +-- ...TwoFactorAuthView+ViewInspectorTests.swift | 96 ++++ .../PasswordHintView+SnapshotTests.swift | 46 ++ ...PasswordHintView+ViewInspectorTests.swift} | 18 +- .../ProfileSwitcherHandlerTests.swift | 1 - ...=> ProfileSwitcherRow+SnapshotTests.swift} | 2 +- .../ProfileSwitcherSheet+SnapshotTests.swift | 159 ++++++ ...fileSwitcherSheet+ViewInspectorTests.swift | 193 +++++++ .../ProfileSwitcherSheetTests.swift | 272 +--------- ...leSwitcherToolbarView+SnapshotTests.swift} | 13 +- ...itcherToolbarView+ViewInspectorTests.swift | 59 +++ .../ProfileSwitcherView+SnapshotTests.swift | 165 ++++++ ...ofileSwitcherView+ViewInspectorTests.swift | 189 +++++++ .../ProfileSwitcherViewTests.swift | 280 +--------- ...moveMasterPasswordView+SnapshotTests.swift | 46 ++ ...sterPasswordView+ViewInspectorTests.swift} | 13 +- .../SetMasterPasswordView+SnapshotTests.swift | 66 +++ ...sterPasswordView+ViewInspectorTests.swift} | 39 +- .../CheckEmailView+SnapshotTests.swift | 45 ++ ...> CheckEmailView+ViewInspectorTests.swift} | 16 +- .../StartRegistrationView+SnapshotTests.swift | 73 +++ ...RegistrationView+ViewInspectorTests.swift} | 44 +- ...dateMasterPasswordView+SnapshotTests.swift | 106 ++++ ...sterPasswordView+ViewInspectorTests.swift} | 64 +-- .../MockUserVerificationHelperDelegate.swift | 26 + .../UserVerificationHelperTests.swift | 22 - ...ft => VaultUnlockView+SnapshotTests.swift} | 99 +--- .../VaultUnlockView+ViewInspectorTests.swift | 140 +++++ .../VaultUnlockSetupView+SnapshotTests.swift | 82 +++ ...tUnlockSetupView+ViewInspectorTests.swift} | 54 +- .../Fido2UserVerificationMediatorTests.swift | 14 - ...ido2UserVerificationMediatorDelegate.swift | 17 + ...ft => ActionCard+ViewInspectorTests.swift} | 1 + ...SegmentedControl+ViewInspectorTests.swift} | 1 + ...ft => BitwardenSlider+SnapshotTests.swift} | 1 + ...ardenTabBarController+SnapshotTests.swift} | 1 + ...xpandableContent+ViewInspectorTests.swift} | 1 + .../GuidedTourView+GeneratorTests.swift | 108 ---- ...> GuidedTourView+LoginSnapshotTests.swift} | 38 -- ...> GuidedTourView+ViewInspectorTests.swift} | 1 + ...llustratedMessageView+SnapshotTests.swift} | 25 +- ...tratedMessageView+ViewInspectorTests.swift | 34 ++ ...=> LoadingOverlayView+SnapshotTests.swift} | 1 + ...swordStrengthIndicator+SnapshotTests.swift | 35 ++ .../PasswordStrengthIndicatorTests.swift | 27 - ....swift => SectionView+SnapshotTests.swift} | 1 + .../DebugMenuView+SnapshotTests.swift | 57 ++ ...=> DebugMenuView+ViewInspectorTests.swift} | 16 +- ...tensionActivationView+SnapshotTests.swift} | 11 +- ...ionActivationView+ViewInspectorTests.swift | 46 ++ .../LoginRequestView+SnapshotTests.swift | 49 ++ ...LoginRequestView+ViewInspectorTests.swift} | 16 +- .../About/AboutView+SnapshotTests.swift | 42 ++ ...ift => AboutView+ViewInspectorTests.swift} | 10 +- .../EnableFlightRecorderProcessorTests.swift | 1 - ...ableFlightRecorderView+SnapshotTests.swift | 39 ++ ...ightRecorderView+ViewInspectorTests.swift} | 10 +- .../FlightRecorderLogsProcessorTests.swift | 1 - ...FlightRecorderLogsView+SnapshotTests.swift | 98 ++++ ...RecorderLogsView+ViewInspectorTests.swift} | 64 +-- .../AccountSecurityView+SnapshotTests.swift | 176 +++++++ ...ountSecurityView+ViewInspectorTests.swift} | 148 +----- .../DeleteAccountView+SnapshotTests.swift | 43 ++ ...eleteAccountView+ViewInspectorTests.swift} | 14 +- ...> PendingRequestsView+SnapshotTests.swift} | 20 +- ...ndingRequestsView+ViewInspectorTests.swift | 49 ++ .../AppearanceView+SnapshotTests.swift | 43 ++ ...> AppearanceView+ViewInspectorTests.swift} | 12 +- .../SelectLanguageView+SnapshotTests.swift | 47 ++ ...lectLanguageView+ViewInspectorTests.swift} | 16 +- ...t => AppExtensionView+SnapshotTests.swift} | 11 +- .../AppExtensionView+ViewInspectorTests.swift | 40 ++ .../AutoFill/AutoFillView+SnapshotTests.swift | 70 +++ ... => AutoFillView+ViewInspectorTests.swift} | 40 +- ... PasswordAutoFillView+SnapshotTests.swift} | 17 +- ...swordAutoFillView+ViewInspectorTests.swift | 49 ++ ...therSettingsView+ViewInspectorTests.swift} | 10 +- ...OtherSettingsViewTests+SnapshotTests.swift | 38 ++ .../Settings/SettingsView+SnapshotTests.swift | 61 +++ ... => SettingsView+ViewInspectorTests.swift} | 30 +- .../ExportSettingsView+SnapshotTests.swift | 39 ++ ...portSettingsView+ViewInspectorTests.swift} | 10 +- .../ExportVaultView+SnapshotTests.swift | 67 +++ ... ExportVaultView+ViewInspectorTests.swift} | 38 +- .../AddEditFolderView+SnapshotTests.swift | 62 +++ ...ddEditFolderView+ViewInspectorTests.swift} | 33 +- .../Folders/FoldersView+SnapshotTests.swift | 49 ++ ...t => FoldersView+ViewInspectorTests.swift} | 21 +- .../VaultSettingsView+SnapshotTests.swift | 50 ++ ...aultSettingsView+ViewInspectorTests.swift} | 20 +- .../Settings/SettingsCoordinatorTests.swift | 40 -- .../MockSettingsCoordinatorDelegate.swift | 41 ++ ...wift => ExportCXFView+SnapshotTests.swift} | 20 +- .../ExportCXFView+ViewInspectorTests.swift | 53 ++ .../GeneratorView+SnapshotTests.swift | 173 +++++++ ...=> GeneratorView+ViewInspectorTests.swift} | 125 +---- ...wift => ImportCXFView+SnapshotTests.swift} | 24 +- .../ImportCXFView+ViewInspectorTests.swift | 57 ++ ...sswordHistoryListView+SnapshotTests.swift} | 32 +- ...rdHistoryListView+ViewInspectorTests.swift | 64 +++ .../SendList/SendListView+SnapshotTests.swift | 121 +++++ ... => SendListView+ViewInspectorTests.swift} | 93 +--- .../AddEditSendItemView+SnapshotTests.swift | 183 +++++++ ...EditSendItemView+ViewInspectorTests.swift} | 162 +----- ...t => ViewSendItemView+SnapshotTests.swift} | 29 +- .../ViewSendItemView+ViewInspectorTests.swift | 57 ++ .../ImportLoginsView+SnapshotTests.swift | 72 +++ ...ImportLoginsView+ViewInspectorTests.swift} | 46 +- ...mportLoginsSuccessView+SnapshotTests.swift | 41 ++ ...oginsSuccessView+ViewInspectorTests.swift} | 15 +- ...VaultAutofillListView+SnapshotTests.swift} | 32 +- ...tAutofillListView+ViewInspectorTests.swift | 65 +++ .../MockVaultCoordinatorDelegate.swift | 51 ++ .../Vault/Vault/VaultCoordinatorTests.swift | 50 -- .../VaultGroup/VaultGroupStateTests.swift | 2 - ...ift => VaultGroupView+SnapshotTests.swift} | 115 +--- .../VaultGroupView+ViewInspectorTests.swift | 152 ++++++ ...aultItemSelectionView+SnapshotTests.swift} | 29 +- ...ItemSelectionView+ViewInspectorTests.swift | 62 +++ ...ultFilterRowView+ViewInspectorTests.swift} | 2 +- .../VaultListView+SnapshotTests.swift | 205 ++++++++ ...=> VaultListView+ViewInspectorTests.swift} | 159 +----- ...> AddEditCardItemView+SnapshotTests.swift} | 1 + ...ddEditCustomFieldsView+SnapshotTests.swift | 54 ++ ...CustomFieldsView+ViewInspectorTests.swift} | 17 +- .../AddEditItemView+SnapshotTests.swift | 489 ++++++++++++++++++ ... AddEditItemView+ViewInspectorTests.swift} | 430 +-------------- ... AddEditLoginItemView+SnapshotTests.swift} | 1 + .../AttachmentsView+SnapshotTests.swift | 85 +++ ... AttachmentsView+ViewInspectorTests.swift} | 47 +- ...aptureCoordinator+ViewInspectorTests.swift | 181 +++++++ ...henticatorKeyCaptureCoordinatorTests.swift | 84 --- .../ManualEntryView+SnapshotTests.swift | 58 +++ ... ManualEntryView+ViewInspectorTests.swift} | 30 +- ...swift => ScanCodeView+SnapshotTests.swift} | 12 +- .../ScanCodeView+ViewInspectorTests.swift | 44 ++ .../EditCollectionsView+SnapshotTests.swift | 46 ++ ...tCollectionsView+ViewInspectorTests.swift} | 17 +- ...MoveToOrganizationView+SnapshotTests.swift | 56 ++ ...OrganizationView+ViewInspectorTests.swift} | 29 +- .../VaultItem/VaultItemCoordinatorTests.swift | 1 - ...nagementMenuView+ViewInspectorTests.swift} | 2 +- ...t => ViewCardItemView+SnapshotTests.swift} | 1 + .../ViewItem/ViewItemView+SnapshotTests.swift | 428 +++++++++++++++ ... => ViewItemView+ViewInspectorTests.swift} | 219 +------- ...ewSSHKeyItemView+ViewInspectorTests.swift} | 2 +- ...emDecorativeImageView+SnapshotTests.swift} | 1 + ... VaultListItemRowView+SnapshotTests.swift} | 28 +- ...ltListItemRowView+ViewInspectorTests.swift | 61 +++ .../Support/BaseBitwardenTestCase.swift | 4 +- TestPlans/Authenticator-Default.xctestplan | 59 +++ TestPlans/Authenticator-Snapshot.xctestplan | 37 ++ TestPlans/Authenticator-Unit.xctestplan | 48 ++ .../Authenticator-ViewInspector.xctestplan | 37 ++ TestPlans/Bitwarden-Default.xctestplan | 94 ++++ TestPlans/Bitwarden-Snapshot.xctestplan | 37 ++ TestPlans/Bitwarden-Unit.xctestplan | 69 +++ TestPlans/Bitwarden-ViewInspector.xctestplan | 37 ++ TestPlans/BitwardenKit-Default.xctestplan | 66 +++ TestPlans/BitwardenKit-Snapshot.xctestplan | 37 ++ TestPlans/BitwardenKit-Unit.xctestplan | 48 ++ .../BitwardenKit-ViewInspector.xctestplan | 37 ++ project-bwa.yml | 77 +++ project-bwk.yml | 47 ++ project-pm.yml | 111 +++- 228 files changed, 8022 insertions(+), 4277 deletions(-) rename AuthenticatorShared/UI/Auth/VaultUnlock/{VaultUnlockViewTests.swift => VaultUnlockView+SnapshotTests.swift} (97%) create mode 100644 AuthenticatorShared/UI/DebugMenu/DebugMenuView+SnapshotTests.swift rename AuthenticatorShared/UI/DebugMenu/{DebugMenuViewTests.swift => DebugMenuView+ViewInspectorTests.swift} (82%) delete mode 100644 AuthenticatorShared/UI/Platform/Application/AppCoordinatorTests.swift delete mode 100644 AuthenticatorShared/UI/Platform/Application/AppModuleTests.swift rename AuthenticatorShared/UI/Platform/Application/Appearance/{StyleGuideFontTests.swift => StyleGuideFont+SnapshotTests.swift} (95%) rename AuthenticatorShared/UI/Platform/Application/Views/LoadingOverlay/{LoadingOverlayViewTests.swift => LoadingOverlayView+SnapshotTests.swift} (92%) rename AuthenticatorShared/UI/Platform/Application/Views/{SectionViewTests.swift => SectionView+SnapshotTests.swift} (92%) create mode 100644 AuthenticatorShared/UI/Platform/Settings/Settings/ExportItems/ExportItemsView+SnapshotTests.swift rename AuthenticatorShared/UI/Platform/Settings/Settings/ExportItems/{ExportItemsViewTests.swift => ExportItemsView+ViewInspectorTests.swift} (87%) create mode 100644 AuthenticatorShared/UI/Platform/Settings/Settings/ImportItems/ImportItemsView+SnapshotTests.swift rename AuthenticatorShared/UI/Platform/Settings/Settings/ImportItems/{ImportItemsViewTests.swift => ImportItemsView+ViewInspectorTests.swift} (88%) create mode 100644 AuthenticatorShared/UI/Platform/Settings/Settings/SelectLanguage/SelectLanguageView+SnapshotTests.swift rename AuthenticatorShared/UI/Platform/Settings/Settings/SelectLanguage/{SelectLanguageViewTests.swift => SelectLanguageView+ViewInspectorTests.swift} (82%) create mode 100644 AuthenticatorShared/UI/Platform/Settings/Settings/SettingsView+SnapshotTests.swift rename AuthenticatorShared/UI/Platform/Settings/Settings/{SettingsViewTests.swift => SettingsView+ViewInspectorTests.swift} (83%) rename AuthenticatorShared/UI/Platform/Tutorial/Tutorial/{TutorialViewTests.swift => TutorialView+SnapshotTests.swift} (97%) rename AuthenticatorShared/UI/Vault/AuthenticatorItem/EditAuthenticatorItem/{EditAuthenticatorItemViewTests.swift => EditAuthenticatorItemView+SnapshotTests.swift} (97%) create mode 100644 AuthenticatorShared/UI/Vault/ItemList/ItemList/ItemListCardView+SnapshotTests.swift rename AuthenticatorShared/UI/Vault/ItemList/ItemList/{ItemListCardViewTests.swift => ItemListCardView+ViewInspectorTests.swift} (64%) rename AuthenticatorShared/UI/Vault/ItemList/ItemList/{ItemListViewTests.swift => ItemListView+SnapshotTests.swift} (72%) create mode 100644 AuthenticatorShared/UI/Vault/ItemList/ItemList/ItemListView+ViewInspectorTests.swift create mode 100644 AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/AuthenticatorKeyCaptureCoordinator+ViewInspectorTests.swift create mode 100644 AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ManualEntryView+SnapshotTests.swift rename AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/{ManualEntryViewTests.swift => ManualEntryView+ViewInspectorTests.swift} (61%) rename AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/{ScanCodeViewTests.swift => ScanCodeView+SnapshotTests.swift} (78%) create mode 100644 AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ScanCodeView+ViewInspectorTests.swift delete mode 100644 BitwardenActionExtension/ActionViewControllerTests.swift delete mode 100644 BitwardenAutoFillExtension/CredentialProviderViewControllerTests.swift rename BitwardenKit/UI/Platform/Application/Appearance/{StyleGuideFontTests.swift => StyleGuideFont+SnapshotTests.swift} (95%) rename BitwardenKit/UI/Platform/Application/Appearance/Styles/{ButtonStylesTests.swift => ButtonStyles+SnapshotTests.swift} (98%) rename BitwardenKit/UI/Platform/Application/Views/{AsyncButtonTests.swift => AsyncButton+ViewInspectorTests.swift} (92%) rename BitwardenKit/UI/Platform/Application/Views/{BitwardenMenuFieldTests.swift => BitwardenMenuField+ViewInspectorTests.swift} (97%) rename BitwardenKit/UI/Platform/Application/Views/{CircularProgressShapeTests.swift => CircularProgressShape+SnapshotTests.swift} (97%) rename BitwardenKit/UI/Platform/Application/Views/{SettingsMenuFieldTests.swift => SettingsMenuField+ViewInspectorTests.swift} (97%) rename BitwardenKit/UI/Platform/Application/Views/{ToastViewTests.swift => ToastView+SnapshotTests.swift} (94%) delete mode 100644 BitwardenShareExtension/ShareViewControllerTests.swift create mode 100644 BitwardenShared/UI/Auth/CompleteRegistration/CompleteRegistrationView+SnapshotTests.swift rename BitwardenShared/UI/Auth/CompleteRegistration/{CompleteRegistrationViewTests.swift => CompleteRegistrationView+ViewInspectorTests.swift} (73%) create mode 100644 BitwardenShared/UI/Auth/CompleteRegistration/ExpiredLink/ExpiredLinkView+SnapshotTests.swift rename BitwardenShared/UI/Auth/CompleteRegistration/ExpiredLink/{ExpiredLinkViewTests.swift => ExpiredLinkView+ViewInspectorTests.swift} (87%) create mode 100644 BitwardenShared/UI/Auth/CompleteRegistration/MasterPasswordGenerator/MasterPasswordGeneratorView+SnapshotTests.swift rename BitwardenShared/UI/Auth/CompleteRegistration/MasterPasswordGenerator/{MasterPasswordGeneratorViewTests.swift => MasterPasswordGeneratorView+ViewInspectorTests.swift} (82%) create mode 100644 BitwardenShared/UI/Auth/CompleteRegistration/MasterPasswordGuidance/MasterPasswordGuidanceView+SnapshotTests.swift rename BitwardenShared/UI/Auth/CompleteRegistration/MasterPasswordGuidance/{MasterPasswordGuidanceViewTests.swift => MasterPasswordGuidanceView+ViewInspectorTests.swift} (74%) rename BitwardenShared/UI/Auth/CompleteRegistration/PreventAccountLock/{PreventAccountLockViewTests.swift => PreventAccountLockView+SnapshotTests.swift} (74%) create mode 100644 BitwardenShared/UI/Auth/CompleteRegistration/PreventAccountLock/PreventAccountLockView+ViewInspectorTests.swift rename BitwardenShared/UI/Auth/IntroCarousel/{IntroCarouselViewTests.swift => IntroCarouselView+SnapshotTests.swift} (75%) create mode 100644 BitwardenShared/UI/Auth/IntroCarousel/IntroCarouselView+ViewInspectorTests.swift create mode 100644 BitwardenShared/UI/Auth/Landing/LandingView+SnapshotTests.swift rename BitwardenShared/UI/Auth/Landing/{LandingViewTests.swift => LandingView+ViewInspectorTests.swift} (64%) create mode 100644 BitwardenShared/UI/Auth/Landing/SelfHosted/SelfHostedView+SnapshotTests.swift rename BitwardenShared/UI/Auth/Landing/SelfHosted/{SelfHostedViewTests.swift => SelfHostedView+ViewInspectorTests.swift} (86%) create mode 100644 BitwardenShared/UI/Auth/Login/LoginDecryptionOptions/LoginDecryptionOptionsView+SnapshotTests.swift rename BitwardenShared/UI/Auth/Login/LoginDecryptionOptions/{LoginDecryptionOptionsViewTests.swift => LoginDecryptionOptionsView+ViewInspectorTests.swift} (93%) create mode 100644 BitwardenShared/UI/Auth/Login/LoginView+SnapshotTests.swift rename BitwardenShared/UI/Auth/Login/{LoginViewTests.swift => LoginView+ViewInspectorTests.swift} (75%) create mode 100644 BitwardenShared/UI/Auth/Login/LoginWithDevice/LoginWithDeviceView+SnapshotTests.swift rename BitwardenShared/UI/Auth/Login/LoginWithDevice/{LoginWithDeviceViewTests.swift => LoginWithDeviceView+ViewInspectorTests.swift} (88%) create mode 100644 BitwardenShared/UI/Auth/Login/SingleSignOn/SingleSignOnView+SnapshotTests.swift rename BitwardenShared/UI/Auth/Login/SingleSignOn/{SingleSignOnViewTests.swift => SingleSignOnView+ViewInspectorTests.swift} (70%) rename BitwardenShared/UI/Auth/Login/TwoFactorAuth/{TwoFactorAuthViewTests.swift => TwoFactorAuthView+SnapshotTests.swift} (56%) create mode 100644 BitwardenShared/UI/Auth/Login/TwoFactorAuth/TwoFactorAuthView+ViewInspectorTests.swift create mode 100644 BitwardenShared/UI/Auth/PasswordHint/PasswordHintView+SnapshotTests.swift rename BitwardenShared/UI/Auth/PasswordHint/{PasswordHintViewTests.swift => PasswordHintView+ViewInspectorTests.swift} (74%) rename BitwardenShared/UI/Auth/ProfileSwitcher/{ProfileSwitcherRowTests.swift => ProfileSwitcherRow+SnapshotTests.swift} (98%) create mode 100644 BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherSheet+SnapshotTests.swift create mode 100644 BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherSheet+ViewInspectorTests.swift rename BitwardenShared/UI/Auth/ProfileSwitcher/{ProfileSwitcherToolbarViewTests.swift => ProfileSwitcherToolbarView+SnapshotTests.swift} (93%) create mode 100644 BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherToolbarView+ViewInspectorTests.swift create mode 100644 BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherView+SnapshotTests.swift create mode 100644 BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherView+ViewInspectorTests.swift create mode 100644 BitwardenShared/UI/Auth/RemoveMasterPassword/RemoveMasterPasswordView+SnapshotTests.swift rename BitwardenShared/UI/Auth/RemoveMasterPassword/{RemoveMasterPasswordViewTests.swift => RemoveMasterPasswordView+ViewInspectorTests.swift} (77%) create mode 100644 BitwardenShared/UI/Auth/SetMasterPassword/SetMasterPasswordView+SnapshotTests.swift rename BitwardenShared/UI/Auth/SetMasterPassword/{SetMasterPasswordViewTests.swift => SetMasterPasswordView+ViewInspectorTests.swift} (75%) create mode 100644 BitwardenShared/UI/Auth/StartRegistration/CheckEmail/CheckEmailView+SnapshotTests.swift rename BitwardenShared/UI/Auth/StartRegistration/CheckEmail/{CheckEmailViewTests.swift => CheckEmailView+ViewInspectorTests.swift} (79%) create mode 100644 BitwardenShared/UI/Auth/StartRegistration/StartRegistrationView+SnapshotTests.swift rename BitwardenShared/UI/Auth/StartRegistration/{StartRegistrationViewTests.swift => StartRegistrationView+ViewInspectorTests.swift} (65%) create mode 100644 BitwardenShared/UI/Auth/UpdateMasterPassword/UpdateMasterPasswordView+SnapshotTests.swift rename BitwardenShared/UI/Auth/UpdateMasterPassword/{UpdateMasterPasswordViewTests.swift => UpdateMasterPasswordView+ViewInspectorTests.swift} (73%) create mode 100644 BitwardenShared/UI/Auth/Utilities/TestHelpers/MockUserVerificationHelperDelegate.swift rename BitwardenShared/UI/Auth/VaultUnlock/{VaultUnlockViewTests.swift => VaultUnlockView+SnapshotTests.swift} (58%) create mode 100644 BitwardenShared/UI/Auth/VaultUnlock/VaultUnlockView+ViewInspectorTests.swift create mode 100644 BitwardenShared/UI/Auth/VaultUnlockSetup/VaultUnlockSetupView+SnapshotTests.swift rename BitwardenShared/UI/Auth/VaultUnlockSetup/{VaultUnlockSetupViewTests.swift => VaultUnlockSetupView+ViewInspectorTests.swift} (58%) create mode 100644 BitwardenShared/UI/Autofill/Utilities/TestHelpers/MockFido2UserVerificationMediatorDelegate.swift rename BitwardenShared/UI/Platform/Application/Views/{ActionCardTests.swift => ActionCard+ViewInspectorTests.swift} (97%) rename BitwardenShared/UI/Platform/Application/Views/{BitwardenSegmentedControlTests.swift => BitwardenSegmentedControl+ViewInspectorTests.swift} (98%) rename BitwardenShared/UI/Platform/Application/Views/{BitwardenSliderTests.swift => BitwardenSlider+SnapshotTests.swift} (97%) rename BitwardenShared/UI/Platform/Application/Views/{BitwardenTabBarControllerTests.swift => BitwardenTabBarController+SnapshotTests.swift} (99%) rename BitwardenShared/UI/Platform/Application/Views/{ExpandableContentTests.swift => ExpandableContent+ViewInspectorTests.swift} (96%) delete mode 100644 BitwardenShared/UI/Platform/Application/Views/GuidedTourView/GuidedTourView+GeneratorTests.swift rename BitwardenShared/UI/Platform/Application/Views/GuidedTourView/{GuidedTourView+LoginTests.swift => GuidedTourView+LoginSnapshotTests.swift} (70%) rename BitwardenShared/UI/Platform/Application/Views/GuidedTourView/{GuidedTourViewTests.swift => GuidedTourView+ViewInspectorTests.swift} (98%) rename BitwardenShared/UI/Platform/Application/Views/{IllustratedMessageViewTests.swift => IllustratedMessageView+SnapshotTests.swift} (75%) create mode 100644 BitwardenShared/UI/Platform/Application/Views/IllustratedMessageView+ViewInspectorTests.swift rename BitwardenShared/UI/Platform/Application/Views/{LoadingOverlayViewTests.swift => LoadingOverlayView+SnapshotTests.swift} (92%) create mode 100644 BitwardenShared/UI/Platform/Application/Views/PasswordStrengthIndicator+SnapshotTests.swift rename BitwardenShared/UI/Platform/Application/Views/{SectionViewTests.swift => SectionView+SnapshotTests.swift} (92%) create mode 100644 BitwardenShared/UI/Platform/DebugMenu/DebugMenuView+SnapshotTests.swift rename BitwardenShared/UI/Platform/DebugMenu/{DebugMenuViewTests.swift => DebugMenuView+ViewInspectorTests.swift} (86%) rename BitwardenShared/UI/Platform/ExtensionSetup/ExtensionActivation/{ExtensionActivationViewTests.swift => ExtensionActivationView+SnapshotTests.swift} (80%) create mode 100644 BitwardenShared/UI/Platform/ExtensionSetup/ExtensionActivation/ExtensionActivationView+ViewInspectorTests.swift create mode 100644 BitwardenShared/UI/Platform/LoginRequest/LoginRequestView+SnapshotTests.swift rename BitwardenShared/UI/Platform/LoginRequest/{LoginRequestViewTests.swift => LoginRequestView+ViewInspectorTests.swift} (82%) create mode 100644 BitwardenShared/UI/Platform/Settings/Settings/About/AboutView+SnapshotTests.swift rename BitwardenShared/UI/Platform/Settings/Settings/About/{AboutViewTests.swift => AboutView+ViewInspectorTests.swift} (93%) create mode 100644 BitwardenShared/UI/Platform/Settings/Settings/About/EnableFlightRecorder/EnableFlightRecorderView+SnapshotTests.swift rename BitwardenShared/UI/Platform/Settings/Settings/About/EnableFlightRecorder/{EnableFlightRecorderViewTests.swift => EnableFlightRecorderView+ViewInspectorTests.swift} (87%) create mode 100644 BitwardenShared/UI/Platform/Settings/Settings/About/FlightRecorderLogs/FlightRecorderLogsView+SnapshotTests.swift rename BitwardenShared/UI/Platform/Settings/Settings/About/FlightRecorderLogs/{FlightRecorderLogsViewTests.swift => FlightRecorderLogsView+ViewInspectorTests.swift} (62%) create mode 100644 BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/AccountSecurityView+SnapshotTests.swift rename BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/{AccountSecurityViewTests.swift => AccountSecurityView+ViewInspectorTests.swift} (62%) create mode 100644 BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/DeleteAccount/DeleteAccountView+SnapshotTests.swift rename BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/DeleteAccount/{DeleteAccountViewTests.swift => DeleteAccountView+ViewInspectorTests.swift} (72%) rename BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/PendingRequests/{PendingRequestsViewTests.swift => PendingRequestsView+SnapshotTests.swift} (65%) create mode 100644 BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/PendingRequests/PendingRequestsView+ViewInspectorTests.swift create mode 100644 BitwardenShared/UI/Platform/Settings/Settings/Appearance/AppearanceView+SnapshotTests.swift rename BitwardenShared/UI/Platform/Settings/Settings/Appearance/{AppearanceViewTests.swift => AppearanceView+ViewInspectorTests.swift} (83%) create mode 100644 BitwardenShared/UI/Platform/Settings/Settings/Appearance/SelectLanguage/SelectLanguageView+SnapshotTests.swift rename BitwardenShared/UI/Platform/Settings/Settings/Appearance/SelectLanguage/{SelectLanguageViewTests.swift => SelectLanguageView+ViewInspectorTests.swift} (78%) rename BitwardenShared/UI/Platform/Settings/Settings/AutoFill/AppExtension/{AppExtensionViewTests.swift => AppExtensionView+SnapshotTests.swift} (82%) create mode 100644 BitwardenShared/UI/Platform/Settings/Settings/AutoFill/AppExtension/AppExtensionView+ViewInspectorTests.swift create mode 100644 BitwardenShared/UI/Platform/Settings/Settings/AutoFill/AutoFillView+SnapshotTests.swift rename BitwardenShared/UI/Platform/Settings/Settings/AutoFill/{AutoFillViewTests.swift => AutoFillView+ViewInspectorTests.swift} (75%) rename BitwardenShared/UI/Platform/Settings/Settings/AutoFill/PasswordAutoFill/{PasswordAutoFillViewTests.swift => PasswordAutoFillView+SnapshotTests.swift} (73%) create mode 100644 BitwardenShared/UI/Platform/Settings/Settings/AutoFill/PasswordAutoFill/PasswordAutoFillView+ViewInspectorTests.swift rename BitwardenShared/UI/Platform/Settings/Settings/Other/{OtherSettingsViewTests.swift => OtherSettingsView+ViewInspectorTests.swift} (80%) create mode 100644 BitwardenShared/UI/Platform/Settings/Settings/Other/OtherSettingsViewTests+SnapshotTests.swift create mode 100644 BitwardenShared/UI/Platform/Settings/Settings/SettingsView+SnapshotTests.swift rename BitwardenShared/UI/Platform/Settings/Settings/{SettingsViewTests.swift => SettingsView+ViewInspectorTests.swift} (75%) create mode 100644 BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportSettings/ExportSettingsView+SnapshotTests.swift rename BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportSettings/{ExportSettingsViewTests.swift => ExportSettingsView+ViewInspectorTests.swift} (84%) create mode 100644 BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportVaultToFile/ExportVaultView+SnapshotTests.swift rename BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportVaultToFile/{ExportVaultViewTests.swift => ExportVaultView+ViewInspectorTests.swift} (78%) create mode 100644 BitwardenShared/UI/Platform/Settings/Settings/Vault/Folders/AddEditFolder/AddEditFolder/AddEditFolderView+SnapshotTests.swift rename BitwardenShared/UI/Platform/Settings/Settings/Vault/Folders/AddEditFolder/AddEditFolder/{AddEditFolderViewTests.swift => AddEditFolderView+ViewInspectorTests.swift} (74%) create mode 100644 BitwardenShared/UI/Platform/Settings/Settings/Vault/Folders/FoldersView+SnapshotTests.swift rename BitwardenShared/UI/Platform/Settings/Settings/Vault/Folders/{FoldersViewTests.swift => FoldersView+ViewInspectorTests.swift} (70%) create mode 100644 BitwardenShared/UI/Platform/Settings/Settings/Vault/VaultSettingsView+SnapshotTests.swift rename BitwardenShared/UI/Platform/Settings/Settings/Vault/{VaultSettingsViewTests.swift => VaultSettingsView+ViewInspectorTests.swift} (85%) create mode 100644 BitwardenShared/UI/Platform/Settings/TestHelpers/MockSettingsCoordinatorDelegate.swift rename BitwardenShared/UI/Tools/ExportCXF/ExportCXF/{ExportCXFViewTests.swift => ExportCXFView+SnapshotTests.swift} (72%) create mode 100644 BitwardenShared/UI/Tools/ExportCXF/ExportCXF/ExportCXFView+ViewInspectorTests.swift create mode 100644 BitwardenShared/UI/Tools/Generator/Generator/GeneratorView+SnapshotTests.swift rename BitwardenShared/UI/Tools/Generator/Generator/{GeneratorViewTests.swift => GeneratorView+ViewInspectorTests.swift} (67%) rename BitwardenShared/UI/Tools/ImportCXF/ImportCXF/{ImportCXFViewTests.swift => ImportCXFView+SnapshotTests.swift} (73%) create mode 100644 BitwardenShared/UI/Tools/ImportCXF/ImportCXF/ImportCXFView+ViewInspectorTests.swift rename BitwardenShared/UI/Tools/PasswordHistory/PasswordHistoryList/{PasswordHistoryListViewTests.swift => PasswordHistoryListView+SnapshotTests.swift} (61%) create mode 100644 BitwardenShared/UI/Tools/PasswordHistory/PasswordHistoryList/PasswordHistoryListView+ViewInspectorTests.swift create mode 100644 BitwardenShared/UI/Tools/Send/Send/SendList/SendListView+SnapshotTests.swift rename BitwardenShared/UI/Tools/Send/Send/SendList/{SendListViewTests.swift => SendListView+ViewInspectorTests.swift} (59%) create mode 100644 BitwardenShared/UI/Tools/Send/SendItem/AddEditSendItem/AddEditSendItemView+SnapshotTests.swift rename BitwardenShared/UI/Tools/Send/SendItem/AddEditSendItem/{AddEditSendItemViewTests.swift => AddEditSendItemView+ViewInspectorTests.swift} (52%) rename BitwardenShared/UI/Tools/Send/SendItem/ViewSendItem/{ViewSendItemViewTests.swift => ViewSendItemView+SnapshotTests.swift} (73%) create mode 100644 BitwardenShared/UI/Tools/Send/SendItem/ViewSendItem/ViewSendItemView+ViewInspectorTests.swift create mode 100644 BitwardenShared/UI/Vault/ImportLogins/ImportLogins/ImportLoginsView+SnapshotTests.swift rename BitwardenShared/UI/Vault/ImportLogins/ImportLogins/{ImportLoginsViewTests.swift => ImportLoginsView+ViewInspectorTests.swift} (62%) create mode 100644 BitwardenShared/UI/Vault/ImportLogins/ImportLoginsSuccess/ImportLoginsSuccessView+SnapshotTests.swift rename BitwardenShared/UI/Vault/ImportLogins/ImportLoginsSuccess/{ImportLoginsSuccessViewTests.swift => ImportLoginsSuccessView+ViewInspectorTests.swift} (73%) rename BitwardenShared/UI/Vault/Vault/AutofillList/{VaultAutofillListViewTests.swift => VaultAutofillListView+SnapshotTests.swift} (93%) create mode 100644 BitwardenShared/UI/Vault/Vault/AutofillList/VaultAutofillListView+ViewInspectorTests.swift create mode 100644 BitwardenShared/UI/Vault/Vault/TestHelpers/MockVaultCoordinatorDelegate.swift rename BitwardenShared/UI/Vault/Vault/VaultGroup/{VaultGroupViewTests.swift => VaultGroupView+SnapshotTests.swift} (59%) create mode 100644 BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupView+ViewInspectorTests.swift rename BitwardenShared/UI/Vault/Vault/VaultItemSelection/{VaultItemSelectionViewTests.swift => VaultItemSelectionView+SnapshotTests.swift} (81%) create mode 100644 BitwardenShared/UI/Vault/Vault/VaultItemSelection/VaultItemSelectionView+ViewInspectorTests.swift rename BitwardenShared/UI/Vault/Vault/VaultList/SearchVaultFilterRowView/{SearchVaultFilterRowViewTests.swift => SearchVaultFilterRowView+ViewInspectorTests.swift} (97%) create mode 100644 BitwardenShared/UI/Vault/Vault/VaultList/VaultListView+SnapshotTests.swift rename BitwardenShared/UI/Vault/Vault/VaultList/{VaultListViewTests.swift => VaultListView+ViewInspectorTests.swift} (69%) rename BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditCardItem/{AddEditCardItemViewTests.swift => AddEditCardItemView+SnapshotTests.swift} (94%) create mode 100644 BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditCustomFields/AddEditCustomFieldsView+SnapshotTests.swift rename BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditCustomFields/{AddEditCustomFieldsViewTests.swift => AddEditCustomFieldsView+ViewInspectorTests.swift} (84%) create mode 100644 BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditItemView+SnapshotTests.swift rename BitwardenShared/UI/Vault/VaultItem/AddEditItem/{AddEditItemViewTests.swift => AddEditItemView+ViewInspectorTests.swift} (60%) rename BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditLoginItem/{AddEditLoginItemViewTests.swift => AddEditLoginItemView+SnapshotTests.swift} (94%) create mode 100644 BitwardenShared/UI/Vault/VaultItem/Attachments/AttachmentsView+SnapshotTests.swift rename BitwardenShared/UI/Vault/VaultItem/Attachments/{AttachmentsViewTests.swift => AttachmentsView+ViewInspectorTests.swift} (66%) create mode 100644 BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/AuthenticatorKeyCaptureCoordinator+ViewInspectorTests.swift create mode 100644 BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ManualEntryView+SnapshotTests.swift rename BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/{ManualEntryViewTests.swift => ManualEntryView+ViewInspectorTests.swift} (75%) rename BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/{ScanCodeViewTests.swift => ScanCodeView+SnapshotTests.swift} (77%) create mode 100644 BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ScanCodeView+ViewInspectorTests.swift create mode 100644 BitwardenShared/UI/Vault/VaultItem/EditCollections/EditCollectionsView+SnapshotTests.swift rename BitwardenShared/UI/Vault/VaultItem/EditCollections/{EditCollectionsViewTests.swift => EditCollectionsView+ViewInspectorTests.swift} (74%) create mode 100644 BitwardenShared/UI/Vault/VaultItem/MoveToOrganization/MoveToOrganizationView+SnapshotTests.swift rename BitwardenShared/UI/Vault/VaultItem/MoveToOrganization/{MoveToOrganizationViewTests.swift => MoveToOrganizationView+ViewInspectorTests.swift} (65%) rename BitwardenShared/UI/Vault/VaultItem/VaultItemManagementMenu/{VaultItemManagementMenuViewTests.swift => VaultItemManagementMenuView+ViewInspectorTests.swift} (98%) rename BitwardenShared/UI/Vault/VaultItem/ViewItem/ViewCardItem/{ViewCardItemViewTests.swift => ViewCardItemView+SnapshotTests.swift} (98%) create mode 100644 BitwardenShared/UI/Vault/VaultItem/ViewItem/ViewItemView+SnapshotTests.swift rename BitwardenShared/UI/Vault/VaultItem/ViewItem/{ViewItemViewTests.swift => ViewItemView+ViewInspectorTests.swift} (73%) rename BitwardenShared/UI/Vault/VaultItem/ViewItem/ViewSSHKeyItemView/{ViewSSHKeyItemViewTests.swift => ViewSSHKeyItemView+ViewInspectorTests.swift} (99%) rename BitwardenShared/UI/Vault/Views/{VaultItemDecorativeImageViewTests.swift => VaultItemDecorativeImageView+SnapshotTests.swift} (97%) rename BitwardenShared/UI/Vault/Views/VaultListItemRow/{VaultListItemRowViewTests.swift => VaultListItemRowView+SnapshotTests.swift} (84%) create mode 100644 BitwardenShared/UI/Vault/Views/VaultListItemRow/VaultListItemRowView+ViewInspectorTests.swift create mode 100644 TestPlans/Authenticator-Default.xctestplan create mode 100644 TestPlans/Authenticator-Snapshot.xctestplan create mode 100644 TestPlans/Authenticator-Unit.xctestplan create mode 100644 TestPlans/Authenticator-ViewInspector.xctestplan create mode 100644 TestPlans/Bitwarden-Default.xctestplan create mode 100644 TestPlans/Bitwarden-Snapshot.xctestplan create mode 100644 TestPlans/Bitwarden-Unit.xctestplan create mode 100644 TestPlans/Bitwarden-ViewInspector.xctestplan create mode 100644 TestPlans/BitwardenKit-Default.xctestplan create mode 100644 TestPlans/BitwardenKit-Snapshot.xctestplan create mode 100644 TestPlans/BitwardenKit-Unit.xctestplan create mode 100644 TestPlans/BitwardenKit-ViewInspector.xctestplan diff --git a/AuthenticatorShared/Core/Vault/Services/TOTP/OTPAuthModelTests.swift b/AuthenticatorShared/Core/Vault/Services/TOTP/OTPAuthModelTests.swift index deeb036f8..c8a9db668 100644 --- a/AuthenticatorShared/Core/Vault/Services/TOTP/OTPAuthModelTests.swift +++ b/AuthenticatorShared/Core/Vault/Services/TOTP/OTPAuthModelTests.swift @@ -5,8 +5,6 @@ import XCTest // MARK: - OTPAuthModelTests class OTPAuthModelTests: BitwardenTestCase { - // MARK: Tests - // MARK: Init Success /// `init` parses an account if there is no issuer diff --git a/AuthenticatorShared/UI/Auth/VaultUnlock/VaultUnlockViewTests.swift b/AuthenticatorShared/UI/Auth/VaultUnlock/VaultUnlockView+SnapshotTests.swift similarity index 97% rename from AuthenticatorShared/UI/Auth/VaultUnlock/VaultUnlockViewTests.swift rename to AuthenticatorShared/UI/Auth/VaultUnlock/VaultUnlockView+SnapshotTests.swift index 4adb0c216..e178af8b6 100644 --- a/AuthenticatorShared/UI/Auth/VaultUnlock/VaultUnlockViewTests.swift +++ b/AuthenticatorShared/UI/Auth/VaultUnlock/VaultUnlockView+SnapshotTests.swift @@ -1,6 +1,6 @@ +// swiftlint:disable:this file_name import SnapshotTesting import SwiftUI -import ViewInspector import XCTest @testable import AuthenticatorShared diff --git a/AuthenticatorShared/UI/DebugMenu/DebugMenuView+SnapshotTests.swift b/AuthenticatorShared/UI/DebugMenu/DebugMenuView+SnapshotTests.swift new file mode 100644 index 000000000..91cff0873 --- /dev/null +++ b/AuthenticatorShared/UI/DebugMenu/DebugMenuView+SnapshotTests.swift @@ -0,0 +1,57 @@ +// swiftlint:disable:this file_name +import BitwardenKit +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import AuthenticatorShared + +// MARK: - DebugMenuViewTests + +class DebugMenuViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: DebugMenuView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor( + state: DebugMenuState( + featureFlags: [ + .init( + feature: .testFeatureFlag, + isEnabled: false, + ), + ], + ), + ) + let store = Store(processor: processor) + + subject = DebugMenuView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Tests + + /// Check the snapshot when feature flags are enabled and disabled. + @MainActor + func disabletest_snapshot_debugMenuWithFeatureFlags() { + processor.state.featureFlags = [ + .init( + feature: .testFeatureFlag, + isEnabled: true, + ), + ] + assertSnapshot(of: subject, as: .defaultPortrait) + } +} diff --git a/AuthenticatorShared/UI/DebugMenu/DebugMenuViewTests.swift b/AuthenticatorShared/UI/DebugMenu/DebugMenuView+ViewInspectorTests.swift similarity index 82% rename from AuthenticatorShared/UI/DebugMenu/DebugMenuViewTests.swift rename to AuthenticatorShared/UI/DebugMenu/DebugMenuView+ViewInspectorTests.swift index 09e481ddb..48cfaee3f 100644 --- a/AuthenticatorShared/UI/DebugMenu/DebugMenuViewTests.swift +++ b/AuthenticatorShared/UI/DebugMenu/DebugMenuView+ViewInspectorTests.swift @@ -1,6 +1,7 @@ +// swiftlint:disable:this file_name import BitwardenKit import BitwardenResources -import SnapshotTesting +import ViewInspector import XCTest @testable import AuthenticatorShared @@ -64,21 +65,9 @@ class DebugMenuViewTests: BitwardenTestCase { /// Test that the refresh button sends the correct effect. @MainActor - func disabletest_snapshot_refreshFeatureFlags_tapped() async throws { + func disabletest_refreshFeatureFlags_tapped() async throws { let button = try subject.inspect().find(asyncButtonWithAccessibilityLabel: "RefreshFeatureFlagsButton") try await button.tap() XCTAssertEqual(processor.effects.last, .refreshFeatureFlags) } - - /// Check the snapshot when feature flags are enabled and disabled. - @MainActor - func disabletest_snapshot_debugMenuWithFeatureFlags() { - processor.state.featureFlags = [ - .init( - feature: .testFeatureFlag, - isEnabled: true, - ), - ] - assertSnapshot(of: subject, as: .defaultPortrait) - } } diff --git a/AuthenticatorShared/UI/Platform/Application/AppCoordinatorTests.swift b/AuthenticatorShared/UI/Platform/Application/AppCoordinatorTests.swift deleted file mode 100644 index c7908d7a3..000000000 --- a/AuthenticatorShared/UI/Platform/Application/AppCoordinatorTests.swift +++ /dev/null @@ -1,39 +0,0 @@ -import XCTest - -@testable import AuthenticatorShared - -// MARK: - AppCoordinatorTests - -class AppCoordinatorTests: BitwardenTestCase { - // MARK: Properties - - var module: MockAppModule! - var rootNavigator: MockRootNavigator! - var services: Services! - var subject: AppCoordinator! - - // MARK: Setup & Teardown - - override func setUp() { - super.setUp() - - module = MockAppModule() - rootNavigator = MockRootNavigator() - services = ServiceContainer.withMocks() - - subject = AppCoordinator( - appContext: .mainApp, - module: module, - rootNavigator: rootNavigator, - services: services, - ) - } - - override func tearDown() { - super.tearDown() - module = nil - rootNavigator = nil - services = nil - subject = nil - } -} diff --git a/AuthenticatorShared/UI/Platform/Application/AppModuleTests.swift b/AuthenticatorShared/UI/Platform/Application/AppModuleTests.swift deleted file mode 100644 index 8267d326f..000000000 --- a/AuthenticatorShared/UI/Platform/Application/AppModuleTests.swift +++ /dev/null @@ -1,27 +0,0 @@ -import SwiftUI -import XCTest - -@testable import AuthenticatorShared - -class AppModuleTests: BitwardenTestCase { - // MARK: Properties - - var rootViewController: RootViewController! - var subject: DefaultAppModule! - - // MARK: Setup & Teardown - - override func setUp() { - super.setUp() - - rootViewController = RootViewController() - subject = DefaultAppModule(services: .withMocks()) - } - - override func tearDown() { - super.tearDown() - - rootViewController = nil - subject = nil - } -} diff --git a/AuthenticatorShared/UI/Platform/Application/Appearance/StyleGuideFontTests.swift b/AuthenticatorShared/UI/Platform/Application/Appearance/StyleGuideFont+SnapshotTests.swift similarity index 95% rename from AuthenticatorShared/UI/Platform/Application/Appearance/StyleGuideFontTests.swift rename to AuthenticatorShared/UI/Platform/Application/Appearance/StyleGuideFont+SnapshotTests.swift index efdc330f6..874d8f673 100644 --- a/AuthenticatorShared/UI/Platform/Application/Appearance/StyleGuideFontTests.swift +++ b/AuthenticatorShared/UI/Platform/Application/Appearance/StyleGuideFont+SnapshotTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import SnapshotTesting import XCTest diff --git a/AuthenticatorShared/UI/Platform/Application/Views/LoadingOverlay/LoadingOverlayViewTests.swift b/AuthenticatorShared/UI/Platform/Application/Views/LoadingOverlay/LoadingOverlayView+SnapshotTests.swift similarity index 92% rename from AuthenticatorShared/UI/Platform/Application/Views/LoadingOverlay/LoadingOverlayViewTests.swift rename to AuthenticatorShared/UI/Platform/Application/Views/LoadingOverlay/LoadingOverlayView+SnapshotTests.swift index 14489d54e..7057ec86e 100644 --- a/AuthenticatorShared/UI/Platform/Application/Views/LoadingOverlay/LoadingOverlayViewTests.swift +++ b/AuthenticatorShared/UI/Platform/Application/Views/LoadingOverlay/LoadingOverlayView+SnapshotTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import SnapshotTesting import XCTest diff --git a/AuthenticatorShared/UI/Platform/Application/Views/SectionViewTests.swift b/AuthenticatorShared/UI/Platform/Application/Views/SectionView+SnapshotTests.swift similarity index 92% rename from AuthenticatorShared/UI/Platform/Application/Views/SectionViewTests.swift rename to AuthenticatorShared/UI/Platform/Application/Views/SectionView+SnapshotTests.swift index 3ef8a03b2..4f8dbb43d 100644 --- a/AuthenticatorShared/UI/Platform/Application/Views/SectionViewTests.swift +++ b/AuthenticatorShared/UI/Platform/Application/Views/SectionView+SnapshotTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import SnapshotTesting import XCTest diff --git a/AuthenticatorShared/UI/Platform/Settings/Settings/ExportItems/ExportItemsView+SnapshotTests.swift b/AuthenticatorShared/UI/Platform/Settings/Settings/ExportItems/ExportItemsView+SnapshotTests.swift new file mode 100644 index 000000000..d01c8060f --- /dev/null +++ b/AuthenticatorShared/UI/Platform/Settings/Settings/ExportItems/ExportItemsView+SnapshotTests.swift @@ -0,0 +1,38 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import AuthenticatorShared + +class ExportItemsViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: ExportItemsView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: ExportItemsState()) + let store = Store(processor: processor) + + subject = ExportItemsView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// The empty view renders correctly. + func disabletest_snapshot_empty() { + assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) + } +} diff --git a/AuthenticatorShared/UI/Platform/Settings/Settings/ExportItems/ExportItemsViewTests.swift b/AuthenticatorShared/UI/Platform/Settings/Settings/ExportItems/ExportItemsView+ViewInspectorTests.swift similarity index 87% rename from AuthenticatorShared/UI/Platform/Settings/Settings/ExportItems/ExportItemsViewTests.swift rename to AuthenticatorShared/UI/Platform/Settings/Settings/ExportItems/ExportItemsView+ViewInspectorTests.swift index 8f8c04a1e..781b63294 100644 --- a/AuthenticatorShared/UI/Platform/Settings/Settings/ExportItems/ExportItemsViewTests.swift +++ b/AuthenticatorShared/UI/Platform/Settings/Settings/ExportItems/ExportItemsView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import XCTest @testable import AuthenticatorShared @@ -55,11 +55,4 @@ class ExportItemsViewTests: BitwardenTestCase { try menuField.select(newValue: ExportFormatType.csv) XCTAssertEqual(processor.dispatchedActions.last, .fileFormatTypeChanged(.csv)) } - - // MARK: Snapshots - - /// The empty view renders correctly. - func disabletest_snapshot_empty() { - assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) - } } diff --git a/AuthenticatorShared/UI/Platform/Settings/Settings/ImportItems/ImportItemsView+SnapshotTests.swift b/AuthenticatorShared/UI/Platform/Settings/Settings/ImportItems/ImportItemsView+SnapshotTests.swift new file mode 100644 index 000000000..0ac732812 --- /dev/null +++ b/AuthenticatorShared/UI/Platform/Settings/Settings/ImportItems/ImportItemsView+SnapshotTests.swift @@ -0,0 +1,38 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import AuthenticatorShared + +class ImportItemsViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: ImportItemsView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: ImportItemsState()) + let store = Store(processor: processor) + + subject = ImportItemsView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// The empty view renders correctly. + func disabletest_snapshot_empty() { + assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) + } +} diff --git a/AuthenticatorShared/UI/Platform/Settings/Settings/ImportItems/ImportItemsViewTests.swift b/AuthenticatorShared/UI/Platform/Settings/Settings/ImportItems/ImportItemsView+ViewInspectorTests.swift similarity index 88% rename from AuthenticatorShared/UI/Platform/Settings/Settings/ImportItems/ImportItemsViewTests.swift rename to AuthenticatorShared/UI/Platform/Settings/Settings/ImportItems/ImportItemsView+ViewInspectorTests.swift index 257701426..2ba520d9e 100644 --- a/AuthenticatorShared/UI/Platform/Settings/Settings/ImportItems/ImportItemsViewTests.swift +++ b/AuthenticatorShared/UI/Platform/Settings/Settings/ImportItems/ImportItemsView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import XCTest @testable import AuthenticatorShared @@ -55,11 +55,4 @@ class ImportItemsViewTests: BitwardenTestCase { try menuField.select(newValue: ImportFormatType.bitwardenJson) XCTAssertEqual(processor.dispatchedActions.last, .fileFormatTypeChanged(.bitwardenJson)) } - - // MARK: Snapshots - - /// The empty view renders correctly. - func disabletest_snapshot_empty() { - assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) - } } diff --git a/AuthenticatorShared/UI/Platform/Settings/Settings/SelectLanguage/SelectLanguageView+SnapshotTests.swift b/AuthenticatorShared/UI/Platform/Settings/Settings/SelectLanguage/SelectLanguageView+SnapshotTests.swift new file mode 100644 index 000000000..0205f62fd --- /dev/null +++ b/AuthenticatorShared/UI/Platform/Settings/Settings/SelectLanguage/SelectLanguageView+SnapshotTests.swift @@ -0,0 +1,43 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +// MARK: - SelectLanguageViewTests + +@testable import AuthenticatorShared + +class SelectLanguageViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: SelectLanguageView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: SelectLanguageState()) + let store = Store(processor: processor) + + subject = SelectLanguageView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// Test that the view renders correctly. + func disabletest_viewRender() { + assertSnapshots( + of: subject.navStackWrapped, + as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5()], + ) + } +} diff --git a/AuthenticatorShared/UI/Platform/Settings/Settings/SelectLanguage/SelectLanguageViewTests.swift b/AuthenticatorShared/UI/Platform/Settings/Settings/SelectLanguage/SelectLanguageView+ViewInspectorTests.swift similarity index 82% rename from AuthenticatorShared/UI/Platform/Settings/Settings/SelectLanguage/SelectLanguageViewTests.swift rename to AuthenticatorShared/UI/Platform/Settings/Settings/SelectLanguage/SelectLanguageView+ViewInspectorTests.swift index de88438f2..426c7e130 100644 --- a/AuthenticatorShared/UI/Platform/Settings/Settings/SelectLanguage/SelectLanguageViewTests.swift +++ b/AuthenticatorShared/UI/Platform/Settings/Settings/SelectLanguage/SelectLanguageView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import XCTest // MARK: - SelectLanguageViewTests @@ -47,14 +47,4 @@ class SelectLanguageViewTests: BitwardenTestCase { try button.tap() XCTAssertEqual(processor.dispatchedActions.last, .languageTapped(.default)) } - - // MARK: Snapshots - - /// Test that the view renders correctly. - func disabletest_viewRender() { - assertSnapshots( - of: subject.navStackWrapped, - as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5()], - ) - } } diff --git a/AuthenticatorShared/UI/Platform/Settings/Settings/SettingsView+SnapshotTests.swift b/AuthenticatorShared/UI/Platform/Settings/Settings/SettingsView+SnapshotTests.swift new file mode 100644 index 000000000..f206e21d6 --- /dev/null +++ b/AuthenticatorShared/UI/Platform/Settings/Settings/SettingsView+SnapshotTests.swift @@ -0,0 +1,67 @@ +// swiftlint:disable:this file_name +import BitwardenKit +import BitwardenResources +import SnapshotTesting +import XCTest + +// MARK: - SettingsViewTests + +@testable import AuthenticatorShared + +class SettingsViewTests: BitwardenTestCase { + // MARK: Properties + + let copyrightText = "© Bitwarden Inc. 2015-2024" + let version = "Version: 1.0.0 (1)" + + var processor: MockProcessor! + var subject: SettingsView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: SettingsState(copyrightText: copyrightText, version: version)) + let store = Store(processor: processor) + + subject = SettingsView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Tests + + /// Tests the view renders correctly. + func disabletest_snapshot_viewRender() { + assertSnapshots( + of: subject, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } + + /// Tests the view renders correctly. + @MainActor + func disabletest_snapshot_viewRenderWithBiometricsAvailable() { + processor.state.biometricUnlockStatus = .available(.faceID, enabled: false, hasValidIntegrity: true) + assertSnapshots( + of: subject, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } + + /// Tests the view renders correctly with `shouldShowDefaultSaveOption` set to `true`. + @MainActor + func disabletest_snapshot_viewRenderWithDefaultSaveOption() { + processor.state.shouldShowDefaultSaveOption = true + assertSnapshots( + of: subject, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } +} diff --git a/AuthenticatorShared/UI/Platform/Settings/Settings/SettingsViewTests.swift b/AuthenticatorShared/UI/Platform/Settings/Settings/SettingsView+ViewInspectorTests.swift similarity index 83% rename from AuthenticatorShared/UI/Platform/Settings/Settings/SettingsViewTests.swift rename to AuthenticatorShared/UI/Platform/Settings/Settings/SettingsView+ViewInspectorTests.swift index cc52586c5..aab277cd6 100644 --- a/AuthenticatorShared/UI/Platform/Settings/Settings/SettingsViewTests.swift +++ b/AuthenticatorShared/UI/Platform/Settings/Settings/SettingsView+ViewInspectorTests.swift @@ -1,6 +1,6 @@ +// swiftlint:disable:this file_name import BitwardenKit import BitwardenResources -import SnapshotTesting import XCTest // MARK: - SettingsViewTests @@ -130,32 +130,4 @@ class SettingsViewTests: BitwardenTestCase { try button.tap() XCTAssertEqual(processor.dispatchedActions.last, .versionTapped) } - - /// Tests the view renders correctly. - func disabletest_snapshot_viewRender() { - assertSnapshots( - of: subject, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } - - /// Tests the view renders correctly. - @MainActor - func disabletest_snapshot_viewRenderWithBiometricsAvailable() { - processor.state.biometricUnlockStatus = .available(.faceID, enabled: false, hasValidIntegrity: true) - assertSnapshots( - of: subject, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } - - /// Tests the view renders correctly with `shouldShowDefaultSaveOption` set to `true`. - @MainActor - func disabletest_snapshot_viewRenderWithDefaultSaveOption() { - processor.state.shouldShowDefaultSaveOption = true - assertSnapshots( - of: subject, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } } diff --git a/AuthenticatorShared/UI/Platform/Tutorial/Tutorial/TutorialViewTests.swift b/AuthenticatorShared/UI/Platform/Tutorial/Tutorial/TutorialView+SnapshotTests.swift similarity index 97% rename from AuthenticatorShared/UI/Platform/Tutorial/Tutorial/TutorialViewTests.swift rename to AuthenticatorShared/UI/Platform/Tutorial/Tutorial/TutorialView+SnapshotTests.swift index 992ba04da..f8fe862ee 100644 --- a/AuthenticatorShared/UI/Platform/Tutorial/Tutorial/TutorialViewTests.swift +++ b/AuthenticatorShared/UI/Platform/Tutorial/Tutorial/TutorialView+SnapshotTests.swift @@ -1,6 +1,6 @@ +// swiftlint:disable:this file_name import SnapshotTesting import SwiftUI -import ViewInspector import XCTest @testable import AuthenticatorShared diff --git a/AuthenticatorShared/UI/Vault/AuthenticatorItem/EditAuthenticatorItem/EditAuthenticatorItemViewTests.swift b/AuthenticatorShared/UI/Vault/AuthenticatorItem/EditAuthenticatorItem/EditAuthenticatorItemView+SnapshotTests.swift similarity index 97% rename from AuthenticatorShared/UI/Vault/AuthenticatorItem/EditAuthenticatorItem/EditAuthenticatorItemViewTests.swift rename to AuthenticatorShared/UI/Vault/AuthenticatorItem/EditAuthenticatorItem/EditAuthenticatorItemView+SnapshotTests.swift index 1c6dc0785..ce375f2bb 100644 --- a/AuthenticatorShared/UI/Vault/AuthenticatorItem/EditAuthenticatorItem/EditAuthenticatorItemViewTests.swift +++ b/AuthenticatorShared/UI/Vault/AuthenticatorItem/EditAuthenticatorItem/EditAuthenticatorItemView+SnapshotTests.swift @@ -1,6 +1,6 @@ +// swiftlint:disable:this file_name import SnapshotTesting import SwiftUI -import ViewInspector import XCTest @testable import AuthenticatorShared diff --git a/AuthenticatorShared/UI/Vault/ItemList/ItemList/ItemListCardView+SnapshotTests.swift b/AuthenticatorShared/UI/Vault/ItemList/ItemList/ItemListCardView+SnapshotTests.swift new file mode 100644 index 000000000..c8ed94ba7 --- /dev/null +++ b/AuthenticatorShared/UI/Vault/ItemList/ItemList/ItemListCardView+SnapshotTests.swift @@ -0,0 +1,27 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import AuthenticatorShared + +// MARK: - ItemListCardViewTests + +class ItemListCardViewTests: BitwardenTestCase { + // MARK: Tests + + /// Test a snapshot of the ItemListView previews. + func disabletest_snapshot_ItemListCardView_previews() { + for preview in ItemListCardView_Previews._allPreviews { + let name = preview.displayName ?? "Unknown" + assertSnapshots( + of: preview.content, + as: [ + "\(name)-portrait": .defaultPortrait, + "\(name)-portraitDark": .defaultPortraitDark, + "\(name)-portraitAX5": .tallPortraitAX5(heightMultiple: 3), + ], + ) + } + } +} diff --git a/AuthenticatorShared/UI/Vault/ItemList/ItemList/ItemListCardViewTests.swift b/AuthenticatorShared/UI/Vault/ItemList/ItemList/ItemListCardView+ViewInspectorTests.swift similarity index 64% rename from AuthenticatorShared/UI/Vault/ItemList/ItemList/ItemListCardViewTests.swift rename to AuthenticatorShared/UI/Vault/ItemList/ItemList/ItemListCardView+ViewInspectorTests.swift index b5d63342d..3f5d47bf2 100644 --- a/AuthenticatorShared/UI/Vault/ItemList/ItemList/ItemListCardViewTests.swift +++ b/AuthenticatorShared/UI/Vault/ItemList/ItemList/ItemListCardView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import ViewInspector import XCTest @@ -10,23 +10,8 @@ import XCTest class ItemListCardViewTests: BitwardenTestCase { // MARK: Tests - /// Test a snapshot of the ItemListView previews. - func disabletest_snapshot_ItemListCardView_previews() { - for preview in ItemListCardView_Previews._allPreviews { - let name = preview.displayName ?? "Unknown" - assertSnapshots( - of: preview.content, - as: [ - "\(name)-portrait": .defaultPortrait, - "\(name)-portraitDark": .defaultPortraitDark, - "\(name)-portraitAX5": .tallPortraitAX5(heightMultiple: 3), - ], - ) - } - } - /// Test the actions are properly wired up in the ItemListCardView. - func disabletest_snapshot_ItemListCardView_actions() throws { + func test_ItemListCardView_actions() throws { let expectationAction = expectation(description: "action Tapped") let expectationClose = expectation(description: "close Tapped") let subject = ItemListCardView( diff --git a/AuthenticatorShared/UI/Vault/ItemList/ItemList/ItemListViewTests.swift b/AuthenticatorShared/UI/Vault/ItemList/ItemList/ItemListView+SnapshotTests.swift similarity index 72% rename from AuthenticatorShared/UI/Vault/ItemList/ItemList/ItemListViewTests.swift rename to AuthenticatorShared/UI/Vault/ItemList/ItemList/ItemListView+SnapshotTests.swift index e6cc36d92..73c0bbf70 100644 --- a/AuthenticatorShared/UI/Vault/ItemList/ItemList/ItemListViewTests.swift +++ b/AuthenticatorShared/UI/Vault/ItemList/ItemList/ItemListView+SnapshotTests.swift @@ -1,8 +1,8 @@ +// swiftlint:disable:this file_name import BitwardenKitMocks import BitwardenResources import SnapshotTesting import SwiftUI -import ViewInspector import XCTest @testable import AuthenticatorShared @@ -118,44 +118,4 @@ class ItemListViewTests: BitwardenTestCase { assertSnapshot(of: NavigationView { subject }, as: .defaultPortrait) } - - /// Test the close taps trigger the associated effect. - @MainActor - func disabletest_snapshot_itemListCardView_close_download() throws { - let state = ItemListState( - itemListCardState: .passwordManagerDownload, - loadingState: .data([ItemListSection.fixture()]), - ) - processor = MockProcessor(state: state) - subject = ItemListView( - store: Store(processor: processor), - timeProvider: timeProvider, - ) - - try subject.inspect().find(buttonWithAccessibilityLabel: Localizations.close).tap() - - waitFor(!processor.effects.isEmpty) - - XCTAssertEqual(processor.effects.last, .closeCard(.passwordManagerDownload)) - } - - /// Test the close taps trigger the associated effect. - @MainActor - func disabletest_snapshot_itemListCardView_close_sync() throws { - let state = ItemListState( - itemListCardState: .passwordManagerSync, - loadingState: .data([]), - ) - processor = MockProcessor(state: state) - subject = ItemListView( - store: Store(processor: processor), - timeProvider: timeProvider, - ) - - try subject.inspect().find(buttonWithAccessibilityLabel: Localizations.close).tap() - - waitFor(!processor.effects.isEmpty) - - XCTAssertEqual(processor.effects.last, .closeCard(.passwordManagerSync)) - } } diff --git a/AuthenticatorShared/UI/Vault/ItemList/ItemList/ItemListView+ViewInspectorTests.swift b/AuthenticatorShared/UI/Vault/ItemList/ItemList/ItemListView+ViewInspectorTests.swift new file mode 100644 index 000000000..d1a1e9efd --- /dev/null +++ b/AuthenticatorShared/UI/Vault/ItemList/ItemList/ItemListView+ViewInspectorTests.swift @@ -0,0 +1,82 @@ +// swiftlint:disable:this file_name +import BitwardenKitMocks +import BitwardenResources +import SwiftUI +import ViewInspector +import XCTest + +@testable import AuthenticatorShared + +// MARK: - ItemListViewTests + +class ItemListViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: ItemListView! + var timeProvider: MockTimeProvider! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + let state = ItemListState() + processor = MockProcessor(state: state) + timeProvider = MockTimeProvider(.mockTime(Date(year: 2023, month: 12, day: 31))) + subject = ItemListView( + store: Store(processor: processor), + timeProvider: timeProvider, + ) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + timeProvider = nil + } + + // MARK: Tests + + /// Test the close taps trigger the associated effect. + @MainActor + func test_itemListCardView_close_download() throws { + let state = ItemListState( + itemListCardState: .passwordManagerDownload, + loadingState: .data([ItemListSection.fixture()]), + ) + processor = MockProcessor(state: state) + subject = ItemListView( + store: Store(processor: processor), + timeProvider: timeProvider, + ) + + try subject.inspect().find(buttonWithAccessibilityLabel: Localizations.close).tap() + + waitFor(!processor.effects.isEmpty) + + XCTAssertEqual(processor.effects.last, .closeCard(.passwordManagerDownload)) + } + + /// Test the close taps trigger the associated effect. + @MainActor + func test_itemListCardView_close_sync() throws { + let state = ItemListState( + itemListCardState: .passwordManagerSync, + loadingState: .data([]), + ) + processor = MockProcessor(state: state) + subject = ItemListView( + store: Store(processor: processor), + timeProvider: timeProvider, + ) + + try subject.inspect().find(buttonWithAccessibilityLabel: Localizations.close).tap() + + waitFor(!processor.effects.isEmpty) + + XCTAssertEqual(processor.effects.last, .closeCard(.passwordManagerSync)) + } +} diff --git a/AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/AuthenticatorKeyCaptureCoordinator+ViewInspectorTests.swift b/AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/AuthenticatorKeyCaptureCoordinator+ViewInspectorTests.swift new file mode 100644 index 000000000..6c116c026 --- /dev/null +++ b/AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/AuthenticatorKeyCaptureCoordinator+ViewInspectorTests.swift @@ -0,0 +1,210 @@ +// swiftlint:disable:this file_name +import AVFoundation +import BitwardenKitMocks +import SwiftUI +import XCTest + +@testable import AuthenticatorShared + +class AuthenticatorKeyCaptureCoordinatorTests: BitwardenTestCase { + // MARK: Properties + + var cameraService: MockCameraService! + var delegate: MockAuthenticatorKeyCaptureDelegate! + var errorReporter: MockErrorReporter! + var stackNavigator: MockStackNavigator! + var subject: AuthenticatorKeyCaptureCoordinator! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + cameraService = MockCameraService() + delegate = MockAuthenticatorKeyCaptureDelegate() + errorReporter = MockErrorReporter() + stackNavigator = MockStackNavigator() + + subject = AuthenticatorKeyCaptureCoordinator( + delegate: delegate, + services: ServiceContainer.withMocks( + cameraService: cameraService, + errorReporter: errorReporter, + ), + stackNavigator: stackNavigator, + ) + cameraService.cameraAuthorizationStatus = .authorized + cameraService.startResult = .success(AVCaptureSession()) + } + + override func tearDown() { + super.tearDown() + + cameraService = nil + errorReporter = nil + stackNavigator = nil + subject = nil + } + + // MARK: Tests + + /// `navigate(to:)` with `.scanCode` shows the scan view. + @MainActor + func test_navigateTo_scanCode() throws { + cameraService.deviceHasCamera = true + let task = Task { + await subject.handleEvent(.showScanCode) + } + waitFor(!stackNavigator.actions.isEmpty) + task.cancel() + + let action = try XCTUnwrap(stackNavigator.actions.last) + XCTAssertEqual(action.type, .replaced) + let view = action.view as? (any View) + XCTAssertNotNil(try? view?.inspect().find(ScanCodeView.self)) + } + + /// `navigate(to:)` with `.scanCode` shows the scan view. + @MainActor + func test_navigateAsyncTo_scanCode() throws { + cameraService.deviceHasCamera = true + let task = Task { + await subject.handleEvent(.showScanCode) + } + waitFor(!stackNavigator.actions.isEmpty) + task.cancel() + + let action = try XCTUnwrap(stackNavigator.actions.last) + XCTAssertEqual(action.type, .replaced) + let view = action.view as? (any View) + XCTAssertNotNil(try? view?.inspect().find(ScanCodeView.self)) + } + + /// `navigate(to:)` with `.scanCode` shows the scan view. + @MainActor + func test_navigateAsyncTo_scanCode_cameraSessionError() throws { + cameraService.deviceHasCamera = true + struct TestError: Error, Equatable {} + cameraService.startResult = .failure(TestError()) + let task = Task { + await subject.handleEvent(.showScanCode) + } + waitFor(!stackNavigator.actions.isEmpty) + task.cancel() + + XCTAssertEqual(errorReporter.errors.last as? TestError, TestError()) + let action = try XCTUnwrap(stackNavigator.actions.last) + XCTAssertEqual(action.type, .replaced) + let view = action.view as? (any View) + XCTAssertNotNil(try? view?.inspect().find(ManualEntryView.self)) + } + + /// `navigate(to:)` with `.scanCode` shows the scan view. + @MainActor + func test_navigateAsyncTo_scanCode_declineAuthorization() throws { + cameraService.deviceHasCamera = true + cameraService.cameraAuthorizationStatus = .denied + let task = Task { + await subject.handleEvent(.showScanCode) + } + waitFor(!stackNavigator.actions.isEmpty) + task.cancel() + + let action = try XCTUnwrap(stackNavigator.actions.last) + XCTAssertEqual(action.type, .replaced) + let view = action.view as? (any View) + XCTAssertNotNil(try? view?.inspect().find(ManualEntryView.self)) + } + + /// `navigate(to:)` with `.scanCode` shows the scan view. + @MainActor + func test_navigateAsyncTo_scanCode_noCamera() throws { + cameraService.deviceHasCamera = false + let task = Task { + await subject.handleEvent(.showScanCode) + } + waitFor(!stackNavigator.actions.isEmpty) + task.cancel() + + let action = try XCTUnwrap(stackNavigator.actions.last) + XCTAssertEqual(action.type, .replaced) + let view = action.view as? (any View) + XCTAssertNotNil(try? view?.inspect().find(ManualEntryView.self)) + } +} + +// MARK: - MockAuthenticatorKeyCaptureDelegate + +class MockAuthenticatorKeyCaptureDelegate: AuthenticatorKeyCaptureDelegate { + var capturedCaptureCoordinator: AnyCoordinator? + var didCancelScanCalled = false + + var didCompleteCaptureCalled = false + var didCompleteCaptureKey: String? + var didCompleteCaptureName: String? + + var didCompleteAutomaticCaptureCalled = false + var didCompleteAutomaticCaptureKey: String? + + var didCompleteManualCaptureCalled = false + var didCompleteManualCaptureKey: String? + var didCompleteManualCaptureName: String? + var didCompleteManualCaptureSendToBitwarden = false + + /// A flag to capture a `showCameraScan` call. + var didRequestCamera: Bool = false + + /// A flag to capture a `showManualEntry` call. + var didRequestManual: Bool = false + + func didCancelScan() { + didCancelScanCalled = true + } + + func didCompleteCapture( + _ captureCoordinator: AnyCoordinator, + key: String, + name: String?, + ) { + didCompleteCaptureCalled = true + capturedCaptureCoordinator = captureCoordinator + didCompleteCaptureKey = key + didCompleteCaptureName = name + } + + func didCompleteAutomaticCapture( + _ captureCoordinator: AnyCoordinator, + key: String, + ) { + didCompleteAutomaticCaptureCalled = true + capturedCaptureCoordinator = captureCoordinator + didCompleteAutomaticCaptureKey = key + } + + func didCompleteManualCapture( + _ captureCoordinator: AnyCoordinator, + key: String, + name: String, + sendToBitwarden: Bool, + ) { + didCompleteManualCaptureCalled = true + capturedCaptureCoordinator = captureCoordinator + didCompleteManualCaptureKey = key + didCompleteManualCaptureName = name + didCompleteManualCaptureSendToBitwarden = sendToBitwarden + } + + func showCameraScan( + _ captureCoordinator: AnyCoordinator, + ) { + didRequestCamera = true + capturedCaptureCoordinator = captureCoordinator + } + + func showManualEntry( + _ captureCoordinator: AnyCoordinator, + ) { + didRequestManual = true + capturedCaptureCoordinator = captureCoordinator + } +} diff --git a/AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/AuthenticatorKeyCaptureCoordinatorTests.swift b/AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/AuthenticatorKeyCaptureCoordinatorTests.swift index c88a9d88f..24200339f 100644 --- a/AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/AuthenticatorKeyCaptureCoordinatorTests.swift +++ b/AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/AuthenticatorKeyCaptureCoordinatorTests.swift @@ -155,22 +155,6 @@ class AuthenticatorKeyCaptureCoordinatorTests: BitwardenTestCase { XCTAssertTrue(stackNavigator.actions.isEmpty) } - /// `navigate(to:)` with `.scanCode` shows the scan view. - @MainActor - func test_navigateTo_scanCode() throws { - cameraService.deviceHasCamera = true - let task = Task { - await subject.handleEvent(.showScanCode) - } - waitFor(!stackNavigator.actions.isEmpty) - task.cancel() - - let action = try XCTUnwrap(stackNavigator.actions.last) - XCTAssertEqual(action.type, .replaced) - let view = action.view as? (any View) - XCTAssertNotNil(try? view?.inspect().find(ScanCodeView.self)) - } - /// `navigate(to:)` with `.scanCode` shows the scan view. @MainActor func test_navigateTo_scanCode_nonEmptyStack() throws { @@ -200,74 +184,6 @@ class AuthenticatorKeyCaptureCoordinatorTests: BitwardenTestCase { XCTAssertNil(window.viewWithTag(LoadingOverlayDisplayHelper.overlayViewTag)) } - /// `navigate(to:)` with `.scanCode` shows the scan view. - @MainActor - func test_navigateAsyncTo_scanCode() throws { - cameraService.deviceHasCamera = true - let task = Task { - await subject.handleEvent(.showScanCode) - } - waitFor(!stackNavigator.actions.isEmpty) - task.cancel() - - let action = try XCTUnwrap(stackNavigator.actions.last) - XCTAssertEqual(action.type, .replaced) - let view = action.view as? (any View) - XCTAssertNotNil(try? view?.inspect().find(ScanCodeView.self)) - } - - /// `navigate(to:)` with `.scanCode` shows the scan view. - @MainActor - func test_navigateAsyncTo_scanCode_cameraSessionError() throws { - cameraService.deviceHasCamera = true - struct TestError: Error, Equatable {} - cameraService.startResult = .failure(TestError()) - let task = Task { - await subject.handleEvent(.showScanCode) - } - waitFor(!stackNavigator.actions.isEmpty) - task.cancel() - - XCTAssertEqual(errorReporter.errors.last as? TestError, TestError()) - let action = try XCTUnwrap(stackNavigator.actions.last) - XCTAssertEqual(action.type, .replaced) - let view = action.view as? (any View) - XCTAssertNotNil(try? view?.inspect().find(ManualEntryView.self)) - } - - /// `navigate(to:)` with `.scanCode` shows the scan view. - @MainActor - func test_navigateAsyncTo_scanCode_declineAuthorization() throws { - cameraService.deviceHasCamera = true - cameraService.cameraAuthorizationStatus = .denied - let task = Task { - await subject.handleEvent(.showScanCode) - } - waitFor(!stackNavigator.actions.isEmpty) - task.cancel() - - let action = try XCTUnwrap(stackNavigator.actions.last) - XCTAssertEqual(action.type, .replaced) - let view = action.view as? (any View) - XCTAssertNotNil(try? view?.inspect().find(ManualEntryView.self)) - } - - /// `navigate(to:)` with `.scanCode` shows the scan view. - @MainActor - func test_navigateAsyncTo_scanCode_noCamera() throws { - cameraService.deviceHasCamera = false - let task = Task { - await subject.handleEvent(.showScanCode) - } - waitFor(!stackNavigator.actions.isEmpty) - task.cancel() - - let action = try XCTUnwrap(stackNavigator.actions.last) - XCTAssertEqual(action.type, .replaced) - let view = action.view as? (any View) - XCTAssertNotNil(try? view?.inspect().find(ManualEntryView.self)) - } - /// `navigate(to:)` with `.scanCode` shows the scan view. @MainActor func test_navigateAsyncTo_scanCode_nonEmptyStack() throws { diff --git a/AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ManualEntryView+SnapshotTests.swift b/AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ManualEntryView+SnapshotTests.swift new file mode 100644 index 000000000..c7d86461e --- /dev/null +++ b/AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ManualEntryView+SnapshotTests.swift @@ -0,0 +1,116 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import AuthenticatorShared + +// MARK: - ManualEntryViewTests + +class ManualEntryViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: ManualEntryView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + processor = MockProcessor(state: DefaultEntryState(deviceSupportsCamera: true)) + let store = Store(processor: processor) + subject = ManualEntryView( + store: store, + ) + } + + override func tearDown() { + super.tearDown() + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// Test a snapshot of the `ManualEntryView` empty state. + func disabletest_snapshot_manualEntryView_empty() { + assertSnapshot( + of: ManualEntryView_Previews.empty, + as: .defaultPortrait, + ) + } + + /// Test a snapshot of the `ManualEntryView` empty state. + func disabletest_snapshot_manualEntryView_empty_landscape() { + assertSnapshot( + of: ManualEntryView_Previews.empty, + as: .defaultLandscape, + ) + } + + /// Test a snapshot of the `ManualEntryView` in dark mode. + func disabletest_snapshot_manualEntryView_text_dark() { + assertSnapshot( + of: ManualEntryView_Previews.textAdded, + as: .defaultPortraitDark, + ) + } + + /// Test a snapshot of the `ManualEntryView` with large text. + func disabletest_snapshot_manualEntryView_text_largeText() { + assertSnapshot( + of: ManualEntryView_Previews.textAdded, + as: .tallPortraitAX5(heightMultiple: 1.75), + ) + } + + /// Test a snapshot of the `ManualEntryView` in light mode. + func disabletest_snapshot_manualEntryView_text_light() { + assertSnapshot( + of: ManualEntryView_Previews.textAdded, + as: .defaultPortrait, + ) + } + + /// Test a snapshot of the `ManualEntryView` in dark mode with the + /// password manager sync flag active. + func disabletest_snapshot_manualEntryView_text_dark_syncActive() { + assertSnapshot( + of: ManualEntryView_Previews.syncActiveNoDefault, + as: .defaultPortraitDark, + ) + } + + /// Test a snapshot of the `ManualEntryView` with large text with the + /// password manager sync flag active. + func disabletest_snapshot_manualEntryView_text_largeText_syncActive() { + assertSnapshot( + of: ManualEntryView_Previews.syncActiveNoDefault, + as: .tallPortraitAX5(heightMultiple: 1.75), + ) + } + + /// Test a snapshot of the `ManualEntryView` in light mode with the + /// password manager sync flag active. + func disabletest_snapshot_manualEntryView_text_light_syncActive() { + assertSnapshot( + of: ManualEntryView_Previews.syncActiveNoDefault, + as: .defaultPortrait, + ) + } + + /// Test a snapshot of the `ManualEntryView` previews. + func disabletest_snapshot_manualEntryView_previews() { + for preview in ManualEntryView_Previews._allPreviews { + let name = preview.displayName ?? "Unknown" + assertSnapshots( + of: preview.content, + as: [ + "\(name)-portrait": .defaultPortrait, + "\(name)-portraitDark": .defaultPortraitDark, + "\(name)-portraitAX5": .defaultPortraitAX5, + ], + ) + } + } +} diff --git a/AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ManualEntryViewTests.swift b/AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ManualEntryView+ViewInspectorTests.swift similarity index 61% rename from AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ManualEntryViewTests.swift rename to AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ManualEntryView+ViewInspectorTests.swift index 32da770e2..05934d8c2 100644 --- a/AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ManualEntryViewTests.swift +++ b/AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ManualEntryView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import ViewInspector import XCTest @@ -127,88 +127,4 @@ class ManualEntryViewTests: BitwardenTestCase { XCTAssertEqual(processor.effects.last, .scanCodePressed) } - - // MARK: Snapshots - - /// Test a snapshot of the `ManualEntryView` empty state. - func disabletest_snapshot_manualEntryView_empty() { - assertSnapshot( - of: ManualEntryView_Previews.empty, - as: .defaultPortrait, - ) - } - - /// Test a snapshot of the `ManualEntryView` empty state. - func disabletest_snapshot_manualEntryView_empty_landscape() { - assertSnapshot( - of: ManualEntryView_Previews.empty, - as: .defaultLandscape, - ) - } - - /// Test a snapshot of the `ManualEntryView` in dark mode. - func disabletest_snapshot_manualEntryView_text_dark() { - assertSnapshot( - of: ManualEntryView_Previews.textAdded, - as: .defaultPortraitDark, - ) - } - - /// Test a snapshot of the `ManualEntryView` with large text. - func disabletest_snapshot_manualEntryView_text_largeText() { - assertSnapshot( - of: ManualEntryView_Previews.textAdded, - as: .tallPortraitAX5(heightMultiple: 1.75), - ) - } - - /// Test a snapshot of the `ManualEntryView` in light mode. - func disabletest_snapshot_manualEntryView_text_light() { - assertSnapshot( - of: ManualEntryView_Previews.textAdded, - as: .defaultPortrait, - ) - } - - /// Test a snapshot of the `ManualEntryView` in dark mode with the - /// password manager sync flag active. - func disabletest_snapshot_manualEntryView_text_dark_syncActive() { - assertSnapshot( - of: ManualEntryView_Previews.syncActiveNoDefault, - as: .defaultPortraitDark, - ) - } - - /// Test a snapshot of the `ManualEntryView` with large text with the - /// password manager sync flag active. - func disabletest_snapshot_manualEntryView_text_largeText_syncActive() { - assertSnapshot( - of: ManualEntryView_Previews.syncActiveNoDefault, - as: .tallPortraitAX5(heightMultiple: 1.75), - ) - } - - /// Test a snapshot of the `ManualEntryView` in light mode with the - /// password manager sync flag active. - func disabletest_snapshot_manualEntryView_text_light_syncActive() { - assertSnapshot( - of: ManualEntryView_Previews.syncActiveNoDefault, - as: .defaultPortrait, - ) - } - - /// Test a snapshot of the `ManualEntryView` previews. - func disabletest_snapshot_manualEntryView_previews() { - for preview in ManualEntryView_Previews._allPreviews { - let name = preview.displayName ?? "Unknown" - assertSnapshots( - of: preview.content, - as: [ - "\(name)-portrait": .defaultPortrait, - "\(name)-portraitDark": .defaultPortraitDark, - "\(name)-portraitAX5": .defaultPortraitAX5, - ], - ) - } - } } diff --git a/AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ScanCodeViewTests.swift b/AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ScanCodeView+SnapshotTests.swift similarity index 78% rename from AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ScanCodeViewTests.swift rename to AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ScanCodeView+SnapshotTests.swift index 6121f31de..8712664d4 100644 --- a/AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ScanCodeViewTests.swift +++ b/AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ScanCodeView+SnapshotTests.swift @@ -1,7 +1,7 @@ +// swiftlint:disable:this file_name import AVFoundation import BitwardenResources import SnapshotTesting -import ViewInspector import XCTest @testable import AuthenticatorShared @@ -32,16 +32,6 @@ class ScanCodeViewTests: BitwardenTestCase { subject = nil } - // MARK: Tests - - /// Tapping the cancel button dispatches the `.dismiss` action. - @MainActor - func test_cancelButton_tap() throws { - let button = try subject.inspect().findCancelToolbarButton() - try button.tap() - XCTAssertEqual(processor.dispatchedActions.last, .dismissPressed) - } - // MARK: Snapshots /// Test a snapshot of the ProfileSwitcherView previews. diff --git a/AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ScanCodeView+ViewInspectorTests.swift b/AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ScanCodeView+ViewInspectorTests.swift new file mode 100644 index 000000000..9e7d8a0d9 --- /dev/null +++ b/AuthenticatorShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ScanCodeView+ViewInspectorTests.swift @@ -0,0 +1,44 @@ +// swiftlint:disable:this file_name +import AVFoundation +import BitwardenResources +import ViewInspector +import XCTest + +@testable import AuthenticatorShared + +// MARK: - ScanCodeViewTests + +class ScanCodeViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: ScanCodeView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + processor = MockProcessor(state: ScanCodeState(showManualEntry: true)) + let store = Store(processor: processor) + subject = ScanCodeView( + cameraSession: .init(), + store: store, + ) + } + + override func tearDown() { + super.tearDown() + processor = nil + subject = nil + } + + // MARK: Tests + + /// Tapping the cancel button dispatches the `.dismiss` action. + @MainActor + func test_cancelButton_tap() throws { + let button = try subject.inspect().findCancelToolbarButton() + try button.tap() + XCTAssertEqual(processor.dispatchedActions.last, .dismissPressed) + } +} diff --git a/BitwardenActionExtension/ActionViewControllerTests.swift b/BitwardenActionExtension/ActionViewControllerTests.swift deleted file mode 100644 index 405b186d8..000000000 --- a/BitwardenActionExtension/ActionViewControllerTests.swift +++ /dev/null @@ -1,6 +0,0 @@ -import SwiftUI -import XCTest - -@testable import BitwardenActionExtension - -class ActionViewControllerTests: BitwardenTestCase {} diff --git a/BitwardenAutoFillExtension/CredentialProviderViewControllerTests.swift b/BitwardenAutoFillExtension/CredentialProviderViewControllerTests.swift deleted file mode 100644 index 7155f63c1..000000000 --- a/BitwardenAutoFillExtension/CredentialProviderViewControllerTests.swift +++ /dev/null @@ -1,6 +0,0 @@ -import SwiftUI -import XCTest - -@testable import BitwardenAutoFillExtension - -class CredentialProviderViewControllerTests: BitwardenTestCase {} diff --git a/BitwardenKit/UI/Platform/Application/Appearance/StyleGuideFontTests.swift b/BitwardenKit/UI/Platform/Application/Appearance/StyleGuideFont+SnapshotTests.swift similarity index 95% rename from BitwardenKit/UI/Platform/Application/Appearance/StyleGuideFontTests.swift rename to BitwardenKit/UI/Platform/Application/Appearance/StyleGuideFont+SnapshotTests.swift index dff442849..7536a94a3 100644 --- a/BitwardenKit/UI/Platform/Application/Appearance/StyleGuideFontTests.swift +++ b/BitwardenKit/UI/Platform/Application/Appearance/StyleGuideFont+SnapshotTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import SnapshotTesting import XCTest diff --git a/BitwardenKit/UI/Platform/Application/Appearance/Styles/ButtonStylesTests.swift b/BitwardenKit/UI/Platform/Application/Appearance/Styles/ButtonStyles+SnapshotTests.swift similarity index 98% rename from BitwardenKit/UI/Platform/Application/Appearance/Styles/ButtonStylesTests.swift rename to BitwardenKit/UI/Platform/Application/Appearance/Styles/ButtonStyles+SnapshotTests.swift index f20c6d6e7..a221301e2 100644 --- a/BitwardenKit/UI/Platform/Application/Appearance/Styles/ButtonStylesTests.swift +++ b/BitwardenKit/UI/Platform/Application/Appearance/Styles/ButtonStyles+SnapshotTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import BitwardenKit import BitwardenResources import SnapshotTesting diff --git a/BitwardenKit/UI/Platform/Application/Views/AsyncButtonTests.swift b/BitwardenKit/UI/Platform/Application/Views/AsyncButton+ViewInspectorTests.swift similarity index 92% rename from BitwardenKit/UI/Platform/Application/Views/AsyncButtonTests.swift rename to BitwardenKit/UI/Platform/Application/Views/AsyncButton+ViewInspectorTests.swift index 83a30f07c..4d9c64de3 100644 --- a/BitwardenKit/UI/Platform/Application/Views/AsyncButtonTests.swift +++ b/BitwardenKit/UI/Platform/Application/Views/AsyncButton+ViewInspectorTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import BitwardenKit import ViewInspector import XCTest diff --git a/BitwardenKit/UI/Platform/Application/Views/BitwardenMenuFieldTests.swift b/BitwardenKit/UI/Platform/Application/Views/BitwardenMenuField+ViewInspectorTests.swift similarity index 97% rename from BitwardenKit/UI/Platform/Application/Views/BitwardenMenuFieldTests.swift rename to BitwardenKit/UI/Platform/Application/Views/BitwardenMenuField+ViewInspectorTests.swift index 71396cabf..1efd8e920 100644 --- a/BitwardenKit/UI/Platform/Application/Views/BitwardenMenuFieldTests.swift +++ b/BitwardenKit/UI/Platform/Application/Views/BitwardenMenuField+ViewInspectorTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import BitwardenKit import SwiftUI import ViewInspector diff --git a/BitwardenKit/UI/Platform/Application/Views/CircularProgressShapeTests.swift b/BitwardenKit/UI/Platform/Application/Views/CircularProgressShape+SnapshotTests.swift similarity index 97% rename from BitwardenKit/UI/Platform/Application/Views/CircularProgressShapeTests.swift rename to BitwardenKit/UI/Platform/Application/Views/CircularProgressShape+SnapshotTests.swift index ba4f56c4d..4a2e1f80f 100644 --- a/BitwardenKit/UI/Platform/Application/Views/CircularProgressShapeTests.swift +++ b/BitwardenKit/UI/Platform/Application/Views/CircularProgressShape+SnapshotTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import BitwardenKit import BitwardenResources import SnapshotTesting diff --git a/BitwardenKit/UI/Platform/Application/Views/SettingsMenuFieldTests.swift b/BitwardenKit/UI/Platform/Application/Views/SettingsMenuField+ViewInspectorTests.swift similarity index 97% rename from BitwardenKit/UI/Platform/Application/Views/SettingsMenuFieldTests.swift rename to BitwardenKit/UI/Platform/Application/Views/SettingsMenuField+ViewInspectorTests.swift index 372af09ea..608e90b06 100644 --- a/BitwardenKit/UI/Platform/Application/Views/SettingsMenuFieldTests.swift +++ b/BitwardenKit/UI/Platform/Application/Views/SettingsMenuField+ViewInspectorTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import BitwardenKit import SwiftUI import ViewInspector diff --git a/BitwardenKit/UI/Platform/Application/Views/ToastViewTests.swift b/BitwardenKit/UI/Platform/Application/Views/ToastView+SnapshotTests.swift similarity index 94% rename from BitwardenKit/UI/Platform/Application/Views/ToastViewTests.swift rename to BitwardenKit/UI/Platform/Application/Views/ToastView+SnapshotTests.swift index b8d47ff9a..29cd13798 100644 --- a/BitwardenKit/UI/Platform/Application/Views/ToastViewTests.swift +++ b/BitwardenKit/UI/Platform/Application/Views/ToastView+SnapshotTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import BitwardenKit import SnapshotTesting import SwiftUI diff --git a/BitwardenShareExtension/ShareViewControllerTests.swift b/BitwardenShareExtension/ShareViewControllerTests.swift deleted file mode 100644 index a95059529..000000000 --- a/BitwardenShareExtension/ShareViewControllerTests.swift +++ /dev/null @@ -1,6 +0,0 @@ -import SwiftUI -import XCTest - -@testable import BitwardenShareExtension - -class ShareViewControllerTests: BitwardenTestCase {} diff --git a/BitwardenShared/UI/Auth/CompleteRegistration/CompleteRegistrationView+SnapshotTests.swift b/BitwardenShared/UI/Auth/CompleteRegistration/CompleteRegistrationView+SnapshotTests.swift new file mode 100644 index 000000000..f05cd4a8c --- /dev/null +++ b/BitwardenShared/UI/Auth/CompleteRegistration/CompleteRegistrationView+SnapshotTests.swift @@ -0,0 +1,85 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import SwiftUI +import XCTest + +@testable import BitwardenShared + +// MARK: - CompleteRegistrationViewTests + +class CompleteRegistrationViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: CompleteRegistrationView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: CompleteRegistrationState( + emailVerificationToken: "emailVerificationToken", + userEmail: "email@example.com", + )) + let store = Store(processor: processor) + subject = CompleteRegistrationView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// Tests the view renders correctly. + @MainActor + func disabletest_snapshot_empty_nativeCreateAccountFlow() throws { + assertSnapshots( + of: subject, + as: [ + .tallPortrait, + .portraitDark(heightMultiple: 2), + .tallPortraitAX5(), + ], + ) + } + + /// Tests the view renders correctly when text fields are hidden. + @MainActor + func disabletest_snapshot_textFields_hidden_nativeCreateAccountFlow() throws { + processor.state.arePasswordsVisible = false + processor.state.userEmail = "email@example.com" + processor.state.passwordText = "12345" + processor.state.retypePasswordText = "12345" + processor.state.passwordHintText = "wink wink" + processor.state.passwordStrengthScore = 0 + + assertSnapshot(of: subject, as: .defaultPortrait) + } + + /// Tests the view renders correctly when the text fields are all populated. + @MainActor + func disabletest_snapshot_textFields_populated_nativeCreateAccountFlow() throws { + processor.state.arePasswordsVisible = true + processor.state.userEmail = "email@example.com" + processor.state.passwordText = "12345" + processor.state.retypePasswordText = "12345" + processor.state.passwordHintText = "wink wink" + processor.state.passwordStrengthScore = 0 + + assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) + } + + /// Tests the view renders correctly when the toggles are on. + @MainActor + func disabletest_snapshot_toggles_on_nativeCreateAccountFlow() throws { + processor.state.isCheckDataBreachesToggleOn = true + + assertSnapshot(of: subject, as: .defaultPortrait) + } +} diff --git a/BitwardenShared/UI/Auth/CompleteRegistration/CompleteRegistrationViewTests.swift b/BitwardenShared/UI/Auth/CompleteRegistration/CompleteRegistrationView+ViewInspectorTests.swift similarity index 73% rename from BitwardenShared/UI/Auth/CompleteRegistration/CompleteRegistrationViewTests.swift rename to BitwardenShared/UI/Auth/CompleteRegistration/CompleteRegistrationView+ViewInspectorTests.swift index 9d9732eb6..631012785 100644 --- a/BitwardenShared/UI/Auth/CompleteRegistration/CompleteRegistrationViewTests.swift +++ b/BitwardenShared/UI/Auth/CompleteRegistration/CompleteRegistrationView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import SwiftUI import ViewInspector import XCTest @@ -129,53 +129,4 @@ class CompleteRegistrationViewTests: BitwardenTestCase { XCTAssertEqual(processor.dispatchedActions.last, .preventAccountLockTapped) } - - // MARK: Snapshots - - /// Tests the view renders correctly. - @MainActor - func disabletest_snapshot_empty_nativeCreateAccountFlow() throws { - assertSnapshots( - of: subject, - as: [ - .tallPortrait, - .portraitDark(heightMultiple: 2), - .tallPortraitAX5(), - ], - ) - } - - /// Tests the view renders correctly when text fields are hidden. - @MainActor - func disabletest_snapshot_textFields_hidden_nativeCreateAccountFlow() throws { - processor.state.arePasswordsVisible = false - processor.state.userEmail = "email@example.com" - processor.state.passwordText = "12345" - processor.state.retypePasswordText = "12345" - processor.state.passwordHintText = "wink wink" - processor.state.passwordStrengthScore = 0 - - assertSnapshot(of: subject, as: .defaultPortrait) - } - - /// Tests the view renders correctly when the text fields are all populated. - @MainActor - func disabletest_snapshot_textFields_populated_nativeCreateAccountFlow() throws { - processor.state.arePasswordsVisible = true - processor.state.userEmail = "email@example.com" - processor.state.passwordText = "12345" - processor.state.retypePasswordText = "12345" - processor.state.passwordHintText = "wink wink" - processor.state.passwordStrengthScore = 0 - - assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) - } - - /// Tests the view renders correctly when the toggles are on. - @MainActor - func disabletest_snapshot_toggles_on_nativeCreateAccountFlow() throws { - processor.state.isCheckDataBreachesToggleOn = true - - assertSnapshot(of: subject, as: .defaultPortrait) - } } diff --git a/BitwardenShared/UI/Auth/CompleteRegistration/ExpiredLink/ExpiredLinkView+SnapshotTests.swift b/BitwardenShared/UI/Auth/CompleteRegistration/ExpiredLink/ExpiredLinkView+SnapshotTests.swift new file mode 100644 index 000000000..d1db7a29b --- /dev/null +++ b/BitwardenShared/UI/Auth/CompleteRegistration/ExpiredLink/ExpiredLinkView+SnapshotTests.swift @@ -0,0 +1,38 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import SwiftUI +import XCTest + +@testable import BitwardenShared + +// MARK: - ExpiredLinkViewTests + +class ExpiredLinkViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: ExpiredLinkView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + processor = MockProcessor(state: ExpiredLinkState()) + subject = ExpiredLinkView(store: Store(processor: processor)) + } + + override func tearDown() { + super.tearDown() + processor = nil + subject = nil + } + + // MARK: Tests + + /// Tests the view renders correctly. + @MainActor + func disabletest_snapshot_toggles_on() throws { + assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) + } +} diff --git a/BitwardenShared/UI/Auth/CompleteRegistration/ExpiredLink/ExpiredLinkViewTests.swift b/BitwardenShared/UI/Auth/CompleteRegistration/ExpiredLink/ExpiredLinkView+ViewInspectorTests.swift similarity index 87% rename from BitwardenShared/UI/Auth/CompleteRegistration/ExpiredLink/ExpiredLinkViewTests.swift rename to BitwardenShared/UI/Auth/CompleteRegistration/ExpiredLink/ExpiredLinkView+ViewInspectorTests.swift index 8c51d4ebb..66a27a178 100644 --- a/BitwardenShared/UI/Auth/CompleteRegistration/ExpiredLink/ExpiredLinkViewTests.swift +++ b/BitwardenShared/UI/Auth/CompleteRegistration/ExpiredLink/ExpiredLinkView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import SwiftUI import ViewInspector import XCTest @@ -53,10 +53,4 @@ class ExpiredLinkViewTests: BitwardenTestCase { try button.tap() XCTAssertEqual(processor.dispatchedActions.last, .logInTapped) } - - /// Tests the view renders correctly. - @MainActor - func disabletest_snapshot_toggles_on() throws { - assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) - } } diff --git a/BitwardenShared/UI/Auth/CompleteRegistration/MasterPasswordGenerator/MasterPasswordGeneratorView+SnapshotTests.swift b/BitwardenShared/UI/Auth/CompleteRegistration/MasterPasswordGenerator/MasterPasswordGeneratorView+SnapshotTests.swift new file mode 100644 index 000000000..77c53bdd3 --- /dev/null +++ b/BitwardenShared/UI/Auth/CompleteRegistration/MasterPasswordGenerator/MasterPasswordGeneratorView+SnapshotTests.swift @@ -0,0 +1,50 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class MasterPasswordGeneratorViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor< + MasterPasswordGeneratorState, + MasterPasswordGeneratorAction, + MasterPasswordGeneratorEffect, + >! + var subject: MasterPasswordGeneratorView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + let state = MasterPasswordGeneratorState(generatedPassword: "Imma-Little-Teapot2") + processor = MockProcessor(state: state) + subject = MasterPasswordGeneratorView(store: Store(processor: processor)) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// The master password generator view renders correctly. + @MainActor + func disabletest_snapshot_masterPasswordGenerator() { + assertSnapshots( + of: subject.navStackWrapped, + as: [ + .defaultPortrait, + .defaultPortraitDark, + .tallPortraitAX5(heightMultiple: 2), + .defaultLandscape, + ], + ) + } +} diff --git a/BitwardenShared/UI/Auth/CompleteRegistration/MasterPasswordGenerator/MasterPasswordGeneratorViewTests.swift b/BitwardenShared/UI/Auth/CompleteRegistration/MasterPasswordGenerator/MasterPasswordGeneratorView+ViewInspectorTests.swift similarity index 82% rename from BitwardenShared/UI/Auth/CompleteRegistration/MasterPasswordGenerator/MasterPasswordGeneratorViewTests.swift rename to BitwardenShared/UI/Auth/CompleteRegistration/MasterPasswordGenerator/MasterPasswordGeneratorView+ViewInspectorTests.swift index 23ef78980..2ef643e1b 100644 --- a/BitwardenShared/UI/Auth/CompleteRegistration/MasterPasswordGenerator/MasterPasswordGeneratorViewTests.swift +++ b/BitwardenShared/UI/Auth/CompleteRegistration/MasterPasswordGenerator/MasterPasswordGeneratorView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import ViewInspector import XCTest @@ -63,20 +63,4 @@ class MasterPasswordGeneratorViewTests: BitwardenTestCase { try await button.tap() XCTAssertEqual(processor.effects.last, .save) } - - // MARK: Snapshots - - /// The master password generator view renders correctly. - @MainActor - func disabletest_snapshot_masterPasswordGenerator() { - assertSnapshots( - of: subject.navStackWrapped, - as: [ - .defaultPortrait, - .defaultPortraitDark, - .tallPortraitAX5(heightMultiple: 2), - .defaultLandscape, - ], - ) - } } diff --git a/BitwardenShared/UI/Auth/CompleteRegistration/MasterPasswordGuidance/MasterPasswordGuidanceView+SnapshotTests.swift b/BitwardenShared/UI/Auth/CompleteRegistration/MasterPasswordGuidance/MasterPasswordGuidanceView+SnapshotTests.swift new file mode 100644 index 000000000..7db5441aa --- /dev/null +++ b/BitwardenShared/UI/Auth/CompleteRegistration/MasterPasswordGuidance/MasterPasswordGuidanceView+SnapshotTests.swift @@ -0,0 +1,46 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class MasterPasswordGuidanceViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: MasterPasswordGuidanceView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: ()) + + subject = MasterPasswordGuidanceView(store: Store(processor: processor)) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// The master password guidance view renders correctly. + @MainActor + func disabletest_snapshot_masterPasswordGuidance() { + assertSnapshots( + of: subject.navStackWrapped, + as: [ + .defaultPortrait, + .defaultPortraitDark, + .tallPortraitAX5(heightMultiple: 2), + .defaultLandscape, + ], + ) + } +} diff --git a/BitwardenShared/UI/Auth/CompleteRegistration/MasterPasswordGuidance/MasterPasswordGuidanceViewTests.swift b/BitwardenShared/UI/Auth/CompleteRegistration/MasterPasswordGuidance/MasterPasswordGuidanceView+ViewInspectorTests.swift similarity index 74% rename from BitwardenShared/UI/Auth/CompleteRegistration/MasterPasswordGuidance/MasterPasswordGuidanceViewTests.swift rename to BitwardenShared/UI/Auth/CompleteRegistration/MasterPasswordGuidance/MasterPasswordGuidanceView+ViewInspectorTests.swift index 141488e91..b5fee7f59 100644 --- a/BitwardenShared/UI/Auth/CompleteRegistration/MasterPasswordGuidance/MasterPasswordGuidanceViewTests.swift +++ b/BitwardenShared/UI/Auth/CompleteRegistration/MasterPasswordGuidance/MasterPasswordGuidanceView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import ViewInspector import XCTest @@ -45,20 +45,4 @@ class MasterPasswordGuidanceViewTests: BitwardenTestCase { try await button.tap() XCTAssertEqual(processor.dispatchedActions.last, .generatePasswordPressed) } - - // MARK: Snapshots - - /// The master password guidance view renders correctly. - @MainActor - func disabletest_snapshot_masterPasswordGuidance() { - assertSnapshots( - of: subject.navStackWrapped, - as: [ - .defaultPortrait, - .defaultPortraitDark, - .tallPortraitAX5(heightMultiple: 2), - .defaultLandscape, - ], - ) - } } diff --git a/BitwardenShared/UI/Auth/CompleteRegistration/PreventAccountLock/PreventAccountLockViewTests.swift b/BitwardenShared/UI/Auth/CompleteRegistration/PreventAccountLock/PreventAccountLockView+SnapshotTests.swift similarity index 74% rename from BitwardenShared/UI/Auth/CompleteRegistration/PreventAccountLock/PreventAccountLockViewTests.swift rename to BitwardenShared/UI/Auth/CompleteRegistration/PreventAccountLock/PreventAccountLockView+SnapshotTests.swift index 89fb83da2..6720542c2 100644 --- a/BitwardenShared/UI/Auth/CompleteRegistration/PreventAccountLock/PreventAccountLockViewTests.swift +++ b/BitwardenShared/UI/Auth/CompleteRegistration/PreventAccountLock/PreventAccountLockView+SnapshotTests.swift @@ -1,6 +1,6 @@ +// swiftlint:disable:this file_name import BitwardenResources import SnapshotTesting -import ViewInspector import XCTest @testable import BitwardenShared @@ -27,16 +27,6 @@ class PreventAccountLockViewTests: BitwardenTestCase { subject = nil } - // MARK: Tests - - /// Tapping the cancel button dispatches the `.dismiss` action. - @MainActor - func test_cancelButton_tap() throws { - let button = try subject.inspect().findCloseToolbarButton() - try button.tap() - XCTAssertEqual(processor.dispatchedActions.last, .dismiss) - } - // MARK: Snapshots /// The prevent account lock view renders correctly. diff --git a/BitwardenShared/UI/Auth/CompleteRegistration/PreventAccountLock/PreventAccountLockView+ViewInspectorTests.swift b/BitwardenShared/UI/Auth/CompleteRegistration/PreventAccountLock/PreventAccountLockView+ViewInspectorTests.swift new file mode 100644 index 000000000..cbc10969b --- /dev/null +++ b/BitwardenShared/UI/Auth/CompleteRegistration/PreventAccountLock/PreventAccountLockView+ViewInspectorTests.swift @@ -0,0 +1,39 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import ViewInspector +import XCTest + +@testable import BitwardenShared + +class PreventAccountLockViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: PreventAccountLockView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: ()) + subject = PreventAccountLockView(store: Store(processor: processor)) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Tests + + /// Tapping the cancel button dispatches the `.dismiss` action. + @MainActor + func test_cancelButton_tap() throws { + let button = try subject.inspect().findCloseToolbarButton() + try button.tap() + XCTAssertEqual(processor.dispatchedActions.last, .dismiss) + } +} diff --git a/BitwardenShared/UI/Auth/IntroCarousel/IntroCarouselViewTests.swift b/BitwardenShared/UI/Auth/IntroCarousel/IntroCarouselView+SnapshotTests.swift similarity index 75% rename from BitwardenShared/UI/Auth/IntroCarousel/IntroCarouselViewTests.swift rename to BitwardenShared/UI/Auth/IntroCarousel/IntroCarouselView+SnapshotTests.swift index 54c9ef02f..fda5acb09 100644 --- a/BitwardenShared/UI/Auth/IntroCarousel/IntroCarouselViewTests.swift +++ b/BitwardenShared/UI/Auth/IntroCarousel/IntroCarouselView+SnapshotTests.swift @@ -1,6 +1,6 @@ +// swiftlint:disable:this file_name import BitwardenResources import SnapshotTesting -import ViewInspector import XCTest @testable import BitwardenShared @@ -28,24 +28,6 @@ class IntroCarouselViewTests: BitwardenTestCase { subject = nil } - // MARK: Tests - - /// Tapping the create account button performs the create account effect. - @MainActor - func test_createAccount_tap() async throws { - let button = try subject.inspect().find(asyncButton: Localizations.createAccount) - try await button.tap() - XCTAssertEqual(processor.effects.last, .createAccount) - } - - /// Tapping the log in button dispatches the login action. - @MainActor - func test_login_tap() throws { - let button = try subject.inspect().find(button: Localizations.logIn) - try button.tap() - XCTAssertEqual(processor.dispatchedActions.last, .logIn) - } - // MARK: Snapshots /// The intro carousel page 1 renders correctly. diff --git a/BitwardenShared/UI/Auth/IntroCarousel/IntroCarouselView+ViewInspectorTests.swift b/BitwardenShared/UI/Auth/IntroCarousel/IntroCarouselView+ViewInspectorTests.swift new file mode 100644 index 000000000..107b245b6 --- /dev/null +++ b/BitwardenShared/UI/Auth/IntroCarousel/IntroCarouselView+ViewInspectorTests.swift @@ -0,0 +1,48 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import ViewInspector +import XCTest + +@testable import BitwardenShared + +class IntroCarouselViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: IntroCarouselView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: IntroCarouselState()) + + subject = IntroCarouselView(store: Store(processor: processor)) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Tests + + /// Tapping the create account button performs the create account effect. + @MainActor + func test_createAccount_tap() async throws { + let button = try subject.inspect().find(asyncButton: Localizations.createAccount) + try await button.tap() + XCTAssertEqual(processor.effects.last, .createAccount) + } + + /// Tapping the log in button dispatches the login action. + @MainActor + func test_login_tap() throws { + let button = try subject.inspect().find(button: Localizations.logIn) + try button.tap() + XCTAssertEqual(processor.dispatchedActions.last, .logIn) + } +} diff --git a/BitwardenShared/UI/Auth/Landing/LandingView+SnapshotTests.swift b/BitwardenShared/UI/Auth/Landing/LandingView+SnapshotTests.swift new file mode 100644 index 000000000..c4bbdf4d2 --- /dev/null +++ b/BitwardenShared/UI/Auth/Landing/LandingView+SnapshotTests.swift @@ -0,0 +1,90 @@ +// swiftlint:disable:this file_name +import BitwardenKit +import BitwardenResources +import SnapshotTesting +import SwiftUI +import XCTest + +@testable import BitwardenShared + +// MARK: - LandingViewTests + +class LandingViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: LandingView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + processor = MockProcessor(state: LandingState()) + let store = Store(processor: processor) + subject = LandingView(store: store) + } + + override func tearDown() { + super.tearDown() + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// Check the snapshot for the empty state. + @MainActor + func disabletest_snapshot_empty() { + assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) + } + + /// Check the snapshot when the email text field has a value. + @MainActor + func disabletest_snapshot_email_value() { + processor.state.email = "email@example.com" + assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) + } + + /// Check the snapshot when the remember me toggle is on. + @MainActor + func disabletest_snapshot_isRememberMeOn_true() { + processor.state.isRememberMeOn = true + assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) + } + + /// Check the snapshot for the profiles visible + @MainActor + func disabletest_snapshot_profilesVisible() { + let account = ProfileSwitcherItem.fixture( + email: "extra.warden@bitwarden.com", + userInitials: "EW", + ) + processor.state.profileSwitcherState = ProfileSwitcherState( + accounts: [ + account, + ], + activeAccountId: account.userId, + allowLockAndLogout: true, + isVisible: true, + ) + assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) + } + + /// Check the snapshot for the profiles closed + @MainActor + func disabletest_snapshot_profilesClosed() { + let account = ProfileSwitcherItem.fixture( + email: "extra.warden@bitwarden.com", + userInitials: "EW", + ) + processor.state.profileSwitcherState = ProfileSwitcherState( + accounts: [ + account, + ], + activeAccountId: account.userId, + allowLockAndLogout: true, + isVisible: false, + ) + assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) + } +} diff --git a/BitwardenShared/UI/Auth/Landing/LandingViewTests.swift b/BitwardenShared/UI/Auth/Landing/LandingView+ViewInspectorTests.swift similarity index 64% rename from BitwardenShared/UI/Auth/Landing/LandingViewTests.swift rename to BitwardenShared/UI/Auth/Landing/LandingView+ViewInspectorTests.swift index c21c39516..23839ba0d 100644 --- a/BitwardenShared/UI/Auth/Landing/LandingViewTests.swift +++ b/BitwardenShared/UI/Auth/Landing/LandingView+ViewInspectorTests.swift @@ -1,6 +1,6 @@ +// swiftlint:disable:this file_name import BitwardenKit import BitwardenResources -import SnapshotTesting import SwiftUI import ViewInspector import XCTest @@ -102,62 +102,4 @@ class LandingViewTests: BitwardenTestCase { try toggle.tap() XCTAssertEqual(processor.dispatchedActions.last, .rememberMeChanged(true)) } - - // MARK: Snapshots - - /// Check the snapshot for the empty state. - @MainActor - func disabletest_snapshot_empty() { - assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) - } - - /// Check the snapshot when the email text field has a value. - @MainActor - func disabletest_snapshot_email_value() { - processor.state.email = "email@example.com" - assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) - } - - /// Check the snapshot when the remember me toggle is on. - @MainActor - func disabletest_snapshot_isRememberMeOn_true() { - processor.state.isRememberMeOn = true - assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) - } - - /// Check the snapshot for the profiles visible - @MainActor - func disabletest_snapshot_profilesVisible() { - let account = ProfileSwitcherItem.fixture( - email: "extra.warden@bitwarden.com", - userInitials: "EW", - ) - processor.state.profileSwitcherState = ProfileSwitcherState( - accounts: [ - account, - ], - activeAccountId: account.userId, - allowLockAndLogout: true, - isVisible: true, - ) - assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) - } - - /// Check the snapshot for the profiles closed - @MainActor - func disabletest_snapshot_profilesClosed() { - let account = ProfileSwitcherItem.fixture( - email: "extra.warden@bitwarden.com", - userInitials: "EW", - ) - processor.state.profileSwitcherState = ProfileSwitcherState( - accounts: [ - account, - ], - activeAccountId: account.userId, - allowLockAndLogout: true, - isVisible: false, - ) - assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) - } } diff --git a/BitwardenShared/UI/Auth/Landing/SelfHosted/SelfHostedView+SnapshotTests.swift b/BitwardenShared/UI/Auth/Landing/SelfHosted/SelfHostedView+SnapshotTests.swift new file mode 100644 index 000000000..d61828169 --- /dev/null +++ b/BitwardenShared/UI/Auth/Landing/SelfHosted/SelfHostedView+SnapshotTests.swift @@ -0,0 +1,36 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class SelfHostedViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: SelfHostedView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: SelfHostedState()) + + subject = SelfHostedView(store: Store(processor: processor)) + } + + override func tearDown() { + super.tearDown() + + subject = nil + } + + // MARK: Snapshots + + /// Tests that the view renders correctly. + func disabletest_snapshot_viewRender() { + assertSnapshot(of: subject.navStackWrapped, as: .defaultPortrait) + } +} diff --git a/BitwardenShared/UI/Auth/Landing/SelfHosted/SelfHostedViewTests.swift b/BitwardenShared/UI/Auth/Landing/SelfHosted/SelfHostedView+ViewInspectorTests.swift similarity index 86% rename from BitwardenShared/UI/Auth/Landing/SelfHosted/SelfHostedViewTests.swift rename to BitwardenShared/UI/Auth/Landing/SelfHosted/SelfHostedView+ViewInspectorTests.swift index 40ef7c965..50d038ded 100644 --- a/BitwardenShared/UI/Auth/Landing/SelfHosted/SelfHostedViewTests.swift +++ b/BitwardenShared/UI/Auth/Landing/SelfHosted/SelfHostedView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import XCTest @testable import BitwardenShared @@ -48,11 +48,4 @@ class SelfHostedViewTests: BitwardenTestCase { try await button.tap() XCTAssertEqual(processor.effects.last, .saveEnvironment) } - - // MARK: Snapshots - - /// Tests that the view renders correctly. - func disabletest_snapshot_viewRender() { - assertSnapshot(of: subject.navStackWrapped, as: .defaultPortrait) - } } diff --git a/BitwardenShared/UI/Auth/Login/LoginDecryptionOptions/LoginDecryptionOptionsView+SnapshotTests.swift b/BitwardenShared/UI/Auth/Login/LoginDecryptionOptions/LoginDecryptionOptionsView+SnapshotTests.swift new file mode 100644 index 000000000..1222b23d8 --- /dev/null +++ b/BitwardenShared/UI/Auth/Login/LoginDecryptionOptions/LoginDecryptionOptionsView+SnapshotTests.swift @@ -0,0 +1,52 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class LoginDecryptionOptionsViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor< + LoginDecryptionOptionsState, + LoginDecryptionOptionsAction, + LoginDecryptionOptionsEffect, + >! + var subject: LoginDecryptionOptionsView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor( + state: LoginDecryptionOptionsState( + shouldShowApproveMasterPasswordButton: true, + shouldShowApproveWithOtherDeviceButton: true, + shouldShowContinueButton: true, + email: "example@bitwarden.com", + isRememberDeviceToggleOn: true, + orgIdentifier: "Bitwarden", + shouldShowAdminApprovalButton: true, + ), + ) + let store = Store(processor: processor) + + subject = LoginDecryptionOptionsView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// The default view renders correctly. + func disabletest_snapshot_default() { + assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) + } +} diff --git a/BitwardenShared/UI/Auth/Login/LoginDecryptionOptions/LoginDecryptionOptionsViewTests.swift b/BitwardenShared/UI/Auth/Login/LoginDecryptionOptions/LoginDecryptionOptionsView+ViewInspectorTests.swift similarity index 93% rename from BitwardenShared/UI/Auth/Login/LoginDecryptionOptions/LoginDecryptionOptionsViewTests.swift rename to BitwardenShared/UI/Auth/Login/LoginDecryptionOptions/LoginDecryptionOptionsView+ViewInspectorTests.swift index 17f8842ad..ae5f517f6 100644 --- a/BitwardenShared/UI/Auth/Login/LoginDecryptionOptions/LoginDecryptionOptionsViewTests.swift +++ b/BitwardenShared/UI/Auth/Login/LoginDecryptionOptions/LoginDecryptionOptionsView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import ViewInspector import XCTest @@ -95,11 +95,4 @@ class LoginDecryptionOptionsViewTests: BitwardenTestCase { try toggle.tap() XCTAssertEqual(processor.dispatchedActions.last, .toggleRememberDevice(true)) } - - // MARK: Snapshots - - /// The default view renders correctly. - func disabletest_snapshot_default() { - assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) - } } diff --git a/BitwardenShared/UI/Auth/Login/LoginView+SnapshotTests.swift b/BitwardenShared/UI/Auth/Login/LoginView+SnapshotTests.swift new file mode 100644 index 000000000..f0fd3deab --- /dev/null +++ b/BitwardenShared/UI/Auth/Login/LoginView+SnapshotTests.swift @@ -0,0 +1,73 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import SwiftUI +import XCTest + +@testable import BitwardenShared + +// MARK: - LoginViewTests + +class LoginViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: LoginView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + processor = MockProcessor(state: LoginState()) + let store = Store(processor: processor) + subject = LoginView(store: store) + } + + override func tearDown() { + super.tearDown() + processor = nil + subject = nil + } + + // MARK: Snapshots + + @MainActor + func disabletest_snapshot_empty() { + processor.state.username = "user@bitwarden.com" + processor.state.serverURLString = "bitwarden.com" + assertSnapshot(of: subject, as: .defaultPortrait) + } + + @MainActor + func disabletest_snapshot_passwordHidden() { + processor.state.username = "user@bitwarden.com" + processor.state.masterPassword = "Password" + processor.state.serverURLString = "bitwarden.com" + processor.state.isMasterPasswordRevealed = false + assertSnapshot(of: subject, as: .defaultPortrait) + } + + @MainActor + func disabletest_snapshot_passwordRevealed() { + processor.state.username = "user@bitwarden.com" + processor.state.masterPassword = "Password" + processor.state.serverURLString = "bitwarden.com" + processor.state.isMasterPasswordRevealed = true + assertSnapshot(of: subject, as: .defaultPortrait) + } + + @MainActor + func disabletest_snapshot_selfHosted() { + processor.state.username = "user@bitwarden.com" + processor.state.serverURLString = "selfhostedserver.com" + assertSnapshot(of: subject, as: .defaultPortrait) + } + + @MainActor + func disabletest_snapshot_withDevice() { + processor.state.username = "user@bitwarden.com" + processor.state.isLoginWithDeviceVisible = true + processor.state.serverURLString = "bitwarden.com" + assertSnapshot(of: subject, as: .defaultPortrait) + } +} diff --git a/BitwardenShared/UI/Auth/Login/LoginViewTests.swift b/BitwardenShared/UI/Auth/Login/LoginView+ViewInspectorTests.swift similarity index 75% rename from BitwardenShared/UI/Auth/Login/LoginViewTests.swift rename to BitwardenShared/UI/Auth/Login/LoginView+ViewInspectorTests.swift index 96e98154c..62139f7d8 100644 --- a/BitwardenShared/UI/Auth/Login/LoginViewTests.swift +++ b/BitwardenShared/UI/Auth/Login/LoginView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import SwiftUI import ViewInspector import XCTest @@ -121,46 +121,4 @@ class LoginViewTests: BitwardenTestCase { try secureField.setInput("text") XCTAssertEqual(processor.dispatchedActions.last, .masterPasswordChanged("text")) } - - // MARK: Snapshots - - @MainActor - func disabletest_snapshot_empty() { - processor.state.username = "user@bitwarden.com" - processor.state.serverURLString = "bitwarden.com" - assertSnapshot(of: subject, as: .defaultPortrait) - } - - @MainActor - func disabletest_snapshot_passwordHidden() { - processor.state.username = "user@bitwarden.com" - processor.state.masterPassword = "Password" - processor.state.serverURLString = "bitwarden.com" - processor.state.isMasterPasswordRevealed = false - assertSnapshot(of: subject, as: .defaultPortrait) - } - - @MainActor - func disabletest_snapshot_passwordRevealed() { - processor.state.username = "user@bitwarden.com" - processor.state.masterPassword = "Password" - processor.state.serverURLString = "bitwarden.com" - processor.state.isMasterPasswordRevealed = true - assertSnapshot(of: subject, as: .defaultPortrait) - } - - @MainActor - func disabletest_snapshot_selfHosted() { - processor.state.username = "user@bitwarden.com" - processor.state.serverURLString = "selfhostedserver.com" - assertSnapshot(of: subject, as: .defaultPortrait) - } - - @MainActor - func disabletest_snapshot_withDevice() { - processor.state.username = "user@bitwarden.com" - processor.state.isLoginWithDeviceVisible = true - processor.state.serverURLString = "bitwarden.com" - assertSnapshot(of: subject, as: .defaultPortrait) - } } diff --git a/BitwardenShared/UI/Auth/Login/LoginWithDevice/LoginWithDeviceView+SnapshotTests.swift b/BitwardenShared/UI/Auth/Login/LoginWithDevice/LoginWithDeviceView+SnapshotTests.swift new file mode 100644 index 000000000..00c5829be --- /dev/null +++ b/BitwardenShared/UI/Auth/Login/LoginWithDevice/LoginWithDeviceView+SnapshotTests.swift @@ -0,0 +1,42 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class LoginWithDeviceViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: LoginWithDeviceView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor( + state: LoginWithDeviceState( + fingerprintPhrase: "some-weird-long-text-thing-as-a-placeholder", + ), + ) + let store = Store(processor: processor) + + subject = LoginWithDeviceView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// The default view renders correctly. + func disabletest_snapshot_default() { + assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) + } +} diff --git a/BitwardenShared/UI/Auth/Login/LoginWithDevice/LoginWithDeviceViewTests.swift b/BitwardenShared/UI/Auth/Login/LoginWithDevice/LoginWithDeviceView+ViewInspectorTests.swift similarity index 88% rename from BitwardenShared/UI/Auth/Login/LoginWithDevice/LoginWithDeviceViewTests.swift rename to BitwardenShared/UI/Auth/Login/LoginWithDevice/LoginWithDeviceView+ViewInspectorTests.swift index 83db7268d..55ae2c973 100644 --- a/BitwardenShared/UI/Auth/Login/LoginWithDevice/LoginWithDeviceViewTests.swift +++ b/BitwardenShared/UI/Auth/Login/LoginWithDevice/LoginWithDeviceView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import XCTest @testable import BitwardenShared @@ -57,11 +57,4 @@ class LoginWithDeviceViewTests: BitwardenTestCase { try button.tap() XCTAssertEqual(processor.dispatchedActions.last, .dismiss) } - - // MARK: Snapshots - - /// The default view renders correctly. - func disabletest_snapshot_default() { - assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) - } } diff --git a/BitwardenShared/UI/Auth/Login/SingleSignOn/SingleSignOnView+SnapshotTests.swift b/BitwardenShared/UI/Auth/Login/SingleSignOn/SingleSignOnView+SnapshotTests.swift new file mode 100644 index 000000000..8a0f5d598 --- /dev/null +++ b/BitwardenShared/UI/Auth/Login/SingleSignOn/SingleSignOnView+SnapshotTests.swift @@ -0,0 +1,51 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class SingleSignOnViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: SingleSignOnView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: SingleSignOnState()) + let store = Store(processor: processor) + + subject = SingleSignOnView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// Tests the view renders correctly when the text field is empty. + func disabletest_snapshot_empty() { + assertSnapshots( + of: subject.navStackWrapped, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } + + /// Tests the view renders correctly when the text field is populated. + @MainActor + func disabletest_snapshot_populated() { + processor.state.identifierText = "Insert cool identifier here" + assertSnapshots( + of: subject.navStackWrapped, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } +} diff --git a/BitwardenShared/UI/Auth/Login/SingleSignOn/SingleSignOnViewTests.swift b/BitwardenShared/UI/Auth/Login/SingleSignOn/SingleSignOnView+ViewInspectorTests.swift similarity index 70% rename from BitwardenShared/UI/Auth/Login/SingleSignOn/SingleSignOnViewTests.swift rename to BitwardenShared/UI/Auth/Login/SingleSignOn/SingleSignOnView+ViewInspectorTests.swift index 50e1027e5..16d5a4dbb 100644 --- a/BitwardenShared/UI/Auth/Login/SingleSignOn/SingleSignOnViewTests.swift +++ b/BitwardenShared/UI/Auth/Login/SingleSignOn/SingleSignOnView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import XCTest @testable import BitwardenShared @@ -54,24 +54,4 @@ class SingleSignOnViewTests: BitwardenTestCase { XCTAssertEqual(processor.effects.last, .loginTapped) } - - // MARK: Snapshots - - /// Tests the view renders correctly when the text field is empty. - func disabletest_snapshot_empty() { - assertSnapshots( - of: subject.navStackWrapped, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } - - /// Tests the view renders correctly when the text field is populated. - @MainActor - func disabletest_snapshot_populated() { - processor.state.identifierText = "Insert cool identifier here" - assertSnapshots( - of: subject.navStackWrapped, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } } diff --git a/BitwardenShared/UI/Auth/Login/TwoFactorAuth/TwoFactorAuthViewTests.swift b/BitwardenShared/UI/Auth/Login/TwoFactorAuth/TwoFactorAuthView+SnapshotTests.swift similarity index 56% rename from BitwardenShared/UI/Auth/Login/TwoFactorAuth/TwoFactorAuthViewTests.swift rename to BitwardenShared/UI/Auth/Login/TwoFactorAuth/TwoFactorAuthView+SnapshotTests.swift index f3757c472..8e7489c51 100644 --- a/BitwardenShared/UI/Auth/Login/TwoFactorAuth/TwoFactorAuthViewTests.swift +++ b/BitwardenShared/UI/Auth/Login/TwoFactorAuth/TwoFactorAuthView+SnapshotTests.swift @@ -1,6 +1,6 @@ +// swiftlint:disable:this file_name import BitwardenResources import SnapshotTesting -import ViewInspector import XCTest @testable import BitwardenShared @@ -29,71 +29,6 @@ class TwoFactorAuthViewTests: BitwardenTestCase { subject = nil } - // MARK: Tests - - /// Tapping an auth method button dispatches the `.authMethodSelected()` action. - @MainActor - func test_authMethodButton_tap() throws { - processor.state.availableAuthMethods = [.recoveryCode] - let menu = try subject.inspect().find(ViewType.Menu.self, containing: Localizations.useAnotherTwoStepMethod) - let subMenu = try menu.find(ViewType.Menu.self, containing: Localizations.recoveryCodeTitle) - let button = try subMenu.find(button: Localizations.recoveryCodeTitle) - try button.tap() - XCTAssertEqual(processor.dispatchedActions.last, .authMethodSelected(.recoveryCode)) - } - - /// Tapping the cancel button dispatches the `.dismiss` action. - @MainActor - func test_cancelButton_tap() throws { - let button = try subject.inspect().findCancelToolbarButton() - try button.tap() - XCTAssertEqual(processor.dispatchedActions.last, .dismiss) - } - - /// Tapping the continue button performs the `.continueTapped` effect. - @MainActor - func test_continueButton_tap() async throws { - let button = try subject.inspect().find(asyncButton: Localizations.continue) - try await button.tap() - XCTAssertEqual(processor.effects.last, .continueTapped) - } - - /// Tapping the duo button performs the `.beginDuoAuth` effect. - @MainActor - func test_launchDuo_tap() async throws { - processor.state.authMethod = .duo - let button = try subject.inspect().find(asyncButton: Localizations.launchDuo) - try await button.tap() - XCTAssertEqual(processor.effects.last, .beginDuoAuth) - } - - /// Changing the remember me toggle dispatches the `.rememberMeToggleChanged(_)` action. - @MainActor - func test_rememberMeToggle_changed() throws { - if #available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *) { - throw XCTSkip("Unable to run test in iOS 16, keep an eye on ViewInspector to see if it gets updated.") - } - let toggle = try subject.inspect().find(ViewType.Toggle.self) - try toggle.tap() - XCTAssertEqual(processor.dispatchedActions.last, .rememberMeToggleChanged(true)) - } - - /// Tapping the resend email button performs the `.resendEmailTapped` effect. - @MainActor - func test_resendEmailButton_tap() async throws { - let button = try subject.inspect().find(asyncButton: Localizations.resendCode) - try await button.tap() - XCTAssertEqual(processor.effects.last, .resendEmailTapped) - } - - /// Updating the value in the verification code text field dispatches the `.verificationCodeChanged(_)` action. - @MainActor - func test_verificationCode_updateValue() throws { - let textField = try subject.inspect().find(textField: "") - try textField.setInput("text") - XCTAssertEqual(processor.dispatchedActions.last, .verificationCodeChanged("text")) - } - // MARK: Snapshots /// The default view renders correctly for the authenticator app method. diff --git a/BitwardenShared/UI/Auth/Login/TwoFactorAuth/TwoFactorAuthView+ViewInspectorTests.swift b/BitwardenShared/UI/Auth/Login/TwoFactorAuth/TwoFactorAuthView+ViewInspectorTests.swift new file mode 100644 index 000000000..34e092ec1 --- /dev/null +++ b/BitwardenShared/UI/Auth/Login/TwoFactorAuth/TwoFactorAuthView+ViewInspectorTests.swift @@ -0,0 +1,96 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import ViewInspector +import XCTest + +@testable import BitwardenShared + +class TwoFactorAuthViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: TwoFactorAuthView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: TwoFactorAuthState(displayEmail: "sh***@livefront.com")) + let store = Store(processor: processor) + + subject = TwoFactorAuthView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Tests + + /// Tapping an auth method button dispatches the `.authMethodSelected()` action. + @MainActor + func test_authMethodButton_tap() throws { + processor.state.availableAuthMethods = [.recoveryCode] + let menu = try subject.inspect().find(ViewType.Menu.self, containing: Localizations.useAnotherTwoStepMethod) + let subMenu = try menu.find(ViewType.Menu.self, containing: Localizations.recoveryCodeTitle) + let button = try subMenu.find(button: Localizations.recoveryCodeTitle) + try button.tap() + XCTAssertEqual(processor.dispatchedActions.last, .authMethodSelected(.recoveryCode)) + } + + /// Tapping the cancel button dispatches the `.dismiss` action. + @MainActor + func test_cancelButton_tap() throws { + let button = try subject.inspect().findCancelToolbarButton() + try button.tap() + XCTAssertEqual(processor.dispatchedActions.last, .dismiss) + } + + /// Tapping the continue button performs the `.continueTapped` effect. + @MainActor + func test_continueButton_tap() async throws { + let button = try subject.inspect().find(asyncButton: Localizations.continue) + try await button.tap() + XCTAssertEqual(processor.effects.last, .continueTapped) + } + + /// Tapping the duo button performs the `.beginDuoAuth` effect. + @MainActor + func test_launchDuo_tap() async throws { + processor.state.authMethod = .duo + let button = try subject.inspect().find(asyncButton: Localizations.launchDuo) + try await button.tap() + XCTAssertEqual(processor.effects.last, .beginDuoAuth) + } + + /// Changing the remember me toggle dispatches the `.rememberMeToggleChanged(_)` action. + @MainActor + func test_rememberMeToggle_changed() throws { + if #available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *) { + throw XCTSkip("Unable to run test in iOS 16, keep an eye on ViewInspector to see if it gets updated.") + } + let toggle = try subject.inspect().find(ViewType.Toggle.self) + try toggle.tap() + XCTAssertEqual(processor.dispatchedActions.last, .rememberMeToggleChanged(true)) + } + + /// Tapping the resend email button performs the `.resendEmailTapped` effect. + @MainActor + func test_resendEmailButton_tap() async throws { + let button = try subject.inspect().find(asyncButton: Localizations.resendCode) + try await button.tap() + XCTAssertEqual(processor.effects.last, .resendEmailTapped) + } + + /// Updating the value in the verification code text field dispatches the `.verificationCodeChanged(_)` action. + @MainActor + func test_verificationCode_updateValue() throws { + let textField = try subject.inspect().find(textField: "") + try textField.setInput("text") + XCTAssertEqual(processor.dispatchedActions.last, .verificationCodeChanged("text")) + } +} diff --git a/BitwardenShared/UI/Auth/PasswordHint/PasswordHintView+SnapshotTests.swift b/BitwardenShared/UI/Auth/PasswordHint/PasswordHintView+SnapshotTests.swift new file mode 100644 index 000000000..a457923cc --- /dev/null +++ b/BitwardenShared/UI/Auth/PasswordHint/PasswordHintView+SnapshotTests.swift @@ -0,0 +1,46 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +// MARK: - PasswordHintViewTests + +class PasswordHintViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: PasswordHintView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + let state = PasswordHintState() + processor = MockProcessor(state: state) + subject = PasswordHintView(store: Store(processor: processor)) + } + + override func tearDown() { + super.tearDown() + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// A snapshot of the view without any values set. + @MainActor + func disabletest_snapshot_empty() { + processor.state.emailAddress = "" + assertSnapshot(of: subject.navStackWrapped, as: .defaultPortrait) + } + + /// A snapshot of the view with a value in the email address field. + @MainActor + func disabletest_snapshot_withEmailAddress() { + processor.state.emailAddress = "email@example.com" + assertSnapshots(of: subject.navStackWrapped, as: [.defaultPortrait, .defaultPortraitAX5, .defaultPortraitDark]) + } +} diff --git a/BitwardenShared/UI/Auth/PasswordHint/PasswordHintViewTests.swift b/BitwardenShared/UI/Auth/PasswordHint/PasswordHintView+ViewInspectorTests.swift similarity index 74% rename from BitwardenShared/UI/Auth/PasswordHint/PasswordHintViewTests.swift rename to BitwardenShared/UI/Auth/PasswordHint/PasswordHintView+ViewInspectorTests.swift index b5e3ed202..d7e9b5309 100644 --- a/BitwardenShared/UI/Auth/PasswordHint/PasswordHintViewTests.swift +++ b/BitwardenShared/UI/Auth/PasswordHint/PasswordHintView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import ViewInspector import XCTest @@ -54,20 +54,4 @@ class PasswordHintViewTests: BitwardenTestCase { try await button.tap() XCTAssertEqual(processor.effects.last, .submitPressed) } - - // MARK: Snapshots - - /// A snapshot of the view without any values set. - @MainActor - func disabletest_snapshot_empty() { - processor.state.emailAddress = "" - assertSnapshot(of: subject.navStackWrapped, as: .defaultPortrait) - } - - /// A snapshot of the view with a value in the email address field. - @MainActor - func disabletest_snapshot_withEmailAddress() { - processor.state.emailAddress = "email@example.com" - assertSnapshots(of: subject.navStackWrapped, as: [.defaultPortrait, .defaultPortraitAX5, .defaultPortraitDark]) - } } diff --git a/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherHandlerTests.swift b/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherHandlerTests.swift index 6b8117c05..a91e86262 100644 --- a/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherHandlerTests.swift +++ b/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherHandlerTests.swift @@ -2,7 +2,6 @@ import BitwardenKit import BitwardenKitMocks import BitwardenResources import BitwardenSdk -import SnapshotTesting import SwiftUI import XCTest diff --git a/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherRowTests.swift b/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherRow+SnapshotTests.swift similarity index 98% rename from BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherRowTests.swift rename to BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherRow+SnapshotTests.swift index dab9aa34f..ea5786f03 100644 --- a/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherRowTests.swift +++ b/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherRow+SnapshotTests.swift @@ -1,6 +1,6 @@ +// swiftlint:disable:this file_name import SnapshotTesting import SwiftUI -import ViewInspector import XCTest @testable import BitwardenShared diff --git a/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherSheet+SnapshotTests.swift b/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherSheet+SnapshotTests.swift new file mode 100644 index 000000000..2c6377cb5 --- /dev/null +++ b/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherSheet+SnapshotTests.swift @@ -0,0 +1,159 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import BitwardenSdk +import SnapshotTesting +import SwiftUI +import XCTest + +@testable import BitwardenShared + +// MARK: - ProfileSwitcherSheet Tests + +class ProfileSwitcherSheetTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: ProfileSwitcherSheet! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + let account = ProfileSwitcherItem.anneAccount + let state = ProfileSwitcherState( + accounts: [account], + activeAccountId: account.userId, + allowLockAndLogout: true, + isVisible: true, + ) + processor = MockProcessor(state: state) + subject = ProfileSwitcherSheet(store: Store(processor: processor)) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + // NB: There's not really a good way, it seems, to capture a view hierarchy when it's presenting a sheet. + // cf. https://github.com/pointfreeco/swift-snapshot-testing/discussions/956 + + func disabletest_snapshot_singleAccount() { + assertSnapshot(of: NavigationView { subject }, as: .defaultPortrait) + } + + @MainActor + func disabletest_snapshot_multiAccount_unlocked_belowMaximum() { + processor.state = ProfileSwitcherState( + accounts: [ + ProfileSwitcherItem.anneAccount, + ProfileSwitcherItem.fixture( + color: .yellow, + email: "bonus.bridge@bitwarden.com", + isUnlocked: true, + userInitials: "BB", + ), + ProfileSwitcherItem.fixture( + color: .teal, + email: "concurrent.claim@bitarden.com", + isUnlocked: true, + userInitials: "CC", + ), + ProfileSwitcherItem.fixture( + color: .indigo, + email: "double.dip@bitwarde.com", + isUnlocked: true, + userInitials: "DD", + ), + ], + activeAccountId: ProfileSwitcherItem.anneAccount.userId, + allowLockAndLogout: true, + isVisible: true, + ) + assertSnapshot(of: NavigationView { subject }, as: .defaultPortrait) + } + + @MainActor + func disabletest_snapshot_multiAccount_unlocked_atMaximum() { + processor.state = ProfileSwitcherState.maximumAccounts + assertSnapshot(of: NavigationView { subject }, as: .defaultPortrait) + } + + @MainActor + func disabletest_snapshot_multiAccount_unlocked_atMaximum_largeText() { + processor.state = ProfileSwitcherState.maximumAccounts + assertSnapshot(of: NavigationView { subject }, as: .defaultPortraitAX5) + } + + @MainActor + func disabletest_snapshot_multiAccount_locked_belowMaximum() { + processor.state = ProfileSwitcherState( + accounts: [ + ProfileSwitcherItem.fixture( + color: .yellow, + email: "bonus.bridge@bitwarden.com", + isUnlocked: false, + userInitials: "BB", + ), + ProfileSwitcherItem.fixture( + color: .teal, + email: "concurrent.claim@bitarden.com", + isUnlocked: false, + userInitials: "CC", + ), + ProfileSwitcherItem.anneAccount, + ProfileSwitcherItem.fixture( + color: .indigo, + email: "double.dip@bitwarde.com", + isUnlocked: false, + userInitials: "DD", + ), + ], + activeAccountId: ProfileSwitcherItem.anneAccount.userId, + allowLockAndLogout: true, + isVisible: true, + ) + assertSnapshot(of: NavigationView { subject }, as: .defaultPortrait) + } + + @MainActor + func disabletest_snapshot_multiAccount_locked_atMaximum() { + processor.state = ProfileSwitcherState( + accounts: [ + ProfileSwitcherItem.fixture( + color: .yellow, + email: "bonus.bridge@bitwarden.com", + isUnlocked: false, + userInitials: "BB", + ), + ProfileSwitcherItem.fixture( + color: .teal, + email: "concurrent.claim@bitarden.com", + isUnlocked: false, + userInitials: "CC", + ), + .anneAccount, + ProfileSwitcherItem.fixture( + color: .indigo, + email: "double.dip@bitwarde.com", + isUnlocked: false, + userInitials: "DD", + ), + ProfileSwitcherItem.fixture( + color: .green, + email: "extra.edition@bitwarden.com", + isUnlocked: false, + userInitials: "EE", + ), + ], + activeAccountId: ProfileSwitcherItem.anneAccount.userId, + allowLockAndLogout: true, + isVisible: true, + ) + assertSnapshot(of: NavigationView { subject }, as: .defaultPortrait) + } +} diff --git a/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherSheet+ViewInspectorTests.swift b/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherSheet+ViewInspectorTests.swift new file mode 100644 index 000000000..73cbca5b1 --- /dev/null +++ b/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherSheet+ViewInspectorTests.swift @@ -0,0 +1,193 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import BitwardenSdk +import SwiftUI +import ViewInspector +import XCTest + +@testable import BitwardenShared + +// MARK: - ProfileSwitcherSheet Tests + +class ProfileSwitcherSheetTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: ProfileSwitcherSheet! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + let account = ProfileSwitcherItem.anneAccount + let state = ProfileSwitcherState( + accounts: [account], + activeAccountId: account.userId, + allowLockAndLogout: true, + isVisible: true, + ) + processor = MockProcessor(state: state) + subject = ProfileSwitcherSheet(store: Store(processor: processor)) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Tests + + /// Long pressing a profile row dispatches the `.accountLongPressed` action. + @MainActor + func test_accountRow_longPress_currentAccount() throws { + let accountRow = try subject.inspect().find(button: "anne.account@bitwarden.com") + try accountRow.labelView().callOnLongPressGesture() + let currentAccount = processor.state.activeAccountProfile! + waitFor(!processor.effects.isEmpty) + + XCTAssertEqual(processor.effects.last, .accountLongPressed(currentAccount)) + } + + /// Long pressing is disabled if lock and logout are not available. + @MainActor + func test_accountRow_longPress_currentAccount_noLockOrLogout() throws { + processor.state.allowLockAndLogout = false + processor.state.accounts[0].canBeLocked = false + let accountRow = try subject.inspect().find(button: "anne.account@bitwarden.com") + XCTAssertThrowsError(try accountRow.labelView().callOnLongPressGesture()) + } + + /// Tapping a profile row dispatches the `.accountPressed` action. + @MainActor + func test_accountRow_tap_currentAccount() throws { + let accountRow = try subject.inspect().find(button: "anne.account@bitwarden.com") + try accountRow.labelView().callOnTapGesture() + let currentAccount = processor.state.activeAccountProfile! + waitFor(!processor.effects.isEmpty) + + XCTAssertEqual(processor.effects.last, .accountPressed(currentAccount)) + } + + /// Tapping a profile row dispatches the `.accountPressed` action. + @MainActor + func test_accountRow_tap_addAccount() throws { + let addAccountRow = try subject.inspect().find(button: "Add account") + try addAccountRow.tap() + waitFor(!processor.effects.isEmpty) + + XCTAssertEqual(processor.effects.last, .addAccountPressed) + } + + /// Long pressing an alternative profile row dispatches the `.accountLongPressed` action. + @MainActor + func test_alternateAccountRow_longPress_alternateAccount() throws { + let alternate = ProfileSwitcherItem.fixture( + email: "alternate@bitwarden.com", + userInitials: "NA", + ) + let current = processor.state.activeAccountProfile! + processor.state = ProfileSwitcherState( + accounts: [ + alternate, + current, + ], + activeAccountId: current.userId, + allowLockAndLogout: true, + isVisible: true, + ) + let alternateRow = try subject.inspect().find(button: "alternate@bitwarden.com") + try alternateRow.labelView().callOnLongPressGesture() + waitFor(!processor.effects.isEmpty) + + XCTAssertEqual(processor.effects.last, .accountLongPressed(alternate)) + } + + /// Long pressing is disabled if lock and logout are not available. + @MainActor + func test_alternateAccountRow_longPress_currentAccount_noLockOrLogout() throws { + let alternate = ProfileSwitcherItem.fixture( + canBeLocked: false, + email: "alternate@bitwarden.com", + userInitials: "NA", + ) + let current = processor.state.activeAccountProfile! + processor.state = ProfileSwitcherState( + accounts: [ + alternate, + current, + ], + activeAccountId: current.userId, + allowLockAndLogout: false, + isVisible: true, + ) + let alternateRow = try subject.inspect().find(button: "alternate@bitwarden.com") + _ = try subject.inspect().find(button: "anne.account@bitwarden.com") + XCTAssertThrowsError(try alternateRow.labelView().callOnLongPressGesture()) + } + + /// Tapping an alternative profile row dispatches the `.accountPressed` action. + @MainActor + func test_alternateAccountRow_tap_alternateAccount() throws { + let alternate = ProfileSwitcherItem.fixture( + email: "alternate@bitwarden.com", + userInitials: "NA", + ) + let current = processor.state.activeAccountProfile! + processor.state = ProfileSwitcherState( + accounts: [ + alternate, + current, + ], + activeAccountId: current.userId, + allowLockAndLogout: true, + isVisible: true, + ) + let alternateRow = try subject.inspect().find(button: "alternate@bitwarden.com") + try alternateRow.labelView().callOnTapGesture() + waitFor(!processor.effects.isEmpty) + + XCTAssertEqual(processor.effects.last, .accountPressed(alternate)) + } + + /// Tapping an alternative profile row dispatches the `.accountPressed` action. + @MainActor + func test_alternateAccountRows_tap_alternateEmptyAccount() throws { + let alternate = ProfileSwitcherItem.fixture( + email: "locked@bitwarden.com", + isUnlocked: false, + userInitials: "LA", + ) + let secondAlternate = ProfileSwitcherItem.fixture() + let alternateAccounts = [ + alternate, + secondAlternate, + ] + let current = processor.state.activeAccountProfile! + processor.state = ProfileSwitcherState( + accounts: alternateAccounts + [current], + activeAccountId: current.userId, + allowLockAndLogout: true, + isVisible: true, + ) + let secondAlternateRow = try subject.inspect().find(button: "") + try secondAlternateRow.labelView().callOnTapGesture() + waitFor(!processor.effects.isEmpty) + + XCTAssertEqual(processor.effects.last, .accountPressed(secondAlternate)) + } + + /// The close toolbar button closes the sheet. + @MainActor + func test_closeToolbarButton() throws { + let closeButton = try subject.inspect().findCloseToolbarButton() + try closeButton.tap() + XCTAssertEqual(processor.dispatchedActions.last, .dismissTapped) + } + + // MARK: Snapshots + + // NB: There's not really a good way, it seems, to capture a view hierarchy when it's presenting a sheet. + // cf. https://github.com/pointfreeco/swift-snapshot-testing/discussions/956 +} diff --git a/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherSheetTests.swift b/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherSheetTests.swift index 8a17798fb..a8d3183e3 100644 --- a/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherSheetTests.swift +++ b/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherSheetTests.swift @@ -1,16 +1,13 @@ import BitwardenResources import BitwardenSdk -import SnapshotTesting import SwiftUI -import ViewInspector import XCTest @testable import BitwardenShared // MARK: - ProfileSwitcherSheet Tests -class ProfileSwitcherSheetTests: BitwardenTestCase { // swiftlint:disable:this type_body_length - +class ProfileSwitcherSheetTests: BitwardenTestCase { // MARK: Properties var processor: MockProcessor! @@ -40,145 +37,6 @@ class ProfileSwitcherSheetTests: BitwardenTestCase { // swiftlint:disable:this t // MARK: Tests - /// Long pressing a profile row dispatches the `.accountLongPressed` action. - @MainActor - func test_accountRow_longPress_currentAccount() throws { - let accountRow = try subject.inspect().find(button: "anne.account@bitwarden.com") - try accountRow.labelView().callOnLongPressGesture() - let currentAccount = processor.state.activeAccountProfile! - waitFor(!processor.effects.isEmpty) - - XCTAssertEqual(processor.effects.last, .accountLongPressed(currentAccount)) - } - - /// Long pressing is disabled if lock and logout are not available. - @MainActor - func test_accountRow_longPress_currentAccount_noLockOrLogout() throws { - processor.state.allowLockAndLogout = false - processor.state.accounts[0].canBeLocked = false - let accountRow = try subject.inspect().find(button: "anne.account@bitwarden.com") - XCTAssertThrowsError(try accountRow.labelView().callOnLongPressGesture()) - } - - /// Tapping a profile row dispatches the `.accountPressed` action. - @MainActor - func test_accountRow_tap_currentAccount() throws { - let accountRow = try subject.inspect().find(button: "anne.account@bitwarden.com") - try accountRow.labelView().callOnTapGesture() - let currentAccount = processor.state.activeAccountProfile! - waitFor(!processor.effects.isEmpty) - - XCTAssertEqual(processor.effects.last, .accountPressed(currentAccount)) - } - - /// Tapping a profile row dispatches the `.accountPressed` action. - @MainActor - func test_accountRow_tap_addAccount() throws { - let addAccountRow = try subject.inspect().find(button: "Add account") - try addAccountRow.tap() - waitFor(!processor.effects.isEmpty) - - XCTAssertEqual(processor.effects.last, .addAccountPressed) - } - - /// Long pressing an alternative profile row dispatches the `.accountLongPressed` action. - @MainActor - func test_alternateAccountRow_longPress_alternateAccount() throws { - let alternate = ProfileSwitcherItem.fixture( - email: "alternate@bitwarden.com", - userInitials: "NA", - ) - let current = processor.state.activeAccountProfile! - processor.state = ProfileSwitcherState( - accounts: [ - alternate, - current, - ], - activeAccountId: current.userId, - allowLockAndLogout: true, - isVisible: true, - ) - let alternateRow = try subject.inspect().find(button: "alternate@bitwarden.com") - try alternateRow.labelView().callOnLongPressGesture() - waitFor(!processor.effects.isEmpty) - - XCTAssertEqual(processor.effects.last, .accountLongPressed(alternate)) - } - - /// Long pressing is disabled if lock and logout are not available. - @MainActor - func test_alternateAccountRow_longPress_currentAccount_noLockOrLogout() throws { - let alternate = ProfileSwitcherItem.fixture( - canBeLocked: false, - email: "alternate@bitwarden.com", - userInitials: "NA", - ) - let current = processor.state.activeAccountProfile! - processor.state = ProfileSwitcherState( - accounts: [ - alternate, - current, - ], - activeAccountId: current.userId, - allowLockAndLogout: false, - isVisible: true, - ) - let alternateRow = try subject.inspect().find(button: "alternate@bitwarden.com") - _ = try subject.inspect().find(button: "anne.account@bitwarden.com") - XCTAssertThrowsError(try alternateRow.labelView().callOnLongPressGesture()) - } - - /// Tapping an alternative profile row dispatches the `.accountPressed` action. - @MainActor - func test_alternateAccountRow_tap_alternateAccount() throws { - let alternate = ProfileSwitcherItem.fixture( - email: "alternate@bitwarden.com", - userInitials: "NA", - ) - let current = processor.state.activeAccountProfile! - processor.state = ProfileSwitcherState( - accounts: [ - alternate, - current, - ], - activeAccountId: current.userId, - allowLockAndLogout: true, - isVisible: true, - ) - let alternateRow = try subject.inspect().find(button: "alternate@bitwarden.com") - try alternateRow.labelView().callOnTapGesture() - waitFor(!processor.effects.isEmpty) - - XCTAssertEqual(processor.effects.last, .accountPressed(alternate)) - } - - /// Tapping an alternative profile row dispatches the `.accountPressed` action. - @MainActor - func test_alternateAccountRows_tap_alternateEmptyAccount() throws { - let alternate = ProfileSwitcherItem.fixture( - email: "locked@bitwarden.com", - isUnlocked: false, - userInitials: "LA", - ) - let secondAlternate = ProfileSwitcherItem.fixture() - let alternateAccounts = [ - alternate, - secondAlternate, - ] - let current = processor.state.activeAccountProfile! - processor.state = ProfileSwitcherState( - accounts: alternateAccounts + [current], - activeAccountId: current.userId, - allowLockAndLogout: true, - isVisible: true, - ) - let secondAlternateRow = try subject.inspect().find(button: "") - try secondAlternateRow.labelView().callOnTapGesture() - waitFor(!processor.effects.isEmpty) - - XCTAssertEqual(processor.effects.last, .accountPressed(secondAlternate)) - } - /// Tests the add account visibility below the maximum account limit @MainActor func test_addAccountRow_subMaximumAccounts_showAdd() throws { @@ -226,132 +84,4 @@ class ProfileSwitcherSheetTests: BitwardenTestCase { // swiftlint:disable:this t processor.state = ProfileSwitcherState.maximumAccounts XCTAssertFalse(subject.store.state.showsAddAccount) } - - /// The close toolbar button closes the sheet. - @MainActor - func test_closeToolbarButton() throws { - let closeButton = try subject.inspect().findCloseToolbarButton() - try closeButton.tap() - XCTAssertEqual(processor.dispatchedActions.last, .dismissTapped) - } - - // MARK: Snapshots - - // NB: There's not really a good way, it seems, to capture a view hierarchy when it's presenting a sheet. - // cf. https://github.com/pointfreeco/swift-snapshot-testing/discussions/956 - - func disabletest_snapshot_singleAccount() { - assertSnapshot(of: NavigationView { subject }, as: .defaultPortrait) - } - - @MainActor - func disabletest_snapshot_multiAccount_unlocked_belowMaximum() { - processor.state = ProfileSwitcherState( - accounts: [ - ProfileSwitcherItem.anneAccount, - ProfileSwitcherItem.fixture( - color: .yellow, - email: "bonus.bridge@bitwarden.com", - isUnlocked: true, - userInitials: "BB", - ), - ProfileSwitcherItem.fixture( - color: .teal, - email: "concurrent.claim@bitarden.com", - isUnlocked: true, - userInitials: "CC", - ), - ProfileSwitcherItem.fixture( - color: .indigo, - email: "double.dip@bitwarde.com", - isUnlocked: true, - userInitials: "DD", - ), - ], - activeAccountId: ProfileSwitcherItem.anneAccount.userId, - allowLockAndLogout: true, - isVisible: true, - ) - assertSnapshot(of: NavigationView { subject }, as: .defaultPortrait) - } - - @MainActor - func disabletest_snapshot_multiAccount_unlocked_atMaximum() { - processor.state = ProfileSwitcherState.maximumAccounts - assertSnapshot(of: NavigationView { subject }, as: .defaultPortrait) - } - - @MainActor - func disabletest_snapshot_multiAccount_unlocked_atMaximum_largeText() { - processor.state = ProfileSwitcherState.maximumAccounts - assertSnapshot(of: NavigationView { subject }, as: .defaultPortraitAX5) - } - - @MainActor - func disabletest_snapshot_multiAccount_locked_belowMaximum() { - processor.state = ProfileSwitcherState( - accounts: [ - ProfileSwitcherItem.fixture( - color: .yellow, - email: "bonus.bridge@bitwarden.com", - isUnlocked: false, - userInitials: "BB", - ), - ProfileSwitcherItem.fixture( - color: .teal, - email: "concurrent.claim@bitarden.com", - isUnlocked: false, - userInitials: "CC", - ), - ProfileSwitcherItem.anneAccount, - ProfileSwitcherItem.fixture( - color: .indigo, - email: "double.dip@bitwarde.com", - isUnlocked: false, - userInitials: "DD", - ), - ], - activeAccountId: ProfileSwitcherItem.anneAccount.userId, - allowLockAndLogout: true, - isVisible: true, - ) - assertSnapshot(of: NavigationView { subject }, as: .defaultPortrait) - } - - @MainActor - func disabletest_snapshot_multiAccount_locked_atMaximum() { - processor.state = ProfileSwitcherState( - accounts: [ - ProfileSwitcherItem.fixture( - color: .yellow, - email: "bonus.bridge@bitwarden.com", - isUnlocked: false, - userInitials: "BB", - ), - ProfileSwitcherItem.fixture( - color: .teal, - email: "concurrent.claim@bitarden.com", - isUnlocked: false, - userInitials: "CC", - ), - .anneAccount, - ProfileSwitcherItem.fixture( - color: .indigo, - email: "double.dip@bitwarde.com", - isUnlocked: false, - userInitials: "DD", - ), - ProfileSwitcherItem.fixture( - color: .green, - email: "extra.edition@bitwarden.com", - isUnlocked: false, - userInitials: "EE", - ), - ], - activeAccountId: ProfileSwitcherItem.anneAccount.userId, - allowLockAndLogout: true, - isVisible: true, - ) - assertSnapshot(of: NavigationView { subject }, as: .defaultPortrait) - } } diff --git a/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherToolbarViewTests.swift b/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherToolbarView+SnapshotTests.swift similarity index 93% rename from BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherToolbarViewTests.swift rename to BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherToolbarView+SnapshotTests.swift index 0fd43841c..c1b8b29f6 100644 --- a/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherToolbarViewTests.swift +++ b/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherToolbarView+SnapshotTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import BitwardenResources import BitwardenSdk import SnapshotTesting @@ -45,18 +46,6 @@ final class ProfileSwitcherToolbarViewTests: BitwardenTestCase { } } - /// Tapping the view dispatches the `.requestedProfileSwitcher` effect. - @MainActor - func test_tap_currentAccount() async throws { - let view = try subject.inspect().find(asyncButtonWithAccessibilityLabel: Localizations.account) - try await view.tap() - - XCTAssertEqual( - processor.effects.last, - .requestedProfileSwitcher(visible: !subject.store.state.isVisible), - ) - } - // MARK: Snapshots @MainActor diff --git a/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherToolbarView+ViewInspectorTests.swift b/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherToolbarView+ViewInspectorTests.swift new file mode 100644 index 000000000..d4349606f --- /dev/null +++ b/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherToolbarView+ViewInspectorTests.swift @@ -0,0 +1,59 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import BitwardenSdk +import SwiftUI +import XCTest + +@testable import BitwardenShared + +final class ProfileSwitcherToolbarViewTests: BitwardenTestCase { + var processor: MockProcessor! + var subject: ProfileSwitcherToolbarView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + let account = ProfileSwitcherItem.anneAccount + let state = ProfileSwitcherState( + accounts: [account], + activeAccountId: account.userId, + allowLockAndLogout: true, + isVisible: true, + ) + processor = MockProcessor(state: state) + subject = ProfileSwitcherToolbarView(store: Store(processor: processor)) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + @ViewBuilder + func snapshotSubject(title: String) -> some View { + NavigationView { + Spacer() + .navigationBarTitle(title, displayMode: .inline) + .toolbar { + ToolbarItem(placement: .navigationBarLeading) { + subject + } + } + } + } + + /// Tapping the view dispatches the `.requestedProfileSwitcher` effect. + @MainActor + func test_tap_currentAccount() async throws { + let view = try subject.inspect().find(asyncButtonWithAccessibilityLabel: Localizations.account) + try await view.tap() + + XCTAssertEqual( + processor.effects.last, + .requestedProfileSwitcher(visible: !subject.store.state.isVisible), + ) + } +} diff --git a/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherView+SnapshotTests.swift b/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherView+SnapshotTests.swift new file mode 100644 index 000000000..c80b1d9ca --- /dev/null +++ b/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherView+SnapshotTests.swift @@ -0,0 +1,165 @@ +// swiftlint:disable:this file_name +import BitwardenSdk +import SnapshotTesting +import SwiftUI +import XCTest + +@testable import BitwardenShared + +// MARK: - ProfileSwitcherViewTests + +class ProfileSwitcherViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: ProfileSwitcherView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + let account = ProfileSwitcherItem.anneAccount + let state = ProfileSwitcherState( + accounts: [account], + activeAccountId: account.userId, + allowLockAndLogout: true, + isVisible: true, + ) + processor = MockProcessor(state: state) + subject = ProfileSwitcherView(store: Store(processor: processor)) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + func disabletest_snapshot_singleAccount() { + assertSnapshot(of: subject, as: .defaultPortrait) + } + + @MainActor + func disabletest_snapshot_multiAccount_unlocked_belowMaximum() { + processor.state = ProfileSwitcherState( + accounts: [ + ProfileSwitcherItem.anneAccount, + ProfileSwitcherItem.fixture( + color: .yellow, + email: "bonus.bridge@bitwarden.com", + isUnlocked: true, + userInitials: "BB", + ), + ProfileSwitcherItem.fixture( + color: .teal, + email: "concurrent.claim@bitarden.com", + isUnlocked: true, + userInitials: "CC", + ), + ProfileSwitcherItem.fixture( + color: .indigo, + email: "double.dip@bitwarde.com", + isUnlocked: true, + userInitials: "DD", + ), + ], + activeAccountId: ProfileSwitcherItem.anneAccount.userId, + allowLockAndLogout: true, + isVisible: true, + ) + assertSnapshot(of: subject, as: .defaultPortrait) + } + + @MainActor + func disabletest_snapshot_multiAccount_unlocked_atMaximum() { + processor.state = ProfileSwitcherState.maximumAccounts + assertSnapshot(of: subject, as: .defaultPortrait) + } + + @MainActor + func disabletest_snapshot_multiAccount_unlocked_atMaximum_largeText() { + processor.state = ProfileSwitcherState.maximumAccounts + assertSnapshot(of: subject, as: .defaultPortraitAX5) + } + + @MainActor + func disabletest_snapshot_multiAccount_locked_belowMaximum() { + processor.state = ProfileSwitcherState( + accounts: [ + ProfileSwitcherItem.fixture( + color: .yellow, + email: "bonus.bridge@bitwarden.com", + isUnlocked: false, + userInitials: "BB", + ), + ProfileSwitcherItem.fixture( + color: .teal, + email: "concurrent.claim@bitarden.com", + isUnlocked: false, + userInitials: "CC", + ), + ProfileSwitcherItem.anneAccount, + ProfileSwitcherItem.fixture( + color: .indigo, + email: "double.dip@bitwarde.com", + isUnlocked: false, + userInitials: "DD", + ), + ], + activeAccountId: ProfileSwitcherItem.anneAccount.userId, + allowLockAndLogout: true, + isVisible: true, + ) + assertSnapshot(of: subject, as: .defaultPortrait) + } + + @MainActor + func disabletest_snapshot_multiAccount_locked_atMaximum() { + processor.state = ProfileSwitcherState( + accounts: [ + ProfileSwitcherItem.fixture( + color: .yellow, + email: "bonus.bridge@bitwarden.com", + isUnlocked: false, + userInitials: "BB", + ), + ProfileSwitcherItem.fixture( + color: .teal, + email: "concurrent.claim@bitarden.com", + isUnlocked: false, + userInitials: "CC", + ), + .anneAccount, + ProfileSwitcherItem.fixture( + color: .indigo, + email: "double.dip@bitwarde.com", + isUnlocked: false, + userInitials: "DD", + ), + ProfileSwitcherItem.fixture( + color: .green, + email: "extra.edition@bitwarden.com", + isUnlocked: false, + userInitials: "EE", + ), + ], + activeAccountId: ProfileSwitcherItem.anneAccount.userId, + allowLockAndLogout: true, + isVisible: true, + ) + assertSnapshot(of: subject, as: .defaultPortrait) + } + + /// Test a snapshot of the ProfileSwitcherView previews. + func disabletest_snapshot_profileSwitcherView_previews() { + for preview in ProfileSwitcherView_Previews._allPreviews { + assertSnapshots( + of: preview.content, + as: [.defaultPortrait], + ) + } + } +} diff --git a/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherView+ViewInspectorTests.swift b/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherView+ViewInspectorTests.swift new file mode 100644 index 000000000..cf64ff629 --- /dev/null +++ b/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherView+ViewInspectorTests.swift @@ -0,0 +1,189 @@ +// swiftlint:disable:this file_name +import BitwardenSdk +import SwiftUI +import ViewInspector +import XCTest + +@testable import BitwardenShared + +// MARK: - ProfileSwitcherViewTests + +class ProfileSwitcherViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: ProfileSwitcherView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + let account = ProfileSwitcherItem.anneAccount + let state = ProfileSwitcherState( + accounts: [account], + activeAccountId: account.userId, + allowLockAndLogout: true, + isVisible: true, + ) + processor = MockProcessor(state: state) + subject = ProfileSwitcherView(store: Store(processor: processor)) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Tests + + /// Long pressing a profile row dispatches the `.accountLongPressed` action. + @MainActor + func test_accountRow_longPress_currentAccount() throws { + let accountRow = try subject.inspect().find(button: "anne.account@bitwarden.com") + try accountRow.labelView().callOnLongPressGesture() + let currentAccount = processor.state.activeAccountProfile! + waitFor(!processor.effects.isEmpty) + + XCTAssertEqual(processor.effects.last, .accountLongPressed(currentAccount)) + } + + /// Long pressing is disabled if lock and logout are not available. + @MainActor + func test_accountRow_longPress_currentAccount_noLockOrLogout() throws { + processor.state.allowLockAndLogout = false + processor.state.accounts[0].canBeLocked = false + let accountRow = try subject.inspect().find(button: "anne.account@bitwarden.com") + XCTAssertThrowsError(try accountRow.labelView().callOnLongPressGesture()) + } + + /// Tapping a profile row dispatches the `.accountPressed` action. + @MainActor + func test_accountRow_tap_currentAccount() throws { + let accountRow = try subject.inspect().find(button: "anne.account@bitwarden.com") + try accountRow.labelView().callOnTapGesture() + let currentAccount = processor.state.activeAccountProfile! + waitFor(!processor.effects.isEmpty) + + XCTAssertEqual(processor.effects.last, .accountPressed(currentAccount)) + } + + /// Tapping a profile row dispatches the `.accountPressed` action. + @MainActor + func test_accountRow_tap_addAccount() throws { + let addAccountRow = try subject.inspect().find(button: "Add account") + try addAccountRow.tap() + waitFor(!processor.effects.isEmpty) + + XCTAssertEqual(processor.effects.last, .addAccountPressed) + } + + /// Long pressing an alternative profile row dispatches the `.accountLongPressed` action. + @MainActor + func test_alternateAccountRow_longPress_alternateAccount() throws { + let alternate = ProfileSwitcherItem.fixture( + email: "alternate@bitwarden.com", + userInitials: "NA", + ) + let current = processor.state.activeAccountProfile! + processor.state = ProfileSwitcherState( + accounts: [ + alternate, + current, + ], + activeAccountId: current.userId, + allowLockAndLogout: true, + isVisible: true, + ) + let alternateRow = try subject.inspect().find(button: "alternate@bitwarden.com") + try alternateRow.labelView().callOnLongPressGesture() + waitFor(!processor.effects.isEmpty) + + XCTAssertEqual(processor.effects.last, .accountLongPressed(alternate)) + } + + /// Long pressing is disabled if lock and logout are not available. + @MainActor + func test_alternateAccountRow_longPress_currentAccount_noLockOrLogout() throws { + let alternate = ProfileSwitcherItem.fixture( + canBeLocked: false, + email: "alternate@bitwarden.com", + userInitials: "NA", + ) + let current = processor.state.activeAccountProfile! + processor.state = ProfileSwitcherState( + accounts: [ + alternate, + current, + ], + activeAccountId: current.userId, + allowLockAndLogout: false, + isVisible: true, + ) + let alternateRow = try subject.inspect().find(button: "alternate@bitwarden.com") + _ = try subject.inspect().find(button: "anne.account@bitwarden.com") + XCTAssertThrowsError(try alternateRow.labelView().callOnLongPressGesture()) + } + + /// Tapping an alternative profile row dispatches the `.accountPressed` action. + @MainActor + func test_alternateAccountRow_tap_alternateAccount() throws { + let alternate = ProfileSwitcherItem.fixture( + email: "alternate@bitwarden.com", + userInitials: "NA", + ) + let current = processor.state.activeAccountProfile! + processor.state = ProfileSwitcherState( + accounts: [ + alternate, + current, + ], + activeAccountId: current.userId, + allowLockAndLogout: true, + isVisible: true, + ) + let alternateRow = try subject.inspect().find(button: "alternate@bitwarden.com") + try alternateRow.labelView().callOnTapGesture() + waitFor(!processor.effects.isEmpty) + + XCTAssertEqual(processor.effects.last, .accountPressed(alternate)) + } + + /// Tapping an alternative profile row dispatches the `.accountPressed` action. + @MainActor + func test_alternateAccountRows_tap_alternateEmptyAccount() throws { + let alternate = ProfileSwitcherItem.fixture( + email: "locked@bitwarden.com", + isUnlocked: false, + userInitials: "LA", + ) + let secondAlternate = ProfileSwitcherItem.fixture() + let alternateAccounts = [ + alternate, + secondAlternate, + ] + let current = processor.state.activeAccountProfile! + processor.state = ProfileSwitcherState( + accounts: alternateAccounts + [current], + activeAccountId: current.userId, + allowLockAndLogout: true, + isVisible: true, + ) + let secondAlternateRow = try subject.inspect().find(button: "") + try secondAlternateRow.labelView().callOnTapGesture() + waitFor(!processor.effects.isEmpty) + + XCTAssertEqual(processor.effects.last, .accountPressed(secondAlternate)) + } + + /// Tapping the background triggers a `.backgroundPressed` action. + @MainActor + func test_background_tap() throws { + let view = try subject.inspect().view(ProfileSwitcherView.self) + let background = view.first + try background?.callOnTapGesture() + + XCTAssertEqual(processor.dispatchedActions.last, .backgroundTapped) + } +} diff --git a/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherViewTests.swift b/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherViewTests.swift index ee968614a..d1dbb5b21 100644 --- a/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherViewTests.swift +++ b/BitwardenShared/UI/Auth/ProfileSwitcher/ProfileSwitcherViewTests.swift @@ -1,14 +1,12 @@ import BitwardenSdk -import SnapshotTesting import SwiftUI -import ViewInspector import XCTest @testable import BitwardenShared // MARK: - ProfileSwitcherViewTests -class ProfileSwitcherViewTests: BitwardenTestCase { // swiftlint:disable:this type_body_length +class ProfileSwitcherViewTests: BitwardenTestCase { // MARK: Properties var processor: MockProcessor! @@ -38,155 +36,6 @@ class ProfileSwitcherViewTests: BitwardenTestCase { // swiftlint:disable:this ty // MARK: Tests - /// Long pressing a profile row dispatches the `.accountLongPressed` action. - @MainActor - func test_accountRow_longPress_currentAccount() throws { - let accountRow = try subject.inspect().find(button: "anne.account@bitwarden.com") - try accountRow.labelView().callOnLongPressGesture() - let currentAccount = processor.state.activeAccountProfile! - waitFor(!processor.effects.isEmpty) - - XCTAssertEqual(processor.effects.last, .accountLongPressed(currentAccount)) - } - - /// Long pressing is disabled if lock and logout are not available. - @MainActor - func test_accountRow_longPress_currentAccount_noLockOrLogout() throws { - processor.state.allowLockAndLogout = false - processor.state.accounts[0].canBeLocked = false - let accountRow = try subject.inspect().find(button: "anne.account@bitwarden.com") - XCTAssertThrowsError(try accountRow.labelView().callOnLongPressGesture()) - } - - /// Tapping a profile row dispatches the `.accountPressed` action. - @MainActor - func test_accountRow_tap_currentAccount() throws { - let accountRow = try subject.inspect().find(button: "anne.account@bitwarden.com") - try accountRow.labelView().callOnTapGesture() - let currentAccount = processor.state.activeAccountProfile! - waitFor(!processor.effects.isEmpty) - - XCTAssertEqual(processor.effects.last, .accountPressed(currentAccount)) - } - - /// Tapping a profile row dispatches the `.accountPressed` action. - @MainActor - func test_accountRow_tap_addAccount() throws { - let addAccountRow = try subject.inspect().find(button: "Add account") - try addAccountRow.tap() - waitFor(!processor.effects.isEmpty) - - XCTAssertEqual(processor.effects.last, .addAccountPressed) - } - - /// Long pressing an alternative profile row dispatches the `.accountLongPressed` action. - @MainActor - func test_alternateAccountRow_longPress_alternateAccount() throws { - let alternate = ProfileSwitcherItem.fixture( - email: "alternate@bitwarden.com", - userInitials: "NA", - ) - let current = processor.state.activeAccountProfile! - processor.state = ProfileSwitcherState( - accounts: [ - alternate, - current, - ], - activeAccountId: current.userId, - allowLockAndLogout: true, - isVisible: true, - ) - let alternateRow = try subject.inspect().find(button: "alternate@bitwarden.com") - try alternateRow.labelView().callOnLongPressGesture() - waitFor(!processor.effects.isEmpty) - - XCTAssertEqual(processor.effects.last, .accountLongPressed(alternate)) - } - - /// Long pressing is disabled if lock and logout are not available. - @MainActor - func test_alternateAccountRow_longPress_currentAccount_noLockOrLogout() throws { - let alternate = ProfileSwitcherItem.fixture( - canBeLocked: false, - email: "alternate@bitwarden.com", - userInitials: "NA", - ) - let current = processor.state.activeAccountProfile! - processor.state = ProfileSwitcherState( - accounts: [ - alternate, - current, - ], - activeAccountId: current.userId, - allowLockAndLogout: false, - isVisible: true, - ) - let alternateRow = try subject.inspect().find(button: "alternate@bitwarden.com") - _ = try subject.inspect().find(button: "anne.account@bitwarden.com") - XCTAssertThrowsError(try alternateRow.labelView().callOnLongPressGesture()) - } - - /// Tapping an alternative profile row dispatches the `.accountPressed` action. - @MainActor - func test_alternateAccountRow_tap_alternateAccount() throws { - let alternate = ProfileSwitcherItem.fixture( - email: "alternate@bitwarden.com", - userInitials: "NA", - ) - let current = processor.state.activeAccountProfile! - processor.state = ProfileSwitcherState( - accounts: [ - alternate, - current, - ], - activeAccountId: current.userId, - allowLockAndLogout: true, - isVisible: true, - ) - let alternateRow = try subject.inspect().find(button: "alternate@bitwarden.com") - try alternateRow.labelView().callOnTapGesture() - waitFor(!processor.effects.isEmpty) - - XCTAssertEqual(processor.effects.last, .accountPressed(alternate)) - } - - /// Tapping an alternative profile row dispatches the `.accountPressed` action. - @MainActor - func test_alternateAccountRows_tap_alternateEmptyAccount() throws { - let alternate = ProfileSwitcherItem.fixture( - email: "locked@bitwarden.com", - isUnlocked: false, - userInitials: "LA", - ) - let secondAlternate = ProfileSwitcherItem.fixture() - let alternateAccounts = [ - alternate, - secondAlternate, - ] - let current = processor.state.activeAccountProfile! - processor.state = ProfileSwitcherState( - accounts: alternateAccounts + [current], - activeAccountId: current.userId, - allowLockAndLogout: true, - isVisible: true, - ) - let secondAlternateRow = try subject.inspect().find(button: "") - try secondAlternateRow.labelView().callOnTapGesture() - waitFor(!processor.effects.isEmpty) - - XCTAssertEqual(processor.effects.last, .accountPressed(secondAlternate)) - } - - /// Tapping the background triggers a `.backgroundPressed` action. - @MainActor - func test_background_tap() throws { - let view = try subject.inspect().view(ProfileSwitcherView.self) - let background = view.first - try background?.callOnTapGesture() - - XCTAssertEqual(processor.dispatchedActions.last, .backgroundTapped) - } - /// Tests the add account visibility below the maximum account limit @MainActor func test_addAccountRow_subMaximumAccounts_showAdd() throws { @@ -234,131 +83,4 @@ class ProfileSwitcherViewTests: BitwardenTestCase { // swiftlint:disable:this ty processor.state = ProfileSwitcherState.maximumAccounts XCTAssertFalse(subject.store.state.showsAddAccount) } - - // MARK: Snapshots - - func disabletest_snapshot_singleAccount() { - assertSnapshot(of: subject, as: .defaultPortrait) - } - - @MainActor - func disabletest_snapshot_multiAccount_unlocked_belowMaximum() { - processor.state = ProfileSwitcherState( - accounts: [ - ProfileSwitcherItem.anneAccount, - ProfileSwitcherItem.fixture( - color: .yellow, - email: "bonus.bridge@bitwarden.com", - isUnlocked: true, - userInitials: "BB", - ), - ProfileSwitcherItem.fixture( - color: .teal, - email: "concurrent.claim@bitarden.com", - isUnlocked: true, - userInitials: "CC", - ), - ProfileSwitcherItem.fixture( - color: .indigo, - email: "double.dip@bitwarde.com", - isUnlocked: true, - userInitials: "DD", - ), - ], - activeAccountId: ProfileSwitcherItem.anneAccount.userId, - allowLockAndLogout: true, - isVisible: true, - ) - assertSnapshot(of: subject, as: .defaultPortrait) - } - - @MainActor - func disabletest_snapshot_multiAccount_unlocked_atMaximum() { - processor.state = ProfileSwitcherState.maximumAccounts - assertSnapshot(of: subject, as: .defaultPortrait) - } - - @MainActor - func disabletest_snapshot_multiAccount_unlocked_atMaximum_largeText() { - processor.state = ProfileSwitcherState.maximumAccounts - assertSnapshot(of: subject, as: .defaultPortraitAX5) - } - - @MainActor - func disabletest_snapshot_multiAccount_locked_belowMaximum() { - processor.state = ProfileSwitcherState( - accounts: [ - ProfileSwitcherItem.fixture( - color: .yellow, - email: "bonus.bridge@bitwarden.com", - isUnlocked: false, - userInitials: "BB", - ), - ProfileSwitcherItem.fixture( - color: .teal, - email: "concurrent.claim@bitarden.com", - isUnlocked: false, - userInitials: "CC", - ), - ProfileSwitcherItem.anneAccount, - ProfileSwitcherItem.fixture( - color: .indigo, - email: "double.dip@bitwarde.com", - isUnlocked: false, - userInitials: "DD", - ), - ], - activeAccountId: ProfileSwitcherItem.anneAccount.userId, - allowLockAndLogout: true, - isVisible: true, - ) - assertSnapshot(of: subject, as: .defaultPortrait) - } - - @MainActor - func disabletest_snapshot_multiAccount_locked_atMaximum() { - processor.state = ProfileSwitcherState( - accounts: [ - ProfileSwitcherItem.fixture( - color: .yellow, - email: "bonus.bridge@bitwarden.com", - isUnlocked: false, - userInitials: "BB", - ), - ProfileSwitcherItem.fixture( - color: .teal, - email: "concurrent.claim@bitarden.com", - isUnlocked: false, - userInitials: "CC", - ), - .anneAccount, - ProfileSwitcherItem.fixture( - color: .indigo, - email: "double.dip@bitwarde.com", - isUnlocked: false, - userInitials: "DD", - ), - ProfileSwitcherItem.fixture( - color: .green, - email: "extra.edition@bitwarden.com", - isUnlocked: false, - userInitials: "EE", - ), - ], - activeAccountId: ProfileSwitcherItem.anneAccount.userId, - allowLockAndLogout: true, - isVisible: true, - ) - assertSnapshot(of: subject, as: .defaultPortrait) - } - - /// Test a snapshot of the ProfileSwitcherView previews. - func disabletest_snapshot_profileSwitcherView_previews() { - for preview in ProfileSwitcherView_Previews._allPreviews { - assertSnapshots( - of: preview.content, - as: [.defaultPortrait], - ) - } - } } diff --git a/BitwardenShared/UI/Auth/RemoveMasterPassword/RemoveMasterPasswordView+SnapshotTests.swift b/BitwardenShared/UI/Auth/RemoveMasterPassword/RemoveMasterPasswordView+SnapshotTests.swift new file mode 100644 index 000000000..cd253e772 --- /dev/null +++ b/BitwardenShared/UI/Auth/RemoveMasterPassword/RemoveMasterPasswordView+SnapshotTests.swift @@ -0,0 +1,46 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class RemoveMasterPasswordViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: RemoveMasterPasswordView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: RemoveMasterPasswordState( + masterPassword: "password", + organizationName: "Example Org", + organizationId: "ORG_ID", + keyConnectorUrl: "https://example.com", + )) + + subject = RemoveMasterPasswordView(store: Store(processor: processor)) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// The remove master password view renders correctly. + @MainActor + func disabletest_snapshot_removeMasterPassword() { + assertSnapshots( + of: subject.navStackWrapped, + as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5(heightMultiple: 1.5)], + ) + } +} diff --git a/BitwardenShared/UI/Auth/RemoveMasterPassword/RemoveMasterPasswordViewTests.swift b/BitwardenShared/UI/Auth/RemoveMasterPassword/RemoveMasterPasswordView+ViewInspectorTests.swift similarity index 77% rename from BitwardenShared/UI/Auth/RemoveMasterPassword/RemoveMasterPasswordViewTests.swift rename to BitwardenShared/UI/Auth/RemoveMasterPassword/RemoveMasterPasswordView+ViewInspectorTests.swift index e4b264aa8..e7457d633 100644 --- a/BitwardenShared/UI/Auth/RemoveMasterPassword/RemoveMasterPasswordViewTests.swift +++ b/BitwardenShared/UI/Auth/RemoveMasterPassword/RemoveMasterPasswordView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import ViewInspector import XCTest @@ -42,15 +42,4 @@ class RemoveMasterPasswordViewTests: BitwardenTestCase { try await button.tap() XCTAssertEqual(processor.effects.last, .continueFlow) } - - // MARK: Snapshots - - /// The remove master password view renders correctly. - @MainActor - func disabletest_snapshot_removeMasterPassword() { - assertSnapshots( - of: subject.navStackWrapped, - as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5(heightMultiple: 1.5)], - ) - } } diff --git a/BitwardenShared/UI/Auth/SetMasterPassword/SetMasterPasswordView+SnapshotTests.swift b/BitwardenShared/UI/Auth/SetMasterPassword/SetMasterPasswordView+SnapshotTests.swift new file mode 100644 index 000000000..d7df5bf10 --- /dev/null +++ b/BitwardenShared/UI/Auth/SetMasterPassword/SetMasterPasswordView+SnapshotTests.swift @@ -0,0 +1,66 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class SetMasterPasswordViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: SetMasterPasswordView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: SetMasterPasswordState(organizationIdentifier: "ORG_ID")) + subject = SetMasterPasswordView(store: Store(processor: processor)) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// A snapshot of the view with all filled values fields. + @MainActor + func disabletest_snapshot_setPassword_filled() { + processor.state.masterPassword = "password123" + processor.state.masterPasswordRetype = "password123" + processor.state.masterPasswordHint = "hint hint" + processor.state.resetPasswordAutoEnroll = true + assertSnapshots( + of: subject.navStackWrapped, + as: [ + "portrait": .portrait(), + "portraitDark": .portraitDark(), + "tallPortraitAX5": .tallPortraitAX5(), + ], + ) + } + + /// A snapshot of the view for privilege elevation. + @MainActor + func disabletest_snapshot_setPassword_privilege_elevation() { + processor.state.isPrivilegeElevation = true + processor.state.masterPassword = "password123" + processor.state.masterPasswordRetype = "password123" + processor.state.masterPasswordHint = "hint hint" + processor.state.resetPasswordAutoEnroll = true + assertSnapshots( + of: subject.navStackWrapped, + as: [ + "portrait": .portrait(), + "portraitDark": .portraitDark(), + "tallPortraitAX5": .tallPortraitAX5(), + ], + ) + } +} diff --git a/BitwardenShared/UI/Auth/SetMasterPassword/SetMasterPasswordViewTests.swift b/BitwardenShared/UI/Auth/SetMasterPassword/SetMasterPasswordView+ViewInspectorTests.swift similarity index 75% rename from BitwardenShared/UI/Auth/SetMasterPassword/SetMasterPasswordViewTests.swift rename to BitwardenShared/UI/Auth/SetMasterPassword/SetMasterPasswordView+ViewInspectorTests.swift index e387925a3..5366fe12b 100644 --- a/BitwardenShared/UI/Auth/SetMasterPassword/SetMasterPasswordViewTests.swift +++ b/BitwardenShared/UI/Auth/SetMasterPassword/SetMasterPasswordView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import ViewInspector import XCTest @@ -99,41 +99,4 @@ class SetMasterPasswordViewTests: BitwardenTestCase { waitFor(!processor.effects.isEmpty) XCTAssertEqual(processor.effects.last, .saveTapped) } - - // MARK: Snapshots - - /// A snapshot of the view with all filled values fields. - @MainActor - func disabletest_snapshot_setPassword_filled() { - processor.state.masterPassword = "password123" - processor.state.masterPasswordRetype = "password123" - processor.state.masterPasswordHint = "hint hint" - processor.state.resetPasswordAutoEnroll = true - assertSnapshots( - of: subject.navStackWrapped, - as: [ - "portrait": .portrait(), - "portraitDark": .portraitDark(), - "tallPortraitAX5": .tallPortraitAX5(), - ], - ) - } - - /// A snapshot of the view for privilege elevation. - @MainActor - func disabletest_snapshot_setPassword_privilege_elevation() { - processor.state.isPrivilegeElevation = true - processor.state.masterPassword = "password123" - processor.state.masterPasswordRetype = "password123" - processor.state.masterPasswordHint = "hint hint" - processor.state.resetPasswordAutoEnroll = true - assertSnapshots( - of: subject.navStackWrapped, - as: [ - "portrait": .portrait(), - "portraitDark": .portraitDark(), - "tallPortraitAX5": .tallPortraitAX5(), - ], - ) - } } diff --git a/BitwardenShared/UI/Auth/StartRegistration/CheckEmail/CheckEmailView+SnapshotTests.swift b/BitwardenShared/UI/Auth/StartRegistration/CheckEmail/CheckEmailView+SnapshotTests.swift new file mode 100644 index 000000000..d7c064dfd --- /dev/null +++ b/BitwardenShared/UI/Auth/StartRegistration/CheckEmail/CheckEmailView+SnapshotTests.swift @@ -0,0 +1,45 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import SwiftUI +import XCTest + +@testable import BitwardenShared + +// MARK: - CheckEmailViewTests + +class CheckEmailViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: CheckEmailView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + processor = MockProcessor(state: CheckEmailState(email: "example@email.com")) + let store = Store(processor: processor) + subject = CheckEmailView(store: store) + } + + override func tearDown() { + super.tearDown() + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// Tests the view renders correctly. + func disabletest_snapshot_empty() { + assertSnapshots( + of: subject, + as: [ + .defaultPortrait, + .defaultPortraitDark, + .tallPortraitAX5(heightMultiple: 2), + ], + ) + } +} diff --git a/BitwardenShared/UI/Auth/StartRegistration/CheckEmail/CheckEmailViewTests.swift b/BitwardenShared/UI/Auth/StartRegistration/CheckEmail/CheckEmailView+ViewInspectorTests.swift similarity index 79% rename from BitwardenShared/UI/Auth/StartRegistration/CheckEmail/CheckEmailViewTests.swift rename to BitwardenShared/UI/Auth/StartRegistration/CheckEmail/CheckEmailView+ViewInspectorTests.swift index efe1c996c..c5dbb41e9 100644 --- a/BitwardenShared/UI/Auth/StartRegistration/CheckEmail/CheckEmailViewTests.swift +++ b/BitwardenShared/UI/Auth/StartRegistration/CheckEmail/CheckEmailView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import SwiftUI import ViewInspector import XCTest @@ -46,18 +46,4 @@ class CheckEmailViewTests: BitwardenTestCase { try button.tap() XCTAssertEqual(processor.dispatchedActions.last, .goBackTapped) } - - // MARK: Snapshots - - /// Tests the view renders correctly. - func disabletest_snapshot_empty() { - assertSnapshots( - of: subject, - as: [ - .defaultPortrait, - .defaultPortraitDark, - .tallPortraitAX5(heightMultiple: 2), - ], - ) - } } diff --git a/BitwardenShared/UI/Auth/StartRegistration/StartRegistrationView+SnapshotTests.swift b/BitwardenShared/UI/Auth/StartRegistration/StartRegistrationView+SnapshotTests.swift new file mode 100644 index 000000000..3904fda7b --- /dev/null +++ b/BitwardenShared/UI/Auth/StartRegistration/StartRegistrationView+SnapshotTests.swift @@ -0,0 +1,73 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import SwiftUI +import XCTest + +@testable import BitwardenShared + +// MARK: - StartRegistrationViewTests + +class StartRegistrationViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: StartRegistrationView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + processor = MockProcessor(state: StartRegistrationState()) + let store = Store(processor: processor) + subject = StartRegistrationView(store: store) + } + + override func tearDown() { + super.tearDown() + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// Tests the view renders correctly when the text fields are all empty. + @MainActor + func disabletest_snapshot_empty() { + assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark]) + } + + /// Tests the view renders correctly when the text fields are all populated. + @MainActor + func disabletest_snapshot_textFields_populated() throws { + processor.state.emailText = "email@example.com" + processor.state.nameText = "user name" + + assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) + } + + /// Tests the view renders correctly when the text fields are all populated with long text. + @MainActor + func disabletest_snapshot_textFields_populated_long() throws { + processor.state.emailText = "emailmmmmmmmmmmmmmmmmmmmmm@exammmmmmmmmmmmmmmmmmmmmmmmmmmmmmmple.com" + processor.state.nameText = "user name name name name name name name name name name name name name name" + + assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) + } + + /// Tests the view renders correctly when the toggles are on. + @MainActor + func disabletest_snapshot_toggles_on() throws { + processor.state.isReceiveMarketingToggleOn = true + + assertSnapshot(of: subject, as: .defaultPortrait) + } + + /// Tests the view renders correctly when the marketing toggle is hidden. + @MainActor + func disabletest_snapshot_marketingToggle_hidden() throws { + processor.state.showReceiveMarketingToggle = false + + assertSnapshot(of: subject, as: .defaultPortrait) + } +} diff --git a/BitwardenShared/UI/Auth/StartRegistration/StartRegistrationViewTests.swift b/BitwardenShared/UI/Auth/StartRegistration/StartRegistrationView+ViewInspectorTests.swift similarity index 65% rename from BitwardenShared/UI/Auth/StartRegistration/StartRegistrationViewTests.swift rename to BitwardenShared/UI/Auth/StartRegistration/StartRegistrationView+ViewInspectorTests.swift index 118b848db..84eb77640 100644 --- a/BitwardenShared/UI/Auth/StartRegistration/StartRegistrationViewTests.swift +++ b/BitwardenShared/UI/Auth/StartRegistration/StartRegistrationView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import SwiftUI import ViewInspector import XCTest @@ -87,46 +87,4 @@ class StartRegistrationViewTests: BitwardenTestCase { try toggle.tap() XCTAssertEqual(processor.dispatchedActions.last, .toggleReceiveMarketing(true)) } - - // MARK: Snapshots - - /// Tests the view renders correctly when the text fields are all empty. - @MainActor - func disabletest_snapshot_empty() { - assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark]) - } - - /// Tests the view renders correctly when the text fields are all populated. - @MainActor - func disabletest_snapshot_textFields_populated() throws { - processor.state.emailText = "email@example.com" - processor.state.nameText = "user name" - - assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) - } - - /// Tests the view renders correctly when the text fields are all populated with long text. - @MainActor - func disabletest_snapshot_textFields_populated_long() throws { - processor.state.emailText = "emailmmmmmmmmmmmmmmmmmmmmm@exammmmmmmmmmmmmmmmmmmmmmmmmmmmmmmple.com" - processor.state.nameText = "user name name name name name name name name name name name name name name" - - assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) - } - - /// Tests the view renders correctly when the toggles are on. - @MainActor - func disabletest_snapshot_toggles_on() throws { - processor.state.isReceiveMarketingToggleOn = true - - assertSnapshot(of: subject, as: .defaultPortrait) - } - - /// Tests the view renders correctly when the marketing toggle is hidden. - @MainActor - func disabletest_snapshot_marketingToggle_hidden() throws { - processor.state.showReceiveMarketingToggle = false - - assertSnapshot(of: subject, as: .defaultPortrait) - } } diff --git a/BitwardenShared/UI/Auth/UpdateMasterPassword/UpdateMasterPasswordView+SnapshotTests.swift b/BitwardenShared/UI/Auth/UpdateMasterPassword/UpdateMasterPasswordView+SnapshotTests.swift new file mode 100644 index 000000000..9993b9aeb --- /dev/null +++ b/BitwardenShared/UI/Auth/UpdateMasterPassword/UpdateMasterPasswordView+SnapshotTests.swift @@ -0,0 +1,106 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +// MARK: - UpdateMasterPasswordViewTests + +class UpdateMasterPasswordViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: UpdateMasterPasswordView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + let state = UpdateMasterPasswordState( + currentMasterPassword: "current master password", + masterPassword: "new master password", + masterPasswordHint: "new master password hint", + masterPasswordPolicy: .init( + minComplexity: 0, + minLength: 20, + requireUpper: true, + requireLower: false, + requireNumbers: false, + requireSpecial: false, + enforceOnLogin: true, + ), + masterPasswordRetype: "new master password", + ) + processor = MockProcessor(state: state) + subject = UpdateMasterPasswordView(store: Store(processor: processor)) + } + + override func tearDown() { + super.tearDown() + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// A snapshot of the view with all filled values fields. + @MainActor + func disabletest_snapshot_resetPassword_withFilled_default() { + processor.state.forcePasswordResetReason = .adminForcePasswordReset + assertSnapshots( + of: subject.navStackWrapped, + as: [.portrait(heightMultiple: 1.25)], + ) + } + + /// A snapshot of the view with all filled values fields in a dark mode. + @MainActor + func disabletest_snapshot_resetPassword_withFilled_dark() { + processor.state.forcePasswordResetReason = .adminForcePasswordReset + assertSnapshots( + of: subject.navStackWrapped, + as: [.portraitDark(heightMultiple: 1.25)], + ) + } + + /// A snapshot of the view with all filled values fields in a large text. + @MainActor + func disabletest_snapshot_resetPassword_withFilled_large() { + processor.state.forcePasswordResetReason = .adminForcePasswordReset + assertSnapshots( + of: subject.navStackWrapped, + as: [.tallPortraitAX5(heightMultiple: 6)], + ) + } + + /// A snapshot of the view with all filled values fields. + @MainActor + func disabletest_snapshot_weakPassword_withFilled_default() { + processor.state.forcePasswordResetReason = .weakMasterPasswordOnLogin + assertSnapshots( + of: subject.navStackWrapped, + as: [.portrait(heightMultiple: 1.25)], + ) + } + + /// A snapshot of the view with all filled values fields in a dark mode. + @MainActor + func disabletest_snapshot_weakPassword_withFilled_dark() { + processor.state.forcePasswordResetReason = .weakMasterPasswordOnLogin + assertSnapshots( + of: subject.navStackWrapped, + as: [.portraitDark(heightMultiple: 1.25)], + ) + } + + /// A snapshot of the view with all filled values fields in a large text. + @MainActor + func disabletest_snapshot_weakPassword_withFilled_large() { + processor.state.forcePasswordResetReason = .weakMasterPasswordOnLogin + assertSnapshots( + of: subject.navStackWrapped, + as: [.tallPortraitAX5(heightMultiple: 6)], + ) + } +} diff --git a/BitwardenShared/UI/Auth/UpdateMasterPassword/UpdateMasterPasswordViewTests.swift b/BitwardenShared/UI/Auth/UpdateMasterPassword/UpdateMasterPasswordView+ViewInspectorTests.swift similarity index 73% rename from BitwardenShared/UI/Auth/UpdateMasterPassword/UpdateMasterPasswordViewTests.swift rename to BitwardenShared/UI/Auth/UpdateMasterPassword/UpdateMasterPasswordView+ViewInspectorTests.swift index 83359cd80..447463c66 100644 --- a/BitwardenShared/UI/Auth/UpdateMasterPassword/UpdateMasterPasswordViewTests.swift +++ b/BitwardenShared/UI/Auth/UpdateMasterPassword/UpdateMasterPasswordView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import ViewInspector import XCTest @@ -145,66 +145,4 @@ class UpdateMasterPasswordViewTests: BitwardenTestCase { try await button.tap() XCTAssertEqual(processor.effects.last, .saveTapped) } - - // MARK: Snapshots - - /// A snapshot of the view with all filled values fields. - @MainActor - func disabletest_snapshot_resetPassword_withFilled_default() { - processor.state.forcePasswordResetReason = .adminForcePasswordReset - assertSnapshots( - of: subject.navStackWrapped, - as: [.portrait(heightMultiple: 1.25)], - ) - } - - /// A snapshot of the view with all filled values fields in a dark mode. - @MainActor - func disabletest_snapshot_resetPassword_withFilled_dark() { - processor.state.forcePasswordResetReason = .adminForcePasswordReset - assertSnapshots( - of: subject.navStackWrapped, - as: [.portraitDark(heightMultiple: 1.25)], - ) - } - - /// A snapshot of the view with all filled values fields in a large text. - @MainActor - func disabletest_snapshot_resetPassword_withFilled_large() { - processor.state.forcePasswordResetReason = .adminForcePasswordReset - assertSnapshots( - of: subject.navStackWrapped, - as: [.tallPortraitAX5(heightMultiple: 6)], - ) - } - - /// A snapshot of the view with all filled values fields. - @MainActor - func disabletest_snapshot_weakPassword_withFilled_default() { - processor.state.forcePasswordResetReason = .weakMasterPasswordOnLogin - assertSnapshots( - of: subject.navStackWrapped, - as: [.portrait(heightMultiple: 1.25)], - ) - } - - /// A snapshot of the view with all filled values fields in a dark mode. - @MainActor - func disabletest_snapshot_weakPassword_withFilled_dark() { - processor.state.forcePasswordResetReason = .weakMasterPasswordOnLogin - assertSnapshots( - of: subject.navStackWrapped, - as: [.portraitDark(heightMultiple: 1.25)], - ) - } - - /// A snapshot of the view with all filled values fields in a large text. - @MainActor - func disabletest_snapshot_weakPassword_withFilled_large() { - processor.state.forcePasswordResetReason = .weakMasterPasswordOnLogin - assertSnapshots( - of: subject.navStackWrapped, - as: [.tallPortraitAX5(heightMultiple: 6)], - ) - } } diff --git a/BitwardenShared/UI/Auth/Utilities/TestHelpers/MockUserVerificationHelperDelegate.swift b/BitwardenShared/UI/Auth/Utilities/TestHelpers/MockUserVerificationHelperDelegate.swift new file mode 100644 index 000000000..0f796f77b --- /dev/null +++ b/BitwardenShared/UI/Auth/Utilities/TestHelpers/MockUserVerificationHelperDelegate.swift @@ -0,0 +1,26 @@ +import Foundation +import XCTest + +@testable import BitwardenShared + +class MockUserVerificationHelperDelegate: UserVerificationDelegate { + var alertShown = [Alert]() + var alertShownHandler: ((Alert) async throws -> Void)? + var alertOnDismissed: (() -> Void)? + + func showAlert(_ alert: Alert) { + alertShown.append(alert) + Task { + do { + try await alertShownHandler?(alert) + } catch { + XCTFail("Error calling alert shown handler: \(error)") + } + } + } + + func showAlert(_ alert: BitwardenShared.Alert, onDismissed: (() -> Void)?) { + showAlert(alert) + alertOnDismissed = onDismissed + } +} diff --git a/BitwardenShared/UI/Auth/Utilities/UserVerificationHelperTests.swift b/BitwardenShared/UI/Auth/Utilities/UserVerificationHelperTests.swift index c0066f4a5..d15972430 100644 --- a/BitwardenShared/UI/Auth/Utilities/UserVerificationHelperTests.swift +++ b/BitwardenShared/UI/Auth/Utilities/UserVerificationHelperTests.swift @@ -425,26 +425,4 @@ class UserVerificationHelperTests: BitwardenTestCase { // swiftlint:disable:this try alert.setText("pin", forTextFieldWithId: "pin") try await alert.tapAction(title: Localizations.submit) } -} - -class MockUserVerificationHelperDelegate: UserVerificationDelegate { - var alertShown = [Alert]() - var alertShownHandler: ((Alert) async throws -> Void)? - var alertOnDismissed: (() -> Void)? - - func showAlert(_ alert: Alert) { - alertShown.append(alert) - Task { - do { - try await alertShownHandler?(alert) - } catch { - XCTFail("Error calling alert shown handler: \(error)") - } - } - } - - func showAlert(_ alert: BitwardenShared.Alert, onDismissed: (() -> Void)?) { - showAlert(alert) - alertOnDismissed = onDismissed - } } // swiftlint:disable:this file_length diff --git a/BitwardenShared/UI/Auth/VaultUnlock/VaultUnlockViewTests.swift b/BitwardenShared/UI/Auth/VaultUnlock/VaultUnlockView+SnapshotTests.swift similarity index 58% rename from BitwardenShared/UI/Auth/VaultUnlock/VaultUnlockViewTests.swift rename to BitwardenShared/UI/Auth/VaultUnlock/VaultUnlockView+SnapshotTests.swift index 93fce214b..999fb40b2 100644 --- a/BitwardenShared/UI/Auth/VaultUnlock/VaultUnlockViewTests.swift +++ b/BitwardenShared/UI/Auth/VaultUnlock/VaultUnlockView+SnapshotTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import BitwardenResources import SnapshotTesting import XCTest @@ -40,104 +41,6 @@ class VaultUnlockViewTests: BitwardenTestCase { subject = nil } - // MARK: Tests - - /// Tapping the cancel button in the navigation bar dispatches the `.cancelPressed` action. - @MainActor - func test_cancelButton_tap() throws { - processor.state.isInAppExtension = true - let button = try subject.inspect().findCancelToolbarButton() - try button.tap() - XCTAssertEqual(processor.dispatchedActions.last, .cancelPressed) - } - - /// The secure field is visible when `isMasterPasswordRevealed` is `false`. - @MainActor - func test_isMasterPasswordRevealed_false() throws { - processor.state.isMasterPasswordRevealed = false - XCTAssertNoThrow(try subject.inspect().find(secureField: "")) - let textField = try subject.inspect().find(textField: "") - XCTAssertTrue(textField.isHidden()) - } - - /// The text field is visible when `isMasterPasswordRevealed` is `true`. - @MainActor - func test_isMasterPasswordRevealed_true() throws { - processor.state.isMasterPasswordRevealed = true - XCTAssertNoThrow(try subject.inspect().find(textField: "")) - XCTAssertThrowsError(try subject.inspect().find(secureField: "")) - } - - /// Tapping the options button in the navigation bar dispatches the `.morePressed` action. - @MainActor - func test_optionsButton_logOut_tap() throws { - let button = try subject.inspect().find(button: Localizations.logOut) - try button.tap() - XCTAssertEqual(processor.dispatchedActions.last, .logOut) - } - - /// Updating the secure field dispatches the `.masterPasswordChanged()` action. - @MainActor - func test_secureField_updateValue() throws { - processor.state.isMasterPasswordRevealed = false - let secureField = try subject.inspect().find(secureField: "") - try secureField.setInput("text") - XCTAssertEqual(processor.dispatchedActions.last, .masterPasswordChanged("text")) - } - - /// Updating the text field dispatches the `.masterPasswordChanged()` action. - @MainActor - func test_textField_updateValue() throws { - processor.state.isMasterPasswordRevealed = true - let textField = try subject.inspect().find(textField: "") - try textField.setInput("text") - XCTAssertEqual(processor.dispatchedActions.last, .masterPasswordChanged("text")) - } - - /// Tapping the vault unlock button dispatches the `.unlockVault` action. - @MainActor - func test_vaultUnlockButton_tap() async throws { - let button = try subject.inspect().find(asyncButton: Localizations.unlock) - try await button.tap() - waitFor(!processor.effects.isEmpty) - XCTAssertEqual(processor.effects.last, .unlockVault) - } - - /// Tapping the vault biometric unlock button dispatches the `.unlockVaultWithBiometrics` action. - @MainActor - func test_vaultUnlockWithBiometricsButton_tap() throws { - processor.state.biometricUnlockStatus = .available( - .faceID, - enabled: true, - ) - var expectedString = Localizations.useFaceIDToUnlock - var button = try subject.inspect().find(button: expectedString) - - processor.state.biometricUnlockStatus = .available( - .touchID, - enabled: true, - ) - expectedString = Localizations.useFingerprintToUnlock - button = try subject.inspect().find(button: expectedString) - - processor.state.biometricUnlockStatus = .available( - .opticID, - enabled: true, - ) - expectedString = Localizations.useOpticIDToUnlock - button = try subject.inspect().find(button: expectedString) - - processor.state.biometricUnlockStatus = .available( - .unknown, - enabled: true, - ) - expectedString = Localizations.useBiometricsToUnlock - button = try subject.inspect().find(button: expectedString) - try button.tap() - waitFor(!processor.effects.isEmpty) - XCTAssertEqual(processor.effects.last, .unlockVaultWithBiometrics) - } - // MARK: Snapshots /// Test a snapshot of the empty view. diff --git a/BitwardenShared/UI/Auth/VaultUnlock/VaultUnlockView+ViewInspectorTests.swift b/BitwardenShared/UI/Auth/VaultUnlock/VaultUnlockView+ViewInspectorTests.swift new file mode 100644 index 000000000..f4eb24461 --- /dev/null +++ b/BitwardenShared/UI/Auth/VaultUnlock/VaultUnlockView+ViewInspectorTests.swift @@ -0,0 +1,140 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import XCTest + +@testable import BitwardenShared + +class VaultUnlockViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: VaultUnlockView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor( + state: VaultUnlockState( + email: "user@bitwarden.com", + profileSwitcherState: .init( + accounts: [], + activeAccountId: nil, + allowLockAndLogout: false, + isVisible: false, + ), + unlockMethod: .password, + webVaultHost: "bitwarden.com", + ), + ) + let store = Store(processor: processor) + + subject = VaultUnlockView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Tests + + /// Tapping the cancel button in the navigation bar dispatches the `.cancelPressed` action. + @MainActor + func test_cancelButton_tap() throws { + processor.state.isInAppExtension = true + let button = try subject.inspect().findCancelToolbarButton() + try button.tap() + XCTAssertEqual(processor.dispatchedActions.last, .cancelPressed) + } + + /// The secure field is visible when `isMasterPasswordRevealed` is `false`. + @MainActor + func test_isMasterPasswordRevealed_false() throws { + processor.state.isMasterPasswordRevealed = false + XCTAssertNoThrow(try subject.inspect().find(secureField: "")) + let textField = try subject.inspect().find(textField: "") + XCTAssertTrue(textField.isHidden()) + } + + /// The text field is visible when `isMasterPasswordRevealed` is `true`. + @MainActor + func test_isMasterPasswordRevealed_true() throws { + processor.state.isMasterPasswordRevealed = true + XCTAssertNoThrow(try subject.inspect().find(textField: "")) + XCTAssertThrowsError(try subject.inspect().find(secureField: "")) + } + + /// Tapping the options button in the navigation bar dispatches the `.morePressed` action. + @MainActor + func test_optionsButton_logOut_tap() throws { + let button = try subject.inspect().find(button: Localizations.logOut) + try button.tap() + XCTAssertEqual(processor.dispatchedActions.last, .logOut) + } + + /// Updating the secure field dispatches the `.masterPasswordChanged()` action. + @MainActor + func test_secureField_updateValue() throws { + processor.state.isMasterPasswordRevealed = false + let secureField = try subject.inspect().find(secureField: "") + try secureField.setInput("text") + XCTAssertEqual(processor.dispatchedActions.last, .masterPasswordChanged("text")) + } + + /// Updating the text field dispatches the `.masterPasswordChanged()` action. + @MainActor + func test_textField_updateValue() throws { + processor.state.isMasterPasswordRevealed = true + let textField = try subject.inspect().find(textField: "") + try textField.setInput("text") + XCTAssertEqual(processor.dispatchedActions.last, .masterPasswordChanged("text")) + } + + /// Tapping the vault unlock button dispatches the `.unlockVault` action. + @MainActor + func test_vaultUnlockButton_tap() async throws { + let button = try subject.inspect().find(asyncButton: Localizations.unlock) + try await button.tap() + waitFor(!processor.effects.isEmpty) + XCTAssertEqual(processor.effects.last, .unlockVault) + } + + /// Tapping the vault biometric unlock button dispatches the `.unlockVaultWithBiometrics` action. + @MainActor + func test_vaultUnlockWithBiometricsButton_tap() throws { + processor.state.biometricUnlockStatus = .available( + .faceID, + enabled: true, + ) + var expectedString = Localizations.useFaceIDToUnlock + var button = try subject.inspect().find(button: expectedString) + + processor.state.biometricUnlockStatus = .available( + .touchID, + enabled: true, + ) + expectedString = Localizations.useFingerprintToUnlock + button = try subject.inspect().find(button: expectedString) + + processor.state.biometricUnlockStatus = .available( + .opticID, + enabled: true, + ) + expectedString = Localizations.useOpticIDToUnlock + button = try subject.inspect().find(button: expectedString) + + processor.state.biometricUnlockStatus = .available( + .unknown, + enabled: true, + ) + expectedString = Localizations.useBiometricsToUnlock + button = try subject.inspect().find(button: expectedString) + try button.tap() + waitFor(!processor.effects.isEmpty) + XCTAssertEqual(processor.effects.last, .unlockVaultWithBiometrics) + } +} diff --git a/BitwardenShared/UI/Auth/VaultUnlockSetup/VaultUnlockSetupView+SnapshotTests.swift b/BitwardenShared/UI/Auth/VaultUnlockSetup/VaultUnlockSetupView+SnapshotTests.swift new file mode 100644 index 000000000..2f10d9b9b --- /dev/null +++ b/BitwardenShared/UI/Auth/VaultUnlockSetup/VaultUnlockSetupView+SnapshotTests.swift @@ -0,0 +1,82 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class VaultUnlockSetupViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: VaultUnlockSetupView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: VaultUnlockSetupState(accountSetupFlow: .createAccount)) + + subject = VaultUnlockSetupView(store: Store(processor: processor)) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// The vault unlock setup view renders correctly. + @MainActor + func disabletest_snapshot_vaultUnlockSetup() { + processor.state.biometricsStatus = .available(.faceID, enabled: false) + assertSnapshots( + of: subject.navStackWrapped, + as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5(heightMultiple: 2), .defaultLandscape], + ) + } + + /// The vault unlock setup view renders correctly when shown from settings. + @MainActor + func disabletest_snapshot_vaultUnlockSetup_settings() { + processor.state.accountSetupFlow = .settings + processor.state.biometricsStatus = .available(.faceID, enabled: false) + assertSnapshots( + of: subject.navStackWrapped, + as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5(heightMultiple: 2)], + ) + } + + /// The vault unlock setup view renders correctly for a device with Touch ID. + @MainActor + func disabletest_snapshot_vaultUnlockSetup_touchID() { + processor.state.biometricsStatus = .available(.touchID, enabled: false) + assertSnapshots( + of: subject.navStackWrapped, + as: [.defaultPortrait], + ) + } + + /// The vault unlock setup view renders correctly for a device without biometrics. + @MainActor + func disabletest_snapshot_vaultUnlockSetup_noBiometrics() { + assertSnapshots( + of: subject.navStackWrapped, + as: [.defaultPortrait], + ) + } + + /// The vault unlock setup view renders correctly with an unlock method enabled. + @MainActor + func disabletest_snapshot_vaultUnlockSetup_unlockMethodEnabled() { + processor.state.biometricsStatus = .available(.faceID, enabled: true) + assertSnapshots( + of: subject.navStackWrapped, + as: [.defaultPortrait], + ) + } +} diff --git a/BitwardenShared/UI/Auth/VaultUnlockSetup/VaultUnlockSetupViewTests.swift b/BitwardenShared/UI/Auth/VaultUnlockSetup/VaultUnlockSetupView+ViewInspectorTests.swift similarity index 58% rename from BitwardenShared/UI/Auth/VaultUnlockSetup/VaultUnlockSetupViewTests.swift rename to BitwardenShared/UI/Auth/VaultUnlockSetup/VaultUnlockSetupView+ViewInspectorTests.swift index 0baeb8e17..308246d7a 100644 --- a/BitwardenShared/UI/Auth/VaultUnlockSetup/VaultUnlockSetupViewTests.swift +++ b/BitwardenShared/UI/Auth/VaultUnlockSetup/VaultUnlockSetupView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import ViewInspector import XCTest @@ -78,56 +78,4 @@ class VaultUnlockSetupViewTests: BitwardenTestCase { try button.tap() XCTAssertEqual(processor.dispatchedActions.last, .setUpLater) } - - // MARK: Snapshots - - /// The vault unlock setup view renders correctly. - @MainActor - func disabletest_snapshot_vaultUnlockSetup() { - processor.state.biometricsStatus = .available(.faceID, enabled: false) - assertSnapshots( - of: subject.navStackWrapped, - as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5(heightMultiple: 2), .defaultLandscape], - ) - } - - /// The vault unlock setup view renders correctly when shown from settings. - @MainActor - func disabletest_snapshot_vaultUnlockSetup_settings() { - processor.state.accountSetupFlow = .settings - processor.state.biometricsStatus = .available(.faceID, enabled: false) - assertSnapshots( - of: subject.navStackWrapped, - as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5(heightMultiple: 2)], - ) - } - - /// The vault unlock setup view renders correctly for a device with Touch ID. - @MainActor - func disabletest_snapshot_vaultUnlockSetup_touchID() { - processor.state.biometricsStatus = .available(.touchID, enabled: false) - assertSnapshots( - of: subject.navStackWrapped, - as: [.defaultPortrait], - ) - } - - /// The vault unlock setup view renders correctly for a device without biometrics. - @MainActor - func disabletest_snapshot_vaultUnlockSetup_noBiometrics() { - assertSnapshots( - of: subject.navStackWrapped, - as: [.defaultPortrait], - ) - } - - /// The vault unlock setup view renders correctly with an unlock method enabled. - @MainActor - func disabletest_snapshot_vaultUnlockSetup_unlockMethodEnabled() { - processor.state.biometricsStatus = .available(.faceID, enabled: true) - assertSnapshots( - of: subject.navStackWrapped, - as: [.defaultPortrait], - ) - } } diff --git a/BitwardenShared/UI/Autofill/Utilities/Fido2UserVerificationMediatorTests.swift b/BitwardenShared/UI/Autofill/Utilities/Fido2UserVerificationMediatorTests.swift index c6ae2e90b..4534ab0d7 100644 --- a/BitwardenShared/UI/Autofill/Utilities/Fido2UserVerificationMediatorTests.swift +++ b/BitwardenShared/UI/Autofill/Utilities/Fido2UserVerificationMediatorTests.swift @@ -419,18 +419,4 @@ class Fido2UserVerificationMediatorTests: BitwardenTestCase { // swiftlint:disab } } } -} - -class MockFido2UserVerificationMediatorDelegate: - MockUserVerificationHelperDelegate, - Fido2UserVerificationMediatorDelegate { - var onNeedsUserInteractionCalled = false - var onNeedsUserInteractionError: Error? - - func onNeedsUserInteraction() async throws { - onNeedsUserInteractionCalled = true - if let onNeedsUserInteractionError { - throw onNeedsUserInteractionError - } - } } // swiftlint:disable:this file_length diff --git a/BitwardenShared/UI/Autofill/Utilities/TestHelpers/MockFido2UserVerificationMediatorDelegate.swift b/BitwardenShared/UI/Autofill/Utilities/TestHelpers/MockFido2UserVerificationMediatorDelegate.swift new file mode 100644 index 000000000..ecbe1b01b --- /dev/null +++ b/BitwardenShared/UI/Autofill/Utilities/TestHelpers/MockFido2UserVerificationMediatorDelegate.swift @@ -0,0 +1,17 @@ +import BitwardenSdk + +@testable import BitwardenShared + +class MockFido2UserVerificationMediatorDelegate: + MockUserVerificationHelperDelegate, + Fido2UserVerificationMediatorDelegate { + var onNeedsUserInteractionCalled = false + var onNeedsUserInteractionError: Error? + + func onNeedsUserInteraction() async throws { + onNeedsUserInteractionCalled = true + if let onNeedsUserInteractionError { + throw onNeedsUserInteractionError + } + } +} diff --git a/BitwardenShared/UI/Platform/Application/Views/ActionCardTests.swift b/BitwardenShared/UI/Platform/Application/Views/ActionCard+ViewInspectorTests.swift similarity index 97% rename from BitwardenShared/UI/Platform/Application/Views/ActionCardTests.swift rename to BitwardenShared/UI/Platform/Application/Views/ActionCard+ViewInspectorTests.swift index d6e42a7df..4e3ab4805 100644 --- a/BitwardenShared/UI/Platform/Application/Views/ActionCardTests.swift +++ b/BitwardenShared/UI/Platform/Application/Views/ActionCard+ViewInspectorTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import SwiftUI import XCTest diff --git a/BitwardenShared/UI/Platform/Application/Views/BitwardenSegmentedControlTests.swift b/BitwardenShared/UI/Platform/Application/Views/BitwardenSegmentedControl+ViewInspectorTests.swift similarity index 98% rename from BitwardenShared/UI/Platform/Application/Views/BitwardenSegmentedControlTests.swift rename to BitwardenShared/UI/Platform/Application/Views/BitwardenSegmentedControl+ViewInspectorTests.swift index da9a06f8e..058686b51 100644 --- a/BitwardenShared/UI/Platform/Application/Views/BitwardenSegmentedControlTests.swift +++ b/BitwardenShared/UI/Platform/Application/Views/BitwardenSegmentedControl+ViewInspectorTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import BitwardenKit import SwiftUI import ViewInspector diff --git a/BitwardenShared/UI/Platform/Application/Views/BitwardenSliderTests.swift b/BitwardenShared/UI/Platform/Application/Views/BitwardenSlider+SnapshotTests.swift similarity index 97% rename from BitwardenShared/UI/Platform/Application/Views/BitwardenSliderTests.swift rename to BitwardenShared/UI/Platform/Application/Views/BitwardenSlider+SnapshotTests.swift index 88439d524..9bb80f544 100644 --- a/BitwardenShared/UI/Platform/Application/Views/BitwardenSliderTests.swift +++ b/BitwardenShared/UI/Platform/Application/Views/BitwardenSlider+SnapshotTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import SnapshotTesting import XCTest diff --git a/BitwardenShared/UI/Platform/Application/Views/BitwardenTabBarControllerTests.swift b/BitwardenShared/UI/Platform/Application/Views/BitwardenTabBarController+SnapshotTests.swift similarity index 99% rename from BitwardenShared/UI/Platform/Application/Views/BitwardenTabBarControllerTests.swift rename to BitwardenShared/UI/Platform/Application/Views/BitwardenTabBarController+SnapshotTests.swift index c8392221c..233c1db8f 100644 --- a/BitwardenShared/UI/Platform/Application/Views/BitwardenTabBarControllerTests.swift +++ b/BitwardenShared/UI/Platform/Application/Views/BitwardenTabBarController+SnapshotTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import BitwardenKitMocks import SnapshotTesting import XCTest diff --git a/BitwardenShared/UI/Platform/Application/Views/ExpandableContentTests.swift b/BitwardenShared/UI/Platform/Application/Views/ExpandableContent+ViewInspectorTests.swift similarity index 96% rename from BitwardenShared/UI/Platform/Application/Views/ExpandableContentTests.swift rename to BitwardenShared/UI/Platform/Application/Views/ExpandableContent+ViewInspectorTests.swift index 5e4c02f68..52ec95d51 100644 --- a/BitwardenShared/UI/Platform/Application/Views/ExpandableContentTests.swift +++ b/BitwardenShared/UI/Platform/Application/Views/ExpandableContent+ViewInspectorTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import SwiftUI import ViewInspector import XCTest diff --git a/BitwardenShared/UI/Platform/Application/Views/GuidedTourView/GuidedTourView+GeneratorTests.swift b/BitwardenShared/UI/Platform/Application/Views/GuidedTourView/GuidedTourView+GeneratorTests.swift deleted file mode 100644 index a5611993d..000000000 --- a/BitwardenShared/UI/Platform/Application/Views/GuidedTourView/GuidedTourView+GeneratorTests.swift +++ /dev/null @@ -1,108 +0,0 @@ -// swiftlint:disable:this file_name -import SnapshotTesting -import SwiftUI -import ViewInspector -import XCTest - -@testable import BitwardenShared - -// MARK: - GuidedTourView+GeneratorTests - -class GuidedTourViewGeneratorTests: BitwardenTestCase { - // MARK: Properties - - var processor: MockProcessor! - var subject: GuidedTourView! - - // MARK: Setup & Teardown - - override func setUp() { - super.setUp() - processor = MockProcessor( - state: GuidedTourViewState(currentIndex: 0, guidedTourStepStates: [ - .generatorStep1, - .generatorStep2, - .generatorStep3, - .generatorStep4, - .generatorStep5, - .generatorStep6, - ]), - ) - let store = Store(processor: processor) - subject = GuidedTourView(store: store) - } - - override func tearDown() { - super.tearDown() - processor = nil - subject = nil - } - - // MARK: Snapshot tests - - /// Test the snapshot of the step 1 of the learn generator guided tour. - @MainActor - func disabletest_snapshot_generatorStep1() { - processor.state.currentIndex = 0 - processor.state.guidedTourStepStates[0].spotlightRegion = CGRect(x: 25, y: 80, width: 340, height: 40) - assertSnapshots( - of: subject, - as: [.defaultPortrait], - ) - } - - /// Test the snapshot of the step 2 of the learn generator guided tour. - @MainActor - func disabletest_snapshot_generatorStep2() { - processor.state.currentIndex = 1 - processor.state.guidedTourStepStates[1].spotlightRegion = CGRect(x: 25, y: 80, width: 340, height: 40) - assertSnapshots( - of: subject, - as: [.defaultPortrait], - ) - } - - /// Test the snapshot of the step 3 of the learn generator guided tour. - @MainActor - func disabletest_snapshot_generatorStep3() { - processor.state.currentIndex = 2 - processor.state.guidedTourStepStates[2].spotlightRegion = CGRect(x: 25, y: 80, width: 340, height: 40) - assertSnapshots( - of: subject, - as: [.defaultPortrait], - ) - } - - /// Test the snapshot of the step 4 of the learn generator guided tour. - @MainActor - func disabletest_snapshot_generatorStep4() { - processor.state.currentIndex = 3 - processor.state.guidedTourStepStates[3].spotlightRegion = CGRect(x: 25, y: 300, width: 340, height: 400) - assertSnapshots( - of: subject, - as: [.defaultPortrait], - ) - } - - /// Test the snapshot of the step 5 of the learn generator guided tour. - @MainActor - func disabletest_snapshot_generatorStep5() { - processor.state.currentIndex = 4 - processor.state.guidedTourStepStates[4].spotlightRegion = CGRect(x: 300, y: 160, width: 40, height: 40) - assertSnapshots( - of: subject, - as: [.defaultPortrait], - ) - } - - /// Test the snapshot of the step 6 of the learn generator guided tour. - @MainActor - func disabletest_snapshot_generatorStep6() { - processor.state.currentIndex = 5 - processor.state.guidedTourStepStates[5].spotlightRegion = CGRect(x: 25, y: 160, width: 340, height: 60) - assertSnapshots( - of: subject, - as: [.defaultPortrait], - ) - } -} diff --git a/BitwardenShared/UI/Platform/Application/Views/GuidedTourView/GuidedTourView+LoginTests.swift b/BitwardenShared/UI/Platform/Application/Views/GuidedTourView/GuidedTourView+LoginSnapshotTests.swift similarity index 70% rename from BitwardenShared/UI/Platform/Application/Views/GuidedTourView/GuidedTourView+LoginTests.swift rename to BitwardenShared/UI/Platform/Application/Views/GuidedTourView/GuidedTourView+LoginSnapshotTests.swift index 5a0dbadcc..9f8e4f43e 100644 --- a/BitwardenShared/UI/Platform/Application/Views/GuidedTourView/GuidedTourView+LoginTests.swift +++ b/BitwardenShared/UI/Platform/Application/Views/GuidedTourView/GuidedTourView+LoginSnapshotTests.swift @@ -2,7 +2,6 @@ import BitwardenResources import SnapshotTesting import SwiftUI -import ViewInspector import XCTest @testable import BitwardenShared @@ -36,43 +35,6 @@ class GuidedTourViewLoginTests: BitwardenTestCase { subject = nil } - // MARK: Tests - - /// Tap the `back` button should dispatch the `backTapped` action. - @MainActor - func test_backButton_tap() async throws { - processor.state.currentIndex = 1 - let button = try subject.inspect().find(button: Localizations.back) - try button.tap() - XCTAssertEqual(processor.dispatchedActions, [.backTapped]) - } - - /// Tapping the `done` button should dispatch the `doneTapped` action. - @MainActor - func test_doneButton_tap() async throws { - processor.state.currentIndex = 2 - let button = try subject.inspect().find(button: Localizations.done) - try button.tap() - XCTAssertEqual(processor.dispatchedActions, [.doneTapped]) - } - - /// Tapping the dismiss button dispatches the `.dismissTapped` action. - @MainActor - func test_dismissButton_tap() async throws { - processor.state.currentIndex = 2 - let button = try subject.inspect().find(button: Localizations.dismiss) - try button.tap() - XCTAssertEqual(processor.dispatchedActions, [.dismissTapped]) - } - - /// Tapping the `next` button should dispatch the `nextTapped` action. - @MainActor - func test_nextButton_tap() async throws { - let button = try subject.inspect().find(button: Localizations.next) - try button.tap() - XCTAssertEqual(processor.dispatchedActions, [.nextTapped]) - } - // MARK: Snapshot tests /// Test the snapshot of the step 1 of the learn new login guided tour. diff --git a/BitwardenShared/UI/Platform/Application/Views/GuidedTourView/GuidedTourViewTests.swift b/BitwardenShared/UI/Platform/Application/Views/GuidedTourView/GuidedTourView+ViewInspectorTests.swift similarity index 98% rename from BitwardenShared/UI/Platform/Application/Views/GuidedTourView/GuidedTourViewTests.swift rename to BitwardenShared/UI/Platform/Application/Views/GuidedTourView/GuidedTourView+ViewInspectorTests.swift index 53293dc2b..eba813236 100644 --- a/BitwardenShared/UI/Platform/Application/Views/GuidedTourView/GuidedTourViewTests.swift +++ b/BitwardenShared/UI/Platform/Application/Views/GuidedTourView/GuidedTourView+ViewInspectorTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import BitwardenResources import SwiftUI import ViewInspector diff --git a/BitwardenShared/UI/Platform/Application/Views/IllustratedMessageViewTests.swift b/BitwardenShared/UI/Platform/Application/Views/IllustratedMessageView+SnapshotTests.swift similarity index 75% rename from BitwardenShared/UI/Platform/Application/Views/IllustratedMessageViewTests.swift rename to BitwardenShared/UI/Platform/Application/Views/IllustratedMessageView+SnapshotTests.swift index 6f8ee69f8..d009685b3 100644 --- a/BitwardenShared/UI/Platform/Application/Views/IllustratedMessageViewTests.swift +++ b/BitwardenShared/UI/Platform/Application/Views/IllustratedMessageView+SnapshotTests.swift @@ -1,7 +1,7 @@ +// swiftlint:disable:this file_name import BitwardenResources import SnapshotTesting import SwiftUI -import ViewInspector import XCTest @testable import BitwardenShared @@ -9,29 +9,6 @@ import XCTest class IllustratedMessageViewTests: BitwardenTestCase { // MARK: Tests - /// Tapping the button (if it is there) dispatches the action. - @MainActor - func test_button_tap() throws { - var tapped = false - let subject = IllustratedMessageView( - image: Asset.Images.Illustrations.biometricsPhone, - style: .mediumImage, - title: Localizations.setUpUnlock, - message: Localizations.setUpBiometricsOrChooseAPinCodeToQuicklyAccessYourVaultAndAutofillYourLogins, - ) { - Button { - tapped = true - } label: { - Text(Localizations.learnMore) - .styleGuide(.subheadline) - .foregroundStyle(SharedAsset.Colors.textInteraction.swiftUIColor) - } - } - let button = try subject.inspect().find(button: Localizations.learnMore) - try button.tap() - XCTAssertTrue(tapped) - } - /// Test snapshots of the largeTextTintedIcon style. func disabletest_snapshot_largeTextTintedIcon() { let subject = IllustratedMessageView( diff --git a/BitwardenShared/UI/Platform/Application/Views/IllustratedMessageView+ViewInspectorTests.swift b/BitwardenShared/UI/Platform/Application/Views/IllustratedMessageView+ViewInspectorTests.swift new file mode 100644 index 000000000..2c1b9e3d2 --- /dev/null +++ b/BitwardenShared/UI/Platform/Application/Views/IllustratedMessageView+ViewInspectorTests.swift @@ -0,0 +1,34 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SwiftUI +import ViewInspector +import XCTest + +@testable import BitwardenShared + +class IllustratedMessageViewTests: BitwardenTestCase { + // MARK: Tests + + /// Tapping the button (if it is there) dispatches the action. + @MainActor + func test_button_tap() throws { + var tapped = false + let subject = IllustratedMessageView( + image: Asset.Images.Illustrations.biometricsPhone, + style: .mediumImage, + title: Localizations.setUpUnlock, + message: Localizations.setUpBiometricsOrChooseAPinCodeToQuicklyAccessYourVaultAndAutofillYourLogins, + ) { + Button { + tapped = true + } label: { + Text(Localizations.learnMore) + .styleGuide(.subheadline) + .foregroundStyle(SharedAsset.Colors.textInteraction.swiftUIColor) + } + } + let button = try subject.inspect().find(button: Localizations.learnMore) + try button.tap() + XCTAssertTrue(tapped) + } +} diff --git a/BitwardenShared/UI/Platform/Application/Views/LoadingOverlayViewTests.swift b/BitwardenShared/UI/Platform/Application/Views/LoadingOverlayView+SnapshotTests.swift similarity index 92% rename from BitwardenShared/UI/Platform/Application/Views/LoadingOverlayViewTests.swift rename to BitwardenShared/UI/Platform/Application/Views/LoadingOverlayView+SnapshotTests.swift index 011184b56..476d40685 100644 --- a/BitwardenShared/UI/Platform/Application/Views/LoadingOverlayViewTests.swift +++ b/BitwardenShared/UI/Platform/Application/Views/LoadingOverlayView+SnapshotTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import SnapshotTesting import TestHelpers import XCTest diff --git a/BitwardenShared/UI/Platform/Application/Views/PasswordStrengthIndicator+SnapshotTests.swift b/BitwardenShared/UI/Platform/Application/Views/PasswordStrengthIndicator+SnapshotTests.swift new file mode 100644 index 000000000..2f76c2dba --- /dev/null +++ b/BitwardenShared/UI/Platform/Application/Views/PasswordStrengthIndicator+SnapshotTests.swift @@ -0,0 +1,35 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import SwiftUI +import XCTest + +@testable import BitwardenShared + +class PasswordStrengthIndicatorTests: BitwardenTestCase { + // MARK: Snapshots + + /// Test a snapshot of the password strength indicator variations. + func disabletest_snapshot_passwordStrengthIndicator() { + struct SnapshotView: View { + var body: some View { + ScrollView { + VStack(spacing: 32) { + PasswordStrengthIndicator( + passwordStrengthScore: nil, + ) + + ForEach(UInt8(0) ... UInt8(4), id: \.self) { score in + PasswordStrengthIndicator( + passwordStrengthScore: score, + ) + } + } + .padding() + } + } + } + + assertSnapshots(of: SnapshotView(), as: [.defaultPortrait, .defaultPortraitDark]) + } +} diff --git a/BitwardenShared/UI/Platform/Application/Views/PasswordStrengthIndicatorTests.swift b/BitwardenShared/UI/Platform/Application/Views/PasswordStrengthIndicatorTests.swift index 3943535fa..82815c06c 100644 --- a/BitwardenShared/UI/Platform/Application/Views/PasswordStrengthIndicatorTests.swift +++ b/BitwardenShared/UI/Platform/Application/Views/PasswordStrengthIndicatorTests.swift @@ -1,5 +1,4 @@ import BitwardenResources -import SnapshotTesting import SwiftUI import XCTest @@ -77,30 +76,4 @@ class PasswordStrengthIndicatorTests: BitwardenTestCase { XCTAssertNil(view.passwordStrength.text) XCTAssertEqual(view.passwordStrength.strengthPercent, 0) } - - // MARK: Snapshots - - /// Test a snapshot of the password strength indicator variations. - func disabletest_snapshot_passwordStrengthIndicator() { - struct SnapshotView: View { - var body: some View { - ScrollView { - VStack(spacing: 32) { - PasswordStrengthIndicator( - passwordStrengthScore: nil, - ) - - ForEach(UInt8(0) ... UInt8(4), id: \.self) { score in - PasswordStrengthIndicator( - passwordStrengthScore: score, - ) - } - } - .padding() - } - } - } - - assertSnapshots(of: SnapshotView(), as: [.defaultPortrait, .defaultPortraitDark]) - } } diff --git a/BitwardenShared/UI/Platform/Application/Views/SectionViewTests.swift b/BitwardenShared/UI/Platform/Application/Views/SectionView+SnapshotTests.swift similarity index 92% rename from BitwardenShared/UI/Platform/Application/Views/SectionViewTests.swift rename to BitwardenShared/UI/Platform/Application/Views/SectionView+SnapshotTests.swift index d8646a664..8fb14d28a 100644 --- a/BitwardenShared/UI/Platform/Application/Views/SectionViewTests.swift +++ b/BitwardenShared/UI/Platform/Application/Views/SectionView+SnapshotTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import SnapshotTesting import XCTest diff --git a/BitwardenShared/UI/Platform/DebugMenu/DebugMenuView+SnapshotTests.swift b/BitwardenShared/UI/Platform/DebugMenu/DebugMenuView+SnapshotTests.swift new file mode 100644 index 000000000..9b69039d8 --- /dev/null +++ b/BitwardenShared/UI/Platform/DebugMenu/DebugMenuView+SnapshotTests.swift @@ -0,0 +1,57 @@ +// swiftlint:disable:this file_name +import BitwardenKit +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +// MARK: - DebugMenuViewTests + +class DebugMenuViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: DebugMenuView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor( + state: DebugMenuState( + featureFlags: [ + .init( + feature: .testFeatureFlag, + isEnabled: false, + ), + ], + ), + ) + let store = Store(processor: processor) + + subject = DebugMenuView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Tests + + /// Check the snapshot when feature flags are enabled and disabled. + @MainActor + func disabletest_snapshot_debugMenuWithFeatureFlags() { + processor.state.featureFlags = [ + .init(feature: .testFeatureFlag, isEnabled: true), + ] + assertSnapshot( + of: subject, + as: .defaultPortrait, + ) + } +} diff --git a/BitwardenShared/UI/Platform/DebugMenu/DebugMenuViewTests.swift b/BitwardenShared/UI/Platform/DebugMenu/DebugMenuView+ViewInspectorTests.swift similarity index 86% rename from BitwardenShared/UI/Platform/DebugMenu/DebugMenuViewTests.swift rename to BitwardenShared/UI/Platform/DebugMenu/DebugMenuView+ViewInspectorTests.swift index 565afedba..f5fb14768 100644 --- a/BitwardenShared/UI/Platform/DebugMenu/DebugMenuViewTests.swift +++ b/BitwardenShared/UI/Platform/DebugMenu/DebugMenuView+ViewInspectorTests.swift @@ -1,6 +1,6 @@ +// swiftlint:disable:this file_name import BitwardenKit import BitwardenResources -import SnapshotTesting import XCTest @testable import BitwardenShared @@ -80,21 +80,9 @@ class DebugMenuViewTests: BitwardenTestCase { /// Test that the refresh button sends the correct effect. @MainActor - func disabletest_snapshot_refreshFeatureFlags_tapped() async throws { + func disabletest_refreshFeatureFlags_tapped() async throws { let button = try subject.inspect().find(asyncButtonWithAccessibilityLabel: "RefreshFeatureFlagsButton") try await button.tap() XCTAssertEqual(processor.effects.last, .refreshFeatureFlags) } - - /// Check the snapshot when feature flags are enabled and disabled. - @MainActor - func disabletest_snapshot_debugMenuWithFeatureFlags() { - processor.state.featureFlags = [ - .init(feature: .testFeatureFlag, isEnabled: true), - ] - assertSnapshot( - of: subject, - as: .defaultPortrait, - ) - } } diff --git a/BitwardenShared/UI/Platform/ExtensionSetup/ExtensionActivation/ExtensionActivationViewTests.swift b/BitwardenShared/UI/Platform/ExtensionSetup/ExtensionActivation/ExtensionActivationView+SnapshotTests.swift similarity index 80% rename from BitwardenShared/UI/Platform/ExtensionSetup/ExtensionActivation/ExtensionActivationViewTests.swift rename to BitwardenShared/UI/Platform/ExtensionSetup/ExtensionActivation/ExtensionActivationView+SnapshotTests.swift index eb374f430..2065a3288 100644 --- a/BitwardenShared/UI/Platform/ExtensionSetup/ExtensionActivation/ExtensionActivationViewTests.swift +++ b/BitwardenShared/UI/Platform/ExtensionSetup/ExtensionActivation/ExtensionActivationView+SnapshotTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import BitwardenResources import SnapshotTesting import XCTest @@ -34,16 +35,6 @@ class ExtensionActivationViewTests: BitwardenTestCase { subject = nil } - // MARK: Tests - - /// Tapping the back to settings dispatches the `.cancelTapped` action. - @MainActor - func test_backToSettingsButton_tap() throws { - let button = try subject.inspect().find(button: Localizations.backToSettings) - try button.tap() - XCTAssertEqual(processor.dispatchedActions.last, .cancelTapped) - } - // MARK: Snapshots /// The autofill extension activation view renders correctly. diff --git a/BitwardenShared/UI/Platform/ExtensionSetup/ExtensionActivation/ExtensionActivationView+ViewInspectorTests.swift b/BitwardenShared/UI/Platform/ExtensionSetup/ExtensionActivation/ExtensionActivationView+ViewInspectorTests.swift new file mode 100644 index 000000000..58da8bfdd --- /dev/null +++ b/BitwardenShared/UI/Platform/ExtensionSetup/ExtensionActivation/ExtensionActivationView+ViewInspectorTests.swift @@ -0,0 +1,46 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import XCTest + +@testable import BitwardenShared + +// MARK: - ExtensionActivationViewTests + +class ExtensionActivationViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor< + ExtensionActivationState, + ExtensionActivationAction, + Void, + >! + var subject: ExtensionActivationView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: ExtensionActivationState(extensionType: .autofillExtension)) + let store = Store(processor: processor) + + subject = ExtensionActivationView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Tests + + /// Tapping the back to settings dispatches the `.cancelTapped` action. + @MainActor + func test_backToSettingsButton_tap() throws { + let button = try subject.inspect().find(button: Localizations.backToSettings) + try button.tap() + XCTAssertEqual(processor.dispatchedActions.last, .cancelTapped) + } +} diff --git a/BitwardenShared/UI/Platform/LoginRequest/LoginRequestView+SnapshotTests.swift b/BitwardenShared/UI/Platform/LoginRequest/LoginRequestView+SnapshotTests.swift new file mode 100644 index 000000000..dae028898 --- /dev/null +++ b/BitwardenShared/UI/Platform/LoginRequest/LoginRequestView+SnapshotTests.swift @@ -0,0 +1,49 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +// MARK: - ViewItemViewTests + +class LoginRequestViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: LoginRequestView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: LoginRequestState(request: .fixture( + fingerprintPhrase: "i-asked-chat-gpt-but-it-said-no", + ))) + let store = Store(processor: processor) + + subject = LoginRequestView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// The default view renders correctly. + func disabletest_snapshot() { + assertSnapshots( + of: subject.navStackWrapped, + as: [ + .defaultPortrait, + .defaultPortraitDark, + .tallPortraitAX5(heightMultiple: 2), + ], + ) + } +} diff --git a/BitwardenShared/UI/Platform/LoginRequest/LoginRequestViewTests.swift b/BitwardenShared/UI/Platform/LoginRequest/LoginRequestView+ViewInspectorTests.swift similarity index 82% rename from BitwardenShared/UI/Platform/LoginRequest/LoginRequestViewTests.swift rename to BitwardenShared/UI/Platform/LoginRequest/LoginRequestView+ViewInspectorTests.swift index bf5a00c8d..f39483254 100644 --- a/BitwardenShared/UI/Platform/LoginRequest/LoginRequestViewTests.swift +++ b/BitwardenShared/UI/Platform/LoginRequest/LoginRequestView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import XCTest @testable import BitwardenShared @@ -57,18 +57,4 @@ class LoginRequestViewTests: BitwardenTestCase { try await button.tap() XCTAssertEqual(processor.effects.last, .answerRequest(approve: false)) } - - // MARK: Snapshots - - /// The default view renders correctly. - func disabletest_snapshot() { - assertSnapshots( - of: subject.navStackWrapped, - as: [ - .defaultPortrait, - .defaultPortraitDark, - .tallPortraitAX5(heightMultiple: 2), - ], - ) - } } diff --git a/BitwardenShared/UI/Platform/Settings/Settings/About/AboutView+SnapshotTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/About/AboutView+SnapshotTests.swift new file mode 100644 index 000000000..ff7cc54d0 --- /dev/null +++ b/BitwardenShared/UI/Platform/Settings/Settings/About/AboutView+SnapshotTests.swift @@ -0,0 +1,42 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class AboutViewTests: BitwardenTestCase { + // MARK: Properties + + let copyrightText = "© Bitwarden Inc. 2015-2023" + let version = "Version: 1.0.0 (1)" + + var processor: MockProcessor! + var subject: AboutView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: AboutState(copyrightText: copyrightText, version: version)) + let store = Store(processor: processor) + + subject = AboutView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// The default view renders correctly. + @MainActor + func disabletest_snapshot_default() { + assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) + } +} diff --git a/BitwardenShared/UI/Platform/Settings/Settings/About/AboutViewTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/About/AboutView+ViewInspectorTests.swift similarity index 93% rename from BitwardenShared/UI/Platform/Settings/Settings/About/AboutViewTests.swift rename to BitwardenShared/UI/Platform/Settings/Settings/About/AboutView+ViewInspectorTests.swift index 98e326f47..5d2198cf9 100644 --- a/BitwardenShared/UI/Platform/Settings/Settings/About/AboutViewTests.swift +++ b/BitwardenShared/UI/Platform/Settings/Settings/About/AboutView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import XCTest @testable import BitwardenShared @@ -96,12 +96,4 @@ class AboutViewTests: BitwardenTestCase { try button.tap() XCTAssertEqual(processor.dispatchedActions.last, .webVaultTapped) } - - // MARK: Snapshots - - /// The default view renders correctly. - @MainActor - func disabletest_snapshot_default() { - assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) - } } diff --git a/BitwardenShared/UI/Platform/Settings/Settings/About/EnableFlightRecorder/EnableFlightRecorderProcessorTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/About/EnableFlightRecorder/EnableFlightRecorderProcessorTests.swift index 1c70f8505..009c6558d 100644 --- a/BitwardenShared/UI/Platform/Settings/Settings/About/EnableFlightRecorder/EnableFlightRecorderProcessorTests.swift +++ b/BitwardenShared/UI/Platform/Settings/Settings/About/EnableFlightRecorder/EnableFlightRecorderProcessorTests.swift @@ -1,5 +1,4 @@ import BitwardenKitMocks -import SnapshotTesting import TestHelpers import XCTest diff --git a/BitwardenShared/UI/Platform/Settings/Settings/About/EnableFlightRecorder/EnableFlightRecorderView+SnapshotTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/About/EnableFlightRecorder/EnableFlightRecorderView+SnapshotTests.swift new file mode 100644 index 000000000..5b4cc5f61 --- /dev/null +++ b/BitwardenShared/UI/Platform/Settings/Settings/About/EnableFlightRecorder/EnableFlightRecorderView+SnapshotTests.swift @@ -0,0 +1,39 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class EnableFlightRecorderViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: EnableFlightRecorderView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: EnableFlightRecorderState()) + let store = Store(processor: processor) + + subject = EnableFlightRecorderView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// The enable flight recorder view renders correctly. + @MainActor + func disabletest_snapshot_enableFlightRecorder() { + assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5(heightMultiple: 3)]) + } +} diff --git a/BitwardenShared/UI/Platform/Settings/Settings/About/EnableFlightRecorder/EnableFlightRecorderViewTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/About/EnableFlightRecorder/EnableFlightRecorderView+ViewInspectorTests.swift similarity index 87% rename from BitwardenShared/UI/Platform/Settings/Settings/About/EnableFlightRecorder/EnableFlightRecorderViewTests.swift rename to BitwardenShared/UI/Platform/Settings/Settings/About/EnableFlightRecorder/EnableFlightRecorderView+ViewInspectorTests.swift index 84bb06804..08187f897 100644 --- a/BitwardenShared/UI/Platform/Settings/Settings/About/EnableFlightRecorder/EnableFlightRecorderViewTests.swift +++ b/BitwardenShared/UI/Platform/Settings/Settings/About/EnableFlightRecorder/EnableFlightRecorderView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import XCTest @testable import BitwardenShared @@ -59,12 +59,4 @@ class EnableFlightRecorderViewTests: BitwardenTestCase { try await button.tap() XCTAssertEqual(processor.effects.last, .save) } - - // MARK: Snapshots - - /// The enable flight recorder view renders correctly. - @MainActor - func disabletest_snapshot_enableFlightRecorder() { - assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5(heightMultiple: 3)]) - } } diff --git a/BitwardenShared/UI/Platform/Settings/Settings/About/FlightRecorderLogs/FlightRecorderLogsProcessorTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/About/FlightRecorderLogs/FlightRecorderLogsProcessorTests.swift index 5009e1576..dc528e4b1 100644 --- a/BitwardenShared/UI/Platform/Settings/Settings/About/FlightRecorderLogs/FlightRecorderLogsProcessorTests.swift +++ b/BitwardenShared/UI/Platform/Settings/Settings/About/FlightRecorderLogs/FlightRecorderLogsProcessorTests.swift @@ -1,7 +1,6 @@ import BitwardenKit import BitwardenKitMocks import BitwardenResources -import SnapshotTesting import TestHelpers import XCTest diff --git a/BitwardenShared/UI/Platform/Settings/Settings/About/FlightRecorderLogs/FlightRecorderLogsView+SnapshotTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/About/FlightRecorderLogs/FlightRecorderLogsView+SnapshotTests.swift new file mode 100644 index 000000000..1dcd9678b --- /dev/null +++ b/BitwardenShared/UI/Platform/Settings/Settings/About/FlightRecorderLogs/FlightRecorderLogsView+SnapshotTests.swift @@ -0,0 +1,98 @@ +// swiftlint:disable:this file_name +import BitwardenKit +import BitwardenKitMocks +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class FlightRecorderLogsViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: FlightRecorderLogsView! + var timeProvider: TimeProvider! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: FlightRecorderLogsState()) + timeProvider = MockTimeProvider(.mockTime(Date(year: 2025, month: 4, day: 1))) + let store = Store(processor: processor) + + subject = FlightRecorderLogsView(store: store, timeProvider: timeProvider) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + timeProvider = nil + } + + // MARK: Snapshots + + /// The empty flight recorder logs view renders correctly. + @MainActor + func disabletest_snapshot_flightRecorderLogs_empty() { + assertSnapshots( + of: subject.navStackWrapped, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } + + /// The populated flight recorder logs view renders correctly. + @MainActor + func disabletest_snapshot_flightRecorderLogs_populated() { + processor.state.logs = [ + FlightRecorderLogMetadata( + duration: .eightHours, + endDate: Date(year: 2025, month: 4, day: 1, hour: 8), + expirationDate: Date(year: 2025, month: 5, day: 1, hour: 8), + fileSize: "2 KB", + id: "1", + isActiveLog: true, + startDate: Date(year: 2025, month: 4, day: 1), + url: URL(string: "https://example.com")!, + ), + FlightRecorderLogMetadata( + duration: .oneWeek, + endDate: Date(year: 2025, month: 3, day: 7), + expirationDate: Date(year: 2025, month: 4, day: 6), + fileSize: "12 KB", + id: "2", + isActiveLog: false, + startDate: Date(year: 2025, month: 3, day: 7), + url: URL(string: "https://example.com")!, + ), + FlightRecorderLogMetadata( + duration: .oneHour, + endDate: Date(year: 2025, month: 3, day: 3, hour: 13), + expirationDate: Date(year: 2025, month: 4, day: 2, hour: 13), + fileSize: "1.5 MB", + id: "3", + isActiveLog: false, + startDate: Date(year: 2025, month: 3, day: 3, hour: 12), + url: URL(string: "https://example.com")!, + ), + FlightRecorderLogMetadata( + duration: .twentyFourHours, + endDate: Date(year: 2025, month: 3, day: 2), + expirationDate: Date(year: 2025, month: 4, day: 1), + fileSize: "50 KB", + id: "4", + isActiveLog: false, + startDate: Date(year: 2025, month: 3, day: 1), + url: URL(string: "https://example.com")!, + ), + ] + assertSnapshots( + of: subject.navStackWrapped, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } +} diff --git a/BitwardenShared/UI/Platform/Settings/Settings/About/FlightRecorderLogs/FlightRecorderLogsViewTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/About/FlightRecorderLogs/FlightRecorderLogsView+ViewInspectorTests.swift similarity index 62% rename from BitwardenShared/UI/Platform/Settings/Settings/About/FlightRecorderLogs/FlightRecorderLogsViewTests.swift rename to BitwardenShared/UI/Platform/Settings/Settings/About/FlightRecorderLogs/FlightRecorderLogsView+ViewInspectorTests.swift index 1f494de77..99781430d 100644 --- a/BitwardenShared/UI/Platform/Settings/Settings/About/FlightRecorderLogs/FlightRecorderLogsViewTests.swift +++ b/BitwardenShared/UI/Platform/Settings/Settings/About/FlightRecorderLogs/FlightRecorderLogsView+ViewInspectorTests.swift @@ -1,7 +1,7 @@ +// swiftlint:disable:this file_name import BitwardenKit import BitwardenKitMocks import BitwardenResources -import SnapshotTesting import XCTest @testable import BitwardenShared @@ -114,66 +114,4 @@ class FlightRecorderLogsViewTests: BitwardenTestCase { try button.tap() XCTAssertEqual(processor.dispatchedActions.last, .shareAll) } - - // MARK: Snapshots - - /// The empty flight recorder logs view renders correctly. - @MainActor - func disabletest_snapshot_flightRecorderLogs_empty() { - assertSnapshots( - of: subject.navStackWrapped, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } - - /// The populated flight recorder logs view renders correctly. - @MainActor - func disabletest_snapshot_flightRecorderLogs_populated() { - processor.state.logs = [ - FlightRecorderLogMetadata( - duration: .eightHours, - endDate: Date(year: 2025, month: 4, day: 1, hour: 8), - expirationDate: Date(year: 2025, month: 5, day: 1, hour: 8), - fileSize: "2 KB", - id: "1", - isActiveLog: true, - startDate: Date(year: 2025, month: 4, day: 1), - url: URL(string: "https://example.com")!, - ), - FlightRecorderLogMetadata( - duration: .oneWeek, - endDate: Date(year: 2025, month: 3, day: 7), - expirationDate: Date(year: 2025, month: 4, day: 6), - fileSize: "12 KB", - id: "2", - isActiveLog: false, - startDate: Date(year: 2025, month: 3, day: 7), - url: URL(string: "https://example.com")!, - ), - FlightRecorderLogMetadata( - duration: .oneHour, - endDate: Date(year: 2025, month: 3, day: 3, hour: 13), - expirationDate: Date(year: 2025, month: 4, day: 2, hour: 13), - fileSize: "1.5 MB", - id: "3", - isActiveLog: false, - startDate: Date(year: 2025, month: 3, day: 3, hour: 12), - url: URL(string: "https://example.com")!, - ), - FlightRecorderLogMetadata( - duration: .twentyFourHours, - endDate: Date(year: 2025, month: 3, day: 2), - expirationDate: Date(year: 2025, month: 4, day: 1), - fileSize: "50 KB", - id: "4", - isActiveLog: false, - startDate: Date(year: 2025, month: 3, day: 1), - url: URL(string: "https://example.com")!, - ), - ] - assertSnapshots( - of: subject.navStackWrapped, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } } diff --git a/BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/AccountSecurityView+SnapshotTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/AccountSecurityView+SnapshotTests.swift new file mode 100644 index 000000000..34c2d7334 --- /dev/null +++ b/BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/AccountSecurityView+SnapshotTests.swift @@ -0,0 +1,176 @@ +// swiftlint:disable:this file_name +import BitwardenKit +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class AccountSecurityViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: AccountSecurityView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: AccountSecurityState()) + let store = Store(processor: processor) + + subject = AccountSecurityView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// The view renders correctly with the vault unlock action card is displayed. + @MainActor + func disabletest_snapshot_actionCardVaultUnlock() async { + processor.state.badgeState = .fixture(vaultUnlockSetupProgress: .setUpLater) + assertSnapshots( + of: subject, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } + + /// The view renders correctly when biometrics are available. + @MainActor + func disabletest_snapshot_biometricsDisabled_touchID() { + let subject = AccountSecurityView( + store: Store( + processor: StateProcessor( + state: AccountSecurityState( + biometricUnlockStatus: .available( + .touchID, + enabled: false, + ), + sessionTimeoutValue: .custom(1), + ), + ), + ), + ) + assertSnapshot(of: subject, as: .defaultPortrait) + } + + /// The view renders correctly when biometrics are available. + @MainActor + func disabletest_snapshot_biometricsEnabled_faceID() { + let subject = AccountSecurityView( + store: Store( + processor: StateProcessor( + state: AccountSecurityState( + biometricUnlockStatus: .available( + .faceID, + enabled: true, + ), + sessionTimeoutValue: .custom(1), + ), + ), + ), + ) + assertSnapshot(of: subject, as: .defaultPortrait) + } + + /// The view renders correctly when showing the custom session timeout field. + @MainActor + func disabletest_snapshot_customSessionTimeoutField() { + let subject = AccountSecurityView( + store: Store( + processor: StateProcessor( + state: AccountSecurityState(sessionTimeoutValue: .custom(1)), + ), + ), + ) + assertSnapshot(of: subject, as: .defaultPortrait) + } + + /// The view renders correctly when the user doesn't have a master password. + @MainActor + func disabletest_snapshot_noMasterPassword() { + let subject = AccountSecurityView( + store: Store( + processor: StateProcessor( + state: AccountSecurityState( + hasMasterPassword: false, + sessionTimeoutAction: .logout, + ), + ), + ), + ) + assertSnapshot(of: subject, as: .defaultPortrait) + } + + /// The view renders correctly when the remove unlock with pin policy is enabled. + @MainActor + func disabletest_snapshot_removeUnlockPinPolicyEnabled() { + let subject = AccountSecurityView( + store: Store( + processor: StateProcessor( + state: AccountSecurityState( + biometricUnlockStatus: .available(.faceID, enabled: true), + removeUnlockWithPinPolicyEnabled: true, + ), + ), + ), + ) + assertSnapshots( + of: subject, + as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5()], + ) + } + + /// The view renders correctly when the timeout policy is enabled. + @MainActor + func disabletest_snapshot_timeoutPolicy() { + let subject = AccountSecurityView( + store: Store( + processor: StateProcessor( + state: AccountSecurityState( + isTimeoutPolicyEnabled: true, + sessionTimeoutValue: .custom(1), + ), + ), + ), + ) + assertSnapshots( + of: subject, + as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5()], + ) + } + + /// The view renders correctly when the timeout policy with an action is enabled. + @MainActor + func disabletest_snapshot_timeoutPolicyWithAction() { + let subject = AccountSecurityView( + store: Store( + processor: StateProcessor( + state: AccountSecurityState( + isTimeoutPolicyEnabled: true, + policyTimeoutAction: .logout, + sessionTimeoutAction: .logout, + sessionTimeoutValue: .custom(1), + ), + ), + ), + ) + assertSnapshots( + of: subject, + as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5()], + ) + } + + /// The view renders correctly. + @MainActor + func disabletest_view_render() { + assertSnapshot(of: subject, as: .defaultPortrait) + } +} diff --git a/BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/AccountSecurityViewTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/AccountSecurityView+ViewInspectorTests.swift similarity index 62% rename from BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/AccountSecurityViewTests.swift rename to BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/AccountSecurityView+ViewInspectorTests.swift index d2dc4b959..bf1e422fd 100644 --- a/BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/AccountSecurityViewTests.swift +++ b/BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/AccountSecurityView+ViewInspectorTests.swift @@ -1,12 +1,12 @@ +// swiftlint:disable:this file_name import BitwardenKit import BitwardenResources -import SnapshotTesting import ViewInspector import XCTest @testable import BitwardenShared -class AccountSecurityViewTests: BitwardenTestCase { // swiftlint:disable:this type_body_length +class AccountSecurityViewTests: BitwardenTestCase { // MARK: Properties var processor: MockProcessor! @@ -204,148 +204,4 @@ class AccountSecurityViewTests: BitwardenTestCase { // swiftlint:disable:this ty try view.accessibilityIdentifier() == "UnlockWithBiometricsSwitch" }) } - - // MARK: Snapshots - - /// The view renders correctly with the vault unlock action card is displayed. - @MainActor - func disabletest_snapshot_actionCardVaultUnlock() async { - processor.state.badgeState = .fixture(vaultUnlockSetupProgress: .setUpLater) - assertSnapshots( - of: subject, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } - - /// The view renders correctly when biometrics are available. - @MainActor - func disabletest_snapshot_biometricsDisabled_touchID() { - let subject = AccountSecurityView( - store: Store( - processor: StateProcessor( - state: AccountSecurityState( - biometricUnlockStatus: .available( - .touchID, - enabled: false, - ), - sessionTimeoutValue: .custom(1), - ), - ), - ), - ) - assertSnapshot(of: subject, as: .defaultPortrait) - } - - /// The view renders correctly when biometrics are available. - @MainActor - func disabletest_snapshot_biometricsEnabled_faceID() { - let subject = AccountSecurityView( - store: Store( - processor: StateProcessor( - state: AccountSecurityState( - biometricUnlockStatus: .available( - .faceID, - enabled: true, - ), - sessionTimeoutValue: .custom(1), - ), - ), - ), - ) - assertSnapshot(of: subject, as: .defaultPortrait) - } - - /// The view renders correctly when showing the custom session timeout field. - @MainActor - func disabletest_snapshot_customSessionTimeoutField() { - let subject = AccountSecurityView( - store: Store( - processor: StateProcessor( - state: AccountSecurityState(sessionTimeoutValue: .custom(1)), - ), - ), - ) - assertSnapshot(of: subject, as: .defaultPortrait) - } - - /// The view renders correctly when the user doesn't have a master password. - @MainActor - func disabletest_snapshot_noMasterPassword() { - let subject = AccountSecurityView( - store: Store( - processor: StateProcessor( - state: AccountSecurityState( - hasMasterPassword: false, - sessionTimeoutAction: .logout, - ), - ), - ), - ) - assertSnapshot(of: subject, as: .defaultPortrait) - } - - /// The view renders correctly when the remove unlock with pin policy is enabled. - @MainActor - func disabletest_snapshot_removeUnlockPinPolicyEnabled() { - let subject = AccountSecurityView( - store: Store( - processor: StateProcessor( - state: AccountSecurityState( - biometricUnlockStatus: .available(.faceID, enabled: true), - removeUnlockWithPinPolicyEnabled: true, - ), - ), - ), - ) - assertSnapshots( - of: subject, - as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5()], - ) - } - - /// The view renders correctly when the timeout policy is enabled. - @MainActor - func disabletest_snapshot_timeoutPolicy() { - let subject = AccountSecurityView( - store: Store( - processor: StateProcessor( - state: AccountSecurityState( - isTimeoutPolicyEnabled: true, - sessionTimeoutValue: .custom(1), - ), - ), - ), - ) - assertSnapshots( - of: subject, - as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5()], - ) - } - - /// The view renders correctly when the timeout policy with an action is enabled. - @MainActor - func disabletest_snapshot_timeoutPolicyWithAction() { - let subject = AccountSecurityView( - store: Store( - processor: StateProcessor( - state: AccountSecurityState( - isTimeoutPolicyEnabled: true, - policyTimeoutAction: .logout, - sessionTimeoutAction: .logout, - sessionTimeoutValue: .custom(1), - ), - ), - ), - ) - assertSnapshots( - of: subject, - as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5()], - ) - } - - /// The view renders correctly. - @MainActor - func disabletest_view_render() { - assertSnapshot(of: subject, as: .defaultPortrait) - } } diff --git a/BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/DeleteAccount/DeleteAccountView+SnapshotTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/DeleteAccount/DeleteAccountView+SnapshotTests.swift new file mode 100644 index 000000000..a79d665ca --- /dev/null +++ b/BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/DeleteAccount/DeleteAccountView+SnapshotTests.swift @@ -0,0 +1,43 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class DeleteAccountViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: DeleteAccountView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + processor = MockProcessor(state: DeleteAccountState()) + + let store = Store(processor: processor) + subject = DeleteAccountView(store: store) + } + + override func tearDown() { + super.tearDown() + processor = nil + subject = nil + } + + // MARK: Tests + + /// The view renders correctly. + func disabletest_snapshot() { + assertSnapshot(of: subject, as: .defaultPortrait) + } + + /// The view renders correctly. + @MainActor + func disabletest_preventUserFromDeletingAccount() { + processor.state.shouldPreventUserFromDeletingAccount = true + assertSnapshot(of: subject, as: .defaultPortrait) + } +} diff --git a/BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/DeleteAccount/DeleteAccountViewTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/DeleteAccount/DeleteAccountView+ViewInspectorTests.swift similarity index 72% rename from BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/DeleteAccount/DeleteAccountViewTests.swift rename to BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/DeleteAccount/DeleteAccountView+ViewInspectorTests.swift index 307c0fbcf..0e946de14 100644 --- a/BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/DeleteAccount/DeleteAccountViewTests.swift +++ b/BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/DeleteAccount/DeleteAccountView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import ViewInspector import XCTest @@ -29,18 +29,6 @@ class DeleteAccountViewTests: BitwardenTestCase { // MARK: Tests - /// The view renders correctly. - func test_snapshot() { - assertSnapshot(of: subject, as: .defaultPortrait) - } - - /// The view renders correctly. - @MainActor - func test_preventUserFromDeletingAccount() { - processor.state.shouldPreventUserFromDeletingAccount = true - assertSnapshot(of: subject, as: .defaultPortrait) - } - /// Tapping the delete account button performs the `.deleteAccount` effect. @MainActor func test_deleteAccount_tap() async throws { diff --git a/BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/PendingRequests/PendingRequestsViewTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/PendingRequests/PendingRequestsView+SnapshotTests.swift similarity index 65% rename from BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/PendingRequests/PendingRequestsViewTests.swift rename to BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/PendingRequests/PendingRequestsView+SnapshotTests.swift index f892795c4..66fb9d07a 100644 --- a/BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/PendingRequests/PendingRequestsViewTests.swift +++ b/BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/PendingRequests/PendingRequestsView+SnapshotTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import BitwardenResources import SnapshotTesting import XCTest @@ -28,25 +29,6 @@ class PendingRequestsViewTests: BitwardenTestCase { subject = nil } - // MARK: Tests - - /// Tapping the decline all requests button dispatches the `.declineAllRequests` action. - @MainActor - func test_declineAllRequestsButton_tap() throws { - processor.state.loadingState = .data([.fixture()]) - let button = try subject.inspect().find(buttonWithAccessibilityLabel: Localizations.declineAllRequests) - try button.tap() - XCTAssertEqual(processor.dispatchedActions.last, .declineAllRequestsTapped) - } - - /// Tapping the cancel button dispatches the `.dismiss` action. - @MainActor - func test_cancelButton_tap() throws { - let button = try subject.inspect().findCancelToolbarButton() - try button.tap() - XCTAssertEqual(processor.dispatchedActions.last, .dismiss) - } - // MARK: Snapshots /// The empty view renders correctly. diff --git a/BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/PendingRequests/PendingRequestsView+ViewInspectorTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/PendingRequests/PendingRequestsView+ViewInspectorTests.swift new file mode 100644 index 000000000..83392732c --- /dev/null +++ b/BitwardenShared/UI/Platform/Settings/Settings/AccountSecurity/PendingRequests/PendingRequestsView+ViewInspectorTests.swift @@ -0,0 +1,49 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import XCTest + +@testable import BitwardenShared + +class PendingRequestsViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: PendingRequestsView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: PendingRequestsState()) + let store = Store(processor: processor) + + subject = PendingRequestsView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Tests + + /// Tapping the decline all requests button dispatches the `.declineAllRequests` action. + @MainActor + func test_declineAllRequestsButton_tap() throws { + processor.state.loadingState = .data([.fixture()]) + let button = try subject.inspect().find(buttonWithAccessibilityLabel: Localizations.declineAllRequests) + try button.tap() + XCTAssertEqual(processor.dispatchedActions.last, .declineAllRequestsTapped) + } + + /// Tapping the cancel button dispatches the `.dismiss` action. + @MainActor + func test_cancelButton_tap() throws { + let button = try subject.inspect().findCancelToolbarButton() + try button.tap() + XCTAssertEqual(processor.dispatchedActions.last, .dismiss) + } +} diff --git a/BitwardenShared/UI/Platform/Settings/Settings/Appearance/AppearanceView+SnapshotTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/Appearance/AppearanceView+SnapshotTests.swift new file mode 100644 index 000000000..d8101e1be --- /dev/null +++ b/BitwardenShared/UI/Platform/Settings/Settings/Appearance/AppearanceView+SnapshotTests.swift @@ -0,0 +1,43 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +// MARK: - AppearanceViewTests + +@testable import BitwardenShared + +class AppearanceViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: AppearanceView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: AppearanceState()) + let store = Store(processor: processor) + + subject = AppearanceView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// Tests the view renders correctly. + func disabletest_snapshot_viewRender() { + assertSnapshots( + of: subject, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } +} diff --git a/BitwardenShared/UI/Platform/Settings/Settings/Appearance/AppearanceViewTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/Appearance/AppearanceView+ViewInspectorTests.swift similarity index 83% rename from BitwardenShared/UI/Platform/Settings/Settings/Appearance/AppearanceViewTests.swift rename to BitwardenShared/UI/Platform/Settings/Settings/Appearance/AppearanceView+ViewInspectorTests.swift index 1b92490aa..20de139a3 100644 --- a/BitwardenShared/UI/Platform/Settings/Settings/Appearance/AppearanceViewTests.swift +++ b/BitwardenShared/UI/Platform/Settings/Settings/Appearance/AppearanceView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import XCTest // MARK: - AppearanceViewTests @@ -48,14 +48,4 @@ class AppearanceViewTests: BitwardenTestCase { try button.tap() XCTAssertEqual(processor.dispatchedActions.last, .languageTapped) } - - // MARK: Snapshots - - /// Tests the view renders correctly. - func disabletest_snapshot_viewRender() { - assertSnapshots( - of: subject, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } } diff --git a/BitwardenShared/UI/Platform/Settings/Settings/Appearance/SelectLanguage/SelectLanguageView+SnapshotTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/Appearance/SelectLanguage/SelectLanguageView+SnapshotTests.swift new file mode 100644 index 000000000..058d1bc74 --- /dev/null +++ b/BitwardenShared/UI/Platform/Settings/Settings/Appearance/SelectLanguage/SelectLanguageView+SnapshotTests.swift @@ -0,0 +1,47 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +// MARK: - SelectLanguageViewTests + +@testable import BitwardenShared + +class SelectLanguageViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: SelectLanguageView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: SelectLanguageState()) + let store = Store(processor: processor) + + subject = SelectLanguageView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// Test that the default view renders correctly. + func disabletest_snapshot_default() { + assertSnapshots( + of: subject.navStackWrapped, + as: [ + .defaultPortrait, + .defaultPortraitDark, + .tallPortraitAX5(), + ], + ) + } +} diff --git a/BitwardenShared/UI/Platform/Settings/Settings/Appearance/SelectLanguage/SelectLanguageViewTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/Appearance/SelectLanguage/SelectLanguageView+ViewInspectorTests.swift similarity index 78% rename from BitwardenShared/UI/Platform/Settings/Settings/Appearance/SelectLanguage/SelectLanguageViewTests.swift rename to BitwardenShared/UI/Platform/Settings/Settings/Appearance/SelectLanguage/SelectLanguageView+ViewInspectorTests.swift index efb71bb39..c5fc7d109 100644 --- a/BitwardenShared/UI/Platform/Settings/Settings/Appearance/SelectLanguage/SelectLanguageViewTests.swift +++ b/BitwardenShared/UI/Platform/Settings/Settings/Appearance/SelectLanguage/SelectLanguageView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import XCTest // MARK: - SelectLanguageViewTests @@ -47,18 +47,4 @@ class SelectLanguageViewTests: BitwardenTestCase { try button.tap() XCTAssertEqual(processor.dispatchedActions.last, .languageTapped(.default)) } - - // MARK: Snapshots - - /// Test that the default view renders correctly. - func disabletest_snapshot_default() { - assertSnapshots( - of: subject.navStackWrapped, - as: [ - .defaultPortrait, - .defaultPortraitDark, - .tallPortraitAX5(), - ], - ) - } } diff --git a/BitwardenShared/UI/Platform/Settings/Settings/AutoFill/AppExtension/AppExtensionViewTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/AutoFill/AppExtension/AppExtensionView+SnapshotTests.swift similarity index 82% rename from BitwardenShared/UI/Platform/Settings/Settings/AutoFill/AppExtension/AppExtensionViewTests.swift rename to BitwardenShared/UI/Platform/Settings/Settings/AutoFill/AppExtension/AppExtensionView+SnapshotTests.swift index f3236bf0a..a32e51af5 100644 --- a/BitwardenShared/UI/Platform/Settings/Settings/AutoFill/AppExtension/AppExtensionViewTests.swift +++ b/BitwardenShared/UI/Platform/Settings/Settings/AutoFill/AppExtension/AppExtensionView+SnapshotTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import BitwardenResources import SnapshotTesting import XCTest @@ -28,16 +29,6 @@ class AppExtensionViewTests: BitwardenTestCase { subject = nil } - // MARK: Tests - - /// Tapping the activate button dispatches the `.activateButtonTapped` action. - @MainActor - func test_activateButton_tap() throws { - let button = try subject.inspect().find(button: Localizations.extensionEnable) - try button.tap() - XCTAssertEqual(processor.dispatchedActions.last, .activateButtonTapped) - } - // MARK: Snapshots /// The activate view renders correctly. diff --git a/BitwardenShared/UI/Platform/Settings/Settings/AutoFill/AppExtension/AppExtensionView+ViewInspectorTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/AutoFill/AppExtension/AppExtensionView+ViewInspectorTests.swift new file mode 100644 index 000000000..6d53ce3d4 --- /dev/null +++ b/BitwardenShared/UI/Platform/Settings/Settings/AutoFill/AppExtension/AppExtensionView+ViewInspectorTests.swift @@ -0,0 +1,40 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import XCTest + +@testable import BitwardenShared + +class AppExtensionViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: AppExtensionView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: AppExtensionState()) + let store = Store(processor: processor) + + subject = AppExtensionView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Tests + + /// Tapping the activate button dispatches the `.activateButtonTapped` action. + @MainActor + func test_activateButton_tap() throws { + let button = try subject.inspect().find(button: Localizations.extensionEnable) + try button.tap() + XCTAssertEqual(processor.dispatchedActions.last, .activateButtonTapped) + } +} diff --git a/BitwardenShared/UI/Platform/Settings/Settings/AutoFill/AutoFillView+SnapshotTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/AutoFill/AutoFillView+SnapshotTests.swift new file mode 100644 index 000000000..78c15c859 --- /dev/null +++ b/BitwardenShared/UI/Platform/Settings/Settings/AutoFill/AutoFillView+SnapshotTests.swift @@ -0,0 +1,70 @@ +// swiftlint:disable:this file_name +import BitwardenKit +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class AutoFillViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: AutoFillView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: AutoFillState()) + let store = Store(processor: processor) + + subject = AutoFillView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// The view renders correctly with the autofill action card is displayed. + @MainActor + func disabletest_snapshot_actionCardAutofill() async { + processor.state.badgeState = .fixture(autofillSetupProgress: .setUpLater) + assertSnapshots( + of: subject, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } + + /// The view renders correctly with the autofill regular expression selected + @MainActor + func disabletest_snapshot_regularExpressionUriMatchType() async { + processor.state.defaultUriMatchType = UriMatchType.regularExpression + assertSnapshots( + of: subject, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } + + /// The view renders correctly with the autofill starts with selected + @MainActor + func disabletest_snapshot_startsWithUriMatchType() async { + processor.state.defaultUriMatchType = UriMatchType.startsWith + assertSnapshots( + of: subject, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } + + /// The view renders correctly. + @MainActor + func disabletest_view_render() { + assertSnapshot(of: subject, as: .defaultPortrait) + } +} diff --git a/BitwardenShared/UI/Platform/Settings/Settings/AutoFill/AutoFillViewTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/AutoFill/AutoFillView+ViewInspectorTests.swift similarity index 75% rename from BitwardenShared/UI/Platform/Settings/Settings/AutoFill/AutoFillViewTests.swift rename to BitwardenShared/UI/Platform/Settings/Settings/AutoFill/AutoFillView+ViewInspectorTests.swift index bdcfa408d..c9d3b3388 100644 --- a/BitwardenShared/UI/Platform/Settings/Settings/AutoFill/AutoFillViewTests.swift +++ b/BitwardenShared/UI/Platform/Settings/Settings/AutoFill/AutoFillView+ViewInspectorTests.swift @@ -1,6 +1,6 @@ +// swiftlint:disable:this file_name import BitwardenKit import BitwardenResources -import SnapshotTesting import XCTest @testable import BitwardenShared @@ -103,42 +103,4 @@ class AutoFillViewTests: BitwardenTestCase { try await button.tap() XCTAssertEqual(processor.dispatchedActions, [.showSetUpAutofill]) } - - // MARK: Snapshots - - /// The view renders correctly with the autofill action card is displayed. - @MainActor - func disabletest_snapshot_actionCardAutofill() async { - processor.state.badgeState = .fixture(autofillSetupProgress: .setUpLater) - assertSnapshots( - of: subject, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } - - /// The view renders correctly with the autofill regular expression selected - @MainActor - func disabletest_snapshot_regularExpressionUriMatchType() async { - processor.state.defaultUriMatchType = UriMatchType.regularExpression - assertSnapshots( - of: subject, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } - - /// The view renders correctly with the autofill starts with selected - @MainActor - func disabletest_snapshot_startsWithUriMatchType() async { - processor.state.defaultUriMatchType = UriMatchType.startsWith - assertSnapshots( - of: subject, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } - - /// The view renders correctly. - @MainActor - func disabletest_view_render() { - assertSnapshot(of: subject, as: .defaultPortrait) - } } diff --git a/BitwardenShared/UI/Platform/Settings/Settings/AutoFill/PasswordAutoFill/PasswordAutoFillViewTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/AutoFill/PasswordAutoFill/PasswordAutoFillView+SnapshotTests.swift similarity index 73% rename from BitwardenShared/UI/Platform/Settings/Settings/AutoFill/PasswordAutoFill/PasswordAutoFillViewTests.swift rename to BitwardenShared/UI/Platform/Settings/Settings/AutoFill/PasswordAutoFill/PasswordAutoFillView+SnapshotTests.swift index ee21a2793..efe2418a6 100644 --- a/BitwardenShared/UI/Platform/Settings/Settings/AutoFill/PasswordAutoFill/PasswordAutoFillViewTests.swift +++ b/BitwardenShared/UI/Platform/Settings/Settings/AutoFill/PasswordAutoFill/PasswordAutoFillView+SnapshotTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import BitwardenResources import SnapshotTesting import XCTest @@ -31,22 +32,6 @@ class PasswordAutoFillViewTests: BitwardenTestCase { // MARK: Tests - /// Tapping the turn on later button dispatches the `.turnAutoFillOnLaterTapped()` effect. - @MainActor - func test_turnOnAutoFillLaterButton_tap() async throws { - processor.state.mode = .onboarding - let button = try subject.inspect().find(asyncButton: Localizations.turnOnLater) - try await button.tap() - XCTAssertEqual(processor.effects.last, .turnAutoFillOnLaterButtonTapped) - } - - /// The button to turn on later doesn't exist when navigating in settings mode. - @MainActor - func test_turnOnAutoFillLaterButton_doesntExist() async throws { - processor.state.mode = .settings - XCTAssertThrowsError(try subject.inspect().find(asyncButton: Localizations.turnOnLater)) - } - /// The legacy view renders correctly. func disabletest_snapshot_view_render() { assertSnapshots( diff --git a/BitwardenShared/UI/Platform/Settings/Settings/AutoFill/PasswordAutoFill/PasswordAutoFillView+ViewInspectorTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/AutoFill/PasswordAutoFill/PasswordAutoFillView+ViewInspectorTests.swift new file mode 100644 index 000000000..920e10a95 --- /dev/null +++ b/BitwardenShared/UI/Platform/Settings/Settings/AutoFill/PasswordAutoFill/PasswordAutoFillView+ViewInspectorTests.swift @@ -0,0 +1,49 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import XCTest + +@testable import BitwardenShared + +// MARK: - PasswordAutoFillViewTests + +class PasswordAutoFillViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: PasswordAutoFillView! + + // MARK: Setup & Teardown + + override func setUp() { + processor = MockProcessor( + state: PasswordAutoFillState( + mode: .settings, + ), + ) + subject = PasswordAutoFillView(store: Store(processor: processor)) + } + + override func tearDown() { + super.tearDown() + processor = nil + subject = nil + } + + // MARK: Tests + + /// Tapping the turn on later button dispatches the `.turnAutoFillOnLaterTapped()` effect. + @MainActor + func test_turnOnAutoFillLaterButton_tap() async throws { + processor.state.mode = .onboarding + let button = try subject.inspect().find(asyncButton: Localizations.turnOnLater) + try await button.tap() + XCTAssertEqual(processor.effects.last, .turnAutoFillOnLaterButtonTapped) + } + + /// The button to turn on later doesn't exist when navigating in settings mode. + @MainActor + func test_turnOnAutoFillLaterButton_doesntExist() async throws { + processor.state.mode = .settings + XCTAssertThrowsError(try subject.inspect().find(asyncButton: Localizations.turnOnLater)) + } +} diff --git a/BitwardenShared/UI/Platform/Settings/Settings/Other/OtherSettingsViewTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/Other/OtherSettingsView+ViewInspectorTests.swift similarity index 80% rename from BitwardenShared/UI/Platform/Settings/Settings/Other/OtherSettingsViewTests.swift rename to BitwardenShared/UI/Platform/Settings/Settings/Other/OtherSettingsView+ViewInspectorTests.swift index 81bb4f829..bb97b20f2 100644 --- a/BitwardenShared/UI/Platform/Settings/Settings/Other/OtherSettingsViewTests.swift +++ b/BitwardenShared/UI/Platform/Settings/Settings/Other/OtherSettingsView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import XCTest @testable import BitwardenShared @@ -48,12 +48,4 @@ class OtherSettingsViewTests: BitwardenTestCase { processor.state.shouldShowConnectToWatchToggle = true XCTAssertNoThrow(try subject.inspect().find(toggleWithAccessibilityLabel: Localizations.connectToWatch)) } - - /// The view renders correctly. - @MainActor - func disabletest_view_render() { - processor.state.lastSyncDate = Date(year: 2023, month: 5, day: 14, hour: 16, minute: 52) - processor.state.shouldShowConnectToWatchToggle = true - assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) - } } diff --git a/BitwardenShared/UI/Platform/Settings/Settings/Other/OtherSettingsViewTests+SnapshotTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/Other/OtherSettingsViewTests+SnapshotTests.swift new file mode 100644 index 000000000..ad28bf148 --- /dev/null +++ b/BitwardenShared/UI/Platform/Settings/Settings/Other/OtherSettingsViewTests+SnapshotTests.swift @@ -0,0 +1,38 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class OtherSettingsViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: OtherSettingsView! + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: OtherSettingsState()) + + subject = OtherSettingsView(store: Store(processor: processor)) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Tests + + /// The view renders correctly. + @MainActor + func disabletest_view_render() { + processor.state.lastSyncDate = Date(year: 2023, month: 5, day: 14, hour: 16, minute: 52) + processor.state.shouldShowConnectToWatchToggle = true + assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) + } +} diff --git a/BitwardenShared/UI/Platform/Settings/Settings/SettingsView+SnapshotTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/SettingsView+SnapshotTests.swift new file mode 100644 index 000000000..49dddc4a9 --- /dev/null +++ b/BitwardenShared/UI/Platform/Settings/Settings/SettingsView+SnapshotTests.swift @@ -0,0 +1,61 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +// MARK: - SettingsViewTests + +@testable import BitwardenShared + +class SettingsViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: SettingsView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: SettingsState()) + let store = Store(processor: processor) + + subject = SettingsView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// Tests the view renders correctly. + func disabletest_snapshot_viewRender() { + assertSnapshot(of: subject.navStackWrapped, as: .defaultPortrait) + } + + /// Tests the view renders correctly for the pre-login mode. + @MainActor + func disabletest_snapshot_viewRender_preLogin() { + processor.state.presentationMode = .preLogin + assertSnapshot(of: subject.navStackWrapped, as: .defaultPortrait) + } + + /// Tests the view renders correctly with badges. + @MainActor + func disabletest_snapshot_settingsView_badges() { + processor.state.badgeState = .fixture( + autofillSetupProgress: .setUpLater, + importLoginsSetupProgress: .setUpLater, + vaultUnlockSetupProgress: .setUpLater, + ) + assertSnapshots( + of: subject.navStackWrapped, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } +} diff --git a/BitwardenShared/UI/Platform/Settings/Settings/SettingsViewTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/SettingsView+ViewInspectorTests.swift similarity index 75% rename from BitwardenShared/UI/Platform/Settings/Settings/SettingsViewTests.swift rename to BitwardenShared/UI/Platform/Settings/Settings/SettingsView+ViewInspectorTests.swift index 3f6f019ff..6ed32f06e 100644 --- a/BitwardenShared/UI/Platform/Settings/Settings/SettingsViewTests.swift +++ b/BitwardenShared/UI/Platform/Settings/Settings/SettingsView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import XCTest // MARK: - SettingsViewTests @@ -88,32 +88,4 @@ class SettingsViewTests: BitwardenTestCase { try button.tap() XCTAssertEqual(processor.dispatchedActions.last, .vaultPressed) } - - // MARK: Snapshots - - /// Tests the view renders correctly. - func disabletest_snapshot_viewRender() { - assertSnapshot(of: subject.navStackWrapped, as: .defaultPortrait) - } - - /// Tests the view renders correctly for the pre-login mode. - @MainActor - func disabletest_snapshot_viewRender_preLogin() { - processor.state.presentationMode = .preLogin - assertSnapshot(of: subject.navStackWrapped, as: .defaultPortrait) - } - - /// Tests the view renders correctly with badges. - @MainActor - func disabletest_snapshot_settingsView_badges() { - processor.state.badgeState = .fixture( - autofillSetupProgress: .setUpLater, - importLoginsSetupProgress: .setUpLater, - vaultUnlockSetupProgress: .setUpLater, - ) - assertSnapshots( - of: subject.navStackWrapped, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } } diff --git a/BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportSettings/ExportSettingsView+SnapshotTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportSettings/ExportSettingsView+SnapshotTests.swift new file mode 100644 index 000000000..ce2900d1d --- /dev/null +++ b/BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportSettings/ExportSettingsView+SnapshotTests.swift @@ -0,0 +1,39 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class ExportSettingsViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: ExportSettingsView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: ()) + let store = Store(processor: processor) + + subject = ExportSettingsView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// The default view renders correctly. + @MainActor + func disabletest_snapshot_default() { + assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) + } +} diff --git a/BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportSettings/ExportSettingsViewTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportSettings/ExportSettingsView+ViewInspectorTests.swift similarity index 84% rename from BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportSettings/ExportSettingsViewTests.swift rename to BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportSettings/ExportSettingsView+ViewInspectorTests.swift index cb166d905..17e5f9682 100644 --- a/BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportSettings/ExportSettingsViewTests.swift +++ b/BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportSettings/ExportSettingsView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import XCTest @testable import BitwardenShared @@ -45,12 +45,4 @@ class ExportSettingsViewTests: BitwardenTestCase { try button.tap() XCTAssertEqual(processor.dispatchedActions.last, .exportToAppTapped) } - - // MARK: Snapshots - - /// The default view renders correctly. - @MainActor - func disabletest_snapshot_default() { - assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) - } } diff --git a/BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportVaultToFile/ExportVaultView+SnapshotTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportVaultToFile/ExportVaultView+SnapshotTests.swift new file mode 100644 index 000000000..92b162334 --- /dev/null +++ b/BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportVaultToFile/ExportVaultView+SnapshotTests.swift @@ -0,0 +1,67 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class ExportVaultViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: ExportVaultView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: ExportVaultState()) + let store = Store(processor: processor) + + subject = ExportVaultView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// The empty view renders correctly. + @MainActor + func disabletest_snapshot_empty() { + assertSnapshots(of: subject.navStackWrapped, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) + } + + /// The populated view renders correctly. + @MainActor + func disabletest_snapshot_populated() { + processor.state.masterPasswordOrOtpText = "password" + assertSnapshots(of: subject.navStackWrapped, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) + } + + /// The vault export disabled view renders correctly. + @MainActor + func disabletest_snapshot_vaultExportDisabled() { + processor.state.disableIndividualVaultExport = true + assertSnapshots(of: subject.navStackWrapped, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) + } + + /// The JSON encrypted view renders correctly. + @MainActor + func disabletest_snapshot_jsonEncrypted() { + processor.state.fileFormat = .jsonEncrypted + assertSnapshots(of: subject.navStackWrapped, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) + } + + /// The view for exporting the vault without a master password renders correctly. + @MainActor + func disabletest_snapshot_noMasterPassword() { + processor.state.hasMasterPassword = false + assertSnapshots(of: subject.navStackWrapped, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) + } +} diff --git a/BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportVaultToFile/ExportVaultViewTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportVaultToFile/ExportVaultView+ViewInspectorTests.swift similarity index 78% rename from BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportVaultToFile/ExportVaultViewTests.swift rename to BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportVaultToFile/ExportVaultView+ViewInspectorTests.swift index 6e1d6fb58..aebf27b27 100644 --- a/BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportVaultToFile/ExportVaultViewTests.swift +++ b/BitwardenShared/UI/Platform/Settings/Settings/Vault/ExportVault/ExportVaultToFile/ExportVaultView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import XCTest @testable import BitwardenShared @@ -134,40 +134,4 @@ class ExportVaultViewTests: BitwardenTestCase { try await sendCodeButton.tap() XCTAssertEqual(processor.effects.last, .sendCodeTapped) } - - // MARK: Snapshots - - /// The empty view renders correctly. - @MainActor - func disabletest_snapshot_empty() { - assertSnapshots(of: subject.navStackWrapped, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) - } - - /// The populated view renders correctly. - @MainActor - func disabletest_snapshot_populated() { - processor.state.masterPasswordOrOtpText = "password" - assertSnapshots(of: subject.navStackWrapped, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) - } - - /// The vault export disabled view renders correctly. - @MainActor - func disabletest_snapshot_vaultExportDisabled() { - processor.state.disableIndividualVaultExport = true - assertSnapshots(of: subject.navStackWrapped, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) - } - - /// The JSON encrypted view renders correctly. - @MainActor - func disabletest_snapshot_jsonEncrypted() { - processor.state.fileFormat = .jsonEncrypted - assertSnapshots(of: subject.navStackWrapped, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) - } - - /// The view for exporting the vault without a master password renders correctly. - @MainActor - func disabletest_snapshot_noMasterPassword() { - processor.state.hasMasterPassword = false - assertSnapshots(of: subject.navStackWrapped, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) - } } diff --git a/BitwardenShared/UI/Platform/Settings/Settings/Vault/Folders/AddEditFolder/AddEditFolder/AddEditFolderView+SnapshotTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/Vault/Folders/AddEditFolder/AddEditFolder/AddEditFolderView+SnapshotTests.swift new file mode 100644 index 000000000..9d86077ee --- /dev/null +++ b/BitwardenShared/UI/Platform/Settings/Settings/Vault/Folders/AddEditFolder/AddEditFolder/AddEditFolderView+SnapshotTests.swift @@ -0,0 +1,62 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class AddEditFolderViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: AddEditFolderView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: AddEditFolderState(mode: .add)) + let store = Store(processor: processor) + + subject = AddEditFolderView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// Tests the view renders correctly when the text field is empty. + func disabletest_snapshot_add_empty() { + assertSnapshots( + of: subject.navStackWrapped, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } + + /// Tests the view renders correctly when the text field is populated. + @MainActor + func disabletest_snapshot_add_populated() { + processor.state.folderName = "Super cool folder name" + assertSnapshots( + of: subject.navStackWrapped, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } + + /// Tests the view renders correctly when the text field is populated. + @MainActor + func disabletest_snapshot_edit_populated() { + processor.state.mode = .edit(.fixture()) + processor.state.folderName = "Super cool folder name" + assertSnapshots( + of: subject.navStackWrapped, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } +} diff --git a/BitwardenShared/UI/Platform/Settings/Settings/Vault/Folders/AddEditFolder/AddEditFolder/AddEditFolderViewTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/Vault/Folders/AddEditFolder/AddEditFolder/AddEditFolderView+ViewInspectorTests.swift similarity index 74% rename from BitwardenShared/UI/Platform/Settings/Settings/Vault/Folders/AddEditFolder/AddEditFolder/AddEditFolderViewTests.swift rename to BitwardenShared/UI/Platform/Settings/Settings/Vault/Folders/AddEditFolder/AddEditFolder/AddEditFolderView+ViewInspectorTests.swift index 7872a884d..5e3c832b2 100644 --- a/BitwardenShared/UI/Platform/Settings/Settings/Vault/Folders/AddEditFolder/AddEditFolder/AddEditFolderViewTests.swift +++ b/BitwardenShared/UI/Platform/Settings/Settings/Vault/Folders/AddEditFolder/AddEditFolder/AddEditFolderView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import ViewInspector import XCTest @@ -92,35 +92,4 @@ class AddEditFolderViewTests: BitwardenTestCase { try await button.tap() XCTAssertEqual(processor.effects.last, .saveTapped) } - - // MARK: Snapshots - - /// Tests the view renders correctly when the text field is empty. - func disabletest_snapshot_add_empty() { - assertSnapshots( - of: subject.navStackWrapped, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } - - /// Tests the view renders correctly when the text field is populated. - @MainActor - func disabletest_snapshot_add_populated() { - processor.state.folderName = "Super cool folder name" - assertSnapshots( - of: subject.navStackWrapped, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } - - /// Tests the view renders correctly when the text field is populated. - @MainActor - func disabletest_snapshot_edit_populated() { - processor.state.mode = .edit(.fixture()) - processor.state.folderName = "Super cool folder name" - assertSnapshots( - of: subject.navStackWrapped, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } } diff --git a/BitwardenShared/UI/Platform/Settings/Settings/Vault/Folders/FoldersView+SnapshotTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/Vault/Folders/FoldersView+SnapshotTests.swift new file mode 100644 index 000000000..76531c454 --- /dev/null +++ b/BitwardenShared/UI/Platform/Settings/Settings/Vault/Folders/FoldersView+SnapshotTests.swift @@ -0,0 +1,49 @@ +// swiftlint:disable:this file_name +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class FoldersViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: FoldersView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: FoldersState()) + let store = Store(processor: processor) + + subject = FoldersView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// The empty view renders correctly. + @MainActor + func disabletest_snapshot_empty() { + processor.state.folders = [] + assertSnapshot(of: subject, as: .defaultPortrait) + } + + /// The folders view renders correctly. + @MainActor + func disabletest_snapshot_folders() { + processor.state.folders = [ + .fixture(id: "test", name: "Secret Folder"), + .fixture(id: "test2", name: "Double Secret Folder"), + ] + assertSnapshot(of: subject, as: .defaultPortrait) + } +} diff --git a/BitwardenShared/UI/Platform/Settings/Settings/Vault/Folders/FoldersViewTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/Vault/Folders/FoldersView+ViewInspectorTests.swift similarity index 70% rename from BitwardenShared/UI/Platform/Settings/Settings/Vault/Folders/FoldersViewTests.swift rename to BitwardenShared/UI/Platform/Settings/Settings/Vault/Folders/FoldersView+ViewInspectorTests.swift index 2cb5ebd5c..c76d1e12b 100644 --- a/BitwardenShared/UI/Platform/Settings/Settings/Vault/Folders/FoldersViewTests.swift +++ b/BitwardenShared/UI/Platform/Settings/Settings/Vault/Folders/FoldersView+ViewInspectorTests.swift @@ -1,4 +1,4 @@ -import SnapshotTesting +// swiftlint:disable:this file_name import XCTest @testable import BitwardenShared @@ -48,23 +48,4 @@ class FoldersViewTests: BitwardenTestCase { try button.tap() XCTAssertEqual(processor.dispatchedActions.last, .folderTapped(id: "test")) } - - // MARK: Snapshots - - /// The empty view renders correctly. - @MainActor - func disabletest_snapshot_empty() { - processor.state.folders = [] - assertSnapshot(of: subject, as: .defaultPortrait) - } - - /// The folders view renders correctly. - @MainActor - func disabletest_snapshot_folders() { - processor.state.folders = [ - .fixture(id: "test", name: "Secret Folder"), - .fixture(id: "test2", name: "Double Secret Folder"), - ] - assertSnapshot(of: subject, as: .defaultPortrait) - } } diff --git a/BitwardenShared/UI/Platform/Settings/Settings/Vault/VaultSettingsView+SnapshotTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/Vault/VaultSettingsView+SnapshotTests.swift new file mode 100644 index 000000000..1d3845e06 --- /dev/null +++ b/BitwardenShared/UI/Platform/Settings/Settings/Vault/VaultSettingsView+SnapshotTests.swift @@ -0,0 +1,50 @@ +// swiftlint:disable:this file_name +import BitwardenKit +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class VaultSettingsViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: VaultSettingsView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: VaultSettingsState()) + let store = Store(processor: processor) + + subject = VaultSettingsView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// The view renders correctly with the import logins action card displayed. + @MainActor + func disabletest_snapshot_actionCardImportLogins() async { + processor.state.badgeState = .fixture(importLoginsSetupProgress: .setUpLater) + assertSnapshots( + of: subject, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } + + /// The default view renders correctly. + @MainActor + func disabletest_snapshot_default() { + assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) + } +} diff --git a/BitwardenShared/UI/Platform/Settings/Settings/Vault/VaultSettingsViewTests.swift b/BitwardenShared/UI/Platform/Settings/Settings/Vault/VaultSettingsView+ViewInspectorTests.swift similarity index 85% rename from BitwardenShared/UI/Platform/Settings/Settings/Vault/VaultSettingsViewTests.swift rename to BitwardenShared/UI/Platform/Settings/Settings/Vault/VaultSettingsView+ViewInspectorTests.swift index e36a6af21..278c9cdfa 100644 --- a/BitwardenShared/UI/Platform/Settings/Settings/Vault/VaultSettingsViewTests.swift +++ b/BitwardenShared/UI/Platform/Settings/Settings/Vault/VaultSettingsView+ViewInspectorTests.swift @@ -1,6 +1,6 @@ +// swiftlint:disable:this file_name import BitwardenKit import BitwardenResources -import SnapshotTesting import XCTest @testable import BitwardenShared @@ -98,22 +98,4 @@ class VaultSettingsViewTests: BitwardenTestCase { try await button.tap() XCTAssertEqual(processor.dispatchedActions, [.showImportLogins]) } - - // MARK: Snapshots - - /// The view renders correctly with the import logins action card displayed. - @MainActor - func disabletest_snapshot_actionCardImportLogins() async { - processor.state.badgeState = .fixture(importLoginsSetupProgress: .setUpLater) - assertSnapshots( - of: subject, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } - - /// The default view renders correctly. - @MainActor - func disabletest_snapshot_default() { - assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5]) - } } diff --git a/BitwardenShared/UI/Platform/Settings/SettingsCoordinatorTests.swift b/BitwardenShared/UI/Platform/Settings/SettingsCoordinatorTests.swift index 8f15ed5a5..be02bb07e 100644 --- a/BitwardenShared/UI/Platform/Settings/SettingsCoordinatorTests.swift +++ b/BitwardenShared/UI/Platform/Settings/SettingsCoordinatorTests.swift @@ -469,44 +469,4 @@ class SettingsCoordinatorTests: BitwardenTestCase { // swiftlint:disable:this ty subject.updateSettingsTabBadge(nil) XCTAssertNil(stackNavigator.rootViewController?.tabBarItem.badgeValue) } -} - -class MockSettingsCoordinatorDelegate: SettingsCoordinatorDelegate { - var didCompleteLoginsImportCalled = false - var didDeleteAccountCalled = false - var didLockVaultCalled = false - var didLogoutCalled = false - var hasManuallyLockedVault = false - var lockedId: String? - var loggedOutId: String? - var switchAccountCalled = false - var switchUserId: String? - var wasLogoutUserInitiated: Bool? - var wasSwitchAutomatic: Bool? - - func didCompleteLoginsImport() { - didCompleteLoginsImportCalled = true - } - - func didDeleteAccount() { - didDeleteAccountCalled = true - } - - func lockVault(userId: String?, isManuallyLocking: Bool) { - lockedId = userId - didLockVaultCalled = true - hasManuallyLockedVault = isManuallyLocking - } - - func logout(userId: String?, userInitiated: Bool) { - loggedOutId = userId - wasLogoutUserInitiated = userInitiated - didLogoutCalled = true - } - - func switchAccount(isAutomatic: Bool, userId: String) { - switchAccountCalled = true - wasSwitchAutomatic = isAutomatic - switchUserId = userId - } } // swiftlint:disable:this file_length diff --git a/BitwardenShared/UI/Platform/Settings/TestHelpers/MockSettingsCoordinatorDelegate.swift b/BitwardenShared/UI/Platform/Settings/TestHelpers/MockSettingsCoordinatorDelegate.swift new file mode 100644 index 000000000..a37ee283d --- /dev/null +++ b/BitwardenShared/UI/Platform/Settings/TestHelpers/MockSettingsCoordinatorDelegate.swift @@ -0,0 +1,41 @@ +@testable import BitwardenShared + +class MockSettingsCoordinatorDelegate: SettingsCoordinatorDelegate { + var didCompleteLoginsImportCalled = false + var didDeleteAccountCalled = false + var didLockVaultCalled = false + var didLogoutCalled = false + var hasManuallyLockedVault = false + var lockedId: String? + var loggedOutId: String? + var switchAccountCalled = false + var switchUserId: String? + var wasLogoutUserInitiated: Bool? + var wasSwitchAutomatic: Bool? + + func didCompleteLoginsImport() { + didCompleteLoginsImportCalled = true + } + + func didDeleteAccount() { + didDeleteAccountCalled = true + } + + func lockVault(userId: String?, isManuallyLocking: Bool) { + lockedId = userId + didLockVaultCalled = true + hasManuallyLockedVault = isManuallyLocking + } + + func logout(userId: String?, userInitiated: Bool) { + loggedOutId = userId + wasLogoutUserInitiated = userInitiated + didLogoutCalled = true + } + + func switchAccount(isAutomatic: Bool, userId: String) { + switchAccountCalled = true + wasSwitchAutomatic = isAutomatic + switchUserId = userId + } +} diff --git a/BitwardenShared/UI/Tools/ExportCXF/ExportCXF/ExportCXFViewTests.swift b/BitwardenShared/UI/Tools/ExportCXF/ExportCXF/ExportCXFView+SnapshotTests.swift similarity index 72% rename from BitwardenShared/UI/Tools/ExportCXF/ExportCXF/ExportCXFViewTests.swift rename to BitwardenShared/UI/Tools/ExportCXF/ExportCXF/ExportCXFView+SnapshotTests.swift index 779f20abf..59d7b3f54 100644 --- a/BitwardenShared/UI/Tools/ExportCXF/ExportCXF/ExportCXFViewTests.swift +++ b/BitwardenShared/UI/Tools/ExportCXF/ExportCXF/ExportCXFView+SnapshotTests.swift @@ -1,6 +1,6 @@ +// swiftlint:disable:this file_name import BitwardenResources import SnapshotTesting -import ViewInspector import XCTest @testable import BitwardenShared @@ -33,24 +33,6 @@ class ExportCXFViewTests: BitwardenTestCase { // MARK: Tests - /// Tapping on the export items button performs the `.mainButtonTapped` effect. - @MainActor - func test_mainButton_tapped() async throws { - processor.state.status = .prepared(itemsToExport: []) - let button = try subject.inspect().find(asyncButton: Localizations.exportItems) - try await button.tap() - XCTAssertEqual(processor.effects.last, .mainButtonTapped) - } - - /// Tapping on the cancel button performs the `.cancel` effect. - @MainActor - func test_cancelButton_tapped() async throws { - processor.state.status = .start - let button = try subject.inspect().find(asyncButton: Localizations.cancel) - try await button.tap() - XCTAssertEqual(processor.effects.last, .cancel) - } - /// Test a snapshot on start status. func disabletest_snapshot_start() { assertSnapshots( diff --git a/BitwardenShared/UI/Tools/ExportCXF/ExportCXF/ExportCXFView+ViewInspectorTests.swift b/BitwardenShared/UI/Tools/ExportCXF/ExportCXF/ExportCXFView+ViewInspectorTests.swift new file mode 100644 index 000000000..105911ddd --- /dev/null +++ b/BitwardenShared/UI/Tools/ExportCXF/ExportCXF/ExportCXFView+ViewInspectorTests.swift @@ -0,0 +1,53 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import ViewInspector +import XCTest + +@testable import BitwardenShared + +// MARK: - ExportCXFViewTests + +class ExportCXFViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: ExportCXFView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: ExportCXFState()) + let store = Store(processor: processor) + + subject = ExportCXFView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Tests + + /// Tapping on the export items button performs the `.mainButtonTapped` effect. + @MainActor + func test_mainButton_tapped() async throws { + processor.state.status = .prepared(itemsToExport: []) + let button = try subject.inspect().find(asyncButton: Localizations.exportItems) + try await button.tap() + XCTAssertEqual(processor.effects.last, .mainButtonTapped) + } + + /// Tapping on the cancel button performs the `.cancel` effect. + @MainActor + func test_cancelButton_tapped() async throws { + processor.state.status = .start + let button = try subject.inspect().find(asyncButton: Localizations.cancel) + try await button.tap() + XCTAssertEqual(processor.effects.last, .cancel) + } +} diff --git a/BitwardenShared/UI/Tools/Generator/Generator/GeneratorView+SnapshotTests.swift b/BitwardenShared/UI/Tools/Generator/Generator/GeneratorView+SnapshotTests.swift new file mode 100644 index 000000000..8a21196e0 --- /dev/null +++ b/BitwardenShared/UI/Tools/Generator/Generator/GeneratorView+SnapshotTests.swift @@ -0,0 +1,173 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import SwiftUI +import XCTest + +@testable import BitwardenShared + +class GeneratorViewTests: BitwardenTestCase { + // MARK: Types + + /// Wraps the generator view in a navigation controller with the hairline divider removed for + /// snapshot tests. + struct SnapshotView: UIViewControllerRepresentable { + let subject: GeneratorView + + func makeUIViewController(context: Context) -> some UIViewController { + let viewController = UIHostingController(rootView: subject) + let navigationController = UINavigationController(rootViewController: viewController) + navigationController.navigationBar.prefersLargeTitles = true + navigationController.removeHairlineDivider() + return navigationController + } + + func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {} + } + + // MARK: Properties + + var processor: MockProcessor! + var subject: GeneratorView! + + var snapshotView: some View { + SnapshotView(subject: subject).edgesIgnoringSafeArea(.all) + } + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: GeneratorState()) + let store = Store(processor: processor) + + subject = GeneratorView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// Test a snapshot of the copied value toast. + @MainActor + func disabletest_snapshot_generatorViewToast() { + processor.state.generatedValue = "pa11w0rd" + processor.state.showCopiedValueToast() + assertSnapshot( + of: snapshotView, + as: .defaultPortrait, + ) + } + + /// Test a snapshot of the passphrase generation view. + @MainActor + func disabletest_snapshot_generatorViewPassphrase() { + processor.state.generatorType = .passphrase + assertSnapshots( + of: snapshotView, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } + + /// Test a snapshot of the password generation view. + @MainActor + func disabletest_snapshot_generatorViewPassword() { + processor.state.generatorType = .password + assertSnapshots( + of: snapshotView, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } + + /// Test a snapshot of the password generation view with the select button. + @MainActor + func disabletest_snapshot_generatorViewPassword_inPlace() { + processor.state.generatorType = .password + processor.state.presentationMode = .inPlace + assertSnapshot(of: snapshotView, as: .tallPortrait) + } + + /// Test a snapshot of the password generation view with a policy in effect. + @MainActor + func disabletest_snapshot_generatorViewPassword_policyInEffect() { + processor.state.isPolicyInEffect = true + processor.state.policyOptions = PasswordGenerationOptions(type: .password, overridePasswordType: true) + assertSnapshot( + of: snapshotView, + as: .defaultPortrait, + ) + } + + /// Test a snapshot of the catch-all username generation view. + @MainActor + func disabletest_snapshot_generatorViewUsernameCatchAll() { + processor.state.generatorType = .username + processor.state.usernameState.usernameGeneratorType = .catchAllEmail + assertSnapshots( + of: snapshotView, + as: [ + Snapshotting.portrait(drawHierarchyInKeyWindow: true), + Snapshotting.portraitDark(drawHierarchyInKeyWindow: true), + Snapshotting.tallPortraitAX5(heightMultiple: 1.5, drawHierarchyInKeyWindow: true), + ], + ) + } + + /// Test a snapshot of the forwarded email alias generation view. + @MainActor + func disabletest_snapshot_generatorViewUsernameForwarded() { + processor.state.generatorType = .username + processor.state.usernameState.usernameGeneratorType = .forwardedEmail + assertSnapshot( + of: snapshotView, + as: .defaultPortrait, + ) + } + + /// Test a snapshot of the plus addressed username generation view. + @MainActor + func disabletest_snapshot_generatorViewUsernamePlusAddressed() { + processor.state.generatorType = .username + processor.state.usernameState.usernameGeneratorType = .plusAddressedEmail + assertSnapshot( + of: snapshotView, + as: .defaultPortrait, + ) + } + + /// Test a snapshot of the plus addressed username generation view with the select button. + @MainActor + func disabletest_snapshot_generatorViewUsernamePlusAddressed_inPlace() { + processor.state.generatorType = .username + processor.state.usernameState.usernameGeneratorType = .plusAddressedEmail + processor.state.presentationMode = .inPlace + assertSnapshot(of: snapshotView, as: .defaultPortrait) + } + + /// Test a snapshot of the random word username generation view. + @MainActor + func disabletest_snapshot_generatorViewUsernameRandomWord() { + processor.state.generatorType = .username + processor.state.usernameState.usernameGeneratorType = .randomWord + assertSnapshot( + of: snapshotView, + as: .defaultPortrait, + ) + } + + /// Tests the snapshot with the learn generator action card. + @MainActor + func disabletest_snapshot_generatorView_learnGeneratorActionCard() throws { + processor.state.isLearnGeneratorActionCardEligible = true + assertSnapshots( + of: subject, + as: [.defaultPortrait, .defaultPortraitDark], + ) + } +} diff --git a/BitwardenShared/UI/Tools/Generator/Generator/GeneratorViewTests.swift b/BitwardenShared/UI/Tools/Generator/Generator/GeneratorView+ViewInspectorTests.swift similarity index 67% rename from BitwardenShared/UI/Tools/Generator/Generator/GeneratorViewTests.swift rename to BitwardenShared/UI/Tools/Generator/Generator/GeneratorView+ViewInspectorTests.swift index 041a1061b..18c3bd123 100644 --- a/BitwardenShared/UI/Tools/Generator/Generator/GeneratorViewTests.swift +++ b/BitwardenShared/UI/Tools/Generator/Generator/GeneratorView+ViewInspectorTests.swift @@ -1,12 +1,12 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import SwiftUI import ViewInspector import XCTest @testable import BitwardenShared -class GeneratorViewTests: BitwardenTestCase { // swiftlint:disable:this type_body_length +class GeneratorViewTests: BitwardenTestCase { // MARK: Types /// Wraps the generator view in a navigation controller with the hairline divider removed for @@ -58,7 +58,7 @@ class GeneratorViewTests: BitwardenTestCase { // swiftlint:disable:this type_bod @MainActor func test_dismissButton_tap() throws { processor.state.presentationMode = .inPlace - var button = try subject.inspect().findCancelToolbarButton() + let button = try subject.inspect().findCancelToolbarButton() try button.tap() XCTAssertEqual(processor.dispatchedActions.last, .dismissPressed) } @@ -227,123 +227,4 @@ class GeneratorViewTests: BitwardenTestCase { // swiftlint:disable:this type_bod try toggle.tap() XCTAssertEqual(processor.dispatchedActions.last, .toggleValueChanged(field: field, isOn: false)) } - - // MARK: Snapshots - - /// Test a snapshot of the copied value toast. - @MainActor - func disabletest_snapshot_generatorViewToast() { - processor.state.generatedValue = "pa11w0rd" - processor.state.showCopiedValueToast() - assertSnapshot( - of: snapshotView, - as: .defaultPortrait, - ) - } - - /// Test a snapshot of the passphrase generation view. - @MainActor - func disabletest_snapshot_generatorViewPassphrase() { - processor.state.generatorType = .passphrase - assertSnapshots( - of: snapshotView, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } - - /// Test a snapshot of the password generation view. - @MainActor - func disabletest_snapshot_generatorViewPassword() { - processor.state.generatorType = .password - assertSnapshots( - of: snapshotView, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } - - /// Test a snapshot of the password generation view with the select button. - @MainActor - func disabletest_snapshot_generatorViewPassword_inPlace() { - processor.state.generatorType = .password - processor.state.presentationMode = .inPlace - assertSnapshot(of: snapshotView, as: .tallPortrait) - } - - /// Test a snapshot of the password generation view with a policy in effect. - @MainActor - func disabletest_snapshot_generatorViewPassword_policyInEffect() { - processor.state.isPolicyInEffect = true - processor.state.policyOptions = PasswordGenerationOptions(type: .password, overridePasswordType: true) - assertSnapshot( - of: snapshotView, - as: .defaultPortrait, - ) - } - - /// Test a snapshot of the catch-all username generation view. - @MainActor - func disabletest_snapshot_generatorViewUsernameCatchAll() { - processor.state.generatorType = .username - processor.state.usernameState.usernameGeneratorType = .catchAllEmail - assertSnapshots( - of: snapshotView, - as: [ - Snapshotting.portrait(drawHierarchyInKeyWindow: true), - Snapshotting.portraitDark(drawHierarchyInKeyWindow: true), - Snapshotting.tallPortraitAX5(heightMultiple: 1.5, drawHierarchyInKeyWindow: true), - ], - ) - } - - /// Test a snapshot of the forwarded email alias generation view. - @MainActor - func disabletest_snapshot_generatorViewUsernameForwarded() { - processor.state.generatorType = .username - processor.state.usernameState.usernameGeneratorType = .forwardedEmail - assertSnapshot( - of: snapshotView, - as: .defaultPortrait, - ) - } - - /// Test a snapshot of the plus addressed username generation view. - @MainActor - func disabletest_snapshot_generatorViewUsernamePlusAddressed() { - processor.state.generatorType = .username - processor.state.usernameState.usernameGeneratorType = .plusAddressedEmail - assertSnapshot( - of: snapshotView, - as: .defaultPortrait, - ) - } - - /// Test a snapshot of the plus addressed username generation view with the select button. - @MainActor - func disabletest_snapshot_generatorViewUsernamePlusAddressed_inPlace() { - processor.state.generatorType = .username - processor.state.usernameState.usernameGeneratorType = .plusAddressedEmail - processor.state.presentationMode = .inPlace - assertSnapshot(of: snapshotView, as: .defaultPortrait) - } - - /// Test a snapshot of the random word username generation view. - @MainActor - func disabletest_snapshot_generatorViewUsernameRandomWord() { - processor.state.generatorType = .username - processor.state.usernameState.usernameGeneratorType = .randomWord - assertSnapshot( - of: snapshotView, - as: .defaultPortrait, - ) - } - - /// Tests the snapshot with the learn generator action card. - @MainActor - func disabletest_snapshot_generatorView_learnGeneratorActionCard() throws { - processor.state.isLearnGeneratorActionCardEligible = true - assertSnapshots( - of: subject, - as: [.defaultPortrait, .defaultPortraitDark], - ) - } } diff --git a/BitwardenShared/UI/Tools/ImportCXF/ImportCXF/ImportCXFViewTests.swift b/BitwardenShared/UI/Tools/ImportCXF/ImportCXF/ImportCXFView+SnapshotTests.swift similarity index 73% rename from BitwardenShared/UI/Tools/ImportCXF/ImportCXF/ImportCXFViewTests.swift rename to BitwardenShared/UI/Tools/ImportCXF/ImportCXF/ImportCXFView+SnapshotTests.swift index bae07cbac..4be4054a9 100644 --- a/BitwardenShared/UI/Tools/ImportCXF/ImportCXF/ImportCXFViewTests.swift +++ b/BitwardenShared/UI/Tools/ImportCXF/ImportCXF/ImportCXFView+SnapshotTests.swift @@ -1,6 +1,6 @@ +// swiftlint:disable:this file_name import BitwardenResources import SnapshotTesting -import ViewInspector import XCTest @testable import BitwardenShared @@ -33,28 +33,6 @@ class ImportCXFViewTests: BitwardenTestCase { // MARK: Tests - /// Tapping on the continue button performs the `.mainButtonTapped` effect. - @MainActor - func test_mainButton_tapped() throws { - processor.state.status = .start - let button = try subject.inspect().find(button: Localizations.continue) - try button.tap() - waitFor { - processor.effects.last == .mainButtonTapped - } - } - - /// Tapping on the cancel button performs the `.cancel` effect. - @MainActor - func test_cancelButton_tapped() throws { - processor.state.status = .start - let button = try subject.inspect().find(button: Localizations.cancel) - try button.tap() - waitFor { - processor.effects.last == .cancel - } - } - /// Test a snapshot on start status. func disabletest_snapshot_start() { assertSnapshots( diff --git a/BitwardenShared/UI/Tools/ImportCXF/ImportCXF/ImportCXFView+ViewInspectorTests.swift b/BitwardenShared/UI/Tools/ImportCXF/ImportCXF/ImportCXFView+ViewInspectorTests.swift new file mode 100644 index 000000000..c3b79898f --- /dev/null +++ b/BitwardenShared/UI/Tools/ImportCXF/ImportCXF/ImportCXFView+ViewInspectorTests.swift @@ -0,0 +1,57 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import ViewInspector +import XCTest + +@testable import BitwardenShared + +// MARK: - ImportCXFViewTests + +class ImportCXFViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: ImportCXFView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: ImportCXFState()) + let store = Store(processor: processor) + + subject = ImportCXFView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Tests + + /// Tapping on the continue button performs the `.mainButtonTapped` effect. + @MainActor + func test_mainButton_tapped() throws { + processor.state.status = .start + let button = try subject.inspect().find(button: Localizations.continue) + try button.tap() + waitFor { + processor.effects.last == .mainButtonTapped + } + } + + /// Tapping on the cancel button performs the `.cancel` effect. + @MainActor + func test_cancelButton_tapped() throws { + processor.state.status = .start + let button = try subject.inspect().find(button: Localizations.cancel) + try button.tap() + waitFor { + processor.effects.last == .cancel + } + } +} diff --git a/BitwardenShared/UI/Tools/PasswordHistory/PasswordHistoryList/PasswordHistoryListViewTests.swift b/BitwardenShared/UI/Tools/PasswordHistory/PasswordHistoryList/PasswordHistoryListView+SnapshotTests.swift similarity index 61% rename from BitwardenShared/UI/Tools/PasswordHistory/PasswordHistoryList/PasswordHistoryListViewTests.swift rename to BitwardenShared/UI/Tools/PasswordHistory/PasswordHistoryList/PasswordHistoryListView+SnapshotTests.swift index 8fac0d0b7..70b6045c8 100644 --- a/BitwardenShared/UI/Tools/PasswordHistory/PasswordHistoryList/PasswordHistoryListViewTests.swift +++ b/BitwardenShared/UI/Tools/PasswordHistory/PasswordHistoryList/PasswordHistoryListView+SnapshotTests.swift @@ -1,7 +1,7 @@ +// swiftlint:disable:this file_name import BitwardenResources import BitwardenSdk import SnapshotTesting -import ViewInspector import XCTest import SwiftUI @@ -32,36 +32,6 @@ class PasswordHistoryListViewTests: BitwardenTestCase { subject = nil } - // MARK: Tests - - /// Tapping the clear button dispatches the `.clearList` action. - @MainActor - func test_clear_tapped() async throws { - let menu = try subject.inspect().find(ViewType.Menu.self, containing: Localizations.options) - let button = try menu.find(asyncButton: Localizations.clear) - try await button.tap() - XCTAssertEqual(processor.effects.last, .clearList) - } - - /// Tapping the close button dispatches the `.dismiss` action. - @MainActor - func test_close_tapped() throws { - var button = try subject.inspect().findCloseToolbarButton() - try button.tap() - XCTAssertEqual(processor.dispatchedActions.last, .dismiss) - } - - /// Tapping the copy button on a password history row dispatches the `.copyPassword` action. - @MainActor - func test_copyPassword_tapped() throws { - let passwordHistory = PasswordHistoryView.fixture(password: "8gr6uY8CLYQwzr#") - processor.state.passwordHistory = [passwordHistory] - - let button = try subject.inspect().find(buttonWithAccessibilityLabel: Localizations.copyPassword) - try button.tap() - XCTAssertEqual(processor.dispatchedActions.last, .copyPassword(passwordHistory)) - } - // MARK: Snapshots /// Test a snapshot of the generator history view's empty state. diff --git a/BitwardenShared/UI/Tools/PasswordHistory/PasswordHistoryList/PasswordHistoryListView+ViewInspectorTests.swift b/BitwardenShared/UI/Tools/PasswordHistory/PasswordHistoryList/PasswordHistoryListView+ViewInspectorTests.swift new file mode 100644 index 000000000..9da08182d --- /dev/null +++ b/BitwardenShared/UI/Tools/PasswordHistory/PasswordHistoryList/PasswordHistoryListView+ViewInspectorTests.swift @@ -0,0 +1,64 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import BitwardenSdk +import ViewInspector +import XCTest + +import SwiftUI + +@testable import BitwardenShared + +class PasswordHistoryListViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: PasswordHistoryListView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: PasswordHistoryListState()) + let store = Store(processor: processor) + + subject = PasswordHistoryListView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Tests + + /// Tapping the clear button dispatches the `.clearList` action. + @MainActor + func test_clear_tapped() async throws { + let menu = try subject.inspect().find(ViewType.Menu.self, containing: Localizations.options) + let button = try menu.find(asyncButton: Localizations.clear) + try await button.tap() + XCTAssertEqual(processor.effects.last, .clearList) + } + + /// Tapping the close button dispatches the `.dismiss` action. + @MainActor + func test_close_tapped() throws { + let button = try subject.inspect().findCloseToolbarButton() + try button.tap() + XCTAssertEqual(processor.dispatchedActions.last, .dismiss) + } + + /// Tapping the copy button on a password history row dispatches the `.copyPassword` action. + @MainActor + func test_copyPassword_tapped() throws { + let passwordHistory = PasswordHistoryView.fixture(password: "8gr6uY8CLYQwzr#") + processor.state.passwordHistory = [passwordHistory] + + let button = try subject.inspect().find(buttonWithAccessibilityLabel: Localizations.copyPassword) + try button.tap() + XCTAssertEqual(processor.dispatchedActions.last, .copyPassword(passwordHistory)) + } +} diff --git a/BitwardenShared/UI/Tools/Send/Send/SendList/SendListView+SnapshotTests.swift b/BitwardenShared/UI/Tools/Send/Send/SendList/SendListView+SnapshotTests.swift new file mode 100644 index 000000000..e3224ae0c --- /dev/null +++ b/BitwardenShared/UI/Tools/Send/Send/SendList/SendListView+SnapshotTests.swift @@ -0,0 +1,121 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import SwiftUI +import XCTest + +@testable import BitwardenShared + +// MARK: - SendListViewTests + +class SendListViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: SendListView! + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: SendListState()) + subject = SendListView(store: Store(processor: processor)) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// The view renders correctly when there are no items. + @MainActor + func disabletest_snapshot_empty() { + processor.state = .empty + assertSnapshots( + of: subject, + as: [ + .defaultPortrait, + .defaultPortraitDark, + .defaultLandscape, + .defaultPortraitAX5, + ], + ) + } + + /// The view renders correctly when it's loading. + @MainActor + func disabletest_snapshot_loading() { + processor.state = .loading + assertSnapshots( + of: subject.navStackWrapped, + as: [ + .defaultPortrait, + .defaultPortraitDark, + ], + ) + } + + /// The view renders correctly when the search results are empty. + @MainActor + func disabletest_snapshot_search_empty() { + processor.state.searchResults = [] + processor.state.searchText = "Searching" + assertSnapshots( + of: subject, + as: [ + .defaultPortrait, + .defaultPortraitDark, + .defaultLandscape, + .defaultPortraitAX5, + ], + ) + } + + /// The view renders correctly when there are search results. + @MainActor + func disabletest_snapshot_search_results() { + processor.state = .hasSearchResults + assertSnapshots( + of: subject, + as: [ + .defaultPortrait, + .defaultPortraitDark, + .defaultLandscape, + .defaultPortraitAX5, + ], + ) + } + + /// The view renders in correctly when there are sends. + @MainActor + func disabletest_snapshot_values() { + processor.state = .content + assertSnapshots( + of: subject, + as: [ + .defaultPortrait, + .defaultPortraitDark, + .defaultLandscape, + .defaultPortraitAX5, + ], + ) + } + + /// The view renders correctly when there are sends. + @MainActor + func disabletest_snapshot_textValues() { + processor.state = .contentTextType + assertSnapshots( + of: subject, + as: [ + .defaultPortrait, + .defaultPortraitDark, + .defaultLandscape, + .defaultPortraitAX5, + ], + ) + } +} diff --git a/BitwardenShared/UI/Tools/Send/Send/SendList/SendListViewTests.swift b/BitwardenShared/UI/Tools/Send/Send/SendList/SendListView+ViewInspectorTests.swift similarity index 59% rename from BitwardenShared/UI/Tools/Send/Send/SendList/SendListViewTests.swift rename to BitwardenShared/UI/Tools/Send/Send/SendList/SendListView+ViewInspectorTests.swift index 459123ab4..43581c4c2 100644 --- a/BitwardenShared/UI/Tools/Send/Send/SendList/SendListViewTests.swift +++ b/BitwardenShared/UI/Tools/Send/Send/SendList/SendListView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import SwiftUI import ViewInspector import XCTest @@ -95,95 +95,4 @@ class SendListViewTests: BitwardenTestCase { try button.tap() XCTAssertEqual(processor.dispatchedActions.last, .infoButtonPressed) } - - // MARK: Snapshots - - /// The view renders correctly when there are no items. - @MainActor - func disabletest_snapshot_empty() { - processor.state = .empty - assertSnapshots( - of: subject, - as: [ - .defaultPortrait, - .defaultPortraitDark, - .defaultLandscape, - .defaultPortraitAX5, - ], - ) - } - - /// The view renders correctly when it's loading. - @MainActor - func disabletest_snapshot_loading() { - processor.state = .loading - assertSnapshots( - of: subject.navStackWrapped, - as: [ - .defaultPortrait, - .defaultPortraitDark, - ], - ) - } - - /// The view renders correctly when the search results are empty. - @MainActor - func disabletest_snapshot_search_empty() { - processor.state.searchResults = [] - processor.state.searchText = "Searching" - assertSnapshots( - of: subject, - as: [ - .defaultPortrait, - .defaultPortraitDark, - .defaultLandscape, - .defaultPortraitAX5, - ], - ) - } - - /// The view renders correctly when there are search results. - @MainActor - func disabletest_snapshot_search_results() { - processor.state = .hasSearchResults - assertSnapshots( - of: subject, - as: [ - .defaultPortrait, - .defaultPortraitDark, - .defaultLandscape, - .defaultPortraitAX5, - ], - ) - } - - /// The view renders in correctly when there are sends. - @MainActor - func disabletest_snapshot_values() { - processor.state = .content - assertSnapshots( - of: subject, - as: [ - .defaultPortrait, - .defaultPortraitDark, - .defaultLandscape, - .defaultPortraitAX5, - ], - ) - } - - /// The view renders correctly when there are sends. - @MainActor - func disabletest_snapshot_textValues() { - processor.state = .contentTextType - assertSnapshots( - of: subject, - as: [ - .defaultPortrait, - .defaultPortraitDark, - .defaultLandscape, - .defaultPortraitAX5, - ], - ) - } } diff --git a/BitwardenShared/UI/Tools/Send/SendItem/AddEditSendItem/AddEditSendItemView+SnapshotTests.swift b/BitwardenShared/UI/Tools/Send/SendItem/AddEditSendItem/AddEditSendItemView+SnapshotTests.swift new file mode 100644 index 000000000..1a6bd4070 --- /dev/null +++ b/BitwardenShared/UI/Tools/Send/SendItem/AddEditSendItem/AddEditSendItemView+SnapshotTests.swift @@ -0,0 +1,183 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import SwiftUI +import XCTest + +@testable import BitwardenShared + +// MARK: - AddEditSendItemViewTests + +class AddEditSendItemViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: AddEditSendItemView! + + /// A deletion date to use within the tests. + let deletionDate = Date(year: 2023, month: 11, day: 5, hour: 9, minute: 41) + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + processor = MockProcessor(state: AddEditSendItemState()) + subject = AddEditSendItemView(store: Store(processor: processor)) + } + + // MARK: Snapshots + + @MainActor + func disabletest_snapshot_file_empty() { + processor.state.type = .file + assertSnapshots( + of: subject.navStackWrapped, + as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5(heightMultiple: 1.1)], + ) + } + + @MainActor + func disabletest_snapshot_file_withValues() { + processor.state.type = .file + processor.state.name = "Name" + processor.state.fileName = "example_file.txt" + processor.state.fileData = Data("example".utf8) + assertSnapshot(of: subject.navStackWrapped, as: .defaultPortrait) + } + + @MainActor + func disabletest_snapshot_file_withValues_prefilled() { + processor.state.type = .file + processor.state.name = "Name" + processor.state.fileName = "example_file.txt" + processor.state.fileData = Data("example".utf8) + processor.state.mode = .shareExtension(.empty()) + assertSnapshot(of: subject.navStackWrapped, as: .defaultPortrait) + } + + @MainActor + func disabletest_snapshot_file_withOptions_empty() { + processor.state.type = .file + processor.state.isOptionsExpanded = true + assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) + } + + @MainActor + func disabletest_snapshot_file_withOptions_withValues() { + processor.state.type = .file + processor.state.isOptionsExpanded = true + processor.state.name = "Name" + processor.state.fileName = "example_file.txt" + processor.state.fileData = Data("example".utf8) + processor.state.isHideTextByDefaultOn = true + processor.state.deletionDate = .custom(deletionDate) + processor.state.customDeletionDate = deletionDate + processor.state.maximumAccessCount = 42 + processor.state.maximumAccessCountText = "42" + processor.state.password = "pa$$w0rd" + processor.state.notes = "Notes" + processor.state.isHideMyEmailOn = true + processor.state.isDeactivateThisSendOn = true + assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) + } + + @MainActor + func disabletest_snapshot_file_edit_withOptions_withValues() { + processor.state.mode = .edit + processor.state.type = .file + processor.state.isOptionsExpanded = true + processor.state.name = "Name" + processor.state.fileName = "example_file.txt" + processor.state.fileSize = "420.42 KB" + processor.state.deletionDate = .custom(deletionDate) + processor.state.customDeletionDate = deletionDate + processor.state.maximumAccessCount = 420 + processor.state.maximumAccessCountText = "420" + processor.state.currentAccessCount = 42 + processor.state.password = "pa$$w0rd" + processor.state.notes = "Notes" + processor.state.isHideMyEmailOn = true + processor.state.isDeactivateThisSendOn = true + assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) + } + + @MainActor + func disabletest_snapshot_sendDisabled() { + processor.state.isSendDisabled = true + assertSnapshot(of: subject.navStackWrapped, as: .defaultPortrait) + } + + @MainActor + func disabletest_snapshot_sendHideEmailDisabled() { + processor.state.isSendHideEmailDisabled = true + assertSnapshot(of: subject.navStackWrapped, as: .defaultPortrait) + } + + @MainActor + func disabletest_snapshot_text_empty() { + assertSnapshots( + of: subject.navStackWrapped, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } + + @MainActor + func disabletest_snapshot_text_withValues() { + processor.state.name = "Name" + processor.state.text = "Text" + processor.state.isHideTextByDefaultOn = true + assertSnapshot(of: subject.navStackWrapped, as: .defaultPortrait) + } + + @MainActor + func disabletest_snapshot_text_withOptions_empty() { + processor.state.isOptionsExpanded = true + assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) + } + + @MainActor + func disabletest_snapshot_text_withOptions_withValues() { + processor.state.isOptionsExpanded = true + processor.state.name = "Name" + processor.state.text = "Text." + processor.state.isHideTextByDefaultOn = true + processor.state.deletionDate = .custom(deletionDate) + processor.state.customDeletionDate = deletionDate + processor.state.maximumAccessCount = 42 + processor.state.maximumAccessCountText = "42" + processor.state.password = "pa$$w0rd" + processor.state.notes = "Notes." + processor.state.isHideMyEmailOn = true + processor.state.isDeactivateThisSendOn = true + assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) + } + + @MainActor + func disabletest_snapshot_text_edit_withOptions_withValues() { + processor.state.mode = .edit + processor.state.type = .text + processor.state.isOptionsExpanded = true + processor.state.name = "Name" + processor.state.text = "Text" + processor.state.deletionDate = .custom(deletionDate) + processor.state.customDeletionDate = deletionDate + processor.state.maximumAccessCount = 420 + processor.state.maximumAccessCountText = "420" + processor.state.currentAccessCount = 42 + processor.state.password = "pa$$w0rd" + processor.state.notes = "Notes" + processor.state.isHideMyEmailOn = true + processor.state.isDeactivateThisSendOn = true + assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) + } + + @MainActor + func disabletest_snapshot_text_extension_withValues() { + processor.state.mode = .shareExtension(.singleAccount) + processor.state.type = .text + processor.state.name = "Name" + processor.state.text = "Text" + processor.state.isHideTextByDefaultOn = true + assertSnapshot(of: subject.navStackWrapped, as: .defaultPortrait) + } +} diff --git a/BitwardenShared/UI/Tools/Send/SendItem/AddEditSendItem/AddEditSendItemViewTests.swift b/BitwardenShared/UI/Tools/Send/SendItem/AddEditSendItem/AddEditSendItemView+ViewInspectorTests.swift similarity index 52% rename from BitwardenShared/UI/Tools/Send/SendItem/AddEditSendItem/AddEditSendItemViewTests.swift rename to BitwardenShared/UI/Tools/Send/SendItem/AddEditSendItem/AddEditSendItemView+ViewInspectorTests.swift index b67936773..6190c99dc 100644 --- a/BitwardenShared/UI/Tools/Send/SendItem/AddEditSendItem/AddEditSendItemViewTests.swift +++ b/BitwardenShared/UI/Tools/Send/SendItem/AddEditSendItem/AddEditSendItemView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import SwiftUI import ViewInspector import XCTest @@ -8,7 +8,7 @@ import XCTest // MARK: - AddEditSendItemViewTests -class AddEditSendItemViewTests: BitwardenTestCase { // swiftlint:disable:this type_body_length +class AddEditSendItemViewTests: BitwardenTestCase { // MARK: Properties var processor: MockProcessor! @@ -30,7 +30,7 @@ class AddEditSendItemViewTests: BitwardenTestCase { // swiftlint:disable:this ty /// Tapping the cancel button sends the `.dismissPressed` action. @MainActor func test_cancelButton_tap() throws { - var button = try subject.inspect().findCancelToolbarButton() + let button = try subject.inspect().findCancelToolbarButton() try button.tap() XCTAssertEqual(processor.dispatchedActions.last, .dismissPressed) } @@ -166,160 +166,4 @@ class AddEditSendItemViewTests: BitwardenTestCase { // swiftlint:disable:this ty try textField.inputBinding().wrappedValue = "Text" XCTAssertEqual(processor.dispatchedActions.last, .textChanged("Text")) } - - // MARK: Snapshots - - @MainActor - func disabletest_snapshot_file_empty() { - processor.state.type = .file - assertSnapshots( - of: subject.navStackWrapped, - as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5(heightMultiple: 1.1)], - ) - } - - @MainActor - func disabletest_snapshot_file_withValues() { - processor.state.type = .file - processor.state.name = "Name" - processor.state.fileName = "example_file.txt" - processor.state.fileData = Data("example".utf8) - assertSnapshot(of: subject.navStackWrapped, as: .defaultPortrait) - } - - @MainActor - func disabletest_snapshot_file_withValues_prefilled() { - processor.state.type = .file - processor.state.name = "Name" - processor.state.fileName = "example_file.txt" - processor.state.fileData = Data("example".utf8) - processor.state.mode = .shareExtension(.empty()) - assertSnapshot(of: subject.navStackWrapped, as: .defaultPortrait) - } - - @MainActor - func disabletest_snapshot_file_withOptions_empty() { - processor.state.type = .file - processor.state.isOptionsExpanded = true - assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) - } - - @MainActor - func disabletest_snapshot_file_withOptions_withValues() { - processor.state.type = .file - processor.state.isOptionsExpanded = true - processor.state.name = "Name" - processor.state.fileName = "example_file.txt" - processor.state.fileData = Data("example".utf8) - processor.state.isHideTextByDefaultOn = true - processor.state.deletionDate = .custom(deletionDate) - processor.state.customDeletionDate = deletionDate - processor.state.maximumAccessCount = 42 - processor.state.maximumAccessCountText = "42" - processor.state.password = "pa$$w0rd" - processor.state.notes = "Notes" - processor.state.isHideMyEmailOn = true - processor.state.isDeactivateThisSendOn = true - assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) - } - - @MainActor - func disabletest_snapshot_file_edit_withOptions_withValues() { - processor.state.mode = .edit - processor.state.type = .file - processor.state.isOptionsExpanded = true - processor.state.name = "Name" - processor.state.fileName = "example_file.txt" - processor.state.fileSize = "420.42 KB" - processor.state.deletionDate = .custom(deletionDate) - processor.state.customDeletionDate = deletionDate - processor.state.maximumAccessCount = 420 - processor.state.maximumAccessCountText = "420" - processor.state.currentAccessCount = 42 - processor.state.password = "pa$$w0rd" - processor.state.notes = "Notes" - processor.state.isHideMyEmailOn = true - processor.state.isDeactivateThisSendOn = true - assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) - } - - @MainActor - func disabletest_snapshot_sendDisabled() { - processor.state.isSendDisabled = true - assertSnapshot(of: subject.navStackWrapped, as: .defaultPortrait) - } - - @MainActor - func disabletest_snapshot_sendHideEmailDisabled() { - processor.state.isSendHideEmailDisabled = true - assertSnapshot(of: subject.navStackWrapped, as: .defaultPortrait) - } - - @MainActor - func disabletest_snapshot_text_empty() { - assertSnapshots( - of: subject.navStackWrapped, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } - - @MainActor - func disabletest_snapshot_text_withValues() { - processor.state.name = "Name" - processor.state.text = "Text" - processor.state.isHideTextByDefaultOn = true - assertSnapshot(of: subject.navStackWrapped, as: .defaultPortrait) - } - - @MainActor - func disabletest_snapshot_text_withOptions_empty() { - processor.state.isOptionsExpanded = true - assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) - } - - @MainActor - func disabletest_snapshot_text_withOptions_withValues() { - processor.state.isOptionsExpanded = true - processor.state.name = "Name" - processor.state.text = "Text." - processor.state.isHideTextByDefaultOn = true - processor.state.deletionDate = .custom(deletionDate) - processor.state.customDeletionDate = deletionDate - processor.state.maximumAccessCount = 42 - processor.state.maximumAccessCountText = "42" - processor.state.password = "pa$$w0rd" - processor.state.notes = "Notes." - processor.state.isHideMyEmailOn = true - processor.state.isDeactivateThisSendOn = true - assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) - } - - @MainActor - func disabletest_snapshot_text_edit_withOptions_withValues() { - processor.state.mode = .edit - processor.state.type = .text - processor.state.isOptionsExpanded = true - processor.state.name = "Name" - processor.state.text = "Text" - processor.state.deletionDate = .custom(deletionDate) - processor.state.customDeletionDate = deletionDate - processor.state.maximumAccessCount = 420 - processor.state.maximumAccessCountText = "420" - processor.state.currentAccessCount = 42 - processor.state.password = "pa$$w0rd" - processor.state.notes = "Notes" - processor.state.isHideMyEmailOn = true - processor.state.isDeactivateThisSendOn = true - assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) - } - - @MainActor - func disabletest_snapshot_text_extension_withValues() { - processor.state.mode = .shareExtension(.singleAccount) - processor.state.type = .text - processor.state.name = "Name" - processor.state.text = "Text" - processor.state.isHideTextByDefaultOn = true - assertSnapshot(of: subject.navStackWrapped, as: .defaultPortrait) - } } diff --git a/BitwardenShared/UI/Tools/Send/SendItem/ViewSendItem/ViewSendItemViewTests.swift b/BitwardenShared/UI/Tools/Send/SendItem/ViewSendItem/ViewSendItemView+SnapshotTests.swift similarity index 73% rename from BitwardenShared/UI/Tools/Send/SendItem/ViewSendItem/ViewSendItemViewTests.swift rename to BitwardenShared/UI/Tools/Send/SendItem/ViewSendItem/ViewSendItemView+SnapshotTests.swift index 5ae69fb64..62e066b30 100644 --- a/BitwardenShared/UI/Tools/Send/SendItem/ViewSendItem/ViewSendItemViewTests.swift +++ b/BitwardenShared/UI/Tools/Send/SendItem/ViewSendItem/ViewSendItemView+SnapshotTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import BitwardenResources import SnapshotTesting import XCTest @@ -27,34 +28,6 @@ class ViewSendItemViewTests: BitwardenTestCase { subject = nil } - // MARK: Tests - - /// Tapping the cancel button sends the `.dismiss` action. - @MainActor - func test_cancel_tap() throws { - var button = try subject.inspect().findCancelToolbarButton() - try button.tap() - XCTAssertEqual(processor.dispatchedActions.last, .dismiss) - } - - /// Tapping the delete button performs the `.delete` effect. - @MainActor - func test_delete_tap() async throws { - let button = try subject.inspect().find(asyncButton: Localizations.deleteSend) - try await button.tap() - XCTAssertEqual(processor.effects.last, .deleteSend) - } - - /// Tapping the edit button sends the `.editItem` action. - @MainActor - func test_editItemFloatingActionButton_tap() async throws { - let fab = try subject.inspect().find( - floatingActionButtonWithAccessibilityIdentifier: "EditItemFloatingActionButton", - ) - try await fab.tap() - XCTAssertEqual(processor.dispatchedActions.last, .editItem) - } - // MARK: Snapshots /// The view send view for a file send renders correctly. diff --git a/BitwardenShared/UI/Tools/Send/SendItem/ViewSendItem/ViewSendItemView+ViewInspectorTests.swift b/BitwardenShared/UI/Tools/Send/SendItem/ViewSendItem/ViewSendItemView+ViewInspectorTests.swift new file mode 100644 index 000000000..419170304 --- /dev/null +++ b/BitwardenShared/UI/Tools/Send/SendItem/ViewSendItem/ViewSendItemView+ViewInspectorTests.swift @@ -0,0 +1,57 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import XCTest + +@testable import BitwardenShared + +class ViewSendItemViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: ViewSendItemView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: ViewSendItemState(sendView: .fixture())) + + subject = ViewSendItemView(store: Store(processor: processor)) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Tests + + /// Tapping the cancel button sends the `.dismiss` action. + @MainActor + func test_cancel_tap() throws { + let button = try subject.inspect().findCancelToolbarButton() + try button.tap() + XCTAssertEqual(processor.dispatchedActions.last, .dismiss) + } + + /// Tapping the delete button performs the `.delete` effect. + @MainActor + func test_delete_tap() async throws { + let button = try subject.inspect().find(asyncButton: Localizations.deleteSend) + try await button.tap() + XCTAssertEqual(processor.effects.last, .deleteSend) + } + + /// Tapping the edit button sends the `.editItem` action. + @MainActor + func test_editItemFloatingActionButton_tap() async throws { + let fab = try subject.inspect().find( + floatingActionButtonWithAccessibilityIdentifier: "EditItemFloatingActionButton", + ) + try await fab.tap() + XCTAssertEqual(processor.dispatchedActions.last, .editItem) + } +} diff --git a/BitwardenShared/UI/Vault/ImportLogins/ImportLogins/ImportLoginsView+SnapshotTests.swift b/BitwardenShared/UI/Vault/ImportLogins/ImportLogins/ImportLoginsView+SnapshotTests.swift new file mode 100644 index 000000000..2bb104d0c --- /dev/null +++ b/BitwardenShared/UI/Vault/ImportLogins/ImportLogins/ImportLoginsView+SnapshotTests.swift @@ -0,0 +1,72 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class ImportLoginsViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: ImportLoginsView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: ImportLoginsState(mode: .vault)) + + subject = ImportLoginsView(store: Store(processor: processor)) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// The import logins intro page renders correctly. + @MainActor + func disabletest_snapshot_importLoginsIntro() { + assertSnapshots( + of: subject.navStackWrapped, + as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5(heightMultiple: 2), .defaultLandscape], + ) + } + + /// The import logins step 1 page renders correctly. + @MainActor + func disabletest_snapshot_importLoginsStep1() { + processor.state.page = .step1 + assertSnapshots( + of: subject.navStackWrapped, + as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5(heightMultiple: 2.5), .defaultLandscape], + ) + } + + /// The import logins step 2 page renders correctly. + @MainActor + func disabletest_snapshot_importLoginsStep2() { + processor.state.page = .step2 + processor.state.webVaultHost = "vault.bitwarden.com" + assertSnapshots( + of: subject.navStackWrapped, + as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5(heightMultiple: 2), .defaultLandscape], + ) + } + + /// The import logins step 3 page renders correctly. + @MainActor + func disabletest_snapshot_importLoginsStep3() { + processor.state.page = .step3 + assertSnapshots( + of: subject.navStackWrapped, + as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5(heightMultiple: 2.5), .defaultLandscape], + ) + } +} diff --git a/BitwardenShared/UI/Vault/ImportLogins/ImportLogins/ImportLoginsViewTests.swift b/BitwardenShared/UI/Vault/ImportLogins/ImportLogins/ImportLoginsView+ViewInspectorTests.swift similarity index 62% rename from BitwardenShared/UI/Vault/ImportLogins/ImportLogins/ImportLoginsViewTests.swift rename to BitwardenShared/UI/Vault/ImportLogins/ImportLogins/ImportLoginsView+ViewInspectorTests.swift index e3b579c12..f14c02367 100644 --- a/BitwardenShared/UI/Vault/ImportLogins/ImportLogins/ImportLoginsViewTests.swift +++ b/BitwardenShared/UI/Vault/ImportLogins/ImportLogins/ImportLoginsView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import ViewInspector import XCTest @@ -33,7 +33,7 @@ class ImportLoginsViewTests: BitwardenTestCase { /// Tapping the dismiss button dispatches the `dismiss` action. @MainActor func test_dismiss_tap() throws { - var button = try subject.inspect().findCancelToolbarButton() + let button = try subject.inspect().findCancelToolbarButton() try button.tap() XCTAssertEqual(processor.dispatchedActions.last, .dismiss) } @@ -80,46 +80,4 @@ class ImportLoginsViewTests: BitwardenTestCase { try await button.tap() XCTAssertEqual(processor.effects.last, .advanceNextPage) } - - // MARK: Snapshots - - /// The import logins intro page renders correctly. - @MainActor - func disabletest_snapshot_importLoginsIntro() { - assertSnapshots( - of: subject.navStackWrapped, - as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5(heightMultiple: 2), .defaultLandscape], - ) - } - - /// The import logins step 1 page renders correctly. - @MainActor - func disabletest_snapshot_importLoginsStep1() { - processor.state.page = .step1 - assertSnapshots( - of: subject.navStackWrapped, - as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5(heightMultiple: 2.5), .defaultLandscape], - ) - } - - /// The import logins step 2 page renders correctly. - @MainActor - func disabletest_snapshot_importLoginsStep2() { - processor.state.page = .step2 - processor.state.webVaultHost = "vault.bitwarden.com" - assertSnapshots( - of: subject.navStackWrapped, - as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5(heightMultiple: 2), .defaultLandscape], - ) - } - - /// The import logins step 3 page renders correctly. - @MainActor - func disabletest_snapshot_importLoginsStep3() { - processor.state.page = .step3 - assertSnapshots( - of: subject.navStackWrapped, - as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5(heightMultiple: 2.5), .defaultLandscape], - ) - } } diff --git a/BitwardenShared/UI/Vault/ImportLogins/ImportLoginsSuccess/ImportLoginsSuccessView+SnapshotTests.swift b/BitwardenShared/UI/Vault/ImportLogins/ImportLoginsSuccess/ImportLoginsSuccessView+SnapshotTests.swift new file mode 100644 index 000000000..74326a17e --- /dev/null +++ b/BitwardenShared/UI/Vault/ImportLogins/ImportLoginsSuccess/ImportLoginsSuccessView+SnapshotTests.swift @@ -0,0 +1,41 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class ImportLoginsSuccessViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: ImportLoginsSuccessView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: ()) + + subject = ImportLoginsSuccessView(store: Store(processor: processor)) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// The import logins success page renders correctly. + @MainActor + func disabletest_snapshot_importLoginsSuccess() { + assertSnapshots( + of: subject.navStackWrapped, + as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5(heightMultiple: 3), .defaultLandscape], + ) + } +} diff --git a/BitwardenShared/UI/Vault/ImportLogins/ImportLoginsSuccess/ImportLoginsSuccessViewTests.swift b/BitwardenShared/UI/Vault/ImportLogins/ImportLoginsSuccess/ImportLoginsSuccessView+ViewInspectorTests.swift similarity index 73% rename from BitwardenShared/UI/Vault/ImportLogins/ImportLoginsSuccess/ImportLoginsSuccessViewTests.swift rename to BitwardenShared/UI/Vault/ImportLogins/ImportLoginsSuccess/ImportLoginsSuccessView+ViewInspectorTests.swift index fc4bfe91e..b9e7e78ba 100644 --- a/BitwardenShared/UI/Vault/ImportLogins/ImportLoginsSuccess/ImportLoginsSuccessViewTests.swift +++ b/BitwardenShared/UI/Vault/ImportLogins/ImportLoginsSuccess/ImportLoginsSuccessView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import ViewInspector import XCTest @@ -33,7 +33,7 @@ class ImportLoginsSuccessViewTests: BitwardenTestCase { /// Tapping the close button dispatches the `dismiss` action. @MainActor func test_close_tap() throws { - var button = try subject.inspect().findCloseToolbarButton() + let button = try subject.inspect().findCloseToolbarButton() try button.tap() waitFor { !processor.effects.isEmpty } XCTAssertEqual(processor.effects.last, .dismiss) @@ -46,15 +46,4 @@ class ImportLoginsSuccessViewTests: BitwardenTestCase { try await button.tap() XCTAssertEqual(processor.effects.last, .dismiss) } - - // MARK: Snapshots - - /// The import logins success page renders correctly. - @MainActor - func disabletest_snapshot_importLoginsSuccess() { - assertSnapshots( - of: subject.navStackWrapped, - as: [.defaultPortrait, .defaultPortraitDark, .tallPortraitAX5(heightMultiple: 3), .defaultLandscape], - ) - } } diff --git a/BitwardenShared/UI/Vault/Vault/AutofillList/VaultAutofillListViewTests.swift b/BitwardenShared/UI/Vault/Vault/AutofillList/VaultAutofillListView+SnapshotTests.swift similarity index 93% rename from BitwardenShared/UI/Vault/Vault/AutofillList/VaultAutofillListViewTests.swift rename to BitwardenShared/UI/Vault/Vault/AutofillList/VaultAutofillListView+SnapshotTests.swift index e1881c721..ef8516303 100644 --- a/BitwardenShared/UI/Vault/Vault/AutofillList/VaultAutofillListViewTests.swift +++ b/BitwardenShared/UI/Vault/Vault/AutofillList/VaultAutofillListView+SnapshotTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import BitwardenKitMocks import BitwardenResources import SnapshotTesting @@ -32,37 +33,6 @@ class VaultAutofillListViewTests: BitwardenTestCase { // swiftlint:disable:this timeProvider = nil } - // MARK: Tests - - /// Tapping the add item floating action button dispatches the `.addItemPressed` action.` - @MainActor - func test_addItemFloatingActionButton_tap() async throws { - let fab = try subject.inspect().find( - floatingActionButtonWithAccessibilityIdentifier: "AddItemFloatingActionButton", - ) - try await fab.tap() - XCTAssertEqual(processor.dispatchedActions.last, .addTapped(fromFAB: true)) - } - - /// Tapping the add an item button dispatches the `.addTapped` action. - @MainActor - func test_addItemButton_tap_fido2CreationFlowEmptyView() throws { - processor.state.isCreatingFido2Credential = true - processor.state.vaultListSections = [] - processor.state.emptyViewButtonText = Localizations.savePasskeyAsNewLogin - let button = try subject.inspect().find(button: Localizations.savePasskeyAsNewLogin) - try button.tap() - XCTAssertEqual(processor.dispatchedActions.last, .addTapped(fromFAB: false)) - } - - /// Tapping the cancel button dispatches the `.cancelTapped` action. - @MainActor - func test_cancelButton_tap() throws { - var button = try subject.inspect().findCancelToolbarButton() - try button.tap() - XCTAssertEqual(processor.dispatchedActions.last, .cancelTapped) - } - // MARK: Snapshots /// The empty view renders correctly. diff --git a/BitwardenShared/UI/Vault/Vault/AutofillList/VaultAutofillListView+ViewInspectorTests.swift b/BitwardenShared/UI/Vault/Vault/AutofillList/VaultAutofillListView+ViewInspectorTests.swift new file mode 100644 index 000000000..5e7933061 --- /dev/null +++ b/BitwardenShared/UI/Vault/Vault/AutofillList/VaultAutofillListView+ViewInspectorTests.swift @@ -0,0 +1,65 @@ +// swiftlint:disable:this file_name +import BitwardenKitMocks +import BitwardenResources +import XCTest + +@testable import BitwardenShared + +class VaultAutofillListViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: VaultAutofillListView! + var timeProvider: MockTimeProvider! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: VaultAutofillListState()) + let store = Store(processor: processor) + timeProvider = MockTimeProvider(.currentTime) + + subject = VaultAutofillListView(store: store, timeProvider: timeProvider) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + timeProvider = nil + } + + // MARK: Tests + + /// Tapping the add item floating action button dispatches the `.addItemPressed` action.` + @MainActor + func test_addItemFloatingActionButton_tap() async throws { + let fab = try subject.inspect().find( + floatingActionButtonWithAccessibilityIdentifier: "AddItemFloatingActionButton", + ) + try await fab.tap() + XCTAssertEqual(processor.dispatchedActions.last, .addTapped(fromFAB: true)) + } + + /// Tapping the add an item button dispatches the `.addTapped` action. + @MainActor + func test_addItemButton_tap_fido2CreationFlowEmptyView() throws { + processor.state.isCreatingFido2Credential = true + processor.state.vaultListSections = [] + processor.state.emptyViewButtonText = Localizations.savePasskeyAsNewLogin + let button = try subject.inspect().find(button: Localizations.savePasskeyAsNewLogin) + try button.tap() + XCTAssertEqual(processor.dispatchedActions.last, .addTapped(fromFAB: false)) + } + + /// Tapping the cancel button dispatches the `.cancelTapped` action. + @MainActor + func test_cancelButton_tap() throws { + let button = try subject.inspect().findCancelToolbarButton() + try button.tap() + XCTAssertEqual(processor.dispatchedActions.last, .cancelTapped) + } +} diff --git a/BitwardenShared/UI/Vault/Vault/TestHelpers/MockVaultCoordinatorDelegate.swift b/BitwardenShared/UI/Vault/Vault/TestHelpers/MockVaultCoordinatorDelegate.swift new file mode 100644 index 000000000..116644f6a --- /dev/null +++ b/BitwardenShared/UI/Vault/Vault/TestHelpers/MockVaultCoordinatorDelegate.swift @@ -0,0 +1,51 @@ +@testable import BitwardenShared + +class MockVaultCoordinatorDelegate: VaultCoordinatorDelegate { + var addAccountTapped = false + var accountTapped = [String]() + var hasManuallyLocked = false + var lockVaultId: String? + var logoutTapped = false + var logoutUserId: String? + var presentLoginRequestRequest: LoginRequest? + var switchAccountAuthCompletionRoute: AppRoute? + var switchAccountIsAutomatic = false + var switchAccountUserId: String? + var switchedAccounts = false + var switchToSettingsTabRoute: SettingsRoute? + var userInitiated: Bool? + + func lockVault(userId: String?, isManuallyLocking: Bool) { + lockVaultId = userId + hasManuallyLocked = isManuallyLocking + } + + func logout(userId: String?, userInitiated: Bool) { + self.userInitiated = userInitiated + logoutUserId = userId + logoutTapped = true + } + + func didTapAddAccount() { + addAccountTapped = true + } + + func didTapAccount(userId: String) { + accountTapped.append(userId) + } + + func presentLoginRequest(_ loginRequest: LoginRequest) { + presentLoginRequestRequest = loginRequest + } + + func switchAccount(userId: String, isAutomatic: Bool, authCompletionRoute: AppRoute?) { + switchAccountAuthCompletionRoute = authCompletionRoute + switchAccountIsAutomatic = isAutomatic + switchAccountUserId = userId + switchedAccounts = true + } + + func switchToSettingsTab(route: SettingsRoute) { + switchToSettingsTabRoute = route + } +} diff --git a/BitwardenShared/UI/Vault/Vault/VaultCoordinatorTests.swift b/BitwardenShared/UI/Vault/Vault/VaultCoordinatorTests.swift index d97736299..53ba7a6c3 100644 --- a/BitwardenShared/UI/Vault/Vault/VaultCoordinatorTests.swift +++ b/BitwardenShared/UI/Vault/Vault/VaultCoordinatorTests.swift @@ -416,54 +416,4 @@ class VaultCoordinatorTests: BitwardenTestCase { // swiftlint:disable:this type_ XCTAssertTrue(stackNavigator.actions.isEmpty) } -} - -class MockVaultCoordinatorDelegate: VaultCoordinatorDelegate { - var addAccountTapped = false - var accountTapped = [String]() - var hasManuallyLocked = false - var lockVaultId: String? - var logoutTapped = false - var logoutUserId: String? - var presentLoginRequestRequest: LoginRequest? - var switchAccountAuthCompletionRoute: AppRoute? - var switchAccountIsAutomatic = false - var switchAccountUserId: String? - var switchedAccounts = false - var switchToSettingsTabRoute: SettingsRoute? - var userInitiated: Bool? - - func lockVault(userId: String?, isManuallyLocking: Bool) { - lockVaultId = userId - hasManuallyLocked = isManuallyLocking - } - - func logout(userId: String?, userInitiated: Bool) { - self.userInitiated = userInitiated - logoutUserId = userId - logoutTapped = true - } - - func didTapAddAccount() { - addAccountTapped = true - } - - func didTapAccount(userId: String) { - accountTapped.append(userId) - } - - func presentLoginRequest(_ loginRequest: LoginRequest) { - presentLoginRequestRequest = loginRequest - } - - func switchAccount(userId: String, isAutomatic: Bool, authCompletionRoute: AppRoute?) { - switchAccountAuthCompletionRoute = authCompletionRoute - switchAccountIsAutomatic = isAutomatic - switchAccountUserId = userId - switchedAccounts = true - } - - func switchToSettingsTab(route: SettingsRoute) { - switchToSettingsTabRoute = route - } } // swiftlint:disable:this file_length diff --git a/BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupStateTests.swift b/BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupStateTests.swift index 97a508b7e..21fb84251 100644 --- a/BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupStateTests.swift +++ b/BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupStateTests.swift @@ -1,5 +1,3 @@ -import SnapshotTesting -import ViewInspector import XCTest @testable import BitwardenShared diff --git a/BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupViewTests.swift b/BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupView+SnapshotTests.swift similarity index 59% rename from BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupViewTests.swift rename to BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupView+SnapshotTests.swift index b2b6c35c4..87e1d5d3f 100644 --- a/BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupViewTests.swift +++ b/BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupView+SnapshotTests.swift @@ -1,14 +1,14 @@ +// swiftlint:disable:this file_name import BitwardenKitMocks import BitwardenResources import SnapshotTesting -import ViewInspector import XCTest @testable import BitwardenShared // MARK: - VaultGroupViewTests -class VaultGroupViewTests: BitwardenTestCase { // swiftlint:disable:this type_body_length +class VaultGroupViewTests: BitwardenTestCase { // MARK: Properties var processor: MockProcessor! @@ -39,117 +39,6 @@ class VaultGroupViewTests: BitwardenTestCase { // swiftlint:disable:this type_bo timeProvider = nil } - // MARK: Tests - - /// Tapping the add item button dispatches the `.addItemPressed` action. - @MainActor - func test_addItemEmptyStateButton_tap() throws { - processor.state.loadingState = .data([]) - let button = try subject.inspect().find(button: Localizations.newLogin) - try button.tap() - XCTAssertEqual(processor.dispatchedActions.last, .addItemPressed(nil)) - } - - /// Tapping an item in the add item menu dispatches the `.addItemPressed` action. - @MainActor - func test_addItemEmptyStateButton_hidden_restrictItemPolicy_enabled() throws { - processor.state.loadingState = .data([]) - processor.state.group = .card - processor.state.itemTypesUserCanCreate = [.login, .identity, .secureNote] - XCTAssertThrowsError(try subject.inspect().find(button: Localizations.newCard)) - } - - /// Add item floating action button is hidden when in card group and restrict item policy is enabled. - @MainActor - func test_addItemFloatingActionButton_hidden_restrictItemPolicy_enabled() async throws { - processor.state.loadingState = .data([]) - processor.state.group = .card - processor.state.itemTypesUserCanCreate = [.login, .identity, .secureNote] - - XCTAssertThrowsError( - try subject.inspect().find( - floatingActionButtonWithAccessibilityIdentifier: "AddItemFloatingActionButton", - ), - ) - } - - /// Tapping an item in the add item menu dispatches the `.addItemPressed` action. - @MainActor - func test_addItemMenuEmptyState_tap() throws { - processor.state.loadingState = .data([]) - processor.state.group = .folder(id: "1", name: "Folder") - let button = try subject.inspect() - .find(viewWithAccessibilityIdentifier: "AddItemButton") - .find(button: Localizations.typeSecureNote) - try button.tap() - XCTAssertEqual(processor.dispatchedActions.last, .addItemPressed(.secureNote)) - } - - /// Tapping the add item floating action button dispatches the `.addItemPressed` action.` - @MainActor - func test_addItemFloatingActionButton_tap() async throws { - let fab = try subject.inspect().find( - floatingActionButtonWithAccessibilityIdentifier: "AddItemFloatingActionButton", - ) - try await fab.tap() - XCTAssertEqual(processor.dispatchedActions.last, .addItemPressed(nil)) - } - - /// Tapping the add item floating action menu dispatches the `.addItemPressed` action.` - @MainActor - func test_addItemFloatingActionMenu_tap() throws { - processor.state.group = .folder(id: "1", name: "Folder") - let button = try subject.inspect().find(button: Localizations.typeCard) - try button.tap() - XCTAssertEqual(processor.dispatchedActions.last, .addItemPressed(.card)) - } - - /// Tapping a vault item dispatches the `.itemPressed` action. - @MainActor - func test_vaultItem_tap() throws { - let item = VaultListItem.fixture(cipherListView: .fixture(name: "Item")) - let section = VaultListSection(id: "Items", items: [item], name: Localizations.items) - processor.state.loadingState = .data([section]) - let button = try subject.inspect().find(button: "Item") - try button.tap() - XCTAssertEqual(processor.dispatchedActions.last, .itemPressed(item)) - } - - /// Tapping the vault item copy totp button dispatches the `.copyTOTPCode` action. - @MainActor - func test_vaultItem_copyTOTPButton_tap() throws { - processor.state.loadingState = .data( - [ - VaultListSection( - id: "Items", - items: [ - .fixtureTOTP( - totp: .fixture( - timeProvider: timeProvider, - ), - ), - ], - name: Localizations.items, - ), - ], - ) - let button = try subject.inspect().find(buttonWithAccessibilityLabel: Localizations.copyTotp) - try button.tap() - waitFor(!processor.dispatchedActions.isEmpty) - XCTAssertEqual(processor.dispatchedActions.last, .copyTOTPCode("123456")) - } - - /// Tapping the more button on a vault item dispatches the `.morePressed` action. - @MainActor - func test_vaultItem_moreButton_tap() async throws { - let item = VaultListItem.fixture() - let section = VaultListSection(id: "Items", items: [item], name: Localizations.items) - processor.state.loadingState = .data([section]) - let button = try subject.inspect().find(asyncButtonWithAccessibilityLabel: Localizations.more) - try await button.tap() - XCTAssertEqual(processor.effects.last, .morePressed(item)) - } - // MARK: Snapshots @MainActor diff --git a/BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupView+ViewInspectorTests.swift b/BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupView+ViewInspectorTests.swift new file mode 100644 index 000000000..9c5720998 --- /dev/null +++ b/BitwardenShared/UI/Vault/Vault/VaultGroup/VaultGroupView+ViewInspectorTests.swift @@ -0,0 +1,152 @@ +// swiftlint:disable:this file_name +import BitwardenKitMocks +import BitwardenResources +import ViewInspector +import XCTest + +@testable import BitwardenShared + +// MARK: - VaultGroupViewTests + +class VaultGroupViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: VaultGroupView! + var timeProvider: MockTimeProvider! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + processor = MockProcessor( + state: VaultGroupState( + searchVaultFilterType: .allVaults, + vaultFilterType: .allVaults, + ), + ) + timeProvider = MockTimeProvider(.mockTime(Date(year: 2023, month: 12, day: 31))) + subject = VaultGroupView( + store: Store(processor: processor), + timeProvider: timeProvider, + ) + } + + override func tearDown() { + super.tearDown() + processor = nil + subject = nil + timeProvider = nil + } + + // MARK: Tests + + /// Tapping the add item button dispatches the `.addItemPressed` action. + @MainActor + func test_addItemEmptyStateButton_tap() throws { + processor.state.loadingState = .data([]) + let button = try subject.inspect().find(button: Localizations.newLogin) + try button.tap() + XCTAssertEqual(processor.dispatchedActions.last, .addItemPressed(nil)) + } + + /// Tapping an item in the add item menu dispatches the `.addItemPressed` action. + @MainActor + func test_addItemEmptyStateButton_hidden_restrictItemPolicy_enabled() throws { + processor.state.loadingState = .data([]) + processor.state.group = .card + processor.state.itemTypesUserCanCreate = [.login, .identity, .secureNote] + XCTAssertThrowsError(try subject.inspect().find(button: Localizations.newCard)) + } + + /// Add item floating action button is hidden when in card group and restrict item policy is enabled. + @MainActor + func test_addItemFloatingActionButton_hidden_restrictItemPolicy_enabled() async throws { + processor.state.loadingState = .data([]) + processor.state.group = .card + processor.state.itemTypesUserCanCreate = [.login, .identity, .secureNote] + + XCTAssertThrowsError( + try subject.inspect().find( + floatingActionButtonWithAccessibilityIdentifier: "AddItemFloatingActionButton", + ), + ) + } + + /// Tapping an item in the add item menu dispatches the `.addItemPressed` action. + @MainActor + func test_addItemMenuEmptyState_tap() throws { + processor.state.loadingState = .data([]) + processor.state.group = .folder(id: "1", name: "Folder") + let button = try subject.inspect() + .find(viewWithAccessibilityIdentifier: "AddItemButton") + .find(button: Localizations.typeSecureNote) + try button.tap() + XCTAssertEqual(processor.dispatchedActions.last, .addItemPressed(.secureNote)) + } + + /// Tapping the add item floating action button dispatches the `.addItemPressed` action.` + @MainActor + func test_addItemFloatingActionButton_tap() async throws { + let fab = try subject.inspect().find( + floatingActionButtonWithAccessibilityIdentifier: "AddItemFloatingActionButton", + ) + try await fab.tap() + XCTAssertEqual(processor.dispatchedActions.last, .addItemPressed(nil)) + } + + /// Tapping the add item floating action menu dispatches the `.addItemPressed` action.` + @MainActor + func test_addItemFloatingActionMenu_tap() throws { + processor.state.group = .folder(id: "1", name: "Folder") + let button = try subject.inspect().find(button: Localizations.typeCard) + try button.tap() + XCTAssertEqual(processor.dispatchedActions.last, .addItemPressed(.card)) + } + + /// Tapping a vault item dispatches the `.itemPressed` action. + @MainActor + func test_vaultItem_tap() throws { + let item = VaultListItem.fixture(cipherListView: .fixture(name: "Item")) + let section = VaultListSection(id: "Items", items: [item], name: Localizations.items) + processor.state.loadingState = .data([section]) + let button = try subject.inspect().find(button: "Item") + try button.tap() + XCTAssertEqual(processor.dispatchedActions.last, .itemPressed(item)) + } + + /// Tapping the vault item copy totp button dispatches the `.copyTOTPCode` action. + @MainActor + func test_vaultItem_copyTOTPButton_tap() throws { + processor.state.loadingState = .data( + [ + VaultListSection( + id: "Items", + items: [ + .fixtureTOTP( + totp: .fixture( + timeProvider: timeProvider, + ), + ), + ], + name: Localizations.items, + ), + ], + ) + let button = try subject.inspect().find(buttonWithAccessibilityLabel: Localizations.copyTotp) + try button.tap() + waitFor(!processor.dispatchedActions.isEmpty) + XCTAssertEqual(processor.dispatchedActions.last, .copyTOTPCode("123456")) + } + + /// Tapping the more button on a vault item dispatches the `.morePressed` action. + @MainActor + func test_vaultItem_moreButton_tap() async throws { + let item = VaultListItem.fixture() + let section = VaultListSection(id: "Items", items: [item], name: Localizations.items) + processor.state.loadingState = .data([section]) + let button = try subject.inspect().find(asyncButtonWithAccessibilityLabel: Localizations.more) + try await button.tap() + XCTAssertEqual(processor.effects.last, .morePressed(item)) + } +} diff --git a/BitwardenShared/UI/Vault/Vault/VaultItemSelection/VaultItemSelectionViewTests.swift b/BitwardenShared/UI/Vault/Vault/VaultItemSelection/VaultItemSelectionView+SnapshotTests.swift similarity index 81% rename from BitwardenShared/UI/Vault/Vault/VaultItemSelection/VaultItemSelectionViewTests.swift rename to BitwardenShared/UI/Vault/Vault/VaultItemSelection/VaultItemSelectionView+SnapshotTests.swift index 2624d1d55..429246e4b 100644 --- a/BitwardenShared/UI/Vault/Vault/VaultItemSelection/VaultItemSelectionViewTests.swift +++ b/BitwardenShared/UI/Vault/Vault/VaultItemSelection/VaultItemSelectionView+SnapshotTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import BitwardenResources import BitwardenSdk import SnapshotTesting @@ -32,34 +33,6 @@ class VaultItemSelectionViewTests: BitwardenTestCase { subject = nil } - // MARK: Tests - - /// Tapping the add item floating action button dispatches the `.addTapped` action.` - @MainActor - func test_addFloatingActionButton_tap() async throws { - let fab = try subject.inspect().find( - floatingActionButtonWithAccessibilityIdentifier: "AddItemFloatingActionButton", - ) - try await fab.tap() - XCTAssertEqual(processor.dispatchedActions.last, .addTapped) - } - - /// Tapping the cancel button dispatches the `.cancelTapped` action. - @MainActor - func test_cancelButton_tap() throws { - var button = try subject.inspect().findCancelToolbarButton() - try button.tap() - XCTAssertEqual(processor.dispatchedActions.last, .cancelTapped) - } - - /// In the empty state, tapping the add item button dispatches the `.addTapped` action. - @MainActor - func test_emptyState_addItemTapped() throws { - let button = try subject.inspect().find(button: Localizations.newItem) - try button.tap() - XCTAssertEqual(processor.dispatchedActions.last, .addTapped) - } - // MARK: Snapshots /// The empty view renders correctly. diff --git a/BitwardenShared/UI/Vault/Vault/VaultItemSelection/VaultItemSelectionView+ViewInspectorTests.swift b/BitwardenShared/UI/Vault/Vault/VaultItemSelection/VaultItemSelectionView+ViewInspectorTests.swift new file mode 100644 index 000000000..f51c8c07b --- /dev/null +++ b/BitwardenShared/UI/Vault/Vault/VaultItemSelection/VaultItemSelectionView+ViewInspectorTests.swift @@ -0,0 +1,62 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import BitwardenSdk +import XCTest + +@testable import BitwardenShared + +class VaultItemSelectionViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: VaultItemSelectionView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: VaultItemSelectionState( + iconBaseURL: nil, + totpKeyModel: .fixtureExample, + )) + let store = Store(processor: processor) + + subject = VaultItemSelectionView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Tests + + /// Tapping the add item floating action button dispatches the `.addTapped` action.` + @MainActor + func test_addFloatingActionButton_tap() async throws { + let fab = try subject.inspect().find( + floatingActionButtonWithAccessibilityIdentifier: "AddItemFloatingActionButton", + ) + try await fab.tap() + XCTAssertEqual(processor.dispatchedActions.last, .addTapped) + } + + /// Tapping the cancel button dispatches the `.cancelTapped` action. + @MainActor + func test_cancelButton_tap() throws { + let button = try subject.inspect().findCancelToolbarButton() + try button.tap() + XCTAssertEqual(processor.dispatchedActions.last, .cancelTapped) + } + + /// In the empty state, tapping the add item button dispatches the `.addTapped` action. + @MainActor + func test_emptyState_addItemTapped() throws { + let button = try subject.inspect().find(button: Localizations.newItem) + try button.tap() + XCTAssertEqual(processor.dispatchedActions.last, .addTapped) + } +} diff --git a/BitwardenShared/UI/Vault/Vault/VaultList/SearchVaultFilterRowView/SearchVaultFilterRowViewTests.swift b/BitwardenShared/UI/Vault/Vault/VaultList/SearchVaultFilterRowView/SearchVaultFilterRowView+ViewInspectorTests.swift similarity index 97% rename from BitwardenShared/UI/Vault/Vault/VaultList/SearchVaultFilterRowView/SearchVaultFilterRowViewTests.swift rename to BitwardenShared/UI/Vault/Vault/VaultList/SearchVaultFilterRowView/SearchVaultFilterRowView+ViewInspectorTests.swift index 63545b8e7..1dafd9f16 100644 --- a/BitwardenShared/UI/Vault/Vault/VaultList/SearchVaultFilterRowView/SearchVaultFilterRowViewTests.swift +++ b/BitwardenShared/UI/Vault/Vault/VaultList/SearchVaultFilterRowView/SearchVaultFilterRowView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenSdk -import SnapshotTesting import SwiftUI import ViewInspector import XCTest diff --git a/BitwardenShared/UI/Vault/Vault/VaultList/VaultListView+SnapshotTests.swift b/BitwardenShared/UI/Vault/Vault/VaultList/VaultListView+SnapshotTests.swift new file mode 100644 index 000000000..af09528ac --- /dev/null +++ b/BitwardenShared/UI/Vault/Vault/VaultList/VaultListView+SnapshotTests.swift @@ -0,0 +1,205 @@ +// swiftlint:disable:this file_name +import BitwardenKitMocks +import BitwardenResources +import BitwardenSdk +import SnapshotTesting +import SwiftUI +import XCTest + +@testable import BitwardenShared + +// MARK: - VaultListViewTests + +class VaultListViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: VaultListView! + var timeProvider: MockTimeProvider! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + let account = ProfileSwitcherItem.fixture( + email: "anne.account@bitwarden.com", + userInitials: "AA", + ) + let state = VaultListState( + profileSwitcherState: ProfileSwitcherState( + accounts: [account], + activeAccountId: account.userId, + allowLockAndLogout: true, + isVisible: false, + ), + ) + processor = MockProcessor(state: state) + timeProvider = MockTimeProvider(.mockTime(Date(year: 2023, month: 12, day: 31))) + subject = VaultListView( + store: Store(processor: processor), + timeProvider: timeProvider, + ) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + timeProvider = nil + } + + // MARK: Snapshots + + @MainActor + func disabletest_snapshot_empty() { + processor.state.profileSwitcherState.isVisible = false + processor.state.loadingState = .data([]) + + assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultLandscape]) + } + + @MainActor + func disabletest_snapshot_empty_singleAccountProfileSwitcher() { + processor.state.profileSwitcherState.isVisible = true + processor.state.loadingState = .data([]) + + assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark]) + } + + @MainActor + func disabletest_snapshot_errorState() { + processor.state.loadingState = .error( + errorMessage: Localizations.weAreUnableToProcessYourRequestPleaseTryAgainOrContactUs, + ) + assertSnapshot(of: subject, as: .defaultPortrait) + } + + @MainActor + func disabletest_snapshot_flightRecorderToastBanner() { + processor.state.loadingState = .data([]) + processor.state.isFlightRecorderToastBannerVisible = true + processor.state.activeFlightRecorderLog = FlightRecorderData.LogMetadata( + duration: .twentyFourHours, + startDate: Date(year: 2025, month: 4, day: 3), + ) + assertSnapshot(of: subject, as: .defaultPortrait) + } + + @MainActor + func disabletest_snapshot_loading() { + processor.state.loadingState = .loading(nil) + assertSnapshot(of: subject, as: .defaultPortrait) + } + + @MainActor + func disabletest_snapshot_myVault() { + processor.state.loadingState = .data([ + VaultListSection( + id: "", + items: [ + .fixture(cipherListView: .fixture( + login: .fixture(username: "email@example.com"), + name: "Example", + subtitle: "email@example.com", + )), + .fixture(cipherListView: .fixture(id: "12", name: "Example", type: .secureNote)), + .fixture(cipherListView: .fixture( + id: "13", + organizationId: "1", + login: .fixture(username: "user@bitwarden.com"), + name: "Bitwarden", + subtitle: "user@bitwarden.com", + attachments: 1, + )), + ], + name: "Favorites", + ), + VaultListSection( + id: "2", + items: [ + VaultListItem( + id: "21", + itemType: .group(.login, 123), + ), + VaultListItem( + id: "22", + itemType: .group(.card, 25), + ), + VaultListItem( + id: "23", + itemType: .group(.identity, 1), + ), + VaultListItem( + id: "24", + itemType: .group(.secureNote, 0), + ), + ], + name: "Types", + ), + ]) + assertSnapshots( + of: subject, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } + + @MainActor + func disabletest_snapshot_withSearchResult() { + processor.state.searchText = "Exam" + processor.state.searchResults = [ + .fixture(cipherListView: .fixture( + login: .fixture(username: "email@example.com"), + name: "Example", + )), + ] + assertSnapshot(of: subject, as: .defaultPortrait) + } + + @MainActor + func disabletest_snapshot_withMultipleSearchResults() { + processor.state.searchText = "Exam" + processor.state.searchResults = [ + .fixture(cipherListView: .fixture( + id: "1", + login: .fixture(username: "email@example.com"), + name: "Example", + )), + .fixture(cipherListView: .fixture( + id: "2", + login: .fixture(username: "email@example.com"), + name: "Example", + )), + .fixture(cipherListView: .fixture( + id: "3", + login: .fixture(username: "email@example.com"), + name: "Example", + )), + .fixture(cipherListView: .fixture( + id: "4", + login: .fixture(username: "email@example.com"), + name: "Example", + )), + ] + assertSnapshot(of: subject, as: .defaultPortrait) + } + + @MainActor + func disabletest_snapshot_withoutSearchResult() { + processor.state.searchText = "Exam" + processor.state.searchResults = [] + assertSnapshot(of: subject, as: .defaultPortrait) + } + + /// Test a snapshot of the VaultListView previews. + @MainActor + func disabletest_snapshot_vaultListView_previews() { + for preview in VaultListView_Previews._allPreviews { + assertSnapshots( + of: preview.content, + as: [.defaultPortrait], + ) + } + } +} diff --git a/BitwardenShared/UI/Vault/Vault/VaultList/VaultListViewTests.swift b/BitwardenShared/UI/Vault/Vault/VaultList/VaultListView+ViewInspectorTests.swift similarity index 69% rename from BitwardenShared/UI/Vault/Vault/VaultList/VaultListViewTests.swift rename to BitwardenShared/UI/Vault/Vault/VaultList/VaultListView+ViewInspectorTests.swift index 835d2137a..66bc76864 100644 --- a/BitwardenShared/UI/Vault/Vault/VaultList/VaultListViewTests.swift +++ b/BitwardenShared/UI/Vault/Vault/VaultList/VaultListView+ViewInspectorTests.swift @@ -1,18 +1,16 @@ +// swiftlint:disable:this file_name import BitwardenKitMocks import BitwardenResources import BitwardenSdk -import SnapshotTesting import SwiftUI import ViewInspector import XCTest @testable import BitwardenShared -// swiftlint:disable file_length - // MARK: - VaultListViewTests -class VaultListViewTests: BitwardenTestCase { // swiftlint:disable:this type_body_length +class VaultListViewTests: BitwardenTestCase { // MARK: Properties var processor: MockProcessor! @@ -282,157 +280,4 @@ class VaultListViewTests: BitwardenTestCase { // swiftlint:disable:this type_bod try await button.tap() XCTAssertEqual(processor.effects.last, .morePressed(item)) } - - // MARK: Snapshots - - @MainActor - func disabletest_snapshot_empty() { - processor.state.profileSwitcherState.isVisible = false - processor.state.loadingState = .data([]) - - assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark, .defaultLandscape]) - } - - @MainActor - func disabletest_snapshot_empty_singleAccountProfileSwitcher() { - processor.state.profileSwitcherState.isVisible = true - processor.state.loadingState = .data([]) - - assertSnapshots(of: subject, as: [.defaultPortrait, .defaultPortraitDark]) - } - - @MainActor - func disabletest_snapshot_errorState() { - processor.state.loadingState = .error( - errorMessage: Localizations.weAreUnableToProcessYourRequestPleaseTryAgainOrContactUs, - ) - assertSnapshot(of: subject, as: .defaultPortrait) - } - - @MainActor - func disabletest_snapshot_flightRecorderToastBanner() { - processor.state.loadingState = .data([]) - processor.state.isFlightRecorderToastBannerVisible = true - processor.state.activeFlightRecorderLog = FlightRecorderData.LogMetadata( - duration: .twentyFourHours, - startDate: Date(year: 2025, month: 4, day: 3), - ) - assertSnapshot(of: subject, as: .defaultPortrait) - } - - @MainActor - func disabletest_snapshot_loading() { - processor.state.loadingState = .loading(nil) - assertSnapshot(of: subject, as: .defaultPortrait) - } - - @MainActor - func disabletest_snapshot_myVault() { - processor.state.loadingState = .data([ - VaultListSection( - id: "", - items: [ - .fixture(cipherListView: .fixture( - login: .fixture(username: "email@example.com"), - name: "Example", - subtitle: "email@example.com", - )), - .fixture(cipherListView: .fixture(id: "12", name: "Example", type: .secureNote)), - .fixture(cipherListView: .fixture( - id: "13", - organizationId: "1", - login: .fixture(username: "user@bitwarden.com"), - name: "Bitwarden", - subtitle: "user@bitwarden.com", - attachments: 1, - )), - ], - name: "Favorites", - ), - VaultListSection( - id: "2", - items: [ - VaultListItem( - id: "21", - itemType: .group(.login, 123), - ), - VaultListItem( - id: "22", - itemType: .group(.card, 25), - ), - VaultListItem( - id: "23", - itemType: .group(.identity, 1), - ), - VaultListItem( - id: "24", - itemType: .group(.secureNote, 0), - ), - ], - name: "Types", - ), - ]) - assertSnapshots( - of: subject, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } - - @MainActor - func disabletest_snapshot_withSearchResult() { - processor.state.searchText = "Exam" - processor.state.searchResults = [ - .fixture(cipherListView: .fixture( - login: .fixture(username: "email@example.com"), - name: "Example", - )), - ] - assertSnapshot(of: subject, as: .defaultPortrait) - } - - @MainActor - func disabletest_snapshot_withMultipleSearchResults() { - processor.state.searchText = "Exam" - processor.state.searchResults = [ - .fixture(cipherListView: .fixture( - id: "1", - login: .fixture(username: "email@example.com"), - name: "Example", - )), - .fixture(cipherListView: .fixture( - id: "2", - login: .fixture(username: "email@example.com"), - name: "Example", - )), - .fixture(cipherListView: .fixture( - id: "3", - login: .fixture(username: "email@example.com"), - name: "Example", - )), - .fixture(cipherListView: .fixture( - id: "4", - login: .fixture(username: "email@example.com"), - name: "Example", - )), - ] - assertSnapshot(of: subject, as: .defaultPortrait) - } - - @MainActor - func disabletest_snapshot_withoutSearchResult() { - processor.state.searchText = "Exam" - processor.state.searchResults = [] - assertSnapshot(of: subject, as: .defaultPortrait) - } - - /// Test a snapshot of the VaultListView previews. - @MainActor - func disabletest_snapshot_vaultListView_previews() { - for preview in VaultListView_Previews._allPreviews { - assertSnapshots( - of: preview.content, - as: [.defaultPortrait], - ) - } - } } diff --git a/BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditCardItem/AddEditCardItemViewTests.swift b/BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditCardItem/AddEditCardItemView+SnapshotTests.swift similarity index 94% rename from BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditCardItem/AddEditCardItemViewTests.swift rename to BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditCardItem/AddEditCardItemView+SnapshotTests.swift index 908a07d17..8992e4c5a 100644 --- a/BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditCardItem/AddEditCardItemViewTests.swift +++ b/BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditCardItem/AddEditCardItemView+SnapshotTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import SnapshotTesting import XCTest diff --git a/BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditCustomFields/AddEditCustomFieldsView+SnapshotTests.swift b/BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditCustomFields/AddEditCustomFieldsView+SnapshotTests.swift new file mode 100644 index 000000000..098db902b --- /dev/null +++ b/BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditCustomFields/AddEditCustomFieldsView+SnapshotTests.swift @@ -0,0 +1,54 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import BitwardenSdk +import SnapshotTesting +import SwiftUI +import XCTest + +@testable import BitwardenShared + +// MARK: - AddEditCustomFieldsViewTests + +class AddEditCustomFieldsViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: AddEditCustomFieldsView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + processor = MockProcessor( + state: .init( + cipherType: .login, + customFields: [.init(name: "custom1", type: .text)], + ), + ) + let store = Store(processor: processor) + subject = AddEditCustomFieldsView(store: store) + } + + override func tearDown() { + super.tearDown() + processor = nil + subject = nil + } + + // MARK: Tests + + /// The view with all types of custom fields renders correctly. + @MainActor + func disabletest_snapshot_allFields() { + for preview in AddEditCustomFieldsView_Previews._allPreviews { + assertSnapshots( + of: preview.content, + as: [ + .defaultPortrait, + .defaultPortraitDark, + .defaultPortraitAX5, + ], + ) + } + } +} diff --git a/BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditCustomFields/AddEditCustomFieldsViewTests.swift b/BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditCustomFields/AddEditCustomFieldsView+ViewInspectorTests.swift similarity index 84% rename from BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditCustomFields/AddEditCustomFieldsViewTests.swift rename to BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditCustomFields/AddEditCustomFieldsView+ViewInspectorTests.swift index 73304a2cc..b0d36b5a4 100644 --- a/BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditCustomFields/AddEditCustomFieldsViewTests.swift +++ b/BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditCustomFields/AddEditCustomFieldsView+ViewInspectorTests.swift @@ -1,6 +1,6 @@ +// swiftlint:disable:this file_name import BitwardenResources import BitwardenSdk -import SnapshotTesting import SwiftUI import ViewInspector import XCTest @@ -76,19 +76,4 @@ class AddEditCustomFieldsViewTests: BitwardenTestCase { try button.tap() XCTAssertEqual(processor.dispatchedActions.last, .removeCustomFieldPressed(index: 0)) } - - /// The view with all types of custom fields renders correctly. - @MainActor - func disabletest_snapshot_allFields() { - for preview in AddEditCustomFieldsView_Previews._allPreviews { - assertSnapshots( - of: preview.content, - as: [ - .defaultPortrait, - .defaultPortraitDark, - .defaultPortraitAX5, - ], - ) - } - } } diff --git a/BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditItemView+SnapshotTests.swift b/BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditItemView+SnapshotTests.swift new file mode 100644 index 000000000..464b44233 --- /dev/null +++ b/BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditItemView+SnapshotTests.swift @@ -0,0 +1,489 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import BitwardenSdk +import SnapshotTesting +import SwiftUI +import XCTest + +@testable import BitwardenShared + +// MARK: - AddEditItemViewTests + +class AddEditItemViewTests: BitwardenTestCase { // swiftlint:disable:this type_body_length + // MARK: Properties + + var processor: MockProcessor! + var subject: AddEditItemView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + processor = MockProcessor( + state: CipherItemState( + hasPremium: true, + ), + ) + processor.state.ownershipOptions = [.personal(email: "user@bitwarden.com")] + let store = Store(processor: processor) + subject = AddEditItemView(store: store) + } + + override func tearDown() { + super.tearDown() + processor = nil + subject = nil + } + + // MARK: Snapshots + + @MainActor + func disabletest_snapshot_add_empty() { + assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) + } + + /// Tests the snapshot with the add state with the learn new login action card. + @MainActor + func disabletest_snapshot_learnNewLoginActionCard() throws { + processor.state = CipherItemState( + hasPremium: false, + ) + processor.state.isLearnNewLoginActionCardEligible = true + assertSnapshots( + of: subject, + as: [.defaultPortrait, .defaultPortraitDark], + ) + } + + /// Tests the add state with identity item empty. + @MainActor + func disabletest_snapshot_add_identity_full_fieldsEmpty() { + processor.state.type = .identity + processor.state.name = "" + processor.state.identityState = .init() + processor.state.isAdditionalOptionsExpanded = true + processor.state.isFavoriteOn = false + processor.state.isMasterPasswordRePromptOn = false + processor.state.notes = "" + processor.state.folderId = nil + + assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait2) + } + + /// Tests the add state with identity item filled. + @MainActor + func disabletest_snapshot_add_identity_full_fieldsFilled() { + processor.state.type = .identity + processor.state.name = "my identity" + processor.state.identityState = .fixture( + title: .custom(.dr), + firstName: "First", + lastName: "Last", + middleName: "Middle", + userName: "userName", + company: "Company name", + socialSecurityNumber: "12-345-6789", + passportNumber: "passport #", + licenseNumber: "license #", + email: "hello@email.com", + phone: "(123) 456-7890", + address1: "123 street", + address2: "address2", + address3: "address3", + cityOrTown: "City", + state: "State", + postalCode: "1234", + country: "country", + ) + processor.state.isAdditionalOptionsExpanded = true + processor.state.isFavoriteOn = true + processor.state.isMasterPasswordRePromptOn = true + processor.state.notes = "A long segment of notes that proves that the multiline feature is working." + processor.state.folderId = "1" + processor.state.folders = [.custom(.fixture(id: "1", name: "Folder"))] + + assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait2) + } + + /// Tests the add state with identity item filled with large text. + @MainActor + func disabletest_snapshot_add_identity_full_fieldsFilled_largeText() { + processor.state.type = .identity + processor.state.name = "my identity" + processor.state.identityState = .fixture( + title: .custom(.dr), + firstName: "First", + lastName: "Last", + middleName: "Middle", + userName: "userName", + company: "Company name", + socialSecurityNumber: "12-345-6789", + passportNumber: "passport #", + licenseNumber: "license #", + email: "hello@email.com", + phone: "(123) 456-7890", + address1: "123 street", + address2: "address2", + address3: "address3", + cityOrTown: "City", + state: "State", + postalCode: "1234", + country: "country", + ) + processor.state.isAdditionalOptionsExpanded = true + processor.state.isFavoriteOn = true + processor.state.isMasterPasswordRePromptOn = true + processor.state.notes = "Notes" + processor.state.folderId = "1" + processor.state.folders = [.custom(.fixture(id: "1", name: "Folder"))] + + assertSnapshot(of: subject.navStackWrapped, as: .tallPortraitAX5(heightMultiple: 7)) + } + + /// Tests the add state with the password field not visible. + @MainActor + func disabletest_snapshot_add_login_full_fieldsNotVisible() { + processor.state.type = .login + processor.state.name = "Name" + processor.state.loginState = .fixture( + password: "password1!", + uris: [ + .init(uri: URL.example.absoluteString), + ], + username: "username", + ) + processor.state.isAdditionalOptionsExpanded = true + processor.state.isFavoriteOn = true + processor.state.isMasterPasswordRePromptOn = true + processor.state.loginState.uris = [ + UriState(id: "id", matchType: .default, uri: URL.example.absoluteString), + ] + processor.state.notes = "Notes" + processor.state.folderId = "1" + processor.state.folders = [.custom(.fixture(id: "1", name: "Folder"))] + + assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) + } + + /// Tests the add state with all fields. + @MainActor + func disabletest_snapshot_add_login_full_fieldsVisible() { + processor.state.type = .login + processor.state.name = "Name" + processor.state.loginState.username = "username" + processor.state.loginState.password = "password1!" + processor.state.isAdditionalOptionsExpanded = true + processor.state.isFavoriteOn = true + processor.state.isMasterPasswordRePromptOn = true + processor.state.loginState.uris = [ + UriState(id: "id", matchType: .default, uri: URL.example.absoluteString), + ] + processor.state.notes = "Notes" + processor.state.folderId = "1" + processor.state.folders = [.custom(.fixture(id: "1", name: "Folder"))] + + processor.state.loginState.isPasswordVisible = true + + assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) + } + + @MainActor + func disabletest_snapshot_add_login_collections() { + processor.state.allUserCollections = [ + .fixture(id: "1", name: "Design", organizationId: "1"), + .fixture(id: "2", name: "Engineering", organizationId: "1"), + ] + processor.state.ownershipOptions.append(.organization(id: "1", name: "Organization")) + processor.state.owner = .organization(id: "1", name: "Organization") + processor.state.collectionIds = ["2"] + + assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) + } + + @MainActor + func disabletest_snapshot_add_login_collectionsNone() { + processor.state.ownershipOptions.append(.organization(id: "1", name: "Organization")) + processor.state.owner = .organization(id: "1", name: "Organization") + + assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) + } + + @MainActor + func disabletest_snapshot_edit_full_fieldsNotVisible() { + processor.state = CipherItemState( + existing: CipherView.loginFixture(), + hasPremium: true, + )! + processor.state.loginState = .fixture( + fido2Credentials: [.fixture()], + isPasswordVisible: false, + password: "password1!", + uris: [ + .init(uri: URL.example.absoluteString), + ], + username: "username", + ) + processor.state.type = .login + processor.state.name = "Name" + processor.state.isAdditionalOptionsExpanded = true + processor.state.isFavoriteOn = true + processor.state.isMasterPasswordRePromptOn = true + processor.state.notes = "Notes" + processor.state.folderId = "1" + processor.state.folders = [.custom(.fixture(id: "1", name: "Folder"))] + processor.state.ownershipOptions = [.personal(email: "user@bitwarden.com")] + + assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) + } + + @MainActor + func disabletest_snapshot_edit_full_readOnly() { + processor.state = CipherItemState( + existing: CipherView.loginFixture(edit: false), + hasPremium: true, + )! + processor.state.loginState = .fixture( + fido2Credentials: [.fixture()], + isPasswordVisible: false, + password: "password1!", + uris: [ + .init(uri: URL.example.absoluteString), + ], + username: "username", + ) + processor.state.type = .login + processor.state.name = "Name" + processor.state.isAdditionalOptionsExpanded = true + processor.state.isFavoriteOn = true + processor.state.isMasterPasswordRePromptOn = true + processor.state.notes = "Notes" + processor.state.folderId = "1" + processor.state.folders = [.custom(.fixture(id: "1", name: "Folder"))] + processor.state.ownershipOptions = [.personal(email: "user@bitwarden.com")] + + assertSnapshots( + of: subject.navStackWrapped, + as: [ + .tallPortrait, + .portraitDark(heightMultiple: 2), + ], + ) + } + + @MainActor + func disabletest_snapshot_add_personalOwnershipPolicy() { + processor.state.ownershipOptions.append(.organization(id: "1", name: "Organization")) + processor.state.owner = .organization(id: "1", name: "Organization") + processor.state.isPersonalOwnershipDisabled = true + processor.state.allUserCollections = [ + .fixture(id: "1", name: "Default collection", organizationId: "1"), + ] + assertSnapshot(of: subject.navStackWrapped, as: .defaultPortrait) + } + + @MainActor + func disabletest_snapshot_add_secureNote_full_fieldsVisible() { + processor.state.type = .secureNote + processor.state.name = "Secure Note Name" + processor.state.isAdditionalOptionsExpanded = true + processor.state.isFavoriteOn = true + processor.state.isMasterPasswordRePromptOn = true + processor.state.notes = "Notes" + processor.state.folderId = "1" + processor.state.folders = [.custom(.fixture(id: "1", name: "Folder"))] + + assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) + } + + @MainActor + func disabletest_snapshot_edit_full_disabledViewPassword() { + processor.state = CipherItemState( + existing: CipherView.loginFixture(), + hasPremium: true, + )! + processor.state.loginState = .fixture( + canViewPassword: false, + fido2Credentials: [.fixture()], + isPasswordVisible: false, + password: "password1!", + uris: [ + .init(uri: URL.example.absoluteString), + ], + username: "username", + ) + processor.state.type = .login + processor.state.name = "Name" + processor.state.isAdditionalOptionsExpanded = true + processor.state.isFavoriteOn = true + processor.state.isMasterPasswordRePromptOn = true + processor.state.notes = "Notes" + processor.state.folderId = "1" + processor.state.folders = [.custom(.fixture(id: "1", name: "Folder"))] + processor.state.ownershipOptions = [.personal(email: "user@bitwarden.com")] + + assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) + } + + @MainActor + func disabletest_snapshot_edit_full_fieldsNotVisible_largeText() { + processor.state = CipherItemState( + existing: CipherView.loginFixture(), + hasPremium: true, + )! + processor.state.loginState = .fixture( + fido2Credentials: [.fixture()], + isPasswordVisible: false, + password: "password1!", + uris: [ + .init(uri: URL.example.absoluteString), + ], + username: "username", + ) + processor.state.type = .login + processor.state.name = "Name" + processor.state.isAdditionalOptionsExpanded = true + processor.state.isFavoriteOn = true + processor.state.isMasterPasswordRePromptOn = true + processor.state.notes = "Notes" + processor.state.folderId = "1" + processor.state.folders = [.custom(.fixture(id: "1", name: "Folder"))] + processor.state.ownershipOptions = [.personal(email: "user@bitwarden.com")] + + assertSnapshot(of: subject.navStackWrapped, as: .tallPortraitAX5()) + } + + @MainActor + func disabletest_snapshot_edit_full_fieldsVisible() { + processor.state = CipherItemState( + existing: CipherView.loginFixture(), + hasPremium: true, + )! + processor.state.type = .login + processor.state.name = "Name" + processor.state.loginState = .fixture( + fido2Credentials: [.fixture()], + isPasswordVisible: true, + password: "password1!", + uris: [ + .init(uri: URL.example.absoluteString), + ], + username: "username", + ) + processor.state.isAdditionalOptionsExpanded = true + processor.state.isFavoriteOn = true + processor.state.isMasterPasswordRePromptOn = true + processor.state.notes = "Notes" + processor.state.folderId = "1" + processor.state.folders = [.custom(.fixture(id: "1", name: "Folder"))] + processor.state.ownershipOptions = [.personal(email: "user@bitwarden.com")] + + assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) + } + + @MainActor + func disabletest_snapshot_edit_full_fieldsVisible_largeText() { + processor.state = CipherItemState( + existing: CipherView.loginFixture(), + hasPremium: true, + )! + processor.state.loginState = .fixture( + fido2Credentials: [.fixture()], + isPasswordVisible: true, + password: "password1!", + uris: [ + .init(uri: URL.example.absoluteString), + ], + username: "username", + ) + processor.state.type = .login + processor.state.name = "Name" + processor.state.isAdditionalOptionsExpanded = true + processor.state.isFavoriteOn = true + processor.state.isMasterPasswordRePromptOn = true + processor.state.notes = "Notes" + processor.state.folderId = "1" + processor.state.folders = [.custom(.fixture(id: "1", name: "Folder"))] + processor.state.ownershipOptions = [.personal(email: "user@bitwarden.com")] + + assertSnapshot(of: subject.navStackWrapped, as: .tallPortraitAX5()) + } + + /// Test a snapshot of the AddEditView previews. + func disabletest_snapshot_previews_addEditItemView() { + for preview in AddEditItemView_Previews._allPreviews { + assertSnapshots( + of: preview.content, + as: [ + .tallPortrait, + .tallPortraitAX5(heightMultiple: 5), + .defaultPortraitDark, + ], + ) + } + } + + /// Snapshots the previews for SSH key type. + @MainActor + func disabletest_snapshot_sshKey() { + processor.state = sshKeyCipherItemState( + canViewPrivateKey: true, + isPrivateKeyVisible: false, + ) + assertSnapshots( + of: subject, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } + + /// Snapshots the previews for SSH key type when private key is visible. + @MainActor + func disabletest_snapshot_sshKeyPrivateKeyVisible() { + processor.state = sshKeyCipherItemState( + canViewPrivateKey: true, + isPrivateKeyVisible: true, + ) + assertSnapshots( + of: subject, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } + + /// Snapshots the previews for SSH key type when `canViewPrivateKey` is `false`. + @MainActor + func disabletest_snapshot_sshKeyCantViewPrivateKey() { + processor.state = sshKeyCipherItemState( + canViewPrivateKey: false, + isPrivateKeyVisible: false, + ) + assertSnapshots( + of: subject, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } + + // MARK: Private + + /// Creates a `CipherItemState` for an SSH key item. + /// - Parameters: + /// - canViewPrivateKey: Whether the private key can be viewed. + /// - isPrivateKeyVisible: Whether the private key is visible. + /// - Returns: The `CipherItemState` for SSH key item. + private func sshKeyCipherItemState(canViewPrivateKey: Bool, isPrivateKeyVisible: Bool) -> CipherItemState { + var state = CipherItemState( + existing: .fixture( + id: "fake-id", + ), + hasPremium: true, + )! + state.name = "Example" + state.type = .sshKey + state.sshKeyState = SSHKeyItemState( + canViewPrivateKey: canViewPrivateKey, + isPrivateKeyVisible: isPrivateKeyVisible, + privateKey: "ajsdfopij1ZXCVZXC12312QW", + publicKey: "ssh-ed25519 AAAAA/asdjfoiwejrpo23323j23ASdfas", + keyFingerprint: "SHA-256:2qwer233ADJOIq1adfweqe21321qw", + ) + return state + } +} // swiftlint:disable:this file_length diff --git a/BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditItemViewTests.swift b/BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditItemView+ViewInspectorTests.swift similarity index 60% rename from BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditItemViewTests.swift rename to BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditItemView+ViewInspectorTests.swift index a6f93d0d1..6de40e6b7 100644 --- a/BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditItemViewTests.swift +++ b/BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditItemView+ViewInspectorTests.swift @@ -1,6 +1,6 @@ +// swiftlint:disable:this file_name import BitwardenResources import BitwardenSdk -import SnapshotTesting import SwiftUI import ViewInspector import XCTest @@ -48,7 +48,7 @@ class AddEditItemViewTests: BitwardenTestCase { // swiftlint:disable:this type_b /// Tapping the cancel button dispatches the `.dismissPressed` action. @MainActor func test_cancelButton_tap() throws { - var button = try subject.inspect().findCancelToolbarButton() + let button = try subject.inspect().findCancelToolbarButton() try button.tap() XCTAssertEqual(processor.dispatchedActions.last, .dismissPressed) } @@ -531,432 +531,6 @@ class AddEditItemViewTests: BitwardenTestCase { // swiftlint:disable:this type_b XCTAssertEqual(processor.dispatchedActions.last, .identityFieldChanged(.countryChanged("text"))) } - // MARK: Snapshots - - @MainActor - func disabletest_snapshot_add_empty() { - assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) - } - - /// Tests the snapshot with the add state with the learn new login action card. - @MainActor - func disabletest_snapshot_learnNewLoginActionCard() throws { - processor.state = CipherItemState( - hasPremium: false, - ) - processor.state.isLearnNewLoginActionCardEligible = true - assertSnapshots( - of: subject, - as: [.defaultPortrait, .defaultPortraitDark], - ) - } - - /// Tests the add state with identity item empty. - @MainActor - func disabletest_snapshot_add_identity_full_fieldsEmpty() { - processor.state.type = .identity - processor.state.name = "" - processor.state.identityState = .init() - processor.state.isAdditionalOptionsExpanded = true - processor.state.isFavoriteOn = false - processor.state.isMasterPasswordRePromptOn = false - processor.state.notes = "" - processor.state.folderId = nil - - assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait2) - } - - /// Tests the add state with identity item filled. - @MainActor - func disabletest_snapshot_add_identity_full_fieldsFilled() { - processor.state.type = .identity - processor.state.name = "my identity" - processor.state.identityState = .fixture( - title: .custom(.dr), - firstName: "First", - lastName: "Last", - middleName: "Middle", - userName: "userName", - company: "Company name", - socialSecurityNumber: "12-345-6789", - passportNumber: "passport #", - licenseNumber: "license #", - email: "hello@email.com", - phone: "(123) 456-7890", - address1: "123 street", - address2: "address2", - address3: "address3", - cityOrTown: "City", - state: "State", - postalCode: "1234", - country: "country", - ) - processor.state.isAdditionalOptionsExpanded = true - processor.state.isFavoriteOn = true - processor.state.isMasterPasswordRePromptOn = true - processor.state.notes = "A long segment of notes that proves that the multiline feature is working." - processor.state.folderId = "1" - processor.state.folders = [.custom(.fixture(id: "1", name: "Folder"))] - - assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait2) - } - - /// Tests the add state with identity item filled with large text. - @MainActor - func disabletest_snapshot_add_identity_full_fieldsFilled_largeText() { - processor.state.type = .identity - processor.state.name = "my identity" - processor.state.identityState = .fixture( - title: .custom(.dr), - firstName: "First", - lastName: "Last", - middleName: "Middle", - userName: "userName", - company: "Company name", - socialSecurityNumber: "12-345-6789", - passportNumber: "passport #", - licenseNumber: "license #", - email: "hello@email.com", - phone: "(123) 456-7890", - address1: "123 street", - address2: "address2", - address3: "address3", - cityOrTown: "City", - state: "State", - postalCode: "1234", - country: "country", - ) - processor.state.isAdditionalOptionsExpanded = true - processor.state.isFavoriteOn = true - processor.state.isMasterPasswordRePromptOn = true - processor.state.notes = "Notes" - processor.state.folderId = "1" - processor.state.folders = [.custom(.fixture(id: "1", name: "Folder"))] - - assertSnapshot(of: subject.navStackWrapped, as: .tallPortraitAX5(heightMultiple: 7)) - } - - /// Tests the add state with the password field not visible. - @MainActor - func disabletest_snapshot_add_login_full_fieldsNotVisible() { - processor.state.type = .login - processor.state.name = "Name" - processor.state.loginState = .fixture( - password: "password1!", - uris: [ - .init(uri: URL.example.absoluteString), - ], - username: "username", - ) - processor.state.isAdditionalOptionsExpanded = true - processor.state.isFavoriteOn = true - processor.state.isMasterPasswordRePromptOn = true - processor.state.loginState.uris = [ - UriState(id: "id", matchType: .default, uri: URL.example.absoluteString), - ] - processor.state.notes = "Notes" - processor.state.folderId = "1" - processor.state.folders = [.custom(.fixture(id: "1", name: "Folder"))] - - assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) - } - - /// Tests the add state with all fields. - @MainActor - func disabletest_snapshot_add_login_full_fieldsVisible() { - processor.state.type = .login - processor.state.name = "Name" - processor.state.loginState.username = "username" - processor.state.loginState.password = "password1!" - processor.state.isAdditionalOptionsExpanded = true - processor.state.isFavoriteOn = true - processor.state.isMasterPasswordRePromptOn = true - processor.state.loginState.uris = [ - UriState(id: "id", matchType: .default, uri: URL.example.absoluteString), - ] - processor.state.notes = "Notes" - processor.state.folderId = "1" - processor.state.folders = [.custom(.fixture(id: "1", name: "Folder"))] - - processor.state.loginState.isPasswordVisible = true - - assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) - } - - @MainActor - func disabletest_snapshot_add_login_collections() { - processor.state.allUserCollections = [ - .fixture(id: "1", name: "Design", organizationId: "1"), - .fixture(id: "2", name: "Engineering", organizationId: "1"), - ] - processor.state.ownershipOptions.append(.organization(id: "1", name: "Organization")) - processor.state.owner = .organization(id: "1", name: "Organization") - processor.state.collectionIds = ["2"] - - assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) - } - - @MainActor - func disabletest_snapshot_add_login_collectionsNone() { - processor.state.ownershipOptions.append(.organization(id: "1", name: "Organization")) - processor.state.owner = .organization(id: "1", name: "Organization") - - assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) - } - - @MainActor - func disabletest_snapshot_edit_full_fieldsNotVisible() { - processor.state = CipherItemState( - existing: CipherView.loginFixture(), - hasPremium: true, - )! - processor.state.loginState = .fixture( - fido2Credentials: [.fixture()], - isPasswordVisible: false, - password: "password1!", - uris: [ - .init(uri: URL.example.absoluteString), - ], - username: "username", - ) - processor.state.type = .login - processor.state.name = "Name" - processor.state.isAdditionalOptionsExpanded = true - processor.state.isFavoriteOn = true - processor.state.isMasterPasswordRePromptOn = true - processor.state.notes = "Notes" - processor.state.folderId = "1" - processor.state.folders = [.custom(.fixture(id: "1", name: "Folder"))] - processor.state.ownershipOptions = [.personal(email: "user@bitwarden.com")] - - assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) - } - - @MainActor - func disabletest_snapshot_edit_full_readOnly() { - processor.state = CipherItemState( - existing: CipherView.loginFixture(edit: false), - hasPremium: true, - )! - processor.state.loginState = .fixture( - fido2Credentials: [.fixture()], - isPasswordVisible: false, - password: "password1!", - uris: [ - .init(uri: URL.example.absoluteString), - ], - username: "username", - ) - processor.state.type = .login - processor.state.name = "Name" - processor.state.isAdditionalOptionsExpanded = true - processor.state.isFavoriteOn = true - processor.state.isMasterPasswordRePromptOn = true - processor.state.notes = "Notes" - processor.state.folderId = "1" - processor.state.folders = [.custom(.fixture(id: "1", name: "Folder"))] - processor.state.ownershipOptions = [.personal(email: "user@bitwarden.com")] - - assertSnapshots( - of: subject.navStackWrapped, - as: [ - .tallPortrait, - .portraitDark(heightMultiple: 2), - ], - ) - } - - @MainActor - func disabletest_snapshot_add_personalOwnershipPolicy() { - processor.state.ownershipOptions.append(.organization(id: "1", name: "Organization")) - processor.state.owner = .organization(id: "1", name: "Organization") - processor.state.isPersonalOwnershipDisabled = true - processor.state.allUserCollections = [ - .fixture(id: "1", name: "Default collection", organizationId: "1"), - ] - assertSnapshot(of: subject.navStackWrapped, as: .defaultPortrait) - } - - @MainActor - func disabletest_snapshot_add_secureNote_full_fieldsVisible() { - processor.state.type = .secureNote - processor.state.name = "Secure Note Name" - processor.state.isAdditionalOptionsExpanded = true - processor.state.isFavoriteOn = true - processor.state.isMasterPasswordRePromptOn = true - processor.state.notes = "Notes" - processor.state.folderId = "1" - processor.state.folders = [.custom(.fixture(id: "1", name: "Folder"))] - - assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) - } - - @MainActor - func disabletest_snapshot_edit_full_disabledViewPassword() { - processor.state = CipherItemState( - existing: CipherView.loginFixture(), - hasPremium: true, - )! - processor.state.loginState = .fixture( - canViewPassword: false, - fido2Credentials: [.fixture()], - isPasswordVisible: false, - password: "password1!", - uris: [ - .init(uri: URL.example.absoluteString), - ], - username: "username", - ) - processor.state.type = .login - processor.state.name = "Name" - processor.state.isAdditionalOptionsExpanded = true - processor.state.isFavoriteOn = true - processor.state.isMasterPasswordRePromptOn = true - processor.state.notes = "Notes" - processor.state.folderId = "1" - processor.state.folders = [.custom(.fixture(id: "1", name: "Folder"))] - processor.state.ownershipOptions = [.personal(email: "user@bitwarden.com")] - - assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) - } - - @MainActor - func disabletest_snapshot_edit_full_fieldsNotVisible_largeText() { - processor.state = CipherItemState( - existing: CipherView.loginFixture(), - hasPremium: true, - )! - processor.state.loginState = .fixture( - fido2Credentials: [.fixture()], - isPasswordVisible: false, - password: "password1!", - uris: [ - .init(uri: URL.example.absoluteString), - ], - username: "username", - ) - processor.state.type = .login - processor.state.name = "Name" - processor.state.isAdditionalOptionsExpanded = true - processor.state.isFavoriteOn = true - processor.state.isMasterPasswordRePromptOn = true - processor.state.notes = "Notes" - processor.state.folderId = "1" - processor.state.folders = [.custom(.fixture(id: "1", name: "Folder"))] - processor.state.ownershipOptions = [.personal(email: "user@bitwarden.com")] - - assertSnapshot(of: subject.navStackWrapped, as: .tallPortraitAX5()) - } - - @MainActor - func disabletest_snapshot_edit_full_fieldsVisible() { - processor.state = CipherItemState( - existing: CipherView.loginFixture(), - hasPremium: true, - )! - processor.state.type = .login - processor.state.name = "Name" - processor.state.loginState = .fixture( - fido2Credentials: [.fixture()], - isPasswordVisible: true, - password: "password1!", - uris: [ - .init(uri: URL.example.absoluteString), - ], - username: "username", - ) - processor.state.isAdditionalOptionsExpanded = true - processor.state.isFavoriteOn = true - processor.state.isMasterPasswordRePromptOn = true - processor.state.notes = "Notes" - processor.state.folderId = "1" - processor.state.folders = [.custom(.fixture(id: "1", name: "Folder"))] - processor.state.ownershipOptions = [.personal(email: "user@bitwarden.com")] - - assertSnapshot(of: subject.navStackWrapped, as: .tallPortrait) - } - - @MainActor - func disabletest_snapshot_edit_full_fieldsVisible_largeText() { - processor.state = CipherItemState( - existing: CipherView.loginFixture(), - hasPremium: true, - )! - processor.state.loginState = .fixture( - fido2Credentials: [.fixture()], - isPasswordVisible: true, - password: "password1!", - uris: [ - .init(uri: URL.example.absoluteString), - ], - username: "username", - ) - processor.state.type = .login - processor.state.name = "Name" - processor.state.isAdditionalOptionsExpanded = true - processor.state.isFavoriteOn = true - processor.state.isMasterPasswordRePromptOn = true - processor.state.notes = "Notes" - processor.state.folderId = "1" - processor.state.folders = [.custom(.fixture(id: "1", name: "Folder"))] - processor.state.ownershipOptions = [.personal(email: "user@bitwarden.com")] - - assertSnapshot(of: subject.navStackWrapped, as: .tallPortraitAX5()) - } - - /// Test a snapshot of the AddEditView previews. - func disabletest_snapshot_previews_addEditItemView() { - for preview in AddEditItemView_Previews._allPreviews { - assertSnapshots( - of: preview.content, - as: [ - .tallPortrait, - .tallPortraitAX5(heightMultiple: 5), - .defaultPortraitDark, - ], - ) - } - } - - /// Snapshots the previews for SSH key type. - @MainActor - func disabletest_snapshot_sshKey() { - processor.state = sshKeyCipherItemState( - canViewPrivateKey: true, - isPrivateKeyVisible: false, - ) - assertSnapshots( - of: subject, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } - - /// Snapshots the previews for SSH key type when private key is visible. - @MainActor - func disabletest_snapshot_sshKeyPrivateKeyVisible() { - processor.state = sshKeyCipherItemState( - canViewPrivateKey: true, - isPrivateKeyVisible: true, - ) - assertSnapshots( - of: subject, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } - - /// Snapshots the previews for SSH key type when `canViewPrivateKey` is `false`. - @MainActor - func disabletest_snapshot_sshKeyCantViewPrivateKey() { - processor.state = sshKeyCipherItemState( - canViewPrivateKey: false, - isPrivateKeyVisible: false, - ) - assertSnapshots( - of: subject, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } - // MARK: Private /// Creates a `CipherItemState` for an SSH key item. diff --git a/BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditLoginItem/AddEditLoginItemViewTests.swift b/BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditLoginItem/AddEditLoginItemView+SnapshotTests.swift similarity index 94% rename from BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditLoginItem/AddEditLoginItemViewTests.swift rename to BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditLoginItem/AddEditLoginItemView+SnapshotTests.swift index 4316148b4..41b6771e3 100644 --- a/BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditLoginItem/AddEditLoginItemViewTests.swift +++ b/BitwardenShared/UI/Vault/VaultItem/AddEditItem/AddEditLoginItem/AddEditLoginItemView+SnapshotTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import SnapshotTesting import XCTest diff --git a/BitwardenShared/UI/Vault/VaultItem/Attachments/AttachmentsView+SnapshotTests.swift b/BitwardenShared/UI/Vault/VaultItem/Attachments/AttachmentsView+SnapshotTests.swift new file mode 100644 index 000000000..cc6783258 --- /dev/null +++ b/BitwardenShared/UI/Vault/VaultItem/Attachments/AttachmentsView+SnapshotTests.swift @@ -0,0 +1,85 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import BitwardenSdk +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class AttachmentsViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: AttachmentsView! + + var cipherWithAttachments: CipherView { + .fixture( + attachments: [ + .fixture(fileName: "selfieWithACat.png", id: "1", sizeName: "10 MB"), + .fixture(fileName: "selfieWithADog.png", id: "2", sizeName: "11.2 MB"), + .fixture(fileName: "selfieWithAPotato.png", id: "3", sizeName: "201.2 MB"), + ], + ) + } + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: AttachmentsState()) + let store = Store(processor: processor) + + subject = AttachmentsView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Previews + + /// The empty view renders correctly in dark mode. + @MainActor + func disabletest_snapshot_attachments_empty() { + assertSnapshots( + of: subject.navStackWrapped, + as: [ + .defaultPortrait, + .defaultPortraitDark, + .defaultPortraitAX5, + ], + ) + } + + /// The view with a selected attachment renders correctly. + @MainActor + func disabletest_snapshot_attachments_selected() { + processor.state.fileName = "photo.jpg" + assertSnapshots( + of: subject.navStackWrapped, + as: [ + .defaultPortrait, + .defaultPortraitDark, + .defaultPortraitAX5, + ], + ) + } + + /// The view with several attachments renders correctly in dark mode. + @MainActor + func disabletest_snapshot_attachments_several() { + processor.state.cipher = cipherWithAttachments + assertSnapshots( + of: subject.navStackWrapped, + as: [ + .defaultPortrait, + .defaultPortraitDark, + .defaultPortraitAX5, + ], + ) + } +} diff --git a/BitwardenShared/UI/Vault/VaultItem/Attachments/AttachmentsViewTests.swift b/BitwardenShared/UI/Vault/VaultItem/Attachments/AttachmentsView+ViewInspectorTests.swift similarity index 66% rename from BitwardenShared/UI/Vault/VaultItem/Attachments/AttachmentsViewTests.swift rename to BitwardenShared/UI/Vault/VaultItem/Attachments/AttachmentsView+ViewInspectorTests.swift index 76d9ad25e..1e2c09dff 100644 --- a/BitwardenShared/UI/Vault/VaultItem/Attachments/AttachmentsViewTests.swift +++ b/BitwardenShared/UI/Vault/VaultItem/Attachments/AttachmentsView+ViewInspectorTests.swift @@ -1,6 +1,6 @@ +// swiftlint:disable:this file_name import BitwardenResources import BitwardenSdk -import SnapshotTesting import XCTest @testable import BitwardenShared @@ -44,7 +44,7 @@ class AttachmentsViewTests: BitwardenTestCase { /// Tapping the cancel button dispatches the `.dismissPressed` action. @MainActor func test_cancelButton_tap() throws { - var button = try subject.inspect().findCancelToolbarButton() + let button = try subject.inspect().findCancelToolbarButton() try button.tap() XCTAssertEqual(processor.dispatchedActions.last, .dismissPressed) } @@ -78,47 +78,4 @@ class AttachmentsViewTests: BitwardenTestCase { try await button.tap() XCTAssertEqual(processor.effects.last, .save) } - - // MARK: Previews - - /// The empty view renders correctly in dark mode. - @MainActor - func disabletest_snapshot_attachments_empty() { - assertSnapshots( - of: subject.navStackWrapped, - as: [ - .defaultPortrait, - .defaultPortraitDark, - .defaultPortraitAX5, - ], - ) - } - - /// The view with a selected attachment renders correctly. - @MainActor - func disabletest_snapshot_attachments_selected() { - processor.state.fileName = "photo.jpg" - assertSnapshots( - of: subject.navStackWrapped, - as: [ - .defaultPortrait, - .defaultPortraitDark, - .defaultPortraitAX5, - ], - ) - } - - /// The view with several attachments renders correctly in dark mode. - @MainActor - func disabletest_snapshot_attachments_several() { - processor.state.cipher = cipherWithAttachments - assertSnapshots( - of: subject.navStackWrapped, - as: [ - .defaultPortrait, - .defaultPortraitDark, - .defaultPortraitAX5, - ], - ) - } } diff --git a/BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/AuthenticatorKeyCaptureCoordinator+ViewInspectorTests.swift b/BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/AuthenticatorKeyCaptureCoordinator+ViewInspectorTests.swift new file mode 100644 index 000000000..d7d6f26b2 --- /dev/null +++ b/BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/AuthenticatorKeyCaptureCoordinator+ViewInspectorTests.swift @@ -0,0 +1,181 @@ +// swiftlint:disable:this file_name +import AVFoundation +import BitwardenKitMocks +import SwiftUI +import XCTest + +@testable import BitwardenShared + +class AuthenticatorKeyCaptureCoordinatorTests: BitwardenTestCase { + // MARK: Properties + + var appExtensionDelegate: MockAppExtensionDelegate! + var cameraService: MockCameraService! + var delegate: MockAuthenticatorKeyCaptureDelegate! + var errorReporter: MockErrorReporter! + var stackNavigator: MockStackNavigator! + var subject: AuthenticatorKeyCaptureCoordinator! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + appExtensionDelegate = MockAppExtensionDelegate() + cameraService = MockCameraService() + delegate = MockAuthenticatorKeyCaptureDelegate() + errorReporter = MockErrorReporter() + stackNavigator = MockStackNavigator() + + subject = AuthenticatorKeyCaptureCoordinator( + appExtensionDelegate: appExtensionDelegate, + delegate: delegate, + services: ServiceContainer.withMocks( + cameraService: cameraService, + errorReporter: errorReporter, + ), + stackNavigator: stackNavigator, + ) + cameraService.cameraAuthorizationStatus = .authorized + cameraService.startResult = .success(AVCaptureSession()) + } + + override func tearDown() { + super.tearDown() + + appExtensionDelegate = nil + cameraService = nil + errorReporter = nil + stackNavigator = nil + subject = nil + } + + // MARK: Tests + + /// `navigate(to:)` with `.scanCode` shows the scan view. + @MainActor + func test_navigateTo_scanCode() throws { + cameraService.deviceHasCamera = true + let task = Task { + await subject.handleEvent(.showScanCode) + } + waitFor(!stackNavigator.actions.isEmpty) + task.cancel() + + let action = try XCTUnwrap(stackNavigator.actions.last) + XCTAssertEqual(action.type, .replaced) + let view = action.view as? (any View) + XCTAssertNotNil(try? view?.inspect().find(ScanCodeView.self)) + } + + /// `navigate(to:)` with `.scanCode` shows the scan view. + @MainActor + func test_navigateAsyncTo_scanCode() throws { + cameraService.deviceHasCamera = true + let task = Task { + await subject.handleEvent(.showScanCode) + } + waitFor(!stackNavigator.actions.isEmpty) + task.cancel() + + let action = try XCTUnwrap(stackNavigator.actions.last) + XCTAssertEqual(action.type, .replaced) + let view = action.view as? (any View) + XCTAssertNotNil(try? view?.inspect().find(ScanCodeView.self)) + } + + /// `navigate(to:)` with `.scanCode` shows the scan view. + @MainActor + func test_navigateAsyncTo_scanCode_cameraSessionError() throws { + cameraService.deviceHasCamera = true + struct TestError: Error, Equatable {} + cameraService.startResult = .failure(TestError()) + let task = Task { + await subject.handleEvent(.showScanCode) + } + waitFor(!stackNavigator.actions.isEmpty) + task.cancel() + + XCTAssertEqual(errorReporter.errors.last as? TestError, TestError()) + let action = try XCTUnwrap(stackNavigator.actions.last) + XCTAssertEqual(action.type, .replaced) + let view = action.view as? (any View) + XCTAssertNotNil(try? view?.inspect().find(ManualEntryView.self)) + } + + /// `navigate(to:)` with `.scanCode` shows the scan view. + @MainActor + func test_navigateAsyncTo_scanCode_declineAuthorization() throws { + cameraService.deviceHasCamera = true + cameraService.cameraAuthorizationStatus = .denied + let task = Task { + await subject.handleEvent(.showScanCode) + } + waitFor(!stackNavigator.actions.isEmpty) + task.cancel() + + let action = try XCTUnwrap(stackNavigator.actions.last) + XCTAssertEqual(action.type, .replaced) + let view = action.view as? (any View) + XCTAssertNotNil(try? view?.inspect().find(ManualEntryView.self)) + } + + /// `navigate(to:)` with `.scanCode` shows the scan view. + @MainActor + func test_navigateAsyncTo_scanCode_noCamera() throws { + cameraService.deviceHasCamera = false + let task = Task { + await subject.handleEvent(.showScanCode) + } + waitFor(!stackNavigator.actions.isEmpty) + task.cancel() + + let action = try XCTUnwrap(stackNavigator.actions.last) + XCTAssertEqual(action.type, .replaced) + let view = action.view as? (any View) + XCTAssertNotNil(try? view?.inspect().find(ManualEntryView.self)) + } +} + +// MARK: - MockAuthenticatorKeyCaptureDelegate + +class MockAuthenticatorKeyCaptureDelegate: AuthenticatorKeyCaptureDelegate { + var capturedCaptureCoordinator: AnyCoordinator? + var didCancelScanCalled = false + + var didCompleteCaptureCalled = false + var didCompleteCaptureValue: String? + + /// A flag to capture a `showCameraScan` call. + var didRequestCamera: Bool = false + + /// A flag to capture a `showManualEntry` call. + var didRequestManual: Bool = false + + func didCancelScan() { + didCancelScanCalled = true + } + + func didCompleteCapture( + _ captureCoordinator: AnyCoordinator, + with value: String, + ) { + didCompleteCaptureCalled = true + capturedCaptureCoordinator = captureCoordinator + didCompleteCaptureValue = value + } + + func showCameraScan( + _ captureCoordinator: AnyCoordinator, + ) { + didRequestCamera = true + capturedCaptureCoordinator = captureCoordinator + } + + func showManualEntry( + _ captureCoordinator: AnyCoordinator, + ) { + didRequestManual = true + capturedCaptureCoordinator = captureCoordinator + } +} diff --git a/BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/AuthenticatorKeyCaptureCoordinatorTests.swift b/BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/AuthenticatorKeyCaptureCoordinatorTests.swift index ccee5b79f..1a72f56ec 100644 --- a/BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/AuthenticatorKeyCaptureCoordinatorTests.swift +++ b/BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/AuthenticatorKeyCaptureCoordinatorTests.swift @@ -123,22 +123,6 @@ class AuthenticatorKeyCaptureCoordinatorTests: BitwardenTestCase { XCTAssertTrue(stackNavigator.actions.isEmpty) } - /// `navigate(to:)` with `.scanCode` shows the scan view. - @MainActor - func test_navigateTo_scanCode() throws { - cameraService.deviceHasCamera = true - let task = Task { - await subject.handleEvent(.showScanCode) - } - waitFor(!stackNavigator.actions.isEmpty) - task.cancel() - - let action = try XCTUnwrap(stackNavigator.actions.last) - XCTAssertEqual(action.type, .replaced) - let view = action.view as? (any View) - XCTAssertNotNil(try? view?.inspect().find(ScanCodeView.self)) - } - /// `navigate(to:)` with `.scanCode` shows the scan view. @MainActor func test_navigateTo_scanCode_nonEmptyStack() throws { @@ -168,74 +152,6 @@ class AuthenticatorKeyCaptureCoordinatorTests: BitwardenTestCase { XCTAssertNil(window.viewWithTag(LoadingOverlayDisplayHelper.overlayViewTag)) } - /// `navigate(to:)` with `.scanCode` shows the scan view. - @MainActor - func test_navigateAsyncTo_scanCode() throws { - cameraService.deviceHasCamera = true - let task = Task { - await subject.handleEvent(.showScanCode) - } - waitFor(!stackNavigator.actions.isEmpty) - task.cancel() - - let action = try XCTUnwrap(stackNavigator.actions.last) - XCTAssertEqual(action.type, .replaced) - let view = action.view as? (any View) - XCTAssertNotNil(try? view?.inspect().find(ScanCodeView.self)) - } - - /// `navigate(to:)` with `.scanCode` shows the scan view. - @MainActor - func test_navigateAsyncTo_scanCode_cameraSessionError() throws { - cameraService.deviceHasCamera = true - struct TestError: Error, Equatable {} - cameraService.startResult = .failure(TestError()) - let task = Task { - await subject.handleEvent(.showScanCode) - } - waitFor(!stackNavigator.actions.isEmpty) - task.cancel() - - XCTAssertEqual(errorReporter.errors.last as? TestError, TestError()) - let action = try XCTUnwrap(stackNavigator.actions.last) - XCTAssertEqual(action.type, .replaced) - let view = action.view as? (any View) - XCTAssertNotNil(try? view?.inspect().find(ManualEntryView.self)) - } - - /// `navigate(to:)` with `.scanCode` shows the scan view. - @MainActor - func test_navigateAsyncTo_scanCode_declineAuthorization() throws { - cameraService.deviceHasCamera = true - cameraService.cameraAuthorizationStatus = .denied - let task = Task { - await subject.handleEvent(.showScanCode) - } - waitFor(!stackNavigator.actions.isEmpty) - task.cancel() - - let action = try XCTUnwrap(stackNavigator.actions.last) - XCTAssertEqual(action.type, .replaced) - let view = action.view as? (any View) - XCTAssertNotNil(try? view?.inspect().find(ManualEntryView.self)) - } - - /// `navigate(to:)` with `.scanCode` shows the scan view. - @MainActor - func test_navigateAsyncTo_scanCode_noCamera() throws { - cameraService.deviceHasCamera = false - let task = Task { - await subject.handleEvent(.showScanCode) - } - waitFor(!stackNavigator.actions.isEmpty) - task.cancel() - - let action = try XCTUnwrap(stackNavigator.actions.last) - XCTAssertEqual(action.type, .replaced) - let view = action.view as? (any View) - XCTAssertNotNil(try? view?.inspect().find(ManualEntryView.self)) - } - /// `navigate(to:)` with `.scanCode` shows the scan view. @MainActor func test_navigateAsyncTo_scanCode_nonEmptyStack() throws { diff --git a/BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ManualEntryView+SnapshotTests.swift b/BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ManualEntryView+SnapshotTests.swift new file mode 100644 index 000000000..fd83c0993 --- /dev/null +++ b/BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ManualEntryView+SnapshotTests.swift @@ -0,0 +1,58 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +// MARK: - ManualEntryViewTests + +class ManualEntryViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: ManualEntryView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + processor = MockProcessor(state: DefaultEntryState(deviceSupportsCamera: true)) + let store = Store(processor: processor) + subject = ManualEntryView( + store: store, + ) + } + + override func tearDown() { + super.tearDown() + processor = nil + subject = nil + } + + // MARK: Snapshots + + /// Test a snapshot of the ProfileSwitcherView empty state. + func disabletest_snapshot_manualEntryView_empty() { + assertSnapshots( + of: ManualEntryView_Previews.empty, + as: [ + .defaultPortrait, + .defaultLandscape, + .defaultPortraitDark, + ], + ) + } + + /// Test a snapshot of the ProfileSwitcherView in with text added. + func disabletest_snapshot_manualEntryView_text() { + assertSnapshots( + of: ManualEntryView_Previews.textAdded, + as: [ + .defaultPortrait, + .defaultPortraitDark, + .tallPortraitAX5(heightMultiple: 1.75), + ], + ) + } +} diff --git a/BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ManualEntryViewTests.swift b/BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ManualEntryView+ViewInspectorTests.swift similarity index 75% rename from BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ManualEntryViewTests.swift rename to BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ManualEntryView+ViewInspectorTests.swift index 0454ac337..ec8a8496d 100644 --- a/BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ManualEntryViewTests.swift +++ b/BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ManualEntryView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import ViewInspector import XCTest @@ -35,7 +35,7 @@ class ManualEntryViewTests: BitwardenTestCase { /// Tapping the cancel button dispatches the `.dismiss` action. @MainActor func test_closeButton_tap() throws { - var button = try subject.inspect().findCancelToolbarButton() + let button = try subject.inspect().findCancelToolbarButton() try button.tap() XCTAssertEqual(processor.dispatchedActions.last, .dismissPressed) } @@ -76,30 +76,4 @@ class ManualEntryViewTests: BitwardenTestCase { try await button.tap() XCTAssertEqual(processor.dispatchedActions.last, .addPressed(code: "pasta-batman")) } - - // MARK: Snapshots - - /// Test a snapshot of the ProfileSwitcherView empty state. - func disabletest_snapshot_manualEntryView_empty() { - assertSnapshots( - of: ManualEntryView_Previews.empty, - as: [ - .defaultPortrait, - .defaultLandscape, - .defaultPortraitDark, - ], - ) - } - - /// Test a snapshot of the ProfileSwitcherView in with text added. - func disabletest_snapshot_manualEntryView_text() { - assertSnapshots( - of: ManualEntryView_Previews.textAdded, - as: [ - .defaultPortrait, - .defaultPortraitDark, - .tallPortraitAX5(heightMultiple: 1.75), - ], - ) - } } diff --git a/BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ScanCodeViewTests.swift b/BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ScanCodeView+SnapshotTests.swift similarity index 77% rename from BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ScanCodeViewTests.swift rename to BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ScanCodeView+SnapshotTests.swift index 3f15effd0..2ec5c127f 100644 --- a/BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ScanCodeViewTests.swift +++ b/BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ScanCodeView+SnapshotTests.swift @@ -1,7 +1,7 @@ +// swiftlint:disable:this file_name import AVFoundation import BitwardenResources import SnapshotTesting -import ViewInspector import XCTest @testable import BitwardenShared @@ -32,16 +32,6 @@ class ScanCodeViewTests: BitwardenTestCase { subject = nil } - // MARK: Tests - - /// Tapping the cancel button dispatches the `.dismiss` action. - @MainActor - func test_cancelButton_tap() throws { - var button = try subject.inspect().findCancelToolbarButton() - try button.tap() - XCTAssertEqual(processor.dispatchedActions.last, .dismissPressed) - } - // MARK: Snapshots /// Test a snapshot of the ProfileSwitcherView previews. diff --git a/BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ScanCodeView+ViewInspectorTests.swift b/BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ScanCodeView+ViewInspectorTests.swift new file mode 100644 index 000000000..4c14b3f14 --- /dev/null +++ b/BitwardenShared/UI/Vault/VaultItem/AuthenticatorKeyCapture/ScanCodeView+ViewInspectorTests.swift @@ -0,0 +1,44 @@ +// swiftlint:disable:this file_name +import AVFoundation +import BitwardenResources +import ViewInspector +import XCTest + +@testable import BitwardenShared + +// MARK: - ScanCodeViewTests + +class ScanCodeViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: ScanCodeView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + processor = MockProcessor(state: .init()) + let store = Store(processor: processor) + subject = ScanCodeView( + cameraSession: .init(), + store: store, + ) + } + + override func tearDown() { + super.tearDown() + processor = nil + subject = nil + } + + // MARK: Tests + + /// Tapping the cancel button dispatches the `.dismiss` action. + @MainActor + func test_cancelButton_tap() throws { + let button = try subject.inspect().findCancelToolbarButton() + try button.tap() + XCTAssertEqual(processor.dispatchedActions.last, .dismissPressed) + } +} diff --git a/BitwardenShared/UI/Vault/VaultItem/EditCollections/EditCollectionsView+SnapshotTests.swift b/BitwardenShared/UI/Vault/VaultItem/EditCollections/EditCollectionsView+SnapshotTests.swift new file mode 100644 index 000000000..badccc671 --- /dev/null +++ b/BitwardenShared/UI/Vault/VaultItem/EditCollections/EditCollectionsView+SnapshotTests.swift @@ -0,0 +1,46 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class EditCollectionsViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: EditCollectionsView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: EditCollectionsState(cipher: .fixture())) + let store = Store(processor: processor) + + subject = EditCollectionsView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Previews + + /// The edit collections view renders correctly. + @MainActor + func disabletest_snapshot_editCollections() { + processor.state.collections = [ + .fixture(id: "1", name: "Design", organizationId: "1"), + .fixture(id: "2", name: "Engineering", organizationId: "1"), + ] + assertSnapshots( + of: subject.navStackWrapped, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } +} diff --git a/BitwardenShared/UI/Vault/VaultItem/EditCollections/EditCollectionsViewTests.swift b/BitwardenShared/UI/Vault/VaultItem/EditCollections/EditCollectionsView+ViewInspectorTests.swift similarity index 74% rename from BitwardenShared/UI/Vault/VaultItem/EditCollections/EditCollectionsViewTests.swift rename to BitwardenShared/UI/Vault/VaultItem/EditCollections/EditCollectionsView+ViewInspectorTests.swift index 4df62170c..79576be29 100644 --- a/BitwardenShared/UI/Vault/VaultItem/EditCollections/EditCollectionsViewTests.swift +++ b/BitwardenShared/UI/Vault/VaultItem/EditCollections/EditCollectionsView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import XCTest @testable import BitwardenShared @@ -50,19 +50,4 @@ class EditCollectionsViewTests: BitwardenTestCase { try await button.tap() XCTAssertEqual(processor.effects.last, .save) } - - // MARK: Previews - - /// The edit collections view renders correctly. - @MainActor - func disabletest_snapshot_editCollections() { - processor.state.collections = [ - .fixture(id: "1", name: "Design", organizationId: "1"), - .fixture(id: "2", name: "Engineering", organizationId: "1"), - ] - assertSnapshots( - of: subject.navStackWrapped, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } } diff --git a/BitwardenShared/UI/Vault/VaultItem/MoveToOrganization/MoveToOrganizationView+SnapshotTests.swift b/BitwardenShared/UI/Vault/VaultItem/MoveToOrganization/MoveToOrganizationView+SnapshotTests.swift new file mode 100644 index 000000000..14d439717 --- /dev/null +++ b/BitwardenShared/UI/Vault/VaultItem/MoveToOrganization/MoveToOrganizationView+SnapshotTests.swift @@ -0,0 +1,56 @@ +// swiftlint:disable:this file_name +import BitwardenResources +import SnapshotTesting +import XCTest + +@testable import BitwardenShared + +class MoveToOrganizationViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: MoveToOrganizationView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + + processor = MockProcessor(state: MoveToOrganizationState(cipher: .fixture())) + let store = Store(processor: processor) + + subject = MoveToOrganizationView(store: store) + } + + override func tearDown() { + super.tearDown() + + processor = nil + subject = nil + } + + // MARK: Previews + + /// The empty view renders correctly. + func disabletest_snapshot_moveToOrganization_empty() { + assertSnapshots( + of: subject.navStackWrapped, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } + + /// The collections view renders correctly. + @MainActor + func disabletest_snapshot_moveToOrganization_collections() { + processor.state.collections = [ + .fixture(id: "1", name: "Design", organizationId: "1"), + .fixture(id: "2", name: "Engineering", organizationId: "1"), + ] + processor.state.organizationId = "1" + processor.state.ownershipOptions = [.organization(id: "1", name: "Organization")] + assertSnapshots( + of: subject.navStackWrapped, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } +} diff --git a/BitwardenShared/UI/Vault/VaultItem/MoveToOrganization/MoveToOrganizationViewTests.swift b/BitwardenShared/UI/Vault/VaultItem/MoveToOrganization/MoveToOrganizationView+ViewInspectorTests.swift similarity index 65% rename from BitwardenShared/UI/Vault/VaultItem/MoveToOrganization/MoveToOrganizationViewTests.swift rename to BitwardenShared/UI/Vault/VaultItem/MoveToOrganization/MoveToOrganizationView+ViewInspectorTests.swift index 8ea1ae171..5f47c2fd8 100644 --- a/BitwardenShared/UI/Vault/VaultItem/MoveToOrganization/MoveToOrganizationViewTests.swift +++ b/BitwardenShared/UI/Vault/VaultItem/MoveToOrganization/MoveToOrganizationView+ViewInspectorTests.swift @@ -1,5 +1,5 @@ +// swiftlint:disable:this file_name import BitwardenResources -import SnapshotTesting import XCTest @testable import BitwardenShared @@ -33,7 +33,7 @@ class MoveToOrganizationViewTests: BitwardenTestCase { /// Tapping the move button dispatches the `.dismissPressed` action. @MainActor func test_cancelButton_tap() throws { - var button = try subject.inspect().findCancelToolbarButton() + let button = try subject.inspect().findCancelToolbarButton() try button.tap() XCTAssertEqual(processor.dispatchedActions.last, .dismissPressed) } @@ -57,29 +57,4 @@ class MoveToOrganizationViewTests: BitwardenTestCase { try menuField.select(newValue: owner) XCTAssertEqual(processor.dispatchedActions.last, .ownerChanged(owner)) } - - // MARK: Previews - - /// The empty view renders correctly. - func disabletest_snapshot_moveToOrganization_empty() { - assertSnapshots( - of: subject.navStackWrapped, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } - - /// The collections view renders correctly. - @MainActor - func disabletest_snapshot_moveToOrganization_collections() { - processor.state.collections = [ - .fixture(id: "1", name: "Design", organizationId: "1"), - .fixture(id: "2", name: "Engineering", organizationId: "1"), - ] - processor.state.organizationId = "1" - processor.state.ownershipOptions = [.organization(id: "1", name: "Organization")] - assertSnapshots( - of: subject.navStackWrapped, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } } diff --git a/BitwardenShared/UI/Vault/VaultItem/VaultItemCoordinatorTests.swift b/BitwardenShared/UI/Vault/VaultItem/VaultItemCoordinatorTests.swift index c75b3b0bb..cf96f175b 100644 --- a/BitwardenShared/UI/Vault/VaultItem/VaultItemCoordinatorTests.swift +++ b/BitwardenShared/UI/Vault/VaultItem/VaultItemCoordinatorTests.swift @@ -1,6 +1,5 @@ import AVFoundation import SwiftUI -import ViewInspector import XCTest @testable import BitwardenShared diff --git a/BitwardenShared/UI/Vault/VaultItem/VaultItemManagementMenu/VaultItemManagementMenuViewTests.swift b/BitwardenShared/UI/Vault/VaultItem/VaultItemManagementMenu/VaultItemManagementMenuView+ViewInspectorTests.swift similarity index 98% rename from BitwardenShared/UI/Vault/VaultItem/VaultItemManagementMenu/VaultItemManagementMenuViewTests.swift rename to BitwardenShared/UI/Vault/VaultItem/VaultItemManagementMenu/VaultItemManagementMenuView+ViewInspectorTests.swift index ab390cdba..95852889e 100644 --- a/BitwardenShared/UI/Vault/VaultItem/VaultItemManagementMenu/VaultItemManagementMenuViewTests.swift +++ b/BitwardenShared/UI/Vault/VaultItem/VaultItemManagementMenu/VaultItemManagementMenuView+ViewInspectorTests.swift @@ -1,6 +1,6 @@ +// swiftlint:disable:this file_name import BitwardenResources import BitwardenSdk -import SnapshotTesting import SwiftUI import ViewInspector import XCTest diff --git a/BitwardenShared/UI/Vault/VaultItem/ViewItem/ViewCardItem/ViewCardItemViewTests.swift b/BitwardenShared/UI/Vault/VaultItem/ViewItem/ViewCardItem/ViewCardItemView+SnapshotTests.swift similarity index 98% rename from BitwardenShared/UI/Vault/VaultItem/ViewItem/ViewCardItem/ViewCardItemViewTests.swift rename to BitwardenShared/UI/Vault/VaultItem/ViewItem/ViewCardItem/ViewCardItemView+SnapshotTests.swift index d2c6f48e3..30b7880df 100644 --- a/BitwardenShared/UI/Vault/VaultItem/ViewItem/ViewCardItem/ViewCardItemViewTests.swift +++ b/BitwardenShared/UI/Vault/VaultItem/ViewItem/ViewCardItem/ViewCardItemView+SnapshotTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import SnapshotTesting import XCTest diff --git a/BitwardenShared/UI/Vault/VaultItem/ViewItem/ViewItemView+SnapshotTests.swift b/BitwardenShared/UI/Vault/VaultItem/ViewItem/ViewItemView+SnapshotTests.swift new file mode 100644 index 000000000..c478709b4 --- /dev/null +++ b/BitwardenShared/UI/Vault/VaultItem/ViewItem/ViewItemView+SnapshotTests.swift @@ -0,0 +1,428 @@ +// swiftlint:disable:this file_name +import BitwardenKit +import BitwardenKitMocks +import BitwardenResources +import BitwardenSdk +import SnapshotTesting +import SwiftUI +import XCTest + +// swiftlint:disable file_length + +@testable import BitwardenShared + +// MARK: - ViewItemViewTests + +class ViewItemViewTests: BitwardenTestCase { // swiftlint:disable:this type_body_length + // MARK: Properties + + var mockPresentTime = Date(year: 2023, month: 12, day: 31, minute: 0, second: 41) + var timeProvider: TimeProvider! + var processor: MockProcessor! + var subject: ViewItemView! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + let state = ViewItemState() + processor = MockProcessor(state: state) + let store = Store(processor: processor) + timeProvider = MockTimeProvider(.mockTime(mockPresentTime)) + subject = ViewItemView(store: store, timeProvider: timeProvider) + } + + override func tearDown() { + super.tearDown() + processor = nil + subject = nil + timeProvider = nil + } + + // MARK: Snapshots + + @MainActor + func disabletest_snapshot_loading() { + processor.state.loadingState = .loading(nil) + assertSnapshot(of: subject, as: .defaultPortrait) + } + + func identityState() -> CipherItemState { + var cipherState = CipherItemState( + existing: .fixture( + id: "1234", + name: "identity example", + type: .identity, + ), + hasPremium: true, + )! + cipherState.folderId = "1" + cipherState.folders = [.custom(.fixture(id: "1", name: "Folder"))] + cipherState.folderName = "Folder" + cipherState.notes = "Notes" + cipherState.updatedDate = Date(year: 2023, month: 11, day: 11, hour: 9, minute: 41) + cipherState.identityState = .fixture( + title: .custom(.dr), + firstName: "First", + lastName: "Last", + middleName: "Middle", + userName: "userName", + company: "Company name", + socialSecurityNumber: "12-345-6789", + passportNumber: "passport #", + licenseNumber: "license #", + email: "hello@email.com", + phone: "(123) 456-7890", + address1: "123 street", + address2: "address2", + address3: "address3", + cityOrTown: "City", + state: "State", + postalCode: "1234", + country: "country", + ) + return cipherState + } + + func loginState( // swiftlint:disable:this function_body_length + canViewPassword: Bool = true, + collectionIds: [String] = ["1", "2"], + isFavorite: Bool = false, + isPasswordVisible: Bool = true, + hasPremium: Bool = true, + hasTotp: Bool = true, + ) -> CipherItemState { + var cipherState = CipherItemState( + existing: .fixture( + collectionIds: collectionIds, + favorite: isFavorite, + id: "fake-id", + ), + hasPremium: hasPremium, + )! + cipherState.accountHasPremium = hasPremium + cipherState.allUserCollections = [ + .fixture(id: "1", name: "Collection 1"), + .fixture(id: "2", name: "Collection 2"), + ] + cipherState.collectionIds = collectionIds + cipherState.folderId = "1" + cipherState.folders = [.custom(.fixture(id: "1", name: "Folder"))] + cipherState.folderName = "Folder" + cipherState.name = "Example" + cipherState.notes = "Notes" + cipherState.organizationName = "Organization" + cipherState.updatedDate = Date(year: 2023, month: 11, day: 11, hour: 9, minute: 41) + cipherState.loginState.canViewPassword = canViewPassword + cipherState.loginState.fido2Credentials = [.fixture()] + cipherState.loginState.isPasswordVisible = isPasswordVisible + cipherState.loginState.password = "Password1234!" + cipherState.loginState.passwordHistoryCount = 4 + cipherState.loginState.passwordUpdatedDate = Date(year: 2023, month: 11, day: 11, hour: 9, minute: 41) + cipherState.loginState.username = "email@example.com" + if hasTotp { + cipherState.loginState.totpState = .init( + authKeyModel: .init(authenticatorKey: .standardTotpKey), + codeModel: .init( + code: "032823", + codeGenerationDate: Date(year: 2023, month: 12, day: 31, minute: 0, second: 33), + period: 30, + ), + ) + } + cipherState.loginState.uris = [ + UriState( + matchType: .custom(.startsWith), + uri: "https://www.example.com", + ), + UriState( + matchType: .custom(.exact), + uri: "https://www.example.com/account/login", + ), + ] + + cipherState.customFieldsState.customFields = [ + CustomFieldState( + linkedIdType: nil, + name: "Text", + type: .text, + value: "Value", + ), + CustomFieldState( + linkedIdType: nil, + name: "Text empty", + type: .text, + value: nil, + ), + CustomFieldState( + isPasswordVisible: false, + linkedIdType: nil, + name: "Hidden Hidden", + type: .hidden, + value: "pa$$w0rd", + ), + CustomFieldState( + isPasswordVisible: true, + linkedIdType: nil, + name: "Hidden Shown", + type: .hidden, + value: "pa$$w0rd", + ), + CustomFieldState( + linkedIdType: nil, + name: "Boolean True", + type: .boolean, + value: "true", + ), + CustomFieldState( + linkedIdType: nil, + name: "Boolean False", + type: .boolean, + value: "false", + ), + CustomFieldState( + linkedIdType: .loginUsername, + name: "Linked", + type: .linked, + value: nil, + ), + ] + return cipherState + } + + @MainActor + func disabletest_snapshot_identity_withAllValues() { + processor.state.loadingState = .data(identityState()) + assertSnapshot(of: subject, as: .portrait(heightMultiple: 1.5)) + } + + @MainActor + func disabletest_snapshot_identity_withAllValues_largeText() { + processor.state.loadingState = .data(identityState()) + assertSnapshot(of: subject, as: .tallPortraitAX5(heightMultiple: 4)) + } + + @MainActor + func disabletest_snapshot_login_disabledViewPassword() { + processor.state.loadingState = .data( + loginState( + canViewPassword: false, + isPasswordVisible: false, + ), + ) + + assertSnapshot(of: subject, as: .tallPortrait) + } + + @MainActor + func disabletest_snapshot_login_empty() { + let loginState = CipherItemState( + existing: .fixture( + favorite: true, + id: "fake-id", + ), + hasPremium: true, + )! + processor.state.loadingState = .data(loginState) + + assertSnapshot(of: subject, as: .defaultPortrait) + } + + @MainActor + func disabletest_snapshot_login_withAllValues() { + processor.state.loadingState = .data(loginState(isFavorite: true)) + assertSnapshot(of: subject, as: .tallPortrait) + } + + @MainActor + func disabletest_snapshot_login_withAllValues_noPremium() { + let loginState = loginState(hasPremium: false) + processor.state.loadingState = .data(loginState) + assertSnapshot(of: subject, as: .tallPortrait) + } + + @MainActor + func disabletest_snapshot_login_withAllValues_noPremium_largeText() { + let loginState = loginState(hasPremium: false) + processor.state.loadingState = .data(loginState) + assertSnapshot(of: subject, as: .tallPortraitAX5(heightMultiple: 5)) + } + + @MainActor + func disabletest_snapshot_login_withAllValues_largeText() { + processor.state.loadingState = .data(loginState()) + assertSnapshot(of: subject, as: .tallPortraitAX5(heightMultiple: 5)) + } + + @MainActor + func disabletest_snapshot_login_withAllValues_exceptTotp_noPremium() { + let loginState = loginState(hasPremium: false, hasTotp: false) + processor.state.loadingState = .data(loginState) + assertSnapshot(of: subject, as: .tallPortrait) + } + + @MainActor + func disabletest_snapshot_login_withAllValuesExceptOrganization() { + var state = loginState(collectionIds: []) + state.organizationId = nil + state.organizationName = nil + state.collectionIds = [] + state.allUserCollections = [] + processor.state.loadingState = .data(state) + assertSnapshot(of: subject, as: .tallPortrait) + } + + @MainActor + func disabletest_snapshot_login_withAllValuesShowMore() { + let state = loginState(isFavorite: true) + processor.state.loadingState = .data(state) + assertSnapshot(of: subject, as: .tallPortrait) + } + + /// Snapshots the previews for card types. + @MainActor + func disabletest_snapshot_previews_card() { + assertSnapshot( + of: ViewItemView_Previews.cardPreview, + as: .defaultPortrait, + ) + } + + /// Snapshots the previews for card types. + @MainActor + func disabletest_snapshot_previews_card_dark() { + assertSnapshot( + of: ViewItemView_Previews.cardPreview, + as: .defaultPortraitDark, + ) + } + + /// Snapshots the previews for card types. + @MainActor + func disabletest_snapshot_previews_card_largeText() { + assertSnapshot( + of: ViewItemView_Previews.cardPreview, + as: .tallPortraitAX5(heightMultiple: 3), + ) + } + + /// Snapshots the previews for login types. + @MainActor + func disabletest_snapshot_previews_login() { + assertSnapshot( + of: ViewItemView_Previews.loginPreview, + as: .tallPortrait, + ) + } + + /// Snapshots the previews for login types. + @MainActor + func disabletest_snapshot_previews_login_dark() { + assertSnapshot( + of: ViewItemView_Previews.loginPreview, + as: .portraitDark(heightMultiple: 2), + ) + } + + /// Snapshots the previews for login types. + @MainActor + func disabletest_snapshot_previews_login_largeText() { + assertSnapshot( + of: ViewItemView_Previews.loginPreview, + as: .tallPortraitAX5(heightMultiple: 4), + ) + } + + /// Snapshots the previews for secure note types. + @MainActor + func disabletest_snapshot_previews_secureNote() { + assertSnapshot( + of: ViewItemView_Previews.secureNotePreview, + as: .defaultPortrait, + ) + } + + /// Snapshots the previews for login types. + @MainActor + func disabletest_snapshot_previews_sshKey() { + assertSnapshot( + of: ViewItemView_Previews.sshKeyPreview, + as: .tallPortrait, + ) + } + + /// Snapshots the previews for SSH key type. + @MainActor + func disabletest_snapshot_sshKey() { + processor.state.loadingState = + .data( + sshKeyCipherItemState( + canViewPrivateKey: true, + isPrivateKeyVisible: false, + ), + ) + assertSnapshots( + of: subject, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } + + /// Snapshots the previews for SSH key type when private key is visible. + @MainActor + func disabletest_snapshot_sshKeyPrivateKeyVisible() { + processor.state.loadingState = + .data( + sshKeyCipherItemState( + canViewPrivateKey: true, + isPrivateKeyVisible: true, + ), + ) + assertSnapshots( + of: subject, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } + + /// Snapshots the previews for SSH key type when `canViewPrivateKey` is `false`. + @MainActor + func disabletest_snapshot_sshKeyCantViewPrivateKey() { + processor.state.loadingState = + .data( + sshKeyCipherItemState( + canViewPrivateKey: false, + isPrivateKeyVisible: false, + ), + ) + assertSnapshots( + of: subject, + as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], + ) + } + + // MARK: Private + + /// Creates a `CipherItemState` for an SSH key item. + /// - Parameters: + /// - canViewPrivateKey: Whether the private key can be viewed. + /// - isPrivateKeyVisible: Whether the private key is visible + /// - Returns: The `CipherItemState` for SSH key item. + private func sshKeyCipherItemState(canViewPrivateKey: Bool, isPrivateKeyVisible: Bool) -> CipherItemState { + var state = CipherItemState( + existing: .fixture( + id: "fake-id", + type: .sshKey, + ), + hasPremium: true, + )! + state.name = "Example" + state.type = .sshKey + state.sshKeyState = SSHKeyItemState( + canViewPrivateKey: canViewPrivateKey, + isPrivateKeyVisible: isPrivateKeyVisible, + privateKey: "ajsdfopij1ZXCVZXC12312QW", + publicKey: "ssh-ed25519 AAAAA/asdjfoiwejrpo23323j23ASdfas", + keyFingerprint: "SHA-256:2qwer233ADJOIq1adfweqe21321qw", + ) + return state + } +} diff --git a/BitwardenShared/UI/Vault/VaultItem/ViewItem/ViewItemViewTests.swift b/BitwardenShared/UI/Vault/VaultItem/ViewItem/ViewItemView+ViewInspectorTests.swift similarity index 73% rename from BitwardenShared/UI/Vault/VaultItem/ViewItem/ViewItemViewTests.swift rename to BitwardenShared/UI/Vault/VaultItem/ViewItem/ViewItemView+ViewInspectorTests.swift index ee16db18e..2cbb9f567 100644 --- a/BitwardenShared/UI/Vault/VaultItem/ViewItem/ViewItemViewTests.swift +++ b/BitwardenShared/UI/Vault/VaultItem/ViewItem/ViewItemView+ViewInspectorTests.swift @@ -1,8 +1,8 @@ +// swiftlint:disable:this file_name import BitwardenKit import BitwardenKitMocks import BitwardenResources import BitwardenSdk -import SnapshotTesting import SwiftUI import ViewInspector import XCTest @@ -137,7 +137,7 @@ class ViewItemViewTests: BitwardenTestCase { // swiftlint:disable:this type_body /// Tapping the dismiss button dispatches the `.dismissPressed` action. @MainActor func test_dismissButton_tap() throws { - var button = try subject.inspect().findCloseToolbarButton() + let button = try subject.inspect().findCloseToolbarButton() try button.tap() XCTAssertEqual(processor.dispatchedActions.last, .dismissPressed) } @@ -330,12 +330,6 @@ class ViewItemViewTests: BitwardenTestCase { // swiftlint:disable:this type_body // MARK: Snapshots - @MainActor - func disabletest_snapshot_loading() { - processor.state.loadingState = .loading(nil) - assertSnapshot(of: subject, as: .defaultPortrait) - } - func identityState() -> CipherItemState { var cipherState = CipherItemState( existing: .fixture( @@ -479,215 +473,6 @@ class ViewItemViewTests: BitwardenTestCase { // swiftlint:disable:this type_body return cipherState } - @MainActor - func disabletest_snapshot_identity_withAllValues() { - processor.state.loadingState = .data(identityState()) - assertSnapshot(of: subject, as: .portrait(heightMultiple: 1.5)) - } - - @MainActor - func disabletest_snapshot_identity_withAllValues_largeText() { - processor.state.loadingState = .data(identityState()) - assertSnapshot(of: subject, as: .tallPortraitAX5(heightMultiple: 4)) - } - - @MainActor - func disabletest_snapshot_login_disabledViewPassword() { - processor.state.loadingState = .data( - loginState( - canViewPassword: false, - isPasswordVisible: false, - ), - ) - - assertSnapshot(of: subject, as: .tallPortrait) - } - - @MainActor - func disabletest_snapshot_login_empty() { - let loginState = CipherItemState( - existing: .fixture( - favorite: true, - id: "fake-id", - ), - hasPremium: true, - )! - processor.state.loadingState = .data(loginState) - - assertSnapshot(of: subject, as: .defaultPortrait) - } - - @MainActor - func disabletest_snapshot_login_withAllValues() { - processor.state.loadingState = .data(loginState(isFavorite: true)) - assertSnapshot(of: subject, as: .tallPortrait) - } - - @MainActor - func disabletest_snapshot_login_withAllValues_noPremium() { - let loginState = loginState(hasPremium: false) - processor.state.loadingState = .data(loginState) - assertSnapshot(of: subject, as: .tallPortrait) - } - - @MainActor - func disabletest_snapshot_login_withAllValues_noPremium_largeText() { - let loginState = loginState(hasPremium: false) - processor.state.loadingState = .data(loginState) - assertSnapshot(of: subject, as: .tallPortraitAX5(heightMultiple: 5)) - } - - @MainActor - func disabletest_snapshot_login_withAllValues_largeText() { - processor.state.loadingState = .data(loginState()) - assertSnapshot(of: subject, as: .tallPortraitAX5(heightMultiple: 5)) - } - - @MainActor - func disabletest_snapshot_login_withAllValues_exceptTotp_noPremium() { - let loginState = loginState(hasPremium: false, hasTotp: false) - processor.state.loadingState = .data(loginState) - assertSnapshot(of: subject, as: .tallPortrait) - } - - @MainActor - func disabletest_snapshot_login_withAllValuesExceptOrganization() { - var state = loginState(collectionIds: []) - state.organizationId = nil - state.organizationName = nil - state.collectionIds = [] - state.allUserCollections = [] - processor.state.loadingState = .data(state) - assertSnapshot(of: subject, as: .tallPortrait) - } - - @MainActor - func disabletest_snapshot_login_withAllValuesShowMore() { - let state = loginState(isFavorite: true) - processor.state.loadingState = .data(state) - assertSnapshot(of: subject, as: .tallPortrait) - } - - /// Snapshots the previews for card types. - @MainActor - func disabletest_snapshot_previews_card() { - assertSnapshot( - of: ViewItemView_Previews.cardPreview, - as: .defaultPortrait, - ) - } - - /// Snapshots the previews for card types. - @MainActor - func disabletest_snapshot_previews_card_dark() { - assertSnapshot( - of: ViewItemView_Previews.cardPreview, - as: .defaultPortraitDark, - ) - } - - /// Snapshots the previews for card types. - @MainActor - func disabletest_snapshot_previews_card_largeText() { - assertSnapshot( - of: ViewItemView_Previews.cardPreview, - as: .tallPortraitAX5(heightMultiple: 3), - ) - } - - /// Snapshots the previews for login types. - @MainActor - func disabletest_snapshot_previews_login() { - assertSnapshot( - of: ViewItemView_Previews.loginPreview, - as: .tallPortrait, - ) - } - - /// Snapshots the previews for login types. - @MainActor - func disabletest_snapshot_previews_login_dark() { - assertSnapshot( - of: ViewItemView_Previews.loginPreview, - as: .portraitDark(heightMultiple: 2), - ) - } - - /// Snapshots the previews for login types. - @MainActor - func disabletest_snapshot_previews_login_largeText() { - assertSnapshot( - of: ViewItemView_Previews.loginPreview, - as: .tallPortraitAX5(heightMultiple: 4), - ) - } - - /// Snapshots the previews for secure note types. - @MainActor - func disabletest_snapshot_previews_secureNote() { - assertSnapshot( - of: ViewItemView_Previews.secureNotePreview, - as: .defaultPortrait, - ) - } - - /// Snapshots the previews for login types. - @MainActor - func disabletest_snapshot_previews_sshKey() { - assertSnapshot( - of: ViewItemView_Previews.sshKeyPreview, - as: .tallPortrait, - ) - } - - /// Snapshots the previews for SSH key type. - @MainActor - func disabletest_snapshot_sshKey() { - processor.state.loadingState = - .data( - sshKeyCipherItemState( - canViewPrivateKey: true, - isPrivateKeyVisible: false, - ), - ) - assertSnapshots( - of: subject, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } - - /// Snapshots the previews for SSH key type when private key is visible. - @MainActor - func disabletest_snapshot_sshKeyPrivateKeyVisible() { - processor.state.loadingState = - .data( - sshKeyCipherItemState( - canViewPrivateKey: true, - isPrivateKeyVisible: true, - ), - ) - assertSnapshots( - of: subject, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } - - /// Snapshots the previews for SSH key type when `canViewPrivateKey` is `false`. - @MainActor - func disabletest_snapshot_sshKeyCantViewPrivateKey() { - processor.state.loadingState = - .data( - sshKeyCipherItemState( - canViewPrivateKey: false, - isPrivateKeyVisible: false, - ), - ) - assertSnapshots( - of: subject, - as: [.defaultPortrait, .defaultPortraitDark, .defaultPortraitAX5], - ) - } - // MARK: Private /// Creates a `CipherItemState` for an SSH key item. diff --git a/BitwardenShared/UI/Vault/VaultItem/ViewItem/ViewSSHKeyItemView/ViewSSHKeyItemViewTests.swift b/BitwardenShared/UI/Vault/VaultItem/ViewItem/ViewSSHKeyItemView/ViewSSHKeyItemView+ViewInspectorTests.swift similarity index 99% rename from BitwardenShared/UI/Vault/VaultItem/ViewItem/ViewSSHKeyItemView/ViewSSHKeyItemViewTests.swift rename to BitwardenShared/UI/Vault/VaultItem/ViewItem/ViewSSHKeyItemView/ViewSSHKeyItemView+ViewInspectorTests.swift index b08898d7e..0c2eccd6c 100644 --- a/BitwardenShared/UI/Vault/VaultItem/ViewItem/ViewSSHKeyItemView/ViewSSHKeyItemViewTests.swift +++ b/BitwardenShared/UI/Vault/VaultItem/ViewItem/ViewSSHKeyItemView/ViewSSHKeyItemView+ViewInspectorTests.swift @@ -1,4 +1,4 @@ -import SnapshotTesting +// swiftlint:disable:this file_name import XCTest @testable import BitwardenShared diff --git a/BitwardenShared/UI/Vault/Views/VaultItemDecorativeImageViewTests.swift b/BitwardenShared/UI/Vault/Views/VaultItemDecorativeImageView+SnapshotTests.swift similarity index 97% rename from BitwardenShared/UI/Vault/Views/VaultItemDecorativeImageViewTests.swift rename to BitwardenShared/UI/Vault/Views/VaultItemDecorativeImageView+SnapshotTests.swift index 4a7e508ef..978cb7f36 100644 --- a/BitwardenShared/UI/Vault/Views/VaultItemDecorativeImageViewTests.swift +++ b/BitwardenShared/UI/Vault/Views/VaultItemDecorativeImageView+SnapshotTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import BitwardenSdk import SnapshotTesting import SwiftUI diff --git a/BitwardenShared/UI/Vault/Views/VaultListItemRow/VaultListItemRowViewTests.swift b/BitwardenShared/UI/Vault/Views/VaultListItemRow/VaultListItemRowView+SnapshotTests.swift similarity index 84% rename from BitwardenShared/UI/Vault/Views/VaultListItemRow/VaultListItemRowViewTests.swift rename to BitwardenShared/UI/Vault/Views/VaultListItemRow/VaultListItemRowView+SnapshotTests.swift index d28e738c3..cd98be60d 100644 --- a/BitwardenShared/UI/Vault/Views/VaultListItemRow/VaultListItemRowViewTests.swift +++ b/BitwardenShared/UI/Vault/Views/VaultListItemRow/VaultListItemRowView+SnapshotTests.swift @@ -1,3 +1,4 @@ +// swiftlint:disable:this file_name import BitwardenKitMocks import BitwardenResources import SnapshotTesting @@ -32,33 +33,6 @@ class VaultListItemRowViewTests: BitwardenTestCase { timeProvider = nil } - // MARK: Tests - - /// Test that tapping the more button dispatches the `.morePressed` action. - @MainActor - func test_moreButton_tap() async throws { - let button = try subject.inspect().find(asyncButtonWithAccessibilityLabel: Localizations.more) - try await button.tap() - XCTAssertEqual(processor.effects.last, .morePressed) - } - - /// Test that tapping the totp copy button dispatches the `.copyTOTPCode` action. - @MainActor - func test_totpCopyButton_tap() throws { - let totp = VaultListTOTP.fixture() - processor.state = VaultListItemRowState( - item: .fixtureTOTP( - totp: totp, - ), - hasDivider: false, - showWebIcons: true, - ) - let button = try subject.inspect().find(buttonWithAccessibilityLabel: Localizations.copyTotp) - try button.tap() - waitFor(!processor.dispatchedActions.isEmpty) - XCTAssertEqual(processor.dispatchedActions.last, .copyTOTPCode(totp.totpCode.code)) - } - // MARK: Snapshots /// Test that the default view renders correctly. diff --git a/BitwardenShared/UI/Vault/Views/VaultListItemRow/VaultListItemRowView+ViewInspectorTests.swift b/BitwardenShared/UI/Vault/Views/VaultListItemRow/VaultListItemRowView+ViewInspectorTests.swift new file mode 100644 index 000000000..a5c94e8bf --- /dev/null +++ b/BitwardenShared/UI/Vault/Views/VaultListItemRow/VaultListItemRowView+ViewInspectorTests.swift @@ -0,0 +1,61 @@ +// swiftlint:disable:this file_name +import BitwardenKitMocks +import BitwardenResources +import XCTest + +@testable import BitwardenShared + +// MARK: - VaultListItemRowViewTests + +class VaultListItemRowViewTests: BitwardenTestCase { + // MARK: Properties + + var processor: MockProcessor! + var subject: VaultListItemRowView! + var timeProvider: MockTimeProvider! + + // MARK: Setup & Teardown + + override func setUp() { + super.setUp() + let state = VaultListItemRowState(item: .fixture(), hasDivider: false, showWebIcons: true) + processor = MockProcessor(state: state) + let store = Store(processor: processor) + timeProvider = MockTimeProvider(.mockTime(Date(year: 2023, month: 12, day: 31))) + subject = VaultListItemRowView(store: store, timeProvider: timeProvider) + } + + override func tearDown() { + super.tearDown() + processor = nil + subject = nil + timeProvider = nil + } + + // MARK: Tests + + /// Test that tapping the more button dispatches the `.morePressed` action. + @MainActor + func test_moreButton_tap() async throws { + let button = try subject.inspect().find(asyncButtonWithAccessibilityLabel: Localizations.more) + try await button.tap() + XCTAssertEqual(processor.effects.last, .morePressed) + } + + /// Test that tapping the totp copy button dispatches the `.copyTOTPCode` action. + @MainActor + func test_totpCopyButton_tap() throws { + let totp = VaultListTOTP.fixture() + processor.state = VaultListItemRowState( + item: .fixtureTOTP( + totp: totp, + ), + hasDivider: false, + showWebIcons: true, + ) + let button = try subject.inspect().find(buttonWithAccessibilityLabel: Localizations.copyTotp) + try button.tap() + waitFor(!processor.dispatchedActions.isEmpty) + XCTAssertEqual(processor.dispatchedActions.last, .copyTOTPCode(totp.totpCode.code)) + } +} diff --git a/TestHelpers/Support/BaseBitwardenTestCase.swift b/TestHelpers/Support/BaseBitwardenTestCase.swift index 039115d22..2bbd94410 100644 --- a/TestHelpers/Support/BaseBitwardenTestCase.swift +++ b/TestHelpers/Support/BaseBitwardenTestCase.swift @@ -6,7 +6,9 @@ open class BaseBitwardenTestCase: XCTestCase { @MainActor override open class func setUp() { - if UIDevice.current.name != "iPhone 17 Pro" || UIDevice.current.systemVersion != "26.0" { + let shouldSkipSimulatorCheck = ProcessInfo.processInfo.environment["SKIP_SIMULATOR_CHECK_FOR_TESTS"] == "true" + let isCorrectSimulator = UIDevice.current.name == "iPhone 17 Pro" || UIDevice.current.systemVersion == "26.0" + if !shouldSkipSimulatorCheck && !isCorrectSimulator { assertionFailure( """ Tests must be run using iOS 26.0 on an iPhone 17 Pro simulator. diff --git a/TestPlans/Authenticator-Default.xctestplan b/TestPlans/Authenticator-Default.xctestplan new file mode 100644 index 000000000..ce1cee470 --- /dev/null +++ b/TestPlans/Authenticator-Default.xctestplan @@ -0,0 +1,59 @@ +{ + "configurations" : [ + { + "id" : "D7A3F6C4-8E2B-4D9F-8C5A-6E4B3F2D1A9C", + "name" : "DefaultConfig", + "options" : { + + } + } + ], + "defaultOptions" : { + "commandLineArgumentEntries" : [ + { + "argument" : "-testing" + } + ], + "environmentVariableEntries" : [ + { + "key" : "TZ", + "value" : "UTC" + } + ], + "language" : "en", + "region" : "US", + "testExecutionOrdering" : "random", + "testTimeoutsEnabled" : true + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:Authenticator.xcodeproj", + "identifier" : "FFECA5139B78B2961268F363", + "name" : "AuthenticatorSharedSnapshotTests" + } + }, + { + "target" : { + "containerPath" : "container:Authenticator.xcodeproj", + "identifier" : "9A8D5254F0C841E3546E43BF", + "name" : "AuthenticatorSharedTests" + } + }, + { + "target" : { + "containerPath" : "container:Authenticator.xcodeproj", + "identifier" : "CF48CFC74FCC367F107BD1EF", + "name" : "AuthenticatorSharedViewInspectorTests" + } + }, + { + "target" : { + "containerPath" : "container:Authenticator.xcodeproj", + "identifier" : "F78877F8DDC2314213F71321", + "name" : "AuthenticatorTests" + } + } + ], + "version" : 1 +} diff --git a/TestPlans/Authenticator-Snapshot.xctestplan b/TestPlans/Authenticator-Snapshot.xctestplan new file mode 100644 index 000000000..e3d299f0a --- /dev/null +++ b/TestPlans/Authenticator-Snapshot.xctestplan @@ -0,0 +1,37 @@ +{ + "configurations" : [ + { + "id" : "E4B9D2A7-5C8F-4E3B-9D6A-7F5E4C3B2A1D", + "name" : "DefaultConfig", + "options" : { + + } + } + ], + "defaultOptions" : { + "commandLineArgumentEntries" : [ + { + "argument" : "-testing" + } + ], + "environmentVariableEntries" : [ + { + "key" : "TZ", + "value" : "UTC" + } + ], + "language" : "en", + "region" : "US", + "testTimeoutsEnabled" : true + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:Authenticator.xcodeproj", + "identifier" : "FFECA5139B78B2961268F363", + "name" : "AuthenticatorSharedSnapshotTests" + } + } + ], + "version" : 1 +} diff --git a/TestPlans/Authenticator-Unit.xctestplan b/TestPlans/Authenticator-Unit.xctestplan new file mode 100644 index 000000000..910fa4f71 --- /dev/null +++ b/TestPlans/Authenticator-Unit.xctestplan @@ -0,0 +1,48 @@ +{ + "configurations" : [ + { + "id" : "F6C3A8E5-9D4B-4F7C-8A9E-6B5D4F3C2E1A", + "name" : "DefaultConfig", + "options" : { + + } + } + ], + "defaultOptions" : { + "commandLineArgumentEntries" : [ + { + "argument" : "-testing" + } + ], + "environmentVariableEntries" : [ + { + "key" : "TZ", + "value" : "UTC" + }, + { + "key" : "SKIP_SIMULATOR_CHECK_FOR_TESTS", + "value" : "true" + } + ], + "language" : "en", + "region" : "US", + "testTimeoutsEnabled" : true + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:Authenticator.xcodeproj", + "identifier" : "F78877F8DDC2314213F71321", + "name" : "AuthenticatorTests" + } + }, + { + "target" : { + "containerPath" : "container:Authenticator.xcodeproj", + "identifier" : "9A8D5254F0C841E3546E43BF", + "name" : "AuthenticatorSharedTests" + } + } + ], + "version" : 1 +} diff --git a/TestPlans/Authenticator-ViewInspector.xctestplan b/TestPlans/Authenticator-ViewInspector.xctestplan new file mode 100644 index 000000000..436ed9f60 --- /dev/null +++ b/TestPlans/Authenticator-ViewInspector.xctestplan @@ -0,0 +1,37 @@ +{ + "configurations" : [ + { + "id" : "A8D5F3C7-4E9B-4A2D-9F8C-5E6B4D3A2F1C", + "name" : "DefaultConfig", + "options" : { + + } + } + ], + "defaultOptions" : { + "commandLineArgumentEntries" : [ + { + "argument" : "-testing" + } + ], + "environmentVariableEntries" : [ + { + "key" : "TZ", + "value" : "UTC" + } + ], + "language" : "en", + "region" : "US", + "testTimeoutsEnabled" : true + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:Authenticator.xcodeproj", + "identifier" : "CF48CFC74FCC367F107BD1EF", + "name" : "AuthenticatorSharedViewInspectorTests" + } + } + ], + "version" : 1 +} diff --git a/TestPlans/Bitwarden-Default.xctestplan b/TestPlans/Bitwarden-Default.xctestplan new file mode 100644 index 000000000..93be62c82 --- /dev/null +++ b/TestPlans/Bitwarden-Default.xctestplan @@ -0,0 +1,94 @@ +{ + "configurations" : [ + { + "id" : "1F1B495F-A80E-4BEF-8B13-35C0D33C74E9", + "name" : "DefaultConfig", + "options" : { + + } + } + ], + "defaultOptions" : { + "commandLineArgumentEntries" : [ + { + "argument" : "-testing" + } + ], + "environmentVariableEntries" : [ + { + "key" : "TZ", + "value" : "UTC" + } + ], + "language" : "en", + "region" : "US", + "testExecutionOrdering" : "random", + "testTimeoutsEnabled" : true + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:Bitwarden.xcodeproj", + "identifier" : "8E852F2FEA58332906A444C6", + "name" : "BitwardenActionExtensionTests" + } + }, + { + "target" : { + "containerPath" : "container:Bitwarden.xcodeproj", + "identifier" : "2AA7964F64AD34FCAE257E17", + "name" : "BitwardenTests" + } + }, + { + "target" : { + "containerPath" : "container:BitwardenKit.xcodeproj", + "identifier" : "9F7BDC2FAE9BA6BFD0EBF905", + "name" : "NetworkingTests" + } + }, + { + "target" : { + "containerPath" : "container:BitwardenKit.xcodeproj", + "identifier" : "192455E6FB7EBDE8BAB85489", + "name" : "BitwardenKitTests" + } + }, + { + "target" : { + "containerPath" : "container:Bitwarden.xcodeproj", + "identifier" : "417A98C7A214F8B5F141E702", + "name" : "BitwardenAutoFillExtensionTests" + } + }, + { + "target" : { + "containerPath" : "container:Bitwarden.xcodeproj", + "identifier" : "9B9276A12810F3EC19899819", + "name" : "BitwardenSharedSnapshotTests" + } + }, + { + "target" : { + "containerPath" : "container:Bitwarden.xcodeproj", + "identifier" : "C026D25C368010616A94990A", + "name" : "BitwardenShareExtensionTests" + } + }, + { + "target" : { + "containerPath" : "container:Bitwarden.xcodeproj", + "identifier" : "1ACA591B401F3A38DB33C366", + "name" : "BitwardenSharedTests" + } + }, + { + "target" : { + "containerPath" : "container:Bitwarden.xcodeproj", + "identifier" : "65DAC3D69CB63D5E39AA4601", + "name" : "BitwardenSharedViewInspectorTests" + } + } + ], + "version" : 1 +} diff --git a/TestPlans/Bitwarden-Snapshot.xctestplan b/TestPlans/Bitwarden-Snapshot.xctestplan new file mode 100644 index 000000000..bd087d7da --- /dev/null +++ b/TestPlans/Bitwarden-Snapshot.xctestplan @@ -0,0 +1,37 @@ +{ + "configurations" : [ + { + "id" : "AE7F8439-11C3-4A5A-AB62-C322355EE6A5", + "name" : "DefaultConfig", + "options" : { + + } + } + ], + "defaultOptions" : { + "commandLineArgumentEntries" : [ + { + "argument" : "-testing" + } + ], + "environmentVariableEntries" : [ + { + "key" : "TZ", + "value" : "UTC" + } + ], + "language" : "en", + "region" : "US", + "testTimeoutsEnabled" : true + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:Bitwarden.xcodeproj", + "identifier" : "9B9276A12810F3EC19899819", + "name" : "BitwardenSharedSnapshotTests" + } + } + ], + "version" : 1 +} diff --git a/TestPlans/Bitwarden-Unit.xctestplan b/TestPlans/Bitwarden-Unit.xctestplan new file mode 100644 index 000000000..aa93c8289 --- /dev/null +++ b/TestPlans/Bitwarden-Unit.xctestplan @@ -0,0 +1,69 @@ +{ + "configurations" : [ + { + "id" : "7F1F3659-44A5-4DB0-8565-F699A65B2C7D", + "name" : "DefaultConfig", + "options" : { + + } + } + ], + "defaultOptions" : { + "commandLineArgumentEntries" : [ + { + "argument" : "-testing" + } + ], + "environmentVariableEntries" : [ + { + "key" : "TZ", + "value" : "UTC" + }, + { + "key" : "SKIP_SIMULATOR_CHECK_FOR_TESTS", + "value" : "true" + } + ], + "language" : "en", + "region" : "US", + "testTimeoutsEnabled" : true + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:Bitwarden.xcodeproj", + "identifier" : "C026D25C368010616A94990A", + "name" : "BitwardenShareExtensionTests" + } + }, + { + "target" : { + "containerPath" : "container:Bitwarden.xcodeproj", + "identifier" : "1ACA591B401F3A38DB33C366", + "name" : "BitwardenSharedTests" + } + }, + { + "target" : { + "containerPath" : "container:Bitwarden.xcodeproj", + "identifier" : "417A98C7A214F8B5F141E702", + "name" : "BitwardenAutoFillExtensionTests" + } + }, + { + "target" : { + "containerPath" : "container:Bitwarden.xcodeproj", + "identifier" : "2AA7964F64AD34FCAE257E17", + "name" : "BitwardenTests" + } + }, + { + "target" : { + "containerPath" : "container:Bitwarden.xcodeproj", + "identifier" : "8E852F2FEA58332906A444C6", + "name" : "BitwardenActionExtensionTests" + } + } + ], + "version" : 1 +} diff --git a/TestPlans/Bitwarden-ViewInspector.xctestplan b/TestPlans/Bitwarden-ViewInspector.xctestplan new file mode 100644 index 000000000..43f815d9b --- /dev/null +++ b/TestPlans/Bitwarden-ViewInspector.xctestplan @@ -0,0 +1,37 @@ +{ + "configurations" : [ + { + "id" : "D4F7B2E5-8A3C-4D6F-9B8E-5C4A3F2E1D7B", + "name" : "DefaultConfig", + "options" : { + + } + } + ], + "defaultOptions" : { + "commandLineArgumentEntries" : [ + { + "argument" : "-testing" + } + ], + "environmentVariableEntries" : [ + { + "key" : "TZ", + "value" : "UTC" + } + ], + "language" : "en", + "region" : "US", + "testTimeoutsEnabled" : true + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:Bitwarden.xcodeproj", + "identifier" : "65DAC3D69CB63D5E39AA4601", + "name" : "BitwardenSharedViewInspectorTests" + } + } + ], + "version" : 1 +} diff --git a/TestPlans/BitwardenKit-Default.xctestplan b/TestPlans/BitwardenKit-Default.xctestplan new file mode 100644 index 000000000..6fd98c23a --- /dev/null +++ b/TestPlans/BitwardenKit-Default.xctestplan @@ -0,0 +1,66 @@ +{ + "configurations" : [ + { + "id" : "C6E9A4F7-3D8B-4C5E-9A2F-7B6D5E4C3A2B", + "name" : "DefaultConfig", + "options" : { + + } + } + ], + "defaultOptions" : { + "commandLineArgumentEntries" : [ + { + "argument" : "-testing" + } + ], + "environmentVariableEntries" : [ + { + "key" : "TZ", + "value" : "UTC" + } + ], + "language" : "en", + "region" : "US", + "testExecutionOrdering" : "random", + "testTimeoutsEnabled" : true + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:BitwardenKit.xcodeproj", + "identifier" : "9F7BDC2FAE9BA6BFD0EBF905", + "name" : "NetworkingTests" + } + }, + { + "target" : { + "containerPath" : "container:BitwardenKit.xcodeproj", + "identifier" : "11D20029373CEF56CBBCF0AA", + "name" : "AuthenticatorBridgeKitTests" + } + }, + { + "target" : { + "containerPath" : "container:BitwardenKit.xcodeproj", + "identifier" : "192455E6FB7EBDE8BAB85489", + "name" : "BitwardenKitTests" + } + }, + { + "target" : { + "containerPath" : "container:BitwardenKit.xcodeproj", + "identifier" : "0F0F8167EDD3A9370CA429CE", + "name" : "BitwardenKitSnapshotTests" + } + }, + { + "target" : { + "containerPath" : "container:BitwardenKit.xcodeproj", + "identifier" : "27C53FBF98252CF56973FD34", + "name" : "BitwardenKitViewInspectorTests" + } + } + ], + "version" : 1 +} diff --git a/TestPlans/BitwardenKit-Snapshot.xctestplan b/TestPlans/BitwardenKit-Snapshot.xctestplan new file mode 100644 index 000000000..1e8ddad9c --- /dev/null +++ b/TestPlans/BitwardenKit-Snapshot.xctestplan @@ -0,0 +1,37 @@ +{ + "configurations" : [ + { + "id" : "B2D5F8A3-9C4E-4B2D-8F7A-5E4C3B2A1D9F", + "name" : "DefaultConfig", + "options" : { + + } + } + ], + "defaultOptions" : { + "commandLineArgumentEntries" : [ + { + "argument" : "-testing" + } + ], + "environmentVariableEntries" : [ + { + "key" : "TZ", + "value" : "UTC" + } + ], + "language" : "en", + "region" : "US", + "testTimeoutsEnabled" : true + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:BitwardenKit.xcodeproj", + "identifier" : "0F0F8167EDD3A9370CA429CE", + "name" : "BitwardenKitSnapshotTests" + } + } + ], + "version" : 1 +} diff --git a/TestPlans/BitwardenKit-Unit.xctestplan b/TestPlans/BitwardenKit-Unit.xctestplan new file mode 100644 index 000000000..e1658bae1 --- /dev/null +++ b/TestPlans/BitwardenKit-Unit.xctestplan @@ -0,0 +1,48 @@ +{ + "configurations" : [ + { + "id" : "A7C4E9F2-8B3D-4A1C-9E7F-6D5B4C3A2E1F", + "name" : "DefaultConfig", + "options" : { + + } + } + ], + "defaultOptions" : { + "commandLineArgumentEntries" : [ + { + "argument" : "-testing" + } + ], + "environmentVariableEntries" : [ + { + "key" : "TZ", + "value" : "UTC" + }, + { + "key" : "SKIP_SIMULATOR_CHECK_FOR_TESTS", + "value" : "true" + } + ], + "language" : "en", + "region" : "US", + "testTimeoutsEnabled" : true + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:BitwardenKit.xcodeproj", + "identifier" : "192455E6FB7EBDE8BAB85489", + "name" : "BitwardenKitTests" + } + }, + { + "target" : { + "containerPath" : "container:BitwardenKit.xcodeproj", + "identifier" : "11D20029373CEF56CBBCF0AA", + "name" : "AuthenticatorBridgeKitTests" + } + } + ], + "version" : 1 +} diff --git a/TestPlans/BitwardenKit-ViewInspector.xctestplan b/TestPlans/BitwardenKit-ViewInspector.xctestplan new file mode 100644 index 000000000..22f8f4c08 --- /dev/null +++ b/TestPlans/BitwardenKit-ViewInspector.xctestplan @@ -0,0 +1,37 @@ +{ + "configurations" : [ + { + "id" : "3F8B9C2A-5D4E-4F1B-9A8C-7E6D5C4B3A2F", + "name" : "DefaultConfig", + "options" : { + + } + } + ], + "defaultOptions" : { + "commandLineArgumentEntries" : [ + { + "argument" : "-testing" + } + ], + "environmentVariableEntries" : [ + { + "key" : "TZ", + "value" : "UTC" + } + ], + "language" : "en", + "region" : "US", + "testTimeoutsEnabled" : true + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:BitwardenKit.xcodeproj", + "identifier" : "27C53FBF98252CF56973FD34", + "name" : "BitwardenKitViewInspectorTests" + } + } + ], + "version" : 1 +} diff --git a/project-bwa.yml b/project-bwa.yml index 8e8079fab..0b3b2f0e8 100644 --- a/project-bwa.yml +++ b/project-bwa.yml @@ -44,11 +44,19 @@ schemes: - BitwardenKit/AuthenticatorBridgeKitTests - BitwardenKit/BitwardenKitTests - BitwardenKit/NetworkingTests + testPlans: + - path: TestPlans/Authenticator-Default.xctestplan + defaultPlan: true + - path: TestPlans/Authenticator-Unit.xctestplan + - path: TestPlans/Authenticator-Snapshot.xctestplan + - path: TestPlans/Authenticator-ViewInspector.xctestplan AuthenticatorShared: build: targets: AuthenticatorShared: all AuthenticatorSharedTests: [test] + AuthenticatorSharedSnapshotTests: [test] + AuthenticatorSharedViewInspectorTests: [test] test: commandLineArguments: "-testing": true @@ -57,6 +65,14 @@ schemes: gatherCoverageData: true targets: - AuthenticatorSharedTests + - AuthenticatorSharedSnapshotTests + - AuthenticatorSharedViewInspectorTests + testPlans: + - path: TestPlans/Authenticator-Default.xctestplan + defaultPlan: true + - path: TestPlans/Authenticator-Unit.xctestplan + - path: TestPlans/Authenticator-Snapshot.xctestplan + - path: TestPlans/Authenticator-ViewInspector.xctestplan targets: Authenticator: type: application @@ -217,7 +233,42 @@ targets: - "**/*Tests.*" - "**/TestHelpers/*" - "**/Fixtures/*" + excludes: + - "**/*SnapshotTests.*" + - "**/*ViewInspectorTests.*" - path: GlobalTestHelpers-bwa + excludes: + - "**/InspectableView.*" + - path: AuthenticatorShared/Sourcery/Generated + optional: true + - path: AuthenticatorShared/Sourcery/Generated/AutoMockable.generated.swift + optional: true + dependencies: + - target: Authenticator + - target: AuthenticatorShared + - target: BitwardenKit/AuthenticatorBridgeKitMocks + - target: BitwardenKit/BitwardenKitMocks + - target: BitwardenKit/TestHelpers + - package: SnapshotTesting + product: InlineSnapshotTesting + randomExecutionOrder: true + AuthenticatorSharedSnapshotTests: + type: bundle.unit-test + platform: iOS + settings: + base: + BUNDLE_LOADER: "$(TEST_HOST)" + TEST_HOST: "$(BUILT_PRODUCTS_DIR)/Authenticator.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Authenticator" + INFOPLIST_FILE: AuthenticatorShared/UI/Platform/Application/TestHelpers/Support/Info.plist + sources: + - path: AuthenticatorShared + includes: + - "**/*SnapshotTests.*" + - "**/TestHelpers/*" + - "**/Fixtures/*" + - path: GlobalTestHelpers-bwa + excludes: + - "**/InspectableView.*" - path: AuthenticatorShared/Sourcery/Generated optional: true - path: AuthenticatorShared/Sourcery/Generated/AutoMockable.generated.swift @@ -231,5 +282,31 @@ targets: - package: SnapshotTesting - package: SnapshotTesting product: InlineSnapshotTesting + randomExecutionOrder: true + AuthenticatorSharedViewInspectorTests: + type: bundle.unit-test + platform: iOS + settings: + base: + BUNDLE_LOADER: "$(TEST_HOST)" + TEST_HOST: "$(BUILT_PRODUCTS_DIR)/Authenticator.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Authenticator" + INFOPLIST_FILE: AuthenticatorShared/UI/Platform/Application/TestHelpers/Support/Info.plist + sources: + - path: AuthenticatorShared + includes: + - "**/*ViewInspectorTests.*" + - "**/TestHelpers/*" + - "**/Fixtures/*" + - path: GlobalTestHelpers-bwa + - path: AuthenticatorShared/Sourcery/Generated + optional: true + - path: AuthenticatorShared/Sourcery/Generated/AutoMockable.generated.swift + optional: true + dependencies: + - target: Authenticator + - target: AuthenticatorShared + - target: BitwardenKit/AuthenticatorBridgeKitMocks + - target: BitwardenKit/BitwardenKitMocks + - target: BitwardenKit/TestHelpers - package: ViewInspector randomExecutionOrder: true diff --git a/project-bwk.yml b/project-bwk.yml index 44bb77880..c2819f349 100644 --- a/project-bwk.yml +++ b/project-bwk.yml @@ -28,10 +28,20 @@ schemes: targets: BitwardenKit: all BitwardenKitTests: [test] + BitwardenKitSnapshotTests: [test] + BitwardenKitViewInspectorTests: [test] test: gatherCoverageData: true targets: - BitwardenKitTests + - BitwardenKitSnapshotTests + - BitwardenKitViewInspectorTests + testPlans: + - path: TestPlans/BitwardenKit-Default.xctestplan + defaultPlan: true + - path: TestPlans/BitwardenKit-Unit.xctestplan + - path: TestPlans/BitwardenKit-Snapshot.xctestplan + - path: TestPlans/BitwardenKit-ViewInspector.xctestplan BitwardenResources: build: targets: @@ -154,12 +164,49 @@ targets: includes: - "**/*Tests.*" - "**/TestHelpers/*" + excludes: + - "**/*SnapshotTests.*" + - "**/*ViewInspectorTests.*" + dependencies: + - target: AuthenticatorBridgeKitMocks + - target: BitwardenKit + - target: BitwardenKitMocks + - target: TestHelpers + randomExecutionOrder: true + BitwardenKitSnapshotTests: + type: bundle.unit-test + platform: iOS + settings: + base: + INFOPLIST_FILE: BitwardenKit/Application/TestHelpers/Support/Info.plist + sources: + - path: BitwardenKit + includes: + - "**/*SnapshotTests.*" + - "**/TestHelpers/*" dependencies: - target: AuthenticatorBridgeKitMocks - target: BitwardenKit - target: BitwardenKitMocks - target: TestHelpers - package: SnapshotTesting + randomExecutionOrder: true + BitwardenKitViewInspectorTests: + type: bundle.unit-test + platform: iOS + settings: + base: + INFOPLIST_FILE: BitwardenKit/Application/TestHelpers/Support/Info.plist + sources: + - path: BitwardenKit + includes: + - "**/*ViewInspectorTests.*" + - "**/TestHelpers/*" + dependencies: + - target: AuthenticatorBridgeKitMocks + - target: BitwardenKit + - target: BitwardenKitMocks + - target: TestHelpers - package: ViewInspector randomExecutionOrder: true BitwardenResources: diff --git a/project-pm.yml b/project-pm.yml index ae691bd02..1a5002a9e 100644 --- a/project-pm.yml +++ b/project-pm.yml @@ -46,9 +46,17 @@ schemes: - BitwardenAutoFillExtensionTests - BitwardenShareExtensionTests - BitwardenSharedTests + - BitwardenSharedSnapshotTests + - BitwardenSharedViewInspectorTests - BitwardenKit/AuthenticatorBridgeKitTests - BitwardenKit/BitwardenKitTests - BitwardenKit/NetworkingTests + testPlans: + - path: TestPlans/Bitwarden-Default.xctestplan + defaultPlan: true + - path: TestPlans/Bitwarden-Unit.xctestplan + - path: TestPlans/Bitwarden-Snapshot.xctestplan + - path: TestPlans/Bitwarden-ViewInspector.xctestplan BitwardenActionExtension: build: targets: @@ -62,6 +70,10 @@ schemes: region: US targets: - BitwardenActionExtensionTests + testPlans: + - path: TestPlans/Bitwarden-Default.xctestplan + defaultPlan: true + - path: TestPlans/Bitwarden-Unit.xctestplan BitwardenAutoFillExtension: build: targets: @@ -75,6 +87,10 @@ schemes: region: US targets: - BitwardenAutoFillExtensionTests + testPlans: + - path: TestPlans/Bitwarden-Default.xctestplan + defaultPlan: true + - path: TestPlans/Bitwarden-Unit.xctestplan BitwardenShareExtension: build: targets: @@ -88,11 +104,17 @@ schemes: region: US targets: - BitwardenShareExtensionTests + testPlans: + - path: TestPlans/Bitwarden-Default.xctestplan + defaultPlan: true + - path: TestPlans/Bitwarden-Unit.xctestplan BitwardenShared: build: targets: BitwardenShared: all BitwardenSharedTests: [test] + BitwardenSharedSnapshotTests: [test] + BitwardenSharedViewInspectorTests: [test] test: commandLineArguments: "-testing": true @@ -103,6 +125,14 @@ schemes: region: US targets: - BitwardenSharedTests + - BitwardenSharedSnapshotTests + - BitwardenSharedViewInspectorTests + testPlans: + - path: TestPlans/Bitwarden-Default.xctestplan + defaultPlan: true + - path: TestPlans/Bitwarden-Unit.xctestplan + - path: TestPlans/Bitwarden-Snapshot.xctestplan + - path: TestPlans/Bitwarden-ViewInspector.xctestplan BitwardenWatchApp: build: targets: @@ -191,13 +221,13 @@ targets: - "**/*Tests.*" - "**/TestHelpers/*" - path: GlobalTestHelpers + excludes: + - "**/InspectableView.*" dependencies: - target: Bitwarden - target: BitwardenShared - target: BitwardenKit/BitwardenKitMocks - target: BitwardenKit/TestHelpers - - package: SnapshotTesting - - package: ViewInspector randomExecutionOrder: true BitwardenActionExtension: @@ -229,12 +259,12 @@ targets: - "**/*Tests.*" - "**/TestHelpers/*" - path: GlobalTestHelpers + excludes: + - "**/InspectableView.*" dependencies: - target: BitwardenActionExtension - target: BitwardenShared - target: BitwardenKit/TestHelpers - - package: SnapshotTesting - - package: ViewInspector randomExecutionOrder: true BitwardenAutoFillExtension: @@ -266,12 +296,12 @@ targets: - "**/*Tests.*" - "**/TestHelpers/*" - path: GlobalTestHelpers + excludes: + - "**/InspectableView.*" dependencies: - target: BitwardenAutoFillExtension - target: BitwardenShared - target: BitwardenKit/TestHelpers - - package: SnapshotTesting - - package: ViewInspector randomExecutionOrder: true BitwardenShareExtension: @@ -303,12 +333,12 @@ targets: - "**/*Tests.*" - "**/TestHelpers/*" - path: GlobalTestHelpers + excludes: + - "**/InspectableView.*" dependencies: - target: BitwardenShareExtension - target: BitwardenShared - target: BitwardenKit/TestHelpers - - package: SnapshotTesting - - package: ViewInspector randomExecutionOrder: true BitwardenShared: @@ -386,7 +416,12 @@ targets: - "**/*Tests.*" - "**/TestHelpers/*" - "**/Fixtures/*" + excludes: + - "**/*SnapshotTests.*" + - "**/*ViewInspectorTests.*" - path: GlobalTestHelpers + excludes: + - "**/InspectableView.*" - path: BitwardenShared/Sourcery/Generated optional: true - path: BitwardenShared/Sourcery/Generated/AutoMockable.generated.swift @@ -397,9 +432,69 @@ targets: - target: BitwardenKit/AuthenticatorBridgeKitMocks - target: BitwardenKit/BitwardenKitMocks - target: BitwardenKit/TestHelpers + - package: SnapshotTesting + product: InlineSnapshotTesting + randomExecutionOrder: true + BitwardenSharedSnapshotTests: + type: bundle.unit-test + platform: iOS + configFiles: + Debug: Configs/BitwardenSharedTests-Debug.xcconfig + Release: Configs/BitwardenSharedTests-Release.xcconfig + settings: + base: + BUNDLE_LOADER: "$(TEST_HOST)" + TEST_HOST: "$(BUILT_PRODUCTS_DIR)/Bitwarden.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Bitwarden" + INFOPLIST_FILE: BitwardenShared/UI/Platform/Application/TestHelpers/Support/Info.plist + sources: + - path: BitwardenShared + includes: + - "**/*SnapshotTests.*" + - "**/TestHelpers/*" + - "**/Fixtures/*" + - path: GlobalTestHelpers + excludes: + - "**/InspectableView.*" + - path: BitwardenShared/Sourcery/Generated + optional: true + - path: BitwardenShared/Sourcery/Generated/AutoMockable.generated.swift + optional: true + dependencies: + - target: Bitwarden + - target: BitwardenShared + - target: BitwardenKit/BitwardenKitMocks + - target: BitwardenKit/TestHelpers - package: SnapshotTesting - package: SnapshotTesting product: InlineSnapshotTesting + randomExecutionOrder: true + BitwardenSharedViewInspectorTests: + type: bundle.unit-test + platform: iOS + configFiles: + Debug: Configs/BitwardenSharedTests-Debug.xcconfig + Release: Configs/BitwardenSharedTests-Release.xcconfig + settings: + base: + BUNDLE_LOADER: "$(TEST_HOST)" + TEST_HOST: "$(BUILT_PRODUCTS_DIR)/Bitwarden.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Bitwarden" + INFOPLIST_FILE: BitwardenShared/UI/Platform/Application/TestHelpers/Support/Info.plist + sources: + - path: BitwardenShared + includes: + - "**/*ViewInspectorTests.*" + - "**/TestHelpers/*" + - "**/Fixtures/*" + - path: GlobalTestHelpers + - path: BitwardenShared/Sourcery/Generated + optional: true + - path: BitwardenShared/Sourcery/Generated/AutoMockable.generated.swift + optional: true + dependencies: + - target: Bitwarden + - target: BitwardenShared + - target: BitwardenKit/BitwardenKitMocks + - target: BitwardenKit/TestHelpers - package: ViewInspector randomExecutionOrder: true