package e2e import ( "net/url" "slices" "strings" "testing" ) // sortCard returns the repo card whose name link is exactly name. func sortCard(r *response, name string) *goquerySel { var found *goquerySel r.Find(".repo-card").Each(func(_ int, card *goquerySel) { if strings.TrimSpace(card.Find(".repo-name").First().Text()) == name { found = card } }) return found } func TestSorting(t *testing.T) { e := newEnv(t) admin := e.admin() // sort-aaa is created first (older), sort-zzz second (newer). That lets // name order and creation order be told apart. my-repo is navigated to in // the cookie persistence test. e.createRepo(admin, "my-repo") e.createRepo(admin, "sort-aaa") e.createRepo(admin, "sort-zzz") t.Run("sort dropdown is visible on repo list page", func(t *testing.T) { opts := admin.get("/").Texts(".repo-sort-select option") if !contains(opts, "Newest") || !contains(opts, "Name") { t.Errorf("options = %v", opts) } }) t.Run("newest option is selected by default", func(t *testing.T) { // A fresh session has no repo_sort cookie. fresh := e.admin() if got := fresh.get("/").Value(".repo-sort-select"); got != "created" { t.Errorf("selected sort = %q", got) } }) t.Run("Go button is rendered inside noscript and the sort form works", func(t *testing.T) { // The button's visibility toggling needs a browser; the no-JS path is // the POST to /sort, which is what is asserted here. r := admin.get("/") // The HTML parser keeps noscript content as raw text, so match on it. raw := r.Find(`form[action="/sort"] noscript`).First().Text() if !strings.Contains(raw, `type="submit"`) || !strings.Contains(raw, ">Go<") { t.Errorf("noscript Go button missing: %q", raw) } s := e.admin() s.post("/sort", url.Values{"sort": {"name"}}).mustRedirect("/") if got := s.get("/").Value(".repo-sort-select"); got != "name" { t.Errorf("selected sort = %q", got) } }) t.Run("selecting name sort sets cookie and persists on next visit", func(t *testing.T) { s := e.admin() s.post("/sort", url.Values{"sort": {"name"}}).mustRedirect("/") if c := s.cookie("repo_sort"); c == nil || c.Value != "name" { t.Fatalf("repo_sort cookie = %v", c) } if got := s.get("/").Value(".repo-sort-select"); got != "name" { t.Errorf("selected sort = %q", got) } // Navigate away and back to confirm the cookie persists. s.get("/my-repo") if got := s.get("/").Value(".repo-sort-select"); got != "name" { t.Errorf("selected sort after navigation = %q", got) } }) t.Run("default sort shows newer repo before older repo", func(t *testing.T) { admin.setCookie("repo_sort", "created") names := admin.get("/?q=sort-").Texts(".repo-name") if slices.Index(names, "sort-zzz") >= slices.Index(names, "sort-aaa") { t.Errorf("names = %v", names) } }) t.Run("name sort shows repos in alphabetical order", func(t *testing.T) { admin.setCookie("repo_sort", "name") names := admin.get("/?q=sort-").Texts(".repo-name") admin.setCookie("repo_sort", "created") if slices.Index(names, "sort-aaa") >= slices.Index(names, "sort-zzz") { t.Errorf("names = %v", names) } }) t.Run("pinning a repo shows pinned badge on list page", func(t *testing.T) { r := admin.follow(admin.post("/sort-aaa/settings", url.Values{"is_pinned": {"1"}})) if !r.Has(".form-success") { t.Fatal("form-success missing") } card := sortCard(admin.get("/"), "sort-aaa") if card == nil { t.Fatal("sort-aaa card missing") } if card.Find(".badge-pinned").Length() == 0 { t.Error("pinned badge missing") } }) t.Run("pinned repo appears before unpinned repos regardless of creation order", func(t *testing.T) { // sort-zzz is newer, so the default sort would list it first. Pinned // repos float above that. names := admin.get("/?q=sort-").Texts(".repo-name") if slices.Index(names, "sort-aaa") >= slices.Index(names, "sort-zzz") { t.Errorf("names = %v", names) } }) t.Run("unpinning a repo removes the pinned badge", func(t *testing.T) { r := admin.follow(admin.post("/sort-aaa/settings", url.Values{})) if !r.Has(".form-success") { t.Fatal("form-success missing") } card := sortCard(admin.get("/"), "sort-aaa") if card == nil { t.Fatal("sort-aaa card missing") } if n := card.Find(".badge-pinned").Length(); n != 0 { t.Errorf("pinned badges = %d", n) } }) }