diff --git a/__tests__/e2e/configs/wdio.ios.local.sim.conf.ts b/__tests__/e2e/configs/wdio.ios.local.sim.conf.ts index bf64727..6a60edb 100644 --- a/__tests__/e2e/configs/wdio.ios.local.sim.conf.ts +++ b/__tests__/e2e/configs/wdio.ios.local.sim.conf.ts @@ -17,7 +17,7 @@ config.capabilities = [ // http://appium.io/docs/en/writing-running-appium/caps/ // This is `appium:` for all Appium Capabilities which can be found here 'appium:deviceName': 'iPhone 13', - 'appium:platformVersion': '15.2', + 'appium:platformVersion': '15.4', 'appium:orientation': 'PORTRAIT', 'appium:automationName': 'XCUITest', // The path to the app diff --git a/__tests__/e2e/helpers/utils.ts b/__tests__/e2e/helpers/utils.ts index 1d1950b..b2bdac1 100644 --- a/__tests__/e2e/helpers/utils.ts +++ b/__tests__/e2e/helpers/utils.ts @@ -32,6 +32,20 @@ const restartApp = async (): Promise => { // Set the firstAppstart to false to say that the following test can be reset (driver.config as MobileConfig).firstAppStart = false; + + // Wait for the app to be ready and reset the state by clicking on the header image + const headerImage = await $(locatorStrategy('longpress reset app')); + await headerImage.waitForDisplayed(); + if (driver.isIOS) { + return driver.execute('mobile: touchAndHold', { + elementId: headerImage.elementId, + duration: 1, + }); + } + await driver.execute('mobile: longClickGesture', { + elementId: headerImage.elementId, + duration: 1000, + }); }; const hideKeyboard = async (): Promise => { // The hideKeyboard is not working on ios devices, so take a different approach diff --git a/__tests__/e2e/screen-objects/ItemDetailsScreen.ts b/__tests__/e2e/screen-objects/ItemDetailsScreen.ts index 7b08527..7691aba 100644 --- a/__tests__/e2e/screen-objects/ItemDetailsScreen.ts +++ b/__tests__/e2e/screen-objects/ItemDetailsScreen.ts @@ -59,7 +59,7 @@ class ItemDetailsScreen extends AppScreen { )?.click(); // We need to have a small pause so the internal state can be updated - return driver.pause(750); + return driver.pause(1000); } async selectColor(color: ColorsType) { @@ -71,7 +71,7 @@ class ItemDetailsScreen extends AppScreen { )?.click(); // Add a hard pause so the state can be updated - return driver.pause(750); + return driver.pause(1000); } async counterAddOne() { @@ -83,7 +83,7 @@ class ItemDetailsScreen extends AppScreen { )?.click(); // We need to have a small pause so the internal state can be updated - return driver.pause(750); + return driver.pause(1000); } async counterLowerOne() { @@ -95,7 +95,7 @@ class ItemDetailsScreen extends AppScreen { )?.click(); // We need to have a small pause so the internal state can be updated - return driver.pause(750); + return driver.pause(1000); } async getCounterAmount(): Promise { diff --git a/__tests__/e2e/screen-objects/Menu.ts b/__tests__/e2e/screen-objects/Menu.ts index cddfac6..1e36018 100644 --- a/__tests__/e2e/screen-objects/Menu.ts +++ b/__tests__/e2e/screen-objects/Menu.ts @@ -152,14 +152,14 @@ class Menu extends AppScreen { await $(driver.isIOS ? iosSelector('OK') : androidSelector('OK')).click(); // Wait for animation to be done - await driver.pause(750); + await driver.pause(1000); } async openMenu() { await this.openMenuButton.click(); // Wait for animation to be done - await driver.pause(750); + await driver.pause(1000); } async closeMenu() { diff --git a/android/app/build.gradle b/android/app/build.gradle index 47b00fe..a844f6a 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -141,7 +141,7 @@ android { applicationId "com.saucelabs.mydemoapp.rn" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 240 + versionCode 243 versionName "1.2.1" // For the QR-code scanner missingDimensionStrategy 'react-native-camera', 'general' diff --git a/ios/MyRNDemoApp/Info.plist b/ios/MyRNDemoApp/Info.plist index 7649871..886be6e 100644 --- a/ios/MyRNDemoApp/Info.plist +++ b/ios/MyRNDemoApp/Info.plist @@ -34,7 +34,7 @@ CFBundleVersion - 157 + 161 LSRequiresIPhoneOS NSAppTransportSecurity diff --git a/ios/MyRNDemoAppTests/Info.plist b/ios/MyRNDemoAppTests/Info.plist index 50e4301..88e125b 100644 --- a/ios/MyRNDemoAppTests/Info.plist +++ b/ios/MyRNDemoAppTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 157 + 161 diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 07f7ab8..8e49922 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -371,6 +371,8 @@ PODS: - React-Core - RNBootSplash (4.0.2): - React-Core + - RNCAsyncStorage (1.17.3): + - React-Core - RNCMaskedView (0.1.11): - React - RNFS (2.18.0): @@ -485,6 +487,7 @@ DEPENDENCIES: - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) - rn-fetch-blob (from `../node_modules/rn-fetch-blob`) - RNBootSplash (from `../node_modules/react-native-bootsplash`) + - "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)" - "RNCMaskedView (from `../node_modules/@react-native-community/masked-view`)" - RNFS (from `../node_modules/react-native-fs`) - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) @@ -598,6 +601,8 @@ EXTERNAL SOURCES: :path: "../node_modules/rn-fetch-blob" RNBootSplash: :path: "../node_modules/react-native-bootsplash" + RNCAsyncStorage: + :path: "../node_modules/@react-native-async-storage/async-storage" RNCMaskedView: :path: "../node_modules/@react-native-community/masked-view" RNFS: @@ -673,6 +678,7 @@ SPEC CHECKSUMS: ReactCommon: 57b69f6383eafcbd7da625bfa6003810332313c4 rn-fetch-blob: f065bb7ab7fb48dd002629f8bdcb0336602d3cba RNBootSplash: 5e82ba24a59a07315cbb2bb4855bb8d76fc7e802 + RNCAsyncStorage: 005c0e2f09575360f142d0d1f1f15e4ec575b1af RNCMaskedView: 0e1bc4bfa8365eba5fbbb71e07fbdc0555249489 RNFS: 3ab21fa6c56d65566d1fb26c2228e2b6132e5e32 RNGestureHandler: e5c7cab5f214503dcefd6b2b0cefb050e1f51c4a diff --git a/package.json b/package.json index 79ee336..c0b383b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "my-demo-app-rn", - "version": "1.2.1", + "version": "1.3.0", "private": true, "scripts": { "android.clean": "cd android && ./gradlew clean && cd .. ", @@ -29,6 +29,7 @@ "version.apps": "npx react-native-version --never-amend" }, "dependencies": { + "@react-native-async-storage/async-storage": "^1.17.3", "@react-native-community/cameraroll": "^4.1.2", "@react-native-community/masked-view": "^0.1.11", "@react-navigation/bottom-tabs": "^6.0.9", diff --git a/src/components/AppHeader.tsx b/src/components/AppHeader.tsx index 1996982..b35f597 100644 --- a/src/components/AppHeader.tsx +++ b/src/components/AppHeader.tsx @@ -1,5 +1,5 @@ import React, {useContext} from 'react'; -import {Image, Platform, StyleSheet, Text, View} from 'react-native'; +import {Image, Platform, Pressable, StyleSheet, Text, View} from 'react-native'; import {IS_IOS, MUSEO_SANS_700} from '../utils/Constants'; import {Colors} from '../styles/Colors'; import {STATUS_BAR_HEIGHT} from './StatusBar'; @@ -7,9 +7,11 @@ import {StackNavigationProp} from '@react-navigation/stack'; import NavigationBackButton from './NavigationBackButton'; import {DrawerActions} from '@react-navigation/native'; import AndroidMenuButton from './AndroidMenuButton'; -import {StoreContext} from '../store/Store'; +import {resetStore, StoreContext} from '../store/Store'; import AndroidCartButton from './AndroidCartButton'; import {ROUTES} from '../navigation/Routes'; +import {testProperties} from '../config/TestProperties'; +import I18n from '../config/I18n'; type AppHeaderProps = { navigation: StackNavigationProp; @@ -33,6 +35,7 @@ const AppHeader = ({ state: { cartContent: {totalAmount}, }, + dispatch, } = useContext(StoreContext); return ( @@ -47,11 +50,16 @@ const AppHeader = ({ )} {title && {title}} {showHeaderImage && ( - + await resetStore(dispatch)} + {...testProperties(I18n.t('appHeader.testId'))}> + + )} {((!IS_IOS && !hideAndroidCart) || rightComponent) && ( @@ -104,8 +112,7 @@ const styles = StyleSheet.create({ fontFamily: MUSEO_SANS_700, fontSize: 16, }, - headerImage: { - height: 20, + headerImageContainer: { left: 'auto', right: 'auto', position: 'absolute', @@ -118,6 +125,9 @@ const styles = StyleSheet.create({ }, }), }, + headerImage: { + height: 20, + }, rightComponent: { marginLeft: 'auto', flexDirection: 'row', diff --git a/src/config/translations/en.ts b/src/config/translations/en.ts index 6f6a402..3f5769a 100644 --- a/src/config/translations/en.ts +++ b/src/config/translations/en.ts @@ -8,6 +8,9 @@ export default { url: 'https://www.saucelabs.com', testId: 'about screen', }, + appHeader: { + testId: 'longpress reset app', + }, apiCalls: { header: 'API calls', testId: 'api calls screen', diff --git a/src/containers/CheckoutCompletePage.tsx b/src/containers/CheckoutCompletePage.tsx index a7c396a..abf58c3 100644 --- a/src/containers/CheckoutCompletePage.tsx +++ b/src/containers/CheckoutCompletePage.tsx @@ -1,4 +1,4 @@ -import React, {useContext} from 'react'; +import React from 'react'; import {Image, ScrollView, StyleSheet, Text, View} from 'react-native'; import {CommonActions} from '@react-navigation/native'; import {ROUTES} from '../navigation/Routes'; @@ -7,10 +7,6 @@ import {CartStackParamList} from '../navigation/types'; import {Colors} from '../styles/Colors'; import {MUSEO_SANS_300, MUSEO_SANS_700} from '../utils/Constants'; import Button from '../components/Button'; -import {StoreContext} from '../store/Store'; -import {resetCart} from '../store/actions/CartActions'; -import {resetCardDetails} from '../store/actions/CardDetailsActions'; -import {resetShippingAddress} from '../store/actions/ShippingAddressActions'; import I18n from '../config/I18n'; import {testProperties} from '../config/TestProperties'; @@ -19,12 +15,7 @@ type CheckoutCompleteProps = { }; const CheckoutCompletePage = ({navigation}: CheckoutCompleteProps) => { - const {dispatch} = useContext(StoreContext); - const continueShopping = () => { - dispatch(resetCart()); - dispatch(resetCardDetails()); - dispatch(resetShippingAddress()); navigation.dispatch({ ...CommonActions.reset({ index: 0, diff --git a/src/containers/CheckoutReviewOrderPage.tsx b/src/containers/CheckoutReviewOrderPage.tsx index 4328b93..d9a2da0 100644 --- a/src/containers/CheckoutReviewOrderPage.tsx +++ b/src/containers/CheckoutReviewOrderPage.tsx @@ -13,10 +13,16 @@ import Footer from '../components/Footer'; import I18n from '../config/I18n'; import {testProperties} from '../config/TestProperties'; import {parseDeepLinkProductData} from '../utils/DeepLinking'; -import {addProductToCart} from '../store/actions/CartActions'; +import {addProductToCart, resetCart} from '../store/actions/CartActions'; import {RouteProp} from '@react-navigation/native'; -import {updateShippingAddress} from '../store/actions/ShippingAddressActions'; -import {updateCardDetails} from '../store/actions/CardDetailsActions'; +import { + resetShippingAddress, + updateShippingAddress, +} from '../store/actions/ShippingAddressActions'; +import { + resetCardDetails, + updateCardDetails, +} from '../store/actions/CardDetailsActions'; type CheckoutReviewOrderProps = { navigation: StackNavigationProp; @@ -38,6 +44,12 @@ const CheckoutReviewOrderPage = ({ } = useContext(StoreContext); const deliveryCosts = 5.99; const totalCosts = cartContent.totalPrice + deliveryCosts; + const navigateToCheckoutComplete = () => { + dispatch(resetCart()); + dispatch(resetCardDetails()); + dispatch(resetShippingAddress()); + navigation.navigate(ROUTES.CHECKOUT_COMPLETE); + }; useEffect(() => { // @ts-ignore @@ -193,7 +205,7 @@ const CheckoutReviewOrderPage = ({