Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
1361cb9
feat: Add mobile E2E testing framework with Appium + WebdriverIO
WiktorStarczewski Jan 19, 2026
0973802
fix: Mobile E2E tests - fix biometric toggle and WebView helpers
WiktorStarczewski Jan 19, 2026
eed0a88
feat: trim whitespace from seed phrase inputs
WiktorStarczewski Jan 20, 2026
fcf446c
feat: add Android E2E test support with platform-aware selectors
WiktorStarczewski Jan 20, 2026
4916135
fix: Android E2E selectors for send/receive tests
WiktorStarczewski Jan 20, 2026
73d36e6
feat: add iOS E2E test support for send/receive flows
WiktorStarczewski Jan 20, 2026
3ab42c1
chore: add mobile-e2e screenshots and logs to gitignore
WiktorStarczewski Jan 20, 2026
008b05a
feat: add aria-label and data-testid to NavigationHeader buttons
WiktorStarczewski Jan 20, 2026
f9c1fc0
refactor: remove redundant wallet-features.spec.ts, add send/receive …
WiktorStarczewski Jan 20, 2026
dbdd92a
fix: use WebView JS navigation for Android E2E test cleanup
WiktorStarczewski Jan 21, 2026
d09304a
perf: use simctl to clear iOS app data instead of fullReset
WiktorStarczewski Jan 21, 2026
765136a
docs: add mobile E2E testing guide and CI workflow notes to CLAUDE.md
WiktorStarczewski Jan 21, 2026
9fc3762
refactor: move mobile E2E to pr.yml, add Android test runner script
WiktorStarczewski Jan 21, 2026
fd03689
chore: update translation files
github-actions[bot] Jan 21, 2026
d6e0130
Potential fix for code scanning alert no. 16: Workflow does not conta…
WiktorStarczewski Jan 21, 2026
9ea9ca3
Potential fix for code scanning alert no. 18: Workflow does not conta…
WiktorStarczewski Jan 21, 2026
f489ee9
Potential fix for code scanning alert no. 17: Workflow does not conta…
WiktorStarczewski Jan 21, 2026
e205535
fix: exclude mobile-e2e from Jest test runner
WiktorStarczewski Jan 21, 2026
7b0d6b4
fix: use xcodeproj instead of xcworkspace for iOS CI build
WiktorStarczewski Jan 21, 2026
2745068
fix: use workspace for iOS CI, update to Java 21 for Android
WiktorStarczewski Jan 21, 2026
72d8b8f
fix: commit Package.resolved for iOS SPM, handle existing Appium driver
WiktorStarczewski Jan 21, 2026
7bc7c4b
fix: pin capacitor-swift-pm to 8.0.0 for plugin compatibility
WiktorStarczewski Jan 21, 2026
55096a5
fix: simplify Android emulator setup, use API 31 with default target
WiktorStarczewski Jan 21, 2026
dba08c5
fix: update capacitor-swift-pm to 8.0.1, fix Android E2E emulator config
WiktorStarczewski Jan 21, 2026
7a4e4a2
fix: remove splash-screen plugin in CI, update Package.resolved to 8.0.1
WiktorStarczewski Jan 21, 2026
18840f2
fix: allow iOS E2E to fail (SPM bug), use npx wdio for Android
WiktorStarczewski Jan 21, 2026
a953328
fix: allow Android E2E to fail (emulator stability issues)
WiktorStarczewski Jan 21, 2026
6e0007f
fix: start Appium manually in CI, skip wdio Appium service in CI
WiktorStarczewski Jan 21, 2026
2591a65
chore: disable iOS E2E tests until Capacitor SPM bug is fixed
WiktorStarczewski Jan 21, 2026
faf6971
fix: commit Package.resolved to fix iOS E2E CI builds
WiktorStarczewski Jan 21, 2026
e93c4f9
fix: increase Android E2E timeouts and enable KVM for faster emulator
WiktorStarczewski Jan 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 158 additions & 0 deletions .github/workflows/mobile-e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
name: Mobile E2E Tests
permissions:
contents: read

# This workflow is for manual runs only.
# PR runs are handled by pr.yml to coordinate with the translations job.
on:
workflow_dispatch:

jobs:
ios-e2e:
name: iOS E2E Tests
runs-on: macos-14
timeout-minutes: 60

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'yarn'

- name: Install dependencies
run: yarn install --frozen-lockfile

- name: Build mobile app
run: yarn build:mobile

- name: Sync Capacitor
run: npx cap sync ios

- name: Select Xcode version
run: sudo xcode-select -s /Applications/Xcode_15.4.app

- name: Build iOS app for simulator
run: |
xcodebuild -workspace ios/App/App.xcworkspace \
-scheme App \
-sdk iphonesimulator \
-destination 'platform=iOS Simulator,name=iPhone 15,OS=17.5' \
-configuration Debug \
-derivedDataPath ios/App/build \
build

- name: Boot iOS Simulator
run: |
xcrun simctl boot "iPhone 15" || true
xcrun simctl list devices

- name: Install Appium
run: |
npm install -g appium
appium driver install xcuitest

- name: Start Appium server
run: |
appium --relaxed-security &
sleep 10

- name: Run iOS E2E tests
run: yarn test:e2e:ios
env:
APPIUM_APP_PATH: ${{ github.workspace }}/ios/App/build/Build/Products/Debug-iphonesimulator/App.app

- name: Upload test screenshots
if: failure()
uses: actions/upload-artifact@v4
with:
name: ios-e2e-screenshots
path: mobile-e2e/screenshots/
retention-days: 7

- name: Upload Appium logs
if: failure()
uses: actions/upload-artifact@v4
with:
name: ios-appium-logs
path: mobile-e2e/logs/
retention-days: 7

