package seed_test import ( "strings" "testing" "github.com/urpi/go-bananas/internal/domain" "github.com/urpi/go-bananas/internal/seed" "github.com/urpi/go-bananas/internal/tokenengine" ) // TestGoTellSlugsAreSeeded is the one that matters for adoption. // // go-tell's theme switcher offers cyberpunk, nordic, obsidian and terminal, and its // stylesheet keys on html[data-theme=""]. If any of those slugs is missing from // the service, selecting it sets an attribute that resolves to nothing and the // application falls back to whichever rule happens to match last. That is invisible in // a smoke test and obvious to a user, so it is asserted here. func TestGoTellSlugsAreSeeded(t *testing.T) { want := []string{"cyberpunk", "nordic", "obsidian", "terminal"} have := map[string]bool{} for _, slug := range seed.Slugs() { have[slug] = true } for _, slug := range want { if !have[slug] { t.Errorf("go-tell's %q palette is not seeded, so selecting it would do nothing", slug) } } } // TestEveryConsolidatedPaletteResolvesInBothAppearances is the property the contract // depends on, and it is expressed through the engine rather than through the token // document's shape. // // The shape is deliberately not the assertion. In this schema the base document *is* // the light scheme and `$appearances` carries only the dark override, so a theme with // both schemes still has one key under `$appearances`. What matters is that resolving // a consolidated palette in each appearance yields a different background, which is // what makes the appearance control do anything at all. func TestEveryConsolidatedPaletteResolvesInBothAppearances(t *testing.T) { for _, def := range seed.All() { if !strings.Contains(def.Description, "go-") { continue // an original go-bananas theme, not a consolidated one } theme := def.Theme() light := tokenengine.Resolve(theme, domain.AppearanceLight) dark := tokenengine.Resolve(theme, domain.AppearanceDark) read := func(doc *tokenengine.Doc, path string) string { token, ok := doc.Lookup(path) if !ok { return "" } return token.CSS } lightBg := read(light, "color.semantic.background") darkBg := read(dark, "color.semantic.background") if lightBg == "" || darkBg == "" { t.Errorf("%s does not resolve a background in both appearances (light=%q dark=%q)", def.Slug, lightBg, darkBg) continue } if lightBg == darkBg { t.Errorf("%s resolves the same background in both appearances (%s), "+ "so the appearance control would do nothing for it", def.Slug, lightBg) } // Text has to differ too, or a palette with a dark background and dark text // would pass the background check and be unreadable. if read(light, "color.semantic.text") == read(dark, "color.semantic.text") { t.Errorf("%s resolves the same text colour in both appearances", def.Slug) } } }