Skip to content

Commit

Permalink
Add end-to-end tests for Enrypted DNS proxy
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon Petersson committed Sep 30, 2024
1 parent 980c837 commit 706fc74
Show file tree
Hide file tree
Showing 11 changed files with 90 additions and 5 deletions.
10 changes: 7 additions & 3 deletions ios/MullvadSettings/AccessMethodRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,28 @@ import MullvadLogging
import MullvadTypes

public class AccessMethodRepository: AccessMethodRepositoryProtocol {
public static let directMethodId = "C9DB7457-2A55-42C3-A926-C07F82131994"
public static let bridgeMethodId = "8586E75A-CA7B-4432-B70D-EE65F3F95084"
public static let encryptedDNSMethodId = "831CB1F8-1829-42DD-B9DC-82902F298EC0"

private let logger = Logger(label: "AccessMethodRepository")

private let direct = PersistentAccessMethod(
id: UUID(uuidString: "C9DB7457-2A55-42C3-A926-C07F82131994")!,
id: UUID(uuidString: AccessMethodRepository.directMethodId)!,
name: "Direct",
isEnabled: true,
proxyConfiguration: .direct
)

private let bridge = PersistentAccessMethod(
id: UUID(uuidString: "8586E75A-CA7B-4432-B70D-EE65F3F95084")!,
id: UUID(uuidString: bridgeMethodId)!,
name: "Mullvad bridges",
isEnabled: true,
proxyConfiguration: .bridges
)

private let encryptedDNS = PersistentAccessMethod(
id: UUID(uuidString: "831CB1F8-1829-42DD-B9DC-82902F298EC0")!,
id: UUID(uuidString: encryptedDNSMethodId)!,
name: "Encrypted DNS proxy",
isEnabled: true,
proxyConfiguration: .encryptedDNS
Expand Down
4 changes: 4 additions & 0 deletions ios/MullvadVPN.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,7 @@
7A9CCCC22A96302800DD6A34 /* SafariCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9CCCB02A96302800DD6A34 /* SafariCoordinator.swift */; };
7A9CCCC32A96302800DD6A34 /* ApplicationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9CCCB12A96302800DD6A34 /* ApplicationCoordinator.swift */; };
7A9CCCC42A96302800DD6A34 /* TunnelCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9CCCB22A96302800DD6A34 /* TunnelCoordinator.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 */; };
7AA513862BC91C6B00D081A4 /* LogRotationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA513852BC91C6B00D081A4 /* LogRotationTests.swift */; };
Expand Down Expand Up @@ -1891,6 +1892,7 @@
7A9CCCB02A96302800DD6A34 /* SafariCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SafariCoordinator.swift; sourceTree = "<group>"; };
7A9CCCB12A96302800DD6A34 /* ApplicationCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApplicationCoordinator.swift; sourceTree = "<group>"; };
7A9CCCB22A96302800DD6A34 /* TunnelCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TunnelCoordinator.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>"; };
7AA513852BC91C6B00D081A4 /* LogRotationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogRotationTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3928,6 +3930,7 @@
852969372B4ED20E007EAD4C /* Info.plist */,
8556EB532B9A1D7100D26DD4 /* BridgingHeader.h */,
85B267602B849ADB0098E3CD /* mullvad-api.h */,
7A9F29342CAA8823005F2089 /* AccessMethodsTests.swift */,
852969272B4D9C1F007EAD4C /* AccountTests.swift */,
85557B112B594FC900795FE1 /* ConnectivityTests.swift */,
A9BFAFFE2BD004ED00F2BCA1 /* CustomListsTests.swift */,
Expand Down Expand Up @@ -6112,6 +6115,7 @@
85D039982BA4711800940E7F /* SettingsMigrationTests.swift in Sources */,
85021CAE2BDBC4290098B400 /* AppLogsPage.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: String {
// Buttons
case addAccessMethodButton
case accessMethodAddButton
case accessMethodTestButton
case accountButton
case accessMethodUnreachableBackButton
case accessMethodUnreachableSaveButton
Expand Down Expand Up @@ -63,6 +64,9 @@ public enum AccessibilityIdentifier: String {

// 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

// Accessibiliry 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 @@ -172,6 +172,7 @@ class EditAccessMethodViewController: UITableViewController {

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 @@ -182,6 +183,7 @@ class EditAccessMethodViewController: UITableViewController {

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 @@ -47,8 +47,20 @@ extension PersistentAccessMethod {
let sanitizedName = name.trimmingCharacters(in: .whitespaces)
let itemName = sanitizedName.isEmpty ? kind.localizedDescription : sanitizedName

let accessibilityId: AccessibilityIdentifier? = switch id.uuidString {
case AccessMethodRepository.directMethodId:
AccessibilityIdentifier.accessMethodDirectCell
case AccessMethodRepository.bridgeMethodId:
AccessibilityIdentifier.accessMethodBridgesCell
case AccessMethodRepository.encryptedDNSMethodId:
AccessibilityIdentifier.accessMethodEncryptedDNSCell
default:
nil
}

return ListAccessMethodItem(
id: id,
accessibilityId: accessibilityId,
name: itemName,
detail: isEnabled
? kind.localizedDescription
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import Foundation
/// A concrete implementation of an API access list item.
struct ListAccessMethodItem: Hashable, Identifiable, Equatable {
let id: UUID
let accessibilityId: AccessibilityIdentifier?

/// The localized name of an API method.
let name: String
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 @@ -201,6 +201,8 @@ class ListAccessMethodViewController: UIViewController, UITableViewDelegate {
cell.disclosureType = .chevron
}

cell.accessibilityIdentifier = item.accessibilityId

return cell
}

Expand Down
32 changes: 32 additions & 0 deletions ios/MullvadVPNUITests/AccessMethodsTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// 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 testEncryptedDNS() throws {
HeaderBar(app)
.tapSettingsButton()

SettingsPage(app)
.tapAPIAccessCell()

let cell = APIAccessPage(app)
.getAccessMethodCell(accessibilityId: AccessibilityIdentifier.accessMethodEncryptedDNSCell)

XCTAssertFalse(APIAccessPage(app).getMethodIsDisabled(cell))

cell.tap()

EditAccessMethodPage(app)
.tapEnableMethodSwitch()
.tapBackButton()

XCTAssertTrue(APIAccessPage(app).getMethodIsDisabled(cell))
}
}
18 changes: 17 additions & 1 deletion ios/MullvadVPNUITests/Pages/APIAccessPage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,22 @@ 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]
}

func getMethodIsInUse(_ cell: XCUIElement) -> Bool {
cell.staticTexts.allElementsBoundByIndex.contains { element in
element.label == "In use"
}
}

func getMethodIsDisabled(_ cell: XCUIElement) -> Bool {
cell.staticTexts.allElementsBoundByIndex.contains { element in
element.label == "Disabled"
}
}
}
5 changes: 5 additions & 0 deletions ios/MullvadVPNUITests/Pages/EditAccessMethodPage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ class EditAccessMethodPage: Page {
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

0 comments on commit 706fc74

Please sign in to comment.