diff --git a/.gitignore b/.gitignore index de9d3dd9..05bd968c 100644 --- a/.gitignore +++ b/.gitignore @@ -10,9 +10,10 @@ fastlane/**/review_information fastlane/**/trade_representative_contact_information build/ dist/ -/iap -templates/ -vendor/ +/iap/ +screenshots/html/*/0*.png +screenshots/results/ +/templates/ Preview.html default.profraw .api diff --git a/Gemfile.lock b/Gemfile.lock index 406f0a5c..5c44beee 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -58,7 +58,7 @@ GEM artifactory (3.0.17) atomos (0.1.3) aws-eventstream (1.3.0) - aws-partitions (1.1019.0) + aws-partitions (1.1020.0) aws-sdk-core (3.214.0) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.992.0) @@ -185,10 +185,10 @@ GEM nanaimo (0.4.0) naturally (2.2.1) nkf (0.2.0) - nokogiri (1.17.0) + nokogiri (1.17.1) mini_portile2 (~> 2.8.2) racc (~> 1.4) - nokogiri (1.17.0-arm64-darwin) + nokogiri (1.17.1-arm64-darwin) racc (~> 1.4) optparse (0.6.0) os (1.1.4) diff --git a/Passepartout.xcodeproj/project.pbxproj b/Passepartout.xcodeproj/project.pbxproj index 0e066869..11918d88 100644 --- a/Passepartout.xcodeproj/project.pbxproj +++ b/Passepartout.xcodeproj/project.pbxproj @@ -8,6 +8,8 @@ /* Begin PBXBuildFile section */ 0E08447C2CF86F2A00ECED7C /* XCTestCase+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E08447B2CF86F2A00ECED7C /* XCTestCase+Extensions.swift */; }; + 0E2267862D0A059B0000B557 /* MainScreenshots.xctestplan in Resources */ = {isa = PBXBuildFile; fileRef = 0E2267852D0A059B0000B557 /* MainScreenshots.xctestplan */; platformFilters = (ios, macos, ); }; + 0E2267882D0A05D20000B557 /* TVScreenshots.xctestplan in Resources */ = {isa = PBXBuildFile; fileRef = 0E2267872D0A05D20000B557 /* TVScreenshots.xctestplan */; platformFilters = (tvos, ); }; 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 */; }; @@ -23,7 +25,7 @@ 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 */; platformFilters = (ios, macos, ); }; + 0E7F460E2CF7F01600B1C53A /* MainFlowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7F460B2CF7F01600B1C53A /* MainFlowTests.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 */; platformFilters = (ios, macos, ); }; 0E81955A2CFDA75200CC8FFD /* Dependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E8195592CFDA75200CC8FFD /* Dependencies.swift */; }; @@ -40,10 +42,10 @@ 0E916B7C2CF811EB0072921A /* XCUIElement+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E916B7B2CF811EB0072921A /* XCUIElement+Extensions.swift */; }; 0E94EE582B93554B00588243 /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7E3D672B9345FD002BBDB4 /* PacketTunnelProvider.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, ); }; + 0EA6340E2D08995800180D7C /* TVScreenshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA6340D2D08995800180D7C /* TVScreenshotTests.swift */; platformFilters = (tvos, ); }; + 0EA634122D08997300180D7C /* TVFlowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA634112D08997300180D7C /* TVFlowTests.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, ); }; + 0EAD6A1B2CF7F79A00CC1F02 /* MainScreenshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EAD6A1A2CF7F79A00CC1F02 /* MainScreenshotTests.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 */; }; @@ -143,6 +145,8 @@ /* Begin PBXFileReference section */ 0E06D18F2B87629100176E1D /* Passepartout.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Passepartout.app; sourceTree = BUILT_PRODUCTS_DIR; }; 0E08447B2CF86F2A00ECED7C /* XCTestCase+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "XCTestCase+Extensions.swift"; sourceTree = ""; }; + 0E2267852D0A059B0000B557 /* MainScreenshots.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = MainScreenshots.xctestplan; sourceTree = ""; }; + 0E2267872D0A05D20000B557 /* TVScreenshots.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = TVScreenshots.xctestplan; sourceTree = ""; }; 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 = ""; }; 0E3FF4B92CE3AFBC00BFF640 /* MigrationManagerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationManagerTests.swift; sourceTree = ""; }; @@ -163,7 +167,7 @@ 0E7E3D5F2B9345FD002BBDB4 /* PassepartoutApp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PassepartoutApp.swift; sourceTree = ""; }; 0E7E3D662B9345FD002BBDB4 /* Tunnel.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Tunnel.entitlements; sourceTree = ""; }; 0E7E3D672B9345FD002BBDB4 /* PacketTunnelProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PacketTunnelProvider.swift; sourceTree = ""; }; - 0E7F460B2CF7F01600B1C53A /* FlowTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlowTests.swift; sourceTree = ""; }; + 0E7F460B2CF7F01600B1C53A /* MainFlowTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlowTests.swift; sourceTree = ""; }; 0E7F460C2CF7F01600B1C53A /* XCUIApplication+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "XCUIApplication+Extensions.swift"; sourceTree = ""; }; 0E7F46102CF7F44C00B1C53A /* AppScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppScreen.swift; sourceTree = ""; }; 0E8195592CFDA75200CC8FFD /* Dependencies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dependencies.swift; sourceTree = ""; }; @@ -176,10 +180,10 @@ 0E916B772CF80FD60072921A /* ProfileEditorScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileEditorScreen.swift; sourceTree = ""; }; 0E916B7B2CF811EB0072921A /* XCUIElement+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "XCUIElement+Extensions.swift"; sourceTree = ""; }; 0E94EE5C2B93570600588243 /* Tunnel.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Tunnel.plist; sourceTree = ""; }; - 0EA6340D2D08995800180D7C /* ScreenshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenshotTests.swift; sourceTree = ""; }; - 0EA634112D08997300180D7C /* FlowTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlowTests.swift; sourceTree = ""; }; + 0EA6340D2D08995800180D7C /* TVScreenshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TVScreenshotTests.swift; sourceTree = ""; }; + 0EA634112D08997300180D7C /* TVFlowTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TVFlowTests.swift; sourceTree = ""; }; 0EA634132D08998700180D7C /* AppScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppScreen.swift; sourceTree = ""; }; - 0EAD6A1A2CF7F79A00CC1F02 /* ScreenshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenshotTests.swift; sourceTree = ""; }; + 0EAD6A1A2CF7F79A00CC1F02 /* MainScreenshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainScreenshotTests.swift; sourceTree = ""; }; 0EAEC8A62D05DB8D001AA50C /* DefaultAppProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultAppProcessor.swift; sourceTree = ""; }; 0EAEC8A72D05DB8D001AA50C /* DefaultTunnelProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultTunnelProcessor.swift; sourceTree = ""; }; 0EB08B972CA46F4900A02591 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/AppPlist.strings; sourceTree = ""; }; @@ -309,8 +313,8 @@ isa = PBXGroup; children = ( 0EA634102D08996500180D7C /* Screens */, - 0EA634112D08997300180D7C /* FlowTests.swift */, - 0EA6340D2D08995800180D7C /* ScreenshotTests.swift */, + 0EA634112D08997300180D7C /* TVFlowTests.swift */, + 0EA6340D2D08995800180D7C /* TVScreenshotTests.swift */, ); path = TV; sourceTree = ""; @@ -386,6 +390,8 @@ 0E916B7A2CF811DE0072921A /* Extensions */, 0EC418C92CF81C6A00AC6F2F /* Main */, 0E418AB72D0752D100D33D47 /* TV */, + 0E2267852D0A059B0000B557 /* MainScreenshots.xctestplan */, + 0E2267872D0A05D20000B557 /* TVScreenshots.xctestplan */, ); path = UITests; sourceTree = ""; @@ -445,8 +451,8 @@ isa = PBXGroup; children = ( 0E916B7E2CF81A110072921A /* Screens */, - 0E7F460B2CF7F01600B1C53A /* FlowTests.swift */, - 0EAD6A1A2CF7F79A00CC1F02 /* ScreenshotTests.swift */, + 0E7F460B2CF7F01600B1C53A /* MainFlowTests.swift */, + 0EAD6A1A2CF7F79A00CC1F02 /* MainScreenshotTests.swift */, ); path = Main; sourceTree = ""; @@ -685,6 +691,8 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 0E2267862D0A059B0000B557 /* MainScreenshots.xctestplan in Resources */, + 0E2267882D0A05D20000B557 /* TVScreenshots.xctestplan in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -770,13 +778,13 @@ buildActionMask = 2147483647; files = ( 0E08447C2CF86F2A00ECED7C /* XCTestCase+Extensions.swift in Sources */, - 0EA6340E2D08995800180D7C /* ScreenshotTests.swift in Sources */, - 0EA634122D08997300180D7C /* FlowTests.swift in Sources */, - 0E7F460E2CF7F01600B1C53A /* FlowTests.swift in Sources */, + 0EA6340E2D08995800180D7C /* TVScreenshotTests.swift in Sources */, + 0EA634122D08997300180D7C /* TVFlowTests.swift in Sources */, + 0E7F460E2CF7F01600B1C53A /* MainFlowTests.swift in Sources */, 0E916B782CF80FD60072921A /* ProfileEditorScreen.swift in Sources */, 0EA634142D08998700180D7C /* AppScreen.swift in Sources */, 0E916B7C2CF811EB0072921A /* XCUIElement+Extensions.swift in Sources */, - 0EAD6A1B2CF7F79A00CC1F02 /* ScreenshotTests.swift in Sources */, + 0EAD6A1B2CF7F79A00CC1F02 /* MainScreenshotTests.swift in Sources */, 0E7F460F2CF7F01600B1C53A /* XCUIApplication+Extensions.swift in Sources */, 0E418AB52D074F0E00D33D47 /* VPNServersScreen.swift in Sources */, 0EC418D22CF86B7400AC6F2F /* ProfileMenuScreen.swift in Sources */, diff --git a/Passepartout.xcodeproj/xcshareddata/xcschemes/PassepartoutUITests.xcscheme b/Passepartout.xcodeproj/xcshareddata/xcschemes/PassepartoutUITests.xcscheme index 576d3d3c..42dca2f7 100644 --- a/Passepartout.xcodeproj/xcshareddata/xcschemes/PassepartoutUITests.xcscheme +++ b/Passepartout.xcodeproj/xcshareddata/xcschemes/PassepartoutUITests.xcscheme @@ -22,8 +22,15 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - shouldUseLaunchSchemeArgsEnv = "YES" - shouldAutocreateTestPlan = "YES"> + shouldUseLaunchSchemeArgsEnv = "YES"> + + + + + + - - - - diff --git a/Passepartout/UITests/Extensions/XCTestCase+Extensions.swift b/Passepartout/UITests/Extensions/XCTestCase+Extensions.swift index e1df66db..d941d316 100644 --- a/Passepartout/UITests/Extensions/XCTestCase+Extensions.swift +++ b/Passepartout/UITests/Extensions/XCTestCase+Extensions.swift @@ -59,8 +59,9 @@ extension XCUIApplicationProviding where Self: XCTestCase { } func snapshot( - _ name: String, - destination: ScreenshotDestination = .temporary, + _ index: String, + _ title: String, + destination: ScreenshotDestination = .attachment, target: ScreenshotTarget = .window ) throws { let container = container(for: target) @@ -69,26 +70,26 @@ extension XCUIApplicationProviding where Self: XCTestCase { switch destination { case .attachment: let attachment = XCTAttachment(screenshot: screenshot) - attachment.name = name + attachment.name = index attachment.lifetime = .keepAlways add(attachment) case .temporary: - let filename = deviceFilename(for: name) + let filename = deviceFilename(for: index) let url = URL(fileURLWithPath: filename, relativeTo: destination.url) try screenshot.pngRepresentation.write(to: url) } } - private func deviceFilename(for name: String) -> String { + private func deviceFilename(for index: String) -> String { #if os(iOS) - let device = UIDevice.current.userInterfaceIdiom == .pad ? "iPad" : "iPhone" + let device = UIDevice.current.userInterfaceIdiom == .pad ? "ipad" : "iphone" #elseif os(macOS) - let device = "Mac" + let device = "mac" #elseif os(tvOS) - let device = "AppleTV" + let device = "appletv" #endif - return "\(device)_\(name).png" + return "\(device)_\(index).png" } private func container(for target: ScreenshotTarget) -> XCUIElement { diff --git a/Passepartout/UITests/Main/FlowTests.swift b/Passepartout/UITests/Main/MainFlowTests.swift similarity index 96% rename from Passepartout/UITests/Main/FlowTests.swift rename to Passepartout/UITests/Main/MainFlowTests.swift index 6ed005c2..7fddd5c8 100644 --- a/Passepartout/UITests/Main/FlowTests.swift +++ b/Passepartout/UITests/Main/MainFlowTests.swift @@ -1,5 +1,5 @@ // -// FlowTests.swift +// MainFlowTests.swift // Passepartout // // Created by Davide De Rosa on 11/27/24. @@ -28,7 +28,7 @@ import UIAccessibility import XCTest @MainActor -final class FlowTests: XCTestCase { +final class MainFlowTests: XCTestCase { private var app: XCUIApplication! override func setUp() async throws { diff --git a/Passepartout/UITests/Main/ScreenshotTests.swift b/Passepartout/UITests/Main/MainScreenshotTests.swift similarity index 82% rename from Passepartout/UITests/Main/ScreenshotTests.swift rename to Passepartout/UITests/Main/MainScreenshotTests.swift index 1932d3a9..f73c2719 100644 --- a/Passepartout/UITests/Main/ScreenshotTests.swift +++ b/Passepartout/UITests/Main/MainScreenshotTests.swift @@ -1,5 +1,5 @@ // -// ScreenshotTests.swift +// MainScreenshotTests.swift // Passepartout // // Created by Davide De Rosa on 11/28/24. @@ -28,7 +28,7 @@ import UIAccessibility import XCTest @MainActor -final class ScreenshotTests: XCTestCase, XCUIApplicationProviding { +final class MainScreenshotTests: XCTestCase, XCUIApplicationProviding { let app: XCUIApplication = { let app = XCUIApplication() app.appArguments = [.uiTesting] @@ -40,7 +40,7 @@ final class ScreenshotTests: XCTestCase, XCUIApplicationProviding { app.launch() #if os(iOS) if UIDevice.current.userInterfaceIdiom == .pad { - XCUIDevice.shared.orientation = .landscapeLeft + XCUIDevice.shared.orientation = .portrait } #endif } @@ -55,27 +55,27 @@ final class ScreenshotTests: XCTestCase, XCUIApplicationProviding { .editProfile() await pause() - try snapshot("02_ProfileEditor", target: .sheet) + try snapshot("03", "ProfileEditor", target: .sheet) profile .enterModule(at: 1) await pause() - try snapshot("03_OnDemand", target: .sheet) + try snapshot("02", "OnDemand", target: .sheet) profile .leaveModule() .enterModule(at: 2) await pause() - try snapshot("04_DNS", target: .sheet) + try snapshot("04", "DNS", target: .sheet) let app = profile .leaveModule() .closeProfile() await pause() - try snapshot("01_Connected") + try snapshot("01", "Connected") app .openProfileMenu(at: 2) @@ -85,7 +85,7 @@ final class ScreenshotTests: XCTestCase, XCUIApplicationProviding { #endif await pause() - try snapshot("05_ProviderServers", target: .sheet) + try snapshot("05", "ProviderServers", target: .sheet) print("Saved to: \(ScreenshotDestination.temporary.url)") } diff --git a/Passepartout/UITests/MainScreenshots.xctestplan b/Passepartout/UITests/MainScreenshots.xctestplan new file mode 100644 index 00000000..a4b790ad --- /dev/null +++ b/Passepartout/UITests/MainScreenshots.xctestplan @@ -0,0 +1,48 @@ +{ + "configurations" : [ + { + "id" : "30682571-78CE-444A-9D31-4E1310B4D166", + "name" : "Configuration 1", + "options" : { + + } + } + ], + "defaultOptions" : { + "testTimeoutsEnabled" : true + }, + "testTargets" : [ + { + "skippedTests" : [ + "FlowTests", + "FlowTests\/testConnect()", + "FlowTests\/testConnectToProviderServer()", + "FlowTests\/testDiscloseProviderCountry()", + "FlowTests\/testEditProfile()", + "FlowTests\/testEditProfileModule()", + "FlowTests\/testPresentProfiles()", + "FlowTests\/testReconnectToOtherProfile()", + "FlowTests\/testShow()", + "MainFlowTests", + "MainFlowTests\/testConnect()", + "MainFlowTests\/testConnectToProviderServer()", + "MainFlowTests\/testDiscloseProviderCountry()", + "MainFlowTests\/testEditProfile()", + "MainFlowTests\/testEditProfileModule()", + "TVFlowTests", + "TVFlowTests\/testConnect()", + "TVFlowTests\/testPresentProfiles()", + "TVFlowTests\/testReconnectToOtherProfile()", + "TVFlowTests\/testShow()", + "TVScreenshotTests", + "TVScreenshotTests\/testTakeScreenshots()" + ], + "target" : { + "containerPath" : "container:Passepartout.xcodeproj", + "identifier" : "0E78FE4B2CF799F400B0C5BF", + "name" : "PassepartoutUITests" + } + } + ], + "version" : 1 +} diff --git a/Passepartout/UITests/TV/FlowTests.swift b/Passepartout/UITests/TV/TVFlowTests.swift similarity index 96% rename from Passepartout/UITests/TV/FlowTests.swift rename to Passepartout/UITests/TV/TVFlowTests.swift index c12a5899..30e72a7b 100644 --- a/Passepartout/UITests/TV/FlowTests.swift +++ b/Passepartout/UITests/TV/TVFlowTests.swift @@ -1,5 +1,5 @@ // -// FlowTests.swift +// TVFlowTests.swift // Passepartout // // Created by Davide De Rosa on 12/10/24. @@ -28,7 +28,7 @@ import UIAccessibility import XCTest @MainActor -final class FlowTests: XCTestCase { +final class TVFlowTests: XCTestCase { private var app: XCUIApplication! override func setUp() async throws { diff --git a/Passepartout/UITests/TV/ScreenshotTests.swift b/Passepartout/UITests/TV/TVScreenshotTests.swift similarity index 87% rename from Passepartout/UITests/TV/ScreenshotTests.swift rename to Passepartout/UITests/TV/TVScreenshotTests.swift index 979c9aea..4b4bd7f2 100644 --- a/Passepartout/UITests/TV/ScreenshotTests.swift +++ b/Passepartout/UITests/TV/TVScreenshotTests.swift @@ -1,5 +1,5 @@ // -// ScreenshotTests.swift +// TVScreenshotTests.swift // Passepartout // // Created by Davide De Rosa on 12/10/24. @@ -28,7 +28,7 @@ import UIAccessibility import XCTest @MainActor -final class ScreenshotTests: XCTestCase, XCUIApplicationProviding { +final class TVScreenshotTests: XCTestCase, XCUIApplicationProviding { let app: XCUIApplication = { let app = XCUIApplication() app.appArguments = [.uiTesting] @@ -47,19 +47,19 @@ final class ScreenshotTests: XCTestCase, XCUIApplicationProviding { .enableProfile(up: 1) await pause() - try snapshot("01_Connected") + try snapshot("01", "Connected") root .presentProfilesWhileConnected() await pause() - try snapshot("02_ConnectedWithProfileList") + try snapshot("02", "ConnectedWithProfileList") root .enableProfile(up: 0) await pause() - try snapshot("03_OnDemand") + try snapshot("03", "OnDemand") print("Saved to: \(ScreenshotDestination.temporary.url)") } diff --git a/Passepartout/UITests/TVScreenshots.xctestplan b/Passepartout/UITests/TVScreenshots.xctestplan new file mode 100644 index 00000000..2728dfdb --- /dev/null +++ b/Passepartout/UITests/TVScreenshots.xctestplan @@ -0,0 +1,48 @@ +{ + "configurations" : [ + { + "id" : "00256A48-9D59-44ED-822A-B35521760457", + "name" : "Configuration 1", + "options" : { + + } + } + ], + "defaultOptions" : { + "testTimeoutsEnabled" : true + }, + "testTargets" : [ + { + "skippedTests" : [ + "FlowTests", + "FlowTests\/testConnect()", + "FlowTests\/testConnectToProviderServer()", + "FlowTests\/testEditProfile()", + "FlowTests\/testEditProfileModule()", + "FlowTests\/testPresentProfiles()", + "FlowTests\/testReconnectToOtherProfile()", + "FlowTests\/testShow()", + "MainFlowTests", + "MainFlowTests\/testConnect()", + "MainFlowTests\/testConnectToProviderServer()", + "MainFlowTests\/testDiscloseProviderCountry()", + "MainFlowTests\/testEditProfile()", + "MainFlowTests\/testEditProfileModule()", + "MainScreenshotTests", + "MainScreenshotTests\/testTakeScreenshots()", + "ScreenshotTests", + "TVFlowTests", + "TVFlowTests\/testConnect()", + "TVFlowTests\/testPresentProfiles()", + "TVFlowTests\/testReconnectToOtherProfile()", + "TVFlowTests\/testShow()" + ], + "target" : { + "containerPath" : "container:Passepartout.xcodeproj", + "identifier" : "0E78FE4B2CF799F400B0C5BF", + "name" : "PassepartoutUITests" + } + } + ], + "version" : 1 +} diff --git a/ci/gen-screenshots.sh b/ci/gen-screenshots.sh new file mode 100755 index 00000000..e3b4aa11 --- /dev/null +++ b/ci/gen-screenshots.sh @@ -0,0 +1,7 @@ +#!/bin/bash +cwd=`dirname $0` +devices=("iphone ipad mac appletv") +for device in $devices; do + $cwd/../screenshots/export.sh $device + $cwd/../screenshots/compose-device.sh $device +done diff --git a/screenshots/compose-device.sh b/screenshots/compose-device.sh new file mode 100755 index 00000000..4b17e7eb --- /dev/null +++ b/screenshots/compose-device.sh @@ -0,0 +1,49 @@ +#!/bin/bash +cwd=`dirname $0` +device=$1 +compose_cmd="$cwd/compose.sh" +fastlane_screenshots_root="$cwd/../fastlane/screenshots" + +case $device in + + "iphone") + nums=("01 02 03 04 05") + template="main" + width=1242 + height=2688 + fastlane="iOS" + ;; + + "ipad") + nums=("01 02 03 04 05") + template="main" + width=2048 + height=2732 + fastlane="iOS" + ;; + + "mac") + nums=("01 02 03 04 05") + template="main" + width=2880 + height=1800 + fastlane="macOS" + ;; + + "appletv") + nums=("01 02 03") + template="tv" + width=3840 + height=2160 + fastlane="tvOS" + ;; + + *) + echo "Unknown device: $device" + exit 1 + ;; +esac + +for num in $nums; do + $compose_cmd $template $device $num $width $height "$fastlane_screenshots_root/$fastlane/en-US" +done diff --git a/screenshots/compose.sh b/screenshots/compose.sh new file mode 100755 index 00000000..95e54348 --- /dev/null +++ b/screenshots/compose.sh @@ -0,0 +1,30 @@ +#!/bin/bash +cwd=`dirname $0` +chrome_app="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" + +# e.g.: main iphone 01 1242 2688 "fastlane/screenshots/iOS" + +template=$1 +device=$2 +num=$3 +width=$4 +height=$5 +screenshots_root="$6" + +# work around Chrome bug +height_bottom_padding="100" +padded_height=$(($height + $height_bottom_padding)) + +tmp_screenshot_path="tmp.png" + +echo "Take screenshot $num for $device..." +page_url="file://`pwd`/$cwd/html/${template}.html?classes=${device},screen-${num}" +"$chrome_app" --headless --disable-gpu --window-size="$width,$padded_height" --screenshot="$tmp_screenshot_path" --virtual-time-budget=10000 "$page_url" + +if [[ $device = "ipad" ]]; then + device="ipadPro129" +fi +screenshot_path="$screenshots_root/$device-$num.png" + +magick $tmp_screenshot_path -geometry 50% -crop ${width}x${height}+0+0 +repage "$screenshot_path" +rm $tmp_screenshot_path diff --git a/screenshots/export.sh b/screenshots/export.sh new file mode 100755 index 00000000..2021b2b9 --- /dev/null +++ b/screenshots/export.sh @@ -0,0 +1,54 @@ +#!/bin/bash +cwd=`dirname $0` +device="$1" +xcscheme="PassepartoutUITests" +results_root="$cwd/results" +results_path="$results_root/$device" +screenshots_path="$cwd/html/$device" + +mkdir -p "$results_root" +mkdir -p "$screenshots_path" + +case $device in + + "iphone") + xcplan="MainScreenshots" + xcdestination="name=iPhone 16 Pro Max" + ;; + + "ipad") + xcplan="MainScreenshots" + xcdestination="name=iPad (10th generation)" + ;; + + "mac") + xcplan="MainScreenshots" + xcdestination="platform=macOS,arch=arm64" + ;; + + "appletv") + xcplan="TVScreenshots" + xcdestination="name=Apple TV 4K (3rd generation)" + ;; + + *) + echo "Unknown device: $device" + exit 1 + ;; +esac + +# 1. run the tests +rm -rf "$results_path" +xcodebuild -scheme "$xcscheme" -testPlan "$xcplan" -destination "$xcdestination" -resultBundlePath "$results_path" test + +# 2. parse the screenshots +xcparse screenshots "$results_path" "$screenshots_path" + +# 3. drop the filename suffix +cd "$screenshots_path" +for file in 0[1-9]_*.png; do + if [[ -e "$file" ]]; then + new_name="${file%%_*}.png" + mv "$file" "$new_name" + fi +done diff --git a/screenshots/html/appletv/frame.png b/screenshots/html/appletv/frame.png new file mode 100755 index 00000000..09797624 Binary files /dev/null and b/screenshots/html/appletv/frame.png differ diff --git a/screenshots/html/appletv/style.css b/screenshots/html/appletv/style.css new file mode 100644 index 00000000..90b3a265 --- /dev/null +++ b/screenshots/html/appletv/style.css @@ -0,0 +1,55 @@ +.appletv #background { + width: 3840px; + height: 2160px; +} + +.appletv #background header { + height: 5em; +} + +.appletv #background .heading { + font-size: 1.2em; +} + +.appletv #box { + left: 50%; + top: 240%; +} + +.appletv #appletv { + display: block; +} + +#appletv .screenshot { + width: 2376px; + top: 100px; +} + +#appletv .frame { + width: 2520px; + top: 10px; +} + +.screen-01.appletv .heading { + padding: 2em; +} + +.screen-02.appletv .heading { + padding: 1em; +} + +.screen-03.appletv .heading { + padding: 1em; +} + +.screen-01 #appletv :nth-child(1) { + display: block; +} + +.screen-02 #appletv :nth-child(2) { + display: block; +} + +.screen-03 #appletv :nth-child(3) { + display: block; +} diff --git a/screenshots/html/ipad/frame.png b/screenshots/html/ipad/frame.png new file mode 100644 index 00000000..708691ac Binary files /dev/null and b/screenshots/html/ipad/frame.png differ diff --git a/screenshots/html/ipad/style.css b/screenshots/html/ipad/style.css new file mode 100644 index 00000000..a3a0d131 --- /dev/null +++ b/screenshots/html/ipad/style.css @@ -0,0 +1,71 @@ +.ipad #background { + width: 2048px; + height: 2732px; +} + +.ipad #background header { + height: 10em; +} + +.ipad #background .heading { + font-size: 1.4em; +} + +.ipad #box { + left: 60%; + bottom: -95%; +} + +.ipad #ipad { + display: block; +} + +#ipad .screenshot { + width: 1600px; + top: 100px; +} + +#ipad .frame { + width: 1780px; + top: -68px; +} + +.screen-01.ipad .heading { + padding: 3.5em; +} + +.screen-02.ipad .heading { + padding: 1em; +} + +.screen-03.ipad .heading { + padding: 2em; +} + +.screen-04.ipad .heading { + padding: 3em; +} + +.screen-05.ipad .heading { + padding: 4em; +} + +.screen-01 #ipad :nth-child(1) { + display: block; +} + +.screen-02 #ipad :nth-child(2) { + display: block; +} + +.screen-03 #ipad :nth-child(3) { + display: block; +} + +.screen-04 #ipad :nth-child(4) { + display: block; +} + +.screen-05 #ipad :nth-child(5) { + display: block; +} diff --git a/screenshots/html/iphone/frame.png b/screenshots/html/iphone/frame.png new file mode 100644 index 00000000..75acb065 Binary files /dev/null and b/screenshots/html/iphone/frame.png differ diff --git a/screenshots/html/iphone/style.css b/screenshots/html/iphone/style.css new file mode 100644 index 00000000..eae98ec3 --- /dev/null +++ b/screenshots/html/iphone/style.css @@ -0,0 +1,72 @@ +.iphone #background { + width: 1242px; + height: 2688px; +} + +.iphone #background header { + height: 10em; +} + +.iphone #background .heading { + font-size: 1.2em; +} + +.iphone #box { + left: 15%; + bottom: -90%; +} + +.iphone #iphone { + display: block; +} + +#iphone .screenshot { + width: 900px; + top: 100px; + border-radius: 100px; +} + +#iphone .frame { + width: 1000px; + top: 70px; +} + +.screen-01.iphone .heading { + padding: 2em; +} + +.screen-02.iphone .heading { + padding: 1em; +} + +.screen-03.iphone .heading { + padding: 1em; +} + +.screen-04.iphone .heading { + padding: 1em; +} + +.screen-05.iphone .heading { + padding: 1.5em; +} + +.screen-01 #iphone :nth-child(1) { + display: block; +} + +.screen-02 #iphone :nth-child(2) { + display: block; +} + +.screen-03 #iphone :nth-child(3) { + display: block; +} + +.screen-04 #iphone :nth-child(4) { + display: block; +} + +.screen-05 #iphone :nth-child(5) { + display: block; +} diff --git a/screenshots/html/mac/style.css b/screenshots/html/mac/style.css new file mode 100644 index 00000000..e77098a2 --- /dev/null +++ b/screenshots/html/mac/style.css @@ -0,0 +1,63 @@ +.mac #background { + width: 2880px; + height: 1800px; +} + +.mac #background header { + height: 6em; +} + +.mac #background .heading { + font-size: 1.4em; +} + +.mac #box { + left: 45%; + top: 140%; +} + +.mac #mac { + display: block; +} + +#mac .screenshot { + width: 1600px; + top: 20px; + border-radius: 25px; +} + +.screen-01.mac .heading { + padding: 5em; +} + +.screen-02.mac .heading { + padding: 3em; +} + +.screen-03.mac .heading { + padding: 5em; +} + +.screen-04.mac .heading { + padding: 6em; +} + +.screen-01 #mac :nth-child(1) { + display: block; +} + +.screen-02 #mac :nth-child(2) { + display: block; +} + +.screen-03 #mac :nth-child(3) { + display: block; +} + +.screen-04 #mac :nth-child(4) { + display: block; +} + +.screen-05 #mac :nth-child(5) { + display: block; +} diff --git a/screenshots/html/main.html b/screenshots/html/main.html new file mode 100644 index 00000000..717069a8 --- /dev/null +++ b/screenshots/html/main.html @@ -0,0 +1,59 @@ + + + + + + + + + + + +
+
+
+

+ All your Profiles in a single App +

+

+ Turn VPN off automatically when at Home +

+

+ Use with Shortcuts, iCloud and Apple TV +

+

+ Override your network settings +

+

+ Presets for
well-known VPN Providers +

+
+
+
+ + + + + + +
+
+ + + + + + +
+
+ + + + + +
+
+
+ + + diff --git a/screenshots/html/script.js b/screenshots/html/script.js new file mode 100644 index 00000000..eef8c0fc --- /dev/null +++ b/screenshots/html/script.js @@ -0,0 +1,4 @@ +let params = new URLSearchParams(document.location.search); +let classes = params.get("classes").split(","); +document.body.className = classes.join(" "); + diff --git a/screenshots/html/style.css b/screenshots/html/style.css new file mode 100644 index 00000000..227917a3 --- /dev/null +++ b/screenshots/html/style.css @@ -0,0 +1,86 @@ +* { + margin: 0; + padding: 0; +} + +body { + font-family: "Ubuntu", sans-serif; + font-size: 100px; +} + +#background { + position: absolute; + background-color: #515d71; + overflow: hidden; +} + +header { + height: 10em; +} + +header p { + position: relative; + top: 50%; + transform: translateY(-50%); + color: #fff; + text-align: center; + line-height: 1.7em; +} + +em { + color: #d69c68; + font-style: normal; +} + +main { + position: relative; +} + +#box { + position: absolute; + background-color: #d69c68; + width: 250%; + height: 150%; + transform: rotate(45deg); +} + +.container { + display: none; +} + +.screenshot { + position: relative; + left: 50%; + transform: translateX(-50%); + display: none; +} + +.frame { + position: absolute; + left: 50%; + transform: translateX(-50%); +} + +.heading { + display: none; +} + +.screen-01 .heading:nth-of-type(1) { + display: block; +} + +.screen-02 .heading:nth-of-type(2) { + display: block; +} + +.screen-03 .heading:nth-of-type(3) { + display: block; +} + +.screen-04 .heading:nth-of-type(4) { + display: block; +} + +.screen-05 .heading:nth-of-type(5) { + display: block; +} diff --git a/screenshots/html/tv.html b/screenshots/html/tv.html new file mode 100644 index 00000000..2f3fd6c9 --- /dev/null +++ b/screenshots/html/tv.html @@ -0,0 +1,34 @@ + + + + + + + + + +
+
+

+ OpenVPN and WireGuard on your Apple TV +

+

+ Synchronize your Profiles within seconds +

+

+ Customize On-demand, DNS, Proxy and Routing +

+
+
+
+
+ + + + +
+
+
+ + +