Skip to content

Commit db88ec9

Browse files
committed
feat: default accessibility roles
1 parent ab679c9 commit db88ec9

File tree

2 files changed

+54
-6
lines changed

2 files changed

+54
-6
lines changed

src/helpers/accessiblity.ts

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,13 @@ import {
44
StyleSheet,
55
} from 'react-native';
66
import { ReactTestInstance } from 'react-test-renderer';
7-
import { getTextContent } from './text-content';
87
import { getHostSiblings, getUnsafeRootElement } from './component-tree';
9-
import { getHostComponentNames } from './host-component-names';
8+
import {
9+
getHostComponentNames,
10+
isHostText,
11+
isHostTextInput,
12+
} from './host-component-names';
13+
import { getTextContent } from './text-content';
1014

1115
type IsInaccessibleOptions = {
1216
cache?: WeakMap<ReactTestInstance, boolean>;
@@ -113,10 +117,39 @@ export function isAccessibilityElement(
113117
);
114118
}
115119

116-
export function getAccessibilityRole(
117-
element: ReactTestInstance
118-
): string | undefined {
119-
return element.props.role ?? element.props.accessibilityRole;
120+
/**
121+
* Returns the accessibility role for given element. It will return explicit
122+
* role from either `role` or `accessibilityRole` props if set.
123+
*
124+
* If explicit role is not available, it would try to return default element
125+
* role:
126+
* - `text` for `Text` elements
127+
* - `textbox`* for `TextInput` elements.
128+
*
129+
* Note: `textbox` is not an official React Native role, you cannot set it
130+
* explicitly on an element. However, it is an ARIA role that better characterizes
131+
* TextInput elements than the default `none` role.
132+
*
133+
* In all other cases this functions returns `none`.
134+
*
135+
* @param element
136+
* @returns
137+
*/
138+
export function getAccessibilityRole(element: ReactTestInstance) {
139+
const explicitRole = element.props.role ?? element.props.accessibilityRole;
140+
if (explicitRole) {
141+
return explicitRole;
142+
}
143+
144+
if (isHostText(element)) {
145+
return 'text';
146+
}
147+
148+
if (isHostTextInput(element)) {
149+
return 'textbox';
150+
}
151+
152+
return 'none';
120153
}
121154

122155
export function getAccessibilityViewIsModal(element: ReactTestInstance) {

src/queries/__tests__/role.test.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
TouchableOpacity,
44
TouchableWithoutFeedback,
55
Text,
6+
TextInput,
67
View,
78
Pressable,
89
Button as RNButton,
@@ -110,6 +111,20 @@ test('supports role prop', () => {
110111
expect(screen.getByRole('button')).toBeTruthy();
111112
});
112113

114+
test('supports default roles', () => {
115+
const screen = render(
116+
<>
117+
<View testID="view-default" accessible />
118+
<Text testID="text-default" />
119+
<TextInput testID="text-input-default" />
120+
</>
121+
);
122+
123+
expect(screen.getByRole('none').props.testID).toBe('view-default');
124+
expect(screen.getByRole('text').props.testID).toBe('text-default');
125+
expect(screen.getByRole('textbox').props.testID).toBe('text-input-default');
126+
});
127+
113128
describe('supports name option', () => {
114129
test('returns an element that has the corresponding role and a children with the name', () => {
115130
const { getByRole } = render(

0 commit comments

Comments
 (0)