e2e/mrdraft_test.go
99 lines · 3371 bytes
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 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", "--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 if _, _, code := inst.ssh(t, aliceKey, "", "repo", "access", "grant", "alice/app", "bob", "write"); code != 0 {
23 t.Fatal("grant failed")
24 }
25
26 env := inst.gitEnv(aliceKey)
27 work := t.TempDir()
28 mustGit(t, work, env, "clone", inst.sshURL("alice/app"), "w")
29 dir := filepath.Join(work, "w")
30 os.WriteFile(filepath.Join(dir, "a.txt"), []byte("a\n"), 0o644)
31 mustGit(t, dir, env, "checkout", "-q", "-b", "main")
32 mustGit(t, dir, env, "add", ".")
33 mustGit(t, dir, env, "commit", "-q", "-m", "base")
34 mustGit(t, dir, env, "push", "-q", "origin", "main")
35 mustGit(t, dir, env, "checkout", "-q", "-b", "feat")
36 mustGit(t, dir, env, "commit", "-q", "--allow-empty", "-m", "work")
37 mustGit(t, dir, env, "push", "-q", "origin", "feat")
38
39 if _, errOut, code := inst.ssh(t, aliceKey, "", "mr", "create", "alice/app",
40 "--source", "feat", "--target", "main", "--title", "'wip'", "--draft"); code != 0 {
41 t.Fatalf("mr create --draft: %s", errOut)
42 }
43
44 draft := func() bool {
45 t.Helper()
46 out, errOut, code := inst.ssh(t, aliceKey, "", "mr", "show", "alice/app", "1", "--json")
47 if code != 0 {
48 t.Fatalf("mr show: %s", errOut)
49 }
50 var env struct {
51 Data struct {
52 State string `json:"state"`
53 Draft bool `json:"draft"`
54 } `json:"data"`
55 }
56 json.Unmarshal([]byte(out), &env)
57 // A draft is open, not a fifth state.
58 if env.Data.State != "open" {
59 t.Fatalf("draft changed the state to %q", env.Data.State)
60 }
61 return env.Data.Draft
62 }
63
64 if !draft() {
65 t.Fatal("--draft did not mark it")
66 }
67
68 // A draft does not merge, and no repository setting is involved.
69 _, errOut, code := inst.ssh(t, aliceKey, "", "mr", "merge", "alice/app", "1")
70 if code != 4 || !strings.Contains(errOut, "is a draft") {
71 t.Fatalf("draft merged: exit %d, %s", code, errOut)
72 }
73
74 // Nor does it sit in anyone's review queue.
75 out, _, _ := inst.ssh(t, bobKey, "", "dashboard", "--json")
76 if strings.Contains(out, `"review_queue":[{`) {
77 t.Fatalf("draft is in the review queue: %s", out)
78 }
79
80 // Ready, and now it does both.
81 if _, errOut, code := inst.ssh(t, aliceKey, "", "mr", "ready", "alice/app", "1"); code != 0 {
82 t.Fatalf("mr ready: %s", errOut)
83 }
84 if draft() {
85 t.Fatal("mr ready did not clear the mark")
86 }
87 out, _, _ = inst.ssh(t, bobKey, "", "dashboard", "--json")
88 if !strings.Contains(out, `"number":1`) {
89 t.Fatalf("ready MR is not in the review queue: %s", out)
90 }
91 if _, errOut, code := inst.ssh(t, aliceKey, "", "mr", "merge", "alice/app", "1"); code != 0 {
92 t.Fatalf("ready MR refused: %s", errOut)
93 }
94
95 // Ready twice is a usage error rather than a silent no-op.
96 if _, _, code := inst.ssh(t, aliceKey, "", "mr", "ready", "alice/app", "1"); code == 0 {
97 t.Fatal("mr ready on a merged MR succeeded")
98 }
99}