e2e/wiki_test.go

6b01ef3788b21e3a4c027a2afe7e7a5bda9ca000
gitbay/e2e/wiki_test.go history · blame · raw

101 lines · 4115 bytes

  1package e2e
  2
  3import (
  4	"os"
  5	"path/filepath"
  6	"strings"
  7	"testing"
  8)
  9
 10func TestWikis(t *testing.T) {
 11	inst := startInstance(t)
 12	aliceKey := inst.newKey(t, "alice")
 13	bobKey := inst.newKey(t, "bob")
 14	inst.admin(t, "admin", "user", "create", "alice", "--key", aliceKey+".pub")
 15	inst.admin(t, "admin", "user", "create", "bob", "--key", bobKey+".pub")
 16	if _, _, code := inst.ssh(t, aliceKey, "", "repo", "create", "alice/app"); code != 0 {
 17		t.Fatal("repo create failed")
 18	}
 19	if _, _, code := inst.ssh(t, aliceKey, "", "repo", "create", "alice/secretive", "--private"); code != 0 {
 20		t.Fatal("private repo create failed")
 21	}
 22
 23	// No wiki yet: the tab is absent, the page shows the push hint, and
 24	// cloning the companion says so.
 25	_, body := inst.get(t, "/alice/app")
 26	if strings.Contains(body, ">wiki<") {
 27		t.Fatal("wiki tab shown with no wiki")
 28	}
 29	_, body = inst.get(t, "/alice/app/wiki")
 30	if !strings.Contains(body, "no wiki yet") {
 31		t.Fatal("missing-wiki hint absent")
 32	}
 33	env := inst.gitEnv(aliceKey)
 34	if out, code := gitRun(t, t.TempDir(), env, "clone", inst.sshURL("alice/app.wiki"), "w"); code == 0 || !strings.Contains(out, "no wiki yet") {
 35		t.Fatalf("clone of absent wiki: %d\n%s", code, out)
 36	}
 37
 38	// First push creates the wiki. A reader without write cannot push it.
 39	work := t.TempDir()
 40	mustGit(t, work, env, "init", "-q", "-b", "main", "w")
 41	dir := filepath.Join(work, "w")
 42	os.WriteFile(filepath.Join(dir, "Home.md"), []byte(
 43		"# welcome\n\nsee [Setup](Setup.md) and ![shot](shot.png)\n"), 0o644)
 44	os.WriteFile(filepath.Join(dir, "Setup.org"), []byte("* setup\n\nsteps here\n"), 0o644)
 45	os.WriteFile(filepath.Join(dir, "shot.png"), []byte{0x89, 0x50, 0x4e, 0x47}, 0o644)
 46	mustGit(t, dir, env, "add", ".")
 47	mustGit(t, dir, env, "commit", "-q", "-m", "wiki start")
 48	mustGit(t, dir, env, "push", "-q", inst.sshURL("alice/app.wiki"), "main")
 49
 50	benv := inst.gitEnv(bobKey)
 51	if out, code := gitRun(t, dir, benv, "push", inst.sshURL("alice/app.wiki"), "main"); code == 0 && !strings.Contains(out, "denied") {
 52		t.Fatalf("reader pushed the wiki: %d\n%s", code, out)
 53	}
 54
 55	// Rendering: home resolves, tab appears, links rewrite to wiki pages
 56	// and images to the wiki raw route; org pages render too.
 57	_, body = inst.get(t, "/alice/app")
 58	if !strings.Contains(body, ">wiki<") {
 59		t.Fatal("wiki tab missing after push")
 60	}
 61	_, body = inst.get(t, "/alice/app/wiki")
 62	if !strings.Contains(body, "welcome") ||
 63		!strings.Contains(body, `href="/alice/app/wiki/Setup"`) ||
 64		!strings.Contains(body, `src="/alice/app/wiki/_raw/shot.png"`) {
 65		t.Fatalf("wiki home rendering:\n%s", body)
 66	}
 67	_, body = inst.get(t, "/alice/app/wiki/Setup")
 68	if !strings.Contains(body, "steps here") {
 69		t.Fatal("org wiki page missing")
 70	}
 71	if status, _ := inst.get(t, "/alice/app/wiki/Nope"); status != 404 {
 72		t.Fatalf("missing page: %d", status)
 73	}
 74	// The raw route serves the image bytes.
 75	status, raw := inst.get(t, "/alice/app/wiki/_raw/shot.png")
 76	if status != 200 || !strings.HasPrefix(raw, "\x89PNG") {
 77		t.Fatalf("wiki raw: %d", status)
 78	}
 79
 80	// 404-parity: a private repo's wiki is invisible, over web and git.
 81	mustGit(t, dir, env, "push", "-q", inst.sshURL("alice/secretive.wiki"), "main")
 82	if status, _ := inst.get(t, "/alice/secretive/wiki"); status != 404 {
 83		t.Fatalf("private wiki page: %d", status)
 84	}
 85	if out, code := gitRun(t, t.TempDir(), benv, "clone", inst.sshURL("alice/secretive.wiki"), "x"); code == 0 || !strings.Contains(out, "not found") {
 86		t.Fatalf("private wiki clone by outsider: %d\n%s", code, out)
 87	}
 88
 89	// Repo names ending .wiki are refused (companion namespace).
 90	if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "create", "alice/notes.wiki"); code != 2 || !strings.Contains(errOut, "reserved") {
 91		t.Fatalf(".wiki name allowed: %d %s", code, errOut)
 92	}
 93
 94	// Deleting the repo removes the wiki companion.
 95	if _, _, code := inst.ssh(t, aliceKey, "", "repo", "delete", "alice/secretive", "--yes"); code != 0 {
 96		t.Fatal("repo delete failed")
 97	}
 98	if _, err := os.Stat(filepath.Join(inst.root, "repos", "alice", "secretive.wiki.git")); err == nil {
 99		t.Fatal("wiki survived repo delete")
100	}
101}