diff --git a/.github/workflows/e2e-matrix.yml b/.github/workflows/e2e-matrix.yml index 7024c55a..eee25c70 100644 --- a/.github/workflows/e2e-matrix.yml +++ b/.github/workflows/e2e-matrix.yml @@ -98,14 +98,28 @@ jobs: - name: Select iOS simulator id: boot-simulator run: | - SIMULATOR_NAME="$(xcrun simctl list devices available | awk -F '[()]' '/iPhone/ {print $1; exit}' | xargs)" - if [ -z "$SIMULATOR_NAME" ]; then + SIMULATOR_UDID="$(xcrun simctl list devices available -j | node -e ' + const fs = require("fs"); + const input = fs.readFileSync(0, "utf8"); + const data = JSON.parse(input); + const runtimes = Object.values(data.devices); + for (const devices of runtimes) { + for (const device of devices) { + if (device.isAvailable && typeof device.name === "string" && device.name.startsWith("iPhone")) { + process.stdout.write(device.udid); + process.exit(0); + } + } + } + process.exit(1); + ')" + if [ -z "$SIMULATOR_UDID" ]; then echo "No available iPhone simulator found." exit 1 fi - xcrun simctl boot "$SIMULATOR_NAME" || true - xcrun simctl bootstatus "$SIMULATOR_NAME" -b - echo "simulator=$SIMULATOR_NAME" >> "$GITHUB_OUTPUT" + xcrun simctl boot "$SIMULATOR_UDID" || true + xcrun simctl bootstatus "$SIMULATOR_UDID" -b + echo "simulator_udid=$SIMULATOR_UDID" >> "$GITHUB_OUTPUT" - name: Reset Xcode module cache run: rm -rf ~/Library/Developer/Xcode/DerivedData/ModuleCache.noindex @@ -117,9 +131,9 @@ jobs: E2E_RETRY_DELAY_SEC: "30" run: | if [ "${{ startsWith(matrix.app, 'Expo') }}" = "true" ]; then - npm run e2e -- --app "${{ matrix.app }}" --platform ios --simulator "${{ steps.boot-simulator.outputs.simulator }}" --framework expo --retry-count "$E2E_RETRY_COUNT" --retry-delay-sec "$E2E_RETRY_DELAY_SEC" + npm run e2e -- --app "${{ matrix.app }}" --platform ios --simulator "${{ steps.boot-simulator.outputs.simulator_udid }}" --framework expo --retry-count "$E2E_RETRY_COUNT" --retry-delay-sec "$E2E_RETRY_DELAY_SEC" else - npm run e2e -- --app "${{ matrix.app }}" --platform ios --simulator "${{ steps.boot-simulator.outputs.simulator }}" --retry-count "$E2E_RETRY_COUNT" --retry-delay-sec "$E2E_RETRY_DELAY_SEC" + npm run e2e -- --app "${{ matrix.app }}" --platform ios --simulator "${{ steps.boot-simulator.outputs.simulator_udid }}" --retry-count "$E2E_RETRY_COUNT" --retry-delay-sec "$E2E_RETRY_DELAY_SEC" fi e2e-android: diff --git a/e2e/flows/01-app-launch.yaml b/e2e/flows/01-app-launch.yaml index 8ca6a7cf..ec4e8b0d 100644 --- a/e2e/flows/01-app-launch.yaml +++ b/e2e/flows/01-app-launch.yaml @@ -1,7 +1,15 @@ appId: ${APP_ID} --- - launchApp +- runFlow: + when: + platform: Android + file: shared/android-dismiss-overlays.yaml +- runFlow: + when: + platform: iOS + file: shared/ios-dismiss-overlays.yaml - assertVisible: "React Native.*" - assertVisible: "Check for updates" - assertVisible: "Clear updates" -- assertVisible: "Restart app" \ No newline at end of file +- assertVisible: "Restart app" diff --git a/e2e/flows/02-restart-no-crash.yaml b/e2e/flows/02-restart-no-crash.yaml index 4d760768..49b5e349 100644 --- a/e2e/flows/02-restart-no-crash.yaml +++ b/e2e/flows/02-restart-no-crash.yaml @@ -6,4 +6,4 @@ appId: ${APP_ID} - waitForAnimationToEnd: timeout: 5000 - assertVisible: "React Native.*" -- assertVisible: "Check for updates" \ No newline at end of file +- assertVisible: "Check for updates" diff --git a/e2e/flows/shared/android-dismiss-overlays.yaml b/e2e/flows/shared/android-dismiss-overlays.yaml new file mode 100644 index 00000000..b4559e5f --- /dev/null +++ b/e2e/flows/shared/android-dismiss-overlays.yaml @@ -0,0 +1,12 @@ +appId: ${APP_ID} +--- +# Dismiss common Android system prompts that can cover the app right after launch in CI. +- tapOn: + text: "(?i)^(allow|ok|continue|got it|while using the app|only this time|allow all the time)$" + optional: true +- tapOn: + text: "(?i)^(allow|ok|continue|got it|while using the app|only this time|allow all the time)$" + optional: true +- tapOn: + text: "(?i)^wait$" + optional: true diff --git a/e2e/flows/shared/ios-dismiss-overlays.yaml b/e2e/flows/shared/ios-dismiss-overlays.yaml new file mode 100644 index 00000000..932021bd --- /dev/null +++ b/e2e/flows/shared/ios-dismiss-overlays.yaml @@ -0,0 +1,9 @@ +appId: ${APP_ID} +--- +# Dismiss common iOS system prompts that can cover the app right after launch in CI. +- tapOn: + text: "(?i)^(allow|ok|continue|not now|allow once|allow while using app|allow paste)$" + optional: true +- tapOn: + text: "(?i)^(allow|ok|continue|not now|allow once|allow while using app|allow paste)$" + optional: true diff --git a/e2e/helpers/build-app.ts b/e2e/helpers/build-app.ts index c0fbb84c..4de080f1 100644 --- a/e2e/helpers/build-app.ts +++ b/e2e/helpers/build-app.ts @@ -59,11 +59,12 @@ async function buildIos(appPath: string, simulator?: string): Promise { await executeCommand("npm", ["run", "setup:pods"], appPath); const sim = simulator ?? getBootedSimulator()?.name ?? DEFAULT_SIMULATOR; + const targetSimulator = resolveSimulator(sim); const args = [ "react-native", "run-ios", "--mode", "Release", "--no-packager", - "--simulator", sim, + "--udid", targetSimulator.udid, ]; console.log(`[command] npx ${args.join(" ")} (cwd: ${appPath})`); return executeCommand("npx", args, appPath);