From bb4808bc92af250c2a111bc0fa750ee2cc0cdb97 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Fri, 11 Sep 2026 09:13:53 -0700 Subject: [PATCH 1/3] 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 671b95e9ff46847cadf6b41d5db7c7f75fe1d828 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Fri, 11 Sep 2026 09:13:53 -0700 Subject: [PATCH 2/3] Add deep-link Maestro flows for RNTester lists 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 ? ( From a9b29fa940b4bc7b63c836ead2e915b7d2ecbb93 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Fri, 11 Sep 2026 09:13:53 -0700 Subject: [PATCH 3/3] Deep-link RNTester Pressable and Modal Maestro flows Summary: Update the existing Pressable and Modal Maestro flows to open their RNTester examples directly. Extend the Pressable flow to cover content presses, feedback events, hit slop, and text presses. Changelog: [Internal] Differential Revision: D119484761 --- packages/rn-tester/.maestro/modal.yml | 26 ++++++----- packages/rn-tester/.maestro/pressable.yml | 57 ++++++++++++++--------- 2 files changed, 49 insertions(+), 34 deletions(-) diff --git a/packages/rn-tester/.maestro/modal.yml b/packages/rn-tester/.maestro/modal.yml index e3b7bef53886..fcfafc715495 100644 --- a/packages/rn-tester/.maestro/modal.yml +++ b/packages/rn-tester/.maestro/modal.yml @@ -6,20 +6,22 @@ appId: ${APP_ID} # iOS: com.meta.RNTester.localDevelopment | Android: com.facebo - extendedWaitUntil: visible: 'Components' timeout: 30000 -- scrollUntilVisible: - element: - id: 'Modal' - direction: DOWN - speed: 60 +- openLink: rntester://example/Modal/onShow +- extendedWaitUntil: + visible: + id: 'open-modal' + timeout: 10000 - tapOn: - id: 'Modal' + id: 'open-modal' - assertVisible: - text: 'Show Modal' -- tapOn: - text: 'Show Modal' + id: 'dismiss-modal' - assertVisible: - text: 'Close' + id: 'modal-on-show-count' + text: 'onShow is called 1 times' - tapOn: - text: 'Close' + id: 'dismiss-modal' +- assertNotVisible: + id: 'dismiss-modal' - assertVisible: - text: 'Show Modal' + id: 'on-show-count' + text: 'onShow is called 1 times' diff --git a/packages/rn-tester/.maestro/pressable.yml b/packages/rn-tester/.maestro/pressable.yml index 86a8b2b00231..2cc66d3f6348 100644 --- a/packages/rn-tester/.maestro/pressable.yml +++ b/packages/rn-tester/.maestro/pressable.yml @@ -1,37 +1,31 @@ appId: ${APP_ID} # iOS: com.meta.RNTester.localDevelopment | Android: com.facebook.react.uiapp --- -- runFlow: ./helpers/launch-app-and-search.yml -- inputText: - text: 'Pressable' -- assertVisible: - id: 'Pressable' -- tapOn: - id: 'Pressable' -- assertVisible: - text: 'Change content based on Press' -- assertVisible: - text: 'Change style based on Press' +- launchApp +- extendedWaitUntil: + visible: 'Components' + timeout: 30000 +- openLink: rntester://example/PressableExample/content-press +- extendedWaitUntil: + visible: + id: 'one_press_me_button' + timeout: 10000 - tapOn: id: 'one_press_me_button' - assertVisible: + id: 'pressable_press_console' text: 'onPress' - tapOn: id: 'one_press_me_button' - assertVisible: + id: 'pressable_press_console' text: '2x onPress' -- scrollUntilVisible: - element: - id: 'pressable_feedback_events' - direction: DOWN - speed: 10 - visibilityPercentage: 100 +- openLink: rntester://example/PressableExample/feedback-events +- extendedWaitUntil: + visible: + id: 'pressable_feedback_events_button' + timeout: 10000 - tapOn: id: 'pressable_feedback_events_button' -- scrollUntilVisible: - element: - text: 'pressIn' - direction: DOWN - speed: 10 - assertVisible: text: 'press' - assertVisible: @@ -44,3 +38,22 @@ appId: ${APP_ID} # iOS: com.meta.RNTester.localDevelopment | Android: com.facebo text: 'longPress' - assertVisible: text: 'pressOut' +- openLink: rntester://example/PressableExample/hit-slop +- extendedWaitUntil: + visible: + id: 'pressable_hit_slop_button' + timeout: 10000 +- tapOn: + id: 'pressable_hit_slop_button' +- assertVisible: + id: 'pressable_hit_slop' +- openLink: rntester://example/PressableExample/text-press +- extendedWaitUntil: + visible: + id: 'tappable_text' + timeout: 10000 +- tapOn: + id: 'tappable_text' +- assertVisible: + id: 'tappable_text_console' + text: 'text onPress'