diff --git a/.github/workflows/test-e2e.yaml b/.github/workflows/test-e2e.yaml index 7fec7c436a..5db817e259 100644 --- a/.github/workflows/test-e2e.yaml +++ b/.github/workflows/test-e2e.yaml @@ -36,7 +36,7 @@ jobs: test-local-android: name: Test on Android - runs-on: ubuntu-24.04 + runs-on: ubuntu-latest if: github.repository == 'mobile-dev-inc/maestro' needs: build diff --git a/.github/workflows/update-samples.yaml b/.github/workflows/update-samples.yaml new file mode 100644 index 0000000000..dbd1445836 --- /dev/null +++ b/.github/workflows/update-samples.yaml @@ -0,0 +1,31 @@ +name: Update samples + +on: + push: + branches: [main] + +jobs: + main: + runs-on: ubuntu-latest + if: github.repository == 'mobile-dev-inc/maestro' + + steps: + - name: Clone repository + uses: actions/checkout@v4 + + - name: Authenticate to Google Cloud + uses: google-github-actions/auth@v2 + with: + # These credentials should only have write access to the bucket + credentials_json: ${{ secrets.GCP_MOBILEDEV_BUCKET_CREDENTIALS }} + + - name: Set up Google Cloud CLI + uses: google-github-actions/setup-gcloud@v2 + with: + version: '>= 484.0.0' + project_id: perf-dev-289002 + + - name: Upload samples to public Google Cloud Storage bucket + run: | + cd e2e/ + ./update_samples diff --git a/e2e/.gitignore b/e2e/.gitignore index d427af6407..57a77c1db6 100644 --- a/e2e/.gitignore +++ b/e2e/.gitignore @@ -1 +1,4 @@ apps/ + +samples/ +samples.zip diff --git a/e2e/README.md b/e2e/README.md index 5a3feeded3..fc081f3b28 100644 --- a/e2e/README.md +++ b/e2e/README.md @@ -2,6 +2,8 @@ This directory contains glue code for testing Maestro itself. +## Testing + Typical workflow is: 1. Start Android emulator and iOS simulator @@ -9,4 +11,45 @@ Typical workflow is: 3. `install_apps` 4. `run_tests` -We try to keep scripts in files, so we don't get too tightly coupled to GitHub Action. +We try to keep shell code in separate files, so we don't get too tightly coupled +to GitHub Actions. + +### Expected failures + +Let's say a critical bug is introduced that causes Maestro to always mark all +tests as passed. If our e2e test suite only was only checking if all tests pass +(i.e. `maestro test` exit code is 0), then wouldn't catch such a bug. + +To prevent this, all flows in this directory MUST have a `passing` or `failing` +label, so the correct outcome can be asserted. + +## Samples + +This directory also contains samples that are downloaded by the `maestro download-samples` command, +and some glue code to facilitate updating those samples. + +`maestro download-samples` provides a set of flows and apps so that users can +quickly try out Maestro, without having to write any flows for their own app. + +`download-samples` downloads these files and apps from our publicly-available +Google Cloud Storage bucket (hosted on `storage.googleapis.com`). + +### Intro + +The samples are automatically updated by the GitHub Action on every new commit +to the `main` branch. + +There zip archive that is downloaded by `download-samples` consists of 2 things: +- the Maestro workspace with flows (located in the `workspaces/wikipedia` directory) +- the app binary files that are used in the flows (located in the `apps` directory) + +App binary files are heavy, so we don't store them in the repository. Instead, they are hosted +on publicly available directory in Google Cloud Storage: + +### Update the samples + +Run the script: + +```console +./update_samples +``` diff --git a/e2e/download_apps b/e2e/download_apps index 5a7f361cbf..6e419c6da1 100755 --- a/e2e/download_apps +++ b/e2e/download_apps @@ -1,5 +1,4 @@ #!/usr/bin/env sh - set -eu # Download apps from URLs listed in manifest.txt. @@ -18,6 +17,5 @@ while read -r url; do extension="${app_file##*.}" if [ "$extension" = "zip" ]; then unzip -qq -o -d ./apps "$app_file" -x "__MACOSX/*" - rm "$app_file" fi done /dev/null 2>&1 || { echo "adb is required" && exit 1; } @@ -12,10 +17,10 @@ for file in ./apps/*; do extension="${file##*.}" if [ "$extension" = "apk" ]; then - adb install -r "$file" >/dev/null + adb install -r "$file" >/dev/null || echo "adb: could not install $filename" elif [ "$extension" = "app" ] && [ "$(uname)" = "Darwin" ]; then - xcrun simctl install booted "$file" + xcrun simctl install booted "$file" || echo "xcrun: could not install $filename" else - echo "unknown file extension $extension" + echo "ignored unsupported file extension $extension" fi done diff --git a/e2e/manifest.txt b/e2e/manifest.txt index 3609de05ec..24ed5e1e11 100644 --- a/e2e/manifest.txt +++ b/e2e/manifest.txt @@ -1,3 +1,3 @@ -https://storage.googleapis.com/mobile.dev/samples/e2e_apps/wikipedia.apk -https://storage.googleapis.com/mobile.dev/samples/e2e_apps/Wikipedia.zip -https://storage.googleapis.com/mobile.dev/samples/e2e_apps/nowinandroid.apk +https://storage.googleapis.com/mobile.dev/cli_e2e/wikipedia.apk +https://storage.googleapis.com/mobile.dev/cli_e2e/wikipedia.zip +https://storage.googleapis.com/mobile.dev/cli_e2e/nowinandroid.apk diff --git a/e2e/run_tests b/e2e/run_tests index 04d5cbd434..00f07a5706 100755 --- a/e2e/run_tests +++ b/e2e/run_tests @@ -1,22 +1,35 @@ #!/usr/bin/env sh - set -eu +# Runs all tests in the workspaces directory. + command -v maestro >/dev/null 2>&1 || { echo "maestro is required" && exit 1; } [ "$(basename "$PWD")" = "e2e" ] || { echo "must be run from e2e directory" && exit 1; } -selected_app="${1:-}" - FAILED=false -for file in ./flows/*; do - filename="$(basename "$file")" - if [ -z "$selected_app" ] || [ "$selected_app" = "$filename" ]; then - cd "$file" || exit 1 - maestro --device emulator-5554 test . || FAILED=true - cd - >/dev/null || exit 1 +# Run passing tests +for workspace_dir in ./workspaces/*; do + echo "run passing tests for app $workspace_dir" + if [ "$(basename "$workspace_dir")" = "wikipedia" ]; then + # wikipedia flows have no passing/failing labels + maestro test --exclude-tags ios "$workspace_dir" || FAILED=true + continue + fi + + maestro test --include-tags passing --exclude-tags ios "$workspace_dir" || FAILED=true +done + +# Run failing tests +for workspace_dir in ./workspaces/*; do + if [ "$(basename "$workspace_dir")" = "wikipedia" ]; then + # wikipedia workspace has no failing flows + continue fi + echo "run failing tests for app $workspace_dir" + + maestro test --include-tags failing --exclude-tags ios "$workspace_dir" && FAILED=true done if [ "$FAILED" = true ]; then diff --git a/e2e/update_samples b/e2e/update_samples new file mode 100755 index 0000000000..b729aec430 --- /dev/null +++ b/e2e/update_samples @@ -0,0 +1,31 @@ +#!/usr/bin/env sh +set -eu + +# Updates the samples that are hosted in mobile.dev's GCS bucket ($SAMPLES_URL). +# The samples are for use with `maestro download-samples` command. + +[ "$(basename "$PWD")" = "e2e" ] || { echo "must be run from e2e directory" && exit 1; } + +command -v curl >/dev/null 2>&1 || { echo "curl is required" && exit 1; } +command -v gsutil >/dev/null 2>&1 || { echo "gsutil is required" && exit 1; } + +SAMPLES_URL="gs://mobile.dev/samples/samples.zip" + +if [ ! -d apps/ ]; then + ./download_apps +fi + +rm -rf samples/ samples.zip +mkdir -p samples/ +cp -r apps/wikipedia.apk apps/wikipedia.zip samples/ +cp -r workspaces/wikipedia/* samples/ +cp samples/wikipedia.apk samples/sample.apk # The name is being depended upon. +cp samples/wikipedia.zip samples/sample.zip # The name is being depended upon. +cd samples/ + +zip -r -q ../samples.zip . -x "/**/.*" -x "__MACOSX" + +cd .. + +gsutil cp samples.zip "$SAMPLES_URL" +gsutil acl ch -r -u AllUsers:R "$SAMPLES_URL" diff --git a/e2e/flows/nowinandroid/bookmarks.yaml b/e2e/workspaces/nowinandroid/bookmarks_1.yaml similarity index 92% rename from e2e/flows/nowinandroid/bookmarks.yaml rename to e2e/workspaces/nowinandroid/bookmarks_1.yaml index e0e83929b5..536862066e 100644 --- a/e2e/flows/nowinandroid/bookmarks.yaml +++ b/e2e/workspaces/nowinandroid/bookmarks_1.yaml @@ -1,4 +1,6 @@ appId: com.google.samples.apps.nowinandroid.demo.debug +tags: + - passing --- - launchApp: clearState: true diff --git a/e2e/workspaces/nowinandroid/bookmarks_2.yaml b/e2e/workspaces/nowinandroid/bookmarks_2.yaml new file mode 100644 index 0000000000..cd19f5b13a --- /dev/null +++ b/e2e/workspaces/nowinandroid/bookmarks_2.yaml @@ -0,0 +1,8 @@ +appId: com.google.samples.apps.nowinandroid.demo.debug +tags: + - failing +--- +- launchApp: + clearState: true +- tapOn: + id: non-existent-id-to-fail-this-test diff --git a/samples/android-advanced-flow.yaml b/e2e/workspaces/wikipedia/android-advanced-flow.yaml similarity index 95% rename from samples/android-advanced-flow.yaml rename to e2e/workspaces/wikipedia/android-advanced-flow.yaml index 31805bd56e..62c91abd4d 100644 --- a/samples/android-advanced-flow.yaml +++ b/e2e/workspaces/wikipedia/android-advanced-flow.yaml @@ -1,5 +1,6 @@ appId: org.wikipedia tags: + - android - advanced --- - runFlow: subflows/onboarding-android.yaml diff --git a/samples/android-flow.yaml b/e2e/workspaces/wikipedia/android-flow.yaml similarity index 67% rename from samples/android-flow.yaml rename to e2e/workspaces/wikipedia/android-flow.yaml index 1f85a94ef7..6f28026579 100644 --- a/samples/android-flow.yaml +++ b/e2e/workspaces/wikipedia/android-flow.yaml @@ -1,3 +1,5 @@ appId: org.wikipedia +tags: + - android --- - launchApp diff --git a/samples/ios-advanced-flow.yaml b/e2e/workspaces/wikipedia/ios-advanced-flow.yaml similarity index 98% rename from samples/ios-advanced-flow.yaml rename to e2e/workspaces/wikipedia/ios-advanced-flow.yaml index 68ca89b516..fd5551a4be 100644 --- a/samples/ios-advanced-flow.yaml +++ b/e2e/workspaces/wikipedia/ios-advanced-flow.yaml @@ -1,5 +1,6 @@ appId: org.wikimedia.wikipedia tags: + - ios - advanced --- - runFlow: subflows/onboarding-ios.yaml @@ -18,4 +19,3 @@ tags: - eraseText - inputText: qwerty - assertVisible: ${output.result} - diff --git a/samples/ios-flow.yaml b/e2e/workspaces/wikipedia/ios-flow.yaml similarity index 77% rename from samples/ios-flow.yaml rename to e2e/workspaces/wikipedia/ios-flow.yaml index fbc91ad300..917b5b4b16 100644 --- a/samples/ios-flow.yaml +++ b/e2e/workspaces/wikipedia/ios-flow.yaml @@ -1,3 +1,5 @@ appId: org.wikimedia.wikipedia +tags: + - ios --- - launchApp diff --git a/samples/scripts/getSearchQuery.js b/e2e/workspaces/wikipedia/scripts/getSearchQuery.js similarity index 100% rename from samples/scripts/getSearchQuery.js rename to e2e/workspaces/wikipedia/scripts/getSearchQuery.js diff --git a/samples/subflows/onboarding-android.yaml b/e2e/workspaces/wikipedia/subflows/onboarding-android.yaml similarity index 100% rename from samples/subflows/onboarding-android.yaml rename to e2e/workspaces/wikipedia/subflows/onboarding-android.yaml diff --git a/samples/subflows/onboarding-ios.yaml b/e2e/workspaces/wikipedia/subflows/onboarding-ios.yaml similarity index 100% rename from samples/subflows/onboarding-ios.yaml rename to e2e/workspaces/wikipedia/subflows/onboarding-ios.yaml diff --git a/samples/wikipedia-android-advanced/auth/login.yml b/e2e/workspaces/wikipedia/wikipedia-android-advanced/auth/login.yml similarity index 100% rename from samples/wikipedia-android-advanced/auth/login.yml rename to e2e/workspaces/wikipedia/wikipedia-android-advanced/auth/login.yml diff --git a/samples/wikipedia-android-advanced/auth/signup.yml b/e2e/workspaces/wikipedia/wikipedia-android-advanced/auth/signup.yml similarity index 100% rename from samples/wikipedia-android-advanced/auth/signup.yml rename to e2e/workspaces/wikipedia/wikipedia-android-advanced/auth/signup.yml diff --git a/samples/wikipedia-android-advanced/dashboard/copy-paste.yml b/e2e/workspaces/wikipedia/wikipedia-android-advanced/dashboard/copy-paste.yml similarity index 100% rename from samples/wikipedia-android-advanced/dashboard/copy-paste.yml rename to e2e/workspaces/wikipedia/wikipedia-android-advanced/dashboard/copy-paste.yml diff --git a/samples/wikipedia-android-advanced/dashboard/feed.yml b/e2e/workspaces/wikipedia/wikipedia-android-advanced/dashboard/feed.yml similarity index 100% rename from samples/wikipedia-android-advanced/dashboard/feed.yml rename to e2e/workspaces/wikipedia/wikipedia-android-advanced/dashboard/feed.yml diff --git a/samples/wikipedia-android-advanced/dashboard/main.yml b/e2e/workspaces/wikipedia/wikipedia-android-advanced/dashboard/main.yml similarity index 100% rename from samples/wikipedia-android-advanced/dashboard/main.yml rename to e2e/workspaces/wikipedia/wikipedia-android-advanced/dashboard/main.yml diff --git a/samples/wikipedia-android-advanced/dashboard/saved.yml b/e2e/workspaces/wikipedia/wikipedia-android-advanced/dashboard/saved.yml similarity index 67% rename from samples/wikipedia-android-advanced/dashboard/saved.yml rename to e2e/workspaces/wikipedia/wikipedia-android-advanced/dashboard/saved.yml index 96e9163b59..be21915c06 100644 --- a/samples/wikipedia-android-advanced/dashboard/saved.yml +++ b/e2e/workspaces/wikipedia/wikipedia-android-advanced/dashboard/saved.yml @@ -3,5 +3,5 @@ appId: org.wikipedia - tapOn: "Saved" - tapOn: "Default list for your saved articles" - assertVisible: "Sun" -- assertVisible: "Star in the Solar System" +- assertVisible: "Star at the center of the Solar System" - back diff --git a/samples/wikipedia-android-advanced/dashboard/search.yml b/e2e/workspaces/wikipedia/wikipedia-android-advanced/dashboard/search.yml similarity index 74% rename from samples/wikipedia-android-advanced/dashboard/search.yml rename to e2e/workspaces/wikipedia/wikipedia-android-advanced/dashboard/search.yml index e505b2d07d..5a79e8a68d 100644 --- a/samples/wikipedia-android-advanced/dashboard/search.yml +++ b/e2e/workspaces/wikipedia/wikipedia-android-advanced/dashboard/search.yml @@ -2,7 +2,7 @@ appId: org.wikipedia --- - tapOn: "Search Wikipedia" - inputText: "Sun" -- assertVisible: "Star in the Solar System" +- assertVisible: "Star at the center of the Solar System" - tapOn: id: ".*page_list_item_title" - tapOn: diff --git a/samples/wikipedia-android-advanced/onboarding/add-language.yml b/e2e/workspaces/wikipedia/wikipedia-android-advanced/onboarding/add-language.yml similarity index 89% rename from samples/wikipedia-android-advanced/onboarding/add-language.yml rename to e2e/workspaces/wikipedia/wikipedia-android-advanced/onboarding/add-language.yml index 3d3a935322..bd498d6017 100644 --- a/samples/wikipedia-android-advanced/onboarding/add-language.yml +++ b/e2e/workspaces/wikipedia/wikipedia-android-advanced/onboarding/add-language.yml @@ -7,4 +7,4 @@ appId: org.wikipedia - inputText: "Greek" - assertVisible: "Ελληνικά" - tapOn: "Ελληνικά" -- tapOn: "Back" +- tapOn: "Navigate up" diff --git a/samples/wikipedia-android-advanced/onboarding/main.yml b/e2e/workspaces/wikipedia/wikipedia-android-advanced/onboarding/main.yml similarity index 100% rename from samples/wikipedia-android-advanced/onboarding/main.yml rename to e2e/workspaces/wikipedia/wikipedia-android-advanced/onboarding/main.yml diff --git a/samples/wikipedia-android-advanced/onboarding/remove-language.yml b/e2e/workspaces/wikipedia/wikipedia-android-advanced/onboarding/remove-language.yml similarity index 91% rename from samples/wikipedia-android-advanced/onboarding/remove-language.yml rename to e2e/workspaces/wikipedia/wikipedia-android-advanced/onboarding/remove-language.yml index 62a72458ff..9dfe1c1045 100644 --- a/samples/wikipedia-android-advanced/onboarding/remove-language.yml +++ b/e2e/workspaces/wikipedia/wikipedia-android-advanced/onboarding/remove-language.yml @@ -10,4 +10,4 @@ appId: org.wikipedia id: ".*menu_delete_selected" - tapOn: "OK" - assertNotVisible: "Ελληνικά" -- tapOn: "Back" +- tapOn: "Navigate up" diff --git a/samples/wikipedia-android-advanced/run-test.yml b/e2e/workspaces/wikipedia/wikipedia-android-advanced/run-test.yml similarity index 90% rename from samples/wikipedia-android-advanced/run-test.yml rename to e2e/workspaces/wikipedia/wikipedia-android-advanced/run-test.yml index b55901b797..bae39105ed 100644 --- a/samples/wikipedia-android-advanced/run-test.yml +++ b/e2e/workspaces/wikipedia/wikipedia-android-advanced/run-test.yml @@ -1,4 +1,6 @@ appId: org.wikipedia +tags: + - android --- - launchApp: clearState: true diff --git a/samples/wikipedia-android-advanced/scripts/fetchTestUser.js b/e2e/workspaces/wikipedia/wikipedia-android-advanced/scripts/fetchTestUser.js similarity index 100% rename from samples/wikipedia-android-advanced/scripts/fetchTestUser.js rename to e2e/workspaces/wikipedia/wikipedia-android-advanced/scripts/fetchTestUser.js diff --git a/samples/wikipedia-android-advanced/scripts/generateCredentials.js b/e2e/workspaces/wikipedia/wikipedia-android-advanced/scripts/generateCredentials.js similarity index 100% rename from samples/wikipedia-android-advanced/scripts/generateCredentials.js rename to e2e/workspaces/wikipedia/wikipedia-android-advanced/scripts/generateCredentials.js diff --git a/samples/Readme.md b/samples/Readme.md deleted file mode 100644 index 709a860151..0000000000 --- a/samples/Readme.md +++ /dev/null @@ -1,18 +0,0 @@ -# Maestro samples - -`maestro download-samples` provides a set of flows and apps so that users can quickly set up a maestro test, without having to create an app. - -download-samples downloads these files and apps from storage.googleapis.com. - -# Update the samples - -Although the samples are checked in, updating them requires a few manual steps: - -* Change the samples in this directory and merge these changes -* Run `maestro download-samples` -* Copy *.yaml to the samples directory created by download-samples -* Run `(cd samples && zip -r "$OLDPWD/samples.zip" . -x "/**/.*" -x "__MACOSX")` -* Open https://console.cloud.google.com/storage/browser/mobile.dev/samples -* Upload samples.zip -* Adjust the permissions of samples.zip to "Public to Internet" -* Run `maestro download-samples` and verify that the change was successful