Skip to content

feat(locator): getByRole { visible } filter#89

Merged
BenSheridanEdwards merged 1 commit into
mainfrom
feat/visible-filter
Jul 3, 2026
Merged

feat(locator): getByRole { visible } filter#89
BenSheridanEdwards merged 1 commit into
mainfrom
feat/visible-filter

Conversation

@BenSheridanEdwards

Copy link
Copy Markdown
Owner

Summary

  • Adds a { visible: true | false } option to by.role / getByRole, exactly mirroring the { checked } / { disabled } filters from feat(locator): toHaveValue matcher and getByRole checked/disabled filters #76. It keeps only elements the toolkit reports on screen — iOS visible="true", Android displayed="true".
  • Why it matters: native trees routinely carry offscreen or shadow duplicates of the same role. A SwiftUI sheet exposes a hidden text field behind the focused one; document order returns the hidden node first, so getByRole("textfield").fill(...) types nowhere. getByRole("textfield", { visible: true }) picks the live instance. This closes the framework gap that forced consumer suites (WordlyMobileAutomatedTests' ios/language-selector.spec.ts) to fall back to raw -ios predicate string:type == "XCUIElementTypeTextField" AND visible == 1.
  • Composes with name/checked/disabled; a node lacking the visibility attribute is treated as not-visible under { visible: true } (conservative). The option is echoed in describeSelector failure messages.

Proof

  • npm run check
    • Passed on feat/visible-filter: Checked 48 files in 23ms. No fixes applied.
  • npm test
    • Passed: 183/183 (2 new fake-driver tests: iOS visible= picks the on-screen field among shadow duplicates and reads its value; Android displayed=, absent-attribute conservatism, filter composition, and the visible: failure-message text).
  • Generated project/device proof, or N/A:
    • Not applicable. Pure selector-filter addition over the already device-proven attribute layer, fully covered in-memory on the exact source shapes real XCUITest/UiAutomator2 emit. This will be exercised end-to-end when the Wordly ios/language-selector spec drops its raw predicate on the next release bump.
    • Screenshots: Not applicable; no rendered UI surface — observable behaviour is which node the selector resolves to, asserted in tests.

Risk

  • Low. Purely additive; existing role selectors and every other locator are unchanged.

Notes

  • Full device coverage not run: the filter reads the same page source the existing role resolution consumes; no new driver traffic.

PR Proof Law

  • I followed .agents/DEFINITION_OF_DONE.md and .agents/skills/pr-inline-screenshot-proof/SKILL.md.
  • Screenshots are committed and embedded inline with ![alt](...png?raw=1), or the proof section says Not applicable with the technical reason.
  • The PR body has no bare screenshot links, local paths, relative paths, or proof placeholders.

Adds a { visible: true|false } option to by.role/getByRole, mirroring the
checked/disabled filters: keep only elements the toolkit reports on screen
(iOS visible="true", Android displayed="true"). Native trees frequently
carry offscreen or shadow duplicates of the same role — a hidden SwiftUI
text field behind the focused one returns first in document order, so
fill() types nowhere. { visible: true } picks the live instance.

Closes the gap that forced consumer suites to fall back to raw
'-ios predicate string:... AND visible == 1' selectors.
@BenSheridanEdwards BenSheridanEdwards merged commit 5c99bcf into main Jul 3, 2026
1 check passed
@BenSheridanEdwards BenSheridanEdwards mentioned this pull request Jul 3, 2026
6 tasks
BenSheridanEdwards added a commit that referenced this pull request Jul 3, 2026
getByRole { visible } filter (#89) — pick the on-screen instance among
offscreen/shadow role duplicates, closing the last raw-predicate fallback
in consumer suites.
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