diff --git a/ios/Gemfile b/ios/Gemfile index 2498e128118d..2ac40ca95e78 100644 --- a/ios/Gemfile +++ b/ios/Gemfile @@ -1,3 +1,3 @@ source "https://rubygems.org" -gem "fastlane", "~> 2.212.2" +gem "fastlane", "~> 2.220" diff --git a/ios/Gemfile.lock b/ios/Gemfile.lock index 5661d8d07975..98a93e22b577 100644 --- a/ios/Gemfile.lock +++ b/ios/Gemfile.lock @@ -1,42 +1,44 @@ GEM remote: https://rubygems.org/ specs: - CFPropertyList (3.0.6) + CFPropertyList (3.0.7) + base64 + nkf rexml - addressable (2.8.4) + addressable (2.8.6) public_suffix (>= 2.0.2, < 6.0) - artifactory (3.0.15) + artifactory (3.0.17) atomos (0.1.3) - aws-eventstream (1.2.0) - aws-partitions (1.750.0) - aws-sdk-core (3.171.0) - aws-eventstream (~> 1, >= 1.0.2) + aws-eventstream (1.3.0) + aws-partitions (1.939.0) + aws-sdk-core (3.196.1) + aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.651.0) - aws-sigv4 (~> 1.5) + aws-sigv4 (~> 1.8) jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.63.0) - aws-sdk-core (~> 3, >= 3.165.0) + aws-sdk-kms (1.82.0) + aws-sdk-core (~> 3, >= 3.193.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.121.0) - aws-sdk-core (~> 3, >= 3.165.0) + aws-sdk-s3 (1.151.0) + aws-sdk-core (~> 3, >= 3.194.0) aws-sdk-kms (~> 1) - aws-sigv4 (~> 1.4) - aws-sigv4 (1.5.2) + aws-sigv4 (~> 1.8) + aws-sigv4 (1.8.0) aws-eventstream (~> 1, >= 1.0.2) babosa (1.0.4) + base64 (0.2.0) claide (1.1.0) colored (1.2) colored2 (3.1.2) commander (4.6.0) highline (~> 2.0.0) declarative (0.0.20) - digest-crc (0.6.4) + digest-crc (0.6.5) rake (>= 12.0.0, < 14.0.0) - domain_name (0.5.20190701) - unf (>= 0.0.5, < 1.0.0) + domain_name (0.6.20240107) dotenv (2.8.1) emoji_regex (3.2.3) - excon (0.99.0) + excon (0.110.0) faraday (1.10.3) faraday-em_http (~> 1.0) faraday-em_synchrony (~> 1.0) @@ -65,15 +67,15 @@ GEM faraday-retry (1.0.3) faraday_middleware (1.2.0) faraday (~> 1.0) - fastimage (2.2.6) - fastlane (2.212.2) + fastimage (2.3.1) + fastlane (2.220.0) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) aws-sdk-s3 (~> 1.0) babosa (>= 1.0.3, < 2.0.0) bundler (>= 1.12.0, < 3.0.0) - colored + colored (~> 1.2) commander (~> 4.6) dotenv (>= 2.1.1, < 3.0.0) emoji_regex (>= 0.1, < 4.0) @@ -85,30 +87,32 @@ GEM gh_inspector (>= 1.1.2, < 2.0.0) google-apis-androidpublisher_v3 (~> 0.3) google-apis-playcustomapp_v1 (~> 0.1) + google-cloud-env (>= 1.6.0, < 2.0.0) google-cloud-storage (~> 1.31) highline (~> 2.0) + http-cookie (~> 1.0.5) json (< 3.0.0) jwt (>= 2.1.0, < 3) mini_magick (>= 4.9.4, < 5.0.0) - multipart-post (~> 2.0.0) + multipart-post (>= 2.0.0, < 3.0.0) naturally (~> 2.2) - optparse (~> 0.1.1) + optparse (>= 0.1.1, < 1.0.0) plist (>= 3.1.0, < 4.0.0) rubyzip (>= 2.0.0, < 3.0.0) - security (= 0.1.3) + security (= 0.1.5) simctl (~> 1.6.3) terminal-notifier (>= 2.0.0, < 3.0.0) - terminal-table (>= 1.4.5, < 2.0.0) + terminal-table (~> 3) tty-screen (>= 0.6.3, < 1.0.0) tty-spinner (>= 0.8.0, < 1.0.0) word_wrap (~> 1.0.0) xcodeproj (>= 1.13.0, < 2.0.0) xcpretty (~> 0.3.0) - xcpretty-travis-formatter (>= 0.0.3) + xcpretty-travis-formatter (>= 0.0.3, < 2.0.0) gh_inspector (1.1.3) - google-apis-androidpublisher_v3 (0.39.0) + google-apis-androidpublisher_v3 (0.54.0) google-apis-core (>= 0.11.0, < 2.a) - google-apis-core (0.11.0) + google-apis-core (0.11.3) addressable (~> 2.5, >= 2.5.1) googleauth (>= 0.16.2, < 2.a) httpclient (>= 2.8.1, < 3.a) @@ -116,64 +120,64 @@ GEM representable (~> 3.0) retriable (>= 2.0, < 4.a) rexml - webrick google-apis-iamcredentials_v1 (0.17.0) google-apis-core (>= 0.11.0, < 2.a) google-apis-playcustomapp_v1 (0.13.0) google-apis-core (>= 0.11.0, < 2.a) - google-apis-storage_v1 (0.19.0) - google-apis-core (>= 0.9.0, < 2.a) - google-cloud-core (1.6.0) - google-cloud-env (~> 1.0) + google-apis-storage_v1 (0.31.0) + google-apis-core (>= 0.11.0, < 2.a) + google-cloud-core (1.7.0) + google-cloud-env (>= 1.0, < 3.a) google-cloud-errors (~> 1.0) google-cloud-env (1.6.0) faraday (>= 0.17.3, < 3.0) - google-cloud-errors (1.3.1) - google-cloud-storage (1.44.0) + google-cloud-errors (1.4.0) + google-cloud-storage (1.47.0) addressable (~> 2.8) digest-crc (~> 0.4) google-apis-iamcredentials_v1 (~> 0.1) - google-apis-storage_v1 (~> 0.19.0) + google-apis-storage_v1 (~> 0.31.0) google-cloud-core (~> 1.6) googleauth (>= 0.16.2, < 2.a) mini_mime (~> 1.0) - googleauth (1.5.2) + googleauth (1.8.1) faraday (>= 0.17.3, < 3.a) jwt (>= 1.4, < 3.0) - memoist (~> 0.16) multi_json (~> 1.11) os (>= 0.9, < 2.0) signet (>= 0.16, < 2.a) highline (2.0.3) - http-cookie (1.0.5) + http-cookie (1.0.6) domain_name (~> 0.5) httpclient (2.8.3) jmespath (1.6.2) - json (2.6.3) - jwt (2.7.0) - memoist (0.16.2) + json (2.7.2) + jwt (2.8.1) + base64 mini_magick (4.12.0) - mini_mime (1.1.2) + mini_mime (1.1.5) multi_json (1.15.0) - multipart-post (2.0.0) + multipart-post (2.4.1) nanaimo (0.3.0) naturally (2.2.1) - optparse (0.1.1) + nkf (0.2.0) + optparse (0.5.0) os (1.1.4) - plist (3.7.0) - public_suffix (5.0.1) - rake (13.0.6) + plist (3.7.1) + public_suffix (5.0.5) + rake (13.2.1) representable (3.2.0) declarative (< 0.1.0) trailblazer-option (>= 0.1.1, < 0.2.0) uber (< 0.2.0) retriable (3.1.2) - rexml (3.2.5) + rexml (3.2.8) + strscan (>= 3.0.9) rouge (2.0.7) ruby2_keywords (0.0.5) rubyzip (2.3.2) - security (0.1.3) - signet (0.17.0) + security (0.1.5) + signet (0.19.0) addressable (~> 2.8) faraday (>= 0.17.5, < 3.a) jwt (>= 1.5, < 3.0) @@ -181,22 +185,19 @@ GEM simctl (1.6.10) CFPropertyList naturally + strscan (3.1.0) terminal-notifier (2.0.0) - terminal-table (1.8.0) - unicode-display_width (~> 1.1, >= 1.1.1) + terminal-table (3.0.2) + unicode-display_width (>= 1.1.1, < 3) trailblazer-option (0.1.2) tty-cursor (0.7.1) - tty-screen (0.8.1) + tty-screen (0.8.2) tty-spinner (0.9.3) tty-cursor (~> 0.7) uber (0.1.0) - unf (0.1.4) - unf_ext - unf_ext (0.0.8.2) - unicode-display_width (1.8.0) - webrick (1.8.1) + unicode-display_width (2.5.0) word_wrap (1.0.0) - xcodeproj (1.22.0) + xcodeproj (1.24.0) CFPropertyList (>= 2.3.3, < 4.0) atomos (~> 0.1.3) claide (>= 1.0.2, < 2.0) @@ -212,7 +213,7 @@ PLATFORMS ruby DEPENDENCIES - fastlane (~> 2.212.2) + fastlane (~> 2.220) BUNDLED WITH - 1.17.3 + 2.2.3 diff --git a/ios/MullvadVPNUITests/Screenshots/ScreenshotTests.swift b/ios/MullvadVPNUITests/Screenshots/ScreenshotTests.swift index 778b04d07403..326a5c56a189 100644 --- a/ios/MullvadVPNUITests/Screenshots/ScreenshotTests.swift +++ b/ios/MullvadVPNUITests/Screenshots/ScreenshotTests.swift @@ -8,8 +8,9 @@ import XCTest +@MainActor class ScreenshotTests: LoggedInWithTimeUITestCase { - override func setUp() { + override func setUp() async throws { setupSnapshot(app, waitForAnimations: false) let argumentsJsonString = try? LaunchArguments( @@ -18,10 +19,10 @@ class ScreenshotTests: LoggedInWithTimeUITestCase { ).toJSON() app.launchEnvironment[LaunchArguments.tag] = argumentsJsonString - super.setUp() + try await super.setUp() } - func testTakeScreenshotOfQuantumSecuredConnection() throws { + func testTakeScreenshotOfQuantumSecuredConnection() async throws { // We can't close banners in the screenshot tests due to how the NotificationController view // is overridden, so we need to restart the app once to make sure the "new device" notification // isn't visible. @@ -54,7 +55,7 @@ class ScreenshotTests: LoggedInWithTimeUITestCase { snapshot("QuantumConnectionSecured") } - func testTakeScreenshotOfCustomListSelected() throws { + func testTakeScreenshotOfCustomListSelected() async throws { let customListName = "Low latency locations" TunnelControlPage(app) @@ -96,7 +97,7 @@ class ScreenshotTests: LoggedInWithTimeUITestCase { snapshot("CustomListSelected") } - func testTakeScreenshotOfRelayFilter() throws { + func testTakeScreenshotOfRelayFilter() async throws { TunnelControlPage(app) .tapSelectLocationButton() @@ -110,7 +111,7 @@ class ScreenshotTests: LoggedInWithTimeUITestCase { snapshot("RelayFilter") } - func testTakeScreenshotOfVPNSettings() throws { + func testTakeScreenshotOfVPNSettings() async throws { HeaderBar(app) .tapSettingsButton() @@ -120,7 +121,7 @@ class ScreenshotTests: LoggedInWithTimeUITestCase { snapshot("VPNSettings") } - func testTakeScreenshotOfDNSSettings() throws { + func testTakeScreenshotOfDNSSettings() async throws { HeaderBar(app) .tapSettingsButton() @@ -142,7 +143,7 @@ class ScreenshotTests: LoggedInWithTimeUITestCase { snapshot("DNSSettings") } - func testTakeScreenshotOfAccount() throws { + func testTakeScreenshotOfAccount() async throws { HeaderBar(app) .tapAccountButton() diff --git a/ios/MullvadVPNUITests/Screenshots/SnapshotHelper.swift b/ios/MullvadVPNUITests/Screenshots/SnapshotHelper.swift index 9638ba7dbd3d..fb43ba3ffeb3 100644 --- a/ios/MullvadVPNUITests/Screenshots/SnapshotHelper.swift +++ b/ios/MullvadVPNUITests/Screenshots/SnapshotHelper.swift @@ -15,13 +15,12 @@ import Foundation import XCTest -var deviceLanguage = "" -var locale = "" - +@MainActor func setupSnapshot(_ app: XCUIApplication, waitForAnimations: Bool = true) { Snapshot.setupSnapshot(app, waitForAnimations: waitForAnimations) } +@MainActor func snapshot(_ name: String, waitForLoadingIndicator: Bool) { if waitForLoadingIndicator { Snapshot.snapshot(name) @@ -33,6 +32,7 @@ func snapshot(_ name: String, waitForLoadingIndicator: Bool) { /// - Parameters: /// - name: The name of the snapshot /// - timeout: Amount of seconds to wait until the network loading indicator disappears. Pass `0` if you don't want to wait. +@MainActor func snapshot(_ name: String, timeWaitingForIdle timeout: TimeInterval = 20) { Snapshot.snapshot(name, timeWaitingForIdle: timeout) } @@ -52,6 +52,7 @@ enum SnapshotError: Error, CustomDebugStringConvertible { } @objcMembers +@MainActor open class Snapshot: NSObject { static var app: XCUIApplication? static var waitForAnimations = true @@ -60,6 +61,9 @@ open class Snapshot: NSObject { return cacheDirectory?.appendingPathComponent("screenshots", isDirectory: true) } + static var deviceLanguage = "" + static var currentLocale = "" + open class func setupSnapshot(_ app: XCUIApplication, waitForAnimations: Bool = true) { Snapshot.app = app Snapshot.waitForAnimations = waitForAnimations @@ -102,17 +106,17 @@ open class Snapshot: NSObject { do { let trimCharacterSet = CharacterSet.whitespacesAndNewlines - locale = try String(contentsOf: path, encoding: .utf8).trimmingCharacters(in: trimCharacterSet) + currentLocale = try String(contentsOf: path, encoding: .utf8).trimmingCharacters(in: trimCharacterSet) } catch { NSLog("Couldn't detect/set locale...") } - if locale.isEmpty && !deviceLanguage.isEmpty { - locale = Locale(identifier: deviceLanguage).identifier + if currentLocale.isEmpty && !deviceLanguage.isEmpty { + currentLocale = Locale(identifier: deviceLanguage).identifier } - if !locale.isEmpty { - app.launchArguments += ["-AppleLocale", "\"\(locale)\""] + if !currentLocale.isEmpty { + app.launchArguments += ["-AppleLocale", "\"\(currentLocale)\""] } } @@ -206,7 +210,7 @@ open class Snapshot: NSObject { let format = UIGraphicsImageRendererFormat() format.scale = image.scale let renderer = UIGraphicsImageRenderer(size: image.size, format: format) - return renderer.image { _ in + return renderer.image { context in image.draw(in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)) } } else { @@ -293,6 +297,7 @@ private extension XCUIElementQuery { return self.containing(isNetworkLoadingIndicator) } + @MainActor var deviceStatusBars: XCUIElementQuery { guard let app = Snapshot.app else { fatalError("XCUIApplication is not set. Please call setupSnapshot(app) before snapshot().") @@ -318,4 +323,4 @@ private extension CGFloat { // Please don't remove the lines below // They are used to detect outdated configuration files -// SnapshotHelperVersion [1.29] +// SnapshotHelperVersion [1.30] diff --git a/ios/Snapfile b/ios/Snapfile index 95dd009cf7e4..43c55ae82dca 100644 --- a/ios/Snapfile +++ b/ios/Snapfile @@ -15,7 +15,7 @@ languages([ ]) # The name of the scheme which contains the UI Tests -scheme("MullvadVPNScreenshots") +scheme("MullvadVPNUITests") # The name of the test plan which contains the UI Tests testplan("MullvadVPNScreenshots")