package catalog import ( "strings" "testing" "time" ) func TestEncodeDecodeProductCursorRoundTrip(t *testing.T) { ts := time.Date(2026, 8, 4, 12, 0, 0, 0, time.UTC) f := ListFilter{SortBy: "updatedAt", SortOrder: "desc"} item := map[string]any{ "id": "00000000-0000-4000-8000-000000000099", "updated_at": ts, } enc, err := EncodeProductCursor(f, item) if err != nil { t.Fatal(err) } if enc == "" { t.Fatal("empty cursor") } cur, err := DecodeProductCursor(enc) if err != nil { t.Fatal(err) } if cur.ID != "00000000-0000-4000-8000-000000000099" { t.Fatalf("id=%q", cur.ID) } if cur.SB != "updatedAt" || cur.SO != "desc" { t.Fatalf("sort meta: %+v", cur) } if !strings.HasPrefix(cur.K, "2026-08-04T12:00:00") { t.Fatalf("key=%q", cur.K) } } func TestNextProductCursor(t *testing.T) { f := ListFilter{SortBy: "updatedAt", SortOrder: "desc"} items := []map[string]any{ {"id": "00000000-0000-4000-8000-000000000001", "updated_at": time.Now().UTC()}, {"id": "00000000-0000-4000-8000-000000000002", "updated_at": time.Now().UTC()}, } next, after := NextProductCursor(f, items, 2) if next == "" || after != "00000000-0000-4000-8000-000000000002" { t.Fatalf("next=%q after=%q", next, after) } none, noneAfter := NextProductCursor(f, items[:1], 2) if none != "" || noneAfter != "" { t.Fatalf("short page should end: next=%q after=%q", none, noneAfter) } } func TestHasProductCursorClearsOffset(t *testing.T) { f := NormalizeListFilter(ListFilter{Offset: 500, AfterID: "00000000-0000-4000-8000-000000000001"}) if !HasProductCursor(f) { t.Fatal("expected cursor") } if f.Offset != 0 { t.Fatalf("offset should clear with cursor: %d", f.Offset) } }