summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJon Petersson <jon.petersson@mullvad.net>2025-03-03 16:23:00 +0100
committerJon Petersson <jon.petersson@mullvad.net>2025-03-03 16:23:00 +0100
commit0199b5872f8268a7017aa202c309b50dafe2c704 (patch)
treec4a8a6497a54d9a55bf8c301d66054ac214d992d
parentb132688dc1025f4da5370aa8851b004ac5c3c29e (diff)
parent74c137749420d12a059c2c7130a84c573e274fdc (diff)
downloadmullvadvpn-0199b5872f8268a7017aa202c309b50dafe2c704.tar.xz
mullvadvpn-0199b5872f8268a7017aa202c309b50dafe2c704.zip
Merge branch 'add-end-to-end-tests-for-this-ios-827'
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj4
-rw-r--r--ios/MullvadVPN/Classes/AccessbilityIdentifier.swift4
-rw-r--r--ios/MullvadVPN/Coordinators/Settings/APIAccess/Cells/ButtonCellContentConfiguration.swift3
-rw-r--r--ios/MullvadVPN/Coordinators/Settings/APIAccess/Cells/ButtonCellContentView.swift1
-rw-r--r--ios/MullvadVPN/Coordinators/Settings/APIAccess/Edit/EditAccessMethodViewController.swift2
-rw-r--r--ios/MullvadVPN/Coordinators/Settings/APIAccess/List/ListAccessMethodItem.swift3
-rw-r--r--ios/MullvadVPN/Coordinators/Settings/APIAccess/List/ListAccessMethodViewController.swift14
-rw-r--r--ios/MullvadVPNUITests/AccessMethodsTests.swift59
-rw-r--r--ios/MullvadVPNUITests/Pages/APIAccessPage.swift6
-rw-r--r--ios/MullvadVPNUITests/Pages/EditAccessMethodPage.swift22
10 files changed, 115 insertions, 3 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index aeb4065128..56aa4423a6 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -633,6 +633,7 @@
7A9F29392CABFAFC005F2089 /* InfoHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9F29382CABFAEC005F2089 /* InfoHeaderView.swift */; };
7A9F293B2CAC4443005F2089 /* InfoHeaderConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9F293A2CAC4420005F2089 /* InfoHeaderConfig.swift */; };
7A9F293D2CAD2FD5005F2089 /* InfoModalConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9F293C2CAD2FCF005F2089 /* InfoModalConfig.swift */; };
+ 7A9F29352CAA8829005F2089 /* AccessMethodsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9F29342CAA8823005F2089 /* AccessMethodsTests.swift */; };
7A9FA1422A2E3306000B728D /* CheckboxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9FA1412A2E3306000B728D /* CheckboxView.swift */; };
7A9FA1442A2E3FE5000B728D /* CheckableSettingsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9FA1432A2E3FE5000B728D /* CheckableSettingsCell.swift */; };
7AA130992CFF365D00640DF9 /* ConnectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA130982CFF365A00640DF9 /* ConnectionView.swift */; };
@@ -2148,6 +2149,7 @@
7A9F29382CABFAEC005F2089 /* InfoHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoHeaderView.swift; sourceTree = "<group>"; };
7A9F293A2CAC4420005F2089 /* InfoHeaderConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoHeaderConfig.swift; sourceTree = "<group>"; };
7A9F293C2CAD2FCF005F2089 /* InfoModalConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoModalConfig.swift; sourceTree = "<group>"; };
+ 7A9F29342CAA8823005F2089 /* AccessMethodsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessMethodsTests.swift; sourceTree = "<group>"; };
7A9FA1412A2E3306000B728D /* CheckboxView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxView.swift; sourceTree = "<group>"; };
7A9FA1432A2E3FE5000B728D /* CheckableSettingsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckableSettingsCell.swift; sourceTree = "<group>"; };
7AA130982CFF365A00640DF9 /* ConnectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectionView.swift; sourceTree = "<group>"; };
@@ -4355,6 +4357,7 @@
8556EB532B9A1D7100D26DD4 /* BridgingHeader.h */,
85B267602B849ADB0098E3CD /* mullvad-api.h */,
852969372B4ED20E007EAD4C /* Info.plist */,
+ 7A9F29342CAA8823005F2089 /* AccessMethodsTests.swift */,
852969272B4D9C1F007EAD4C /* AccountTests.swift */,
85557B112B594FC900795FE1 /* ConnectivityTests.swift */,
A9BFAFFE2BD004ED00F2BCA1 /* CustomListsTests.swift */,
@@ -6683,6 +6686,7 @@
85021CAE2BDBC4290098B400 /* AppLogsPage.swift in Sources */,
4495ECD12D0B170700A7358B /* UDPOverTCPObfuscationSettingsPage.swift in Sources */,
850201DB2B503D7700EF8C96 /* RelayTests.swift in Sources */,
+ 7A9F29352CAA8829005F2089 /* AccessMethodsTests.swift in Sources */,
7A45CFC62C05FF6A00D80B21 /* ScreenshotTests.swift in Sources */,
852D054D2BC3DE3A008578D2 /* APIAccessPage.swift in Sources */,
85139B2D2B84B4A700734217 /* OutOfTimePage.swift in Sources */,
diff --git a/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift b/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift
index 820c2cabdb..ea585cebcf 100644
--- a/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift
+++ b/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift
@@ -12,6 +12,7 @@ public enum AccessibilityIdentifier: Equatable {
// Buttons
case addAccessMethodButton
case accessMethodAddButton
+ case accessMethodTestButton
case accountButton
case accessMethodUnreachableBackButton
case accessMethodUnreachableSaveButton
@@ -64,6 +65,9 @@ public enum AccessibilityIdentifier: Equatable {
case acceptLocalNetworkSharingButton
// Cells
case deviceCell
+ case accessMethodDirectCell
+ case accessMethodBridgesCell
+ case accessMethodEncryptedDNSCell
case accessMethodProtocolSelectionCell
case vpnSettingsCell
case dnsSettingsAddServerCell
diff --git a/ios/MullvadVPN/Coordinators/Settings/APIAccess/Cells/ButtonCellContentConfiguration.swift b/ios/MullvadVPN/Coordinators/Settings/APIAccess/Cells/ButtonCellContentConfiguration.swift
index c5c58ef77a..b4b0558352 100644
--- a/ios/MullvadVPN/Coordinators/Settings/APIAccess/Cells/ButtonCellContentConfiguration.swift
+++ b/ios/MullvadVPN/Coordinators/Settings/APIAccess/Cells/ButtonCellContentConfiguration.swift
@@ -25,6 +25,9 @@ struct ButtonCellContentConfiguration: UIContentConfiguration, Equatable {
/// The button content edge insets.
var directionalContentEdgeInsets: NSDirectionalEdgeInsets = UIMetrics.SettingsCell.insetLayoutMargins
+ // Accessibility identifier.
+ var accessibilityIdentifier: AccessibilityIdentifier?
+
func makeContentView() -> UIView & UIContentView {
return ButtonCellContentView(configuration: self)
}
diff --git a/ios/MullvadVPN/Coordinators/Settings/APIAccess/Cells/ButtonCellContentView.swift b/ios/MullvadVPN/Coordinators/Settings/APIAccess/Cells/ButtonCellContentView.swift
index a766b9cfd8..533fa76631 100644
--- a/ios/MullvadVPN/Coordinators/Settings/APIAccess/Cells/ButtonCellContentView.swift
+++ b/ios/MullvadVPN/Coordinators/Settings/APIAccess/Cells/ButtonCellContentView.swift
@@ -67,6 +67,7 @@ class ButtonCellContentView: UIView, UIContentView {
button.isEnabled = actualConfiguration.isEnabled
button.style = actualConfiguration.style
button.configuration?.contentInsets = actualConfiguration.directionalContentEdgeInsets
+ button.setAccessibilityIdentifier(actualConfiguration.accessibilityIdentifier)
}
private func addSubviews() {
diff --git a/ios/MullvadVPN/Coordinators/Settings/APIAccess/Edit/EditAccessMethodViewController.swift b/ios/MullvadVPN/Coordinators/Settings/APIAccess/Edit/EditAccessMethodViewController.swift
index ec27f17c9b..9b36dcc530 100644
--- a/ios/MullvadVPN/Coordinators/Settings/APIAccess/Edit/EditAccessMethodViewController.swift
+++ b/ios/MullvadVPN/Coordinators/Settings/APIAccess/Edit/EditAccessMethodViewController.swift
@@ -199,6 +199,7 @@ extension EditAccessMethodViewController: UITableViewDelegate {
private func configureTestMethod(_ cell: UITableViewCell, itemIdentifier: EditAccessMethodItemIdentifier) {
var contentConfiguration = ButtonCellContentConfiguration()
+ contentConfiguration.accessibilityIdentifier = .accessMethodTestButton
contentConfiguration.text = itemIdentifier.text
contentConfiguration.isEnabled = subject.value.testingStatus != .inProgress
contentConfiguration.primaryAction = UIAction { [weak self] _ in
@@ -209,6 +210,7 @@ extension EditAccessMethodViewController: UITableViewDelegate {
private func configureCancelTest(_ cell: UITableViewCell, itemIdentifier: EditAccessMethodItemIdentifier) {
var contentConfiguration = ButtonCellContentConfiguration()
+ contentConfiguration.accessibilityIdentifier = .accessMethodTestButton
contentConfiguration.text = itemIdentifier.text
contentConfiguration.isEnabled = subject.value.testingStatus == .inProgress
contentConfiguration.primaryAction = UIAction { [weak self] _ in
diff --git a/ios/MullvadVPN/Coordinators/Settings/APIAccess/List/ListAccessMethodItem.swift b/ios/MullvadVPN/Coordinators/Settings/APIAccess/List/ListAccessMethodItem.swift
index 063546ce83..0319ba9b66 100644
--- a/ios/MullvadVPN/Coordinators/Settings/APIAccess/List/ListAccessMethodItem.swift
+++ b/ios/MullvadVPN/Coordinators/Settings/APIAccess/List/ListAccessMethodItem.swift
@@ -10,9 +10,10 @@ import Foundation
/// A concrete implementation of an API access list item.
struct ListAccessMethodItem: Hashable, Identifiable, Equatable {
+ /// The unique ID.
let id: UUID
- /// The localized name of an API method.
+ /// The localized name.
let name: String
/// The detailed information displayed alongside.
diff --git a/ios/MullvadVPN/Coordinators/Settings/APIAccess/List/ListAccessMethodViewController.swift b/ios/MullvadVPN/Coordinators/Settings/APIAccess/List/ListAccessMethodViewController.swift
index 9e4b91f39c..d04a532f1c 100644
--- a/ios/MullvadVPN/Coordinators/Settings/APIAccess/List/ListAccessMethodViewController.swift
+++ b/ios/MullvadVPN/Coordinators/Settings/APIAccess/List/ListAccessMethodViewController.swift
@@ -16,7 +16,7 @@ enum ListAccessMethodSectionIdentifier: Hashable {
}
struct ListAccessMethodItemIdentifier: Hashable {
- var id: UUID
+ let id: UUID
}
/// View controller presenting a list of API access methods.
@@ -220,6 +220,18 @@ class ListAccessMethodViewController: UIViewController, UITableViewDelegate {
cell.disclosureType = .chevron
}
+ let accessibilityId: AccessibilityIdentifier? = switch item.id.uuidString {
+ case AccessMethodRepository.directId.uuidString:
+ AccessibilityIdentifier.accessMethodDirectCell
+ case AccessMethodRepository.bridgeId.uuidString:
+ AccessibilityIdentifier.accessMethodBridgesCell
+ case AccessMethodRepository.encryptedDNSId.uuidString:
+ AccessibilityIdentifier.accessMethodEncryptedDNSCell
+ default:
+ nil
+ }
+ cell.setAccessibilityIdentifier(accessibilityId)
+
return cell
}
diff --git a/ios/MullvadVPNUITests/AccessMethodsTests.swift b/ios/MullvadVPNUITests/AccessMethodsTests.swift
new file mode 100644
index 0000000000..37ec9e832d
--- /dev/null
+++ b/ios/MullvadVPNUITests/AccessMethodsTests.swift
@@ -0,0 +1,59 @@
+//
+// AccessMethodsTests.swift
+// MullvadVPN
+//
+// Created by Jon Petersson on 2024-09-30.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+import XCTest
+
+class AccessMethodsTests: LoggedOutUITestCase {
+ func testDirect() throws {
+ HeaderBar(app)
+ .tapSettingsButton()
+
+ SettingsPage(app)
+ .tapAPIAccessCell()
+
+ APIAccessPage(app)
+ .getAccessMethodCell(accessibilityId: AccessibilityIdentifier.accessMethodDirectCell)
+ .tap()
+
+ EditAccessMethodPage(app)
+ .tapTestMethodButton()
+ .verifyTestStatus(.reachable)
+ }
+
+ func testBridges() throws {
+ HeaderBar(app)
+ .tapSettingsButton()
+
+ SettingsPage(app)
+ .tapAPIAccessCell()
+
+ APIAccessPage(app)
+ .getAccessMethodCell(accessibilityId: AccessibilityIdentifier.accessMethodBridgesCell)
+ .tap()
+
+ EditAccessMethodPage(app)
+ .tapTestMethodButton()
+ .verifyTestStatus(.reachable)
+ }
+
+ func testEncryptedDNS() throws {
+ HeaderBar(app)
+ .tapSettingsButton()
+
+ SettingsPage(app)
+ .tapAPIAccessCell()
+
+ APIAccessPage(app)
+ .getAccessMethodCell(accessibilityId: AccessibilityIdentifier.accessMethodEncryptedDNSCell)
+ .tap()
+
+ EditAccessMethodPage(app)
+ .tapTestMethodButton()
+ .verifyTestStatus(.reachable)
+ }
+}
diff --git a/ios/MullvadVPNUITests/Pages/APIAccessPage.swift b/ios/MullvadVPNUITests/Pages/APIAccessPage.swift
index feea7a2bb8..1ea3a19784 100644
--- a/ios/MullvadVPNUITests/Pages/APIAccessPage.swift
+++ b/ios/MullvadVPNUITests/Pages/APIAccessPage.swift
@@ -23,6 +23,10 @@ class APIAccessPage: Page {
}
func getAccessMethodCells() -> [XCUIElement] {
- return app.otherElements[AccessibilityIdentifier.apiAccessView].cells.allElementsBoundByIndex
+ app.otherElements[AccessibilityIdentifier.apiAccessView].cells.allElementsBoundByIndex
+ }
+
+ func getAccessMethodCell(accessibilityId: AccessibilityIdentifier) -> XCUIElement {
+ app.otherElements[AccessibilityIdentifier.apiAccessView].cells[accessibilityId]
}
}
diff --git a/ios/MullvadVPNUITests/Pages/EditAccessMethodPage.swift b/ios/MullvadVPNUITests/Pages/EditAccessMethodPage.swift
index 9363e602fb..0941f8edab 100644
--- a/ios/MullvadVPNUITests/Pages/EditAccessMethodPage.swift
+++ b/ios/MullvadVPNUITests/Pages/EditAccessMethodPage.swift
@@ -10,6 +10,10 @@ import Foundation
import XCTest
class EditAccessMethodPage: Page {
+ enum TestStatus {
+ case reachable, unreachable, testing
+ }
+
override init(_ app: XCUIApplication) {
super.init(app)
self.pageElement = app.tables[.editAccessMethodView]
@@ -31,6 +35,24 @@ class EditAccessMethodPage: Page {
return self
}
+ @discardableResult func verifyTestStatus(_ status: TestStatus) -> Self {
+ switch status {
+ case .reachable:
+ XCTAssertTrue(app.staticTexts["API reachable"].waitForExistence(timeout: BaseUITestCase.longTimeout))
+ case .unreachable:
+ XCTAssertTrue(app.staticTexts["API unreachable"].waitForExistence(timeout: BaseUITestCase.longTimeout))
+ case .testing:
+ XCTAssertTrue(app.staticTexts["Testing..."].waitForExistence(timeout: BaseUITestCase.longTimeout))
+ }
+
+ return self
+ }
+
+ @discardableResult func tapTestMethodButton() -> Self {
+ app.buttons[AccessibilityIdentifier.accessMethodTestButton].tap()
+ return self
+ }
+
@discardableResult func tapBackButton() -> Self {
// Workaround due to the way automatically managed back buttons work. Back button needs to be nil for the automatic back button behaviour in iOS, and since its nil we cannot set accessibilityIdentifier for it
let backButton = app.navigationBars.firstMatch.buttons.firstMatch