summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrew Bulhak <andrew.bulhak@mullvad.net>2024-12-18 16:48:45 +0100
committeracb-mv <158061187+acb-mv@users.noreply.github.com>2025-01-02 10:05:47 +0100
commit3eed252d030eadd388332d5599452ea6f62fed07 (patch)
treee5cfd0e12111645952167bc24093b9d3b609b27a
parent71fe0b42d29a521c436fea92150d3c4dec2104e4 (diff)
downloadmullvadvpn-3eed252d030eadd388332d5599452ea6f62fed07.tar.xz
mullvadvpn-3eed252d030eadd388332d5599452ea6f62fed07.zip
Update UI tests for the new WG Obfuscation views
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj8
-rw-r--r--ios/MullvadVPN/Classes/AccessbilityIdentifier.swift4
-rw-r--r--ios/MullvadVPN/View controllers/Settings/Obfuscation/ShadowsocksObfuscationSettingsView.swift1
-rw-r--r--ios/MullvadVPN/View controllers/Settings/Obfuscation/UDPOverTCPObfuscationSettingsView.swift1
-rw-r--r--ios/MullvadVPN/View controllers/Settings/SwiftUI components/SingleChoiceList.swift87
-rw-r--r--ios/MullvadVPNUITests/Pages/ShadowsocksObfuscationSettingsPage.swift54
-rw-r--r--ios/MullvadVPNUITests/Pages/UDPOverTCPObfuscationSettingsPage.swift35
-rw-r--r--ios/MullvadVPNUITests/Pages/VPNSettingsPage.swift9
-rw-r--r--ios/MullvadVPNUITests/SettingsMigrationTests.swift18
9 files changed, 169 insertions, 48 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index ecc4ce38a8..8969294266 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -48,6 +48,8 @@
447F3D8A2CDE1853006E3462 /* ShadowsocksObfuscationSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 447F3D882CDE1852006E3462 /* ShadowsocksObfuscationSettingsViewModel.swift */; };
447F3D8B2CDE1853006E3462 /* ShadowsocksObfuscationSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 447F3D892CDE1853006E3462 /* ShadowsocksObfuscationSettingsView.swift */; };
449275422C3570CA000526DE /* ICMP.swift in Sources */ = {isa = PBXBuildFile; fileRef = 449275412C3570CA000526DE /* ICMP.swift */; };
+ 4495ECD12D0B170700A7358B /* UDPOverTCPObfuscationSettingsPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4495ECD02D0B16F700A7358B /* UDPOverTCPObfuscationSettingsPage.swift */; };
+ 4495ECD52D131A4800A7358B /* ShadowsocksObfuscationSettingsPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4495ECD42D131A3E00A7358B /* ShadowsocksObfuscationSettingsPage.swift */; };
449872E12B7BBC5400094DDC /* TunnelSettingsUpdate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 449872E02B7BBC5400094DDC /* TunnelSettingsUpdate.swift */; };
449872E42B7CB96300094DDC /* TunnelSettingsUpdateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 449872E32B7CB96300094DDC /* TunnelSettingsUpdateTests.swift */; };
449EBA262B975B9700DFA4EB /* EphemeralPeerReceiving.swift in Sources */ = {isa = PBXBuildFile; fileRef = 449EBA252B975B9700DFA4EB /* EphemeralPeerReceiving.swift */; };
@@ -1437,6 +1439,8 @@
447F3D892CDE1853006E3462 /* ShadowsocksObfuscationSettingsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShadowsocksObfuscationSettingsView.swift; sourceTree = "<group>"; };
449275412C3570CA000526DE /* ICMP.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ICMP.swift; sourceTree = "<group>"; };
449275432C3C3029000526DE /* TunnelPinger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelPinger.swift; sourceTree = "<group>"; };
+ 4495ECD02D0B16F700A7358B /* UDPOverTCPObfuscationSettingsPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UDPOverTCPObfuscationSettingsPage.swift; sourceTree = "<group>"; };
+ 4495ECD42D131A3E00A7358B /* ShadowsocksObfuscationSettingsPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShadowsocksObfuscationSettingsPage.swift; sourceTree = "<group>"; };
449872E02B7BBC5400094DDC /* TunnelSettingsUpdate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelSettingsUpdate.swift; sourceTree = "<group>"; };
449872E32B7CB96300094DDC /* TunnelSettingsUpdateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelSettingsUpdateTests.swift; sourceTree = "<group>"; };
449EB9FC2B95F8AD00DFA4EB /* DeviceMock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceMock.swift; sourceTree = "<group>"; };
@@ -4196,8 +4200,10 @@
8542F7522BCFBD050035C042 /* SelectLocationFilterPage.swift */,
850201DC2B503D8C00EF8C96 /* SelectLocationPage.swift */,
850201E22B51A93C00EF8C96 /* SettingsPage.swift */,
+ 4495ECD42D131A3E00A7358B /* ShadowsocksObfuscationSettingsPage.swift */,
852969392B4F0238007EAD4C /* TermsOfServicePage.swift */,
850201DE2B5040A500EF8C96 /* TunnelControlPage.swift */,
+ 4495ECD02D0B16F700A7358B /* UDPOverTCPObfuscationSettingsPage.swift */,
8542CE232B95F7B9006FCA14 /* VPNSettingsPage.swift */,
85FB5A0B2B6903990015DCED /* WelcomePage.swift */,
);
@@ -6398,11 +6404,13 @@
850201DD2B503D8C00EF8C96 /* SelectLocationPage.swift in Sources */,
85D039982BA4711800940E7F /* SettingsMigrationTests.swift in Sources */,
85021CAE2BDBC4290098B400 /* AppLogsPage.swift in Sources */,
+ 4495ECD12D0B170700A7358B /* UDPOverTCPObfuscationSettingsPage.swift in Sources */,
850201DB2B503D7700EF8C96 /* RelayTests.swift in Sources */,
7A45CFC62C05FF6A00D80B21 /* ScreenshotTests.swift in Sources */,
852D054D2BC3DE3A008578D2 /* APIAccessPage.swift in Sources */,
85139B2D2B84B4A700734217 /* OutOfTimePage.swift in Sources */,
852969362B4E9724007EAD4C /* AccessbilityIdentifier.swift in Sources */,
+ 4495ECD52D131A4800A7358B /* ShadowsocksObfuscationSettingsPage.swift in Sources */,
85E3BDE52B70E18C00FA71FD /* Networking.swift in Sources */,
856952E22BD6B04C008C1F84 /* XCUIElement+Extensions.swift in Sources */,
85C7A2E92B89024B00035D5A /* SettingsTests.swift in Sources */,
diff --git a/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift b/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift
index 5aa1e0c868..86fc7df767 100644
--- a/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift
+++ b/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift
@@ -210,6 +210,10 @@ public enum AccessibilityIdentifier: Equatable {
// Multihop
case multihopSwitch
+ // WireGuard obfuscation settings
+ case wireGuardObfuscationUdpOverTcpTable
+ case wireGuardObfuscationShadowsocksTable
+
// Error
case unknown
}
diff --git a/ios/MullvadVPN/View controllers/Settings/Obfuscation/ShadowsocksObfuscationSettingsView.swift b/ios/MullvadVPN/View controllers/Settings/Obfuscation/ShadowsocksObfuscationSettingsView.swift
index e5434b06e7..4c4ddbad6c 100644
--- a/ios/MullvadVPN/View controllers/Settings/Obfuscation/ShadowsocksObfuscationSettingsView.swift
+++ b/ios/MullvadVPN/View controllers/Settings/Obfuscation/ShadowsocksObfuscationSettingsView.swift
@@ -24,6 +24,7 @@ struct ShadowsocksObfuscationSettingsView<VM>: View where VM: ShadowsocksObfusca
title: portString,
options: [WireGuardObfuscationShadowsocksPort.automatic],
value: $viewModel.value,
+ tableAccessibilityIdentifier: AccessibilityIdentifier.wireGuardObfuscationShadowsocksTable.asString,
itemDescription: { item in NSLocalizedString(
"SHADOWSOCKS_PORT_VALUE_\(item)",
tableName: "Shadowsocks",
diff --git a/ios/MullvadVPN/View controllers/Settings/Obfuscation/UDPOverTCPObfuscationSettingsView.swift b/ios/MullvadVPN/View controllers/Settings/Obfuscation/UDPOverTCPObfuscationSettingsView.swift
index c14cd3e709..3d074a0d1d 100644
--- a/ios/MullvadVPN/View controllers/Settings/Obfuscation/UDPOverTCPObfuscationSettingsView.swift
+++ b/ios/MullvadVPN/View controllers/Settings/Obfuscation/UDPOverTCPObfuscationSettingsView.swift
@@ -23,6 +23,7 @@ struct UDPOverTCPObfuscationSettingsView<VM>: View where VM: UDPOverTCPObfuscati
title: portString,
options: [WireGuardObfuscationUdpOverTcpPort.automatic, .port80, .port5001],
value: $viewModel.value,
+ tableAccessibilityIdentifier: AccessibilityIdentifier.wireGuardObfuscationUdpOverTcpTable.asString,
itemDescription: { item in NSLocalizedString(
"UDP_TCP_PORT_VALUE_\(item)",
tableName: "UdpToTcp",
diff --git a/ios/MullvadVPN/View controllers/Settings/SwiftUI components/SingleChoiceList.swift b/ios/MullvadVPN/View controllers/Settings/SwiftUI components/SingleChoiceList.swift
index 4f9ce77f26..bdfba41480 100644
--- a/ios/MullvadVPN/View controllers/Settings/SwiftUI components/SingleChoiceList.swift
+++ b/ios/MullvadVPN/View controllers/Settings/SwiftUI components/SingleChoiceList.swift
@@ -56,8 +56,8 @@ struct SingleChoiceList<Value>: View where Value: Equatable {
private let options: [OptionSpec]
var value: Binding<Value>
@State var initialValue: Value?
+ let tableAccessibilityIdentifier: String
let itemDescription: (Value) -> String
- let itemAccessibilityIdentifier: (Value) -> String
let customFieldMode: CustomFieldMode
/// The configuration for the field for a custom value row
@@ -84,7 +84,6 @@ struct SingleChoiceList<Value>: View where Value: Equatable {
// this row consists of a text field into which the user can enter a custom value, which may yield a valid Value. This has accompanying text, and functions to translate between text field contents and the Value. (The fromValue method only needs to give a non-nil value if its input is a custom value that could have come from this row.)
case custom(
label: String,
- accessibilityIdentifier: String,
prompt: String,
legend: String?,
minInputWidth: CGFloat?,
@@ -103,15 +102,15 @@ struct SingleChoiceList<Value>: View where Value: Equatable {
title: String,
optionSpecs: [OptionSpec.OptValue],
value: Binding<Value>,
+ tableAccessibilityIdentifier: String?,
itemDescription: ((Value) -> String)? = nil,
- itemAccessibilityIdentifier: ((Value) -> String)? = nil,
customFieldMode: CustomFieldMode = .freeText
) {
self.title = title
self.options = optionSpecs.enumerated().map { OptionSpec(id: $0.offset, value: $0.element) }
self.value = value
self.itemDescription = itemDescription ?? { "\($0)" }
- self.itemAccessibilityIdentifier = itemAccessibilityIdentifier ?? { "\($0)" }
+ self.tableAccessibilityIdentifier = tableAccessibilityIdentifier ?? "SingleChoiceList"
self.customFieldMode = customFieldMode
self.initialValue = value.wrappedValue
}
@@ -122,11 +121,11 @@ struct SingleChoiceList<Value>: View where Value: Equatable {
/// - title: The title of the list, which is typically the name of the item being chosen.
/// - options: A list of `Value`s to be presented.
/// - itemDescription: An optional function that, when given a `Value`, returns the string representation to present in the list. If not provided, this will be generated naïvely using string interpolation.
- /// - itemAccessibilityIdentifier: An optional function that, when given a `Value`, returns the accessibility identifier for the value's list item. If not provided, this will be generated naïvely using string interpolation.
init(
title: String,
options: [Value],
value: Binding<Value>,
+ tableAccessibilityIdentifier: String? = nil,
itemDescription: ((Value) -> String)? = nil,
itemAccessibilityIdentifier: ((Value) -> String)? = nil
) {
@@ -134,8 +133,8 @@ struct SingleChoiceList<Value>: View where Value: Equatable {
title: title,
optionSpecs: options.map { .literal($0) },
value: value,
- itemDescription: itemDescription,
- itemAccessibilityIdentifier: itemAccessibilityIdentifier
+ tableAccessibilityIdentifier: tableAccessibilityIdentifier,
+ itemDescription: itemDescription
)
}
@@ -144,12 +143,11 @@ struct SingleChoiceList<Value>: View where Value: Equatable {
/// - Parameters:
/// - title: The title of the list, which is typically the name of the item being chosen.
/// - options: A list of fixed `Value`s to be presented.
+ /// - tableAccessibilityIdentifier: an optional string value for the accessibility identifier of the table element enclosing the list. If not present, it will be "SingleChoiceList"
/// - itemDescription: An optional function that, when given a `Value`, returns the string representation to present in the list. If not provided, this will be generated naïvely using string interpolation. This is only used for the non-custom values.
- /// - itemAccessibilityIdentifier: An optional function that, when given a `Value`, returns the accessibility identifier for the value's list item. If not provided, this will be generated naïvely using string interpolation.
/// - parseCustomValue: A function that attempts to parse the text entered into the text field and produce a `Value` (typically the tagged custom value with an argument applied to it). If the text is not valid for a value, it should return `nil`
/// - formatCustomValue: A function that, when passed a `Value` containing user-entered custom data, formats that data into a string, which should match what the user would have entered. This function can expect to only be called for the custom value, and should return `nil` in the event of its argument not being a valid custom value.
/// - customLabel: The caption to display in the custom row, next to the text field.
- /// - customAccessibilityIdentifier: The accessibility identifier to use for the custom row. If not provided, "customValue" will be used. The accessibility identifier for the text field will be this value with ".input" appended.
/// - customPrompt: The text to display, greyed, in the text field when it is empty. This also serves to set the width of the field, and should be right-padded with spaces as appropriate.
/// - customLegend: Optional text to display below the custom field, i.e., to explain sensible values
/// - customInputWidth: An optional minimum width (in pseudo-pixels) for the custom input field
@@ -159,12 +157,11 @@ struct SingleChoiceList<Value>: View where Value: Equatable {
title: String,
options: [Value],
value: Binding<Value>,
+ tableAccessibilityIdentifier: String? = nil,
itemDescription: ((Value) -> String)? = nil,
- itemAccessibilityIdentifier: ((Value) -> String)? = nil,
parseCustomValue: @escaping ((String) -> Value?),
formatCustomValue: @escaping ((Value) -> String?),
customLabel: String,
- customAccessibilityIdentifier: String = "customValue",
customPrompt: String,
customLegend: String? = nil,
customInputMinWidth: CGFloat? = nil,
@@ -175,7 +172,6 @@ struct SingleChoiceList<Value>: View where Value: Equatable {
title: title,
optionSpecs: options.map { .literal($0) } + [.custom(
label: customLabel,
- accessibilityIdentifier: customAccessibilityIdentifier,
prompt: customPrompt,
legend: customLegend,
minInputWidth: customInputMinWidth,
@@ -184,8 +180,8 @@ struct SingleChoiceList<Value>: View where Value: Equatable {
fromValue: formatCustomValue
)],
value: value,
+ tableAccessibilityIdentifier: tableAccessibilityIdentifier,
itemDescription: itemDescription,
- itemAccessibilityIdentifier: itemAccessibilityIdentifier,
customFieldMode: customFieldMode
)
}
@@ -220,14 +216,12 @@ struct SingleChoiceList<Value>: View where Value: Equatable {
customValueIsFocused = false
customValueInput = ""
}
- .accessibilityIdentifier(itemAccessibilityIdentifier(item))
}
// Construct the one row with a custom input field for a custom value
// swiftlint:disable function_body_length
private func customRow(
label: String,
- accessibilityIdentifier: String,
prompt: String,
inputWidth: CGFloat?,
maxInputLength: Int?,
@@ -308,7 +302,6 @@ struct SingleChoiceList<Value>: View where Value: Equatable {
customValueInput = valueText
}
}
- .accessibilityIdentifier(accessibilityIdentifier + ".input")
}
.onTapGesture {
if let v = toValue(customValueInput) {
@@ -317,7 +310,6 @@ struct SingleChoiceList<Value>: View where Value: Equatable {
customValueIsFocused = true
}
}
- .accessibilityIdentifier(accessibilityIdentifier)
}
// swiftlint:enable function_body_length
@@ -331,6 +323,10 @@ struct SingleChoiceList<Value>: View where Value: Equatable {
}
.padding(.horizontal, UIMetrics.SettingsCell.layoutMargins.leading)
.padding(.vertical, 4)
+ .background(
+ Color(.secondaryColor)
+ )
+ .foregroundColor(Color(UIColor.Cell.titleTextColor))
}
var body: some View {
@@ -341,34 +337,41 @@ struct SingleChoiceList<Value>: View where Value: Equatable {
}
.padding(EdgeInsets(UIMetrics.SettingsCell.layoutMargins))
.background(Color(UIColor.Cell.Background.normal))
- ForEach(options) { opt in
- switch opt.value {
- case let .literal(v):
- literalRow(v)
- case let .custom(
- label,
- accessibilityIdentifier,
- prompt,
- legend,
- inputWidth,
- maxInputLength,
- toValue,
- fromValue
- ):
- customRow(
- label: label,
- accessibilityIdentifier: accessibilityIdentifier,
- prompt: prompt,
- inputWidth: inputWidth,
- maxInputLength: maxInputLength,
- toValue: toValue,
- fromValue: fromValue
- )
- if let legend {
- subtitleRow(legend)
+ List {
+ Section {
+ ForEach(options) { opt in
+ switch opt.value {
+ case let .literal(v):
+ literalRow(v)
+ case let .custom(
+ label,
+ prompt,
+ legend,
+ inputWidth,
+ maxInputLength,
+ toValue,
+ fromValue
+ ):
+ customRow(
+ label: label,
+ prompt: prompt,
+ inputWidth: inputWidth,
+ maxInputLength: maxInputLength,
+ toValue: toValue,
+ fromValue: fromValue
+ )
+ if let legend {
+ subtitleRow(legend)
+ }
+ }
}
}
+ .listRowInsets(.init()) // remove insets
}
+ .accessibilityIdentifier(tableAccessibilityIdentifier)
+ .listStyle(.plain)
+ .listRowSpacing(UIMetrics.TableView.separatorHeight)
+ .environment(\.defaultMinListRowHeight, 0)
Spacer()
}
.padding(EdgeInsets(top: 24, leading: 0, bottom: 0, trailing: 0))
diff --git a/ios/MullvadVPNUITests/Pages/ShadowsocksObfuscationSettingsPage.swift b/ios/MullvadVPNUITests/Pages/ShadowsocksObfuscationSettingsPage.swift
new file mode 100644
index 0000000000..0334c9e49f
--- /dev/null
+++ b/ios/MullvadVPNUITests/Pages/ShadowsocksObfuscationSettingsPage.swift
@@ -0,0 +1,54 @@
+//
+// ShadowsocksObfuscationSettingsPage.swift
+// MullvadVPN
+//
+// Created by Andrew Bulhak on 2024-12-18.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+import XCTest
+
+class ShadowsocksObfuscationSettingsPage: Page {
+ @discardableResult override init(_ app: XCUIApplication) {
+ super.init(app)
+ }
+
+ private var table: XCUIElement {
+ app.collectionViews[AccessibilityIdentifier.wireGuardObfuscationShadowsocksTable]
+ }
+
+ private func portCell(_ index: Int) -> XCUIElement {
+ table.cells.element(boundBy: index)
+ }
+
+ private var customCell: XCUIElement {
+ // assumption: the last cell is the legend
+ table.cells.allElementsBoundByIndex.dropLast().last!
+ }
+
+ private var customTextField: XCUIElement {
+ customCell.textFields.firstMatch
+ }
+
+ @discardableResult func tapPortCell(_ index: Int) -> Self {
+ portCell(index).tap()
+ return self
+ }
+
+ @discardableResult func tapCustomCell() -> Self {
+ customCell.tap()
+ return self
+ }
+
+ @discardableResult func typeTextIntoCustomField(_ text: String) -> Self {
+ customTextField.typeText(text)
+ return self
+ }
+
+ @discardableResult func tapBackButton() -> Self {
+ // Workaround for setting accessibility identifier on navigation bar button being non-trivial
+ app.navigationBars.buttons.element(boundBy: 0).tap()
+ return self
+ }
+}
diff --git a/ios/MullvadVPNUITests/Pages/UDPOverTCPObfuscationSettingsPage.swift b/ios/MullvadVPNUITests/Pages/UDPOverTCPObfuscationSettingsPage.swift
new file mode 100644
index 0000000000..c133ce776a
--- /dev/null
+++ b/ios/MullvadVPNUITests/Pages/UDPOverTCPObfuscationSettingsPage.swift
@@ -0,0 +1,35 @@
+//
+// UDPOverTCPObfuscationSettingsPage.swift
+// MullvadVPN
+//
+// Created by Andrew Bulhak on 2024-12-12.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+import XCTest
+
+class UDPOverTCPObfuscationSettingsPage: Page {
+ @discardableResult override init(_ app: XCUIApplication) {
+ super.init(app)
+ }
+
+ private var table: XCUIElement {
+ app.collectionViews[AccessibilityIdentifier.wireGuardObfuscationUdpOverTcpTable]
+ }
+
+ private func portCell(_ index: Int) -> XCUIElement {
+ table.cells.element(boundBy: index)
+ }
+
+ @discardableResult func tapPortCell(_ index: Int) -> Self {
+ portCell(index).tap()
+ return self
+ }
+
+ @discardableResult func tapBackButton() -> Self {
+ // Workaround for setting accessibility identifier on navigation bar button being non-trivial
+ app.navigationBars.buttons.element(boundBy: 0).tap()
+ return self
+ }
+}
diff --git a/ios/MullvadVPNUITests/Pages/VPNSettingsPage.swift b/ios/MullvadVPNUITests/Pages/VPNSettingsPage.swift
index 33a8023ca6..4469607168 100644
--- a/ios/MullvadVPNUITests/Pages/VPNSettingsPage.swift
+++ b/ios/MullvadVPNUITests/Pages/VPNSettingsPage.swift
@@ -19,7 +19,7 @@ class VPNSettingsPage: Page {
_ subButtonAccessibilityIdentifier: AccessibilityIdentifier
) -> XCUIElement {
let tableView = app.tables[AccessibilityIdentifier.vpnSettingsTableView]
- let matchingCells = tableView.otherElements[cellAccessiblityIdentifier.asString]
+ let matchingCells = tableView.cells[cellAccessiblityIdentifier]
let expandButton = matchingCells.buttons[subButtonAccessibilityIdentifier]
let lastCell = tableView.cells.allElementsBoundByIndex.last!
tableView.scrollDownToElement(element: lastCell)
@@ -27,7 +27,12 @@ class VPNSettingsPage: Page {
}
private func cellExpandButton(_ cellAccessiblityIdentifier: AccessibilityIdentifier) -> XCUIElement {
- return cellSubButton(cellAccessiblityIdentifier, .expandButton)
+ let tableView = app.tables[AccessibilityIdentifier.vpnSettingsTableView]
+ let matchingCells = tableView.otherElements[cellAccessiblityIdentifier]
+ let expandButton = matchingCells.buttons[.expandButton]
+ let lastCell = tableView.cells.allElementsBoundByIndex.last!
+ tableView.scrollDownToElement(element: lastCell)
+ return expandButton
}
private func cellPortSelectorButton(_ cellAccessiblityIdentifier: AccessibilityIdentifier) -> XCUIElement {
diff --git a/ios/MullvadVPNUITests/SettingsMigrationTests.swift b/ios/MullvadVPNUITests/SettingsMigrationTests.swift
index 581bba946d..0d4281b682 100644
--- a/ios/MullvadVPNUITests/SettingsMigrationTests.swift
+++ b/ios/MullvadVPNUITests/SettingsMigrationTests.swift
@@ -132,12 +132,22 @@ class SettingsMigrationTests: BaseUITestCase {
.tapCustomWireGuardPortTextField()
.enterText(wireGuardPort)
.dismissKeyboard()
- .tapWireGuardObfuscationExpandButton()
- .tapWireGuardObfuscationUdpOverTcpCell()
- .tapUDPOverTCPPortExpandButton()
- .tapUDPOverTCPPort80Cell()
.tapQuantumResistantTunnelExpandButton()
.tapQuantumResistantTunnelOnCell()
+ .tapWireGuardObfuscationExpandButton()
+ .tapUDPOverTCPPortSelectorButton()
+
+ UDPOverTCPObfuscationSettingsPage(app)
+ .tapPortCell(2)
+ .tapPortCell(1)
+ .tapBackButton()
+ VPNSettingsPage(app)
+ .tapShadowsocksPortSelectorButton()
+ ShadowsocksObfuscationSettingsPage(app)
+ .tapPortCell(0)
+ .tapCustomCell()
+ .enterText("1234")
+ .tapBackButton()
}
func testVerifySettingsStillChanged() {