android-e2e:
name: Android E2E Tests
runs-on: ubuntu-latest
timeout-minutes: 60
permissions:
contents: read

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'yarn'

- name: Setup Java
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'

- name: Setup Android SDK
uses: android-actions/setup-android@v3

- name: Install dependencies
run: yarn install --frozen-lockfile

- name: Build mobile app
run: yarn build:mobile

- name: Sync Capacitor
run: npx cap sync android

- name: Build Android APK
run: |
cd android
./gradlew assembleDebug
cd ..

- name: Install Appium
run: |
npm install -g appium
appium driver install uiautomator2 || echo "Driver already installed"

- name: Run Android E2E tests
uses: reactivecircus/android-emulator-runner@v2
timeout-minutes: 30
with:
api-level: 31
target: default
arch: x86_64
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -no-snapshot-load
disable-animations: true
script: |
appium --relaxed-security &
sleep 10
yarn test:e2e:android

- name: Upload test screenshots
if: failure()
uses: actions/upload-artifact@v4
with:
name: android-e2e-screenshots
path: mobile-e2e/screenshots/
retention-days: 7

- name: Upload Appium logs
if: failure()
uses: actions/upload-artifact@v4
with:
name: android-appium-logs
path: mobile-e2e/logs/
retention-days: 7
170 changes: 170 additions & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ on:
- 'mw-**'
- 'feat/**'

permissions:
contents: read

jobs:
translations:
name: Update Translation Files
Expand Down Expand Up @@ -149,3 +152,170 @@ jobs:

- name: Check i18n compliance
run: yarn lint:i18n

ios-e2e:
name: iOS E2E Tests
needs: translations
runs-on: macos-14
timeout-minutes: 60

steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'yarn'

- name: Install dependencies
run: yarn install --frozen-lockfile

- name: Build mobile app
run: yarn build:mobile

- name: Sync Capacitor
run: npx cap sync ios

- name: Remove splash-screen plugin for CI build
run: |
# Remove splash-screen from Package.swift (has compatibility issues with SPM)
sed -i '' '/CapacitorSplashScreen/d' ios/App/CapApp-SPM/Package.swift

- name: Select Xcode version
run: sudo xcode-select -s /Applications/Xcode_15.4.app

- name: Build iOS app for simulator
run: |
xcodebuild -workspace ios/App/App.xcworkspace \
-scheme App \
-sdk iphonesimulator \
-destination 'platform=iOS Simulator,name=iPhone 15,OS=17.5' \
-configuration Debug \
-derivedDataPath ios/App/build \
build

- name: Boot iOS Simulator
run: |
xcrun simctl boot "iPhone 15" || true
xcrun simctl list devices

- name: Install Appium
run: |
npm install -g appium
appium driver install xcuitest

- name: Start Appium server
run: |
appium --relaxed-security &
sleep 10

- name: Run iOS E2E tests
run: yarn test:e2e:ios
env:
APPIUM_APP_PATH: ${{ github.workspace }}/ios/App/build/Build/Products/Debug-iphonesimulator/App.app

- name: Upload test screenshots
if: failure()
uses: actions/upload-artifact@v4
with:
name: ios-e2e-screenshots
path: mobile-e2e/screenshots/
retention-days: 7

- name: Upload Appium logs
if: failure()
uses: actions/upload-artifact@v4
with:
name: ios-appium-logs
path: mobile-e2e/logs/
retention-days: 7

android-e2e:
name: Android E2E Tests
needs: translations
runs-on: ubuntu-latest
timeout-minutes: 60

steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'yarn'

- name: Setup Java
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'

- name: Setup Android SDK
uses: android-actions/setup-android@v3

- name: Install dependencies
run: yarn install --frozen-lockfile

- name: Build mobile app
run: yarn build:mobile

- name: Sync Capacitor
run: npx cap sync android

- name: Build Android APK
run: |
cd android
./gradlew assembleDebug
cd ..

- name: Enable KVM
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm

- name: Install Appium
run: |
npm install -g appium
appium driver install uiautomator2 || echo "Driver already installed"

- name: Run Android E2E tests
uses: reactivecircus/android-emulator-runner@v2
timeout-minutes: 45
with:
api-level: 31
target: default
arch: x86_64
force-avd-creation: false
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -no-snapshot-save
disable-animations: true
script: |
# Start Appium server (wdio service doesn't work reliably in CI)
appium --relaxed-security --log-level info &
sleep 15
# Run wdio directly - emulator is already running from the action
npx wdio run mobile-e2e/wdio.android.conf.ts

- name: Upload test screenshots
if: failure()
uses: actions/upload-artifact@v4
with:
name: android-e2e-screenshots
path: mobile-e2e/screenshots/
retention-days: 7

- name: Upload Appium logs
if: failure()
uses: actions/upload-artifact@v4
with:
name: android-appium-logs
path: mobile-e2e/logs/
retention-days: 7
16 changes: 13 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,14 @@ DerivedData

*storybook.log

# Xcode generated
ios/App/App.xcworkspace/
ios/App/App.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/
# Xcode generated (keep workspace and Package.resolved for CI)
ios/App/App.xcworkspace/xcuserdata/
ios/App/App.xcworkspace/xcshareddata/*
!ios/App/App.xcworkspace/xcshareddata/swiftpm/
ios/App/App.xcworkspace/xcshareddata/swiftpm/*
!ios/App/App.xcworkspace/xcshareddata/swiftpm/Package.resolved
ios/App/App.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/*
!ios/App/App.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

# Android release signing
android/keystore.properties
Expand All @@ -63,3 +68,8 @@ android/app/*.jks

# iOS build artifacts
ios/App/build/
ios/App/build-sim/

# Mobile E2E test artifacts
mobile-e2e/screenshots/
mobile-e2e/logs/
Loading
Loading