From a92d906ef4a8d5fda2a1f89123b1eb05597b59dd Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Tue, 30 Jun 2020 18:09:19 +0200 Subject: [PATCH 01/10] [#173521040] rework navigation handling and return back at the end of eligibility / activation instead of wallet --- .../screens/BonusCTAEligibilityStartScreen.tsx | 2 -- .../screens/BonusInformationScreen.tsx | 2 -- .../screens/activation/BonusAlreadyExists.tsx | 12 +++++++++--- .../bonusVacanze/store/actions/bonusVacanze.ts | 5 +++++ .../activation/handleBonusActivationSaga.ts | 17 ++++++++++++----- .../eligibility/handleBonusEligibilitySaga.ts | 7 +++---- 6 files changed, 29 insertions(+), 16 deletions(-) diff --git a/ts/features/bonusVacanze/screens/BonusCTAEligibilityStartScreen.tsx b/ts/features/bonusVacanze/screens/BonusCTAEligibilityStartScreen.tsx index 93f2fa3738f..7d5c3ad03d5 100644 --- a/ts/features/bonusVacanze/screens/BonusCTAEligibilityStartScreen.tsx +++ b/ts/features/bonusVacanze/screens/BonusCTAEligibilityStartScreen.tsx @@ -1,6 +1,5 @@ import React, { useEffect } from "react"; import { connect } from "react-redux"; -import { navigationHistoryPop } from "../../../store/actions/navigationHistory"; import { Dispatch } from "../../../store/actions/types"; import { checkBonusVacanzeEligibility } from "../store/actions/bonusVacanze"; import LoadBonusEligibilityScreen from "./eligibility/LoadBonusEligibilityScreen"; @@ -18,7 +17,6 @@ const BonusCTAEligibilityStartScreen = (props: Props) => { const mapDispatchToProps = (dispatch: Dispatch) => ({ startEligibilityCheck: () => { dispatch(checkBonusVacanzeEligibility.request()); - dispatch(navigationHistoryPop(1)); } }); diff --git a/ts/features/bonusVacanze/screens/BonusInformationScreen.tsx b/ts/features/bonusVacanze/screens/BonusInformationScreen.tsx index e216cbc9bd6..adf6fa195ab 100644 --- a/ts/features/bonusVacanze/screens/BonusInformationScreen.tsx +++ b/ts/features/bonusVacanze/screens/BonusInformationScreen.tsx @@ -20,7 +20,6 @@ import { LightModalContextInterface } from "../../../components/ui/LightModal"; import Markdown from "../../../components/ui/Markdown"; import I18n from "../../../i18n"; import { navigateBack } from "../../../store/actions/navigation"; -import { navigationHistoryPop } from "../../../store/actions/navigationHistory"; import customVariables from "../../../theme/variables"; import { getLocalePrimaryWithFallback } from "../../../utils/locale"; import { maybeNotNullyString } from "../../../utils/strings"; @@ -239,7 +238,6 @@ const BonusInformationScreen: React.FunctionComponent = props => { const mapDispatchToProps = (dispatch: Dispatch) => ({ requestBonusActivation: () => { dispatch(checkBonusVacanzeEligibility.request()); - dispatch(navigationHistoryPop(1)); }, navigateBack: () => dispatch(navigateBack()) }); diff --git a/ts/features/bonusVacanze/screens/activation/BonusAlreadyExists.tsx b/ts/features/bonusVacanze/screens/activation/BonusAlreadyExists.tsx index 617767e6c79..34c0acfdda8 100644 --- a/ts/features/bonusVacanze/screens/activation/BonusAlreadyExists.tsx +++ b/ts/features/bonusVacanze/screens/activation/BonusAlreadyExists.tsx @@ -9,7 +9,10 @@ import { useHardwareBackButton } from "../../components/hooks/useHardwareBackBut import { renderInfoRasterImage } from "../../components/infoScreen/imageRendering"; import { InfoScreenComponent } from "../../components/infoScreen/InfoScreenComponent"; import { bonusVacanzeStyle } from "../../components/Styles"; -import { cancelBonusVacanzeRequest } from "../../store/actions/bonusVacanze"; +import { + cancelBonusVacanzeRequest, + showBonusVacanze +} from "../../store/actions/bonusVacanze"; type Props = ReturnType; @@ -41,13 +44,16 @@ const BonusAlreadyExists: React.FunctionComponent = props => { title={title} body={body} /> - + ); }; const mapDispatchToProps = (dispatch: Dispatch) => ({ - onCancel: () => dispatch(cancelBonusVacanzeRequest()) + onCancel: () => dispatch(cancelBonusVacanzeRequest()), + onGoToBonus: () => dispatch(showBonusVacanze()) }); export default connect( diff --git a/ts/features/bonusVacanze/store/actions/bonusVacanze.ts b/ts/features/bonusVacanze/store/actions/bonusVacanze.ts index 91b528804ab..97f390577ef 100644 --- a/ts/features/bonusVacanze/store/actions/bonusVacanze.ts +++ b/ts/features/bonusVacanze/store/actions/bonusVacanze.ts @@ -59,6 +59,10 @@ export const cancelBonusVacanzeRequest = createStandardAction( "BONUS_VACANZE_REQUEST_CANCEL" )(); +export const showBonusVacanze = createStandardAction("BONUS_VACANZE_SHOW")< + void +>(); + // Complete the bonus activation phase with success export const completeBonusVacanzeActivation = createStandardAction( "BONUS_VACANZE_ACTIVATION_COMPLETE" @@ -94,4 +98,5 @@ export type BonusActions = | ActionType | ActionType | ActionType + | ActionType | ActionType; diff --git a/ts/features/bonusVacanze/store/sagas/activation/handleBonusActivationSaga.ts b/ts/features/bonusVacanze/store/sagas/activation/handleBonusActivationSaga.ts index 3e923ad30cf..6fbb3a9e78e 100644 --- a/ts/features/bonusVacanze/store/sagas/activation/handleBonusActivationSaga.ts +++ b/ts/features/bonusVacanze/store/sagas/activation/handleBonusActivationSaga.ts @@ -1,4 +1,5 @@ import { fromNullable } from "fp-ts/lib/Option"; +import { NavigationActions } from "react-navigation"; import { SagaIterator } from "redux-saga"; import { call, put, race, select, take } from "redux-saga/effects"; import { getType } from "typesafe-actions"; @@ -18,7 +19,8 @@ import BONUSVACANZE_ROUTES from "../../../navigation/routes"; import { activateBonusVacanze, cancelBonusVacanzeRequest, - completeBonusVacanzeActivation + completeBonusVacanzeActivation, + showBonusVacanze } from "../../actions/bonusVacanze"; import { BonusActivationProgressEnum } from "../../reducers/activation"; import { bonusActivationSaga } from "./getBonusActivationSaga"; @@ -60,6 +62,7 @@ export function* activationWorker(activationSaga: BonusActivationSagaType) { if (currentRoute.isSome() && !isLoadingScreen(currentRoute.value)) { // show the loading page for the activation yield put(navigateToBonusActivationLoading()); + yield put(navigationHistoryPop(1)); } // start and wait for network request @@ -85,6 +88,8 @@ export function* activationWorker(activationSaga: BonusActivationSagaType) { yield put( navigateToBonusActiveDetailScreen({ bonus: progress.payload.activation }) ); + // remove the congratulation screen from the navigation stack + yield put(navigationHistoryPop(1)); } } @@ -99,13 +104,15 @@ export function* handleBonusActivationSaga( ): SagaIterator { // an event of bonusVacanzeActivation.request trigger a new workflow for the activation - const { cancelAction } = yield race({ + const { cancelAction, showAction } = yield race({ activation: call(activationWorker, activationSaga), - cancelAction: take(cancelBonusVacanzeRequest) + cancelAction: take(cancelBonusVacanzeRequest), + showAction: take(showBonusVacanze) }); if (cancelAction) { + yield put(NavigationActions.back()); + } else if (showAction) { yield put(navigateToWalletHome()); + yield put(navigationHistoryPop(1)); } - // remove the congratulation screen from the navigation stack - yield put(navigationHistoryPop(1)); } diff --git a/ts/features/bonusVacanze/store/sagas/eligibility/handleBonusEligibilitySaga.ts b/ts/features/bonusVacanze/store/sagas/eligibility/handleBonusEligibilitySaga.ts index 6224332630b..0b3ef8f88ad 100644 --- a/ts/features/bonusVacanze/store/sagas/eligibility/handleBonusEligibilitySaga.ts +++ b/ts/features/bonusVacanze/store/sagas/eligibility/handleBonusEligibilitySaga.ts @@ -1,8 +1,8 @@ import { fromNullable } from "fp-ts/lib/Option"; +import { NavigationActions } from "react-navigation"; import { SagaIterator } from "redux-saga"; import { call, put, race, select, take } from "redux-saga/effects"; import { getType } from "typesafe-actions"; -import { navigateToWalletHome } from "../../../../../store/actions/navigation"; import { navigationHistoryPop } from "../../../../../store/actions/navigationHistory"; import { navigationCurrentRouteSelector } from "../../../../../store/reducers/navigation"; import { SagaCallReturnType } from "../../../../../types/utils"; @@ -63,6 +63,7 @@ export function* eligibilityWorker(eligibilitySaga: BonusEligibilitySagaType) { if (currentRoute.isSome() && !isLoadingScreen(currentRoute.value)) { // show the loading page for the check eligibility yield put(navigateToBonusEligibilityLoading()); + yield put(navigationHistoryPop(1)); } // start and wait for network request @@ -98,8 +99,6 @@ export function* handleBonusEligibilitySaga( cancelAction: take(cancelBonusVacanzeRequest) }); if (cancelAction) { - yield put(navigateToWalletHome()); + yield put(NavigationActions.back()); } - // remove the eligibility detail info screen from the navigation stack - yield put(navigationHistoryPop(1)); } From 7d44803c258ba8f96a435bab4d5cd0a28a637655 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Tue, 30 Jun 2020 18:39:14 +0200 Subject: [PATCH 02/10] [#173521040] Change image and add cta for EligibilityExpired --- img/pictograms/hourglass.png | Bin 0 -> 5489 bytes img/pictograms/hourglass.svg | 20 +++++++++++++++ locales/en/index.yml | 1 + locales/it/index.yml | 1 + .../screens/activation/EligibilityExpired.tsx | 24 +++++++++++++----- .../activation/handleBonusActivationSaga.ts | 4 ++- ts/screens/wallet/WalletHomeScreen.tsx | 5 ++-- 7 files changed, 45 insertions(+), 10 deletions(-) create mode 100644 img/pictograms/hourglass.png create mode 100644 img/pictograms/hourglass.svg diff --git a/img/pictograms/hourglass.png b/img/pictograms/hourglass.png new file mode 100644 index 0000000000000000000000000000000000000000..ad2d20d326256a97a8473b0c42e5de826b308f29 GIT binary patch literal 5489 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 + + pictograms/deco/glasshour + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/locales/en/index.yml b/locales/en/index.yml index 90bea5abb0c..c7c24de08f4 100644 --- a/locales/en/index.yml +++ b/locales/en/index.yml @@ -1402,6 +1402,7 @@ bonus: eligibilityExpired: title: Time expired. body: The 24 hours needed to continue your request have expired. Please, start a new request. + cta: Request Bonus completed: title: Congratulation! description: Bonus activated diff --git a/locales/it/index.yml b/locales/it/index.yml index e9b51d286d2..907e9f06938 100644 --- a/locales/it/index.yml +++ b/locales/it/index.yml @@ -1434,6 +1434,7 @@ bonus: eligibilityExpired: title: Tempo scaduto. body: Le 24 ore utili a proseguire la tua richiesta sono scadute. Ti chiediamo di ricominciare una nuova richiesta. + cta: "Richiedi Bonus" confirm: title: Attenzione body: Continuando nel processo, non sarà più possibile annullare la richiesta. diff --git a/ts/features/bonusVacanze/screens/activation/EligibilityExpired.tsx b/ts/features/bonusVacanze/screens/activation/EligibilityExpired.tsx index 6bfd78c335c..e6385e9ec26 100644 --- a/ts/features/bonusVacanze/screens/activation/EligibilityExpired.tsx +++ b/ts/features/bonusVacanze/screens/activation/EligibilityExpired.tsx @@ -2,18 +2,24 @@ import * as React from "react"; import { SafeAreaView } from "react-native"; import { connect } from "react-redux"; import { Dispatch } from "redux"; +import FooterWithButtons from "../../../../components/ui/FooterWithButtons"; import I18n from "../../../../i18n"; -import { cancelButtonProps } from "../../components/buttons/ButtonConfigurations"; -import { FooterStackButton } from "../../components/buttons/FooterStackButtons"; +import { + cancelButtonProps, + confirmButtonProps +} from "../../components/buttons/ButtonConfigurations"; import { useHardwareBackButton } from "../../components/hooks/useHardwareBackButton"; import { renderInfoRasterImage } from "../../components/infoScreen/imageRendering"; import { InfoScreenComponent } from "../../components/infoScreen/InfoScreenComponent"; import { bonusVacanzeStyle } from "../../components/Styles"; -import { cancelBonusVacanzeRequest } from "../../store/actions/bonusVacanze"; +import { + cancelBonusVacanzeRequest, + checkBonusVacanzeEligibility +} from "../../store/actions/bonusVacanze"; type Props = ReturnType; -const image = require("../../../../../img/wallet/errors/payment-expired-icon.png"); +const image = require("../../../../../img/pictograms/hourglass.png"); /** * This screen informs the user that the eligibility data has expired @@ -32,6 +38,7 @@ const EligibilityExpired: React.FunctionComponent = props => { ); const body = I18n.t("bonus.bonusVacanze.activation.eligibilityExpired.body"); const cancel = I18n.t("global.buttons.close"); + const cta = I18n.t("bonus.bonusVacanze.activation.eligibilityExpired.cta"); useHardwareBackButton(() => { props.onCancel(); @@ -45,15 +52,18 @@ const EligibilityExpired: React.FunctionComponent = props => { title={title} body={body} /> - ); }; const mapDispatchToProps = (dispatch: Dispatch) => ({ - onCancel: () => dispatch(cancelBonusVacanzeRequest()) + onCancel: () => dispatch(cancelBonusVacanzeRequest()), + onRestart: () => dispatch(checkBonusVacanzeEligibility.request()) }); export default connect( diff --git a/ts/features/bonusVacanze/store/sagas/activation/handleBonusActivationSaga.ts b/ts/features/bonusVacanze/store/sagas/activation/handleBonusActivationSaga.ts index 6fbb3a9e78e..3a986c28371 100644 --- a/ts/features/bonusVacanze/store/sagas/activation/handleBonusActivationSaga.ts +++ b/ts/features/bonusVacanze/store/sagas/activation/handleBonusActivationSaga.ts @@ -19,6 +19,7 @@ import BONUSVACANZE_ROUTES from "../../../navigation/routes"; import { activateBonusVacanze, cancelBonusVacanzeRequest, + checkBonusVacanzeEligibility, completeBonusVacanzeActivation, showBonusVacanze } from "../../actions/bonusVacanze"; @@ -107,7 +108,8 @@ export function* handleBonusActivationSaga( const { cancelAction, showAction } = yield race({ activation: call(activationWorker, activationSaga), cancelAction: take(cancelBonusVacanzeRequest), - showAction: take(showBonusVacanze) + showAction: take(showBonusVacanze), + restartEligibility: take(checkBonusVacanzeEligibility.request) }); if (cancelAction) { yield put(NavigationActions.back()); diff --git a/ts/screens/wallet/WalletHomeScreen.tsx b/ts/screens/wallet/WalletHomeScreen.tsx index ec8513b4300..e1a72bff141 100644 --- a/ts/screens/wallet/WalletHomeScreen.tsx +++ b/ts/screens/wallet/WalletHomeScreen.tsx @@ -26,7 +26,8 @@ import { bonusVacanzeEnabled } from "../../config"; import RequestBonus from "../../features/bonusVacanze/components/RequestBonus"; import { navigateToAvailableBonusScreen, - navigateToBonusActiveDetailScreen + navigateToBonusActiveDetailScreen, + navigateToEligibilityExpired } from "../../features/bonusVacanze/navigation/action"; import { loadAllBonusActivations, @@ -537,7 +538,7 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ navigateToWalletAddPaymentMethod: (keyFrom?: string) => dispatch(navigateToWalletAddPaymentMethod({ inPayment: none, keyFrom })), navigateToWalletList: () => dispatch(navigateToWalletList()), - navigateToPaymentScanQrCode: () => dispatch(navigateToPaymentScanQrCode()), + navigateToPaymentScanQrCode: () => dispatch(navigateToEligibilityExpired()), navigateToTransactionDetailsScreen: (transaction: Transaction) => { dispatch(readTransaction(transaction)); dispatch( From c32a54ddb1e5057b45ed13abf8b761fddc80db88 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Tue, 30 Jun 2020 18:43:03 +0200 Subject: [PATCH 03/10] restore wallethomescreen --- ts/screens/wallet/WalletHomeScreen.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ts/screens/wallet/WalletHomeScreen.tsx b/ts/screens/wallet/WalletHomeScreen.tsx index e1a72bff141..ec8513b4300 100644 --- a/ts/screens/wallet/WalletHomeScreen.tsx +++ b/ts/screens/wallet/WalletHomeScreen.tsx @@ -26,8 +26,7 @@ import { bonusVacanzeEnabled } from "../../config"; import RequestBonus from "../../features/bonusVacanze/components/RequestBonus"; import { navigateToAvailableBonusScreen, - navigateToBonusActiveDetailScreen, - navigateToEligibilityExpired + navigateToBonusActiveDetailScreen } from "../../features/bonusVacanze/navigation/action"; import { loadAllBonusActivations, @@ -538,7 +537,7 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ navigateToWalletAddPaymentMethod: (keyFrom?: string) => dispatch(navigateToWalletAddPaymentMethod({ inPayment: none, keyFrom })), navigateToWalletList: () => dispatch(navigateToWalletList()), - navigateToPaymentScanQrCode: () => dispatch(navigateToEligibilityExpired()), + navigateToPaymentScanQrCode: () => dispatch(navigateToPaymentScanQrCode()), navigateToTransactionDetailsScreen: (transaction: Transaction) => { dispatch(readTransaction(transaction)); dispatch( From cfc8ebdc32cc88346c0dd18c6398bf782d0caef6 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Tue, 30 Jun 2020 19:15:16 +0200 Subject: [PATCH 04/10] fix test to the new logic --- .../integration/activationIntegrationTests.ts | 14 ++++++++------ .../activation/__tests__/integration/mockData.ts | 1 + 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/activationIntegrationTests.ts b/ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/activationIntegrationTests.ts index 647f53087e3..7da7e6f2f95 100644 --- a/ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/activationIntegrationTests.ts +++ b/ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/activationIntegrationTests.ts @@ -1,12 +1,11 @@ import { Either, right } from "fp-ts/lib/Either"; import { fromNullable, some } from "fp-ts/lib/Option"; import { Errors } from "io-ts"; +import { NavigationActions } from "react-navigation"; import { Action, combineReducers } from "redux"; import { expectSaga } from "redux-saga-test-plan"; import * as matchers from "redux-saga-test-plan/matchers"; import { select } from "redux-saga-test-plan/matchers"; -import { navigateToWalletHome } from "../../../../../../../store/actions/navigation"; -import { navigationHistoryPop } from "../../../../../../../store/actions/navigationHistory"; import { navigationCurrentRouteSelector } from "../../../../../../../store/reducers/navigation"; import BONUSVACANZE_ROUTES from "../../../../../navigation/routes"; import { @@ -74,13 +73,17 @@ describe("Bonus Activation Saga Integration Test", () => { ] ]) .dispatch(cancelBonusVacanzeRequest()) - .put(navigationHistoryPop(1)) - .put(navigateToWalletHome()) + .put(NavigationActions.back()) .hasFinalState({ activation: { status: BonusActivationProgressEnum.ERROR }, allActive: {} } as MockActivationState) - .run(); + .run() + .then(results => { + expect(results.effects.select.length).toEqual(1); + // in this phase the put in the store is not tested, at the end I should have only one put action left + expect(results.effects.put.length).toEqual(1); + }); }); backendIntegrationTestCases.map(testCase => testCase.responses.map(response => { @@ -131,7 +134,6 @@ const expectSagaFactory = ( .reduce((acc, val) => acc.put(val), baseSaga) // when the last event completeBonusVacanze is received, the navigation stack is popped .dispatch(completeBonusVacanzeActivation()) - .put(navigationHistoryPop(1)) .hasFinalState(finalState) .run() .then(results => { diff --git a/ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/mockData.ts b/ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/mockData.ts index a77373a5819..87a5c5a1ce5 100644 --- a/ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/mockData.ts +++ b/ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/mockData.ts @@ -100,6 +100,7 @@ export const success: MockBackendScenario = { ], expectedActions: [ navigateToBonusActivationCompleted(), + navigationHistoryPop(1), navigateToBonusActiveDetailScreen({ bonus: mockedBonus }), navigationHistoryPop(1) ], From 034dcbc7893ef9aaefe490aa24166dabdbf47704 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Tue, 30 Jun 2020 19:43:19 +0200 Subject: [PATCH 05/10] add new test case --- .../integration/activationIntegrationTests.ts | 39 ++++++++++++++- .../__tests__/integration/mockData.ts | 47 +++++++++++++++++++ 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/activationIntegrationTests.ts b/ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/activationIntegrationTests.ts index 7da7e6f2f95..e7304efe07d 100644 --- a/ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/activationIntegrationTests.ts +++ b/ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/activationIntegrationTests.ts @@ -6,11 +6,14 @@ import { Action, combineReducers } from "redux"; import { expectSaga } from "redux-saga-test-plan"; import * as matchers from "redux-saga-test-plan/matchers"; import { select } from "redux-saga-test-plan/matchers"; +import { navigateToWalletHome } from "../../../../../../../store/actions/navigation"; +import { navigationHistoryPop } from "../../../../../../../store/actions/navigationHistory"; import { navigationCurrentRouteSelector } from "../../../../../../../store/reducers/navigation"; import BONUSVACANZE_ROUTES from "../../../../../navigation/routes"; import { cancelBonusVacanzeRequest, - completeBonusVacanzeActivation + completeBonusVacanzeActivation, + showBonusVacanze } from "../../../../actions/bonusVacanze"; import allActiveReducer from "../../../../reducers/allActive"; import { bonusActivationSaga } from "../../getBonusActivationSaga"; @@ -85,6 +88,40 @@ describe("Bonus Activation Saga Integration Test", () => { expect(results.effects.put.length).toEqual(1); }); }); + //TODO: refactor with the previous test + it("Handle showBonusVacanze", () => { + const startBonusActivation = jest.fn(); + const getActivationById = jest.fn(); + + return expectSaga( + handleBonusActivationSaga, + bonusActivationSaga(startBonusActivation, getActivationById) + ) + .withReducer(activationReducer) + .provide([ + [ + select(navigationCurrentRouteSelector), + some(BONUSVACANZE_ROUTES.ACTIVATION.LOADING) + ], + [ + matchers.call.fn(startBonusActivation), + right({ status: 500, value: {} }) + ] + ]) + .dispatch(showBonusVacanze()) + .put(navigateToWalletHome()) + .put(navigationHistoryPop(1)) + .hasFinalState({ + activation: { status: BonusActivationProgressEnum.ERROR }, + allActive: {} + } as MockActivationState) + .run() + .then(results => { + expect(results.effects.select.length).toEqual(1); + // in this phase the put in the store is not tested, at the end I should have only one put action left + expect(results.effects.put.length).toEqual(1); + }); + }); backendIntegrationTestCases.map(testCase => testCase.responses.map(response => { return it(`${ diff --git a/ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/mockData.ts b/ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/mockData.ts index 87a5c5a1ce5..ab5fc636e0c 100644 --- a/ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/mockData.ts +++ b/ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/mockData.ts @@ -2,8 +2,11 @@ import { Either, left, right } from "fp-ts/lib/Either"; import { Errors } from "io-ts"; import { pot } from "italia-ts-commons"; import { ProblemJson } from "italia-ts-commons/lib/responses"; +import { NavigationActions } from "react-navigation"; +import { Action } from "redux"; import { BonusActivationStatusEnum } from "../../../../../../../../definitions/bonus_vacanze/BonusActivationStatus"; import { InstanceId } from "../../../../../../../../definitions/bonus_vacanze/InstanceId"; +import { navigateToWalletHome } from "../../../../../../../store/actions/navigation"; import { navigationHistoryPop } from "../../../../../../../store/actions/navigationHistory"; import { mockedBonus } from "../../../../../mock/mockData"; import { @@ -13,6 +16,12 @@ import { navigateToBonusAlreadyExists, navigateToEligibilityExpired } from "../../../../../navigation/action"; +import { + cancelBonusVacanzeRequest, + checkBonusVacanzeEligibility, + completeBonusVacanzeActivation, + showBonusVacanze +} from "../../../../actions/bonusVacanze"; import { ActivationState, BonusActivationProgressEnum @@ -90,6 +99,44 @@ interface MockBackendScenario extends IExpectedActions { finalState: MockActivationState; } +interface IMockUserActions extends IExpectedActions { + userAction: Action; +} + +// Mock user actions + +const userCancel: IMockUserActions = { + displayName: "User Cancel Action", + userAction: cancelBonusVacanzeRequest(), + expectedActions: [NavigationActions.back()] +}; + +const userCompleteActivation: IMockUserActions = { + displayName: "User Complete Activation", + userAction: completeBonusVacanzeActivation(), + expectedActions: [] +}; + +const userShowBonusVacanze: IMockUserActions = { + displayName: "User Show Bonus Vacanze", + userAction: showBonusVacanze(), + expectedActions: [navigateToWalletHome(), navigationHistoryPop(1)] +}; + +const userRestartEligibility: IMockUserActions = { + displayName: "User Restart Eligibility", + userAction: checkBonusVacanzeEligibility.request(), + expectedActions: [] +}; + +export const possibleUserActions: ReadonlyArray = [ + userCancel, + userCompleteActivation, + userShowBonusVacanze, + userRestartEligibility +]; + +// Mock Backend response export const success: MockBackendScenario = { displayName: "success", responses: [ From 8e0321779bf99904e6d83412debd49cc75a2ba5c Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Wed, 1 Jul 2020 15:05:37 +0200 Subject: [PATCH 06/10] fix lint --- .../integration/activationIntegrationTests.ts | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/activationIntegrationTests.ts b/ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/activationIntegrationTests.ts index e7304efe07d..f753a595bd9 100644 --- a/ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/activationIntegrationTests.ts +++ b/ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/activationIntegrationTests.ts @@ -3,7 +3,7 @@ import { fromNullable, some } from "fp-ts/lib/Option"; import { Errors } from "io-ts"; import { NavigationActions } from "react-navigation"; import { Action, combineReducers } from "redux"; -import { expectSaga } from "redux-saga-test-plan"; +import { expectSaga, RunResult } from "redux-saga-test-plan"; import * as matchers from "redux-saga-test-plan/matchers"; import { select } from "redux-saga-test-plan/matchers"; import { navigateToWalletHome } from "../../../../../../../store/actions/navigation"; @@ -82,13 +82,9 @@ describe("Bonus Activation Saga Integration Test", () => { allActive: {} } as MockActivationState) .run() - .then(results => { - expect(results.effects.select.length).toEqual(1); - // in this phase the put in the store is not tested, at the end I should have only one put action left - expect(results.effects.put.length).toEqual(1); - }); + .then(expectFinalSagaState); }); - //TODO: refactor with the previous test + // TODO: refactor with the previous test it("Handle showBonusVacanze", () => { const startBonusActivation = jest.fn(); const getActivationById = jest.fn(); @@ -116,11 +112,7 @@ describe("Bonus Activation Saga Integration Test", () => { allActive: {} } as MockActivationState) .run() - .then(results => { - expect(results.effects.select.length).toEqual(1); - // in this phase the put in the store is not tested, at the end I should have only one put action left - expect(results.effects.put.length).toEqual(1); - }); + .then(expectFinalSagaState); }); backendIntegrationTestCases.map(testCase => testCase.responses.map(response => { @@ -173,10 +165,12 @@ const expectSagaFactory = ( .dispatch(completeBonusVacanzeActivation()) .hasFinalState(finalState) .run() - .then(results => { - expect(results.effects.select.length).toEqual(1); - // in this phase the put in the store is not tested, at the end I should have only one put action left - expect(results.effects.put.length).toEqual(1); - }) + .then(expectFinalSagaState) ); }; + +const expectFinalSagaState = (result: RunResult) => { + expect(result.effects.select.length).toEqual(1); + // in this phase the put in the store is not tested, at the end I should have only one put action left + expect(result.effects.put.length).toEqual(1); +}; From 55a7c65ae2e16b9142ae06ff12577f4ff77e70a3 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Wed, 1 Jul 2020 18:59:44 +0200 Subject: [PATCH 07/10] fix test --- .../activation/__tests__/handleBonusActivationTests.ts | 7 ++----- .../store/sagas/activation/__tests__/mockData.ts | 3 ++- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/ts/features/bonusVacanze/store/sagas/activation/__tests__/handleBonusActivationTests.ts b/ts/features/bonusVacanze/store/sagas/activation/__tests__/handleBonusActivationTests.ts index 33b48e25784..80c64e49d11 100644 --- a/ts/features/bonusVacanze/store/sagas/activation/__tests__/handleBonusActivationTests.ts +++ b/ts/features/bonusVacanze/store/sagas/activation/__tests__/handleBonusActivationTests.ts @@ -1,10 +1,9 @@ import { fromNullable } from "fp-ts/lib/Option"; +import { NavigationActions } from "react-navigation"; import { Action } from "redux"; import { expectSaga } from "redux-saga-test-plan"; import { select } from "redux-saga-test-plan/matchers"; import { ActionType } from "typesafe-actions"; -import { navigateToWalletHome } from "../../../../../../store/actions/navigation"; -import { navigationHistoryPop } from "../../../../../../store/actions/navigationHistory"; import { navigationCurrentRouteSelector } from "../../../../../../store/reducers/navigation"; import BONUSVACANZE_ROUTES from "../../../../navigation/routes"; import { @@ -42,8 +41,7 @@ describe("Bonus Activation Saga", () => { ] ]) .dispatch(cancelBonusVacanzeRequest()) - .put(navigateToWalletHome()) - .put(navigationHistoryPop(1)) + .put(NavigationActions.back()) .run(); }); networkingActivationResultActions.map(networkingScenario => @@ -85,7 +83,6 @@ const expectSagaFactory = ( .reduce((acc, val) => acc.put(val), baseSaga) // when the last event completeBonusVacanze is received, the navigation stack is popped .dispatch(completeBonusVacanzeActivation()) - .put(navigationHistoryPop(1)) .run() .then(results => { expect(results.effects.select.length).toEqual(1); diff --git a/ts/features/bonusVacanze/store/sagas/activation/__tests__/mockData.ts b/ts/features/bonusVacanze/store/sagas/activation/__tests__/mockData.ts index 5a8173c05c2..13e8edac8b9 100644 --- a/ts/features/bonusVacanze/store/sagas/activation/__tests__/mockData.ts +++ b/ts/features/bonusVacanze/store/sagas/activation/__tests__/mockData.ts @@ -35,7 +35,7 @@ export const startFromLoadingScreen: StartScreenScenario = { export const startFromAnotherScreen: StartScreenScenario = { displayName: "startFromAnotherScreen", startScreen: BONUSVACANZE_ROUTES.MAIN, - expectedActions: [navigateToBonusActivationLoading()] + expectedActions: [navigateToBonusActivationLoading(), navigationHistoryPop(1)] }; interface NetworkingResults extends IExpectedActions { @@ -51,6 +51,7 @@ export const activationSuccess: NetworkingResults = { }), expectedActions: [ navigateToBonusActivationCompleted(), + navigationHistoryPop(1), navigateToBonusActiveDetailScreen({ bonus: mockedBonus }), navigationHistoryPop(1) ] From dfe37c152332144b0805c3a76dba32f28bd43d3e Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 3 Jul 2020 11:02:13 +0200 Subject: [PATCH 08/10] handle showBonusVacanze action in eligibility saga --- .../backendMockData.ts} | 42 ++++++++++++------- .../networkingSagaResponseMockData.ts} | 36 ++++++++++++---- .../activationIntegrationTests.ts | 24 ++++++----- .../__tests__/handleBonusActivationTests.ts | 4 +- .../activation/handleBonusActivationSaga.ts | 4 ++ .../eligibility/handleBonusEligibilitySaga.ts | 12 ++++-- 6 files changed, 82 insertions(+), 40 deletions(-) rename ts/features/bonusVacanze/store/sagas/activation/{__tests__/integration/mockData.ts => __mock__/backendMockData.ts} (86%) rename ts/features/bonusVacanze/store/sagas/activation/{__tests__/mockData.ts => __mock__/networkingSagaResponseMockData.ts} (79%) rename ts/features/bonusVacanze/store/sagas/activation/__tests__/{integration => }/activationIntegrationTests.ts (87%) diff --git a/ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/mockData.ts b/ts/features/bonusVacanze/store/sagas/activation/__mock__/backendMockData.ts similarity index 86% rename from ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/mockData.ts rename to ts/features/bonusVacanze/store/sagas/activation/__mock__/backendMockData.ts index ab5fc636e0c..2214ce2373e 100644 --- a/ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/mockData.ts +++ b/ts/features/bonusVacanze/store/sagas/activation/__mock__/backendMockData.ts @@ -4,30 +4,33 @@ import { pot } from "italia-ts-commons"; import { ProblemJson } from "italia-ts-commons/lib/responses"; import { NavigationActions } from "react-navigation"; import { Action } from "redux"; -import { BonusActivationStatusEnum } from "../../../../../../../../definitions/bonus_vacanze/BonusActivationStatus"; -import { InstanceId } from "../../../../../../../../definitions/bonus_vacanze/InstanceId"; -import { navigateToWalletHome } from "../../../../../../../store/actions/navigation"; -import { navigationHistoryPop } from "../../../../../../../store/actions/navigationHistory"; -import { mockedBonus } from "../../../../../mock/mockData"; +import { BonusActivationStatusEnum } from "../../../../../../../definitions/bonus_vacanze/BonusActivationStatus"; +import { InstanceId } from "../../../../../../../definitions/bonus_vacanze/InstanceId"; +import { navigateToWalletHome } from "../../../../../../store/actions/navigation"; +import { navigationHistoryPop } from "../../../../../../store/actions/navigationHistory"; +import { mockedBonus } from "../../../../mock/mockData"; import { navigateToBonusActivationCompleted, navigateToBonusActivationTimeout, navigateToBonusActiveDetailScreen, navigateToBonusAlreadyExists, navigateToEligibilityExpired -} from "../../../../../navigation/action"; +} from "../../../../navigation/action"; import { cancelBonusVacanzeRequest, checkBonusVacanzeEligibility, completeBonusVacanzeActivation, showBonusVacanze -} from "../../../../actions/bonusVacanze"; +} from "../../../actions/bonusVacanze"; import { ActivationState, BonusActivationProgressEnum -} from "../../../../reducers/activation"; -import { AllActiveState } from "../../../../reducers/allActive"; -import { IExpectedActions } from "../mockData"; +} from "../../../reducers/activation"; +import { AllActiveState } from "../../../reducers/allActive"; +import { + completeBonusDefaultActions, + IExpectedActions +} from "./networkingSagaResponseMockData"; const genericServiceUnavailable: Either = right({ status: 500, @@ -165,7 +168,11 @@ export const eligibilityExpired: MockBackendScenario = { getBonusActivationResponseById: right(undefined) } ], - expectedActions: [navigateToEligibilityExpired(), navigationHistoryPop(1)], + expectedActions: [ + navigateToEligibilityExpired(), + navigationHistoryPop(1), + ...completeBonusDefaultActions + ], finalState: { activation: { status: BonusActivationProgressEnum.ELIGIBILITY_EXPIRED }, allActive: {} @@ -180,7 +187,11 @@ export const bonusAlreadyExists: MockBackendScenario = { getBonusActivationResponseById: right(undefined) } ], - expectedActions: [navigateToBonusAlreadyExists(), navigationHistoryPop(1)], + expectedActions: [ + navigateToBonusAlreadyExists(), + navigationHistoryPop(1), + ...completeBonusDefaultActions + ], finalState: { activation: { status: BonusActivationProgressEnum.EXISTS }, allActive: {} @@ -198,7 +209,8 @@ export const timeout: MockBackendScenario = { ], expectedActions: [ navigateToBonusActivationTimeout(), - navigationHistoryPop(1) + navigationHistoryPop(1), + ...completeBonusDefaultActions ], finalState: { activation: { status: BonusActivationProgressEnum.TIMEOUT }, @@ -242,7 +254,7 @@ export const error: MockBackendScenario = { getBonusActivationResponseById: getActivationSuccessBonusError } ], - expectedActions: [], + expectedActions: completeBonusDefaultActions, finalState: { activation: { status: BonusActivationProgressEnum.ERROR }, allActive: {} @@ -256,5 +268,3 @@ export const backendIntegrationTestCases: ReadonlyArray = [ timeout, error ]; - -test.skip("mockDataOnlyFile", () => undefined); diff --git a/ts/features/bonusVacanze/store/sagas/activation/__tests__/mockData.ts b/ts/features/bonusVacanze/store/sagas/activation/__mock__/networkingSagaResponseMockData.ts similarity index 79% rename from ts/features/bonusVacanze/store/sagas/activation/__tests__/mockData.ts rename to ts/features/bonusVacanze/store/sagas/activation/__mock__/networkingSagaResponseMockData.ts index 13e8edac8b9..75ade20e9af 100644 --- a/ts/features/bonusVacanze/store/sagas/activation/__tests__/mockData.ts +++ b/ts/features/bonusVacanze/store/sagas/activation/__mock__/networkingSagaResponseMockData.ts @@ -1,6 +1,7 @@ import { Action } from "redux"; import { ActionType } from "typesafe-actions"; import { InstanceId } from "../../../../../../../definitions/bonus_vacanze/InstanceId"; +import { navigateToWalletHome } from "../../../../../../store/actions/navigation"; import { navigationHistoryPop } from "../../../../../../store/actions/navigationHistory"; import { mockedBonus } from "../../../../mock/mockData"; import { @@ -15,6 +16,8 @@ import BONUSVACANZE_ROUTES from "../../../../navigation/routes"; import { activateBonusVacanze } from "../../../actions/bonusVacanze"; import { BonusActivationProgressEnum } from "../../../reducers/activation"; +// This file mocks response from the networking saga. + export interface IExpectedActions { displayName: string; expectedActions: ReadonlyArray; @@ -42,6 +45,13 @@ interface NetworkingResults extends IExpectedActions { results: ActionType; } +// When the saga is completed with a `completeBonusVacanzeActivation` and no a valid payload is found +// return to wallet. To test the saga, after the networking part a `completeDummyActions` is executed. +export const completeBonusDefaultActions: ReadonlyArray = [ + navigateToWalletHome(), + navigationHistoryPop(1) +]; + export const activationSuccess: NetworkingResults = { displayName: "activationSuccess", results: activateBonusVacanze.success({ @@ -63,7 +73,11 @@ export const activationTimeout: NetworkingResults = { status: BonusActivationProgressEnum.TIMEOUT, instanceId: { id: "unique_id" } as InstanceId }), - expectedActions: [navigateToBonusActivationTimeout(), navigationHistoryPop(1)] + expectedActions: [ + navigateToBonusActivationTimeout(), + navigationHistoryPop(1), + ...completeBonusDefaultActions + ] }; export const activationExpired: NetworkingResults = { @@ -71,7 +85,11 @@ export const activationExpired: NetworkingResults = { results: activateBonusVacanze.success({ status: BonusActivationProgressEnum.ELIGIBILITY_EXPIRED }), - expectedActions: [navigateToEligibilityExpired(), navigationHistoryPop(1)] + expectedActions: [ + navigateToEligibilityExpired(), + navigationHistoryPop(1), + ...completeBonusDefaultActions + ] }; export const activationExists: NetworkingResults = { @@ -79,7 +97,11 @@ export const activationExists: NetworkingResults = { results: activateBonusVacanze.success({ status: BonusActivationProgressEnum.EXISTS }), - expectedActions: [navigateToBonusAlreadyExists(), navigationHistoryPop(1)] + expectedActions: [ + navigateToBonusAlreadyExists(), + navigationHistoryPop(1), + ...completeBonusDefaultActions + ] }; // when an error occurs, no navigation is expected, just the reducer `isLoading` should return false @@ -88,7 +110,7 @@ export const activationError: NetworkingResults = { results: activateBonusVacanze.success({ status: BonusActivationProgressEnum.ERROR }), - expectedActions: [] + expectedActions: completeBonusDefaultActions }; // This case should never happens, but in case no action is expected @@ -97,7 +119,7 @@ export const activationUndefined: NetworkingResults = { results: activateBonusVacanze.success({ status: BonusActivationProgressEnum.UNDEFINED }), - expectedActions: [] + expectedActions: completeBonusDefaultActions }; // This case should never happens, but in case no action is expected @@ -106,7 +128,7 @@ export const activationProgress: NetworkingResults = { results: activateBonusVacanze.success({ status: BonusActivationProgressEnum.PROGRESS }), - expectedActions: [] + expectedActions: completeBonusDefaultActions }; export const networkingActivationResultActions: ReadonlyArray< @@ -125,5 +147,3 @@ export const navigationActions: ReadonlyArray = [ startFromAnotherScreen, startFromLoadingScreen ]; - -test.skip("mockDataOnlyFile", () => undefined); diff --git a/ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/activationIntegrationTests.ts b/ts/features/bonusVacanze/store/sagas/activation/__tests__/activationIntegrationTests.ts similarity index 87% rename from ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/activationIntegrationTests.ts rename to ts/features/bonusVacanze/store/sagas/activation/__tests__/activationIntegrationTests.ts index f753a595bd9..9f0a90700c7 100644 --- a/ts/features/bonusVacanze/store/sagas/activation/__tests__/integration/activationIntegrationTests.ts +++ b/ts/features/bonusVacanze/store/sagas/activation/__tests__/activationIntegrationTests.ts @@ -6,26 +6,26 @@ import { Action, combineReducers } from "redux"; import { expectSaga, RunResult } from "redux-saga-test-plan"; import * as matchers from "redux-saga-test-plan/matchers"; import { select } from "redux-saga-test-plan/matchers"; -import { navigateToWalletHome } from "../../../../../../../store/actions/navigation"; -import { navigationHistoryPop } from "../../../../../../../store/actions/navigationHistory"; -import { navigationCurrentRouteSelector } from "../../../../../../../store/reducers/navigation"; -import BONUSVACANZE_ROUTES from "../../../../../navigation/routes"; +import { navigateToWalletHome } from "../../../../../../store/actions/navigation"; +import { navigationHistoryPop } from "../../../../../../store/actions/navigationHistory"; +import { navigationCurrentRouteSelector } from "../../../../../../store/reducers/navigation"; +import BONUSVACANZE_ROUTES from "../../../../navigation/routes"; import { cancelBonusVacanzeRequest, completeBonusVacanzeActivation, showBonusVacanze -} from "../../../../actions/bonusVacanze"; -import allActiveReducer from "../../../../reducers/allActive"; -import { bonusActivationSaga } from "../../getBonusActivationSaga"; -import { handleBonusActivationSaga } from "../../handleBonusActivationSaga"; +} from "../../../actions/bonusVacanze"; +import allActiveReducer from "../../../reducers/allActive"; +import { bonusActivationSaga } from "../getBonusActivationSaga"; +import { handleBonusActivationSaga } from "../handleBonusActivationSaga"; import bonusVacanzeActivationReducer, { BonusActivationProgressEnum -} from "./../../../../reducers/activation"; +} from "../../../reducers/activation"; import { ActivationBackendResponse, backendIntegrationTestCases, MockActivationState -} from "./mockData"; +} from "../__mock__/backendMockData"; jest.mock("react-native-background-timer", () => { return { @@ -54,7 +54,9 @@ const getDisplayNameBackendResponse = (value: Either): string => { } ); }; - +/** This test suite test the integration of the Activation saga, mocking the backend responses + * + */ describe("Bonus Activation Saga Integration Test", () => { it("Cancel A bonus request after server error", () => { const startBonusActivation = jest.fn(); diff --git a/ts/features/bonusVacanze/store/sagas/activation/__tests__/handleBonusActivationTests.ts b/ts/features/bonusVacanze/store/sagas/activation/__tests__/handleBonusActivationTests.ts index 80c64e49d11..2a13738b60f 100644 --- a/ts/features/bonusVacanze/store/sagas/activation/__tests__/handleBonusActivationTests.ts +++ b/ts/features/bonusVacanze/store/sagas/activation/__tests__/handleBonusActivationTests.ts @@ -15,7 +15,7 @@ import { handleBonusActivationSaga } from "../handleBonusActivationSaga"; import { navigationActions, networkingActivationResultActions -} from "./mockData"; +} from "../__mock__/networkingSagaResponseMockData"; jest.mock("react-native-background-timer", () => { return { @@ -31,7 +31,7 @@ jest.mock("react-native-share", () => { type BonusVacanzeReturnType = ActionType; -describe("Bonus Activation Saga", () => { +describe("Bonus Activation Saga, mock networking saga", () => { it("Cancel bonus activation saga", () => { return expectSaga(handleBonusActivationSaga, mockRemote) .provide([ diff --git a/ts/features/bonusVacanze/store/sagas/activation/handleBonusActivationSaga.ts b/ts/features/bonusVacanze/store/sagas/activation/handleBonusActivationSaga.ts index 3a986c28371..5d5dd1887bf 100644 --- a/ts/features/bonusVacanze/store/sagas/activation/handleBonusActivationSaga.ts +++ b/ts/features/bonusVacanze/store/sagas/activation/handleBonusActivationSaga.ts @@ -91,6 +91,10 @@ export function* activationWorker(activationSaga: BonusActivationSagaType) { ); // remove the congratulation screen from the navigation stack yield put(navigationHistoryPop(1)); + } else { + // to avoid leaving the user stuck in this screen in case of lack of payload, return to wallet + yield put(navigateToWalletHome()); + yield put(navigationHistoryPop(1)); } } diff --git a/ts/features/bonusVacanze/store/sagas/eligibility/handleBonusEligibilitySaga.ts b/ts/features/bonusVacanze/store/sagas/eligibility/handleBonusEligibilitySaga.ts index 0b3ef8f88ad..7b5b6083869 100644 --- a/ts/features/bonusVacanze/store/sagas/eligibility/handleBonusEligibilitySaga.ts +++ b/ts/features/bonusVacanze/store/sagas/eligibility/handleBonusEligibilitySaga.ts @@ -3,6 +3,7 @@ import { NavigationActions } from "react-navigation"; import { SagaIterator } from "redux-saga"; import { call, put, race, select, take } from "redux-saga/effects"; import { getType } from "typesafe-actions"; +import { navigateToWalletHome } from "../../../../../store/actions/navigation"; import { navigationHistoryPop } from "../../../../../store/actions/navigationHistory"; import { navigationCurrentRouteSelector } from "../../../../../store/reducers/navigation"; import { SagaCallReturnType } from "../../../../../types/utils"; @@ -19,7 +20,8 @@ import BONUSVACANZE_ROUTES from "../../../navigation/routes"; import { activateBonusVacanze, cancelBonusVacanzeRequest, - checkBonusVacanzeEligibility + checkBonusVacanzeEligibility, + showBonusVacanze } from "../../actions/bonusVacanze"; import { EligibilityRequestProgressEnum } from "../../reducers/eligibility"; import { bonusEligibilitySaga } from "./getBonusEligibilitySaga"; @@ -94,11 +96,15 @@ export function* handleBonusEligibilitySaga( ): SagaIterator { // an event of checkBonusEligibility.request trigger a new workflow for the eligibility - const { cancelAction } = yield race({ + const { cancelAction, showAction } = yield race({ eligibility: call(eligibilityWorker, eligibilitySaga), - cancelAction: take(cancelBonusVacanzeRequest) + cancelAction: take(cancelBonusVacanzeRequest), + showAction: take(showBonusVacanze) }); if (cancelAction) { yield put(NavigationActions.back()); + } else if (showAction) { + yield put(navigateToWalletHome()); + yield put(navigationHistoryPop(1)); } } From 750e03f252db498bb791ee2486c76b0f0ee3be52 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 3 Jul 2020 11:21:41 +0200 Subject: [PATCH 09/10] fix lint --- .../activation/__tests__/activationIntegrationTests.ts | 6 +++--- .../activation/__tests__/handleBonusActivationTests.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ts/features/bonusVacanze/store/sagas/activation/__tests__/activationIntegrationTests.ts b/ts/features/bonusVacanze/store/sagas/activation/__tests__/activationIntegrationTests.ts index 9f0a90700c7..be051fd8980 100644 --- a/ts/features/bonusVacanze/store/sagas/activation/__tests__/activationIntegrationTests.ts +++ b/ts/features/bonusVacanze/store/sagas/activation/__tests__/activationIntegrationTests.ts @@ -15,17 +15,17 @@ import { completeBonusVacanzeActivation, showBonusVacanze } from "../../../actions/bonusVacanze"; -import allActiveReducer from "../../../reducers/allActive"; -import { bonusActivationSaga } from "../getBonusActivationSaga"; -import { handleBonusActivationSaga } from "../handleBonusActivationSaga"; import bonusVacanzeActivationReducer, { BonusActivationProgressEnum } from "../../../reducers/activation"; +import allActiveReducer from "../../../reducers/allActive"; import { ActivationBackendResponse, backendIntegrationTestCases, MockActivationState } from "../__mock__/backendMockData"; +import { bonusActivationSaga } from "../getBonusActivationSaga"; +import { handleBonusActivationSaga } from "../handleBonusActivationSaga"; jest.mock("react-native-background-timer", () => { return { diff --git a/ts/features/bonusVacanze/store/sagas/activation/__tests__/handleBonusActivationTests.ts b/ts/features/bonusVacanze/store/sagas/activation/__tests__/handleBonusActivationTests.ts index 2a13738b60f..5a720b61a75 100644 --- a/ts/features/bonusVacanze/store/sagas/activation/__tests__/handleBonusActivationTests.ts +++ b/ts/features/bonusVacanze/store/sagas/activation/__tests__/handleBonusActivationTests.ts @@ -11,11 +11,11 @@ import { cancelBonusVacanzeRequest, completeBonusVacanzeActivation } from "../../../actions/bonusVacanze"; -import { handleBonusActivationSaga } from "../handleBonusActivationSaga"; import { navigationActions, networkingActivationResultActions } from "../__mock__/networkingSagaResponseMockData"; +import { handleBonusActivationSaga } from "../handleBonusActivationSaga"; jest.mock("react-native-background-timer", () => { return { From e5af8d55f5de3fabef6c969c6b2e2a7a781be0bc Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Tue, 14 Jul 2020 15:14:37 +0200 Subject: [PATCH 10/10] remove svg --- img/pictograms/hourglass.svg | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 img/pictograms/hourglass.svg diff --git a/img/pictograms/hourglass.svg b/img/pictograms/hourglass.svg deleted file mode 100644 index e7dbb8ff09b..00000000000 --- a/img/pictograms/hourglass.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - pictograms/deco/glasshour - - - - - - - - - - - - - - - - - \ No newline at end of file