From 859a88f5904db6b282fb8ca8326a6f80749d6ee5 Mon Sep 17 00:00:00 2001 From: Chiara Mooney <34109996+chiaramooney@users.noreply.github.com> Date: Thu, 6 Feb 2025 09:28:41 -0800 Subject: [PATCH 1/7] [Fabric] Add Support for ITextProvider, ITextProvider2, and ITextRangeProvider (#14332) * Partial Implementation * Add More Implementation * More Implementation * More Implementation * Add Support for Bounding Rectangles * Complete Initial Implementation * Change files * Code Cleanup * Code Cleanup * Update Snapshots + Code Cleanup * Update Snapshots * Address Feedback * Address Feedback * Update Snapshots * Fix Tests --------- Co-authored-by: Jon Thysell --- ...-d334336e-c641-4b9e-bbd3-9c6dd4f5b228.json | 7 + .../test/ButtonComponentTest.test.ts | 6 +- .../test/PressableComponentTest.test.ts | 12 +- .../AccessibilityTest.test.ts.snap | 7 + .../ButtonComponentTest.test.ts.snap | 12 + .../FlatListComponentTest.test.ts.snap | 6372 +++++++++++++++++ .../__snapshots__/HomeUIADump.test.ts.snap | 155 + .../ImageComponentTest.test.ts.snap | 26 + .../LegacySelectableTextTest.test.ts.snap | 4 + .../LegacyTextHitTestTest.test.ts.snap | 15 + .../LegacyTextInputTest.test.ts.snap | 100 + .../PressableComponentTest.test.ts.snap | 31 + .../ScrollViewComponentTest.test.ts.snap | 5 + .../TextComponentTest.test.ts.snap | 19 + .../TextInputComponentTest.test.ts.snap | 69 + .../TouchableComponentTest.test.ts.snap | 9 + .../ViewComponentTest.test.ts.snap | 51 + .../RNTesterApp-Fabric/RNTesterApp-Fabric.cpp | 16 + .../CompositionDynamicAutomationProvider.cpp | 20 + .../CompositionDynamicAutomationProvider.h | 1 + .../Composition/CompositionTextProvider.cpp | 115 + .../Composition/CompositionTextProvider.h | 41 + .../CompositionTextRangeProvider.cpp | 298 + .../CompositionTextRangeProvider.h | 59 + .../Fabric/Composition/UiaHelpers.cpp | 14 + .../Fabric/Composition/UiaHelpers.h | 3 + vnext/Shared/Shared.vcxitems | 6 + vnext/Shared/Shared.vcxitems.filters | 8 + 28 files changed, 7474 insertions(+), 7 deletions(-) create mode 100644 change/react-native-windows-d334336e-c641-4b9e-bbd3-9c6dd4f5b228.json create mode 100644 packages/e2e-test-app-fabric/test/__snapshots__/FlatListComponentTest.test.ts.snap create mode 100644 vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.cpp create mode 100644 vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.h create mode 100644 vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.cpp create mode 100644 vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.h diff --git a/change/react-native-windows-d334336e-c641-4b9e-bbd3-9c6dd4f5b228.json b/change/react-native-windows-d334336e-c641-4b9e-bbd3-9c6dd4f5b228.json new file mode 100644 index 00000000000..f68dfc5830b --- /dev/null +++ b/change/react-native-windows-d334336e-c641-4b9e-bbd3-9c6dd4f5b228.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "ITextProvider Implementation", + "packageName": "react-native-windows", + "email": "34109996+chiaramooney@users.noreply.github.com", + "dependentChangeType": "patch" +} diff --git a/packages/e2e-test-app-fabric/test/ButtonComponentTest.test.ts b/packages/e2e-test-app-fabric/test/ButtonComponentTest.test.ts index 3b28682be94..f7b85df5c53 100644 --- a/packages/e2e-test-app-fabric/test/ButtonComponentTest.test.ts +++ b/packages/e2e-test-app-fabric/test/ButtonComponentTest.test.ts @@ -27,7 +27,11 @@ const searchBox = async (input: string) => { await app.waitUntil( async () => { await searchBox.setValue(input); - return (await searchBox.getText()) === input; + if (input === '') { + return (await searchBox.getText()) === 'Search...'; + } else { + return (await searchBox.getText()) === input; + } }, { interval: 1500, diff --git a/packages/e2e-test-app-fabric/test/PressableComponentTest.test.ts b/packages/e2e-test-app-fabric/test/PressableComponentTest.test.ts index a16f1879521..49313784258 100644 --- a/packages/e2e-test-app-fabric/test/PressableComponentTest.test.ts +++ b/packages/e2e-test-app-fabric/test/PressableComponentTest.test.ts @@ -45,7 +45,7 @@ describe('Pressable Tests', () => { await app.waitUntil( async () => { await searchBox.setValue(['Backspace', 'Backspace', 'Backspace']); - return (await searchBox.getText()) === ''; + return (await searchBox.getText()) === 'Search...'; }, { interval: 1500, @@ -84,7 +84,7 @@ describe('Pressable Tests', () => { await app.waitUntil( async () => { await searchBox.setValue(['Backspace', 'Backspace', 'Backspace']); - return (await searchBox.getText()) === ''; + return (await searchBox.getText()) === 'Search...'; }, { interval: 1500, @@ -118,7 +118,7 @@ describe('Pressable Tests', () => { await app.waitUntil( async () => { await searchBox.setValue(['Backspace', 'Backspace', 'Backspace']); - return (await searchBox.getText()) === ''; + return (await searchBox.getText()) === 'Search...'; }, { interval: 1500, @@ -152,7 +152,7 @@ describe('Pressable Tests', () => { await app.waitUntil( async () => { await searchBox.setValue(['Backspace', 'Backspace', 'Backspace']); - return (await searchBox.getText()) === ''; + return (await searchBox.getText()) === 'Search...'; }, { interval: 1500, @@ -181,7 +181,7 @@ describe('Pressable Tests', () => { await app.waitUntil( async () => { await searchBox.setValue(['Backspace', 'Backspace', 'Backspace']); - return (await searchBox.getText()) === ''; + return (await searchBox.getText()) === 'Search...'; }, { interval: 1500, @@ -210,7 +210,7 @@ describe('Pressable Tests', () => { await app.waitUntil( async () => { await searchBox.setValue(['Backspace', 'Backspace', 'Backspace']); - return (await searchBox.getText()) === ''; + return (await searchBox.getText()) === 'Search...'; }, { interval: 1500, diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/AccessibilityTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/AccessibilityTest.test.ts.snap index b70e1b1ac77..41968769ec3 100644 --- a/packages/e2e-test-app-fabric/test/__snapshots__/AccessibilityTest.test.ts.snap +++ b/packages/e2e-test-app-fabric/test/__snapshots__/AccessibilityTest.test.ts.snap @@ -17,6 +17,7 @@ exports[`Accessibility Tests Components can store range data by setting the min, "ControlType": 50020, "LocalizedControlType": "text", "Name": "The View's (accessibilityRole == adjustable, ie. Slider) properties should be the following according to UIA: Min- 5Max- 125Now- 10", + "TextRangePattern.GetText": "The View's (accessibilityRole == adjustable, ie. Slider) properties should be the following according to UIA: Min- 5Max- 125Now- 10", }, ], }, @@ -73,6 +74,7 @@ exports[`Accessibility Tests Components can store value data by setting the text "ControlType": 50020, "LocalizedControlType": "text", "Name": "The View's properties should be the following according to UIA: Text- testText", + "TextRangePattern.GetText": "The View's properties should be the following according to UIA: Text- testText", }, ], }, @@ -129,6 +131,7 @@ exports[`Accessibility Tests Elements can set accessibilityState:selected to fal "ControlType": 50020, "LocalizedControlType": "text", "Name": "Unselected", + "TextRangePattern.GetText": "Unselected", }, ], }, @@ -187,6 +190,7 @@ exports[`Accessibility Tests Elements can set accessibilityState:selected to tru "ControlType": 50020, "LocalizedControlType": "text", "Name": "Selected", + "TextRangePattern.GetText": "Selected", }, ], }, @@ -252,6 +256,7 @@ exports[`Accessibility Tests Selectable items must have a Selection Container. E "ControlType": 50020, "LocalizedControlType": "text", "Name": "Unselected", + "TextRangePattern.GetText": "Unselected", }, ], }, @@ -267,6 +272,7 @@ exports[`Accessibility Tests Selectable items must have a Selection Container. E "ControlType": 50020, "LocalizedControlType": "text", "Name": "Unselected", + "TextRangePattern.GetText": "Unselected", }, ], }, @@ -282,6 +288,7 @@ exports[`Accessibility Tests Selectable items must have a Selection Container. E "ControlType": 50020, "LocalizedControlType": "text", "Name": "Unselected", + "TextRangePattern.GetText": "Unselected", }, ], }, diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/ButtonComponentTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/ButtonComponentTest.test.ts.snap index 5684dfbf035..be96cdebaab 100644 --- a/packages/e2e-test-app-fabric/test/__snapshots__/ButtonComponentTest.test.ts.snap +++ b/packages/e2e-test-app-fabric/test/__snapshots__/ButtonComponentTest.test.ts.snap @@ -15,6 +15,7 @@ exports[`Button Tests Buttons can be disabled 1`] = ` "IsEnabled": false, "LocalizedControlType": "text", "Name": "Submit Application", + "TextRangePattern.GetText": "Submit Application", }, ], }, @@ -158,6 +159,7 @@ exports[`Button Tests Buttons can have accessibility labels 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Submit Application", + "TextRangePattern.GetText": "Submit Application", }, ], }, @@ -306,6 +308,7 @@ exports[`Button Tests Buttons can have accessibility props 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Submit Application", + "TextRangePattern.GetText": "Submit Application", }, ], }, @@ -432,6 +435,7 @@ exports[`Button Tests Buttons can have accessibility states 1`] = ` "IsEnabled": false, "LocalizedControlType": "text", "Name": "Submit Application", + "TextRangePattern.GetText": "Submit Application", }, ], }, @@ -575,6 +579,7 @@ exports[`Button Tests Buttons can have custom colors 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Cancel Application", + "TextRangePattern.GetText": "Cancel Application", }, ], }, @@ -833,6 +838,7 @@ exports[`Button Tests Buttons can have custom focusable and accessible props 2`] "ControlType": 50020, "LocalizedControlType": "text", "Name": "Button with focusable=false", + "TextRangePattern.GetText": "Button with focusable=false", }, ], }, @@ -1074,6 +1080,7 @@ exports[`Button Tests Buttons can have flexbox styling 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Cancel", + "TextRangePattern.GetText": "Cancel", }, ], }, @@ -1089,6 +1096,7 @@ exports[`Button Tests Buttons can have flexbox styling 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Submit", + "TextRangePattern.GetText": "Submit", }, ], }, @@ -1400,6 +1408,7 @@ exports[`Button Tests Buttons can have flexbox styling with three buttons 1`] = "ControlType": 50020, "LocalizedControlType": "text", "Name": "Cancel", + "TextRangePattern.GetText": "Cancel", }, ], }, @@ -1415,6 +1424,7 @@ exports[`Button Tests Buttons can have flexbox styling with three buttons 1`] = "ControlType": 50020, "LocalizedControlType": "text", "Name": "Save For Later", + "TextRangePattern.GetText": "Save For Later", }, ], }, @@ -1430,6 +1440,7 @@ exports[`Button Tests Buttons can have flexbox styling with three buttons 1`] = "ControlType": 50020, "LocalizedControlType": "text", "Name": "Submit", + "TextRangePattern.GetText": "Submit", }, ], }, @@ -1870,6 +1881,7 @@ exports[`Button Tests Buttons have default styling 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Submit Application", + "TextRangePattern.GetText": "Submit Application", }, ], }, diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/FlatListComponentTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/FlatListComponentTest.test.ts.snap new file mode 100644 index 00000000000..63a9e12c59b --- /dev/null +++ b/packages/e2e-test-app-fabric/test/__snapshots__/FlatListComponentTest.test.ts.snap @@ -0,0 +1,6372 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`FlatList Tests A FlatList can be filtered by a key word 1`] = ` +{ + "Automation Tree": { + "AutomationId": "flatlist-basic", + "ControlType": 50008, + "LocalizedControlType": "list", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Item 555 - Lorem ipsum dolor sit amet, ius ad pertinax oportere accommodare, a", + "TextRangePattern.GetText": "Item 555 - Lorem ipsum dolor sit amet, ius ad pertinax oportere accommodare, a", + }, + ], + }, + ], + }, + "Component Tree": { + "Type": "Microsoft.ReactNative.Composition.ScrollViewComponentView", + "_Props": { + "TestId": "flatlist-basic", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ActivityIndicatorComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ImageComponentView", + "_Props": { + "Sources": [ + { + "Size": "128, 128", + "Type": "Local", + "Uri": "@react-native-windows/tester/js/assets/dislike.png", + }, + ], + }, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ActivityIndicatorComponentView", + "_Props": {}, + }, + ], + }, + ], + }, + ], + }, + "Visual Tree": { + "Comment": "flatlist-basic", + "Offset": "0, 0, 0", + "Size": "998, 398", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(0, 0, 0, 0)", + }, + "Offset": "0, 0, 0", + "Size": "998, 398", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(0, 0, 0, 0)", + }, + "Offset": "0, 0, 0", + "Size": "998, 398", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 398", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 255, 255, 255)", + }, + "Offset": "0, 0, 0", + "Size": "998, 398", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 100", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 100", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 100", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 100", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "0, 1", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "0, 0, 0", + "Size": "-0, 1", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-0, 0, 0", + "Size": "0, 1", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-0, 1, 0", + "Size": "0, -1", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-0, -0, 0", + "Size": "0, 0", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "0, -0, 0", + "Size": "-0, 0", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "0, -0, 0", + "Size": "0, 0", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "0, 1, 0", + "Size": "0, -1", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + { + "Offset": "489, 41, 0", + "Size": "20, 20", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "20, 20", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "0, 0, 0", + "Size": "0, 0", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "0, 0", + "Visual Type": "Visual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "80, 80", + "Visual Type": "Visual", + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 100, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 255, 255, 255)", + }, + "Offset": "0, 0, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "5, 10, 0", + "Size": "50, 50", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "50, 50", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "60, 10, 0", + "Size": "928, 52", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "928, 52", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 172, 0", + "Size": "998, 100", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 100", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 100", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 100", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "0, 1", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "0, 0, 0", + "Size": "-0, 1", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-0, 0, 0", + "Size": "0, 1", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-0, 1, 0", + "Size": "0, -1", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-0, -0, 0", + "Size": "0, 0", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "0, -0, 0", + "Size": "-0, 0", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "0, -0, 0", + "Size": "0, 0", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "0, 1, 0", + "Size": "0, -1", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + { + "Offset": "489, 41, 0", + "Size": "20, 20", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "20, 20", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "0, 0, 0", + "Size": "0, 0", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "0, 0", + "Visual Type": "Visual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "80, 80", + "Visual Type": "Visual", + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "-13, 0, 0", + "Size": "12, 0", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "-12, 3, 0", + "Opacity": 0, + "Size": "12, 392", + "Visual Type": "Visual", + }, + { + "Offset": "0, 4, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "0, -16, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-5, 16, 0", + "Size": "6, 366", + "Visual Type": "Visual", + }, + ], + }, + { + "Offset": "0, -13, 0", + "Size": "0, 12", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "3, -12, 0", + "Opacity": 0, + "Size": "992, 12", + "Visual Type": "Visual", + }, + { + "Offset": "4, 0, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-16, 0, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "16, -5, 0", + "Size": "966, 6", + "Visual Type": "Visual", + }, + ], + }, + ], + }, +} +`; + +exports[`FlatList Tests A FlatList can be inverted 1`] = ` +{ + "Automation Tree": { + "AutomationId": "flat_list", + "ControlType": 50014, + "LocalizedControlType": "scroll bar", + "__Children": [ + { + "AutomationId": "Pizza", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Pizza", + "TextRangePattern.GetText": "Pizza", + }, + ], + }, + { + "AutomationId": "Burger", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Burger", + "TextRangePattern.GetText": "Burger", + }, + ], + }, + { + "AutomationId": "Risotto", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Risotto", + "TextRangePattern.GetText": "Risotto", + }, + ], + }, + { + "AutomationId": "French Fries", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "French Fries", + "TextRangePattern.GetText": "French Fries", + }, + ], + }, + { + "AutomationId": "Onion Rings", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Onion Rings", + "TextRangePattern.GetText": "Onion Rings", + }, + ], + }, + { + "AutomationId": "Fried Shrimps", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Fried Shrimps", + "TextRangePattern.GetText": "Fried Shrimps", + }, + ], + }, + { + "AutomationId": "Water", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Water", + "TextRangePattern.GetText": "Water", + }, + ], + }, + { + "AutomationId": "Coke", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Coke", + "TextRangePattern.GetText": "Coke", + }, + ], + }, + { + "AutomationId": "Beer", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Beer", + "TextRangePattern.GetText": "Beer", + }, + ], + }, + { + "AutomationId": "Cheesecake", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Cheesecake", + "TextRangePattern.GetText": "Cheesecake", + }, + ], + }, + { + "AutomationId": "Brownie", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Brownie", + "TextRangePattern.GetText": "Brownie", + }, + ], + }, + ], + }, + "Component Tree": { + "Type": "Microsoft.ReactNative.Composition.ScrollViewComponentView", + "_Props": { + "TestId": "flat_list", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Pizza", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Burger", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Risotto", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "French Fries", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Onion Rings", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Fried Shrimps", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Water", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Coke", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Beer", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Cheesecake", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Brownie", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + ], + }, + ], + }, + "Visual Tree": { + "Comment": "flat_list", + "Offset": "0, 0, 0", + "Size": "998, 534", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(0, 0, 0, 0)", + }, + "Offset": "0, 0, 0", + "Size": "998, 534", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(0, 0, 0, 0)", + }, + "Offset": "0, 0, 0", + "Size": "998, 946", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 946", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 946", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 8, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Pizza", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 94, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Burger", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 180, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Risotto", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 266, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "French Fries", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 352, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Onion Rings", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 438, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Fried Shrimps", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 524, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Water", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 610, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Coke", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 696, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Beer", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 782, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Cheesecake", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 868, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Brownie", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "-13, 0, 0", + "Size": "12, 0", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "-12, 3, 0", + "Opacity": 0, + "Size": "12, 528", + "Visual Type": "Visual", + }, + { + "Offset": "0, 4, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "0, -16, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-5, 16, 0", + "Size": "6, 283", + "Visual Type": "Visual", + }, + ], + }, + { + "Offset": "0, -13, 0", + "Size": "0, 12", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "3, -12, 0", + "Opacity": 0, + "Size": "992, 12", + "Visual Type": "Visual", + }, + { + "Offset": "4, 0, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-16, 0, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "16, -5, 0", + "Size": "966, 6", + "Visual Type": "Visual", + }, + ], + }, + ], + }, +} +`; + +exports[`FlatList Tests A FlatList can have a content inset 1`] = ` +{ + "Automation Tree": { + "AutomationId": "flat_list", + "ControlType": 50014, + "LocalizedControlType": "scroll bar", + "__Children": [ + { + "AutomationId": "Pizza", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Pizza", + "TextRangePattern.GetText": "Pizza", + }, + ], + }, + { + "AutomationId": "Burger", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Burger", + "TextRangePattern.GetText": "Burger", + }, + ], + }, + { + "AutomationId": "Risotto", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Risotto", + "TextRangePattern.GetText": "Risotto", + }, + ], + }, + { + "AutomationId": "French Fries", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "French Fries", + "TextRangePattern.GetText": "French Fries", + }, + ], + }, + { + "AutomationId": "Onion Rings", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Onion Rings", + "TextRangePattern.GetText": "Onion Rings", + }, + ], + }, + { + "AutomationId": "Fried Shrimps", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Fried Shrimps", + "TextRangePattern.GetText": "Fried Shrimps", + }, + ], + }, + { + "AutomationId": "Water", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Water", + "TextRangePattern.GetText": "Water", + }, + ], + }, + { + "AutomationId": "Coke", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Coke", + "TextRangePattern.GetText": "Coke", + }, + ], + }, + { + "AutomationId": "Beer", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Beer", + "TextRangePattern.GetText": "Beer", + }, + ], + }, + { + "AutomationId": "Cheesecake", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Cheesecake", + "TextRangePattern.GetText": "Cheesecake", + }, + ], + }, + { + "AutomationId": "Brownie", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Brownie", + "TextRangePattern.GetText": "Brownie", + }, + ], + }, + ], + }, + "Component Tree": { + "Type": "Microsoft.ReactNative.Composition.ScrollViewComponentView", + "_Props": { + "TestId": "flat_list", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Pizza", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Burger", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Risotto", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "French Fries", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Onion Rings", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Fried Shrimps", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Water", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Coke", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Beer", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Cheesecake", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Brownie", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + ], + }, + ], + }, + "Visual Tree": { + "Comment": "flat_list", + "Offset": "0, 0, 0", + "Size": "998, 534", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(0, 0, 0, 0)", + }, + "Offset": "0, 0, 0", + "Size": "998, 534", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(0, 0, 0, 0)", + }, + "Offset": "0, 0, 0", + "Size": "998, 946", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 946", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 946", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 8, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Pizza", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 94, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Burger", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 180, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Risotto", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 266, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "French Fries", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 352, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Onion Rings", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 438, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Fried Shrimps", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 524, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Water", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 610, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Coke", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 696, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Beer", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 782, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Cheesecake", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 868, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Brownie", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "-13, 0, 0", + "Size": "12, 0", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "-12, 3, 0", + "Opacity": 0, + "Size": "12, 528", + "Visual Type": "Visual", + }, + { + "Offset": "0, 4, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "0, -16, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-5, 16, 0", + "Size": "6, 283", + "Visual Type": "Visual", + }, + ], + }, + { + "Offset": "0, -13, 0", + "Size": "0, 12", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "3, -12, 0", + "Opacity": 0, + "Size": "992, 12", + "Visual Type": "Visual", + }, + { + "Offset": "4, 0, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-16, 0, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "16, -5, 0", + "Size": "966, 6", + "Visual Type": "Visual", + }, + ], + }, + ], + }, +} +`; + +exports[`FlatList Tests A FlatList can have separators 1`] = ` +{ + "Automation Tree": { + "AutomationId": "flat_list", + "ControlType": 50014, + "LocalizedControlType": "scroll bar", + "__Children": [ + { + "AutomationId": "Pizza", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Pizza", + "TextRangePattern.GetText": "Pizza", + }, + ], + }, + { + "AutomationId": "flat_list_separator", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Separator for leading Pizza and trailing undefined has not been pressed", + "TextRangePattern.GetText": "Separator for leading Pizza and trailing undefined has not been pressed", + }, + { + "AutomationId": "Burger", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Burger", + "TextRangePattern.GetText": "Burger", + }, + ], + }, + { + "AutomationId": "flat_list_separator", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Separator for leading Burger and trailing undefined has not been pressed", + "TextRangePattern.GetText": "Separator for leading Burger and trailing undefined has not been pressed", + }, + { + "AutomationId": "Risotto", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Risotto", + "TextRangePattern.GetText": "Risotto", + }, + ], + }, + { + "AutomationId": "flat_list_separator", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Separator for leading Risotto and trailing undefined has not been pressed", + "TextRangePattern.GetText": "Separator for leading Risotto and trailing undefined has not been pressed", + }, + { + "AutomationId": "French Fries", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "French Fries", + "TextRangePattern.GetText": "French Fries", + }, + ], + }, + { + "AutomationId": "flat_list_separator", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Separator for leading French Fries and trailing undefined has not been pressed", + "TextRangePattern.GetText": "Separator for leading French Fries and trailing undefined has not been pressed", + }, + { + "AutomationId": "Onion Rings", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Onion Rings", + "TextRangePattern.GetText": "Onion Rings", + }, + ], + }, + { + "AutomationId": "flat_list_separator", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Separator for leading Onion Rings and trailing undefined has not been pressed", + "TextRangePattern.GetText": "Separator for leading Onion Rings and trailing undefined has not been pressed", + }, + { + "AutomationId": "Fried Shrimps", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Fried Shrimps", + "TextRangePattern.GetText": "Fried Shrimps", + }, + ], + }, + { + "AutomationId": "flat_list_separator", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Separator for leading Fried Shrimps and trailing undefined has not been pressed", + "TextRangePattern.GetText": "Separator for leading Fried Shrimps and trailing undefined has not been pressed", + }, + { + "AutomationId": "Water", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Water", + "TextRangePattern.GetText": "Water", + }, + ], + }, + { + "AutomationId": "flat_list_separator", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Separator for leading Water and trailing undefined has not been pressed", + "TextRangePattern.GetText": "Separator for leading Water and trailing undefined has not been pressed", + }, + { + "AutomationId": "Coke", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Coke", + "TextRangePattern.GetText": "Coke", + }, + ], + }, + { + "AutomationId": "flat_list_separator", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Separator for leading Coke and trailing undefined has not been pressed", + "TextRangePattern.GetText": "Separator for leading Coke and trailing undefined has not been pressed", + }, + { + "AutomationId": "Beer", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Beer", + "TextRangePattern.GetText": "Beer", + }, + ], + }, + { + "AutomationId": "flat_list_separator", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Separator for leading Beer and trailing undefined has not been pressed", + "TextRangePattern.GetText": "Separator for leading Beer and trailing undefined has not been pressed", + }, + { + "AutomationId": "Cheesecake", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Cheesecake", + "TextRangePattern.GetText": "Cheesecake", + }, + ], + }, + { + "AutomationId": "flat_list_separator", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Separator for leading Cheesecake and trailing undefined has not been pressed", + "TextRangePattern.GetText": "Separator for leading Cheesecake and trailing undefined has not been pressed", + }, + { + "AutomationId": "Brownie", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Brownie", + "TextRangePattern.GetText": "Brownie", + }, + ], + }, + ], + }, + "Component Tree": { + "Type": "Microsoft.ReactNative.Composition.ScrollViewComponentView", + "_Props": { + "TestId": "flat_list", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Pizza", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": { + "TestId": "flat_list_separator", + }, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Burger", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": { + "TestId": "flat_list_separator", + }, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Risotto", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": { + "TestId": "flat_list_separator", + }, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "French Fries", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": { + "TestId": "flat_list_separator", + }, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Onion Rings", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": { + "TestId": "flat_list_separator", + }, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Fried Shrimps", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": { + "TestId": "flat_list_separator", + }, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Water", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": { + "TestId": "flat_list_separator", + }, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Coke", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": { + "TestId": "flat_list_separator", + }, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Beer", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": { + "TestId": "flat_list_separator", + }, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Cheesecake", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": { + "TestId": "flat_list_separator", + }, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Brownie", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + ], + }, + ], + }, + "Visual Tree": { + "Comment": "flat_list", + "Offset": "0, 0, 0", + "Size": "998, 574", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(0, 0, 0, 0)", + }, + "Offset": "0, 0, 0", + "Size": "998, 574", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(0, 0, 0, 0)", + }, + "Offset": "0, 0, 0", + "Size": "998, 1066", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 1066", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 1066", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 8, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Pizza", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 86, 0", + "Size": "998, 12", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(144, 238, 144, 255)", + }, + "Offset": "0, 0, 0", + "Size": "998, 12", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 86, 0", + "Size": "998, 14", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Comment": "flat_list_separator", + "Offset": "0, 0, 0", + "Size": "998, 14", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 106, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Burger", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 184, 0", + "Size": "998, 12", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(144, 238, 144, 255)", + }, + "Offset": "0, 0, 0", + "Size": "998, 12", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 184, 0", + "Size": "998, 14", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Comment": "flat_list_separator", + "Offset": "0, 0, 0", + "Size": "998, 14", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 204, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Risotto", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 282, 0", + "Size": "998, 12", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(144, 238, 144, 255)", + }, + "Offset": "0, 0, 0", + "Size": "998, 12", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 282, 0", + "Size": "998, 14", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Comment": "flat_list_separator", + "Offset": "0, 0, 0", + "Size": "998, 14", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 302, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "French Fries", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 380, 0", + "Size": "998, 12", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(144, 238, 144, 255)", + }, + "Offset": "0, 0, 0", + "Size": "998, 12", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 380, 0", + "Size": "998, 14", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Comment": "flat_list_separator", + "Offset": "0, 0, 0", + "Size": "998, 14", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 400, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Onion Rings", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 478, 0", + "Size": "998, 12", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(144, 238, 144, 255)", + }, + "Offset": "0, 0, 0", + "Size": "998, 12", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 478, 0", + "Size": "998, 14", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Comment": "flat_list_separator", + "Offset": "0, 0, 0", + "Size": "998, 14", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 498, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Fried Shrimps", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 576, 0", + "Size": "998, 12", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(144, 238, 144, 255)", + }, + "Offset": "0, 0, 0", + "Size": "998, 12", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 576, 0", + "Size": "998, 14", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Comment": "flat_list_separator", + "Offset": "0, 0, 0", + "Size": "998, 14", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 596, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Water", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 674, 0", + "Size": "998, 12", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(144, 238, 144, 255)", + }, + "Offset": "0, 0, 0", + "Size": "998, 12", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 674, 0", + "Size": "998, 14", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Comment": "flat_list_separator", + "Offset": "0, 0, 0", + "Size": "998, 14", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 694, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Coke", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 772, 0", + "Size": "998, 12", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(144, 238, 144, 255)", + }, + "Offset": "0, 0, 0", + "Size": "998, 12", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 772, 0", + "Size": "998, 14", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Comment": "flat_list_separator", + "Offset": "0, 0, 0", + "Size": "998, 14", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 792, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Beer", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 870, 0", + "Size": "998, 12", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(144, 238, 144, 255)", + }, + "Offset": "0, 0, 0", + "Size": "998, 12", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 870, 0", + "Size": "998, 14", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Comment": "flat_list_separator", + "Offset": "0, 0, 0", + "Size": "998, 14", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 890, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Cheesecake", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 968, 0", + "Size": "998, 12", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(144, 238, 144, 255)", + }, + "Offset": "0, 0, 0", + "Size": "998, 12", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 968, 0", + "Size": "998, 14", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Comment": "flat_list_separator", + "Offset": "0, 0, 0", + "Size": "998, 14", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 988, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Brownie", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "-13, 0, 0", + "Size": "12, 0", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "-12, 3, 0", + "Opacity": 0, + "Size": "12, 568", + "Visual Type": "Visual", + }, + { + "Offset": "0, 4, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "0, -16, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-5, 16, 0", + "Size": "6, 292", + "Visual Type": "Visual", + }, + ], + }, + { + "Offset": "0, -13, 0", + "Size": "0, 12", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "3, -12, 0", + "Opacity": 0, + "Size": "992, 12", + "Visual Type": "Visual", + }, + { + "Offset": "4, 0, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-16, 0, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "16, -5, 0", + "Size": "966, 6", + "Visual Type": "Visual", + }, + ], + }, + ], + }, +} +`; + +exports[`FlatList Tests A FlatList can have sticky headers 1`] = ` +{ + "Automation Tree": { + "AutomationId": "flatlist-sticky", + "ControlType": 50014, + "LocalizedControlType": "scroll bar", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Burger", + "TextRangePattern.GetText": "Burger", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "French Fries", + "TextRangePattern.GetText": "French Fries", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Fried Shrimps", + "TextRangePattern.GetText": "Fried Shrimps", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Water", + "TextRangePattern.GetText": "Water", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Coke", + "TextRangePattern.GetText": "Coke", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Beer", + "TextRangePattern.GetText": "Beer", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Cheesecake", + "TextRangePattern.GetText": "Cheesecake", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Ice Cream", + "TextRangePattern.GetText": "Ice Cream", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Sticky Pizza", + "TextRangePattern.GetText": "Sticky Pizza", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Sticky Risotto", + "TextRangePattern.GetText": "Sticky Risotto", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Sticky Onion Rings", + "TextRangePattern.GetText": "Sticky Onion Rings", + }, + ], + }, + "Component Tree": { + "Type": "Microsoft.ReactNative.Composition.ScrollViewComponentView", + "_Props": { + "TestId": "flatlist-sticky", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + ], + }, + ], + }, + "Visual Tree": { + "Comment": "flatlist-sticky", + "Offset": "0, 0, 0", + "Size": "998, 574", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(0, 0, 0, 0)", + }, + "Offset": "0, 0, 0", + "Size": "998, 574", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(0, 0, 0, 0)", + }, + "Offset": "0, 0, 0", + "Size": "998, 967", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 967", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 967", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 96, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Offset": "0, 0, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "20, 116, 0", + "Size": "958, 32", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 32", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 272, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Offset": "0, 0, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "20, 292, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 448, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Offset": "0, 0, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "20, 468, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 536, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Offset": "0, 0, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "20, 556, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 623, 0", + "Size": "998, 71", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Offset": "0, 0, 0", + "Size": "998, 71", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "20, 643, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 711, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Offset": "0, 0, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "20, 731, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 799, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Offset": "0, 0, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "20, 819, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 887, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Offset": "0, 0, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "20, 907, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "0, 0, 0", + "Size": "998, 88", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 88", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 8, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Offset": "0, 0, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "20, 28, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 176, 0", + "Size": "998, 88", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 88", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 8, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Offset": "0, 0, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "20, 28, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 352, 0", + "Size": "998, 88", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 88", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 8, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Offset": "0, 0, 0", + "Size": "998, 72", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "20, 28, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "-13, 0, 0", + "Size": "12, 0", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "-12, 3, 0", + "Opacity": 0, + "Size": "12, 568", + "Visual Type": "Visual", + }, + { + "Offset": "0, 4, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "0, -16, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-5, 16, 0", + "Size": "6, 322", + "Visual Type": "Visual", + }, + ], + }, + { + "Offset": "0, -13, 0", + "Size": "0, 12", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "3, -12, 0", + "Opacity": 0, + "Size": "992, 12", + "Visual Type": "Visual", + }, + { + "Offset": "4, 0, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-16, 0, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "16, -5, 0", + "Size": "966, 6", + "Visual Type": "Visual", + }, + ], + }, + ], + }, +} +`; + +exports[`FlatList Tests A FlatList can nest other Flatlists 1`] = ` +{ + "Automation Tree": { + "AutomationId": "flatlist-nested", + "ControlType": 50014, + "LocalizedControlType": "scroll bar", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Header", + "TextRangePattern.GetText": "Header", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "16", + "TextRangePattern.GetText": "16", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "17", + "TextRangePattern.GetText": "17", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "18", + "TextRangePattern.GetText": "18", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "19", + "TextRangePattern.GetText": "19", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "21", + "TextRangePattern.GetText": "21", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "22", + "TextRangePattern.GetText": "22", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "23", + "TextRangePattern.GetText": "23", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "24", + "TextRangePattern.GetText": "24", + }, + ], + }, + "Component Tree": { + "Type": "Microsoft.ReactNative.Composition.ScrollViewComponentView", + "_Props": { + "TestId": "flatlist-nested", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + ], + }, + "Visual Tree": { + "Comment": "flatlist-nested", + "Offset": "0, 0, 0", + "Size": "998, 347", + "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, 0)", + }, + "Offset": "0, 0, 0", + "Size": "998, 347", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(0, 0, 0, 0)", + }, + "Offset": "0, 0, 0", + "Size": "998, 777", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "1, 1, 0", + "Size": "996, 776", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "996, 776", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "996, 40", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(240, 128, 128, 255)", + }, + "Offset": "0, 0, 0", + "Size": "996, 40", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "475, 10, 0", + "Size": "46, 19", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "46, 19", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "10, 50, 0", + "Size": "478, 368", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(144, 238, 144, 255)", + }, + "Offset": "0, 0, 0", + "Size": "478, 368", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "20, 60, 0", + "Size": "458, 72", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(253, 245, 230, 255)", + }, + "Offset": "0, 0, 0", + "Size": "458, 72", + "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", + }, + ], + }, + ], + }, + { + "Offset": "241, 86, 0", + "Size": "16, 19", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "16, 19", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "20, 152, 0", + "Size": "458, 72", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(253, 245, 230, 255)", + }, + "Offset": "0, 0, 0", + "Size": "458, 72", + "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", + }, + ], + }, + ], + }, + { + "Offset": "241, 178, 0", + "Size": "16, 19", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "16, 19", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "20, 244, 0", + "Size": "458, 72", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(253, 245, 230, 255)", + }, + "Offset": "0, 0, 0", + "Size": "458, 72", + "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", + }, + ], + }, + ], + }, + { + "Offset": "241, 270, 0", + "Size": "16, 19", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "16, 19", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "20, 336, 0", + "Size": "458, 72", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(253, 245, 230, 255)", + }, + "Offset": "0, 0, 0", + "Size": "458, 72", + "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", + }, + ], + }, + ], + }, + { + "Offset": "241, 362, 0", + "Size": "16, 19", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "16, 19", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "508, 50, 0", + "Size": "478, 368", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(144, 238, 144, 255)", + }, + "Offset": "0, 0, 0", + "Size": "478, 368", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "518, 60, 0", + "Size": "458, 72", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(253, 245, 230, 255)", + }, + "Offset": "0, 0, 0", + "Size": "458, 72", + "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", + }, + ], + }, + ], + }, + { + "Offset": "739, 86, 0", + "Size": "16, 19", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "16, 19", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "518, 152, 0", + "Size": "458, 72", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(253, 245, 230, 255)", + }, + "Offset": "0, 0, 0", + "Size": "458, 72", + "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", + }, + ], + }, + ], + }, + { + "Offset": "739, 178, 0", + "Size": "16, 19", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "16, 19", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "518, 244, 0", + "Size": "458, 72", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(253, 245, 230, 255)", + }, + "Offset": "0, 0, 0", + "Size": "458, 72", + "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", + }, + ], + }, + ], + }, + { + "Offset": "739, 270, 0", + "Size": "16, 19", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "16, 19", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "518, 336, 0", + "Size": "458, 72", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(253, 245, 230, 255)", + }, + "Offset": "0, 0, 0", + "Size": "458, 72", + "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", + }, + ], + }, + ], + }, + { + "Offset": "739, 362, 0", + "Size": "16, 19", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "16, 19", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "-13, 0, 0", + "Size": "12, 0", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "-12, 3, 0", + "Opacity": 0, + "Size": "12, 341", + "Visual Type": "Visual", + }, + { + "Offset": "0, 4, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "0, -16, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-5, 16, 0", + "Size": "6, 141", + "Visual Type": "Visual", + }, + ], + }, + { + "Offset": "0, -13, 0", + "Size": "0, 12", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "3, -12, 0", + "Opacity": 0, + "Size": "992, 12", + "Visual Type": "Visual", + }, + { + "Offset": "4, 0, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-16, 0, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "16, -5, 0", + "Size": "966, 6", + "Visual Type": "Visual", + }, + ], + }, + ], + }, +} +`; + +exports[`FlatList Tests A FlatList has an onEndReached event 1`] = ` +{ + "Automation Tree": { + "AutomationId": "flat_list", + "ControlType": 50014, + "LocalizedControlType": "scroll bar", + "__Children": [ + { + "AutomationId": "Pizza", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Pizza", + "TextRangePattern.GetText": "Pizza", + }, + ], + }, + { + "AutomationId": "Burger", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Burger", + "TextRangePattern.GetText": "Burger", + }, + ], + }, + { + "AutomationId": "Risotto", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Risotto", + "TextRangePattern.GetText": "Risotto", + }, + ], + }, + { + "AutomationId": "French Fries", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "French Fries", + "TextRangePattern.GetText": "French Fries", + }, + ], + }, + { + "AutomationId": "Onion Rings", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Onion Rings", + "TextRangePattern.GetText": "Onion Rings", + }, + ], + }, + { + "AutomationId": "Fried Shrimps", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Fried Shrimps", + "TextRangePattern.GetText": "Fried Shrimps", + }, + ], + }, + { + "AutomationId": "Water", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Water", + "TextRangePattern.GetText": "Water", + }, + ], + }, + { + "AutomationId": "Coke", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Coke", + "TextRangePattern.GetText": "Coke", + }, + ], + }, + { + "AutomationId": "Beer", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Beer", + "TextRangePattern.GetText": "Beer", + }, + ], + }, + { + "AutomationId": "Cheesecake", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Cheesecake", + "TextRangePattern.GetText": "Cheesecake", + }, + ], + }, + { + "AutomationId": "Brownie", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Brownie", + "TextRangePattern.GetText": "Brownie", + }, + ], + }, + ], + }, + "Component Tree": { + "Type": "Microsoft.ReactNative.Composition.ScrollViewComponentView", + "_Props": { + "TestId": "flat_list", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Pizza", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Burger", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Risotto", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "French Fries", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Onion Rings", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Fried Shrimps", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Water", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Coke", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Beer", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Cheesecake", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Brownie", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + ], + }, + ], + }, + "Visual Tree": { + "Comment": "flat_list", + "Offset": "0, 0, 0", + "Size": "998, 534", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(0, 0, 0, 0)", + }, + "Offset": "0, 0, 0", + "Size": "998, 534", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(0, 0, 0, 0)", + }, + "Offset": "0, 0, 0", + "Size": "998, 946", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 946", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 946", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 8, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Pizza", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 94, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Burger", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 180, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Risotto", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 266, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "French Fries", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 352, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Onion Rings", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 438, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Fried Shrimps", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 524, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Water", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 610, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Coke", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 696, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Beer", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 782, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Cheesecake", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 868, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Brownie", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "-13, 0, 0", + "Size": "12, 0", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "-12, 3, 0", + "Opacity": 0, + "Size": "12, 528", + "Visual Type": "Visual", + }, + { + "Offset": "0, 4, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "0, -16, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-5, 16, 0", + "Size": "6, 283", + "Visual Type": "Visual", + }, + ], + }, + { + "Offset": "0, -13, 0", + "Size": "0, 12", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "3, -12, 0", + "Opacity": 0, + "Size": "992, 12", + "Visual Type": "Visual", + }, + { + "Offset": "4, 0, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-16, 0, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "16, -5, 0", + "Size": "966, 6", + "Visual Type": "Visual", + }, + ], + }, + ], + }, +} +`; + +exports[`FlatList Tests A FlatList has an onStartReached event 1`] = ` +{ + "Automation Tree": { + "AutomationId": "flat_list", + "ControlType": 50014, + "LocalizedControlType": "scroll bar", + "__Children": [ + { + "AutomationId": "Pizza", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Pizza", + "TextRangePattern.GetText": "Pizza", + }, + ], + }, + { + "AutomationId": "Burger", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Burger", + "TextRangePattern.GetText": "Burger", + }, + ], + }, + { + "AutomationId": "Risotto", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Risotto", + "TextRangePattern.GetText": "Risotto", + }, + ], + }, + { + "AutomationId": "French Fries", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "French Fries", + "TextRangePattern.GetText": "French Fries", + }, + ], + }, + { + "AutomationId": "Onion Rings", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Onion Rings", + "TextRangePattern.GetText": "Onion Rings", + }, + ], + }, + { + "AutomationId": "Fried Shrimps", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Fried Shrimps", + "TextRangePattern.GetText": "Fried Shrimps", + }, + ], + }, + { + "AutomationId": "Water", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Water", + "TextRangePattern.GetText": "Water", + }, + ], + }, + { + "AutomationId": "Coke", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Coke", + "TextRangePattern.GetText": "Coke", + }, + ], + }, + { + "AutomationId": "Beer", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Beer", + "TextRangePattern.GetText": "Beer", + }, + ], + }, + { + "AutomationId": "Cheesecake", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Cheesecake", + "TextRangePattern.GetText": "Cheesecake", + }, + ], + }, + { + "AutomationId": "Brownie", + "ControlType": 50026, + "IsKeyboardFocusable": true, + "LocalizedControlType": "group", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Brownie", + "TextRangePattern.GetText": "Brownie", + }, + ], + }, + ], + }, + "Component Tree": { + "Type": "Microsoft.ReactNative.Composition.ScrollViewComponentView", + "_Props": { + "TestId": "flat_list", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Pizza", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Burger", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Risotto", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "French Fries", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Onion Rings", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Fried Shrimps", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Water", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Coke", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Beer", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Cheesecake", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": { + "TestId": "Brownie", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + ], + }, + ], + }, + "Visual Tree": { + "Comment": "flat_list", + "Offset": "0, 0, 0", + "Size": "998, 534", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(0, 0, 0, 0)", + }, + "Offset": "0, 0, 0", + "Size": "998, 534", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(0, 0, 0, 0)", + }, + "Offset": "0, 0, 0", + "Size": "998, 946", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 946", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "998, 946", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 8, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Pizza", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 94, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Burger", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 180, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Risotto", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 266, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "French Fries", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 352, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Onion Rings", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 438, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Fried Shrimps", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 524, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Water", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 610, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Coke", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 696, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Beer", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 782, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Cheesecake", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "0, 868, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(255, 192, 203, 255)", + }, + "Comment": "Brownie", + "Offset": "0, 0, 0", + "Size": "998, 70", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "20, 19, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "958, 33", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "-13, 0, 0", + "Size": "12, 0", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "-12, 3, 0", + "Opacity": 0, + "Size": "12, 528", + "Visual Type": "Visual", + }, + { + "Offset": "0, 4, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "0, -16, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-5, 235, 0", + "Size": "6, 283", + "Visual Type": "Visual", + }, + ], + }, + { + "Offset": "0, -13, 0", + "Size": "0, 12", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "3, -12, 0", + "Opacity": 0, + "Size": "992, 12", + "Visual Type": "Visual", + }, + { + "Offset": "4, 0, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-16, 0, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "16, -5, 0", + "Size": "966, 6", + "Visual Type": "Visual", + }, + ], + }, + ], + }, +} +`; 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 d0057572694..ce44c67c6fb 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 @@ -13,6 +13,7 @@ exports[`Home UIA Tree Dump APIs Tab 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "APIs", + "TextRangePattern.GetText": "APIs", }, ], }, @@ -113,12 +114,14 @@ exports[`Home UIA Tree Dump Accessibility 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Accessibility", + "TextRangePattern.GetText": "Accessibility", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Examples of using Accessibility APIs.", + "TextRangePattern.GetText": "Examples of using Accessibility APIs.", }, ], }, @@ -192,12 +195,14 @@ exports[`Home UIA Tree Dump Accessibility Windows 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Accessibility Windows", + "TextRangePattern.GetText": "Accessibility Windows", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Usage of accessibility properties.", + "TextRangePattern.GetText": "Usage of accessibility properties.", }, ], }, @@ -271,12 +276,14 @@ exports[`Home UIA Tree Dump AccessibilityInfo 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "AccessibilityInfo", + "TextRangePattern.GetText": "AccessibilityInfo", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Examples of using AccessibilityInfo APIs.", + "TextRangePattern.GetText": "Examples of using AccessibilityInfo APIs.", }, ], }, @@ -350,12 +357,14 @@ exports[`Home UIA Tree Dump ActivityIndicator 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "ActivityIndicator", + "TextRangePattern.GetText": "ActivityIndicator", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Animated loading indicators.", + "TextRangePattern.GetText": "Animated loading indicators.", }, ], }, @@ -429,12 +438,14 @@ exports[`Home UIA Tree Dump Alerts 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Alerts", + "TextRangePattern.GetText": "Alerts", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Alerts display a concise and informative message and prompt the user to make a decision.", + "TextRangePattern.GetText": "Alerts display a concise and informative message and prompt the user to make a decision.", }, ], }, @@ -508,12 +519,14 @@ exports[`Home UIA Tree Dump Animated - Gratuitous App 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Animated - Gratuitous App", + "TextRangePattern.GetText": "Animated - Gratuitous App", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Bunch of Animations - tap a circle to open a view with more animations, or longPress and drag to reorder circles.", + "TextRangePattern.GetText": "Bunch of Animations - tap a circle to open a view with more animations, or longPress and drag to reorder circles.", }, ], }, @@ -587,12 +600,14 @@ exports[`Home UIA Tree Dump Animated 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Animated", + "TextRangePattern.GetText": "Animated", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Library designed to make animations fluid, powerful, and painless to build and maintain.", + "TextRangePattern.GetText": "Library designed to make animations fluid, powerful, and painless to build and maintain.", }, ], }, @@ -666,12 +681,14 @@ exports[`Home UIA Tree Dump AppState 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "AppState", + "TextRangePattern.GetText": "AppState", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "app background status", + "TextRangePattern.GetText": "app background status", }, ], }, @@ -745,12 +762,14 @@ exports[`Home UIA Tree Dump Appearance 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Appearance", + "TextRangePattern.GetText": "Appearance", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Light and dark user interface examples.", + "TextRangePattern.GetText": "Light and dark user interface examples.", }, ], }, @@ -824,12 +843,14 @@ exports[`Home UIA Tree Dump Border 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Border", + "TextRangePattern.GetText": "Border", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Demonstrates some of the border styles available to Views.", + "TextRangePattern.GetText": "Demonstrates some of the border styles available to Views.", }, ], }, @@ -903,12 +924,14 @@ exports[`Home UIA Tree Dump Button 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Button", + "TextRangePattern.GetText": "Button", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Simple React Native button component.", + "TextRangePattern.GetText": "Simple React Native button component.", }, ], }, @@ -981,6 +1004,7 @@ exports[`Home UIA Tree Dump Components Tab 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Components", + "TextRangePattern.GetText": "Components", }, ], }, @@ -1121,12 +1145,14 @@ exports[`Home UIA Tree Dump Composition Bugs Example 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Composition Bugs Example", + "TextRangePattern.GetText": "Composition Bugs Example", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "See bugs in UI.Composition driven native animations", + "TextRangePattern.GetText": "See bugs in UI.Composition driven native animations", }, ], }, @@ -1200,12 +1226,14 @@ exports[`Home UIA Tree Dump Crash 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Crash", + "TextRangePattern.GetText": "Crash", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Crash examples.", + "TextRangePattern.GetText": "Crash examples.", }, ], }, @@ -1279,12 +1307,14 @@ exports[`Home UIA Tree Dump Cxx TurboModule 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Cxx TurboModule", + "TextRangePattern.GetText": "Cxx TurboModule", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Usage of Cxx TurboModule", + "TextRangePattern.GetText": "Usage of Cxx TurboModule", }, ], }, @@ -1358,12 +1388,14 @@ exports[`Home UIA Tree Dump DevSettings 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "DevSettings", + "TextRangePattern.GetText": "DevSettings", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Customize the development settings", + "TextRangePattern.GetText": "Customize the development settings", }, ], }, @@ -1437,12 +1469,14 @@ exports[`Home UIA Tree Dump Dimensions 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Dimensions", + "TextRangePattern.GetText": "Dimensions", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Dimensions of the viewport", + "TextRangePattern.GetText": "Dimensions of the viewport", }, ], }, @@ -1516,12 +1550,14 @@ exports[`Home UIA Tree Dump Display: contents 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Display: contents", + "TextRangePattern.GetText": "Display: contents", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Demonstrates various ways display: contents may be used in the tree", + "TextRangePattern.GetText": "Demonstrates various ways display: contents may be used in the tree", }, ], }, @@ -1595,12 +1631,14 @@ exports[`Home UIA Tree Dump Display:none Style 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Display:none Style", + "TextRangePattern.GetText": "Display:none Style", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Style prop which will collapse the element in XAML tree.", + "TextRangePattern.GetText": "Style prop which will collapse the element in XAML tree.", }, ], }, @@ -1674,12 +1712,14 @@ exports[`Home UIA Tree Dump Drawing Island Example 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Drawing Island Example", + "TextRangePattern.GetText": "Drawing Island Example", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Sample Fabric Native Component that contains a custom ContentIsland", + "TextRangePattern.GetText": "Sample Fabric Native Component that contains a custom ContentIsland", }, ], }, @@ -1753,12 +1793,14 @@ exports[`Home UIA Tree Dump Fabric Native Component 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Fabric Native Component", + "TextRangePattern.GetText": "Fabric Native Component", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Sample Fabric Native Component that sizes based on max desired size of native XAML contained within", + "TextRangePattern.GetText": "Sample Fabric Native Component that sizes based on max desired size of native XAML contained within", }, ], }, @@ -1832,12 +1874,14 @@ exports[`Home UIA Tree Dump Fabric Native Component Yoga 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Fabric Native Component Yoga", + "TextRangePattern.GetText": "Fabric Native Component Yoga", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Sample Fabric Native Component that places native XAML inside a container sized by yoga", + "TextRangePattern.GetText": "Sample Fabric Native Component that places native XAML inside a container sized by yoga", }, ], }, @@ -1911,12 +1955,14 @@ exports[`Home UIA Tree Dump Fast Path Texts 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Fast Path Texts", + "TextRangePattern.GetText": "Fast Path Texts", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Examples of performant fast path texts, turn on IsTextPerformanceVisualizationEnabled to visualize examples", + "TextRangePattern.GetText": "Examples of performant fast path texts, turn on IsTextPerformanceVisualizationEnabled to visualize examples", }, ], }, @@ -1990,12 +2036,14 @@ exports[`Home UIA Tree Dump Filter 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Filter", + "TextRangePattern.GetText": "Filter", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "A set of graphical effects that can be applied to a view.", + "TextRangePattern.GetText": "A set of graphical effects that can be applied to a view.", }, ], }, @@ -2069,12 +2117,14 @@ exports[`Home UIA Tree Dump FlatList 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "FlatList", + "TextRangePattern.GetText": "FlatList", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Performant, scrollable list of data.", + "TextRangePattern.GetText": "Performant, scrollable list of data.", }, ], }, @@ -2148,12 +2198,14 @@ exports[`Home UIA Tree Dump Flyout 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Flyout", + "TextRangePattern.GetText": "Flyout", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Displays content on top of existing content, within the bounds of the application window.", + "TextRangePattern.GetText": "Displays content on top of existing content, within the bounds of the application window.", }, ], }, @@ -2227,12 +2279,14 @@ exports[`Home UIA Tree Dump Glyph UWP 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Glyph UWP", + "TextRangePattern.GetText": "Glyph UWP", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Usage of Glyph control.", + "TextRangePattern.GetText": "Usage of Glyph control.", }, ], }, @@ -2306,12 +2360,14 @@ exports[`Home UIA Tree Dump Image 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Image", + "TextRangePattern.GetText": "Image", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Base component for displaying different types of images.", + "TextRangePattern.GetText": "Base component for displaying different types of images.", }, ], }, @@ -2385,12 +2441,14 @@ exports[`Home UIA Tree Dump Keyboard 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Keyboard", + "TextRangePattern.GetText": "Keyboard", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Demonstrates usage of the "Keyboard" static API", + "TextRangePattern.GetText": "Demonstrates usage of the "Keyboard" static API", }, ], }, @@ -2464,12 +2522,14 @@ exports[`Home UIA Tree Dump Keyboard 2`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Keyboard", + "TextRangePattern.GetText": "Keyboard", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Demonstrates usage of the "Keyboard" static API", + "TextRangePattern.GetText": "Demonstrates usage of the "Keyboard" static API", }, ], }, @@ -2543,12 +2603,14 @@ exports[`Home UIA Tree Dump Keyboard Focus Example 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Keyboard Focus Example", + "TextRangePattern.GetText": "Keyboard Focus Example", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Demo of keyboard focus.", + "TextRangePattern.GetText": "Demo of keyboard focus.", }, ], }, @@ -2622,12 +2684,14 @@ exports[`Home UIA Tree Dump Keyboard extension Example 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Keyboard extension Example", + "TextRangePattern.GetText": "Keyboard extension Example", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Demo of keyboard properties.", + "TextRangePattern.GetText": "Demo of keyboard properties.", }, ], }, @@ -2701,12 +2765,14 @@ exports[`Home UIA Tree Dump Layout - Flexbox 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Layout - Flexbox", + "TextRangePattern.GetText": "Layout - Flexbox", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Examples of using the flexbox API to layout views.", + "TextRangePattern.GetText": "Examples of using the flexbox API to layout views.", }, ], }, @@ -2780,12 +2846,14 @@ exports[`Home UIA Tree Dump Layout Events 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Layout Events", + "TextRangePattern.GetText": "Layout Events", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Examples that show how Layout events can be used to measure view size and position.", + "TextRangePattern.GetText": "Examples that show how Layout events can be used to measure view size and position.", }, ], }, @@ -2859,12 +2927,14 @@ exports[`Home UIA Tree Dump Legacy Native Module 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Legacy Native Module", + "TextRangePattern.GetText": "Legacy Native Module", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Usage of legacy Native Module", + "TextRangePattern.GetText": "Usage of legacy Native Module", }, ], }, @@ -2938,12 +3008,14 @@ exports[`Home UIA Tree Dump LegacyControlStyleTest 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "LegacyControlStyleTest", + "TextRangePattern.GetText": "LegacyControlStyleTest", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Legacy e2e test for Control Styles", + "TextRangePattern.GetText": "Legacy e2e test for Control Styles", }, ], }, @@ -3017,12 +3089,14 @@ exports[`Home UIA Tree Dump LegacyImageTest 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "LegacyImageTest", + "TextRangePattern.GetText": "LegacyImageTest", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Legacy e2e test for Image", + "TextRangePattern.GetText": "Legacy e2e test for Image", }, ], }, @@ -3096,12 +3170,14 @@ exports[`Home UIA Tree Dump LegacyLoginTest 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "LegacyLoginTest", + "TextRangePattern.GetText": "LegacyLoginTest", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Legacy e2e test for TextInput with password", + "TextRangePattern.GetText": "Legacy e2e test for TextInput with password", }, ], }, @@ -3175,12 +3251,14 @@ exports[`Home UIA Tree Dump LegacySelectableTextTest 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "LegacySelectableTextTest", + "TextRangePattern.GetText": "LegacySelectableTextTest", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Legacy e2e test for selectable Text hit testing", + "TextRangePattern.GetText": "Legacy e2e test for selectable Text hit testing", }, ], }, @@ -3254,12 +3332,14 @@ exports[`Home UIA Tree Dump LegacyTextHitTestTest 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "LegacyTextHitTestTest", + "TextRangePattern.GetText": "LegacyTextHitTestTest", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Legacy e2e test for Text hit testing", + "TextRangePattern.GetText": "Legacy e2e test for Text hit testing", }, ], }, @@ -3333,12 +3413,14 @@ exports[`Home UIA Tree Dump LegacyTextInputTest 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "LegacyTextInputTest", + "TextRangePattern.GetText": "LegacyTextInputTest", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Legacy e2e test for TextInput", + "TextRangePattern.GetText": "Legacy e2e test for TextInput", }, ], }, @@ -3412,12 +3494,14 @@ exports[`Home UIA Tree Dump Linking 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Linking", + "TextRangePattern.GetText": "Linking", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Shows how to use Linking to open URLs.", + "TextRangePattern.GetText": "Shows how to use Linking to open URLs.", }, ], }, @@ -3491,12 +3575,14 @@ exports[`Home UIA Tree Dump Modal 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Modal", + "TextRangePattern.GetText": "Modal", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Component for presenting modal views.", + "TextRangePattern.GetText": "Component for presenting modal views.", }, ], }, @@ -3570,12 +3656,14 @@ exports[`Home UIA Tree Dump Mouse Click Events 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Mouse Click Events", + "TextRangePattern.GetText": "Mouse Click Events", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Tests that mouse click events work on intended components", + "TextRangePattern.GetText": "Tests that mouse click events work on intended components", }, ], }, @@ -3649,12 +3737,14 @@ exports[`Home UIA Tree Dump Mouse Events 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Mouse Events", + "TextRangePattern.GetText": "Mouse Events", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Tests that mouse events can be observed", + "TextRangePattern.GetText": "Tests that mouse events can be observed", }, ], }, @@ -3728,12 +3818,14 @@ exports[`Home UIA Tree Dump Moving Light Example 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Moving Light Example", + "TextRangePattern.GetText": "Moving Light Example", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Sample Custom Fabric Native Component", + "TextRangePattern.GetText": "Sample Custom Fabric Native Component", }, ], }, @@ -3807,12 +3899,14 @@ exports[`Home UIA Tree Dump Native Animated Example 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Native Animated Example", + "TextRangePattern.GetText": "Native Animated Example", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Test out Native Animations", + "TextRangePattern.GetText": "Test out Native Animations", }, ], }, @@ -3886,12 +3980,14 @@ exports[`Home UIA Tree Dump New App Screen 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "New App Screen", + "TextRangePattern.GetText": "New App Screen", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Displays the content of the new app screen", + "TextRangePattern.GetText": "Displays the content of the new app screen", }, ], }, @@ -3965,12 +4061,14 @@ exports[`Home UIA Tree Dump PanResponder Sample 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "PanResponder Sample", + "TextRangePattern.GetText": "PanResponder Sample", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Shows the Use of PanResponder to provide basic gesture handling", + "TextRangePattern.GetText": "Shows the Use of PanResponder to provide basic gesture handling", }, ], }, @@ -4044,12 +4142,14 @@ exports[`Home UIA Tree Dump Performance API Examples 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Performance API Examples", + "TextRangePattern.GetText": "Performance API Examples", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Shows the performance API provided in React Native", + "TextRangePattern.GetText": "Shows the performance API provided in React Native", }, ], }, @@ -4123,12 +4223,14 @@ exports[`Home UIA Tree Dump Performance Comparison Examples 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Performance Comparison Examples", + "TextRangePattern.GetText": "Performance Comparison Examples", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Compare performance with bad and good examples. Use React DevTools to highlight re-renders is recommended.", + "TextRangePattern.GetText": "Compare performance with bad and good examples. Use React DevTools to highlight re-renders is recommended.", }, ], }, @@ -4202,12 +4304,14 @@ exports[`Home UIA Tree Dump PixelRatio 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "PixelRatio", + "TextRangePattern.GetText": "PixelRatio", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Gives access to device's pixel density and font scale", + "TextRangePattern.GetText": "Gives access to device's pixel density and font scale", }, ], }, @@ -4281,12 +4385,14 @@ exports[`Home UIA Tree Dump PlatformColor 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "PlatformColor", + "TextRangePattern.GetText": "PlatformColor", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Examples that show how PlatformColors may be used in an app.", + "TextRangePattern.GetText": "Examples that show how PlatformColors may be used in an app.", }, ], }, @@ -4360,12 +4466,14 @@ exports[`Home UIA Tree Dump Pointer Events 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pointer Events", + "TextRangePattern.GetText": "Pointer Events", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Demonstrates the use of the pointerEvents prop of a View to control how touches should be handled.", + "TextRangePattern.GetText": "Demonstrates the use of the pointerEvents prop of a View to control how touches should be handled.", }, ], }, @@ -4439,12 +4547,14 @@ exports[`Home UIA Tree Dump Popup 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Popup", + "TextRangePattern.GetText": "Popup", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Displays content on top of existing content, within the bounds of the application window.", + "TextRangePattern.GetText": "Displays content on top of existing content, within the bounds of the application window.", }, ], }, @@ -4518,12 +4628,14 @@ exports[`Home UIA Tree Dump Pressable 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressable", + "TextRangePattern.GetText": "Pressable", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Component for making views pressable.", + "TextRangePattern.GetText": "Component for making views pressable.", }, ], }, @@ -4597,12 +4709,14 @@ exports[`Home UIA Tree Dump RTLExample 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "RTLExample", + "TextRangePattern.GetText": "RTLExample", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Examples to show how to apply components to RTL layout.", + "TextRangePattern.GetText": "Examples to show how to apply components to RTL layout.", }, ], }, @@ -4676,12 +4790,14 @@ exports[`Home UIA Tree Dump ScrollView 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "ScrollView", + "TextRangePattern.GetText": "ScrollView", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Component that enables scrolling through child components", + "TextRangePattern.GetText": "Component that enables scrolling through child components", }, ], }, @@ -4755,12 +4871,14 @@ exports[`Home UIA Tree Dump ScrollViewAnimated 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "ScrollViewAnimated", + "TextRangePattern.GetText": "ScrollViewAnimated", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Component that is animated when ScrollView is offset.", + "TextRangePattern.GetText": "Component that is animated when ScrollView is offset.", }, ], }, @@ -4834,12 +4952,14 @@ exports[`Home UIA Tree Dump ScrollViewSimpleExample 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "ScrollViewSimpleExample", + "TextRangePattern.GetText": "ScrollViewSimpleExample", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Component that enables scrolling through child components.", + "TextRangePattern.GetText": "Component that enables scrolling through child components.", }, ], }, @@ -4908,6 +5028,7 @@ exports[`Home UIA Tree Dump Search Bar 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "Search...", + "TextRangePattern.GetText": "Search...", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -5022,12 +5143,14 @@ exports[`Home UIA Tree Dump SectionList 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "SectionList", + "TextRangePattern.GetText": "SectionList", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Performant, scrollable list of data.", + "TextRangePattern.GetText": "Performant, scrollable list of data.", }, ], }, @@ -5101,12 +5224,14 @@ exports[`Home UIA Tree Dump Share 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Share", + "TextRangePattern.GetText": "Share", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Share data with other Apps.", + "TextRangePattern.GetText": "Share data with other Apps.", }, ], }, @@ -5180,12 +5305,14 @@ exports[`Home UIA Tree Dump SwipeableCard 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "SwipeableCard", + "TextRangePattern.GetText": "SwipeableCard", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Example of a swipeable card with scrollable content to test PanResponder and JSResponderHandler interaction.", + "TextRangePattern.GetText": "Example of a swipeable card with scrollable content to test PanResponder and JSResponderHandler interaction.", }, ], }, @@ -5259,12 +5386,14 @@ exports[`Home UIA Tree Dump Switch 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Switch", + "TextRangePattern.GetText": "Switch", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Native boolean input", + "TextRangePattern.GetText": "Native boolean input", }, ], }, @@ -5338,12 +5467,14 @@ exports[`Home UIA Tree Dump Text 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Text", + "TextRangePattern.GetText": "Text", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Base component for rendering styled text.", + "TextRangePattern.GetText": "Base component for rendering styled text.", }, ], }, @@ -5417,12 +5548,14 @@ exports[`Home UIA Tree Dump TextInput 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "TextInput", + "TextRangePattern.GetText": "TextInput", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Single and multi-line text inputs.", + "TextRangePattern.GetText": "Single and multi-line text inputs.", }, ], }, @@ -5496,12 +5629,14 @@ exports[`Home UIA Tree Dump TextInputs with key prop 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "TextInputs with key prop", + "TextRangePattern.GetText": "TextInputs with key prop", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Periodically render large number of TextInputs with key prop without a Runtime Error", + "TextRangePattern.GetText": "Periodically render large number of TextInputs with key prop without a Runtime Error", }, ], }, @@ -5575,12 +5710,14 @@ exports[`Home UIA Tree Dump Timers 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Timers", + "TextRangePattern.GetText": "Timers", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "A demonstration of Timers in React Native.", + "TextRangePattern.GetText": "A demonstration of Timers in React Native.", }, ], }, @@ -5654,12 +5791,14 @@ exports[`Home UIA Tree Dump Touchable* and onPress 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Touchable* and onPress", + "TextRangePattern.GetText": "Touchable* and onPress", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Touchable and onPress examples.", + "TextRangePattern.GetText": "Touchable and onPress examples.", }, ], }, @@ -5733,12 +5872,14 @@ exports[`Home UIA Tree Dump TransferProperties 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "TransferProperties", + "TextRangePattern.GetText": "TransferProperties", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Some tests that change the backing XAML element to see if transfer properties is working.", + "TextRangePattern.GetText": "Some tests that change the backing XAML element to see if transfer properties is working.", }, ], }, @@ -5812,12 +5953,14 @@ exports[`Home UIA Tree Dump Transforms 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Transforms", + "TextRangePattern.GetText": "Transforms", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "View transforms", + "TextRangePattern.GetText": "View transforms", }, ], }, @@ -5891,12 +6034,14 @@ exports[`Home UIA Tree Dump TransparentHitTestExample 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "TransparentHitTestExample", + "TextRangePattern.GetText": "TransparentHitTestExample", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Transparent view receiving touch events", + "TextRangePattern.GetText": "Transparent view receiving touch events", }, ], }, @@ -5970,12 +6115,14 @@ exports[`Home UIA Tree Dump TurboModule 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "TurboModule", + "TextRangePattern.GetText": "TurboModule", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Usage of TurboModule", + "TextRangePattern.GetText": "Usage of TurboModule", }, ], }, @@ -6049,12 +6196,14 @@ exports[`Home UIA Tree Dump View 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "View", + "TextRangePattern.GetText": "View", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Basic building block of all UI, examples that demonstrate some of the many styles available.", + "TextRangePattern.GetText": "Basic building block of all UI, examples that demonstrate some of the many styles available.", }, ], }, @@ -6128,12 +6277,14 @@ exports[`Home UIA Tree Dump WebSocket 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "WebSocket", + "TextRangePattern.GetText": "WebSocket", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "WebSocket API", + "TextRangePattern.GetText": "WebSocket API", }, ], }, @@ -6207,12 +6358,14 @@ exports[`Home UIA Tree Dump XAML 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "XAML", + "TextRangePattern.GetText": "XAML", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Usage of react-native-xaml controls", + "TextRangePattern.GetText": "Usage of react-native-xaml controls", }, ], }, @@ -6286,12 +6439,14 @@ exports[`Home UIA Tree Dump XMLHttpRequest 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "XMLHttpRequest", + "TextRangePattern.GetText": "XMLHttpRequest", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Example that demonstrates upload and download requests using XMLHttpRequest.", + "TextRangePattern.GetText": "Example that demonstrates upload and download requests using XMLHttpRequest.", }, ], }, diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/ImageComponentTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/ImageComponentTest.test.ts.snap index a073f452ec8..b57ec8bc64f 100644 --- a/packages/e2e-test-app-fabric/test/__snapshots__/ImageComponentTest.test.ts.snap +++ b/packages/e2e-test-app-fabric/test/__snapshots__/ImageComponentTest.test.ts.snap @@ -552,6 +552,7 @@ exports[`Image Tests An Image can be nested inside of a component 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "React", + "TextRangePattern.GetText": "React", }, ], }, @@ -1137,18 +1138,21 @@ exports[`Image Tests An Image can have a tint color 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "It also works using the \`tintColor\` style prop", + "TextRangePattern.GetText": "It also works using the \`tintColor\` style prop", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "The \`tintColor\` prop has precedence over the \`tintColor\` style prop", + "TextRangePattern.GetText": "The \`tintColor\` prop has precedence over the \`tintColor\` style prop", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "It also works with downloaded images:", + "TextRangePattern.GetText": "It also works with downloaded images:", }, ], }, @@ -2174,60 +2178,70 @@ exports[`Image Tests An Image customized how it is rendered within the frame usi "ControlType": 50020, "LocalizedControlType": "text", "Name": "Contain", + "TextRangePattern.GetText": "Contain", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Cover", + "TextRangePattern.GetText": "Cover", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Fill", + "TextRangePattern.GetText": "Fill", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Scale Down", + "TextRangePattern.GetText": "Scale Down", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "None", + "TextRangePattern.GetText": "None", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Contain", + "TextRangePattern.GetText": "Contain", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Cover", + "TextRangePattern.GetText": "Cover", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Fill", + "TextRangePattern.GetText": "Fill", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Scale Down", + "TextRangePattern.GetText": "Scale Down", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "None", + "TextRangePattern.GetText": "None", }, ], }, @@ -3162,72 +3176,84 @@ exports[`Image Tests Images have multiple resize modes 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Contain", + "TextRangePattern.GetText": "Contain", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Cover", + "TextRangePattern.GetText": "Cover", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Stretch", + "TextRangePattern.GetText": "Stretch", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Repeat", + "TextRangePattern.GetText": "Repeat", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Center", + "TextRangePattern.GetText": "Center", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "None", + "TextRangePattern.GetText": "None", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Contain", + "TextRangePattern.GetText": "Contain", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Cover", + "TextRangePattern.GetText": "Cover", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Stretch", + "TextRangePattern.GetText": "Stretch", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Repeat", + "TextRangePattern.GetText": "Repeat", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Center", + "TextRangePattern.GetText": "Center", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "None", + "TextRangePattern.GetText": "None", }, ], }, diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/LegacySelectableTextTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/LegacySelectableTextTest.test.ts.snap index bdc18fec82e..9c68ae84d69 100644 --- a/packages/e2e-test-app-fabric/test/__snapshots__/LegacySelectableTextTest.test.ts.snap +++ b/packages/e2e-test-app-fabric/test/__snapshots__/LegacySelectableTextTest.test.ts.snap @@ -7,6 +7,7 @@ exports[`LegacySelectableTextTest DoubleClickWhenNotSelectable 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressed: 2 times.", + "TextRangePattern.GetText": "Pressed: 2 times.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -30,6 +31,7 @@ exports[`LegacySelectableTextTest DoubleClickWhenSelectable 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressed: 2 times.", + "TextRangePattern.GetText": "Pressed: 2 times.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -53,6 +55,7 @@ exports[`LegacySelectableTextTest PressableWhenNotSelectable 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressed: 1 times.", + "TextRangePattern.GetText": "Pressed: 1 times.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -76,6 +79,7 @@ exports[`LegacySelectableTextTest PressableWhenSelectable 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressed: 1 times.", + "TextRangePattern.GetText": "Pressed: 1 times.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/LegacyTextHitTestTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/LegacyTextHitTestTest.test.ts.snap index b0b7f3a23f4..a31407e3fde 100644 --- a/packages/e2e-test-app-fabric/test/__snapshots__/LegacyTextHitTestTest.test.ts.snap +++ b/packages/e2e-test-app-fabric/test/__snapshots__/LegacyTextHitTestTest.test.ts.snap @@ -7,6 +7,7 @@ exports[`LegacyTextHitTestTest BidirectionalTextPressable 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressed: 2 times.", + "TextRangePattern.GetText": "Pressed: 2 times.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -30,6 +31,7 @@ exports[`LegacyTextHitTestTest BidirectionalTextPressableEdgeCaseNotPressable 1` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressed: 1 times.", + "TextRangePattern.GetText": "Pressed: 1 times.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -53,6 +55,7 @@ exports[`LegacyTextHitTestTest BidirectionalTextSeparateRunsEdgeCasePressable 1` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressed: 1 times.", + "TextRangePattern.GetText": "Pressed: 1 times.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -76,6 +79,7 @@ exports[`LegacyTextHitTestTest BidirectionalTextSeparateRunsPressable 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressed: 2 times.", + "TextRangePattern.GetText": "Pressed: 2 times.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -99,6 +103,7 @@ exports[`LegacyTextHitTestTest InsertedVirtualTextPressable 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressed: 1 times.", + "TextRangePattern.GetText": "Pressed: 1 times.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -122,6 +127,7 @@ exports[`LegacyTextHitTestTest LTRTextInRTLFlowPressable 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressed: 1 times.", + "TextRangePattern.GetText": "Pressed: 1 times.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -145,6 +151,7 @@ exports[`LegacyTextHitTestTest MultilineRTLTextEdgeCaseNotPressable 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressed: 1 times.", + "TextRangePattern.GetText": "Pressed: 1 times.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -168,6 +175,7 @@ exports[`LegacyTextHitTestTest MultilineRTLTextPressable 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressed: 2 times.", + "TextRangePattern.GetText": "Pressed: 2 times.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -191,6 +199,7 @@ exports[`LegacyTextHitTestTest MultilineTextPressable 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressed: 1 times.", + "TextRangePattern.GetText": "Pressed: 1 times.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -214,6 +223,7 @@ exports[`LegacyTextHitTestTest RTLTextInRTLFlowPressable 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressed: 1 times.", + "TextRangePattern.GetText": "Pressed: 1 times.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -237,6 +247,7 @@ exports[`LegacyTextHitTestTest RTLTextPressable 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressed: 1 times.", + "TextRangePattern.GetText": "Pressed: 1 times.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -260,6 +271,7 @@ exports[`LegacyTextHitTestTest TextPressableWithVirtualText 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressed: 1 times.", + "TextRangePattern.GetText": "Pressed: 1 times.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -283,6 +295,7 @@ exports[`LegacyTextHitTestTest ToggleVirtualTextPressable 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressed: 1 times.", + "TextRangePattern.GetText": "Pressed: 1 times.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -306,6 +319,7 @@ exports[`LegacyTextHitTestTest VirtualTextPressable 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressed: 1 times.", + "TextRangePattern.GetText": "Pressed: 1 times.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -329,6 +343,7 @@ exports[`LegacyTextHitTestTest WrappedLTRInRTLFlowEdgeCaseNotPressable 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressed: 1 times.", + "TextRangePattern.GetText": "Pressed: 1 times.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/LegacyTextInputTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/LegacyTextInputTest.test.ts.snap index 1aab4be6ea6..ebcf3a1ce6a 100644 --- a/packages/e2e-test-app-fabric/test/__snapshots__/LegacyTextInputTest.test.ts.snap +++ b/packages/e2e-test-app-fabric/test/__snapshots__/LegacyTextInputTest.test.ts.snap @@ -7,6 +7,8 @@ exports[`LegacyTextInputTest Click on TextInput to focus 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "onFocus +", + "TextRangePattern.GetText": "onFocus ", }, "Component Tree": { @@ -32,6 +34,9 @@ exports[`LegacyTextInputTest Click on multiline TextInput to move focus away fro "LocalizedControlType": "text", "Name": "onBlur onFocus +", + "TextRangePattern.GetText": "onBlur +onFocus ", }, "Component Tree": { @@ -98,6 +103,50 @@ onKeyPress key: a onFocus onBlur onFocus +", + "TextRangePattern.GetText": "onChange text: a +onSelectionChange range: 1,1 +onKeyPress key: a +onChange text: +onSelectionChange range: 0,0 +onFocus +onBlur +onSubmitEditing text: abc +onChange text: abc +onSelectionChange range: 3,3 +onKeyPress key: c +onChange text: ab +onSelectionChange range: 2,2 +onKeyPress key: b +onChange text: a +onSelectionChange range: 1,1 +onKeyPress key: a +onChange text: +onSelectionChange range: 0,0 +onChange text: def +onSelectionChange range: 3,3 +onKeyPress key: f +onChange text: de +onSelectionChange range: 2,2 +onKeyPress key: e +onChange text: d +onSelectionChange range: 1,1 +onKeyPress key: d +onChange text: +onSelectionChange range: 0,0 +onChange text: abc +onSelectionChange range: 3,3 +onKeyPress key: c +onChange text: ab +onSelectionChange range: 2,2 +onKeyPress key: b +onChange text: a +onChange text: a +onSelectionChange range: 1,1 +onKeyPress key: a +onFocus +onBlur +onFocus ", }, "Component Tree": { @@ -134,6 +183,20 @@ onKeyPress key: a onFocus onBlur onFocus +", + "TextRangePattern.GetText": "onChange text: abc +onSelectionChange range: 3,3 +onKeyPress key: c +onChange text: ab +onSelectionChange range: 2,2 +onKeyPress key: b +onChange text: a +onChange text: a +onSelectionChange range: 1,1 +onKeyPress key: a +onFocus +onBlur +onFocus ", }, "Component Tree": { @@ -193,6 +256,43 @@ onKeyPress key: a onFocus onBlur onFocus +", + "TextRangePattern.GetText": "onSubmitEditing text: abc +onChange text: abc +onSelectionChange range: 3,3 +onKeyPress key: c +onChange text: ab +onSelectionChange range: 2,2 +onKeyPress key: b +onChange text: a +onSelectionChange range: 1,1 +onKeyPress key: a +onChange text: +onSelectionChange range: 0,0 +onChange text: def +onSelectionChange range: 3,3 +onKeyPress key: f +onChange text: de +onSelectionChange range: 2,2 +onKeyPress key: e +onChange text: d +onSelectionChange range: 1,1 +onKeyPress key: d +onChange text: +onSelectionChange range: 0,0 +onChange text: abc +onSelectionChange range: 3,3 +onKeyPress key: c +onChange text: ab +onSelectionChange range: 2,2 +onKeyPress key: b +onChange text: a +onChange text: a +onSelectionChange range: 1,1 +onKeyPress key: a +onFocus +onBlur +onFocus ", }, "Component Tree": { 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 453352c323f..70213d9d735 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 @@ -20,6 +20,7 @@ exports[`Pressable Tests Pressables can be defined as a set using accessibilityP "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressable 1 of 3", + "TextRangePattern.GetText": "Pressable 1 of 3", }, ], }, @@ -37,6 +38,7 @@ exports[`Pressable Tests Pressables can be defined as a set using accessibilityP "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressable 2 of 3", + "TextRangePattern.GetText": "Pressable 2 of 3", }, ], }, @@ -54,6 +56,7 @@ exports[`Pressable Tests Pressables can be defined as a set using accessibilityP "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressable 3 of 3", + "TextRangePattern.GetText": "Pressable 3 of 3", }, ], }, @@ -199,6 +202,7 @@ exports[`Pressable Tests Pressables can be disabled, disabled = {false} 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Enabled Pressable", + "TextRangePattern.GetText": "Enabled Pressable", }, ], }, @@ -251,6 +255,7 @@ exports[`Pressable Tests Pressables can be disabled, disabled = {true} 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Disabled Pressable", + "TextRangePattern.GetText": "Disabled Pressable", }, ], }, @@ -305,6 +310,7 @@ exports[`Pressable Tests Pressables can change style when pressed 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Press Me", + "TextRangePattern.GetText": "Press Me", }, ], }, @@ -354,6 +360,7 @@ exports[`Pressable Tests Pressables can change text on press/rest, state rest 1` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Press Me", + "TextRangePattern.GetText": "Press Me", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -377,6 +384,7 @@ exports[`Pressable Tests Pressables can change text on press/rest, state rest 2` "ControlType": 50020, "LocalizedControlType": "text", "Name": "onPress", + "TextRangePattern.GetText": "onPress", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -406,6 +414,7 @@ exports[`Pressable Tests Pressables can have advanced borders 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Press Outside This View", + "TextRangePattern.GetText": "Press Outside This View", }, ], }, @@ -461,6 +470,7 @@ exports[`Pressable Tests Pressables can have delayed event handlers 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Press Me", + "TextRangePattern.GetText": "Press Me", }, ], }, @@ -511,12 +521,14 @@ exports[`Pressable Tests Pressables can have delayed event handlers 2`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "pressOut", + "TextRangePattern.GetText": "pressOut", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "pressIn", + "TextRangePattern.GetText": "pressIn", }, ], }, @@ -630,6 +642,7 @@ exports[`Pressable Tests Pressables can have event handlers 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Press Me", + "TextRangePattern.GetText": "Press Me", }, ], }, @@ -681,24 +694,28 @@ exports[`Pressable Tests Pressables can have event handlers 2`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "pressOut", + "TextRangePattern.GetText": "pressOut", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "press", + "TextRangePattern.GetText": "press", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "pressIn", + "TextRangePattern.GetText": "pressIn", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "hover in", + "TextRangePattern.GetText": "hover in", }, ], }, @@ -842,6 +859,7 @@ exports[`Pressable Tests Pressables can have hit slop functionality 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Press Outside This View", + "TextRangePattern.GetText": "Press Outside This View", }, ], }, @@ -1246,6 +1264,7 @@ exports[`Pressable Tests Pressables can have their accessibility and keyboard fo "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressable with accessible=true and focusable=true", + "TextRangePattern.GetText": "Pressable with accessible=true and focusable=true", }, ], }, @@ -1254,6 +1273,7 @@ exports[`Pressable Tests Pressables can have their accessibility and keyboard fo "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressable with accessible=false", + "TextRangePattern.GetText": "Pressable with accessible=false", }, { "AutomationId": "", @@ -1265,6 +1285,7 @@ exports[`Pressable Tests Pressables can have their accessibility and keyboard fo "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressable with focusable=false", + "TextRangePattern.GetText": "Pressable with focusable=false", }, ], }, @@ -1273,6 +1294,7 @@ exports[`Pressable Tests Pressables can have their accessibility and keyboard fo "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressable with accessible=false and focusable=false", + "TextRangePattern.GetText": "Pressable with accessible=false and focusable=false", }, ], }, @@ -1452,6 +1474,7 @@ exports[`Pressable Tests Pressables can have tooltips 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Pressable with ToolTip "Pressable"", + "TextRangePattern.GetText": "Pressable with ToolTip "Pressable"", }, ], }, @@ -1502,6 +1525,7 @@ exports[`Pressable Tests Pressables can hide their backface 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "View #1, front is visible, back is hidden.", + "TextRangePattern.GetText": "View #1, front is visible, back is hidden.", }, { "AutomationId": "", @@ -1514,6 +1538,7 @@ exports[`Pressable Tests Pressables can hide their backface 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Front", + "TextRangePattern.GetText": "Front", }, ], }, @@ -1528,6 +1553,7 @@ exports[`Pressable Tests Pressables can hide their backface 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Back (You should not see this)", + "TextRangePattern.GetText": "Back (You should not see this)", }, ], }, @@ -1536,6 +1562,7 @@ exports[`Pressable Tests Pressables can hide their backface 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "View #2, front is hidden, back is visible.", + "TextRangePattern.GetText": "View #2, front is hidden, back is visible.", }, { "AutomationId": "", @@ -1548,6 +1575,7 @@ exports[`Pressable Tests Pressables can hide their backface 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Front (You should not see this)", + "TextRangePattern.GetText": "Front (You should not see this)", }, ], }, @@ -1562,6 +1590,7 @@ exports[`Pressable Tests Pressables can hide their backface 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Back", + "TextRangePattern.GetText": "Back", }, ], }, @@ -1785,6 +1814,7 @@ exports[`Pressable Tests Text can have pressable behavior 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Text has built-in onPress handling", + "TextRangePattern.GetText": "Text has built-in onPress handling", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -1808,6 +1838,7 @@ exports[`Pressable Tests Text can have pressable behavior 2`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "2x text onPress", + "TextRangePattern.GetText": "2x text onPress", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/ScrollViewComponentTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/ScrollViewComponentTest.test.ts.snap index a7ba4d2a645..f3bb0cfe118 100644 --- a/packages/e2e-test-app-fabric/test/__snapshots__/ScrollViewComponentTest.test.ts.snap +++ b/packages/e2e-test-app-fabric/test/__snapshots__/ScrollViewComponentTest.test.ts.snap @@ -13,6 +13,7 @@ exports[`ScrollView Tests ScrollView has scrollTo method, scroll to bottom butto "ControlType": 50020, "LocalizedControlType": "text", "Name": "Scroll to bottom", + "TextRangePattern.GetText": "Scroll to bottom", }, ], }, @@ -68,6 +69,7 @@ exports[`ScrollView Tests ScrollView has scrollTo method, scroll to end button 1 "ControlType": 50020, "LocalizedControlType": "text", "Name": "Scroll to end", + "TextRangePattern.GetText": "Scroll to end", }, ], }, @@ -123,6 +125,7 @@ exports[`ScrollView Tests ScrollView has scrollTo method, scroll to start button "ControlType": 50020, "LocalizedControlType": "text", "Name": "Scroll to start", + "TextRangePattern.GetText": "Scroll to start", }, ], }, @@ -178,6 +181,7 @@ exports[`ScrollView Tests ScrollView has scrollTo method, scroll to top button 1 "ControlType": 50020, "LocalizedControlType": "text", "Name": "Scroll to top", + "TextRangePattern.GetText": "Scroll to top", }, ], }, @@ -233,6 +237,7 @@ exports[`ScrollView Tests ScrollViews has flash scroll indicators 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Flash scroll indicators", + "TextRangePattern.GetText": "Flash scroll indicators", }, ], }, diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/TextComponentTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/TextComponentTest.test.ts.snap index 44cdac22324..d68dbb2125e 100644 --- a/packages/e2e-test-app-fabric/test/__snapshots__/TextComponentTest.test.ts.snap +++ b/packages/e2e-test-app-fabric/test/__snapshots__/TextComponentTest.test.ts.snap @@ -7,6 +7,7 @@ exports[`Text Tests Padding can be added to Text 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "This text is indented by 10px padding on all sides.", + "TextRangePattern.GetText": "This text is indented by 10px padding on all sides.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -30,6 +31,7 @@ exports[`Text Tests Text can be restricted to one line 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Maximum of one line no matter now much I write here. If I keep writing it'll just truncate after one line", + "TextRangePattern.GetText": "Maximum of one line no matter now much I write here. If I keep writing it'll just truncate after one line", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -53,6 +55,7 @@ exports[`Text Tests Text can be selectable 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "This text is selectable if you click-and-hold, and will offer the native Android selection menus.", + "TextRangePattern.GetText": "This text is selectable if you click-and-hold, and will offer the native Android selection menus.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -76,6 +79,7 @@ exports[`Text Tests Text can have a color 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Red color", + "TextRangePattern.GetText": "Red color", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -99,6 +103,7 @@ exports[`Text Tests Text can have a customized selection color 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "This text will have a orange highlight on selection.", + "TextRangePattern.GetText": "This text will have a orange highlight on selection.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -122,6 +127,7 @@ exports[`Text Tests Text can have a size 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Size 23", + "TextRangePattern.GetText": "Size 23", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -151,18 +157,21 @@ exports[`Text Tests Text can have advanced borders 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "This text has customized borders.", + "TextRangePattern.GetText": "This text has customized borders.", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "This text has customized borders.", + "TextRangePattern.GetText": "This text has customized borders.", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "This text has customized borders.", + "TextRangePattern.GetText": "This text has customized borders.", }, ], }, @@ -463,6 +472,7 @@ exports[`Text Tests Text can have an outer color 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "(Normal text,(R)red(G)green(B)blue(C)cyan(M)magenta(Y)yellow(K)black(and bold(and tiny bold italic blue(and tiny normal blue))))", + "TextRangePattern.GetText": "(Normal text,(R)red(G)green(B)blue(C)cyan(M)magenta(Y)yellow(K)black(and bold(and tiny bold italic blue(and tiny normal blue))))", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -492,6 +502,7 @@ exports[`Text Tests Text can have borders 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Sample bordered text with default styling.", + "TextRangePattern.GetText": "Sample bordered text with default styling.", }, { "AutomationId": "", @@ -499,6 +510,9 @@ exports[`Text Tests Text can have borders 1`] = ` "LocalizedControlType": "text", "Name": "Some more bordered text + a tad of CSS. 1st nested - border specifcied but ignored. +2nd Inside text!", + "TextRangePattern.GetText": "Some more bordered text + a tad of CSS. +1st nested - border specifcied but ignored. 2nd Inside text!", }, { @@ -506,6 +520,7 @@ exports[`Text Tests Text can have borders 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "This text is outlined and laid out within the normal text run, so will wrap etc as normal text.", + "TextRangePattern.GetText": "This text is outlined and laid out within the normal text run, so will wrap etc as normal text.", }, ], }, @@ -668,6 +683,7 @@ exports[`Text Tests Text can have decoration lines: Solid Line Through 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Solid line-through", + "TextRangePattern.GetText": "Solid line-through", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -691,6 +707,7 @@ exports[`Text Tests Text can have decoration lines: Underline 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Solid underline", + "TextRangePattern.GetText": "Solid underline", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -714,6 +731,7 @@ exports[`Text Tests Text can have shadows 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Demo text shadow", + "TextRangePattern.GetText": "Demo text shadow", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -737,6 +755,7 @@ exports[`Text Tests Text can wrap 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "The text should wrap if it goes on multiple lines. See, this is going to the next line.", + "TextRangePattern.GetText": "The text should wrap if it goes on multiple lines. See, this is going to the next line.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", 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 535d9828c25..00f95d98e12 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,8 @@ exports[`TextInput Tests Multi-line TextInputs can enable text selection (Impera "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "TextRangePattern.GetText": "multiline text selection +can also be changed imperatively", "ValuePattern.Value": "multiline text selection can also be changed imperatively", }, @@ -84,6 +86,8 @@ exports[`TextInput Tests Multi-line TextInputs can enable text selection 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "TextRangePattern.GetText": "multiline text selection +can also be changed", "ValuePattern.Value": "multiline text selection can also be changed", }, @@ -161,6 +165,7 @@ exports[`TextInput Tests Single-line TextInputs can enable text selection (Imper "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "TextRangePattern.GetText": "text selection can be changed imperatively", "ValuePattern.Value": "text selection can be changed imperatively", }, "Component Tree": { @@ -237,6 +242,7 @@ exports[`TextInput Tests Single-line TextInputs can enable text selection 1`] = "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "TextRangePattern.GetText": "text selection can be changed", "ValuePattern.Value": "text selection can be changed", }, "Component Tree": { @@ -315,6 +321,7 @@ exports[`TextInput Tests Text have cursorColor 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "cursorColor={"green"}", + "TextRangePattern.GetText": "Hello World", "ValuePattern.Value": "Hello World", }, "Component Tree": { @@ -543,6 +550,7 @@ exports[`TextInput Tests TextInputs can autocomplete, address country 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "postal-address-country", + "TextRangePattern.GetText": "postal-address-country", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -620,6 +628,7 @@ exports[`TextInput Tests TextInputs can autocomplete, country 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "country", + "TextRangePattern.GetText": "country", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -697,6 +706,7 @@ exports[`TextInput Tests TextInputs can autocomplete, one-time-code 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "one-time-code", + "TextRangePattern.GetText": "one-time-code", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -774,6 +784,7 @@ exports[`TextInput Tests TextInputs can autocomplete, sms-otp 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "sms-otp", + "TextRangePattern.GetText": "sms-otp", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -849,6 +860,7 @@ exports[`TextInput Tests TextInputs can autogrow 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "TextRangePattern.GetText": "small small small small small small", "ValuePattern.Value": "small small small small small small", }, "Component Tree": { @@ -934,6 +946,7 @@ exports[`TextInput Tests TextInputs can be defined as a set using accessibilityP "Name": "TextInput 1 in Set of 3", "PositionInSet": 1, "SizeofSet": 3, + "TextRangePattern.GetText": "TextInput 1 in Set of 3", }, { "AutomationId": "", @@ -945,6 +958,7 @@ exports[`TextInput Tests TextInputs can be defined as a set using accessibilityP "Name": "TextInput 2 in Set of 3", "PositionInSet": 2, "SizeofSet": 3, + "TextRangePattern.GetText": "TextInput 2 in Set of 3", }, { "AutomationId": "", @@ -956,6 +970,7 @@ exports[`TextInput Tests TextInputs can be defined as a set using accessibilityP "Name": "TextInput 3 in Set of 3", "PositionInSet": 3, "SizeofSet": 3, + "TextRangePattern.GetText": "TextInput 3 in Set of 3", }, ], }, @@ -1191,6 +1206,7 @@ exports[`TextInput Tests TextInputs can be editable 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "editable text input using editable prop", + "TextRangePattern.GetText": "editable text input using editable prop", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -1266,6 +1282,7 @@ exports[`TextInput Tests TextInputs can be multiline, bottomright alignment 1`] "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "TextRangePattern.GetText": "multiline with children, aligned bottom-right", "ValuePattern.Value": "multiline with children, aligned bottom-right", }, "Component Tree": { @@ -1344,6 +1361,7 @@ exports[`TextInput Tests TextInputs can be multiline, center alignment 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "multiline, aligned center", + "TextRangePattern.GetText": "multiline, aligned center", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -1421,6 +1439,7 @@ exports[`TextInput Tests TextInputs can be multiline, topleft alignment 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "multiline, aligned top-left", + "TextRangePattern.GetText": "multiline, aligned top-left", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -1496,6 +1515,7 @@ exports[`TextInput Tests TextInputs can be set to not editable 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "TextRangePattern.GetText": "Can't touch this! (>'-')> ^(' - ')^ <('-'<) (>'-')> ^(' - ')^", "ValuePattern.Value": "Can't touch this! (>'-')> ^(' - ')^ <('-'<) (>'-')> ^(' - ')^", }, "Component Tree": { @@ -1574,6 +1594,7 @@ exports[`TextInput Tests TextInputs can be set to not editable 2 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "uneditable text input using editable prop", + "TextRangePattern.GetText": "uneditable text input using editable prop", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -1951,6 +1972,7 @@ exports[`TextInput Tests TextInputs can enable spellcheck 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "Type text to test spell check functionality.", + "TextRangePattern.GetText": "Type text to test spell check functionality.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -2026,6 +2048,7 @@ exports[`TextInput Tests TextInputs can have a background color 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "TextRangePattern.GetText": "He", "ValuePattern.Value": "He", }, "Component Tree": { @@ -2102,6 +2125,7 @@ exports[`TextInput Tests TextInputs can have a color 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "TextRangePattern.GetText": "He", "ValuePattern.Value": "He", }, "Component Tree": { @@ -2178,6 +2202,7 @@ exports[`TextInput Tests TextInputs can have a font family 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "TextRangePattern.GetText": "He", "ValuePattern.Value": "He", }, "Component Tree": { @@ -2254,6 +2279,7 @@ exports[`TextInput Tests TextInputs can have a font size 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "TextRangePattern.GetText": "He", "ValuePattern.Value": "He", }, "Component Tree": { @@ -2330,6 +2356,7 @@ exports[`TextInput Tests TextInputs can have a font style 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "TextRangePattern.GetText": "He", "ValuePattern.Value": "He", }, "Component Tree": { @@ -2406,6 +2433,7 @@ exports[`TextInput Tests TextInputs can have a font weight 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "TextRangePattern.GetText": "He", "ValuePattern.Value": "He", }, "Component Tree": { @@ -2482,6 +2510,7 @@ exports[`TextInput Tests TextInputs can have attributed text 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "TextRangePattern.GetText": "Hello ", "ValuePattern.Value": "Hello ", }, "Component Tree": { @@ -2560,6 +2589,7 @@ exports[`TextInput Tests TextInputs can have caretHidden 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "caretHidden={true}", + "TextRangePattern.GetText": "Hello World", "ValuePattern.Value": "Hello World", }, "Component Tree": { @@ -2638,6 +2668,7 @@ exports[`TextInput Tests TextInputs can have custom return key label, Compile 1` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "returnKeyLabel: Compile", + "TextRangePattern.GetText": "returnKeyLabel: Compile", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -2715,6 +2746,7 @@ exports[`TextInput Tests TextInputs can have custom return key label, React Nati "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "returnKeyLabel: React Native", + "TextRangePattern.GetText": "returnKeyLabel: React Native", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -2792,6 +2824,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, done 1`] = "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "returnKeyType: done", + "TextRangePattern.GetText": "returnKeyType: done", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -2869,6 +2902,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, go 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "returnKeyType: go", + "TextRangePattern.GetText": "returnKeyType: go", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -2946,6 +2980,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, next 1`] = "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "returnKeyType: next", + "TextRangePattern.GetText": "returnKeyType: next", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -3023,6 +3058,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, none 1`] = "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "returnKeyType: none", + "TextRangePattern.GetText": "returnKeyType: none", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -3100,6 +3136,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, previous 1` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "returnKeyType: previous", + "TextRangePattern.GetText": "returnKeyType: previous", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -3177,6 +3214,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, search 1`] "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "returnKeyType: search", + "TextRangePattern.GetText": "returnKeyType: search", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -3254,6 +3292,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, send 1`] = "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "returnKeyType: send", + "TextRangePattern.GetText": "returnKeyType: send", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -3331,6 +3370,7 @@ exports[`TextInput Tests TextInputs can have customer letter spacing, spacing=-1 "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "letterSpacing = -1", + "TextRangePattern.GetText": "letterSpacing = -1", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -3408,6 +3448,7 @@ exports[`TextInput Tests TextInputs can have customer letter spacing, spacing=0 "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "letterSpacing = 0", + "TextRangePattern.GetText": "letterSpacing = 0", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -3485,6 +3526,7 @@ exports[`TextInput Tests TextInputs can have customer letter spacing, spacing=2 "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "letterSpacing = 2", + "TextRangePattern.GetText": "letterSpacing = 2", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -3562,6 +3604,7 @@ exports[`TextInput Tests TextInputs can have customer letter spacing, spacing=9 "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "letterSpacing = 9", + "TextRangePattern.GetText": "letterSpacing = 9", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -3733,6 +3776,7 @@ exports[`TextInput Tests TextInputs can have customized letter spacing 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "TextRangePattern.GetText": "He", "ValuePattern.Value": "He", }, "Component Tree": { @@ -3809,6 +3853,8 @@ exports[`TextInput Tests TextInputs can have customized line height 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "TextRangePattern.GetText": "Hel +", "ValuePattern.Value": "Hel ", }, @@ -3888,6 +3934,7 @@ exports[`TextInput Tests TextInputs can have inline images 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "This has drawableLeft set", + "TextRangePattern.GetText": "This has drawableLeft set", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -3965,6 +4012,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", + "TextRangePattern.GetText": "This does not have drawable props set", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -4042,6 +4090,7 @@ exports[`TextInput Tests TextInputs can have inline images, drawableLeft and dra "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "This has drawableLeft and drawablePadding set", + "TextRangePattern.GetText": "This has drawableLeft and drawablePadding set", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -4119,6 +4168,7 @@ exports[`TextInput Tests TextInputs can have shadows 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "shadowColor: purple", + "TextRangePattern.GetText": "shadowColor: purple", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -4194,6 +4244,7 @@ exports[`TextInput Tests TextInputs can have text decoration lines 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "TextRangePattern.GetText": "He", "ValuePattern.Value": "He", }, "Component Tree": { @@ -4270,6 +4321,7 @@ exports[`TextInput Tests TextInputs can have text shadows 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "TextRangePattern.GetText": "He", "ValuePattern.Value": "He", }, "Component Tree": { @@ -4348,6 +4400,7 @@ exports[`TextInput Tests TextInputs can propagate events 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "Click inside the box to observe events being fired.", + "TextRangePattern.GetText": "Click inside the box to observe events being fired.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -4425,6 +4478,7 @@ exports[`TextInput Tests TextInputs can register press events 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "Click inside the box to observe events being fired.", + "TextRangePattern.GetText": "Click inside the box to observe events being fired.", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -4727,6 +4781,7 @@ exports[`TextInput Tests TextInputs can set their readOnly prop to false 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "editable text input using readOnly prop", + "TextRangePattern.GetText": "editable text input using readOnly prop", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -4804,6 +4859,7 @@ exports[`TextInput Tests TextInputs can set their readOnly prop to true 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "uneditable text input using readOnly prop", + "TextRangePattern.GetText": "uneditable text input using readOnly prop", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -4954,6 +5010,7 @@ exports[`TextInput Tests TextInputs have a custom background color 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "TextRangePattern.GetText": "Same BackgroundColor as View ", "ValuePattern.Value": "Same BackgroundColor as View ", }, "Component Tree": { @@ -5030,6 +5087,7 @@ exports[`TextInput Tests TextInputs have a custom highlight color 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "TextRangePattern.GetText": "Selection Color is red", "ValuePattern.Value": "Selection Color is red", }, "Component Tree": { @@ -5108,6 +5166,7 @@ exports[`TextInput Tests TextInputs have a custom placeholder text color 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "Red placeholder text color", + "TextRangePattern.GetText": "Red placeholder text color", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -5183,6 +5242,7 @@ exports[`TextInput Tests TextInputs have a custom text color 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "TextRangePattern.GetText": "Green Text", "ValuePattern.Value": "Green Text", }, "Component Tree": { @@ -5261,6 +5321,7 @@ exports[`TextInput Tests TextInputs have a custom underline color 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "Blue underline color", + "TextRangePattern.GetText": "Blue underline color", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -5338,6 +5399,7 @@ exports[`TextInput Tests TextInputs have a default placeholder text color 1`] = "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "Default placeholder text color", + "TextRangePattern.GetText": "Default placeholder text color", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -5413,6 +5475,7 @@ exports[`TextInput Tests TextInputs have a default text color 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "TextRangePattern.GetText": "Default color text", "ValuePattern.Value": "Default color text", }, "Component Tree": { @@ -5491,6 +5554,7 @@ exports[`TextInput Tests TextInputs have a default underline color 1`] = ` "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "Default underline color", + "TextRangePattern.GetText": "Default underline color", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -5566,6 +5630,7 @@ exports[`TextInput Tests TextInputs support secure entry 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "TextRangePattern.GetText": "iloveturtles", "ValuePattern.Value": "iloveturtles", }, "Component Tree": { @@ -5644,6 +5709,7 @@ exports[`TextInput Tests TextInputs support secure entry, with placeholder text "IsKeyboardFocusable": true, "LocalizedControlType": "edit", "Name": "color is supported too", + "TextRangePattern.GetText": "color is supported too", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -5724,6 +5790,7 @@ exports[`TextInput Tests TextInputs which have a searchbox role should also supp "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "TextRangePattern.GetText": "Search", "ValuePattern.Value": "Search", }, ], @@ -5824,6 +5891,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", + "TextRangePattern.GetText": "If you set height, beware of padding set from themes", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.WindowsTextInputComponentView", @@ -5899,6 +5967,7 @@ exports[`TextInput Tests Uncontrolled TextInput 1`] = ` "ControlType": 50004, "IsKeyboardFocusable": true, "LocalizedControlType": "edit", + "TextRangePattern.GetText": "Hello World!", "ValuePattern.Value": "Hello World!", }, "Component Tree": { 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 3773900dcbf..2ba5443b459 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 @@ -7,6 +7,7 @@ exports[`Touchable Tests Text components can be tappable 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Text has built-in onPress handling", + "TextRangePattern.GetText": "Text has built-in onPress handling", }, "Component Tree": { "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", @@ -36,6 +37,7 @@ exports[`Touchable Tests TouchableWithoutFeedback components should not give vis "ControlType": 50020, "LocalizedControlType": "text", "Name": "Tap Here For No Feedback!", + "TextRangePattern.GetText": "Tap Here For No Feedback!", }, ], }, @@ -94,6 +96,7 @@ exports[`Touchable Tests Touchables can be defined in a set using accessibilityP "ControlType": 50020, "LocalizedControlType": "text", "Name": "Touchable Highlight (Control 1 in Set of 3)", + "TextRangePattern.GetText": "Touchable Highlight (Control 1 in Set of 3)", }, ], }, @@ -111,6 +114,7 @@ exports[`Touchable Tests Touchables can be defined in a set using accessibilityP "ControlType": 50020, "LocalizedControlType": "text", "Name": "Touchable Opacity (Control 2 in Set of 3)", + "TextRangePattern.GetText": "Touchable Opacity (Control 2 in Set of 3)", }, ], }, @@ -123,6 +127,7 @@ exports[`Touchable Tests Touchables can be defined in a set using accessibilityP "Name": "TouchableWithoutFeedback (Control 3 in Set of 3)", "PositionInSet": 3, "SizeofSet": 3, + "TextRangePattern.GetText": "TouchableWithoutFeedback (Control 3 in Set of 3)", }, ], }, @@ -246,6 +251,7 @@ exports[`Touchable Tests Touchables can contain a Text component 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Tap Here For Custom Highlight!", + "TextRangePattern.GetText": "Tap Here For Custom Highlight!", }, ], }, @@ -347,6 +353,7 @@ exports[`Touchable Tests Touchables can delay events 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Press Me", + "TextRangePattern.GetText": "Press Me", }, ], }, @@ -398,6 +405,7 @@ exports[`Touchable Tests Touchables can enable a hit slop region 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Press Outside This View", + "TextRangePattern.GetText": "Press Outside This View", }, ], }, @@ -455,6 +463,7 @@ exports[`Touchable Tests Touchables can register feedback events 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Press Me", + "TextRangePattern.GetText": "Press Me", }, ], }, 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 5582dcde123..3d3eb0fd2c7 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 @@ -41,6 +41,7 @@ exports[`View Tests Views can have a nativeid 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "A View with a nativeID "native-id-view"", + "TextRangePattern.GetText": "A View with a nativeID "native-id-view"", }, ], }, @@ -93,30 +94,35 @@ exports[`View Tests Views can have a z-index 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "ZIndex -1", + "TextRangePattern.GetText": "ZIndex -1", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Tap to flip sorting order", + "TextRangePattern.GetText": "Tap to flip sorting order", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "ZIndex 0", + "TextRangePattern.GetText": "ZIndex 0", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "ZIndex 1", + "TextRangePattern.GetText": "ZIndex 1", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "ZIndex 2", + "TextRangePattern.GetText": "ZIndex 2", }, ], }, @@ -328,6 +334,7 @@ exports[`View Tests Views can have aria-labels 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Blue background", + "TextRangePattern.GetText": "Blue background", }, ], }, @@ -384,36 +391,42 @@ exports[`View Tests Views can have backface visibility 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "View #1, front is visible, back is hidden.", + "TextRangePattern.GetText": "View #1, front is visible, back is hidden.", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Front", + "TextRangePattern.GetText": "Front", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Back (You should not see this)", + "TextRangePattern.GetText": "Back (You should not see this)", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "View #2, front is hidden, back is visible.", + "TextRangePattern.GetText": "View #2, front is hidden, back is visible.", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Front (You should not see this)", + "TextRangePattern.GetText": "Front (You should not see this)", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Back", + "TextRangePattern.GetText": "Back", }, ], }, @@ -630,6 +643,7 @@ exports[`View Tests Views can have background color 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Blue background", + "TextRangePattern.GetText": "Blue background", }, ], }, @@ -686,12 +700,14 @@ exports[`View Tests Views can have border styles 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Dashed border style", + "TextRangePattern.GetText": "Dashed border style", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Dotted border style", + "TextRangePattern.GetText": "Dotted border style", }, ], }, @@ -875,6 +891,7 @@ exports[`View Tests Views can have borders 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "5px blue border", + "TextRangePattern.GetText": "5px blue border", }, ], }, @@ -975,12 +992,14 @@ exports[`View Tests Views can have customized accessibility 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "A View with accessibility values.", + "TextRangePattern.GetText": "A View with accessibility values.", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Current Number of Accessibility Taps: 0", + "TextRangePattern.GetText": "Current Number of Accessibility Taps: 0", }, { "AutomationId": "", @@ -992,6 +1011,7 @@ exports[`View Tests Views can have customized accessibility 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "This sub-view should not have an accessibility value. It's control type does not support the value pattern.", + "TextRangePattern.GetText": "This sub-view should not have an accessibility value. It's control type does not support the value pattern.", }, ], }, @@ -1114,42 +1134,49 @@ exports[`View Tests Views can have customized opacity 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Opacity 0", + "TextRangePattern.GetText": "Opacity 0", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Opacity 0.1", + "TextRangePattern.GetText": "Opacity 0.1", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Opacity 0.3", + "TextRangePattern.GetText": "Opacity 0.3", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Opacity 0.5", + "TextRangePattern.GetText": "Opacity 0.5", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Opacity 0.7", + "TextRangePattern.GetText": "Opacity 0.7", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Opacity 0.9", + "TextRangePattern.GetText": "Opacity 0.9", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Opacity 1", + "TextRangePattern.GetText": "Opacity 1", }, ], }, @@ -1436,24 +1463,28 @@ exports[`View Tests Views can have customized pasdding and margins 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "5px padding", + "TextRangePattern.GetText": "5px padding", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "5px margin", + "TextRangePattern.GetText": "5px margin", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "5px margin and padding,", + "TextRangePattern.GetText": "5px margin and padding,", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "widthAutonomous=true", + "TextRangePattern.GetText": "widthAutonomous=true", }, ], }, @@ -1780,6 +1811,7 @@ exports[`View Tests Views can have display: none 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Press to toggle \`display: none\`", + "TextRangePattern.GetText": "Press to toggle \`display: none\`", }, ], }, @@ -2118,42 +2150,49 @@ exports[`View Tests Views can have insets 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "inset 5", + "TextRangePattern.GetText": "inset 5", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "insetBlock 5", + "TextRangePattern.GetText": "insetBlock 5", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "insetBlockEnd 5", + "TextRangePattern.GetText": "insetBlockEnd 5", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "insetBlockStart 5", + "TextRangePattern.GetText": "insetBlockStart 5", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "insetInline 5", + "TextRangePattern.GetText": "insetInline 5", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "insetInlineEnd 5", + "TextRangePattern.GetText": "insetInlineEnd 5", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "insetInlineStart 5", + "TextRangePattern.GetText": "insetInlineStart 5", }, ], }, @@ -2847,18 +2886,21 @@ exports[`View Tests Views can have logical border colors 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "borderBlockColor orange", + "TextRangePattern.GetText": "borderBlockColor orange", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "borderBlockStartColor purple", + "TextRangePattern.GetText": "borderBlockStartColor purple", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "borderBlockEndColor green", + "TextRangePattern.GetText": "borderBlockEndColor green", }, ], }, @@ -3175,18 +3217,21 @@ exports[`View Tests Views can have offscreen alpha compositing 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Blobs", + "TextRangePattern.GetText": "Blobs", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Same blobs, but their shared container have 0.5 opacity", + "TextRangePattern.GetText": "Same blobs, but their shared container have 0.5 opacity", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Tap to deactivate needsOffscreenAlphaCompositing", + "TextRangePattern.GetText": "Tap to deactivate needsOffscreenAlphaCompositing", }, ], }, @@ -3373,18 +3418,21 @@ exports[`View Tests Views can have overflow 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "undefined", + "TextRangePattern.GetText": "undefined", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "hidden", + "TextRangePattern.GetText": "hidden", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "visible", + "TextRangePattern.GetText": "visible", }, ], }, @@ -5183,18 +5231,21 @@ exports[`View Tests Views can have tooltips 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "This Parent View has tooltip "Parent View"", + "TextRangePattern.GetText": "This Parent View has tooltip "Parent View"", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "This view has tooltip "Child View 1"", + "TextRangePattern.GetText": "This view has tooltip "Child View 1"", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "This view has tooltip "Child View 2"", + "TextRangePattern.GetText": "This view has tooltip "Child View 2"", }, ], }, 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 9cb662862c0..033558a7715 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 @@ -363,6 +363,7 @@ void DumpUIAPatternInfo(IUIAutomationElement *pTarget, const winrt::Windows::Dat BOOL isSelected; BOOL multipleSelection; BOOL selectionRequired; + BSTR text = nullptr; // Dump IValueProvider Information IValueProvider *valuePattern; @@ -451,6 +452,21 @@ void DumpUIAPatternInfo(IUIAutomationElement *pTarget, const winrt::Windows::Dat selectionPattern->Release(); } + // Dump ITextRangeProvider Information + winrt::com_ptr textPattern; + hr = pTarget->GetCurrentPattern(UIA_TextPatternId, reinterpret_cast(textPattern.put())); + if (SUCCEEDED(hr) && textPattern) { + winrt::com_ptr textRangePattern; + hr = textPattern->get_DocumentRange(textRangePattern.put()); + if (SUCCEEDED(hr) && textRangePattern) { + textRangePattern->GetText(20, &text); + if (SUCCEEDED(hr)) { + InsertStringValueIfNotEmpty(result, L"TextRangePattern.GetText", text); + } + } + } + + ::SysFreeString(text); ::SysFreeString(value); } diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp index ca254789899..59ac05d1674 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp @@ -1,6 +1,8 @@ #include "pch.h" #include "CompositionDynamicAutomationProvider.h" #include +#include +#include #include #include #include @@ -25,6 +27,13 @@ CompositionDynamicAutomationProvider::CompositionDynamicAutomationProvider( if (props->accessibilityState.has_value() && props->accessibilityState->selected.has_value()) { AddSelectionItemsToContainer(this); } + + if (strongView.try_as() || + strongView.try_as()) { + m_textProvider = winrt::make( + strongView.as(), this) + .try_as(); + } } HRESULT __stdcall CompositionDynamicAutomationProvider::Navigate( @@ -242,6 +251,17 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPatternProvider(PATTE AddRef(); } + if (patternId == UIA_TextPatternId && + (strongView.try_as() || + strongView.try_as())) { + m_textProvider.as().copy_to(pRetVal); + } + + if (patternId == UIA_TextPattern2Id && + strongView.try_as()) { + m_textProvider.as().copy_to(pRetVal); + } + return S_OK; } diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h index 34a15284196..f6f09f98d61 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h @@ -85,6 +85,7 @@ class CompositionDynamicAutomationProvider : public winrt::implements< private: ::Microsoft::ReactNative::ReactTaggedView m_view; + winrt::com_ptr m_textProvider; std::vector> m_selectionItems; }; diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.cpp new file mode 100644 index 00000000000..ef997fe0ae4 --- /dev/null +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.cpp @@ -0,0 +1,115 @@ +#include "pch.h" +#include +#include +#include +#include +#include "CompositionTextRangeProvider.h" +#include "RootComponentView.h" +#include "UiaHelpers.h" + +namespace winrt::Microsoft::ReactNative::implementation { + +CompositionTextProvider::CompositionTextProvider( + const winrt::Microsoft::ReactNative::Composition::ComponentView &componentView, + CompositionDynamicAutomationProvider *parentProvider) noexcept + : m_view{componentView} { + m_parentProvider.copy_from(parentProvider); + EnsureTextRangeProvider(); +} + +void CompositionTextProvider::EnsureTextRangeProvider() { + auto strongView = m_view.view(); + + if (!strongView) + return; + + if (!m_textRangeProvider) { + m_textRangeProvider = + winrt::make( + strongView.as(), m_parentProvider.get()) + .try_as(); + } +} + +HRESULT __stdcall CompositionTextProvider::get_DocumentRange(ITextRangeProvider **pRetVal) { + if (pRetVal == nullptr) + return E_POINTER; + auto strongView = m_view.view(); + + if (!strongView) + return UIA_E_ELEMENTNOTAVAILABLE; + + if (m_textRangeProvider == nullptr) + return UIA_E_ELEMENTNOTAVAILABLE; + + m_textRangeProvider.copy_to(pRetVal); + return S_OK; +} + +HRESULT __stdcall CompositionTextProvider::get_SupportedTextSelection(SupportedTextSelection *pRetVal) { + if (pRetVal == nullptr) + return E_POINTER; + auto strongView = m_view.view(); + + if (!strongView) + return UIA_E_ELEMENTNOTAVAILABLE; + + if (strongView.try_as()) { + *pRetVal = SupportedTextSelection_Single; + } else if ( + auto textView = + strongView.try_as()) { + auto props = std::static_pointer_cast(textView->props()); + if (props == nullptr) + return UIA_E_ELEMENTNOTAVAILABLE; + *pRetVal = props->isSelectable ? SupportedTextSelection_Single : SupportedTextSelection_None; + } else { + *pRetVal = SupportedTextSelection_None; + } + + return S_OK; +} + +HRESULT __stdcall CompositionTextProvider::GetSelection(SAFEARRAY **pRetVal) { + // no-op + *pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, 0); + return S_OK; +} + +HRESULT __stdcall CompositionTextProvider::GetVisibleRanges(SAFEARRAY **pRetVal) { + *pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, 1); + if (m_textRangeProvider == nullptr) + return UIA_E_ELEMENTNOTAVAILABLE; + LONG pos = 0; + return SafeArrayPutElement(*pRetVal, &pos, m_textRangeProvider.get()); +} + +HRESULT __stdcall CompositionTextProvider::RangeFromChild( + IRawElementProviderSimple *childElement, + ITextRangeProvider **pRetVal) { + // no-op + *pRetVal = nullptr; + return S_OK; +} + +HRESULT __stdcall CompositionTextProvider::RangeFromPoint(UiaPoint point, ITextRangeProvider **pRetVal) { + // no-op + if (m_textRangeProvider == nullptr) + return UIA_E_ELEMENTNOTAVAILABLE; + m_textRangeProvider.copy_to(pRetVal); + return S_OK; +} +HRESULT __stdcall CompositionTextProvider::GetCaretRange(BOOL *isActive, ITextRangeProvider **pRetVal) { + // no-op + *pRetVal = nullptr; + return S_OK; +} + +HRESULT __stdcall CompositionTextProvider::RangeFromAnnotation( + IRawElementProviderSimple *annotationElement, + ITextRangeProvider **pRetVal) { + // no-op + *pRetVal = nullptr; + return S_OK; +} +} // namespace winrt::Microsoft::ReactNative::implementation diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.h b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.h new file mode 100644 index 00000000000..cb68ad7bfe9 --- /dev/null +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.h @@ -0,0 +1,41 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace winrt::Microsoft::ReactNative::implementation { + +class CompositionTextProvider : public winrt::implements { + public: + CompositionTextProvider( + const winrt::Microsoft::ReactNative::Composition::ComponentView &componentView, + CompositionDynamicAutomationProvider *parentProvider) noexcept; + + // inherited via ITextProvider + virtual HRESULT __stdcall get_DocumentRange(ITextRangeProvider **pRetVal) override; + virtual HRESULT __stdcall get_SupportedTextSelection(SupportedTextSelection *pRetVal) override; + virtual HRESULT __stdcall GetSelection(SAFEARRAY **pRetVal) override; + virtual HRESULT __stdcall GetVisibleRanges(SAFEARRAY **pRetVal) override; + virtual HRESULT __stdcall RangeFromChild(IRawElementProviderSimple *childElement, ITextRangeProvider **pRetVal) + override; + virtual HRESULT __stdcall RangeFromPoint(UiaPoint point, ITextRangeProvider **pRetVal) override; + + // inherited via ITextProvider2 + virtual HRESULT __stdcall GetCaretRange(BOOL *isActive, ITextRangeProvider **pRetVal) override; + virtual HRESULT __stdcall RangeFromAnnotation( + IRawElementProviderSimple *annotationElement, + ITextRangeProvider **pRetVal) override; + + void EnsureTextRangeProvider(); + + private: + ::Microsoft::ReactNative::ReactTaggedView m_view; + winrt::com_ptr m_textRangeProvider; + winrt::com_ptr m_parentProvider; +}; + +} // namespace winrt::Microsoft::ReactNative::implementation diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.cpp new file mode 100644 index 00000000000..1f69c84b3df --- /dev/null +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.cpp @@ -0,0 +1,298 @@ +#include "pch.h" +#include "CompositionTextRangeProvider.h" +#include +#include +#include +#include +#include +#include "RootComponentView.h" +#include "UiaHelpers.h" + +namespace winrt::Microsoft::ReactNative::implementation { + +CompositionTextRangeProvider::CompositionTextRangeProvider( + const winrt::Microsoft::ReactNative::Composition::ComponentView &componentView, + CompositionDynamicAutomationProvider *parentProvider) noexcept + : m_view{componentView} { + m_parentProvider.copy_from(parentProvider); +} + +HRESULT __stdcall CompositionTextRangeProvider::Clone(ITextRangeProvider **pRetVal) { + // no-op + *pRetVal = nullptr; + return S_OK; +} + +HRESULT __stdcall CompositionTextRangeProvider::Compare(ITextRangeProvider *range, BOOL *pRetVal) { + // no-op + *pRetVal = false; + return S_OK; +} + +HRESULT __stdcall CompositionTextRangeProvider::CompareEndpoints( + TextPatternRangeEndpoint endpoint, + ITextRangeProvider *targetRange, + TextPatternRangeEndpoint targetEndpoint, + int *pRetVal) { + // no-op + *pRetVal = 0; + return S_OK; +} + +HRESULT __stdcall CompositionTextRangeProvider::ExpandToEnclosingUnit(TextUnit unit) { + // no-op + return S_OK; +} + +HRESULT __stdcall CompositionTextRangeProvider::FindAttribute( + TEXTATTRIBUTEID attributeId, + VARIANT val, + BOOL backward, + ITextRangeProvider **pRetVal) { + // no-op + *pRetVal = nullptr; + return S_OK; +} + +HRESULT __stdcall CompositionTextRangeProvider::FindText( + BSTR text, + BOOL backward, + BOOL ignoreCase, + ITextRangeProvider **pRetVal) { + // no-op + *pRetVal = nullptr; + return S_OK; +} + +HRESULT __stdcall CompositionTextRangeProvider::GetAttributeValue(TEXTATTRIBUTEID attributeId, VARIANT *pRetVal) { + if (pRetVal == nullptr) + return E_POINTER; + auto strongView = m_view.view(); + + if (!strongView) + return UIA_E_ELEMENTNOTAVAILABLE; + + auto props = std::static_pointer_cast( + winrt::get_self(strongView)->props()); + + auto textinputProps = std::static_pointer_cast( + winrt::get_self(strongView)->props()); + + auto isTextInput = + strongView.try_as(); + + if (props == nullptr) + return UIA_E_ELEMENTNOTAVAILABLE; + + if (attributeId == UIA_BackgroundColorAttributeId) { + pRetVal->vt = VT_I4; + pRetVal->lVal = (*props->backgroundColor).AsColorRefWithAlpha(); + } else if (attributeId == UIA_CapStyleAttributeId) { + pRetVal->vt = VT_I4; + auto fontVariant = facebook::react::FontVariant::Default; + auto textTransform = facebook::react::TextTransform::None; + if (props->textAttributes.fontVariant.has_value()) { + fontVariant = props->textAttributes.fontVariant.value(); + } + if (props->textAttributes.textTransform.has_value()) { + textTransform = props->textAttributes.textTransform.value(); + } + if (fontVariant == facebook::react::FontVariant::SmallCaps) { + return CapStyle_SmallCap; + } else if (textTransform == facebook::react::TextTransform::Capitalize) { + return CapStyle_Titling; + } else if (textTransform == facebook::react::TextTransform::Lowercase) { + return CapStyle_None; + } else if (textTransform == facebook::react::TextTransform::Uppercase) { + return CapStyle_AllCap; + } + } else if (attributeId == UIA_FontNameAttributeId) { + pRetVal->vt = VT_BSTR; + auto fontName = props->textAttributes.fontFamily; + if (fontName.empty()) { + fontName = "Segoe UI"; + } + std::wstring wfontName(fontName.begin(), fontName.end()); + pRetVal->bstrVal = SysAllocString(wfontName.c_str()); + } else if (attributeId == UIA_FontSizeAttributeId) { + pRetVal->vt = VT_R8; + pRetVal->dblVal = props->textAttributes.fontSize; + } else if (attributeId == UIA_FontWeightAttributeId) { + if (props->textAttributes.fontWeight.has_value()) { + pRetVal->vt = VT_I4; + pRetVal->lVal = static_cast(props->textAttributes.fontWeight.value()); + } + } else if (attributeId == UIA_ForegroundColorAttributeId) { + pRetVal->vt = VT_I4; + pRetVal->lVal = (*props->textAttributes.foregroundColor).AsColorRefWithAlpha(); + } else if (attributeId == UIA_IsItalicAttributeId) { + pRetVal->vt = VT_BOOL; + pRetVal->boolVal = (props->textAttributes.fontStyle.has_value() && + props->textAttributes.fontStyle.value() == facebook::react::FontStyle::Italic) + ? VARIANT_TRUE + : VARIANT_FALSE; + } else if (attributeId == UIA_IsReadOnlyAttributeId) { + pRetVal->vt = VT_BOOL; + pRetVal->boolVal = isTextInput ? textinputProps->editable ? VARIANT_FALSE : VARIANT_TRUE : VARIANT_TRUE; + } else if (attributeId == UIA_HorizontalTextAlignmentAttributeId) { + pRetVal->vt = VT_I4; + auto textAlign = facebook::react::TextAlignment::Center; + if (props->textAttributes.alignment.has_value()) { + textAlign = props->textAttributes.alignment.value(); + } + if (textAlign == facebook::react::TextAlignment::Left) { + pRetVal->lVal = HorizontalTextAlignment_Left; + } else if (textAlign == facebook::react::TextAlignment::Right) { + pRetVal->lVal = HorizontalTextAlignment_Right; + } else if (textAlign == facebook::react::TextAlignment::Center) { + pRetVal->lVal = HorizontalTextAlignment_Centered; + } else if (textAlign == facebook::react::TextAlignment::Justified) { + pRetVal->lVal = HorizontalTextAlignment_Justified; + } else if (textAlign == facebook::react::TextAlignment::Natural) { + pRetVal->lVal = HorizontalTextAlignment_Left; + } + } else if (attributeId == UIA_StrikethroughColorAttributeId) { + if (props->textAttributes.textDecorationLineType.has_value() && + (props->textAttributes.textDecorationLineType.value() == + facebook::react::TextDecorationLineType::Strikethrough || + props->textAttributes.textDecorationLineType.value() == + facebook::react::TextDecorationLineType::UnderlineStrikethrough)) { + pRetVal->vt = VT_I4; + pRetVal->lVal = (*props->textAttributes.textDecorationColor).AsColorRefWithAlpha(); + } + } else if (attributeId == UIA_StrikethroughStyleAttributeId) { + if (props->textAttributes.textDecorationLineType.has_value() && + (props->textAttributes.textDecorationLineType.value() == + facebook::react::TextDecorationLineType::Strikethrough || + props->textAttributes.textDecorationLineType.value() == + facebook::react::TextDecorationLineType::UnderlineStrikethrough)) { + pRetVal->vt = VT_I4; + auto style = props->textAttributes.textDecorationStyle.value(); + pRetVal->lVal = GetTextDecorationLineStyle(style); + } + } else if (attributeId == UIA_UnderlineColorAttributeId) { + if (props->textAttributes.textDecorationLineType.has_value() && + (props->textAttributes.textDecorationLineType.value() == facebook::react::TextDecorationLineType::Underline || + props->textAttributes.textDecorationLineType.value() == + facebook::react::TextDecorationLineType::UnderlineStrikethrough)) { + pRetVal->vt = VT_I4; + pRetVal->lVal = (*props->textAttributes.textDecorationColor).AsColorRefWithAlpha(); + } + } else if (attributeId == UIA_UnderlineStyleAttributeId) { + if (props->textAttributes.textDecorationLineType.has_value() && + (props->textAttributes.textDecorationLineType.value() == facebook::react::TextDecorationLineType::Underline || + props->textAttributes.textDecorationLineType.value() == + facebook::react::TextDecorationLineType::UnderlineStrikethrough)) { + pRetVal->vt = VT_I4; + auto style = props->textAttributes.textDecorationStyle.value(); + pRetVal->lVal = GetTextDecorationLineStyle(style); + } + } + return S_OK; +} + +HRESULT __stdcall CompositionTextRangeProvider::GetBoundingRectangles(SAFEARRAY **pRetVal) { + if (pRetVal == nullptr) + return E_POINTER; + UiaRect rect; + auto hr = m_parentProvider->get_BoundingRectangle(&rect); + if (FAILED(hr)) + return hr; + *pRetVal = SafeArrayCreateVector(VT_R8, 0, 4); + double *pData = nullptr; + hr = SafeArrayAccessData(*pRetVal, reinterpret_cast(&pData)); + if (FAILED(hr)) + return hr; + pData[0] = rect.left; + pData[1] = rect.top; + pData[2] = rect.width; + pData[3] = rect.height; + hr = SafeArrayUnaccessData(*pRetVal); + if (FAILED(hr)) + return hr; + return S_OK; +} + +HRESULT __stdcall CompositionTextRangeProvider::GetChildren(SAFEARRAY **pRetVal) { + // no-op + *pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, 0); + return S_OK; +} + +HRESULT __stdcall CompositionTextRangeProvider::GetEnclosingElement(IRawElementProviderSimple **pRetVal) { + // no-op + *pRetVal = nullptr; + return S_OK; +} + +HRESULT __stdcall CompositionTextRangeProvider::GetText(int maxLength, BSTR *pRetVal) { + if (pRetVal == nullptr) + return E_POINTER; + auto strongView = m_view.view(); + + if (!strongView) + return UIA_E_ELEMENTNOTAVAILABLE; + auto paragraphView = + strongView.try_as(); + std::string text = ""; + if (paragraphView) { + text = paragraphView->DefaultAccessibleName(); + } else { + auto textInputView = + strongView.try_as(); + if (textInputView) { + text = textInputView->getAccessiblityValue().value().empty() ? textInputView->DefaultAccessibleName() + : textInputView->getAccessiblityValue().value(); + } else { + return UIA_E_NOTSUPPORTED; + } + } + + std::wstring wtext(text.begin(), text.end()); + *pRetVal = SysAllocString(wtext.c_str()); + return S_OK; +} + +HRESULT __stdcall CompositionTextRangeProvider::Move(TextUnit unit, int count, int *pRetVal) { + // no-op + *pRetVal = 0; + return S_OK; +} + +HRESULT __stdcall CompositionTextRangeProvider::MoveEndpointByRange( + TextPatternRangeEndpoint endpoint, + ITextRangeProvider *targetRange, + TextPatternRangeEndpoint targetEndpoint) { + // no-op + return S_OK; +} + +HRESULT __stdcall CompositionTextRangeProvider::MoveEndpointByUnit( + TextPatternRangeEndpoint endpoint, + TextUnit unit, + int count, + int *pRetVal) { + // no-op + *pRetVal = 0; + return S_OK; +} + +HRESULT __stdcall CompositionTextRangeProvider::ScrollIntoView(BOOL alignToTop) { + // no-op + return S_OK; +} + +HRESULT __stdcall CompositionTextRangeProvider::AddToSelection() { + // no-op + return S_OK; +} +HRESULT __stdcall CompositionTextRangeProvider::RemoveFromSelection() { + // no-op + return S_OK; +} +HRESULT __stdcall CompositionTextRangeProvider::Select() { + // no-op + return S_OK; +} + +} // namespace winrt::Microsoft::ReactNative::implementation diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.h b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.h new file mode 100644 index 00000000000..18ec13688bf --- /dev/null +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.h @@ -0,0 +1,59 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace winrt::Microsoft::ReactNative::implementation { + +class CompositionTextRangeProvider : public winrt::implements { + public: + CompositionTextRangeProvider( + const winrt::Microsoft::ReactNative::Composition::ComponentView &componentView, + CompositionDynamicAutomationProvider *parentProvider) noexcept; + + // inherited via ITextRangeProvider + virtual HRESULT __stdcall Clone(ITextRangeProvider **pRetVal) override; + virtual HRESULT __stdcall Compare(ITextRangeProvider *range, BOOL *pRetVal) override; + virtual HRESULT __stdcall CompareEndpoints( + TextPatternRangeEndpoint endpoint, + ITextRangeProvider *targetRange, + TextPatternRangeEndpoint targetEndpoint, + int *pRetVal) override; + virtual HRESULT __stdcall ExpandToEnclosingUnit(TextUnit unit) override; + virtual HRESULT __stdcall FindAttribute( + TEXTATTRIBUTEID attributeId, + VARIANT val, + BOOL backward, + ITextRangeProvider **pRetVal) override; + virtual HRESULT __stdcall FindText(BSTR text, BOOL backward, BOOL ignoreCase, ITextRangeProvider **pRetVal) override; + virtual HRESULT __stdcall GetAttributeValue(TEXTATTRIBUTEID attributeId, VARIANT *pRetVal) override; + virtual HRESULT __stdcall GetBoundingRectangles(SAFEARRAY **pRetVal) override; + virtual HRESULT __stdcall GetChildren(SAFEARRAY **pRetVal) override; + virtual HRESULT __stdcall GetEnclosingElement(IRawElementProviderSimple **pRetVal) override; + virtual HRESULT __stdcall GetText(int maxLength, BSTR *pRetVal) override; + virtual HRESULT __stdcall Move(TextUnit unit, int count, int *pRetVal) override; + virtual HRESULT __stdcall MoveEndpointByRange( + TextPatternRangeEndpoint endpoint, + ITextRangeProvider *targetRange, + TextPatternRangeEndpoint targetEndpoint) override; + virtual HRESULT __stdcall MoveEndpointByUnit( + TextPatternRangeEndpoint endpoint, + TextUnit unit, + int count, + int *pRetVal) override; + virtual HRESULT __stdcall ScrollIntoView(BOOL alignToTop) override; + virtual HRESULT __stdcall AddToSelection() override; + virtual HRESULT __stdcall RemoveFromSelection() override; + virtual HRESULT __stdcall Select() override; + + private: + ::Microsoft::ReactNative::ReactTaggedView m_view; + winrt::com_ptr m_parentProvider; +}; + +} // namespace winrt::Microsoft::ReactNative::implementation diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp index 4739ca7ff5a..cb04dfe8d28 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp @@ -254,4 +254,18 @@ ToggleState GetToggleState(const std::optional #include +#include #include #include @@ -41,4 +42,6 @@ void AddSelectionItemsToContainer(CompositionDynamicAutomationProvider *provider void RemoveSelectionItemsFromContainer(CompositionDynamicAutomationProvider *provider) noexcept; ToggleState GetToggleState(const std::optional &state) noexcept; + +TextDecorationLineStyle GetTextDecorationLineStyle(facebook::react::TextDecorationStyle style) noexcept; } // namespace winrt::Microsoft::ReactNative::implementation diff --git a/vnext/Shared/Shared.vcxitems b/vnext/Shared/Shared.vcxitems index e2595b0e5dc..093d709e149 100644 --- a/vnext/Shared/Shared.vcxitems +++ b/vnext/Shared/Shared.vcxitems @@ -67,6 +67,12 @@ true + + true + + + true + true $(ReactNativeWindowsDir)Microsoft.ReactNative\ReactNativeIsland.idl diff --git a/vnext/Shared/Shared.vcxitems.filters b/vnext/Shared/Shared.vcxitems.filters index 9be57880a88..f0e4ef9e9dc 100644 --- a/vnext/Shared/Shared.vcxitems.filters +++ b/vnext/Shared/Shared.vcxitems.filters @@ -209,6 +209,12 @@ Source Files\Fabric\Composition + + Source Files\Fabric\Composition + + + Source Files\Fabric\Composition + Source Files\Fabric\Composition @@ -330,6 +336,8 @@ + + From ed728d9dd41dbd56d3d7748633df3c836395fbee Mon Sep 17 00:00:00 2001 From: Chiara Mooney <34109996+chiaramooney@users.noreply.github.com> Date: Tue, 11 Mar 2025 10:22:36 -0700 Subject: [PATCH 2/7] [Fabric] Add Support for Role Prop (#14352) * Add Support for Role Prop * Change files * Format * Update Tests --------- Co-authored-by: Tatiana Kapos --- ...-56f137a7-212a-483c-9771-7bf7c0fad2a8.json | 7 ++ .../AccessibilityExampleWindows.tsx | 2 +- .../__snapshots__/snapshotPages.test.js.snap | 2 +- .../CompositionDynamicAutomationProvider.cpp | 109 +++++++++++++++++- 4 files changed, 112 insertions(+), 8 deletions(-) create mode 100644 change/react-native-windows-56f137a7-212a-483c-9771-7bf7c0fad2a8.json diff --git a/change/react-native-windows-56f137a7-212a-483c-9771-7bf7c0fad2a8.json b/change/react-native-windows-56f137a7-212a-483c-9771-7bf7c0fad2a8.json new file mode 100644 index 00000000000..4e52914ba5c --- /dev/null +++ b/change/react-native-windows-56f137a7-212a-483c-9771-7bf7c0fad2a8.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "Add Support for Role Prop", + "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/Accessibility/AccessibilityExampleWindows.tsx b/packages/@react-native-windows/tester/src/js/examples-win/Accessibility/AccessibilityExampleWindows.tsx index 91edb0fcf2e..2c3ffef60bb 100644 --- a/packages/@react-native-windows/tester/src/js/examples-win/Accessibility/AccessibilityExampleWindows.tsx +++ b/packages/@react-native-windows/tester/src/js/examples-win/Accessibility/AccessibilityExampleWindows.tsx @@ -475,7 +475,7 @@ class AccessibilityStateExamples extends React.Component { accessibilityValue={{ text: this.state.viewValueText, }} - accessibilityRole="combobox" + role="combobox" testID="accessibilityValue-text" accessible aria-readonly> 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 cfcc75e2088..a57c46fba34 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 @@ -751,7 +751,6 @@ exports[`snapshotAllPages Accessibility Windows 4`] = ` The following View exposes the accessibilityValue.Text field vt = VT_I4; - auto role = props->accessibilityRole.empty() ? compositionView->DefaultControlType() : props->accessibilityRole; - pRetVal->lVal = GetControlType(role); + pRetVal->lVal = props->role == facebook::react::Role::None ? props->accessibilityRole.empty() + ? GetControlTypeFromString(compositionView->DefaultControlType()) + : GetControlTypeFromString(props->accessibilityRole) + : GetControlTypeFromRole(props->role); break; } case UIA_AutomationIdPropertyId: { @@ -394,12 +486,18 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERT } case UIA_IsContentElementPropertyId: { pRetVal->vt = VT_BOOL; - pRetVal->boolVal = (props->accessible && props->accessibilityRole != "none") ? VARIANT_TRUE : VARIANT_FALSE; + pRetVal->boolVal = + (props->accessible && (props->accessibilityRole != "none" || props->role != facebook::react::Role::None)) + ? VARIANT_TRUE + : VARIANT_FALSE; break; } case UIA_IsControlElementPropertyId: { pRetVal->vt = VT_BOOL; - pRetVal->boolVal = (props->accessible && props->accessibilityRole != "none") ? VARIANT_TRUE : VARIANT_FALSE; + pRetVal->boolVal = + (props->accessible && (props->accessibilityRole != "none" || props->role != facebook::react::Role::None)) + ? VARIANT_TRUE + : VARIANT_FALSE; break; } case UIA_IsOffscreenPropertyId: { @@ -546,7 +644,6 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::get_IsReadOnly(BOOL *pRe winrt::get_self(strongView)->props()); if (props == nullptr) return UIA_E_ELEMENTNOTAVAILABLE; - auto accessibilityRole = props->accessibilityRole; if (props->accessibilityState.has_value() && props->accessibilityState->readOnly.has_value()) { *pRetVal = props->accessibilityState->readOnly.value(); } else { From 049990a15f799720b526f106cb4b886177515a72 Mon Sep 17 00:00:00 2001 From: Chiara Mooney <34109996+chiaramooney@users.noreply.github.com> Date: Wed, 12 Mar 2025 10:24:08 -0700 Subject: [PATCH 3/7] [Fabric] Add Support for ScrollProvider (#14411) * Save State * Continue ScrollProvider Implementation * Complete Implementation * Add Test Infra * Change files * Format + Remove Unneeded * Add Override * Update Snapshots * Add Comments --- ...-7d072016-5414-4327-b40c-a149c1dc34b9.json | 7 + .../test/ScrollViewComponentTest.test.ts | 5 +- .../AccessibilityTest.test.ts.snap | 27 +- .../FlatListComponentTest.test.ts.snap | 6372 ----------------- .../ScrollViewComponentTest.test.ts.snap | 647 ++ .../RNTesterApp-Fabric/RNTesterApp-Fabric.cpp | 10 + .../CompositionDynamicAutomationProvider.cpp | 167 + .../CompositionDynamicAutomationProvider.h | 11 + .../Composition/ScrollViewComponentView.cpp | 26 +- .../Composition/ScrollViewComponentView.h | 5 + vnext/overrides.json | 6 + .../ScrollView/ScrollView.windows.js | 1920 +++++ 12 files changed, 2803 insertions(+), 6400 deletions(-) create mode 100644 change/react-native-windows-7d072016-5414-4327-b40c-a149c1dc34b9.json delete mode 100644 packages/e2e-test-app-fabric/test/__snapshots__/FlatListComponentTest.test.ts.snap create mode 100644 vnext/src-win/Libraries/Components/ScrollView/ScrollView.windows.js diff --git a/change/react-native-windows-7d072016-5414-4327-b40c-a149c1dc34b9.json b/change/react-native-windows-7d072016-5414-4327-b40c-a149c1dc34b9.json new file mode 100644 index 00000000000..7f23502a86e --- /dev/null +++ b/change/react-native-windows-7d072016-5414-4327-b40c-a149c1dc34b9.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "Add IScrollProvider Implementation", + "packageName": "react-native-windows", + "email": "34109996+chiaramooney@users.noreply.github.com", + "dependentChangeType": "patch" +} diff --git a/packages/e2e-test-app-fabric/test/ScrollViewComponentTest.test.ts b/packages/e2e-test-app-fabric/test/ScrollViewComponentTest.test.ts index f8a4d699e6a..fa0f7467143 100644 --- a/packages/e2e-test-app-fabric/test/ScrollViewComponentTest.test.ts +++ b/packages/e2e-test-app-fabric/test/ScrollViewComponentTest.test.ts @@ -49,13 +49,12 @@ describe('ScrollView Tests', () => { const dump = await dumpVisualTree('flash_scroll_indicators_button'); expect(dump).toMatchSnapshot(); }); - // Disable tests where testID is not found. - /*test('ScrollViews can scroll an item list horizontally', async () => { + test('ScrollViews can scroll an item list horizontally', async () => { const component = await app.findElementByTestID('scroll_horizontal'); await component.waitForDisplayed({timeout: 20000}); const dump = await dumpVisualTree('scroll_horizontal'); expect(dump).toMatchSnapshot(); - });*/ + }); test('ScrollView has scrollTo method, scroll to start button', async () => { const component = await app.findElementByTestID('scroll_to_start_button'); await component.waitForDisplayed({timeout: 20000}); diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/AccessibilityTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/AccessibilityTest.test.ts.snap index 41968769ec3..6101cd246c9 100644 --- a/packages/e2e-test-app-fabric/test/__snapshots__/AccessibilityTest.test.ts.snap +++ b/packages/e2e-test-app-fabric/test/__snapshots__/AccessibilityTest.test.ts.snap @@ -245,11 +245,10 @@ exports[`Accessibility Tests Selectable items must have a Selection Container. E "SelectionPattern.IsSelectionRequired": true, "__Children": [ { - "AutomationId": "Selectable item 1", - "ControlType": 50000, - "IsKeyboardFocusable": true, - "LocalizedControlType": "button", - "Name": "Selectable item 1", + "AutomationId": "", + "ControlType": 50033, + "LocalizedControlType": "pane", + "Name": "List of selectable items", "__Children": [ { "AutomationId": "", @@ -258,15 +257,6 @@ exports[`Accessibility Tests Selectable items must have a Selection Container. E "Name": "Unselected", "TextRangePattern.GetText": "Unselected", }, - ], - }, - { - "AutomationId": "Selectable item 2", - "ControlType": 50000, - "IsKeyboardFocusable": true, - "LocalizedControlType": "button", - "Name": "Selectable item 2", - "__Children": [ { "AutomationId": "", "ControlType": 50020, @@ -274,15 +264,6 @@ exports[`Accessibility Tests Selectable items must have a Selection Container. E "Name": "Unselected", "TextRangePattern.GetText": "Unselected", }, - ], - }, - { - "AutomationId": "Selectable item 3", - "ControlType": 50000, - "IsKeyboardFocusable": true, - "LocalizedControlType": "button", - "Name": "Selectable item 3", - "__Children": [ { "AutomationId": "", "ControlType": 50020, diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/FlatListComponentTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/FlatListComponentTest.test.ts.snap deleted file mode 100644 index 63a9e12c59b..00000000000 --- a/packages/e2e-test-app-fabric/test/__snapshots__/FlatListComponentTest.test.ts.snap +++ /dev/null @@ -1,6372 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`FlatList Tests A FlatList can be filtered by a key word 1`] = ` -{ - "Automation Tree": { - "AutomationId": "flatlist-basic", - "ControlType": 50008, - "LocalizedControlType": "list", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Item 555 - Lorem ipsum dolor sit amet, ius ad pertinax oportere accommodare, a", - "TextRangePattern.GetText": "Item 555 - Lorem ipsum dolor sit amet, ius ad pertinax oportere accommodare, a", - }, - ], - }, - ], - }, - "Component Tree": { - "Type": "Microsoft.ReactNative.Composition.ScrollViewComponentView", - "_Props": { - "TestId": "flatlist-basic", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ActivityIndicatorComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ImageComponentView", - "_Props": { - "Sources": [ - { - "Size": "128, 128", - "Type": "Local", - "Uri": "@react-native-windows/tester/js/assets/dislike.png", - }, - ], - }, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ActivityIndicatorComponentView", - "_Props": {}, - }, - ], - }, - ], - }, - ], - }, - "Visual Tree": { - "Comment": "flatlist-basic", - "Offset": "0, 0, 0", - "Size": "998, 398", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(0, 0, 0, 0)", - }, - "Offset": "0, 0, 0", - "Size": "998, 398", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(0, 0, 0, 0)", - }, - "Offset": "0, 0, 0", - "Size": "998, 398", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 398", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 255, 255, 255)", - }, - "Offset": "0, 0, 0", - "Size": "998, 398", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 100", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 100", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 100", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 100", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "0, 1", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "0, 0, 0", - "Size": "-0, 1", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "-0, 0, 0", - "Size": "0, 1", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "-0, 1, 0", - "Size": "0, -1", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "-0, -0, 0", - "Size": "0, 0", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "0, -0, 0", - "Size": "-0, 0", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "0, -0, 0", - "Size": "0, 0", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "0, 1, 0", - "Size": "0, -1", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - { - "Offset": "489, 41, 0", - "Size": "20, 20", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "20, 20", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "0, 0, 0", - "Size": "0, 0", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "0, 0", - "Visual Type": "Visual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "80, 80", - "Visual Type": "Visual", - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 100, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 255, 255, 255)", - }, - "Offset": "0, 0, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "5, 10, 0", - "Size": "50, 50", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "50, 50", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "60, 10, 0", - "Size": "928, 52", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "928, 52", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 172, 0", - "Size": "998, 100", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 100", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 100", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 100", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "0, 1", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "0, 0, 0", - "Size": "-0, 1", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "-0, 0, 0", - "Size": "0, 1", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "-0, 1, 0", - "Size": "0, -1", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "-0, -0, 0", - "Size": "0, 0", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "0, -0, 0", - "Size": "-0, 0", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "0, -0, 0", - "Size": "0, 0", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "0, 1, 0", - "Size": "0, -1", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - { - "Offset": "489, 41, 0", - "Size": "20, 20", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "20, 20", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "0, 0, 0", - "Size": "0, 0", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "0, 0", - "Visual Type": "Visual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "80, 80", - "Visual Type": "Visual", - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "-13, 0, 0", - "Size": "12, 0", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "-12, 3, 0", - "Opacity": 0, - "Size": "12, 392", - "Visual Type": "Visual", - }, - { - "Offset": "0, 4, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "0, -16, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "-5, 16, 0", - "Size": "6, 366", - "Visual Type": "Visual", - }, - ], - }, - { - "Offset": "0, -13, 0", - "Size": "0, 12", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "3, -12, 0", - "Opacity": 0, - "Size": "992, 12", - "Visual Type": "Visual", - }, - { - "Offset": "4, 0, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "-16, 0, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "16, -5, 0", - "Size": "966, 6", - "Visual Type": "Visual", - }, - ], - }, - ], - }, -} -`; - -exports[`FlatList Tests A FlatList can be inverted 1`] = ` -{ - "Automation Tree": { - "AutomationId": "flat_list", - "ControlType": 50014, - "LocalizedControlType": "scroll bar", - "__Children": [ - { - "AutomationId": "Pizza", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Pizza", - "TextRangePattern.GetText": "Pizza", - }, - ], - }, - { - "AutomationId": "Burger", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Burger", - "TextRangePattern.GetText": "Burger", - }, - ], - }, - { - "AutomationId": "Risotto", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Risotto", - "TextRangePattern.GetText": "Risotto", - }, - ], - }, - { - "AutomationId": "French Fries", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "French Fries", - "TextRangePattern.GetText": "French Fries", - }, - ], - }, - { - "AutomationId": "Onion Rings", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Onion Rings", - "TextRangePattern.GetText": "Onion Rings", - }, - ], - }, - { - "AutomationId": "Fried Shrimps", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Fried Shrimps", - "TextRangePattern.GetText": "Fried Shrimps", - }, - ], - }, - { - "AutomationId": "Water", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Water", - "TextRangePattern.GetText": "Water", - }, - ], - }, - { - "AutomationId": "Coke", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Coke", - "TextRangePattern.GetText": "Coke", - }, - ], - }, - { - "AutomationId": "Beer", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Beer", - "TextRangePattern.GetText": "Beer", - }, - ], - }, - { - "AutomationId": "Cheesecake", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Cheesecake", - "TextRangePattern.GetText": "Cheesecake", - }, - ], - }, - { - "AutomationId": "Brownie", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Brownie", - "TextRangePattern.GetText": "Brownie", - }, - ], - }, - ], - }, - "Component Tree": { - "Type": "Microsoft.ReactNative.Composition.ScrollViewComponentView", - "_Props": { - "TestId": "flat_list", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Pizza", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Burger", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Risotto", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "French Fries", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Onion Rings", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Fried Shrimps", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Water", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Coke", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Beer", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Cheesecake", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Brownie", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - ], - }, - ], - }, - "Visual Tree": { - "Comment": "flat_list", - "Offset": "0, 0, 0", - "Size": "998, 534", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(0, 0, 0, 0)", - }, - "Offset": "0, 0, 0", - "Size": "998, 534", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(0, 0, 0, 0)", - }, - "Offset": "0, 0, 0", - "Size": "998, 946", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 946", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 946", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 8, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Pizza", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 94, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Burger", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 180, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Risotto", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 266, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "French Fries", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 352, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Onion Rings", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 438, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Fried Shrimps", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 524, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Water", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 610, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Coke", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 696, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Beer", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 782, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Cheesecake", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 868, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Brownie", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "-13, 0, 0", - "Size": "12, 0", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "-12, 3, 0", - "Opacity": 0, - "Size": "12, 528", - "Visual Type": "Visual", - }, - { - "Offset": "0, 4, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "0, -16, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "-5, 16, 0", - "Size": "6, 283", - "Visual Type": "Visual", - }, - ], - }, - { - "Offset": "0, -13, 0", - "Size": "0, 12", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "3, -12, 0", - "Opacity": 0, - "Size": "992, 12", - "Visual Type": "Visual", - }, - { - "Offset": "4, 0, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "-16, 0, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "16, -5, 0", - "Size": "966, 6", - "Visual Type": "Visual", - }, - ], - }, - ], - }, -} -`; - -exports[`FlatList Tests A FlatList can have a content inset 1`] = ` -{ - "Automation Tree": { - "AutomationId": "flat_list", - "ControlType": 50014, - "LocalizedControlType": "scroll bar", - "__Children": [ - { - "AutomationId": "Pizza", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Pizza", - "TextRangePattern.GetText": "Pizza", - }, - ], - }, - { - "AutomationId": "Burger", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Burger", - "TextRangePattern.GetText": "Burger", - }, - ], - }, - { - "AutomationId": "Risotto", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Risotto", - "TextRangePattern.GetText": "Risotto", - }, - ], - }, - { - "AutomationId": "French Fries", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "French Fries", - "TextRangePattern.GetText": "French Fries", - }, - ], - }, - { - "AutomationId": "Onion Rings", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Onion Rings", - "TextRangePattern.GetText": "Onion Rings", - }, - ], - }, - { - "AutomationId": "Fried Shrimps", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Fried Shrimps", - "TextRangePattern.GetText": "Fried Shrimps", - }, - ], - }, - { - "AutomationId": "Water", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Water", - "TextRangePattern.GetText": "Water", - }, - ], - }, - { - "AutomationId": "Coke", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Coke", - "TextRangePattern.GetText": "Coke", - }, - ], - }, - { - "AutomationId": "Beer", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Beer", - "TextRangePattern.GetText": "Beer", - }, - ], - }, - { - "AutomationId": "Cheesecake", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Cheesecake", - "TextRangePattern.GetText": "Cheesecake", - }, - ], - }, - { - "AutomationId": "Brownie", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Brownie", - "TextRangePattern.GetText": "Brownie", - }, - ], - }, - ], - }, - "Component Tree": { - "Type": "Microsoft.ReactNative.Composition.ScrollViewComponentView", - "_Props": { - "TestId": "flat_list", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Pizza", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Burger", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Risotto", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "French Fries", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Onion Rings", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Fried Shrimps", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Water", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Coke", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Beer", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Cheesecake", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Brownie", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - ], - }, - ], - }, - "Visual Tree": { - "Comment": "flat_list", - "Offset": "0, 0, 0", - "Size": "998, 534", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(0, 0, 0, 0)", - }, - "Offset": "0, 0, 0", - "Size": "998, 534", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(0, 0, 0, 0)", - }, - "Offset": "0, 0, 0", - "Size": "998, 946", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 946", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 946", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 8, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Pizza", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 94, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Burger", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 180, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Risotto", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 266, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "French Fries", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 352, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Onion Rings", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 438, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Fried Shrimps", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 524, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Water", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 610, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Coke", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 696, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Beer", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 782, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Cheesecake", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 868, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Brownie", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "-13, 0, 0", - "Size": "12, 0", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "-12, 3, 0", - "Opacity": 0, - "Size": "12, 528", - "Visual Type": "Visual", - }, - { - "Offset": "0, 4, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "0, -16, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "-5, 16, 0", - "Size": "6, 283", - "Visual Type": "Visual", - }, - ], - }, - { - "Offset": "0, -13, 0", - "Size": "0, 12", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "3, -12, 0", - "Opacity": 0, - "Size": "992, 12", - "Visual Type": "Visual", - }, - { - "Offset": "4, 0, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "-16, 0, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "16, -5, 0", - "Size": "966, 6", - "Visual Type": "Visual", - }, - ], - }, - ], - }, -} -`; - -exports[`FlatList Tests A FlatList can have separators 1`] = ` -{ - "Automation Tree": { - "AutomationId": "flat_list", - "ControlType": 50014, - "LocalizedControlType": "scroll bar", - "__Children": [ - { - "AutomationId": "Pizza", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Pizza", - "TextRangePattern.GetText": "Pizza", - }, - ], - }, - { - "AutomationId": "flat_list_separator", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Separator for leading Pizza and trailing undefined has not been pressed", - "TextRangePattern.GetText": "Separator for leading Pizza and trailing undefined has not been pressed", - }, - { - "AutomationId": "Burger", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Burger", - "TextRangePattern.GetText": "Burger", - }, - ], - }, - { - "AutomationId": "flat_list_separator", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Separator for leading Burger and trailing undefined has not been pressed", - "TextRangePattern.GetText": "Separator for leading Burger and trailing undefined has not been pressed", - }, - { - "AutomationId": "Risotto", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Risotto", - "TextRangePattern.GetText": "Risotto", - }, - ], - }, - { - "AutomationId": "flat_list_separator", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Separator for leading Risotto and trailing undefined has not been pressed", - "TextRangePattern.GetText": "Separator for leading Risotto and trailing undefined has not been pressed", - }, - { - "AutomationId": "French Fries", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "French Fries", - "TextRangePattern.GetText": "French Fries", - }, - ], - }, - { - "AutomationId": "flat_list_separator", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Separator for leading French Fries and trailing undefined has not been pressed", - "TextRangePattern.GetText": "Separator for leading French Fries and trailing undefined has not been pressed", - }, - { - "AutomationId": "Onion Rings", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Onion Rings", - "TextRangePattern.GetText": "Onion Rings", - }, - ], - }, - { - "AutomationId": "flat_list_separator", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Separator for leading Onion Rings and trailing undefined has not been pressed", - "TextRangePattern.GetText": "Separator for leading Onion Rings and trailing undefined has not been pressed", - }, - { - "AutomationId": "Fried Shrimps", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Fried Shrimps", - "TextRangePattern.GetText": "Fried Shrimps", - }, - ], - }, - { - "AutomationId": "flat_list_separator", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Separator for leading Fried Shrimps and trailing undefined has not been pressed", - "TextRangePattern.GetText": "Separator for leading Fried Shrimps and trailing undefined has not been pressed", - }, - { - "AutomationId": "Water", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Water", - "TextRangePattern.GetText": "Water", - }, - ], - }, - { - "AutomationId": "flat_list_separator", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Separator for leading Water and trailing undefined has not been pressed", - "TextRangePattern.GetText": "Separator for leading Water and trailing undefined has not been pressed", - }, - { - "AutomationId": "Coke", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Coke", - "TextRangePattern.GetText": "Coke", - }, - ], - }, - { - "AutomationId": "flat_list_separator", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Separator for leading Coke and trailing undefined has not been pressed", - "TextRangePattern.GetText": "Separator for leading Coke and trailing undefined has not been pressed", - }, - { - "AutomationId": "Beer", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Beer", - "TextRangePattern.GetText": "Beer", - }, - ], - }, - { - "AutomationId": "flat_list_separator", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Separator for leading Beer and trailing undefined has not been pressed", - "TextRangePattern.GetText": "Separator for leading Beer and trailing undefined has not been pressed", - }, - { - "AutomationId": "Cheesecake", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Cheesecake", - "TextRangePattern.GetText": "Cheesecake", - }, - ], - }, - { - "AutomationId": "flat_list_separator", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Separator for leading Cheesecake and trailing undefined has not been pressed", - "TextRangePattern.GetText": "Separator for leading Cheesecake and trailing undefined has not been pressed", - }, - { - "AutomationId": "Brownie", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Brownie", - "TextRangePattern.GetText": "Brownie", - }, - ], - }, - ], - }, - "Component Tree": { - "Type": "Microsoft.ReactNative.Composition.ScrollViewComponentView", - "_Props": { - "TestId": "flat_list", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Pizza", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": { - "TestId": "flat_list_separator", - }, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Burger", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": { - "TestId": "flat_list_separator", - }, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Risotto", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": { - "TestId": "flat_list_separator", - }, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "French Fries", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": { - "TestId": "flat_list_separator", - }, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Onion Rings", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": { - "TestId": "flat_list_separator", - }, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Fried Shrimps", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": { - "TestId": "flat_list_separator", - }, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Water", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": { - "TestId": "flat_list_separator", - }, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Coke", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": { - "TestId": "flat_list_separator", - }, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Beer", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": { - "TestId": "flat_list_separator", - }, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Cheesecake", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": { - "TestId": "flat_list_separator", - }, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Brownie", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - ], - }, - ], - }, - "Visual Tree": { - "Comment": "flat_list", - "Offset": "0, 0, 0", - "Size": "998, 574", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(0, 0, 0, 0)", - }, - "Offset": "0, 0, 0", - "Size": "998, 574", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(0, 0, 0, 0)", - }, - "Offset": "0, 0, 0", - "Size": "998, 1066", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 1066", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 1066", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 8, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Pizza", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 86, 0", - "Size": "998, 12", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(144, 238, 144, 255)", - }, - "Offset": "0, 0, 0", - "Size": "998, 12", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 86, 0", - "Size": "998, 14", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Comment": "flat_list_separator", - "Offset": "0, 0, 0", - "Size": "998, 14", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 106, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Burger", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 184, 0", - "Size": "998, 12", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(144, 238, 144, 255)", - }, - "Offset": "0, 0, 0", - "Size": "998, 12", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 184, 0", - "Size": "998, 14", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Comment": "flat_list_separator", - "Offset": "0, 0, 0", - "Size": "998, 14", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 204, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Risotto", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 282, 0", - "Size": "998, 12", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(144, 238, 144, 255)", - }, - "Offset": "0, 0, 0", - "Size": "998, 12", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 282, 0", - "Size": "998, 14", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Comment": "flat_list_separator", - "Offset": "0, 0, 0", - "Size": "998, 14", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 302, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "French Fries", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 380, 0", - "Size": "998, 12", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(144, 238, 144, 255)", - }, - "Offset": "0, 0, 0", - "Size": "998, 12", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 380, 0", - "Size": "998, 14", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Comment": "flat_list_separator", - "Offset": "0, 0, 0", - "Size": "998, 14", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 400, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Onion Rings", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 478, 0", - "Size": "998, 12", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(144, 238, 144, 255)", - }, - "Offset": "0, 0, 0", - "Size": "998, 12", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 478, 0", - "Size": "998, 14", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Comment": "flat_list_separator", - "Offset": "0, 0, 0", - "Size": "998, 14", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 498, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Fried Shrimps", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 576, 0", - "Size": "998, 12", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(144, 238, 144, 255)", - }, - "Offset": "0, 0, 0", - "Size": "998, 12", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 576, 0", - "Size": "998, 14", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Comment": "flat_list_separator", - "Offset": "0, 0, 0", - "Size": "998, 14", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 596, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Water", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 674, 0", - "Size": "998, 12", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(144, 238, 144, 255)", - }, - "Offset": "0, 0, 0", - "Size": "998, 12", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 674, 0", - "Size": "998, 14", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Comment": "flat_list_separator", - "Offset": "0, 0, 0", - "Size": "998, 14", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 694, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Coke", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 772, 0", - "Size": "998, 12", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(144, 238, 144, 255)", - }, - "Offset": "0, 0, 0", - "Size": "998, 12", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 772, 0", - "Size": "998, 14", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Comment": "flat_list_separator", - "Offset": "0, 0, 0", - "Size": "998, 14", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 792, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Beer", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 870, 0", - "Size": "998, 12", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(144, 238, 144, 255)", - }, - "Offset": "0, 0, 0", - "Size": "998, 12", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 870, 0", - "Size": "998, 14", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Comment": "flat_list_separator", - "Offset": "0, 0, 0", - "Size": "998, 14", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 890, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Cheesecake", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 968, 0", - "Size": "998, 12", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(144, 238, 144, 255)", - }, - "Offset": "0, 0, 0", - "Size": "998, 12", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 968, 0", - "Size": "998, 14", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Comment": "flat_list_separator", - "Offset": "0, 0, 0", - "Size": "998, 14", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 988, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Brownie", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "-13, 0, 0", - "Size": "12, 0", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "-12, 3, 0", - "Opacity": 0, - "Size": "12, 568", - "Visual Type": "Visual", - }, - { - "Offset": "0, 4, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "0, -16, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "-5, 16, 0", - "Size": "6, 292", - "Visual Type": "Visual", - }, - ], - }, - { - "Offset": "0, -13, 0", - "Size": "0, 12", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "3, -12, 0", - "Opacity": 0, - "Size": "992, 12", - "Visual Type": "Visual", - }, - { - "Offset": "4, 0, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "-16, 0, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "16, -5, 0", - "Size": "966, 6", - "Visual Type": "Visual", - }, - ], - }, - ], - }, -} -`; - -exports[`FlatList Tests A FlatList can have sticky headers 1`] = ` -{ - "Automation Tree": { - "AutomationId": "flatlist-sticky", - "ControlType": 50014, - "LocalizedControlType": "scroll bar", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Burger", - "TextRangePattern.GetText": "Burger", - }, - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "French Fries", - "TextRangePattern.GetText": "French Fries", - }, - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Fried Shrimps", - "TextRangePattern.GetText": "Fried Shrimps", - }, - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Water", - "TextRangePattern.GetText": "Water", - }, - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Coke", - "TextRangePattern.GetText": "Coke", - }, - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Beer", - "TextRangePattern.GetText": "Beer", - }, - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Cheesecake", - "TextRangePattern.GetText": "Cheesecake", - }, - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Ice Cream", - "TextRangePattern.GetText": "Ice Cream", - }, - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Sticky Pizza", - "TextRangePattern.GetText": "Sticky Pizza", - }, - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Sticky Risotto", - "TextRangePattern.GetText": "Sticky Risotto", - }, - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Sticky Onion Rings", - "TextRangePattern.GetText": "Sticky Onion Rings", - }, - ], - }, - "Component Tree": { - "Type": "Microsoft.ReactNative.Composition.ScrollViewComponentView", - "_Props": { - "TestId": "flatlist-sticky", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - ], - }, - ], - }, - "Visual Tree": { - "Comment": "flatlist-sticky", - "Offset": "0, 0, 0", - "Size": "998, 574", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(0, 0, 0, 0)", - }, - "Offset": "0, 0, 0", - "Size": "998, 574", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(0, 0, 0, 0)", - }, - "Offset": "0, 0, 0", - "Size": "998, 967", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 967", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 967", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 96, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Offset": "0, 0, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "20, 116, 0", - "Size": "958, 32", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 32", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 272, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Offset": "0, 0, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "20, 292, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 448, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Offset": "0, 0, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "20, 468, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 536, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Offset": "0, 0, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "20, 556, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 623, 0", - "Size": "998, 71", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Offset": "0, 0, 0", - "Size": "998, 71", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "20, 643, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 711, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Offset": "0, 0, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "20, 731, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 799, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Offset": "0, 0, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "20, 819, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 887, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Offset": "0, 0, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "20, 907, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "0, 0, 0", - "Size": "998, 88", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 88", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 8, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Offset": "0, 0, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "20, 28, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 176, 0", - "Size": "998, 88", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 88", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 8, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Offset": "0, 0, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "20, 28, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 352, 0", - "Size": "998, 88", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 88", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 8, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Offset": "0, 0, 0", - "Size": "998, 72", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "20, 28, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "-13, 0, 0", - "Size": "12, 0", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "-12, 3, 0", - "Opacity": 0, - "Size": "12, 568", - "Visual Type": "Visual", - }, - { - "Offset": "0, 4, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "0, -16, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "-5, 16, 0", - "Size": "6, 322", - "Visual Type": "Visual", - }, - ], - }, - { - "Offset": "0, -13, 0", - "Size": "0, 12", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "3, -12, 0", - "Opacity": 0, - "Size": "992, 12", - "Visual Type": "Visual", - }, - { - "Offset": "4, 0, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "-16, 0, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "16, -5, 0", - "Size": "966, 6", - "Visual Type": "Visual", - }, - ], - }, - ], - }, -} -`; - -exports[`FlatList Tests A FlatList can nest other Flatlists 1`] = ` -{ - "Automation Tree": { - "AutomationId": "flatlist-nested", - "ControlType": 50014, - "LocalizedControlType": "scroll bar", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Header", - "TextRangePattern.GetText": "Header", - }, - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "16", - "TextRangePattern.GetText": "16", - }, - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "17", - "TextRangePattern.GetText": "17", - }, - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "18", - "TextRangePattern.GetText": "18", - }, - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "19", - "TextRangePattern.GetText": "19", - }, - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "21", - "TextRangePattern.GetText": "21", - }, - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "22", - "TextRangePattern.GetText": "22", - }, - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "23", - "TextRangePattern.GetText": "23", - }, - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "24", - "TextRangePattern.GetText": "24", - }, - ], - }, - "Component Tree": { - "Type": "Microsoft.ReactNative.Composition.ScrollViewComponentView", - "_Props": { - "TestId": "flatlist-nested", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - }, - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - ], - }, - "Visual Tree": { - "Comment": "flatlist-nested", - "Offset": "0, 0, 0", - "Size": "998, 347", - "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, 0)", - }, - "Offset": "0, 0, 0", - "Size": "998, 347", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(0, 0, 0, 0)", - }, - "Offset": "0, 0, 0", - "Size": "998, 777", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "1, 1, 0", - "Size": "996, 776", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "996, 776", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "996, 40", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(240, 128, 128, 255)", - }, - "Offset": "0, 0, 0", - "Size": "996, 40", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "475, 10, 0", - "Size": "46, 19", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "46, 19", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "10, 50, 0", - "Size": "478, 368", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(144, 238, 144, 255)", - }, - "Offset": "0, 0, 0", - "Size": "478, 368", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "20, 60, 0", - "Size": "458, 72", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(253, 245, 230, 255)", - }, - "Offset": "0, 0, 0", - "Size": "458, 72", - "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", - }, - ], - }, - ], - }, - { - "Offset": "241, 86, 0", - "Size": "16, 19", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "16, 19", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "20, 152, 0", - "Size": "458, 72", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(253, 245, 230, 255)", - }, - "Offset": "0, 0, 0", - "Size": "458, 72", - "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", - }, - ], - }, - ], - }, - { - "Offset": "241, 178, 0", - "Size": "16, 19", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "16, 19", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "20, 244, 0", - "Size": "458, 72", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(253, 245, 230, 255)", - }, - "Offset": "0, 0, 0", - "Size": "458, 72", - "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", - }, - ], - }, - ], - }, - { - "Offset": "241, 270, 0", - "Size": "16, 19", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "16, 19", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "20, 336, 0", - "Size": "458, 72", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(253, 245, 230, 255)", - }, - "Offset": "0, 0, 0", - "Size": "458, 72", - "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", - }, - ], - }, - ], - }, - { - "Offset": "241, 362, 0", - "Size": "16, 19", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "16, 19", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "508, 50, 0", - "Size": "478, 368", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(144, 238, 144, 255)", - }, - "Offset": "0, 0, 0", - "Size": "478, 368", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "518, 60, 0", - "Size": "458, 72", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(253, 245, 230, 255)", - }, - "Offset": "0, 0, 0", - "Size": "458, 72", - "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", - }, - ], - }, - ], - }, - { - "Offset": "739, 86, 0", - "Size": "16, 19", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "16, 19", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "518, 152, 0", - "Size": "458, 72", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(253, 245, 230, 255)", - }, - "Offset": "0, 0, 0", - "Size": "458, 72", - "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", - }, - ], - }, - ], - }, - { - "Offset": "739, 178, 0", - "Size": "16, 19", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "16, 19", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "518, 244, 0", - "Size": "458, 72", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(253, 245, 230, 255)", - }, - "Offset": "0, 0, 0", - "Size": "458, 72", - "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", - }, - ], - }, - ], - }, - { - "Offset": "739, 270, 0", - "Size": "16, 19", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "16, 19", - "Visual Type": "SpriteVisual", - }, - ], - }, - { - "Offset": "518, 336, 0", - "Size": "458, 72", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(253, 245, 230, 255)", - }, - "Offset": "0, 0, 0", - "Size": "458, 72", - "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", - }, - ], - }, - ], - }, - { - "Offset": "739, 362, 0", - "Size": "16, 19", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "16, 19", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "-13, 0, 0", - "Size": "12, 0", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "-12, 3, 0", - "Opacity": 0, - "Size": "12, 341", - "Visual Type": "Visual", - }, - { - "Offset": "0, 4, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "0, -16, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "-5, 16, 0", - "Size": "6, 141", - "Visual Type": "Visual", - }, - ], - }, - { - "Offset": "0, -13, 0", - "Size": "0, 12", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "3, -12, 0", - "Opacity": 0, - "Size": "992, 12", - "Visual Type": "Visual", - }, - { - "Offset": "4, 0, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "-16, 0, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "16, -5, 0", - "Size": "966, 6", - "Visual Type": "Visual", - }, - ], - }, - ], - }, -} -`; - -exports[`FlatList Tests A FlatList has an onEndReached event 1`] = ` -{ - "Automation Tree": { - "AutomationId": "flat_list", - "ControlType": 50014, - "LocalizedControlType": "scroll bar", - "__Children": [ - { - "AutomationId": "Pizza", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Pizza", - "TextRangePattern.GetText": "Pizza", - }, - ], - }, - { - "AutomationId": "Burger", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Burger", - "TextRangePattern.GetText": "Burger", - }, - ], - }, - { - "AutomationId": "Risotto", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Risotto", - "TextRangePattern.GetText": "Risotto", - }, - ], - }, - { - "AutomationId": "French Fries", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "French Fries", - "TextRangePattern.GetText": "French Fries", - }, - ], - }, - { - "AutomationId": "Onion Rings", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Onion Rings", - "TextRangePattern.GetText": "Onion Rings", - }, - ], - }, - { - "AutomationId": "Fried Shrimps", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Fried Shrimps", - "TextRangePattern.GetText": "Fried Shrimps", - }, - ], - }, - { - "AutomationId": "Water", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Water", - "TextRangePattern.GetText": "Water", - }, - ], - }, - { - "AutomationId": "Coke", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Coke", - "TextRangePattern.GetText": "Coke", - }, - ], - }, - { - "AutomationId": "Beer", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Beer", - "TextRangePattern.GetText": "Beer", - }, - ], - }, - { - "AutomationId": "Cheesecake", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Cheesecake", - "TextRangePattern.GetText": "Cheesecake", - }, - ], - }, - { - "AutomationId": "Brownie", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Brownie", - "TextRangePattern.GetText": "Brownie", - }, - ], - }, - ], - }, - "Component Tree": { - "Type": "Microsoft.ReactNative.Composition.ScrollViewComponentView", - "_Props": { - "TestId": "flat_list", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Pizza", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Burger", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Risotto", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "French Fries", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Onion Rings", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Fried Shrimps", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Water", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Coke", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Beer", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Cheesecake", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Brownie", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - ], - }, - ], - }, - "Visual Tree": { - "Comment": "flat_list", - "Offset": "0, 0, 0", - "Size": "998, 534", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(0, 0, 0, 0)", - }, - "Offset": "0, 0, 0", - "Size": "998, 534", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(0, 0, 0, 0)", - }, - "Offset": "0, 0, 0", - "Size": "998, 946", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 946", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 946", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 8, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Pizza", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 94, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Burger", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 180, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Risotto", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 266, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "French Fries", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 352, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Onion Rings", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 438, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Fried Shrimps", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 524, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Water", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 610, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Coke", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 696, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Beer", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 782, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Cheesecake", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 868, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Brownie", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "-13, 0, 0", - "Size": "12, 0", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "-12, 3, 0", - "Opacity": 0, - "Size": "12, 528", - "Visual Type": "Visual", - }, - { - "Offset": "0, 4, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "0, -16, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "-5, 16, 0", - "Size": "6, 283", - "Visual Type": "Visual", - }, - ], - }, - { - "Offset": "0, -13, 0", - "Size": "0, 12", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "3, -12, 0", - "Opacity": 0, - "Size": "992, 12", - "Visual Type": "Visual", - }, - { - "Offset": "4, 0, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "-16, 0, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "16, -5, 0", - "Size": "966, 6", - "Visual Type": "Visual", - }, - ], - }, - ], - }, -} -`; - -exports[`FlatList Tests A FlatList has an onStartReached event 1`] = ` -{ - "Automation Tree": { - "AutomationId": "flat_list", - "ControlType": 50014, - "LocalizedControlType": "scroll bar", - "__Children": [ - { - "AutomationId": "Pizza", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Pizza", - "TextRangePattern.GetText": "Pizza", - }, - ], - }, - { - "AutomationId": "Burger", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Burger", - "TextRangePattern.GetText": "Burger", - }, - ], - }, - { - "AutomationId": "Risotto", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Risotto", - "TextRangePattern.GetText": "Risotto", - }, - ], - }, - { - "AutomationId": "French Fries", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "French Fries", - "TextRangePattern.GetText": "French Fries", - }, - ], - }, - { - "AutomationId": "Onion Rings", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Onion Rings", - "TextRangePattern.GetText": "Onion Rings", - }, - ], - }, - { - "AutomationId": "Fried Shrimps", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Fried Shrimps", - "TextRangePattern.GetText": "Fried Shrimps", - }, - ], - }, - { - "AutomationId": "Water", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Water", - "TextRangePattern.GetText": "Water", - }, - ], - }, - { - "AutomationId": "Coke", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Coke", - "TextRangePattern.GetText": "Coke", - }, - ], - }, - { - "AutomationId": "Beer", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Beer", - "TextRangePattern.GetText": "Beer", - }, - ], - }, - { - "AutomationId": "Cheesecake", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Cheesecake", - "TextRangePattern.GetText": "Cheesecake", - }, - ], - }, - { - "AutomationId": "Brownie", - "ControlType": 50026, - "IsKeyboardFocusable": true, - "LocalizedControlType": "group", - "__Children": [ - { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Brownie", - "TextRangePattern.GetText": "Brownie", - }, - ], - }, - ], - }, - "Component Tree": { - "Type": "Microsoft.ReactNative.Composition.ScrollViewComponentView", - "_Props": { - "TestId": "flat_list", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": {}, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Pizza", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Burger", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Risotto", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "French Fries", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Onion Rings", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Fried Shrimps", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Water", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Coke", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Beer", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Cheesecake", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - { - "Type": "Microsoft.ReactNative.Composition.ViewComponentView", - "_Props": { - "TestId": "Brownie", - }, - "__Children": [ - { - "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", - "_Props": {}, - }, - ], - }, - ], - }, - ], - }, - "Visual Tree": { - "Comment": "flat_list", - "Offset": "0, 0, 0", - "Size": "998, 534", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(0, 0, 0, 0)", - }, - "Offset": "0, 0, 0", - "Size": "998, 534", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(0, 0, 0, 0)", - }, - "Offset": "0, 0, 0", - "Size": "998, 946", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 946", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "998, 946", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 8, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Pizza", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 94, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Burger", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 180, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Risotto", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 266, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "French Fries", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 352, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Onion Rings", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 438, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Fried Shrimps", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 524, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Water", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 610, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Coke", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 696, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Beer", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 782, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Cheesecake", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "0, 868, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Brush": { - "Brush Type": "ColorBrush", - "Color": "rgba(255, 192, 203, 255)", - }, - "Comment": "Brownie", - "Offset": "0, 0, 0", - "Size": "998, 70", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "20, 19, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "0, 0, 0", - "Size": "958, 33", - "Visual Type": "SpriteVisual", - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, - { - "Offset": "-13, 0, 0", - "Size": "12, 0", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "-12, 3, 0", - "Opacity": 0, - "Size": "12, 528", - "Visual Type": "Visual", - }, - { - "Offset": "0, 4, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "0, -16, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "-5, 235, 0", - "Size": "6, 283", - "Visual Type": "Visual", - }, - ], - }, - { - "Offset": "0, -13, 0", - "Size": "0, 12", - "Visual Type": "SpriteVisual", - "__Children": [ - { - "Offset": "3, -12, 0", - "Opacity": 0, - "Size": "992, 12", - "Visual Type": "Visual", - }, - { - "Offset": "4, 0, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "-16, 0, 0", - "Opacity": 0, - "Size": "12, 12", - "Visual Type": "SpriteVisual", - }, - { - "Offset": "16, -5, 0", - "Size": "966, 6", - "Visual Type": "Visual", - }, - ], - }, - ], - }, -} -`; diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/ScrollViewComponentTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/ScrollViewComponentTest.test.ts.snap index f3bb0cfe118..efb33774859 100644 --- a/packages/e2e-test-app-fabric/test/__snapshots__/ScrollViewComponentTest.test.ts.snap +++ b/packages/e2e-test-app-fabric/test/__snapshots__/ScrollViewComponentTest.test.ts.snap @@ -224,6 +224,653 @@ exports[`ScrollView Tests ScrollView has scrollTo method, scroll to top button 1 } `; +exports[`ScrollView Tests ScrollViews can scroll an item list horizontally 1`] = ` +{ + "Automation Tree": { + "AutomationId": "scroll_horizontal", + "ControlType": 50033, + "LocalizedControlType": "pane", + "ScrollPattern.HorizontallyScrollable": true, + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Item 0", + "TextRangePattern.GetText": "Item 0", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Item 1", + "TextRangePattern.GetText": "Item 1", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Item 2", + "TextRangePattern.GetText": "Item 2", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Item 3", + "TextRangePattern.GetText": "Item 3", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Item 4", + "TextRangePattern.GetText": "Item 4", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Item 5", + "TextRangePattern.GetText": "Item 5", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Item 6", + "TextRangePattern.GetText": "Item 6", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Item 7", + "TextRangePattern.GetText": "Item 7", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Item 8", + "TextRangePattern.GetText": "Item 8", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Item 9", + "TextRangePattern.GetText": "Item 9", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Item 10", + "TextRangePattern.GetText": "Item 10", + }, + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Item 11", + "TextRangePattern.GetText": "Item 11", + }, + ], + }, + "Component Tree": { + "Type": "Microsoft.ReactNative.Composition.ScrollViewComponentView", + "_Props": { + "TestId": "scroll_horizontal", + }, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + "__Children": [ + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ViewComponentView", + "_Props": {}, + }, + { + "Type": "Microsoft.ReactNative.Composition.ParagraphComponentView", + "_Props": {}, + }, + ], + }, + ], + }, + "Visual Tree": { + "Comment": "scroll_horizontal", + "Offset": "0, 0, 0", + "Size": "916, 106", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(238, 238, 238, 255)", + }, + "Offset": "0, 0, 0", + "Size": "916, 106", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(0, 0, 0, 0)", + }, + "Offset": "0, 0, 0", + "Size": "1272, 106", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "1272, 106", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "1272, 106", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "5, 5, 0", + "Size": "96, 96", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(204, 204, 204, 255)", + }, + "Offset": "0, 0, 0", + "Size": "96, 96", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "10, 10, 0", + "Size": "86, 20", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "86, 20", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "111, 5, 0", + "Size": "96, 96", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(204, 204, 204, 255)", + }, + "Offset": "0, 0, 0", + "Size": "96, 96", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "116, 10, 0", + "Size": "86, 20", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "86, 20", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "217, 5, 0", + "Size": "96, 96", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(204, 204, 204, 255)", + }, + "Offset": "0, 0, 0", + "Size": "96, 96", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "222, 10, 0", + "Size": "86, 20", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "86, 20", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "323, 5, 0", + "Size": "96, 96", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(204, 204, 204, 255)", + }, + "Offset": "0, 0, 0", + "Size": "96, 96", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "328, 10, 0", + "Size": "86, 20", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "86, 20", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "429, 5, 0", + "Size": "96, 96", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(204, 204, 204, 255)", + }, + "Offset": "0, 0, 0", + "Size": "96, 96", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "434, 10, 0", + "Size": "86, 20", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "86, 20", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "535, 5, 0", + "Size": "96, 96", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(204, 204, 204, 255)", + }, + "Offset": "0, 0, 0", + "Size": "96, 96", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "540, 10, 0", + "Size": "86, 20", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "86, 20", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "641, 5, 0", + "Size": "96, 96", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(204, 204, 204, 255)", + }, + "Offset": "0, 0, 0", + "Size": "96, 96", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "646, 10, 0", + "Size": "86, 20", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "86, 20", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "747, 5, 0", + "Size": "96, 96", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(204, 204, 204, 255)", + }, + "Offset": "0, 0, 0", + "Size": "96, 96", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "752, 10, 0", + "Size": "86, 20", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "86, 20", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "853, 5, 0", + "Size": "96, 96", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(204, 204, 204, 255)", + }, + "Offset": "0, 0, 0", + "Size": "96, 96", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "858, 10, 0", + "Size": "86, 20", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "86, 20", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "959, 5, 0", + "Size": "96, 96", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(204, 204, 204, 255)", + }, + "Offset": "0, 0, 0", + "Size": "96, 96", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "964, 10, 0", + "Size": "86, 20", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "86, 20", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "1065, 5, 0", + "Size": "96, 96", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(204, 204, 204, 255)", + }, + "Offset": "0, 0, 0", + "Size": "96, 96", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "1070, 10, 0", + "Size": "86, 20", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "86, 20", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "1171, 5, 0", + "Size": "96, 96", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Brush": { + "Brush Type": "ColorBrush", + "Color": "rgba(204, 204, 204, 255)", + }, + "Offset": "0, 0, 0", + "Size": "96, 96", + "Visual Type": "SpriteVisual", + }, + ], + }, + { + "Offset": "1176, 10, 0", + "Size": "86, 20", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "0, 0, 0", + "Size": "86, 20", + "Visual Type": "SpriteVisual", + }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + { + "Offset": "-13, 0, 0", + "Size": "12, 0", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "-12, 3, 0", + "Opacity": 0, + "Size": "12, 100", + "Visual Type": "Visual", + }, + { + "Offset": "0, 4, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "0, -16, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-5, 16, 0", + "Size": "6, 74", + "Visual Type": "Visual", + }, + ], + }, + { + "Offset": "0, -13, 0", + "Size": "0, 12", + "Visual Type": "SpriteVisual", + "__Children": [ + { + "Offset": "3, -12, 0", + "Opacity": 0, + "Size": "910, 12", + "Visual Type": "Visual", + }, + { + "Offset": "4, 0, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "-16, 0, 0", + "Opacity": 0, + "Size": "12, 12", + "Visual Type": "SpriteVisual", + }, + { + "Offset": "16, -5, 0", + "Size": "637, 6", + "Visual Type": "Visual", + }, + ], + }, + ], + }, +} +`; + exports[`ScrollView Tests ScrollViews has flash scroll indicators 1`] = ` { "Automation Tree": { 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 033558a7715..974b44236ba 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 @@ -466,6 +466,16 @@ void DumpUIAPatternInfo(IUIAutomationElement *pTarget, const winrt::Windows::Dat } } + // Dump IScrollProvider Information + winrt::com_ptr scrollPattern; + hr = pTarget->GetCurrentPattern(UIA_ScrollPatternId, reinterpret_cast(scrollPattern.put())); + if (SUCCEEDED(hr) && scrollPattern) { + hr = scrollPattern->get_HorizontallyScrollable(&horizontallyScrollable); + if (SUCCEEDED(hr)) { + InsertBooleanValueIfNotDefault(result, L"ScrollPattern.HorizontallyScrollable", horizontallyScrollable, false); + } + } + ::SysFreeString(text); ::SysFreeString(value); } diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp index 6acbb639192..384170cb797 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp @@ -1,8 +1,17 @@ #include "pch.h" #include "CompositionDynamicAutomationProvider.h" #include +<<<<<<< HEAD #include #include +======= +<<<<<<< HEAD +======= +#include +#include +#include +>>>>>>> 70823b2f70 ([Fabric] Add Support for ScrollProvider (#14411)) +>>>>>>> 0a726428ac ([Fabric] Add Support for ScrollProvider (#14411)) #include #include #include @@ -213,6 +222,12 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPatternProvider(PATTE AddRef(); } + if (patternId == UIA_ScrollPatternId && + strongView.try_as()) { + *pRetVal = static_cast(this); + AddRef(); + } + if (patternId == UIA_ValuePatternId && ((strongView .try_as() && @@ -323,6 +338,8 @@ long GetControlTypeFromString(const std::string &role) noexcept { return UIA_TreeControlTypeId; } else if (role == "treeitem") { return UIA_TreeItemControlTypeId; + } else if (role == "pane") { + return UIA_PaneControlTypeId; } assert(false); return UIA_GroupControlTypeId; @@ -588,6 +605,156 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::ScrollIntoView() { return S_OK; } +HRESULT __stdcall CompositionDynamicAutomationProvider::get_HorizontalScrollPercent(double *pRetVal) { + BOOL horizontallyScrollable; + auto hr = get_HorizontallyScrollable(&horizontallyScrollable); + if (!SUCCEEDED(hr)) { + return hr; + } + if (!horizontallyScrollable) { + *pRetVal = UIA_ScrollPatternNoScroll; + } else { + auto strongView = m_view.view(); + auto scrollComponentView = + strongView.try_as(); + *pRetVal = scrollComponentView->getScrollPositionX(); + } + return S_OK; +} + +HRESULT __stdcall CompositionDynamicAutomationProvider::get_VerticalScrollPercent(double *pRetVal) { + BOOL verticallyScrollable; + auto hr = get_VerticallyScrollable(&verticallyScrollable); + if (!SUCCEEDED(hr)) { + return hr; + } + if (!verticallyScrollable) { + *pRetVal = UIA_ScrollPatternNoScroll; + } else { + auto strongView = m_view.view(); + auto scrollComponentView = + strongView.try_as(); + *pRetVal = scrollComponentView->getScrollPositionY(); + } + return S_OK; +} + +HRESULT __stdcall CompositionDynamicAutomationProvider::get_HorizontalViewSize(double *pRetVal) { + BOOL horizontallyScrollable; + auto hr = get_HorizontallyScrollable(&horizontallyScrollable); + if (!SUCCEEDED(hr)) { + return hr; + } + if (!horizontallyScrollable) { + *pRetVal = 100; + } else { + auto strongView = m_view.view(); + auto scrollComponentView = + strongView.try_as(); + *pRetVal = scrollComponentView->getHorizontalSize(); + } + return S_OK; +} + +HRESULT __stdcall CompositionDynamicAutomationProvider::get_VerticalViewSize(double *pRetVal) { + BOOL verticallyScrollable; + auto hr = get_VerticallyScrollable(&verticallyScrollable); + if (!SUCCEEDED(hr)) { + return hr; + } + if (!verticallyScrollable) { + *pRetVal = 100; + } else { + auto strongView = m_view.view(); + auto scrollComponentView = + strongView.try_as(); + *pRetVal = scrollComponentView->getVerticalSize(); + } + return S_OK; +} + +HRESULT __stdcall CompositionDynamicAutomationProvider::get_HorizontallyScrollable(BOOL *pRetVal) { + if (pRetVal == nullptr) + return E_POINTER; + auto strongView = m_view.view(); + + if (!strongView) + return UIA_E_ELEMENTNOTAVAILABLE; + + auto props = std::static_pointer_cast( + winrt::get_self(strongView)->props()); + if (props == nullptr) + return UIA_E_ELEMENTNOTAVAILABLE; + *pRetVal = (props->horizontal && props->scrollEnabled); + return S_OK; +} + +HRESULT __stdcall CompositionDynamicAutomationProvider::get_VerticallyScrollable(BOOL *pRetVal) { + if (pRetVal == nullptr) + return E_POINTER; + auto strongView = m_view.view(); + + if (!strongView) + return UIA_E_ELEMENTNOTAVAILABLE; + + auto props = std::static_pointer_cast( + winrt::get_self(strongView)->props()); + if (props == nullptr) + return UIA_E_ELEMENTNOTAVAILABLE; + *pRetVal = (!props->horizontal && props->scrollEnabled); + return S_OK; +} + +HRESULT __stdcall CompositionDynamicAutomationProvider::Scroll( + ScrollAmount horizontalAmount, + ScrollAmount verticalAmount) { + DispatchAccessibilityAction(m_view, "scroll"); + auto strongView = m_view.view(); + auto scrollComponentView = + strongView.try_as(); + BOOL verticallyScrollable; + BOOL horizontallyScrollable; + float vertical = 0.0f; + float horizontal = 0.0f; + auto hr = get_VerticallyScrollable(&verticallyScrollable); + if (!SUCCEEDED(hr)) { + return hr; + } + if (verticallyScrollable) { + if (verticalAmount == ScrollAmount_LargeIncrement) { + scrollComponentView->pageDown(true); + } else if (verticalAmount == ScrollAmount_LargeDecrement) { + scrollComponentView->pageUp(true); + } else if (verticalAmount == ScrollAmount_SmallIncrement) { + scrollComponentView->lineDown(true); + } else if (verticalAmount == ScrollAmount_SmallDecrement) { + scrollComponentView->lineUp(true); + } + } + hr = get_HorizontallyScrollable(&horizontallyScrollable); + if (!SUCCEEDED(hr)) { + return hr; + } + if (horizontallyScrollable) { + if (horizontalAmount == ScrollAmount_LargeIncrement) { + scrollComponentView->pageDown(true); + } else if (horizontalAmount == ScrollAmount_LargeDecrement) { + scrollComponentView->pageUp(true); + } else if (horizontalAmount == ScrollAmount_SmallIncrement) { + scrollComponentView->lineRight(true); + } else if (horizontalAmount == ScrollAmount_SmallDecrement) { + scrollComponentView->lineLeft(true); + } + } + return S_OK; +} + +HRESULT __stdcall CompositionDynamicAutomationProvider::SetScrollPercent( + double horiztonalPercent, + double verticalPercent) { + return S_OK; +} + BSTR StringToBSTR(const std::string &str) { // Calculate the required BSTR size in bytes int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0); diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h index f6f09f98d61..535448f854e 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h @@ -15,6 +15,7 @@ class CompositionDynamicAutomationProvider : public winrt::implements< IRawElementProviderSimple, IInvokeProvider, IScrollItemProvider, + IScrollProvider, IValueProvider, IRangeValueProvider, IToggleProvider, @@ -46,6 +47,16 @@ class CompositionDynamicAutomationProvider : public winrt::implements< // inherited via IScrollItemProvider HRESULT __stdcall ScrollIntoView() override; + // inherited via IScrollProvider + HRESULT __stdcall get_HorizontalScrollPercent(double *pRetVal) override; + HRESULT __stdcall get_VerticalScrollPercent(double *pRetVal) override; + HRESULT __stdcall get_HorizontalViewSize(double *pRetVal) override; + HRESULT __stdcall get_VerticalViewSize(double *pRetVal) override; + HRESULT __stdcall get_HorizontallyScrollable(BOOL *pRetVal) override; + HRESULT __stdcall get_VerticallyScrollable(BOOL *pRetVal) override; + HRESULT __stdcall Scroll(ScrollAmount horizontalAmount, ScrollAmount verticalAmount) override; + HRESULT __stdcall SetScrollPercent(double horiztonalPercent, double verticalPercent) override; + // inherited via IValueProvider virtual HRESULT __stdcall SetValue(LPCWSTR val) override; virtual HRESULT __stdcall get_Value(BSTR *pRetVal) override; diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp index 2643827a3cc..12e2ae3d84c 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp @@ -976,10 +976,16 @@ bool ScrollViewComponentView::scrollToStart(bool animate) noexcept { } bool ScrollViewComponentView::pageUp(bool animate) noexcept { + if (std::static_pointer_cast(viewProps())->horizontal) { + return scrollLeft(m_layoutMetrics.frame.size.height * m_layoutMetrics.pointScaleFactor, animate); + } return scrollUp(m_layoutMetrics.frame.size.height * m_layoutMetrics.pointScaleFactor, animate); } bool ScrollViewComponentView::pageDown(bool animate) noexcept { + if (std::static_pointer_cast(viewProps())->horizontal) { + return scrollRight(m_layoutMetrics.frame.size.height * m_layoutMetrics.pointScaleFactor, animate); + } return scrollDown(m_layoutMetrics.frame.size.height * m_layoutMetrics.pointScaleFactor, animate); } @@ -1036,7 +1042,7 @@ bool ScrollViewComponentView::scrollLeft(float delta, bool animate) noexcept { return false; } - m_scrollVisual.ScrollBy({delta, 0, 0}, animate); + m_scrollVisual.ScrollBy({-delta, 0, 0}, animate); return true; } @@ -1259,7 +1265,7 @@ facebook::react::Point ScrollViewComponentView::getClientOffset() const noexcept } std::string ScrollViewComponentView::DefaultControlType() const noexcept { - return "scrollbar"; + return "pane"; } winrt::com_ptr ScrollViewComponentView::focusVisualRoot( @@ -1272,4 +1278,20 @@ ScrollViewComponentView::visualToHostFocus() noexcept { return m_scrollVisual; } +int ScrollViewComponentView::getScrollPositionX() noexcept { + return int((m_scrollVisual.ScrollPosition().x / m_horizontalScrollbarComponent->getScrollRange()) * 100); +} + +int ScrollViewComponentView::getScrollPositionY() noexcept { + return int((m_scrollVisual.ScrollPosition().y / m_verticalScrollbarComponent->getScrollRange()) * 100); +} + +double ScrollViewComponentView::getVerticalSize() noexcept { + return std::min((m_layoutMetrics.frame.size.height / m_contentSize.height * 100.0), 100.0); +} + +double ScrollViewComponentView::getHorizontalSize() noexcept { + return std::min((m_layoutMetrics.frame.size.width / m_contentSize.width * 100.0), 100.0); +} + } // namespace winrt::Microsoft::ReactNative::Composition::implementation diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h index ebabbffeec9..c82e6ae5f0b 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h @@ -113,6 +113,11 @@ struct ScrollInteractionTrackerOwner : public winrt::implements< winrt::Microsoft::ReactNative::Composition::Experimental::IVisual visualToHostFocus() noexcept override; winrt::com_ptr focusVisualRoot(const facebook::react::Rect &focusRect) noexcept override; + int getScrollPositionX() noexcept; + int getScrollPositionY() noexcept; + double getVerticalSize() noexcept; + double getHorizontalSize() noexcept; + private: void updateContentVisualSize() noexcept; bool scrollToEnd(bool animate) noexcept; diff --git a/vnext/overrides.json b/vnext/overrides.json index ec6e6b74a04..988c2ae659d 100644 --- a/vnext/overrides.json +++ b/vnext/overrides.json @@ -328,6 +328,12 @@ "baseFile": "packages/react-native/Libraries/Components/RefreshControl/RefreshControl.js", "baseHash": "d86c2a4b2ff6ae7947a4117d8ad81c8e58a9bb51" }, + { + "type": "derived", + "file": "src-win/Libraries/Components/ScrollView/ScrollView.windows.js", + "baseFile": "packages/react-native/Libraries/Components/ScrollView/ScrollView.js", + "baseHash": "eb392989a1ca57ffd2c583eab45c939c510936fd" + }, { "type": "derived", "file": "src-win/Libraries/Components/ScrollView/ScrollViewNativeComponent.windows.js", diff --git a/vnext/src-win/Libraries/Components/ScrollView/ScrollView.windows.js b/vnext/src-win/Libraries/Components/ScrollView/ScrollView.windows.js new file mode 100644 index 00000000000..01b77c79b19 --- /dev/null +++ b/vnext/src-win/Libraries/Components/ScrollView/ScrollView.windows.js @@ -0,0 +1,1920 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow strict-local + */ + +import type {HostInstance} from '../../Renderer/shims/ReactNativeTypes'; +import type {EdgeInsetsProp} from '../../StyleSheet/EdgeInsetsPropType'; +import type {PointProp} from '../../StyleSheet/PointPropType'; +import type {ViewStyleProp} from '../../StyleSheet/StyleSheet'; +import type {ColorValue} from '../../StyleSheet/StyleSheet'; +import type { + LayoutEvent, + PressEvent, + ScrollEvent, +} from '../../Types/CoreEventTypes'; +import type {EventSubscription} from '../../vendor/emitter/EventEmitter'; +import type {KeyboardEvent, KeyboardMetrics} from '../Keyboard/Keyboard'; +import typeof View from '../View/View'; +import type {ViewProps} from '../View/ViewPropTypes'; +import type {Props as ScrollViewStickyHeaderProps} from './ScrollViewStickyHeader'; + +import { + HScrollContentViewNativeComponent, + HScrollViewNativeComponent, +} from '../../../src/private/components/HScrollViewNativeComponents'; +import { + VScrollContentViewNativeComponent, + VScrollViewNativeComponent, +} from '../../../src/private/components/VScrollViewNativeComponents'; +import AnimatedImplementation from '../../Animated/AnimatedImplementation'; +import FrameRateLogger from '../../Interaction/FrameRateLogger'; +import {findNodeHandle} from '../../ReactNative/RendererProxy'; +import UIManager from '../../ReactNative/UIManager'; +import flattenStyle from '../../StyleSheet/flattenStyle'; +import splitLayoutProps from '../../StyleSheet/splitLayoutProps'; +import StyleSheet from '../../StyleSheet/StyleSheet'; +import Dimensions from '../../Utilities/Dimensions'; +import dismissKeyboard from '../../Utilities/dismissKeyboard'; +import Platform from '../../Utilities/Platform'; +import Keyboard from '../Keyboard/Keyboard'; +import TextInputState from '../TextInput/TextInputState'; +import processDecelerationRate from './processDecelerationRate'; +import Commands from './ScrollViewCommands'; +import ScrollViewContext, {HORIZONTAL, VERTICAL} from './ScrollViewContext'; +import ScrollViewStickyHeader from './ScrollViewStickyHeader'; +import invariant from 'invariant'; +import memoize from 'memoize-one'; +import nullthrows from 'nullthrows'; +import * as React from 'react'; + +/* + * iOS scroll event timing nuances: + * =============================== + * + * + * Scrolling without bouncing, if you touch down: + * ------------------------------- + * + * 1. `onMomentumScrollBegin` (when animation begins after letting up) + * ... physical touch starts ... + * 2. `onTouchStartCapture` (when you press down to stop the scroll) + * 3. `onTouchStart` (same, but bubble phase) + * 4. `onResponderRelease` (when lifting up - you could pause forever before * lifting) + * 5. `onMomentumScrollEnd` + * + * + * Scrolling with bouncing, if you touch down: + * ------------------------------- + * + * 1. `onMomentumScrollBegin` (when animation begins after letting up) + * ... bounce begins ... + * ... some time elapses ... + * ... physical touch during bounce ... + * 2. `onMomentumScrollEnd` (Makes no sense why this occurs first during bounce) + * 3. `onTouchStartCapture` (immediately after `onMomentumScrollEnd`) + * 4. `onTouchStart` (same, but bubble phase) + * 5. `onTouchEnd` (You could hold the touch start for a long time) + * 6. `onMomentumScrollBegin` (When releasing the view starts bouncing back) + * + * So when we receive an `onTouchStart`, how can we tell if we are touching + * *during* an animation (which then causes the animation to stop)? The only way + * to tell is if the `touchStart` occurred immediately after the + * `onMomentumScrollEnd`. + * + * This is abstracted out for you, so you can just call this.scrollResponderIsAnimating() if + * necessary + * + * `ScrollView` also includes logic for blurring a currently focused input + * if one is focused while scrolling. This is a natural place + * to put this logic since it can support not dismissing the keyboard while + * scrolling, unless a recognized "tap"-like gesture has occurred. + * + * The public lifecycle API includes events for keyboard interaction, responder + * interaction, and scrolling (among others). The keyboard callbacks + * `onKeyboardWill/Did/*` are *global* events, but are invoked on scroll + * responder's props so that you can guarantee that the scroll responder's + * internal state has been updated accordingly (and deterministically) by + * the time the props callbacks are invoke. Otherwise, you would always wonder + * if the scroll responder is currently in a state where it recognizes new + * keyboard positions etc. If coordinating scrolling with keyboard movement, + * *always* use these hooks instead of listening to your own global keyboard + * events. + * + * Public keyboard lifecycle API: (props callbacks) + * + * Standard Keyboard Appearance Sequence: + * + * this.props.onKeyboardWillShow + * this.props.onKeyboardDidShow + * + * `onScrollResponderKeyboardDismissed` will be invoked if an appropriate + * tap inside the scroll responder's scrollable region was responsible + * for the dismissal of the keyboard. There are other reasons why the + * keyboard could be dismissed. + * + * this.props.onScrollResponderKeyboardDismissed + * + * Standard Keyboard Hide Sequence: + * + * this.props.onKeyboardWillHide + * this.props.onKeyboardDidHide + */ + +// Public methods for ScrollView +export type ScrollViewImperativeMethods = $ReadOnly<{| + getScrollResponder: $PropertyType, + getScrollableNode: $PropertyType, + getInnerViewNode: $PropertyType, + getInnerViewRef: $PropertyType, + getNativeScrollRef: $PropertyType, + scrollTo: $PropertyType, + scrollToEnd: $PropertyType, + flashScrollIndicators: $PropertyType, + scrollResponderZoomTo: $PropertyType, + scrollResponderScrollNativeHandleToKeyboard: $PropertyType< + ScrollView, + 'scrollResponderScrollNativeHandleToKeyboard', + >, +|}>; + +export type DecelerationRateType = 'fast' | 'normal' | number; +export type ScrollResponderType = ScrollViewImperativeMethods; + +type PublicScrollViewInstance = $ReadOnly<{| + ...HostInstance, + ...ScrollViewImperativeMethods, +|}>; + +type InnerViewInstance = React.ElementRef; + +type IOSProps = $ReadOnly<{| + /** + * Controls whether iOS should automatically adjust the content inset + * for scroll views that are placed behind a navigation bar or + * tab bar/ toolbar. The default value is true. + * @platform ios + */ + automaticallyAdjustContentInsets?: ?boolean, + /** + * Controls whether the ScrollView should automatically adjust its `contentInset` + * and `scrollViewInsets` when the Keyboard changes its size. The default value is false. + * @platform ios + */ + automaticallyAdjustKeyboardInsets?: ?boolean, + /** + * Controls whether iOS should automatically adjust the scroll indicator + * insets. The default value is true. Available on iOS 13 and later. + * @platform ios + */ + automaticallyAdjustsScrollIndicatorInsets?: ?boolean, + /** + * The amount by which the scroll view content is inset from the edges + * of the scroll view. Defaults to `{top: 0, left: 0, bottom: 0, right: 0}`. + * @platform ios + */ + contentInset?: ?EdgeInsetsProp, + /** + * When true, the scroll view bounces when it reaches the end of the + * content if the content is larger then the scroll view along the axis of + * the scroll direction. When false, it disables all bouncing even if + * the `alwaysBounce*` props are true. The default value is true. + * @platform ios + */ + bounces?: ?boolean, + /** + * By default, ScrollView has an active pan responder that hijacks panresponders + * deeper in the render tree in order to prevent accidental touches while scrolling. + * However, in certain occasions (such as when using snapToInterval) in a vertical scrollview + * You may want to disable this behavior in order to prevent the ScrollView from blocking touches + */ + disableScrollViewPanResponder?: ?boolean, + /** + * When true, gestures can drive zoom past min/max and the zoom will animate + * to the min/max value at gesture end, otherwise the zoom will not exceed + * the limits. + * @platform ios + */ + bouncesZoom?: ?boolean, + /** + * When true, the scroll view bounces horizontally when it reaches the end + * even if the content is smaller than the scroll view itself. The default + * value is true when `horizontal={true}` and false otherwise. + * @platform ios + */ + alwaysBounceHorizontal?: ?boolean, + /** + * When true, the scroll view bounces vertically when it reaches the end + * even if the content is smaller than the scroll view itself. The default + * value is false when `horizontal={true}` and true otherwise. + * @platform ios + */ + alwaysBounceVertical?: ?boolean, + /** + * When true, the scroll view automatically centers the content when the + * content is smaller than the scroll view bounds; when the content is + * larger than the scroll view, this property has no effect. The default + * value is false. + * @platform ios + */ + centerContent?: ?boolean, + /** + * The style of the scroll indicators. + * + * - `'default'` (the default), same as `black`. + * - `'black'`, scroll indicator is black. This style is good against a light background. + * - `'white'`, scroll indicator is white. This style is good against a dark background. + * + * @platform ios + */ + indicatorStyle?: ?('default' | 'black' | 'white'), + /** + * When true, the ScrollView will try to lock to only vertical or horizontal + * scrolling while dragging. The default value is false. + * @platform ios + */ + directionalLockEnabled?: ?boolean, + /** + * When false, once tracking starts, won't try to drag if the touch moves. + * The default value is true. + * @platform ios + */ + canCancelContentTouches?: ?boolean, + /** + * The maximum allowed zoom scale. The default value is 1.0. + * @platform ios + */ + maximumZoomScale?: ?number, + /** + * The minimum allowed zoom scale. The default value is 1.0. + * @platform ios + */ + minimumZoomScale?: ?number, + /** + * When true, ScrollView allows use of pinch gestures to zoom in and out. + * The default value is true. + * @platform ios + */ + pinchGestureEnabled?: ?boolean, + /** + * The amount by which the scroll view indicators are inset from the edges + * of the scroll view. This should normally be set to the same value as + * the `contentInset`. Defaults to `{0, 0, 0, 0}`. + * @platform ios + */ + scrollIndicatorInsets?: ?EdgeInsetsProp, + /** + * When true, the scroll view can be programmatically scrolled beyond its + * content size. The default value is false. + * @platform ios + */ + scrollToOverflowEnabled?: ?boolean, + /** + * When true, the scroll view scrolls to top when the status bar is tapped. + * The default value is true. + * @platform ios + */ + scrollsToTop?: ?boolean, + /** + * Fires when the scroll view scrolls to top after the status bar has been tapped + * @platform ios + */ + onScrollToTop?: (event: ScrollEvent) => void, + /** + * When true, shows a horizontal scroll indicator. + * The default value is true. + */ + showsHorizontalScrollIndicator?: ?boolean, + /** + * The current scale of the scroll view content. The default value is 1.0. + * @platform ios + */ + zoomScale?: ?number, + /** + * This property specifies how the safe area insets are used to modify the + * content area of the scroll view. The default value of this property is + * "never". Available on iOS 11 and later. + * @platform ios + */ + contentInsetAdjustmentBehavior?: ?( + | 'automatic' + | 'scrollableAxes' + | 'never' + | 'always' + ), +|}>; + +type AndroidProps = $ReadOnly<{| + /** + * Enables nested scrolling for Android API level 21+. + * Nested scrolling is supported by default on iOS + * @platform android + */ + nestedScrollEnabled?: ?boolean, + /** + * Sometimes a scrollview takes up more space than its content fills. When this is + * the case, this prop will fill the rest of the scrollview with a color to avoid setting + * a background and creating unnecessary overdraw. This is an advanced optimization + * that is not needed in the general case. + * @platform android + */ + endFillColor?: ?ColorValue, + /** + * Tag used to log scroll performance on this scroll view. Will force + * momentum events to be turned on (see sendMomentumEvents). This doesn't do + * anything out of the box and you need to implement a custom native + * FpsListener for it to be useful. + * @platform android + */ + scrollPerfTag?: ?string, + /** + * Used to override default value of overScroll mode. + * + * Possible values: + * + * - `'auto'` - Default value, allow a user to over-scroll + * this view only if the content is large enough to meaningfully scroll. + * - `'always'` - Always allow a user to over-scroll this view. + * - `'never'` - Never allow a user to over-scroll this view. + * + * @platform android + */ + overScrollMode?: ?('auto' | 'always' | 'never'), + /** + * Causes the scrollbars not to turn transparent when they are not in use. + * The default value is false. + * + * @platform android + */ + persistentScrollbar?: ?boolean, + /** + * Fades out the edges of the scroll content. + * + * If the value is greater than 0, the fading edges will be set accordingly + * to the current scroll direction and position, + * indicating if there is more content to show. + * + * The default value is 0. + * + * @platform android + */ + fadingEdgeLength?: ?number, +|}>; + +type StickyHeaderComponentType = component( + ref?: React.RefSetter<$ReadOnly void}>>, + ...ScrollViewStickyHeaderProps +); + +export type Props = $ReadOnly<{| + ...ViewProps, + ...IOSProps, + ...AndroidProps, + + /** + * These styles will be applied to the scroll view content container which + * wraps all of the child views. Example: + * + * ``` + * return ( + * + * + * ); + * ... + * const styles = StyleSheet.create({ + * contentContainer: { + * paddingVertical: 20 + * } + * }); + * ``` + */ + contentContainerStyle?: ?ViewStyleProp, + /** + * Used to manually set the starting scroll offset. + * The default value is `{x: 0, y: 0}`. + */ + contentOffset?: ?PointProp, + /** + * When true, the scroll view stops on the next index (in relation to scroll + * position at release) regardless of how fast the gesture is. This can be + * used for pagination when the page is less than the width of the + * horizontal ScrollView or the height of the vertical ScrollView. The default value is false. + */ + disableIntervalMomentum?: ?boolean, + /** + * A floating-point number that determines how quickly the scroll view + * decelerates after the user lifts their finger. You may also use string + * shortcuts `"normal"` and `"fast"` which match the underlying iOS settings + * for `UIScrollViewDecelerationRateNormal` and + * `UIScrollViewDecelerationRateFast` respectively. + * + * - `'normal'`: 0.998 on iOS, 0.985 on Android (the default) + * - `'fast'`: 0.99 on iOS, 0.9 on Android + */ + decelerationRate?: ?DecelerationRateType, + + /** + * *Experimental, iOS Only*. The API is experimental and will change in future releases. + * + * Controls how much distance is travelled after user stops scrolling. + * Value greater than 1 will increase the distance travelled. + * Value less than 1 will decrease the distance travelled. + * + * @deprecated + * + * The default value is 1. + */ + experimental_endDraggingSensitivityMultiplier?: ?number, + + /** + * When true, the scroll view's children are arranged horizontally in a row + * instead of vertically in a column. The default value is false. + */ + horizontal?: ?boolean, + /** + * If sticky headers should stick at the bottom instead of the top of the + * ScrollView. This is usually used with inverted ScrollViews. + */ + invertStickyHeaders?: ?boolean, + /** + * Determines whether the keyboard gets dismissed in response to a drag. + * + * *Cross platform* + * + * - `'none'` (the default), drags do not dismiss the keyboard. + * - `'on-drag'`, the keyboard is dismissed when a drag begins. + * + * *iOS Only* + * + * - `'interactive'`, the keyboard is dismissed interactively with the drag and moves in + * synchrony with the touch; dragging upwards cancels the dismissal. + * On android this is not supported and it will have the same behavior as 'none'. + */ + keyboardDismissMode?: ?// default + // cross-platform + ('none' | 'on-drag' | 'interactive'), // ios only + /** + * Determines when the keyboard should stay visible after a tap. + * + * - `'never'` (the default), tapping outside of the focused text input when the keyboard + * is up dismisses the keyboard. When this happens, children won't receive the tap. + * - `'always'`, the keyboard will not dismiss automatically, and the scroll view will not + * catch taps, but children of the scroll view can catch taps. + * - `'handled'`, the keyboard will not dismiss automatically when the tap was handled by + * a children, (or captured by an ancestor). + * - `false`, deprecated, use 'never' instead + * - `true`, deprecated, use 'always' instead + */ + keyboardShouldPersistTaps?: ?('always' | 'never' | 'handled' | true | false), + /** + * When set, the scroll view will adjust the scroll position so that the first child that is + * partially or fully visible and at or beyond `minIndexForVisible` will not change position. + * This is useful for lists that are loading content in both directions, e.g. a chat thread, + * where new messages coming in might otherwise cause the scroll position to jump. A value of 0 + * is common, but other values such as 1 can be used to skip loading spinners or other content + * that should not maintain position. + * + * The optional `autoscrollToTopThreshold` can be used to make the content automatically scroll + * to the top after making the adjustment if the user was within the threshold of the top before + * the adjustment was made. This is also useful for chat-like applications where you want to see + * new messages scroll into place, but not if the user has scrolled up a ways and it would be + * disruptive to scroll a bunch. + * + * Caveat 1: Reordering elements in the scrollview with this enabled will probably cause + * jumpiness and jank. It can be fixed, but there are currently no plans to do so. For now, + * don't re-order the content of any ScrollViews or Lists that use this feature. + * + * Caveat 2: This simply uses `contentOffset` and `frame.origin` in native code to compute + * visibility. Occlusion, transforms, and other complexity won't be taken into account as to + * whether content is "visible" or not. + * + */ + maintainVisibleContentPosition?: ?$ReadOnly<{| + minIndexForVisible: number, + autoscrollToTopThreshold?: ?number, + |}>, + /** + * Called when the momentum scroll starts (scroll which occurs as the ScrollView glides to a stop). + */ + onMomentumScrollBegin?: ?(event: ScrollEvent) => void, + /** + * Called when the momentum scroll ends (scroll which occurs as the ScrollView glides to a stop). + */ + onMomentumScrollEnd?: ?(event: ScrollEvent) => void, + + /** + * Fires at most once per frame during scrolling. + */ + onScroll?: ?(event: ScrollEvent) => void, + /** + * Called when the user begins to drag the scroll view. + */ + onScrollBeginDrag?: ?(event: ScrollEvent) => void, + /** + * Called when the user stops dragging the scroll view and it either stops + * or begins to glide. + */ + onScrollEndDrag?: ?(event: ScrollEvent) => void, + /** + * Called when scrollable content view of the ScrollView changes. + * + * Handler function is passed the content width and content height as parameters: + * `(contentWidth, contentHeight)` + * + * It's implemented using onLayout handler attached to the content container + * which this ScrollView renders. + */ + onContentSizeChange?: (contentWidth: number, contentHeight: number) => void, + onKeyboardDidShow?: (event: KeyboardEvent) => void, + onKeyboardDidHide?: (event: KeyboardEvent) => void, + onKeyboardWillShow?: (event: KeyboardEvent) => void, + onKeyboardWillHide?: (event: KeyboardEvent) => void, + /** + * When true, the scroll view stops on multiples of the scroll view's size + * when scrolling. This can be used for horizontal pagination. The default + * value is false. + */ + pagingEnabled?: ?boolean, + /** + * When false, the view cannot be scrolled via touch interaction. + * The default value is true. + * + * Note that the view can always be scrolled by calling `scrollTo`. + */ + scrollEnabled?: ?boolean, + /** + * Limits how often scroll events will be fired while scrolling, specified as + * a time interval in ms. This may be useful when expensive work is performed + * in response to scrolling. Values <= `16` will disable throttling, + * regardless of the refresh rate of the device. + */ + scrollEventThrottle?: ?number, + /** + * When true, shows a vertical scroll indicator. + * The default value is true. + */ + showsVerticalScrollIndicator?: ?boolean, + /** + * When true, Sticky header is hidden when scrolling down, and dock at the top + * when scrolling up + */ + stickyHeaderHiddenOnScroll?: ?boolean, + /** + * An array of child indices determining which children get docked to the + * top of the screen when scrolling. For example, passing + * `stickyHeaderIndices={[0]}` will cause the first child to be fixed to the + * top of the scroll view. This property is not supported in conjunction + * with `horizontal={true}`. + */ + stickyHeaderIndices?: ?$ReadOnlyArray, + /** + * A React Component that will be used to render sticky headers. + * To be used together with `stickyHeaderIndices` or with `SectionList`, defaults to `ScrollViewStickyHeader`. + * You may need to set this if your sticky header uses custom transforms (eg. translation), + * for example when you want your list to have an animated hidable header. + */ + StickyHeaderComponent?: StickyHeaderComponentType, + /** + * When `snapToInterval` is set, `snapToAlignment` will define the relationship + * of the snapping to the scroll view. + * + * - `'start'` (the default) will align the snap at the left (horizontal) or top (vertical) + * - `'center'` will align the snap in the center + * - `'end'` will align the snap at the right (horizontal) or bottom (vertical) + */ + snapToAlignment?: ?('start' | 'center' | 'end'), + /** + * When set, causes the scroll view to stop at multiples of the value of + * `snapToInterval`. This can be used for paginating through children + * that have lengths smaller than the scroll view. Typically used in + * combination with `snapToAlignment` and `decelerationRate="fast"`. + * + * Overrides less configurable `pagingEnabled` prop. + */ + snapToInterval?: ?number, + /** + * When set, causes the scroll view to stop at the defined offsets. + * This can be used for paginating through variously sized children + * that have lengths smaller than the scroll view. Typically used in + * combination with `decelerationRate="fast"`. + * + * Overrides less configurable `pagingEnabled` and `snapToInterval` props. + */ + snapToOffsets?: ?$ReadOnlyArray, + /** + * Use in conjunction with `snapToOffsets`. By default, the beginning + * of the list counts as a snap offset. Set `snapToStart` to false to disable + * this behavior and allow the list to scroll freely between its start and + * the first `snapToOffsets` offset. + * The default value is true. + */ + snapToStart?: ?boolean, + /** + * Use in conjunction with `snapToOffsets`. By default, the end + * of the list counts as a snap offset. Set `snapToEnd` to false to disable + * this behavior and allow the list to scroll freely between its end and + * the last `snapToOffsets` offset. + * The default value is true. + */ + snapToEnd?: ?boolean, + /** + * Experimental: When true, offscreen child views (whose `overflow` value is + * `hidden`) are removed from their native backing superview when offscreen. + * This can improve scrolling performance on long lists. The default value is + * true. + */ + removeClippedSubviews?: ?boolean, + /** + * A RefreshControl component, used to provide pull-to-refresh + * functionality for the ScrollView. Only works for vertical ScrollViews + * (`horizontal` prop must be `false`). + * + * See [RefreshControl](docs/refreshcontrol.html). + */ + /* $FlowFixMe[unclear-type] - how to handle generic type without existential + * operator? */ + refreshControl?: ?ExactReactElement_DEPRECATED, + children?: React.Node, + /** + * A ref to the inner View element of the ScrollView. This should be used + * instead of calling `getInnerViewRef`. + */ + innerViewRef?: React.RefSetter, + /** + * A ref to the Native ScrollView component. This ref can be used to call + * all of ScrollView's public methods, in addition to native methods like + * measure, measureLayout, etc. + */ + scrollViewRef?: React.RefSetter, +|}>; + +type State = {| + layoutHeight: ?number, +|}; + +const IS_ANIMATING_TOUCH_START_THRESHOLD_MS = 16; + +export type ScrollViewComponentStatics = $ReadOnly<{| + Context: typeof ScrollViewContext, +|}>; + +/** + * Component that wraps platform ScrollView while providing + * integration with touch locking "responder" system. + * + * Keep in mind that ScrollViews must have a bounded height in order to work, + * since they contain unbounded-height children into a bounded container (via + * a scroll interaction). In order to bound the height of a ScrollView, either + * set the height of the view directly (discouraged) or make sure all parent + * views have bounded height. Forgetting to transfer `{flex: 1}` down the + * view stack can lead to errors here, which the element inspector makes + * easy to debug. + * + * Doesn't yet support other contained responders from blocking this scroll + * view from becoming the responder. + * + * + * `` vs [``](https://reactnative.dev/docs/flatlist) - which one to use? + * + * `ScrollView` simply renders all its react child components at once. That + * makes it very easy to understand and use. + * + * On the other hand, this has a performance downside. Imagine you have a very + * long list of items you want to display, maybe several screens worth of + * content. Creating JS components and native views for everything all at once, + * much of which may not even be shown, will contribute to slow rendering and + * increased memory usage. + * + * This is where `FlatList` comes into play. `FlatList` renders items lazily, + * just when they are about to appear, and removes items that scroll way off + * screen to save memory and processing time. + * + * `FlatList` is also handy if you want to render separators between your items, + * multiple columns, infinite scroll loading, or any number of other features it + * supports out of the box. + */ +class ScrollView extends React.Component { + static Context: typeof ScrollViewContext = ScrollViewContext; + + constructor(props: Props) { + super(props); + + this._scrollAnimatedValue = new AnimatedImplementation.Value( + this.props.contentOffset?.y ?? 0, + ); + this._scrollAnimatedValue.setOffset(this.props.contentInset?.top ?? 0); + } + + _scrollAnimatedValue: AnimatedImplementation.Value; + _scrollAnimatedValueAttachment: ?{detach: () => void, ...} = null; + _stickyHeaderRefs: Map> = + new Map(); + _headerLayoutYs: Map = new Map(); + + _keyboardMetrics: ?KeyboardMetrics = null; + _additionalScrollOffset: number = 0; + _isTouching: boolean = false; + _lastMomentumScrollBeginTime: number = 0; + _lastMomentumScrollEndTime: number = 0; + + // Reset to false every time becomes responder. This is used to: + // - Determine if the scroll view has been scrolled and therefore should + // refuse to give up its responder lock. + // - Determine if releasing should dismiss the keyboard when we are in + // tap-to-dismiss mode (this.props.keyboardShouldPersistTaps !== 'always'). + _observedScrollSinceBecomingResponder: boolean = false; + _becameResponderWhileAnimating: boolean = false; + _preventNegativeScrollOffset: ?boolean = null; + + _animated: ?boolean = null; + + _subscriptionKeyboardWillShow: ?EventSubscription = null; + _subscriptionKeyboardWillHide: ?EventSubscription = null; + _subscriptionKeyboardDidShow: ?EventSubscription = null; + _subscriptionKeyboardDidHide: ?EventSubscription = null; + + state: State = { + layoutHeight: null, + }; + + componentDidMount() { + if (typeof this.props.keyboardShouldPersistTaps === 'boolean') { + console.warn( + `'keyboardShouldPersistTaps={${ + this.props.keyboardShouldPersistTaps === true ? 'true' : 'false' + }}' is deprecated. ` + + `Use 'keyboardShouldPersistTaps="${ + this.props.keyboardShouldPersistTaps ? 'always' : 'never' + }"' instead`, + ); + } + + this._keyboardMetrics = Keyboard.metrics(); + this._additionalScrollOffset = 0; + + this._subscriptionKeyboardWillShow = Keyboard.addListener( + 'keyboardWillShow', + this.scrollResponderKeyboardWillShow, + ); + this._subscriptionKeyboardWillHide = Keyboard.addListener( + 'keyboardWillHide', + this.scrollResponderKeyboardWillHide, + ); + this._subscriptionKeyboardDidShow = Keyboard.addListener( + 'keyboardDidShow', + this.scrollResponderKeyboardDidShow, + ); + this._subscriptionKeyboardDidHide = Keyboard.addListener( + 'keyboardDidHide', + this.scrollResponderKeyboardDidHide, + ); + + this._updateAnimatedNodeAttachment(); + } + + componentDidUpdate(prevProps: Props) { + const prevContentInsetTop = prevProps.contentInset + ? prevProps.contentInset.top + : 0; + const newContentInsetTop = this.props.contentInset + ? this.props.contentInset.top + : 0; + if (prevContentInsetTop !== newContentInsetTop) { + this._scrollAnimatedValue.setOffset(newContentInsetTop || 0); + } + + this._updateAnimatedNodeAttachment(); + } + + componentWillUnmount() { + if (this._subscriptionKeyboardWillShow != null) { + this._subscriptionKeyboardWillShow.remove(); + } + if (this._subscriptionKeyboardWillHide != null) { + this._subscriptionKeyboardWillHide.remove(); + } + if (this._subscriptionKeyboardDidShow != null) { + this._subscriptionKeyboardDidShow.remove(); + } + if (this._subscriptionKeyboardDidHide != null) { + this._subscriptionKeyboardDidHide.remove(); + } + + if (this._scrollAnimatedValueAttachment) { + this._scrollAnimatedValueAttachment.detach(); + } + } + + /** + * Returns a reference to the underlying scroll responder, which supports + * operations like `scrollTo`. All ScrollView-like components should + * implement this method so that they can be composed while providing access + * to the underlying scroll responder's methods. + */ + getScrollResponder: () => ScrollResponderType = () => { + // $FlowFixMe[unclear-type] + return ((this: any): ScrollResponderType); + }; + + getScrollableNode: () => ?number = () => { + return findNodeHandle(this.getNativeScrollRef()); + }; + + getInnerViewNode: () => ?number = () => { + return findNodeHandle(this._innerView.nativeInstance); + }; + + getInnerViewRef: () => InnerViewInstance | null = () => { + return this._innerView.nativeInstance; + }; + + getNativeScrollRef: () => HostInstance | null = () => { + return this._scrollView.nativeInstance; + }; + + /** + * Scrolls to a given x, y offset, either immediately or with a smooth animation. + * + * Example: + * + * `scrollTo({x: 0, y: 0, animated: true})` + * + * Note: The weird function signature is due to the fact that, for historical reasons, + * the function also accepts separate arguments as an alternative to the options object. + * This is deprecated due to ambiguity (y before x), and SHOULD NOT BE USED. + */ + scrollTo: ( + options?: + | { + x?: number, + y?: number, + animated?: boolean, + ... + } + | number, + deprecatedX?: number, + deprecatedAnimated?: boolean, + ) => void = ( + options?: + | { + x?: number, + y?: number, + animated?: boolean, + ... + } + | number, + deprecatedX?: number, + deprecatedAnimated?: boolean, + ) => { + let x, y, animated; + if (typeof options === 'number') { + console.warn( + '`scrollTo(y, x, animated)` is deprecated. Use `scrollTo({x: 5, y: 5, ' + + 'animated: true})` instead.', + ); + y = options; + x = deprecatedX; + animated = deprecatedAnimated; + } else if (options) { + y = options.y; + x = options.x; + animated = options.animated; + } + const component = this.getNativeScrollRef(); + if (component == null) { + return; + } + Commands.scrollTo(component, x || 0, y || 0, animated !== false); + }; + + /** + * If this is a vertical ScrollView scrolls to the bottom. + * If this is a horizontal ScrollView scrolls to the right. + * + * Use `scrollToEnd({animated: true})` for smooth animated scrolling, + * `scrollToEnd({animated: false})` for immediate scrolling. + * If no options are passed, `animated` defaults to true. + */ + scrollToEnd: (options?: ?{animated?: boolean, ...}) => void = ( + options?: ?{animated?: boolean, ...}, + ) => { + // Default to true + const animated = (options && options.animated) !== false; + const component = this.getNativeScrollRef(); + if (component == null) { + return; + } + Commands.scrollToEnd(component, animated); + }; + + /** + * Displays the scroll indicators momentarily. + * + * @platform ios + */ + flashScrollIndicators: () => void = () => { + const component = this.getNativeScrollRef(); + if (component == null) { + return; + } + Commands.flashScrollIndicators(component); + }; + + /** + * This method should be used as the callback to onFocus in a TextInputs' + * parent view. Note that any module using this mixin needs to return + * the parent view's ref in getScrollViewRef() in order to use this method. + * @param {number} nodeHandle The TextInput node handle + * @param {number} additionalOffset The scroll view's bottom "contentInset". + * Default is 0. + * @param {bool} preventNegativeScrolling Whether to allow pulling the content + * down to make it meet the keyboard's top. Default is false. + */ + scrollResponderScrollNativeHandleToKeyboard: ( + nodeHandle: number | HostInstance, + additionalOffset?: number, + preventNegativeScrollOffset?: boolean, + ) => void = ( + nodeHandle: number | HostInstance, + additionalOffset?: number, + preventNegativeScrollOffset?: boolean, + ) => { + this._additionalScrollOffset = additionalOffset || 0; + this._preventNegativeScrollOffset = !!preventNegativeScrollOffset; + + if (this._innerView.nativeInstance == null) { + return; + } + + if (typeof nodeHandle === 'number') { + UIManager.measureLayout( + nodeHandle, + nullthrows(findNodeHandle(this)), + // $FlowFixMe[method-unbinding] added when improving typing for this parameters + this._textInputFocusError, + this._inputMeasureAndScrollToKeyboard, + ); + } else { + nodeHandle.measureLayout( + this._innerView.nativeInstance, + this._inputMeasureAndScrollToKeyboard, + // $FlowFixMe[method-unbinding] added when improving typing for this parameters + this._textInputFocusError, + ); + } + }; + + /** + * A helper function to zoom to a specific rect in the scrollview. The argument has the shape + * {x: number; y: number; width: number; height: number; animated: boolean = true} + * + * @platform ios + */ + scrollResponderZoomTo: ( + rect: {| + x: number, + y: number, + width: number, + height: number, + animated?: boolean, + |}, + animated?: boolean, // deprecated, put this inside the rect argument instead + ) => void = ( + rect: {| + x: number, + y: number, + width: number, + height: number, + animated?: boolean, + |}, + animated?: boolean, // deprecated, put this inside the rect argument instead + ) => { + invariant(Platform.OS === 'ios', 'zoomToRect is not implemented'); + if ('animated' in rect) { + this._animated = rect.animated; + delete rect.animated; + } else if (typeof animated !== 'undefined') { + console.warn( + '`scrollResponderZoomTo` `animated` argument is deprecated. Use `options.animated` instead', + ); + } + + const component = this.getNativeScrollRef(); + if (component == null) { + return; + } + Commands.zoomToRect(component, rect, animated !== false); + }; + + _textInputFocusError() { + console.warn('Error measuring text field.'); + } + + /** + * The calculations performed here assume the scroll view takes up the entire + * screen - even if has some content inset. We then measure the offsets of the + * keyboard, and compensate both for the scroll view's "contentInset". + * + * @param {number} left Position of input w.r.t. table view. + * @param {number} top Position of input w.r.t. table view. + * @param {number} width Width of the text input. + * @param {number} height Height of the text input. + */ + _inputMeasureAndScrollToKeyboard: ( + left: number, + top: number, + width: number, + height: number, + ) => void = (left: number, top: number, width: number, height: number) => { + let keyboardScreenY = Dimensions.get('window').height; + + const scrollTextInputIntoVisibleRect = () => { + if (this._keyboardMetrics != null) { + keyboardScreenY = this._keyboardMetrics.screenY; + } + let scrollOffsetY = + top - keyboardScreenY + height + this._additionalScrollOffset; + + // By default, this can scroll with negative offset, pulling the content + // down so that the target component's bottom meets the keyboard's top. + // If requested otherwise, cap the offset at 0 minimum to avoid content + // shifting down. + if (this._preventNegativeScrollOffset === true) { + scrollOffsetY = Math.max(0, scrollOffsetY); + } + this.scrollTo({x: 0, y: scrollOffsetY, animated: true}); + + this._additionalScrollOffset = 0; + this._preventNegativeScrollOffset = false; + }; + + if (this._keyboardMetrics == null) { + // `_keyboardMetrics` is set inside `scrollResponderKeyboardWillShow` which + // is not guaranteed to be called before `_inputMeasureAndScrollToKeyboard` but native has already scheduled it. + // In case it was not called before `_inputMeasureAndScrollToKeyboard`, we postpone scrolling to + // text input. + setTimeout(() => { + scrollTextInputIntoVisibleRect(); + }, 0); + } else { + scrollTextInputIntoVisibleRect(); + } + }; + + _getKeyForIndex(index: $FlowFixMe, childArray: $FlowFixMe): $FlowFixMe { + const child = childArray[index]; + return child && child.key; + } + + _updateAnimatedNodeAttachment() { + if (this._scrollAnimatedValueAttachment) { + this._scrollAnimatedValueAttachment.detach(); + } + if ( + this.props.stickyHeaderIndices && + this.props.stickyHeaderIndices.length > 0 + ) { + this._scrollAnimatedValueAttachment = + AnimatedImplementation.attachNativeEvent( + this.getNativeScrollRef(), + 'onScroll', + [{nativeEvent: {contentOffset: {y: this._scrollAnimatedValue}}}], + ); + } + } + + _setStickyHeaderRef( + key: string, + ref: ?React.ElementRef, + ) { + if (ref) { + this._stickyHeaderRefs.set(key, ref); + } else { + this._stickyHeaderRefs.delete(key); + } + } + + _onStickyHeaderLayout(index: $FlowFixMe, event: $FlowFixMe, key: $FlowFixMe) { + const {stickyHeaderIndices} = this.props; + if (!stickyHeaderIndices) { + return; + } + const childArray = React.Children.toArray<$FlowFixMe>(this.props.children); + if (key !== this._getKeyForIndex(index, childArray)) { + // ignore stale layout update + return; + } + + const layoutY = event.nativeEvent.layout.y; + this._headerLayoutYs.set(key, layoutY); + + const indexOfIndex = stickyHeaderIndices.indexOf(index); + const previousHeaderIndex = stickyHeaderIndices[indexOfIndex - 1]; + if (previousHeaderIndex != null) { + const previousHeader = this._stickyHeaderRefs.get( + this._getKeyForIndex(previousHeaderIndex, childArray), + ); + previousHeader && + previousHeader.setNextHeaderY && + previousHeader.setNextHeaderY(layoutY); + } + } + + _handleScroll = (e: ScrollEvent) => { + this._observedScrollSinceBecomingResponder = true; + this.props.onScroll && this.props.onScroll(e); + }; + + _handleLayout = (e: LayoutEvent) => { + if (this.props.invertStickyHeaders === true) { + this.setState({layoutHeight: e.nativeEvent.layout.height}); + } + if (this.props.onLayout) { + this.props.onLayout(e); + } + }; + + _handleContentOnLayout = (e: LayoutEvent) => { + const {width, height} = e.nativeEvent.layout; + this.props.onContentSizeChange && + this.props.onContentSizeChange(width, height); + }; + + _innerView: RefForwarder = + createRefForwarder( + (instance: InnerViewInstance): InnerViewInstance => instance, + ); + + _scrollView: RefForwarder = + createRefForwarder(nativeInstance => { + // This is a hack. Ideally we would forwardRef to the underlying + // host component. However, since ScrollView has it's own methods that can be + // called as well, if we used the standard forwardRef then these + // methods wouldn't be accessible and thus be a breaking change. + // + // Therefore we edit ref to include ScrollView's public methods so that + // they are callable from the ref. + + // $FlowFixMe[prop-missing] - Known issue with appending custom methods. + const publicInstance: PublicScrollViewInstance = Object.assign( + nativeInstance, + { + getScrollResponder: this.getScrollResponder, + getScrollableNode: this.getScrollableNode, + getInnerViewNode: this.getInnerViewNode, + getInnerViewRef: this.getInnerViewRef, + getNativeScrollRef: this.getNativeScrollRef, + scrollTo: this.scrollTo, + scrollToEnd: this.scrollToEnd, + flashScrollIndicators: this.flashScrollIndicators, + scrollResponderZoomTo: this.scrollResponderZoomTo, + scrollResponderScrollNativeHandleToKeyboard: + this.scrollResponderScrollNativeHandleToKeyboard, + }, + ); + + return publicInstance; + }); + + /** + * Warning, this may be called several times for a single keyboard opening. + * It's best to store the information in this method and then take any action + * at a later point (either in `keyboardDidShow` or other). + * + * Here's the order that events occur in: + * - focus + * - willShow {startCoordinates, endCoordinates} several times + * - didShow several times + * - blur + * - willHide {startCoordinates, endCoordinates} several times + * - didHide several times + * + * The `ScrollResponder` module callbacks for each of these events. + * Even though any user could have easily listened to keyboard events + * themselves, using these `props` callbacks ensures that ordering of events + * is consistent - and not dependent on the order that the keyboard events are + * subscribed to. This matters when telling the scroll view to scroll to where + * the keyboard is headed - the scroll responder better have been notified of + * the keyboard destination before being instructed to scroll to where the + * keyboard will be. Stick to the `ScrollResponder` callbacks, and everything + * will work. + * + * WARNING: These callbacks will fire even if a keyboard is displayed in a + * different navigation pane. Filter out the events to determine if they are + * relevant to you. (For example, only if you receive these callbacks after + * you had explicitly focused a node etc). + */ + + scrollResponderKeyboardWillShow: (e: KeyboardEvent) => void = ( + e: KeyboardEvent, + ) => { + this._keyboardMetrics = e.endCoordinates; + this.props.onKeyboardWillShow && this.props.onKeyboardWillShow(e); + }; + + scrollResponderKeyboardWillHide: (e: KeyboardEvent) => void = ( + e: KeyboardEvent, + ) => { + this._keyboardMetrics = null; + this.props.onKeyboardWillHide && this.props.onKeyboardWillHide(e); + }; + + scrollResponderKeyboardDidShow: (e: KeyboardEvent) => void = ( + e: KeyboardEvent, + ) => { + this._keyboardMetrics = e.endCoordinates; + this.props.onKeyboardDidShow && this.props.onKeyboardDidShow(e); + }; + + scrollResponderKeyboardDidHide: (e: KeyboardEvent) => void = ( + e: KeyboardEvent, + ) => { + this._keyboardMetrics = null; + this.props.onKeyboardDidHide && this.props.onKeyboardDidHide(e); + }; + + /** + * Invoke this from an `onMomentumScrollBegin` event. + */ + _handleMomentumScrollBegin: (e: ScrollEvent) => void = (e: ScrollEvent) => { + this._lastMomentumScrollBeginTime = global.performance.now(); + this.props.onMomentumScrollBegin && this.props.onMomentumScrollBegin(e); + }; + + /** + * Invoke this from an `onMomentumScrollEnd` event. + */ + _handleMomentumScrollEnd: (e: ScrollEvent) => void = (e: ScrollEvent) => { + FrameRateLogger.endScroll(); + this._lastMomentumScrollEndTime = global.performance.now(); + this.props.onMomentumScrollEnd && this.props.onMomentumScrollEnd(e); + }; + + /** + * Unfortunately, `onScrollBeginDrag` also fires when *stopping* the scroll + * animation, and there's not an easy way to distinguish a drag vs. stopping + * momentum. + * + * Invoke this from an `onScrollBeginDrag` event. + */ + _handleScrollBeginDrag: (e: ScrollEvent) => void = (e: ScrollEvent) => { + FrameRateLogger.beginScroll(); // TODO: track all scrolls after implementing onScrollEndAnimation + + if ( + Platform.OS === 'android' && + this.props.keyboardDismissMode === 'on-drag' + ) { + dismissKeyboard(); + } + + this.props.onScrollBeginDrag && this.props.onScrollBeginDrag(e); + }; + + /** + * Invoke this from an `onScrollEndDrag` event. + */ + _handleScrollEndDrag: (e: ScrollEvent) => void = (e: ScrollEvent) => { + const {velocity} = e.nativeEvent; + // - If we are animating, then this is a "drag" that is stopping the scrollview and momentum end + // will fire. + // - If velocity is non-zero, then the interaction will stop when momentum scroll ends or + // another drag starts and ends. + // - If we don't get velocity, better to stop the interaction twice than not stop it. + if ( + !this._isAnimating() && + (!velocity || (velocity.x === 0 && velocity.y === 0)) + ) { + FrameRateLogger.endScroll(); + } + this.props.onScrollEndDrag && this.props.onScrollEndDrag(e); + }; + + /** + * A helper function for this class that lets us quickly determine if the + * view is currently animating. This is particularly useful to know when + * a touch has just started or ended. + */ + _isAnimating: () => boolean = () => { + const now = global.performance.now(); + const timeSinceLastMomentumScrollEnd = + now - this._lastMomentumScrollEndTime; + const isAnimating = + timeSinceLastMomentumScrollEnd < IS_ANIMATING_TOUCH_START_THRESHOLD_MS || + this._lastMomentumScrollEndTime < this._lastMomentumScrollBeginTime; + return isAnimating; + }; + + /** + * Invoke this from an `onResponderGrant` event. + */ + _handleResponderGrant: (e: PressEvent) => void = (e: PressEvent) => { + this._observedScrollSinceBecomingResponder = false; + this.props.onResponderGrant && this.props.onResponderGrant(e); + this._becameResponderWhileAnimating = this._isAnimating(); + }; + + /** + * Invoke this from an `onResponderReject` event. + * + * Some other element is not yielding its role as responder. Normally, we'd + * just disable the `UIScrollView`, but a touch has already began on it, the + * `UIScrollView` will not accept being disabled after that. The easiest + * solution for now is to accept the limitation of disallowing this + * altogether. To improve this, find a way to disable the `UIScrollView` after + * a touch has already started. + */ + _handleResponderReject: () => void = () => {}; + + /** + * Invoke this from an `onResponderRelease` event. + */ + _handleResponderRelease: (e: PressEvent) => void = (e: PressEvent) => { + this._isTouching = e.nativeEvent.touches.length !== 0; + this.props.onResponderRelease && this.props.onResponderRelease(e); + + if (typeof e.target === 'number') { + if (__DEV__) { + console.error( + 'Did not expect event target to be a number. Should have been a native component', + ); + } + + return; + } + + // By default scroll views will unfocus a textField + // if another touch occurs outside of it + const currentlyFocusedTextInput = TextInputState.currentlyFocusedInput(); + if ( + currentlyFocusedTextInput != null && + this.props.keyboardShouldPersistTaps !== true && + this.props.keyboardShouldPersistTaps !== 'always' && + this._keyboardIsDismissible() && + e.target !== currentlyFocusedTextInput && + !this._observedScrollSinceBecomingResponder && + !this._becameResponderWhileAnimating + ) { + TextInputState.blurTextInput(currentlyFocusedTextInput); + } + }; + + /** + * We will allow the scroll view to give up its lock iff it acquired the lock + * during an animation. This is a very useful default that happens to satisfy + * many common user experiences. + * + * - Stop a scroll on the left edge, then turn that into an outer view's + * backswipe. + * - Stop a scroll mid-bounce at the top, continue pulling to have the outer + * view dismiss. + * - However, without catching the scroll view mid-bounce (while it is + * motionless), if you drag far enough for the scroll view to become + * responder (and therefore drag the scroll view a bit), any backswipe + * navigation of a swipe gesture higher in the view hierarchy, should be + * rejected. + */ + _handleResponderTerminationRequest: () => boolean = () => { + return !this._observedScrollSinceBecomingResponder; + }; + + /** + * Invoke this from an `onScroll` event. + */ + _handleScrollShouldSetResponder: () => boolean = () => { + // Allow any event touch pass through if the default pan responder is disabled + if (this.props.disableScrollViewPanResponder === true) { + return false; + } + return this._isTouching; + }; + + /** + * Merely touch starting is not sufficient for a scroll view to become the + * responder. Being the "responder" means that the very next touch move/end + * event will result in an action/movement. + * + * Invoke this from an `onStartShouldSetResponder` event. + * + * `onStartShouldSetResponder` is used when the next move/end will trigger + * some UI movement/action, but when you want to yield priority to views + * nested inside of the view. + * + * There may be some cases where scroll views actually should return `true` + * from `onStartShouldSetResponder`: Any time we are detecting a standard tap + * that gives priority to nested views. + * + * - If a single tap on the scroll view triggers an action such as + * recentering a map style view yet wants to give priority to interaction + * views inside (such as dropped pins or labels), then we would return true + * from this method when there is a single touch. + * + * - Similar to the previous case, if a two finger "tap" should trigger a + * zoom, we would check the `touches` count, and if `>= 2`, we would return + * true. + * + */ + _handleStartShouldSetResponder: (e: PressEvent) => boolean = ( + e: PressEvent, + ) => { + // Allow any event touch pass through if the default pan responder is disabled + if (this.props.disableScrollViewPanResponder === true) { + return false; + } + + const currentlyFocusedInput = TextInputState.currentlyFocusedInput(); + if ( + this.props.keyboardShouldPersistTaps === 'handled' && + this._keyboardIsDismissible() && + e.target !== currentlyFocusedInput + ) { + return true; + } + return false; + }; + + /** + * There are times when the scroll view wants to become the responder + * (meaning respond to the next immediate `touchStart/touchEnd`), in a way + * that *doesn't* give priority to nested views (hence the capture phase): + * + * - Currently animating. + * - Tapping anywhere that is not a text input, while the keyboard is + * up (which should dismiss the keyboard). + * + * Invoke this from an `onStartShouldSetResponderCapture` event. + */ + _handleStartShouldSetResponderCapture: (e: PressEvent) => boolean = ( + e: PressEvent, + ) => { + // The scroll view should receive taps instead of its descendants if: + // * it is already animating/decelerating + if (this._isAnimating()) { + return true; + } + + // Allow any event touch pass through if the default pan responder is disabled + if (this.props.disableScrollViewPanResponder === true) { + return false; + } + + // * the keyboard is up, keyboardShouldPersistTaps is 'never' (the default), + // and a new touch starts with a non-textinput target (in which case the + // first tap should be sent to the scroll view and dismiss the keyboard, + // then the second tap goes to the actual interior view) + const {keyboardShouldPersistTaps} = this.props; + const keyboardNeverPersistTaps = + !keyboardShouldPersistTaps || keyboardShouldPersistTaps === 'never'; + + if (typeof e.target === 'number') { + if (__DEV__) { + console.error( + 'Did not expect event target to be a number. Should have been a native component', + ); + } + + return false; + } + + // Let presses through if the soft keyboard is detached from the viewport + if (this._softKeyboardIsDetached()) { + return false; + } + + if ( + keyboardNeverPersistTaps && + this._keyboardIsDismissible() && + e.target != null && + // $FlowFixMe[incompatible-call] + !TextInputState.isTextInput(e.target) + ) { + return true; + } + + return false; + }; + + /** + * Do we consider there to be a dismissible soft-keyboard open? + */ + _keyboardIsDismissible: () => boolean = () => { + const currentlyFocusedInput = TextInputState.currentlyFocusedInput(); + + // We cannot dismiss the keyboard without an input to blur, even if a soft + // keyboard is open (e.g. when keyboard is open due to a native component + // not participating in TextInputState). It's also possible that the + // currently focused input isn't a TextInput (such as by calling ref.focus + // on a non-TextInput). + const hasFocusedTextInput = + currentlyFocusedInput != null && + TextInputState.isTextInput(currentlyFocusedInput); + + // Even if an input is focused, we may not have a keyboard to dismiss. E.g + // when using a physical keyboard. Ensure we have an event for an opened + // keyboard. + const softKeyboardMayBeOpen = + this._keyboardMetrics != null || this._keyboardEventsAreUnreliable(); + + return hasFocusedTextInput && softKeyboardMayBeOpen; + }; + + /** + * Whether an open soft keyboard is present which does not overlap the + * viewport. E.g. for a VR soft-keyboard which is detached from the app + * viewport. + */ + _softKeyboardIsDetached: () => boolean = () => { + return this._keyboardMetrics != null && this._keyboardMetrics.height === 0; + }; + + _keyboardEventsAreUnreliable: () => boolean = () => { + // Android versions prior to API 30 rely on observing layout changes when + // `android:windowSoftInputMode` is set to `adjustResize` or `adjustPan`. + return Platform.OS === 'android' && Platform.Version < 30; + }; + + /** + * Invoke this from an `onTouchEnd` event. + * + * @param {PressEvent} e Event. + */ + _handleTouchEnd: (e: PressEvent) => void = (e: PressEvent) => { + const nativeEvent = e.nativeEvent; + this._isTouching = nativeEvent.touches.length !== 0; + + const {keyboardShouldPersistTaps} = this.props; + const keyboardNeverPersistsTaps = + !keyboardShouldPersistTaps || keyboardShouldPersistTaps === 'never'; + + // Dismiss the keyboard now if we didn't become responder in capture phase + // to eat presses, but still want to dismiss on interaction. + // Don't do anything if the target of the touch event is the current input. + const currentlyFocusedTextInput = TextInputState.currentlyFocusedInput(); + if ( + currentlyFocusedTextInput != null && + e.target !== currentlyFocusedTextInput && + this._softKeyboardIsDetached() && + this._keyboardIsDismissible() && + keyboardNeverPersistsTaps + ) { + TextInputState.blurTextInput(currentlyFocusedTextInput); + } + + this.props.onTouchEnd && this.props.onTouchEnd(e); + }; + + /** + * Invoke this from an `onTouchCancel` event. + * + * @param {PressEvent} e Event. + */ + _handleTouchCancel: (e: PressEvent) => void = (e: PressEvent) => { + this._isTouching = false; + this.props.onTouchCancel && this.props.onTouchCancel(e); + }; + + /** + * Invoke this from an `onTouchStart` event. + * + * Since we know that the `SimpleEventPlugin` occurs later in the plugin + * order, after `ResponderEventPlugin`, we can detect that we were *not* + * permitted to be the responder (presumably because a contained view became + * responder). The `onResponderReject` won't fire in that case - it only + * fires when a *current* responder rejects our request. + * + * @param {PressEvent} e Touch Start event. + */ + _handleTouchStart: (e: PressEvent) => void = (e: PressEvent) => { + this._isTouching = true; + this.props.onTouchStart && this.props.onTouchStart(e); + }; + + /** + * Invoke this from an `onTouchMove` event. + * + * Since we know that the `SimpleEventPlugin` occurs later in the plugin + * order, after `ResponderEventPlugin`, we can detect that we were *not* + * permitted to be the responder (presumably because a contained view became + * responder). The `onResponderReject` won't fire in that case - it only + * fires when a *current* responder rejects our request. + * + * @param {PressEvent} e Touch Start event. + */ + _handleTouchMove: (e: PressEvent) => void = (e: PressEvent) => { + this.props.onTouchMove && this.props.onTouchMove(e); + }; + + render(): React.Node { + const horizontal = this.props.horizontal === true; + + const NativeScrollView = horizontal + ? HScrollViewNativeComponent + : VScrollViewNativeComponent; + + const NativeScrollContentView = horizontal + ? HScrollContentViewNativeComponent + : VScrollContentViewNativeComponent; + + const contentContainerStyle = [ + horizontal && styles.contentContainerHorizontal, + this.props.contentContainerStyle, + ]; + if (__DEV__ && this.props.style !== undefined) { + // $FlowFixMe[underconstrained-implicit-instantiation] + const style = flattenStyle(this.props.style); + const childLayoutProps = ['alignItems', 'justifyContent'].filter( + // $FlowFixMe[incompatible-use] + prop => style && style[prop] !== undefined, + ); + invariant( + childLayoutProps.length === 0, + 'ScrollView child layout (' + + JSON.stringify(childLayoutProps) + + ') must be applied through the contentContainerStyle prop.', + ); + } + + const contentSizeChangeProps = + this.props.onContentSizeChange == null + ? null + : { + onLayout: this._handleContentOnLayout, + }; + + const {stickyHeaderIndices} = this.props; + let children = this.props.children; + /** + * This function can cause unnecessary remount when nested in conditionals as it causes remap of children keys. + * https://react.dev/reference/react/Children#children-toarray-caveats + */ + children = React.Children.toArray<$FlowFixMe>(children); + + if (stickyHeaderIndices != null && stickyHeaderIndices.length > 0) { + children = children.map((child, index) => { + const indexOfIndex = child ? stickyHeaderIndices.indexOf(index) : -1; + if (indexOfIndex > -1) { + const key = child.key; + const nextIndex = stickyHeaderIndices[indexOfIndex + 1]; + const StickyHeaderComponent = + this.props.StickyHeaderComponent || ScrollViewStickyHeader; + return ( + this._setStickyHeaderRef(key, ref)} + nextHeaderLayoutY={this._headerLayoutYs.get( + this._getKeyForIndex(nextIndex, children), + )} + onLayout={event => this._onStickyHeaderLayout(index, event, key)} + scrollAnimatedValue={this._scrollAnimatedValue} + inverted={this.props.invertStickyHeaders} + hiddenOnScroll={this.props.stickyHeaderHiddenOnScroll} + scrollViewHeight={this.state.layoutHeight}> + {child} + + ); + } else { + return child; + } + }); + } + children = ( + + {children} + + ); + + const hasStickyHeaders = + Array.isArray(stickyHeaderIndices) && stickyHeaderIndices.length > 0; + + // Some ScrollView native component behaviors rely on using the metrics + // of mounted views for anchoring. Make sure not to flatten children if + // this is the case. + const preserveChildren = + this.props.maintainVisibleContentPosition != null || + (Platform.OS === 'android' && this.props.snapToAlignment != null); + + const contentContainer = ( + + {children} + + ); + + const alwaysBounceHorizontal = + this.props.alwaysBounceHorizontal !== undefined + ? this.props.alwaysBounceHorizontal + : this.props.horizontal; + + const alwaysBounceVertical = + this.props.alwaysBounceVertical !== undefined + ? this.props.alwaysBounceVertical + : !this.props.horizontal; + + const accessible = this.props.accessible !== false; // [Windows] + + const baseStyle = horizontal ? styles.baseHorizontal : styles.baseVertical; + + const {experimental_endDraggingSensitivityMultiplier, ...otherProps} = + this.props; + const props = { + ...otherProps, + accessible, // [Windows] + alwaysBounceHorizontal, + alwaysBounceVertical, + style: StyleSheet.compose(baseStyle, this.props.style), + // Override the onContentSizeChange from props, since this event can + // bubble up from TextInputs + onContentSizeChange: null, + onLayout: this._handleLayout, + onMomentumScrollBegin: this._handleMomentumScrollBegin, + onMomentumScrollEnd: this._handleMomentumScrollEnd, + onResponderGrant: this._handleResponderGrant, + onResponderReject: this._handleResponderReject, + onResponderRelease: this._handleResponderRelease, + onResponderTerminationRequest: this._handleResponderTerminationRequest, + onScrollBeginDrag: this._handleScrollBeginDrag, + onScrollEndDrag: this._handleScrollEndDrag, + onScrollShouldSetResponder: this._handleScrollShouldSetResponder, + onStartShouldSetResponder: this._handleStartShouldSetResponder, + onStartShouldSetResponderCapture: + this._handleStartShouldSetResponderCapture, + onTouchEnd: this._handleTouchEnd, + onTouchMove: this._handleTouchMove, + onTouchStart: this._handleTouchStart, + onTouchCancel: this._handleTouchCancel, + onScroll: this._handleScroll, + endDraggingSensitivityMultiplier: + experimental_endDraggingSensitivityMultiplier, + scrollEventThrottle: hasStickyHeaders + ? 1 + : this.props.scrollEventThrottle, + sendMomentumEvents: + this.props.onMomentumScrollBegin || this.props.onMomentumScrollEnd + ? true + : false, + // default to true + snapToStart: this.props.snapToStart !== false, + // default to true + snapToEnd: this.props.snapToEnd !== false, + // pagingEnabled is overridden by snapToInterval / snapToOffsets + pagingEnabled: Platform.select({ + // on iOS, pagingEnabled must be set to false to have snapToInterval / snapToOffsets work + ios: + this.props.pagingEnabled === true && + this.props.snapToInterval == null && + this.props.snapToOffsets == null, + // on Android, pagingEnabled must be set to true to have snapToInterval / snapToOffsets work + android: + this.props.pagingEnabled === true || + this.props.snapToInterval != null || + this.props.snapToOffsets != null, + }), + }; + + const {decelerationRate} = this.props; + if (decelerationRate != null) { + props.decelerationRate = processDecelerationRate(decelerationRate); + } + + const refreshControl = this.props.refreshControl; + const scrollViewRef = this._scrollView.getForwardingRef( + this.props.scrollViewRef, + ); + + if (refreshControl) { + if (Platform.OS === 'ios') { + // On iOS the RefreshControl is a child of the ScrollView. + return ( + // $FlowFixMe[incompatible-type] - Flow only knows element refs. + + {refreshControl} + {contentContainer} + + ); + } else if (Platform.OS === 'android') { + // On Android wrap the ScrollView with a AndroidSwipeRefreshLayout. + // Since the ScrollView is wrapped add the style props to the + // AndroidSwipeRefreshLayout and use flex: 1 for the ScrollView. + // Note: we should split props.style on the inner and outer props + // however, the ScrollView still needs the baseStyle to be scrollable + // $FlowFixMe[underconstrained-implicit-instantiation] + // $FlowFixMe[incompatible-call] + const {outer, inner} = splitLayoutProps(flattenStyle(props.style)); + return React.cloneElement( + refreshControl, + {style: StyleSheet.compose(baseStyle, outer)}, + + {contentContainer} + , + ); + } + } + return ( + // $FlowFixMe[incompatible-type] - Flow only knows element refs. + + {contentContainer} + + ); + } +} + +const styles = StyleSheet.create({ + baseVertical: { + flexGrow: 1, + flexShrink: 1, + flexDirection: 'column', + overflow: 'scroll', + }, + baseHorizontal: { + flexGrow: 1, + flexShrink: 1, + flexDirection: 'row', + overflow: 'scroll', + }, + contentContainerHorizontal: { + flexDirection: 'row', + }, +}); + +type RefForwarder = { + getForwardingRef: ( + ?React.RefSetter, + ) => (TNativeInstance | null) => void, + nativeInstance: TNativeInstance | null, + publicInstance: TPublicInstance | null, +}; + +/** + * Helper function that should be replaced with `useCallback` and `useMergeRefs` + * once `ScrollView` is reimplemented as a functional component. + */ +function createRefForwarder( + mutator: TNativeInstance => TPublicInstance, +): RefForwarder { + const state: RefForwarder = { + getForwardingRef: memoize(forwardedRef => { + return (nativeInstance: TNativeInstance | null): void => { + const publicInstance = + nativeInstance == null ? null : mutator(nativeInstance); + + state.nativeInstance = nativeInstance; + state.publicInstance = publicInstance; + + if (forwardedRef != null) { + if (typeof forwardedRef === 'function') { + forwardedRef(publicInstance); + } else { + forwardedRef.current = publicInstance; + } + } + }; + }), + nativeInstance: null, + publicInstance: null, + }; + + return state; +} + +// TODO: After upgrading to React 19, remove `forwardRef` from this component. +// NOTE: This wrapper component is necessary because `ScrollView` is a class +// component and we need to map `ref` to a differently named prop. This can be +// removed when `ScrollView` is a functional component. +const Wrapper: component( + ref: React.RefSetter, + ...props: Props +) = React.forwardRef(function Wrapper( + props: Props, + ref: ?React.RefSetter, +): React.Node { + return ref == null ? ( + + ) : ( + + ); +}); +Wrapper.displayName = 'ScrollView'; +// $FlowExpectedError[prop-missing] +Wrapper.Context = ScrollViewContext; + +module.exports = ((Wrapper: $FlowFixMe): typeof Wrapper & + ScrollViewComponentStatics); From 118222e7b9edbd78ecf060ee47afeea476d1d901 Mon Sep 17 00:00:00 2001 From: Chiara Mooney <34109996+chiaramooney@users.noreply.github.com> Date: Wed, 19 Mar 2025 10:18:54 -0700 Subject: [PATCH 4/7] Update Change Files --- ...t-native-windows-56f137a7-212a-483c-9771-7bf7c0fad2a8.json | 4 ++-- ...t-native-windows-7d072016-5414-4327-b40c-a149c1dc34b9.json | 4 ++-- ...t-native-windows-d334336e-c641-4b9e-bbd3-9c6dd4f5b228.json | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/change/react-native-windows-56f137a7-212a-483c-9771-7bf7c0fad2a8.json b/change/react-native-windows-56f137a7-212a-483c-9771-7bf7c0fad2a8.json index 4e52914ba5c..235de4de3ee 100644 --- a/change/react-native-windows-56f137a7-212a-483c-9771-7bf7c0fad2a8.json +++ b/change/react-native-windows-56f137a7-212a-483c-9771-7bf7c0fad2a8.json @@ -1,7 +1,7 @@ { - "type": "prerelease", + "type": "patch", "comment": "Add Support for Role Prop", "packageName": "react-native-windows", "email": "34109996+chiaramooney@users.noreply.github.com", "dependentChangeType": "patch" -} +} \ No newline at end of file diff --git a/change/react-native-windows-7d072016-5414-4327-b40c-a149c1dc34b9.json b/change/react-native-windows-7d072016-5414-4327-b40c-a149c1dc34b9.json index 7f23502a86e..0f95aad40d3 100644 --- a/change/react-native-windows-7d072016-5414-4327-b40c-a149c1dc34b9.json +++ b/change/react-native-windows-7d072016-5414-4327-b40c-a149c1dc34b9.json @@ -1,7 +1,7 @@ { - "type": "prerelease", + "type": "patch", "comment": "Add IScrollProvider Implementation", "packageName": "react-native-windows", "email": "34109996+chiaramooney@users.noreply.github.com", "dependentChangeType": "patch" -} +} \ No newline at end of file diff --git a/change/react-native-windows-d334336e-c641-4b9e-bbd3-9c6dd4f5b228.json b/change/react-native-windows-d334336e-c641-4b9e-bbd3-9c6dd4f5b228.json index f68dfc5830b..f610408e7f3 100644 --- a/change/react-native-windows-d334336e-c641-4b9e-bbd3-9c6dd4f5b228.json +++ b/change/react-native-windows-d334336e-c641-4b9e-bbd3-9c6dd4f5b228.json @@ -1,7 +1,7 @@ { - "type": "prerelease", + "type": "patch", "comment": "ITextProvider Implementation", "packageName": "react-native-windows", "email": "34109996+chiaramooney@users.noreply.github.com", "dependentChangeType": "patch" -} +} \ No newline at end of file From c9c51c9fbec060cba266939760687b84a2cb7535 Mon Sep 17 00:00:00 2001 From: Chiara Mooney <34109996+chiaramooney@users.noreply.github.com> Date: Thu, 20 Mar 2025 11:21:42 -0700 Subject: [PATCH 5/7] Resolve Merge Conflict --- .../Composition/CompositionDynamicAutomationProvider.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp index 384170cb797..138aef62810 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp @@ -1,17 +1,9 @@ #include "pch.h" #include "CompositionDynamicAutomationProvider.h" #include -<<<<<<< HEAD -#include -#include -======= -<<<<<<< HEAD -======= #include #include #include ->>>>>>> 70823b2f70 ([Fabric] Add Support for ScrollProvider (#14411)) ->>>>>>> 0a726428ac ([Fabric] Add Support for ScrollProvider (#14411)) #include #include #include From fb146925b70a40dfc30e35f7b2963afc2b988edc Mon Sep 17 00:00:00 2001 From: Chiara Mooney <34109996+chiaramooney@users.noreply.github.com> Date: Thu, 20 Mar 2025 13:55:14 -0700 Subject: [PATCH 6/7] Fix Merge --- .../windows/RNTesterApp-Fabric/RNTesterApp-Fabric.cpp | 1 + 1 file changed, 1 insertion(+) 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 974b44236ba..7cff87dadb2 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 @@ -364,6 +364,7 @@ void DumpUIAPatternInfo(IUIAutomationElement *pTarget, const winrt::Windows::Dat BOOL multipleSelection; BOOL selectionRequired; BSTR text = nullptr; + BOOL horizontallyScrollable; // Dump IValueProvider Information IValueProvider *valuePattern; From aabb8a91f600a0e4ed267158ba88ed297bc507c9 Mon Sep 17 00:00:00 2001 From: Chiara Mooney <34109996+chiaramooney@users.noreply.github.com> Date: Thu, 20 Mar 2025 14:53:21 -0700 Subject: [PATCH 7/7] Update Snapshots --- .../AccessibilityTest.test.ts.snap | 57 ++++++++++++++----- .../__snapshots__/HomeUIADump.test.ts.snap | 2 + 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/AccessibilityTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/AccessibilityTest.test.ts.snap index 6101cd246c9..cf7f392168f 100644 --- a/packages/e2e-test-app-fabric/test/__snapshots__/AccessibilityTest.test.ts.snap +++ b/packages/e2e-test-app-fabric/test/__snapshots__/AccessibilityTest.test.ts.snap @@ -251,25 +251,52 @@ exports[`Accessibility Tests Selectable items must have a Selection Container. E "Name": "List of selectable items", "__Children": [ { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Unselected", - "TextRangePattern.GetText": "Unselected", + "AutomationId": "Selectable item 1", + "ControlType": 50000, + "IsKeyboardFocusable": true, + "LocalizedControlType": "button", + "Name": "Selectable item 1", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Unselected", + "TextRangePattern.GetText": "Unselected", + }, + ], }, { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Unselected", - "TextRangePattern.GetText": "Unselected", + "AutomationId": "Selectable item 2", + "ControlType": 50000, + "IsKeyboardFocusable": true, + "LocalizedControlType": "button", + "Name": "Selectable item 2", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Unselected", + "TextRangePattern.GetText": "Unselected", + }, + ], }, { - "AutomationId": "", - "ControlType": 50020, - "LocalizedControlType": "text", - "Name": "Unselected", - "TextRangePattern.GetText": "Unselected", + "AutomationId": "Selectable item 3", + "ControlType": 50000, + "IsKeyboardFocusable": true, + "LocalizedControlType": "button", + "Name": "Selectable item 3", + "__Children": [ + { + "AutomationId": "", + "ControlType": 50020, + "LocalizedControlType": "text", + "Name": "Unselected", + "TextRangePattern.GetText": "Unselected", + }, + ], }, ], }, 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 ce44c67c6fb..9861f83e39e 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 @@ -6520,12 +6520,14 @@ exports[`Home UIA Tree Dump Xaml WinUI3 (Experimental, for Fabric) 1`] = ` "ControlType": 50020, "LocalizedControlType": "text", "Name": "Xaml WinUI3 (Experimental, for Fabric)", + "TextRangePattern.GetText": "Xaml WinUI3 (Experimental, for Fabric)", }, { "AutomationId": "", "ControlType": 50020, "LocalizedControlType": "text", "Name": "Requires UseExperimentalWinUI3 - Xaml content that works in Fabric", + "TextRangePattern.GetText": "Requires UseExperimentalWinUI3 - Xaml content that works in Fabric", }, ], },