diff options
| author | Christian Cleberg <[email protected]> | 2026-07-15 19:19:43 -0500 |
|---|---|---|
| committer | Christian Cleberg <[email protected]> | 2026-07-15 19:19:43 -0500 |
| commit | 4346adc50f01be7f7322249d32745d119c757ff2 (patch) | |
| tree | b530424272118e56d1545de460f3cf2433d8ae89 /HutchTests | |
| parent | ed572a864debd7df840ea5873173be18ff27e809 (diff) | |
| download | hutch-4346adc50f01be7f7322249d32745d119c757ff2.tar.gz hutch-4346adc50f01be7f7322249d32745d119c757ff2.tar.bz2 hutch-4346adc50f01be7f7322249d32745d119c757ff2.zip | |
test: repair stale expectations and request-body capture
These tests drifted from the code and went unnoticed because CI never ran
them. All four are test-side errors; no app behavior is involved.
- TicketListViewModelTests asserted lowercase "resolved"/"fixed"/"reported"
against TicketStatus/TicketResolution rawValues, which are uppercase to
match the todo.sr.ht GraphQL enums.
- HomeViewModelTests expected failedBuilds in ascending id order. Ordering
moved to newest-first when sortBuildItemsForTriage landed in 5f6d545; the
filtering the test covers is unchanged.
- SettingsViewModelTests read request.httpBody inside a URLProtocol, where it
is always nil because URLSession moves the body onto httpBodyStream. The
stub now reads the body off the stream at capture time.
Diffstat (limited to 'HutchTests')
| -rw-r--r-- | HutchTests/HomeViewModelTests.swift | 2 | ||||
| -rw-r--r-- | HutchTests/SettingsViewModelTests.swift | 26 | ||||
| -rw-r--r-- | HutchTests/TicketListViewModelTests.swift | 6 |
3 files changed, 28 insertions, 6 deletions
diff --git a/HutchTests/HomeViewModelTests.swift b/HutchTests/HomeViewModelTests.swift index e4f6d9a..851b520 100644 --- a/HutchTests/HomeViewModelTests.swift +++ b/HutchTests/HomeViewModelTests.swift @@ -15,7 +15,7 @@ struct HomeViewModelTests { let failedBuilds = HomeViewModel.failedBuilds(from: jobs) - #expect(failedBuilds.map(\.job.id) == [2, 3]) + #expect(failedBuilds.map(\.job.id) == [3, 2]) } @Test diff --git a/HutchTests/SettingsViewModelTests.swift b/HutchTests/SettingsViewModelTests.swift index 9e4b912..906f33f 100644 --- a/HutchTests/SettingsViewModelTests.swift +++ b/HutchTests/SettingsViewModelTests.swift @@ -4,12 +4,14 @@ import Testing private final class SettingsViewModelCapturingURLProtocol: URLProtocol, @unchecked Sendable { nonisolated(unsafe) static var capturedRequests: [URLRequest] = [] + nonisolated(unsafe) static var capturedBodies: [Data] = [] override class func canInit(with _: URLRequest) -> Bool { true } override class func canonicalRequest(for request: URLRequest) -> URLRequest { request } override func startLoading() { Self.capturedRequests.append(request) + Self.capturedBodies.append(Self.readBody(from: request)) let response = HTTPURLResponse( url: request.url!, @@ -26,6 +28,26 @@ private final class SettingsViewModelCapturingURLProtocol: URLProtocol, @uncheck // No cleanup is needed because the stub responds immediately in `startLoading()`. } + /// `URLSession` moves `httpBody` onto `httpBodyStream` before handing a request + /// to a `URLProtocol`, so `request.httpBody` is always nil here and the body has + /// to be read back off the stream while it is still open. + private static func readBody(from request: URLRequest) -> Data { + if let body = request.httpBody { return body } + guard let stream = request.httpBodyStream else { return Data() } + + stream.open() + defer { stream.close() } + + var data = Data() + var buffer = [UInt8](repeating: 0, count: 4096) + while stream.hasBytesAvailable { + let read = stream.read(&buffer, maxLength: buffer.count) + guard read > 0 else { break } + data.append(buffer, count: read) + } + return data + } + static func makeSession() -> URLSession { let config = URLSessionConfiguration.ephemeral config.protocolClasses = [Self.self] @@ -73,6 +95,7 @@ struct SettingsViewModelTests { @MainActor func loadProfileDoesNotRequestSSHKeyFingerprintField() async throws { SettingsViewModelCapturingURLProtocol.capturedRequests = [] + SettingsViewModelCapturingURLProtocol.capturedBodies = [] let client = SRHTClient( session: SettingsViewModelCapturingURLProtocol.makeSession(), @@ -82,8 +105,7 @@ struct SettingsViewModelTests { await viewModel.loadProfile() - let request = try #require(SettingsViewModelCapturingURLProtocol.capturedRequests.first) - let body = try #require(request.httpBody) + let body = try #require(SettingsViewModelCapturingURLProtocol.capturedBodies.first) let jsonObject = try #require(JSONSerialization.jsonObject(with: body) as? [String: Any]) let query = try #require(jsonObject["query"] as? String) diff --git a/HutchTests/TicketListViewModelTests.swift b/HutchTests/TicketListViewModelTests.swift index 7fa5449..a203091 100644 --- a/HutchTests/TicketListViewModelTests.swift +++ b/HutchTests/TicketListViewModelTests.swift @@ -162,8 +162,8 @@ struct TicketListViewModelTests { "status": TicketStatus.resolved.rawValue, "resolution": TicketResolution.fixed.rawValue ] - #expect(input["status"] as? String == "resolved") - #expect(input["resolution"] as? String == "fixed") + #expect(input["status"] as? String == "RESOLVED") + #expect(input["resolution"] as? String == "FIXED") } @Test @@ -172,7 +172,7 @@ struct TicketListViewModelTests { let input: [String: any Sendable] = [ "status": TicketStatus.reported.rawValue ] - #expect(input["status"] as? String == "reported") + #expect(input["status"] as? String == "REPORTED") #expect(input["resolution"] == nil) } |
