From c7e05e1c7f971c9360c159a3f92d4c57a1c8969f Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Wed, 16 Sep 2026 12:00:22 -0700 Subject: [PATCH 1/2] Add deep-link Maestro flows for RNTester basics (#58480) Summary: Add Maestro coverage for portable RNTester interaction scenarios using direct example deep links. The flows cover alerts, animations, appearance, filters, text input, and touchables without screenshot baselines. Changelog: [Internal] Differential Revision: D119484759 --- packages/rn-tester/.maestro/alert.yml | 24 ++++++++++ .../.maestro/animated-fade-in-view.yml | 21 +++++++++ packages/rn-tester/.maestro/appearance.yml | 14 ++++++ .../.maestro/filter-animated-blur.yml | 15 +++++++ .../.maestro/textinput-uncontrolled.yml | 19 ++++++++ packages/rn-tester/.maestro/touchable.yml | 44 +++++++++++++++++++ 6 files changed, 137 insertions(+) create mode 100644 packages/rn-tester/.maestro/alert.yml create mode 100644 packages/rn-tester/.maestro/animated-fade-in-view.yml create mode 100644 packages/rn-tester/.maestro/appearance.yml create mode 100644 packages/rn-tester/.maestro/filter-animated-blur.yml create mode 100644 packages/rn-tester/.maestro/textinput-uncontrolled.yml create mode 100644 packages/rn-tester/.maestro/touchable.yml diff --git a/packages/rn-tester/.maestro/alert.yml b/packages/rn-tester/.maestro/alert.yml new file mode 100644 index 000000000000..513029744ee8 --- /dev/null +++ b/packages/rn-tester/.maestro/alert.yml @@ -0,0 +1,24 @@ +appId: ${APP_ID} # iOS: com.meta.RNTester.localDevelopment | Android: com.facebook.react.uiapp +--- +- launchApp +- extendedWaitUntil: + visible: 'Components' + timeout: 30000 +- openLink: rntester://example/AlertExample/default-button +- extendedWaitUntil: + visible: + id: 'alert-with-default-button' + timeout: 10000 +- tapOn: + id: 'alert-with-default-button' +- assertVisible: 'An external USB drive has been detected!' +- tapOn: 'OK' +- openLink: rntester://example/AlertExample/three-buttons +- extendedWaitUntil: + visible: + id: 'alert-with-three-buttons' + timeout: 10000 +- tapOn: + id: 'alert-with-three-buttons' +- assertVisible: 'Do you want to save your changes?' +- tapOn: 'Cancel' diff --git a/packages/rn-tester/.maestro/animated-fade-in-view.yml b/packages/rn-tester/.maestro/animated-fade-in-view.yml new file mode 100644 index 000000000000..e7b96d2e4794 --- /dev/null +++ b/packages/rn-tester/.maestro/animated-fade-in-view.yml @@ -0,0 +1,21 @@ +appId: ${APP_ID} # iOS: com.meta.RNTester.localDevelopment | Android: com.facebook.react.uiapp +--- +- launchApp +- extendedWaitUntil: + visible: 'Components' + timeout: 30000 +- openLink: rntester://example/Animated/fadeInView +- extendedWaitUntil: + visible: + id: 'toggle-button' + timeout: 10000 +- assertVisible: + id: 'fade-in-view' +- tapOn: + id: 'toggle-button' +- assertNotVisible: + id: 'fade-in-view' +- tapOn: + id: 'toggle-button' +- assertVisible: + id: 'fade-in-view' diff --git a/packages/rn-tester/.maestro/appearance.yml b/packages/rn-tester/.maestro/appearance.yml new file mode 100644 index 000000000000..08c022a98951 --- /dev/null +++ b/packages/rn-tester/.maestro/appearance.yml @@ -0,0 +1,14 @@ +appId: ${APP_ID} # iOS: com.meta.RNTester.localDevelopment | Android: com.facebook.react.uiapp +--- +- launchApp +- extendedWaitUntil: + visible: 'Components' + timeout: 30000 +- assertVisible: + id: 'components-tab' +- assertVisible: + id: 'apis-tab' +- openLink: rntester://example/AppearanceExample +- extendedWaitUntil: + visible: 'useColorScheme hook' + timeout: 10000 diff --git a/packages/rn-tester/.maestro/filter-animated-blur.yml b/packages/rn-tester/.maestro/filter-animated-blur.yml new file mode 100644 index 000000000000..b3e9368c652e --- /dev/null +++ b/packages/rn-tester/.maestro/filter-animated-blur.yml @@ -0,0 +1,15 @@ +appId: ${APP_ID} # iOS: com.meta.RNTester.localDevelopment | Android: com.facebook.react.uiapp +--- +- launchApp +- extendedWaitUntil: + visible: 'Components' + timeout: 30000 +- openLink: rntester://example/Filter/animated-blur +- extendedWaitUntil: + visible: + id: 'animated-blur-button' + timeout: 10000 +- tapOn: + id: 'animated-blur-button' +- assertVisible: + id: 'animated-blur-view' diff --git a/packages/rn-tester/.maestro/textinput-uncontrolled.yml b/packages/rn-tester/.maestro/textinput-uncontrolled.yml new file mode 100644 index 000000000000..ff85bbe42833 --- /dev/null +++ b/packages/rn-tester/.maestro/textinput-uncontrolled.yml @@ -0,0 +1,19 @@ +appId: ${APP_ID} # iOS: com.meta.RNTester.localDevelopment | Android: com.facebook.react.uiapp +--- +- launchApp +- extendedWaitUntil: + visible: 'Components' + timeout: 30000 +- openLink: rntester://example/TextInput/uncontrolledComponent +- extendedWaitUntil: + visible: + id: 'uncontrolled-textinput' + timeout: 10000 +- tapOn: + id: 'uncontrolled-textinput' +- eraseText +- inputText: 'New value' +- hideKeyboard +- assertVisible: + id: 'uncontrolled-textinput' + text: 'New value' diff --git a/packages/rn-tester/.maestro/touchable.yml b/packages/rn-tester/.maestro/touchable.yml new file mode 100644 index 000000000000..b027f447cdfc --- /dev/null +++ b/packages/rn-tester/.maestro/touchable.yml @@ -0,0 +1,44 @@ +appId: ${APP_ID} # iOS: com.meta.RNTester.localDevelopment | Android: com.facebook.react.uiapp +--- +- launchApp +- extendedWaitUntil: + visible: 'Components' + timeout: 30000 +- openLink: rntester://example/TouchableExample/feedback-events +- extendedWaitUntil: + visible: + id: 'touchable_feedback_events_button' + timeout: 10000 +- tapOn: + id: 'touchable_feedback_events_button' +- assertVisible: + id: 'touchable_feedback_events_console' +- openLink: rntester://example/TouchableExample/highlight +- extendedWaitUntil: + visible: + id: 'touchable_highlight_text_button' + timeout: 10000 +- tapOn: + id: 'touchable_highlight_text_button' +- assertVisible: + id: 'touchable_highlight_console' + text: 'TouchableHighlight onPress' +- openLink: rntester://example/TouchableExample/hit-slop +- extendedWaitUntil: + visible: + id: 'touchable_hit_slop_button' + timeout: 10000 +- tapOn: + id: 'touchable_hit_slop_button' +- assertVisible: + id: 'touchable_hit_slop' +- openLink: rntester://example/TouchableExample/without-feedback +- extendedWaitUntil: + visible: + id: 'touchable_without_feedback_button' + timeout: 10000 +- tapOn: + id: 'touchable_without_feedback_button' +- assertVisible: + id: 'touchable_without_feedback_console' + text: 'TouchableWithoutFeedback onPress' From 79568b44e97075cb68c5824211a280859f46a1a8 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Wed, 16 Sep 2026 12:00:22 -0700 Subject: [PATCH 2/2] Add deep-link Maestro flows for RNTester lists (#58481) Summary: Add Maestro coverage for FlatList and SectionList viewability behavior using direct RNTester example deep links. Use explicit gestures inside the virtualized lists and wait for the callback output. Add nonvisual, route-specific readiness IDs so successive deep links cannot match the previously mounted list. Changelog: [Internal] Differential Revision: D119484760 --- .../.maestro/flatlist-viewability.yml | 48 ++++++++++++++ .../.maestro/sectionlist-viewability.yml | 62 +++++++++++++++++++ .../examples/FlatList/BaseFlatListExample.js | 3 +- .../FlatList-BaseOnViewableItemsChanged.js | 4 ++ .../SectionList-BaseOnViewableItemsChanged.js | 4 ++ .../SectionList/SectionListBaseExample.js | 3 +- 6 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 packages/rn-tester/.maestro/flatlist-viewability.yml create mode 100644 packages/rn-tester/.maestro/sectionlist-viewability.yml diff --git a/packages/rn-tester/.maestro/flatlist-viewability.yml b/packages/rn-tester/.maestro/flatlist-viewability.yml new file mode 100644 index 000000000000..14fcee0b95ae --- /dev/null +++ b/packages/rn-tester/.maestro/flatlist-viewability.yml @@ -0,0 +1,48 @@ +appId: ${APP_ID} # iOS: com.meta.RNTester.localDevelopment | Android: com.facebook.react.uiapp +--- +- launchApp +- extendedWaitUntil: + visible: 'Components' + timeout: 30000 +- openLink: rntester://example/FlatListExample/onViewableItemsChanged-horizontal-noWaitForInteraction +- extendedWaitUntil: + visible: + id: 'flat-list-viewability-horizontal-no-wait' + timeout: 10000 +- assertVisible: + id: 'output' + text: '.*Pizza, Burger.*' +- openLink: rntester://example/FlatListExample/onViewableItemsChanged-horizontal-waitForInteraction +- extendedWaitUntil: + visible: + id: 'flat-list-viewability-horizontal-wait' + timeout: 10000 +- repeat: + times: 3 + commands: + - swipe: + start: 90%, 50% + end: 10%, 50% + speed: fast +- extendedWaitUntil: + visible: + id: 'output' + text: '.*Cheesecake.*' + timeout: 10000 +- openLink: rntester://example/FlatListExample/onViewableItemsChanged-waitForInteraction +- extendedWaitUntil: + visible: + id: 'flat-list-viewability-vertical-wait' + timeout: 10000 +- repeat: + times: 2 + commands: + - swipe: + start: 50%, 80% + end: 50%, 20% + speed: fast +- extendedWaitUntil: + visible: + id: 'output' + text: '.*Cheesecake, Brownie.*' + timeout: 10000 diff --git a/packages/rn-tester/.maestro/sectionlist-viewability.yml b/packages/rn-tester/.maestro/sectionlist-viewability.yml new file mode 100644 index 000000000000..2057475b5be4 --- /dev/null +++ b/packages/rn-tester/.maestro/sectionlist-viewability.yml @@ -0,0 +1,62 @@ +appId: ${APP_ID} # iOS: com.meta.RNTester.localDevelopment | Android: com.facebook.react.uiapp +--- +- launchApp +- extendedWaitUntil: + visible: 'Components' + timeout: 30000 +- openLink: rntester://example/SectionList/onEndReached +- extendedWaitUntil: + visible: + id: 'start_test' + timeout: 10000 +- tapOn: + id: 'start_test' +- assertVisible: + id: 'output' + text: 'onEndReached' +- openLink: rntester://example/SectionList/onViewableItemsChanged-horizontal-noWaitForInteraction +- extendedWaitUntil: + visible: + id: 'section-list-viewability-horizontal-no-wait' + timeout: 10000 +- assertVisible: + id: 'output' + text: '.*Pizza.*' +- openLink: rntester://example/SectionList/onViewableItemsChanged-horizontal-waitForInteraction +- extendedWaitUntil: + visible: + id: 'section-list-viewability-horizontal-wait' + timeout: 10000 +- repeat: + times: 3 + commands: + - swipe: + start: 90%, 50% + end: 10%, 50% + speed: fast +- extendedWaitUntil: + visible: + id: 'output' + text: '.*Cheesecake.*' + timeout: 10000 +- runFlow: + when: + platform: Android + commands: + - openLink: rntester://example/SectionList/onViewableItemsChanged-waitForInteraction + - extendedWaitUntil: + visible: + id: 'section-list-viewability-vertical-wait' + timeout: 10000 + - repeat: + times: 3 + commands: + - swipe: + start: 50%, 80% + end: 50%, 20% + speed: fast + - extendedWaitUntil: + visible: + id: 'output' + text: '.*Cheesecake.*' + timeout: 10000 diff --git a/packages/rn-tester/js/examples/FlatList/BaseFlatListExample.js b/packages/rn-tester/js/examples/FlatList/BaseFlatListExample.js index 11fffe822a9c..1c77581facfd 100644 --- a/packages/rn-tester/js/examples/FlatList/BaseFlatListExample.js +++ b/packages/rn-tester/js/examples/FlatList/BaseFlatListExample.js @@ -61,6 +61,7 @@ const Item = ({item, separators}: ListRenderItemInfo) => { type Props = Readonly<{ exampleProps: Partial>, + exampleTestID?: ?string, onTest?: ?() => void, testLabel?: ?string, testOutput?: ?string, @@ -72,7 +73,7 @@ const BaseFlatListExample: component( ...props: Props ) = ({ref, ...props}: {ref: React.RefSetter>, ...Props}) => { return ( - + {props.testOutput != null ? ( diff --git a/packages/rn-tester/js/examples/FlatList/FlatList-BaseOnViewableItemsChanged.js b/packages/rn-tester/js/examples/FlatList/FlatList-BaseOnViewableItemsChanged.js index fb555cfe99a9..0d967cb3deed 100644 --- a/packages/rn-tester/js/examples/FlatList/FlatList-BaseOnViewableItemsChanged.js +++ b/packages/rn-tester/js/examples/FlatList/FlatList-BaseOnViewableItemsChanged.js @@ -32,6 +32,9 @@ export function FlatList_BaseOnViewableItemsChanged(props: { waitForInteraction?: ?boolean, }): React.Node { const {offScreen, horizontal, useScrollRefScroll, waitForInteraction} = props; + const exampleTestID = `flat-list-viewability-${ + horizontal === true ? 'horizontal' : 'vertical' + }-${waitForInteraction === true ? 'wait' : 'no-wait'}`; const [output, setOutput] = useState(''); const onViewableItemsChanged = useCallback( (info: {changed: Array, viewableItems: Array, ...}) => @@ -65,6 +68,7 @@ export function FlatList_BaseOnViewableItemsChanged(props: { {offScreen === true ? : null} diff --git a/packages/rn-tester/js/examples/SectionList/SectionList-BaseOnViewableItemsChanged.js b/packages/rn-tester/js/examples/SectionList/SectionList-BaseOnViewableItemsChanged.js index bb075043f438..bfebad3f0a9e 100644 --- a/packages/rn-tester/js/examples/SectionList/SectionList-BaseOnViewableItemsChanged.js +++ b/packages/rn-tester/js/examples/SectionList/SectionList-BaseOnViewableItemsChanged.js @@ -30,6 +30,9 @@ export function SectionList_BaseOnViewableItemsChanged(props: { waitForInteraction?: ?boolean, }): React.Node { const {offScreen, horizontal, useScrollRefScroll, waitForInteraction} = props; + const exampleTestID = `section-list-viewability-${ + horizontal === true ? 'horizontal' : 'vertical' + }-${waitForInteraction === true ? 'wait' : 'no-wait'}`; const [output, setOutput] = useState(''); const viewabilityConfig: ViewabilityConfig = { ...BASE_VIEWABILITY_CONFIG, @@ -62,6 +65,7 @@ export function SectionList_BaseOnViewableItemsChanged(props: { {offScreen === true ? : null} diff --git a/packages/rn-tester/js/examples/SectionList/SectionListBaseExample.js b/packages/rn-tester/js/examples/SectionList/SectionListBaseExample.js index d4de9daae6c5..21c42c0ca641 100644 --- a/packages/rn-tester/js/examples/SectionList/SectionListBaseExample.js +++ b/packages/rn-tester/js/examples/SectionList/SectionListBaseExample.js @@ -67,6 +67,7 @@ const Item = ({item, section, separators}) => { type Props = Readonly<{ // $FlowFixMe[unclear-type] exampleProps: Partial>>, + exampleTestID?: ?string, onTest?: ?() => void, testLabel?: ?string, testOutput?: ?string, @@ -86,7 +87,7 @@ const SectionListBaseExample: component( ...Props, }): React.Node => { return ( - + {props.testOutput != null ? (