e2e/reposhowstate_test.go

f8b976a97290a20d552056a999511f5d27d8e8ec
gitbay/e2e/reposhowstate_test.go history · blame · raw

76 lines · 3494 bytes

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