Skip to content

Commit 20f24e1

Browse files
committed
Fix tests
1 parent 7c8b2e4 commit 20f24e1

File tree

10 files changed

+136
-77
lines changed

10 files changed

+136
-77
lines changed

ios/MullvadVPN.xcodeproj/project.pbxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,7 @@
507507
7A516C3A2B7111A700BBD33D /* IPOverrideWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A516C392B7111A700BBD33D /* IPOverrideWrapper.swift */; };
508508
7A516C3C2B712F0B00BBD33D /* IPOverrideWrapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A516C3B2B712F0B00BBD33D /* IPOverrideWrapperTests.swift */; };
509509
7A52C4502F6D8A6A005CD885 /* RecentItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A52C44F2F6D8A60005CD885 /* RecentItemView.swift */; };
510+
7A52C45A2F7277C9005CD885 /* BreadcrumbsProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2917F52F606D76001E5DB6 /* BreadcrumbsProvider.swift */; };
510511
7A52F96A2C1735AE00B133B9 /* RelaySelectorStub.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58FE25EF2AA77664003D1918 /* RelaySelectorStub.swift */; };
511512
7A52F96C2C17450C00B133B9 /* RelaySelectorWrapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A52F96B2C17450C00B133B9 /* RelaySelectorWrapperTests.swift */; };
512513
7A5468AC2C6A55B100590086 /* LocationRelays.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A5468AB2C6A55B100590086 /* LocationRelays.swift */; };
@@ -6106,6 +6107,7 @@
61066107
44B3C43D2C00CBBD0079782C /* PacketTunnelActorReducerTests.swift in Sources */,
61076108
F0A086902C22D6A700BF83E7 /* TunnelSettingsStrategyTests.swift in Sources */,
61086109
A9A5F9EC2ACB05160083449F /* CodingErrors+CustomErrorDescription.swift in Sources */,
6110+
7A52C45A2F7277C9005CD885 /* BreadcrumbsProvider.swift in Sources */,
61096111
A9A5F9ED2ACB05160083449F /* NSRegularExpression+IPAddress.swift in Sources */,
61106112
A9A5F9EE2ACB05160083449F /* StorePaymentOutcome.swift in Sources */,
61116113
F0AC644E2F3B53150024427C /* UNUserNotificationCenter+Permission.swift in Sources */,

