e2e/bookmarks_test.go
107 lines · 4704 bytes
1package e2e
2
3import (
4 "net/url"
5 "os"
6 "path/filepath"
7 "strings"
8 "testing"
9)
10
11// Bookmarks are the public "saved for later", separate from pins: they
12// are something you do to someone else's repository, and the count is a
13// signal of what people found worth returning to (#146).
14func TestBookmarks(t *testing.T) {
15 inst := startInstanceWith(t, "[web]\nmode = \"accounts\"\n")
16 aliceKey := inst.newKey(t, "alice")
17 bobKey := inst.newKey(t, "bob")
18 inst.admin(t, "admin", "user", "create", "alice", "--key", aliceKey+".pub")
19 inst.admin(t, "admin", "user", "create", "bob", "--key", bobKey+".pub")
20 if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "create", "alice/app"); code != 0 {
21 t.Fatalf("repo create: %s", errOut)
22 }
23 if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "create", "alice/secret", "--private"); code != 0 {
24 t.Fatalf("repo create: %s", errOut)
25 }
26 // The facts bar, where the count shows, needs a repository with
27 // commits: an empty one has nothing to size up.
28 env := inst.gitEnv(aliceKey)
29 work := t.TempDir()
30 mustGit(t, work, env, "clone", inst.sshURL("alice/app"), "w")
31 dir := filepath.Join(work, "w")
32 os.WriteFile(filepath.Join(dir, "a.txt"), []byte("a\n"), 0o644)
33 mustGit(t, dir, env, "checkout", "-q", "-b", "main")
34 mustGit(t, dir, env, "add", ".")
35 mustGit(t, dir, env, "commit", "-q", "-m", "base")
36 mustGit(t, dir, env, "push", "-q", "origin", "main")
37
38 // Bob bookmarks someone else's repository; read access is enough.
39 if out, errOut, code := inst.ssh(t, bobKey, "", "repo", "bookmark", "alice/app"); code != 0 {
40 t.Fatalf("bookmark: %s%s", out, errOut)
41 }
42 if out, _, _ := inst.ssh(t, bobKey, "", "repo", "bookmarks", "--json"); !strings.Contains(out, `"path":"alice/app"`) ||
43 !strings.Contains(out, `"bookmarks":1`) {
44 t.Fatalf("bookmark not listed with its count:\n%s", out)
45 }
46 // Bookmarking twice is not an error and does not double the count.
47 inst.ssh(t, bobKey, "", "repo", "bookmark", "alice/app")
48 if out, _, _ := inst.ssh(t, bobKey, "", "repo", "bookmarks", "--json"); !strings.Contains(out, `"bookmarks":1`) {
49 t.Fatalf("a second bookmark changed the count:\n%s", out)
50 }
51
52 // A private repository a stranger cannot read is not found, the same
53 // as everywhere.
54 if _, _, code := inst.ssh(t, bobKey, "", "repo", "bookmark", "alice/secret"); code != 3 {
55 t.Errorf("bookmarking an invisible repository exited %d, want 3", code)
56 }
57
58 // Pins stay separate: bookmarking does not pin.
59 if out, _, _ := inst.ssh(t, bobKey, "", "dashboard", "--json"); strings.Contains(out, "alice/app") {
60 t.Errorf("a bookmark showed up as a pin:\n%s", out)
61 }
62
63 // The count is public and shows on the repository page.
64 if _, body := inst.get(t, "/alice/app"); !strings.Contains(body, "1</strong> bookmark") {
65 t.Errorf("count not on the repo page:\n%s", body)
66 }
67
68 // The web toggles it, through the same command.
69 bob := inst.login(t, bobKey)
70 if status, _ := browserPost(t, bob, inst.base()+"/alice/app/bookmark", url.Values{}); status != 200 {
71 t.Fatal("web unbookmark failed")
72 }
73 if out, _, _ := inst.ssh(t, bobKey, "", "repo", "bookmarks", "--json"); strings.Contains(out, "alice/app") {
74 t.Fatalf("still bookmarked after the toggle:\n%s", out)
75 }
76 if status, _ := browserPost(t, bob, inst.base()+"/alice/app/bookmark", url.Values{}); status != 200 {
77 t.Fatal("web bookmark failed")
78 }
79 if _, page := browserGet(t, bob, inst.base()+"/bookmarks"); !strings.Contains(page, "alice/app") {
80 t.Fatalf("bookmarks page does not list it:\n%s", page)
81 }
82
83 // Unbookmarking something that is not bookmarked says so.
84 if _, _, code := inst.ssh(t, aliceKey, "", "repo", "unbookmark", "alice/app"); code != 3 {
85 t.Errorf("unbookmarking what was never bookmarked exited %d, want 3", code)
86 }
87}
88
89// A repository bookmarked while public and since made private drops out
90// of the listing rather than leaking its existence.
91func TestBookmarkOfRepoGonePrivate(t *testing.T) {
92 inst := startInstance(t)
93 aliceKey := inst.newKey(t, "alice")
94 bobKey := inst.newKey(t, "bob")
95 inst.admin(t, "admin", "user", "create", "alice", "--key", aliceKey+".pub")
96 inst.admin(t, "admin", "user", "create", "bob", "--key", bobKey+".pub")
97 inst.ssh(t, aliceKey, "", "repo", "create", "alice/app")
98 if _, errOut, code := inst.ssh(t, bobKey, "", "repo", "bookmark", "alice/app"); code != 0 {
99 t.Fatalf("bookmark: %s", errOut)
100 }
101 if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "settings", "visibility", "alice/app", "private"); code != 0 {
102 t.Fatalf("visibility: %s", errOut)
103 }
104 if out, _, _ := inst.ssh(t, bobKey, "", "repo", "bookmarks", "--json"); strings.Contains(out, "alice/app") {
105 t.Fatalf("a repository gone private is still listed:\n%s", out)
106 }
107}