package modules import ( "html/template" "os" "path/filepath" "strings" "testing" "gsg/internal/core" "gsg/internal/notices" ) // Global notices come before the repository's own; a site-scoped Ctx (nil // Repo, empty Slug) gets the global list only and must not panic. func TestNoticesModMergesGlobalThenRepo(t *testing.T) { path := filepath.Join(t.TempDir(), "notices.yaml") st, err := notices.Open(path) if err != nil { t.Fatal(err) } t.Cleanup(st.Close) err = st.Set(notices.Document{ Global: []notices.Notice{{Type: notices.TypeCritical, Title: "global"}}, Repos: map[string][]notices.Notice{"demo": {{Type: notices.TypeInfo, Title: "repo"}}}, }) if err != nil { t.Fatal(err) } notices.SetDefault(st) t.Cleanup(func() { notices.SetDefault(nil) }) v, err := noticesMod(&core.Ctx{Info: core.RepoInfo{Slug: "demo"}}) if err != nil { t.Fatal(err) } got, ok := v.([]notices.Notice) if !ok { t.Fatalf("notices returned %T", v) } if len(got) != 2 || got[0].Title != "global" || got[1].Title != "repo" { t.Fatalf("got %+v", got) } v, err = noticesMod(&core.Ctx{}) if err != nil { t.Fatal(err) } if got := v.([]notices.Notice); len(got) != 1 || got[0].Title != "global" { t.Fatalf("site-scoped got %+v", got) } } // The notices partial must render nothing on a page that will be cached // immutably, and must not even call the module there -- the guard wraps the // modOr call, not just its output. func TestNoticesPartialSuppressesImmutable(t *testing.T) { src, err := os.ReadFile("../../templates/layouts/notices.html") if err != nil { t.Fatal(err) } calls := 0 tmpl, err := template.New("notices.html").Funcs(template.FuncMap{ "modOr": func(string, ...string) any { calls++ return []notices.Notice{{Type: notices.TypeInfo, Title: "banner"}} }, }).Parse(string(src)) if err != nil { t.Fatal(err) } render := func(immutable bool) string { var sb strings.Builder if err := tmpl.ExecuteTemplate(&sb, "notices", struct{ Immutable bool }{immutable}); err != nil { t.Fatal(err) } return sb.String() } got := render(true) if strings.Contains(got, "banner") || calls != 0 { t.Fatalf("immutable page rendered notices (calls=%d): %q", calls, got) } got = render(false) if !strings.Contains(got, "banner") || calls != 1 { t.Fatalf("non-immutable page did not render (calls=%d): %q", calls, got) } }