e2e/labelweb_test.go
100 lines · 4209 bytes
1package e2e
2
3import (
4 "net/url"
5 "strings"
6 "testing"
7)
8
9// The label set itself is managed from the browser: create, recolour and
10// remove, each through the label command the CLI runs (#163).
11func TestLabelsWeb(t *testing.T) {
12 t.Parallel()
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", "--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 inst.ssh(t, aliceKey, "", "issue", "create", "alice/app", "--title", "one")
22 inst.ssh(t, aliceKey, "", "issue", "label", "alice/app", "1", "--add", "bug")
23
24 alice := inst.login(t, aliceKey)
25 base := inst.base() + "/alice/app"
26
27 // The existing label is listed with its use count.
28 status, page := browserGet(t, alice, base+"/labels")
29 if status != 200 || !strings.Contains(page, "bug") {
30 t.Fatalf("labels page: %d\n%s", status, page)
31 }
32
33 // Creating one with a colour, and recolouring the existing one.
34 if status, _ := browserPost(t, alice, base+"/labels", url.Values{
35 "name": {"docs"}, "color": {"1f6feb"}}); status != 200 {
36 t.Fatal("label create failed")
37 }
38 if status, _ := browserPost(t, alice, base+"/labels", url.Values{
39 "name": {"bug"}, "color": {"cf222e"}}); status != 200 {
40 t.Fatal("label recolour failed")
41 }
42 out, _, _ := inst.ssh(t, aliceKey, "", "label", "list", "alice/app", "--json")
43 if !strings.Contains(out, `{"name":"bug","color":"#cf222e","issues":1,"mrs":0}`) ||
44 !strings.Contains(out, `{"name":"docs","color":"#1f6feb","issues":0,"mrs":0}`) {
45 t.Fatalf("labels not as posted:\n%s", out)
46 }
47
48 // A bad colour comes back as an error on the page, not a silent no-op.
49 _, body := browserPost(t, alice, base+"/labels", url.Values{
50 "name": {"docs"}, "color": {"red"}})
51 if !strings.Contains(body, `class="error"`) {
52 t.Errorf("bad colour accepted:\n%s", body)
53 }
54
55 // The issue list's column lists the label with its count and a link
56 // that keeps the state (desktop layout spec).
57 status, page = browserGet(t, alice, base+"/issues?state=open")
58 if status != 200 || !strings.Contains(page, `<nav class="sidecol" aria-label="Filters">`) {
59 t.Fatalf("issues page lacks the side column: %d", status)
60 }
61 if !strings.Contains(page, `href="?label=bug&state=open">bug <i>1</i></a>`) {
62 t.Fatalf("issues column lacks the bug facet:\n%s", page)
63 }
64 status, page = browserGet(t, alice, base+"/issues?state=open&label=bug")
65 if status != 200 || !strings.Contains(page, `aria-current="page" href="?state=open">bug <i>1</i></a>`) {
66 t.Fatalf("active facet does not clear itself:\n%s", page)
67 }
68
69 // Removing a label needs its name typed; a bare post is refused and
70 // the label stays.
71 _, body = browserPost(t, alice, base+"/labels", url.Values{
72 "action": {"remove"}, "name": {"bug"}})
73 if !strings.Contains(body, "type bug to confirm") {
74 t.Fatalf("unconfirmed remove was not refused:\n%s", body)
75 }
76 if out, _, _ := inst.ssh(t, aliceKey, "", "label", "list", "alice/app", "--json"); !strings.Contains(out, `"name":"bug"`) {
77 t.Fatalf("label removed without confirmation: %s", out)
78 }
79 if status, _ := browserPost(t, alice, base+"/labels", url.Values{
80 "action": {"remove"}, "name": {"bug"}, "confirm": {"bug"}}); status != 200 {
81 t.Fatal("label remove failed")
82 }
83 if out, _, _ := inst.ssh(t, aliceKey, "", "issue", "show", "alice/app", "1", "--json"); strings.Contains(out, `"bug"`) {
84 t.Fatalf("issue still carries the removed label:\n%s", out)
85 }
86
87 // A reader sees the set and none of the controls.
88 bob := inst.login(t, bobKey)
89 _, p := browserGet(t, bob, base+"/labels")
90 if !strings.Contains(p, "docs") {
91 t.Fatalf("reader cannot see the labels:\n%s", p)
92 }
93 if strings.Contains(p, "New label") || strings.Contains(p, "Remove") {
94 t.Fatal("reader sees a label control")
95 }
96 browserPost(t, bob, base+"/labels", url.Values{"name": {"sneak"}})
97 if out, _, _ := inst.ssh(t, aliceKey, "", "label", "list", "alice/app", "--json"); strings.Contains(out, "sneak") {
98 t.Fatal("reader created a label")
99 }
100}