e2e/issueweb_test.go

v1.42.0
gitbay/e2e/issueweb_test.go history · blame · raw

92 lines · 3751 bytes

 1package e2e
 2
 3import (
 4	"net/url"
 5	"strings"
 6	"testing"
 7)
 8
 9// TestIssueWebTriage closes, labels, assigns, and sets a milestone from
10// the browser. Each action runs the issue command the CLI runs, so the
11// CLI is the check that they took effect.
12func TestIssueWebTriage(t *testing.T) {
13	t.Parallel()
14	inst := startInstanceWith(t, "[web]\nmode = \"accounts\"\n")
15	aliceKey := inst.newKey(t, "alice")
16	bobKey := inst.newKey(t, "bob")
17	inst.admin(t, "admin", "user", "create", "alice",
18		"--key", aliceKey+".pub", "--email", "alice@example.test", "--verified")
19	inst.admin(t, "admin", "user", "create", "bob",
20		"--key", bobKey+".pub", "--email", "bob@example.test", "--verified")
21
22	if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "create", "alice/app"); code != 0 {
23		t.Fatalf("repo create: %s", errOut)
24	}
25	if _, errOut, code := inst.ssh(t, aliceKey, "", "milestone", "create", "alice/app", "v1"); code != 0 {
26		t.Fatalf("milestone create: %s", errOut)
27	}
28	if _, errOut, code := inst.ssh(t, aliceKey, "", "issue", "create", "alice/app", "--title", "'needs triage'"); code != 0 {
29		t.Fatalf("issue create: %s", errOut)
30	}
31
32	alice := inst.login(t, aliceKey)
33	issueURL := inst.base() + "/alice/app/issues/1"
34
35	// The triage controls are on the page for someone with write access.
36	_, body := browserGet(t, alice, issueURL)
37	for _, want := range []string{`/issues/1/state`, `/issues/1/label`, `/issues/1/assign`, `value="v1"`} {
38		if !strings.Contains(body, want) {
39			t.Fatalf("issue page missing %q:\n%s", want, body)
40		}
41	}
42
43	// Label, assign, and milestone, each verified through the CLI.
44	if status, _ := browserPost(t, alice, issueURL+"/label", url.Values{"add": {"bug ui"}}); status != 200 {
45		t.Fatalf("label post: %d", status)
46	}
47	if status, _ := browserPost(t, alice, issueURL+"/assign", url.Values{"add": {"bob"}}); status != 200 {
48		t.Fatalf("assign post: %d", status)
49	}
50	if status, _ := browserPost(t, alice, issueURL+"/milestone", url.Values{"milestone": {"v1"}}); status != 200 {
51		t.Fatalf("milestone post: %d", status)
52	}
53	out, _, _ := inst.ssh(t, aliceKey, "", "issue", "show", "alice/app", "1", "--json")
54	for _, want := range []string{`"bug"`, `"ui"`, `"bob"`, `"v1"`} {
55		if !strings.Contains(out, want) {
56			t.Fatalf("triage did not land (%s):\n%s", want, out)
57		}
58	}
59
60	// Removing works the same way.
61	if status, _ := browserPost(t, alice, issueURL+"/label", url.Values{"remove": {"ui"}}); status != 200 {
62		t.Fatalf("label remove: %d", status)
63	}
64	out, _, _ = inst.ssh(t, aliceKey, "", "issue", "show", "alice/app", "1", "--json")
65	if strings.Contains(out, `"ui"`) {
66		t.Fatalf("label not removed:\n%s", out)
67	}
68
69	// Close, then reopen.
70	if status, _ := browserPost(t, alice, issueURL+"/state", url.Values{"action": {"close"}}); status != 200 {
71		t.Fatalf("close post: %d", status)
72	}
73	if out, _, _ := inst.ssh(t, aliceKey, "", "issue", "show", "alice/app", "1", "--json"); !strings.Contains(out, `"state":"closed"`) {
74		t.Fatalf("issue not closed:\n%s", out)
75	}
76	_, reopened := browserPost(t, alice, issueURL+"/state", url.Values{"action": {"reopen"}})
77	if !strings.Contains(reopened, "chip-open") {
78		t.Fatalf("issue not reopened:\n%s", reopened)
79	}
80
81	// A reader sees no controls and is refused if they forge the post.
82	carolKey := inst.newKey(t, "carol")
83	inst.admin(t, "admin", "user", "create", "carol", "--key", carolKey+".pub")
84	_, readerView := browserGet(t, inst.login(t, carolKey), issueURL)
85	if strings.Contains(readerView, `/issues/1/label`) {
86		t.Fatal("reader sees triage controls")
87	}
88	_, denied := browserPost(t, inst.login(t, carolKey), issueURL+"/state", url.Values{"action": {"close"}})
89	if !strings.Contains(denied, `class="error"`) {
90		t.Fatalf("reader closed someone else's issue:\n%s", denied)
91	}
92}