Skip to content

Commit

Permalink
Merge branch 'master' into IOBP-1231-remove-total-amount-on-idpay-exp…
Browse files Browse the repository at this point in the history
…ense-card
  • Loading branch information
Hantex9 authored Mar 3, 2025
2 parents 08735f0 + 085181b commit e47f1e2
Show file tree
Hide file tree
Showing 12 changed files with 272 additions and 89 deletions.
2 changes: 2 additions & 0 deletions ts/features/itwallet/common/saga/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { watchItwCredentialsSaga } from "../../credentials/saga";
import { checkCredentialsStatusAttestation } from "../../credentials/saga/checkCredentialsStatusAttestation";
import { handleWalletCredentialsRehydration } from "../../credentials/saga/handleWalletCredentialsRehydration";
import { watchItwLifecycleSaga } from "../../lifecycle/saga";
import { warmUpIntegrityServiceSaga } from "../../lifecycle/saga/checkIntegrityServiceReadySaga";
import { checkWalletInstanceStateSaga } from "../../lifecycle/saga/checkWalletInstanceStateSaga";

function* checkWalletInstanceAndCredentialsValiditySaga() {
Expand All @@ -14,6 +15,7 @@ function* checkWalletInstanceAndCredentialsValiditySaga() {
}

export function* watchItwSaga(): SagaIterator {
yield* fork(warmUpIntegrityServiceSaga);
yield* fork(checkWalletInstanceAndCredentialsValiditySaga);
yield* fork(handleWalletCredentialsRehydration);
yield* fork(watchItwCredentialsSaga);
Expand Down
9 changes: 5 additions & 4 deletions ts/features/itwallet/issuance/store/actions/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ActionType, createStandardAction } from "typesafe-actions";
import { IntegrityServiceStatus } from "../reducers";

export const itwStoreIntegrityKeyTag = createStandardAction(
"ITW_STORE_INTEGRITY_KEY_TAG"
Expand All @@ -8,11 +9,11 @@ export const itwRemoveIntegrityKeyTag = createStandardAction(
"ITW_REMOVE_INTEGRITY_KEY_TAG"
)<void>();

export const itwIntegritySetServiceIsReady = createStandardAction(
"ITW_INTEGRITY_SET_SERVICE_IS_READY"
)<boolean>();
export const itwSetIntegrityServiceStatus = createStandardAction(
"ITW_SET_INTEGRITY_SERVICE_STATUS"
)<IntegrityServiceStatus>();

export type ItwIssuanceActions =
| ActionType<typeof itwStoreIntegrityKeyTag>
| ActionType<typeof itwRemoveIntegrityKeyTag>
| ActionType<typeof itwIntegritySetServiceIsReady>;
| ActionType<typeof itwSetIntegrityServiceStatus>;
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Action } from "../../../../../../store/actions/types";
import { GlobalState } from "../../../../../../store/reducers/types";
import { itwLifecycleStoresReset } from "../../../../lifecycle/store/actions";
import {
itwIntegritySetServiceIsReady,
itwSetIntegrityServiceStatus,
itwRemoveIntegrityKeyTag,
itwStoreIntegrityKeyTag
} from "../../actions";
Expand Down Expand Up @@ -58,20 +58,20 @@ describe("ITW issuance reducer", () => {
expect(targetSate.features.itWallet.issuance.integrityKeyTag).toEqual(
O.none
);
expect(targetSate.features.itWallet.issuance.integrityServiceReady).toEqual(
undefined
);
expect(
targetSate.features.itWallet.issuance.integrityServiceStatus
).toEqual(undefined);
});

it("should set the integrity preparation flag", () => {
const targetSate = pipe(
undefined,
curriedAppReducer(applicationChangeState("active")),
curriedAppReducer(itwIntegritySetServiceIsReady(true))
curriedAppReducer(itwSetIntegrityServiceStatus("ready"))
);

expect(targetSate.features.itWallet.issuance.integrityServiceReady).toEqual(
true
);
expect(
targetSate.features.itWallet.issuance.integrityServiceStatus
).toEqual("ready");
});
});
22 changes: 12 additions & 10 deletions ts/features/itwallet/issuance/store/reducers/index.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import AsyncStorage from "@react-native-async-storage/async-storage";
import * as O from "fp-ts/lib/Option";
import { getType } from "typesafe-actions";
import { PersistConfig, persistReducer } from "redux-persist";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { getType } from "typesafe-actions";
import { Action } from "../../../../../store/actions/types";
import { itwLifecycleStoresReset } from "../../../lifecycle/store/actions";
import {
itwIntegritySetServiceIsReady,
itwRemoveIntegrityKeyTag,
itwSetIntegrityServiceStatus,
itwStoreIntegrityKeyTag
} from "../actions";
import { itwLifecycleStoresReset } from "../../../lifecycle/store/actions";

