e2e/previewweb_test.go

v1.30.0
gitbay/e2e/previewweb_test.go history · blame · raw

165 lines · 7136 bytes

  1package e2e
  2
  3import (
  4	"net/url"
  5	"os"
  6	"path/filepath"
  7	"strings"
  8	"testing"
  9)
 10
 11// Every markup form has a Preview button that renders the draft above
 12// the textarea and writes nothing (#235). The forms are: issue and MR
 13// create, their edit and comment boxes, release create and edit, the
 14// profile about text, and the file editor on a path the forge renders.
 15func TestMarkupPreviewWeb(t *testing.T) {
 16	inst := startInstanceWith(t, "[web]\nmode = \"accounts\"\n")
 17	aliceKey := inst.newKey(t, "alice")
 18	inst.admin(t, "admin", "user", "create", "alice",
 19		"--key", aliceKey+".pub", "--email", "alice@example.test", "--verified")
 20	if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "create", "alice/app"); code != 0 {
 21		t.Fatalf("repo create: %s", errOut)
 22	}
 23	env := inst.gitEnv(aliceKey)
 24	work := t.TempDir()
 25	mustGit(t, work, env, "clone", inst.sshURL("alice/app"), "w")
 26	dir := filepath.Join(work, "w")
 27	mustGit(t, dir, env, "checkout", "-q", "-b", "main")
 28	os.WriteFile(filepath.Join(dir, "README.md"), []byte("# hi\n"), 0o644)
 29	os.WriteFile(filepath.Join(dir, "a.txt"), []byte("a\n"), 0o644)
 30	mustGit(t, dir, env, "add", ".")
 31	mustGit(t, dir, env, "commit", "-q", "-m", "base")
 32	mustGit(t, dir, env, "push", "-q", "origin", "main")
 33	mustGit(t, dir, env, "checkout", "-q", "-b", "topic")
 34	os.WriteFile(filepath.Join(dir, "b.txt"), []byte("b\n"), 0o644)
 35	mustGit(t, dir, env, "add", ".")
 36	mustGit(t, dir, env, "commit", "-q", "-m", "topic")
 37	mustGit(t, dir, env, "push", "-q", "origin", "topic")
 38	mustGit(t, dir, env, "tag", "v1")
 39	mustGit(t, dir, env, "push", "-q", "origin", "v1")
 40
 41	alice := inst.login(t, aliceKey)
 42	base := inst.base() + "/alice/app"
 43
 44	post := func(where string, v url.Values) string {
 45		t.Helper()
 46		status, body := browserPost(t, alice, where, v)
 47		if status != 200 {
 48			t.Fatalf("post %s %v: %d", where, v, status)
 49		}
 50		return body
 51	}
 52	// previewed asserts the rendering is on the page and the draft came
 53	// back with it.
 54	previewed := func(what, body, want, kept string) {
 55		t.Helper()
 56		if !strings.Contains(body, `<p class="previewmark">Preview</p>`) {
 57			t.Fatalf("%s: no preview block:\n%s", what, body)
 58		}
 59		if !strings.Contains(body, want) {
 60			t.Fatalf("%s: preview does not contain %q:\n%s", what, want, body)
 61		}
 62		if kept != "" && !strings.Contains(body, kept) {
 63			t.Fatalf("%s: form lost %q:\n%s", what, kept, body)
 64		}
 65	}
 66
 67	// Issue create: markdown renders, and the title and labels survive.
 68	b := post(base+"/issues/new", url.Values{
 69		"title": {"draft title"}, "body": {"# heading\n"}, "labels": {"bug"},
 70		"format": {"md"}, "preview": {"1"},
 71	})
 72	previewed("issue create", b, "<h1", `value="draft title"`)
 73	if !strings.Contains(b, `value="bug"`) {
 74		t.Fatalf("issue create preview lost the labels:\n%s", b)
 75	}
 76	// Nothing was opened.
 77	if out, _, _ := inst.ssh(t, aliceKey, "", "issue", "list", "alice/app", "--json"); strings.Contains(out, "draft title") {
 78		t.Fatalf("preview created an issue: %s", out)
 79	}
 80
 81	// The org choice previews as org, not markdown.
 82	b = post(base+"/issues/new", url.Values{
 83		"title": {"t"}, "body": {"Some /emphasis/ here.\n"}, "format": {"org"}, "preview": {"1"},
 84	})
 85	previewed("issue create org", b, "<em>emphasis</em>", `<option value="org" selected>`)
 86
 87	// A real issue, then its comment and edit boxes.
 88	if _, errOut, code := inst.ssh(t, aliceKey, "", "issue", "create", "alice/app", "--title", "real", "--body", "body"); code != 0 {
 89		t.Fatalf("issue create: %s", errOut)
 90	}
 91	b = post(base+"/issues/1/comment", url.Values{"body": {"a **bold** remark"}, "preview": {"1"}})
 92	previewed("issue comment", b, "<strong>bold</strong>", "a **bold** remark")
 93	b = post(base+"/issues/1/edit", url.Values{
 94		"title": {"real"}, "body": {"## edited"}, "preview": {"1"},
 95	})
 96	previewed("issue edit", b, "<h2", "## edited")
 97	if !strings.Contains(b, `<details class="editbox" open>`) {
 98		t.Fatalf("issue edit preview left the box shut:\n%s", b)
 99	}
