Skip to content

Commit ca24c87

Browse files
committed
Normalize RN E2E selector contract
1 parent 12ce7e4 commit ca24c87

8 files changed

Lines changed: 129 additions & 29 deletions

File tree

platforms/react-native/sample/src/App.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import env from 'react-native-config';
4444
import {createDebugLogger} from './utils';
4545
import {useShopifyEventHandlers} from './hooks/useCheckoutEventHandlers';
4646
import useShopify from './hooks/useShopify';
47+
import {e2eTestIds} from './e2e/testIds';
4748

4849
const log = createDebugLogger('ENV');
4950

@@ -300,7 +301,7 @@ function CartIcon({onPress}: {onPress: () => void}) {
300301
const theme = useTheme();
301302

302303
return (
303-
<Pressable onPress={onPress} testID="header-cart-icon">
304+
<Pressable onPress={onPress} testID={e2eTestIds.catalog.headerCartIcon}>
304305
<Icon name="shopping-basket" size={24} color={theme.colors.secondary} />
305306
</Pressable>
306307
);
@@ -562,22 +563,22 @@ function Routes() {
562563
return (
563564
<View
564565
style={{flex: 1}}
565-
testID={linkingReady ? 'checkout-kit-sample-ready' : undefined}>
566+
testID={linkingReady ? e2eTestIds.appReady : undefined}>
566567
<Tab.Navigator>
567568
<Tab.Screen
568569
name="Catalog"
569570
component={CatalogStack}
570571
options={{
571572
headerShown: false,
572-
tabBarButtonTestID: 'catalog-tab',
573+
tabBarButtonTestID: e2eTestIds.tabs.catalog,
573574
tabBarIcon: createNavigationIcon('shop'),
574575
}}
575576
/>
576577
<Tab.Screen
577578
name="Cart"
578579
component={CartScreen}
579580
options={{
580-
tabBarButtonTestID: 'cart-tab',
581+
tabBarButtonTestID: e2eTestIds.tabs.cart,
581582
tabBarIcon: createNavigationIcon('shopping-bag'),
582583
tabBarBadge: totalQuantity > 0 ? totalQuantity : undefined,
583584
}}
@@ -587,15 +588,15 @@ function Routes() {
587588
component={AccountStackScreen}
588589
options={{
589590
headerShown: false,
590-
tabBarButtonTestID: 'account-tab',
591+
tabBarButtonTestID: e2eTestIds.tabs.account,
591592
tabBarIcon: createNavigationIcon('user'),
592593
}}
593594
/>
594595
<Tab.Screen
595596
name="Settings"
596597
component={SettingsScreen}
597598
options={{
598-
tabBarButtonTestID: 'settings-tab',
599+
tabBarButtonTestID: e2eTestIds.tabs.settings,
599600
tabBarIcon: createNavigationIcon('cog'),
600601
}}
601602
/>
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
function kebabCase(value: string) {
2+
return value
3+
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
4+
.replace(/[\s_]+/g, '-')
5+
.toLowerCase();
6+
}
7+
8+
export const e2eTestIds = {
9+
appReady: 'checkout-kit-sample-ready',
10+
tabs: {
11+
catalog: 'catalog-tab',
12+
cart: 'cart-tab',
13+
account: 'account-tab',
14+
settings: 'settings-tab',
15+
},
16+
catalog: {
17+
headerCartIcon: 'header-cart-icon',
18+
productGridItem: (index: number) => `product-${index}-grid-item`,
19+
},
20+
productDetails: {
21+
addToCartButton: 'add-to-cart-button',
22+
},
23+
cart: {
24+
emptyMessage: 'cart-empty-message',
25+
checkoutButton: 'checkout-button',
26+
},
27+
settings: {
28+
screen: 'settings-screen',
29+
section: (section: string) => `settings-section-${kebabCase(section)}`,
30+
buyerIdentityOption: (mode: string) =>
31+
`settings-buyer-identity-option-${kebabCase(mode)}`,
32+
themeOption: (scheme: string) =>
33+
`settings-theme-option-${kebabCase(scheme)}`,
34+
applePayStyleOption: (style: string) =>
35+
`settings-apple-pay-style-option-${kebabCase(style)}`,
36+
buyerIdentityDetails: 'settings-buyer-identity-details',
37+
buyerIdentitySignInLink: 'settings-buyer-identity-sign-in-link',
38+
buyerIdentityChangeUserLink: 'settings-buyer-identity-change-user-link',
39+
},
40+
account: {
41+
screen: 'account-screen',
42+
loading: 'account-loading',
43+
signedInView: 'account-signed-in-view',
44+
signedOutView: 'account-signed-out-view',
45+
email: 'account-email',
46+
signInButton: 'account-sign-in-button',
47+
signOutButton: 'account-sign-out-button',
48+
loginProcessing: 'account-login-processing',
49+
loginWebView: 'account-login-webview',
50+
},
51+
} as const;

platforms/react-native/sample/src/screens/AccountScreen.tsx

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type {AccountStackParamList} from '../App';
1313
import type {Colors} from '../context/Theme';
1414
import {useTheme} from '../context/Theme';
1515
import {useAuth} from '../context/Auth';
16+
import {e2eTestIds} from '../e2e/testIds';
1617

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

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

2425
if (isLoading) {
2526
return (
26-
<View style={styles.centered}>
27+
<View testID={e2eTestIds.account.loading} style={styles.centered}>
2728
<ActivityIndicator size="large" />
2829
</View>
2930
);
@@ -51,15 +52,22 @@ function AuthenticatedView({
5152
const {logout} = useAuth();
5253

5354
return (
54-
<SafeAreaView style={styles.container}>
55-
<View style={styles.centered}>
55+
<SafeAreaView testID={e2eTestIds.account.screen} style={styles.container}>
56+
<View testID={e2eTestIds.account.signedInView} style={styles.centered}>
5657
<Icon name="user" size={60} color="#81b0ff" />
5758
<Text style={styles.heading}>Signed In</Text>
58-
{email && <Text style={styles.email}>{email}</Text>}
59+
{email && (
60+
<Text testID={e2eTestIds.account.email} style={styles.email}>
61+
{email}
62+
</Text>
63+
)}
5964
<Text style={styles.description}>
6065
Your checkout will be pre-filled with your account information.
6166
</Text>
62-
<Pressable style={styles.button} onPress={logout}>
67+
<Pressable
68+
testID={e2eTestIds.account.signOutButton}
69+
style={styles.button}
70+
onPress={logout}>
6371
<Text style={styles.buttonText}>Sign Out</Text>
6472
</Pressable>
6573
</View>
@@ -75,8 +83,8 @@ function UnauthenticatedView({
7583
onSignIn: () => void;
7684
}) {
7785
return (
78-
<SafeAreaView style={styles.container}>
79-
<View style={styles.centered}>
86+
<SafeAreaView testID={e2eTestIds.account.screen} style={styles.container}>
87+
<View testID={e2eTestIds.account.signedOutView} style={styles.centered}>
8088
<Icon name="user" size={60} color="#bbc1d6" />
8189
<Text style={styles.heading}>Sign in to your account</Text>
8290
<Text style={styles.description}>
@@ -87,7 +95,10 @@ function UnauthenticatedView({
8795
<Text style={styles.benefitItem}>• Pre-filled shipping details</Text>
8896
<Text style={styles.benefitItem}>• Order history and tracking</Text>
8997
</View>
90-
<Pressable style={styles.button} onPress={onSignIn}>
98+
<Pressable
99+
testID={e2eTestIds.account.signInButton}
100+
style={styles.button}
101+
onPress={onSignIn}>
91102
<Text style={styles.buttonText}>Sign In</Text>
92103
</Pressable>
93104
</View>

platforms/react-native/sample/src/screens/CartScreen.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
useShopifyEventHandlers,
3131
useShopifyProtocolEventHandlers,
3232
} from '../hooks/useCheckoutEventHandlers';
33+
import {e2eTestIds} from '../e2e/testIds';
3334

3435
function CartScreen(): React.JSX.Element {
3536
const ShopifyCheckout = useShopifyCheckout();
@@ -139,7 +140,7 @@ function CartScreen(): React.JSX.Element {
139140
return (
140141
<View style={styles.loading}>
141142
<Icon name="shopping-bag" size={60} color="#bbc1d6" />
142-
<Text testID="cart-empty-message" style={styles.loadingText}>
143+
<Text testID={e2eTestIds.cart.emptyMessage} style={styles.loadingText}>
143144
Your cart is empty.
144145
</Text>
145146
</View>
@@ -204,7 +205,7 @@ function CartScreen(): React.JSX.Element {
204205
/>
205206

206207
<Pressable
207-
testID="checkout-button"
208+
testID={e2eTestIds.cart.checkoutButton}
208209
style={styles.cartButton}
209210
disabled={totalQuantity === 0}
210211
onPress={presentCheckout}>

platforms/react-native/sample/src/screens/CatalogScreen.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {useCart} from '../context/Cart';
1919
import type {NativeStackScreenProps} from '@react-navigation/native-stack';
2020
import type {RootStackParamList} from '../App';
2121
import {currency} from '../utils';
22+
import {e2eTestIds} from '../e2e/testIds';
2223

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

@@ -64,7 +65,7 @@ function CatalogScreen({navigation}: Props) {
6465
<Product
6566
key={node.id}
6667
product={node}
67-
testID={`product-${index}-grid-item`}
68+
testID={e2eTestIds.catalog.productGridItem(index)}
6869
onPress={() => {
6970
navigation.navigate('ProductDetails', {
7071
product: node,

platforms/react-native/sample/src/screens/LoginScreen.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
} from '../auth/customerAccountManager';
1414
import type {Colors} from '../context/Theme';
1515
import {useTheme} from '../context/Theme';
16+
import {e2eTestIds} from '../e2e/testIds';
1617

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

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

6768
if (isProcessing) {
6869
return (
69-
<View style={styles.loading}>
70+
<View testID={e2eTestIds.account.loginProcessing} style={styles.loading}>
7071
<ActivityIndicator size="large" />
7172
</View>
7273
);
@@ -75,6 +76,7 @@ function LoginScreen({navigation}: Props) {
7576
return (
7677
<View style={styles.container}>
7778
<WebView
79+
testID={e2eTestIds.account.loginWebView}
7880
source={{uri: authorizationURL}}
7981
onShouldStartLoadWithRequest={handleNavigationRequest}
8082
originWhitelist={['https://*', `${callbackScheme}://*`]}

platforms/react-native/sample/src/screens/ProductDetailsScreen.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
} from '@shopify/checkout-kit-react-native';
2525
import {useConfig} from '../context/Config';
2626
import {useShopifyEventHandlers} from '../hooks/useCheckoutEventHandlers';
27+
import {e2eTestIds} from '../e2e/testIds';
2728

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

@@ -114,15 +115,14 @@ function ProductDetails({
114115
)}
115116

116117
<Pressable
118+
testID={e2eTestIds.productDetails.addToCartButton}
117119
disabled={loading}
118120
style={styles.addToCartButton}
119121
onPress={() => variant?.id && onAddToCart(variant.id)}>
120122
{loading ? (
121123
<ActivityIndicator size="small" color="white" />
122124
) : (
123-
<Text
124-
testID="add-to-cart-button"
125-
style={styles.addToCartButtonText}>
125+
<Text style={styles.addToCartButtonText}>
126126
Add to cart
127127
</Text>
128128
)}

0 commit comments

Comments
 (0)