Skip to content

Commit 74c1377

Browse files
Jon Peterssonrablador
Jon Petersson
authored andcommitted
Add end-to-end tests for access methods
1 parent b132688 commit 74c1377

10 files changed

+115
-3
lines changed

ios/MullvadVPN.xcodeproj/project.pbxproj

+4
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,7 @@
633633
7A9F29392CABFAFC005F2089 /* InfoHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9F29382CABFAEC005F2089 /* InfoHeaderView.swift */; };
634634
7A9F293B2CAC4443005F2089 /* InfoHeaderConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9F293A2CAC4420005F2089 /* InfoHeaderConfig.swift */; };
635635
7A9F293D2CAD2FD5005F2089 /* InfoModalConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9F293C2CAD2FCF005F2089 /* InfoModalConfig.swift */; };
636+
7A9F29352CAA8829005F2089 /* AccessMethodsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9F29342CAA8823005F2089 /* AccessMethodsTests.swift */; };
636637
7A9FA1422A2E3306000B728D /* CheckboxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9FA1412A2E3306000B728D /* CheckboxView.swift */; };
637638
7A9FA1442A2E3FE5000B728D /* CheckableSettingsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9FA1432A2E3FE5000B728D /* CheckableSettingsCell.swift */; };
638639
7AA130992CFF365D00640DF9 /* ConnectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA130982CFF365A00640DF9 /* ConnectionView.swift */; };
@@ -2148,6 +2149,7 @@
21482149
7A9F29382CABFAEC005F2089 /* InfoHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoHeaderView.swift; sourceTree = "<group>"; };
21492150
7A9F293A2CAC4420005F2089 /* InfoHeaderConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoHeaderConfig.swift; sourceTree = "<group>"; };
21502151
7A9F293C2CAD2FCF005F2089 /* InfoModalConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoModalConfig.swift; sourceTree = "<group>"; };
2152+
7A9F29342CAA8823005F2089 /* AccessMethodsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessMethodsTests.swift; sourceTree = "<group>"; };
21512153
7A9FA1412A2E3306000B728D /* CheckboxView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxView.swift; sourceTree = "<group>"; };
21522154
7A9FA1432A2E3FE5000B728D /* CheckableSettingsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckableSettingsCell.swift; sourceTree = "<group>"; };
21532155
7AA130982CFF365A00640DF9 /* ConnectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectionView.swift; sourceTree = "<group>"; };
@@ -4355,6 +4357,7 @@
43554357
8556EB532B9A1D7100D26DD4 /* BridgingHeader.h */,
43564358
85B267602B849ADB0098E3CD /* mullvad-api.h */,
43574359
852969372B4ED20E007EAD4C /* Info.plist */,
4360+
7A9F29342CAA8823005F2089 /* AccessMethodsTests.swift */,
43584361
852969272B4D9C1F007EAD4C /* AccountTests.swift */,
43594362
85557B112B594FC900795FE1 /* ConnectivityTests.swift */,
43604363
A9BFAFFE2BD004ED00F2BCA1 /* CustomListsTests.swift */,
@@ -6683,6 +6686,7 @@
66836686
85021CAE2BDBC4290098B400 /* AppLogsPage.swift in Sources */,
66846687
4495ECD12D0B170700A7358B /* UDPOverTCPObfuscationSettingsPage.swift in Sources */,
66856688
850201DB2B503D7700EF8C96 /* RelayTests.swift in Sources */,
6689+
7A9F29352CAA8829005F2089 /* AccessMethodsTests.swift in Sources */,
66866690
7A45CFC62C05FF6A00D80B21 /* ScreenshotTests.swift in Sources */,
66876691
852D054D2BC3DE3A008578D2 /* APIAccessPage.swift in Sources */,
66886692
85139B2D2B84B4A700734217 /* OutOfTimePage.swift in Sources */,

ios/MullvadVPN/Classes/AccessbilityIdentifier.swift