const CURRENT_REDUX_ITW_ISSUANCE_STORE_VERSION = -1;

export type IntegrityServiceStatus = "ready" | "unavailable" | "error";

export type ItwIssuanceState = {
integrityKeyTag: O.Option<string>;
integrityServiceReady?: boolean;
integrityServiceStatus?: IntegrityServiceStatus;
};

export const itwIssuanceInitialState: ItwIssuanceState = {
Expand All @@ -26,6 +28,11 @@ const reducer = (
action: Action
): ItwIssuanceState => {
switch (action.type) {
case getType(itwSetIntegrityServiceStatus):
return {
...state,
integrityServiceStatus: action.payload
};
case getType(itwStoreIntegrityKeyTag):
return {
...state,
Expand All @@ -37,11 +44,6 @@ const reducer = (
...state,
integrityKeyTag: O.none
};
case getType(itwIntegritySetServiceIsReady):
return {
...state,
integrityServiceReady: action.payload
};
}
return state;
};
Expand Down
6 changes: 3 additions & 3 deletions ts/features/itwallet/issuance/store/selectors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export const itwIntegrityKeyTagSelector = (state: GlobalState) =>
state.features.itWallet.issuance.integrityKeyTag;

/**
* Selector that returns the integrityServiceReady flag.
* Selector that returns the integrityService status
*/
export const itwIntegrityServiceReadySelector = (state: GlobalState) =>
state.features.itWallet.issuance.integrityServiceReady;
export const itwIntegrityServiceStatusSelector = (state: GlobalState) =>
state.features.itWallet.issuance.integrityServiceStatus;
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { type DeepPartial } from "redux";
import { expectSaga } from "redux-saga-test-plan";
import * as matchers from "redux-saga-test-plan/matchers";
import { throwError } from "redux-saga-test-plan/providers";
import { GlobalState } from "../../../../../store/reducers/types";
import { ensureIntegrityServiceIsReady } from "../../../common/utils/itwIntegrityUtils";
import { itwSetIntegrityServiceStatus } from "../../../issuance/store/actions";
import { itwIntegrityServiceStatusSelector } from "../../../issuance/store/selectors";
import {
checkIntegrityServiceReadySaga,
warmUpIntegrityServiceSaga
} from "../checkIntegrityServiceReadySaga";

describe("checkIntegrityServiceReadySaga", () => {
it("Should wait for the integrity service status to be set", () => {
const store: DeepPartial<GlobalState> = {
features: {
itWallet: {
issuance: {
integrityServiceStatus: undefined
}
}
}
};
return expectSaga(checkIntegrityServiceReadySaga)
.withState(store)
.select(itwIntegrityServiceStatusSelector)
.take(itwSetIntegrityServiceStatus)
.not.call.fn(warmUpIntegrityServiceSaga)
.not.returns(expect.anything())
.run();
});

it("Should return true when the integrity service status is ready", () => {
const store: DeepPartial<GlobalState> = {
features: {
itWallet: {
issuance: {
integrityServiceStatus: "ready"
}
}
}
};
return expectSaga(checkIntegrityServiceReadySaga)
.withState(store)
.select(itwIntegrityServiceStatusSelector)
.not.take(itwSetIntegrityServiceStatus)
.not.call.fn(warmUpIntegrityServiceSaga)
.returns(true)
.run();
});

it("Should return false when the integrity service status is unavailable", () => {
const store: DeepPartial<GlobalState> = {
features: {
itWallet: {
issuance: {
integrityServiceStatus: "unavailable"
}
}
}
};
return expectSaga(checkIntegrityServiceReadySaga)
.withState(store)
.select(itwIntegrityServiceStatusSelector)
.not.take(itwSetIntegrityServiceStatus)
.not.call.fn(warmUpIntegrityServiceSaga)
.returns(false)
.run();
});

it("Should retry the integrity service warm up when the integrity service status is error", () => {
const store: DeepPartial<GlobalState> = {
features: {
itWallet: {
issuance: {
integrityServiceStatus: "error"
}
}
}
};
return expectSaga(checkIntegrityServiceReadySaga)
.withState(store)
.select(itwIntegrityServiceStatusSelector)
.call.fn(warmUpIntegrityServiceSaga)
.take(itwSetIntegrityServiceStatus)
.not.returns(expect.anything())
.run();
});
});

describe("warmUpIntegrityServiceSaga", () => {
it("Sets the integrity service status to ready when the integrity service is ready", () =>
expectSaga(warmUpIntegrityServiceSaga)
.provide([[matchers.call.fn(ensureIntegrityServiceIsReady), true]])
.call.fn(ensureIntegrityServiceIsReady)
.put(itwSetIntegrityServiceStatus("ready"))
.run());

it("Sets the integrity service status to unavailable when the integrity service is unavailable", () =>
expectSaga(warmUpIntegrityServiceSaga)
.provide([[matchers.call.fn(ensureIntegrityServiceIsReady), false]])
.call.fn(ensureIntegrityServiceIsReady)
.put(itwSetIntegrityServiceStatus("unavailable"))
.run());

it("Sets the integrity service status to error when the integrity service is unavailable", () =>
expectSaga(warmUpIntegrityServiceSaga)
.provide([
[
matchers.call.fn(ensureIntegrityServiceIsReady),
throwError(new Error("Integrity service error"))
]
])
.call.fn(ensureIntegrityServiceIsReady)
.put(itwSetIntegrityServiceStatus("error"))
.run());
});
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import * as O from "fp-ts/lib/Option";
import { type DeepPartial } from "redux";
import { expectSaga } from "redux-saga-test-plan";
import * as matchers from "redux-saga-test-plan/matchers";
import * as O from "fp-ts/lib/Option";
import { sessionTokenSelector } from "../../../../../store/reducers/authentication";
import { GlobalState } from "../../../../../store/reducers/types";
import { getWalletInstanceStatus } from "../../../common/utils/itwAttestationUtils";
import { StoredCredential } from "../../../common/utils/itwTypesUtils";
import { itwIntegrityServiceStatusSelector } from "../../../issuance/store/selectors";
import { itwIsWalletInstanceAttestationValidSelector } from "../../../walletInstance/store/selectors";
import { ItwLifecycleState } from "../../store/reducers";
import { checkIntegrityServiceReadySaga } from "../checkIntegrityServiceReadySaga";
import {
checkWalletInstanceStateSaga,
getStatusOrResetWalletInstance
} from "../checkWalletInstanceStateSaga";
import { ItwLifecycleState } from "../../store/reducers";
import { GlobalState } from "../../../../../store/reducers/types";
import { getWalletInstanceStatus } from "../../../common/utils/itwAttestationUtils";
import { StoredCredential } from "../../../common/utils/itwTypesUtils";
import { sessionTokenSelector } from "../../../../../store/reducers/authentication";
import { handleWalletInstanceResetSaga } from "../handleWalletInstanceResetSaga";
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
Expand All @@ -34,8 +34,8 @@ describe("checkWalletInstanceStateSaga", () => {
};
return expectSaga(checkWalletInstanceStateSaga)
.withState(store)
.provide([[matchers.call.fn(ensureIntegrityServiceIsReady), true]])
.call.fn(ensureIntegrityServiceIsReady)
.provide([[matchers.call.fn(checkIntegrityServiceReadySaga), true]])
.call.fn(checkIntegrityServiceReadySaga)
.not.call.fn(getStatusOrResetWalletInstance)
.run();
});
Expand All @@ -46,7 +46,7 @@ describe("checkWalletInstanceStateSaga", () => {
itWallet: {
lifecycle: ItwLifecycleState.ITW_LIFECYCLE_OPERATIONAL,
issuance: {
integrityServiceReady: true,
integrityServiceStatus: "ready",
integrityKeyTag: O.some("aac6e82a-e27e-4293-9b55-94a9fab22763")
},
credentials: { eid: O.none, credentials: [] }
Expand All @@ -59,11 +59,11 @@ describe("checkWalletInstanceStateSaga", () => {
.provide([
[matchers.select(sessionTokenSelector), "h94LhbfJCLGH1S3qHj"],
[matchers.select(itwIsWalletInstanceAttestationValidSelector), false],
[matchers.select(itwIntegrityServiceReadySelector), true],
[matchers.select(itwIntegrityServiceStatusSelector), "ready"],
[matchers.call.fn(getWalletInstanceStatus), { is_revoked: false }],
[matchers.call.fn(ensureIntegrityServiceIsReady), true]
[matchers.call.fn(checkIntegrityServiceReadySaga), true]
])
.call.fn(ensureIntegrityServiceIsReady)
.call.fn(checkIntegrityServiceReadySaga)
.call.fn(getStatusOrResetWalletInstance)
.not.call.fn(handleWalletInstanceResetSaga)
.run();
Expand All @@ -88,9 +88,9 @@ describe("checkWalletInstanceStateSaga", () => {
[matchers.select(sessionTokenSelector), "h94LhbfJCLGH1S3qHj"],
[matchers.select(itwIsWalletInstanceAttestationValidSelector), false],
[matchers.call.fn(getWalletInstanceStatus), { is_revoked: true }],
[matchers.call.fn(ensureIntegrityServiceIsReady), true]
[matchers.call.fn(checkIntegrityServiceReadySaga), true]
])
.call.fn(ensureIntegrityServiceIsReady)
.call.fn(checkIntegrityServiceReadySaga)
.call.fn(getStatusOrResetWalletInstance)
.call.fn(handleWalletInstanceResetSaga)
.run();
Expand All @@ -115,9 +115,9 @@ describe("checkWalletInstanceStateSaga", () => {
[matchers.select(sessionTokenSelector), "h94LhbfJCLGH1S3qHj"],
[matchers.select(itwIsWalletInstanceAttestationValidSelector), false],
[matchers.call.fn(getWalletInstanceStatus), { is_revoked: false }],
[matchers.call.fn(ensureIntegrityServiceIsReady), true]
[matchers.call.fn(checkIntegrityServiceReadySaga), true]
])
.call.fn(ensureIntegrityServiceIsReady)
.call.fn(checkIntegrityServiceReadySaga)
.call.fn(getStatusOrResetWalletInstance)
.not.call.fn(handleWalletInstanceResetSaga)
.run();
Expand All @@ -142,9 +142,9 @@ describe("checkWalletInstanceStateSaga", () => {
[matchers.select(sessionTokenSelector), "h94LhbfJCLGH1S3qHj"],
[matchers.select(itwIsWalletInstanceAttestationValidSelector), false],
[matchers.call.fn(getWalletInstanceStatus), { is_revoked: true }],
[matchers.call.fn(ensureIntegrityServiceIsReady), true]
[matchers.call.fn(checkIntegrityServiceReadySaga), true]
])
.call.fn(ensureIntegrityServiceIsReady)
.call.fn(checkIntegrityServiceReadySaga)
.call.fn(getStatusOrResetWalletInstance)
.call.fn(handleWalletInstanceResetSaga)
.run();
Expand Down
Loading

0 comments on commit e47f1e2

Please sign in to comment.