fix(e2e): exempt truncate-clamped elements from per-element overflow walk

The api-tokens mobile no-overflow spec walks every descendant of the
mobile card-list and asserts `scrollWidth <= clientWidth + 1`. The
v1.4.19 fix wrapped long token names / usernames / permissions in a
`<TruncatedCell>` (Tailwind `truncate` ⇒ `overflow:hidden +
text-overflow:ellipsis + white-space:nowrap`), which by design keeps
`clientWidth` clamped to the parent column while `scrollWidth` reflects
the full text — exactly the case the assertion was tripping on.

Skip elements whose computed `text-overflow: ellipsis` and clamped
`overflow-x` show they are intentionally truncating. The page-level
`document.documentElement.scrollWidth <= innerWidth + 1` assertion
remains the authoritative no-scrollbar guard, so the regression intent
is preserved without false-positives on the truncate helper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marc-André BombeckandClaude Opus 4.7 committed 2026-05-10 19:49:32 +02:00
1 parent 812b68a99d
commit e8d0660198
1 file changed
+23 -1
+23 -1
View File
@@ -167,9 +167,31 @@ test.describe("/admin/api-tokens mobile no-overflow", () => {
// Walk every element inside the mobile card-list and assert no
// child has a wider scrollWidth than its container. This is the
// Pixel-5 worst-case Marc kept hitting.
//
// Elements clamped via `truncate` (Tailwind's `overflow:hidden +
// text-overflow:ellipsis + white-space:nowrap` shorthand) are by
// design `scrollWidth > clientWidth` whenever the underlying text
// is longer than the parent column — that IS the truncation, not
// an overflow leak. Skip those so the assertion only fires on real
// layout culprits (a span without a width clamp pushing its parent
// wider). The page-level `dims.scrollWidth <= dims.innerWidth + 1`
// assertion below remains the authoritative no-scrollbar guard.
const culprits = await page
.getByTestId("admin-tokens-mobile-list")
.evaluate((root) => {
const isTruncated = (el: Element): boolean => {
const cs = window.getComputedStyle(el);
if (cs.textOverflow === "ellipsis" && cs.overflowX !== "visible") {
return true;
}
// Tailwind's `truncate` shorthand and any explicit overflow
// clamp also legitimately keep the visible content inside
// clientWidth even though scrollWidth measures full content.
if (cs.overflowX === "hidden" || cs.overflowX === "clip") {
return true;
}
return false;
};
const out: Array<{
tag: string;
klass: string;
@@ -177,7 +199,7 @@ test.describe("/admin/api-tokens mobile no-overflow", () => {
clientWidth: number;
}> = [];
for (const el of root.querySelectorAll("*")) {
if (el.scrollWidth > el.clientWidth + 1) {
if (el.scrollWidth > el.clientWidth + 1 && !isTruncated(el)) {
out.push({
tag: el.tagName,
klass: