e2e/issueweb_test.go

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

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