e2e/mrdraft_test.go
100 lines · 3385 bytes
1 symbol in this file
1package e2e
2
3import (
4 "encoding/json"
5 "os"
6 "path/filepath"
7 "strings"
8 "testing"
9)
10
11// TestMRDraft covers the first stage of #111: a merge request opened to
12// show work rather than to ask for a merge.
13func TestMRDraft(t *testing.T) {
14 t.Parallel()
15 inst := startInstanceWith(t, "[web]\nmode = \"accounts\"\n")
16 aliceKey := inst.newKey(t, "alice")
17 bobKey := inst.newKey(t, "bob")
18 inst.admin(t, "admin", "user", "create", "alice", "--key", aliceKey+".pub")
19 inst.admin(t, "admin", "user", "create", "bob", "--key", bobKey+".pub")
20 if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "create", "alice/app"); code != 0 {
21 t.Fatalf("repo create: %s", errOut)
22 }
23 if _, _, code := inst.ssh(t, aliceKey, "", "repo", "access", "grant", "alice/app", "bob", "write"); code != 0 {
24 t.Fatal("grant failed")
25 }
26
27 env := inst.gitEnv(aliceKey)
28 work := t.TempDir()
29 mustGit(t, work, env, "clone", inst.sshURL("alice/app"), "w")
30 dir := filepath.Join(work, "w")
31 os.WriteFile(filepath.Join(dir, "a.txt"), []byte("a\n"), 0o644)
32 mustGit(t, dir, env, "checkout", "-q", "-b", "main")
33 mustGit(t, dir, env, "add", ".")
34 mustGit(t, dir, env, "commit", "-q", "-m", "base")
35 mustGit(t, dir, env, "push", "-q", "origin", "main")
36 mustGit(t, dir, env, "checkout", "-q", "-b", "feat")
37 mustGit(t, dir, env, "commit", "-q", "--allow-empty", "-m", "work")
38 mustGit(t, dir, env, "push", "-q", "origin", "feat")
39
40 if _, errOut, code := inst.ssh(t, aliceKey, "", "mr", "create", "alice/app",
41 "--source", "feat", "--target", "main", "--title", "'wip'", "--draft"); code != 0 {
42 t.Fatalf("mr create --draft: %s", errOut)
43 }
44
45 draft := func() bool {
46 t.Helper()
47 out, errOut, code := inst.ssh(t, aliceKey, "", "mr", "show", "alice/app", "1", "--json")
48 if code != 0 {
49 t.Fatalf("mr show: %s", errOut)
50 }
51 var env struct {
52 Data struct {
53 State string `json:"state"`
54 Draft bool `json:"draft"`
55 } `json:"data"`
56 }
57 json.Unmarshal([]byte(out), &env)
58 // A draft is open, not a fifth state.
59 if env.Data.State != "open" {
60 t.Fatalf("draft changed the state to %q", env.Data.State)
61 }
62 return env.Data.Draft
63 }
64
65 if !draft() {
66 t.Fatal("--draft did not mark it")
67 }
68
69 // A draft does not merge, and no repository setting is involved.
70 _, errOut, code := inst.ssh(t, aliceKey, "", "mr", "merge", "alice/app", "1")
71 if code != 4 || !strings.Contains(errOut, "is a draft") {
72 t.Fatalf("draft merged: exit %d, %s", code, errOut)
73 }
74
75 // Nor does it sit in anyone's review queue.
76 out, _, _ := inst.ssh(t, bobKey, "", "dashboard", "--json")
77 if strings.Contains(out, `"review_queue":[{`) {
78 t.Fatalf("draft is in the review queue: %s", out)
79 }
80
81 // Ready, and now it does both.
82 if _, errOut, code := inst.ssh(t, aliceKey, "", "mr", "ready", "alice/app", "1"); code != 0 {
83 t.Fatalf("mr ready: %s", errOut)
84 }
85 if draft() {
86 t.Fatal("mr ready did not clear the mark")
87 }
88 out, _, _ = inst.ssh(t, bobKey, "", "dashboard", "--json")
89 if !strings.Contains(out, `"number":1`) {
90 t.Fatalf("ready MR is not in the review queue: %s", out)
91 }
92 if _, errOut, code := inst.ssh(t, aliceKey, "", "mr", "merge", "alice/app", "1"); code != 0 {
93 t.Fatalf("ready MR refused: %s", errOut)
94 }
95
96 // Ready twice is a usage error rather than a silent no-op.
97 if _, _, code := inst.ssh(t, aliceKey, "", "mr", "ready", "alice/app", "1"); code == 0 {
98 t.Fatal("mr ready on a merged MR succeeded")
99 }
100}