fix(android): publish the Compose role on its clickable parent instead of a fake child

Merged
SR
3d ago
+216-2

Summary

Fixes #3982. For a merging node with a role and children, Compose's SemanticsNode.emitFakeNodes adds a childless, non-clickable child carrying only the role's class (Button, CheckBox, RadioButton, Spinner, NumberPicker). The clickable parent stays android.view.View, so tap resolution refused it with covered_by_interactive_descendants.

Regular and interactive captures now publish that parent with the child's class and skip the child. A native android.view.View is not a ViewGroup, so only a virtual hierarchy gives one children. The child must be visible, unlabeled, id-less, childless, not an agent target, and inside the parent. Raw is unchanged.

4 files. Behavior change: Compose controls publish Button/CheckBox/… instead of View. Not covered: WebDriver/Appium Android. Residual: other virtual hierarchies (WebView, Flutter, ExploreByTouchHelper) with an unlabeled, non-clickable role child inside a clickable View fold the same way.

Validation

Head 9e660b758, base a16d43723.

  • pnpm check:affected --run --head 9e660b758 passed.
  • Each fold guard has a builder-test row that fails on it alone; a press test refuses the raw capture and taps the regular one.
  • Live at head 9e660b758, API 34, android-helper 0.21.33-dev, a Compose sandbox:
    • Containers publish Button/CheckBox/RadioButton, no fake child, checked kept; -i matches; --raw keeps the child.
    • The press is refused on base; on head it taps (counter 0→1).
    • A native checkbox row, a Compose row with its own Checkbox, and Settings match base (apart from live status bar and storage text).