From d80860acc9363ba3a967bcd873630c39415e4bc2 Mon Sep 17 00:00:00 2001 From: Kieran Osgood Date: Thu, 30 Jul 2026 18:46:51 +0100 Subject: [PATCH] feat(e2e): add the present-and-close checkout test on all four targets Second test of the rollout. It seeds a cart through the control link, presents checkout, closes it, and asserts the sheet is gone. Swift iOS, Kotlin Android, React Native iOS and React Native Android all run it. Assert on the close control, not on checkout copy: the React Native catalog sells a product called "Email", which the checkout field pattern matches, so copy-based assertions pass on the wrong screen. Extract flows/checkout/close.yaml so the close identifier, which differs by SDK version rather than by platform, has one home. The React Native order flow now calls it instead of carrying its own platform split. The four targets return to different screens after the sheet closes, so this test asserts dismissal only. The tests that place an order assert the cart. Add the checkout tag to the CI matrix and exclude full, because the remaining full tests place a real order and live under tests/react-native/. Pass the installed device to Maestro from both native runners. Maestro otherwise picks a device itself, and it can pick one the app is missing from. Co-Authored-By: Claude Opus 5 (1M context) --- e2e/README.md | 14 +++++++------- e2e/config/matrix.yml | 6 +++++- e2e/flows/checkout/assert-dismissed.yaml | 6 ++++++ .../checkout/assert-returned-to-empty-cart.yaml | 16 +--------------- e2e/flows/checkout/close.yaml | 5 +++++ .../e2e_matrix_to_browserstack_run_plan_test.rb | 6 +++--- .../checkout-hardcoded-buyer-identity.yaml | 3 ++- e2e/tests/shared/cart-from-control-link.yaml | 11 ----------- e2e/tests/shared/checkout-present-and-close.yaml | 16 ++++++++++++++++ 9 files changed, 45 insertions(+), 38 deletions(-) create mode 100644 e2e/flows/checkout/assert-dismissed.yaml create mode 100644 e2e/flows/checkout/close.yaml delete mode 100644 e2e/tests/shared/cart-from-control-link.yaml create mode 100644 e2e/tests/shared/checkout-present-and-close.yaml diff --git a/e2e/README.md b/e2e/README.md index e65bee9d7..9a317eccf 100644 --- a/e2e/README.md +++ b/e2e/README.md @@ -35,15 +35,15 @@ Each command runs the tests in `tests/shared/` and its target namespace under `tests/`. Narrow a run with `--tags`: ```bash -dev swift e2e --tags cart +dev swift e2e --tags checkout dev rn e2e ios --tags checkout -dev android e2e --tags cart,checkout +dev android e2e --tags launch,checkout ``` Both options match **any** listed tag, because that is how Maestro filters. -`--tags cart,checkout` runs the cart tests and the checkout tests. `--exclude-tags` -skips tests carrying any listed tag. `config.yaml` quarantines `flaky` and `wip` -for every run, so those need no command line option. +`--tags launch,checkout` runs the launch tests and the checkout tests. +`--exclude-tags` skips tests carrying any listed tag. `config.yaml` quarantines +`flaky` and `wip` for every run, so those need no command line option. ### Tags @@ -146,8 +146,8 @@ ruby e2e/scripts/e2e_matrix_to_browserstack_run_plan count - `tests/shared/` holds the tests every target runs through the CI matrix. - `tests//` holds platform-local tests. The matrix may ignore their tags. - `tests/shared/launch-smoke.yaml` is the shared launch smoke test. -- `tests/shared/cart-from-control-link.yaml` seeds a cart through the control link - and waits for the cart marker. +- `tests/shared/checkout-present-and-close.yaml` seeds a cart through the control + link, presents checkout, closes it, and asserts dismissal. - `tests/react-native/checkout-guest.yaml` composes the React Native guest checkout smoke test from those subflows. - `tests/react-native/checkout-hardcoded-buyer-identity.yaml` verifies checkout diff --git a/e2e/config/matrix.yml b/e2e/config/matrix.yml index a551be192..c342e7d8d 100644 --- a/e2e/config/matrix.yml +++ b/e2e/config/matrix.yml @@ -6,10 +6,14 @@ tests_path: tests tags: include: - launch - - cart + - checkout exclude: - flaky - wip + # The remaining `full` tests place a real order and live under tests/react-native/, + # so they cannot run on the Swift and Kotlin rows. Drop this entry when the shared + # ordering tests replace them. + - full applications: - id: react-native-ios target: react-native diff --git a/e2e/flows/checkout/assert-dismissed.yaml b/e2e/flows/checkout/assert-dismissed.yaml new file mode 100644 index 000000000..b5cd84090 --- /dev/null +++ b/e2e/flows/checkout/assert-dismissed.yaml @@ -0,0 +1,6 @@ +appId: ${E2E_APP_ID} +--- +- extendedWaitUntil: + notVisible: + id: "shopify_checkout_kit_close_button" + timeout: 30000 diff --git a/e2e/flows/checkout/assert-returned-to-empty-cart.yaml b/e2e/flows/checkout/assert-returned-to-empty-cart.yaml index ba7f925ed..34ef280a4 100644 --- a/e2e/flows/checkout/assert-returned-to-empty-cart.yaml +++ b/e2e/flows/checkout/assert-returned-to-empty-cart.yaml @@ -1,20 +1,6 @@ appId: ${E2E_APP_ID} --- -# RN E2E runs against released native SDK artifacts. Android 4.0.0-alpha.2 -# still exposes checkoutKitCloseBtn; #333 normalized the source id to -# shopify_checkout_kit_close_button. When RN nativeSdkVersions point at native -# SDK releases containing #333, replace this platform split with that id. -- runFlow: - when: - platform: android - commands: - - tapOn: - id: checkoutKitCloseBtn -- runFlow: - when: - platform: ios - commands: - - tapOn: "Close" +- runFlow: close.yaml - extendedWaitUntil: visible: diff --git a/e2e/flows/checkout/close.yaml b/e2e/flows/checkout/close.yaml new file mode 100644 index 000000000..9de6e637e --- /dev/null +++ b/e2e/flows/checkout/close.yaml @@ -0,0 +1,5 @@ +appId: ${E2E_APP_ID} +--- +- tapOn: + id: "shopify_checkout_kit_close_button" +- waitForAnimationToEnd diff --git a/e2e/test/e2e_matrix_to_browserstack_run_plan_test.rb b/e2e/test/e2e_matrix_to_browserstack_run_plan_test.rb index c1de16520..99228a2b8 100644 --- a/e2e/test/e2e_matrix_to_browserstack_run_plan_test.rb +++ b/e2e/test/e2e_matrix_to_browserstack_run_plan_test.rb @@ -47,9 +47,9 @@ def test_runs_carry_default_tags_and_the_other_platform_exclusion ios_run = run_for("swift-ios") android_run = run_for("kotlin-android") - assert_equal ["launch", "cart"], ios_run.fetch("include_tags") - assert_equal ["flaky", "wip", "android-only"], ios_run.fetch("exclude_tags") - assert_equal ["flaky", "wip", "ios-only"], android_run.fetch("exclude_tags") + assert_equal ["launch", "checkout"], ios_run.fetch("include_tags") + assert_equal ["flaky", "wip", "full", "android-only"], ios_run.fetch("exclude_tags") + assert_equal ["flaky", "wip", "full", "ios-only"], android_run.fetch("exclude_tags") end def test_an_application_overrides_the_default_tags diff --git a/e2e/tests/react-native/checkout-hardcoded-buyer-identity.yaml b/e2e/tests/react-native/checkout-hardcoded-buyer-identity.yaml index 386d21710..47215670e 100644 --- a/e2e/tests/react-native/checkout-hardcoded-buyer-identity.yaml +++ b/e2e/tests/react-native/checkout-hardcoded-buyer-identity.yaml @@ -2,7 +2,8 @@ appId: ${E2E_APP_ID} name: React Native checkout - hardcoded buyer identity tags: - checkout - - smoke + # This test submits a real order, so it belongs to the expensive tier. + - full env: # Sample app buyer identity configuration diff --git a/e2e/tests/shared/cart-from-control-link.yaml b/e2e/tests/shared/cart-from-control-link.yaml deleted file mode 100644 index 6f59c6534..000000000 --- a/e2e/tests/shared/cart-from-control-link.yaml +++ /dev/null @@ -1,11 +0,0 @@ -appId: ${E2E_APP_ID} -name: Cart from control link -tags: - - cart - - smoke - -env: - # No buyerIdentityMode: this test asserts cart seeding, not buyer identity. - E2E_CART_PARAMS: "productIndex=0&quantity=1" ---- -- runFlow: ../../flows/app/bootstrap-cart-from-link.yaml diff --git a/e2e/tests/shared/checkout-present-and-close.yaml b/e2e/tests/shared/checkout-present-and-close.yaml new file mode 100644 index 000000000..9ce835c1e --- /dev/null +++ b/e2e/tests/shared/checkout-present-and-close.yaml @@ -0,0 +1,16 @@ +appId: ${E2E_APP_ID} +name: Present checkout and close it +tags: + - checkout + - smoke + +env: + # No buyerIdentityMode: this test asserts presentation and dismissal, not identity. + E2E_CART_PARAMS: "productIndex=0&quantity=1" +--- +- runFlow: ../../flows/app/bootstrap-cart-from-link.yaml +- runFlow: ../../flows/checkout/present.yaml +- runFlow: ../../flows/checkout/close.yaml +# The four targets return to different screens, so this test asserts dismissal only. +# The tests that place an order assert what the cart holds afterwards. +- runFlow: ../../flows/checkout/assert-dismissed.yaml