From ea06a3191f988fb12f49367486fe9855078a9d8e Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Tue, 25 Aug 2026 10:59:46 -0700 Subject: [PATCH] Stabilize Android E2E tests for ARM64 APKs (#58140) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Stabilizes the Android RNTester E2E jobs after switching their APKs to ARM64 while continuing to run the emulator on an x86_64 host. - Updates the Android wide-gamut screenshot baseline using the stable ARM64 result from the API 35 emulator. The emulator does not support wide color, so the Display-P3 fixture is converted to solid sRGB red. - Marks the FlatList `maintainVisibleContentPosition` flows as Android release-only. These flows remain fully covered by the release APK, where they consistently pass, while avoiding debug-only timing failures caused by running the ARM64 debug runtime through native translation. - Adds generic tag filtering to the Android Maestro runner and unit coverage for it. Across seven post-migration `main` runs, the release APK passed every FlatList flow, while the debug APK consistently dropped or delayed Maestro interactions and skipped up to 172 frames during startup. ## Changelog: [INTERNAL] [FIXED] - Stabilize Android RNTester E2E tests when running ARM64 APKs on x86_64 emulators. Pull Request resolved: https://github.com/react/react-native/pull/58140 Test Plan: - `./node_modules/.bin/jest .github/workflow-scripts/__tests__/maestro-android-test.js --runInBand --config='{"testEnvironment":"node","transform":{},"roots":["/.github/workflow-scripts"]}'` — passed (3 tests) - `maestro 2.6.1 check-syntax` for all 24 tagged FlatList flows — passed - Prettier check for all changed text files — passed - `git diff --check` — passed - Verified the filtered RNTester suite contains 16 debug flows and excludes 24 release-only FlatList MVCP flows - Compared the new baseline against ARM64 CI screenshots: exact match for release; debug RMSE 0.0024 - Manually exercised the ARM64 release APK on an API 35 ARM64 emulator at 320×640: FlatList offsets progressed as expected (`500 → 544 → 2744 → 4944 → 7144`), and five rapid prepends reached `11500` Related failing run: https://github.com/react/react-native/actions/runs/32821468795 Reviewed By: Abbondanzo Differential Revision: D117361459 Pulled By: cortinico fbshipit-source-id: 4514f8c42f7599c875672efe3c56aae7c9f0395c --- .github/actions/maestro-android/action.yml | 6 ++- .../__tests__/maestro-android-test.js | 21 ++++++++ .github/workflow-scripts/maestro-android.js | 46 ++++++++++++++++-- .github/workflows/e2e-android-rntester.yml | 4 ++ .../flatlist-append-maintainvisible.yml | 2 + ...list-complex-mutations-maintainvisible.yml | 2 + ...flatlist-delete-anchor-maintainvisible.yml | 2 + ...flatlist-delete-middle-maintainvisible.yml | 2 + .../flatlist-empty-list-maintainvisible.yml | 2 + ...flatlist-first-prepend-maintainvisible.yml | 2 + ...horizontal-add50-reset-maintainvisible.yml | 2 + ...st-horizontal-inverted-maintainvisible.yml | 2 + ...ontal-inverted-recycle-maintainvisible.yml | 2 + .../flatlist-horizontal-maintainvisible.yml | 2 + ...ist-horizontal-recycle-maintainvisible.yml | 2 + .../flatlist-inverted-maintainvisible.yml | 2 + ...tlist-inverted-recycle-maintainvisible.yml | 2 + .../.maestro/flatlist-maintainvisible.yml | 4 ++ ...atlist-momentum-scroll-maintainvisible.yml | 2 + .../flatlist-orientation-maintainvisible.yml | 2 + ...latlist-prepend-delete-maintainvisible.yml | 2 + ...atlist-pull-to-refresh-maintainvisible.yml | 2 + ...latlist-rapid-prepends-maintainvisible.yml | 2 + .../flatlist-recycle-maintainvisible.yml | 2 + ...latlist-scrolltooffset-maintainvisible.yml | 2 + .../flatlist-throttle-maintainvisible.yml | 2 + ...e-height-first-prepend-maintainvisible.yml | 2 + ...atlist-variable-height-maintainvisible.yml | 2 + .../rn-tester/.maestro/image-wide-gamut.yml | 4 +- .../screenshots/image-wide-gamut-android.png | Bin 18088 -> 17914 bytes 30 files changed, 125 insertions(+), 6 deletions(-) diff --git a/.github/actions/maestro-android/action.yml b/.github/actions/maestro-android/action.yml index 58a7351da64..7f760573c94 100644 --- a/.github/actions/maestro-android/action.yml +++ b/.github/actions/maestro-android/action.yml @@ -38,6 +38,10 @@ inputs: required: false default: /tmp/maestro-android-state/results.json description: The path used to persist per-flow test results between retries + exclude-tags: + required: false + default: '' + description: Comma-separated flow tags to exclude from the test run runs: using: composite @@ -77,7 +81,7 @@ runs: cores: '4' disable-animations: false avd-name: e2e_emulator - script: node .github/workflow-scripts/maestro-android.js ${{ inputs.app-path }} ${{ inputs.app-id }} ${{ inputs.maestro-flow }} ${{ inputs.flavor }} ${{ inputs.working-directory }} ${{ inputs.test-state-path }} + script: node .github/workflow-scripts/maestro-android.js ${{ inputs.app-path }} ${{ inputs.app-id }} ${{ inputs.maestro-flow }} ${{ inputs.flavor }} ${{ inputs.working-directory }} ${{ inputs.test-state-path }} "${{ inputs.exclude-tags }}" - name: Normalize APP_ID id: normalize-app-id shell: bash diff --git a/.github/workflow-scripts/__tests__/maestro-android-test.js b/.github/workflow-scripts/__tests__/maestro-android-test.js index 77b5711030b..c07def601b2 100644 --- a/.github/workflow-scripts/__tests__/maestro-android-test.js +++ b/.github/workflow-scripts/__tests__/maestro-android-test.js @@ -14,6 +14,7 @@ const path = require('path'); const { collectFlows, executeFlowSuite, + filterFlowsByTags, loadState, } = require('../maestro-android'); @@ -45,6 +46,26 @@ describe('Maestro Android runner', () => { ]); }); + it('excludes flows with matching tags', () => { + const releaseOnlyFlow = path.join( + temporaryDirectory, + 'android-release-only.yml', + ); + const regularFlow = path.join(temporaryDirectory, 'regular.yml'); + fs.writeFileSync( + releaseOnlyFlow, + 'appId: x\ntags:\n - android-release-only\n---\n- launchApp\n', + ); + fs.writeFileSync(regularFlow, 'appId: x\n---\n- launchApp\n'); + + expect( + filterFlowsByTags( + [releaseOnlyFlow, regularFlow], + ['android-release-only'], + ), + ).toEqual([regularFlow]); + }); + it('runs every flow and retries only flows that have not passed', () => { const flows = ['first.yml', 'second.yml', 'third.yml'].map(file => path.join(temporaryDirectory, file), diff --git a/.github/workflow-scripts/maestro-android.js b/.github/workflow-scripts/maestro-android.js index 7b2365512ef..d409afb42a5 100644 --- a/.github/workflow-scripts/maestro-android.js +++ b/.github/workflow-scripts/maestro-android.js @@ -13,7 +13,7 @@ const path = require('path'); const usage = ` === Usage === -node maestro-android.js [test_state_path] +node maestro-android.js [test_state_path] [exclude_tags] @param {string} appPath - Path to the app APK @param {string} appId - App ID that needs to be launched @@ -21,6 +21,7 @@ node maestro-android.js { + const tags = getFlowTags(flow); + const excludedTag = tags.find(tag => excludeTags.includes(tag)); + if (excludedTag != null) { + console.info(`Skipping flow tagged ${excludedTag}: ${flow}`); + return false; + } + return true; + }); +} + function getFlowKey(flow) { return path .relative(process.cwd(), path.resolve(flow)) @@ -274,7 +308,7 @@ function executeFlowSuite({ } async function main(args = process.argv.slice(2)) { - if (args.length < 5 || args.length > 6) { + if (args.length < 5 || args.length > 7) { throw new Error(`Invalid number of arguments.\n${usage}`); } @@ -284,6 +318,10 @@ async function main(args = process.argv.slice(2)) { const isDebug = args[3] === 'debug'; const workingDirectory = args[4]; const statePath = args[5] ?? DEFAULT_STATE_PATH; + const excludeTags = (args[6] ?? '') + .split(',') + .map(tag => tag.trim()) + .filter(Boolean); console.info('\n=============================='); console.info('Running tests for Android with the following parameters:'); @@ -293,6 +331,7 @@ async function main(args = process.argv.slice(2)) { console.info(`IS_DEBUG: ${isDebug}`); console.info(`WORKING_DIRECTORY: ${workingDirectory}`); console.info(`TEST_STATE_PATH: ${statePath}`); + console.info(`EXCLUDE_TAGS: ${excludeTags.join(',') || ''}`); console.info('==============================\n'); logAndroidAbiConfiguration(); @@ -338,7 +377,7 @@ async function main(args = process.argv.slice(2)) { let error = null; try { - const flows = collectFlows(maestroFlow); + const flows = filterFlowsByTags(collectFlows(maestroFlow), excludeTags); const state = loadState(statePath); console.info(`Start testing ${flows.length} flow(s)`); executeFlowSuite({flows, appId, state, statePath}); @@ -378,6 +417,7 @@ if (require.main === module) { module.exports = { collectFlows, executeFlowSuite, + filterFlowsByTags, formatResults, loadState, }; diff --git a/.github/workflows/e2e-android-rntester.yml b/.github/workflows/e2e-android-rntester.yml index dca0ae68ced..7b98d00fed2 100644 --- a/.github/workflows/e2e-android-rntester.yml +++ b/.github/workflows/e2e-android-rntester.yml @@ -71,6 +71,10 @@ jobs: emulator-api-level: '35' emulator-target: google_apis emulator-arch: x86_64 + # These timing-sensitive flows remain covered by the release APK. + # Running the debug ARM64 APK through native translation can delay + # React commits long enough for Maestro to miss taps and assertions. + exclude-tags: ${{ matrix.flavor == 'debug' && 'android-release-only' || '' }} - name: Store per-flow test state if: always() uses: actions/upload-artifact@v6 diff --git a/packages/rn-tester/.maestro/flatlist-append-maintainvisible.yml b/packages/rn-tester/.maestro/flatlist-append-maintainvisible.yml index 8698e0ecd95..47a3097fe68 100644 --- a/packages/rn-tester/.maestro/flatlist-append-maintainvisible.yml +++ b/packages/rn-tester/.maestro/flatlist-append-maintainvisible.yml @@ -1,6 +1,8 @@ # Test FlatList maintainVisibleContentPosition with append (baseline) # Appending items should NOT affect scroll offset (delta ~0) appId: ${APP_ID} +tags: + - android-release-only --- - launchApp # Change to portrait diff --git a/packages/rn-tester/.maestro/flatlist-complex-mutations-maintainvisible.yml b/packages/rn-tester/.maestro/flatlist-complex-mutations-maintainvisible.yml index 701074f2122..72781f1a9a3 100644 --- a/packages/rn-tester/.maestro/flatlist-complex-mutations-maintainvisible.yml +++ b/packages/rn-tester/.maestro/flatlist-complex-mutations-maintainvisible.yml @@ -1,6 +1,8 @@ # Test FlatList maintainVisibleContentPosition — complex concurrent mutations # Tests prepend + append + delete in sequence appId: ${APP_ID} +tags: + - android-release-only --- - launchApp - setOrientation: portrait diff --git a/packages/rn-tester/.maestro/flatlist-delete-anchor-maintainvisible.yml b/packages/rn-tester/.maestro/flatlist-delete-anchor-maintainvisible.yml index 498c919bc0d..7e6dd3a5f6c 100644 --- a/packages/rn-tester/.maestro/flatlist-delete-anchor-maintainvisible.yml +++ b/packages/rn-tester/.maestro/flatlist-delete-anchor-maintainvisible.yml @@ -1,6 +1,8 @@ # Test FlatList maintainVisibleContentPosition — delete anchor item # When the anchor item (first visible) is deleted, MVCP should select a new anchor appId: ${APP_ID} +tags: + - android-release-only --- - launchApp - setOrientation: portrait diff --git a/packages/rn-tester/.maestro/flatlist-delete-middle-maintainvisible.yml b/packages/rn-tester/.maestro/flatlist-delete-middle-maintainvisible.yml index c807d1770e9..8ca036af020 100644 --- a/packages/rn-tester/.maestro/flatlist-delete-middle-maintainvisible.yml +++ b/packages/rn-tester/.maestro/flatlist-delete-middle-maintainvisible.yml @@ -1,6 +1,8 @@ # Test FlatList maintainVisibleContentPosition — delete from middle # When items are deleted from the middle, MVCP should adjust scroll offset appId: ${APP_ID} +tags: + - android-release-only --- - launchApp - setOrientation: portrait diff --git a/packages/rn-tester/.maestro/flatlist-empty-list-maintainvisible.yml b/packages/rn-tester/.maestro/flatlist-empty-list-maintainvisible.yml index 7dee4a0baaf..be79c35b7a6 100644 --- a/packages/rn-tester/.maestro/flatlist-empty-list-maintainvisible.yml +++ b/packages/rn-tester/.maestro/flatlist-empty-list-maintainvisible.yml @@ -3,6 +3,8 @@ # _firstVisibleView.frame on nil returns {0,0}, causing incorrect scroll # correction. appId: ${APP_ID} +tags: + - android-release-only --- - launchApp # Change to portrait diff --git a/packages/rn-tester/.maestro/flatlist-first-prepend-maintainvisible.yml b/packages/rn-tester/.maestro/flatlist-first-prepend-maintainvisible.yml index 1b90a7454a7..8305cbc874c 100644 --- a/packages/rn-tester/.maestro/flatlist-first-prepend-maintainvisible.yml +++ b/packages/rn-tester/.maestro/flatlist-first-prepend-maintainvisible.yml @@ -1,6 +1,8 @@ # Test FlatList maintainVisibleContentPosition — first prepend only # Single prepend with fixed-height items: delta should be ~44px (40px height + 4px margin) appId: ${APP_ID} +tags: + - android-release-only --- - launchApp # Change to portrait diff --git a/packages/rn-tester/.maestro/flatlist-horizontal-add50-reset-maintainvisible.yml b/packages/rn-tester/.maestro/flatlist-horizontal-add50-reset-maintainvisible.yml index 79a805e89c2..04d9c3c2072 100644 --- a/packages/rn-tester/.maestro/flatlist-horizontal-add50-reset-maintainvisible.yml +++ b/packages/rn-tester/.maestro/flatlist-horizontal-add50-reset-maintainvisible.yml @@ -2,6 +2,8 @@ # Verifies that after horizontal mode with 50 prepended items and scroll to 500, # reset returns offset to 0. appId: ${APP_ID} +tags: + - android-release-only --- - launchApp - setOrientation: portrait diff --git a/packages/rn-tester/.maestro/flatlist-horizontal-inverted-maintainvisible.yml b/packages/rn-tester/.maestro/flatlist-horizontal-inverted-maintainvisible.yml index c9b60ab70c2..c53fcd8db23 100644 --- a/packages/rn-tester/.maestro/flatlist-horizontal-inverted-maintainvisible.yml +++ b/packages/rn-tester/.maestro/flatlist-horizontal-inverted-maintainvisible.yml @@ -2,6 +2,8 @@ # Items are 200px wide + 4px margin = 204px each # In inverted mode, prepending adds items to the right end appId: ${APP_ID} +tags: + - android-release-only --- - launchApp # Change to portrait diff --git a/packages/rn-tester/.maestro/flatlist-horizontal-inverted-recycle-maintainvisible.yml b/packages/rn-tester/.maestro/flatlist-horizontal-inverted-recycle-maintainvisible.yml index b86ebefe8b7..ce9234cae13 100644 --- a/packages/rn-tester/.maestro/flatlist-horizontal-inverted-recycle-maintainvisible.yml +++ b/packages/rn-tester/.maestro/flatlist-horizontal-inverted-recycle-maintainvisible.yml @@ -1,6 +1,8 @@ # Test FlatList maintainVisibleContentPosition with view recycling in horizontal + inverted mode # Items are 200px wide + 4px margin = 204px each appId: ${APP_ID} +tags: + - android-release-only --- - launchApp # Change to portrait diff --git a/packages/rn-tester/.maestro/flatlist-horizontal-maintainvisible.yml b/packages/rn-tester/.maestro/flatlist-horizontal-maintainvisible.yml index 4289802fc0b..8258d117230 100644 --- a/packages/rn-tester/.maestro/flatlist-horizontal-maintainvisible.yml +++ b/packages/rn-tester/.maestro/flatlist-horizontal-maintainvisible.yml @@ -1,6 +1,8 @@ # Test FlatList maintainVisibleContentPosition in horizontal mode # Horizontal: items are 200px wide, delta should be ~204px (200px + 4px margin) appId: ${APP_ID} +tags: + - android-release-only --- - launchApp # Change to portrait diff --git a/packages/rn-tester/.maestro/flatlist-horizontal-recycle-maintainvisible.yml b/packages/rn-tester/.maestro/flatlist-horizontal-recycle-maintainvisible.yml index 5267afec16e..c63531017e3 100644 --- a/packages/rn-tester/.maestro/flatlist-horizontal-recycle-maintainvisible.yml +++ b/packages/rn-tester/.maestro/flatlist-horizontal-recycle-maintainvisible.yml @@ -1,6 +1,8 @@ # Test FlatList maintainVisibleContentPosition with view recycling in horizontal mode # Items are 200px wide + 4px margin = 204px each appId: ${APP_ID} +tags: + - android-release-only --- - launchApp # Change to portrait diff --git a/packages/rn-tester/.maestro/flatlist-inverted-maintainvisible.yml b/packages/rn-tester/.maestro/flatlist-inverted-maintainvisible.yml index 1efb844b3b1..28f585f95f4 100644 --- a/packages/rn-tester/.maestro/flatlist-inverted-maintainvisible.yml +++ b/packages/rn-tester/.maestro/flatlist-inverted-maintainvisible.yml @@ -2,6 +2,8 @@ # Delta is +44 (same as non-inverted) — frame-based delta measures actual frame shift, # not logical order. Prepending shifts anchor view frame downward in both modes. appId: ${APP_ID} +tags: + - android-release-only --- - launchApp # Change to portrait diff --git a/packages/rn-tester/.maestro/flatlist-inverted-recycle-maintainvisible.yml b/packages/rn-tester/.maestro/flatlist-inverted-recycle-maintainvisible.yml index 928e968c7c6..ded9fe4c987 100644 --- a/packages/rn-tester/.maestro/flatlist-inverted-recycle-maintainvisible.yml +++ b/packages/rn-tester/.maestro/flatlist-inverted-recycle-maintainvisible.yml @@ -3,6 +3,8 @@ # With windowSize=3, only ~3 pages of items are rendered # In inverted mode, items display in reverse order but MVCP delta behavior is the same appId: ${APP_ID} +tags: + - android-release-only --- - launchApp # Change to portrait diff --git a/packages/rn-tester/.maestro/flatlist-maintainvisible.yml b/packages/rn-tester/.maestro/flatlist-maintainvisible.yml index ff86df5d49b..d0e05fc6287 100644 --- a/packages/rn-tester/.maestro/flatlist-maintainvisible.yml +++ b/packages/rn-tester/.maestro/flatlist-maintainvisible.yml @@ -7,6 +7,8 @@ # - After prepend: record offset # - Delta should equal height of prepended items (~44px per item with margin) appId: ${APP_ID} +tags: + - android-release-only --- - launchApp # Change to portrait @@ -87,6 +89,8 @@ appId: ${APP_ID} --- # Test that user scroll is not interrupted during prepend appId: ${APP_ID} +tags: + - android-release-only --- - launchApp - assertVisible: 'Components' diff --git a/packages/rn-tester/.maestro/flatlist-momentum-scroll-maintainvisible.yml b/packages/rn-tester/.maestro/flatlist-momentum-scroll-maintainvisible.yml index dbf2fe96b2a..820c6586db2 100644 --- a/packages/rn-tester/.maestro/flatlist-momentum-scroll-maintainvisible.yml +++ b/packages/rn-tester/.maestro/flatlist-momentum-scroll-maintainvisible.yml @@ -2,6 +2,8 @@ # Verifies that scroll position remains stable after momentum scroll completes # post-prepend. MVCP correction runs asynchronously in didMountItems. appId: ${APP_ID} +tags: + - android-release-only --- - launchApp # Change to portrait diff --git a/packages/rn-tester/.maestro/flatlist-orientation-maintainvisible.yml b/packages/rn-tester/.maestro/flatlist-orientation-maintainvisible.yml index 003946fa209..8ecefd77df5 100644 --- a/packages/rn-tester/.maestro/flatlist-orientation-maintainvisible.yml +++ b/packages/rn-tester/.maestro/flatlist-orientation-maintainvisible.yml @@ -6,6 +6,8 @@ # This test verifies that MVCP survives an orientation change and continues # to work correctly after the change. appId: ${APP_ID} +tags: + - android-release-only --- - launchApp # Change to portrait diff --git a/packages/rn-tester/.maestro/flatlist-prepend-delete-maintainvisible.yml b/packages/rn-tester/.maestro/flatlist-prepend-delete-maintainvisible.yml index f0a27be47b0..ad116f7a61e 100644 --- a/packages/rn-tester/.maestro/flatlist-prepend-delete-maintainvisible.yml +++ b/packages/rn-tester/.maestro/flatlist-prepend-delete-maintainvisible.yml @@ -4,6 +4,8 @@ # The native side is unaffected by bottom deletes since MVCP only looks at # the first visible view, but re-ordering edge case is untested. appId: ${APP_ID} +tags: + - android-release-only --- - launchApp # Change to portrait diff --git a/packages/rn-tester/.maestro/flatlist-pull-to-refresh-maintainvisible.yml b/packages/rn-tester/.maestro/flatlist-pull-to-refresh-maintainvisible.yml index 2fe197270ae..31445c02d9a 100644 --- a/packages/rn-tester/.maestro/flatlist-pull-to-refresh-maintainvisible.yml +++ b/packages/rn-tester/.maestro/flatlist-pull-to-refresh-maintainvisible.yml @@ -1,6 +1,8 @@ # Test FlatList maintainVisibleContentPosition — pull-to-refresh pattern # Simulates scroll-to-top then prepend (like pull-to-refresh with new items) appId: ${APP_ID} +tags: + - android-release-only --- - launchApp - setOrientation: portrait diff --git a/packages/rn-tester/.maestro/flatlist-rapid-prepends-maintainvisible.yml b/packages/rn-tester/.maestro/flatlist-rapid-prepends-maintainvisible.yml index 0f126d5f664..c7434fb6a12 100644 --- a/packages/rn-tester/.maestro/flatlist-rapid-prepends-maintainvisible.yml +++ b/packages/rn-tester/.maestro/flatlist-rapid-prepends-maintainvisible.yml @@ -2,6 +2,8 @@ # Exercises the throttle edge case where pendingScrollUpdateCount may not decrement # promptly, blocking render window updates. All prepends fired without waiting. appId: ${APP_ID} +tags: + - android-release-only --- - launchApp # Change to portrait diff --git a/packages/rn-tester/.maestro/flatlist-recycle-maintainvisible.yml b/packages/rn-tester/.maestro/flatlist-recycle-maintainvisible.yml index 0706607843b..16cb6cf3132 100644 --- a/packages/rn-tester/.maestro/flatlist-recycle-maintainvisible.yml +++ b/packages/rn-tester/.maestro/flatlist-recycle-maintainvisible.yml @@ -2,6 +2,8 @@ # Items are 40px tall + 4px margin = 44px each # With windowSize=3, only ~3 pages of items are rendered appId: ${APP_ID} +tags: + - android-release-only --- - launchApp # Change to portrait diff --git a/packages/rn-tester/.maestro/flatlist-scrolltooffset-maintainvisible.yml b/packages/rn-tester/.maestro/flatlist-scrolltooffset-maintainvisible.yml index 8a5b077c570..db298cc2b2f 100644 --- a/packages/rn-tester/.maestro/flatlist-scrolltooffset-maintainvisible.yml +++ b/packages/rn-tester/.maestro/flatlist-scrolltooffset-maintainvisible.yml @@ -3,6 +3,8 @@ # during MVCP active causes additive correction (MVCP delta added on top # of the scrollTo target). appId: ${APP_ID} +tags: + - android-release-only --- - launchApp # Change to portrait diff --git a/packages/rn-tester/.maestro/flatlist-throttle-maintainvisible.yml b/packages/rn-tester/.maestro/flatlist-throttle-maintainvisible.yml index 945a8032a09..5b0e4103f5e 100644 --- a/packages/rn-tester/.maestro/flatlist-throttle-maintainvisible.yml +++ b/packages/rn-tester/.maestro/flatlist-throttle-maintainvisible.yml @@ -1,6 +1,8 @@ # Test FlatList maintainVisibleContentPosition with scroll event throttle # Throttle affects timing but not final delta: should be ~44px appId: ${APP_ID} +tags: + - android-release-only --- - launchApp # Change to portrait diff --git a/packages/rn-tester/.maestro/flatlist-variable-height-first-prepend-maintainvisible.yml b/packages/rn-tester/.maestro/flatlist-variable-height-first-prepend-maintainvisible.yml index 4409227b927..385b1d20952 100644 --- a/packages/rn-tester/.maestro/flatlist-variable-height-first-prepend-maintainvisible.yml +++ b/packages/rn-tester/.maestro/flatlist-variable-height-first-prepend-maintainvisible.yml @@ -1,6 +1,8 @@ # Test variable-height items with first prepend # Single prepend with variable height: delta should be 28-112px appId: ${APP_ID} +tags: + - android-release-only --- - launchApp # Change to portrait diff --git a/packages/rn-tester/.maestro/flatlist-variable-height-maintainvisible.yml b/packages/rn-tester/.maestro/flatlist-variable-height-maintainvisible.yml index 0f5580e0909..da034ec4b2b 100644 --- a/packages/rn-tester/.maestro/flatlist-variable-height-maintainvisible.yml +++ b/packages/rn-tester/.maestro/flatlist-variable-height-maintainvisible.yml @@ -1,6 +1,8 @@ # Test FlatList maintainVisibleContentPosition with variable-height items # Delta should be between 28-112px (random height from [30,50,70,90,110]) appId: ${APP_ID} +tags: + - android-release-only --- - launchApp # Change to portrait diff --git a/packages/rn-tester/.maestro/image-wide-gamut.yml b/packages/rn-tester/.maestro/image-wide-gamut.yml index f607bc87542..5d7ca283527 100644 --- a/packages/rn-tester/.maestro/image-wide-gamut.yml +++ b/packages/rn-tester/.maestro/image-wide-gamut.yml @@ -3,8 +3,8 @@ tags: - android-only --- # Android-only: alpha transparency + sRGB vs Display-P3 wide-gamut. Color -# fidelity needs a screenshot, so we assert load status only. Flaky on the iOS -# E2E job, so guarded to Android; iOS skips this flow (empty=pass). +# fidelity is covered by a screenshot captured from the ARM64 APK on the API 35 +# sRGB emulator. The flow is guarded because it is flaky on the iOS E2E job. - runFlow: when: platform: Android diff --git a/packages/rn-tester/.maestro/screenshots/image-wide-gamut-android.png b/packages/rn-tester/.maestro/screenshots/image-wide-gamut-android.png index 0bf56881588924b5cf9dc3b6cb3424c4fd006325..3b7ca2ca47c97ef902fa5664d2a4ab1bc1b87125 100644 GIT binary patch literal 17914 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 MV)CNpB6|M+3tEqln*aa+ literal 18088 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 A)&Kwi