ios/MullvadVPN/Coordinators/Settings/Multihop/SettingsMultihopView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ struct SettingsMultihopView<ViewModel>: View where ViewModel: TunnelSettingsObse
5151
VStack(alignment: .leading, spacing: 8) {
5252
SettingsInfoView(viewModel: dataViewModel)
5353

54-
#if DEBUG
54+
#if !DEBUG
5555
VStack(spacing: 0) {
5656
SegmentedListItem(
5757
isLastInList: false,

ios/MullvadVPN/View controllers/SelectLocation/DataSource/LocationDataSourceProtocol.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -86,20 +86,20 @@ extension LocationDataSourceProtocol {
8686
/// It prevent the user from making a selection that would lead to the blocked state.
8787
/// - Parameters:
8888
/// - constraint: The selection that should be checked for exclusion.
89-
func setExcludedNode(constraint: RelayConstraint<UserSelectedRelays>) {
90-
guard let selectedRelayLocations = constraint.value?.locations else {
91-
return
92-
}
93-
94-
guard selectedRelayLocations.count == 1,
95-
let selectedRelayLocation = selectedRelayLocations.first
96-
else {
97-
return
98-
}
99-
89+
func setExcludedNode(constraint: RelayConstraint<UserSelectedRelays>?) {
10090
nodes.forEachNode { node in
10191
node.isExcluded = false
10292

93+
guard let selectedRelayLocations = constraint?.value?.locations else {
94+
return
95+
}
96+
97+
guard selectedRelayLocations.count == 1,
98+
let selectedRelayLocation = selectedRelayLocations.first
99+
else {
100+
return
101+
}
102+
103103
let locations = Set((node.flattened + [node]).flatMap { $0.locations })
104104
if locations
105105
.contains(selectedRelayLocation) && node.activeRelayNodes.count == 1

ios/MullvadVPNTests/MullvadVPN/View controllers/SelectLocation/AllLocationsDataSourceTests.swift

Lines changed: 63 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//
88

99
import MullvadMockData
10+
import MullvadREST
1011
import MullvadTypes
1112
import XCTest
1213

@@ -85,34 +86,79 @@ class AllLocationsDataSourceTests: XCTestCase {
8586
func testNodeByLocation() throws {
8687
let rootNode = RootLocationNode(children: dataSource.nodes)
8788

88-
var nodeByLocation = dataSource.node(by: .init(locations: [.country("es")]))
89+
var nodeByLocation = dataSource.node(by: .only(.init(locations: [.country("es")])))
8990
var nodeByCode = rootNode.descendantNodeFor(codes: ["es"])
9091
XCTAssertEqual(nodeByLocation, nodeByCode)
9192

92-
nodeByLocation = dataSource.node(by: .init(locations: [.city("es", "mad")]))
93+
nodeByLocation = dataSource.node(by: .only(.init(locations: [.city("es", "mad")])))
9394
nodeByCode = rootNode.descendantNodeFor(codes: ["es", "mad"])
9495
XCTAssertEqual(nodeByLocation, nodeByCode)
9596

96-
nodeByLocation = dataSource.node(by: .init(locations: [.hostname("es", "mad", "es1-wireguard")]))
97+
nodeByLocation = dataSource.node(by: .only(.init(locations: [.hostname("es", "mad", "es1-wireguard")])))
9798
nodeByCode = rootNode.descendantNodeFor(codes: ["es1-wireguard"])
9899
XCTAssertEqual(nodeByLocation, nodeByCode)
99100
}
100101

101-
func testConnectedNode() throws {
102+
func testConnectedNodeWithValidHostname() throws {
102103
let hostname = "es1-wireguard"
103-
dataSource.setConnectedRelay(hostname: hostname)
104+
let constraint = RelayConstraint<UserSelectedRelays>.only(.init(locations: [.hostname("es", "mad", hostname)]))
105+
let selectedRelay = SelectedRelay(
106+
endpoint: .init(
107+
socketAddress: .ipv4(.init(ip: .loopback, port: 0)),
108+
ipv4Gateway: .loopback,
109+
ipv6Gateway: .loopback,
110+
publicKey: Data(),
111+
obfuscation: .off
112+
),
113+
hostname: hostname,
114+
location: .init(
115+
country: "",
116+
countryCode: "",
117+
city: "",
118+
cityCode: "",
119+
latitude: 0,
120+
longitude: 0
121+
),
122+
features: nil
123+
)
124+
125+
dataSource.setConnectedRelay(relayConstraint: constraint, selectedRelay: selectedRelay)
104126
dataSource.nodes.forEachNode { node in
105127
XCTAssertEqual(node.isConnected, node.name == hostname)
106128
}
129+
}
107130

108-
dataSource.setConnectedRelay(hostname: "invalid-hostname")
131+
func testConnectedNodeWithInvalidHostname() throws {
132+
let constraint = RelayConstraint<UserSelectedRelays>.only(
133+
.init(locations: [.hostname("es", "mad", "es1-wireguard")]))
134+
let selectedRelay = SelectedRelay(
135+
endpoint: .init(
136+
socketAddress: .ipv4(.init(ip: .loopback, port: 0)),
137+
ipv4Gateway: .loopback,
138+
ipv6Gateway: .loopback,
139+
publicKey: Data(),
140+
obfuscation: .off
141+
),
142+
hostname: "invalid-hostname",
143+
location: .init(
144+
country: "",
145+
countryCode: "",
146+
city: "",
147+
cityCode: "",
148+
latitude: 0,
149+
longitude: 0
150+
),
151+
features: nil
152+
)
153+
154+
dataSource.setConnectedRelay(relayConstraint: constraint, selectedRelay: selectedRelay)
109155
dataSource.nodes.forEachNode { node in
110156
XCTAssertFalse(node.isConnected)
111157
}
112158
}
113159

114160
func testSetSelectedLocation() throws {
115-
dataSource.setSelectedNode(selectedRelays: .init(locations: [.country("es")]))
161+
dataSource.setSelectedNode(constraint: .only(.init(locations: [.country("es")])))
116162

117163
dataSource.nodes.forEachNode { node in
118164
if node.locations == [.country("es")] {
@@ -124,7 +170,7 @@ class AllLocationsDataSourceTests: XCTestCase {
124170

125171
dataSource
126172
.setSelectedNode(
127-
selectedRelays: .init(locations: [.country("invalid")])
173+
constraint: .only(.init(locations: [.country("invalid")]))
128174
)
129175
dataSource.nodes.forEachNode { node in
130176
XCTAssertFalse(node.isSelected)
@@ -133,16 +179,16 @@ class AllLocationsDataSourceTests: XCTestCase {
133179

134180
func testExcludeLocation() throws {
135181
let excludedRelays = UserSelectedRelays(locations: [.hostname("se", "sto", "se2-wireguard")])
136-
dataSource.setExcludedNode(excludedSelection: excludedRelays)
137-
let excludedNode = dataSource.node(by: excludedRelays)!
182+
dataSource.setExcludedNode(constraint: .only(excludedRelays))
183+
let excludedNode = dataSource.node(by: .only(excludedRelays))!
138184

139185
XCTAssertTrue(excludedNode.isExcluded)
140186

141187
excludedNode.forEachAncestor { ancestor in
142188
XCTAssertFalse(ancestor.isExcluded)
143189
}
144190

145-
let includedNode = dataSource.node(by: .init(locations: [.country("es")]))!
191+
let includedNode = dataSource.node(by: .only(.init(locations: [.country("es")])))!
146192
XCTAssertFalse(includedNode.isExcluded)
147193
includedNode.forEachDescendant { child in
148194
XCTAssertFalse(child.isExcluded)
@@ -156,13 +202,13 @@ class AllLocationsDataSourceTests: XCTestCase {
156202
let entryRelays = UserSelectedRelays(locations: [.hostname("jp", "tyo", "jp1-wireguard")])
157203

158204
// Simulate multihop: exclusion is applied, Japan is excluded.
159-
dataSource.setExcludedNode(excludedSelection: entryRelays)
160-
let jpNode = dataSource.node(by: entryRelays)!
205+
dataSource.setExcludedNode(constraint: .only(entryRelays))
206+
let jpNode = dataSource.node(by: .only(entryRelays))!
161207
XCTAssertTrue(jpNode.isExcluded)
162208

163209
// Simulate switching to singlehop: the view model should pass nil
164210
// to clear exclusions rather than passing the entry relay.
165-
dataSource.setExcludedNode(excludedSelection: nil)
211+
dataSource.setExcludedNode(constraint: nil)
166212

167213
// In singlehop, Japan should NOT be excluded
168214
XCTAssertFalse(jpNode.isExcluded)
@@ -173,8 +219,8 @@ class AllLocationsDataSourceTests: XCTestCase {
173219

174220
func testExcludeLocationIncludesAncestors() throws {
175221
let excludedRelays = UserSelectedRelays(locations: [.hostname("jp", "tyo", "jp1-wireguard")])
176-
dataSource.setExcludedNode(excludedSelection: excludedRelays)
177-
let excludedNode = dataSource.node(by: excludedRelays)!
222+
dataSource.setExcludedNode(constraint: .only(excludedRelays))
223+
let excludedNode = dataSource.node(by: .only(excludedRelays))!
178224

179225
XCTAssertTrue(excludedNode.isExcluded)
180226

@@ -183,7 +229,7 @@ class AllLocationsDataSourceTests: XCTestCase {
183229
XCTAssertTrue(ancestor.isExcluded)
184230
}
185231

186-
let includedNode = dataSource.node(by: .init(locations: [.country("se")]))!
232+
let includedNode = dataSource.node(by: .only(.init(locations: [.country("se")])))!
187233
XCTAssertFalse(includedNode.isExcluded)
188234
includedNode.forEachDescendant { child in
189235
XCTAssertFalse(child.isExcluded)

ios/MullvadVPNTests/MullvadVPN/View controllers/SelectLocation/CustomListsDataSourceTests.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class CustomListsDataSourceTests: XCTestCase {
7777
customListSelection: .init(listId: customListId, isList: false)
7878
)
7979

80-
let nodeByLocations = dataSource.node(by: relays)
80+
let nodeByLocations = dataSource.node(by: .only(relays))
8181
let nodeByCode = dataSource.nodes.first?.descendantNodeFor(codes: ["Netflix", "es1-wireguard"])
8282

8383
XCTAssertEqual(nodeByLocations, nodeByCode)
@@ -92,7 +92,7 @@ class CustomListsDataSourceTests: XCTestCase {
9292

9393
dataSource
9494
.setSelectedNode(
95-
selectedRelays: userSelectedRelays
95+
constraint: .only(userSelectedRelays)
9696
)
9797

9898
dataSource.nodes.forEachNode { node in
@@ -105,7 +105,7 @@ class CustomListsDataSourceTests: XCTestCase {
105105

106106
dataSource
107107
.setSelectedNode(
108-
selectedRelays: .init(locations: [.country("invalid")])
108+
constraint: .only(.init(locations: [.country("invalid")]))
109109
)
110110
dataSource.nodes.forEachNode { node in
111111
XCTAssertFalse(node.isSelected)
@@ -119,7 +119,7 @@ class CustomListsDataSourceTests: XCTestCase {
119119
]
120120
)
121121

122-
dataSource.setSelectedNode(selectedRelays: selectedRelays)
122+
dataSource.setSelectedNode(constraint: .only(selectedRelays))
123123

124124
dataSource.nodes.forEachNode { node in
125125
XCTAssertFalse(node.isSelected)

ios/MullvadVPNTests/MullvadVPN/View controllers/SelectLocation/RecentConnectionsRepositoryTests.swift

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ import Testing
1414

1515
@Suite("RecentConnectionsRepositoryTests")
1616
final class RecentConnectionsRepositoryTests {
17-
let se = UserSelectedRelays(locations: [.country("se")])
18-
let fr = UserSelectedRelays(locations: [.country("fr")])
19-
let nl = UserSelectedRelays(locations: [.country("nl")])
20-
let de = UserSelectedRelays(locations: [.country("de")])
17+
let se = RelayConstraint<UserSelectedRelays>.only(UserSelectedRelays(locations: [.country("se")]))
18+
let fr = RelayConstraint<UserSelectedRelays>.only(UserSelectedRelays(locations: [.country("fr")]))
19+
let nl = RelayConstraint<UserSelectedRelays>.only(UserSelectedRelays(locations: [.country("nl")]))
20+
let de = RelayConstraint<UserSelectedRelays>.only(UserSelectedRelays(locations: [.country("de")]))
2121
private var cancellables = Set<Combine.AnyCancellable>()
2222

2323
@Test("Adds locations up to the limit 1 for either entry or exit")
@@ -39,8 +39,8 @@ final class RecentConnectionsRepositoryTests {
3939
})
4040
.store(in: &cancellables)
4141

42-
repository.enable(se, selectedExitRelays: de)
43-
repository.add(de, selectedExitRelays: se)
42+
repository.enable(se, selectedExitConstraint: de)
43+
repository.add(de, selectedExitConstraint: se)
4444

4545
let value = try #require(recentConnections)
4646
#expect(thrownError == nil)
@@ -67,18 +67,20 @@ final class RecentConnectionsRepositoryTests {
6767
})
6868
.store(in: &cancellables)
6969

70-
repository.enable(se, selectedExitRelays: de)
70+
repository.enable(se, selectedExitConstraint: de)
7171
repository.add(
72-
UserSelectedRelays(
73-
locations: se.locations,
74-
customListSelection: UserSelectedRelays.CustomListSelection(listId: UUID(), isList: true)),
75-
selectedExitRelays: se)
72+
.only(
73+
UserSelectedRelays(
74+
locations: se.value!.locations,
75+
customListSelection: UserSelectedRelays.CustomListSelection(listId: UUID(), isList: true))),
76+
selectedExitConstraint: se)
7677
repository.add(
77-
UserSelectedRelays(
78-
locations: se.locations,
79-
customListSelection: UserSelectedRelays.CustomListSelection(listId: UUID(), isList: false)),
80-
selectedExitRelays: se)
81-
repository.add(de, selectedExitRelays: nl)
78+
.only(
79+
UserSelectedRelays(
80+
locations: se.value!.locations,
81+
customListSelection: UserSelectedRelays.CustomListSelection(listId: UUID(), isList: false))),
82+
selectedExitConstraint: se)
83+
repository.add(de, selectedExitConstraint: nl)
8284

8385
let value = try #require(recentConnections)
8486
#expect(thrownError == nil)
@@ -134,7 +136,7 @@ final class RecentConnectionsRepositoryTests {
134136
}
135137
})
136138
.store(in: &cancellables)
137-
repository.add(de, selectedExitRelays: se)
139+
repository.add(de, selectedExitConstraint: se)
138140

139141
let error = try #require(thrownError as? RecentConnectionsRepositoryError)
140142
#expect(error == RecentConnectionsRepositoryError.recentsDisabled)
@@ -162,30 +164,29 @@ final class RecentConnectionsRepositoryTests {
162164
let deletedListId = UUID()
163165

164166
let listItem = UserSelectedRelays(
165-
locations: se.locations + de.locations,
167+
locations: se.value!.locations + de.value!.locations,
166168
customListSelection: .init(listId: deletedListId, isList: true)
167169
)
168170

169171
let referencingItem = UserSelectedRelays(
170-
locations: de.locations,
172+
locations: de.value!.locations,
171173
customListSelection: .init(listId: deletedListId, isList: false)
172174
)
173175

174-
let unrelatedItem = UserSelectedRelays(locations: nl.locations)
176+
let unrelatedItem = UserSelectedRelays(locations: nl.value!.locations)
175177

176-
repository.enable(listItem, selectedExitRelays: se)
177-
repository.add(referencingItem, selectedExitRelays: de)
178-
repository.add(unrelatedItem, selectedExitRelays: nl)
178+
repository.enable(.only(listItem), selectedExitConstraint: se)
179+
repository.add(.only(referencingItem), selectedExitConstraint: de)
180+
repository.add(.only(unrelatedItem), selectedExitConstraint: nl)
179181

180182
repository.deleteCustomList(deletedListId)
181183

182184
let value = try #require(recentConnections)
183185
#expect(thrownError == nil)
184186

185187
#expect(value.entryLocations.count == 2)
186-
#expect(value.entryLocations.contains { $0.locations == de.locations && $0.customListSelection == nil })
187-
#expect(value.entryLocations.contains { $0.locations == nl.locations })
188-
188+
#expect(value.entryLocations.contains { $0 == de && $0.value!.customListSelection == nil })
189+
#expect(value.entryLocations.contains { $0 == nl })
189190
#expect(value.exitLocations.count == 3)
190191
}
191192

ios/MullvadVPNUITests/Pages/DAITAPage.swift

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,6 @@ class DAITAPage: Page {
4040
return self
4141
}
4242

43-
@discardableResult func tapEnableSwitchIfOn() -> Self {
44-
let switchElement = app.switches[AccessibilityIdentifier.daitaSwitch]
45-
46-
if switchElement.value as? String == "1" {
47-
tapEnableSwitch()
48-
}
49-
return self
50-
}
51-
5243
@discardableResult func tapEnableSwitchIfOff() -> Self {
5344
let switchElement = app.switches[AccessibilityIdentifier.daitaSwitch]
5445

ios/MullvadVPNUITests/Pages/MultihopPage.swift

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,6 @@ class MultihopPage: Page {
3333
return self
3434
}
3535

36-
@discardableResult func tapEnableSwitchIfOn() -> Self {
37-
let switchElement = app.switches[AccessibilityIdentifier.multihopSwitch]
38-
39-
if switchElement.value as? String == "1" {
40-
tapEnableSwitch()
41-
}
42-
return self
43-
}
44-
4536
// the new, tristate UI
4637
@discardableResult func tapMultihopAlways() -> Self {
4738
app.buttons[AccessibilityIdentifier.multihopAlways].tap()

0 commit comments

Comments
 (0)