Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion e2e/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ terminal.
| Platform | From | Command |
| ------------------ | ------------------------------- | ------------------ |
| React Native, iOS | `platforms/react-native/` | `pnpm e2e:ios` |
| Swift, iOS | TBD | TBD |
| Swift, iOS | `platforms/swift/` | `./Scripts/e2e_maestro_ios` |
| Android (native) | TBD | TBD |
| RN, Android | `platforms/react-native/` | `pnpm e2e:android` |

Expand Down
190 changes: 190 additions & 0 deletions e2e/swift/checkout-completion.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
appId: com.shopify.example.MobileBuyIntegration
name: Checkout completes
tags:
- swift
- ios
- 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
arguments:
AppleLocale: en_US
AppleLanguages: "(en)"
- extendedWaitUntil:
visible:
id: product-0-grid-item
timeout: 60000
- scrollUntilVisible:
element:
id: product-${PRODUCT_INDEX}-grid-item
direction: DOWN
timeout: 10000
centerElement: true
- tapOn:
id: product-${PRODUCT_INDEX}-grid-item
- extendedWaitUntil:
visible:
id: add-to-cart-button
timeout: 10000
- tapOn:
id: add-to-cart-button
enabled: true
- extendedWaitUntil:
visible: "^Added$"
timeout: 30000
- tapOn:
id: product-sheet-close-button
- 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)?$"
index: -1
- inputText: "maestro.e2e@shopify.com"
- tapOn: "selected"
- tapOn:
text: "^First name( \\(optional\\))?$"
index: -1
- inputText: "Maestro"
- tapOn: "selected"
- tapOn:
text: "^Last name$"
index: -1
- inputText: "Shopify"
- tapOn: "selected"

# 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
- tapOn: "selected"
- waitForAnimationToEnd:
timeout: 5000

# Payment
- scrollUntilVisible:
element:
text: "^Field container for: Card number$"
direction: DOWN
timeout: 30000
centerElement: true
- tapOn:
text: "^Field container for: Card number$"
- inputText: "4242424242424242"
- tapOn: "selected"
- tapOn: "Expiration date (MM / YY)"
- inputText: "1230"
- tapOn: "selected"
- tapOn: "Field container for: Security code"
- inputText: "123"
- tapOn: "selected"
- scrollUntilVisible:
element:
text: "^Field container for: 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
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@
mainGroup = 4EBBA75E2A5F0CE200193E19;
packageReferences = (
CB00000012345678 /* XCRemoteSwiftPackageReference "apollo-ios" */,
CB2370002FB21BF100F0D914 /* XCLocalSwiftPackageReference "../../../../../checkout-kit" */,
CB2370002FB21BF100F0D914 /* XCLocalSwiftPackageReference "../../../.." */,
);
productRefGroup = 4EBBA7682A5F0CE200193E19 /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -443,9 +443,9 @@
/* End XCConfigurationList section */

