From b9aed0ec10714180efaea48acb076749f6d32a6e Mon Sep 17 00:00:00 2001 From: Chiara Mooney <34109996+chiaramooney@users.noreply.github.com> Date: Tue, 20 Aug 2024 11:39:42 -0700 Subject: [PATCH] Add Testing for accessibilityValue and Implement IValueProvider conditionally (#13544) * Adjust Support for IValueProvider * Add Testing for accessibilityValue * Edit Examples * Change files * Add Extra Func * Fix Up Test Infra * Update Snapshots * Update Snapshots * Format * Fix Typo * Fix Typo * Format * Update ImageComponentTest.test.ts.snap * Update RNTesterApp-Fabric.cpp --- ...-5fe16ce6-e8a9-4b9f-a0a4-1a5a06287bcc.json | 7 + .../Button/ButtonExample.windows.js | 3 +- .../Pressable/PressableExample.windows.js | 3 +- .../TextInput/TextInputExample.windows.js | 14 ++ .../Touchable/TouchableExample.windows.js | 1 + .../js/examples/View/ViewExample.windows.js | 5 +- .../test/TextInputComponentTest.test.ts | 6 + .../__snapshots__/HomeUIADump.test.ts.snap | 1 + .../PressableComponentTest.test.ts.snap | 1 + .../TextInputComponentTest.test.ts.snap | 211 ++++++++++++++++++ .../TouchableComponentTest.test.ts.snap | 1 + .../ViewComponentTest.test.ts.snap | 62 ++++- .../__snapshots__/snapshotPages.test.js.snap | 55 ++++- .../RNTesterApp-Fabric/RNTesterApp-Fabric.cpp | 16 +- .../ViewComponentTest.test.ts.snap | 80 ++++++- .../Fabric/ComponentView.cpp | 2 +- .../Fabric/ComponentView.h | 2 +- .../CompositionDynamicAutomationProvider.cpp | 42 +++- .../CompositionViewComponentView.cpp | 5 +- .../CompositionViewComponentView.h | 2 +- .../WindowsTextInputComponentView.cpp | 2 +- .../TextInput/WindowsTextInputComponentView.h | 2 +- .../Fabric/Composition/UiaHelpers.cpp | 10 + .../Fabric/Composition/UiaHelpers.h | 2 + 24 files changed, 512 insertions(+), 23 deletions(-) create mode 100644 change/react-native-windows-5fe16ce6-e8a9-4b9f-a0a4-1a5a06287bcc.json diff --git a/change/react-native-windows-5fe16ce6-e8a9-4b9f-a0a4-1a5a06287bcc.json b/change/react-native-windows-5fe16ce6-e8a9-4b9f-a0a4-1a5a06287bcc.json new file mode 100644 index 00000000000..b1f05bd51f5 --- /dev/null +++ b/change/react-native-windows-5fe16ce6-e8a9-4b9f-a0a4-1a5a06287bcc.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "Adjust Support for IValueProvider", + "packageName": "react-native-windows", + "email": "34109996+chiaramooney@users.noreply.github.com", + "dependentChangeType": "patch" +} diff --git a/packages/@react-native-windows/tester/src/js/examples-win/Button/ButtonExample.windows.js b/packages/@react-native-windows/tester/src/js/examples-win/Button/ButtonExample.windows.js index fcf7662f5a0..20e397fb40f 100644 --- a/packages/@react-native-windows/tester/src/js/examples-win/Button/ButtonExample.windows.js +++ b/packages/@react-native-windows/tester/src/js/examples-win/Button/ButtonExample.windows.js @@ -217,10 +217,11 @@ exports.examples = [ testID="accessibility_props" title="Submit Application" accessibilityLabel="Press to submit your application!" - accessibilityRole="Button" + accessibilityRole="button" accessibilityHint="Submit Button" accessibilityPosInSet={1} accessibilitySetSize={1} + accessibilityValue={{Text: "Submit Application"}} /> ); }} diff --git a/packages/@react-native-windows/tester/src/js/examples/Pressable/PressableExample.windows.js b/packages/@react-native-windows/tester/src/js/examples/Pressable/PressableExample.windows.js index 5308d63f22a..c1aeaf04afb 100644 --- a/packages/@react-native-windows/tester/src/js/examples/Pressable/PressableExample.windows.js +++ b/packages/@react-native-windows/tester/src/js/examples/Pressable/PressableExample.windows.js @@ -122,6 +122,7 @@ function PressableFeedbackEvents() { testID="pressable_feedback_events_button" accessibilityLabel="pressable feedback events" accessibilityRole="button" + accessibilityValue={{text: "Press Me"}} // [Windows onFocus={() => appendEvent('focus')} onBlur={() => appendEvent('blur')} @@ -959,7 +960,7 @@ const examples = [ onPress={() => {}} importantForAccessibility="no-hide-descendants" accessibilityHint="Button" - accessibilityValue={0}> + accessibilityValue={{text: "Child Pressable"}}> Parent Pressable {}}> Child Pressable diff --git a/packages/@react-native-windows/tester/src/js/examples/TextInput/TextInputExample.windows.js b/packages/@react-native-windows/tester/src/js/examples/TextInput/TextInputExample.windows.js index 4571755fd07..afe213b0be9 100644 --- a/packages/@react-native-windows/tester/src/js/examples/TextInput/TextInputExample.windows.js +++ b/packages/@react-native-windows/tester/src/js/examples/TextInput/TextInputExample.windows.js @@ -827,6 +827,20 @@ const examples: Array = [ ); }, }, + { + title: 'Searchbox', + render: function (): React.Node { + return ( + + + + ); + }, + }, // Windows] ]; diff --git a/packages/@react-native-windows/tester/src/js/examples/Touchable/TouchableExample.windows.js b/packages/@react-native-windows/tester/src/js/examples/Touchable/TouchableExample.windows.js index 28951e896db..f35c320a9e0 100644 --- a/packages/@react-native-windows/tester/src/js/examples/Touchable/TouchableExample.windows.js +++ b/packages/@react-native-windows/tester/src/js/examples/Touchable/TouchableExample.windows.js @@ -162,6 +162,7 @@ class TouchableFeedbackEvents extends React.Component<{...}, $FlowFixMeState> { testID="touchable_feedback_events_button" accessibilityLabel="touchable feedback events" accessibilityRole="button" + accessibilityValue={{text: "Press Me"}} onPress={() => this._appendEvent('press')} onPressIn={() => this._appendEvent('pressIn')} onPressOut={() => this._appendEvent('pressOut')} diff --git a/packages/@react-native-windows/tester/src/js/examples/View/ViewExample.windows.js b/packages/@react-native-windows/tester/src/js/examples/View/ViewExample.windows.js index bd571201f36..533b6ac8390 100644 --- a/packages/@react-native-windows/tester/src/js/examples/View/ViewExample.windows.js +++ b/packages/@react-native-windows/tester/src/js/examples/View/ViewExample.windows.js @@ -471,7 +471,7 @@ class AccessibilityExample extends React.Component< accessibilityLabel="A View with accessibility values" accessibilityHint="Accessibility Hint" accessibilityRole="button" - accessibilityValue={0} + accessibilityValue={{now: this.state.tap}} accessibilityActions={[ {name: 'cut', label: 'cut'}, {name: 'copy', label: 'copy'}, @@ -503,6 +503,9 @@ class AccessibilityExample extends React.Component< This element should be hidden from accessibility. + + This sub-view should not have an accessibility value. It's control type does not support the value pattern. + ); } diff --git a/packages/e2e-test-app-fabric/test/TextInputComponentTest.test.ts b/packages/e2e-test-app-fabric/test/TextInputComponentTest.test.ts index 61611f51d9f..6167e2fe503 100644 --- a/packages/e2e-test-app-fabric/test/TextInputComponentTest.test.ts +++ b/packages/e2e-test-app-fabric/test/TextInputComponentTest.test.ts @@ -803,4 +803,10 @@ describe('TextInput Tests', () => { const dump = await dumpVisualTree('textinput-cursorColor'); expect(dump).toMatchSnapshot(); }); + test('TextInputs which have a searchbox role should also support the value pattern.', async () => { + const component = await app.findElementByTestID('textinput-searchbox'); + await component.waitForDisplayed({timeout: 5000}); + const dump = await dumpVisualTree('textinput-searchbox'); + expect(dump).toMatchSnapshot(); + }); }); diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/HomeUIADump.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/HomeUIADump.test.ts.snap index 55dd4d226a4..9265b7cfeae 100644 --- a/packages/e2e-test-app-fabric/test/__snapshots__/HomeUIADump.test.ts.snap +++ b/packages/e2e-test-app-fabric/test/__snapshots__/HomeUIADump.test.ts.snap @@ -9627,6 +9627,7 @@ exports[`Home UIA Tree Dump Search Bar 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "Search...", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/PressableComponentTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/PressableComponentTest.test.ts.snap index 9cbe7f321a9..1769d9eb536 100644 --- a/packages/e2e-test-app-fabric/test/__snapshots__/PressableComponentTest.test.ts.snap +++ b/packages/e2e-test-app-fabric/test/__snapshots__/PressableComponentTest.test.ts.snap @@ -686,6 +686,7 @@ exports[`Pressable Tests Pressables can have event handlers 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "button", "Name": "pressable feedback events", + "ValuePattern.Value": "Press Me", "__Children": [ { "AutomationId": "", diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/TextInputComponentTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/TextInputComponentTest.test.ts.snap index fdb280782a2..a58b02269e8 100644 --- a/packages/e2e-test-app-fabric/test/__snapshots__/TextInputComponentTest.test.ts.snap +++ b/packages/e2e-test-app-fabric/test/__snapshots__/TextInputComponentTest.test.ts.snap @@ -7,6 +7,9 @@ exports[`TextInput Tests Multi-line TextInputs can enable text selection (Impera "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "multiline text selection +can also be changed imperatively", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -82,6 +85,9 @@ exports[`TextInput Tests Multi-line TextInputs can enable text selection 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "multiline text selection +can also be changed", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -157,6 +163,8 @@ exports[`TextInput Tests Single-line TextInputs can enable text selection (Imper "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "text selection can be changed imperatively", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -232,6 +240,8 @@ exports[`TextInput Tests Single-line TextInputs can enable text selection 1`] = "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "text selection can be changed", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -309,6 +319,8 @@ exports[`TextInput Tests Text have cursorColor 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "cursorColor={"green"}", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "Hello World", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -384,6 +396,7 @@ exports[`TextInput Tests TextInputs can autocapitalize: Autocapitalize Character "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -459,6 +472,7 @@ exports[`TextInput Tests TextInputs can autocapitalize: Autocapitalize Sentences "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -534,6 +548,7 @@ exports[`TextInput Tests TextInputs can autocapitalize: Autocapitalize Turned Of "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -609,6 +624,7 @@ exports[`TextInput Tests TextInputs can autocapitalize: Autocapitalize Words 1`] "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -686,6 +702,7 @@ exports[`TextInput Tests TextInputs can autocomplete, address country 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "postal-address-country", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -763,6 +780,7 @@ exports[`TextInput Tests TextInputs can autocomplete, country 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "country", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -840,6 +858,7 @@ exports[`TextInput Tests TextInputs can autocomplete, one-time-code 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "one-time-code", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -917,6 +936,7 @@ exports[`TextInput Tests TextInputs can autocomplete, sms-otp 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "sms-otp", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -992,6 +1012,8 @@ exports[`TextInput Tests TextInputs can autogrow 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "small small small small small small", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -1076,6 +1098,7 @@ exports[`TextInput Tests TextInputs can be defined as a set using accessibilityP "Name": "TextInput 1 in Set of 3", "PositionInSet": 1, "SizeofSet": 3, + "ValuePattern.IsReadOnly": false, }, { "AutomationId": "", @@ -1086,6 +1109,7 @@ exports[`TextInput Tests TextInputs can be defined as a set using accessibilityP "Name": "TextInput 2 in Set of 3", "PositionInSet": 2, "SizeofSet": 3, + "ValuePattern.IsReadOnly": false, }, { "AutomationId": "", @@ -1096,6 +1120,7 @@ exports[`TextInput Tests TextInputs can be defined as a set using accessibilityP "Name": "TextInput 3 in Set of 3", "PositionInSet": 3, "SizeofSet": 3, + "ValuePattern.IsReadOnly": false, }, ], }, @@ -1346,6 +1371,7 @@ exports[`TextInput Tests TextInputs can be editable 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "editable text input using editable prop", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -1421,6 +1447,8 @@ exports[`TextInput Tests TextInputs can be multiline, bottomright alignment 1`] "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "multiline with children, aligned bottom-right", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -1498,6 +1526,7 @@ exports[`TextInput Tests TextInputs can be multiline, center alignment 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "multiline, aligned center", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -1575,6 +1604,7 @@ exports[`TextInput Tests TextInputs can be multiline, topleft alignment 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "multiline, aligned top-left", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -1650,6 +1680,7 @@ exports[`TextInput Tests TextInputs can be set to not editable 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.Value": "Can't touch this! (>'-')> ^(' - ')^ <('-'<) (>'-')> ^(' - ')^", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -1802,6 +1833,7 @@ exports[`TextInput Tests TextInputs can clear on submit 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -1877,6 +1909,7 @@ exports[`TextInput Tests TextInputs can clear on submit with custom submit key e "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -1952,6 +1985,7 @@ exports[`TextInput Tests TextInputs can clear on submit with custom submit key e "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -2027,6 +2061,7 @@ exports[`TextInput Tests TextInputs can customize its padding 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -2104,6 +2139,7 @@ exports[`TextInput Tests TextInputs can enable spellcheck 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "Type text to test spell check functionality.", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -2179,6 +2215,8 @@ exports[`TextInput Tests TextInputs can have a background color 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "He", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -2254,6 +2292,8 @@ exports[`TextInput Tests TextInputs can have a color 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "He", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -2329,6 +2369,8 @@ exports[`TextInput Tests TextInputs can have a font family 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "He", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -2404,6 +2446,8 @@ exports[`TextInput Tests TextInputs can have a font size 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "He", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -2479,6 +2523,8 @@ exports[`TextInput Tests TextInputs can have a font style 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "He", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -2554,6 +2600,8 @@ exports[`TextInput Tests TextInputs can have a font weight 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "He", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -2629,6 +2677,8 @@ exports[`TextInput Tests TextInputs can have attributed text 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "Hello", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -2706,6 +2756,8 @@ exports[`TextInput Tests TextInputs can have caretHidden 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "caretHidden={true}", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "Hello World", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -2783,6 +2835,7 @@ exports[`TextInput Tests TextInputs can have custom return key label, Compile 1` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "returnKeyLabel: Compile", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -2860,6 +2913,7 @@ exports[`TextInput Tests TextInputs can have custom return key label, React Nati "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "returnKeyLabel: React Native", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -2937,6 +2991,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, done 1`] = "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "returnKeyType: done", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -3014,6 +3069,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, go 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "returnKeyType: go", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -3091,6 +3147,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, next 1`] = "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "returnKeyType: next", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -3168,6 +3225,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, none 1`] = "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "returnKeyType: none", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -3245,6 +3303,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, previous 1` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "returnKeyType: previous", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -3322,6 +3381,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, search 1`] "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "returnKeyType: search", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -3399,6 +3459,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, send 1`] = "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "returnKeyType: send", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -3476,6 +3537,7 @@ exports[`TextInput Tests TextInputs can have customer letter spacing, spacing=-1 "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "letterSpacing = -1", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -3553,6 +3615,7 @@ exports[`TextInput Tests TextInputs can have customer letter spacing, spacing=0 "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "letterSpacing = 0", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -3630,6 +3693,7 @@ exports[`TextInput Tests TextInputs can have customer letter spacing, spacing=2 "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "letterSpacing = 2", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -3707,6 +3771,7 @@ exports[`TextInput Tests TextInputs can have customer letter spacing, spacing=9 "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "letterSpacing = 9", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -3878,6 +3943,8 @@ exports[`TextInput Tests TextInputs can have customized letter spacing 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "He", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -3953,6 +4020,8 @@ exports[`TextInput Tests TextInputs can have customized line height 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "Hel", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -4030,6 +4099,7 @@ exports[`TextInput Tests TextInputs can have inline images 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "This has drawableLeft set", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -4107,6 +4177,7 @@ exports[`TextInput Tests TextInputs can have inline images, drawable props not s "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "This does not have drawable props set", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -4184,6 +4255,7 @@ exports[`TextInput Tests TextInputs can have inline images, drawableLeft and dra "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "This has drawableLeft and drawablePadding set", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -4261,6 +4333,7 @@ exports[`TextInput Tests TextInputs can have shadows 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "shadowColor: purple", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -4336,6 +4409,8 @@ exports[`TextInput Tests TextInputs can have text decoration lines 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "He", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -4411,6 +4486,8 @@ exports[`TextInput Tests TextInputs can have text shadows 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "He", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -4488,6 +4565,7 @@ exports[`TextInput Tests TextInputs can propagate events 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "Click inside the box to observe events being fired.", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -4565,6 +4643,7 @@ exports[`TextInput Tests TextInputs can register press events 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "Click inside the box to observe events being fired.", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -4640,6 +4719,7 @@ exports[`TextInput Tests TextInputs can rewrite characters: Replace Space with C "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -4715,6 +4795,7 @@ exports[`TextInput Tests TextInputs can rewrite characters: Replace Space with N "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -4790,6 +4871,7 @@ exports[`TextInput Tests TextInputs can rewrite characters: Replace Space with U "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -4867,6 +4949,7 @@ exports[`TextInput Tests TextInputs can set their readOnly prop to false 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "editable text input using readOnly prop", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -5019,6 +5102,7 @@ exports[`TextInput Tests TextInputs can submit with custom key, multilined and s "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -5094,6 +5178,8 @@ exports[`TextInput Tests TextInputs have a custom background color 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "Same BackgroundColor as View ", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -5169,6 +5255,8 @@ exports[`TextInput Tests TextInputs have a custom highlight color 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "Selection Color is red", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -5246,6 +5334,7 @@ exports[`TextInput Tests TextInputs have a custom placeholder text color 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "Red placeholder text color", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -5321,6 +5410,8 @@ exports[`TextInput Tests TextInputs have a custom text color 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "Green Text", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -5398,6 +5489,7 @@ exports[`TextInput Tests TextInputs have a custom underline color 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "Blue underline color", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -5475,6 +5567,7 @@ exports[`TextInput Tests TextInputs have a default placeholder text color 1`] = "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "Default placeholder text color", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -5550,6 +5643,8 @@ exports[`TextInput Tests TextInputs have a default text color 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "Default color text", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -5627,6 +5722,7 @@ exports[`TextInput Tests TextInputs have a default underline color 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "Default underline color", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -5702,6 +5798,8 @@ exports[`TextInput Tests TextInputs support secure entry 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "iloveturtles", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -5779,6 +5877,7 @@ exports[`TextInput Tests TextInputs support secure entry, with placeholder text "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "color is supported too", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -5847,6 +5946,115 @@ exports[`TextInput Tests TextInputs support secure entry, with placeholder text } `; +exports[`TextInput Tests TextInputs which have a searchbox role should also support the value pattern. 1`] = ` +{ + "Automation Tree": { + "AutomationId": "textinput-searchbox", + "ControlType": 50026, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50004, + "IsKeyboardFocusable": true, + "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "Search", + }, + ], + }, + "Component Tree": { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "textinput-searchbox", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", + "_Props": {}, + }, + ], + }, + "Visual Tree": { + "Comment": "textinput-searchbox", + "Offset": "0, 0, 0", + "Size": "916, 31", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "916, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "916, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "1, 1", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "1, 0, 0", + "Size": "-2, 1", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-1, 0, 0", + "Size": "1, 1", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-1, 1, 0", + "Size": "1, -2", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-1, -1, 0", + "Size": "1, 1", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "1, -1, 0", + "Size": "-2, 1", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "0, -1, 0", + "Size": "1, 1", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "0, 1, 0", + "Size": "1, -2", + "Visual Type": "SpriteVisual", + }, + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(0, 0, 0, 255)", + }, + "Offset": "0, 0, 0", + "Opacity": 0, + "Size": "0, 0", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 0, 0", + "Size": "0, 0", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, +} +`; + exports[`TextInput Tests TextInputs with set height and padding from theme 1`] = ` { "Automation Tree": { @@ -5856,6 +6064,7 @@ exports[`TextInput Tests TextInputs with set height and padding from theme 1`] = "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "If you set height, beware of padding set from themes", + "ValuePattern.IsReadOnly": false, }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -5931,6 +6140,8 @@ exports[`TextInput Tests Uncontrolled TextInput 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "ValuePattern.IsReadOnly": false, + "ValuePattern.Value": "Hello World!", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/TouchableComponentTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/TouchableComponentTest.test.ts.snap index 39db53b76a0..19702b93e46 100644 --- a/packages/e2e-test-app-fabric/test/__snapshots__/TouchableComponentTest.test.ts.snap +++ b/packages/e2e-test-app-fabric/test/__snapshots__/TouchableComponentTest.test.ts.snap @@ -496,6 +496,7 @@ exports[`Touchable Tests Touchables can register feedback events 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "button", "Name": "touchable feedback events", + "ValuePattern.Value": "Press Me", "__Children": [ { "AutomationId": "", diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/ViewComponentTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/ViewComponentTest.test.ts.snap index 4e301244432..cadb2233726 100644 --- a/packages/e2e-test-app-fabric/test/__snapshots__/ViewComponentTest.test.ts.snap +++ b/packages/e2e-test-app-fabric/test/__snapshots__/ViewComponentTest.test.ts.snap @@ -1100,6 +1100,7 @@ exports[`View Tests Views can have customized accessibility 1`] = ` "Name": "A View with accessibility values", "PositionInSet": 1, "SizeofSet": 1, + "ValuePattern.Value": "0", "__Children": [ { "AutomationId": "", @@ -1113,6 +1114,19 @@ exports[`View Tests Views can have customized accessibility 1`] = ` "LocalizedControlType": "text", "Name": "Current Number of Accessibility Taps: 0", }, + { + "AutomationId": "", + "ControlType": 50026, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "This sub-view should not have an accessibility value. It's control type does not support the value pattern.", + }, + ], + }, ], }, "Component Tree": { @@ -1134,12 +1148,22 @@ exports[`View Tests Views can have customized accessibility 1`] = ` "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", "_Props": {}, }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, ], }, "Visual Tree": { "Comment": "accessibility", "Offset": "0, 0, 0", - "Size": "916, 55", + "Size": "916, 74", "Visual Type": "SpriteVisual", "__Children": [ { @@ -1193,6 +1217,42 @@ exports[`View Tests Views can have customized accessibility 1`] = ` }, ], }, + { + "Offset": "0, 56, 0", + "Size": "916, 19", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "916, 19", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "916, 20", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "916, 20", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "0, 0, 0", + "Size": "0, 0", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + { + "Offset": "0, 0, 0", + "Size": "0, 0", + "Visual Type": "SpriteVisual", + }, + ], + }, ], }, } diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/snapshotPages.test.js.snap b/packages/e2e-test-app-fabric/test/__snapshots__/snapshotPages.test.js.snap index 1fc7ba91227..d636732043a 100644 --- a/packages/e2e-test-app-fabric/test/__snapshots__/snapshotPages.test.js.snap +++ b/packages/e2e-test-app-fabric/test/__snapshots__/snapshotPages.test.js.snap @@ -27402,7 +27402,7 @@ exports[`snapshotAllPages Pressable 3`] = ` "max": undefined, "min": undefined, "now": undefined, - "text": undefined, + "text": "Press Me", } } accessible={true} @@ -29424,7 +29424,7 @@ exports[`snapshotAllPages Pressable 20`] = ` "max": undefined, "min": undefined, "now": undefined, - "text": undefined, + "text": "Child Pressable", } } accessible={true} @@ -62873,6 +62873,37 @@ exports[`snapshotAllPages TextInput 42`] = ` `; +exports[`snapshotAllPages TextInput 43`] = ` + + + +`; + exports[`snapshotAllPages TextInputs with key prop 1`] = ` + + + This sub-view should not have an accessibility value. It's control type does not support the value pattern. + + `; diff --git a/packages/e2e-test-app-fabric/windows/RNTesterApp-Fabric/RNTesterApp-Fabric.cpp b/packages/e2e-test-app-fabric/windows/RNTesterApp-Fabric/RNTesterApp-Fabric.cpp index 7d2552d7289..6d67727369c 100644 --- a/packages/e2e-test-app-fabric/windows/RNTesterApp-Fabric/RNTesterApp-Fabric.cpp +++ b/packages/e2e-test-app-fabric/windows/RNTesterApp-Fabric/RNTesterApp-Fabric.cpp @@ -306,6 +306,8 @@ winrt::Windows::Data::Json::JsonObject DumpUIATreeRecurse( BSTR name; int positionInSet = 0; int sizeOfSet = 0; + BSTR value; + BOOL isReadOnly; pTarget->get_CurrentAutomationId(&automationId); pTarget->get_CurrentControlType(&controlType); @@ -331,7 +333,19 @@ winrt::Windows::Data::Json::JsonObject DumpUIATreeRecurse( InsertStringValueIfNotEmpty(result, L"Name", name); InsertIntValueIfNotDefault(result, L"PositionInSet", positionInSet); InsertIntValueIfNotDefault(result, L"SizeofSet", sizeOfSet); - + IValueProvider *valuePattern; + hr = pTarget->GetCurrentPattern(UIA_ValuePatternId, reinterpret_cast(&valuePattern)); + if (SUCCEEDED(hr) && valuePattern) { + hr = valuePattern->get_Value(&value); + if (SUCCEEDED(hr)) { + InsertStringValueIfNotEmpty(result, L"ValuePattern.Value", value); + } + hr = valuePattern->get_IsReadOnly(&isReadOnly); + if (SUCCEEDED(hr)) { + InsertBooleanValueIfNotDefault(result, L"ValuePattern.IsReadOnly", isReadOnly, true); + } + valuePattern->Release(); + } IUIAutomationElement *pChild; IUIAutomationElement *pSibling; pWalker->GetFirstChildElement(pTarget, &pChild); diff --git a/packages/e2e-test-app/test/__snapshots__/ViewComponentTest.test.ts.snap b/packages/e2e-test-app/test/__snapshots__/ViewComponentTest.test.ts.snap index dba5464c7ff..631f203d108 100644 --- a/packages/e2e-test-app/test/__snapshots__/ViewComponentTest.test.ts.snap +++ b/packages/e2e-test-app/test/__snapshots__/ViewComponentTest.test.ts.snap @@ -373,7 +373,7 @@ exports[`ViewTests Views can have accessibility customization 1`] = ` "CornerRadius": "0,0,0,0", "FlowDirection": "LeftToRight", "Foreground": "#FF000000", - "Height": 57, + "Height": 76, "HorizontalAlignment": "Stretch", "Left": 0, "Margin": "0,0,0,0", @@ -408,7 +408,7 @@ exports[`ViewTests Views can have accessibility customization 1`] = ` "Clip": null, "CornerRadius": "0,0,0,0", "FlowDirection": "LeftToRight", - "Height": 57, + "Height": 76, "HorizontalAlignment": "Stretch", "Left": 0, "Margin": "0,0,0,0", @@ -487,6 +487,82 @@ exports[`ViewTests Views can have accessibility customization 1`] = ` }, ], }, + { + "Background": null, + "BorderBrush": null, + "BorderThickness": "0,0,0,0", + "Clip": null, + "CornerRadius": "0,0,0,0", + "FlowDirection": "LeftToRight", + "Foreground": "#FF000000", + "Height": 19, + "HorizontalAlignment": "Stretch", + "Left": 0, + "Margin": "0,0,0,0", + "Padding": "0,0,0,0", + "Top": 57, + "VerticalAlignment": "Stretch", + "Visibility": "Visible", + "Width": 718, + "XamlType": "Microsoft.ReactNative.ViewControl", + "children": [ + { + "Background": null, + "BorderBrush": null, + "BorderThickness": "0,0,0,0", + "Clip": null, + "CornerRadius": "0,0,0,0", + "FlowDirection": "LeftToRight", + "Foreground": "#FF000000", + "HorizontalAlignment": "Stretch", + "Left": 0, + "Margin": "0,0,0,0", + "Padding": "0,0,0,0", + "Top": 0, + "VerticalAlignment": "Stretch", + "Visibility": "Visible", + "XamlType": "Windows.UI.Xaml.Controls.ContentPresenter", + "children": [ + { + "Background": null, + "BorderBrush": "#E4000000", + "BorderThickness": "0,0,0,0", + "Clip": null, + "CornerRadius": "0,0,0,0", + "FlowDirection": "LeftToRight", + "Height": 19, + "HorizontalAlignment": "Stretch", + "Left": 0, + "Margin": "0,0,0,0", + "Padding": "0,0,0,0", + "Top": 0, + "VerticalAlignment": "Stretch", + "Visibility": "Visible", + "Width": 718, + "XamlType": "Microsoft.ReactNative.ViewPanel", + "children": [ + { + "Clip": null, + "FlowDirection": "LeftToRight", + "Foreground": "#FF000000", + "Height": 19, + "HorizontalAlignment": "Stretch", + "Left": 0, + "Margin": "0,0,0,0", + "Padding": "0,0,0,0", + "Text": "This sub-view should not have an accessibility value. It's control type does not support the value pattern.", + "Top": 0, + "VerticalAlignment": "Stretch", + "Visibility": "Visible", + "Width": 718, + "XamlType": "Windows.UI.Xaml.Controls.TextBlock", + }, + ], + }, + ], + }, + ], + }, ], }, ], diff --git a/vnext/Microsoft.ReactNative/Fabric/ComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/ComponentView.cpp index 6876376d759..2d026e43408 100644 --- a/vnext/Microsoft.ReactNative/Fabric/ComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/ComponentView.cpp @@ -387,7 +387,7 @@ winrt::IInspectable ComponentView::EnsureUiaProvider() noexcept { return nullptr; } -std::optional ComponentView::getAcccessiblityValue() noexcept { +std::optional ComponentView::getAccessiblityValue() noexcept { return std::nullopt; } diff --git a/vnext/Microsoft.ReactNative/Fabric/ComponentView.h b/vnext/Microsoft.ReactNative/Fabric/ComponentView.h index 5683d19a5f3..e2fb698fe92 100644 --- a/vnext/Microsoft.ReactNative/Fabric/ComponentView.h +++ b/vnext/Microsoft.ReactNative/Fabric/ComponentView.h @@ -120,7 +120,7 @@ struct ComponentView : public ComponentViewT { virtual facebook::react::Tag hitTest(facebook::react::Point pt, facebook::react::Point &localPt, bool ignorePointerEvents = false) const noexcept; virtual winrt::IInspectable EnsureUiaProvider() noexcept; - virtual std::optional getAcccessiblityValue() noexcept; + virtual std::optional getAccessiblityValue() noexcept; virtual void setAcccessiblityValue(std::string &&value) noexcept; virtual bool getAcccessiblityIsReadOnly() noexcept; winrt::Microsoft::ReactNative::IReactContext ReactContext() const noexcept; diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp index cffc7ee7b7f..60faca9bbf2 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp @@ -125,6 +125,10 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::get_ProviderOptions(Prov return S_OK; } +bool accessibilityValueHasValue(const facebook::react::AccessibilityValue &value) { + return (value.min.has_value() && value.max.has_value()) || value.now.has_value() || value.text.has_value(); +} + HRESULT __stdcall CompositionDynamicAutomationProvider::GetPatternProvider(PATTERNID patternId, IUnknown **pRetVal) { if (pRetVal == nullptr) return E_POINTER; @@ -135,11 +139,15 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPatternProvider(PATTE if (strongView == nullptr) return UIA_E_ELEMENTNOTAVAILABLE; + auto compositionView = strongView.try_as(); + if (compositionView == nullptr) + return UIA_E_ELEMENTNOTAVAILABLE; auto props = std::static_pointer_cast( winrt::get_self(strongView)->props()); if (props == nullptr) return UIA_E_ELEMENTNOTAVAILABLE; - auto accessibilityRole = props->accessibilityRole; + auto accessibilityRole = + props->accessibilityRole.empty() ? compositionView->DefaultControlType() : props->accessibilityRole; // Invoke control pattern is used to support controls that do not maintain state // when activated but rather initiate or perform a single, unambiguous action. if (patternId == UIA_InvokePatternId && @@ -155,7 +163,15 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPatternProvider(PATTE AddRef(); } - if (patternId == UIA_ValuePatternId) { + if (patternId == UIA_ValuePatternId && + (accessibilityRole == "textinput" || accessibilityRole == "searchbox" || + (accessibilityRole == "button" && accessibilityValueHasValue(props->accessibilityValue)) || + (accessibilityRole == "combobox" && accessibilityValueHasValue(props->accessibilityValue)) || + (accessibilityRole == "link" && accessibilityValueHasValue(props->accessibilityValue)) || + (accessibilityRole == "listitem" && accessibilityValueHasValue(props->accessibilityValue)) || + (accessibilityRole == "progressbar" && accessibilityValueHasValue(props->accessibilityValue)) || + (accessibilityRole == "adjustable" && accessibilityValueHasValue(props->accessibilityValue)) || + (accessibilityRole == "spinbutton" && accessibilityValueHasValue(props->accessibilityValue)))) { *pRetVal = static_cast(this); AddRef(); } @@ -408,7 +424,7 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::get_Value(BSTR *pRetVal) return UIA_E_ELEMENTNOTAVAILABLE; *pRetVal = StringToBSTR(winrt::get_self(strongView) - ->getAcccessiblityValue() + ->getAccessiblityValue() .value_or("")); return S_OK; } @@ -421,8 +437,24 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::get_IsReadOnly(BOOL *pRe if (!strongView) return UIA_E_ELEMENTNOTAVAILABLE; - *pRetVal = winrt::get_self(strongView) - ->getAcccessiblityIsReadOnly(); + auto props = std::static_pointer_cast( + winrt::get_self(strongView)->props()); + if (props == nullptr) + return UIA_E_ELEMENTNOTAVAILABLE; + auto accessibilityRole = props->accessibilityRole; + if (accessibilityRole.empty()) { + // Control is using default control type. Use default IsReadOnly value. + *pRetVal = winrt::get_self(strongView) + ->getAcccessiblityIsReadOnly(); + } else if ( + accessibilityRole == "textinput" || accessibilityRole == "searchbox" || accessibilityRole == "adjustable" || + accessibilityRole == "spinbutton" || accessibilityRole == "combobox") { + // Control is using customized control type which should not be IsReadOnly for value pattern. + *pRetVal = false; + } else { + // Control is using customized control type which should be IsReadOnly for value pattern. + *pRetVal = true; + } return S_OK; } diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp index 7a969d91da2..835c9d2d001 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp @@ -1334,8 +1334,9 @@ void ComponentView::updateAccessibilityProps( m_uiaProvider, UIA_SizeOfSetPropertyId, oldViewProps.accessibilitySetSize, newViewProps.accessibilitySetSize); } -std::optional ComponentView::getAcccessiblityValue() noexcept { - return std::static_pointer_cast(props())->accessibilityValue.text; +std::optional ComponentView::getAccessiblityValue() noexcept { + return winrt::Microsoft::ReactNative::implementation::extractAccessibilityValue( + std::static_pointer_cast(props())->accessibilityValue); } void ComponentView::setAcccessiblityValue(std::string &&value) noexcept { diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h index ef9927b1f76..0a031a6d651 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h @@ -115,7 +115,7 @@ struct ComponentView void EnsureTransformMatrixFacade() noexcept; winrt::IInspectable EnsureUiaProvider() noexcept override; - std::optional getAcccessiblityValue() noexcept override; + std::optional getAccessiblityValue() noexcept override; void setAcccessiblityValue(std::string &&value) noexcept override; bool getAcccessiblityIsReadOnly() noexcept override; virtual winrt::Microsoft::ReactNative::implementation::ClipState getClipState() noexcept; diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp index 6431a2498ef..f2bee67fd20 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp @@ -1254,7 +1254,7 @@ void WindowsTextInputComponentView::FinalizeUpdates( } } -std::optional WindowsTextInputComponentView::getAcccessiblityValue() noexcept { +std::optional WindowsTextInputComponentView::getAccessiblityValue() noexcept { return GetTextFromRichEdit(); } diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h index ee0aef6e434..e2c5da407e0 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h @@ -73,7 +73,7 @@ struct WindowsTextInputComponentView const winrt::Microsoft::ReactNative::Composition::Input::CharacterReceivedRoutedEventArgs &args) noexcept override; - std::optional getAcccessiblityValue() noexcept override; + std::optional getAccessiblityValue() noexcept override; void setAcccessiblityValue(std::string &&value) noexcept override; bool getAcccessiblityIsReadOnly() noexcept override; diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp index 54670617af3..8acdfc0387d 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp @@ -163,4 +163,14 @@ void UpdateUiaProperty( spProviderSimple.get(), propId, CComVariant(oldValue.c_str()), CComVariant(newValue.c_str())); } +std::string extractAccessibilityValue(const facebook::react::AccessibilityValue &value) noexcept { + if (value.now.has_value()) { + return std::to_string(value.now.value()); + } else if (value.text.has_value()) { + return value.text.value(); + } else { + return ""; + } +} + } // namespace winrt::Microsoft::ReactNative::implementation diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.h b/vnext/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.h index 2350b164bee..c69aadce19b 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.h @@ -29,4 +29,6 @@ void UpdateUiaProperty( const std::string &oldValue, const std::string &newValue) noexcept; +std::string extractAccessibilityValue(const facebook::react::AccessibilityValue &value) noexcept; + } // namespace winrt::Microsoft::ReactNative::implementation