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)
}
}