summaryrefslogtreecommitdiff
path: root/HutchTests
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-04-23 17:39:13 -0500
committerChristian Cleberg <[email protected]>2026-04-23 17:39:13 -0500
commit66601a8091a73f3e31f4fb534c38b3eca4756e93 (patch)
treef85cd883e63177d25dfe5993a4d545efa4812923 /HutchTests
parent380fb866d090c5f13b2ad3f88f1fe23c4ade4801 (diff)
downloadhutch-66601a8091a73f3e31f4fb534c38b3eca4756e93.tar.gz
hutch-66601a8091a73f3e31f4fb534c38b3eca4756e93.tar.bz2
hutch-66601a8091a73f3e31f4fb534c38b3eca4756e93.zip
fix: profile loading error and user-timeline prefs updatev3.2.1
Diffstat (limited to 'HutchTests')
-rw-r--r--HutchTests/BuildListViewModelTests.swift58
-rw-r--r--HutchTests/SettingsViewModelTests.swift55
2 files changed, 108 insertions, 5 deletions
diff --git a/HutchTests/BuildListViewModelTests.swift b/HutchTests/BuildListViewModelTests.swift
index fccd7cf..aa2e46b 100644
--- a/HutchTests/BuildListViewModelTests.swift
+++ b/HutchTests/BuildListViewModelTests.swift
@@ -49,22 +49,70 @@ struct BuildListViewModelTests {
makeJob(id: 4, status: .cancelled, tags: [])
]
- let attention = BuildListViewModel.filterJobs(jobs, filter: .attention)
- let active = BuildListViewModel.filterJobs(jobs, filter: .active)
+ let attention = BuildListViewModel.filterJobs(
+ jobs,
+ filter: .attention,
+ lookbackDays: BuildListViewModel.defaultLookbackDays
+ )
+ let active = BuildListViewModel.filterJobs(
+ jobs,
+ filter: .active,
+ lookbackDays: BuildListViewModel.defaultLookbackDays
+ )
#expect(attention.map(\.id) == [2, 3])
#expect(active.map(\.id) == [3])
}
+ @Test
+ func buildFilterRestrictsJobsToSelectedLookbackWindow() {
+ let now = Date(timeIntervalSince1970: 60 * 60 * 24 * 20)
+ let jobs = [
+ makeJob(
+ id: 1,
+ status: .failed,
+ tags: [],
+ updated: now.addingTimeInterval(-(60 * 60 * 24))
+ ),
+ makeJob(
+ id: 2,
+ status: .running,
+ tags: [],
+ updated: now.addingTimeInterval(-(60 * 60 * 24 * 8))
+ ),
+ makeJob(
+ id: 3,
+ status: .success,
+ tags: [],
+ updated: now.addingTimeInterval(-(60 * 60 * 24 * 2))
+ ),
+ ]
+
+ let filtered = BuildListViewModel.filterJobs(
+ jobs,
+ filter: .all,
+ lookbackDays: 3,
+ now: now,
+ calendar: Calendar(identifier: .gregorian)
+ )
+
+ #expect(filtered.map(\.id) == [1, 3])
+ }
+
private func filterJobs(_ jobs: [JobSummary], query: String) -> [JobSummary] {
BuildListViewModel.searchJobs(jobs, matching: query)
}
- private func makeJob(id: Int, status: JobStatus = .success, tags: [String]) -> JobSummary {
+ private func makeJob(
+ id: Int,
+ status: JobStatus = .success,
+ tags: [String],
+ updated: Date = Date()
+ ) -> JobSummary {
JobSummary(
id: id,
- created: Date(),
- updated: Date(),
+ created: updated,
+ updated: updated,
status: status,
note: nil,
tags: tags,
diff --git a/HutchTests/SettingsViewModelTests.swift b/HutchTests/SettingsViewModelTests.swift
index fc18162..9e4b912 100644
--- a/HutchTests/SettingsViewModelTests.swift
+++ b/HutchTests/SettingsViewModelTests.swift
@@ -2,6 +2,37 @@ import Foundation
import Testing
@testable import Hutch
+private final class SettingsViewModelCapturingURLProtocol: URLProtocol, @unchecked Sendable {
+ nonisolated(unsafe) static var capturedRequests: [URLRequest] = []
+
+ override class func canInit(with _: URLRequest) -> Bool { true }
+ override class func canonicalRequest(for request: URLRequest) -> URLRequest { request }
+
+ override func startLoading() {
+ Self.capturedRequests.append(request)
+
+ let response = HTTPURLResponse(
+ url: request.url!,
+ statusCode: 401,
+ httpVersion: nil,
+ headerFields: nil
+ )!
+ client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed)
+ client?.urlProtocol(self, didLoad: Data())
+ client?.urlProtocolDidFinishLoading(self)
+ }
+
+ override func stopLoading() {
+ // No cleanup is needed because the stub responds immediately in `startLoading()`.
+ }
+
+ static func makeSession() -> URLSession {
+ let config = URLSessionConfiguration.ephemeral
+ config.protocolClasses = [Self.self]
+ return URLSession(configuration: config)
+ }
+}
+
private struct DeletePGPKeyEnvelope: Decodable {
let deletePGPKey: DeleteResultPayload?
}
@@ -10,6 +41,7 @@ private struct DeleteResultPayload: Decodable {
let id: Int?
}
+@Suite(.serialized)
struct SettingsViewModelTests {
@Test
@@ -36,4 +68,27 @@ struct SettingsViewModelTests {
#expect(decoded.data?.deletePGPKey == nil)
#expect(decoded.errors?.first?.message.contains("preferred PGP key") == true)
}
+
+ @Test
+ @MainActor
+ func loadProfileDoesNotRequestSSHKeyFingerprintField() async throws {
+ SettingsViewModelCapturingURLProtocol.capturedRequests = []
+
+ let client = SRHTClient(
+ session: SettingsViewModelCapturingURLProtocol.makeSession(),
+ token: "test-token"
+ )
+ let viewModel = SettingsViewModel(client: client)
+
+ await viewModel.loadProfile()
+
+ let request = try #require(SettingsViewModelCapturingURLProtocol.capturedRequests.first)
+ let body = try #require(request.httpBody)
+ let jsonObject = try #require(JSONSerialization.jsonObject(with: body) as? [String: Any])
+ let query = try #require(jsonObject["query"] as? String)
+
+ #expect(query.contains("sshKeys"))
+ #expect(!query.contains("results { id fingerprint comment created lastUsed }"))
+ #expect(!query.contains("fingerprint comment created lastUsed"))
+ }
}