Skip to content

fix: treat an element with no area as not visible - #6

Merged
DouweBos merged 1 commit into
mainfrom
douwe/zero-area-element-not-visible
Sep 24, 2026
Merged

DouweBos merged 1 commit into
mainfrom
douwe/zero-area-element-not-visible

Conversation

@DouweBos

Copy link
Copy Markdown

Proposed changes

UiElement.getVisiblePercentage returned NaN for a box with exactly one zero dimension: the early return only covered width == 0 && height == 0, so everything else fell through to visibleArea / totalArea, and a zero dimension makes both sides 0.

TreeNode.filterOutOfBounds prunes on visiblePercentage < 0.1, and NaN fails every comparison, so those elements were never pruned — an element collapsed to no area stayed in the hierarchy and satisfied assertVisible. Widening the guard to || fixes it, and matches what the existing && guard was already reaching for.

This makes visibility stricter on every platform, not just web. A flow that currently passes because it asserts on a zero-area element will start failing. That is the intended correction, but it is worth a full E2E run before release.

Found via a Plex Lightning nav drawer: collapsed off-screen at [-452,0][-452,72], Maestro reported it visible, and a while notVisible: gate meant to expand the rail was skipped outright — so the flow pressed no keys and failed several commands later on an unrelated assertion.

Testing

./gradlew :maestro-client:test — 297 tests, 0 failures.

Four new cases, confirmed red before the fix for the right reason (expected: 0 but was: NaN, and the zero-area node surviving the filter):

  • UiElementTest — zero width and zero height each return 0
  • ViewHierarchyTest (new file) — filterOutOfBounds drops a zero-width and a zero-height node, and still keeps an ordinary on-screen one

No demo-app flow: the defect is in hierarchy filtering rather than in any on-device behavior, and the unit tests pin it at the layer it occurs. Happy to add a defects_screen.dart widget plus a flow if you'd rather have the e2e coverage too.

Issues fixed

Unblocks the search.tv and navigation.tv Lightning smoke flows in plexinc/react-native-client, which have been failing on Assertion is false: id: primary-navigation-account, focused is visible.

getVisiblePercentage only short-circuited when both dimensions were zero, so
a box with one zero dimension divided zero by zero and returned NaN.
filterOutOfBounds keeps anything failing `visiblePercentage < 0.1`, and NaN
fails every comparison, so a collapsed element stayed in the hierarchy and
read as visible. A Lightning nav drawer collapsed to [-452,0][-452,72] is
what surfaced it.
@DouweBos DouweBos self-assigned this Sep 24, 2026
@DouweBos
DouweBos marked this pull request as ready for review September 24, 2026 15:47
@DouweBos
DouweBos merged commit 40af7c0 into main Sep 24, 2026
88 of 96 checks passed
@DouweBos
DouweBos deleted the douwe/zero-area-element-not-visible branch September 24, 2026 19:05
DouweBos added a commit that referenced this pull request Oct 9, 2026
getVisiblePercentage only short-circuited when both dimensions were zero, so
a box with one zero dimension divided zero by zero and returned NaN.
filterOutOfBounds keeps anything failing `visiblePercentage < 0.1`, and NaN
fails every comparison, so a collapsed element stayed in the hierarchy and
read as visible. A Lightning nav drawer collapsed to [-452,0][-452,72] is
what surfaced it.
DouweBos added a commit that referenced this pull request Oct 9, 2026
getVisiblePercentage only short-circuited when both dimensions were zero, so
a box with one zero dimension divided zero by zero and returned NaN.
filterOutOfBounds keeps anything failing `visiblePercentage < 0.1`, and NaN
fails every comparison, so a collapsed element stayed in the hierarchy and
read as visible. A Lightning nav drawer collapsed to [-452,0][-452,72] is
what surfaced it.
DouweBos added a commit that referenced this pull request Oct 9, 2026
getVisiblePercentage only short-circuited when both dimensions were zero, so
a box with one zero dimension divided zero by zero and returned NaN.
filterOutOfBounds keeps anything failing `visiblePercentage < 0.1`, and NaN
fails every comparison, so a collapsed element stayed in the hierarchy and
read as visible. A Lightning nav drawer collapsed to [-452,0][-452,72] is
what surfaced it.
DouweBos added a commit that referenced this pull request Oct 9, 2026
getVisiblePercentage only short-circuited when both dimensions were zero, so
a box with one zero dimension divided zero by zero and returned NaN.
filterOutOfBounds keeps anything failing `visiblePercentage < 0.1`, and NaN
fails every comparison, so a collapsed element stayed in the hierarchy and
read as visible. A Lightning nav drawer collapsed to [-452,0][-452,72] is
what surfaced it.
DouweBos added a commit that referenced this pull request Oct 9, 2026
getVisiblePercentage only short-circuited when both dimensions were zero, so
a box with one zero dimension divided zero by zero and returned NaN.
filterOutOfBounds keeps anything failing `visiblePercentage < 0.1`, and NaN
fails every comparison, so a collapsed element stayed in the hierarchy and
read as visible. A Lightning nav drawer collapsed to [-452,0][-452,72] is
what surfaced it.
DouweBos added a commit that referenced this pull request Oct 9, 2026
getVisiblePercentage only short-circuited when both dimensions were zero, so
a box with one zero dimension divided zero by zero and returned NaN.
filterOutOfBounds keeps anything failing `visiblePercentage < 0.1`, and NaN
fails every comparison, so a collapsed element stayed in the hierarchy and
read as visible. A Lightning nav drawer collapsed to [-452,0][-452,72] is
what surfaced it.
DouweBos added a commit that referenced this pull request Oct 9, 2026
getVisiblePercentage only short-circuited when both dimensions were zero, so
a box with one zero dimension divided zero by zero and returned NaN.
filterOutOfBounds keeps anything failing `visiblePercentage < 0.1`, and NaN
fails every comparison, so a collapsed element stayed in the hierarchy and
read as visible. A Lightning nav drawer collapsed to [-452,0][-452,72] is
what surfaced it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant