Add CircleCI job for maestro E2E tests#826
Open
ajpallares wants to merge 47 commits into
Open
Conversation
Fastlane consistency updates
* Version bump for 3.0.0-beta.1 * Updates VERSIONS.md
981e194 to
8e88cba
Compare
22cf6fc to
7a1eec0
Compare
8e88cba to
d2164aa
Compare
d309589 to
d6fec48
Compare
d2164aa to
91d2e25
Compare
d6fec48 to
dbaca90
Compare
Covers the multi-target Package.swift / cross-project cinterop wiring introduced for Xcode 26 compatibility: per-target scratch directories, dependency header copying, and modulemap inclusion of dependency headers. Also corrects the `dependencyHeaders` docstring on `SwiftBuildTask` to describe the actual modulemap-based mechanism. Made-with: Cursor
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
The MultiTargetPackageBuilder already knows which targets depend on which, and the test context knows which subproject registered each target. Derive evaluationDependsOn calls automatically instead of requiring tests to pass dependsOnSubprojects explicitly. This closes a footgun where alphabetically-sorted subproject names could mask a missing dependency declaration. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Avoids a hardcoded path for the dep's scratch directory assertion; both dep and consumer now use getScratchDir(projectDir) so the test stays correct if the production layout changes. Co-authored-by: Cursor <cursoragent@cursor.com>
The previous assertion checked that a root-level shared scratch dir didn't exist, but that path would never exist anyway since the root project has no Swift packages. Instead, assert that each scratch dir lives under its own subproject's build directory and that they differ. Co-authored-by: Cursor <cursoragent@cursor.com>
Replace the silent `if (depHeader.exists())` guard with a `check` assertion so a missing dependency header surfaces immediately instead of deferring to a confusing cinterop "unresolved type" error. Co-authored-by: Cursor <cursoragent@cursor.com>
The cinterop task already depends on swiftBuildTask, which itself depends on each cross-project compileSwift task. The explicit dependsOn on the cinterop task was therefore redundant and duplicated the wiring expressed on swiftBuildTask. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…xtract moduleDir helper Co-authored-by: Cursor <cursoragent@cursor.com>
…ralize task name, fix formatting Co-authored-by: Cursor <cursoragent@cursor.com>
…ernal Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
* Add maestro E2E test app for 3.0.0
Adds a minimal Kotlin Multiplatform Compose app under e2e-tests/MaestroTestApp
for running Maestro E2E tests against the RevenueCat SDK.
Adapted for the 3.0.0 architecture:
- No CocoaPods dependency — iOS builds via Gradle + purchases-ios submodule
- Uses projects.knUi for native iOS paywall types
- Paywall presented as a native modal on iOS to work around Compose
Multiplatform's UIKitViewController accessibility bridge limitation
that prevents Maestro from seeing embedded SwiftUI content
- Android uses inline Compose Paywall which works with Maestro
- Uses RCPaywallViewControllerDelegateProtocol (not the removed PaywallProxy)
Made-with: Cursor
* Fix build.gradle.kts for Kotlin 2.3.20
Remove deprecated kotlinOptions { jvmTarget } block — the android {}
compileOptions block already sets Java compatibility, and Kotlin 2.3.20
no longer supports the old KotlinCommonOptions.jvmTarget accessor.
Made-with: Cursor
* Exclude MaestroTestApp from binary compatibility validation
The E2E test app is an application, not a library — it has no public
API surface to validate.
Made-with: Cursor
* Use SDK's Paywall composable directly instead of custom PaywallPresenter
Replace the expect/actual PaywallPresenter with the SDK's own
Paywall(options) composable — the E2E app should test the KMP public
API, not a custom native presentation layer.
Made-with: Cursor
* Skip test cases list in maestro tests using launch arguments
Pass e2e_test_flow as a launchApp argument so the app navigates
directly to the target test case screen, making tests faster.
The Test Cases list is preserved for manual/local usage.
Made-with: Cursor
* Refactor test case routing to use a central registry
Extract TEST_CASES registry to a dedicated TestCases.kt file, matching
the pattern used by purchases-capacitor and purchases-flutter. The
TestCasesScreen now dynamically builds from the registry, and App.kt
routes by flow key instead of a hardcoded Screen enum.
Made-with: Cursor
* Use version catalog for MaestroTestApp minSdk
Match the SDK's minSdk (21) instead of hardcoding 24.
Made-with: Cursor
* Document launch arguments and how to add new test cases
Made-with: Cursor
* Revert MaestroTestApp minSdk to 24 (required by revenuecatui)
The revenuecatui module has minSdk 24, which is higher than the SDK's
global android-minSdk of 21. Since MaestroTestApp depends on
revenuecatui, it must use minSdk 24.
Made-with: Cursor
* Simplify customer info fetching, remove delegate
Re-fetch customer info when the paywall is dismissed instead of
maintaining a global delegate. Also add a comment explaining the
minSdk 24 requirement.
Made-with: Cursor
* Review feedback: fix build phase and update README
- Remove reference to non-existent disable-x64.init.gradle.kts from the
Xcode build phase (ARCHS/EXCLUDED_ARCHS env vars already handle this)
- Update README to reflect that Xcode handles the Kotlin framework build
via its build phase, and clarify the CI vs local build flow
Made-with: Cursor
* Add .gitignore for MaestroTestApp
Covers Xcode build output and user-specific project data.
Made-with: Cursor
* Update README API key section with lane name and local run instructions
Made-with: Cursor
* Move API key commit warning to apply to both local run methods
Made-with: Cursor
* Remove unused testTag modifiers from PurchaseThroughPaywallScreen
Maestro uses visible text, not Compose test tags.
Made-with: Cursor
* Add maestro E2E test flows
Adds Maestro YAML test flows under e2e-tests/maestro/:
- purchase_through_paywall: navigates to the paywall screen, waits for
the V2 paywall to render, confirms the test-store purchase, and
verifies the "pro" entitlement is active
- confirm_purchase: reusable subflow for the sandbox purchase dialog
- config.yaml: sets the app ID for all flows
Made-with: Cursor
* Use launch arguments to skip test cases list in maestro tests
Navigate directly to the target test case screen via e2e_test_flow
launch argument instead of tapping through the test cases list.
Made-with: Cursor
* Use exact strings in confirm_purchase instead of regex
Both iOS and Android now show the same text, so regex patterns
are no longer needed. Matches the Capacitor approach.
Made-with: Cursor
* Remove redundant appId from confirm_purchase subflow
The parent flow already sets appId, so the subflow doesn't need it.
Made-with: Cursor
* Restore appId in confirm_purchase subflow
Maestro requires appId in any flow file that has a config section (---
separator). This is not redundant - without it Maestro fails with
"Either 'url' or 'appId' must be specified in the config section."
Made-with: Cursor
- iOS job uses xcode26 executor (matching other jobs in this branch) - Android job uses machine:android:2025.10.1 with emulator - Fastlane lanes: change_maestro_test_app_api_key, build_maestro_test_app_ios, build_maestro_test_app_android, run_maestro_e2e_tests_ios/android - Pre-boots iOS simulator in parallel with build for faster CI - Uses run_maestro_e2e_tests from fastlane-plugin-revenuecat_internal for retry logic - Crash/logcat collection on failure for diagnostics Co-authored-by: Cursor <cursoragent@cursor.com>
66e5543 to
4e586c4
Compare
Xcode 26 ships with iPhone 17 as the default simulator. Co-authored-by: Cursor <cursoragent@cursor.com>
268ad87 to
f49600b
Compare
…e2e-test-ci-job-v3 Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # .circleci/config.yml # CHANGELOG-LATEST.md # CHANGELOG.md # Gemfile.lock # VERSIONS.md # core/src/iosMain/kotlin/com/revenuecat/purchases/kmp/AdTracker.ios.kt # core/src/iosMain/kotlin/com/revenuecat/purchases/kmp/Purchases.ios.kt # fastlane/Fastfile # gradle/libs.versions.toml # gradle/wrapper/gradle-wrapper.properties # kn-core/build.gradle.kts # kn-ui/api/kn-ui.klib.api # kn-ui/build.gradle.kts # mappings/src/iosMain/kotlin/com/revenuecat/purchases/kmp/mappings/AdEventTypes.ios.kt # mappings/src/iosMain/kotlin/com/revenuecat/purchases/kmp/mappings/EntitlementVerificationMode.ios.kt # mappings/src/iosMain/kotlin/com/revenuecat/purchases/kmp/mappings/Price.ios.kt # mappings/src/iosMain/kotlin/com/revenuecat/purchases/kmp/mappings/PurchasesAreCompletedBy.ios.kt # mappings/src/iosMain/kotlin/com/revenuecat/purchases/kmp/mappings/StoreKitVersion.ios.kt # mappings/src/iosMain/kotlin/com/revenuecat/purchases/kmp/mappings/StoreMessageType.ios.kt # mappings/src/iosMain/kotlin/com/revenuecat/purchases/kmp/mappings/StoreProduct.ios.kt # revenuecatui/src/iosMain/kotlin/com/revenuecat/purchases/kmp/ui/revenuecatui/PaywallOptionsKtx.kt # revenuecatui/src/iosMain/kotlin/com/revenuecat/purchases/kmp/ui/revenuecatui/UIKitCustomerCenter.kt # revenuecatui/src/iosMain/kotlin/com/revenuecat/purchases/kmp/ui/revenuecatui/UIKitPaywall.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Adds CI jobs to build and run Maestro E2E tests on every PR commit.
Description
machine: android:2025.10.1) Maestro E2E testschange_maestro_test_app_api_key,build_maestro_test_app,run_maestro_e2e_tests_ios,run_maestro_e2e_tests_androidrun_maestro_e2e_testsfromfastlane-plugin-revenuecat_internalfor retry logicRelated PRs: #824 (E2E test app), #825 (Maestro test flows)