diff --git a/.github/workflows/maestro-cloud-rntester.yml b/.github/workflows/maestro-cloud-rntester.yml index 7f245bbcbebf..7c2afc24ea8b 100644 --- a/.github/workflows/maestro-cloud-rntester.yml +++ b/.github/workflows/maestro-cloud-rntester.yml @@ -46,7 +46,7 @@ jobs: test: name: Maestro Cloud ${{ inputs.platform }} RNTester runs-on: ubuntu-latest - timeout-minutes: 75 + timeout-minutes: 105 steps: - name: Checkout uses: actions/checkout@v6 @@ -84,7 +84,7 @@ jobs: env: | APP_ID=${{ inputs.app-id }} maestro-cli-version: 2.6.1 - timeout: 60 + timeout: 90 - name: Check Maestro Cloud result if: always() env: diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml index c138cd5730fa..97083115acac 100644 --- a/.github/workflows/test-all.yml +++ b/.github/workflows/test-all.yml @@ -186,7 +186,7 @@ jobs: app-id: com.meta.RNTester.localDevelopment device-model: iPhone-17-Pro device-os: iOS-26-2 - exclude-tags: android-only + exclude-tags: android-only,local-screenshot-baseline secrets: inherit test_e2e_ios_rntester: diff --git a/packages/rn-tester/.maestro/alert.yml b/packages/rn-tester/.maestro/alert.yml new file mode 100644 index 000000000000..a8892ddc5da6 --- /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 +- stopApp +- openLink: rntester://example/AlertExample/default-button +- runFlow: ./helpers/confirm-open-link.yml +- extendedWaitUntil: + visible: + id: 'alert-with-default-button' + timeout: 120000 +- tapOn: + id: 'alert-with-default-button' +- assertVisible: 'An external USB drive has been detected!' +- tapOn: 'OK' +- openLink: rntester://example/AlertExample/three-buttons +- runFlow: ./helpers/confirm-open-link.yml +- extendedWaitUntil: + visible: + id: 'alert-with-three-buttons' + timeout: 30000 +- 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..d71c1b2d2ceb --- /dev/null +++ b/packages/rn-tester/.maestro/animated-fade-in-view.yml @@ -0,0 +1,20 @@ +appId: ${APP_ID} # iOS: com.meta.RNTester.localDevelopment | Android: com.facebook.react.uiapp +--- +- launchApp +- stopApp +- openLink: rntester://example/Animated/fadeInView +- runFlow: ./helpers/confirm-open-link.yml +- extendedWaitUntil: + visible: + id: 'toggle-button' + timeout: 120000 +- 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..18a1f6cc4d8f --- /dev/null +++ b/packages/rn-tester/.maestro/appearance.yml @@ -0,0 +1,9 @@ +appId: ${APP_ID} # iOS: com.meta.RNTester.localDevelopment | Android: com.facebook.react.uiapp +--- +- launchApp +- stopApp +- openLink: rntester://example/AppearanceExample +- runFlow: ./helpers/confirm-open-link.yml +- extendedWaitUntil: + visible: 'useColorScheme hook' + timeout: 120000 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..158794ca7988 --- /dev/null +++ b/packages/rn-tester/.maestro/filter-animated-blur.yml @@ -0,0 +1,14 @@ +appId: ${APP_ID} # iOS: com.meta.RNTester.localDevelopment | Android: com.facebook.react.uiapp +--- +- launchApp +- stopApp +- openLink: rntester://example/Filter/animated-blur +- runFlow: ./helpers/confirm-open-link.yml +- extendedWaitUntil: + visible: + id: 'animated-blur-button' + timeout: 120000 +- tapOn: + id: 'animated-blur-button' +- assertVisible: + id: 'animated-blur-view' diff --git a/packages/rn-tester/.maestro/flatlist-viewability.yml b/packages/rn-tester/.maestro/flatlist-viewability.yml new file mode 100644 index 000000000000..d40f2633a118 --- /dev/null +++ b/packages/rn-tester/.maestro/flatlist-viewability.yml @@ -0,0 +1,51 @@ +appId: ${APP_ID} # iOS: com.meta.RNTester.localDevelopment | Android: com.facebook.react.uiapp +--- +- launchApp +- stopApp +- openLink: rntester://example/FlatListExample/onViewableItemsChanged-horizontal-noWaitForInteraction +- runFlow: ./helpers/confirm-open-link.yml +- extendedWaitUntil: + visible: + id: 'flat-list-viewability-horizontal-no-wait' + timeout: 120000 +- assertVisible: + id: 'output' + text: '.*Pizza, Burger.*' +- openLink: rntester://example/FlatListExample/onViewableItemsChanged-horizontal-waitForInteraction +- runFlow: ./helpers/confirm-open-link.yml +- extendedWaitUntil: + visible: + id: 'flat-list-viewability-horizontal-wait' + timeout: 30000 +- scrollUntilVisible: + element: + text: 'Cheesecake' + direction: RIGHT + speed: 60 + visibilityPercentage: 50 + centerElement: true + timeout: 60000 +- extendedWaitUntil: + visible: + id: 'output' + text: '.*Cheesecake.*' + timeout: 30000 +- openLink: rntester://example/FlatListExample/onViewableItemsChanged-waitForInteraction +- runFlow: ./helpers/confirm-open-link.yml +- extendedWaitUntil: + visible: + id: 'flat-list-viewability-vertical-wait' + timeout: 30000 +- scrollUntilVisible: + element: + text: 'Cheesecake' + direction: DOWN + speed: 60 + visibilityPercentage: 50 + centerElement: true + timeout: 60000 +- extendedWaitUntil: + visible: + id: 'output' + text: '.*Cheesecake, Brownie.*' + timeout: 30000 diff --git a/packages/rn-tester/.maestro/helpers/confirm-open-link.yml b/packages/rn-tester/.maestro/helpers/confirm-open-link.yml new file mode 100644 index 000000000000..1fa66d36dbcf --- /dev/null +++ b/packages/rn-tester/.maestro/helpers/confirm-open-link.yml @@ -0,0 +1,9 @@ +appId: ${APP_ID} # iOS: com.meta.RNTester.localDevelopment | Android: com.facebook.react.uiapp +--- +- runFlow: + when: + platform: iOS + commands: + - tapOn: + text: 'Open' + optional: true diff --git a/packages/rn-tester/.maestro/sectionlist-viewability.yml b/packages/rn-tester/.maestro/sectionlist-viewability.yml new file mode 100644 index 000000000000..575ea2f7cb01 --- /dev/null +++ b/packages/rn-tester/.maestro/sectionlist-viewability.yml @@ -0,0 +1,66 @@ +appId: ${APP_ID} # iOS: com.meta.RNTester.localDevelopment | Android: com.facebook.react.uiapp +--- +- launchApp +- stopApp +- openLink: rntester://example/SectionList/onEndReached +- runFlow: ./helpers/confirm-open-link.yml +- extendedWaitUntil: + visible: + id: 'start_test' + timeout: 120000 +- tapOn: + id: 'start_test' +- assertVisible: + id: 'output' + text: 'onEndReached' +- openLink: rntester://example/SectionList/onViewableItemsChanged-horizontal-noWaitForInteraction +- runFlow: ./helpers/confirm-open-link.yml +- extendedWaitUntil: + visible: + id: 'section-list-viewability-horizontal-no-wait' + timeout: 30000 +- assertVisible: + id: 'output' + text: '.*Pizza.*' +- openLink: rntester://example/SectionList/onViewableItemsChanged-horizontal-waitForInteraction +- runFlow: ./helpers/confirm-open-link.yml +- extendedWaitUntil: + visible: + id: 'section-list-viewability-horizontal-wait' + timeout: 30000 +- scrollUntilVisible: + element: + text: 'Cheesecake' + direction: RIGHT + speed: 60 + visibilityPercentage: 50 + centerElement: true + timeout: 60000 +- extendedWaitUntil: + visible: + id: 'output' + text: '.*Cheesecake.*' + timeout: 30000 +- runFlow: + when: + platform: Android + commands: + - openLink: rntester://example/SectionList/onViewableItemsChanged-waitForInteraction + - runFlow: ./helpers/confirm-open-link.yml + - extendedWaitUntil: + visible: + id: 'section-list-viewability-vertical-wait' + timeout: 30000 + - scrollUntilVisible: + element: + text: 'Cheesecake' + direction: DOWN + speed: 60 + visibilityPercentage: 50 + centerElement: true + timeout: 60000 + - extendedWaitUntil: + visible: + id: 'output' + text: '.*Cheesecake.*' + timeout: 30000 diff --git a/packages/rn-tester/.maestro/textinput-uncontrolled.yml b/packages/rn-tester/.maestro/textinput-uncontrolled.yml new file mode 100644 index 000000000000..3e992b2acb3a --- /dev/null +++ b/packages/rn-tester/.maestro/textinput-uncontrolled.yml @@ -0,0 +1,18 @@ +appId: ${APP_ID} # iOS: com.meta.RNTester.localDevelopment | Android: com.facebook.react.uiapp +--- +- launchApp +- stopApp +- openLink: rntester://example/TextInput/uncontrolledComponent +- runFlow: ./helpers/confirm-open-link.yml +- extendedWaitUntil: + visible: + id: 'uncontrolled-textinput' + timeout: 120000 +- 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..ae2dcdb6ae68 --- /dev/null +++ b/packages/rn-tester/.maestro/touchable.yml @@ -0,0 +1,46 @@ +appId: ${APP_ID} # iOS: com.meta.RNTester.localDevelopment | Android: com.facebook.react.uiapp +--- +- launchApp +- stopApp +- openLink: rntester://example/TouchableExample/feedback-events +- runFlow: ./helpers/confirm-open-link.yml +- extendedWaitUntil: + visible: + id: 'touchable_feedback_events_button' + timeout: 120000 +- tapOn: + id: 'touchable_feedback_events_button' +- assertVisible: + id: 'touchable_feedback_events_console' +- openLink: rntester://example/TouchableExample/highlight +- runFlow: ./helpers/confirm-open-link.yml +- extendedWaitUntil: + visible: + id: 'touchable_highlight_text_button' + timeout: 30000 +- tapOn: + id: 'touchable_highlight_text_button' +- assertVisible: + id: 'touchable_highlight_console' + text: 'TouchableHighlight onPress' +- openLink: rntester://example/TouchableExample/hit-slop +- runFlow: ./helpers/confirm-open-link.yml +- extendedWaitUntil: + visible: + id: 'touchable_hit_slop_button' + timeout: 30000 +- tapOn: + id: 'touchable_hit_slop_button' +- assertVisible: + id: 'touchable_hit_slop' +- openLink: rntester://example/TouchableExample/without-feedback +- runFlow: ./helpers/confirm-open-link.yml +- extendedWaitUntil: + visible: + id: 'touchable_without_feedback_button' + timeout: 30000 +- tapOn: + id: 'touchable_without_feedback_button' +- assertVisible: + id: 'touchable_without_feedback_console' + text: 'TouchableWithoutFeedback onPress' 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 ? (