gitbayTests/OrgLabelMilestoneTests.swift
119 lines · 4534 bytes
1import Foundation
2import Testing
3@testable import gitbay
4
5private func makeClient() throws -> (GitbayClient, StubProtocol.Box) {
6 let box = StubProtocol.box()
7 let client = GitbayClient(
8 instance: try GitbayInstance(url: "https://gitbay.org"),
9 token: "test-token",
10 session: box.session()
11 )
12 return (client, box)
13}
14
15private func argvOf(_ seen: StubProtocol.Seen) throws -> [String] {
16 let body = try #require(try JSONSerialization.jsonObject(with: seen.body) as? [String: Any])
17 return try #require(body["argv"] as? [String])
18}
19
20private let okJSON = #"{"protocol_version":1,"data":{},"exit_code":0}"#
21
22private let orgLabelsJSON = """
23 {"protocol_version":1,"data":[\
24 {"name":"bug","color":"#cf222e","org":true,"issues":18},\
25 {"name":"ci","org":true,"issues":2}],"exit_code":0}
26 """
27
28private let orgMilestonesJSON = """
29 {"protocol_version":1,"data":[\
30 {"title":"v2.0.0","state":"open","org":true,"open":3,"closed":9}],"exit_code":0}
31 """
32
33struct LabelOwnerTests {
34
35 /// A repository's set is `label <verb> <repo>`; an org's is
36 /// `org label <verb> <org>`. Milestones follow the same shape.
37 @Test func eachOwnerSpellsItsOwnCommand() {
38 #expect(LabelOwner.repo("krz/gitbay").argv("label", "set") == ["label", "set", "krz/gitbay"])
39 #expect(LabelOwner.org("krz").argv("label", "set") == ["org", "label", "set", "krz"])
40 #expect(LabelOwner.org("krz").argv("milestone", "list") == ["org", "milestone", "list", "krz"])
41 #expect(LabelOwner.repo("krz/gitbay").isOrg == false)
42 #expect(LabelOwner.org("krz").isOrg)
43 }
44}
45
46@MainActor
47struct OrgLabelListTests {
48
49 @Test func anOrgListsItsLabelsThroughOrgLabel() async throws {
50 let (client, stub) = try makeClient()
51 stub.enqueue(.init(status: 200, json: orgLabelsJSON))
52 let model = LabelListViewModel(client: client, owner: .org("krz"))
53
54 await model.load()
55
56 #expect(stub.seen.first?.url.query() == "argv=org&argv=label&argv=list&argv=krz")
57 #expect(model.state.value?.map(\.name) == ["bug", "ci"])
58 #expect(model.state.value?.allSatisfy(\.org) == true)
59 }
60
61 @Test func setAndRemoveUseTheOrgCommands() async throws {
62 let (client, stub) = try makeClient()
63 stub.enqueue(.init(status: 200, json: orgLabelsJSON))
64 let model = LabelListViewModel(client: client, owner: .org("krz"))
65 await model.load()
66 for _ in 0..<2 {
67 stub.enqueue(.init(status: 200, json: okJSON, match: "cmd"))
68 stub.enqueue(.init(status: 200, json: orgLabelsJSON, match: "argv=list"))
69 }
70
71 await model.setLabel("bug", color: "cf222e")
72 await model.remove("ci")
73
74 let writes = try stub.seen.filter { $0.method == "POST" }.map(argvOf)
75 #expect(writes == [
76 ["org", "label", "set", "krz", "bug", "--color", "cf222e"],
77 ["org", "label", "remove", "krz", "ci"],
78 ])
79 }
80}
81
82@MainActor
83struct OrgMilestoneListTests {
84
85 @Test func anOrgListsItsMilestonesWithTheState() async throws {
86 let (client, stub) = try makeClient()
87 stub.enqueue(.init(status: 200, json: orgMilestonesJSON))
88 let model = MilestoneListViewModel(client: client, owner: .org("krz"))
89
90 await model.load()
91
92 #expect(stub.seen.first?.url.query()
93 == "argv=org&argv=milestone&argv=list&argv=krz&argv=--state&argv=open")
94 #expect(model.state.value?.map(\.title) == ["v2.0.0"])
95 }
96
97 @Test func createCloseAndReopenUseTheOrgCommands() async throws {
98 let (client, stub) = try makeClient()
99 stub.enqueue(.init(status: 200, json: orgMilestonesJSON))
100 let model = MilestoneListViewModel(client: client, owner: .org("krz"))
101 await model.load()
102 for _ in 0..<3 {
103 stub.enqueue(.init(status: 200, json: okJSON, match: "cmd"))
104 stub.enqueue(.init(status: 200, json: orgMilestonesJSON, match: "argv=list"))
105 }
106
107 let ok = await model.create(title: "v2.1.0", description: "next", due: "2026-10-01")
108 await model.close("v2.0.0")
109 await model.reopen("v2.0.0")
110
111 #expect(ok)
112 let writes = try stub.seen.filter { $0.method == "POST" }.map(argvOf)
113 #expect(writes == [
114 ["org", "milestone", "create", "krz", "v2.1.0", "--description", "next", "--due", "2026-10-01"],
115 ["org", "milestone", "close", "krz", "v2.0.0"],
116 ["org", "milestone", "reopen", "krz", "v2.0.0"],
117 ])
118 }
119}