100	// Neither wrote: one comment would show in the thread, an edit in the body.
101	if out, _, _ := inst.ssh(t, aliceKey, "", "issue", "show", "alice/app", "1", "--json"); strings.Contains(out, "bold") || strings.Contains(out, "edited") {
102		t.Fatalf("preview wrote to the issue: %s", out)
103	}
104
105	// MR create, comment and edit.
106	b = post(base+"/mrs/new", url.Values{
107		"source": {"topic"}, "target": {"main"}, "title": {"mr draft"},
108		"body": {"# mr heading"}, "format": {"md"}, "preview": {"1"},
109	})
110	previewed("mr create", b, "<h1", `value="mr draft"`)
111	if out, _, _ := inst.ssh(t, aliceKey, "", "mr", "list", "alice/app", "--json"); strings.Contains(out, "mr draft") {
112		t.Fatalf("preview opened a merge request: %s", out)
113	}
114	if _, errOut, code := inst.ssh(t, aliceKey, "", "mr", "create", "alice/app",
115		"--source", "topic", "--target", "main", "--title", "'real mr'"); code != 0 {
116		t.Fatalf("mr create: %s", errOut)
117	}
118	b = post(base+"/mrs/1/comment", url.Values{"body": {"a `code` remark"}, "preview": {"1"}})
119	previewed("mr comment", b, "<code>code</code>", "a `code` remark")
120	b = post(base+"/mrs/1/edit", url.Values{"title": {"real mr"}, "body": {"## mr edited"}, "preview": {"1"}})
121	previewed("mr edit", b, "<h2", "## mr edited")
122
123	// Release create, then edit.
124	b = post(base+"/releases", url.Values{
125		"tag": {"v1"}, "title": {"first"}, "notes": {"* a bullet"}, "preview": {"1"},
126	})
127	previewed("release create", b, "<li>", "* a bullet")
128	if out, _, _ := inst.ssh(t, aliceKey, "", "release", "list", "alice/app", "--json"); strings.Contains(out, "first") {
129		t.Fatalf("preview created a release: %s", out)
130	}
131	if _, errOut, code := inst.ssh(t, aliceKey, "", "release", "create", "alice/app", "v1", "--title", "first"); code != 0 {
132		t.Fatalf("release create: %s", errOut)
133	}
134	b = post(base+"/releases", url.Values{
135		"action": {"edit"}, "tag": {"v1"}, "title": {"first"},
136		"notes": {"## release notes"}, "preview": {"1"},
137	})
138	previewed("release edit", b, "<h2", "## release notes")
139
140	// The profile's about text.
141	b = post(inst.base()+"/settings", url.Values{
142		"field": {"profile"}, "about": {"# about me"}, "format": {"md"},
143		"description": {"kept"}, "preview": {"1"},
144	})
145	previewed("profile about", b, "<h1", `value="kept"`)
146	if out, _, _ := inst.ssh(t, aliceKey, "", "profile", "show", "--json"); strings.Contains(out, "about me") {
147		t.Fatalf("preview saved the profile: %s", out)
148	}
149
150	// The file editor previews a rendered path and offers nothing on one
151	// it does not render.
152	b = post(base+"/edit/main/README.md", url.Values{
153		"content": {"# from the editor"}, "message": {"kept message"}, "preview": {"1"},
154	})
155	previewed("file editor", b, "from the editor", `value="kept message"`)
156	if _, body := browserGet(t, alice, base+"/blob/main/README.md"); strings.Contains(body, "from the editor") {
157		t.Fatalf("preview committed the file:\n%s", body)
158	}
159	if _, body := browserGet(t, alice, base+"/edit/main/a.txt"); strings.Contains(body, `name="preview"`) {
160		t.Fatalf("a plain text file offers a preview:\n%s", body)
161	}
162	if _, body := browserGet(t, alice, base+"/edit/main/README.md"); !strings.Contains(body, `name="preview"`) {
163		t.Fatalf("no preview button on a markdown file:\n%s", body)
164	}
165}