package templates_test import ( "bytes" "html/template" "strings" "testing" "git.eeqj.de/sneak/routewatch/internal/templates" ) // renderPage renders a page with the data every page needs. func renderPage(t *testing.T, tmpl *template.Template) string { t.Helper() var page bytes.Buffer err := tmpl.Execute(&page, struct{ CSPNonce string }{}) if err != nil { t.Fatalf("rendering the page: %v", err) } return page.String() } // TestFooterLicense renders the home and status pages and expects each footer // to name the licence in LICENSE, MIT, and not WTFPL. func TestFooterLicense(t *testing.T) { t.Parallel() const ( license = "MIT" wrongLicense = "WTFPL" ) pages := map[string]*template.Template{ "index": templates.IndexTemplate(), "status": templates.StatusTemplate(), } for name, tmpl := range pages { t.Run(name, func(t *testing.T) { t.Parallel() _, footer, found := strings.Cut(renderPage(t, tmpl), "") if !strings.Contains(footer, license) { t.Errorf("footer does not name %s: %q", license, footer) } if strings.Contains(footer, wrongLicense) { t.Errorf("footer names %s: %q", wrongLicense, footer) } }) } } // TestFreshnessIndicator renders the home and status pages and expects each to // have, right after the status element, the element where the page's script // shows its spinner or "stale". func TestFreshnessIndicator(t *testing.T) { t.Parallel() pages := map[string]struct { tmpl *template.Template status string indicator string }{ "index": { tmpl: templates.IndexTemplate(), status: `-`, indicator: ``, }, "status": { tmpl: templates.StatusTemplate(), status: `-`, indicator: ``, }, } for name, page := range pages { t.Run(name, func(t *testing.T) { t.Parallel() _, afterStatus, found := strings.Cut(renderPage(t, page.tmpl), page.status) if !found { t.Fatalf("the page has no status element %s", page.status) } if !strings.HasPrefix(strings.TrimSpace(afterStatus), page.indicator) { t.Errorf("the status element is not followed by %s", page.indicator) } }) } }