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
13 changes: 7 additions & 6 deletions platforms/react-native/sample/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {
parseCartBootstrapLink,
type CartBootstrapLink,
} from './linking/cartBootstrap';
import {e2eTestIds} from './e2e/testIds';

const log = createDebugLogger('ENV');

Expand Down Expand Up @@ -247,7 +248,7 @@ function CartIcon({onPress}: {onPress: () => void}) {
const theme = useTheme();

return (
<Pressable onPress={onPress} testID="header-cart-icon">
<Pressable onPress={onPress} testID={e2eTestIds.catalog.headerCartIcon}>
<Icon name="shopping-basket" size={24} color={theme.colors.secondary} />
</Pressable>
);
Expand Down Expand Up @@ -509,22 +510,22 @@ function Routes() {
return (
<View
style={{flex: 1}}
testID={linkingReady ? 'checkout-kit-sample-ready' : undefined}>
testID={linkingReady ? e2eTestIds.appReady : undefined}>
<Tab.Navigator>
<Tab.Screen
name="Catalog"
component={CatalogStack}
options={{
headerShown: false,
tabBarButtonTestID: 'catalog-tab',
tabBarButtonTestID: e2eTestIds.tabs.catalog,
tabBarIcon: createNavigationIcon('shop'),
}}
/>
<Tab.Screen
name="Cart"
component={CartScreen}
options={{
tabBarButtonTestID: 'cart-tab',
tabBarButtonTestID: e2eTestIds.tabs.cart,
tabBarIcon: createNavigationIcon('shopping-bag'),
tabBarBadge: totalQuantity > 0 ? totalQuantity : undefined,
}}
Expand All @@ -534,15 +535,15 @@ function Routes() {
component={AccountStackScreen}
options={{
headerShown: false,
tabBarButtonTestID: 'account-tab',
tabBarButtonTestID: e2eTestIds.tabs.account,
tabBarIcon: createNavigationIcon('user'),
}}
/>
<Tab.Screen
name="Settings"
component={SettingsScreen}
options={{
tabBarButtonTestID: 'settings-tab',
tabBarButtonTestID: e2eTestIds.tabs.settings,
tabBarIcon: createNavigationIcon('cog'),
}}
/>
Expand Down
51 changes: 51 additions & 0 deletions platforms/react-native/sample/src/e2e/testIds.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
function kebabCase(value: string) {
return value
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
.replace(/[\s_]+/g, '-')
.toLowerCase();
}

export const e2eTestIds = {
appReady: 'checkout-kit-sample-ready',
tabs: {
catalog: 'catalog-tab',
cart: 'cart-tab',
account: 'account-tab',
settings: 'settings-tab',
},
catalog: {
headerCartIcon: 'header-cart-icon',
productGridItem: (index: number) => `product-${index}-grid-item`,
},
productDetails: {
addToCartButton: 'add-to-cart-button',
},
cart: {
emptyMessage: 'cart-empty-message',
checkoutButton: 'checkout-button',
},
settings: {
screen: 'settings-screen',
section: (section: string) => `settings-section-${kebabCase(section)}`,
buyerIdentityOption: (mode: string) =>
`settings-buyer-identity-option-${kebabCase(mode)}`,
themeOption: (scheme: string) =>
`settings-theme-option-${kebabCase(scheme)}`,
applePayStyleOption: (style: string) =>
`settings-apple-pay-style-option-${kebabCase(style)}`,
buyerIdentityDetails: 'settings-buyer-identity-details',
buyerIdentitySignInLink: 'settings-buyer-identity-sign-in-link',
buyerIdentityChangeUserLink: 'settings-buyer-identity-change-user-link',
},
account: {
screen: 'account-screen',
loading: 'account-loading',
signedInView: 'account-signed-in-view',
signedOutView: 'account-signed-out-view',
email: 'account-email',
signInButton: 'account-sign-in-button',
signOutButton: 'account-sign-out-button',
loginProcessing: 'account-login-processing',
loginWebView: 'account-login-webview',
},
} as const;
27 changes: 19 additions & 8 deletions platforms/react-native/sample/src/screens/AccountScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type {AccountStackParamList} from '../App';
import type {Colors} from '../context/Theme';
import {useTheme} from '../context/Theme';
import {useAuth} from '../context/Auth';
import {e2eTestIds} from '../e2e/testIds';

type Props = NativeStackScreenProps<AccountStackParamList, 'AccountHome'>;

Expand All @@ -23,7 +24,7 @@ function AccountScreen({navigation}: Props) {

if (isLoading) {
return (
<View style={styles.centered}>
<View testID={e2eTestIds.account.loading} style={styles.centered}>
<ActivityIndicator size="large" />
</View>
);
Expand Down Expand Up @@ -51,15 +52,22 @@ function AuthenticatedView({
const {logout} = useAuth();

return (
<SafeAreaView style={styles.container}>
<View style={styles.centered}>
<SafeAreaView testID={e2eTestIds.account.screen} style={styles.container}>
<View testID={e2eTestIds.account.signedInView} style={styles.centered}>
<Icon name="user" size={60} color="#81b0ff" />
<Text style={styles.heading}>Signed In</Text>
{email && <Text style={styles.email}>{email}</Text>}
{email && (
<Text testID={e2eTestIds.account.email} style={styles.email}>
{email}
</Text>
)}
<Text style={styles.description}>
Your checkout will be pre-filled with your account information.
</Text>
<Pressable style={styles.button} onPress={logout}>
<Pressable
testID={e2eTestIds.account.signOutButton}
style={styles.button}
onPress={logout}>
<Text style={styles.buttonText}>Sign Out</Text>
</Pressable>
</View>
Expand All @@ -75,8 +83,8 @@ function UnauthenticatedView({
onSignIn: () => void;
}) {
return (
<SafeAreaView style={styles.container}>
<View style={styles.centered}>
<SafeAreaView testID={e2eTestIds.account.screen} style={styles.container}>
<View testID={e2eTestIds.account.signedOutView} style={styles.centered}>
<Icon name="user" size={60} color="#bbc1d6" />
<Text style={styles.heading}>Sign in to your account</Text>
<Text style={styles.description}>
Expand All @@ -87,7 +95,10 @@ function UnauthenticatedView({
<Text style={styles.benefitItem}>• Pre-filled shipping details</Text>
<Text style={styles.benefitItem}>• Order history and tracking</Text>
</View>
<Pressable style={styles.button} onPress={onSignIn}>
<Pressable
testID={e2eTestIds.account.signInButton}
style={styles.button}
onPress={onSignIn}>
<Text style={styles.buttonText}>Sign In</Text>
</Pressable>
</View>
Expand Down
5 changes: 3 additions & 2 deletions platforms/react-native/sample/src/screens/CartScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
useShopifyEventHandlers,
useShopifyProtocolEventHandlers,
} from '../hooks/useCheckoutEventHandlers';
import {e2eTestIds} from '../e2e/testIds';

function CartScreen(): React.JSX.Element {
const ShopifyCheckout = useShopifyCheckout();
Expand Down Expand Up @@ -139,7 +140,7 @@ function CartScreen(): React.JSX.Element {
return (
<View style={styles.loading}>
<Icon name="shopping-bag" size={60} color="#bbc1d6" />
<Text testID="cart-empty-message" style={styles.loadingText}>
<Text testID={e2eTestIds.cart.emptyMessage} style={styles.loadingText}>
Your cart is empty.
</Text>
</View>
Expand Down Expand Up @@ -204,7 +205,7 @@ function CartScreen(): React.JSX.Element {
/>

<Pressable
testID="checkout-button"
testID={e2eTestIds.cart.checkoutButton}
style={styles.cartButton}
disabled={totalQuantity === 0}
onPress={presentCheckout}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {useCart} from '../context/Cart';
import type {NativeStackScreenProps} from '@react-navigation/native-stack';
import type {RootStackParamList} from '../App';
import {currency} from '../utils';
import {e2eTestIds} from '../e2e/testIds';

type Props = NativeStackScreenProps<RootStackParamList, 'CatalogScreen'>;

Expand Down Expand Up @@ -64,7 +65,7 @@ function CatalogScreen({navigation}: Props) {
<Product
key={node.id}
product={node}
testID={`product-${index}-grid-item`}
testID={e2eTestIds.catalog.productGridItem(index)}
onPress={() => {
navigation.navigate('ProductDetails', {
product: node,
Expand Down
4 changes: 3 additions & 1 deletion platforms/react-native/sample/src/screens/LoginScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
} from '../auth/customerAccountManager';
import type {Colors} from '../context/Theme';
import {useTheme} from '../context/Theme';
import {e2eTestIds} from '../e2e/testIds';

type Props = NativeStackScreenProps<AccountStackParamList, 'Login'>;

Expand Down Expand Up @@ -66,7 +67,7 @@ function LoginScreen({navigation}: Props) {

if (isProcessing) {
return (
<View style={styles.loading}>
<View testID={e2eTestIds.account.loginProcessing} style={styles.loading}>
<ActivityIndicator size="large" />
</View>
);
Expand All @@ -75,6 +76,7 @@ function LoginScreen({navigation}: Props) {
return (
<View style={styles.container}>
<WebView
testID={e2eTestIds.account.loginWebView}
source={{uri: authorizationURL}}
onShouldStartLoadWithRequest={handleNavigationRequest}
originWhitelist={['https://*', `${callbackScheme}://*`]}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
} from '@shopify/checkout-kit-react-native';
import {useConfig} from '../context/Config';
import {useShopifyEventHandlers} from '../hooks/useCheckoutEventHandlers';
import {e2eTestIds} from '../e2e/testIds';

type Props = NativeStackScreenProps<RootStackParamList, 'ProductDetails'>;

Expand Down Expand Up @@ -114,15 +115,14 @@ function ProductDetails({
)}

<Pressable
testID={e2eTestIds.productDetails.addToCartButton}
disabled={loading}
style={styles.addToCartButton}
onPress={() => variant?.id && onAddToCart(variant.id)}>
{loading ? (
<ActivityIndicator size="small" color="white" />
) : (
<Text
testID="add-to-cart-button"
style={styles.addToCartButtonText}>
<Text style={styles.addToCartButtonText}>
Add to cart
</Text>
)}
Expand Down
Loading
Loading