Files
pbakaus_impeccable/tests/fixtures/antipatterns/nonrendered-text.html
T
Paul BakausandClaude Fable 5 507725c935 Harden detector against form.id shadowing and gradient/non-rendered false positives
Fixes three detector bugs that surfaced on real-world (Shopify) URL scans:

#407 — DOM named-property shadowing crash. On a <form> with a named control
like <input name="id"> (every Shopify product form), HTMLFormElement's
[LegacyOverrideBuiltIns] behavior makes `form.id` return the input element, not
the id string, so `elId.startsWith(...)` throws and aborts the whole scan. Read
the id via getAttribute whenever `el.id` is not a string, at all three sites:
checkQuality (checks.mjs) and collectBrowserFindings + generateSelector
(browser/injected/index.mjs). Regenerated the browser bundle.

#408 — tiny-text / undersized-ui-text flagged non-rendered elements. On sites
that set html{font-size:62.5%} the root computes to 10px, so <script>/<style>/
<title>/<noscript> and display:none / visibility:hidden blocks — whose JS/CSS/
JSON-LD text clears the hasDirectText gate — produced dozens of phantom "10px
body text" findings. Added isNonRenderedText() (tag list + head descendants +
display/visibility) and gated both text-size floors on it.

#409 — contrast rules misjudged gradients. Case A: background-clip:text paints
its glyphs with the element's own gradient, not a backdrop, so measuring the
never-painted `color` against those stops is a guaranteed false positive; skip
the backdrop-contrast checks when bgClip is 'text' (the gradient-text pattern
flag still fires). Case B: a translucent gradient stop (e.g. a 9%-alpha accent
glow) was treated as an opaque accent; composite alpha stops over the resolved
surface beneath the gradient in resolveGradientStops(), dropping the stop rather
than guessing when that surface is unresolvable.

Fixtures + tests: shadowed-form-id.html (browser, #407), nonrendered-text.html
(#408), and gradient-clipped + alpha-glow cases added to color.html (#409).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 16:17:24 -07:00

51 lines
2.7 KiB
HTML

<!DOCTYPE html>
<!--
Regression fixture for issue #408: tiny-text / undersized-ui-text must only
measure rendered text. On sites that set `html { font-size: 62.5% }` the root
computes to 10px, so every element that inherits the root and carries text
content — including <script>, <style>, <title>, <noscript>, and display:none /
visibility:hidden blocks — reports a 10px computed size. Their JS / CSS /
JSON-LD text satisfies hasDirectText, so before the fix they produced dozens
of phantom "10px body text" findings on every Shopify page.
Explicit pixel sizes throughout because jsdom does no layout.
-->
<html style="font-size: 10px">
<head>
<meta charset="utf-8">
<!-- SHOULD PASS: a long <title> inherits the 10px root, but nothing renders it. -->
<title>This is a fairly long document title that easily exceeds twenty characters</title>
<!-- SHOULD PASS: stylesheet text is never painted. -->
<style>
/* This CSS comment is deliberately longer than twenty characters so the style
element's text node clears the hasDirectText / textLen > 20 gate. */
body { font-size: 10px; font-family: system-ui, sans-serif; }
.rendered-body { font-size: 10px; }
.rendered-nav-link { font-size: 9px; }
.none-block { display: none; font-size: 10px; }
.hidden-block { visibility: hidden; font-size: 10px; }
</style>
<!-- SHOULD PASS: script payload text is never painted. -->
<script>window.__ANALYTICS__ = { id: 1, ts: 0 }; console.log("an analytics payload string that is clearly longer than twenty characters");</script>
<!-- SHOULD PASS: JSON-LD schema block, a Shopify staple. -->
<script type="application/ld+json">{"@context":"https://schema.org","@type":"Product","name":"A product name long enough to exceed twenty characters"}</script>
<!-- SHOULD PASS: noscript fallback prose is only shown without JS; still non-rendered here. -->
<noscript>Please enable JavaScript in your browser to view this page content correctly.</noscript>
</head>
<body>
<!-- SHOULD PASS: display:none block, its text is never painted. -->
<div class="none-block">Hidden display-none block of body text long enough to exceed twenty characters.</div>
<!-- SHOULD PASS: visibility:hidden paragraph, its text is never painted. -->
<p class="hidden-block">Invisible visibility-hidden paragraph copy that is longer than the twenty char gate.</p>
<!-- SHOULD FLAG (tiny-text): genuinely rendered body copy at 10px. -->
<p class="rendered-body">This is real rendered body copy at 10px that is definitely long enough to flag.</p>
<!-- SHOULD FLAG (undersized-ui-text): genuinely rendered interactive text at 9px. -->
<nav aria-label="primary"><a href="/docs" class="rendered-nav-link">Rendered Nav Link</a></nav>
</body>
</html>