APIClient (77 -> 125 tests, coverage 92.22%): POST /auth probe with the four distinct outcomes from the frozen contract, Cookie/Accept landed at the same single header choke point that already enforces Origin-iff-G, plus the whole project-ops surface the server has had since late July and iOS consumed none of: /projects/log, /projects/pr, /projects/worktree/state, git stage/commit/push/ fetch, worktree create/remove/prune, GET /sessions, follow-up queue. HostRegistry (30 -> 73 tests, 88.12% -> 92.49%): per-host token in the Keychain under the existing SecItemShim conventions (device-only, never synchronizable), charset/length validated at the boundary, old token-less records still decode. SessionCore (93 -> 108 tests, 96.74%): the WS upgrade carries the cookie from the same point that writes Origin, and a 401 handshake is a terminal .unauthorized -- never entering the backoff loop, since retrying one wrong shared token is a brute-force generator against the server's 10/min limiter.
53 lines
2.1 KiB
Swift
53 lines
2.1 KiB
Swift
import Foundation
|
|
import WireProtocol
|
|
import HostRegistry
|
|
|
|
/// On macOS `Foundation.Host` (NSHost) shadows the package type in test
|
|
/// files that import Foundation — pin resolution for the whole test target.
|
|
typealias Host = HostRegistry.Host
|
|
|
|
/// Shared fixtures for HostRegistryTests. Pure helpers only — no state.
|
|
enum Fixtures {
|
|
/// Builds a valid Host; traps loudly if the fixture URL is malformed
|
|
/// (a broken fixture must fail the suite, not silently skip assertions).
|
|
static func makeHost(
|
|
name: String = "mac-studio",
|
|
urlString: String = "http://192.168.1.5:3000",
|
|
id: UUID = UUID()
|
|
) -> Host {
|
|
guard let url = URL(string: urlString), let endpoint = HostEndpoint(baseURL: url) else {
|
|
fatalError("test fixture URL invalid: \(urlString)")
|
|
}
|
|
return Host(id: id, name: name, endpoint: endpoint)
|
|
}
|
|
|
|
/// Unique UserDefaults suite name per test — isolates parallel tests.
|
|
static func makeSuiteName() -> String {
|
|
"HostRegistryTests." + UUID().uuidString
|
|
}
|
|
|
|
// MARK: - Access-token fixtures (coordination doc §1.1)
|
|
|
|
/// 22 chars exercising EVERY class of the frozen charset
|
|
/// `[A-Za-z0-9._~+/=-]` (upper/lower/digit/`.`/`_`/`~`/`+`/`/`/`=`/`-`),
|
|
/// comfortably above the 16-char minimum. Test-only value — not a secret.
|
|
static let validTokenString = "A9z._~+/=-Abcdef012345"
|
|
|
|
/// A second, distinct valid token (for "replaced/other host" assertions).
|
|
static let otherValidTokenString = "Zy8-=/+~_.9876543210fedcba"
|
|
|
|
/// Builds a valid token; traps loudly if a fixture string is malformed
|
|
/// (a broken fixture must fail the suite, not silently skip assertions).
|
|
static func makeToken(_ raw: String = Fixtures.validTokenString) -> AccessToken {
|
|
guard let token = AccessToken(rawValue: raw) else {
|
|
fatalError("test fixture token invalid: length \(raw.count)")
|
|
}
|
|
return token
|
|
}
|
|
|
|
/// A repeated-character token of an exact length (length-boundary tests).
|
|
static func tokenString(length: Int) -> String {
|
|
String(repeating: "a", count: length)
|
|
}
|
|
}
|