Skip to content

Commit d08960a

Browse files
committed
test(iOS): update gateway tests for Keychain-backed storage
1 parent fea884f commit d08960a

File tree

2 files changed

+52
-27
lines changed

2 files changed

+52
-27
lines changed

apps/ios/Tests/GatewayConnectionControllerTests.swift

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,18 +71,37 @@ import UIKit
7171
}
7272

7373
@Test @MainActor func loadLastConnectionReadsSavedValues() {
74-
withUserDefaults([:]) {
75-
GatewaySettingsStore.saveLastGatewayConnectionManual(
76-
host: "gateway.example.com",
77-
port: 443,
78-
useTLS: true,
79-
stableID: "manual|gateway.example.com|443")
80-
let loaded = GatewaySettingsStore.loadLastGatewayConnection()
81-
#expect(loaded == .manual(host: "gateway.example.com", port: 443, useTLS: true, stableID: "manual|gateway.example.com|443"))
74+
let prior = KeychainStore.loadString(service: "ai.openclaw.gateway", account: "lastConnection")
75+
defer {
76+
if let prior {
77+
_ = KeychainStore.saveString(prior, service: "ai.openclaw.gateway", account: "lastConnection")
78+
} else {
79+
_ = KeychainStore.delete(service: "ai.openclaw.gateway", account: "lastConnection")
80+
}
8281
}
82+
_ = KeychainStore.delete(service: "ai.openclaw.gateway", account: "lastConnection")
83+
84+
GatewaySettingsStore.saveLastGatewayConnectionManual(
85+
host: "gateway.example.com",
86+
port: 443,
87+
useTLS: true,
88+
stableID: "manual|gateway.example.com|443")
89+
let loaded = GatewaySettingsStore.loadLastGatewayConnection()
90+
#expect(loaded == .manual(host: "gateway.example.com", port: 443, useTLS: true, stableID: "manual|gateway.example.com|443"))
8391
}
8492

8593
@Test @MainActor func loadLastConnectionReturnsNilForInvalidData() {
94+
let prior = KeychainStore.loadString(service: "ai.openclaw.gateway", account: "lastConnection")
95+
defer {
96+
if let prior {
97+
_ = KeychainStore.saveString(prior, service: "ai.openclaw.gateway", account: "lastConnection")
98+
} else {
99+
_ = KeychainStore.delete(service: "ai.openclaw.gateway", account: "lastConnection")
100+
}
101+
}
102+
_ = KeychainStore.delete(service: "ai.openclaw.gateway", account: "lastConnection")
103+
104+
// Plant legacy UserDefaults with invalid host/port to exercise migration + validation.
86105
withUserDefaults([
87106
"gateway.last.kind": "manual",
88107
"gateway.last.host": "",

apps/ios/Tests/GatewaySettingsStoreTests.swift

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ private let lastGatewayDefaultsKeys = [
2727
"gateway.last.tls",
2828
"gateway.last.stableID",
2929
]
30+
private let lastGatewayKeychainEntry = KeychainEntry(service: gatewayService, account: "lastConnection")
3031

3132
private func snapshotDefaults(_ keys: [String]) -> [String: Any?] {
3233
let defaults = UserDefaults.standard
@@ -84,9 +85,13 @@ private func withBootstrapSnapshots(_ body: () -> Void) {
8485
body()
8586
}
8687

87-
private func withLastGatewayDefaultsSnapshot(_ body: () -> Void) {
88-
let snapshot = snapshotDefaults(lastGatewayDefaultsKeys)
89-
defer { restoreDefaults(snapshot) }
88+
private func withLastGatewaySnapshot(_ body: () -> Void) {
89+
let defaultsSnapshot = snapshotDefaults(lastGatewayDefaultsKeys)
90+
let keychainSnapshot = snapshotKeychain([lastGatewayKeychainEntry])
91+
defer {
92+
restoreDefaults(defaultsSnapshot)
93+
restoreKeychain(keychainSnapshot)
94+
}
9095
body()
9196
}
9297

@@ -135,7 +140,7 @@ private func withLastGatewayDefaultsSnapshot(_ body: () -> Void) {
135140
}
136141

137142
@Test func lastGateway_manualRoundTrip() {
138-
withLastGatewayDefaultsSnapshot {
143+
withLastGatewaySnapshot {
139144
GatewaySettingsStore.saveLastGatewayConnectionManual(
140145
host: "example.com",
141146
port: 443,
@@ -147,28 +152,24 @@ private func withLastGatewayDefaultsSnapshot(_ body: () -> Void) {
147152
}
148153
}
149154

150-
@Test func lastGateway_discoveredDoesNotPersistResolvedHostPort() {
151-
withLastGatewayDefaultsSnapshot {
152-
// Simulate a prior manual record that included host/port.
153-
applyDefaults([
154-
"gateway.last.host": "10.0.0.99",
155-
"gateway.last.port": 18789,
156-
"gateway.last.tls": true,
157-
"gateway.last.stableID": "manual|10.0.0.99|18789",
158-
"gateway.last.kind": "manual",
159-
])
155+
@Test func lastGateway_discoveredOverwritesManual() {
156+
withLastGatewaySnapshot {
157+
GatewaySettingsStore.saveLastGatewayConnectionManual(
158+
host: "10.0.0.99",
159+
port: 18789,
160+
useTLS: true,
161+
stableID: "manual|10.0.0.99|18789")
160162

161163
GatewaySettingsStore.saveLastGatewayConnectionDiscovered(stableID: "gw|abc", useTLS: true)
162164

163-
let defaults = UserDefaults.standard
164-
#expect(defaults.object(forKey: "gateway.last.host") == nil)
165-
#expect(defaults.object(forKey: "gateway.last.port") == nil)
166165
#expect(GatewaySettingsStore.loadLastGatewayConnection() == .discovered(stableID: "gw|abc", useTLS: true))
167166
}
168167
}
169168

170-
@Test func lastGateway_backCompat_manualLoadsWhenKindMissing() {
171-
withLastGatewayDefaultsSnapshot {
169+
@Test func lastGateway_migratesFromUserDefaults() {
170+
withLastGatewaySnapshot {
171+
// Clear Keychain entry and plant legacy UserDefaults values.
172+
applyKeychain([lastGatewayKeychainEntry: nil])
172173
applyDefaults([
173174
"gateway.last.kind": nil,
174175
"gateway.last.host": "example.org",
@@ -179,6 +180,11 @@ private func withLastGatewayDefaultsSnapshot(_ body: () -> Void) {
179180

180181
let loaded = GatewaySettingsStore.loadLastGatewayConnection()
181182
#expect(loaded == .manual(host: "example.org", port: 18789, useTLS: false, stableID: "manual|example.org|18789"))
183+
184+
// Legacy keys should be cleaned up after migration.
185+
let defaults = UserDefaults.standard
186+
#expect(defaults.object(forKey: "gateway.last.stableID") == nil)
187+
#expect(defaults.object(forKey: "gateway.last.host") == nil)
182188
}
183189
}
184190

0 commit comments

Comments
 (0)