krz/hutch
an ios client for sourcehut
clone: git clone https://gitbay.org/krz/hutch.git
v3.4.0: HutchTests/SettingsViewModelTests.swift · raw
1import Foundation
2import Testing
3@testable import Hutch
4
5private final class SettingsViewModelCapturingURLProtocol: URLProtocol, @unchecked Sendable {
6 nonisolated(unsafe) static var capturedRequests: [URLRequest] = []
7
8 override class func canInit(with _: URLRequest) -> Bool { true }
9 override class func canonicalRequest(for request: URLRequest) -> URLRequest { request }
10
11 override func startLoading() {
12 Self.capturedRequests.append(request)
13
14 let response = HTTPURLResponse(
15 url: request.url!,
16 statusCode: 401,
17 httpVersion: nil,
18 headerFields: nil
19 )!
20 client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed)
21 client?.urlProtocol(self, didLoad: Data())
22 client?.urlProtocolDidFinishLoading(self)
23 }
24
25 override func stopLoading() {
26 // No cleanup is needed because the stub responds immediately in `startLoading()`.
27 }
28
29 static func makeSession() -> URLSession {
30 let config = URLSessionConfiguration.ephemeral
31 config.protocolClasses = [Self.self]
32 return URLSession(configuration: config)
33 }
34}
35
36private struct DeletePGPKeyEnvelope: Decodable {
37 let deletePGPKey: DeleteResultPayload?
38}
39
40private struct DeleteResultPayload: Decodable {
41 let id: Int?
42}
43
44@Suite(.serialized)
45struct SettingsViewModelTests {
46
47 @Test
48 @MainActor
49 func deletePGPKeyResponseDecodesNullPayloadWithGraphQLErrors() throws {
50 let json = """
51 {
52 "errors": [
53 {
54 "message": "PGP key ID 13629 is set as the user's preferred PGP key - it must be unset before removing the key"
55 }
56 ],
57 "data": {
58 "deletePGPKey": null
59 }
60 }
61 """
62
63 let decoded = try JSONDecoder().decode(
64 GraphQLResponse<DeletePGPKeyEnvelope>.self,
65 from: Data(json.utf8)
66 )
67
68 #expect(decoded.data?.deletePGPKey == nil)
69 #expect(decoded.errors?.first?.message.contains("preferred PGP key") == true)
70 }
71
72 @Test
73 @MainActor
74 func loadProfileDoesNotRequestSSHKeyFingerprintField() async throws {
75 SettingsViewModelCapturingURLProtocol.capturedRequests = []
76
77 let client = SRHTClient(
78 session: SettingsViewModelCapturingURLProtocol.makeSession(),
79 token: "test-token"
80 )
81 let viewModel = SettingsViewModel(client: client)
82
83 await viewModel.loadProfile()
84
85 let request = try #require(SettingsViewModelCapturingURLProtocol.capturedRequests.first)
86 let body = try #require(request.httpBody)
87 let jsonObject = try #require(JSONSerialization.jsonObject(with: body) as? [String: Any])
88 let query = try #require(jsonObject["query"] as? String)
89
90 #expect(query.contains("sshKeys"))
91 #expect(!query.contains("results { id fingerprint comment created lastUsed }"))
92 #expect(!query.contains("fingerprint comment created lastUsed"))
93 }
94}