/* Begin XCLocalSwiftPackageReference section */
CB2370002FB21BF100F0D914 /* XCLocalSwiftPackageReference "../../../../../checkout-kit" */ = {
CB2370002FB21BF100F0D914 /* XCLocalSwiftPackageReference "../../../.." */ = {
isa = XCLocalSwiftPackageReference;
relativePath = "../../../../../checkout-kit";
relativePath = "../../../..";
};
/* End XCLocalSwiftPackageReference section */

Expand Down Expand Up @@ -473,17 +473,17 @@
};
CB001E302F3CDA0300286F69 /* ShopifyCheckoutProtocol */ = {
isa = XCSwiftPackageProductDependency;
package = CB2370002FB21BF100F0D914 /* XCLocalSwiftPackageReference "../../../../../checkout-kit" */;
package = CB2370002FB21BF100F0D914 /* XCLocalSwiftPackageReference "../../../.." */;
productName = ShopifyCheckoutProtocol;
};
CB1B10B42E4CDDB0001713F8 /* ShopifyCheckoutKit */ = {
isa = XCSwiftPackageProductDependency;
package = CB2370002FB21BF100F0D914 /* XCLocalSwiftPackageReference "../../../../../checkout-kit" */;
package = CB2370002FB21BF100F0D914 /* XCLocalSwiftPackageReference "../../../.." */;
productName = ShopifyCheckoutKit;
};
CBED2D4E2F3F5D1B00EC866A /* ShopifyAcceleratedCheckouts */ = {
isa = XCSwiftPackageProductDependency;
package = CB2370002FB21BF100F0D914 /* XCLocalSwiftPackageReference "../../../../../checkout-kit" */;
package = CB2370002FB21BF100F0D914 /* XCLocalSwiftPackageReference "../../../.." */;
productName = ShopifyAcceleratedCheckouts;
};
/* End XCSwiftPackageProductDependency section */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,30 +108,35 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
// Catalog grid view
productGridController.tabBarItem.image = UIImage(systemName: "square.grid.2x2")
productGridController.tabBarItem.title = "Catalog"
productGridController.tabBarItem.accessibilityIdentifier = "catalog-tab"
productGridController.navigationItem.titleView = logoImageView
catalogCartButton = createCartButtonWithBadge()
productGridController.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: catalogCartButton!)

// Product Gallery
productGalleryController.tabBarItem.image = UIImage(systemName: "appwindow.swipe.rectangle")
productGalleryController.tabBarItem.title = "Products"
productGalleryController.tabBarItem.accessibilityIdentifier = "products-tab"
productGalleryController.navigationItem.titleView = logoImageView
galleryCartButton = createCartButtonWithBadge()
productGalleryController.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: galleryCartButton!)

// Cart (UI Kit)
swiftUICartController.tabBarItem.image = UIImage(systemName: "cart")
swiftUICartController.tabBarItem.title = "Cart"
swiftUICartController.tabBarItem.accessibilityIdentifier = "cart-tab"
swiftUICartController.navigationItem.title = "Cart (SwiftUI)"

// Account
accountController.tabBarItem.image = UIImage(systemName: "person.circle")
accountController.tabBarItem.title = "Log in"
accountController.tabBarItem.accessibilityIdentifier = "account-tab"
subscribeToAuthStateChanges()

// Settings
settingsController.tabBarItem.image = UIImage(systemName: "gearshape.2")
settingsController.tabBarItem.title = "Settings"
settingsController.tabBarItem.accessibilityIdentifier = "settings-tab"
}

private func subscribeToAuthStateChanges() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ struct CartView: View {
)
.disabled(isBusy)
.foregroundColor(.white)
.accessibilityIdentifier("checkoutSheetButton")
.accessibilityIdentifier("checkout-button")
}
.padding(.horizontal, 20)
.padding(.bottom, 20)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ struct ProductGridView: View {
ScrollView {
LazyVGrid(columns: columns, spacing: 2) {
if let products = productCache.collection, !products.isEmpty {
ForEach(products, id: \.id) { product in
ForEach(Array(products.enumerated()), id: \.element.id) { index, product in
ProductGridItem(product: product)
.accessibilityIdentifier("product-\(index)-grid-item")
.onTapGesture {
selectProductAndShowSheet(for: product)
}
Expand Down Expand Up @@ -88,6 +89,7 @@ struct ProductSheetView: View {
.padding()
.foregroundStyle(.white)
}
.accessibilityIdentifier("product-sheet-close-button")
.padding([.top, .trailing], 16)
}
.edgesIgnoringSafeArea(.top)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ struct ProductView: View {
.foregroundStyle(.white)
.cornerRadius(DesignSystem.cornerRadius)
.disabled(!variant.availableForSale || loading)
.accessibilityIdentifier("add-to-cart-button")

if variant.availableForSale {
AcceleratedCheckoutButtons(variantID: variant.id, quantity: 1)
Expand Down
5 changes: 5 additions & 0 deletions platforms/swift/Scripts/e2e_maestro_ios
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env bash

set -euo pipefail

maestro --platform ios test --config ../../e2e/config.yaml ../../e2e/swift
Loading