diff --git a/e2e/README.md b/e2e/README.md index 5fb58a0e..87e8eb5f 100644 --- a/e2e/README.md +++ b/e2e/README.md @@ -23,6 +23,11 @@ sample ships to both platforms; its flows are split because some assertions are platform-specific (iOS accessibility-label patterns vs Android resource strings). +The React Native Android checkout flow submits payment and waits for the order +confirmation screen. The React Native iOS checkout flow currently stops at +`Pay now`; the store/address path can show a checkout-web shipping availability +banner after submit, which is outside the Checkout Kit integration contract. + Folders are created when their first flow lands. Don't pre-create empty directories. @@ -35,7 +40,7 @@ Use these in the `appId:` header of every flow. Don't invent new bundle ids. | `swift/` | `com.shopify.example.MobileBuyIntegration` | | `android/` | `com.shopify.checkout_kit_mobile_buy_integration_sample` | | `react-native/ios/` | `com.shopify.example.CheckoutKitReactNative` | -| `react-native/android/` | `com.shopify.example.CheckoutKitReactNative` | +| `react-native/android/` | `com.shopify.checkoutkitreactnative` | ## Running @@ -48,7 +53,7 @@ terminal. | React Native, iOS | `platforms/react-native/` | `pnpm e2e:ios` | | Swift, iOS | TBD | TBD | | Android (native) | TBD | TBD | -| RN, Android | TBD | TBD | +| RN, Android | `platforms/react-native/` | `pnpm e2e:android` | Maestro itself is a system CLI, not an npm dependency. Install once with: @@ -61,7 +66,8 @@ curl -fsSL "https://get.maestro.mobile.dev" | bash 1. Drop a new `.yaml` under the right folder. 2. Set `appId:` from the table above. 3. Keep timeouts in the existing tiers (in-app interactions ~10s, network - transitions ~30s, cold starts and checkout first-paint ~60s). + transitions ~30s, cold starts, checkout first-paint, and order confirmation + ~60s). 4. If the flow needs an npm script wrapper, add an `e2e:` script to the matching `package.json` next to existing scripts. The script should point at the folder, not an individual file, so the whole folder runs. diff --git a/e2e/react-native/android/checkout-completion.yaml b/e2e/react-native/android/checkout-completion.yaml new file mode 100644 index 00000000..9b5156b3 --- /dev/null +++ b/e2e/react-native/android/checkout-completion.yaml @@ -0,0 +1,173 @@ +appId: com.shopify.checkoutkitreactnative +name: Checkout completes +tags: + - android + - checkout + +# Override these for store-specific product and shipping-address data. +env: + PRODUCT_INDEX: ${PRODUCT_INDEX || "1"} + COUNTRY: ${COUNTRY || "United States"} + ADDRESS_LINE1: ${ADDRESS_LINE1 || "350 5th Ave"} + CITY: ${CITY || "New York"} + POSTAL_CODE: ${POSTAL_CODE || "10118"} + POSTAL_FIELD: ${POSTAL_FIELD || "ZIP code"} +--- +# Timeout tiers: +# 10000 - in-app interactions (taps, animations) +# 30000 - checkout step transitions (network) +# 60000 - cold starts, first checkout paint, final confirmation + +# Product and cart +- launchApp: + clearState: true +- extendedWaitUntil: + visible: + id: product-0-add-to-cart-button + timeout: 60000 +- scrollUntilVisible: + element: + id: product-${PRODUCT_INDEX}-add-to-cart-button + direction: DOWN + timeout: 10000 + centerElement: true +- tapOn: + id: product-${PRODUCT_INDEX}-add-to-cart-button + enabled: true +- waitForAnimationToEnd: + timeout: 10000 +- tapOn: + id: cart-tab +- extendedWaitUntil: + visible: + id: checkout-button + timeout: 30000 +- tapOn: + id: checkout-button + enabled: true + +# Contact +- extendedWaitUntil: + visible: + text: "^Email( or mobile phone number)?$" + timeout: 60000 +- tapOn: + text: "^Email( or mobile phone number)?$" +- inputText: "maestro.e2e@shopify.com" +- hideKeyboard +- tapOn: + text: "^First name( \\(optional\\))?$" +- inputText: "Maestro" +- hideKeyboard +- tapOn: + text: "^Last name$" +- inputText: "Shopify" +- hideKeyboard + +# Shipping address +- scrollUntilVisible: + element: + text: "Country/Region" + direction: DOWN + timeout: 10000 +- tapOn: + text: "Country/Region" + index: 1 +- waitForAnimationToEnd: + timeout: 3000 +- scrollUntilVisible: + element: + text: "^${COUNTRY}$" + direction: UP + timeout: 10000 + visibilityPercentage: 50 + centerElement: true + optional: true +- runFlow: + when: + notVisible: "^${COUNTRY}$" + commands: + - scrollUntilVisible: + element: + text: "^${COUNTRY}$" + direction: DOWN + timeout: 30000 + visibilityPercentage: 50 + centerElement: true +- tapOn: + text: "^${COUNTRY}$" +- waitForAnimationToEnd: + timeout: 3000 + +- scrollUntilVisible: + element: + text: "Address" + direction: DOWN + timeout: 10000 +- tapOn: + text: "Address" + index: -1 +- eraseText: 80 +- scrollUntilVisible: + element: + text: "^${POSTAL_FIELD}$" + direction: DOWN + timeout: 10000 + centerElement: true +- inputText: "${ADDRESS_LINE1} ${CITY} ${POSTAL_CODE}" +- extendedWaitUntil: + visible: ".*${ADDRESS_LINE1}, ${CITY}.*${POSTAL_CODE}.*${COUNTRY}.*" + timeout: 30000 +- waitForAnimationToEnd: + timeout: 2000 +- tapOn: + text: ".*${ADDRESS_LINE1}, ${CITY}.*${POSTAL_CODE}.*${COUNTRY}.*" + index: 0 + retryTapIfNoChange: true +- waitForAnimationToEnd: + timeout: 5000 +- extendedWaitUntil: + visible: "^${POSTAL_CODE}$" + timeout: 15000 +- hideKeyboard +- waitForAnimationToEnd: + timeout: 5000 + +# Payment +- scrollUntilVisible: + element: + text: "^Card number$" + direction: DOWN + timeout: 30000 + centerElement: true +- tapOn: + text: "^Card number$" +- inputText: "4242424242424242" +- hideKeyboard +- tapOn: "Expiration date (MM / YY)" +- inputText: "1230" +- hideKeyboard +- tapOn: + text: "^Security code$" +- inputText: "123" +- hideKeyboard +- scrollUntilVisible: + element: + text: "^Name on card$" + direction: DOWN + timeout: 30000 + centerElement: true +- scrollUntilVisible: + element: + text: "^Pay now$" + direction: DOWN + timeout: 30000 +- extendedWaitUntil: + visible: "^Pay now$" + timeout: 30000 +- tapOn: + text: "^Pay now$" + enabled: true +- extendedWaitUntil: + visible: ".*(Thank you|[Oo]rder (is )?confirmed).*" + timeout: 60000 diff --git a/platforms/react-native/package.json b/platforms/react-native/package.json index 6acad1ac..43fdb5bf 100644 --- a/platforms/react-native/package.json +++ b/platforms/react-native/package.json @@ -25,7 +25,8 @@ "compare-snapshot": "./scripts/compare_snapshot", "turbo": "turbo", "test": "jest", - "e2e:ios": "maestro --platform ios test --config ../../e2e/config.yaml ../../e2e/react-native/ios" + "e2e:ios": "maestro --platform ios test --config ../../e2e/config.yaml ../../e2e/react-native/ios", + "e2e:android": "maestro --platform android test --config ../../e2e/config.yaml ../../e2e/react-native/android" }, "devDependencies": { "@babel/core": "^7.25.2",