Skip to content

Commit

Permalink
Merge branch 'master' into IOCOM-864-865-dsPreviewAttachment
Browse files Browse the repository at this point in the history
  • Loading branch information
Vangaorth authored Jan 24, 2024
2 parents 27d3dfd + d34be63 commit aad36b3
Show file tree
Hide file tree
Showing 19 changed files with 113 additions and 26 deletions.
5 changes: 5 additions & 0 deletions locales/en/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,11 @@ wallet:
title: Vuoi pagare in app?
content: Scopri quali sono i metodi che puoi aggiungere al tuo portafoglio.
cta: Scopri di più
error:
title: Si è verificato un errore
subtitle: Riprova o contatta l'assistenza
primaryButton: Chiudi
secondaryButton: Riprova
wallet: Wallet
refreshWallet: Refresh the Wallet
favourite:
Expand Down
5 changes: 5 additions & 0 deletions locales/it/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,11 @@ wallet:
title: Vuoi pagare in app?
content: Scopri quali sono i metodi che puoi aggiungere al tuo portafoglio.
cta: Scopri di più
error:
title: Si è verificato un errore
subtitle: Riprova o contatta l'assistenza
primaryButton: Chiudi
secondaryButton: Riprova
wallet: Portafoglio
refreshWallet: Aggiorna il Portafoglio
favourite:
Expand Down
7 changes: 4 additions & 3 deletions ts/__e2e__/payment.e2e.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import I18n from "../i18n";
import { formatNumberCentsToAmount } from "../utils/stringBuilder";
import { e2eWaitRenderTimeout } from "./config";
import { ensureLoggedIn } from "./utils";
import { closeKeyboard, ensureLoggedIn } from "./utils";

