initial commit
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"path"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
webui "github.com/owen/vibedns/web"
|
||||
)
|
||||
|
||||
// TestTemplatesParse fails the build if any embedded template has a syntax
|
||||
// error or calls a function that is not registered. Without this, a typo in a
|
||||
// template only surfaces when a user opens that particular page.
|
||||
func TestTemplatesParse(t *testing.T) {
|
||||
tmpl, err := loadTemplates(templateFuncs())
|
||||
if err != nil {
|
||||
t.Fatalf("templates did not parse: %v", err)
|
||||
}
|
||||
|
||||
pages, err := fs.Glob(webui.Templates(), "pages/*.html")
|
||||
if err != nil {
|
||||
t.Fatalf("could not list pages: %v", err)
|
||||
}
|
||||
if len(pages) == 0 {
|
||||
t.Fatal("no page templates were embedded")
|
||||
}
|
||||
|
||||
for _, p := range pages {
|
||||
name := strings.TrimSuffix(path.Base(p), ".html")
|
||||
if _, ok := tmpl.sets[name]; !ok {
|
||||
t.Errorf("page %s produced no template set", name)
|
||||
}
|
||||
}
|
||||
t.Logf("parsed %d page templates", len(pages))
|
||||
}
|
||||
|
||||
// TestEveryRoutedPageHasTemplate guards against a handler rendering a page name
|
||||
// that does not exist, which would otherwise be a 500 at runtime.
|
||||
func TestEveryRoutedPageHasTemplate(t *testing.T) {
|
||||
tmpl, err := loadTemplates(templateFuncs())
|
||||
if err != nil {
|
||||
t.Fatalf("templates did not parse: %v", err)
|
||||
}
|
||||
|
||||
// Every name passed to s.render anywhere in the package.
|
||||
rendered := []string{
|
||||
"dashboard", "error", "zones", "zone_form", "records", "records_all",
|
||||
"resolver", "cache", "networks", "network_form", "policies", "policy_form",
|
||||
"lists", "list_detail", "querylog", "audit", "tools", "account",
|
||||
"settings_dns", "settings_resolver", "settings_cache", "settings_logging",
|
||||
"settings_http", "settings_database", "settings_api",
|
||||
}
|
||||
for _, name := range rendered {
|
||||
if _, ok := tmpl.sets[name]; !ok {
|
||||
t.Errorf("handler renders %q but no such template exists", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestStaticAssetsEmbedded confirms the offline assets actually made it into
|
||||
// the binary. The management interface must work without Internet access.
|
||||
func TestStaticAssetsEmbedded(t *testing.T) {
|
||||
static := webui.Static()
|
||||
required := []string{
|
||||
"css/bootstrap.min.css",
|
||||
"css/bootstrap-icons.min.css",
|
||||
"css/app.css",
|
||||
"js/bootstrap.bundle.min.js",
|
||||
"js/chart.umd.js",
|
||||
"js/app.js",
|
||||
"fonts/bootstrap-icons.woff2",
|
||||
"img/favicon.svg",
|
||||
}
|
||||
for _, name := range required {
|
||||
f, err := static.Open(name)
|
||||
if err != nil {
|
||||
t.Errorf("static asset %s is missing from the binary: %v", name, err)
|
||||
continue
|
||||
}
|
||||
info, err := f.Stat()
|
||||
if err == nil && info.Size() == 0 {
|
||||
t.Errorf("static asset %s is empty", name)
|
||||
}
|
||||
f.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// TestNoCDNReferences guards the offline guarantee: a stray absolute URL in a
|
||||
// template or stylesheet would silently break the UI on an air-gapped network.
|
||||
func TestNoCDNReferences(t *testing.T) {
|
||||
check := func(fsys fs.FS, label string) {
|
||||
err := fs.WalkDir(fsys, ".", func(p string, d fs.DirEntry, err error) error {
|
||||
if err != nil || d.IsDir() {
|
||||
return err
|
||||
}
|
||||
switch path.Ext(p) {
|
||||
case ".html", ".css", ".js":
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
body, err := fs.ReadFile(fsys, p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, bad := range []string{"https://cdn.", "http://cdn.", "//cdn.jsdelivr", "//unpkg.com"} {
|
||||
if strings.Contains(string(body), bad) {
|
||||
t.Errorf("%s/%s references an external CDN (%q); assets must be served from the binary",
|
||||
label, p, bad)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("walking %s: %v", label, err)
|
||||
}
|
||||
}
|
||||
check(webui.Templates(), "templates")
|
||||
check(webui.Static(), "static")
|
||||
}
|
||||
Reference in New Issue
Block a user