Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add end-to-end tests for access methods #6886

Merged
merged 1 commit into from
Mar 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ios/MullvadVPN.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */; };
Expand Down Expand Up @@ -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>"; };
Expand Down Expand Up @@ -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 */,
Expand Down Expand Up @@ -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 */,
Expand Down
4 changes: 4 additions & 0 deletions ios/MullvadVPN/Classes/AccessbilityIdentifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public enum AccessibilityIdentifier: Equatable {
// Buttons
case addAccessMethodButton
case accessMethodAddButton
case accessMethodTestButton
case accountButton
case accessMethodUnreachableBackButton
case accessMethodUnreachableSaveButton
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
}

Expand Down
59 changes: 59 additions & 0 deletions ios/MullvadVPNUITests/AccessMethodsTests.swift
Original file line number Diff line number Diff line change
@@ -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)
}
}
6 changes: 5 additions & 1 deletion ios/MullvadVPNUITests/Pages/APIAccessPage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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]
}
}
22 changes: 22 additions & 0 deletions ios/MullvadVPNUITests/Pages/EditAccessMethodPage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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
Expand Down
Loading