krz/hutch

an ios client for sourcehut

clone: git clone https://gitbay.org/krz/hutch.git

v3.11.0: HutchTests/BuildListViewModelTests.swift · raw

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