rastrillo / fiesta Public

Clone
git clone https://amadan.net/rastrillo/fiesta

Plain git — no account needed to clone.

Download

Download this file

1package check
2
3import (
4 "regexp"
5 "slices"
6 "strings"
7 "testing"
8
9 "amadan.net/rastrillo/fiesta"
10)
11
12// The rake line is retired (design doc §6-v2.2), and "retired" has to
13// mean one place. tokens.css is the single stylesheet every rastrillo
14// page links, so a pseudo-element declared there once, as content:none,
15// is a pseudo-element that draws nothing anywhere — provided nothing
16// else in the shipped CSS declares one too.
17//
18// That last clause is what this test is for. A theme is colour, type
19// and shape; a theme that grew a [rst-page-header]::after would put the
20// flourish back on one theme and nowhere else, which is both the
21// hardest version of this bug to see and the easiest one to write.
22//
23// The browser half of the claim — that content:none lays out no box, in
24// every theme, in both schemes, in ar as well as en — is
25// header_rule_browser_test.go's. This is the cheap half, and it runs in
26// the ordinary suite.
27func TestTheRakeLineIsDeclaredRetiredExactlyOnce(t *testing.T) {
28 // The rule as it now stands, spelled in both markup vocabularies
29 // because tokens.css pairs a class selector with every attribute one
30 // until stage 3 of the migration.
31 //
32 // Read as rules, not text: a copy in a comment counted as the one
33 // declaration, and a pattern that stopped at a comma missed a
34 // pseudo-element after a selector list inside :is().
35 rules := leafRules(t, string(fiesta.TokensCSS()))
36 const retired = ".rst-page-header::after, [rst-page-header]::after"
37 got := 0
38 for _, r := range rules {
39 if r.selector == retired && slices.Equal(r.decls, [][3]string{{"content", "none", ""}}) {
40 got++
41 }
42 }
43 if got != 1 {
44 t.Errorf("tokens.css declares the retired header pseudo-element %d times as\n%s { content: none; }\nwant exactly 1 — the whole point of retiring it in one file is that there is one place to look", got, retired)
45 }
46
47 // Nothing else may draw one. The reading is deliberately loose (any
48 // selector naming a page header, any pseudo-element after it, : or
49 // ::) so a flourish reintroduced under ::before, or on the titles,
50 // is caught as readily as the exact rule that was removed.
51 headerPseudo := regexp.MustCompile(`(\.rst-page-header|\[rst-page-header).*::?(after|before)`)
52 for _, r := range rules {
53 if r.selector == retired {
54 continue
55 }
56 for _, sel := range splitSelectorList(r.selector) {
57 if headerPseudo.MatchString(sel) {
58 t.Errorf("tokens.css draws %q on the page header; the header's one decoration is its rule, and that lives on the theme axis as --rst-header-rule", sel)
59 }
60 }
61 }
62 for _, name := range fiesta.ThemeNames() {
63 theme, ok := fiesta.ThemeCSS(name)
64 if !ok {
65 t.Fatalf("fiesta.ThemeCSS(%q) missing", name)
66 }
67 // A theme file has no selectors at all — it is one :root block
68 // and two toggle rules — so any mention of the header at all is
69 // the beginning of this bug.
70 if strings.Contains(string(theme), "page-header") {
71 t.Errorf("themes/%s.css mentions the page header. A theme sets --rst-header-rule and stops there: structure is tokens.css's, and a theme that styles a component has started a second stylesheet", name)
72 }
73 }
74}
75