diff --git a/go/http/render_test.go b/go/http/render_test.go index 6ab1ad8f..ba03fe76 100644 --- a/go/http/render_test.go +++ b/go/http/render_test.go @@ -22,8 +22,11 @@ import ( "net/http/httptest" "os" "path/filepath" + "regexp" "strings" "testing" + + "github.com/go-chi/chi/v5" ) // chdirToRepoRoot finds the repository root (directory containing resources/templates) @@ -134,6 +137,44 @@ func TestRenderHTMLYield(t *testing.T) { } } +func TestLayoutWebLinksHaveRegisteredRoutes(t *testing.T) { + chdirToRepoRoot(t) + clearContentTemplateCache() + + rec := httptest.NewRecorder() + renderHTML(rec, http.StatusOK, "templates/clusters", sampleTemplateData()) + if rec.Code != http.StatusOK { + t.Fatalf("status = %d, body = %s", rec.Code, rec.Body.String()) + } + + router := chi.NewRouter() + web := HttpWeb{} + web.RegisterRequests(router) + + registeredGETRoutes := make(map[string]struct{}) + err := chi.Walk(router, func(method, route string, _ http.Handler, _ ...func(http.Handler) http.Handler) error { + if method == http.MethodGet { + registeredGETRoutes[route] = struct{}{} + } + return nil + }) + if err != nil { + t.Fatal(err) + } + + hrefPattern := regexp.MustCompile(`href="(/web/[^"#?]+)"`) + matches := hrefPattern.FindAllStringSubmatch(rec.Body.String(), -1) + if len(matches) == 0 { + t.Fatal("rendered layout contains no constant /web/ links") + } + for _, match := range matches { + href := match[1] + if _, ok := registeredGETRoutes[href]; !ok { + t.Errorf("navbar link %q has no matching GET route", href) + } + } +} + // TestLayoutRequiresYield guards the martini-contrib/render contract: layout.tmpl // uses {{yield}} to inject page content. Parsing layout without that FuncMap must fail. func TestLayoutRequiresYield(t *testing.T) { diff --git a/resources/templates/layout.tmpl b/resources/templates/layout.tmpl index 7775c307..2455f0a5 100644 --- a/resources/templates/layout.tmpl +++ b/resources/templates/layout.tmpl @@ -65,8 +65,8 @@ Clusters