From 92c8e32c8215a5bdeb5c587576a506e1bf28905e Mon Sep 17 00:00:00 2001 From: Manish Garg Date: Mon, 15 Jul 2024 12:10:12 +0100 Subject: [PATCH 1/8] CIV-14636 test pr --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0dba3e56510..0706d1c5a5c 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "build": "yarn webpack --config webpack.config.js", "build:prod": "NODE_ENV=production yarn webpack --mode production --config webpack.config.js", "test": "echo -c jest.config.js", - "test:coverage": "jest --coverage --maxWorkers=4 --logHeapUsage --silent", + "test:coverage": "echo jest --coverage --maxWorkers=4 --logHeapUsage --silent", "test:a11y": "echo 'a11y tests are ran through GitHub actions as a mandatory step in order to save time on the main pipeline and unable to mock at the moment.'", "tests:a11y": "NODE_TLS_REJECT_UNAUTHORIZED=0 NODE_ENV=test LOG_LEVEL=ERROR mocha --exit --reporter mochawesome --require ts-node/register --require tsconfig-paths/register src/test/a11y/a11y.mock-test.ts --timeout 60000 --reporter-options reportDir=functional-output/accessibility-report,reportFilename=a11y,inlineAssets=true,reportTitle=civil-citizen-ui", "sonar-scan": "sonar-scanner", From 1c55584808c072e39b91c2501de014ca99f910bb Mon Sep 17 00:00:00 2001 From: Manish Garg Date: Mon, 15 Jul 2024 15:37:20 +0100 Subject: [PATCH 2/8] CIV-14636 clearing cache after fee breakup controller --- package.json | 2 +- .../claim/payment/claimFeeBreakDownController.ts | 5 +++-- .../payment/claimFeePaymentUnsuccessfulController.ts | 4 ++-- .../claim/payment/claimFeeMakePaymentAgainService.ts | 4 ---- .../payment/claimFeePaymentConfirmationService.ts | 11 ++++++----- 5 files changed, 12 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 0706d1c5a5c..0dba3e56510 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "build": "yarn webpack --config webpack.config.js", "build:prod": "NODE_ENV=production yarn webpack --mode production --config webpack.config.js", "test": "echo -c jest.config.js", - "test:coverage": "echo jest --coverage --maxWorkers=4 --logHeapUsage --silent", + "test:coverage": "jest --coverage --maxWorkers=4 --logHeapUsage --silent", "test:a11y": "echo 'a11y tests are ran through GitHub actions as a mandatory step in order to save time on the main pipeline and unable to mock at the moment.'", "tests:a11y": "NODE_TLS_REJECT_UNAUTHORIZED=0 NODE_ENV=test LOG_LEVEL=ERROR mocha --exit --reporter mochawesome --require ts-node/register --require tsconfig-paths/register src/test/a11y/a11y.mock-test.ts --timeout 60000 --reporter-options reportDir=functional-output/accessibility-report,reportFilename=a11y,inlineAssets=true,reportTitle=civil-citizen-ui", "sonar-scan": "sonar-scanner", diff --git a/src/main/routes/features/claim/payment/claimFeeBreakDownController.ts b/src/main/routes/features/claim/payment/claimFeeBreakDownController.ts index e70359a4409..6705e0310b4 100644 --- a/src/main/routes/features/claim/payment/claimFeeBreakDownController.ts +++ b/src/main/routes/features/claim/payment/claimFeeBreakDownController.ts @@ -1,6 +1,6 @@ import {AppRequest} from 'common/models/AppRequest'; import {NextFunction, RequestHandler, Response, Router} from 'express'; -import {generateRedisKey, getCaseDataFromStore, saveDraftClaim} from 'modules/draft-store/draftStoreService'; +import {deleteDraftClaimFromStore, generateRedisKey, getCaseDataFromStore} from 'modules/draft-store/draftStoreService'; import {CLAIM_FEE_BREAKUP} from 'routes/urls'; import {YesNo} from 'common/form/models/yesNo'; import {calculateInterestToDate} from 'common/utils/interestUtils'; @@ -32,7 +32,8 @@ claimFeeBreakDownController.post(CLAIM_FEE_BREAKUP, (async (req: AppRequest, res const paymentRedirectInformation = await getFeePaymentRedirectInformation(claimId, FeeType.CLAIMISSUED , req); const claim = await getCaseDataFromStore(generateRedisKey(req)); claim.claimDetails.claimFeePayment = paymentRedirectInformation; - await saveDraftClaim(claim.id, claim, true); + // await saveDraftClaim(claim.id, claim, true); + await deleteDraftClaimFromStore(claimId); res.redirect(paymentRedirectInformation?.nextUrl); } catch (error) { next(error); diff --git a/src/main/routes/features/claim/payment/claimFeePaymentUnsuccessfulController.ts b/src/main/routes/features/claim/payment/claimFeePaymentUnsuccessfulController.ts index 85664abb5bf..deaab1433ec 100644 --- a/src/main/routes/features/claim/payment/claimFeePaymentUnsuccessfulController.ts +++ b/src/main/routes/features/claim/payment/claimFeePaymentUnsuccessfulController.ts @@ -1,8 +1,8 @@ import {NextFunction, RequestHandler, Response, Router} from 'express'; import {CLAIM_FEE_MAKE_PAYMENT_AGAIN_URL, DASHBOARD_CLAIMANT_URL, PAY_CLAIM_FEE_UNSUCCESSFUL_URL} from 'routes/urls'; import {AppRequest} from 'models/AppRequest'; -import {generateRedisKey, getCaseDataFromStore} from 'modules/draft-store/draftStoreService'; import {constructResponseUrlWithIdParams} from 'common/utils/urlFormatter'; +import { getClaimById } from 'modules/utilityService'; const paymentUnsuccessfulController: Router = Router(); @@ -12,7 +12,7 @@ paymentUnsuccessfulController.get(PAY_CLAIM_FEE_UNSUCCESSFUL_URL, (async (req: A try { const claimId = req.params.id; const makePaymentAgainUrl = constructResponseUrlWithIdParams(claimId, CLAIM_FEE_MAKE_PAYMENT_AGAIN_URL); - const claim = await getCaseDataFromStore(generateRedisKey(req)); + const claim = await getClaimById(claimId, req); const claimNumber : string = claim.getFormattedCaseReferenceNumber(claimId); res.render(paymentUnsuccessfulViewPath, { claimNumber, diff --git a/src/main/services/features/claim/payment/claimFeeMakePaymentAgainService.ts b/src/main/services/features/claim/payment/claimFeeMakePaymentAgainService.ts index 9c6d1bcda8c..b86a8721af9 100644 --- a/src/main/services/features/claim/payment/claimFeeMakePaymentAgainService.ts +++ b/src/main/services/features/claim/payment/claimFeeMakePaymentAgainService.ts @@ -1,7 +1,6 @@ import {AppRequest} from 'models/AppRequest'; import {getFeePaymentRedirectInformation} from 'services/features/feePayment/feePaymentService'; -import {generateRedisKey, getCaseDataFromStore, saveDraftClaim} from 'modules/draft-store/draftStoreService'; import {FeeType} from 'form/models/helpWithFees/feeType'; const {Logger} = require('@hmcts/nodejs-logging'); @@ -10,9 +9,6 @@ const logger = Logger.getLogger('ClaimFeeMakePaymentAgainService'); export const getRedirectUrl = async (claimId: string, req: AppRequest): Promise => { try{ const paymentRedirectInformation = await getFeePaymentRedirectInformation(claimId, FeeType.CLAIMISSUED, req); - const claim = await getCaseDataFromStore(generateRedisKey(req)); - claim.claimDetails.claimFeePayment = paymentRedirectInformation; - await saveDraftClaim(claim.id, claim, true); return paymentRedirectInformation?.nextUrl; } catch (error) { diff --git a/src/main/services/features/claim/payment/claimFeePaymentConfirmationService.ts b/src/main/services/features/claim/payment/claimFeePaymentConfirmationService.ts index 23f7e05d6d5..d7af6a9290e 100644 --- a/src/main/services/features/claim/payment/claimFeePaymentConfirmationService.ts +++ b/src/main/services/features/claim/payment/claimFeePaymentConfirmationService.ts @@ -4,11 +4,12 @@ import { PAY_CLAIM_FEE_UNSUCCESSFUL_URL, DASHBOARD_URL, } from 'routes/urls'; -import { deleteDraftClaimFromStore, generateRedisKey, getCaseDataFromStore } from 'modules/draft-store/draftStoreService'; +import { deleteDraftClaimFromStore, generateRedisKey } from 'modules/draft-store/draftStoreService'; import {getFeePaymentStatus} from 'services/features/feePayment/feePaymentService'; import {FeeType} from 'form/models/helpWithFees/feeType'; import {Claim} from 'models/claim'; import { ClaimBilingualLanguagePreference } from 'common/models/claimBilingualLanguagePreference'; +import { getClaimById } from 'modules/utilityService'; const {Logger} = require('@hmcts/nodejs-logging'); const logger = Logger.getLogger('claimFeePaymentConfirmationService'); @@ -19,16 +20,16 @@ const paymentCancelledByUser = 'Payment was cancelled by the user'; export const getRedirectUrl = async (claimId: string, req: AppRequest): Promise => { try { const redisClaimId = generateRedisKey(req); - const claim: Claim = await getCaseDataFromStore(redisClaimId); + const claim: Claim = await getClaimById(claimId,req); const paymentInfo = claim.claimDetails?.claimFeePayment; const paymentStatus = await getFeePaymentStatus(claimId, paymentInfo?.paymentReference, FeeType.CLAIMISSUED, req); - + + deleteDraftClaimFromStore(redisClaimId); if(paymentStatus.status === success) { const lang = claim.claimantBilingualLanguagePreference === ClaimBilingualLanguagePreference.WELSH_AND_ENGLISH ? 'cy' : 'en'; - deleteDraftClaimFromStore(redisClaimId); return `${PAY_CLAIM_FEE_SUCCESSFUL_URL}?lang=${lang}`; } - + return paymentStatus.errorDescription !== paymentCancelledByUser ? PAY_CLAIM_FEE_UNSUCCESSFUL_URL : DASHBOARD_URL; } From 261be495d26695878ade3746a498ea34260abc25 Mon Sep 17 00:00:00 2001 From: Manish Garg Date: Mon, 15 Jul 2024 16:11:39 +0100 Subject: [PATCH 3/8] CIV-14363 reverted temp change --- .../claim/payment/claimFeeBreakDownController.ts | 5 ++--- .../payment/claimFeePaymentUnsuccessfulController.ts | 4 ++-- .../claim/payment/claimFeeMakePaymentAgainService.ts | 4 ++++ .../payment/claimFeePaymentConfirmationService.ts | 11 +++++------ 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/main/routes/features/claim/payment/claimFeeBreakDownController.ts b/src/main/routes/features/claim/payment/claimFeeBreakDownController.ts index 6705e0310b4..e70359a4409 100644 --- a/src/main/routes/features/claim/payment/claimFeeBreakDownController.ts +++ b/src/main/routes/features/claim/payment/claimFeeBreakDownController.ts @@ -1,6 +1,6 @@ import {AppRequest} from 'common/models/AppRequest'; import {NextFunction, RequestHandler, Response, Router} from 'express'; -import {deleteDraftClaimFromStore, generateRedisKey, getCaseDataFromStore} from 'modules/draft-store/draftStoreService'; +import {generateRedisKey, getCaseDataFromStore, saveDraftClaim} from 'modules/draft-store/draftStoreService'; import {CLAIM_FEE_BREAKUP} from 'routes/urls'; import {YesNo} from 'common/form/models/yesNo'; import {calculateInterestToDate} from 'common/utils/interestUtils'; @@ -32,8 +32,7 @@ claimFeeBreakDownController.post(CLAIM_FEE_BREAKUP, (async (req: AppRequest, res const paymentRedirectInformation = await getFeePaymentRedirectInformation(claimId, FeeType.CLAIMISSUED , req); const claim = await getCaseDataFromStore(generateRedisKey(req)); claim.claimDetails.claimFeePayment = paymentRedirectInformation; - // await saveDraftClaim(claim.id, claim, true); - await deleteDraftClaimFromStore(claimId); + await saveDraftClaim(claim.id, claim, true); res.redirect(paymentRedirectInformation?.nextUrl); } catch (error) { next(error); diff --git a/src/main/routes/features/claim/payment/claimFeePaymentUnsuccessfulController.ts b/src/main/routes/features/claim/payment/claimFeePaymentUnsuccessfulController.ts index deaab1433ec..85664abb5bf 100644 --- a/src/main/routes/features/claim/payment/claimFeePaymentUnsuccessfulController.ts +++ b/src/main/routes/features/claim/payment/claimFeePaymentUnsuccessfulController.ts @@ -1,8 +1,8 @@ import {NextFunction, RequestHandler, Response, Router} from 'express'; import {CLAIM_FEE_MAKE_PAYMENT_AGAIN_URL, DASHBOARD_CLAIMANT_URL, PAY_CLAIM_FEE_UNSUCCESSFUL_URL} from 'routes/urls'; import {AppRequest} from 'models/AppRequest'; +import {generateRedisKey, getCaseDataFromStore} from 'modules/draft-store/draftStoreService'; import {constructResponseUrlWithIdParams} from 'common/utils/urlFormatter'; -import { getClaimById } from 'modules/utilityService'; const paymentUnsuccessfulController: Router = Router(); @@ -12,7 +12,7 @@ paymentUnsuccessfulController.get(PAY_CLAIM_FEE_UNSUCCESSFUL_URL, (async (req: A try { const claimId = req.params.id; const makePaymentAgainUrl = constructResponseUrlWithIdParams(claimId, CLAIM_FEE_MAKE_PAYMENT_AGAIN_URL); - const claim = await getClaimById(claimId, req); + const claim = await getCaseDataFromStore(generateRedisKey(req)); const claimNumber : string = claim.getFormattedCaseReferenceNumber(claimId); res.render(paymentUnsuccessfulViewPath, { claimNumber, diff --git a/src/main/services/features/claim/payment/claimFeeMakePaymentAgainService.ts b/src/main/services/features/claim/payment/claimFeeMakePaymentAgainService.ts index b86a8721af9..9c6d1bcda8c 100644 --- a/src/main/services/features/claim/payment/claimFeeMakePaymentAgainService.ts +++ b/src/main/services/features/claim/payment/claimFeeMakePaymentAgainService.ts @@ -1,6 +1,7 @@ import {AppRequest} from 'models/AppRequest'; import {getFeePaymentRedirectInformation} from 'services/features/feePayment/feePaymentService'; +import {generateRedisKey, getCaseDataFromStore, saveDraftClaim} from 'modules/draft-store/draftStoreService'; import {FeeType} from 'form/models/helpWithFees/feeType'; const {Logger} = require('@hmcts/nodejs-logging'); @@ -9,6 +10,9 @@ const logger = Logger.getLogger('ClaimFeeMakePaymentAgainService'); export const getRedirectUrl = async (claimId: string, req: AppRequest): Promise => { try{ const paymentRedirectInformation = await getFeePaymentRedirectInformation(claimId, FeeType.CLAIMISSUED, req); + const claim = await getCaseDataFromStore(generateRedisKey(req)); + claim.claimDetails.claimFeePayment = paymentRedirectInformation; + await saveDraftClaim(claim.id, claim, true); return paymentRedirectInformation?.nextUrl; } catch (error) { diff --git a/src/main/services/features/claim/payment/claimFeePaymentConfirmationService.ts b/src/main/services/features/claim/payment/claimFeePaymentConfirmationService.ts index d7af6a9290e..23f7e05d6d5 100644 --- a/src/main/services/features/claim/payment/claimFeePaymentConfirmationService.ts +++ b/src/main/services/features/claim/payment/claimFeePaymentConfirmationService.ts @@ -4,12 +4,11 @@ import { PAY_CLAIM_FEE_UNSUCCESSFUL_URL, DASHBOARD_URL, } from 'routes/urls'; -import { deleteDraftClaimFromStore, generateRedisKey } from 'modules/draft-store/draftStoreService'; +import { deleteDraftClaimFromStore, generateRedisKey, getCaseDataFromStore } from 'modules/draft-store/draftStoreService'; import {getFeePaymentStatus} from 'services/features/feePayment/feePaymentService'; import {FeeType} from 'form/models/helpWithFees/feeType'; import {Claim} from 'models/claim'; import { ClaimBilingualLanguagePreference } from 'common/models/claimBilingualLanguagePreference'; -import { getClaimById } from 'modules/utilityService'; const {Logger} = require('@hmcts/nodejs-logging'); const logger = Logger.getLogger('claimFeePaymentConfirmationService'); @@ -20,16 +19,16 @@ const paymentCancelledByUser = 'Payment was cancelled by the user'; export const getRedirectUrl = async (claimId: string, req: AppRequest): Promise => { try { const redisClaimId = generateRedisKey(req); - const claim: Claim = await getClaimById(claimId,req); + const claim: Claim = await getCaseDataFromStore(redisClaimId); const paymentInfo = claim.claimDetails?.claimFeePayment; const paymentStatus = await getFeePaymentStatus(claimId, paymentInfo?.paymentReference, FeeType.CLAIMISSUED, req); - - deleteDraftClaimFromStore(redisClaimId); + if(paymentStatus.status === success) { const lang = claim.claimantBilingualLanguagePreference === ClaimBilingualLanguagePreference.WELSH_AND_ENGLISH ? 'cy' : 'en'; + deleteDraftClaimFromStore(redisClaimId); return `${PAY_CLAIM_FEE_SUCCESSFUL_URL}?lang=${lang}`; } - + return paymentStatus.errorDescription !== paymentCancelledByUser ? PAY_CLAIM_FEE_UNSUCCESSFUL_URL : DASHBOARD_URL; } From ddbd837f5e7833b9c4d06d7fc4fe4a227e9be61d Mon Sep 17 00:00:00 2001 From: Manish Garg Date: Tue, 16 Jul 2024 13:59:57 +0100 Subject: [PATCH 4/8] CIV-14636 Added redis logic for claimantIntent guard --- src/main/routes/guards/claimantIntentGuard.ts | 14 +++++++++- .../routes/guards/claimantIntentGuard.test.ts | 28 +++++++++++++++---- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/main/routes/guards/claimantIntentGuard.ts b/src/main/routes/guards/claimantIntentGuard.ts index 6bb6d33b539..27fda188640 100644 --- a/src/main/routes/guards/claimantIntentGuard.ts +++ b/src/main/routes/guards/claimantIntentGuard.ts @@ -3,6 +3,9 @@ import { Claim } from '../../common/models/claim'; import { constructResponseUrlWithIdParams } from '../../common/utils/urlFormatter'; import { DASHBOARD_CLAIMANT_URL } from '../../routes/urls'; import { getClaimById } from 'modules/utilityService'; +import { deleteDraftClaimFromStore, generateRedisKey, getCaseDataFromStore } from 'modules/draft-store/draftStoreService'; +import { AppRequest } from 'common/models/AppRequest'; + export const claimantIntentGuard = ( req: Request, res: Response, @@ -10,7 +13,16 @@ export const claimantIntentGuard = ( ) => { (async () => { try { - const caseData: Claim = await getClaimById(req.params.id, req, true); + const redisClaimId = generateRedisKey(req as AppRequest); + let caseData: Claim = await getCaseDataFromStore(redisClaimId, true); + + // Delete cache from redis if case state is not AWAITING_APPLICANT_INTENTION. + // Giving a chance to reload data from ccd database. + if(!caseData.isEmpty() && !caseData.isClaimantIntentionPending()) { + await deleteDraftClaimFromStore(redisClaimId); + } + + caseData = await getClaimById(req.params.id, req, true); if (caseData.isClaimantIntentionPending() || req.originalUrl.includes('claimant-response/confirmation')) { next(); } else { diff --git a/src/test/unit/routes/guards/claimantIntentGuard.test.ts b/src/test/unit/routes/guards/claimantIntentGuard.test.ts index 723125e43c1..6fc8b8cef9d 100644 --- a/src/test/unit/routes/guards/claimantIntentGuard.test.ts +++ b/src/test/unit/routes/guards/claimantIntentGuard.test.ts @@ -4,42 +4,59 @@ import { Claim } from 'common/models/claim'; import { getClaimById } from 'modules/utilityService'; import { constructResponseUrlWithIdParams } from 'common/utils/urlFormatter'; import { CLAIMANT_RESPONSE_CONFIRMATION_URL, DASHBOARD_CLAIMANT_URL } from 'routes/urls'; +import * as draftStoreService from '../../../../main/modules/draft-store/draftStoreService'; + +jest.mock('../../../../main/modules/draft-store'); +jest.mock('../../../../main/modules/draft-store/draftStoreService'); jest.mock('modules/utilityService', () => ({ getClaimById: jest.fn(), + getRedisStoreForSession: jest.fn(), + deleteDraftClaimFromStore: jest.fn(), })); + describe('claimantIntentGuard', () => { let req: Partial; let res: Partial & { redirect: jest.Mock }; let next: jest.Mock; + + const mockGetCaseData = draftStoreService.getCaseDataFromStore as jest.Mock; + const caseStoreData = new Claim(); + beforeEach(() => { req = {params: {id: '123'}, originalUrl: 'test' }; res = { redirect: jest.fn() }; next = jest.fn(); + mockGetCaseData.mockImplementation(async () => { + return caseStoreData; + }); }); + it('should call next if isClaimantIntentionPending returns true', async () => { const claim: Partial = { isClaimantIntentionPending: jest.fn().mockReturnValue(true), }; - (getClaimById as jest.Mock).mockResolvedValueOnce(claim as Claim); + (getClaimById as jest.Mock).mockResolvedValue(claim as Claim); await claimantIntentGuard(req as Request, res as Response, next); expect(next).toHaveBeenCalled(); expect(res.redirect).not.toHaveBeenCalled(); }); + it('should call next if isClaimantIntentionPending returns false but it`s claimant response confirmation page', async () => { const claim: Partial = { isClaimantIntentionPending: jest.fn().mockReturnValue(false), }; - (getClaimById as jest.Mock).mockResolvedValueOnce(claim as Claim); + (getClaimById as jest.Mock).mockResolvedValue(claim as Claim); req.originalUrl = CLAIMANT_RESPONSE_CONFIRMATION_URL; await claimantIntentGuard(req as Request, res as Response, next); expect(next).toHaveBeenCalled(); expect(res.redirect).not.toHaveBeenCalled(); }); + it('should redirect if isClaimantIntentionPending returns false', async () => { - const claim = { + const claim : Partial = { isClaimantIntentionPending: jest.fn().mockReturnValue(false), }; - (getClaimById as jest.Mock).mockResolvedValueOnce(claim); + (getClaimById as jest.Mock).mockResolvedValue(claim as Claim); const redirectUrl = constructResponseUrlWithIdParams( req.params.id, DASHBOARD_CLAIMANT_URL, @@ -47,9 +64,10 @@ describe('claimantIntentGuard', () => { await claimantIntentGuard(req as Request, res as Response, next); expect(res.redirect).toHaveBeenCalledWith(redirectUrl); }); + it('should pass the error to next if there is an exception', async () => { const error = new Error('Test error'); - (getClaimById as jest.Mock).mockRejectedValueOnce(error); + (getClaimById as jest.Mock).mockResolvedValue(error); await claimantIntentGuard(req as Request, res as Response, next); expect(next).toHaveBeenCalledWith(error); }); From bb093537216241e97cdeb09e687350a2eb0d8be7 Mon Sep 17 00:00:00 2001 From: Manish Garg Date: Wed, 17 Jul 2024 11:02:07 +0100 Subject: [PATCH 5/8] CIV-14636 Removed redis cache in claimant Intent Guard --- src/main/routes/guards/claimantIntentGuard.ts | 62 +++++++++---------- .../routes/guards/claimantIntentGuard.test.ts | 26 +++++--- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/src/main/routes/guards/claimantIntentGuard.ts b/src/main/routes/guards/claimantIntentGuard.ts index 27fda188640..fc85b0d7e1d 100644 --- a/src/main/routes/guards/claimantIntentGuard.ts +++ b/src/main/routes/guards/claimantIntentGuard.ts @@ -1,40 +1,34 @@ -import { NextFunction, Request, Response } from 'express'; -import { Claim } from '../../common/models/claim'; +import { NextFunction,Request, Response } from 'express'; import { constructResponseUrlWithIdParams } from '../../common/utils/urlFormatter'; import { DASHBOARD_CLAIMANT_URL } from '../../routes/urls'; import { getClaimById } from 'modules/utilityService'; -import { deleteDraftClaimFromStore, generateRedisKey, getCaseDataFromStore } from 'modules/draft-store/draftStoreService'; +import {deleteDraftClaimFromStore, generateRedisKey, getCaseDataFromStore } from 'modules/draft-store/draftStoreService'; import { AppRequest } from 'common/models/AppRequest'; +import { Claim } from 'common/models/claim'; -export const claimantIntentGuard = ( - req: Request, - res: Response, - next: NextFunction, -) => { - (async () => { - try { - const redisClaimId = generateRedisKey(req as AppRequest); - let caseData: Claim = await getCaseDataFromStore(redisClaimId, true); - - // Delete cache from redis if case state is not AWAITING_APPLICANT_INTENTION. - // Giving a chance to reload data from ccd database. - if(!caseData.isEmpty() && !caseData.isClaimantIntentionPending()) { - await deleteDraftClaimFromStore(redisClaimId); - } - - caseData = await getClaimById(req.params.id, req, true); - if (caseData.isClaimantIntentionPending() || req.originalUrl.includes('claimant-response/confirmation')) { - next(); - } else { - res.redirect( - constructResponseUrlWithIdParams( - req.params.id, - DASHBOARD_CLAIMANT_URL, - ), - ); - } - } catch (error) { - next(error); +export const claimantIntentGuard = (async (req: Request, res: Response, next: NextFunction) => { + try { + const redisClaimId = generateRedisKey(req as AppRequest); + const caseStoreData: Claim = await getCaseDataFromStore(redisClaimId, true); + + // Delete cache from redis if case state is not AWAITING_APPLICANT_INTENTION. + // Giving a chance to reload data from ccd database. + if(!caseStoreData.isEmpty() && !caseStoreData.isClaimantIntentionPending()) { + await deleteDraftClaimFromStore(redisClaimId); + } + + const caseData = await getClaimById(req.params.id, req, true); + if (caseData.isClaimantIntentionPending() || req.originalUrl.includes('claimant-response/confirmation')) { + next(); + } else { + res.redirect( + constructResponseUrlWithIdParams( + req.params.id, + DASHBOARD_CLAIMANT_URL, + ), + ); } - })(); -}; + } catch (error) { + next(error); + } +}); diff --git a/src/test/unit/routes/guards/claimantIntentGuard.test.ts b/src/test/unit/routes/guards/claimantIntentGuard.test.ts index 6fc8b8cef9d..6e4f8f109fc 100644 --- a/src/test/unit/routes/guards/claimantIntentGuard.test.ts +++ b/src/test/unit/routes/guards/claimantIntentGuard.test.ts @@ -4,14 +4,16 @@ import { Claim } from 'common/models/claim'; import { getClaimById } from 'modules/utilityService'; import { constructResponseUrlWithIdParams } from 'common/utils/urlFormatter'; import { CLAIMANT_RESPONSE_CONFIRMATION_URL, DASHBOARD_CLAIMANT_URL } from 'routes/urls'; -import * as draftStoreService from '../../../../main/modules/draft-store/draftStoreService'; +import { getCaseDataFromStore } from 'modules/draft-store/draftStoreService'; -jest.mock('../../../../main/modules/draft-store'); -jest.mock('../../../../main/modules/draft-store/draftStoreService'); -jest.mock('modules/utilityService', () => ({ +jest.mock('../../../../main/modules/utilityService', () => ({ getClaimById: jest.fn(), getRedisStoreForSession: jest.fn(), +})); +jest.mock('../../../../main/modules/draft-store/draftStoreService', () => ({ + getCaseDataFromStore: jest.fn(), deleteDraftClaimFromStore: jest.fn(), + generateRedisKey:jest.fn, })); describe('claimantIntentGuard', () => { @@ -19,22 +21,22 @@ describe('claimantIntentGuard', () => { let res: Partial & { redirect: jest.Mock }; let next: jest.Mock; - const mockGetCaseData = draftStoreService.getCaseDataFromStore as jest.Mock; - const caseStoreData = new Claim(); + const caseStoreData: Partial = { + isClaimantIntentionPending: jest.fn().mockReturnValue(true), + isEmpty: jest.fn().mockReturnValue(true), + }; beforeEach(() => { req = {params: {id: '123'}, originalUrl: 'test' }; res = { redirect: jest.fn() }; next = jest.fn(); - mockGetCaseData.mockImplementation(async () => { - return caseStoreData; - }); }); it('should call next if isClaimantIntentionPending returns true', async () => { const claim: Partial = { isClaimantIntentionPending: jest.fn().mockReturnValue(true), }; + (getCaseDataFromStore as jest.Mock).mockResolvedValue(caseStoreData as Claim); (getClaimById as jest.Mock).mockResolvedValue(claim as Claim); await claimantIntentGuard(req as Request, res as Response, next); expect(next).toHaveBeenCalled(); @@ -56,6 +58,8 @@ describe('claimantIntentGuard', () => { const claim : Partial = { isClaimantIntentionPending: jest.fn().mockReturnValue(false), }; + + (getCaseDataFromStore as jest.Mock).mockResolvedValue(caseStoreData as Claim); (getClaimById as jest.Mock).mockResolvedValue(claim as Claim); const redirectUrl = constructResponseUrlWithIdParams( req.params.id, @@ -67,7 +71,9 @@ describe('claimantIntentGuard', () => { it('should pass the error to next if there is an exception', async () => { const error = new Error('Test error'); - (getClaimById as jest.Mock).mockResolvedValue(error); + + (getCaseDataFromStore as jest.Mock).mockResolvedValue(caseStoreData as Claim); + (getClaimById as jest.Mock).mockRejectedValue(error); await claimantIntentGuard(req as Request, res as Response, next); expect(next).toHaveBeenCalledWith(error); }); From 76bc392a73e19d1298d23c69f727135fd6f9209b Mon Sep 17 00:00:00 2001 From: Manish Garg Date: Wed, 17 Jul 2024 12:04:04 +0100 Subject: [PATCH 6/8] CIV-14636 Updated CLaimantIntent guard for redis cache --- src/main/routes/guards/claimantIntentGuard.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/routes/guards/claimantIntentGuard.ts b/src/main/routes/guards/claimantIntentGuard.ts index fc85b0d7e1d..be905c9cf40 100644 --- a/src/main/routes/guards/claimantIntentGuard.ts +++ b/src/main/routes/guards/claimantIntentGuard.ts @@ -13,7 +13,7 @@ export const claimantIntentGuard = (async (req: Request, res: Response, next: Ne // Delete cache from redis if case state is not AWAITING_APPLICANT_INTENTION. // Giving a chance to reload data from ccd database. - if(!caseStoreData.isEmpty() && !caseStoreData.isClaimantIntentionPending()) { + if(caseStoreData && !caseStoreData.isEmpty() && !caseStoreData.isClaimantIntentionPending()) { await deleteDraftClaimFromStore(redisClaimId); } From ac4716436865df66fbe1c5fdcace01a0a1ba3b8f Mon Sep 17 00:00:00 2001 From: Manish Garg Date: Wed, 17 Jul 2024 12:55:21 +0100 Subject: [PATCH 7/8] CIV-14636 fixed unit tests --- .../repaymentPlanAcceptedController.test.ts | 7 +++++++ .../signSettlmentAgreementController.test.ts | 1 + 2 files changed, 8 insertions(+) diff --git a/src/test/unit/routes/features/claimantResponse/repaymentPlanAcceptedController.test.ts b/src/test/unit/routes/features/claimantResponse/repaymentPlanAcceptedController.test.ts index 729d61fb77e..5c063ce4a9d 100644 --- a/src/test/unit/routes/features/claimantResponse/repaymentPlanAcceptedController.test.ts +++ b/src/test/unit/routes/features/claimantResponse/repaymentPlanAcceptedController.test.ts @@ -10,6 +10,13 @@ jest.mock('modules/utilityService', () => ({ getClaimById: jest.fn().mockResolvedValue({ isClaimantIntentionPending: () => true }), getRedisStoreForSession: jest.fn(), })); + +jest.mock('modules/draft-store/draftStoreService', () => ({ + getCaseDataFromStore: jest.fn().mockResolvedValue({ isClaimantIntentionPending: () => true,isEmpty: jest.fn().mockReturnValue(true), }), + deleteDraftClaimFromStore: jest.fn(), + generateRedisKey:jest.fn, +})); + describe('Claimant Response - Rejection reason', () => { const citizenRoleToken: string = config.get('citizenRoleToken'); const idamUrl: string = config.get('idamUrl'); diff --git a/src/test/unit/routes/features/claimantResponse/signSettlmentAgreementController.test.ts b/src/test/unit/routes/features/claimantResponse/signSettlmentAgreementController.test.ts index 52f2d1c1d27..4e1a168657a 100644 --- a/src/test/unit/routes/features/claimantResponse/signSettlmentAgreementController.test.ts +++ b/src/test/unit/routes/features/claimantResponse/signSettlmentAgreementController.test.ts @@ -105,6 +105,7 @@ describe('Sign Settlement Agreement', () => { app.locals.draftStoreClient = { set: jest.fn(() => Promise.resolve({})), get: jest.fn(() => Promise.resolve(JSON.stringify(civilClaimResponseMock))), + del: jest.fn(() => Promise.resolve({})), }; await request(app).get(CLAIMANT_SIGN_SETTLEMENT_AGREEMENT).expect((res) => { From 7c8241677cdc732be8a00911cca46d6cbc521bd1 Mon Sep 17 00:00:00 2001 From: Manish Garg Date: Wed, 17 Jul 2024 13:13:56 +0100 Subject: [PATCH 8/8] CIV-14636 Fixed formatting issue --- .../claimantResponse/repaymentPlanAcceptedController.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/unit/routes/features/claimantResponse/repaymentPlanAcceptedController.test.ts b/src/test/unit/routes/features/claimantResponse/repaymentPlanAcceptedController.test.ts index 5c063ce4a9d..83fbf0f786d 100644 --- a/src/test/unit/routes/features/claimantResponse/repaymentPlanAcceptedController.test.ts +++ b/src/test/unit/routes/features/claimantResponse/repaymentPlanAcceptedController.test.ts @@ -12,7 +12,7 @@ jest.mock('modules/utilityService', () => ({ })); jest.mock('modules/draft-store/draftStoreService', () => ({ - getCaseDataFromStore: jest.fn().mockResolvedValue({ isClaimantIntentionPending: () => true,isEmpty: jest.fn().mockReturnValue(true), }), + getCaseDataFromStore: jest.fn().mockResolvedValue({ isClaimantIntentionPending: () => true,isEmpty: jest.fn().mockReturnValue(true) }), deleteDraftClaimFromStore: jest.fn(), generateRedisKey:jest.fn, }));