go-bananas/internal/seed/consolidated_test.go

81 lines
2.8 KiB
Go
Raw Permalink Normal View History

2026-10-07 15:11:35 +02:00
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="<slug>"]. 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)
}
}
}