From a84b02d33ce662783be1d3b2427d0fa4c8dc9567 Mon Sep 17 00:00:00 2001 From: ChrisMattew Date: Mon, 16 Dec 2024 14:09:30 +0100 Subject: [PATCH 1/4] fix(CieIdNotInstalled): handle openUrl error with toast message --- locales/en/index.yml | 1 + locales/it/index.yml | 1 + ts/features/cie/components/CieIdNotInstalled.tsx | 6 +++++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/locales/en/index.yml b/locales/en/index.yml index 0351bdc8b29..0d8c22f79bb 100644 --- a/locales/en/index.yml +++ b/locales/en/index.yml @@ -752,6 +752,7 @@ authentication: title: We can't find the CieID app description: To login, you must have the app installed on your device. primary_action_label: Get the app + link_error: Non siamo riusciti a indirizzarti allo store. Aprilo manualmente e cerca CieID cie: genericTitle: Login with CIE cie: CIE diff --git a/locales/it/index.yml b/locales/it/index.yml index 38adc05833c..ff51fdfcad6 100644 --- a/locales/it/index.yml +++ b/locales/it/index.yml @@ -752,6 +752,7 @@ authentication: title: Non riusciamo a trovare l'app CieID description: Per accedere, devi avere l'app installata sul tuo dispositivo. primary_action_label: Scarica CieID + link_error: Non siamo riusciti a indirizzarti allo store. Aprilo manualmente e cerca CieID cie: genericTitle: Entra con CIE cie: CIE diff --git a/ts/features/cie/components/CieIdNotInstalled.tsx b/ts/features/cie/components/CieIdNotInstalled.tsx index aec42c74e56..88b01dfce7f 100644 --- a/ts/features/cie/components/CieIdNotInstalled.tsx +++ b/ts/features/cie/components/CieIdNotInstalled.tsx @@ -1,5 +1,6 @@ import React from "react"; import { Linking, Platform } from "react-native"; +import { useIOToast } from "@pagopa/io-app-design-system"; import { OperationResultScreenContent } from "../../../components/screens/OperationResultScreenContent"; import { useIONavigation } from "../../../navigation/params/AppParamsList"; import I18n from "../../../i18n"; @@ -17,6 +18,7 @@ export type CieIdNotInstalledProps = { const CieIdNotInstalled = ({ isUat }: CieIdNotInstalledProps) => { const { popToTop } = useIONavigation(); + const { error } = useIOToast(); return ( { android: isUat ? CIE_ID_ANDROID_COLL_LINK : CIE_ID_ANDROID_LINK, default: "" }) - ); + ).catch(() => { + error(I18n.t("authentication.cie_id.cie_not_installed.link_error")); + }); } }} secondaryAction={{ From 625c3e650f4f3b6741509b1e691c564b00fe135a Mon Sep 17 00:00:00 2001 From: ChrisMattew Date: Mon, 16 Dec 2024 15:26:05 +0100 Subject: [PATCH 2/4] chore(CieIdNotInstalled): update tests --- .../cie/__tests__/CieIdNotInstalled.test.tsx | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/ts/features/cie/__tests__/CieIdNotInstalled.test.tsx b/ts/features/cie/__tests__/CieIdNotInstalled.test.tsx index 1d5136c324d..63355d2ff00 100644 --- a/ts/features/cie/__tests__/CieIdNotInstalled.test.tsx +++ b/ts/features/cie/__tests__/CieIdNotInstalled.test.tsx @@ -1,4 +1,4 @@ -import { Linking, Platform } from "react-native"; +import { Platform } from "react-native"; import { fireEvent, render } from "@testing-library/react-native"; import React from "react"; import CieIdNotInstalled, { @@ -10,6 +10,7 @@ import CieIdNotInstalled, { const UAT_ENV_ENABLE_STATES = [true, false]; const mockPopToTop = jest.fn(); +const mockOpenUrl = jest.fn((url: string) => Promise.resolve(url)); jest.mock("@react-navigation/native", () => ({ ...jest.requireActual("@react-navigation/native"), @@ -17,6 +18,9 @@ jest.mock("@react-navigation/native", () => ({ popToTop: mockPopToTop }) })); +jest.mock("react-native/Libraries/Linking/Linking", () => ({ + openURL: mockOpenUrl +})); describe(CieIdNotInstalled, () => { afterEach(jest.clearAllMocks); @@ -28,15 +32,13 @@ describe(CieIdNotInstalled, () => { describe("Behavior on iOS", () => { UAT_ENV_ENABLE_STATES.forEach(uatState => { - it("Should open CIE_ID_IOS_LINK", () => { + it("Should open CIE_ID_IOS_LINK", async () => { const { getByTestId } = render(); const openStore = getByTestId("cie-id-not-installed-open-store"); fireEvent.press(openStore); - expect(jest.spyOn(Linking, "openURL")).toHaveBeenCalledWith( - CIE_ID_IOS_LINK - ); + expect(mockOpenUrl).toHaveBeenCalledWith(CIE_ID_IOS_LINK); expect(mockPopToTop).not.toHaveBeenCalled(); }); }); @@ -50,9 +52,7 @@ describe(CieIdNotInstalled, () => { const openStore = getByTestId("cie-id-not-installed-open-store"); fireEvent.press(openStore); - expect(jest.spyOn(Linking, "openURL")).toHaveBeenCalledWith( - CIE_ID_ANDROID_LINK - ); + expect(mockOpenUrl).toHaveBeenCalledWith(CIE_ID_ANDROID_LINK); expect(mockPopToTop).not.toHaveBeenCalled(); }); it("Should open CIE_ID_ANDROID_COLL_LINK", () => { @@ -63,9 +63,7 @@ describe(CieIdNotInstalled, () => { const openStore = getByTestId("cie-id-not-installed-open-store"); fireEvent.press(openStore); - expect(jest.spyOn(Linking, "openURL")).toHaveBeenCalledWith( - CIE_ID_ANDROID_COLL_LINK - ); + expect(mockOpenUrl).toHaveBeenCalledWith(CIE_ID_ANDROID_COLL_LINK); expect(mockPopToTop).not.toHaveBeenCalled(); }); }); @@ -76,7 +74,7 @@ describe(CieIdNotInstalled, () => { const popToTop = getByTestId("cie-id-not-installed-pop-to-top"); fireEvent.press(popToTop); - expect(jest.spyOn(Linking, "openURL")).not.toHaveBeenCalled(); + expect(mockOpenUrl).not.toHaveBeenCalled(); expect(mockPopToTop).toHaveBeenCalledTimes(1); }); }); From f92b6ed6ed318fdcab2591231764b145193cdd0e Mon Sep 17 00:00:00 2001 From: mariateresaventura <90319761+mariateresaventura@users.noreply.github.com> Date: Mon, 16 Dec 2024 15:36:19 +0100 Subject: [PATCH 3/4] Update index.yml --- locales/en/index.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/en/index.yml b/locales/en/index.yml index 0d8c22f79bb..fa4381f773d 100644 --- a/locales/en/index.yml +++ b/locales/en/index.yml @@ -752,7 +752,7 @@ authentication: title: We can't find the CieID app description: To login, you must have the app installed on your device. primary_action_label: Get the app - link_error: Non siamo riusciti a indirizzarti allo store. Aprilo manualmente e cerca CieID + link_error: We could not direct you to the store. Open it manually and search for CieID cie: genericTitle: Login with CIE cie: CIE From 55487ba318bc298a7700f72e2cd3dbf9b06d9e9f Mon Sep 17 00:00:00 2001 From: ChrisMattew Date: Mon, 16 Dec 2024 15:45:44 +0100 Subject: [PATCH 4/4] refactor(CieIdNotInstalled): replace Linking.openURL with the openWebUrl function --- .../cie/__tests__/CieIdNotInstalled.test.tsx | 19 ++++++++++++------- .../cie/components/CieIdNotInstalled.tsx | 16 ++++++++++------ 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/ts/features/cie/__tests__/CieIdNotInstalled.test.tsx b/ts/features/cie/__tests__/CieIdNotInstalled.test.tsx index 63355d2ff00..23ac3e19dd3 100644 --- a/ts/features/cie/__tests__/CieIdNotInstalled.test.tsx +++ b/ts/features/cie/__tests__/CieIdNotInstalled.test.tsx @@ -6,11 +6,13 @@ import CieIdNotInstalled, { CIE_ID_ANDROID_LINK, CIE_ID_IOS_LINK } from "../components/CieIdNotInstalled"; +import * as urlUtils from "../../../utils/url"; const UAT_ENV_ENABLE_STATES = [true, false]; const mockPopToTop = jest.fn(); -const mockOpenUrl = jest.fn((url: string) => Promise.resolve(url)); +const mockOpenUrl = jest.spyOn(urlUtils, "openWebUrl"); +const anyFunction = expect.any(Function); jest.mock("@react-navigation/native", () => ({ ...jest.requireActual("@react-navigation/native"), @@ -18,9 +20,6 @@ jest.mock("@react-navigation/native", () => ({ popToTop: mockPopToTop }) })); -jest.mock("react-native/Libraries/Linking/Linking", () => ({ - openURL: mockOpenUrl -})); describe(CieIdNotInstalled, () => { afterEach(jest.clearAllMocks); @@ -38,7 +37,7 @@ describe(CieIdNotInstalled, () => { const openStore = getByTestId("cie-id-not-installed-open-store"); fireEvent.press(openStore); - expect(mockOpenUrl).toHaveBeenCalledWith(CIE_ID_IOS_LINK); + expect(mockOpenUrl).toHaveBeenCalledWith(CIE_ID_IOS_LINK, anyFunction); expect(mockPopToTop).not.toHaveBeenCalled(); }); }); @@ -52,7 +51,10 @@ describe(CieIdNotInstalled, () => { const openStore = getByTestId("cie-id-not-installed-open-store"); fireEvent.press(openStore); - expect(mockOpenUrl).toHaveBeenCalledWith(CIE_ID_ANDROID_LINK); + expect(mockOpenUrl).toHaveBeenCalledWith( + CIE_ID_ANDROID_LINK, + anyFunction + ); expect(mockPopToTop).not.toHaveBeenCalled(); }); it("Should open CIE_ID_ANDROID_COLL_LINK", () => { @@ -63,7 +65,10 @@ describe(CieIdNotInstalled, () => { const openStore = getByTestId("cie-id-not-installed-open-store"); fireEvent.press(openStore); - expect(mockOpenUrl).toHaveBeenCalledWith(CIE_ID_ANDROID_COLL_LINK); + expect(mockOpenUrl).toHaveBeenCalledWith( + CIE_ID_ANDROID_COLL_LINK, + anyFunction + ); expect(mockPopToTop).not.toHaveBeenCalled(); }); }); diff --git a/ts/features/cie/components/CieIdNotInstalled.tsx b/ts/features/cie/components/CieIdNotInstalled.tsx index 88b01dfce7f..577f548fe9b 100644 --- a/ts/features/cie/components/CieIdNotInstalled.tsx +++ b/ts/features/cie/components/CieIdNotInstalled.tsx @@ -1,10 +1,11 @@ import React from "react"; -import { Linking, Platform } from "react-native"; +import { Platform } from "react-native"; import { useIOToast } from "@pagopa/io-app-design-system"; import { OperationResultScreenContent } from "../../../components/screens/OperationResultScreenContent"; import { useIONavigation } from "../../../navigation/params/AppParamsList"; import I18n from "../../../i18n"; import { trackCieIdNotInstalledDownloadAction } from "../analytics"; +import { openWebUrl } from "../../../utils/url"; export const CIE_ID_IOS_LINK = "https://apps.apple.com/it/app/cieid/id1504644677"; @@ -32,15 +33,18 @@ const CieIdNotInstalled = ({ isUat }: CieIdNotInstalledProps) => { ), onPress: () => { void trackCieIdNotInstalledDownloadAction(); - void Linking.openURL( + openWebUrl( Platform.select({ ios: CIE_ID_IOS_LINK, android: isUat ? CIE_ID_ANDROID_COLL_LINK : CIE_ID_ANDROID_LINK, default: "" - }) - ).catch(() => { - error(I18n.t("authentication.cie_id.cie_not_installed.link_error")); - }); + }), + () => { + error( + I18n.t("authentication.cie_id.cie_not_installed.link_error") + ); + } + ); } }} secondaryAction={{