fix: store registry page timestamps in UTC
- GORM stamped created_at and updated_at in the process's local time, which the timestamp columns keep as the wall clock; east of UTC a page without a content date got a sitemap lastmod in the future - Page.BeforeSave stamps both in UTC for the admin's and the API's saves, and the admin's address change writes updated_at in UTC
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.golem15.com/golem15/sm-sitemap-plugin/contract"
|
||||
"git.golem15.com/golem15/summercms/modules/cooler"
|
||||
@@ -32,6 +33,58 @@ func (e *testEnv) refusal(t *testing.T, method, path, token string, body map[str
|
||||
}
|
||||
}
|
||||
|
||||
// TestRegistryTimestampsUTC pins the registry page's created_at and
|
||||
// updated_at in UTC on a machine east of UTC: the admin create, the
|
||||
// management API's update and the admin's address change each store the
|
||||
// UTC wall clock, so a page without a content date never gets a lastmod
|
||||
// in the future.
|
||||
func TestRegistryTimestampsUTC(t *testing.T) {
|
||||
local := time.Local
|
||||
time.Local = time.FixedZone("UTC+3", 3*60*60)
|
||||
t.Cleanup(func() { time.Local = local })
|
||||
env := bootEnv(t)
|
||||
token := env.admin(t, true)
|
||||
|
||||
stamps := func(id string) (created, updated time.Time) {
|
||||
t.Helper()
|
||||
var row struct {
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
if err := env.db.Raw(`SELECT created_at, updated_at FROM golem15_seo_pages WHERE id = ?`, id).Scan(&row).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return row.CreatedAt, row.UpdatedAt
|
||||
}
|
||||
within := func(what string, got, from, to time.Time) {
|
||||
t.Helper()
|
||||
if got.Before(from.Add(-time.Second)) || got.After(to.Add(time.Second)) {
|
||||
t.Fatalf("%s = %s, want between %s and %s (UTC)", what, got.Format(time.RFC3339), from.Format(time.RFC3339), to.Format(time.RFC3339))
|
||||
}
|
||||
}
|
||||
|
||||
from := time.Now().UTC()
|
||||
id := env.createRegistryPage(t, token, map[string]any{"url": map[string]any{"en": "/kontakt"}, "title": map[string]any{"en": "Kontakt"}})
|
||||
created, updated := stamps(id)
|
||||
within("created_at after the admin create", created, from, time.Now().UTC())
|
||||
within("updated_at after the admin create", updated, from, time.Now().UTC())
|
||||
|
||||
from = time.Now().UTC()
|
||||
env.expect(t, http.StatusOK, http.MethodPut, "/_seo/api/v1/pages/"+id, token, map[string]any{"title": "Kontakt z nami", "content_updated_at": ""})
|
||||
_, updated = stamps(id)
|
||||
within("updated_at after the API update", updated, from, time.Now().UTC())
|
||||
reg, _ := env.app.Lookup[*signpost.Registry]()
|
||||
rec, err := reg.Describe(t.Context(), "seo-page", id, "")
|
||||
if err != nil || rec == nil || rec.LastMod == nil || rec.LastMod.After(time.Now().UTC().Add(time.Second)) {
|
||||
t.Fatalf("describe = %+v err=%v, want a lastmod no later than now", rec, err)
|
||||
}
|
||||
|
||||
from = time.Now().UTC()
|
||||
env.expect(t, http.StatusOK, http.MethodPut, pagesAPI+"/"+id, token, map[string]any{"url": map[string]any{"en": "/kontakt-z-nami"}})
|
||||
_, updated = stamps(id)
|
||||
within("updated_at after the admin address change", updated, from, time.Now().UTC())
|
||||
}
|
||||
|
||||
// TestRegistry covers the page registry (D-33, UI-SPEC C21): a page made
|
||||
// in the Pages screen is a seo-page record with the SEO tab, resolves ok,
|
||||
// is listed in the sitemap file of its kind with hreflang alternates, the
|
||||
|
||||
Reference in New Issue
Block a user