package harness
import (
"io"
"net/http"
"os"
"path/filepath"
"strings"
"testing"
"time"
)
// The repo landing page is GitHub's front door translated: an About
// aggregate (description, homepage, topics — .quarry/repo.json) and a
// tabbed document panel (README | Contributing | … by root convention,
// curated by the same file). Tabs are URL state, so the whole panel
// works scriptless; a tab that does not exist 404s rather than
// rendering an arbitrary file through a curated strip.
func TestLandingAboutPanelAndDocTabs(t *testing.T) {
store := buildStore(t, "aboutseed")
write := func(name, body string) {
t.Helper()
if err := os.MkdirAll(filepath.Dir(filepath.Join(store, name)), 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(store, name), []byte(body), 0o644); err != nil {
t.Fatal(err)
}
zrun(t, store, "add", name)
}
write("CONTRIBUTING.md", "# Contributing\nSend patches.\n")
write(".quarry/repo.json", `{"homepage": "https://example.org", "topics": ["forge", "zit"]}`)
zrun(t, store, "commit", "-m", "about config")
srv := ingestAndServe(t, map[string]string{"alpha": store}, t.TempDir())
get := func(path string) (int, string) {
resp, err := http.Get(srv.URL + path)
if err != nil {
t.Fatal(err)
}
defer resp.Body.Close()
b, _ := io.ReadAll(resp.Body)
return resp.StatusCode, string(b)
}
_, landing := get("/r/alpha")
for _, want := range []string{
`https://example.org`, // homepage link
`forge`, `zit`, // topics
`class="doc-tabs"`, // the strip
`>README<`, `>Contributing<`,
"store aboutseed", // README is the default tab, rendered
} {
if !strings.Contains(landing, want) {
t.Fatalf("landing missing %q:\n%s", want, landing)
}
}
// Tab selection is URL state.
_, contrib := get("/r/alpha?doc=CONTRIBUTING.md")
if !strings.Contains(contrib, "Send patches.") {
t.Fatalf("?doc did not switch the panel:\n%s", contrib)
}
// The strip is curated: not a render-any-file endpoint.
if code, _ := get("/r/alpha?doc=src/main.go"); code != http.StatusNotFound {
t.Fatalf("?doc rendered a non-tab file (status %d)", code)
}
// Deeper tree views stay working views: no About, no tabs.
_, sub := get("/r/alpha/tree/trunk/src")
if strings.Contains(sub, `class="doc-tabs"`) || strings.Contains(sub, "example.org") {
t.Fatalf("the About panel leaked into a subdirectory view:\n%s", sub)
}
}
// Switching document tabs is a morph, not a navigation: a page reload
// threw away the reader's scroll position mid-README. The tab keeps its
// href (the no-script path renders the same view server-side); scripted
// clicks fetch this one-shot fragment, which must close and must carry
// both the panel and the moved underline.
func TestDocTabSwitchIsAMorph(t *testing.T) {
store := buildStore(t, "morphseed")
if err := os.WriteFile(filepath.Join(store, "CONTRIBUTING.md"), []byte("# How\nPatches welcome.\n"), 0o644); err != nil {
t.Fatal(err)
}
zrun(t, store, "add", "CONTRIBUTING.md")
zrun(t, store, "commit", "-m", "add contributing")
srv := ingestAndServe(t, map[string]string{"alpha": store}, t.TempDir())
resp, err := http.Get(srv.URL + "/r/alpha/doc.frag?doc=CONTRIBUTING.md")
if err != nil {
t.Fatal(err)
}
defer resp.Body.Close()
done := make(chan []byte, 1)
go func() { b, _ := io.ReadAll(resp.Body); done <- b }()
var frag string
select {
case b := <-done:
frag = string(b)
case <-time.After(3 * time.Second):
t.Fatal("doc.frag held its connection; a one-shot must close")
}
for _, want := range []string{
"datastar-patch-elements",
`<div id="docs">`,
"Patches welcome.",
} {
if !strings.Contains(frag, want) {
t.Fatalf("fragment missing %q:\n%s", want, frag)
}
}
// The underline must move with the content: CONTRIBUTING is .here.
i := strings.Index(frag, ">Contributing</a>")
if i < 0 || !strings.Contains(frag[max(0, i-200):i], `class="here"`) {
t.Fatalf("the active underline did not follow the tab:\n%s", frag)
}
// The tabs keep their no-script hrefs.
if !strings.Contains(frag, `href="/r/alpha?doc=`) {
t.Fatalf("tabs lost their fallback hrefs:\n%s", frag)
}
}