missingrepos_test.go
⎇
Raw
1package e2e
2
3import (
4 "net/url"
5 "os"
6 "strings"
7 "testing"
8
9 "github.com/PuerkitoBio/goquery"
10)
11
12// A repo whose git directory is gone keeps its database row. The admin
13// settings page lists it and lets the admin drop it.
14func TestMissingRepos(t *testing.T) {
15 e := newEnv(t)
16 admin := e.admin()
17 for _, name := range []string{"gone-a", "gone-b", "stays"} {
18 e.createRepo(admin, name)
19 admin.post("/"+name+"/issues", url.Values{"title": {"An issue"}, "body": {"x"}}).mustStatus(302)
20 }
21 for _, name := range []string{"gone-a", "gone-b"} {
22 if err := os.RemoveAll(e.repoPath(name)); err != nil {
23 t.Fatal(err)
24 }
25 }
26
27 // dropID returns the hidden id of the drop form for a listed repo.
28 dropID := func(name string) string {
29 var id string
30 admin.get("/settings").Find(".queue-item").Each(func(_ int, s *goquery.Selection) {
31 if s.Find("strong").Text() == name {
32 id, _ = s.Find(`input[name=id]`).Attr("value")
33 }
34 })
35 return id
36 }
37
38 t.Run("settings lists missing repos with counts", func(t *testing.T) {
39 r := admin.get("/settings")
40 names := r.Texts(".queue-item strong")
41 if !contains(names, "gone-a") || !contains(names, "gone-b") || contains(names, "stays") {
42 t.Errorf("missing list = %v", names)
43 }
44 if !r.Contains("1 issue, 0 patches") {
45 t.Error("issue count not shown")
46 }
47 })
48
49 t.Run("opening a missing repo errors", func(t *testing.T) {
50 if c := admin.get("/gone-a").Code; c < 400 {
51 t.Errorf("status = %d", c)
52 }
53 })
54
55 t.Run("drop refuses an unknown or present repo", func(t *testing.T) {
56 r := admin.post("/admin/repos/drop", url.Values{"id": {"999999"}})
57 if !strings.Contains(r.Location(), "error=") {
58 t.Errorf("location = %q", r.Location())
59 }
60 })
61
62 t.Run("drop one removes only that repo", func(t *testing.T) {
63 id := dropID("gone-a")
64 if id == "" {
65 t.Fatal("no drop form for gone-a")
66 }
67 admin.post("/admin/repos/drop", url.Values{"id": {id}}).mustRedirect("/settings?success=repo_dropped")
68 names := admin.get("/settings").Texts(".queue-item strong")
69 if contains(names, "gone-a") || !contains(names, "gone-b") {
70 t.Errorf("after drop: %v", names)
71 }
72 admin.get("/gone-a").mustStatus(404)
73 admin.get("/stays/issues/1").mustStatus(200)
74 })
75
76 t.Run("drop all clears the section", func(t *testing.T) {
77 admin.post("/admin/repos/drop-all", nil).mustRedirect("/settings?success=repos_dropped")
78 r := admin.get("/settings")
79 if r.Count(".queue-item input[name=id]") != 0 || !r.Contains("Every repository has its git directory") {
80 t.Error("section not empty after drop all")
81 }
82 admin.get("/gone-b").mustStatus(404)
83 admin.get("/stays/issues/1").mustStatus(200)
84 })
85
86 t.Run("restart keeps a missing repo's data", func(t *testing.T) {
87 e.createRepo(admin, "gone-c")
88 admin.post("/gone-c/issues", url.Values{"title": {"Kept"}, "body": {"x"}}).mustStatus(302)
89 if err := os.RemoveAll(e.repoPath("gone-c")); err != nil {
90 t.Fatal(err)
91 }
92 if err := e.Srv.SyncRepos(t.Context()); err != nil {
93 t.Fatal(err)
94 }
95 if !contains(admin.get("/settings").Texts(".queue-item strong"), "gone-c") {
96 t.Error("gone-c dropped by startup sync")
97 }
98 })
99
100 t.Run("non-admin cannot drop", func(t *testing.T) {
101 e.register("bob", "password123").post("/admin/repos/drop-all", nil).mustStatus(403)
102 })
103}
104