package classes import ( "slices" "strings" "testing" "time" "git.golem15.com/golem15/summercms/modules/compass" "git.golem15.com/golem15/summercms/modules/pact" ) // TestRealChanges pins which saves move lastmod (D-30, RESEARCH Pitfall // 4): nothing for an empty or ignored-only change list; every locale for a // change on the record's own row; only the named locales for translated // changes. func TestRealChanges(t *testing.T) { ignore := map[string]bool{"updated_at": true, "views": true} for name, c := range map[string]struct { changes []pact.RecordChange any bool all bool locales []string }{ "no-op save": {nil, false, false, nil}, "ignored only": {[]pact.RecordChange{{Attribute: "updated_at"}, {Attribute: "views"}}, false, false, nil}, "own row": {[]pact.RecordChange{{Attribute: "updated_at"}, {Attribute: "title"}}, true, true, nil}, "translated": {[]pact.RecordChange{{Attribute: "title", Locale: "pl"}, {Attribute: "slug", Locale: "de"}}, true, false, []string{"de", "pl"}}, "both": {[]pact.RecordChange{{Attribute: "title", Locale: "pl"}, {Attribute: "content"}}, true, true, nil}, } { got := RealChanges(c.changes, ignore) if got.Any != c.any || got.All != c.all || len(got.Locales) != len(c.locales) { t.Errorf("%s: %+v", name, got) continue } for _, l := range c.locales { if !got.Locales[l] { t.Errorf("%s: locale %s missing in %+v", name, l, got) } } } } // TestLastmodIgnore pins golem15.sitemap.lastmod_ignore: the default list // when unset, a YAML list or a comma-separated string replacing it (names // trimmed, blanks dropped), and an empty list ignoring nothing. func TestLastmodIgnore(t *testing.T) { keys := func(m map[string]bool) string { out := make([]string, 0, len(m)) for k := range m { out = append(out, k) } slices.Sort(out) return strings.Join(out, ",") } if got := keys(LastmodIgnore(nil)); got != "created_at,sort_order,updated_at,views" { t.Fatalf("default = %s", got) } for _, tc := range []struct { value any want string }{ {[]any{"updated_at", " hits ", ""}, "hits,updated_at"}, {[]string{"a", "b"}, "a,b"}, {" views , rank,,", "rank,views"}, {[]any{}, ""}, } { cfg := testConfig(t) if err := cfg.Set(LastmodIgnoreConfigKey, tc.value); err != nil { t.Fatal(err) } if got := keys(LastmodIgnore(cfg)); got != tc.want { t.Errorf("LastmodIgnore(%#v) = %s, want %s", tc.value, got, tc.want) } } } // TestRebuildDelay pins golem15.sitemap.rebuild_delay_seconds: 60 s when // unset, the value in seconds, and 0 for 0 or a negative value. func TestRebuildDelay(t *testing.T) { if RebuildDelay(nil) != time.Minute || RebuildDelay(testConfig(t)) != time.Minute { t.Fatal("default delay is not 60 s") } for value, want := range map[int]time.Duration{5: 5 * time.Second, 0: 0, -3: 0} { cfg := testConfig(t) if err := cfg.Set(RebuildDelayConfigKey, value); err != nil { t.Fatal(err) } if got := RebuildDelay(cfg); got != want { t.Errorf("RebuildDelay(%d) = %s, want %s", value, got, want) } } } func testConfig(t *testing.T) *compass.Config { t.Helper() cfg, err := compass.Open(compass.Options{Dir: t.TempDir()}) if err != nil { t.Fatal(err) } return cfg } // TestRecordSavedNilEvent pins L2 IN-01: a nil event is ignored before it // is read. func TestRecordSavedNilEvent(t *testing.T) { if err := RecordSaved(t.Context(), nil, nil); err != nil { t.Fatal(err) } if err := RecordDeleted(t.Context(), nil, nil); err != nil { t.Fatal(err) } }