-
Notifications
You must be signed in to change notification settings - Fork 51
feat(pos-app): Add Maestro E2E testing infrastructure #303
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,144 @@ | ||
| name: e2e-tests-pos-android | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| push: | ||
| branches: | ||
| - main | ||
| - develop | ||
| paths: | ||
| - 'dapps/pos-app/**' | ||
| pull_request: | ||
| paths: | ||
| - 'dapps/pos-app/**' | ||
|
|
||
| jobs: | ||
| e2e-tests: | ||
| name: Maestro E2E Tests | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v3 | ||
|
|
||
| - name: Setup | ||
| uses: ./.github/actions/ci-setup | ||
| with: | ||
| root-path: dapps/pos-app | ||
| package-manager: npm | ||
|
|
||
| - name: Install Java 17 | ||
| uses: actions/setup-java@v3 | ||
| with: | ||
| distribution: 'zulu' | ||
| java-version: '17' | ||
| architecture: x86_64 | ||
|
|
||
| - name: Create env file | ||
| run: | | ||
| if [ -n "${{ vars.POS_DEV_ENV_FILE }}" ]; then | ||
| echo "${{ vars.POS_DEV_ENV_FILE }}" > dapps/pos-app/.env 2>/dev/null | ||
| fi | ||
|
|
||
| - name: Expo Prebuild | ||
| run: | | ||
| cd dapps/pos-app | ||
| npm run prebuild | ||
|
|
||
| - name: Cache Gradle | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: | | ||
| ~/.gradle/caches | ||
| ~/.gradle/wrapper | ||
| key: ${{ runner.os }}-gradle-pos-e2e-${{ hashFiles('dapps/pos-app/package.json', 'dapps/pos-app/app.json') }} | ||
| restore-keys: | | ||
| ${{ runner.os }}-gradle-pos-e2e- | ||
|
|
||
| - name: Build Release APK | ||
| id: build | ||
| run: | | ||
| cd dapps/pos-app/android | ||
| ./gradlew assembleRelease | ||
|
|
||
| - 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 Maestro | ||
| run: | | ||
| curl -Ls "https://get.maestro.mobile.dev" | bash | ||
| echo "$HOME/.maestro/bin" >> $GITHUB_PATH | ||
|
|
||
| - name: Run Maestro E2E Tests | ||
| id: maestro | ||
| uses: reactivecircus/android-emulator-runner@v2 | ||
| with: | ||
| api-level: 31 | ||
| arch: x86_64 | ||
| profile: pixel_6 | ||
| heap-size: 512M | ||
| ram-size: 4096M | ||
| emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim | ||
| disable-animations: true | ||
| script: | | ||
| adb install dapps/pos-app/android/app/build/outputs/apk/release/app-release.apk | ||
| $HOME/.maestro/bin/maestro test dapps/pos-app/e2e/ --format junit --output maestro-report.xml | ||
|
|
||
| - name: Upload Test Results | ||
| if: always() | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: maestro-test-results | ||
| path: maestro-report.xml | ||
|
|
||
| - name: Send Slack notification | ||
| if: always() && !cancelled() | ||
| uses: slackapi/[email protected] | ||
| with: | ||
| webhook: ${{ secrets.SLACK_WEBHOOK_URL }} | ||
| webhook-type: incoming-webhook | ||
| payload: | | ||
| { | ||
| "text": "POS App E2E Test Report", | ||
| "blocks": [ | ||
| { | ||
| "type": "header", | ||
| "text": { "type": "plain_text", "text": "🧪 POS App E2E Test Report" } | ||
| }, | ||
| { | ||
| "type": "section", | ||
| "fields": [ | ||
| { "type": "mrkdwn", "text": "*Branch:*\n`${{ github.ref_name }}`" }, | ||
| { "type": "mrkdwn", "text": "*Triggered by:*\n`${{ github.actor }}`" } | ||
| ] | ||
| }, | ||
| { | ||
| "type": "section", | ||
| "fields": [ | ||
| { "type": "mrkdwn", "text": "*Build:*\n`${{ steps.build.outcome == 'success' && '✅ Success' || '❌ Failed' }}`" }, | ||
| { "type": "mrkdwn", "text": "*E2E Tests:*\n`${{ steps.maestro.outcome == 'success' && '✅ Passed' || '❌ Failed' }}`" } | ||
| ] | ||
| }, | ||
| { | ||
| "type": "section", | ||
| "fields": [ | ||
| { "type": "mrkdwn", "text": "*Overall Status:*\n`${{ job.status == 'success' && '✅ Success' || '❌ Failed' }}`" } | ||
| ] | ||
| }, | ||
| { | ||
| "type": "actions", | ||
| "elements": [ | ||
| { | ||
| "type": "button", | ||
| "text": { "type": "plain_text", "text": "View Workflow Run" }, | ||
| "url": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -16,7 +16,7 @@ import * as Clipboard from "expo-clipboard"; | |||||||||||||
| import { Image } from "expo-image"; | ||||||||||||||
| import { router, UnknownOutputParams, useLocalSearchParams } from "expo-router"; | ||||||||||||||
| import React, { useCallback, useEffect, useState } from "react"; | ||||||||||||||
| import { StyleSheet, View } from "react-native"; | ||||||||||||||
| import { Linking, StyleSheet, View } from "react-native"; | ||||||||||||||
| import { v4 as uuidv4 } from "uuid"; | ||||||||||||||
|
|
||||||||||||||
| interface ScreenParams extends UnknownOutputParams { | ||||||||||||||
|
|
@@ -65,9 +65,13 @@ export default function ScanScreen() { | |||||||||||||
| resetNavigation("/amount"); | ||||||||||||||
| }; | ||||||||||||||
|
|
||||||||||||||
| const handleCopyPaymentUrl = async () => { | ||||||||||||||
| await Clipboard.setStringAsync(qrUri); | ||||||||||||||
| showSuccessToast("Payment URL copied"); | ||||||||||||||
| const handleLogoPress = async () => { | ||||||||||||||
| try { | ||||||||||||||
| await Clipboard.setStringAsync(qrUri); | ||||||||||||||
| await Linking.openURL(qrUri); | ||||||||||||||
| } catch { | ||||||||||||||
| showErrorToast("Failed to open payment URL"); | ||||||||||||||
|
Comment on lines
+71
to
+73
|
||||||||||||||
| await Linking.openURL(qrUri); | |
| } catch { | |
| showErrorToast("Failed to open payment URL"); | |
| showSuccessToast("Payment URL copied to clipboard"); | |
| } catch { | |
| showErrorToast("Failed to copy payment URL"); |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,83 @@ | ||||||
| # E2E Tests with Maestro | ||||||
|
|
||||||
| This directory contains end-to-end tests using [Maestro](https://maestro.mobile.dev/). | ||||||
|
|
||||||
| ## Prerequisites | ||||||
|
|
||||||
| 1. Install Maestro CLI: | ||||||
| ```bash | ||||||
| curl -Ls "https://get.maestro.mobile.dev" | bash | ||||||
| ``` | ||||||
|
|
||||||
| 2. Build and install the app on your device/emulator: | ||||||
| ```bash | ||||||
| npm run android:build | ||||||
| adb install android/app/build/outputs/apk/release/app-release.apk | ||||||
| ``` | ||||||
|
|
||||||
| 3. Configure merchant settings in the app before running tests | ||||||
|
|
||||||
| ## Running Tests | ||||||
|
|
||||||
| ### Run all tests | ||||||
| ```bash | ||||||
| maestro test e2e/ | ||||||
| ``` | ||||||
|
|
||||||
| ### Run specific test | ||||||
| ```bash | ||||||
| maestro test e2e/payment-flow.yaml | ||||||
| ``` | ||||||
|
|
||||||
| ### Run with Maestro Studio (interactive debugging) | ||||||
| ```bash | ||||||
| maestro studio | ||||||
| ``` | ||||||
|
|
||||||
| ## Test Files | ||||||
|
|
||||||
| | File | Description | | ||||||
| |------|-------------| | ||||||
| | `payment-flow.yaml` | Basic payment flow: New sale → Enter amount → QR code → Copy URL | | ||||||
|
|
||||||
| ## Adding New Tests | ||||||
|
|
||||||
| 1. Create a new `.yaml` file in this directory | ||||||
| 2. Start with `appId: com.reown.pos` | ||||||
|
||||||
| 2. Start with `appId: com.reown.pos` | |
| 2. Start with `appId: com.reown.mobilepos` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The maestro command outputs to 'maestro-report.xml' without specifying a directory, which means it will be created in the current working directory. Since the script runs in the emulator context and the working directory is not explicitly set, the output file location may be unpredictable. Consider using an absolute path or explicitly setting the working directory, for example: '$HOME/.maestro/bin/maestro test dapps/pos-app/e2e/ --format junit --output ${{ github.workspace }}/maestro-report.xml'