Skip to content

Commit

Permalink
Merge branch 'master' into PE-732-CGN-header-on-scroll
Browse files Browse the repository at this point in the history
  • Loading branch information
Hantex9 authored Nov 4, 2024
2 parents 5265b68 + b8622e1 commit 11e8a0e
Show file tree
Hide file tree
Showing 11 changed files with 145 additions and 30 deletions.
10 changes: 5 additions & 5 deletions locales/en/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,8 @@ inbox:
enableButton: Enable Inbox
disableButton: Disable Inbox
enableCallToActionDescription: Enable the inbox to view messages
settings:
informativeBanner:
settings:
informativeBanner:
content: Looking for your profile? We have moved it, it is now in the top right corner!
action: Go to Settings
profile:
Expand Down Expand Up @@ -3421,10 +3421,10 @@ features:
alerts:
mdl:
content: "Puoi usare la tua Patente su IO solo in Italia per dimostrare di essere abilitato alla guida in caso di controlli delle Forze dell'ordine."
action: Scopri di più
ehc:
content: "Puoi usare la tua Tessera Sanitaria - Tessera europea di assicurazione malattia su IO per accedere alle prestazioni fornite dal Servizio Sanitario Nazionale."
action: "Scopri di più"
edc:
content: "Puoi usare la tua Carta Europea della Disabilità su IO per accedere ai servizi sul territorio italiano, negli stessi contesti d’uso del tuo documento fisico."
expired:
content: Il documento non è più valido. Se sei già in possesso del nuovo documento valido, puoi aggiornare la versione digitale nel Portafoglio
action: Aggiorna il documento
Expand Down Expand Up @@ -3512,7 +3512,7 @@ support:
panicMode:
title: "We cannot help you at the moment"
body: "We know there is a problem and we are working to solve it. If the problem remains, or if you need support on another topic, please try again later."
errorGetZendeskToken:
errorGetZendeskToken:
title: Sorry, we're unable to open a service request at the moment.
subtitle: Try again later
askPermissions:
Expand Down
10 changes: 5 additions & 5 deletions locales/it/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,8 @@ inbox:
enableButton: Abilita Inbox
disableButton: Disabilita Inbox
enableCallToActionDescription: Abilita l'inbox per visualizzare i messaggi
settings:
informativeBanner:
settings:
informativeBanner:
content: Cerchi il Profilo? Lo abbiamo spostato, ora è in alto a destra!
action: Vai alle Impostazioni
profile:
Expand Down Expand Up @@ -3421,10 +3421,10 @@ features:
alerts:
mdl:
content: "Puoi usare la tua Patente su IO solo in Italia per dimostrare di essere abilitato alla guida in caso di controlli delle Forze dell'ordine."
action: Scopri di più
ehc:
content: "Puoi usare la tua Tessera Sanitaria - Tessera europea di assicurazione malattia su IO per accedere alle prestazioni fornite dal Servizio Sanitario Nazionale."
action: "Scopri di più"
edc:
content: "Puoi usare la tua Carta Europea della Disabilità su IO per accedere ai servizi sul territorio italiano, negli stessi contesti d’uso del tuo documento fisico."
expired:
content: Il documento non è più valido. Se sei già in possesso del nuovo documento valido, puoi aggiornare la versione digitale nel Portafoglio
action: Aggiorna il documento
Expand Down Expand Up @@ -3512,7 +3512,7 @@ support:
panicMode:
title: "Purtroppo, in questo momento non riusciamo ad aiutarti"
body: "Sappiamo che c’è un problema e siamo al lavoro per risolverlo. Se il problema persiste, o se hai bisogno di assistenza su un altro argomento, riprova a scriverci più tardi."
errorGetZendeskToken:
errorGetZendeskToken:
title: Al momento non riusciamo ad aprire una richiesta di assistenza
subtitle: Riprova più tardi
askPermissions:
Expand Down
23 changes: 15 additions & 8 deletions ts/features/itwallet/common/saga/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,33 +9,40 @@ import {
trialSystemActivationStatusUpsert
} from "../../../../trialSystem/store/actions";
import { SubscriptionStateEnum } from "../../../../../../definitions/trial_system/SubscriptionState";
import { trialStatusSelector } from "../../../../trialSystem/store/reducers";
import {
trialStatusPotSelector,
trialStatusSelector
} from "../../../../trialSystem/store/reducers";
import { TrialId } from "../../../../../../definitions/trial_system/TrialId";
import { TrialSystemError } from "../../../../trialSystem/utils/error";

