From ef281c800652e4ae89c0f88d28355ce507cc188b Mon Sep 17 00:00:00 2001 From: Leendert de Borst Date: Fri, 16 Jan 2026 12:31:01 +0100 Subject: [PATCH] Create ios-ui-tests.yml GitHub Action (#1404) --- .github/workflows/ios-ui-tests.yml | 200 +++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 .github/workflows/ios-ui-tests.yml diff --git a/.github/workflows/ios-ui-tests.yml b/.github/workflows/ios-ui-tests.yml new file mode 100644 index 000000000..9d3720e8e --- /dev/null +++ b/.github/workflows/ios-ui-tests.yml @@ -0,0 +1,200 @@ +name: iOS UI Tests + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + ios-ui-tests: + timeout-minutes: 60 + runs-on: macos-15 + defaults: + run: + working-directory: apps/mobile-app + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Xcode + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: latest-stable + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + cache-dependency-path: apps/mobile-app/package-lock.json + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 9.0.x + + - name: Setup Rust toolchain + uses: dtolnay/rust-toolchain@stable + with: + targets: aarch64-apple-ios,aarch64-apple-ios-sim,x86_64-apple-ios + + - name: Cache Rust dependencies + uses: Swatinem/rust-cache@v2 + with: + workspaces: core/rust + + - name: Setup Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.2' + bundler-cache: true + + - name: Install CocoaPods + run: sudo gem install cocoapods + + - name: Build core libraries (including iOS Rust) + run: | + cd ../../core + chmod +x build-and-distribute.sh + ./build-and-distribute.sh + + - name: Verify core library distribution + run: | + TARGET_DIRS=( + "utils/dist/core/identity-generator" + "utils/dist/core/password-generator" + "utils/dist/core/models" + "utils/dist/core/vault" + ) + for dir in "${TARGET_DIRS[@]}"; do + if [ ! -d "$dir" ]; then + echo "Error: Directory $dir does not exist" + exit 1 + fi + done + echo "Core library distribution verified" + + - name: Install mobile app dependencies + run: npm ci + + - name: Install CocoaPods dependencies + run: | + cd ios + pod install + + - name: Install .NET workloads + working-directory: apps/server + run: dotnet workload install wasm-tools + + - name: Build API server + working-directory: apps/server + run: dotnet build AliasVault.Api + + - name: Start dev database + working-directory: ${{ github.workspace }} + run: ./install.sh configure-dev-db start + + - name: Start API server + working-directory: apps/server/AliasVault.Api + run: | + dotnet run --no-build & + # Wait for API to be ready + echo "Waiting for API to start..." + for i in {1..30}; do + if curl -s http://localhost:5092/v1/Auth/status > /dev/null 2>&1; then + echo "API is ready!" + break + fi + echo "Attempt $i: API not ready yet..." + sleep 2 + done + env: + ConnectionStrings__AliasServerDbContext: "Host=localhost;Port=5433;Database=aliasdb_e2e_ios;Username=aliasvault;Password=password" + JWT_KEY: "12345678901234567890123456789012" + DATA_PROTECTION_CERT_PASS: "Development" + PUBLIC_REGISTRATION_ENABLED: "true" + ADMIN_PASSWORD_HASH: "AQAAAAIAAYagAAAAEKWfKfa2gh9Z72vjAlnNP1xlME7FsunRznzyrfqFte40FToufRwa3kX8wwDwnEXZag==" + ADMIN_PASSWORD_GENERATED: "2024-01-01T00:00:00Z" + + - name: Boot iOS Simulator + run: | + # List available simulators + xcrun simctl list devices available + + # Find and boot iPhone 16 Pro simulator (or fallback to any iPhone) + SIMULATOR_ID=$(xcrun simctl list devices available | grep "iPhone 16 Pro" | head -1 | grep -oE '[A-F0-9-]{36}') + + if [ -z "$SIMULATOR_ID" ]; then + # Fallback to iPhone 15 Pro + SIMULATOR_ID=$(xcrun simctl list devices available | grep "iPhone 15 Pro" | head -1 | grep -oE '[A-F0-9-]{36}') + fi + + if [ -z "$SIMULATOR_ID" ]; then + # Fallback to any iPhone + SIMULATOR_ID=$(xcrun simctl list devices available | grep "iPhone" | head -1 | grep -oE '[A-F0-9-]{36}') + fi + + if [ -z "$SIMULATOR_ID" ]; then + echo "No iPhone simulator found!" + exit 1 + fi + + echo "Booting simulator: $SIMULATOR_ID" + xcrun simctl boot "$SIMULATOR_ID" || true + echo "SIMULATOR_ID=$SIMULATOR_ID" >> $GITHUB_ENV + + - name: Build iOS app for testing + run: | + cd ios + xcodebuild build-for-testing \ + -workspace AliasVault.xcworkspace \ + -scheme AliasVault \ + -sdk iphonesimulator \ + -destination "id=${{ env.SIMULATOR_ID }}" \ + -derivedDataPath build \ + CODE_SIGNING_ALLOWED=NO \ + IDEFileSystemSynchronizedGroupsAreEnabled=NO + env: + IDEFileSystemSynchronizedGroupsAreEnabled: NO + + - name: Run iOS UI Tests + run: | + cd ios + xcodebuild test-without-building \ + -workspace AliasVault.xcworkspace \ + -scheme AliasVault \ + -sdk iphonesimulator \ + -destination "id=${{ env.SIMULATOR_ID }}" \ + -derivedDataPath build \ + -only-testing:AliasVaultUITests \ + -resultBundlePath TestResults.xcresult \ + CODE_SIGNING_ALLOWED=NO \ + IDEFileSystemSynchronizedGroupsAreEnabled=NO + env: + API_URL: "http://localhost:5092" + IDEFileSystemSynchronizedGroupsAreEnabled: NO + + - name: Upload test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: ios-ui-test-results + path: apps/mobile-app/ios/TestResults.xcresult + retention-days: 14 + + - name: Upload screenshots on failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: ios-ui-test-screenshots + path: | + apps/mobile-app/ios/build/Logs/Test/**/*.png + apps/mobile-app/ios/build/Logs/Test/**/*.jpg + retention-days: 14