package render import ( "html/template" "net/http/httptest" "testing" ) // stubFuncMap satisfies every function name the embedded templates reference // (see New's doc comment for the full list) with the minimum needed to parse. // The real implementations live in package content (funcmap.go), which itself // imports render — so render's own test cannot import content without a // cycle, and stands up its own stand-in instead. This only proves the // template set PARSES against the real function names; content_test.go (via // content.FuncMap) is what proves they render correctly. func stubFuncMap() template.FuncMap { return template.FuncMap{ "temp": func(unit, f any) template.HTML { return "" }, "temp_bare": func(unit, f any) template.HTML { return "" }, "temp_class": func(f any) string { return "" }, "ordinal": func(pct any) string { return "" }, "head_verify": func() template.HTML { return "" }, "tojson": func(v any) (template.HTML, error) { return "", nil }, "comment": func(s string) template.HTML { return "" }, "jscomment": func(s string) template.JS { return "" }, } } func TestETagFormat(t *testing.T) { // Same construction as the Python: W/"sha1(body)[:20]". // sha1("hello") = aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d got := ETag([]byte("hello")) want := `W/"aaf4c61ddcc5e8a2dabe"` if got != want { t.Errorf("ETag = %s, want %s", got, want) } } func TestNotModifiedAnySplitsOnCommas(t *testing.T) { etag := `W/"abc"` if !NotModifiedAny(`W/"zzz", W/"abc"`, etag) { t.Error("comma-separated candidate list should match") } if !NotModifiedAny(`W/"abc"`, etag) { t.Error("single candidate should match") } if NotModifiedAny("", etag) { t.Error("empty header must not match") } if NotModifiedAny(`W/"zzz"`, etag) { t.Error("non-matching header must not match") } } func TestNotModifiedExact(t *testing.T) { etag := `W/"abc"` if !NotModifiedExact(`W/"abc"`, etag) { t.Error("exact match should match") } // app.py's _page compared the raw header — a comma list is NOT split there. if NotModifiedExact(`W/"zzz", W/"abc"`, etag) { t.Error("exact comparison must not split on commas") } } func TestWriteHTML(t *testing.T) { body := []byte("x") etag := ETag(body) rec := httptest.NewRecorder() req := httptest.NewRequest("GET", "/", nil) WriteHTML(rec, req, body) if rec.Code != 200 || rec.Body.String() != string(body) { t.Errorf("fresh GET: code=%d body=%q", rec.Code, rec.Body.String()) } if got := rec.Header().Get("Content-Type"); got != "text/html; charset=utf-8" { t.Errorf("Content-Type = %q", got) } if got := rec.Header().Get("ETag"); got != etag { t.Errorf("ETag header = %q, want %q", got, etag) } rec = httptest.NewRecorder() req = httptest.NewRequest("GET", "/", nil) req.Header.Set("If-None-Match", etag) WriteHTML(rec, req, body) if rec.Code != 304 { t.Errorf("conditional GET: code = %d, want 304", rec.Code) } if rec.Body.Len() != 0 { t.Error("304 must have an empty body") } if got := rec.Header().Get("ETag"); got != etag { t.Errorf("304 must still carry the ETag, got %q", got) } } func TestEngineParsesEmbeddedTemplates(t *testing.T) { if _, err := New(stubFuncMap()); err != nil { t.Fatalf("New: %v", err) } }