diff --git a/.env.local b/.env.local index 15b6ff0d3a8..ead00523583 100644 --- a/.env.local +++ b/.env.local @@ -97,6 +97,4 @@ ITW_BYPASS_IDENTITY_MATCH=YES # Use the test environment for the IDP hint for both CIE and SPID ITW_IDP_HINT_TEST=YES # IPZS Privacy Policy URL -ITW_IPZS_PRIVACY_URL='https://io.italia.it/informativa-ipzs' -# ITW Documents on IO URL -ITW_DOCUMENTS_ON_IO_URL='https://io.italia.it/documenti-su-io' +ITW_IPZS_PRIVACY_URL='https://io.italia.it/informativa-ipzs' \ No newline at end of file diff --git a/.env.production b/.env.production index 0d09f9f56db..6d01eebd819 100644 --- a/.env.production +++ b/.env.production @@ -97,6 +97,4 @@ ITW_BYPASS_IDENTITY_MATCH=NO # Use the test environment for the IDP hint for both CIE and SPID ITW_IDP_HINT_TEST=NO # IPZS Privacy Policy URL -ITW_IPZS_PRIVACY_URL='https://io.italia.it/informativa-ipzs' -# ITW Documents on IO URL -ITW_DOCUMENTS_ON_IO_URL='https://io.italia.it/documenti-su-io' +ITW_IPZS_PRIVACY_URL='https://io.italia.it/informativa-ipzs' \ No newline at end of file diff --git a/locales/en/index.yml b/locales/en/index.yml index 8c2b33fac22..a10530a05a0 100644 --- a/locales/en/index.yml +++ b/locales/en/index.yml @@ -3555,6 +3555,20 @@ features: title: Dicci cosa ne pensi content: Raccontaci la tua esperienza con la funzionalità Documenti su IO. action: Inizia + walletInstanceRevoked: + alert: + cta: Scopri di più + closeButton: Chiudi + closeButtonAlt: Ho capito + revokedByWalletProvider: + title: Documenti su IO è stata disattivata + content: Per verificare i requisiti richiesti per continuare a usare la funzionalità sul tuo dispositivo, premi "Scopri di più". + newWalletInstanceCreated: + title: Documenti su IO è stata disattivata su questo dispositivo + content: Puoi usare i tuoi documenti su IO su un solo dispositivo alla volta per ragioni di sicurezza. + revokedByUser: + title: Hai disattivato Documenti su IO + content: Se cambi idea, potrai riattivare Documenti su IO in futuro. support: ticketList: noTicket: diff --git a/locales/it/index.yml b/locales/it/index.yml index 640a6ab0a72..3a5cbe020ce 100644 --- a/locales/it/index.yml +++ b/locales/it/index.yml @@ -3555,6 +3555,20 @@ features: title: Dicci cosa ne pensi content: Raccontaci la tua esperienza con la funzionalità Documenti su IO. action: Inizia + walletInstanceRevoked: + alert: + cta: Scopri di più + closeButton: Chiudi + closeButtonAlt: Ho capito + revokedByWalletProvider: + title: Documenti su IO è stata disattivata + content: Per verificare i requisiti richiesti per continuare a usare la funzionalità sul tuo dispositivo, premi "Scopri di più". + newWalletInstanceCreated: + title: Documenti su IO è stata disattivata su questo dispositivo + content: Puoi usare i tuoi documenti su IO su un solo dispositivo alla volta per ragioni di sicurezza. + revokedByUser: + title: Hai disattivato Documenti su IO + content: Se cambi idea, potrai riattivare Documenti su IO in futuro. support: ticketList: noTicket: diff --git a/ts/config.ts b/ts/config.ts index fa847bbb3ad..505771f19eb 100644 --- a/ts/config.ts +++ b/ts/config.ts @@ -252,8 +252,3 @@ export const itwIpzsPrivacyUrl: string = pipe( t.string.decode, E.getOrElse(() => "https://io.italia.it/informativa-ipzs") ); -export const itwDocumentsOnIOUrl: string = pipe( - Config.ITW_DOCUMENTS_ON_IO_URL, - t.string.decode, - E.getOrElse(() => "https://io.italia.it/documenti-su-io") -); diff --git a/ts/features/common/store/reducers/__tests__/__snapshots__/index.test.ts.snap b/ts/features/common/store/reducers/__tests__/__snapshots__/index.test.ts.snap index 527cdcd64ce..81dd7b4bcb0 100644 --- a/ts/features/common/store/reducers/__tests__/__snapshots__/index.test.ts.snap +++ b/ts/features/common/store/reducers/__tests__/__snapshots__/index.test.ts.snap @@ -132,6 +132,7 @@ exports[`featuresPersistor should match snapshot 1`] = ` }, "walletInstance": { "attestation": undefined, + "status": undefined, }, }, "landingBanners": { diff --git a/ts/features/itwallet/common/store/reducers/__tests__/__snapshots__/index.test.ts.snap b/ts/features/itwallet/common/store/reducers/__tests__/__snapshots__/index.test.ts.snap index 7fb4ec75a32..e6f11fb8d17 100644 --- a/ts/features/itwallet/common/store/reducers/__tests__/__snapshots__/index.test.ts.snap +++ b/ts/features/itwallet/common/store/reducers/__tests__/__snapshots__/index.test.ts.snap @@ -19,6 +19,7 @@ exports[`itWalletReducer should match snapshot [if this test fails, remember to }, "walletInstance": { "attestation": undefined, + "status": undefined, }, } `; diff --git a/ts/features/itwallet/common/utils/itwTypesUtils.ts b/ts/features/itwallet/common/utils/itwTypesUtils.ts index fe04304f663..3fab058e345 100644 --- a/ts/features/itwallet/common/utils/itwTypesUtils.ts +++ b/ts/features/itwallet/common/utils/itwTypesUtils.ts @@ -1,4 +1,8 @@ -import { Credential, Trust } from "@pagopa/io-react-native-wallet"; +import { + Credential, + Trust, + WalletInstance +} from "@pagopa/io-react-native-wallet"; /** * Alias type for the return type of the start issuance flow operation. @@ -43,6 +47,19 @@ export type ParsedStatusAttestation = Awaited< ReturnType >["parsedStatusAttestation"]["payload"]; +/** + * Alias for the WalletInstanceStatus type + */ +export type WalletInstanceStatus = Awaited< + ReturnType +>; + +/** + * Alias for the WalletInstanceRevocationReason type + */ +export type WalletInstanceRevocationReason = + WalletInstanceStatus["revocation_reason"]; + export type StoredStatusAttestation = | { credentialStatus: "valid"; diff --git a/ts/features/itwallet/lifecycle/saga/__tests__/checkWalletInstanceStateSaga.test.ts b/ts/features/itwallet/lifecycle/saga/__tests__/checkWalletInstanceStateSaga.test.ts index fdf253d364c..574090dea19 100644 --- a/ts/features/itwallet/lifecycle/saga/__tests__/checkWalletInstanceStateSaga.test.ts +++ b/ts/features/itwallet/lifecycle/saga/__tests__/checkWalletInstanceStateSaga.test.ts @@ -12,9 +12,9 @@ import { getWalletInstanceStatus } from "../../../common/utils/itwAttestationUti import { StoredCredential } from "../../../common/utils/itwTypesUtils"; import { sessionTokenSelector } from "../../../../../store/reducers/authentication"; import { handleWalletInstanceResetSaga } from "../handleWalletInstanceResetSaga"; -import { itwIsWalletInstanceAttestationValidSelector } from "../../../walletInstance/store/reducers"; import { ensureIntegrityServiceIsReady } from "../../../common/utils/itwIntegrityUtils"; import { itwIntegrityServiceReadySelector } from "../../../issuance/store/selectors"; +import { itwIsWalletInstanceAttestationValidSelector } from "../../../walletInstance/store/selectors"; jest.mock("@pagopa/io-react-native-crypto", () => ({ deleteKey: jest.fn diff --git a/ts/features/itwallet/lifecycle/saga/checkWalletInstanceStateSaga.ts b/ts/features/itwallet/lifecycle/saga/checkWalletInstanceStateSaga.ts index 779a11a929e..07d6dc12719 100644 --- a/ts/features/itwallet/lifecycle/saga/checkWalletInstanceStateSaga.ts +++ b/ts/features/itwallet/lifecycle/saga/checkWalletInstanceStateSaga.ts @@ -8,6 +8,7 @@ import { ensureIntegrityServiceIsReady } from "../../common/utils/itwIntegrityUt import { itwIntegrityKeyTagSelector } from "../../issuance/store/selectors"; import { itwLifecycleIsOperationalOrValid } from "../store/selectors"; import { itwIntegritySetServiceIsReady } from "../../issuance/store/actions"; +import { itwUpdateWalletInstanceStatus } from "../../walletInstance/store/actions"; import { handleWalletInstanceResetSaga } from "./handleWalletInstanceResetSaga"; export function* getStatusOrResetWalletInstance(integrityKeyTag: string) { @@ -23,6 +24,9 @@ export function* getStatusOrResetWalletInstance(integrityKeyTag: string) { if (walletInstanceStatus.is_revoked) { yield* call(handleWalletInstanceResetSaga); } + + // Update wallet instance status + yield* put(itwUpdateWalletInstanceStatus(walletInstanceStatus)); } /** diff --git a/ts/features/itwallet/machine/credential/actions.ts b/ts/features/itwallet/machine/credential/actions.ts index f5f1eaf9990..ee43befc3b9 100644 --- a/ts/features/itwallet/machine/credential/actions.ts +++ b/ts/features/itwallet/machine/credential/actions.ts @@ -19,7 +19,7 @@ import { import { itwCredentialsStore } from "../../credentials/store/actions"; import { ITW_ROUTES } from "../../navigation/routes"; import { itwWalletInstanceAttestationStore } from "../../walletInstance/store/actions"; -import { itwWalletInstanceAttestationSelector } from "../../walletInstance/store/reducers"; +import { itwWalletInstanceAttestationSelector } from "../../walletInstance/store/selectors"; import { Context } from "./context"; import { CredentialIssuanceEvents } from "./events"; diff --git a/ts/features/itwallet/machine/eid/actions.ts b/ts/features/itwallet/machine/eid/actions.ts index d7581cc2b7a..9b84d7a1e23 100644 --- a/ts/features/itwallet/machine/eid/actions.ts +++ b/ts/features/itwallet/machine/eid/actions.ts @@ -22,8 +22,8 @@ import { trackSaveCredentialSuccess, updateITWStatusAndIDProperties } from "../../analytics"; -import { itwWalletInstanceAttestationSelector } from "../../walletInstance/store/reducers"; import { itwIntegrityKeyTagSelector } from "../../issuance/store/selectors"; +import { itwWalletInstanceAttestationSelector } from "../../walletInstance/store/selectors"; import { Context } from "./context"; import { EidIssuanceEvents } from "./events"; diff --git a/ts/features/itwallet/trustmark/machine/actions.ts b/ts/features/itwallet/trustmark/machine/actions.ts index 929d2d32104..145a4ba00fd 100644 --- a/ts/features/itwallet/trustmark/machine/actions.ts +++ b/ts/features/itwallet/trustmark/machine/actions.ts @@ -4,7 +4,7 @@ import { useIONavigation } from "../../../../navigation/params/AppParamsList"; import { checkCurrentSession } from "../../../../store/actions/authentication"; import { useIOStore } from "../../../../store/hooks"; import { itwCredentialByTypeSelector } from "../../credentials/store/selectors"; -import { itwWalletInstanceAttestationSelector } from "../../walletInstance/store/reducers"; +import { itwWalletInstanceAttestationSelector } from "../../walletInstance/store/selectors"; import { Context } from "./context"; export const createItwTrustmarkActionsImplementation = ( diff --git a/ts/features/itwallet/walletInstance/hook/useItwWalletInstanceRevocationAlert.ts b/ts/features/itwallet/walletInstance/hook/useItwWalletInstanceRevocationAlert.ts new file mode 100644 index 00000000000..15698a1baf2 --- /dev/null +++ b/ts/features/itwallet/walletInstance/hook/useItwWalletInstanceRevocationAlert.ts @@ -0,0 +1,101 @@ +import { Alert } from "react-native"; +import { useCallback } from "react"; +import I18n from "../../../../i18n"; +import { WalletInstanceRevocationReason } from "../../common/utils/itwTypesUtils"; +import { useIODispatch, useIOSelector } from "../../../../store/hooks"; +import { itwWalletInstanceStatusSelector } from "../store/selectors"; +import { useOnFirstRender } from "../../../../utils/hooks/useOnFirstRender"; +import { itwUpdateWalletInstanceStatus } from "../store/actions"; +import { openWebUrl } from "../../../../utils/url"; + +const closeButtonText = I18n.t( + "features.itWallet.walletInstanceRevoked.alert.closeButton" +); +const alertCtaText = I18n.t( + "features.itWallet.walletInstanceRevoked.alert.cta" +); + +const itwMinIntegrityReqUrl = "https://io.italia.it/documenti-su-io/faq/#n1_12"; +const itwDocsOnIOMultipleDevicesUrl = + "https://io.italia.it/documenti-su-io/faq/#n1_14"; + +/** + * Hook to monitor wallet instance status and display alerts if revoked. + */ +export const useItwWalletInstanceRevocationAlert = () => { + const walletInstanceStatus = useIOSelector(itwWalletInstanceStatusSelector); + const dispatch = useIODispatch(); + + useOnFirstRender( + useCallback(() => { + if (walletInstanceStatus?.is_revoked) { + showWalletRevocationAlert(walletInstanceStatus.revocation_reason); + dispatch(itwUpdateWalletInstanceStatus(undefined)); + } + }, [walletInstanceStatus, dispatch]) + ); +}; + +/** + * Displays an alert based on the revocation reason. + */ +const showWalletRevocationAlert = ( + revocationReason?: WalletInstanceRevocationReason +) => { + switch (revocationReason) { + case "CERTIFICATE_REVOKED_BY_ISSUER": + Alert.alert( + I18n.t( + "features.itWallet.walletInstanceRevoked.alert.revokedByWalletProvider.title" + ), + I18n.t( + "features.itWallet.walletInstanceRevoked.alert.revokedByWalletProvider.content" + ), + [ + { text: closeButtonText }, + { + text: alertCtaText, + onPress: () => openWebUrl(itwMinIntegrityReqUrl) + } + ] + ); + break; + + case "NEW_WALLET_INSTANCE_CREATED": + Alert.alert( + I18n.t( + "features.itWallet.walletInstanceRevoked.alert.newWalletInstanceCreated.title" + ), + I18n.t( + "features.itWallet.walletInstanceRevoked.alert.newWalletInstanceCreated.content" + ), + [ + { text: closeButtonText }, + { + text: alertCtaText, + onPress: () => openWebUrl(itwDocsOnIOMultipleDevicesUrl) + } + ] + ); + break; + case "REVOKED_BY_USER": + Alert.alert( + I18n.t( + "features.itWallet.walletInstanceRevoked.alert.revokedByUser.title" + ), + I18n.t( + "features.itWallet.walletInstanceRevoked.alert.revokedByUser.content" + ), + [ + { + text: I18n.t( + "features.itWallet.walletInstanceRevoked.alert.closeButtonAlt" + ) + } + ] + ); + break; + default: + break; + } +}; diff --git a/ts/features/itwallet/walletInstance/store/actions/index.ts b/ts/features/itwallet/walletInstance/store/actions/index.ts index 3d0c05b05c2..cbf6db80535 100644 --- a/ts/features/itwallet/walletInstance/store/actions/index.ts +++ b/ts/features/itwallet/walletInstance/store/actions/index.ts @@ -1,4 +1,5 @@ import { ActionType, createStandardAction } from "typesafe-actions"; +import { WalletInstanceStatus } from "../../../common/utils/itwTypesUtils"; /** * This action stores the Wallet Instance Attestation @@ -7,6 +8,13 @@ export const itwWalletInstanceAttestationStore = createStandardAction( "ITW_WALLET_INSTANCE_ATTESTATION_STORE" )(); -export type ItwWalletInstanceActions = ActionType< - typeof itwWalletInstanceAttestationStore ->; +/** + * This action update the Wallet Instance Status + */ +export const itwUpdateWalletInstanceStatus = createStandardAction( + "ITW_WALLET_INSTANCE_STATUS_UPDATE" +)(); + +export type ItwWalletInstanceActions = + | ActionType + | ActionType; diff --git a/ts/features/itwallet/walletInstance/store/reducers/index.ts b/ts/features/itwallet/walletInstance/store/reducers/index.ts index 2494833ff35..778d134d4fb 100644 --- a/ts/features/itwallet/walletInstance/store/reducers/index.ts +++ b/ts/features/itwallet/walletInstance/store/reducers/index.ts @@ -1,21 +1,22 @@ -import * as O from "fp-ts/lib/Option"; -import { flow } from "fp-ts/lib/function"; import { PersistConfig, persistReducer } from "redux-persist"; -import { createSelector } from "reselect"; import { getType } from "typesafe-actions"; import { Action } from "../../../../../store/actions/types"; -import { GlobalState } from "../../../../../store/reducers/types"; import itwCreateSecureStorage from "../../../common/store/storages/itwSecureStorage"; -import { isWalletInstanceAttestationValid } from "../../../common/utils/itwAttestationUtils"; import { itwLifecycleStoresReset } from "../../../lifecycle/store/actions"; -import { itwWalletInstanceAttestationStore } from "../actions"; +import { + itwWalletInstanceAttestationStore, + itwUpdateWalletInstanceStatus +} from "../actions"; +import { WalletInstanceStatus } from "../../../common/utils/itwTypesUtils"; export type ItwWalletInstanceState = { attestation: string | undefined; + status: WalletInstanceStatus | undefined; }; export const itwWalletInstanceInitialState: ItwWalletInstanceState = { - attestation: undefined + attestation: undefined, + status: undefined }; const CURRENT_REDUX_ITW_WALLET_INSTANCE_STORE_VERSION = -1; @@ -27,10 +28,18 @@ const reducer = ( switch (action.type) { case getType(itwWalletInstanceAttestationStore): { return { + status: undefined, attestation: action.payload }; } + case getType(itwUpdateWalletInstanceStatus): { + return { + ...state, + status: action.payload + }; + } + case getType(itwLifecycleStoresReset): return { ...itwWalletInstanceInitialState }; @@ -50,16 +59,4 @@ const persistedReducer = persistReducer( reducer ); -export const itwWalletInstanceAttestationSelector = (state: GlobalState) => - state.features.itWallet.walletInstance.attestation; - -export const itwIsWalletInstanceAttestationValidSelector = createSelector( - itwWalletInstanceAttestationSelector, - flow( - O.fromNullable, - O.map(isWalletInstanceAttestationValid), - O.getOrElse(() => false) - ) -); - export default persistedReducer; diff --git a/ts/features/itwallet/walletInstance/store/selectors/index.ts b/ts/features/itwallet/walletInstance/store/selectors/index.ts new file mode 100644 index 00000000000..85a98084d61 --- /dev/null +++ b/ts/features/itwallet/walletInstance/store/selectors/index.ts @@ -0,0 +1,23 @@ +import * as O from "fp-ts/lib/Option"; +import { flow } from "fp-ts/lib/function"; +import { createSelector } from "reselect"; +import { GlobalState } from "../../../../../store/reducers/types"; +import { isWalletInstanceAttestationValid } from "../../../common/utils/itwAttestationUtils"; + +/* Selector to get the wallet instance attestation */ +export const itwWalletInstanceAttestationSelector = (state: GlobalState) => + state.features.itWallet.walletInstance.attestation; + +/* Selector to check if the attestation is valid */ +export const itwIsWalletInstanceAttestationValidSelector = createSelector( + itwWalletInstanceAttestationSelector, + flow( + O.fromNullable, + O.map(isWalletInstanceAttestationValid), + O.getOrElse(() => false) + ) +); + +/* Selector to get the wallet instance status */ +export const itwWalletInstanceStatusSelector = (state: GlobalState) => + state.features.itWallet.walletInstance.status; diff --git a/ts/features/wallet/components/WalletCardsContainer.tsx b/ts/features/wallet/components/WalletCardsContainer.tsx index 394dc54ee19..9d08e1c2a8b 100644 --- a/ts/features/wallet/components/WalletCardsContainer.tsx +++ b/ts/features/wallet/components/WalletCardsContainer.tsx @@ -28,6 +28,7 @@ import { shouldRenderWalletEmptyStateSelector } from "../store/selectors"; import { WalletCardCategoryFilter } from "../types"; +import { useItwWalletInstanceRevocationAlert } from "../../itwallet/walletInstance/hook/useItwWalletInstanceRevocationAlert"; import { WalletCardsCategoryContainer } from "./WalletCardsCategoryContainer"; import { WalletCardsCategoryRetryErrorBanner } from "./WalletCardsCategoryRetryErrorBanner"; import { WalletCardSkeleton } from "./WalletCardSkeleton"; @@ -48,6 +49,8 @@ const WalletCardsContainer = () => { shouldRenderWalletEmptyStateSelector ); + useItwWalletInstanceRevocationAlert(); + // Loading state is only displayed if there is the initial loading and there are no cards or // placeholders in the wallet const shouldRenderLoadingState = isLoading && isWalletEmpty; diff --git a/ts/features/wallet/components/__tests__/WalletCardsContainer.test.tsx b/ts/features/wallet/components/__tests__/WalletCardsContainer.test.tsx index 45aabf4fb3b..c364c9f9a4f 100644 --- a/ts/features/wallet/components/__tests__/WalletCardsContainer.test.tsx +++ b/ts/features/wallet/components/__tests__/WalletCardsContainer.test.tsx @@ -2,6 +2,7 @@ import * as O from "fp-ts/lib/Option"; import _ from "lodash"; import * as React from "react"; import configureMockStore from "redux-mock-store"; +import { Alert } from "react-native"; import ROUTES from "../../../../navigation/routes"; import { applicationChangeState } from "../../../../store/actions/application"; import { appReducer } from "../../../../store/reducers"; @@ -16,6 +17,7 @@ import { import { ItwJwtCredentialStatus } from "../../../itwallet/common/utils/itwTypesUtils"; import * as itwCredentialsSelectors from "../../../itwallet/credentials/store/selectors"; import * as itwLifecycleSelectors from "../../../itwallet/lifecycle/store/selectors"; +import * as itwWalletInstanceSelectors from "../../../itwallet/walletInstance/store/selectors"; import { WalletCardsState } from "../../store/reducers/cards"; import * as walletSelectors from "../../store/selectors"; import { WalletCard } from "../../types"; @@ -24,7 +26,9 @@ import { OtherWalletCardsContainer, WalletCardsContainer } from "../WalletCardsContainer"; +import I18n from "../../../../i18n"; +jest.spyOn(Alert, "alert"); jest.mock("react-native-reanimated", () => ({ ...require("react-native-reanimated/mock"), useReducedMotion: jest.fn, @@ -357,6 +361,112 @@ describe("OtherWalletCardsContainer", () => { expect(queryByTestId(`walletCardTestID_cgn_cgn_3`)).not.toBeNull(); expect(queryByTestId(`walletCardTestID_itw_placeholder_4`)).not.toBeNull(); }); + + it("should not show alert if not revoked", () => { + jest + .spyOn(itwWalletInstanceSelectors, "itwWalletInstanceStatusSelector") + .mockImplementation(() => ({ + id: "39cc62ab-1df0-4a9d-974d-4c58173a1750", + is_revoked: false, + revocation_reason: undefined + })); + + renderComponent(WalletCardsContainer); + + expect(Alert.alert).not.toHaveBeenCalled(); + }); + + it("should show alert for NEW_WALLET_INSTANCE_CREATED", () => { + jest + .spyOn(itwWalletInstanceSelectors, "itwWalletInstanceStatusSelector") + .mockImplementation(() => ({ + id: "39cc62ab-1df0-4a9d-974d-4c58173a1750", + is_revoked: true, + revocation_reason: "NEW_WALLET_INSTANCE_CREATED" + })); + + renderComponent(WalletCardsContainer); + + expect(Alert.alert).toHaveBeenCalledWith( + I18n.t( + "features.itWallet.walletInstanceRevoked.alert.newWalletInstanceCreated.title" + ), + I18n.t( + "features.itWallet.walletInstanceRevoked.alert.newWalletInstanceCreated.content" + ), + [ + { + text: I18n.t( + "features.itWallet.walletInstanceRevoked.alert.closeButton" + ) + }, + { + text: I18n.t("features.itWallet.walletInstanceRevoked.alert.cta"), + onPress: expect.any(Function) + } + ] + ); + }); + + it("should show alert for CERTIFICATE_REVOKED_BY_ISSUER", () => { + jest + .spyOn(itwWalletInstanceSelectors, "itwWalletInstanceStatusSelector") + .mockImplementation(() => ({ + id: "39cc62ab-1df0-4a9d-974d-4c58173a1750", + is_revoked: true, + revocation_reason: "CERTIFICATE_REVOKED_BY_ISSUER" + })); + + renderComponent(WalletCardsContainer); + + expect(Alert.alert).toHaveBeenCalledWith( + I18n.t( + "features.itWallet.walletInstanceRevoked.alert.revokedByWalletProvider.title" + ), + I18n.t( + "features.itWallet.walletInstanceRevoked.alert.revokedByWalletProvider.content" + ), + [ + { + text: I18n.t( + "features.itWallet.walletInstanceRevoked.alert.closeButton" + ) + }, + { + text: I18n.t("features.itWallet.walletInstanceRevoked.alert.cta"), + onPress: expect.any(Function) + } + ] + ); + }); + + it("should show alert for REVOKED_BY_USER", () => { + jest + .spyOn(itwWalletInstanceSelectors, "itwWalletInstanceStatusSelector") + .mockImplementation(() => ({ + id: "39cc62ab-1df0-4a9d-974d-4c58173a1750", + is_revoked: true, + revocation_reason: "REVOKED_BY_USER" + })); + + renderComponent(WalletCardsContainer); + + expect(Alert.alert).toHaveBeenCalledWith( + I18n.t( + "features.itWallet.walletInstanceRevoked.alert.revokedByUser.title" + ), + I18n.t( + "features.itWallet.walletInstanceRevoked.alert.revokedByUser.content" + ), + [ + { + text: I18n.t( + "features.itWallet.walletInstanceRevoked.alert.closeButtonAlt" + ) + } + ] + ); + }); }); const renderComponent = (component: React.ComponentType) => {