From afee4037e2cf5907b9c844c63a71d018db3277bd Mon Sep 17 00:00:00 2001 From: Davide Date: Thu, 13 Feb 2025 08:20:56 +0100 Subject: [PATCH] Fix UI tests for screenshots (#1168) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Outdated after reworking the UI. Some fixes were also needed because: - [WireGuardModule requires a configuration](https://github.com/passepartoutvpn/passepartout/pull/1164) - [OpenVPNModule is interactive when no credentials are set](https://github.com/passepartoutvpn/passepartout/pull/1104) - Mock profile had a wrong category ("" → "default") --- Packages/App/Sources/AppUIMain/AppUIMain.swift | 4 ++++ .../Views/App/InstalledProfileView.swift | 1 - .../AppUIMain/Views/App/ProfileCardView.swift | 2 ++ .../AppUIMain/Views/App/ProfileRowView.swift | 4 ---- .../Views/App/ProfilesHeaderView.swift | 1 + .../OpenVPN/OpenVPNModule+Extensions.swift | 1 + .../Views/Profile/ActiveProfileView.swift | 2 +- .../Domain/AccessibilityInfo.swift | 2 ++ .../Sources/UIAccessibility/Screens/App.swift | 6 +++--- .../UIAccessibility/Screens/Profile.swift | 2 ++ .../xcschemes/PassepartoutUITests.xcscheme | 8 +++++--- .../App/Context/ProfileManager+Testing.swift | 8 +++++++- .../Extensions/XCUIElement+Extensions.swift | 4 ++++ Passepartout/UITests/Main/MainFlowTests.swift | 18 ++++-------------- .../UITests/Main/MainScreenshotTests.swift | 9 ++++----- .../UITests/Main/Screens/AppScreen.swift | 8 ++++---- .../Main/Screens/ProfileEditorScreen.swift | 7 +++++++ .../UITests/TV/Screens/AppScreen.swift | 2 +- 18 files changed, 52 insertions(+), 37 deletions(-) diff --git a/Packages/App/Sources/AppUIMain/AppUIMain.swift b/Packages/App/Sources/AppUIMain/AppUIMain.swift index da6dfc85..3b16c577 100644 --- a/Packages/App/Sources/AppUIMain/AppUIMain.swift +++ b/Packages/App/Sources/AppUIMain/AppUIMain.swift @@ -27,6 +27,7 @@ import CommonLibrary import Foundation import PassepartoutKit import TipKit +import UIAccessibility @_exported import UILibrary public final class AppUIMain: UILibraryConfiguring { @@ -40,6 +41,9 @@ public final class AppUIMain: UILibraryConfiguring { // for debugging // Tips.showAllTipsForTesting() + if AppCommandLine.contains(.uiTesting) { + Tips.hideAllTipsForTesting() + } try? Tips.configure([ .displayFrequency(.immediate) diff --git a/Packages/App/Sources/AppUIMain/Views/App/InstalledProfileView.swift b/Packages/App/Sources/AppUIMain/Views/App/InstalledProfileView.swift index 7d1ba133..6fccd3d4 100644 --- a/Packages/App/Sources/AppUIMain/Views/App/InstalledProfileView.swift +++ b/Packages/App/Sources/AppUIMain/Views/App/InstalledProfileView.swift @@ -50,7 +50,6 @@ struct InstalledProfileView: View, Routable { debugChanges() return HStack(alignment: .center) { cardView - .uiAccessibility(.App.installedProfile) Spacer() toggleButton } diff --git a/Packages/App/Sources/AppUIMain/Views/App/ProfileCardView.swift b/Packages/App/Sources/AppUIMain/Views/App/ProfileCardView.swift index b51f78bc..04396c0a 100644 --- a/Packages/App/Sources/AppUIMain/Views/App/ProfileCardView.swift +++ b/Packages/App/Sources/AppUIMain/Views/App/ProfileCardView.swift @@ -53,6 +53,8 @@ struct ProfileCardView: View { .font(.headline) .themeMultiLine(true) } + .uiAccessibility(.App.profileEdit) + tunnelView .font(.subheadline) diff --git a/Packages/App/Sources/AppUIMain/Views/App/ProfileRowView.swift b/Packages/App/Sources/AppUIMain/Views/App/ProfileRowView.swift index ad8ded77..4487ac38 100644 --- a/Packages/App/Sources/AppUIMain/Views/App/ProfileRowView.swift +++ b/Packages/App/Sources/AppUIMain/Views/App/ProfileRowView.swift @@ -73,9 +73,6 @@ private extension ProfileRowView { ) .contentShape(.rect) .foregroundStyle(.primary) - - // FIXME: ###, UI tests - .uiAccessibility(.App.profileMenu) } var attributesView: some View { @@ -94,7 +91,6 @@ private extension ProfileRowView { flow: flow?.connectionFlow ) .labelsHidden() - // FIXME: ###, UI tests .uiAccessibility(.App.profileToggle) } } diff --git a/Packages/App/Sources/AppUIMain/Views/App/ProfilesHeaderView.swift b/Packages/App/Sources/AppUIMain/Views/App/ProfilesHeaderView.swift index 6d99de07..93a8960b 100644 --- a/Packages/App/Sources/AppUIMain/Views/App/ProfilesHeaderView.swift +++ b/Packages/App/Sources/AppUIMain/Views/App/ProfilesHeaderView.swift @@ -39,5 +39,6 @@ struct ProfilesHeaderView: View { Text(Strings.Views.Verification.message) } } + .uiAccessibility(.App.profilesHeader) } } diff --git a/Packages/App/Sources/AppUIMain/Views/Modules/OpenVPN/OpenVPNModule+Extensions.swift b/Packages/App/Sources/AppUIMain/Views/Modules/OpenVPN/OpenVPNModule+Extensions.swift index d9a7f0d1..9c69e862 100644 --- a/Packages/App/Sources/AppUIMain/Views/Modules/OpenVPN/OpenVPNModule+Extensions.swift +++ b/Packages/App/Sources/AppUIMain/Views/Modules/OpenVPN/OpenVPNModule+Extensions.swift @@ -50,6 +50,7 @@ extension OpenVPNModule.Builder: ModuleShortcutsProviding { NavigationLink(value: OpenVPNView.Subroute.providerServer) { ProviderServerRow(selectedEntity: providerSelection.entity) } + .uiAccessibility(.Profile.providerServerLink) } if providerSelection != nil || configurationBuilder?.authUserPass == true { NavigationLink(value: OpenVPNView.Subroute.credentials) { diff --git a/Packages/App/Sources/AppUITV/Views/Profile/ActiveProfileView.swift b/Packages/App/Sources/AppUITV/Views/Profile/ActiveProfileView.swift index 46f99222..282dce6f 100644 --- a/Packages/App/Sources/AppUITV/Views/Profile/ActiveProfileView.swift +++ b/Packages/App/Sources/AppUITV/Views/Profile/ActiveProfileView.swift @@ -86,7 +86,7 @@ private extension ActiveProfileView { .font(.title) .fontWeight(theme.relevantWeight) .frame(maxWidth: .infinity, alignment: .leading) - .uiAccessibility(.App.installedProfile) + .uiAccessibility(.App.profilesHeader) } var statusView: some View { diff --git a/Packages/App/Sources/UIAccessibility/Domain/AccessibilityInfo.swift b/Packages/App/Sources/UIAccessibility/Domain/AccessibilityInfo.swift index 1221f93c..fb022ab7 100644 --- a/Packages/App/Sources/UIAccessibility/Domain/AccessibilityInfo.swift +++ b/Packages/App/Sources/UIAccessibility/Domain/AccessibilityInfo.swift @@ -36,6 +36,8 @@ public struct AccessibilityInfo: Equatable, Sendable { case menuItem case text + + case toggle } public let id: String diff --git a/Packages/App/Sources/UIAccessibility/Screens/App.swift b/Packages/App/Sources/UIAccessibility/Screens/App.swift index ca6fbb3e..627a3197 100644 --- a/Packages/App/Sources/UIAccessibility/Screens/App.swift +++ b/Packages/App/Sources/UIAccessibility/Screens/App.swift @@ -37,10 +37,10 @@ extension AccessibilityInfo { public static let profile = AccessibilityInfo("app.profileList.profile", .button) } - public static let installedProfile = AccessibilityInfo("app.installedProfile", .text) + public static let profilesHeader = AccessibilityInfo("app.profilesHeader", .text) - public static let profileToggle = AccessibilityInfo("app.profileToggle", .button) + public static let profileToggle = AccessibilityInfo("app.profileToggle", .toggle) - public static let profileMenu = AccessibilityInfo("app.profileMenu", .menu) + public static let profileEdit = AccessibilityInfo("app.profileEdit", .button) } } diff --git a/Packages/App/Sources/UIAccessibility/Screens/Profile.swift b/Packages/App/Sources/UIAccessibility/Screens/Profile.swift index cb932eda..257d7122 100644 --- a/Packages/App/Sources/UIAccessibility/Screens/Profile.swift +++ b/Packages/App/Sources/UIAccessibility/Screens/Profile.swift @@ -31,6 +31,8 @@ extension AccessibilityInfo { public static let moduleLink = AccessibilityInfo("profile.moduleLink", .link) + public static let providerServerLink = AccessibilityInfo("profile.providerServerLink", .link) + public static let cancel = AccessibilityInfo("profile.cancel", .button) } } diff --git a/Passepartout.xcodeproj/xcshareddata/xcschemes/PassepartoutUITests.xcscheme b/Passepartout.xcodeproj/xcshareddata/xcschemes/PassepartoutUITests.xcscheme index 42dca2f7..19d15b5c 100644 --- a/Passepartout.xcodeproj/xcshareddata/xcschemes/PassepartoutUITests.xcscheme +++ b/Passepartout.xcodeproj/xcshareddata/xcschemes/PassepartoutUITests.xcscheme @@ -13,8 +13,9 @@ buildForProfiling = "NO" buildForArchiving = "NO" buildForAnalyzing = "NO"> - - + + @@ -25,7 +26,8 @@ shouldUseLaunchSchemeArgsEnv = "YES"> + reference = "container:Passepartout/UITests/TVScreenshots.xctestplan" + default = "YES"> diff --git a/Passepartout/App/Context/ProfileManager+Testing.swift b/Passepartout/App/Context/ProfileManager+Testing.swift index c2bf5f2e..a08d2bf5 100644 --- a/Passepartout/App/Context/ProfileManager+Testing.swift +++ b/Passepartout/App/Context/ProfileManager+Testing.swift @@ -56,6 +56,7 @@ extension ProfileManager { ovpnBuilder.isInteractive = true #endif ovpnBuilder.providerEntity = mockHideMeEntity + ovpnBuilder.credentials = OpenVPN.Credentials.Builder(username: "foo", password: "bar").build() moduleBuilder = ovpnBuilder } else if var onDemandBuilder = moduleBuilder as? OnDemandModule.Builder { #if !os(tvOS) @@ -93,6 +94,11 @@ extension ProfileManager { } } + if var wgBuilder = moduleBuilder as? WireGuardModule.Builder { + wgBuilder.configurationBuilder = WireGuard.Configuration.Builder(privateKey: "") + moduleBuilder = wgBuilder + } + let module = try moduleBuilder.tryBuild() builder.modules.append(module) } @@ -163,7 +169,7 @@ private extension ProfileManager { serverId: "be-v4", supportedConfigurationIdentifiers: ["OpenVPN"], supportedPresetIds: nil, - categoryName: "", + categoryName: "default", countryCode: "BE", otherCountryCodes: nil, area: nil diff --git a/Passepartout/UITests/Extensions/XCUIElement+Extensions.swift b/Passepartout/UITests/Extensions/XCUIElement+Extensions.swift index 5ae20124..975e2ae9 100644 --- a/Passepartout/UITests/Extensions/XCUIElement+Extensions.swift +++ b/Passepartout/UITests/Extensions/XCUIElement+Extensions.swift @@ -48,6 +48,8 @@ private extension XCUIElement { return buttons case .text: return staticTexts + case .toggle: + return switches } #else switch elementType { @@ -59,6 +61,8 @@ private extension XCUIElement { return menuItems case .text: return staticTexts + case .toggle: + return checkBoxes } #endif } diff --git a/Passepartout/UITests/Main/MainFlowTests.swift b/Passepartout/UITests/Main/MainFlowTests.swift index ad1e8609..ca606d17 100644 --- a/Passepartout/UITests/Main/MainFlowTests.swift +++ b/Passepartout/UITests/Main/MainFlowTests.swift @@ -47,33 +47,23 @@ final class MainFlowTests: XCTestCase { func testEditProfile() { AppScreen(app: app) .waitForProfiles() - .openProfileMenu(at: 2) - .editProfile() + .editProfile(at: 2) } func testEditProfileModule() { AppScreen(app: app) .waitForProfiles() - .openProfileMenu(at: 2) - .editProfile() + .editProfile(at: 2) .enterModule(at: 1) .leaveModule() } - func testConnectToProviderServer() { - AppScreen(app: app) - .waitForProfiles() - .openProfileMenu(at: 2) - .connectToProfile() - } - #if os(iOS) func testDiscloseProviderCountry() { AppScreen(app: app) .waitForProfiles() - .openProfileMenu(at: 2) - .connectToProfile() - .discloseCountry(at: 2) + .editProfile(at: 2) + .editProviderServer() } #endif } diff --git a/Passepartout/UITests/Main/MainScreenshotTests.swift b/Passepartout/UITests/Main/MainScreenshotTests.swift index 880dfb24..30c65f2a 100644 --- a/Passepartout/UITests/Main/MainScreenshotTests.swift +++ b/Passepartout/UITests/Main/MainScreenshotTests.swift @@ -48,11 +48,10 @@ final class MainScreenshotTests: XCTestCase, XCUIApplicationProviding { func testTakeScreenshots() async throws { let root = AppScreen(app: app) .waitForProfiles() - .enableProfile(at: 0) + .enableProfile(at: 1) let profile = root - .openProfileMenu(at: 2) - .editProfile() + .editProfile(at: 2) await pause() try snapshot("03", "ProfileEditor", target: .sheet) @@ -78,8 +77,8 @@ final class MainScreenshotTests: XCTestCase, XCUIApplicationProviding { try snapshot("01", "Connected") app - .openProfileMenu(at: 2) - .connectToProfile() + .editProfile(at: 2) + .editProviderServer() #if os(iOS) .discloseCountry(at: 2) #endif diff --git a/Passepartout/UITests/Main/Screens/AppScreen.swift b/Passepartout/UITests/Main/Screens/AppScreen.swift index 585a5f4f..51c9aecb 100644 --- a/Passepartout/UITests/Main/Screens/AppScreen.swift +++ b/Passepartout/UITests/Main/Screens/AppScreen.swift @@ -33,7 +33,7 @@ struct AppScreen { @discardableResult func waitForProfiles() -> Self { - app.get(.App.installedProfile) + app.get(.App.profilesHeader) return self } @@ -45,9 +45,9 @@ struct AppScreen { } @discardableResult - func openProfileMenu(at index: Int) -> ProfileMenuScreen { - let profileMenu = app.get(.App.profileMenu, at: index) + func editProfile(at index: Int) -> ProfileEditorScreen { + let profileMenu = app.get(.App.profileEdit, at: index) profileMenu.tap() - return ProfileMenuScreen(app: app) + return ProfileEditorScreen(app: app) } } diff --git a/Passepartout/UITests/Main/Screens/ProfileEditorScreen.swift b/Passepartout/UITests/Main/Screens/ProfileEditorScreen.swift index 9f30d90f..4742e406 100644 --- a/Passepartout/UITests/Main/Screens/ProfileEditorScreen.swift +++ b/Passepartout/UITests/Main/Screens/ProfileEditorScreen.swift @@ -48,6 +48,13 @@ struct ProfileEditorScreen { return self } + @discardableResult + func editProviderServer() -> ProviderServersScreen { + let providerServerLink = app.get(.Profile.providerServerLink) + providerServerLink.tap() + return ProviderServersScreen(app: app) + } + @discardableResult func closeProfile() -> AppScreen { let cancelButton = app.get(.Profile.cancel) diff --git a/Passepartout/UITests/TV/Screens/AppScreen.swift b/Passepartout/UITests/TV/Screens/AppScreen.swift index f43618b9..c921af58 100644 --- a/Passepartout/UITests/TV/Screens/AppScreen.swift +++ b/Passepartout/UITests/TV/Screens/AppScreen.swift @@ -35,7 +35,7 @@ struct AppScreen { @discardableResult func waitForProfiles() -> Self { - app.get(.App.installedProfile) + app.get(.App.profilesHeader) return self }