diff --git a/.github/workflows/e2e-manual.yml b/.github/workflows/e2e-manual.yml index 335715ec..d3384a35 100644 --- a/.github/workflows/e2e-manual.yml +++ b/.github/workflows/e2e-manual.yml @@ -22,6 +22,11 @@ on: required: true default: false type: boolean + exclude_timing_sensitive: + description: Exclude timing-sensitive optional scenarios (ON_NEXT_RESUME/ON_NEXT_SUSPEND) + required: false + default: true + type: boolean jobs: e2e-ios: @@ -85,11 +90,17 @@ jobs: env: E2E_RETRY_COUNT: "3" E2E_RETRY_DELAY_SEC: "30" + E2E_EXCLUDE_TIMING_SENSITIVE: ${{ inputs.exclude_timing_sensitive }} run: | + TIMING_SENSITIVE_ARG="" + if [ "$E2E_EXCLUDE_TIMING_SENSITIVE" = "true" ]; then + TIMING_SENSITIVE_ARG="--exclude-timing-sensitive" + fi + if [ "${{ inputs.expo }}" = "true" ]; then - npm run e2e -- --app "${{ inputs.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 "${{ inputs.app }}" --platform ios --simulator "${{ steps.boot-simulator.outputs.simulator }}" --framework expo --retry-count "$E2E_RETRY_COUNT" --retry-delay-sec "$E2E_RETRY_DELAY_SEC" $TIMING_SENSITIVE_ARG else - npm run e2e -- --app "${{ inputs.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 "${{ inputs.app }}" --platform ios --simulator "${{ steps.boot-simulator.outputs.simulator }}" --retry-count "$E2E_RETRY_COUNT" --retry-delay-sec "$E2E_RETRY_DELAY_SEC" $TIMING_SENSITIVE_ARG fi e2e-android: @@ -150,4 +161,4 @@ jobs: arch: x86_64 profile: pixel_7 emulator-boot-timeout: 900 - script: if [ "${{ inputs.expo }}" = "true" ]; then npm run e2e -- --app "${{ inputs.app }}" --platform android --framework expo --retry-count "$E2E_RETRY_COUNT" --retry-delay-sec "$E2E_RETRY_DELAY_SEC"; else npm run e2e -- --app "${{ inputs.app }}" --platform android --retry-count "$E2E_RETRY_COUNT" --retry-delay-sec "$E2E_RETRY_DELAY_SEC"; fi + script: TIMING_SENSITIVE_ARG=$([ "${{ inputs.exclude_timing_sensitive }}" = "true" ] && echo "--exclude-timing-sensitive" || echo ""); if [ "${{ inputs.expo }}" = "true" ]; then npm run e2e -- --app "${{ inputs.app }}" --platform android --framework expo --retry-count "$E2E_RETRY_COUNT" --retry-delay-sec "$E2E_RETRY_DELAY_SEC" $TIMING_SENSITIVE_ARG; else npm run e2e -- --app "${{ inputs.app }}" --platform android --retry-count "$E2E_RETRY_COUNT" --retry-delay-sec "$E2E_RETRY_DELAY_SEC" $TIMING_SENSITIVE_ARG; fi diff --git a/.github/workflows/e2e-matrix.yml b/.github/workflows/e2e-matrix.yml index b82c554d..e261b0a6 100644 --- a/.github/workflows/e2e-matrix.yml +++ b/.github/workflows/e2e-matrix.yml @@ -13,10 +13,10 @@ on: required: false default: true type: boolean - include_timing_sensitive: - description: Include timing-sensitive optional scenarios (ON_NEXT_RESUME/ON_NEXT_SUSPEND) + exclude_timing_sensitive: + description: Exclude timing-sensitive optional scenarios (ON_NEXT_RESUME/ON_NEXT_SUSPEND) required: false - default: false + default: true type: boolean jobs: @@ -146,11 +146,11 @@ jobs: MAESTRO_DRIVER_STARTUP_TIMEOUT: "300000" E2E_RETRY_COUNT: "3" E2E_RETRY_DELAY_SEC: "30" - E2E_INCLUDE_TIMING_SENSITIVE: ${{ inputs.include_timing_sensitive }} + E2E_EXCLUDE_TIMING_SENSITIVE: ${{ inputs.exclude_timing_sensitive }} run: | TIMING_SENSITIVE_ARG="" - if [ "$E2E_INCLUDE_TIMING_SENSITIVE" = "true" ]; then - TIMING_SENSITIVE_ARG="--include-timing-sensitive" + if [ "$E2E_EXCLUDE_TIMING_SENSITIVE" = "true" ]; then + TIMING_SENSITIVE_ARG="--exclude-timing-sensitive" fi if [ "${{ startsWith(matrix.app, 'Expo') }}" = "true" ]; then @@ -233,4 +233,4 @@ jobs: arch: x86_64 profile: pixel_7 emulator-boot-timeout: 900 - script: TIMING_SENSITIVE_ARG=$([ "${{ inputs.include_timing_sensitive }}" = "true" ] && echo "--include-timing-sensitive" || echo ""); if [ "${{ startsWith(matrix.app, 'Expo') }}" = "true" ]; then npm run e2e -- --app "${{ matrix.app }}" --platform android --framework expo --retry-count "$E2E_RETRY_COUNT" --retry-delay-sec "$E2E_RETRY_DELAY_SEC" $TIMING_SENSITIVE_ARG; else npm run e2e -- --app "${{ matrix.app }}" --platform android --retry-count "$E2E_RETRY_COUNT" --retry-delay-sec "$E2E_RETRY_DELAY_SEC" $TIMING_SENSITIVE_ARG; fi + script: TIMING_SENSITIVE_ARG=$([ "${{ inputs.exclude_timing_sensitive }}" = "true" ] && echo "--exclude-timing-sensitive" || echo ""); if [ "${{ startsWith(matrix.app, 'Expo') }}" = "true" ]; then npm run e2e -- --app "${{ matrix.app }}" --platform android --framework expo --retry-count "$E2E_RETRY_COUNT" --retry-delay-sec "$E2E_RETRY_DELAY_SEC" $TIMING_SENSITIVE_ARG; else npm run e2e -- --app "${{ matrix.app }}" --platform android --retry-count "$E2E_RETRY_COUNT" --retry-delay-sec "$E2E_RETRY_DELAY_SEC" $TIMING_SENSITIVE_ARG; fi diff --git a/e2e/README.ko.md b/e2e/README.ko.md index b0753a32..438d38fd 100644 --- a/e2e/README.ko.md +++ b/e2e/README.ko.md @@ -40,7 +40,7 @@ npm run e2e -- --app Expo55Beta --framework expo --platform ios --maestro-only | `--framework ` | 아니오 | Expo 예제 앱인 경우 `expo` 지정 | | `--simulator ` | 아니오 | iOS 시뮬레이터 이름 (부팅된 시뮬레이터 자동 감지, 기본값 "iPhone 16") | | `--maestro-only` | 아니오 | 빌드 단계 생략, 테스트 플로우만 실행 | -| `--include-timing-sensitive` | 아니오 | 타이밍 민감 optional 시나리오(`03`, `04`) 추가 실행. 기본값: 비활성 | +| `--exclude-timing-sensitive` | 아니오 | 타이밍 민감 optional 시나리오(`03`, `04`)를 제외합니다. 기본값: 비활성, 즉 로컬 실행에는 기본 포함 | ## 실행 과정 @@ -75,8 +75,8 @@ npm run e2e -- --app Expo55Beta --framework expo --platform ios --maestro-only 13. **optional 업데이트 플로우 실행** — 아래 조건에서 업데이트가 적용되는지 확인합니다. - `01-optional-update-on-relaunch` — 앱을 종료 후 재실행할 때 - `02-optional-update-on-restart-button` — 앱 내 "Restart app" 버튼을 누를 때 - - `03-optional-update-on-resume-after-20s` — 앱이 백그라운드에 20초 이상 머문 뒤 포그라운드로 돌아올 때 `ON_NEXT_RESUME`으로 업데이트가 적용되는지 확인합니다. `--include-timing-sensitive` 옵션 사용 시에만 실행 - - `04-optional-update-on-suspend-after-20s` — 앱이 백그라운드에 20초 이상 머무는 동안 `ON_NEXT_SUSPEND`로 업데이트가 적용되고, 다음 포그라운드 진입 시 반영된 번들이 보이는지 확인합니다. `--include-timing-sensitive` 옵션 사용 시에만 실행 + - `03-optional-update-on-resume-after-20s` — 앱이 백그라운드에 20초 이상 머문 뒤 포그라운드로 돌아올 때 `ON_NEXT_RESUME`으로 업데이트가 적용되는지 확인합니다. `--exclude-timing-sensitive`를 주지 않으면 실행됩니다. + - `04-optional-update-on-suspend-after-20s` — 앱이 백그라운드에 20초 이상 머무는 동안 `ON_NEXT_SUSPEND`로 업데이트가 적용되고, 다음 포그라운드 진입 시 반영된 번들이 보이는지 확인합니다. `--exclude-timing-sensitive`를 주지 않으면 실행됩니다. ## 아키텍처 diff --git a/e2e/README.md b/e2e/README.md index b765f753..066c47f2 100644 --- a/e2e/README.md +++ b/e2e/README.md @@ -40,7 +40,7 @@ npm run e2e -- --app Expo55Beta --framework expo --platform ios --maestro-only | `--framework ` | No | Use `expo` for Expo example apps | | `--simulator ` | No | iOS simulator name (auto-detects booted simulator, defaults to "iPhone 16") | | `--maestro-only` | No | Skip build step, only run test flows | -| `--include-timing-sensitive` | No | Also run timing-sensitive optional scenarios (`03`, `04`). Default: off | +| `--exclude-timing-sensitive` | No | Skip timing-sensitive optional scenarios (`03`, `04`). Default: off, so local runs include them | ## What It Does @@ -75,8 +75,8 @@ The test runner (`e2e/run.ts`) executes these phases in order: 13. **Run optional update flows** — Verifies optional updates are applied when: - `01-optional-update-on-relaunch` — The app is killed and relaunched. - `02-optional-update-on-restart-button` — The in-app "Restart app" button is pressed. - - `03-optional-update-on-resume-after-20s` — Verifies `ON_NEXT_RESUME` applies the update when the app returns to foreground after staying in background for at least 20 seconds. Runs only with `--include-timing-sensitive`. - - `04-optional-update-on-suspend-after-20s` — Verifies `ON_NEXT_SUSPEND` applies the update while the app stays in background for at least 20 seconds, so the updated bundle is visible on the next foreground. Runs only with `--include-timing-sensitive`. + - `03-optional-update-on-resume-after-20s` — Verifies `ON_NEXT_RESUME` applies the update when the app returns to foreground after staying in background for at least 20 seconds. Runs unless `--exclude-timing-sensitive` is passed. + - `04-optional-update-on-suspend-after-20s` — Verifies `ON_NEXT_SUSPEND` applies the update while the app stays in background for at least 20 seconds, so the updated bundle is visible on the next foreground. Runs unless `--exclude-timing-sensitive` is passed. ## Architecture diff --git a/e2e/run.ts b/e2e/run.ts index eb130d2e..7efe9eb5 100644 --- a/e2e/run.ts +++ b/e2e/run.ts @@ -14,7 +14,7 @@ interface CliOptions { framework?: "expo"; simulator?: string; maestroOnly?: boolean; - includeTimingSensitive?: boolean; + excludeTimingSensitive?: boolean; retryCount: number; retryDelaySec: number; } @@ -50,8 +50,8 @@ const program = new Command() .option("--simulator ", "iOS simulator name (default: booted)") .option("--maestro-only", "Skip build, only run test flows", false) .option( - "--include-timing-sensitive", - "Include timing-sensitive optional install mode scenarios (ON_NEXT_RESUME/ON_NEXT_SUSPEND)", + "--exclude-timing-sensitive", + "Exclude timing-sensitive optional install mode scenarios (ON_NEXT_RESUME/ON_NEXT_SUSPEND)", false, ) .option( @@ -227,7 +227,7 @@ async function main() { }, ]; - if (options.includeTimingSensitive) { + if (!options.excludeTimingSensitive) { optionalUpdateScenarios.push( { name: "apply on resume after 20 seconds", @@ -240,8 +240,10 @@ async function main() { flowPath: path.resolve(__dirname, "flows-optional/04-optional-update-on-suspend-after-20s.yaml"), }, ); - } else { - console.log("\n=== [phase 4] skipping timing-sensitive scenarios (pass --include-timing-sensitive to enable) ==="); + } + + if (options.excludeTimingSensitive) { + console.log("\n=== [phase 4] skipping timing-sensitive scenarios (omit --exclude-timing-sensitive to include them) ==="); } for (const scenario of optionalUpdateScenarios) {