rastrillo / fiesta Public

Hold the footer's panels to the row's inline end where nothing anchors them

Where nothing anchors a panel, the footer row is its containing block
and every panel opens flush with the row's inline end, under the
menus, whichever menu it belongs to. The test only held the panel
inside the row, so a panel at the row's inline start, under nothing
it belongs to, passed: with the row's panels moved to
inset-inline-start: 0, TestTheFootersMenusOpenOnScreen stayed green.

It now asserts the panel's inline end is the row's (its padding box's,
the edge inset-inline-end measures from), in both no-anchor legs, with
anchor.js and with scripts off, LTR with the widest left-to-right
labels and RTL with Arabic's, and in the class spelling as well as the
attribute one. The anchored leg is unchanged: there each panel is
anchored to its own summary, as the spec has it.

Already passing against the footer's CSS, as it should be. The named
mutation, the row's panels at inset-inline-start: 0, turns it red in
32 places: both no-anchor legs, both sizes, both directions, both
spellings, both menus.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev 4ac98b33e5154cd5eb2bb091f2d7a494e2efa625 parent b5dcf46
1 file changed, +22 −8
  • check/footer_browser_test.go +22 −8
diff --git a/check/footer_browser_test.go b/check/footer_browser_test.go
index d3ab8d3..3608ced 100644
--- a/check/footer_browser_test.go
+++ b/check/footer_browser_test.go
@@ -240,8 +240,11 @@ func labelled(t *testing.T, doc, lang, dir, language, scheme string) string {
// the box that holds it, and in the row Language is not at the end:
// hung from its own <details>, its panel, at least 176px wide, runs
// past the opposite edge at 320. So the row holds every panel, under
-// it and inside it, with anchor.js running and with no script at all,
-// and the page grows to hold the panel so it can be scrolled to.
+// it and flush with its inline end, whichever menu it belongs to, with
+// anchor.js running and with no script at all, in both spellings, and
+// the page grows to hold the panel so it can be scrolled to. A panel
+// at the row's inline start would be inside the row and on the screen
+// too, and under nothing it belongs to.
func TestTheFootersMenusOpenOnScreen(t *testing.T) {
doc := columnDoc(t)
noAnchor := strings.ReplaceAll(string(fiesta.TokensCSS()), "@supports (position-area: block-end) and (position-try-fallbacks: flip-block)", "@supports (position-area: rastrillo-no-such-value)")
@@ -264,7 +267,7 @@ func TestTheFootersMenusOpenOnScreen(t *testing.T) {
{"no anchor positioning, no scripts", false, false},
} {
t.Run(leg.name, func(t *testing.T) {
- pages := map[string]string{"/ltr": ltr, "/rtl": rtl}
+ pages := map[string]string{"/ltr": ltr, "/rtl": rtl, "/ltr-class": classSpelling(t, ltr), "/rtl-class": classSpelling(t, rtl)}
if !leg.anchor {
for path, page := range pages {
pages[path] = strings.Replace(page, `href="tokens.css"`, `href="tokens-noanchor.css"`, 1)
@@ -290,17 +293,20 @@ func TestTheFootersMenusOpenOnScreen(t *testing.T) {
mustRun(t, ctx, emulation.SetScriptExecutionDisabled(true))
}
for _, size := range [][2]int64{{390, 640}, {320, 568}} {
- for _, path := range []string{"/ltr", "/rtl"} {
+ for _, path := range []string{"/ltr", "/rtl", "/ltr-class", "/rtl-class"} {
for _, menu := range []string{"rst-locale", "rst-scheme"} {
where := fmt.Sprintf("%s at %dx%d, %s", path, size[0], size[1], menu)
- details := "[rst-page-foot] > [" + menu + "]"
+ details, panel := "[rst-page-foot] > ["+menu+"]", "[rst-dropdown-menu]"
+ if strings.HasSuffix(path, "-class") {
+ details, panel = ".rst-page__foot > ."+menu, ".rst-dropdown__menu"
+ }
mustRun(t, ctx, chromedp.EmulateViewport(size[0], size[1]), chromedp.Navigate(rig.Origin+path), chromedp.WaitVisible(details, chromedp.ByQuery))
var flips bool
at(t, ctx, `JSON.stringify(document.documentElement.hasAttribute("data-rst-flip-menus"))`, &flips)
if want := !leg.anchor && leg.scripts; flips != want {
t.Fatalf("%s: <html> data-rst-flip-menus is %v, want %v; anchor.js is not doing what this leg needs", where, flips, want)
}
- RequireAnchorPositioning(t, ctx, where, details+" > [rst-dropdown-menu]", leg.anchor)
+ RequireAnchorPositioning(t, ctx, where, details+" > "+panel, leg.anchor)
mustRun(t, ctx, chromedp.Evaluate(`window.scrollTo(0, document.documentElement.scrollHeight)`, nil),
chromedp.Click(details+" > summary", chromedp.ByQuery))
if leg.scripts {
@@ -312,10 +318,15 @@ func TestTheFootersMenusOpenOnScreen(t *testing.T) {
Open bool
L, R, T, B, FL, FR, FB, VW float64
VH, SY, SH float64
+ PanelEnd, RowEnd float64
}
- at(t, ctx, `(() => { const d = document.querySelector(`+jsStr(details)+`), p = d.querySelector(":scope > [rst-dropdown-menu]").getBoundingClientRect(), f = d.parentElement.getBoundingClientRect();
+ // The row's inline end is its padding box's, the
+ // edge an absolute panel's inset-inline-end
+ // measures from: the right in LTR, the left in RTL.
+ at(t, ctx, `(() => { const d = document.querySelector(`+jsStr(details)+`), p = d.querySelector(":scope > `+panel+`").getBoundingClientRect(), row = d.parentElement, f = row.getBoundingClientRect(), cs = getComputedStyle(row), rtl = cs.direction === "rtl";
return JSON.stringify({Open: d.open, L: p.left, R: p.right, T: p.top, B: p.bottom, FL: f.left, FR: f.right, FB: f.bottom,
- VW: document.documentElement.clientWidth, VH: innerHeight, SY: scrollY, SH: document.documentElement.scrollHeight}); })()`, &g)
+ VW: document.documentElement.clientWidth, VH: innerHeight, SY: scrollY, SH: document.documentElement.scrollHeight,
+ PanelEnd: rtl ? p.left : p.right, RowEnd: rtl ? f.left + parseFloat(cs.borderLeftWidth) : f.right - parseFloat(cs.borderRightWidth)}); })()`, &g)
if !g.Open {
t.Fatalf("%s: the menu did not open; this leg proves nothing", where)
}
@@ -331,6 +342,9 @@ func TestTheFootersMenusOpenOnScreen(t *testing.T) {
if g.L < g.FL-0.5 || g.R > g.FR+0.5 {
t.Errorf("%s: the panel spans %.1f to %.1f and the footer %.1f to %.1f; the row must hold its panel", where, g.L, g.R, g.FL, g.FR)
}
+ if math.Abs(g.PanelEnd-g.RowEnd) > 0.5 {
+ t.Errorf("%s: the panel's inline end is at %.1f and the row's at %.1f; without anchoring every panel opens flush with the row's inline end", where, g.PanelEnd, g.RowEnd)
+ }
if g.T < g.FB-0.5 {
t.Errorf("%s: the panel starts at %.1f, above the footer's foot at %.1f; it must open under the row", where, g.T, g.FB)
}