Skip to content
Merged
15 changes: 8 additions & 7 deletions .github/actions/maestro-ios/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,23 @@ inputs:

runs:
using: composite
# Expects Node.js to be set up by the calling job.
steps:
# Booting takes a couple of minutes; it finishes while the next steps run.
- name: Boot simulator
shell: bash
run: |
node .github/workflow-scripts/maestro-ios.js boot \
"${{ inputs.device-model }}" \
"${{ inputs.device-os }}"
- name: Installing Maestro
shell: bash
run: export MAESTRO_VERSION=2.6.1; curl -Ls "https://get.maestro.mobile.dev" | bash
- name: Installing Maestro dependencies
shell: bash
run: |
brew tap facebook/fb
brew install facebook/fb/idb-companion
- name: Set up JDK 17
uses: actions/setup-java@v5
with:
java-version: '17'
distribution: 'zulu'
- name: Setup node.js
uses: ./.github/actions/setup-node
- name: Run yarn install
uses: ./.github/actions/yarn-install
- name: Start Metro in Debug
Expand Down
12 changes: 3 additions & 9 deletions .github/workflow-scripts/__tests__/maestro-android-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,22 +47,16 @@ describe('Maestro Android runner', () => {
});

it('excludes flows with matching tags', () => {
const releaseOnlyFlow = path.join(
temporaryDirectory,
'android-release-only.yml',
);
const releaseOnlyFlow = path.join(temporaryDirectory, 'release-only.yml');
const regularFlow = path.join(temporaryDirectory, 'regular.yml');
fs.writeFileSync(
releaseOnlyFlow,
'appId: x\ntags:\n - android-release-only\n---\n- launchApp\n',
'appId: x\ntags:\n - release-only\n---\n- launchApp\n',
);
fs.writeFileSync(regularFlow, 'appId: x\n---\n- launchApp\n');

expect(
filterFlowsByTags(
[releaseOnlyFlow, regularFlow],
['android-release-only'],
),
filterFlowsByTags([releaseOnlyFlow, regularFlow], ['release-only']),
).toEqual([regularFlow]);
});

Expand Down
26 changes: 22 additions & 4 deletions .github/workflow-scripts/maestro-ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ node maestro-ios.js <path to app> <app_id> <maestro_flow> <jsengine> <flavor> <w
@param {string} deviceOS - Optional Maestro device OS, such as iOS-26-2
@param {string} testStatePath - Optional file used to persist per-flow results between CI retries
@param {string} excludeTags - Optional comma-separated flow tags to exclude

node maestro-ios.js boot [device_model] [device_os]

