Go · 1675 bytes Raw Blame History
1 // SPDX-License-Identifier: AGPL-3.0-or-later
2
3 package handlers
4
5 import (
6 "io"
7 "log/slog"
8 "net/http/httptest"
9 "os"
10 "testing"
11
12 "github.com/tenseleyFlow/shithub/internal/web/render"
13 )
14
15 // TestHelloHandler_RendersAgainstRealTemplates exercises the homepage
16 // handler against the real templates on disk (NOT the embed.FS, since
17 // importing internal/web from internal/web/handlers would cycle). The
18 // repo layout makes this safe: tests run with cwd = package dir, so
19 // os.DirFS("../templates") reads internal/web/templates/.
20 //
21 // This is a regression for an outage on 2026-05-09: _nav.html started
22 // referencing .GlobalSearchQuery and the typed helloData struct didn't
23 // carry the field, so every request to / returned 500 from a template
24 // execute error. html/template parses fine — the failure only shows
25 // at exec time, and only when the data is a typed struct (maps swallow
26 // missing keys under `with`). Hence: render the actual handler with
27 // the actual struct against the actual templates.
28 func TestHelloHandler_RendersAgainstRealTemplates(t *testing.T) {
29 t.Parallel()
30
31 tmplFS := os.DirFS("../templates")
32 r, err := render.New(tmplFS, render.Options{})
33 if err != nil {
34 t.Fatalf("render.New on real templates: %v", err)
35 }
36
37 logo, err := os.ReadFile("../static/logo/shithub.svg")
38 if err != nil {
39 t.Fatalf("read logo: %v", err)
40 }
41
42 h := helloHandler{
43 render: r,
44 logoSVG: string(logo),
45 logger: slog.New(slog.NewTextHandler(io.Discard, nil)),
46 }
47
48 req := httptest.NewRequest("GET", "/", nil)
49 rw := httptest.NewRecorder()
50 h.ServeHTTP(rw, req)
51
52 if rw.Code != 200 {
53 t.Fatalf("expected 200, got %d; body=%s", rw.Code, rw.Body.String())
54 }
55 }
56