Autogenerate screenshots for all platforms (#998)
Unframed for now. - Split Main/TV targets - Extend ProfileManager for screenshot scenarios - Rename UITesting to UIAccessibility Active profile looks very big on TV simulator, temporarily commented `.padding(.top, 50)` in ActiveProfileView. Closes #974
This commit is contained in:
parent
a626722224
commit
f441a2eed0
|
@ -55,12 +55,12 @@ let package = Package(
|
|||
]
|
||||
),
|
||||
.library(
|
||||
name: "UILibrary",
|
||||
targets: ["UILibrary"]
|
||||
name: "UIAccessibility",
|
||||
targets: ["UIAccessibility"]
|
||||
),
|
||||
.library(
|
||||
name: "UITesting",
|
||||
targets: ["UITesting"]
|
||||
name: "UILibrary",
|
||||
targets: ["UILibrary"]
|
||||
)
|
||||
],
|
||||
dependencies: [
|
||||
|
@ -186,20 +186,20 @@ let package = Package(
|
|||
.product(name: "PassepartoutWireGuardGo", package: "passepartoutkit-source-wireguard-go")
|
||||
]
|
||||
),
|
||||
.target(
|
||||
name: "UIAccessibility"
|
||||
),
|
||||
.target(
|
||||
name: "UILibrary",
|
||||
dependencies: [
|
||||
"CommonAPI",
|
||||
"CommonLibrary",
|
||||
"UITesting"
|
||||
"UIAccessibility"
|
||||
],
|
||||
resources: [
|
||||
.process("Resources")
|
||||
]
|
||||
),
|
||||
.target(
|
||||
name: "UITesting"
|
||||
),
|
||||
.testTarget(
|
||||
name: "AppUIMainTests",
|
||||
dependencies: ["AppUIMain"]
|
||||
|
|
|
@ -27,7 +27,7 @@ import CommonLibrary
|
|||
import CommonUtils
|
||||
import PassepartoutKit
|
||||
import SwiftUI
|
||||
import UITesting
|
||||
import UIAccessibility
|
||||
|
||||
struct InstalledProfileView: View, Routable {
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ import CommonLibrary
|
|||
import CommonUtils
|
||||
import PassepartoutKit
|
||||
import SwiftUI
|
||||
import UITesting
|
||||
import UIAccessibility
|
||||
|
||||
struct ProfileContextMenu: View, Routable {
|
||||
enum Style {
|
||||
|
|
|
@ -25,9 +25,13 @@
|
|||
|
||||
import PassepartoutKit
|
||||
import SwiftUI
|
||||
import UIAccessibility
|
||||
|
||||
struct ModuleViewModifier<T>: ViewModifier where T: ModuleBuilder & Equatable {
|
||||
|
||||
@Environment(\.isUITesting)
|
||||
private var isUITesting
|
||||
|
||||
@ObservedObject
|
||||
var editor: ProfileEditor
|
||||
|
||||
|
@ -37,7 +41,9 @@ struct ModuleViewModifier<T>: ViewModifier where T: ModuleBuilder & Equatable {
|
|||
Form {
|
||||
content
|
||||
#if DEBUG
|
||||
UUIDSection(uuid: draft.id)
|
||||
if !isUITesting {
|
||||
UUIDSection(uuid: draft.id)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
.themeForm()
|
||||
|
|
|
@ -37,5 +37,6 @@ struct ProfileNameSection: View {
|
|||
placeholder: Strings.Placeholders.Profile.name,
|
||||
footer: Strings.Views.Profile.Sections.Name.footer
|
||||
)
|
||||
.uiAccessibility(.Profile.name)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,6 +131,7 @@ private extension ProfileEditView {
|
|||
.contentShape(.rect)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.uiAccessibility(.Profile.moduleLink)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,10 +29,14 @@ import CommonLibrary
|
|||
import CommonUtils
|
||||
import PassepartoutKit
|
||||
import SwiftUI
|
||||
import UIAccessibility
|
||||
|
||||
struct ModuleListView: View, Routable {
|
||||
static let generalModuleId = UUID()
|
||||
|
||||
@Environment(\.isUITesting)
|
||||
private var isUITesting
|
||||
|
||||
@ObservedObject
|
||||
var profileEditor: ProfileEditor
|
||||
|
||||
|
@ -58,6 +62,7 @@ struct ModuleListView: View, Routable {
|
|||
NavigationLink(value: ProfileSplitView.Detail.module(id: module.id)) {
|
||||
moduleRow(for: module)
|
||||
}
|
||||
.uiAccessibility(.Profile.moduleLink)
|
||||
}
|
||||
.onMove(perform: moveModules)
|
||||
}
|
||||
|
@ -82,8 +87,10 @@ private extension ModuleListView {
|
|||
)
|
||||
}
|
||||
Spacer()
|
||||
EditorModuleToggle(profileEditor: profileEditor, module: module) {
|
||||
EmptyView()
|
||||
if !isUITesting {
|
||||
EditorModuleToggle(profileEditor: profileEditor, module: module) {
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import CommonAPI
|
|||
import CommonLibrary
|
||||
import PassepartoutKit
|
||||
import SwiftUI
|
||||
import UIAccessibility
|
||||
|
||||
extension VPNProviderServerView {
|
||||
struct ContentView: View {
|
||||
|
@ -129,6 +130,7 @@ private extension VPNProviderServerView.ContentView {
|
|||
} label: {
|
||||
ThemeCountryText(code)
|
||||
}
|
||||
.uiAccessibility(.VPNServers.countryGroup)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ import CommonLibrary
|
|||
import CommonUtils
|
||||
import PassepartoutKit
|
||||
import SwiftUI
|
||||
import UIAccessibility
|
||||
|
||||
struct ActiveProfileView: View {
|
||||
|
||||
|
@ -73,7 +74,7 @@ struct ActiveProfileView: View {
|
|||
.clipShape(RoundedRectangle(cornerRadius: 50))
|
||||
}
|
||||
.padding(.horizontal, 100)
|
||||
.padding(.top, 50)
|
||||
// .padding(.top, 50)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
|
@ -86,6 +87,7 @@ private extension ActiveProfileView {
|
|||
.font(.title)
|
||||
.fontWeight(theme.relevantWeight)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.uiAccessibility(.App.installedProfile)
|
||||
}
|
||||
|
||||
var statusView: some View {
|
||||
|
|
|
@ -27,6 +27,7 @@ import CommonLibrary
|
|||
import CommonUtils
|
||||
import PassepartoutKit
|
||||
import SwiftUI
|
||||
import UIAccessibility
|
||||
|
||||
struct ProfileListView: View {
|
||||
|
||||
|
@ -84,6 +85,7 @@ private extension ProfileListView {
|
|||
}
|
||||
)
|
||||
.focused($focusedField, equals: .profile(preview.id))
|
||||
.uiAccessibility(.App.ProfileList.profile)
|
||||
}
|
||||
|
||||
func toggleView(for preview: ProfilePreview) -> some View {
|
||||
|
|
|
@ -29,6 +29,8 @@ public struct AccessibilityInfo: Equatable, Sendable {
|
|||
public enum ElementType: Sendable {
|
||||
case button
|
||||
|
||||
case link
|
||||
|
||||
case menu
|
||||
|
||||
case menuItem
|
|
@ -33,14 +33,14 @@ extension AccessibilityInfo {
|
|||
public static let connectTo = AccessibilityInfo("app.profileMenu.connectTo", .menuItem)
|
||||
}
|
||||
|
||||
public enum ProfileList {
|
||||
public static let profile = AccessibilityInfo("app.profileList.profile", .button)
|
||||
}
|
||||
|
||||
public static let installedProfile = AccessibilityInfo("app.installedProfile", .text)
|
||||
|
||||
public static let profileToggle = AccessibilityInfo("app.profileToggle", .button)
|
||||
|
||||
public static let profileMenu = AccessibilityInfo("app.profileMenu", .menu)
|
||||
}
|
||||
|
||||
public enum Profile {
|
||||
public static let cancel = AccessibilityInfo("profile.cancel", .button)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// Profile.swift
|
||||
// Passepartout
|
||||
//
|
||||
// Created by Davide De Rosa on 12/2/24.
|
||||
// Copyright (c) 2024 Davide De Rosa. All rights reserved.
|
||||
//
|
||||
// https://github.com/passepartoutvpn
|
||||
//
|
||||
// This file is part of Passepartout.
|
||||
//
|
||||
// Passepartout is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Passepartout is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension AccessibilityInfo {
|
||||
public enum Profile {
|
||||
public static let name = AccessibilityInfo("profile.name", .text)
|
||||
|
||||
public static let moduleLink = AccessibilityInfo("profile.moduleLink", .link)
|
||||
|
||||
public static let cancel = AccessibilityInfo("profile.cancel", .button)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// VPNServers.swift
|
||||
// Passepartout
|
||||
//
|
||||
// Created by Davide De Rosa on 12/9/24.
|
||||
// Copyright (c) 2024 Davide De Rosa. All rights reserved.
|
||||
//
|
||||
// https://github.com/passepartoutvpn
|
||||
//
|
||||
// This file is part of Passepartout.
|
||||
//
|
||||
// Passepartout is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Passepartout is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension AccessibilityInfo {
|
||||
public enum VPNServers {
|
||||
public static let countryGroup = AccessibilityInfo("vpnServers.countryGroup", .button)
|
||||
}
|
||||
}
|
|
@ -28,7 +28,7 @@ import CommonLibrary
|
|||
import CommonUtils
|
||||
import Foundation
|
||||
import PassepartoutKit
|
||||
import UITesting
|
||||
import UIAccessibility
|
||||
|
||||
@MainActor
|
||||
public final class AppContext: ObservableObject, Sendable {
|
||||
|
|
|
@ -8,11 +8,11 @@
|
|||
|
||||
/* Begin PBXBuildFile section */
|
||||
0E08447C2CF86F2A00ECED7C /* XCTestCase+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E08447B2CF86F2A00ECED7C /* XCTestCase+Extensions.swift */; };
|
||||
0E2D68DC2CF7CF7500DC95BC /* UITesting in Frameworks */ = {isa = PBXBuildFile; productRef = 0E2D68DB2CF7CF7500DC95BC /* UITesting */; };
|
||||
0E3E22962CE53510005135DF /* AppUIMain in Frameworks */ = {isa = PBXBuildFile; platformFilters = (ios, macos, ); productRef = 0E3E22952CE53510005135DF /* AppUIMain */; };
|
||||
0E3E22982CE53510005135DF /* AppUITV in Frameworks */ = {isa = PBXBuildFile; platformFilters = (tvos, ); productRef = 0E3E22972CE53510005135DF /* AppUITV */; };
|
||||
0E3FF4BA2CE3AFBC00BFF640 /* Profiles.sqlite in Resources */ = {isa = PBXBuildFile; fileRef = 0E3FF4B72CE3AFBC00BFF640 /* Profiles.sqlite */; };
|
||||
0E3FF4BB2CE3AFBC00BFF640 /* MigrationManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E3FF4B92CE3AFBC00BFF640 /* MigrationManagerTests.swift */; };
|
||||
0E418AB52D074F0E00D33D47 /* VPNServersScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E418AB42D074F0E00D33D47 /* VPNServersScreen.swift */; platformFilters = (ios, macos, ); };
|
||||
0E483E812CE64D6B00584B32 /* TunnelContext+Shared.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E483E7F2CE64D6B00584B32 /* TunnelContext+Shared.swift */; };
|
||||
0E60512C2CE5393C00F763D4 /* PassepartoutImplementations in Frameworks */ = {isa = PBXBuildFile; productRef = 0E60512B2CE5393C00F763D4 /* PassepartoutImplementations */; };
|
||||
0E6EEEE32CF8CABA0076E2B0 /* AppContext+Testing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E6EEEE12CF8CABA0076E2B0 /* AppContext+Testing.swift */; };
|
||||
|
@ -23,9 +23,9 @@
|
|||
0E7C3CCD2C9AF44600B72E69 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7C3CCC2C9AF44600B72E69 /* AppDelegate.swift */; };
|
||||
0E7E3D692B9345FD002BBDB4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0E7E3D5C2B9345FD002BBDB4 /* Assets.xcassets */; };
|
||||
0E7E3D6B2B9345FD002BBDB4 /* PassepartoutApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7E3D5F2B9345FD002BBDB4 /* PassepartoutApp.swift */; };
|
||||
0E7F460E2CF7F01600B1C53A /* FlowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7F460B2CF7F01600B1C53A /* FlowTests.swift */; };
|
||||
0E7F460E2CF7F01600B1C53A /* FlowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7F460B2CF7F01600B1C53A /* FlowTests.swift */; platformFilters = (ios, macos, ); };
|
||||
0E7F460F2CF7F01600B1C53A /* XCUIApplication+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7F460C2CF7F01600B1C53A /* XCUIApplication+Extensions.swift */; };
|
||||
0E7F46122CF7F44C00B1C53A /* AppScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7F46102CF7F44C00B1C53A /* AppScreen.swift */; };
|
||||
0E7F46122CF7F44C00B1C53A /* AppScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7F46102CF7F44C00B1C53A /* AppScreen.swift */; platformFilters = (ios, macos, ); };
|
||||
0E81955A2CFDA75200CC8FFD /* Dependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E8195592CFDA75200CC8FFD /* Dependencies.swift */; };
|
||||
0E81955B2CFDA7BF00CC8FFD /* Dependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E8195592CFDA75200CC8FFD /* Dependencies.swift */; };
|
||||
0E8DFD482D05FA7000531CDE /* TunnelContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E8DFD472D05FA7000531CDE /* TunnelContext.swift */; };
|
||||
|
@ -36,10 +36,14 @@
|
|||
0E8DFD532D05FE5A00531CDE /* Dependencies+PassepartoutKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E8DFD4C2D05FE5A00531CDE /* Dependencies+PassepartoutKit.swift */; };
|
||||
0E8DFD542D05FE5A00531CDE /* Dependencies+IAPManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E8DFD4B2D05FE5A00531CDE /* Dependencies+IAPManager.swift */; };
|
||||
0E8DFD562D05FE5A00531CDE /* Dependencies+CoreData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E8DFD492D05FE5A00531CDE /* Dependencies+CoreData.swift */; };
|
||||
0E916B782CF80FD60072921A /* ProfileEditorScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E916B772CF80FD60072921A /* ProfileEditorScreen.swift */; };
|
||||
0E916B782CF80FD60072921A /* ProfileEditorScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E916B772CF80FD60072921A /* ProfileEditorScreen.swift */; platformFilters = (ios, macos, ); };
|
||||
0E916B7C2CF811EB0072921A /* XCUIElement+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E916B7B2CF811EB0072921A /* XCUIElement+Extensions.swift */; };
|
||||
0E94EE582B93554B00588243 /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7E3D672B9345FD002BBDB4 /* PacketTunnelProvider.swift */; };
|
||||
0EAD6A1B2CF7F79A00CC1F02 /* ScreenshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EAD6A1A2CF7F79A00CC1F02 /* ScreenshotTests.swift */; };
|
||||
0EA6340C2D088C8200180D7C /* UIAccessibility in Frameworks */ = {isa = PBXBuildFile; productRef = 0EA6340B2D088C8200180D7C /* UIAccessibility */; };
|
||||
0EA6340E2D08995800180D7C /* ScreenshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA6340D2D08995800180D7C /* ScreenshotTests.swift */; platformFilters = (tvos, ); };
|
||||
0EA634122D08997300180D7C /* FlowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA634112D08997300180D7C /* FlowTests.swift */; platformFilters = (tvos, ); };
|
||||
0EA634142D08998700180D7C /* AppScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA634132D08998700180D7C /* AppScreen.swift */; platformFilters = (tvos, ); };
|
||||
0EAD6A1B2CF7F79A00CC1F02 /* ScreenshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EAD6A1A2CF7F79A00CC1F02 /* ScreenshotTests.swift */; platformFilters = (ios, macos, ); };
|
||||
0EAEC8A92D05DB8D001AA50C /* DefaultAppProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EAEC8A62D05DB8D001AA50C /* DefaultAppProcessor.swift */; };
|
||||
0EAEC8AA2D05DB8D001AA50C /* DefaultTunnelProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EAEC8A72D05DB8D001AA50C /* DefaultTunnelProcessor.swift */; };
|
||||
0EB08B982CA46F4900A02591 /* AppPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0EB08B962CA46F4900A02591 /* AppPlist.strings */; };
|
||||
|
@ -47,7 +51,7 @@
|
|||
0EC066D12C7DC47600D88A94 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0EC066D02C7DC47600D88A94 /* LaunchScreen.storyboard */; platformFilter = ios; };
|
||||
0EC332CA2B8A1808000B9C2F /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0EC332C92B8A1808000B9C2F /* NetworkExtension.framework */; };
|
||||
0EC332D22B8A1808000B9C2F /* PassepartoutTunnel.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 0EC332C82B8A1808000B9C2F /* PassepartoutTunnel.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
0EC418D22CF86B7400AC6F2F /* ProfileMenuScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EC418D12CF86B7400AC6F2F /* ProfileMenuScreen.swift */; };
|
||||
0EC418D22CF86B7400AC6F2F /* ProfileMenuScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EC418D12CF86B7400AC6F2F /* ProfileMenuScreen.swift */; platformFilters = (ios, macos, ); };
|
||||
0EC797422B9378E000C093B7 /* AppContext+Shared.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EC797402B9378E000C093B7 /* AppContext+Shared.swift */; };
|
||||
0ED61CF82CD0418C008FE259 /* App+macOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ED61CF72CD0418C008FE259 /* App+macOS.swift */; };
|
||||
0ED61CFA2CD04192008FE259 /* App+iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ED61CF92CD04192008FE259 /* App+iOS.swift */; };
|
||||
|
@ -142,6 +146,7 @@
|
|||
0E3FF4AE2CE3AF6F00BFF640 /* PassepartoutTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PassepartoutTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
0E3FF4B72CE3AFBC00BFF640 /* Profiles.sqlite */ = {isa = PBXFileReference; lastKnownFileType = file; path = Profiles.sqlite; sourceTree = "<group>"; };
|
||||
0E3FF4B92CE3AFBC00BFF640 /* MigrationManagerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationManagerTests.swift; sourceTree = "<group>"; };
|
||||
0E418AB42D074F0E00D33D47 /* VPNServersScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNServersScreen.swift; sourceTree = "<group>"; };
|
||||
0E483E7F2CE64D6B00584B32 /* TunnelContext+Shared.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TunnelContext+Shared.swift"; sourceTree = "<group>"; };
|
||||
0E5DFDDC2CDB8F9100F2DE70 /* Passepartout.storekit */ = {isa = PBXFileReference; lastKnownFileType = text; path = Passepartout.storekit; sourceTree = "<group>"; };
|
||||
0E6EEEE12CF8CABA0076E2B0 /* AppContext+Testing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppContext+Testing.swift"; sourceTree = "<group>"; };
|
||||
|
@ -171,6 +176,9 @@
|
|||
0E916B772CF80FD60072921A /* ProfileEditorScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileEditorScreen.swift; sourceTree = "<group>"; };
|
||||
0E916B7B2CF811EB0072921A /* XCUIElement+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "XCUIElement+Extensions.swift"; sourceTree = "<group>"; };
|
||||
0E94EE5C2B93570600588243 /* Tunnel.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Tunnel.plist; sourceTree = "<group>"; };
|
||||
0EA6340D2D08995800180D7C /* ScreenshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenshotTests.swift; sourceTree = "<group>"; };
|
||||
0EA634112D08997300180D7C /* FlowTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlowTests.swift; sourceTree = "<group>"; };
|
||||
0EA634132D08998700180D7C /* AppScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppScreen.swift; sourceTree = "<group>"; };
|
||||
0EAD6A1A2CF7F79A00CC1F02 /* ScreenshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenshotTests.swift; sourceTree = "<group>"; };
|
||||
0EAEC8A62D05DB8D001AA50C /* DefaultAppProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultAppProcessor.swift; sourceTree = "<group>"; };
|
||||
0EAEC8A72D05DB8D001AA50C /* DefaultTunnelProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultTunnelProcessor.swift; sourceTree = "<group>"; };
|
||||
|
@ -213,7 +221,7 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
0E2D68DC2CF7CF7500DC95BC /* UITesting in Frameworks */,
|
||||
0EA6340C2D088C8200180D7C /* UIAccessibility in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -297,6 +305,16 @@
|
|||
path = Resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0E418AB72D0752D100D33D47 /* TV */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0EA634102D08996500180D7C /* Screens */,
|
||||
0EA634112D08997300180D7C /* FlowTests.swift */,
|
||||
0EA6340D2D08995800180D7C /* ScreenshotTests.swift */,
|
||||
);
|
||||
path = TV;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0E757F112CD0CFFC006E13E1 /* LoginItem */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -366,9 +384,8 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
0E916B7A2CF811DE0072921A /* Extensions */,
|
||||
0E916B7E2CF81A110072921A /* Screens */,
|
||||
0E7F460B2CF7F01600B1C53A /* FlowTests.swift */,
|
||||
0EAD6A1A2CF7F79A00CC1F02 /* ScreenshotTests.swift */,
|
||||
0EC418C92CF81C6A00AC6F2F /* Main */,
|
||||
0E418AB72D0752D100D33D47 /* TV */,
|
||||
);
|
||||
path = UITests;
|
||||
sourceTree = "<group>";
|
||||
|
@ -408,7 +425,18 @@
|
|||
0E916B7E2CF81A110072921A /* Screens */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0EC418C92CF81C6A00AC6F2F /* Main */,
|
||||
0E7F46102CF7F44C00B1C53A /* AppScreen.swift */,
|
||||
0E916B772CF80FD60072921A /* ProfileEditorScreen.swift */,
|
||||
0EC418D12CF86B7400AC6F2F /* ProfileMenuScreen.swift */,
|
||||
0E418AB42D074F0E00D33D47 /* VPNServersScreen.swift */,
|
||||
);
|
||||
path = Screens;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0EA634102D08996500180D7C /* Screens */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0EA634132D08998700180D7C /* AppScreen.swift */,
|
||||
);
|
||||
path = Screens;
|
||||
sourceTree = "<group>";
|
||||
|
@ -416,9 +444,9 @@
|
|||
0EC418C92CF81C6A00AC6F2F /* Main */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0E7F46102CF7F44C00B1C53A /* AppScreen.swift */,
|
||||
0E916B772CF80FD60072921A /* ProfileEditorScreen.swift */,
|
||||
0EC418D12CF86B7400AC6F2F /* ProfileMenuScreen.swift */,
|
||||
0E916B7E2CF81A110072921A /* Screens */,
|
||||
0E7F460B2CF7F01600B1C53A /* FlowTests.swift */,
|
||||
0EAD6A1A2CF7F79A00CC1F02 /* ScreenshotTests.swift */,
|
||||
);
|
||||
path = Main;
|
||||
sourceTree = "<group>";
|
||||
|
@ -527,7 +555,7 @@
|
|||
);
|
||||
name = PassepartoutUITests;
|
||||
packageProductDependencies = (
|
||||
0E2D68DB2CF7CF7500DC95BC /* UITesting */,
|
||||
0EA6340B2D088C8200180D7C /* UIAccessibility */,
|
||||
);
|
||||
productName = PassepartoutUITests;
|
||||
productReference = 0E78FE4C2CF799F400B0C5BF /* PassepartoutUITests.xctest */;
|
||||
|
@ -742,11 +770,15 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
0E08447C2CF86F2A00ECED7C /* XCTestCase+Extensions.swift in Sources */,
|
||||
0EA6340E2D08995800180D7C /* ScreenshotTests.swift in Sources */,
|
||||
0EA634122D08997300180D7C /* FlowTests.swift in Sources */,
|
||||
0E7F460E2CF7F01600B1C53A /* FlowTests.swift in Sources */,
|
||||
0E916B782CF80FD60072921A /* ProfileEditorScreen.swift in Sources */,
|
||||
0EA634142D08998700180D7C /* AppScreen.swift in Sources */,
|
||||
0E916B7C2CF811EB0072921A /* XCUIElement+Extensions.swift in Sources */,
|
||||
0EAD6A1B2CF7F79A00CC1F02 /* ScreenshotTests.swift in Sources */,
|
||||
0E7F460F2CF7F01600B1C53A /* XCUIApplication+Extensions.swift in Sources */,
|
||||
0E418AB52D074F0E00D33D47 /* VPNServersScreen.swift in Sources */,
|
||||
0EC418D22CF86B7400AC6F2F /* ProfileMenuScreen.swift in Sources */,
|
||||
0E7F46122CF7F44C00B1C53A /* AppScreen.swift in Sources */,
|
||||
);
|
||||
|
@ -1349,10 +1381,6 @@
|
|||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
0E2D68DB2CF7CF7500DC95BC /* UITesting */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
productName = UITesting;
|
||||
};
|
||||
0E3E22952CE53510005135DF /* AppUIMain */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
productName = AppUIMain;
|
||||
|
@ -1373,6 +1401,10 @@
|
|||
isa = XCSwiftPackageProductDependency;
|
||||
productName = TunnelLibrary;
|
||||
};
|
||||
0EA6340B2D088C8200180D7C /* UIAccessibility */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
productName = UIAccessibility;
|
||||
};
|
||||
0EBE80DB2BF55C0E00E36A20 /* TunnelLibrary */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
productName = TunnelLibrary;
|
||||
|
|
|
@ -85,7 +85,7 @@
|
|||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = "-pp_ui_testing"
|
||||
isEnabled = "NO">
|
||||
isEnabled = "YES">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = "-pp_fake_migration"
|
||||
|
|
|
@ -26,8 +26,8 @@
|
|||
import CommonLibrary
|
||||
import PassepartoutKit
|
||||
import SwiftUI
|
||||
import UIAccessibility
|
||||
import UILibrary
|
||||
import UITesting
|
||||
|
||||
@MainActor
|
||||
final class AppDelegate: NSObject {
|
||||
|
|
|
@ -32,8 +32,8 @@ import CommonUtils
|
|||
import Foundation
|
||||
import LegacyV2
|
||||
import PassepartoutKit
|
||||
import UIAccessibility
|
||||
import UILibrary
|
||||
import UITesting
|
||||
|
||||
extension AppContext {
|
||||
static let shared: AppContext = {
|
||||
|
|
|
@ -48,7 +48,10 @@ extension AppContext {
|
|||
)
|
||||
let tunnelEnvironment = InMemoryEnvironment()
|
||||
let tunnel = ExtendedTunnel(
|
||||
tunnel: Tunnel(strategy: FakeTunnelStrategy(environment: tunnelEnvironment)),
|
||||
tunnel: Tunnel(strategy: FakeTunnelStrategy(
|
||||
environment: tunnelEnvironment,
|
||||
dataCountDelta: DataCount(2 * 1200000, 1200000)
|
||||
)),
|
||||
environment: tunnelEnvironment,
|
||||
processor: processor,
|
||||
interval: Constants.shared.tunnel.refreshInterval
|
||||
|
|
|
@ -52,10 +52,47 @@ extension ProfileManager {
|
|||
assert((moduleBuilder as? any ProviderSelecting)?.providerId == parameters.providerId)
|
||||
}
|
||||
|
||||
if parameters.name == "Hide.me",
|
||||
var ovpnBuilder = moduleBuilder as? OpenVPNModule.Builder {
|
||||
ovpnBuilder.isInteractive = true
|
||||
moduleBuilder = ovpnBuilder
|
||||
if parameters.name == "Hide.me" {
|
||||
if var ovpnBuilder = moduleBuilder as? OpenVPNModule.Builder {
|
||||
#if !os(tvOS)
|
||||
ovpnBuilder.isInteractive = true
|
||||
#endif
|
||||
ovpnBuilder.providerEntity = mockHideMeEntity
|
||||
moduleBuilder = ovpnBuilder
|
||||
} else if var onDemandBuilder = moduleBuilder as? OnDemandModule.Builder {
|
||||
#if !os(tvOS)
|
||||
onDemandBuilder.isEnabled = true
|
||||
#endif
|
||||
onDemandBuilder.policy = .excluding
|
||||
onDemandBuilder.withSSIDs = [
|
||||
"Friend's House": false,
|
||||
"My Home Network": true,
|
||||
"Safe Wi-Fi": true
|
||||
]
|
||||
moduleBuilder = onDemandBuilder
|
||||
} else if var dnsBuilder = moduleBuilder as? DNSModule.Builder {
|
||||
dnsBuilder.protocolType = .https
|
||||
dnsBuilder.dohURL = "https://cloudflare-dns.com/dns-query"
|
||||
dnsBuilder.servers = ["1.1.1.1", "1.0.0.1"]
|
||||
dnsBuilder.domainName = "my-domain.com"
|
||||
dnsBuilder.searchDomains = ["search-one.com", "search-two.org"]
|
||||
moduleBuilder = dnsBuilder
|
||||
}
|
||||
}
|
||||
|
||||
if parameters.name == "My VPS" {
|
||||
if var ovpnBuilder = moduleBuilder as? OpenVPNModule.Builder {
|
||||
var cfgBuilder = OpenVPN.Configuration.Builder()
|
||||
cfgBuilder.ca = .init(pem: "...")
|
||||
cfgBuilder.remotes = [
|
||||
ExtendedEndpoint(rawValue: "1.2.3.4:UDP:1234")!
|
||||
]
|
||||
ovpnBuilder.configurationBuilder = cfgBuilder
|
||||
moduleBuilder = ovpnBuilder
|
||||
} else if var onDemandBuilder = moduleBuilder as? OnDemandModule.Builder {
|
||||
onDemandBuilder.isEnabled = true
|
||||
moduleBuilder = onDemandBuilder
|
||||
}
|
||||
}
|
||||
|
||||
let module = try moduleBuilder.tryBuild()
|
||||
|
@ -99,9 +136,47 @@ private extension ProfileManager {
|
|||
static let mockParameters: [Parameters] = [
|
||||
Parameters("CloudFlare DoT", false, false, [.dns]),
|
||||
Parameters("Coffee VPN", true, false, [.wireGuard, .onDemand]),
|
||||
Parameters("Hide.me", true, true, [.openVPN, .onDemand, .ip], .hideme),
|
||||
Parameters("My VPS", true, true, [.openVPN]),
|
||||
Parameters("Hide.me", true, true, [.openVPN, .onDemand, .dns, .ip], .hideme),
|
||||
Parameters("My VPS", true, true, [.openVPN, .onDemand]),
|
||||
Parameters("Office", true, false, [.onDemand, .httpProxy]),
|
||||
Parameters("Personal DoH", false, false, [.dns, .onDemand])
|
||||
]
|
||||
|
||||
static var mockHideMeEntity: VPNEntity<OpenVPN.Configuration> {
|
||||
do {
|
||||
var cfgBuilder = OpenVPN.Configuration.Builder()
|
||||
cfgBuilder.ca = .init(pem: "...")
|
||||
let cfg = try cfgBuilder.tryBuild(isClient: false)
|
||||
let cfgData = try JSONEncoder().encode(cfg)
|
||||
|
||||
let preset = AnyVPNPreset(
|
||||
providerId: .hideme,
|
||||
presetId: "default",
|
||||
description: "Default",
|
||||
endpoints: [.init(.udp, 1194)],
|
||||
configurationIdentifier: "OpenVPN",
|
||||
configuration: cfgData
|
||||
)
|
||||
|
||||
return VPNEntity(
|
||||
server: .init(
|
||||
provider: .init(
|
||||
id: .hideme,
|
||||
serverId: "be-v4",
|
||||
supportedConfigurationIdentifiers: ["OpenVPN"],
|
||||
supportedPresetIds: nil,
|
||||
categoryName: "",
|
||||
countryCode: "BE",
|
||||
otherCountryCodes: nil,
|
||||
area: nil
|
||||
),
|
||||
hostname: "be-v4.hideservers.net",
|
||||
ipAddresses: nil
|
||||
),
|
||||
preset: try preset.ofType(OpenVPN.Configuration.self)
|
||||
)
|
||||
} catch {
|
||||
fatalError("Unable to build Hide.me entity: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
import AppUIMain
|
||||
import SwiftUI
|
||||
import UITesting
|
||||
import UIAccessibility
|
||||
|
||||
extension AppDelegate: UIApplicationDelegate {
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
|
||||
|
|
|
@ -31,7 +31,7 @@ import CommonLibrary
|
|||
import CommonUtils
|
||||
import PassepartoutKit
|
||||
import SwiftUI
|
||||
import UITesting
|
||||
import UIAccessibility
|
||||
|
||||
extension AppDelegate: NSApplicationDelegate {
|
||||
func applicationDidFinishLaunching(_ notification: Notification) {
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
import AppUITV
|
||||
import SwiftUI
|
||||
import UITesting
|
||||
import UIAccessibility
|
||||
|
||||
extension AppDelegate: UIApplicationDelegate {
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import UITesting
|
||||
import UIAccessibility
|
||||
import XCTest
|
||||
|
||||
protocol XCUIApplicationProviding {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import UITesting
|
||||
import UIAccessibility
|
||||
import XCTest
|
||||
|
||||
extension XCUIElement {
|
||||
|
@ -44,14 +44,14 @@ private extension XCUIElement {
|
|||
func query(for elementType: AccessibilityInfo.ElementType) -> XCUIElementQuery {
|
||||
#if os(iOS)
|
||||
switch elementType {
|
||||
case .button, .menu, .menuItem:
|
||||
case .button, .link, .menu, .menuItem:
|
||||
return buttons
|
||||
case .text:
|
||||
return staticTexts
|
||||
}
|
||||
#else
|
||||
#elseif os(macOS)
|
||||
switch elementType {
|
||||
case .button:
|
||||
case .button, .link:
|
||||
return buttons
|
||||
case .menu:
|
||||
return menuButtons
|
||||
|
@ -60,6 +60,13 @@ private extension XCUIElement {
|
|||
case .text:
|
||||
return staticTexts
|
||||
}
|
||||
#else
|
||||
switch elementType {
|
||||
case .button, .link, .menu, .menuItem:
|
||||
return buttons
|
||||
case .text:
|
||||
return staticTexts
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,8 @@
|
|||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
import UITesting
|
||||
import Foundation
|
||||
import UIAccessibility
|
||||
import XCTest
|
||||
|
||||
@MainActor
|
||||
|
@ -41,23 +42,42 @@ final class FlowTests: XCTestCase {
|
|||
try await Task.sleep(for: .seconds(2))
|
||||
}
|
||||
|
||||
func testMainConnected() async throws {
|
||||
func testConnect() {
|
||||
AppScreen(app: app)
|
||||
.waitForProfiles()
|
||||
.enableProfile(at: 2)
|
||||
}
|
||||
|
||||
func testEditProfile() async throws {
|
||||
func testEditProfile() {
|
||||
AppScreen(app: app)
|
||||
.waitForProfiles()
|
||||
.openProfileMenu(at: 2)
|
||||
.editProfile()
|
||||
}
|
||||
|
||||
func testConnectToProviderServer() async throws {
|
||||
func testEditProfileModule() {
|
||||
AppScreen(app: app)
|
||||
.waitForProfiles()
|
||||
.openProfileMenu(at: 2)
|
||||
.editProfile()
|
||||
.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)
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import UITesting
|
||||
import UIAccessibility
|
||||
import XCTest
|
||||
|
||||
@MainActor
|
|
@ -0,0 +1,57 @@
|
|||
//
|
||||
// ProfileEditorScreen.swift
|
||||
// Passepartout
|
||||
//
|
||||
// Created by Davide De Rosa on 11/28/24.
|
||||
// Copyright (c) 2024 Davide De Rosa. All rights reserved.
|
||||
//
|
||||
// https://github.com/passepartoutvpn
|
||||
//
|
||||
// This file is part of Passepartout.
|
||||
//
|
||||
// Passepartout is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Passepartout is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIAccessibility
|
||||
import XCTest
|
||||
|
||||
@MainActor
|
||||
struct ProfileEditorScreen {
|
||||
let app: XCUIApplication
|
||||
|
||||
@discardableResult
|
||||
func enterModule(at index: Int) -> Self {
|
||||
let moduleLink = app.get(.Profile.moduleLink, at: index)
|
||||
moduleLink.tap()
|
||||
return self
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func leaveModule() -> Self {
|
||||
#if os(iOS)
|
||||
let backButton = app.navigationBars.element(boundBy: 1).buttons.element(boundBy: 0)
|
||||
XCTAssertTrue(backButton.waitForExistence(timeout: 1.0))
|
||||
backButton.tap()
|
||||
#endif
|
||||
return self
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func closeProfile() -> AppScreen {
|
||||
let cancelButton = app.get(.Profile.cancel)
|
||||
cancelButton.tap()
|
||||
return AppScreen(app: app)
|
||||
}
|
||||
}
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import UITesting
|
||||
import UIAccessibility
|
||||
import XCTest
|
||||
|
||||
@MainActor
|
||||
|
@ -32,16 +32,17 @@ struct ProfileMenuScreen {
|
|||
let app: XCUIApplication
|
||||
|
||||
@discardableResult
|
||||
func editProfile() -> ProfileEditorScreen {
|
||||
let editButton = app.get(.App.ProfileMenu.edit)
|
||||
editButton.tap()
|
||||
return ProfileEditorScreen(app: app)
|
||||
func connectToProfile() -> VPNServersScreen {
|
||||
let connectToButton = app.get(.App.ProfileMenu.connectTo)
|
||||
connectToButton.tap()
|
||||
return VPNServersScreen(app: app)
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func connectToProfile() -> AppScreen {
|
||||
let connectToButton = app.get(.App.ProfileMenu.connectTo)
|
||||
connectToButton.tap()
|
||||
return AppScreen(app: app)
|
||||
func editProfile() -> ProfileEditorScreen {
|
||||
let editButton = app.get(.App.ProfileMenu.edit)
|
||||
editButton.tap()
|
||||
_ = app.get(.Profile.name)
|
||||
return ProfileEditorScreen(app: app)
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
//
|
||||
// ProfileEditorScreen.swift
|
||||
// VPNServersScreen.swift
|
||||
// Passepartout
|
||||
//
|
||||
// Created by Davide De Rosa on 11/28/24.
|
||||
// Created by Davide De Rosa on 12/9/24.
|
||||
// Copyright (c) 2024 Davide De Rosa. All rights reserved.
|
||||
//
|
||||
// https://github.com/passepartoutvpn
|
||||
|
@ -24,17 +24,17 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import UITesting
|
||||
import UIAccessibility
|
||||
import XCTest
|
||||
|
||||
@MainActor
|
||||
struct ProfileEditorScreen {
|
||||
struct VPNServersScreen {
|
||||
let app: XCUIApplication
|
||||
|
||||
@discardableResult
|
||||
func closeProfile() -> AppScreen {
|
||||
let cancelButton = app.get(.Profile.cancel)
|
||||
cancelButton.tap()
|
||||
return AppScreen(app: app)
|
||||
func discloseCountry(at index: Int) -> Self {
|
||||
let group = app.get(.VPNServers.countryGroup, at: index)
|
||||
group.tap()
|
||||
return self
|
||||
}
|
||||
}
|
|
@ -23,7 +23,8 @@
|
|||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
import UITesting
|
||||
import Foundation
|
||||
import UIAccessibility
|
||||
import XCTest
|
||||
|
||||
@MainActor
|
||||
|
@ -50,7 +51,7 @@ final class ScreenshotTests: XCTestCase, XCUIApplicationProviding {
|
|||
.enableProfile(at: 0)
|
||||
|
||||
try await Task.sleep(for: .seconds(2))
|
||||
try snapshot("1_MainConnected")
|
||||
try snapshot("1_Connected")
|
||||
|
||||
let profile = root
|
||||
.openProfileMenu(at: 2)
|
||||
|
@ -60,12 +61,29 @@ final class ScreenshotTests: XCTestCase, XCUIApplicationProviding {
|
|||
try snapshot("2_ProfileEditor", target: .sheet)
|
||||
|
||||
profile
|
||||
.enterModule(at: 1)
|
||||
|
||||
try await Task.sleep(for: .seconds(2))
|
||||
try snapshot("3_OnDemand", target: .sheet)
|
||||
|
||||
profile
|
||||
.leaveModule()
|
||||
.enterModule(at: 2)
|
||||
|
||||
try await Task.sleep(for: .seconds(2))
|
||||
try snapshot("4_DNS", target: .sheet)
|
||||
|
||||
profile
|
||||
.leaveModule()
|
||||
.closeProfile()
|
||||
.openProfileMenu(at: 2)
|
||||
.connectToProfile()
|
||||
#if os(iOS)
|
||||
.discloseCountry(at: 2)
|
||||
#endif
|
||||
|
||||
try await Task.sleep(for: .seconds(2))
|
||||
try snapshot("3_ProviderServers", target: .sheet)
|
||||
try snapshot("5_ProviderServers", target: .sheet)
|
||||
|
||||
print("Saved to: \(ScreenshotDestination.temporary.url)")
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
//
|
||||
// FlowTests.swift
|
||||
// Passepartout
|
||||
//
|
||||
// Created by Davide De Rosa on 12/10/24.
|
||||
// Copyright (c) 2024 Davide De Rosa. All rights reserved.
|
||||
//
|
||||
// https://github.com/passepartoutvpn
|
||||
//
|
||||
// This file is part of Passepartout.
|
||||
//
|
||||
// Passepartout is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Passepartout is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIAccessibility
|
||||
import XCTest
|
||||
|
||||
@MainActor
|
||||
final class FlowTests: XCTestCase {
|
||||
private var app: XCUIApplication!
|
||||
|
||||
override func setUp() async throws {
|
||||
continueAfterFailure = false
|
||||
app = XCUIApplication()
|
||||
app.appArguments = [.uiTesting]
|
||||
app.launch()
|
||||
}
|
||||
|
||||
override func tearDown() async throws {
|
||||
try await Task.sleep(for: .seconds(2))
|
||||
}
|
||||
|
||||
func testShow() {
|
||||
AppScreen(app: app)
|
||||
.waitForProfiles()
|
||||
}
|
||||
|
||||
func testPresentProfiles() {
|
||||
AppScreen(app: app)
|
||||
.waitForProfiles()
|
||||
.presentInitialProfiles()
|
||||
}
|
||||
|
||||
func testConnect() {
|
||||
AppScreen(app: app)
|
||||
.waitForProfiles()
|
||||
.presentInitialProfiles()
|
||||
.enableProfile(up: 1)
|
||||
}
|
||||
|
||||
func testReconnectToOtherProfile() {
|
||||
AppScreen(app: app)
|
||||
.waitForProfiles()
|
||||
.presentInitialProfiles()
|
||||
.enableProfile(up: 1)
|
||||
.presentProfilesWhileConnected()
|
||||
.enableProfile(up: 0)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
//
|
||||
// AppScreen.swift
|
||||
// Passepartout
|
||||
//
|
||||
// Created by Davide De Rosa on 12/10/24.
|
||||
// Copyright (c) 2024 Davide De Rosa. All rights reserved.
|
||||
//
|
||||
// https://github.com/passepartoutvpn
|
||||
//
|
||||
// This file is part of Passepartout.
|
||||
//
|
||||
// Passepartout is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Passepartout is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIAccessibility
|
||||
import XCTest
|
||||
|
||||
@MainActor
|
||||
struct AppScreen {
|
||||
let app: XCUIApplication
|
||||
|
||||
private let remote: XCUIRemote = .shared
|
||||
|
||||
@discardableResult
|
||||
func waitForProfiles() -> Self {
|
||||
app.get(.App.installedProfile)
|
||||
return self
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func presentInitialProfiles() -> Self {
|
||||
remote.press(.down)
|
||||
return self
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func enableProfile(up: Int) -> Self {
|
||||
let profileButton = app.get(.App.ProfileList.profile)
|
||||
remote.press(.right)
|
||||
for _ in 0..<up {
|
||||
remote.press(.up)
|
||||
}
|
||||
remote.press(.select)
|
||||
profileButton.waitForNonExistence(timeout: 1.0)
|
||||
return self
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func presentProfilesWhileConnected() -> Self {
|
||||
remote.press(.down)
|
||||
_ = app.get(.App.ProfileList.profile)
|
||||
return self
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
//
|
||||
// ScreenshotTests.swift
|
||||
// Passepartout
|
||||
//
|
||||
// Created by Davide De Rosa on 12/10/24.
|
||||
// Copyright (c) 2024 Davide De Rosa. All rights reserved.
|
||||
//
|
||||
// https://github.com/passepartoutvpn
|
||||
//
|
||||
// This file is part of Passepartout.
|
||||
//
|
||||
// Passepartout is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Passepartout is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIAccessibility
|
||||
import XCTest
|
||||
|
||||
@MainActor
|
||||
final class ScreenshotTests: XCTestCase, XCUIApplicationProviding {
|
||||
let app: XCUIApplication = {
|
||||
let app = XCUIApplication()
|
||||
app.appArguments = [.uiTesting]
|
||||
return app
|
||||
}()
|
||||
|
||||
override func setUp() async throws {
|
||||
continueAfterFailure = false
|
||||
app.launch()
|
||||
}
|
||||
|
||||
func testTakeScreenshots() async throws {
|
||||
let root = AppScreen(app: app)
|
||||
.waitForProfiles()
|
||||
.presentInitialProfiles()
|
||||
.enableProfile(up: 1)
|
||||
|
||||
try await Task.sleep(for: .seconds(2))
|
||||
try snapshot("1_Connected")
|
||||
|
||||
root
|
||||
.presentProfilesWhileConnected()
|
||||
|
||||
try await Task.sleep(for: .seconds(2))
|
||||
try snapshot("2_ConnectedWithProfileList")
|
||||
|
||||
root
|
||||
.enableProfile(up: 0)
|
||||
|
||||
try await Task.sleep(for: .seconds(2))
|
||||
try snapshot("3_OnDemand")
|
||||
|
||||
print("Saved to: \(ScreenshotDestination.temporary.url)")
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue