internal/store/milestones_test.go
117 lines · 4005 bytes
3 symbols in this file
1package store
2
3import (
4 "errors"
5 "testing"
6)
7
8func TestOrgMilestoneSpansRepos(t *testing.T) {
9 f := newAcme(t)
10 id, folded, err := f.s.CreateOrgMilestone(f.org, "v1", "first", "2027-01-01")
11 if err != nil || folded != 0 || id == 0 {
12 t.Fatalf("CreateOrgMilestone: %d, %d, %v", id, folded, err)
13 }
14 // Resolves from either repo, not from alice/app.
15 m, err := f.s.MilestoneByTitle(f.core, "v1")
16 if err != nil || m.OrgID != f.org || m.RepoID != 0 {
17 t.Fatalf("core resolves v1 = %+v, %v", m, err)
18 }
19 if _, err := f.s.MilestoneByTitle(f.app, "v1"); !errors.Is(err, ErrNotFound) {
20 t.Fatalf("app resolves v1: %v", err)
21 }
22 if err := f.s.SetIssueMilestone(f.coreIssue, id); err != nil {
23 t.Fatal(err)
24 }
25 if err := f.s.SetIssueMilestone(f.siteIssue, id); err != nil {
26 t.Fatal(err)
27 }
28 if err := f.s.SetIssueState(f.siteIssue, "closed"); err != nil {
29 t.Fatal(err)
30 }
31 ms, err := f.s.ListOrgMilestones(f.org, "open", f.orgRepos())
32 if err != nil || len(ms) != 1 || ms[0].OpenItems != 1 || ms[0].ClosedItems != 1 {
33 t.Fatalf("org list = %+v, %v", ms, err)
34 }
35 // Counts stop at what the caller can read.
36 ms, _ = f.s.ListOrgMilestones(f.org, "open", []int64{f.core.ID})
37 if ms[0].OpenItems != 1 || ms[0].ClosedItems != 0 {
38 t.Fatalf("org list over core = %+v", ms)
39 }
40 // A repo's list shows the org milestone first, then its own.
41 if _, err := f.s.CreateMilestone(f.core, "core-only", "", ""); err != nil {
42 t.Fatal(err)
43 }
44 ms, _ = f.s.ListMilestones(f.core, "open", f.orgRepos())
45 if len(ms) != 2 || ms[0].Title != "v1" || ms[0].OrgID != f.org || ms[1].Title != "core-only" || ms[1].RepoID != f.core.ID {
46 t.Fatalf("core list = %+v", ms)
47 }
48 if _, err := f.s.OrgMilestoneByTitle(f.org, "core-only"); !errors.Is(err, ErrNotFound) {
49 t.Fatalf("org resolves a repo milestone: %v", err)
50 }
51}
52
53func TestRepoMilestoneRefusedWhenOrgHoldsTitle(t *testing.T) {
54 f := newAcme(t)
55 if _, _, err := f.s.CreateOrgMilestone(f.org, "v1", "", ""); err != nil {
56 t.Fatal(err)
57 }
58 if _, err := f.s.CreateMilestone(f.core, "v1", "", ""); !errors.Is(err, ErrOrgScoped) {
59 t.Fatalf("CreateMilestone over org title: %v", err)
60 }
61 if _, err := f.s.CreateMilestone(f.app, "v1", "", ""); err != nil {
62 t.Fatalf("user repo unaffected: %v", err)
63 }
64 if _, _, err := f.s.CreateOrgMilestone(f.org, "v1", "", ""); err == nil {
65 t.Fatal("duplicate org milestone accepted")
66 }
67}
68
69func TestCreateOrgMilestonePromotes(t *testing.T) {
70 f := newAcme(t)
71 cid, err := f.s.CreateMilestone(f.core, "v1", "", "")
72 if err != nil {
73 t.Fatal(err)
74 }
75 sid, err := f.s.CreateMilestone(f.site, "v1", "", "")
76 if err != nil {
77 t.Fatal(err)
78 }
79 if err := f.s.SetIssueMilestone(f.coreIssue, cid); err != nil {
80 t.Fatal(err)
81 }
82 n, err := f.s.CreateMR(f.site.ID, f.alice, f.site.ID, "feat", "main", "t", "", "abc", "md", false)
83 if err != nil {
84 t.Fatal(err)
85 }
86 // CreateMR returns the per-repo MR number, not the merge_requests.id
87 // row that milestone_id references; resolve it the way SetMRMilestone
88 // callers must.
89 mr, err := f.s.MRByNumber(f.site.ID, n)
90 if err != nil {
91 t.Fatal(err)
92 }
93 if err := f.s.SetMRMilestone(mr.ID, sid); err != nil {
94 t.Fatal(err)
95 }
96 id, folded, err := f.s.CreateOrgMilestone(f.org, "v1", "org wide", "2027-06-01")
97 if err != nil || folded != 2 {
98 t.Fatalf("promote: folded %d, %v", folded, err)
99 }
100 var count int
101 f.s.DB.QueryRow("SELECT COUNT(*) FROM milestones WHERE title = 'v1'").Scan(&count)
102 if count != 1 {
103 t.Fatalf("milestones named v1: %d", count)
104 }
105 f.s.DB.QueryRow("SELECT COUNT(*) FROM issues WHERE milestone_id = ?", id).Scan(&count)
106 if count != 1 {
107 t.Fatalf("issues on org milestone: %d", count)
108 }
109 f.s.DB.QueryRow("SELECT COUNT(*) FROM merge_requests WHERE milestone_id = ?", id).Scan(&count)
110 if count != 1 {
111 t.Fatalf("mrs on org milestone: %d", count)
112 }
113 ms, _ := f.s.ListOrgMilestones(f.org, "open", f.orgRepos())
114 if len(ms) != 1 || ms[0].OpenItems != 2 || ms[0].Description != "org wide" || ms[0].DueDate != "2027-06-01" {
115 t.Fatalf("after promote: %+v", ms)
116 }
117}