describe("handleTrialSystemSubscription", () => {
it("should handle trial system subscription correctly", async () => {
it("should handle trial system subscription correctly when the endpoint returns 404", async () => {
const trialId = "baz" as TrialId;
const state = SubscriptionStateEnum.UNSUBSCRIBED;
const error = new TrialSystemError(
"User not found",
"TRIAL_SYSTEM_USER_NOT_FOUND"
);
const state = pot.noneError(error);
const store: DeepPartial<GlobalState> = {
trialSystem: {
[trialId]: pot.some(state)
[trialId]: state
}
};
return expectSaga(handleTrialSystemSubscription)
.withState(store)
.put(trialSystemActivationStatus.request(trialId))
.dispatch(
trialSystemActivationStatus.success({
trialSystemActivationStatus.failure({
trialId,
state,
createdAt: new Date()
error
})
)
.take([
trialSystemActivationStatus.success,
trialSystemActivationStatus.failure
])
.provide([[matchers.select(trialStatusSelector), state]])
.provide([[matchers.select(trialStatusPotSelector), state]])
.put(trialSystemActivationStatusUpsert.request(trialId))
.run();
});
Expand Down
16 changes: 11 additions & 5 deletions ts/features/itwallet/common/saga/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { SagaIterator } from "redux-saga";
import { fork, put, call, take, select } from "typed-redux-saga/macro";
import * as pot from "@pagopa/ts-commons/lib/pot";
import { isActionOf } from "typesafe-actions";
import {
trialSystemActivationStatus,
Expand All @@ -13,8 +14,7 @@ import { itwCieIsSupported } from "../../identification/store/actions";
import { watchItwCredentialsSaga } from "../../credentials/saga";
import { watchItwLifecycleSaga } from "../../lifecycle/saga";
import { checkCredentialsStatusAttestation } from "../../credentials/saga/checkCredentialsStatusAttestation";
import { trialStatusSelector } from "../../../trialSystem/store/reducers";
import { SubscriptionStateEnum } from "../../../../../definitions/trial_system/SubscriptionState";
import { trialStatusPotSelector } from "../../../trialSystem/store/reducers";

function* checkWalletInstanceAndCredentialsValiditySaga() {
// Status attestations of credentials are checked only in case of a valid wallet instance.
Expand All @@ -34,9 +34,15 @@ export function* handleTrialSystemSubscription() {
trialSystemActivationStatus.success,
trialSystemActivationStatus.failure
]);
if (isActionOf(trialSystemActivationStatus.success, outputAction)) {
const status = yield* select(trialStatusSelector(itwTrialId));
if (status && status === SubscriptionStateEnum.UNSUBSCRIBED) {
if (isActionOf(trialSystemActivationStatus.failure, outputAction)) {
/* We check if the error is due to the user not being found in the trial system and we try to subscribe the user
the trial system returns 404 if the usuer is not found or if the trial id is not found. However, the trial id is
hardcoded in the config file and we assume it is correct so the only reason for the 404 is the user not being found. */
const potStatus = yield* select(trialStatusPotSelector(itwTrialId));
if (
pot.isError(potStatus) &&
potStatus.error.type === "TRIAL_SYSTEM_USER_NOT_FOUND"
) {
yield* put(trialSystemActivationStatusUpsert.request(itwTrialId));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,8 @@ const styles = StyleSheet.create({
height: TRUSTMARK_HEIGHT,
borderCurve: "continuous",
borderRadius: buttonBorderRadius,
overflow: "hidden"
overflow: "hidden",
marginVertical: 8
},
gradientView: {
...StyleSheet.absoluteFillObject
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ export const ItwPresentationAlertsSection = ({ credential }: Props) => {
const isMdl = credential.credentialType === CredentialType.DRIVING_LICENSE;
const isEhc =
credential.credentialType === CredentialType.EUROPEAN_HEALTH_INSURANCE_CARD;
const isEdc =
credential.credentialType === CredentialType.EUROPEAN_DISABILITY_CARD;

const expireStatus = getCredentialStatus(credential);
const expireDays = getCredentialExpireDays(credential.parsedCredential);
Expand Down Expand Up @@ -75,6 +77,13 @@ export const ItwPresentationAlertsSection = ({ credential }: Props) => {
variant="info"
/>
)}
{isEdc && (
<Alert
testID="itwEdcBannerTestID"
content={I18n.t("features.itWallet.presentation.alerts.edc.content")}
variant="info"
/>
)}
</VStack>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,34 @@ describe("ItwPresentationAlertsSection", () => {
expect(queryByTestId("itwExpiredBannerTestID")).toBeNull();
expect(queryByTestId("itwExpiringBannerTestID")).toBeNull();
expect(queryByTestId("itwMdlBannerTestID")).not.toBeNull();
expect(queryByTestId("itwEhcBannerTestID")).toBeNull();
expect(queryByTestId("itwEdcBannerTestID")).toBeNull();
});

it("should render EHC alert", () => {
const { queryByTestId } = renderComponent(
CredentialType.EUROPEAN_HEALTH_INSURANCE_CARD,
new Date(2000, 2, 20)
);

expect(queryByTestId("itwExpiredBannerTestID")).toBeNull();
expect(queryByTestId("itwExpiringBannerTestID")).toBeNull();
expect(queryByTestId("itwMdlBannerTestID")).toBeNull();
expect(queryByTestId("itwEhcBannerTestID")).not.toBeNull();
expect(queryByTestId("itwEdcBannerTestID")).toBeNull();
});

it("should render EDC alert", () => {
const { queryByTestId } = renderComponent(
CredentialType.EUROPEAN_DISABILITY_CARD,
new Date(2000, 2, 20)
);

expect(queryByTestId("itwExpiredBannerTestID")).toBeNull();
expect(queryByTestId("itwExpiringBannerTestID")).toBeNull();
expect(queryByTestId("itwMdlBannerTestID")).toBeNull();
expect(queryByTestId("itwEhcBannerTestID")).toBeNull();
expect(queryByTestId("itwEdcBannerTestID")).not.toBeNull();
});
});

Expand Down
3 changes: 2 additions & 1 deletion ts/features/trialSystem/store/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import {
} from "typesafe-actions";
import { TrialId } from "../../../../../definitions/trial_system/TrialId";
import { Subscription } from "../../../../../definitions/trial_system/Subscription";
import { TrialSystemError } from "../../utils/error";

type ErrorPayload = {
trialId: TrialId;
error: Error;
error: TrialSystemError;
};

export const trialSystemActivationStatusUpsert = createAsyncAction(
Expand Down
15 changes: 14 additions & 1 deletion ts/features/trialSystem/store/reducers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ import {
} from "../actions";
import { GlobalState } from "../../../../store/reducers/types";
import { itwTrialId } from "../../../../config";
import { TrialSystemError } from "../../utils/error";

export type TrialSystemState = Record<
TrialId,
pot.Pot<SubscriptionState, Error>
pot.Pot<SubscriptionState, TrialSystemError>
>;

const initialState: TrialSystemState = {};
Expand Down Expand Up @@ -109,6 +110,18 @@ export const isUpdatingTrialStatusSelector =
pot.isUpdating
);

/**
* Returns the pot state of a given trial
* @param id - The trial id
* @returns the pot state of the trial
*/
export const trialStatusPotSelector = (id: TrialId) => (state: GlobalState) =>
pipe(
state,
trialSystemActivationStatusSelector,
status => status[id] ?? pot.none
);

/**
* Allows to know if the user has the access to the specified trial
*/
Expand Down
23 changes: 19 additions & 4 deletions ts/features/trialSystem/store/sagas/watchTrialSystemSaga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import { TrialSystemClient, createTrialSystemClient } from "../../api/client";
import { apiUrlPrefix } from "../../../../config";
import {
trialSystemActivationStatus,
trialSystemActivationStatusReset,
trialSystemActivationStatusUpsert
} from "../actions";
import { getError } from "../../../../utils/errors";
import { TrialSystemError } from "../../utils/error";

function* handleTrialSystemActivationStatusUpsert(
upsertTrialSystemActivationStatus: TrialSystemClient["createSubscription"],
Expand Down Expand Up @@ -74,21 +74,36 @@ function* handleTrialSystemActivationStatus(
}

if (result.right.status === 404) {
yield* put(trialSystemActivationStatusReset(action.payload));
/**
* 404 is returned when the user is not found in the trial system. However, the API also returns 404 when the trial id is not found.
* We assume the trial id is correct so the only reason for the 404 is the user not being found.
*/
yield* put(
trialSystemActivationStatus.failure({
trialId: action.payload,
error: new TrialSystemError(
"User not found",
"TRIAL_SYSTEM_USER_NOT_FOUND"
)
})
);
return;
} else {
yield* put(
trialSystemActivationStatus.failure({
trialId: action.payload,
error: new Error(`response status ${result.right.status}`)
error: new TrialSystemError(`response status ${result.right.status}`)
})
);
}
} catch (e) {
yield* put(
trialSystemActivationStatus.failure({
trialId: action.payload,
error: getError(e)
error: new TrialSystemError(
getError(e).message,
"TRIAL_SYSTEM_NETWORK_ERROR"
)
})
);
}
Expand Down
35 changes: 35 additions & 0 deletions ts/features/trialSystem/utils/error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
type TrialSystemErrorType =
/* The user is not found in the trial system which corresponds to a 404 error
However, the API also returns 404 when the trial id is not found
We assume the trial id is correct so the only reason for the 404 is the user not being found. */
| "TRIAL_SYSTEM_USER_NOT_FOUND"
| "TRIAL_SYSTEM_GENERIC_ERROR"
| "TRIAL_SYSTEM_NETWORK_ERROR";

/**
* Custom error class for Trial System errors. It allows to specify a type of error
* as some specific errors need to be handled differently.
*/
export class TrialSystemError extends Error {
public readonly type?: TrialSystemErrorType;

constructor(
message: string | undefined,
type: TrialSystemErrorType = "TRIAL_SYSTEM_GENERIC_ERROR"
) {
// Pass parent constructor parameters
super(message);

// Maintains stack trace for where our error was thrown (only available on V8)
if (Error.captureStackTrace) {
Error.captureStackTrace(this, TrialSystemError);
}

this.name = "TrialSystemError";
if (message) {
this.message = message;
}
// Set custom information
this.type = type;
}
}

0 comments on commit 11e8a0e

Please sign in to comment.