Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
210 changes: 173 additions & 37 deletions .github/workflows/e2e-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,171 @@ name: 🧪 E2E Tests
on:
push:
branches: [main]
workflow_dispatch:
inputs:
test_type:
description: 'Type of E2E test to run'
required: true
default: 'smoke'
type: choice
options:
- smoke
- verification
- all
platform:
description: 'Platform to test on'
required: true
default: 'ios'
type: choice
options:
- ios
- android
- both

# Set minimal required permissions (contents: read-only). Note: GitHub Actions default permissions are broader.
permissions:
contents: read

env:
APP_VARIANT: internal
CI: true

jobs:
e2e-test:
name: Run ${{ matrix.test }} on ${{ matrix.platform }}
# Job for automatic push triggers (only iOS smoke test)
e2e-test-auto:
name: Run smoke on ios (auto)
runs-on: macos-latest
if: github.event_name == 'push'

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

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "22"

- name: Cache Yarn dependencies
uses: actions/cache@v4
with:
path: node_modules
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-

- name: Install dependencies
run: yarn

- name: Install Maestro
run: |
curl -Ls "https://get.maestro.mobile.dev" | bash
export PATH="$PATH":"$HOME/.maestro/bin"

- name: Decrypt GPG secure files
run: |
brew install [email protected]
echo ${{ secrets.SUPER_SECRET_PASSWORD }} | gpg1 --no-tty --passphrase-fd 0 google-services.json.gpg

- name: Build Expo app prebuild
run: yarn expo prebuild --platform ios

- name: Cache iOS build
uses: actions/cache@v4
with:
path: |
ios/build
~/Library/Developer/Xcode/DerivedData
key: ${{ runner.os }}-ios-build-${{ hashFiles('ios/**/*.pbxproj', 'ios/Podfile.lock', 'src/**/*.tsx', 'src/**/*.ts') }}
restore-keys: |
${{ runner.os }}-ios-build-

- name: Setup iOS Simulator
run: |
DEVICE_ID=$(xcrun xctrace list devices | grep -m 1 "iPhone" | awk '{print $NF}' | tr -d '()')
xcrun simctl boot $DEVICE_ID || true

- name: Build iOS App
run: |
xcodebuild -workspace DEMOCRACYInternal.xcworkspace -scheme DEMOCRACYInternal -configuration Release -sdk iphonesimulator -derivedDataPath build | xcbeautify
working-directory: ${{ github.workspace }}/ios

- name: Install iOS App
run: |
DEVICE_ID=$(xcrun xctrace list devices | grep -m 1 "iPhone" | awk '{print $NF}' | tr -d '()')
xcrun simctl install $DEVICE_ID ${{ github.workspace }}/ios/build/Build/Products/Release-iphonesimulator/DEMOCRACYInternal.app

- name: Launch iOS App
run: |
DEVICE_ID=$(xcrun xctrace list devices | grep -m 1 "iPhone" | awk '{print $NF}' | tr -d '()')
xcrun simctl launch $DEVICE_ID de.democracy-deutschland.clientapp.internal

- name: Wait for App to be ready
run: sleep 30

- name: Run Maestro Tests
run: |
export PATH="$PATH":"$HOME/.maestro/bin"
yarn test:e2e:smoke

- name: Upload Test Results
if: always()
uses: actions/upload-artifact@v4
with:
name: maestro-smoke-ios-auto
path: |
.maestro/test-results
.maestro/logs

# Job for manual workflow dispatch triggers
e2e-test-manual:
name: Run ${{ matrix.test }} on ${{ matrix.platform }} (manual)
strategy:
matrix:
include:
# iOS tests
- platform: ios
os: macos-latest
test: smoke
- platform: ios
os: macos-latest
test: verification

