package middleware_test import ( "context" "crypto/sha256" "encoding/base64" "regexp" "strings" "testing" "bookhoard/internal/middleware" "bookhoard/templates" ) // TestThemeFlashGuardHashMatchesCSP pins the CSP script hash to the theme // flash guard's rendered bytes: the guard is the app's ONLY inline script, // and script-src allow-lists it by content hash. If the guard's script text // is ever edited, this test fails and prints the replacement hash — copy it // into middleware.ScriptHashThemeFlashGuard. func TestThemeFlashGuardHashMatchesCSP(t *testing.T) { var sb strings.Builder if err := templates.ThemeFlashGuard().Render(context.Background(), &sb); err != nil { t.Fatalf("render ThemeFlashGuard: %v", err) } rendered := sb.String() m := regexp.MustCompile(`(?s)`).FindStringSubmatch(rendered) if m == nil { t.Fatalf("rendered guard contains no of templates/theme_flash_guard.templ, base64-encoded, then update middleware.ScriptHashThemeFlashGuard and the CSP header string.`, middleware.ScriptHashThemeFlashGuard, computed) } // The strict allow-list only holds the guard: no 'unsafe-inline' may // sneak back into script-src (style-src keeps it for htmx/Alpine). if strings.Contains(middleware.ScriptHashThemeFlashGuard, "unsafe-inline") { t.Error("script-src must not re-introduce 'unsafe-inline' alongside the hash") } }