describe("Payment", () => {
beforeEach(async () => {
await device.reloadReactNative();
await device.launchApp({ newInstance: true });
await ensureLoggedIn();
});

Expand Down Expand Up @@ -106,8 +106,9 @@ describe("Payment", () => {

await element(matchNoticeCodeInput).typeText("123123123123123123");
await element(by.id("EntityCodeInputMask")).typeText("12345678901");

// Close the keyboard
await element(by.label("Fine")).atIndex(0).tap();
await closeKeyboard();

await element(by.text(I18n.t("global.buttons.continue"))).tap();

Expand Down
10 changes: 10 additions & 0 deletions ts/__e2e__/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,13 @@ export const ensureLoggedIn = async () => {
await loginWithSPID();
}
};

export const closeKeyboard = async () => {
// Sometimes the device ignores the locale set by the detox setup
// In such case we can try to close the keyboard using the english translation
try {
await element(by.label("Fine")).atIndex(0).tap();
} catch (e) {
await element(by.label("Done")).atIndex(0).tap();
}
};
1 change: 1 addition & 0 deletions ts/components/wallet/WalletHomeHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export const useWalletHomeHeaderBottomSheet = (): IOBottomSheetModal => {
const navigationListItems: ReadonlyArray<NavigationListItem> = [
{
title: I18n.t("wallet.paymentMethod"),
testId: "wallet.paymentMethod",
subtitle: I18n.t("wallet.paymentMethodDesc"),
onPress: () =>
navigateToWalletAddPaymentMethod({
Expand Down
2 changes: 1 addition & 1 deletion ts/features/bonus/cgn/__e2e__/cgn.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const activateBonusSuccess = async () => {

describe("CGN", () => {
beforeEach(async () => {
await device.reloadReactNative();
await device.launchApp({ newInstance: true });
await ensureLoggedIn();
});

Expand Down
7 changes: 1 addition & 6 deletions ts/features/bonus/cgn/components/detail/CgnUnsubscribe.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { isError, isReady } from "../../../../../common/model/RemoteValue";
import { navigateBack } from "../../../../../store/actions/navigation";
import { cgnDetails } from "../../store/actions/details";
import { IOToast } from "../../../../../components/Toast";
import { skipToastShowingDueToE2ECrash } from "./ToastPatch";

const CgnUnsubscribe = () => {
const dispatch = useIODispatch();
Expand Down Expand Up @@ -39,11 +38,7 @@ const CgnUnsubscribe = () => {
if (isReady(unsubscriptionStatus)) {
navigateBack();
dispatch(cgnDetails.request());
// This is needed to prevent a crash while running E2E tests. Showing
// the toast causes random crashes upon calling device.reloadReactNative
if (!skipToastShowingDueToE2ECrash) {
IOToast.success(I18n.t("bonus.cgn.activation.deactivate.toast"));
}
IOToast.success(I18n.t("bonus.cgn.activation.deactivate.toast"));
}
if (isError(unsubscriptionStatus) && !isFirstRender.current) {
IOToast.error(I18n.t("global.genericError"));
Expand Down
1 change: 0 additions & 1 deletion ts/features/bonus/cgn/components/detail/ToastPatch.e2e.ts

This file was deleted.

1 change: 0 additions & 1 deletion ts/features/bonus/cgn/components/detail/ToastPatch.ts

This file was deleted.

2 changes: 1 addition & 1 deletion ts/features/euCovidCert/__e2e__/euCovidCertExpired.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const learnMoreLinkTestId = "euCovidCertLearnMoreLink";

describe("EuCovidCert Expired", () => {
beforeAll(async () => {
await device.reloadReactNative();
await device.launchApp({ newInstance: true });
await ensureLoggedIn();
});

Expand Down
2 changes: 1 addition & 1 deletion ts/features/euCovidCert/__e2e__/euCovidCertRevoked.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const learnMoreLinkTestId = "euCovidCertLearnMoreLink";

describe("EuCovidCert Revoked", () => {
beforeAll(async () => {
await device.reloadReactNative();
await device.launchApp({ newInstance: true });
await ensureLoggedIn();
});

Expand Down
2 changes: 1 addition & 1 deletion ts/features/euCovidCert/__e2e__/euCovidCertValid.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const fullScreenQrCodeTestId = "fullScreenQRCode";

describe("EuCovidCert Valid", () => {
beforeAll(async () => {
await device.reloadReactNative();
await device.launchApp({ newInstance: true });
await ensureLoggedIn();
});

Expand Down
2 changes: 1 addition & 1 deletion ts/features/messages/__e2e__/messages.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ensureLoggedIn } from "../../../__e2e__/utils";

describe("Messages Screen", () => {
beforeEach(async () => {
await device.reloadReactNative();
await device.launchApp({ newInstance: true });
await ensureLoggedIn();
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { e2eWaitRenderTimeout } from "../../../../__e2e__/config";
import { ensureLoggedIn } from "../../../../__e2e__/utils";
import { closeKeyboard, ensureLoggedIn } from "../../../../__e2e__/utils";
import I18n from "../../../../i18n";

describe("Credit Card onboarding", () => {
beforeEach(async () => {
await device.reloadReactNative();
await device.launchApp({ newInstance: true });
await ensureLoggedIn();
});

Expand All @@ -24,12 +24,12 @@ describe("Credit Card onboarding", () => {
// Button "+ Add"
await element(by.id("walletAddNewPaymentMethodTestId")).tap();

await waitFor(element(by.text(I18n.t("wallet.paymentMethod"))))
await waitFor(element(by.id("wallet.paymentMethod")))
.toBeVisible()
.withTimeout(e2eWaitRenderTimeout);

// Add payment method listItem in bottomSheet
await element(by.text(I18n.t("wallet.paymentMethod"))).tap();
await element(by.id("wallet.paymentMethod")).tap();

await waitFor(element(by.text(I18n.t("wallet.methods.card.name"))))
.toBeVisible()
Expand All @@ -51,7 +51,7 @@ describe("Credit Card onboarding", () => {
await element(by.id("securityCodeInputMask")).typeText("123");

// Close the keyboard
await element(by.label("Fine")).atIndex(0).tap();
await closeKeyboard();
await element(by.text(I18n.t("global.buttons.continue"))).tap();

await waitFor(element(by.id("saveOrContinueButton")))
Expand Down
36 changes: 33 additions & 3 deletions ts/features/walletV3/details/screens/WalletDetailsScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import * as React from "react";
import { RouteProp, useRoute } from "@react-navigation/native";
import { RouteProp, useNavigation, useRoute } from "@react-navigation/native";
import { useDispatch } from "react-redux";
import { IOLogoPaymentExtType } from "@pagopa/io-app-design-system";

import * as O from "fp-ts/lib/Option";
import { pipe } from "fp-ts/lib/function";
import LoadingSpinnerOverlay from "../../../../components/LoadingSpinnerOverlay";
import WorkunitGenericFailure from "../../../../components/error/WorkunitGenericFailure";
import { PaymentCardBig } from "../../../../components/ui/cards/payment/PaymentCardBig";
import { useIOSelector } from "../../../../store/hooks";
import { idPayAreInitiativesFromInstrumentLoadingSelector } from "../../../idpay/wallet/store/reducers";
Expand All @@ -22,6 +21,12 @@ import {
import { walletDetailsGetInstrument } from "../store/actions";
import { UIWalletInfoDetails } from "../types/UIWalletInfoDetails";
import { getDateFromExpiryDate } from "../../../../utils/dates";
import { OperationResultScreenContent } from "../../../../components/screens/OperationResultScreenContent";
import I18n from "../../../../i18n";
import {
AppParamsList,
IOStackNavigationProp
} from "../../../../navigation/params/AppParamsList";

export type WalletDetailsScreenNavigationParams = Readonly<{
walletId: string;
Expand Down Expand Up @@ -71,6 +76,7 @@ const generateCardHeaderTitle = (details?: UIWalletInfoDetails) => {
*/
const WalletDetailsScreen = () => {
const route = useRoute<WalletDetailsScreenRouteProps>();
const navigation = useNavigation<IOStackNavigationProp<AppParamsList>>();
const dispatch = useDispatch();
const { walletId } = route.params;
const walletDetails = useIOSelector(walletDetailsInstrumentSelector);
Expand All @@ -82,6 +88,30 @@ const WalletDetailsScreen = () => {
idPayAreInitiativesFromInstrumentLoadingSelector
);

const WalletDetailsGenericFailure = () => (
<OperationResultScreenContent
title={I18n.t("wallet.methodDetails.error.title")}
subtitle={I18n.t("wallet.methodDetails.error.subtitle")}
pictogram="umbrellaNew"
action={{
label: I18n.t("wallet.methodDetails.error.primaryButton"),
accessibilityLabel: I18n.t("wallet.methodDetails.error.primaryButton"),
onPress: () => navigation.pop()
}}
secondaryAction={{
label: I18n.t("wallet.methodDetails.error.secondaryButton"),
accessibilityLabel: I18n.t(
"wallet.methodDetails.error.secondaryButton"
),
onPress: handleOnRetry
}}
/>
);

const handleOnRetry = () => {
dispatch(walletDetailsGetInstrument.request({ walletId }));
};

React.useEffect(() => {
dispatch(walletDetailsGetInstrument.request({ walletId }));
}, [walletId, dispatch]);
Expand Down Expand Up @@ -122,7 +152,7 @@ const WalletDetailsScreen = () => {
</LoadingSpinnerOverlay>
);
} else if (isErrorWalletDetails) {
return <WorkunitGenericFailure />;
return <WalletDetailsGenericFailure />;
}
return null;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ import { formatNumberCentsToAmount } from "../../../../utils/stringBuilder";
import { WalletPaymentFeebackBanner } from "../components/WalletPaymentFeedbackBanner";
import { usePaymentFailureSupportModal } from "../hooks/usePaymentFailureSupportModal";
import { WalletPaymentParamsList } from "../navigation/params";
import { walletPaymentDetailsSelector } from "../store/selectors";
import {
walletPaymentDetailsSelector,
walletPaymentStartRouteSelector
} from "../store/selectors";
import {
WalletPaymentOutcome,
WalletPaymentOutcomeEnum
Expand All @@ -38,6 +41,7 @@ const WalletPaymentOutcomeScreen = () => {

const navigation = useNavigation<IOStackNavigationProp<AppParamsList>>();
const paymentDetailsPot = useIOSelector(walletPaymentDetailsSelector);
const paymentStartRoute = useIOSelector(walletPaymentStartRouteSelector);

const supportModal = usePaymentFailureSupportModal({
outcome
Expand All @@ -55,6 +59,12 @@ const WalletPaymentOutcomeScreen = () => {
};

const handleClose = () => {
if (paymentStartRoute) {
navigation.navigate(paymentStartRoute.routeName, {
screen: paymentStartRoute.routeKey
});
return;
}
navigation.popToTop();
navigation.pop();
};
Expand Down
4 changes: 4 additions & 0 deletions ts/features/walletV3/payment/store/actions/orchestration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import { ActionType, createStandardAction } from "typesafe-actions";
import { Bundle } from "../../../../../../definitions/pagopa/ecommerce/Bundle";
import { WalletInfo } from "../../../../../../definitions/pagopa/walletv3/WalletInfo";

/**
* Action to initialize the state of a payment, optionally you can specify the route to go back to
* after the payment is completed or cancelled (default is the popToTop route)
*/
export const walletPaymentInitState = createStandardAction(
"WALLET_PAYMENT_INIT_STATE"
)();
Expand Down
25 changes: 24 additions & 1 deletion ts/features/walletV3/payment/store/reducers/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import _ from "lodash";
import * as pot from "@pagopa/ts-commons/lib/pot";
import * as O from "fp-ts/lib/Option";
import { NavigatorScreenParams } from "@react-navigation/native";
import { getType } from "typesafe-actions";
import { pipe } from "fp-ts/lib/function";
import { sequenceS } from "fp-ts/lib/Apply";
import { Bundle } from "../../../../../../definitions/pagopa/ecommerce/Bundle";
import { NewTransactionResponse } from "../../../../../../definitions/pagopa/ecommerce/NewTransactionResponse";
import { PaymentRequestsGetResponse } from "../../../../../../definitions/pagopa/ecommerce/PaymentRequestsGetResponse";
Expand All @@ -27,6 +30,8 @@ import {
import { WalletInfo } from "../../../../../../definitions/pagopa/walletv3/WalletInfo";
import { WalletPaymentFailure } from "../../types/failure";
import { RptId } from "../../../../../../definitions/pagopa/ecommerce/RptId";
import NavigationService from "../../../../../navigation/NavigationService";
import { AppParamsList } from "../../../../../navigation/params/AppParamsList";

export type WalletPaymentState = {
rptId?: RptId;
Expand All @@ -44,6 +49,10 @@ export type WalletPaymentState = {
NetworkError | WalletPaymentFailure
>;
authorizationUrl: pot.Pot<string, NetworkError>;
startRoute?: {
routeName: keyof AppParamsList;
routeKey: keyof NavigatorScreenParams<AppParamsList>["screen"];
};
};

const INITIAL_STATE: WalletPaymentState = {
Expand All @@ -64,7 +73,21 @@ const reducer = (
): WalletPaymentState => {
switch (action.type) {
case getType(walletPaymentInitState):
return INITIAL_STATE;
const startRoute = pipe(
sequenceS(O.Monad)({
routeName: O.fromNullable(
NavigationService.getCurrentRouteName() as keyof AppParamsList
),
routeKey: O.fromNullable(
NavigationService.getCurrentRouteKey() as keyof NavigatorScreenParams<AppParamsList>["screen"]
)
}),
O.toUndefined
);
return {
...INITIAL_STATE,
startRoute
};

// Payment verification and details
case getType(walletPaymentGetDetails.request):
Expand Down
5 changes: 5 additions & 0 deletions ts/features/walletV3/payment/store/selectors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,8 @@ export const walletPaymentAuthorizationUrlSelector = createSelector(
selectWalletPayment,
state => state.authorizationUrl
);

export const walletPaymentStartRouteSelector = createSelector(
selectWalletPayment,
state => state.startRoute
);

0 comments on commit aad36b3

Please sign in to comment.