# Android tests (commented out due to current setup issues)
# - platform: android
# os: macos-latest
# test: smoke
# - platform: android
# os: macos-latest
# test: verification
- platform: ios
os: macos-latest
test: smoke
# - platform: ios
# os: macos-latest
# test: verification
runs-on: ${{ matrix.os }}
if: github.event_name == 'workflow_dispatch'

steps:
- name: Check if this test should run
id: should_run
run: |
should_run="false"
if [[ "${{ inputs.test_type }}" == "all" || "${{ inputs.test_type }}" == "${{ matrix.test }}" ]]; then
if [[ "${{ inputs.platform }}" == "both" || "${{ inputs.platform }}" == "${{ matrix.platform }}" ]]; then
should_run="true"
fi
fi
echo "should_run=$should_run" >> $GITHUB_OUTPUT
echo "Test: ${{ matrix.test }}, Platform: ${{ matrix.platform }}, Should run: $should_run"

- name: Checkout repository
if: steps.should_run.outputs.should_run == 'true'
uses: actions/checkout@v4

- name: Set up Node.js
if: steps.should_run.outputs.should_run == 'true'
uses: actions/setup-node@v4
with:
node-version: "22"

- name: Cache Yarn dependencies
if: steps.should_run.outputs.should_run == 'true'
uses: actions/cache@v4
with:
path: node_modules
Expand All @@ -46,24 +176,28 @@ jobs:
${{ runner.os }}-yarn-

- name: Install dependencies
if: steps.should_run.outputs.should_run == 'true'
run: yarn

- name: Install Maestro
if: steps.should_run.outputs.should_run == 'true'
run: |
curl -Ls "https://get.maestro.mobile.dev" | bash
export PATH="$PATH":"$HOME/.maestro/bin"

- name: Decrypt GPG secure files
if: steps.should_run.outputs.should_run == 'true'
run: |
brew install [email protected]
echo ${{ secrets.SUPER_SECRET_PASSWORD }} | gpg1 --no-tty --passphrase-fd 0 google-services.json.gpg

- name: Build Expo app prebuild
if: steps.should_run.outputs.should_run == 'true'
run: yarn expo prebuild --platform ${{ matrix.platform }}

- name: Cache iOS build
if: steps.should_run.outputs.should_run == 'true' && matrix.platform == 'ios'
uses: actions/cache@v4
if: matrix.platform == 'ios'
with:
path: |
ios/build
Expand All @@ -73,53 +207,55 @@ jobs:
${{ runner.os }}-ios-build-

- name: Setup iOS Simulator
if: matrix.platform == 'ios'
if: steps.should_run.outputs.should_run == 'true' && matrix.platform == 'ios'
run: |
DEVICE_ID=$(xcrun xctrace list devices | grep -m 1 "iPhone" | awk '{print $NF}' | tr -d '()')
xcrun simctl boot $DEVICE_ID || true

# - name: Setup Android Emulator
# if: matrix.platform == 'android'
# if: steps.should_run.outputs.should_run == 'true' && matrix.platform == 'android'
# uses: reactivecircus/android-emulator-runner@v2
# with:
# api-level: 31
# script: echo "Emulator started"

- name: Build iOS App
if: matrix.platform == 'ios'
if: steps.should_run.outputs.should_run == 'true' && matrix.platform == 'ios'
run: |
xcodebuild -workspace DEMOCRACYInternal.xcworkspace -scheme DEMOCRACYInternal -configuration Release -sdk iphonesimulator -derivedDataPath build | xcbeautify
working-directory: ${{ github.workspace }}/ios

# - name: Install iOS App
# if: matrix.platform == 'ios'
# run: |
# DEVICE_ID=$(xcrun xctrace list devices | grep -m 1 "iPhone" | awk '{print $NF}' | tr -d '()')
# xcrun simctl install $DEVICE_ID ios/build/Build/Products/Release-iphonesimulator/DEMOCRACYInternal.app
- name: Install iOS App
if: steps.should_run.outputs.should_run == 'true' && matrix.platform == 'ios'
run: |
DEVICE_ID=$(xcrun xctrace list devices | grep -m 1 "iPhone" | awk '{print $NF}' | tr -d '()')
xcrun simctl install $DEVICE_ID ios/build/Build/Products/Release-iphonesimulator/DEMOCRACYInternal.app

