diff options
Diffstat (limited to 'HutchTests')
| -rw-r--r-- | HutchTests/BuildListViewModelTests.swift | 21 | ||||
| -rw-r--r-- | HutchTests/RepositoryListViewModelTests.swift | 23 | ||||
| -rw-r--r-- | HutchTests/ScopedSearchHistoryStoreTests.swift | 54 | ||||
| -rw-r--r-- | HutchTests/TicketListViewModelTests.swift | 41 |
4 files changed, 126 insertions, 13 deletions
diff --git a/HutchTests/BuildListViewModelTests.swift b/HutchTests/BuildListViewModelTests.swift index a8cdc30..fccd7cf 100644 --- a/HutchTests/BuildListViewModelTests.swift +++ b/HutchTests/BuildListViewModelTests.swift @@ -29,6 +29,18 @@ struct BuildListViewModelTests { } @Test + func filteredJobsMatchesByStatus() { + let jobs = [ + makeJob(id: 1, status: .running, tags: []), + makeJob(id: 2, status: .success, tags: []) + ] + + let filtered = filterJobs(jobs, query: "running") + + #expect(filtered.map(\.id) == [1]) + } + + @Test func buildFilterPrioritizesActionableStates() { let jobs = [ makeJob(id: 1, status: .success, tags: []), @@ -45,14 +57,7 @@ struct BuildListViewModelTests { } private func filterJobs(_ jobs: [JobSummary], query: String) -> [JobSummary] { - let q = query.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - guard !q.isEmpty else { return jobs } - return jobs.filter { - String($0.id).contains(q) || - $0.tags.contains { $0.lowercased().contains(q) } || - ($0.note?.lowercased().contains(q) == true) || - ($0.image?.lowercased().contains(q) == true) - } + BuildListViewModel.searchJobs(jobs, matching: query) } private func makeJob(id: Int, status: JobStatus = .success, tags: [String]) -> JobSummary { diff --git a/HutchTests/RepositoryListViewModelTests.swift b/HutchTests/RepositoryListViewModelTests.swift index 7bd9126..07f66aa 100644 --- a/HutchTests/RepositoryListViewModelTests.swift +++ b/HutchTests/RepositoryListViewModelTests.swift @@ -29,6 +29,21 @@ struct RepositoryListViewModelTests { } @Test + @MainActor + func filterRepositoriesMatchesOwnerAndDefaultBranchLocally() { + let repositories = [ + makeRepository(id: 1, service: .git, name: "Hutch", description: nil, owner: "~alice", branch: "main"), + makeRepository(id: 2, service: .hg, name: "Mail", description: nil, owner: "~bob", branch: "stable") + ] + + let ownerMatches = RepositoryListViewModel.filterRepositories(repositories, matching: "~bob") + let branchMatches = RepositoryListViewModel.filterRepositories(repositories, matching: "main") + + #expect(ownerMatches.map(\.id) == [2]) + #expect(branchMatches.map(\.id) == [1]) + } + + @Test func buildStatusKeysParsesSourceHutRepositoryURLsFromManifest() { let manifest = """ image: alpine/latest @@ -59,7 +74,9 @@ struct RepositoryListViewModelTests { id: Int, service: SRHTService, name: String, - description: String? + description: String?, + owner: String = "~owner", + branch: String = "main" ) -> RepositorySummary { RepositorySummary( id: id, @@ -69,8 +86,8 @@ struct RepositoryListViewModelTests { description: description, visibility: .public, updated: Date(timeIntervalSince1970: TimeInterval(id)), - owner: Entity(canonicalName: "~owner"), - head: Reference(name: "main", target: nil) + owner: Entity(canonicalName: owner), + head: Reference(name: branch, target: nil) ) } } diff --git a/HutchTests/ScopedSearchHistoryStoreTests.swift b/HutchTests/ScopedSearchHistoryStoreTests.swift new file mode 100644 index 0000000..856d69f --- /dev/null +++ b/HutchTests/ScopedSearchHistoryStoreTests.swift @@ -0,0 +1,54 @@ +import Foundation +import Testing +@testable import Hutch + +struct ScopedSearchHistoryStoreTests { + + @Test + func recordsMostRecentUniqueSearchPerScopeFirst() { + let suiteName = "ScopedSearchHistoryStoreTests-\(UUID().uuidString)" + let defaults = UserDefaults(suiteName: suiteName)! + defer { defaults.removePersistentDomain(forName: suiteName) } + + ScopedSearchHistoryStore.record( + query: "hutch", + scopeID: "repositories", + defaults: defaults, + now: Date(timeIntervalSince1970: 100) + ) + ScopedSearchHistoryStore.record( + query: "running", + scopeID: "builds", + defaults: defaults, + now: Date(timeIntervalSince1970: 200) + ) + ScopedSearchHistoryStore.record( + query: "Hutch", + scopeID: "repositories", + defaults: defaults, + now: Date(timeIntervalSince1970: 300) + ) + + let repositoryHistory = ScopedSearchHistoryStore.load(scopeID: "repositories", defaults: defaults) + let buildHistory = ScopedSearchHistoryStore.load(scopeID: "builds", defaults: defaults) + + #expect(repositoryHistory.map(\.query) == ["Hutch"]) + #expect(repositoryHistory.first?.createdAt == Date(timeIntervalSince1970: 300)) + #expect(buildHistory.map(\.query) == ["running"]) + } + + @Test + func clearsOnlyRequestedScope() { + let suiteName = "ScopedSearchHistoryStoreTests-\(UUID().uuidString)" + let defaults = UserDefaults(suiteName: suiteName)! + defer { defaults.removePersistentDomain(forName: suiteName) } + + ScopedSearchHistoryStore.record(query: "repo", scopeID: "repositories", defaults: defaults) + ScopedSearchHistoryStore.record(query: "ticket", scopeID: "tickets.rid", defaults: defaults) + + ScopedSearchHistoryStore.clear(scopeID: "repositories", defaults: defaults) + + #expect(ScopedSearchHistoryStore.load(scopeID: "repositories", defaults: defaults).isEmpty) + #expect(ScopedSearchHistoryStore.load(scopeID: "tickets.rid", defaults: defaults).map(\.query) == ["ticket"]) + } +} diff --git a/HutchTests/TicketListViewModelTests.swift b/HutchTests/TicketListViewModelTests.swift index a237071..7fa5449 100644 --- a/HutchTests/TicketListViewModelTests.swift +++ b/HutchTests/TicketListViewModelTests.swift @@ -66,6 +66,42 @@ struct TicketListViewModelTests { } @Test + func filteredTicketsMatchesAssigneeAndStatus() { + let tickets = [ + makeTicket( + id: 1, + title: "Crash on launch", + status: .inProgress, + submitter: "~owner", + labels: [], + assignees: [Entity(canonicalName: "~alice")] + ), + makeTicket( + id: 2, + title: "Settings polish", + status: .resolved, + submitter: "~owner", + labels: [], + assignees: [] + ) + ] + + let assigneeMatches = filterTickets( + tickets, + state: TicketListFilterState(status: .all), + query: "~alice" + ) + let statusMatches = filterTickets( + tickets, + state: TicketListFilterState(status: .all), + query: "resolved" + ) + + #expect(assigneeMatches.map(\.id) == [1]) + #expect(statusMatches.map(\.id) == [2]) + } + + @Test func filteredTicketsMatchesAnySelectedLabel() { let tickets = [ makeTicket(id: 1, title: "Crash on launch", status: .reported, submitter: "~owner", labels: [makeLabel(id: 1, name: "bug")]), @@ -153,7 +189,8 @@ struct TicketListViewModelTests { title: String, status: TicketStatus, submitter: String, - labels: [TicketLabel] + labels: [TicketLabel], + assignees: [Entity] = [] ) -> TicketSummary { TicketSummary( id: id, @@ -163,7 +200,7 @@ struct TicketListViewModelTests { created: Date(), submitter: Entity(canonicalName: submitter), labels: labels, - assignees: [] + assignees: assignees ) } |
