569340cf5fa42e3986981d057b955fb893418910 / internal/web/repohome_test.go · 5786 bytes · raw
package web
import (
"net/http"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
)
// seedFiles gives a repo created via /new one commit on main.
func seedFiles(t *testing.T, dataDir, name string) {
t.Helper()
bare := filepath.Join(dataDir, "repos", "josie", name+".git")
work := filepath.Join(t.TempDir(), "work")
cmd := exec.Command("git", "clone", "-q", bare, work)
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("clone seed: %v: %s", err, out)
}
write := func(rel, content string) {
full := filepath.Join(work, rel)
if err := os.MkdirAll(filepath.Dir(full), 0o755); err != nil {
t.Fatalf("mkdir: %v", err)
}
if err := os.WriteFile(full, []byte(content), 0o644); err != nil {
t.Fatalf("write %s: %v", rel, err)
}
}
write("README.md", "# demo repo\n\nthe **readme** body\n")
write("LICENSE", "MIT License\n\nPermission is hereby granted, free of charge, to any person...\n")
write("hello.c", "int main(void) { return 0; }\n")
write("sub/note.txt", "note\n")
for _, args := range [][]string{
{"add", "."},
{"-c", "user.email=t@t", "-c", "user.name=t", "commit", "-qm", "seed"},
{"push", "-q", "origin", "main"},
} {
cmd := exec.Command("git", args...)
cmd.Dir = work
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("git %v: %v: %s", args, err, out)
}
}
}
func TestRepoHomePublic(t *testing.T) {
httpServer, _, dataDir := newTestServer(t)
createRepo(t, newLoggedInClient(t, httpServer), httpServer, "pub", "public")
seedFiles(t, dataDir, "pub")
resp, err := (&http.Client{}).Get(httpServer.URL + "/josie/pub")
if err != nil {
t.Fatalf("GET /josie/pub: %v", err)
}
body := readAll(t, resp)
if resp.StatusCode != http.StatusOK {
t.Fatalf("status = %d, want 200: %q", resp.StatusCode, body)
}
for _, want := range []string{
"josie/pub", "README.md", "hello.c", "sub/",
"<strong>readme</strong>", "MIT", "/josie/pub.git",
"/josie/pub/blob/main/hello.c", "/josie/pub/blob/main/sub/note.txt",
`class="file-tree`, "✓ main", `value="http`,
} {
if !strings.Contains(body, want) {
t.Errorf("body lacks %q", want)
}
}
}
func TestRepoHomePrivate(t *testing.T) {
httpServer, _, dataDir := newTestServer(t)
loggedIn := newLoggedInClient(t, httpServer)
createRepo(t, loggedIn, httpServer, "sec", "private")
seedFiles(t, dataDir, "sec")
noFollow := &http.Client{CheckRedirect: func(*http.Request, []*http.Request) error {
return http.ErrUseLastResponse
}}
resp, err := noFollow.Get(httpServer.URL + "/josie/sec")
if err != nil {
t.Fatalf("anonymous GET private home: %v", err)
}
readAll(t, resp)
if resp.StatusCode != http.StatusNotFound {
t.Errorf("anonymous status = %d, want 404 (no existence oracle)", resp.StatusCode)
}
resp, err = loggedIn.Get(httpServer.URL + "/josie/sec")
if err != nil {
t.Fatalf("signed-in GET private home: %v", err)
}
body := readAll(t, resp)
if resp.StatusCode != http.StatusOK || !strings.Contains(body, "README.md") {
t.Errorf("signed-in status = %d, want 200 with listing", resp.StatusCode)
}
}
func TestRepoHomeLowercaseReadme(t *testing.T) {
httpServer, _, dataDir := newTestServer(t)
createRepo(t, newLoggedInClient(t, httpServer), httpServer, "lc", "public")
seedFiles(t, dataDir, "lc")
work := filepath.Join(t.TempDir(), "work")
cmd := exec.Command("git", "clone", "-q", filepath.Join(dataDir, "repos", "josie", "lc.git"), work)
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("clone: %v: %s", err, out)
}
for _, args := range [][]string{
{"mv", "README.md", "readme.md"},
{"-c", "user.email=t@t", "-c", "user.name=t", "commit", "-qm", "lowercase readme"},
{"push", "-q", "origin", "main"},
} {
cmd := exec.Command("git", args...)
cmd.Dir = work
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("git %v: %v: %s", args, err, out)
}
}
resp, err := (&http.Client{}).Get(httpServer.URL + "/josie/lc")
if err != nil {
t.Fatalf("GET /josie/lc: %v", err)
}
body := readAll(t, resp)
if resp.StatusCode != http.StatusOK {
t.Fatalf("status = %d, want 200: %q", resp.StatusCode, body)
}
for _, want := range []string{"readme.md", "<strong>readme</strong>"} {
if !strings.Contains(body, want) {
t.Errorf("body lacks %q", want)
}
}
}
func TestRepoHomeEmptyRepoShowsInstructions(t *testing.T) {
httpServer, _, _ := newTestServer(t)
loggedIn := newLoggedInClient(t, httpServer)
createRepo(t, loggedIn, httpServer, "fresh", "private")
resp, err := loggedIn.Get(httpServer.URL + "/josie/fresh")
if err != nil {
t.Fatalf("GET empty home: %v", err)
}
body := readAll(t, resp)
if !strings.Contains(body, "The repository is empty") || !strings.Contains(body, "git remote add origin") {
t.Errorf("empty repo page lacks push instructions: %q", body)
}
}
func TestRepoHomePrivateOwnerOnly(t *testing.T) {
httpServer, database, dataDir := newTestServer(t)
createRepo(t, newLoggedInClient(t, httpServer), httpServer, "sec", "private")
seedFiles(t, dataDir, "sec")
addUser(t, database, "mallory", "pw")
mallory := loginAs(t, httpServer, "mallory", "pw")
for _, path := range []string{"/josie/sec", "/josie/sec/tree/main", "/josie/sec/blob/main/README.md"} {
resp, err := mallory.Get(httpServer.URL + path)
if err != nil {
t.Fatalf("GET %s as non-owner: %v", path, err)
}
readAll(t, resp)
if resp.StatusCode != http.StatusNotFound {
t.Errorf("non-owner GET %s = %d, want 404", path, resp.StatusCode)
}
}
}
func TestRepoHomeUnknown(t *testing.T) {
httpServer, _, _ := newTestServer(t)
resp, err := (&http.Client{}).Get(httpServer.URL + "/josie/nope")
if err != nil {
t.Fatalf("GET unknown: %v", err)
}
readAll(t, resp)
if resp.StatusCode != http.StatusNotFound {
t.Errorf("status = %d, want 404", resp.StatusCode)
}
}