Skip to content

feat(e2e): port Behave/Appium UI tests + UITests mode in Example#48

Draft
mikemilla wants to merge 1 commit into
mainfrom
mike-miller/end-to-end-tests
Draft

feat(e2e): port Behave/Appium UI tests + UITests mode in Example#48
mikemilla wants to merge 1 commit into
mainfrom
mike-miller/end-to-end-tests

Conversation

@mikemilla

Copy link
Copy Markdown
Collaborator

Summary

  • Ports the iOS UIKit end-to-end suite from trycourier/mobile-automation-tests into /e2e in this repo — Behave + Appium + Py-TestUI, iOS-only.
  • Adds a parallel -UITests UI flow to the Example app (Example/Example/UITests/) so the existing Behave selectors resolve. Normal demo UI is unchanged.
  • New e2e-ios workflow runs the suite on macos-latest for every PR: installs Appium 2 + xcuitest driver, boots a sim, runs behave -t @iOS, uploads artifacts.

What's in /e2e

Faithful copy of the iOS-relevant parts of mobile-automation-tests:

  • features/smoke.feature, features/smoke_push.feature
  • features/screens_ios/ (selectors), features/screens_common/ (base classes), features/steps/, features/utils/
  • Adapted install_apps.py: builds Example.xcodeproj (scheme Example, bundle com.courier.ios-example), writes Env.swift from COURIER_AUTH_KEY, drops CocoaPods chmod (Example is pure SPM)
  • IOS_UDID env override so CI can pass a freshly-booted simulator UDID

UITests mode in Example

Gated by -UITests launch argument. When inactive, app behaves identically.

  • AppDelegate: sets Courier.isUITestsActive = true if launched with -UITests
  • SceneDelegate: swaps the storyboard tab bar for a programmatic UITestsAuthVC → UITestsComponentsVC → Inbox/Push/Preferences/EditTheme flow
  • Accessibility ids match the Behave selectors verbatim: usernameInput, signInButton, inboxButton, pushNotificationsButton, preferencesButton, signOutButton, <kind>Input rows, button titles Edit / Close / Save / Request permission
  • New files added via a PBXFileSystemSynchronizedRootGroup on Example/Example/UITests/ — drop any .swift in that folder and it auto-compiles, no per-file pbxproj edits

Workflow

.github/workflows/e2e-ios.yml on macos-latest:

  1. Write placeholder GoogleService-Info.plist (the real one is gitignored)
  2. Setup Python 3.11 + Node 20, install Appium 2 + xcuitest driver
  3. Boot iPhone 16 Pro simulator, export UDID to IOS_UDID
  4. pip install -r e2e/requirements.txt
  5. Start Appium server in background
  6. python -m behave features -t @iOS -k
  7. Upload e2e/features/artifacts/ + e2e/logs/

Trigger: PR to main, workflow_dispatch, and repository_dispatch: [iOS-UIKit].

Required secrets

Secret Used for
COURIER_AUTH_KEY Written into Env.swift (JWT minting) and also passed as COURIER_API_KEY so utils/courier_api.py can hit /send. Must point at a workspace where templates YV8XBE4N4X438RG0WT3Q42HSPQR7, 4Z2A89Q7F149SHPP45YFB8C1WSYA, J5VKSSE0PXMFWFQAAZN7BBRZE49V, J08YK1WN2YMY6APMK1Q26JMK61ZE are published
COURIER_USER_ID, COURIER_CLIENT_KEY, COURIER_BRAND_ID, COURIER_PREFERENCE_TOPIC_ID, COURIER_MESSAGE_TEMPLATE_ID Optional — also written to Env.swift for parity with ci.yml

Known caveats

  • smoke_push.feature @iOS APNS scenario won't pass on a hosted-simulator runner — APNs delivery doesn't work there. The default tag filter is @iOS which picks up these scenarios; will need a real device or self-hosted runner to exercise. Inbox scenarios in smoke.feature work on simulator.
  • The workflow writes a placeholder GoogleService-Info.plist. Firebase will log init errors at runtime but won't crash. Swap in a real plist via a secret when you want FCM to actually work.
  • I went with runs-on: macos-latest to match the existing ci.yml. If you'd rather use the self-hosted Mac runner that mobile-automation-tests used, change one line.

Test plan

  • Set COURIER_AUTH_KEY secret on the repo
  • Trigger workflow via workflow_dispatch first, watch the run
  • Verify e2e/features/artifacts/screenshots/ artifact uploaded on failure
  • Manually launch Example with -UITests from Xcode → sanity check the new flow works without breaking the normal demo UI

🤖 Generated with Claude Code

Brings the iOS UIKit end-to-end tests from trycourier/mobile-automation-tests
into this repo so they run against this Example app on PRs.

- e2e/: Python/Behave/Appium suite (smoke.feature, smoke_push.feature, iOS
  screens, steps, courier_api util). install_apps.py adapted to build
  Example.xcodeproj on a CI-supplied IOS_UDID and write Env.swift from
  COURIER_AUTH_KEY (CocoaPods chmod dropped — Example is pure SPM).
- Example/Example/UITests/: parallel UI flow gated by `-UITests` launch arg.
  Adds UITestsAuthVC (usernameInput + signInButton), UITestsComponentsVC
  (inboxButton / pushNotificationsButton / preferencesButton / signOutButton),
  inbox + edit-theme + push + preferences screens with the accessibility
  identifiers the Behave suite drives. Normal demo UI is unchanged.
- AppDelegate sets `Courier.isUITestsActive = true` when launched with
  -UITests; SceneDelegate swaps the root VC accordingly.
- .github/workflows/e2e-ios.yml: macos-latest, installs Appium 2 + xcuitest
  driver, boots a sim, runs `behave -t @iOS`, uploads artifacts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@mikemilla
mikemilla marked this pull request as draft July 15, 2026 16:35
@linear

linear Bot commented Jul 15, 2026

Copy link
Copy Markdown

C-18849

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant