e2e/reposhowstate_test.go
75 lines · 3469 bytes
1package e2e
2
3import (
4 "strings"
5 "testing"
6)
7
8// repo show carries the caller's own watch and bookmark state and, when
9// the caller can read it, what the repository was forked from — so a
10// client draws the real state without a second read per screen (#178).
11func TestRepoShowCarriesViewerState(t *testing.T) {
12 t.Parallel()
13 inst := startInstance(t)
14 aliceKey := inst.newKey(t, "alice")
15 bobKey := inst.newKey(t, "bob")
16 inst.admin(t, "admin", "user", "create", "alice", "--key", aliceKey+".pub")
17 inst.admin(t, "admin", "user", "create", "bob", "--key", bobKey+".pub")
18 if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "create", "alice/app"); code != 0 {
19 t.Fatalf("repo create: %s", errOut)
20 }
21
22 // Nothing yet: the fields are absent, not false or empty strings.
23 out, _, _ := inst.ssh(t, bobKey, "", "repo", "show", "alice/app", "--json")
24 for _, k := range []string{`"watch"`, `"bookmarked"`, `"fork_of"`} {
25 if strings.Contains(out, k) {
26 t.Errorf("%s present with no state:\n%s", k, out)
27 }
28 }
29
30 inst.ssh(t, bobKey, "", "repo", "watch", "alice/app")
31 inst.ssh(t, bobKey, "", "repo", "bookmark", "alice/app")
32 out, _, _ = inst.ssh(t, bobKey, "", "repo", "show", "alice/app", "--json")
33 if !strings.Contains(out, `"watch":"watching"`) || !strings.Contains(out, `"bookmarked":true`) {
34 t.Fatalf("bob's state not reported:\n%s", out)
35 }
36 // unwatch is the way back to the default from either state, and
37 // mute is its own state, not what unwatch means (#180).
38 inst.ssh(t, bobKey, "", "repo", "unwatch", "alice/app")
39 if out, _, _ := inst.ssh(t, bobKey, "", "repo", "show", "alice/app", "--json"); strings.Contains(out, `"watch"`) {
40 t.Errorf("unwatch did not clear the state:\n%s", out)
41 }
42 inst.ssh(t, bobKey, "", "repo", "mute", "alice/app")
43 if out, _, _ := inst.ssh(t, bobKey, "", "repo", "show", "alice/app", "--json"); !strings.Contains(out, `"watch":"muted"`) {
44 t.Errorf("mute not reported:\n%s", out)
45 }
46 inst.ssh(t, bobKey, "", "repo", "unwatch", "alice/app")
47 if out, _, _ := inst.ssh(t, bobKey, "", "repo", "show", "alice/app", "--json"); strings.Contains(out, `"watch"`) {
48 t.Errorf("unwatch did not clear a mute:\n%s", out)
49 }
50 inst.ssh(t, bobKey, "", "repo", "watch", "alice/app")
51 // It is the caller's state: alice sees her own, not bob's.
52 if out, _, _ := inst.ssh(t, aliceKey, "", "repo", "show", "alice/app", "--json"); strings.Contains(out, `"bookmarked"`) {
53 t.Errorf("alice sees bob's bookmark:\n%s", out)
54 }
55
56 // Plain output carries the same.
57 if out, _, _ := inst.ssh(t, bobKey, "", "repo", "show", "alice/app"); !strings.Contains(out, "watch: watching") ||
58 !strings.Contains(out, "bookmarked") {
59 t.Errorf("plain output lacks the state:\n%s", out)
60 }
61
62 // A fork names its parent to anyone who can read the parent.
63 if _, errOut, code := inst.ssh(t, bobKey, "", "repo", "fork", "alice/app"); code != 0 {
64 t.Fatalf("fork: %s", errOut)
65 }
66 if out, _, _ := inst.ssh(t, bobKey, "", "repo", "show", "bob/app", "--json"); !strings.Contains(out, `"fork_of":"alice/app"`) {
67 t.Fatalf("fork_of missing:\n%s", out)
68 }
69 // Once the parent is private and unreadable, the fork stops naming
70 // it: a private repository is never confirmed to exist.
71 inst.ssh(t, aliceKey, "", "repo", "settings", "visibility", "alice/app", "private")
72 if out, _, _ := inst.ssh(t, bobKey, "", "repo", "show", "bob/app", "--json"); strings.Contains(out, "alice/app") {
73 t.Errorf("a fork named a parent the caller cannot read:\n%s", out)
74 }
75}