Skip to content

*ByRole: return only elements with implicit or explicit accessible={true} prop #1180

Closed
@mdjastrzebski

Description

@mdjastrzebski

Describe the Feature

This is a proposed tweak to *ByRole query. It can be treated as either a fix or a (breaking) change.

Currently getByRole query is based on explicit role set in accessibilityRole prop. Other props are not taken into account (at least until #1064 is merged). This behaviour while basic can be problematic as according to screen readers, elements with accessible={false} (either explicit or implicit) are not focusable by screen reader.

This manifests in relatively common RN pattern:

<Pressable accessibilityRole="button" accessible={false}>
  <Text>Cell title</Text>
  <Pressable accessibilityRole="button">
    <Text>Action</Text>
  </Pressable>
</Pressable>

Under current implementation getByRole('button', { name: "Action" }) would select both outer and inner pressables. After implementing the proposed change it would select only the inner one.

Possible Implementations

  • element can be matched by getByRole using the same criteria as now (host component, equal accessibilityRole) but also needs to be considered accessibility element (i.e. be focusable).
  • each host view can be made focusable by explicitly passing accessible={true}
  • some host view types are considered focusable without the accessible prop (e.g. Text, TextInput), but can have their "focusability" disabled by setting accessible={false}
  • basic host View is not consider focusable
  • some RN built in components, e.g. Pressable, TouchableOpacity which render to host View actually set explicit accessible={true} prop on the view

In more practical terms we could use something like isAccessibilityElement to check for focusable state:

export function isAccessibilityElement(
  element: ReactTestInstance | null
): boolean {
  if (element == null) {
    return false;
  }

  if (element.props.accessible !== undefined) {
    return element.props.accessible;
  }

  return (
    isHostElementForType(element, Text) ||
    isHostElementForType(element, TextInput)
  );
}

Then this criteria should be added to *ByRole query.

This change should not affect other general purpose queries as *ByText or *ByTestId. It may be worth considering applying it to some other a11y-related queries, which would make only sense if selected view is accessible: *ByA11yValue, *ByA11State.

Related Issues

#1152 - initial source for issue
#1163 - related discussion
#1064 - hidden query option

CC: @AugustinLF @pierrezimmermannbam @MattAgn @thymikee

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions