Skip to content

Commit d429f4f

Browse files
chiaramooneyacoates-ms
authored andcommitted
Implement ISelectionProvider and ISelectionItemProvider (microsoft#14019)
Adds support for ISelectionProvider interface Adds support for ISelectionItemProvider interface Adds support for accessibilityState:selected Adjusts AccessibilityState native type on Windows to be std::optional instead of bool Adjusts AccessibilityState native type on Windows to include multiselectable and required fields of type std::optional Adds multiselectable and required fields to AccessibilityState type in JS with type boolean | undefined Adds support for aria-multiselectable and aria-required. Adds support for the following accessibilityActions: addToSelection, removeFromSelection, select Fixes crash in AccessibilityInsights.
1 parent 0f9d266 commit d429f4f

28 files changed

+49658
-32853
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "prerelease",
3+
"comment": "Implement ISelectionProvider and ISelectionItemProvider",
4+
"packageName": "react-native-windows",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}

packages/@react-native-windows/tester/src/js/examples-win/Accessibility/AccessibilityExampleWindows.tsx

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -312,33 +312,40 @@ class AccessibilityStateExamples extends React.Component {
312312
The following list of TouchableHighlights toggles
313313
accessibilityState.selected when touched:
314314
</Text>
315-
<FlatList
316-
accessibilityLabel="List of selectable items"
317-
data={selectableItems}
318-
renderItem={item => (
319-
<TouchableHighlight
320-
style={{
321-
width: 100,
322-
height: 50,
323-
backgroundColor: this.state.itemsSelected[item.index]
324-
? 'gray'
325-
: 'lightskyblue',
326-
}}
327-
accessibilityRole="button"
328-
accessibilityLabel={'Selectable item ' + (item.index + 1)}
329-
accessibilityState={{
330-
selected: this.state.itemsSelected[item.index],
331-
}}
332-
onPress={() => this.selectPress(item.index)}>
333-
<Text>
334-
{this.state.itemsSelected[item.index]
335-
? 'Selected'
336-
: 'Unselected'}
337-
</Text>
338-
</TouchableHighlight>
339-
)}
340-
keyExtractor={(item, index) => index.toString()}
341-
/>
315+
<View
316+
accessible
317+
accessibilityLabel="Selection Container"
318+
accessibilityState={{multiselectable: true, required: true}}
319+
testID="selection-container">
320+
<FlatList
321+
accessibilityLabel="List of selectable items"
322+
data={selectableItems}
323+
renderItem={item => (
324+
<TouchableHighlight
325+
style={{
326+
width: 100,
327+
height: 50,
328+
backgroundColor: this.state.itemsSelected[item.index]
329+
? 'gray'
330+
: 'lightskyblue',
331+
}}
332+
accessibilityRole="button"
333+
accessibilityLabel={'Selectable item ' + (item.index + 1)}
334+
testID={'Selectable item ' + (item.index + 1)}
335+
accessibilityState={{
336+
selected: this.state.itemsSelected[item.index],
337+
}}
338+
onPress={() => this.selectPress(item.index)}>
339+
<Text>
340+
{this.state.itemsSelected[item.index]
341+
? 'Selected'
342+
: 'Unselected'}
343+
</Text>
344+
</TouchableHighlight>
345+
)}
346+
keyExtractor={(item, index) => index.toString()}
347+
/>
348+
</View>
342349
<Text>
343350
The following TouchableHighlight cycles accessibilityState.checked
344351
through unchecked/checked/mixed for the View under it:
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/**
2+
* Copyright (c) Microsoft Corporation.
3+
* Licensed under the MIT License.
4+
*
5+
* @format
6+
*/
7+
8+
import {dumpVisualTree} from '@react-native-windows/automation-commands';
9+
import {goToApiExample} from './RNTesterNavigation';
10+
import {app} from '@react-native-windows/automation';
11+
import {verifyNoErrorLogs} from './Helpers';
12+
13+
beforeAll(async () => {
14+
// If window is partially offscreen, tests will fail to click on certain elements
15+
await app.setWindowPosition(0, 0);
16+
await app.setWindowSize(1000, 1250);
17+
await goToApiExample('Accessibility Windows');
18+
});
19+
20+
afterEach(async () => {
21+
await verifyNoErrorLogs();
22+
});
23+
24+
const searchBox = async (input: string) => {
25+
const searchBox = await app.findElementByTestID('example_search');
26+
await app.waitUntil(
27+
async () => {
28+
await searchBox.setValue(input);
29+
return (await searchBox.getText()) === input;
30+
},
31+
{
32+
interval: 1500,
33+
timeout: 5000,
34+
timeoutMsg: `Unable to enter correct search text into test searchbox.`,
35+
},
36+
);
37+
};
38+
39+
describe('Accessibility Tests', () => {
40+
test('Elements can set accessibilityState:selected to false', async () => {
41+
await searchBox('Sta');
42+
const component = await app.findElementByTestID('Selectable item 1');
43+
await component.waitForDisplayed({timeout: 5000});
44+
const dump = await dumpVisualTree('Selectable item 1');
45+
expect(dump).toMatchSnapshot();
46+
});
47+
test('Elements can set accessibilityState:selected to true', async () => {
48+
await searchBox('Sta');
49+
const component = await app.findElementByTestID('Selectable item 1');
50+
await component.waitForDisplayed({timeout: 5000});
51+
await component.click();
52+
const dump = await dumpVisualTree('Selectable item 1');
53+
expect(dump).toMatchSnapshot();
54+
});
55+
test('Selectable items must have a Selection Container. Elements can set accessibilityState:multiselectable and accessibilityState:required to true', async () => {
56+
await searchBox('Sta');
57+
const componentsTab = await app.findElementByTestID('selection-container');
58+
await componentsTab.waitForDisplayed({timeout: 5000});
59+
const dump = await dumpVisualTree('selection-container');
60+
expect(dump).toMatchSnapshot();
61+
});
62+
});

0 commit comments

Comments
 (0)