Starts booting the simulator the tests will run on and returns without
waiting for the boot to finish.
==============
`;

Expand Down Expand Up @@ -557,11 +562,24 @@ async function main(args = process.argv.slice(2)) {
console.log('Test finished');
}

// Lets the workflow start the (slow) simulator boot before the rest of the
// setup, instead of waiting for it in the middle of the test step.
function boot(args) {
if (args.length > 2) {
throw new Error(`Invalid number of arguments.\n${usage}`);
}
launchSimulator(findAvailableSimulator(args[0] || null, args[1] || null));
}

if (require.main === module) {
main().catch(error => {
console.error(error);
process.exitCode = 1;
});
const args = process.argv.slice(2);
const command = args[0] === 'boot' ? () => boot(args.slice(1)) : main;
Promise.resolve()
.then(command)
.catch(error => {
console.error(error);
process.exitCode = 1;
});
}

module.exports = {
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/e2e-android-rntester.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ jobs:
# 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' || '' }}
exclude-tags: ${{ matrix.flavor == 'debug' && 'release-only' || '' }}
- name: Store per-flow test state
if: always()
uses: ./.github/actions/upload-artifact
Expand Down
28 changes: 21 additions & 7 deletions .github/workflows/e2e-ios-rntester.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ on:

jobs:
test:
runs-on: macos-26-large
# Standard arm64 runner: the simulator runs natively, and standard runners
# aren't billed for public repositories. RNTesterApp is built for both
# x86_64 and arm64 simulators.
runs-on: macos-26
outputs:
# Matrix legs only keep the last value written to an output name, so each
# flavor writes its own.
Expand Down Expand Up @@ -52,10 +55,9 @@ jobs:
SHOULD_RUN=false
fi
echo "should-run=$SHOULD_RUN" >> "$GITHUB_OUTPUT"
- name: Setup Node.js
if: steps.test-state.outputs.should-run == 'true'
uses: ./.github/actions/setup-node
# First, so that a missing app fails the job before any other setup.
- name: Download App
id: download-app
if: steps.test-state.outputs.should-run == 'true'
uses: ./.github/actions/download-artifact
with:
Expand All @@ -64,6 +66,9 @@ jobs:
- name: Check downloaded folder content
if: steps.test-state.outputs.should-run == 'true'
run: ls -lR /tmp/RNTesterBuild
- name: Setup Node.js
if: steps.test-state.outputs.should-run == 'true'
uses: ./.github/actions/setup-node
- name: Run E2E Tests
id: run-tests
if: steps.test-state.outputs.should-run == 'true'
Expand All @@ -77,7 +82,11 @@ jobs:
device-model: iPhone-17-Pro
device-os: iOS-26-2
test-state-path: /tmp/maestro-ios-state/results.json
exclude-tags: android-only
# The `release-only` flows (FlatList maintainVisibleContentPosition)
# are half of the suite and test scroll behavior that doesn't depend
# on the build flavor. Nearly 90% of their failed attempts were in
# Debug, so like on Android they only run against Release.
exclude-tags: ${{ matrix.flavor == 'Debug' && 'android-only,release-only' || 'android-only' }}
- name: Store per-flow test state
if: always()
uses: ./.github/actions/upload-artifact
Expand All @@ -91,14 +100,19 @@ jobs:
if: always()
shell: bash
# passed: every flow passed.
# failed: a flow failed all of its attempts; retrying the job would only
# repeat the same failure.
# failed: a flow failed all of its attempts, or the app to test is
# missing; retrying the job would only repeat the same failure.
# incomplete: the job stopped before running every flow (runner or
# setup failure); a retry can pick up the remaining flows.
run: |
STATE=/tmp/maestro-ios-state/results.json
if [[ "${{ steps.test-state.outputs.should-run }}" == "false" || "${{ steps.run-tests.outcome }}" == "success" ]]; then
RESULT=passed
elif [[ "${{ steps.download-app.outcome }}" == "failure" ]]; then
# test_ios_rntester uses continue-on-error, so it reports success
# even when the build that uploads this app failed.
echo "::error::RNTesterApp-NewArch-${{ matrix.flavor }} is missing. Check the test_ios_rntester (${{ matrix.flavor }}, frameworks: false) job."
RESULT=failed
elif [[ -f "$STATE" ]] && jq -e 'any(.flows[]; .status == "failed")' "$STATE" > /dev/null; then
RESULT=failed
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Appending items should NOT affect scroll offset (delta ~0)
appId: ${APP_ID}
tags:
- android-release-only
- release-only
---
- launchApp
# Change to portrait
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Tests prepend + append + delete in sequence
appId: ${APP_ID}
tags:
- android-release-only
- release-only
---
- launchApp
- setOrientation: portrait
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# When the anchor item (first visible) is deleted, MVCP should select a new anchor
appId: ${APP_ID}
tags:
- android-release-only
- release-only
---
- launchApp
- setOrientation: portrait
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# When items are deleted from the middle, MVCP should adjust scroll offset
appId: ${APP_ID}
tags:
- android-release-only
- release-only
---
- launchApp
- setOrientation: portrait
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# correction.
appId: ${APP_ID}
tags:
- android-release-only
- release-only
---
- launchApp
# Change to portrait
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Single prepend with fixed-height items: delta should be ~44px (40px height + 4px margin)
appId: ${APP_ID}
tags:
- android-release-only
- release-only
---
- launchApp
# Change to portrait
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# reset returns offset to 0.
appId: ${APP_ID}
tags:
- android-release-only
- release-only
---
- launchApp
- setOrientation: portrait
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# In inverted mode, prepending adds items to the right end
appId: ${APP_ID}
tags:
- android-release-only
- release-only
---
- launchApp
# Change to portrait
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Items are 200px wide + 4px margin = 204px each
appId: ${APP_ID}
tags:
- android-release-only
- release-only
---
- launchApp
# Change to portrait
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Horizontal: items are 200px wide, delta should be ~204px (200px + 4px margin)
appId: ${APP_ID}
tags:
- android-release-only
- release-only
---
- launchApp
# Change to portrait
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Items are 200px wide + 4px margin = 204px each
appId: ${APP_ID}
tags:
- android-release-only
- release-only
---
- launchApp
# Change to portrait
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# not logical order. Prepending shifts anchor view frame downward in both modes.
appId: ${APP_ID}
tags:
- android-release-only
- release-only
---
- launchApp
# Change to portrait
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# In inverted mode, items display in reverse order but MVCP delta behavior is the same
appId: ${APP_ID}
tags:
- android-release-only
- release-only
---
- launchApp
# Change to portrait
Expand Down
4 changes: 2 additions & 2 deletions packages/rn-tester/.maestro/flatlist-maintainvisible.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# - Delta should equal height of prepended items (~44px per item with margin)
appId: ${APP_ID}
tags:
- android-release-only
- release-only
---
- launchApp
# Change to portrait
Expand Down Expand Up @@ -90,7 +90,7 @@ tags:
# Test that user scroll is not interrupted during prepend
appId: ${APP_ID}
tags:
- android-release-only
- release-only
---
- launchApp
- assertVisible: 'Components'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# post-prepend. MVCP correction runs asynchronously in didMountItems.
appId: ${APP_ID}
tags:
- android-release-only
- release-only
---
- launchApp
# Change to portrait
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
# to work correctly after the change.
appId: ${APP_ID}
tags:
- android-release-only
- release-only
---
- launchApp
# Change to portrait
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# the first visible view, but re-ordering edge case is untested.
appId: ${APP_ID}
tags:
- android-release-only
- release-only
---
- launchApp
# Change to portrait
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Simulates scroll-to-top then prepend (like pull-to-refresh with new items)
appId: ${APP_ID}
tags:
- android-release-only
- release-only
---
- launchApp
- setOrientation: portrait
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# promptly, blocking render window updates. All prepends fired without waiting.
appId: ${APP_ID}
tags:
- android-release-only
- release-only
---
- launchApp
# Change to portrait
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# With windowSize=3, only ~3 pages of items are rendered
appId: ${APP_ID}
tags:
- android-release-only
- release-only
---
- launchApp
# Change to portrait
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# of the scrollTo target).
appId: ${APP_ID}
tags:
- android-release-only
- release-only
---
- launchApp
# Change to portrait
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Throttle affects timing but not final delta: should be ~44px
appId: ${APP_ID}
tags:
- android-release-only
- release-only
---
- launchApp
# Change to portrait
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Single prepend with variable height: delta should be 28-112px
appId: ${APP_ID}
tags:
- android-release-only
- release-only
---
- launchApp
# Change to portrait
Expand Down
Loading
Loading