package web import ( "io" "log/slog" "net/http" "net/http/httptest" "strings" "testing" llmgw "gitea.mynodes.xyz/ilker/llmgw" "gitea.mynodes.xyz/ilker/llmgw/internal/store" ) // docsMux mounts the portal the way the router does. func docsMux(h http.HandlerFunc) *http.ServeMux { mux := http.NewServeMux() mux.HandleFunc("GET /docs", h) mux.HandleFunc("GET /docs/{doc}", h) return mux } func TestTheDocsPortalRendersADocumentWithItsHeadingsAndCode(t *testing.T) { code, body := get(t, docsMux(Docs("v1", false)), "/docs/clients", nil) if code != http.StatusOK { t.Fatalf("status %d", code) } for _, want := range []string{ `

Using llmgw from code`, // A heading links to itself, for someone sending a section to someone. `

Streaming`, `client.chat.completions.create(`, // Tables are GitHub's. ``, // The sidebar offers every document and marks the open one. `Using llmgw from code`, ``, // And this document's sections beneath it. `The Anthropic SDK`, } { if !strings.Contains(body, want) { t.Errorf("the page lacks %q", want) } } } func TestEveryDocumentInTheManualIsAPage(t *testing.T) { h := docsMux(Docs("v1", false)) for _, d := range llmgw.Manual() { if code, _ := get(t, h, "/docs/"+d.Key, nil); code != http.StatusOK { t.Errorf("/docs/%s: %d", d.Key, code) } } } func TestTheIndexLeadsWithTheClientGuide(t *testing.T) { code, body := get(t, docsMux(Docs("v1", true)), "/docs", nil) if code != http.StatusOK { t.Fatalf("status %d", code) } lead := strings.Index(body, `Using llmgw from code shows`) every := strings.Index(body, "Every document") if lead < 0 || every < 0 || lead > every { t.Errorf("the client guide is not offered first:\n%s", body) } if !strings.Contains(body, `Sign in`) { t.Error("a gateway with accounts does not offer to sign in") } } func TestLinksBetweenDocumentsStayInThePortal(t *testing.T) { paths := map[string]string{"docs/install.md": "install", "docs/guardrails.md": "guardrails", "README.md": "readme", "CHANGELOG.md": "changes"} src := "See [install](install.md), [a section](install.md#2-the-control-plane), " + "[here](#local), [the readme](../README.md), [proxies](../deploy/proxy/), " + "[the plan](llmgw-plan.md) and [elsewhere](https://example.com/x.md).\n" body, _ := renderDoc(src, "docs/guardrails.md", paths) for _, want := range []string{ `href="/docs/install"`, `href="/docs/install#2-the-control-plane"`, `href="#local"`, `href="/docs/readme"`, // Not in the binary: the repository has it. `href="` + repoURL + `/src/branch/main/deploy/proxy/"`, `href="` + repoURL + `/src/branch/main/docs/llmgw-plan.md"`, `href="https://example.com/x.md"`, } { if !strings.Contains(string(body), want) { t.Errorf("rendered without %s:\n%s", want, body) } } // The README links into docs/ from the repository's root. body, _ = renderDoc("[guardrails](docs/guardrails.md)\n", "README.md", paths) if !strings.Contains(string(body), `href="/docs/guardrails"`) { t.Errorf("a link from the README: %s", body) } } func TestNoEmbeddedDocumentLinksToAPageThePortalLacks(t *testing.T) { // Every link a document makes into /docs/ must land on a page, or the // portal ships its own 404s. keys := map[string]bool{} for _, d := range manual() { keys[d.Key] = true } for _, d := range manual() { for _, part := range strings.Split(string(d.Body), `href="/docs/`)[1:] { key := part[:strings.IndexAny(part, `"#`)] if !keys[key] { t.Errorf("%s links to /docs/%s, which is not a page", d.Key, key) } } } } func TestAnUnknownDocumentIsNotFound(t *testing.T) { h := docsMux(Docs("v1", false)) for _, path := range []string{"/docs/no-such-doc", "/docs/..%2fgo.mod", "/docs/BACKLOG"} { if code, _ := get(t, h, path, nil); code != http.StatusNotFound { t.Errorf("%s: %d, want 404", path, code) } } // The file name works as well as the key: it is what the documents say. if code, _ := get(t, h, "/docs/install.md", nil); code != http.StatusOK { t.Errorf("/docs/install.md: %d", code) } } func TestTheDocsCarryThePolicyAndNoScript(t *testing.T) { for _, path := range []string{"/docs", "/docs/clients", "/docs/reference", "/docs/readme"} { rec := httptest.NewRecorder() docsMux(Docs("v1", false)).ServeHTTP(rec, httptest.NewRequest("GET", path, nil)) csp := rec.Header().Get("Content-Security-Policy") if !strings.Contains(csp, "script-src 'self';") || strings.Contains(csp, "sha256-") { t.Errorf("%s: policy %q, want this server's scripts and no inline one", path, csp) } if strings.Contains(strings.ToLower(rec.Body.String()), "Docs<`) || !strings.Contains(menu, `"/logout"`) { t.Errorf("the signed-in menu:\n%s", menu) } if !strings.Contains(signedIn.Header().Get("Cache-Control"), "no-store") { t.Error("a page with someone's menu on it may be cached") } public := docsMux(p.DocsPage(Docs("v0", true), false)) rec = httptest.NewRecorder() public.ServeHTTP(rec, httptest.NewRequest("GET", "/docs/install", nil)) if rec.Code != http.StatusOK || strings.Contains(rec.Body.String(), `"/logout"`) { t.Errorf("public, without a session: %d", rec.Code) } }