package web
import (
"go/ast"
"go/parser"
"go/token"
"html/template"
"os"
"path/filepath"
"strings"
"testing"
)
// Every page template is registered, so every handler draws it with its
// own hooks. A page cloned from base but left unregistered keeps the
// hooks base was parsed with — noHooks — and silently draws without
// namespaces, uploaded marks or agent badges whichever handler serves it.
func TestEveryPageTemplateIsRegistered(t *testing.T) {
files, err := filepath.Glob("*.go")
if err != nil {
t.Fatal(err)
}
fs := token.NewFileSet()
pages := 0
for _, name := range files {
if strings.HasSuffix(name, "_test.go") {
continue
}
src, err := os.ReadFile(name)
if err != nil {
t.Fatal(err)
}
f, err := parser.ParseFile(fs, name, src, 0)
if err != nil {
t.Fatal(err)
}
for _, d := range f.Decls {
g, ok := d.(*ast.GenDecl)
if !ok || g.Tok != token.VAR {
continue
}
for _, sp := range g.Specs {
vs := sp.(*ast.ValueSpec)
for i, v := range vs.Values {
text := string(src[fs.Position(v.Pos()).Offset:fs.Position(v.End()).Offset])
if !strings.Contains(text, ".Clone()") && !strings.Contains(text, ".clone()") {
continue
}
if call, ok := v.(*ast.CallExpr); ok {
if id, ok := call.Fun.(*ast.Ident); ok && id.Name == "page" {
pages++
continue
}
}
t.Errorf("FAIL: %s: %s is a cloned template that is not registered with page()",
fs.Position(v.Pos()), vs.Names[i].Name)
}
}
}
}
if pages != len(pristine) {
t.Errorf("FAIL: %d page() declarations, %d registered", pages, len(pristine))
}
t.Logf("ok: %d page templates, all registered", pages)
}
// A pristine template that has somehow been executed cannot be cloned.
// Drawing it must not then fail every later request for that page: the
// copy falls back to the template itself, drawn without hooks.
func TestAnExecutedPageFallsBackInsteadOfFailing(t *testing.T) {
tpl := template.Must(template.New("t").Parse(`<p>{{.}}</p>`))
var b strings.Builder
if err := tpl.Execute(&b, "x"); err != nil {
t.Fatal(err)
}
got := drawnCopy(tpl, nil)
if got != tpl {
t.Fatalf("FAIL: an executed template did not fall back to itself")
}
b.Reset()
if err := got.Execute(&b, "y"); err != nil || b.String() != "<p>y</p>" {
t.Fatalf("FAIL: the fallback does not draw: %q %v", b.String(), err)
}
t.Log("ok: an executed page falls back and still draws")
}