package main import ( "io/fs" "net/http" "net/http/httptest" "regexp" "testing" ) // Every {{asset "…"}} in the templates must name an embedded file, or the page // fails to render. func TestTemplateAssetsExist(t *testing.T) { ref := regexp.MustCompile(`\{\{asset "([^"]+)"\}\}`) _ = fs.WalkDir(assets, "assets", func(p string, d fs.DirEntry, err error) error { if err != nil || d.IsDir() { return err } b, _ := assets.ReadFile(p) for _, m := range ref.FindAllSubmatch(b, -1) { if _, err := assetURL(string(m[1])); err != nil { t.Errorf("%s: %v", p, err) } } return nil }) } func TestServeStaticCaching(t *testing.T) { h := serveStatic() get := func(url, ifNoneMatch string) *httptest.ResponseRecorder { r := httptest.NewRequest(http.MethodGet, url, nil) if ifNoneMatch != "" { r.Header.Set("If-None-Match", ifNoneMatch) } w := httptest.NewRecorder() h.ServeHTTP(w, r) return w } v := assetVersions["style.css"] versioned, _ := assetURL("style.css") if w := get(versioned, ""); w.Code != 200 || w.Header().Get("Cache-Control") != "public, max-age=31536000, immutable" { t.Errorf("versioned: %d %q", w.Code, w.Header().Get("Cache-Control")) } for _, u := range []string{"/_/style.css", "/_/style.css?v=stale"} { w := get(u, "") if w.Code != 200 || w.Header().Get("Cache-Control") != "no-cache" || w.Header().Get("ETag") != `"`+v+`"` { t.Errorf("%s: %d %q %q", u, w.Code, w.Header().Get("Cache-Control"), w.Header().Get("ETag")) } } if w := get("/_/style.css", `"`+v+`"`); w.Code != http.StatusNotModified { t.Errorf("revalidate: got %d, want 304", w.Code) } if w := get("/_/fonts/IosevkaSlab.woff2", ""); w.Header().Get("Cache-Control") != "public, max-age=31536000, immutable" { t.Errorf("font: %q", w.Header().Get("Cache-Control")) } }