Skip to content
quarry Artifact [ec4eebd176]
Login

Artifact [ec4eebd176]

Artifact ec4eebd1761b2fea7fe85c57cbc0f801bc176885f4e7698a8bba877cf398a1cf:


package web

import (
	"go/ast"
	"go/parser"
	"go/token"
	"html/template"
	"os"
	"path/filepath"
	"strings"
	"testing"

	"craftdesign.group/quarry/internal/errlog"
)

// 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)
	}
	was := errlog.Default
	errlog.Default = errlog.New(50)
	t.Cleanup(func() { errlog.Default = was })
	got := drawnCopy(tpl, nil)
	if got != tpl {
		t.Fatalf("FAIL: an executed template did not fall back to itself")
	}
	// A page that lost its hooks draws plausibly, so nobody would see
	// it: the journal is where it has to show.
	if j := errlog.Default.Recent(50); len(j) != 1 || j[0].Surface != "template" || j[0].Path != "t" {
		t.Fatalf("FAIL: the fallback is not journalled as the page's template fault: %+v", j)
	}
	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")
}