summaryrefslogtreecommitdiff
path: root/HutchTests
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-04-12 00:55:42 -0500
committerChristian Cleberg <[email protected]>2026-04-12 00:55:42 -0500
commit9050405b4f33b2b9b70458fcf3e43b80c940eef7 (patch)
tree983c3a07a560258059cfe421beb3ffcf3c18baf4 /HutchTests
parent5f6d545eb3455a9e4da5a3cb4460811e3a48d939 (diff)
downloadhutch-9050405b4f33b2b9b70458fcf3e43b80c940eef7.tar.gz
hutch-9050405b4f33b2b9b70458fcf3e43b80c940eef7.tar.bz2
hutch-9050405b4f33b2b9b70458fcf3e43b80c940eef7.zip
add shortcuts widgets and power-user workflowsv2.15.0
Diffstat (limited to 'HutchTests')
-rw-r--r--HutchTests/DeepLinkTests.swift90
-rw-r--r--HutchTests/HutchIntentsTests.swift75
-rw-r--r--HutchTests/SystemStatusWidgetSnapshotTests.swift73
3 files changed, 238 insertions, 0 deletions
diff --git a/HutchTests/DeepLinkTests.swift b/HutchTests/DeepLinkTests.swift
new file mode 100644
index 0000000..12f759b
--- /dev/null
+++ b/HutchTests/DeepLinkTests.swift
@@ -0,0 +1,90 @@
+import Foundation
+import Testing
+@testable import Hutch
+
+struct DeepLinkTests {
+
+ @Test
+ func parsesHomeLink() {
+ let link = DeepLink(url: URL(string: "hutch://home")!)
+ #expect(link == .home)
+ }
+
+ @Test
+ func parsesNilPathAsHome() {
+ let link = DeepLink(url: URL(string: "hutch://")!)
+ #expect(link == .home)
+ }
+
+ @Test
+ func parsesRepositoryLink() {
+ let link = DeepLink(url: URL(string: "hutch://git/~user/repo")!)
+ #expect(link == .repository(owner: "~user", repo: "repo"))
+ }
+
+ @Test
+ func parsesTicketLink() {
+ let link = DeepLink(url: URL(string: "hutch://todo/~owner/tracker/42")!)
+ #expect(link == .ticket(owner: "~owner", tracker: "tracker", ticketId: 42))
+ }
+
+ @Test
+ func parsesBuildJobLink() {
+ let link = DeepLink(url: URL(string: "hutch://builds/12345")!)
+ #expect(link == .build(jobId: 12345))
+ }
+
+ @Test
+ func parsesBuildsTabLink() {
+ let link = DeepLink(url: URL(string: "hutch://builds")!)
+ #expect(link == .buildsTab)
+ }
+
+ @Test
+ func parsesRepositoriesTabLink() {
+ let link = DeepLink(url: URL(string: "hutch://repositories")!)
+ #expect(link == .repositoriesTab)
+ }
+
+ @Test
+ func parsesTrackersTabLink() {
+ let link = DeepLink(url: URL(string: "hutch://trackers")!)
+ #expect(link == .trackersTab)
+ }
+
+ @Test
+ func parsesSystemStatusLink() {
+ let link = DeepLink(url: URL(string: "hutch://status")!)
+ #expect(link == .systemStatus)
+ }
+
+ @Test
+ func parsesLookupLink() {
+ let link = DeepLink(url: URL(string: "hutch://lookup")!)
+ #expect(link == .lookup)
+ }
+
+ @Test
+ func rejectsNonHutchScheme() {
+ let link = DeepLink(url: URL(string: "https://example.com/home")!)
+ #expect(link == nil)
+ }
+
+ @Test
+ func rejectsUnknownPath() {
+ let link = DeepLink(url: URL(string: "hutch://unknown")!)
+ #expect(link == nil)
+ }
+
+ @Test
+ func rejectsTicketLinkWithNonNumericId() {
+ let link = DeepLink(url: URL(string: "hutch://todo/~owner/tracker/abc")!)
+ #expect(link == nil)
+ }
+
+ @Test
+ func rejectsBuildLinkWithNonNumericId() {
+ let link = DeepLink(url: URL(string: "hutch://builds/abc")!)
+ #expect(link == nil)
+ }
+}
diff --git a/HutchTests/HutchIntentsTests.swift b/HutchTests/HutchIntentsTests.swift
new file mode 100644
index 0000000..94ecbf0
--- /dev/null
+++ b/HutchTests/HutchIntentsTests.swift
@@ -0,0 +1,75 @@
+import Foundation
+import Testing
+@testable import Hutch
+
+@MainActor
+struct HutchIntentsTests {
+
+ @Test
+ func checkSystemStatusReturnsOperationalWhenNoDisruption() async throws {
+ let defaultsName = "HutchIntentsTests-status-\(UUID().uuidString)"
+ let defaults = UserDefaults(suiteName: defaultsName)!
+ defer { defaults.removePersistentDomain(forName: defaultsName) }
+
+ let snapshot = SystemStatusWidgetSnapshot(
+ services: [
+ .init(id: "git", name: "git.sr.ht", status: "Operational", requiresAttention: false),
+ ],
+ hasDisruption: false,
+ overallStatusText: "All monitored services operational",
+ bannerSummary: "",
+ updatedAt: .now
+ )
+ SystemStatusWidgetSnapshotStore.save(snapshot, defaults: defaults)
+
+ let loaded = SystemStatusWidgetSnapshotStore.load(defaults: defaults)
+ #expect(loaded != nil)
+ #expect(loaded?.hasDisruption == false)
+ }
+
+ @Test
+ func checkSystemStatusReturnsDisruptionDetails() async throws {
+ let defaultsName = "HutchIntentsTests-disruption-\(UUID().uuidString)"
+ let defaults = UserDefaults(suiteName: defaultsName)!
+ defer { defaults.removePersistentDomain(forName: defaultsName) }
+
+ let snapshot = SystemStatusWidgetSnapshot(
+ services: [
+ .init(id: "git", name: "git.sr.ht", status: "Degraded", requiresAttention: true),
+ .init(id: "meta", name: "meta.sr.ht", status: "Operational", requiresAttention: false),
+ ],
+ hasDisruption: true,
+ overallStatusText: "Experiencing disruptions",
+ bannerSummary: "git.sr.ht disrupted",
+ updatedAt: .now
+ )
+ SystemStatusWidgetSnapshotStore.save(snapshot, defaults: defaults)
+
+ let loaded = SystemStatusWidgetSnapshotStore.load(defaults: defaults)
+ #expect(loaded?.hasDisruption == true)
+
+ let disrupted = loaded!.services.filter(\.requiresAttention)
+ #expect(disrupted.count == 1)
+ #expect(disrupted.first?.name == "git.sr.ht")
+ }
+
+ @Test
+ func needsAttentionSnapshotSupportsBuildsCheck() {
+ let defaultsName = "HutchIntentsTests-builds-\(UUID().uuidString)"
+ let defaults = UserDefaults(suiteName: defaultsName)!
+ defer { defaults.removePersistentDomain(forName: defaultsName) }
+
+ let snapshot = NeedsAttentionSnapshot(
+ unreadInboxThreads: 5,
+ assignedOpenTickets: 3,
+ failedBuilds: 2,
+ updatedAt: .now
+ )
+ NeedsAttentionSnapshotStore.save(snapshot, defaults: defaults)
+
+ let loaded = NeedsAttentionSnapshotStore.load(defaults: defaults)
+ #expect(loaded?.failedBuilds == 2)
+ #expect(loaded?.unreadInboxThreads == 5)
+ #expect(loaded?.assignedOpenTickets == 3)
+ }
+}
diff --git a/HutchTests/SystemStatusWidgetSnapshotTests.swift b/HutchTests/SystemStatusWidgetSnapshotTests.swift
new file mode 100644
index 0000000..ddb74b1
--- /dev/null
+++ b/HutchTests/SystemStatusWidgetSnapshotTests.swift
@@ -0,0 +1,73 @@
+import Foundation
+import Testing
+@testable import Hutch
+
+@MainActor
+struct SystemStatusWidgetSnapshotTests {
+
+ @Test
+ func saveAndLoadRoundTrips() {
+ let defaultsName = "SystemStatusWidgetSnapshotTests-\(UUID().uuidString)"
+ let defaults = UserDefaults(suiteName: defaultsName)!
+ defer { defaults.removePersistentDomain(forName: defaultsName) }
+
+ let snapshot = SystemStatusWidgetSnapshot(
+ services: [
+ .init(id: "git", name: "git.sr.ht", status: "Operational", requiresAttention: false),
+ .init(id: "builds", name: "builds.sr.ht", status: "Degraded", requiresAttention: true),
+ ],
+ hasDisruption: true,
+ overallStatusText: "Experiencing disruptions",
+ bannerSummary: "builds.sr.ht disrupted",
+ updatedAt: Date(timeIntervalSince1970: 1000)
+ )
+
+ SystemStatusWidgetSnapshotStore.save(snapshot, defaults: defaults)
+ let loaded = SystemStatusWidgetSnapshotStore.load(defaults: defaults)
+
+ #expect(loaded != nil)
+ #expect(loaded?.services.count == 2)
+ #expect(loaded?.hasDisruption == true)
+ #expect(loaded?.bannerSummary == "builds.sr.ht disrupted")
+ #expect(loaded?.services[0].name == "git.sr.ht")
+ #expect(loaded?.services[1].requiresAttention == true)
+ }
+
+ @Test
+ func loadReturnsNilWhenEmpty() {
+ let defaultsName = "SystemStatusWidgetSnapshotTests-empty-\(UUID().uuidString)"
+ let defaults = UserDefaults(suiteName: defaultsName)!
+ defer { defaults.removePersistentDomain(forName: defaultsName) }
+
+ let loaded = SystemStatusWidgetSnapshotStore.load(defaults: defaults)
+ #expect(loaded == nil)
+ }
+
+ @Test
+ func clearRemovesSnapshot() {
+ let defaultsName = "SystemStatusWidgetSnapshotTests-clear-\(UUID().uuidString)"
+ let defaults = UserDefaults(suiteName: defaultsName)!
+ defer { defaults.removePersistentDomain(forName: defaultsName) }
+
+ let snapshot = SystemStatusWidgetSnapshot(
+ services: [.init(id: "meta", name: "meta.sr.ht", status: "Operational", requiresAttention: false)],
+ hasDisruption: false,
+ overallStatusText: "All monitored services operational",
+ bannerSummary: "",
+ updatedAt: .now
+ )
+
+ SystemStatusWidgetSnapshotStore.save(snapshot, defaults: defaults)
+ #expect(SystemStatusWidgetSnapshotStore.load(defaults: defaults) != nil)
+
+ SystemStatusWidgetSnapshotStore.clear(defaults: defaults)
+ #expect(SystemStatusWidgetSnapshotStore.load(defaults: defaults) == nil)
+ }
+
+ @Test
+ func unavailableSnapshotHasEmptyServices() {
+ let snapshot = SystemStatusWidgetSnapshot.unavailable
+ #expect(snapshot.services.isEmpty)
+ #expect(snapshot.hasDisruption == false)
+ }
+}