- pact: the content kinds and tools, zero facts, the value types - cabana: mergeRequestOptions precedence, one call per type, fail-open, no shared maps - attach: VariantKey on thumbnail names - attach/webp: every image kind, the stored content type, the broken-image thumbnail and a refused mode
102 lines
3.8 KiB
Go
102 lines
3.8 KiB
Go
package pact
|
|
|
|
import (
|
|
"encoding/json"
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// TestContentKindAndToolValues pins the wire values of the content kinds
|
|
// and tools: plugins store and compare them as strings, so a value never
|
|
// changes once released, and each is distinct and lower-case.
|
|
func TestContentKindAndToolValues(t *testing.T) {
|
|
kinds := map[string]string{
|
|
ContentKindArticle: "article",
|
|
ContentKindCollection: "collection",
|
|
ContentKindProfile: "profile",
|
|
ContentKindPage: "page",
|
|
}
|
|
tools := map[string]string{
|
|
ContentToolEdit: "edit",
|
|
ContentToolHeadings: "headings",
|
|
ContentToolImageAlt: "image_alt",
|
|
}
|
|
for _, set := range []map[string]string{kinds, tools} {
|
|
seen := map[string]bool{}
|
|
for got, want := range set {
|
|
if got != want {
|
|
t.Errorf("constant = %q, want %q", got, want)
|
|
}
|
|
if seen[got] {
|
|
t.Errorf("%q is used twice", got)
|
|
}
|
|
seen[got] = true
|
|
}
|
|
}
|
|
if len(kinds) != 4 || len(tools) != 3 {
|
|
t.Fatalf("%d kinds and %d tools, want 4 and 3 distinct values", len(kinds), len(tools))
|
|
}
|
|
}
|
|
|
|
// TestContentRecordZeroFacts pins the additive contract: a record and a
|
|
// locale built without the new facts carry their zero values (no date, no
|
|
// parents or authors, TopHeading 0 for "not known", no images, videos or
|
|
// headings), and a descriptor without Kind or Tools says nothing.
|
|
func TestContentRecordZeroFacts(t *testing.T) {
|
|
rec := ContentRecord{ID: "1", Published: true, Locales: []ContentLocale{{Locale: "en", URL: "/a", Title: "A"}}}
|
|
if rec.PublishedAt != nil || rec.Parents != nil || rec.Authors != nil || rec.TopHeading != 0 {
|
|
t.Fatalf("record facts = %+v, want zero", rec)
|
|
}
|
|
l := rec.Locales[0]
|
|
if l.Images != nil || l.Videos != nil || l.Headings != nil {
|
|
t.Fatalf("locale facts = %+v, want zero", l)
|
|
}
|
|
var d ContentDescriptor
|
|
if d.Kind != "" || d.Tools != nil {
|
|
t.Fatalf("descriptor = %+v, want no kind and no tools", d)
|
|
}
|
|
}
|
|
|
|
// TestContentValueTypes pins the value types' fields: a record with every
|
|
// fact set round-trips through a copy, and the value types are plain data
|
|
// (comparable where they hold no slice), so plugins can key maps by a ref.
|
|
func TestContentValueTypes(t *testing.T) {
|
|
at := time.Date(2026, 11, 4, 10, 0, 0, 0, time.UTC)
|
|
rec := ContentRecord{
|
|
ID: "7",
|
|
Published: true,
|
|
PublishedAt: &at,
|
|
Parents: []ContentRef{{Type: "acme-category", ID: "3"}},
|
|
Authors: []ContentPerson{{Name: "Ada", Ref: ContentRef{Type: "acme-author", ID: "1"}}, {Name: "Guest"}},
|
|
TopHeading: 2,
|
|
Locales: []ContentLocale{{
|
|
Locale: "en",
|
|
URL: "/posts/x",
|
|
Images: []ContentImage{{URL: "/m/a.jpg", Alt: "A cap", Width: 800, Height: 600}, {URL: "/m/line.png", Decorative: true}},
|
|
Videos: []ContentVideo{{Provider: "youtube", ID: "abc"}},
|
|
Headings: []ContentHeading{{Level: 2, Text: "Intro"}, {Level: 3, Text: "Detail"}},
|
|
}},
|
|
}
|
|
raw, err := json.Marshal(rec)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var back ContentRecord
|
|
if err := json.Unmarshal(raw, &back); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !reflect.DeepEqual(back.Parents, rec.Parents) || !reflect.DeepEqual(back.Authors, rec.Authors) || back.TopHeading != 2 ||
|
|
!back.PublishedAt.Equal(at) || !reflect.DeepEqual(back.Locales[0].Images, rec.Locales[0].Images) ||
|
|
!reflect.DeepEqual(back.Locales[0].Videos, rec.Locales[0].Videos) || !reflect.DeepEqual(back.Locales[0].Headings, rec.Locales[0].Headings) {
|
|
t.Fatalf("round trip = %+v, want %+v", back, rec)
|
|
}
|
|
refs := map[ContentRef]bool{{Type: "acme-category", ID: "3"}: true}
|
|
if !refs[rec.Parents[0]] || refs[rec.Authors[0].Ref] {
|
|
t.Fatal("ContentRef must work as a map key")
|
|
}
|
|
if (ContentHeading{Level: 2, Text: "Intro"}) != rec.Locales[0].Headings[0] || (ContentVideo{Provider: "youtube", ID: "abc"}) != rec.Locales[0].Videos[0] {
|
|
t.Fatal("headings and videos must compare by value")
|
|
}
|
|
}
|