package fiesta import ( "os" "strings" "testing" "time" ) // This file is rastrillo's cssfloor_test.go aimed at Fiesta's two // documents, plus the two checks that hold the README and the // changelog to the release they describe. // cssFloor is the engine floor the stylesheets impose on every page // that links them. It is derived, not chosen: take the features // tokens.css and the three themes use, and keep the highest engine // version among them. light-dark() sets it everywhere except Firefox, // where :has() does. Both documents state the result, because a // reader who cannot find the floor invents one: an agent building on // rastrillo once refused oklch() as "a 2023-era browser feature" and // reached for hex twins, which protect nobody, since an engine too old // for oklch() dropped the whole light-dark() palette several // declarations earlier. // // Two files stating one fact can drift into two facts. // TestCSSFloorIsStatedTheSameInBothFiles holds them equal. Both // hard-wrap prose, so the comparison normalises whitespace: the string // may break across a line, it may not disagree. const cssFloor = "Chrome 123, Safari 17.5, Firefox 121" // The adoption policy is a rolling one: a feature is fair game once it // has been in all three engines about a year. A rolling policy with no // clock is a lapsed one nobody has noticed yet, and these two constants // are the clock. // // What does not move when the policy rolls is the floor. It rises only // when someone writes a newer feature into the CSS, so "anything a year // old may be used" and "today we bottom out at Chrome 123" stay true // together. That is also why the review is by hand: the computable // half, what is now a year old, was never the hard half. The judgement // is which of those to want, and every yes raises the floor for every // page that links the CSS. // // Nine months rather than twelve, so a review that slips a release // still lands inside the year the policy names. // // Answering the failure means re-deriving, not bumping the date: list // the features css/tokens.css and css/themes/*.css use, take the // highest engine version among them, and if it differs from cssFloor // change it here, in README.md and in DESIGN.md together. Then set // floorReviewed to the day you did it. const ( floorReviewed = "2026-09-01" floorReviewMonths = 9 ) // floorFiles are the documents that state the floor: the README, for // someone deciding whether to link the CSS, and DESIGN.md, for someone // writing against it. var floorFiles = []string{"README.md", "DESIGN.md"} // TestCSSFloorIsStatedTheSameInBothFiles fails when the README and // DESIGN.md disagree about the floor, or either leaves it out. They // are written for different readers, and a reader who checks one // against the other and finds two numbers trusts neither. func TestCSSFloorIsStatedTheSameInBothFiles(t *testing.T) { for _, path := range floorFiles { b, err := os.ReadFile(path) if err != nil { t.Errorf("%s must exist and state the floor %q: %v", path, cssFloor, err) continue } if !strings.Contains(strings.Join(strings.Fields(string(b)), " "), cssFloor) { t.Errorf("%s does not state the floor %q.\n"+ "Either it drifted, or the floor moved and this file was not brought along: "+ "cssFloor, README.md and DESIGN.md change together or not at all.", path, cssFloor) } } } // TestCSSFloorHasBeenReviewedRecently is the tripwire. It fails on a // date, which is unusual and intended: the alternative is a warning, // and a warning on a release evening is a thing you scroll past. A // build that stops for ten minutes while somebody re-reads a list of // CSS features is cheap; a floor that quietly describes 2024 while // the policy promises "about a year" is the silence the policy exists // to end. func TestCSSFloorHasBeenReviewedRecently(t *testing.T) { reviewed, err := time.Parse(time.DateOnly, floorReviewed) if err != nil { t.Fatalf("floorReviewed must be a %s date: %v", time.DateOnly, err) } due := reviewed.AddDate(0, floorReviewMonths, 0) if time.Now().After(due) { t.Fatalf("the CSS floor was last reviewed %s and was due %s.\n"+ "Re-derive it, the features css/tokens.css and css/themes/*.css use and the highest engine "+ "version among them, then update cssFloor, README.md and DESIGN.md if it moved, and set "+ "floorReviewed to today. Do not bump the date alone; the date is the record that somebody looked.", floorReviewed, due.Format(time.DateOnly)) } } // changelogName is the file whose newest release must be Version. const changelogName = "CHANGELOG.md" // TestVersionIsTheChangelogsNewestRelease holds the changelog and the // tree to one version: the first second-level heading is Unreleased, // and the one after it names Version, so a release is cut only once // its entry is written, and the tree is never a version the changelog // has not heard of. TestTheVersionIsSemver pins Version itself. func TestVersionIsTheChangelogsNewestRelease(t *testing.T) { b, err := os.ReadFile(changelogName) if err != nil { t.Fatalf("%s must exist, with ## Unreleased and then ## %s: %v", changelogName, Version, err) } var headings []string for _, line := range strings.Split(string(b), "\n") { if strings.HasPrefix(line, "## ") { headings = append(headings, strings.TrimSpace(line)) } } if len(headings) < 2 { t.Fatalf("%s has %d second-level headings %q; want ## Unreleased and then ## %s", changelogName, len(headings), headings, Version) } if headings[0] != "## Unreleased" { t.Errorf("%s's first heading is %q, want %q", changelogName, headings[0], "## Unreleased") } if want := "## " + Version; headings[1] != want { t.Errorf("%s's newest release is %q, but the tree is %q: the changelog entry and fiesta.Version move together", changelogName, headings[1], want) } } // oneLink is the tag the README exists to show: a page links this and // has the design system. /1/ is rewritten to the newest 1.y.z release. const oneLink = `` // TestTheReadmeShowsTheOneLink: the README carries the link tag // exactly as a page should paste it. func TestTheReadmeShowsTheOneLink(t *testing.T) { b, err := os.ReadFile("README.md") if err != nil { t.Fatalf("README.md must exist and show the one link: %v", err) } if !strings.Contains(string(b), oneLink) { t.Errorf("README.md does not show the one link, verbatim: %s", oneLink) } }