sorting_test.go
⎇
Raw
1package e2e
2
3import (
4 "net/url"
5 "slices"
6 "strings"
7 "testing"
8)
9
10// sortCard returns the repo card whose name link is exactly name.
11func sortCard(r *response, name string) *goquerySel {
12 var found *goquerySel
13 r.Find(".repo-card").Each(func(_ int, card *goquerySel) {
14 if strings.TrimSpace(card.Find(".repo-name").First().Text()) == name {
15 found = card
16 }
17 })
18 return found
19}
20
21func TestSorting(t *testing.T) {
22 e := newEnv(t)
23 admin := e.admin()
24
25 // sort-aaa is created first (older), sort-zzz second (newer). That lets
26 // name order and creation order be told apart. my-repo is navigated to in
27 // the cookie persistence test.
28 e.createRepo(admin, "my-repo")
29 e.createRepo(admin, "sort-aaa")
30 e.createRepo(admin, "sort-zzz")
31
32 t.Run("sort dropdown is visible on repo list page", func(t *testing.T) {
33 opts := admin.get("/").Texts(".repo-sort-select option")
34 if !contains(opts, "Newest") || !contains(opts, "Name") {
35 t.Errorf("options = %v", opts)
36 }
37 })
38
39 t.Run("newest option is selected by default", func(t *testing.T) {
40 // A fresh session has no repo_sort cookie.
41 fresh := e.admin()
42 if got := fresh.get("/").Value(".repo-sort-select"); got != "created" {
43 t.Errorf("selected sort = %q", got)
44 }
45 })
46
47 t.Run("Go button is rendered inside noscript and the sort form works", func(t *testing.T) {
48 // The button's visibility toggling needs a browser; the no-JS path is
49 // the POST to /sort, which is what is asserted here.
50 r := admin.get("/")
51 // The HTML parser keeps noscript content as raw text, so match on it.
52 raw := r.Find(`form[action="/sort"] noscript`).First().Text()
53 if !strings.Contains(raw, `type="submit"`) || !strings.Contains(raw, ">Go<") {
54 t.Errorf("noscript Go button missing: %q", raw)
55 }
56 s := e.admin()
57 s.post("/sort", url.Values{"sort": {"name"}}).mustRedirect("/")
58 if got := s.get("/").Value(".repo-sort-select"); got != "name" {
59 t.Errorf("selected sort = %q", got)
60 }
61 })
62
63 t.Run("selecting name sort sets cookie and persists on next visit", func(t *testing.T) {
64 s := e.admin()
65 s.post("/sort", url.Values{"sort": {"name"}}).mustRedirect("/")
66 if c := s.cookie("repo_sort"); c == nil || c.Value != "name" {
67 t.Fatalf("repo_sort cookie = %v", c)
68 }
69 if got := s.get("/").Value(".repo-sort-select"); got != "name" {
70 t.Errorf("selected sort = %q", got)
71 }
72 // Navigate away and back to confirm the cookie persists.
73 s.get("/my-repo")
74 if got := s.get("/").Value(".repo-sort-select"); got != "name" {
75 t.Errorf("selected sort after navigation = %q", got)
76 }
77 })
78
79 t.Run("default sort shows newer repo before older repo", func(t *testing.T) {
80 admin.setCookie("repo_sort", "created")
81 names := admin.get("/?q=sort-").Texts(".repo-name")
82 if slices.Index(names, "sort-zzz") >= slices.Index(names, "sort-aaa") {
83 t.Errorf("names = %v", names)
84 }
85 })
86
87 t.Run("name sort shows repos in alphabetical order", func(t *testing.T) {
88 admin.setCookie("repo_sort", "name")
89 names := admin.get("/?q=sort-").Texts(".repo-name")
90 admin.setCookie("repo_sort", "created")
91 if slices.Index(names, "sort-aaa") >= slices.Index(names, "sort-zzz") {
92 t.Errorf("names = %v", names)
93 }
94 })
95
96 t.Run("pinning a repo shows pinned badge on list page", func(t *testing.T) {
97 r := admin.follow(admin.post("/sort-aaa/settings", url.Values{"is_pinned": {"1"}}))
98 if !r.Has(".form-success") {
99 t.Fatal("form-success missing")
100 }
101 card := sortCard(admin.get("/"), "sort-aaa")
102 if card == nil {
103 t.Fatal("sort-aaa card missing")
104 }
105 if card.Find(".badge-pinned").Length() == 0 {
106 t.Error("pinned badge missing")
107 }
108 })
109
110 t.Run("pinned repo appears before unpinned repos regardless of creation order", func(t *testing.T) {
111 // sort-zzz is newer, so the default sort would list it first. Pinned
112 // repos float above that.
113 names := admin.get("/?q=sort-").Texts(".repo-name")
114 if slices.Index(names, "sort-aaa") >= slices.Index(names, "sort-zzz") {
115 t.Errorf("names = %v", names)
116 }
117 })
118
119 t.Run("unpinning a repo removes the pinned badge", func(t *testing.T) {
120 r := admin.follow(admin.post("/sort-aaa/settings", url.Values{}))
121 if !r.Has(".form-success") {
122 t.Fatal("form-success missing")
123 }
124 card := sortCard(admin.get("/"), "sort-aaa")
125 if card == nil {
126 t.Fatal("sort-aaa card missing")
127 }
128 if n := card.Find(".badge-pinned").Length(); n != 0 {
129 t.Errorf("pinned badges = %d", n)
130 }
131 })
132}
133