krz/hutch
an ios client for sourcehut
clone: git clone https://gitbay.org/krz/hutch.git
main: HutchTests/BuildListViewModelTests.swift · raw
1import Foundation
2import Testing
3@testable import Hutch
4
5@MainActor
6struct BuildListViewModelTests {
7
8 @Test
9 func filteredJobsReturnsAllWhenSearchTextIsEmpty() {
10 let jobs = [makeJob(id: 1, tags: ["ci"]), makeJob(id: 2, tags: [])]
11 let filtered = filterJobs(jobs, query: "")
12
13 #expect(filtered.count == 2)
14 }
15
16 @Test
17 func filteredJobsMatchesByTag() {
18 let jobs = [makeJob(id: 1, tags: ["ci", "deploy"]), makeJob(id: 2, tags: ["lint"])]
19 let filtered = filterJobs(jobs, query: "deploy")
20
21 #expect(filtered.map(\.id) == [1])
22 }
23
24 @Test
25 func filteredJobsMatchesByJobId() {
26 let jobs = [makeJob(id: 42, tags: []), makeJob(id: 99, tags: [])]
27 let filtered = filterJobs(jobs, query: "42")
28
29 #expect(filtered.map(\.id) == [42])
30 }
31
32 @Test
33 func filteredJobsMatchesByStatus() {
34 let jobs = [
35 makeJob(id: 1, status: .running, tags: []),
36 makeJob(id: 2, status: .success, tags: [])
37 ]
38
39 let filtered = filterJobs(jobs, query: "running")
40
41 #expect(filtered.map(\.id) == [1])
42 }
43
44 @Test
45 func buildFilterPrioritizesActionableStates() {
46 let jobs = [
47 makeJob(id: 1, status: .success, tags: []),
48 makeJob(id: 2, status: .failed, tags: []),
49 makeJob(id: 3, status: .running, tags: []),
50 makeJob(id: 4, status: .cancelled, tags: [])
51 ]
52
53 let attention = BuildListViewModel.filterJobs(
54 jobs,
55 filter: .attention,
56 lookbackDays: BuildListViewModel.defaultLookbackDays
57 )
58 let active = BuildListViewModel.filterJobs(
59 jobs,
60 filter: .active,
61 lookbackDays: BuildListViewModel.defaultLookbackDays
62 )
63 let failed = BuildListViewModel.filterJobs(
64 jobs,
65 filter: .failed,
66 lookbackDays: BuildListViewModel.defaultLookbackDays
67 )
68
69 #expect(attention.map(\.id) == [2, 3])
70 #expect(active.map(\.id) == [3])
71 #expect(failed.map(\.id) == [2])
72 }
73
74 @Test
75 func buildFilterRestrictsJobsToSelectedLookbackWindow() {
76 let now = Date(timeIntervalSince1970: 60 * 60 * 24 * 20)
77 let jobs = [
78 makeJob(
79 id: 1,
80 status: .failed,
81 tags: [],
82 updated: now.addingTimeInterval(-(60 * 60 * 24))
83 ),
84 makeJob(
85 id: 2,
86 status: .running,
87 tags: [],
88 updated: now.addingTimeInterval(-(60 * 60 * 24 * 8))
89 ),
90 makeJob(
91 id: 3,
92 status: .success,
93 tags: [],
94 updated: now.addingTimeInterval(-(60 * 60 * 24 * 2))
95 ),
96 ]
97
98 let filtered = BuildListViewModel.filterJobs(
99 jobs,
100 filter: .all,
101 lookbackDays: 3,
102 now: now,
103 calendar: Calendar(identifier: .gregorian)
104 )
105
106 #expect(filtered.map(\.id) == [1, 3])
107 }
108
109 private func filterJobs(_ jobs: [JobSummary], query: String) -> [JobSummary] {
110 BuildListViewModel.searchJobs(jobs, matching: query)
111 }
112
113 private func makeJob(
114 id: Int,
115 status: JobStatus = .success,
116 tags: [String],
117 updated: Date = Date()
118 ) -> JobSummary {
119 JobSummary(
120 id: id,
121 created: updated,
122 updated: updated,
123 status: status,
124 note: nil,
125 tags: tags,
126 visibility: nil,
127 image: nil,
128 tasks: []
129 )
130 }
131}