From b875c1be664ec7164b6bd4c114334ae3e80580ec Mon Sep 17 00:00:00 2001 From: Jon Petersson Date: Wed, 29 May 2024 17:09:15 +0200 Subject: [PATCH] Rewrite screenshot tests to use new syntax --- ios/MullvadVPN.xcodeproj/project.pbxproj | 207 +++--------------- .../xcschemes/MullvadVPNScreenshots.xcscheme | 81 ------- ios/MullvadVPNScreenshots/Info.plist | 28 --- .../MullvadVPNScreenshots.swift | 154 ------------- .../BaseUITestCase.swift | 0 .../LoggedInWithTimeUITestCase.swift | 0 .../LoggedOutUITestCase.swift | 0 ios/MullvadVPNUITests/CustomListsTests.swift | 4 +- .../Pages/AddCustomListLocationsPage.swift | 16 ++ .../Pages/CustomListPage.swift | 8 +- .../Pages/DNSSettingsPage.swift | 2 +- .../Pages/EditCustomListLocationsPage.swift | 6 +- .../Pages/TunnelControlPage.swift | 4 + .../Pages/VPNSettingsPage.swift | 12 +- .../Screenshots/ScreenshotTests.swift | 151 +++++++++++++ .../Screenshots}/SnapshotHelper.swift | 128 ++++++----- .../MullvadVPNScreenshots.xctestplan | 12 +- ios/TestPlans/MullvadVPNUITestsAll.xctestplan | 1 + 18 files changed, 304 insertions(+), 510 deletions(-) delete mode 100644 ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/MullvadVPNScreenshots.xcscheme delete mode 100644 ios/MullvadVPNScreenshots/Info.plist delete mode 100644 ios/MullvadVPNScreenshots/MullvadVPNScreenshots.swift rename ios/MullvadVPNUITests/{Test base classes => Base}/BaseUITestCase.swift (100%) rename ios/MullvadVPNUITests/{Test base classes => Base}/LoggedInWithTimeUITestCase.swift (100%) rename ios/MullvadVPNUITests/{Test base classes => Base}/LoggedOutUITestCase.swift (100%) create mode 100644 ios/MullvadVPNUITests/Pages/AddCustomListLocationsPage.swift create mode 100644 ios/MullvadVPNUITests/Screenshots/ScreenshotTests.swift rename ios/{MullvadVPNScreenshots => MullvadVPNUITests/Screenshots}/SnapshotHelper.swift (72%) diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj index 8e0a79894885..8ae7c3dd961e 100644 --- a/ios/MullvadVPN.xcodeproj/project.pbxproj +++ b/ios/MullvadVPN.xcodeproj/project.pbxproj @@ -334,8 +334,6 @@ 58CEB30A2AFD584700E6E088 /* CustomCellDisclosureHandling.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58CEB3092AFD584700E6E088 /* CustomCellDisclosureHandling.swift */; }; 58CEB30C2AFD586600E6E088 /* DynamicBackgroundConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58CEB30B2AFD586600E6E088 /* DynamicBackgroundConfiguration.swift */; }; 58CF95A22AD6F35800B59F5D /* ObservedState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58CF95A12AD6F35800B59F5D /* ObservedState.swift */; }; - 58D0C79E23F1CEBA00FE9BA7 /* SnapshotHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58D0C79D23F1CEBA00FE9BA7 /* SnapshotHelper.swift */; }; - 58D0C7A223F1CECF00FE9BA7 /* MullvadVPNScreenshots.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58D0C7A023F1CECF00FE9BA7 /* MullvadVPNScreenshots.swift */; }; 58D223A8294C8A490029F5F8 /* Operations.h in Headers */ = {isa = PBXBuildFile; fileRef = 58D223A7294C8A490029F5F8 /* Operations.h */; settings = {ATTRIBUTES = (Public, ); }; }; 58D223AC294C8A630029F5F8 /* GroupOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 589D28812846306C00F9A7B3 /* GroupOperation.swift */; }; 58D223AD294C8A630029F5F8 /* AsyncBlockOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580EE22324B3243100F9D8A1 /* AsyncBlockOperation.swift */; }; @@ -475,7 +473,6 @@ 7A02D4EB2A9CEC7A00C19E31 /* MullvadVPNScreenshots.xctestplan in Resources */ = {isa = PBXBuildFile; fileRef = 7A02D4EA2A9CEC7A00C19E31 /* MullvadVPNScreenshots.xctestplan */; }; 7A09C98129D99215000C2CAC /* String+FuzzyMatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A09C98029D99215000C2CAC /* String+FuzzyMatch.swift */; }; 7A0B311E2B303A0D004B12E0 /* AccessbilityIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0B311D2B303A0D004B12E0 /* AccessbilityIdentifier.swift */; }; - 7A0B311F2B303A11004B12E0 /* AccessbilityIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0B311D2B303A0D004B12E0 /* AccessbilityIdentifier.swift */; }; 7A0C0F632A979C4A0058EFCE /* Coordinator+Router.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0C0F622A979C4A0058EFCE /* Coordinator+Router.swift */; }; 7A11DD0B2A9495D400098CD8 /* AppRoutes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5802EBC42A8E44AC00E5CE4C /* AppRoutes.swift */; }; 7A12D0762B062D5C00E9602D /* URLSessionProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A12D0752B062D5C00E9602D /* URLSessionProtocol.swift */; }; @@ -499,6 +496,8 @@ 7A3FD1B72AD54ABD0042BEA6 /* AnyTransport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58BDEB982A98F4ED00F578F2 /* AnyTransport.swift */; }; 7A3FD1B82AD54AE60042BEA6 /* TimeServerProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58BDEB9A2A98F58600F578F2 /* TimeServerProxy.swift */; }; 7A42DEC92A05164100B209BE /* SettingsInputCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A42DEC82A05164100B209BE /* SettingsInputCell.swift */; }; + 7A45CFC62C05FF6A00D80B21 /* ScreenshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A45CFC22C05FF2F00D80B21 /* ScreenshotTests.swift */; }; + 7A45CFC72C071DD400D80B21 /* SnapshotHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58D0C79D23F1CEBA00FE9BA7 /* SnapshotHelper.swift */; }; 7A516C2E2B6D357500BBD33D /* URL+Scoping.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A516C2D2B6D357500BBD33D /* URL+Scoping.swift */; }; 7A516C3A2B7111A700BBD33D /* IPOverrideWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A516C392B7111A700BBD33D /* IPOverrideWrapper.swift */; }; 7A516C3C2B712F0B00BBD33D /* IPOverrideWrapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A516C3B2B712F0B00BBD33D /* IPOverrideWrapperTests.swift */; }; @@ -599,6 +598,7 @@ 7ABFB09E2BA316220074A49E /* RelayConstraintsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ABFB09D2BA316220074A49E /* RelayConstraintsTests.swift */; }; 7AC8A3AE2ABC6FBB00DC4939 /* SettingsHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AC8A3AD2ABC6FBB00DC4939 /* SettingsHeaderView.swift */; }; 7AC8A3AF2ABC71D600DC4939 /* TermsOfServiceCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9CCCA22A96302700DD6A34 /* TermsOfServiceCoordinator.swift */; }; + 7ACD79392C0DAADD00DBEE14 /* AddCustomListLocationsPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ACD79382C0DAADC00DBEE14 /* AddCustomListLocationsPage.swift */; }; 7AD0AA1C2AD6A63F00119E10 /* PacketTunnelActorStub.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AD0AA1B2AD6A63F00119E10 /* PacketTunnelActorStub.swift */; }; 7AD0AA1D2AD6A86700119E10 /* PacketTunnelActorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AD0AA192AD69B6E00119E10 /* PacketTunnelActorProtocol.swift */; }; 7AD0AA1F2AD6C8B900119E10 /* URLRequestProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AD0AA1E2AD6C8B900119E10 /* URLRequestProxyProtocol.swift */; }; @@ -939,7 +939,6 @@ F0EF50D32A8FA47E0031E8DF /* ChangeLogInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0EF50D22A8FA47E0031E8DF /* ChangeLogInteractor.swift */; }; F0EF50D52A949F8E0031E8DF /* ChangeLogViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0EF50D42A949F8E0031E8DF /* ChangeLogViewModel.swift */; }; F0FADDEA2BE90AAA000D0B02 /* LaunchArguments.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0F1EF8C2BE8FF0A00CED01D /* LaunchArguments.swift */; }; - F0FADDEB2BE90AAE000D0B02 /* LaunchArguments.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0F1EF8C2BE8FF0A00CED01D /* LaunchArguments.swift */; }; F0FADDEC2BE90AB0000D0B02 /* LaunchArguments.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0F1EF8C2BE8FF0A00CED01D /* LaunchArguments.swift */; }; /* End PBXBuildFile section */ @@ -1021,13 +1020,6 @@ remoteGlobalIDString = 58CE5E78224146470008646E; remoteInfo = PacketTunnel; }; - 58D0C79823F1CE7000FE9BA7 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 58CE5E58224146200008646E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 58CE5E5F224146200008646E; - remoteInfo = MullvadVPN; - }; 58D2239D294C89B50029F5F8 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 58CE5E58224146200008646E /* Project object */; @@ -1734,10 +1726,7 @@ 58CEB3092AFD584700E6E088 /* CustomCellDisclosureHandling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomCellDisclosureHandling.swift; sourceTree = ""; }; 58CEB30B2AFD586600E6E088 /* DynamicBackgroundConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicBackgroundConfiguration.swift; sourceTree = ""; }; 58CF95A12AD6F35800B59F5D /* ObservedState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObservedState.swift; sourceTree = ""; }; - 58D0C79323F1CE7000FE9BA7 /* MullvadVPNScreenshots.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MullvadVPNScreenshots.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 58D0C79D23F1CEBA00FE9BA7 /* SnapshotHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SnapshotHelper.swift; sourceTree = ""; }; - 58D0C79F23F1CECF00FE9BA7 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 58D0C7A023F1CECF00FE9BA7 /* MullvadVPNScreenshots.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MullvadVPNScreenshots.swift; sourceTree = ""; }; 58D223A5294C8A480029F5F8 /* Operations.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Operations.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 58D223A7294C8A490029F5F8 /* Operations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Operations.h; sourceTree = ""; }; 58D223D5294C8E5E0029F5F8 /* MullvadTypes.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MullvadTypes.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1844,6 +1833,7 @@ 7A3353962AAA0F8600F0A71C /* OperationBlockObserverSupport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OperationBlockObserverSupport.swift; sourceTree = ""; }; 7A3FD1B42AD4465A0042BEA6 /* AppMessageHandlerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppMessageHandlerTests.swift; sourceTree = ""; }; 7A42DEC82A05164100B209BE /* SettingsInputCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsInputCell.swift; sourceTree = ""; }; + 7A45CFC22C05FF2F00D80B21 /* ScreenshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenshotTests.swift; sourceTree = ""; }; 7A516C2D2B6D357500BBD33D /* URL+Scoping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+Scoping.swift"; sourceTree = ""; }; 7A516C392B7111A700BBD33D /* IPOverrideWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPOverrideWrapper.swift; sourceTree = ""; }; 7A516C3B2B712F0B00BBD33D /* IPOverrideWrapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPOverrideWrapperTests.swift; sourceTree = ""; }; @@ -1932,6 +1922,7 @@ 7ABE318C2A1CDD4500DF4963 /* UIFont+Weight.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIFont+Weight.swift"; sourceTree = ""; }; 7ABFB09D2BA316220074A49E /* RelayConstraintsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayConstraintsTests.swift; sourceTree = ""; }; 7AC8A3AD2ABC6FBB00DC4939 /* SettingsHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsHeaderView.swift; sourceTree = ""; }; + 7ACD79382C0DAADC00DBEE14 /* AddCustomListLocationsPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddCustomListLocationsPage.swift; sourceTree = ""; }; 7AD0AA192AD69B6E00119E10 /* PacketTunnelActorProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PacketTunnelActorProtocol.swift; sourceTree = ""; }; 7AD0AA1B2AD6A63F00119E10 /* PacketTunnelActorStub.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PacketTunnelActorStub.swift; sourceTree = ""; }; 7AD0AA1E2AD6C8B900119E10 /* URLRequestProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLRequestProxyProtocol.swift; sourceTree = ""; }; @@ -2266,13 +2257,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 58D0C79023F1CE7000FE9BA7 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; 58D223A2294C8A480029F5F8 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -3445,7 +3429,6 @@ 58B2FDD42AA71D2A003EB5C6 /* MullvadSettings */, 581943F228F8014500B0CB5E /* MullvadTypes */, 58CE5E62224146200008646E /* MullvadVPN */, - 58D0C79423F1CE7000FE9BA7 /* MullvadVPNScreenshots */, 58B0A2A1238EE67E00BC001D /* MullvadVPNTests */, 852969262B4D9C1F007EAD4C /* MullvadVPNUITests */, 58D223A6294C8A490029F5F8 /* Operations */, @@ -3471,7 +3454,6 @@ 58CE5E60224146200008646E /* MullvadVPN.app */, 58CE5E79224146470008646E /* PacketTunnel.appex */, 58B0A2A0238EE67E00BC001D /* MullvadVPNTests.xctest */, - 58D0C79323F1CE7000FE9BA7 /* MullvadVPNScreenshots.xctest */, 589A455228E094B300565204 /* OperationsTests.xctest */, 06799ABC28F98E1D00ACD94E /* MullvadREST.framework */, 58FBFBE6291622580020E046 /* MullvadRESTTests.xctest */, @@ -3574,16 +3556,6 @@ path = Add; sourceTree = ""; }; - 58D0C79423F1CE7000FE9BA7 /* MullvadVPNScreenshots */ = { - isa = PBXGroup; - children = ( - 58D0C79F23F1CECF00FE9BA7 /* Info.plist */, - 58D0C7A023F1CECF00FE9BA7 /* MullvadVPNScreenshots.swift */, - 58D0C79D23F1CEBA00FE9BA7 /* SnapshotHelper.swift */, - ); - path = MullvadVPNScreenshots; - sourceTree = ""; - }; 58D1560C29C0B27600749324 /* Root */ = { isa = PBXGroup; children = ( @@ -3780,6 +3752,15 @@ path = Alert; sourceTree = ""; }; + 7A45CFCD2C08697100D80B21 /* Screenshots */ = { + isa = PBXGroup; + children = ( + 7A45CFC22C05FF2F00D80B21 /* ScreenshotTests.swift */, + 58D0C79D23F1CEBA00FE9BA7 /* SnapshotHelper.swift */, + ); + path = Screenshots; + sourceTree = ""; + }; 7A5869A92B55516700640D27 /* IPOverride */ = { isa = PBXGroup; children = ( @@ -3879,32 +3860,33 @@ path = RelayFilter; sourceTree = ""; }; - 8518F6392B601910009EB113 /* Test base classes */ = { + 8518F6392B601910009EB113 /* Base */ = { isa = PBXGroup; children = ( 8590896A2B61763B003AF5F5 /* BaseUITestCase.swift */, 859089692B61763B003AF5F5 /* LoggedInWithTimeUITestCase.swift */, 8590896B2B61763B003AF5F5 /* LoggedOutUITestCase.swift */, ); - path = "Test base classes"; + path = Base; sourceTree = ""; }; 852969262B4D9C1F007EAD4C /* MullvadVPNUITests */ = { isa = PBXGroup; children = ( - 852969272B4D9C1F007EAD4C /* AccountTests.swift */, + 8518F6392B601910009EB113 /* Base */, + 85557B0C2B591B0F00795FE1 /* Networking */, + 852969312B4E9220007EAD4C /* Pages */, + 7A45CFCD2C08697100D80B21 /* Screenshots */, + 852969372B4ED20E007EAD4C /* Info.plist */, 8556EB532B9A1D7100D26DD4 /* BridgingHeader.h */, + 85B267602B849ADB0098E3CD /* mullvad-api.h */, + 852969272B4D9C1F007EAD4C /* AccountTests.swift */, 85557B112B594FC900795FE1 /* ConnectivityTests.swift */, A9BFAFFE2BD004ED00F2BCA1 /* CustomListsTests.swift */, - 852969372B4ED20E007EAD4C /* Info.plist */, - 85B267602B849ADB0098E3CD /* mullvad-api.h */, - 85557B0C2B591B0F00795FE1 /* Networking */, - 852969312B4E9220007EAD4C /* Pages */, 850201DA2B503D7700EF8C96 /* RelayTests.swift */, - 856952E12BD6B04C008C1F84 /* XCUIElement+Extensions.swift */, 85D039972BA4711800940E7F /* SettingsMigrationTests.swift */, 85C7A2E82B89024B00035D5A /* SettingsTests.swift */, - 8518F6392B601910009EB113 /* Test base classes */, + 856952E12BD6B04C008C1F84 /* XCUIElement+Extensions.swift */, 85557B152B5ABBBE00795FE1 /* XCUIElementQuery+Extensions.swift */, ); path = MullvadVPNUITests; @@ -3915,11 +3897,15 @@ children = ( 85FB5A0F2B6960A30015DCED /* AccountDeletionPage.swift */, 85557B1F2B5FBBD700795FE1 /* AccountPage.swift */, + 852D054E2BC43DF7008578D2 /* AddAccessMethodPage.swift */, + 7ACD79382C0DAADC00DBEE14 /* AddCustomListLocationsPage.swift */, 8529693B2B4F0257007EAD4C /* Alert.swift */, + 852D054C2BC3DE3A008578D2 /* APIAccessPage.swift */, 8587A05C2B84D43100152938 /* ChangeLogAlert.swift */, A9BFB0002BD00B7F00F2BCA1 /* CustomListPage.swift */, 85A42B872BB44D31007BABF7 /* DeviceManagementPage.swift */, 852A26452BA9C9CB006EB9C8 /* DNSSettingsPage.swift */, + 8585CBE22BC684180015B6A4 /* EditAccessMethodPage.swift */, A998DA822BD2B055001D61A2 /* EditCustomListLocationsPage.swift */, 85557B1D2B5FB8C700795FE1 /* HeaderBar.swift */, A998DA802BD147AD001D61A2 /* ListCustomListsPage.swift */, @@ -3929,16 +3915,13 @@ 855D9F5A2B63E56B00D7C64D /* ProblemReportPage.swift */, 8532E6862B8CCED600ACECD1 /* ProblemReportSubmittedPage.swift */, 8556EB552B9B0AC500D26DD4 /* RevokedDevicePage.swift */, + 8542F7522BCFBD050035C042 /* SelectLocationFilterPage.swift */, 850201DC2B503D8C00EF8C96 /* SelectLocationPage.swift */, 850201E22B51A93C00EF8C96 /* SettingsPage.swift */, 852969392B4F0238007EAD4C /* TermsOfServicePage.swift */, 850201DE2B5040A500EF8C96 /* TunnelControlPage.swift */, 8542CE232B95F7B9006FCA14 /* VPNSettingsPage.swift */, 85FB5A0B2B6903990015DCED /* WelcomePage.swift */, - 8542F7522BCFBD050035C042 /* SelectLocationFilterPage.swift */, - 852D054C2BC3DE3A008578D2 /* APIAccessPage.swift */, - 852D054E2BC43DF7008578D2 /* AddAccessMethodPage.swift */, - 8585CBE22BC684180015B6A4 /* EditAccessMethodPage.swift */, ); path = Pages; sourceTree = ""; @@ -4543,24 +4526,6 @@ productReference = 58CE5E79224146470008646E /* PacketTunnel.appex */; productType = "com.apple.product-type.app-extension"; }; - 58D0C79223F1CE7000FE9BA7 /* MullvadVPNScreenshots */ = { - isa = PBXNativeTarget; - buildConfigurationList = 58D0C79A23F1CE7000FE9BA7 /* Build configuration list for PBXNativeTarget "MullvadVPNScreenshots" */; - buildPhases = ( - 58D0C78F23F1CE7000FE9BA7 /* Sources */, - 58D0C79023F1CE7000FE9BA7 /* Frameworks */, - 58D0C79123F1CE7000FE9BA7 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 58D0C79923F1CE7000FE9BA7 /* PBXTargetDependency */, - ); - name = MullvadVPNScreenshots; - productName = MullvadVPNScreenshots; - productReference = 58D0C79323F1CE7000FE9BA7 /* MullvadVPNScreenshots.xctest */; - productType = "com.apple.product-type.bundle.ui-testing"; - }; 58D223A4294C8A480029F5F8 /* Operations */ = { isa = PBXNativeTarget; buildConfigurationList = 58D223A9294C8A490029F5F8 /* Build configuration list for PBXNativeTarget "Operations" */; @@ -4807,10 +4772,6 @@ }; }; }; - 58D0C79223F1CE7000FE9BA7 = { - CreatedOnToolsVersion = 11.3; - TestTargetID = 58CE5E5F224146200008646E; - }; 58D223A4294C8A480029F5F8 = { CreatedOnToolsVersion = 14.1; }; @@ -4865,7 +4826,6 @@ 58FBDA9722A519BC00EB69A3 /* WireGuardGoBridge */, 58CE5E78224146470008646E /* PacketTunnel */, 58B0A29F238EE67E00BC001D /* MullvadVPNTests */, - 58D0C79223F1CE7000FE9BA7 /* MullvadVPNScreenshots */, 852969242B4D9C1F007EAD4C /* MullvadVPNUITests */, 58D223A4294C8A480029F5F8 /* Operations */, 589A455128E094B300565204 /* OperationsTests */, @@ -4953,13 +4913,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 58D0C79123F1CE7000FE9BA7 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; 58D223A3294C8A480029F5F8 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -5937,17 +5890,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 58D0C78F23F1CE7000FE9BA7 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 58D0C7A223F1CECF00FE9BA7 /* MullvadVPNScreenshots.swift in Sources */, - F0FADDEB2BE90AAE000D0B02 /* LaunchArguments.swift in Sources */, - 7A0B311F2B303A11004B12E0 /* AccessbilityIdentifier.swift in Sources */, - 58D0C79E23F1CEBA00FE9BA7 /* SnapshotHelper.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 58D223A1294C8A480029F5F8 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -6079,6 +6021,7 @@ 850201DD2B503D8C00EF8C96 /* SelectLocationPage.swift in Sources */, 85D039982BA4711800940E7F /* SettingsMigrationTests.swift in Sources */, 850201DB2B503D7700EF8C96 /* RelayTests.swift in Sources */, + 7A45CFC62C05FF6A00D80B21 /* ScreenshotTests.swift in Sources */, 852D054D2BC3DE3A008578D2 /* APIAccessPage.swift in Sources */, 85139B2D2B84B4A700734217 /* OutOfTimePage.swift in Sources */, 852969362B4E9724007EAD4C /* AccessbilityIdentifier.swift in Sources */, @@ -6089,6 +6032,7 @@ 85557B202B5FBBD700795FE1 /* AccountPage.swift in Sources */, 852969352B4E9270007EAD4C /* LoginPage.swift in Sources */, A998DA832BD2B055001D61A2 /* EditCustomListLocationsPage.swift in Sources */, + 7ACD79392C0DAADD00DBEE14 /* AddCustomListLocationsPage.swift in Sources */, 8556EB562B9B0AC500D26DD4 /* RevokedDevicePage.swift in Sources */, A9BFAFFF2BD004ED00F2BCA1 /* CustomListsTests.swift in Sources */, 85557B102B59215F00795FE1 /* FirewallRule.swift in Sources */, @@ -6096,6 +6040,7 @@ 852969282B4D9C1F007EAD4C /* AccountTests.swift in Sources */, 8587A05D2B84D43100152938 /* ChangeLogAlert.swift in Sources */, 85FB5A102B6960A30015DCED /* AccountDeletionPage.swift in Sources */, + 7A45CFC72C071DD400D80B21 /* SnapshotHelper.swift in Sources */, 85557B162B5ABBBE00795FE1 /* XCUIElementQuery+Extensions.swift in Sources */, 855D9F5B2B63E56B00D7C64D /* ProblemReportPage.swift in Sources */, 8529693A2B4F0238007EAD4C /* TermsOfServicePage.swift in Sources */, @@ -6209,11 +6154,6 @@ target = 58CE5E78224146470008646E /* PacketTunnel */; targetProxy = 58CE5E7F224146470008646E /* PBXContainerItemProxy */; }; - 58D0C79923F1CE7000FE9BA7 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 58CE5E5F224146200008646E /* MullvadVPN */; - targetProxy = 58D0C79823F1CE7000FE9BA7 /* PBXContainerItemProxy */; - }; 58D223C2294C8AE90029F5F8 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 58D223A4294C8A480029F5F8 /* Operations */; @@ -7036,42 +6976,6 @@ }; name = Release; }; - 58D0C79B23F1CE7000FE9BA7 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 58ECD29123F178FD004298B6 /* Screenshots.xcconfig */; - buildSettings = { - INFOPLIST_FILE = MullvadVPNScreenshots/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = "$(APPLICATION_IDENTIFIER).Screenshots"; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - SWIFT_VERSION = 5.0; - TEST_TARGET_NAME = MullvadVPN; - }; - name = Debug; - }; - 58D0C79C23F1CE7000FE9BA7 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 58ECD29123F178FD004298B6 /* Screenshots.xcconfig */; - buildSettings = { - INFOPLIST_FILE = MullvadVPNScreenshots/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = "$(APPLICATION_IDENTIFIER).Screenshots"; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - SWIFT_VERSION = 5.0; - TEST_TARGET_NAME = MullvadVPN; - }; - name = Release; - }; 58D223AA294C8A490029F5F8 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 5808273928487E3E006B77A4 /* Base.xcconfig */; @@ -7703,24 +7607,6 @@ }; name = Staging; }; - A93559532B4EADD600D5D524 /* Staging */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 58ECD29123F178FD004298B6 /* Screenshots.xcconfig */; - buildSettings = { - INFOPLIST_FILE = MullvadVPNScreenshots/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = "$(APPLICATION_IDENTIFIER).Screenshots"; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - SWIFT_VERSION = 5.0; - TEST_TARGET_NAME = MullvadVPN; - }; - name = Staging; - }; A93559542B4EADD600D5D524 /* Staging */ = { isa = XCBuildConfiguration; baseConfigurationReference = 5808273928487E3E006B77A4 /* Base.xcconfig */; @@ -8518,24 +8404,6 @@ }; name = MockRelease; }; - A9E99CE62B5195E600869AF2 /* MockRelease */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 58ECD29123F178FD004298B6 /* Screenshots.xcconfig */; - buildSettings = { - INFOPLIST_FILE = MullvadVPNScreenshots/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = "$(APPLICATION_IDENTIFIER).Screenshots"; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - SWIFT_VERSION = 5.0; - TEST_TARGET_NAME = MullvadVPN; - }; - name = MockRelease; - }; A9E99CE72B5195E600869AF2 /* MockRelease */ = { isa = XCBuildConfiguration; baseConfigurationReference = 5808273928487E3E006B77A4 /* Base.xcconfig */; @@ -9267,17 +9135,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 58D0C79A23F1CE7000FE9BA7 /* Build configuration list for PBXNativeTarget "MullvadVPNScreenshots" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 58D0C79B23F1CE7000FE9BA7 /* Debug */, - A93559532B4EADD600D5D524 /* Staging */, - 58D0C79C23F1CE7000FE9BA7 /* Release */, - A9E99CE62B5195E600869AF2 /* MockRelease */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; 58D223A9294C8A490029F5F8 /* Build configuration list for PBXNativeTarget "Operations" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/MullvadVPNScreenshots.xcscheme b/ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/MullvadVPNScreenshots.xcscheme deleted file mode 100644 index 9e2f37241665..000000000000 --- a/ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/MullvadVPNScreenshots.xcscheme +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/MullvadVPNScreenshots/Info.plist b/ios/MullvadVPNScreenshots/Info.plist deleted file mode 100644 index 0d3e8d46de9c..000000000000 --- a/ios/MullvadVPNScreenshots/Info.plist +++ /dev/null @@ -1,28 +0,0 @@ - - - - - ApiHostName - $(API_HOST_NAME) - ApiEndpoint - $(API_ENDPOINT) - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - CFBundleShortVersionString - 1.0 - MullvadAccountToken - $(MULLVAD_ACCOUNT_TOKEN) - CFBundleVersion - 1 - - diff --git a/ios/MullvadVPNScreenshots/MullvadVPNScreenshots.swift b/ios/MullvadVPNScreenshots/MullvadVPNScreenshots.swift deleted file mode 100644 index 55debaa9b3a1..000000000000 --- a/ios/MullvadVPNScreenshots/MullvadVPNScreenshots.swift +++ /dev/null @@ -1,154 +0,0 @@ -// -// MullvadVPNScreenshots.swift -// MullvadVPNScreenshots -// -// Created by pronebird on 04/02/2020. -// Copyright © 2020 Mullvad VPN AB. All rights reserved. -// - -import XCTest - -class MullvadVPNScreenshots: XCTestCase { - let app = XCUIApplication() - - override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of - // each test method in the class. - - // In UI tests it is usually best to stop immediately when a failure occurs. - continueAfterFailure = false - - let argumentsJsonString = try LaunchArguments( - target: .screenshots, - areAnimationsDisabled: true - ).toJSON() - - app.launchEnvironment[LaunchArguments.tag] = argumentsJsonString - - // In UI tests it’s important to set the initial state - such as interface orientation - - // required for your tests before they run. The setUp method is a good place to do this. - } - - override func tearDown() { - // Put teardown code here. This method is called after the invocation of - // each test method in the class. - } - - func testTakeScreenshots() { - let accountToken = Bundle(for: Self.self).infoDictionary?["MullvadAccountToken"] as! String - - // UI tests must launch the application that they test. - setupSnapshot(app, waitForAnimations: false) - app.launch() - - // Dismiss terms of service screen - _ = app.buttons[AccessibilityIdentifier.agreeButton.rawValue].waitForExistence(timeout: 10) - app.buttons[AccessibilityIdentifier.agreeButton.rawValue].tap() - - // Dismiss changelog screen - _ = app.buttons[AccessibilityIdentifier.alertOkButton.rawValue].waitForExistence(timeout: 10) - app.buttons[AccessibilityIdentifier.alertOkButton.rawValue].tap() - - // Wait for Login screen - let textField = app.textFields[AccessibilityIdentifier.loginTextField.rawValue] - _ = textField.waitForExistence(timeout: 5) - - // Enter account token - textField.tap() - textField.typeText(accountToken) - - // Tap "Log in" button to log in - if case .phone = UIDevice.current.userInterfaceIdiom { - app.toolbars["Toolbar"].buttons[AccessibilityIdentifier.loginBarButton.rawValue].tap() - } else { - textField.typeText("\n") - } - - // Select Sweden, Gothenburg in Select location controller - if case .phone = UIDevice.current.userInterfaceIdiom { - _ = app.buttons[AccessibilityIdentifier.selectLocationButton.rawValue].waitForExistence(timeout: 10) - app.buttons[AccessibilityIdentifier.selectLocationButton.rawValue].tap() - } - - let countryCell = app.cells["se"] - let cityCell = app.cells["se-got"] - let relayCell = app.cells["se-got-wg-101"] - - _ = countryCell.waitForExistence(timeout: 2) - - if relayCell.exists { - relayCell.tap() - } else { - _ = countryCell.buttons[AccessibilityIdentifier.expandButton.rawValue].waitForExistence(timeout: 5) - countryCell.buttons[AccessibilityIdentifier.expandButton.rawValue].tap() - cityCell.buttons[AccessibilityIdentifier.expandButton.rawValue].tap() - relayCell.tap() - } - - // Wait for Disconnect button to appear - _ = app.buttons[AccessibilityIdentifier.disconnectButton.rawValue].waitForExistence(timeout: 2) - - snapshot("MainSecured") - - // Re-open Select location controller (iPhone only) - if case .phone = UIDevice.current.userInterfaceIdiom { - app.buttons[AccessibilityIdentifier.selectLocationButton.rawValue].tap() - snapshot("SelectLocation") - - // Tap the "Filter" button and expand each relay filter - app.navigationBars.buttons["Filter"].tap() - app.otherElements[AccessibilityIdentifier.locationFilterOwnershipHeaderCell.rawValue] - .buttons[AccessibilityIdentifier.expandButton.rawValue].tap() - app.otherElements[AccessibilityIdentifier.locationFilterProvidersHeaderCell.rawValue] - .buttons[AccessibilityIdentifier.expandButton.rawValue].tap() - snapshot("RelayFilter") - - app.navigationBars.buttons["Cancel"].tap() - app.navigationBars.buttons["Done"].tap() - } - - // Open Settings - app.buttons[AccessibilityIdentifier.settingsButton.rawValue].tap() - - // Tap on VPN settings cell - _ = app.tables.cells[AccessibilityIdentifier.vpnSettingsCell.rawValue].waitForExistence(timeout: 2) - app.tables.cells[AccessibilityIdentifier.vpnSettingsCell.rawValue].tap() - - app.tables.element - .cells - .matching(NSPredicate(format: "identifier BEGINSWITH %@", "mullvadDNS")) - .switches - .matching(NSPredicate(format: "value = %@", "0")) - .allElementsBoundByAccessibilityElement - .forEach { $0.tap() } - snapshot("VPN Settings") - - // Tap back button - app.navigationBars.buttons.firstMatch.tap() - - // Tap dismiss button - app.navigationBars.buttons.firstMatch.tap() - - // Open Account - app.buttons[AccessibilityIdentifier.accountButton.rawValue].tap() - - // Wait for StoreKit to fetch subscriptions - _ = app.buttons[AccessibilityIdentifier.purchaseButton.rawValue].waitForExistence(timeout: 2) - - wait(for: [ - expectation( - for: NSPredicate(format: "isEnabled = YES"), - evaluatedWith: app.buttons[AccessibilityIdentifier.purchaseButton.rawValue] - ), - ], timeout: 10) - snapshot("Account") - - // Hit "Log out" button - _ = app.buttons[AccessibilityIdentifier.logoutButton.rawValue].waitForExistence(timeout: 2) - app.buttons[AccessibilityIdentifier.logoutButton.rawValue].tap() - app.alerts.buttons.allElementsBoundByIndex.last?.tap() - - // Wait for Login view to appear after log out - _ = app.textFields[AccessibilityIdentifier.loginTextField.rawValue].waitForExistence(timeout: 10) - } -} diff --git a/ios/MullvadVPNUITests/Test base classes/BaseUITestCase.swift b/ios/MullvadVPNUITests/Base/BaseUITestCase.swift similarity index 100% rename from ios/MullvadVPNUITests/Test base classes/BaseUITestCase.swift rename to ios/MullvadVPNUITests/Base/BaseUITestCase.swift diff --git a/ios/MullvadVPNUITests/Test base classes/LoggedInWithTimeUITestCase.swift b/ios/MullvadVPNUITests/Base/LoggedInWithTimeUITestCase.swift similarity index 100% rename from ios/MullvadVPNUITests/Test base classes/LoggedInWithTimeUITestCase.swift rename to ios/MullvadVPNUITests/Base/LoggedInWithTimeUITestCase.swift diff --git a/ios/MullvadVPNUITests/Test base classes/LoggedOutUITestCase.swift b/ios/MullvadVPNUITests/Base/LoggedOutUITestCase.swift similarity index 100% rename from ios/MullvadVPNUITests/Test base classes/LoggedOutUITestCase.swift rename to ios/MullvadVPNUITests/Base/LoggedOutUITestCase.swift diff --git a/ios/MullvadVPNUITests/CustomListsTests.swift b/ios/MullvadVPNUITests/CustomListsTests.swift index 6a3f9f1db725..29cb9c2f44dc 100644 --- a/ios/MullvadVPNUITests/CustomListsTests.swift +++ b/ios/MullvadVPNUITests/CustomListsTests.swift @@ -65,7 +65,7 @@ class CustomListsTests: LoggedInWithTimeUITestCase { EditCustomListLocationsPage(app) .scrollToLocationWith(identifier: "se") .toggleLocationCheckmarkWith(identifier: "se") - .pressBackButton() + .tapBackButton() CustomListPage(app) .tapSaveListButton() @@ -96,7 +96,7 @@ class CustomListsTests: LoggedInWithTimeUITestCase { .unfoldLocationwith(identifier: "se") .unfoldLocationwith(identifier: "se-got") .toggleLocationCheckmarkWith(identifier: "se-got-wg-001") - .pressBackButton() + .tapBackButton() CustomListPage(app) .tapSaveListButton() diff --git a/ios/MullvadVPNUITests/Pages/AddCustomListLocationsPage.swift b/ios/MullvadVPNUITests/Pages/AddCustomListLocationsPage.swift new file mode 100644 index 000000000000..13ffc95299ec --- /dev/null +++ b/ios/MullvadVPNUITests/Pages/AddCustomListLocationsPage.swift @@ -0,0 +1,16 @@ +// +// AddCustomListLocationsPage.swift +// MullvadVPNUITests +// +// Created by Jon Petersson on 2024-06-03. +// Copyright © 2024 Mullvad VPN AB. All rights reserved. +// + +import XCTest + +class AddCustomListLocationsPage: EditCustomListLocationsPage { + @discardableResult override func tapBackButton() -> Self { + app.navigationBars["Add locations"].buttons.firstMatch.tap() + return self + } +} diff --git a/ios/MullvadVPNUITests/Pages/CustomListPage.swift b/ios/MullvadVPNUITests/Pages/CustomListPage.swift index 17ebf363c343..071b2b939455 100644 --- a/ios/MullvadVPNUITests/Pages/CustomListPage.swift +++ b/ios/MullvadVPNUITests/Pages/CustomListPage.swift @@ -39,8 +39,12 @@ class CustomListPage: Page { editCustomListNameCell.tap() // Select the entire text with a triple tap editCustomListNameCell.tap(withNumberOfTaps: 3, numberOfTouches: 1) - // Tap the "delete" key on the on-screen keyboard, the case is sensitive - app.keys["delete"].tap() + // Tap the "delete" key on the on-screen keyboard, the case is sensitive. + // However, on a simulator the keyboard isn't visible by default, so we + // need to take that into consideration. + if app.keys["delete"].isHittable { + app.keys["delete"].tap() + } editCustomListNameCell.typeText(name) return self } diff --git a/ios/MullvadVPNUITests/Pages/DNSSettingsPage.swift b/ios/MullvadVPNUITests/Pages/DNSSettingsPage.swift index e592862cbf33..c7bb9d0783f9 100644 --- a/ios/MullvadVPNUITests/Pages/DNSSettingsPage.swift +++ b/ios/MullvadVPNUITests/Pages/DNSSettingsPage.swift @@ -38,7 +38,7 @@ class DNSSettingsPage: Page { @discardableResult func tapDNSContentBlockersHeaderExpandButton() -> Self { let headerView = app.otherElements[AccessibilityIdentifier.dnsContentBlockersHeaderView] - let expandButton = headerView.buttons[AccessibilityIdentifier.collapseButton] + let expandButton = headerView.buttons[AccessibilityIdentifier.expandButton] expandButton.tap() return self diff --git a/ios/MullvadVPNUITests/Pages/EditCustomListLocationsPage.swift b/ios/MullvadVPNUITests/Pages/EditCustomListLocationsPage.swift index 08d3d6fa9fef..7a75c0720bb7 100644 --- a/ios/MullvadVPNUITests/Pages/EditCustomListLocationsPage.swift +++ b/ios/MullvadVPNUITests/Pages/EditCustomListLocationsPage.swift @@ -9,6 +9,10 @@ import XCTest class EditCustomListLocationsPage: Page { + enum Action { + case add, edit + } + @discardableResult override init(_ app: XCUIApplication) { super.init(app) @@ -46,7 +50,7 @@ class EditCustomListLocationsPage: Page { return self } - @discardableResult func pressBackButton() -> Self { + @discardableResult func tapBackButton() -> Self { app.navigationBars["Edit locations"].buttons.firstMatch.tap() return self } diff --git a/ios/MullvadVPNUITests/Pages/TunnelControlPage.swift b/ios/MullvadVPNUITests/Pages/TunnelControlPage.swift index 4a2eeee4c790..945b6bb73bab 100644 --- a/ios/MullvadVPNUITests/Pages/TunnelControlPage.swift +++ b/ios/MullvadVPNUITests/Pages/TunnelControlPage.swift @@ -16,6 +16,10 @@ class TunnelControlPage: Page { let protocolName: String } + var connectionIsSecured: Bool { + app.staticTexts[AccessibilityIdentifier.connectionStatusConnectedLabel].exists + } + /// Poll the "in address row" label for its updated values and output an array of ConnectionAttempt objects representing the connection attempts that have been communicated through the UI. /// - Parameters: /// - attemptsCount: number of connection attempts to look for diff --git a/ios/MullvadVPNUITests/Pages/VPNSettingsPage.swift b/ios/MullvadVPNUITests/Pages/VPNSettingsPage.swift index 71adb3eaaa3f..c89a2fb04562 100644 --- a/ios/MullvadVPNUITests/Pages/VPNSettingsPage.swift +++ b/ios/MullvadVPNUITests/Pages/VPNSettingsPage.swift @@ -14,10 +14,10 @@ class VPNSettingsPage: Page { super.init(app) } - private func cellExpandCollapseButton(_ cellAccessiblityIdentifier: AccessibilityIdentifier) -> XCUIElement { + private func cellExpandButton(_ cellAccessiblityIdentifier: AccessibilityIdentifier) -> XCUIElement { let table = app.tables[AccessibilityIdentifier.vpnSettingsTableView] let matchingCells = table.otherElements.containing(.any, identifier: cellAccessiblityIdentifier.rawValue) - let expandButton = matchingCells.buttons[AccessibilityIdentifier.collapseButton] + let expandButton = matchingCells.buttons[AccessibilityIdentifier.expandButton] return expandButton } @@ -37,18 +37,18 @@ class VPNSettingsPage: Page { } @discardableResult func tapWireGuardPortsExpandButton() -> Self { - cellExpandCollapseButton(AccessibilityIdentifier.wireGuardPortsCell).tap() + cellExpandButton(AccessibilityIdentifier.wireGuardPortsCell).tap() return self } @discardableResult func tapWireGuardObfuscationExpandButton() -> Self { - cellExpandCollapseButton(AccessibilityIdentifier.wireGuardObfuscationCell).tap() + cellExpandButton(AccessibilityIdentifier.wireGuardObfuscationCell).tap() return self } @discardableResult func tapUDPOverTCPPortExpandButton() -> Self { - cellExpandCollapseButton(AccessibilityIdentifier.udpOverTCPPortCell).tap() + cellExpandButton(AccessibilityIdentifier.udpOverTCPPortCell).tap() return self } @@ -72,7 +72,7 @@ class VPNSettingsPage: Page { } @discardableResult func tapQuantumResistantTunnelExpandButton() -> Self { - cellExpandCollapseButton(AccessibilityIdentifier.quantumResistantTunnelCell).tap() + cellExpandButton(AccessibilityIdentifier.quantumResistantTunnelCell).tap() return self } diff --git a/ios/MullvadVPNUITests/Screenshots/ScreenshotTests.swift b/ios/MullvadVPNUITests/Screenshots/ScreenshotTests.swift new file mode 100644 index 000000000000..778b04d07403 --- /dev/null +++ b/ios/MullvadVPNUITests/Screenshots/ScreenshotTests.swift @@ -0,0 +1,151 @@ +// +// ScreenshotTests.swift +// MullvadVPNScreenshots +// +// Created by Jon Petersson on 2024-05-28. +// Copyright © 2024 Mullvad VPN AB. All rights reserved. +// + +import XCTest + +class ScreenshotTests: LoggedInWithTimeUITestCase { + override func setUp() { + setupSnapshot(app, waitForAnimations: false) + + let argumentsJsonString = try? LaunchArguments( + target: .screenshots, + areAnimationsDisabled: true + ).toJSON() + app.launchEnvironment[LaunchArguments.tag] = argumentsJsonString + + super.setUp() + } + + func testTakeScreenshotOfQuantumSecuredConnection() throws { + // We can't close banners in the screenshot tests due to how the NotificationController view + // is overridden, so we need to restart the app once to make sure the "new device" notification + // isn't visible. + app.terminate() + app.launch() + + HeaderBar(app) + .tapSettingsButton() + + SettingsPage(app) + .tapVPNSettingsCell() + + VPNSettingsPage(app) + .tapQuantumResistantTunnelExpandButton() + .tapQuantumResistantTunnelOnCell() + .tapBackButton() + + SettingsPage(app) + .tapDoneButton() + + TunnelControlPage(app) + .tapSelectLocationButton() + + SelectLocationPage(app) + .tapLocationCell(withName: "Sweden") + + TunnelControlPage(app) + .waitForSecureConnectionLabel() + + snapshot("QuantumConnectionSecured") + } + + func testTakeScreenshotOfCustomListSelected() throws { + let customListName = "Low latency locations" + + TunnelControlPage(app) + .tapSelectLocationButton() + + SelectLocationPage(app) + .tapWhereStatusBarShouldBeToScrollToTopMostPosition() + .tapCustomListEllipsisButton() + .tapAddNewCustomList() + + CustomListPage(app) + .renameCustomList(name: customListName) + .addOrEditLocations() + + AddCustomListLocationsPage(app) + .scrollToLocationWith(identifier: "se") + .unfoldLocationwith(identifier: "se") + .unfoldLocationwith(identifier: "se-got") + .toggleLocationCheckmarkWith(identifier: "se-got-wg-101") + .scrollToLocationWith(identifier: "de") + .unfoldLocationwith(identifier: "de") + .toggleLocationCheckmarkWith(identifier: "de-ber") + .scrollToLocationWith(identifier: "fi") + .toggleLocationCheckmarkWith(identifier: "fi") + .tapBackButton() + + CustomListPage(app) + .tapCreateListButton() + + SelectLocationPage(app) + .tapLocationCell(withName: customListName) + + TunnelControlPage(app) + .tapSelectLocationButton() + + SelectLocationPage(app) + .tapLocationCellExpandButton(withName: customListName) + + snapshot("CustomListSelected") + } + + func testTakeScreenshotOfRelayFilter() throws { + TunnelControlPage(app) + .tapSelectLocationButton() + + SelectLocationPage(app) + .tapFilterButton() + + SelectLocationFilterPage(app) + .tapOwnershipCellExpandButton() + .tapProvidersCellExpandButton() + + snapshot("RelayFilter") + } + + func testTakeScreenshotOfVPNSettings() throws { + HeaderBar(app) + .tapSettingsButton() + + SettingsPage(app) + .tapVPNSettingsCell() + + snapshot("VPNSettings") + } + + func testTakeScreenshotOfDNSSettings() throws { + HeaderBar(app) + .tapSettingsButton() + + SettingsPage(app) + .tapVPNSettingsCell() + + VPNSettingsPage(app) + .tapDNSSettingsCell() + + DNSSettingsPage(app) + .tapDNSContentBlockersHeaderExpandButton() + .tapBlockAdsSwitch() + .tapBlockTrackerSwitch() + .tapBlockMalwareSwitch() + .tapBlockAdultContentSwitch() + .tapBlockGamblingSwitch() + .tapBlockSocialMediaSwitch() + + snapshot("DNSSettings") + } + + func testTakeScreenshotOfAccount() throws { + HeaderBar(app) + .tapAccountButton() + + snapshot("Account") + } +} diff --git a/ios/MullvadVPNScreenshots/SnapshotHelper.swift b/ios/MullvadVPNUITests/Screenshots/SnapshotHelper.swift similarity index 72% rename from ios/MullvadVPNScreenshots/SnapshotHelper.swift rename to ios/MullvadVPNUITests/Screenshots/SnapshotHelper.swift index 0b8a4c53eb24..9638ba7dbd3d 100644 --- a/ios/MullvadVPNScreenshots/SnapshotHelper.swift +++ b/ios/MullvadVPNUITests/Screenshots/SnapshotHelper.swift @@ -61,7 +61,6 @@ open class Snapshot: NSObject { } open class func setupSnapshot(_ app: XCUIApplication, waitForAnimations: Bool = true) { - Snapshot.app = app Snapshot.waitForAnimations = waitForAnimations @@ -129,7 +128,11 @@ open class Snapshot: NSObject { do { let launchArguments = try String(contentsOf: path, encoding: String.Encoding.utf8) let regex = try NSRegularExpression(pattern: "(\\\".+?\\\"|\\S+)", options: []) - let matches = regex.matches(in: launchArguments, options: [], range: NSRange(location: 0, length: launchArguments.count)) + let matches = regex.matches( + in: launchArguments, + options: [], + range: NSRange(location: 0, length: launchArguments.count) + ) let results = matches.map { result -> String in (launchArguments as NSString).substring(with: result.range) } @@ -151,67 +154,70 @@ open class Snapshot: NSObject { } #if os(OSX) - guard let app = self.app else { - NSLog("XCUIApplication is not set. Please call setupSnapshot(app) before snapshot().") - return - } + guard let app = self.app else { + NSLog("XCUIApplication is not set. Please call setupSnapshot(app) before snapshot().") + return + } - app.typeKey(XCUIKeyboardKeySecondaryFn, modifierFlags: []) + app.typeKey(XCUIKeyboardKeySecondaryFn, modifierFlags: []) #else - guard self.app != nil else { - NSLog("XCUIApplication is not set. Please call setupSnapshot(app) before snapshot().") - return - } + guard self.app != nil else { + NSLog("XCUIApplication is not set. Please call setupSnapshot(app) before snapshot().") + return + } + + let screenshot = XCUIScreen.main.screenshot() + #if os(iOS) && !targetEnvironment(macCatalyst) + let image = XCUIDevice.shared.orientation.isLandscape + ? fixLandscapeOrientation(image: screenshot.image) + : screenshot.image + #else + let image = screenshot.image + #endif - let screenshot = XCUIScreen.main.screenshot() - #if os(iOS) && !targetEnvironment(macCatalyst) - let image = XCUIDevice.shared.orientation.isLandscape ? fixLandscapeOrientation(image: screenshot.image) : screenshot.image + guard var simulator = ProcessInfo().environment["SIMULATOR_DEVICE_NAME"], + let screenshotsDir = screenshotsDirectory else { return } + + do { + // The simulator name contains "Clone X of " inside the screenshot file when running parallelized UI Tests on concurrent devices + let regex = try NSRegularExpression(pattern: "Clone [0-9]+ of ") + let range = NSRange(location: 0, length: simulator.count) + simulator = regex.stringByReplacingMatches(in: simulator, range: range, withTemplate: "") + + let path = screenshotsDir.appendingPathComponent("\(simulator)-\(name).png") + #if swift(<5.0) + try UIImagePNGRepresentation(image)?.write(to: path, options: .atomic) #else - let image = screenshot.image + try image.pngData()?.write(to: path, options: .atomic) #endif - - guard var simulator = ProcessInfo().environment["SIMULATOR_DEVICE_NAME"], let screenshotsDir = screenshotsDirectory else { return } - - do { - // The simulator name contains "Clone X of " inside the screenshot file when running parallelized UI Tests on concurrent devices - let regex = try NSRegularExpression(pattern: "Clone [0-9]+ of ") - let range = NSRange(location: 0, length: simulator.count) - simulator = regex.stringByReplacingMatches(in: simulator, range: range, withTemplate: "") - - let path = screenshotsDir.appendingPathComponent("\(simulator)-\(name).png") - #if swift(<5.0) - try UIImagePNGRepresentation(image)?.write(to: path, options: .atomic) - #else - try image.pngData()?.write(to: path, options: .atomic) - #endif - } catch let error { - NSLog("Problem writing screenshot: \(name) to \(screenshotsDir)/\(simulator)-\(name).png") - NSLog(error.localizedDescription) - } + } catch let error { + NSLog("Problem writing screenshot: \(name) to \(screenshotsDir)/\(simulator)-\(name).png") + NSLog(error.localizedDescription) + } #endif } class func fixLandscapeOrientation(image: UIImage) -> UIImage { #if os(watchOS) - return image + return image #else - if #available(iOS 10.0, *) { - let format = UIGraphicsImageRendererFormat() - format.scale = image.scale - let renderer = UIGraphicsImageRenderer(size: image.size, format: format) - return renderer.image { _ in - image.draw(in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)) - } - } else { - return image + if #available(iOS 10.0, *) { + let format = UIGraphicsImageRendererFormat() + format.scale = image.scale + let renderer = UIGraphicsImageRenderer(size: image.size, format: format) + return renderer.image { _ in + image.draw(in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)) } + } else { + return image + } #endif } class func waitForLoadingIndicatorToDisappear(within timeout: TimeInterval) { #if os(tvOS) - return + return #endif guard let app = self.app else { @@ -220,7 +226,10 @@ open class Snapshot: NSObject { } let networkLoadingIndicator = app.otherElements.deviceStatusBars.networkLoadingIndicators.element - let networkLoadingIndicatorDisappeared = XCTNSPredicateExpectation(predicate: NSPredicate(format: "exists == false"), object: networkLoadingIndicator) + let networkLoadingIndicatorDisappeared = XCTNSPredicateExpectation( + predicate: NSPredicate(format: "exists == false"), + object: networkLoadingIndicator + ) _ = XCTWaiter.wait(for: [networkLoadingIndicatorDisappeared], timeout: timeout) } @@ -229,16 +238,16 @@ open class Snapshot: NSObject { // on OSX config is stored in /Users//Library // and on iOS/tvOS/WatchOS it's in simulator's home dir #if os(OSX) - let homeDir = URL(fileURLWithPath: NSHomeDirectory()) - return homeDir.appendingPathComponent(cachePath) + let homeDir = URL(fileURLWithPath: NSHomeDirectory()) + return homeDir.appendingPathComponent(cachePath) #elseif arch(i386) || arch(x86_64) || arch(arm64) - guard let simulatorHostHome = ProcessInfo().environment["SIMULATOR_HOST_HOME"] else { - throw SnapshotError.cannotFindSimulatorHomeDirectory - } - let homeDir = URL(fileURLWithPath: simulatorHostHome) - return homeDir.appendingPathComponent(cachePath) + guard let simulatorHostHome = ProcessInfo().environment["SIMULATOR_HOST_HOME"] else { + throw SnapshotError.cannotFindSimulatorHomeDirectory + } + let homeDir = URL(fileURLWithPath: simulatorHostHome) + return homeDir.appendingPathComponent(cachePath) #else - throw SnapshotError.cannotRunOnPhysicalDevice + throw SnapshotError.cannotRunOnPhysicalDevice #endif } } @@ -248,7 +257,10 @@ private extension XCUIElementAttributes { if hasAllowListedIdentifier { return false } let hasOldLoadingIndicatorSize = frame.size == CGSize(width: 10, height: 20) - let hasNewLoadingIndicatorSize = frame.size.width.isBetween(46, and: 47) && frame.size.height.isBetween(2, and: 3) + let hasNewLoadingIndicatorSize = frame.size.width.isBetween(46, and: 47) && frame.size.height.isBetween( + 2, + and: 3 + ) return hasOldLoadingIndicatorSize || hasNewLoadingIndicatorSize } @@ -272,7 +284,7 @@ private extension XCUIElementAttributes { private extension XCUIElementQuery { var networkLoadingIndicators: XCUIElementQuery { - let isNetworkLoadingIndicator = NSPredicate { (evaluatedObject, _) in + let isNetworkLoadingIndicator = NSPredicate { evaluatedObject, _ in guard let element = evaluatedObject as? XCUIElementAttributes else { return false } return element.isNetworkLoadingIndicator @@ -288,7 +300,7 @@ private extension XCUIElementQuery { let deviceWidth = app.windows.firstMatch.frame.width - let isStatusBar = NSPredicate { (evaluatedObject, _) in + let isStatusBar = NSPredicate { evaluatedObject, _ in guard let element = evaluatedObject as? XCUIElementAttributes else { return false } return element.isStatusBar(deviceWidth) @@ -300,7 +312,7 @@ private extension XCUIElementQuery { private extension CGFloat { func isBetween(_ numberA: CGFloat, and numberB: CGFloat) -> Bool { - return numberA...numberB ~= self + return numberA ... numberB ~= self } } diff --git a/ios/TestPlans/MullvadVPNScreenshots.xctestplan b/ios/TestPlans/MullvadVPNScreenshots.xctestplan index 001a120aa81b..b6af32545231 100644 --- a/ios/TestPlans/MullvadVPNScreenshots.xctestplan +++ b/ios/TestPlans/MullvadVPNScreenshots.xctestplan @@ -18,10 +18,18 @@ }, "testTargets" : [ { + "selectedTests" : [ + "ScreenshotTests\/testTakeScreenshotOfAccount()", + "ScreenshotTests\/testTakeScreenshotOfCustomListSelected()", + "ScreenshotTests\/testTakeScreenshotOfDNSSettings()", + "ScreenshotTests\/testTakeScreenshotOfQuantumSecuredConnection()", + "ScreenshotTests\/testTakeScreenshotOfRelayFilter()", + "ScreenshotTests\/testTakeScreenshotOfVPNSettings()" + ], "target" : { "containerPath" : "container:MullvadVPN.xcodeproj", - "identifier" : "58D0C79223F1CE7000FE9BA7", - "name" : "MullvadVPNScreenshots" + "identifier" : "852969242B4D9C1F007EAD4C", + "name" : "MullvadVPNUITests" } } ], diff --git a/ios/TestPlans/MullvadVPNUITestsAll.xctestplan b/ios/TestPlans/MullvadVPNUITestsAll.xctestplan index 74265b9ddad7..475af04ab2c4 100644 --- a/ios/TestPlans/MullvadVPNUITestsAll.xctestplan +++ b/ios/TestPlans/MullvadVPNUITestsAll.xctestplan @@ -22,6 +22,7 @@ "LoggedInWithTimeUITestCase", "LoggedInWithoutTimeUITestCase", "LoggedOutUITestCase", + "ScreenshotTests", "SettingsMigrationTests" ], "target" : {