+4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public enum AccessibilityIdentifier: Equatable {
1212
// Buttons
1313
case addAccessMethodButton
1414
case accessMethodAddButton
15+
case accessMethodTestButton
1516
case accountButton
1617
case accessMethodUnreachableBackButton
1718
case accessMethodUnreachableSaveButton
@@ -64,6 +65,9 @@ public enum AccessibilityIdentifier: Equatable {
6465
case acceptLocalNetworkSharingButton
6566
// Cells
6667
case deviceCell
68+
case accessMethodDirectCell
69+
case accessMethodBridgesCell
70+
case accessMethodEncryptedDNSCell
6771
case accessMethodProtocolSelectionCell
6872
case vpnSettingsCell
6973
case dnsSettingsAddServerCell

ios/MullvadVPN/Coordinators/Settings/APIAccess/Cells/ButtonCellContentConfiguration.swift

+3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ struct ButtonCellContentConfiguration: UIContentConfiguration, Equatable {
2525
/// The button content edge insets.
2626
var directionalContentEdgeInsets: NSDirectionalEdgeInsets = UIMetrics.SettingsCell.insetLayoutMargins
2727

28+
// Accessibility identifier.
29+
var accessibilityIdentifier: AccessibilityIdentifier?
30+
2831
func makeContentView() -> UIView & UIContentView {
2932
return ButtonCellContentView(configuration: self)
3033
}

ios/MullvadVPN/Coordinators/Settings/APIAccess/Cells/ButtonCellContentView.swift

+1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ class ButtonCellContentView: UIView, UIContentView {
6767
button.isEnabled = actualConfiguration.isEnabled
6868
button.style = actualConfiguration.style
6969
button.configuration?.contentInsets = actualConfiguration.directionalContentEdgeInsets
70+
button.setAccessibilityIdentifier(actualConfiguration.accessibilityIdentifier)
7071
}
7172

7273
private func addSubviews() {

ios/MullvadVPN/Coordinators/Settings/APIAccess/Edit/EditAccessMethodViewController.swift

+2
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ extension EditAccessMethodViewController: UITableViewDelegate {
199199

200200
private func configureTestMethod(_ cell: UITableViewCell, itemIdentifier: EditAccessMethodItemIdentifier) {
201201
var contentConfiguration = ButtonCellContentConfiguration()
202+
contentConfiguration.accessibilityIdentifier = .accessMethodTestButton
202203
contentConfiguration.text = itemIdentifier.text
203204
contentConfiguration.isEnabled = subject.value.testingStatus != .inProgress
204205
contentConfiguration.primaryAction = UIAction { [weak self] _ in
@@ -209,6 +210,7 @@ extension EditAccessMethodViewController: UITableViewDelegate {
209210

210211
private func configureCancelTest(_ cell: UITableViewCell, itemIdentifier: EditAccessMethodItemIdentifier) {
211212
var contentConfiguration = ButtonCellContentConfiguration()
213+
contentConfiguration.accessibilityIdentifier = .accessMethodTestButton
212214
contentConfiguration.text = itemIdentifier.text
213215
contentConfiguration.isEnabled = subject.value.testingStatus == .inProgress
214216
contentConfiguration.primaryAction = UIAction { [weak self] _ in

ios/MullvadVPN/Coordinators/Settings/APIAccess/List/ListAccessMethodItem.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ import Foundation
1010

1111
/// A concrete implementation of an API access list item.
1212
struct ListAccessMethodItem: Hashable, Identifiable, Equatable {
13+
/// The unique ID.
1314
let id: UUID
1415

15-
/// The localized name of an API method.
16+
/// The localized name.
1617
let name: String
1718

1819
/// The detailed information displayed alongside.

ios/MullvadVPN/Coordinators/Settings/APIAccess/List/ListAccessMethodViewController.swift

+13-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ enum ListAccessMethodSectionIdentifier: Hashable {
1616
}
1717

1818
struct ListAccessMethodItemIdentifier: Hashable {
19-
var id: UUID
19+
let id: UUID
2020
}
2121

2222
/// View controller presenting a list of API access methods.
@@ -220,6 +220,18 @@ class ListAccessMethodViewController: UIViewController, UITableViewDelegate {
220220
cell.disclosureType = .chevron
221221
}
222222

223+
let accessibilityId: AccessibilityIdentifier? = switch item.id.uuidString {
224+
case AccessMethodRepository.directId.uuidString:
225+
AccessibilityIdentifier.accessMethodDirectCell
226+
case AccessMethodRepository.bridgeId.uuidString:
227+
AccessibilityIdentifier.accessMethodBridgesCell
228+
case AccessMethodRepository.encryptedDNSId.uuidString:
229+
AccessibilityIdentifier.accessMethodEncryptedDNSCell
230+
default:
231+
nil
232+
}
233+
cell.setAccessibilityIdentifier(accessibilityId)
234+
223235
return cell
224236
}
225237

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//
2+
// AccessMethodsTests.swift
3+
// MullvadVPN
4+
//
5+
// Created by Jon Petersson on 2024-09-30.
6+
// Copyright © 2024 Mullvad VPN AB. All rights reserved.
7+
//
8+
9+
import XCTest
10+
11+
class AccessMethodsTests: LoggedOutUITestCase {
12+
func testDirect() throws {
13+
HeaderBar(app)
14+
.tapSettingsButton()
15+
16+
SettingsPage(app)
17+
.tapAPIAccessCell()
18+
19+
APIAccessPage(app)
20+
.getAccessMethodCell(accessibilityId: AccessibilityIdentifier.accessMethodDirectCell)
21+
.tap()
22+
23+
EditAccessMethodPage(app)
24+
.tapTestMethodButton()
25+
.verifyTestStatus(.reachable)
26+
}
27+
28+
func testBridges() throws {
29+
HeaderBar(app)
30+
.tapSettingsButton()
31+
32+
SettingsPage(app)
33+
.tapAPIAccessCell()
34+
35+
APIAccessPage(app)
36+
.getAccessMethodCell(accessibilityId: AccessibilityIdentifier.accessMethodBridgesCell)
37+
.tap()
38+
39+
EditAccessMethodPage(app)
40+
.tapTestMethodButton()
41+
.verifyTestStatus(.reachable)
42+
}
43+
44+
func testEncryptedDNS() throws {
45+
HeaderBar(app)
46+
.tapSettingsButton()
47+
48+
SettingsPage(app)
49+
.tapAPIAccessCell()
50+
51+
APIAccessPage(app)
52+
.getAccessMethodCell(accessibilityId: AccessibilityIdentifier.accessMethodEncryptedDNSCell)
53+
.tap()
54+
55+
EditAccessMethodPage(app)
56+
.tapTestMethodButton()
57+
.verifyTestStatus(.reachable)
58+
}
59+
}

ios/MullvadVPNUITests/Pages/APIAccessPage.swift

+5-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ class APIAccessPage: Page {
2323
}
2424

2525
func getAccessMethodCells() -> [XCUIElement] {
26-
return app.otherElements[AccessibilityIdentifier.apiAccessView].cells.allElementsBoundByIndex
26+
app.otherElements[AccessibilityIdentifier.apiAccessView].cells.allElementsBoundByIndex
27+
}
28+
29+
func getAccessMethodCell(accessibilityId: AccessibilityIdentifier) -> XCUIElement {
30+
app.otherElements[AccessibilityIdentifier.apiAccessView].cells[accessibilityId]
2731
}
2832
}

ios/MullvadVPNUITests/Pages/EditAccessMethodPage.swift

+22
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ import Foundation
1010
import XCTest
1111

1212
class EditAccessMethodPage: Page {
13+
enum TestStatus {
14+
case reachable, unreachable, testing
15+
}
16+
1317
override init(_ app: XCUIApplication) {
1418
super.init(app)
1519
self.pageElement = app.tables[.editAccessMethodView]
@@ -31,6 +35,24 @@ class EditAccessMethodPage: Page {
3135
return self
3236
}
3337

38+
@discardableResult func verifyTestStatus(_ status: TestStatus) -> Self {
39+
switch status {
40+
case .reachable:
41+
XCTAssertTrue(app.staticTexts["API reachable"].waitForExistence(timeout: BaseUITestCase.longTimeout))
42+
case .unreachable:
43+
XCTAssertTrue(app.staticTexts["API unreachable"].waitForExistence(timeout: BaseUITestCase.longTimeout))
44+
case .testing:
45+
XCTAssertTrue(app.staticTexts["Testing..."].waitForExistence(timeout: BaseUITestCase.longTimeout))
46+
}
47+
48+
return self
49+
}
50+
51+
@discardableResult func tapTestMethodButton() -> Self {
52+
app.buttons[AccessibilityIdentifier.accessMethodTestButton].tap()
53+
return self
54+
}
55+
3456
@discardableResult func tapBackButton() -> Self {
3557
// 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
3658
let backButton = app.navigationBars.firstMatch.buttons.firstMatch

0 commit comments

Comments
 (0)