package web
import (
"regexp"
"strings"
"testing"
)
// icRule is the one global svg.ic rule, as served.
func icRule(t *testing.T) string {
t.Helper()
re := regexp.MustCompile(`(?s)(^|[};])\s*\.ic\s*\{([^}]*)\}`)
for _, m := range re.FindAllStringSubmatch(sheet, -1) {
// The base rule is the one that sets fill; the scoped ones
// (.cbtn .ic and friends) only resize.
if strings.Contains(m[2], "fill") {
return m[2]
}
}
t.Fatal("no base .ic rule in the served stylesheet")
return ""
}
// The base icon rule centres itself in a flex host.
//
// vertical-align does NOTHING to a flex item, and about half of these
// icons sit in one. Hosts that say align-items:center came out right
// anyway; hosts that say align-items:baseline did not, because an SVG
// has no baseline — the browser synthesises one from its bottom margin
// edge, standing the whole icon ON the text baseline.
//
// Measured in Chrome against the deployed stylesheet: the ticket,
// landing and sqlite state tabs each sat exactly -2.00px high (icon
// centre against the adjacent text's glyph box), and exactly 0.00 with
// align-self. Both declarations are kept: align-self covers the flex
// hosts, vertical-align covers the block and table-cell ones, where
// align-self does not apply.
func TestTheIconRuleAlignsItselfInAFlexHost(t *testing.T) {
body := icRule(t)
for _, want := range []string{"align-self", "vertical-align"} {
if !strings.Contains(body, want) {
t.Errorf("FAIL: the base .ic rule does not set %s: %s", want, strings.TrimSpace(body))
continue
}
t.Logf("ok: .ic sets %s", want)
}
}
// A flex host that aligns on the BASELINE is the case that breaks, so
// the stylesheet is allowed to keep writing them — but any rule that
// re-declares align-self on an icon has to answer for itself, because
// putting it back to auto or baseline reintroduces the 2px lift with
// nothing to say why.
func TestNoScopedRuleUndoesTheIconAlignment(t *testing.T) {
re := regexp.MustCompile(`(?s)([^};{]*\.ic[^{]*)\{([^}]*)\}`)
for _, m := range re.FindAllStringSubmatch(sheet, -1) {
decl := m[2]
if !strings.Contains(decl, "align-self") || strings.Contains(decl, "fill") {
continue
}
if strings.Contains(decl, "align-self:auto") || strings.Contains(decl, "align-self:baseline") {
t.Errorf("FAIL: %s puts an icon back on the baseline: %s",
strings.TrimSpace(m[1]), strings.TrimSpace(decl))
}
}
t.Log("ok: no scoped .ic rule returns an icon to baseline alignment")
}