# - name: Launch iOS App
# if: matrix.platform == 'ios'
# run: |
# DEVICE_ID=$(xcrun xctrace list devices | grep -m 1 "iPhone" | awk '{print $NF}' | tr -d '()')
# xcrun simctl launch $DEVICE_ID de.democracy-deutschland.clientapp.internal
- name: Launch iOS App
if: steps.should_run.outputs.should_run == 'true' && matrix.platform == 'ios'
run: |
DEVICE_ID=$(xcrun xctrace list devices | grep -m 1 "iPhone" | awk '{print $NF}' | tr -d '()')
xcrun simctl launch $DEVICE_ID de.democracy-deutschland.clientapp.internal

# - name: Build and Run Android App
# if: matrix.platform == 'android'
# if: steps.should_run.outputs.should_run == 'true' && matrix.platform == 'android'
# run: yarn android

# - name: Wait for App to be ready
# run: sleep 30
- name: Wait for App to be ready
if: steps.should_run.outputs.should_run == 'true'
run: sleep 30

# - name: Run Maestro Tests
# run: |
# export PATH="$PATH":"$HOME/.maestro/bin"
# yarn test:e2e:${{ matrix.test }}
- name: Run Maestro Tests
if: steps.should_run.outputs.should_run == 'true'
run: |
export PATH="$PATH":"$HOME/.maestro/bin"
yarn test:e2e:${{ matrix.test }}

# - name: Upload Test Results
# if: always()
# uses: actions/upload-artifact@v4
# with:
# name: maestro-${{ matrix.test }}-${{ matrix.platform }}
# path: |
# .maestro/test-results
# .maestro/logs
- name: Upload Test Results
if: always() && steps.should_run.outputs.should_run == 'true'
uses: actions/upload-artifact@v4
with:
name: maestro-${{ matrix.test }}-${{ matrix.platform }}
path: |
.maestro/test-results
.maestro/logs
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,23 @@ We pin `[email protected]`, `[email protected]`, and `[email protected]` to avoid

The project uses Maestro for end-to-end testing. See [Testing Documentation](./docs/TESTING.md) for more information.

Run tests with:
Run tests locally with:

```bash
yarn test:e2e # Run all E2E tests
yarn test:e2e:smoke # Run smoke tests only
yarn test:e2e:verification # Run verification flow tests only
```

### Manual E2E Testing on GitHub Actions

E2E tests can be manually triggered on any branch through GitHub Actions:
1. Go to **Actions** → **🧪 E2E Tests** workflow
2. Click **Run workflow** and select test type and platform
3. Tests will run on the selected branch

This is useful for testing feature branches before merging.

## Deployment

This project uses fastlane for both iOS and Android deployments.
Expand Down
16 changes: 15 additions & 1 deletion docs/TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,18 @@ When writing new tests:

## CI/CD Integration

E2E tests are integrated into the GitHub Actions workflow to ensure automated testing on each pull request and deploy.
E2E tests are integrated into the GitHub Actions workflow to ensure automated testing on each push to main branch and can be manually triggered on any branch.

### Manual E2E Test Execution

You can manually trigger E2E tests on any branch using GitHub Actions:

1. Go to the **Actions** tab in the GitHub repository
2. Select the **🧪 E2E Tests** workflow
3. Click **Run workflow**
4. Choose your options:
- **Test type**: `smoke`, `verification`, or `all`
- **Platform**: `ios`, `android`, or `both` (currently only iOS is fully supported)
5. Click **Run workflow** to start the tests

This allows for testing feature branches and specific scenarios without waiting for merge to main.