From 77d9bef8bd96bab06ec30ddac38621ef2913b19e Mon Sep 17 00:00:00 2001 From: jeswanth Date: Tue, 9 Jul 2024 14:19:59 +0100 Subject: [PATCH 01/17] added code for upload submit functinality --- .../models/gaEvents/applicationEvent.ts | 1 + src/main/common/models/gaEvents/eventDto.ts | 38 +++++--- .../generalApplication/GeneralApplication.ts | 2 + .../UploadAdditionalDocument.ts | 19 ++++ src/main/modules/i18n/locales/cy.json | 3 + src/main/modules/i18n/locales/en.json | 8 ++ .../checkAnswersController.ts | 65 ++++++++++++++ .../uploadAdditionalDocumentsController.ts | 83 ++++++++++++++++++ src/main/routes/routes.ts | 4 + src/main/routes/urls.ts | 2 + .../additionalDocuments/check-answers.njk | 51 +++++++++++ .../upload-additional-documents.njk | 87 +++++++++++++++++++ 12 files changed, 353 insertions(+), 10 deletions(-) create mode 100644 src/main/common/models/generalApplication/UploadAdditionalDocument.ts create mode 100644 src/main/routes/features/generalApplication/additionalDocuments/checkAnswersController.ts create mode 100644 src/main/routes/features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.ts create mode 100644 src/main/views/features/generalApplication/additionalDocuments/check-answers.njk create mode 100644 src/main/views/features/generalApplication/additionalDocuments/upload-additional-documents.njk diff --git a/src/main/common/models/gaEvents/applicationEvent.ts b/src/main/common/models/gaEvents/applicationEvent.ts index ffbc23ade91..e523ecc5057 100644 --- a/src/main/common/models/gaEvents/applicationEvent.ts +++ b/src/main/common/models/gaEvents/applicationEvent.ts @@ -1,3 +1,4 @@ export enum ApplicationEvent { // TODO: Add events here for use by GA client + UPLOAD_ADDL_DOCUMENTS = 'UPLOAD_ADDL_DOCUMENTS', } diff --git a/src/main/common/models/gaEvents/eventDto.ts b/src/main/common/models/gaEvents/eventDto.ts index dbeab10ff25..4aa14326430 100644 --- a/src/main/common/models/gaEvents/eventDto.ts +++ b/src/main/common/models/gaEvents/eventDto.ts @@ -24,15 +24,33 @@ export interface EventDto { } export interface CCDGeneralApplication extends ClaimUpdate { - generalAppType: CcdGeneralApplicationTypes; - generalAppRespondentAgreement: CcdGeneralApplicationRespondentAgreement; - generalAppInformOtherParty: CcdGeneralApplicationInformOtherParty; - generalAppAskForCosts: YesNoUpperCamelCase; - generalAppDetailsOfOrder: string; - generalAppReasonsOfOrder: string; - generalAppEvidenceDocument: CcdGeneralApplicationEvidenceDocument[]; - generalAppHearingDetails: CcdGeneralApplicationHearingDetails; - generalAppStatementOfTruth: CcdGeneralApplicationStatementOfTruth; - generalAppHelpWithFees: CCDHelpWithFees; + generalAppType?: CcdGeneralApplicationTypes; + generalAppRespondentAgreement?: CcdGeneralApplicationRespondentAgreement; + generalAppInformOtherParty?: CcdGeneralApplicationInformOtherParty; + generalAppAskForCosts?: YesNoUpperCamelCase; + generalAppDetailsOfOrder?: string; + generalAppReasonsOfOrder?: string; + generalAppEvidenceDocument?: CcdGeneralApplicationEvidenceDocument[]; + generalAppHearingDetails?: CcdGeneralApplicationHearingDetails; + generalAppStatementOfTruth?: CcdGeneralApplicationStatementOfTruth; + generalAppHelpWithFees?: CCDHelpWithFees; caseLink?: CaseLink; + uploadDocument?: AdditionDocDetails[] } +interface Document { + documentUrl: string; + documentBinaryUrl: string; + documentFileName: string; + documentHash?: string; + categoryID?: string; + uploadTimestamp?: string; +} + +interface AdditionDocDetails { + documentType: string, + additionalDocument: Document +} + +// export interface AdditionalDocuments { + +// } diff --git a/src/main/common/models/generalApplication/GeneralApplication.ts b/src/main/common/models/generalApplication/GeneralApplication.ts index cf86ba93460..81e95caf01e 100644 --- a/src/main/common/models/generalApplication/GeneralApplication.ts +++ b/src/main/common/models/generalApplication/GeneralApplication.ts @@ -14,6 +14,7 @@ import {GaResponse} from 'models/generalApplication/response/gaResponse'; import {GaHelpWithFees} from 'models/generalApplication/gaHelpWithFees'; import {PaymentInformation} from 'models/feePayment/paymentInformation'; import {CaseLink} from 'models/generalApplication/CaseLink'; +import { UploadAdditionalDocument } from './UploadAdditionalDocument'; export class GeneralApplication { @@ -36,6 +37,7 @@ export class GeneralApplication { helpWithFees?: GaHelpWithFees; applicationFeePaymentDetails : PaymentInformation; caseLink?: CaseLink; + uploadAdditionalDocuments?: UploadAdditionalDocument[] = []; constructor( applicationType?: ApplicationType, diff --git a/src/main/common/models/generalApplication/UploadAdditionalDocument.ts b/src/main/common/models/generalApplication/UploadAdditionalDocument.ts new file mode 100644 index 00000000000..e147d42960c --- /dev/null +++ b/src/main/common/models/generalApplication/UploadAdditionalDocument.ts @@ -0,0 +1,19 @@ +import { IsNotEmpty, ValidateIf, ValidateNested } from 'class-validator'; +import { FileUpload } from '../caseProgression/uploadDocumentsUserForm'; +import { CaseDocument } from '../document/caseDocument'; + +export class UploadAdditionalDocument { + @ValidateNested() + @ValidateIf((object) => object.caseDocument === undefined || object.caseDocument === null || object.caseDocument === '') + @IsNotEmpty({ message: 'ERRORS.GENERAL_APPLICATION.UPLOAD_FILE_MESSAGE' }) + fileUpload: FileUpload; + caseDocument: CaseDocument; + + @IsNotEmpty({ message: 'You need to tell us what type of document you are uploading.' }) + typeOfDocument: string; + + constructor(fileUpload?: FileUpload) { + this.fileUpload = fileUpload; + } + +} \ No newline at end of file diff --git a/src/main/modules/i18n/locales/cy.json b/src/main/modules/i18n/locales/cy.json index 013165d8f4d..831c5f9c61a 100644 --- a/src/main/modules/i18n/locales/cy.json +++ b/src/main/modules/i18n/locales/cy.json @@ -2369,6 +2369,9 @@ "WHY_NOT_ACCEPT": "Why do you not accept the defendant's offer?", "WHY_NOT_ACCEPT_2": "Why you do not accept the defendant's offer?" }, + "ADDITIONAL_DOCUMENTS": { + "ADDITIONAL_DOCUMENTS_CAPTION": "Upload additional documents" + }, "AGREE_TO_ORDER": { "MADE_AWARE": "If you have not been made aware of this application by the other parties, select 'No'.", "RESPOND_TO": "Respond to an application to {{applicationType}}", diff --git a/src/main/modules/i18n/locales/en.json b/src/main/modules/i18n/locales/en.json index d2a0ac0837a..03b11bd6b46 100644 --- a/src/main/modules/i18n/locales/en.json +++ b/src/main/modules/i18n/locales/en.json @@ -2369,6 +2369,14 @@ "WHY_NOT_ACCEPT": "Why do you not accept the defendant's offer?", "WHY_NOT_ACCEPT_2": "Why you do not accept the defendant's offer?" }, + "ADDITIONAL_DOCUMENTS": { + "ADDITIONAL_DOCUMENTS_CAPTION": "Upload additional documents", + "UPLOAD_DOCUMENTS_TITLE": "Upload documents", + "ADDITIONAL_DOCUMENTS_ROW1": "You should only upload documents that are relevant to your application, for example if the judge has ordered a hearing and instructed you to provide documents ahead of this.", + "ADDITIONAL_DOCUMENTS_ROW2": "Before you upload the document you will need to describe the type of document you are uploading, for example, Bundle, witness statement or costs schedule.", + "TYPE_OF_DOCUMENT": "Type of document", + "TYPE_OF_DOCUMENT_HINT": "For example, contract, invoice receipt, email, text message, photo, social media message" + }, "AGREE_TO_ORDER": { "MADE_AWARE": "If you have not been made aware of this application by the other parties, select 'No'.", "RESPOND_TO": "Respond to an application to {{applicationType}}", diff --git a/src/main/routes/features/generalApplication/additionalDocuments/checkAnswersController.ts b/src/main/routes/features/generalApplication/additionalDocuments/checkAnswersController.ts new file mode 100644 index 00000000000..14e8c2e99e7 --- /dev/null +++ b/src/main/routes/features/generalApplication/additionalDocuments/checkAnswersController.ts @@ -0,0 +1,65 @@ +import { AppRequest } from 'common/models/AppRequest'; +import { GeneralApplication } from 'common/models/generalApplication/GeneralApplication'; +import { UploadAdditionalDocument } from 'common/models/generalApplication/UploadAdditionalDocument'; +import { SummaryRow, summaryRow } from 'common/models/summaryList/summaryList'; +import { changeLabel } from 'common/utils/checkYourAnswer/changeButton'; +import { caseNumberPrettify } from 'common/utils/stringUtils'; +import { NextFunction, RequestHandler, Response, Router } from 'express'; +import { getClaimById } from 'modules/utilityService'; +import config from 'config'; +import { GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL } from 'routes/urls'; +import { GaServiceClient } from 'client/gaServiceClient'; +import { ApplicationEvent } from 'common/models/gaEvents/applicationEvent'; + +const gaAdditionalDocCheckAnswerController = Router(); +const viewPath = 'features/generalApplication/additionalDocuments/check-answers'; +const generalAppApiBaseUrl = config.get('services.generalApplication.url'); +const gaServiceClient: GaServiceClient = new GaServiceClient(generalAppApiBaseUrl); + +gaAdditionalDocCheckAnswerController.get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, (async (req: AppRequest, res: Response, next: NextFunction) => { + try { + const { gaId, id } = req.params + const claim = await getClaimById(id, req, true); + const claimIdPrettified = caseNumberPrettify(id); + const gaApplication = Object.assign(new GeneralApplication(), claim.generalApplication) + // const formattedSummary = getSummaryList(gaApplication.uploadAdditionalDocuments, id, gaId) + // const lang = req.query.lang ? req.query.lang : req.cookies.lang; + const summaryRows = buildSummarySection(gaApplication.uploadAdditionalDocuments, id, gaId) + res.render(viewPath, { claimIdPrettified, claim, summaryRows }); + } catch (error) { + next(error); + } +}) as RequestHandler) + +gaAdditionalDocCheckAnswerController.post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, (async (req: AppRequest, res: Response, next: NextFunction) => { + + const { gaId, id } = req.params; + console.log(gaId); + const claim = await getClaimById(id, req, true); + const gaApplication = Object.assign(new GeneralApplication(), claim.generalApplication); + const uploadedDocuments = gaApplication.uploadAdditionalDocuments.map(doc => { + + return { + documentType: doc.typeOfDocument, + additionalDocument: { + documentUrl: doc.caseDocument.documentLink.document_url, + documentBinaryUrl: doc.caseDocument.documentLink.document_binary_url, + documentFileName: doc.caseDocument.documentName, + } + } + + }) + const data = await gaServiceClient.submitEvent(ApplicationEvent.UPLOAD_ADDL_DOCUMENTS, gaId, { uploadDocument: uploadedDocuments }, req); + console.log(data); + +}) as RequestHandler); +const buildSummarySection = (additionalDocumentsList: UploadAdditionalDocument[], claimId: string, gaId: string) => { + const rows: SummaryRow[] = [] + additionalDocumentsList.forEach(doc => { + rows.push(summaryRow('Type of document', doc.typeOfDocument)); + rows.push(summaryRow('Uploaded document', doc.caseDocument.documentName, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId), changeLabel('en'))) + }) + return rows; +} + +export default gaAdditionalDocCheckAnswerController; \ No newline at end of file diff --git a/src/main/routes/features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.ts b/src/main/routes/features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.ts new file mode 100644 index 00000000000..5395df7515b --- /dev/null +++ b/src/main/routes/features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.ts @@ -0,0 +1,83 @@ +import { GenericForm } from 'common/form/models/genericForm'; +import { AppRequest } from 'common/models/AppRequest'; +import { NextFunction, RequestHandler, Response, Router } from 'express'; +import { GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL } from 'routes/urls'; +import multer from 'multer'; +import { UploadAdditionalDocument } from 'common/models/generalApplication/UploadAdditionalDocument'; +import { TypeOfDocumentSectionMapper } from 'services/features/caseProgression/TypeOfDocumentSectionMapper'; +import config from 'config'; +import { CivilServiceClient } from 'client/civilServiceClient'; +import { getClaimById } from 'modules/utilityService'; +import { GeneralApplication } from 'common/models/generalApplication/GeneralApplication'; +import { generateRedisKey, saveDraftClaim } from 'modules/draft-store/draftStoreService'; +import { SummarySection, summarySection } from 'common/models/summaryList/summarySections'; +import { summaryRow } from 'common/models/summaryList/summaryList'; +import { constructResponseUrlWithIdParams } from 'common/utils/urlFormatter'; + +const uploadAdditionalDocumentsController = Router(); +const viewPath = 'features/generalApplication/additionalDocuments/upload-additional-documents'; +const civilServiceApiBaseUrl = config.get('services.civilService.url'); +const civilServiceClientForDocRetrieve: CivilServiceClient = new CivilServiceClient(civilServiceApiBaseUrl, true); +const fileSize = Infinity; +const upload = multer({ + limits: { + fileSize: fileSize, + }, +}); + +uploadAdditionalDocumentsController.get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL, (async (req: AppRequest, res: Response, next: NextFunction) => { + console.log(req.params) + const { gaId, id } = req.params + const uploadedDocument = + new UploadAdditionalDocument(); + let form = new GenericForm(uploadedDocument); + const claim = await getClaimById(id, req, true) + const gaApplication = Object.assign(new GeneralApplication(), claim.generalApplication) + const formattedSummary = getSummaryList(gaApplication.uploadAdditionalDocuments, id, gaId) + + res.render(viewPath, { form, formattedSummary }) + +}) as RequestHandler) + +uploadAdditionalDocumentsController.post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL, upload.single('selectedFile'), (async (req: AppRequest, res: Response, next: NextFunction) => { + const { gaId, id } = req.params + const currentUrl = GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', id).replace(':gaId', gaId) + const uploadedDocument = new UploadAdditionalDocument(); + + //let form = new GenericForm(uploadedDocument); + if (req.body.action === 'uploadButton') { + const fileUpload = TypeOfDocumentSectionMapper.mapToSingleFile(req); + uploadedDocument.fileUpload = fileUpload; + uploadedDocument.typeOfDocument = req.body.typeOfDocument; + const form = new GenericForm(uploadedDocument); + form.validateSync() + if (!form.hasErrors()) { + uploadedDocument.caseDocument = await civilServiceClientForDocRetrieve.uploadDocument(req, fileUpload); + const claim = await getClaimById(id, req, true) + const gaApplication = Object.assign(new GeneralApplication(), claim.generalApplication) + gaApplication.uploadAdditionalDocuments.push(uploadedDocument); + claim.generalApplication = gaApplication; + await saveDraftClaim(generateRedisKey(req), claim); + return res.redirect(`${currentUrl}`); + } + //await uploadSelectedFile(req, formattedSummary, claimId); + + } + res.redirect(constructResponseUrlWithIdParams(id, GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL).replace(':gaId', gaId)); +})) + +export const getSummaryList = (additionalDocumentsList: UploadAdditionalDocument[], claimId: string, gaId: string): SummarySection => { + let index = 0; + const formattedSummary = summarySection( + { + title: '', + summaryRows: [], + }); + additionalDocumentsList.forEach((uploadDocument: UploadAdditionalDocument) => { + index = index + 1; + formattedSummary.summaryList.rows.push(summaryRow('Type of document', uploadDocument.typeOfDocument)); + formattedSummary.summaryList.rows.push(summaryRow(uploadDocument.caseDocument.documentName, '', `${GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)}+ '?id=' + ${index}`, 'Remove document')); + }); + return formattedSummary +}; +export default uploadAdditionalDocumentsController; \ No newline at end of file diff --git a/src/main/routes/routes.ts b/src/main/routes/routes.ts index e5c166ca4ec..2059a348573 100644 --- a/src/main/routes/routes.ts +++ b/src/main/routes/routes.ts @@ -381,6 +381,8 @@ import whyNotSubjectToFRCController from 'routes/features/directionsQuestionnaire/fixedRecoverableCosts/whyNotSubjectToFRCController'; import backController from 'routes/common/backController'; import applicationFeePaymentConfirmationController from './features/generalApplication/payment/applicationFeePaymentConfirmationController'; +import uploadAdditionalDocumentsController from './features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController'; +import gaAdditionalDocCheckAnswerController from './features/generalApplication/additionalDocuments/checkAnswersController'; export default [ homeController, @@ -693,4 +695,6 @@ export default [ whyNotSubjectToFRCController, backController, applicationFeePaymentConfirmationController, + uploadAdditionalDocumentsController, + gaAdditionalDocCheckAnswerController ]; diff --git a/src/main/routes/urls.ts b/src/main/routes/urls.ts index e7541a2c412..e809296d264 100644 --- a/src/main/routes/urls.ts +++ b/src/main/routes/urls.ts @@ -359,3 +359,5 @@ export const FRC_BAND_AGREED_URL = `${DIRECTIONS_QUESTIONNAIRE_URL}/frc-band-agr export const ASSIGN_FRC_BAND_URL = `${DIRECTIONS_QUESTIONNAIRE_URL}/assign-complexity-band`; export const REASON_FOR_FRC_BAND_URL = `${DIRECTIONS_QUESTIONNAIRE_URL}/reason-for-complexity-band`; export const WHY_NOT_SUBJECT_TO_FRC_URL = `${DIRECTIONS_QUESTIONNAIRE_URL}/why-not-subject-to-frc`; +export const GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL = `${BASE_GENERAL_APPLICATION_URL}/:gaId/upload-additional-documents` +export const GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL = `${BASE_GENERAL_APPLICATION_URL}/:gaId/upload-additional-documents/check-and-send` diff --git a/src/main/views/features/generalApplication/additionalDocuments/check-answers.njk b/src/main/views/features/generalApplication/additionalDocuments/check-answers.njk new file mode 100644 index 00000000000..c7a52e2d526 --- /dev/null +++ b/src/main/views/features/generalApplication/additionalDocuments/check-answers.njk @@ -0,0 +1,51 @@ +{% extends "claim-details-tpl-dashboard.njk" %} +{% from "govuk/components/summary-list/macro.njk" import govukSummaryList %} +{% from "govuk/components/input/macro.njk" import govukInput %} +{% from "govuk/components/button/macro.njk" import govukButton %} +{% from "../../../macro/ga-statement-of-truth.njk" import statementOfTruth %} +{% from "../../../macro/heading-with-caption.njk" import headingWithCaption %} +{% from "../../../macro/page-title.njk" import setPageTitle %} +{% from "../../../macro/csrf.njk" import csrfProtection %} + +{% block pageTitle %} + {{ setPageTitle(t, 'PAGES.CHECK_YOUR_ANSWER.TITLE') }} +{% endblock %} + +{% set submitText = t('COMMON.BUTTONS.SUBMIT_CLAIM') %} +{% set labelHtml = t('PAGES.GENERAL_APPLICATION.CHECK_YOUR_ANSWER.STATEMENT_OF_TRUTH.CHECKBOX') + + '

' + + t('PAGES.CHECK_YOUR_ANSWER.CLAIM_CHECKBOX_PROCEEDINGS') + +'

' %} +{% set claimantName = claim.getClaimantFullName() %} +{% set defendantName = claim.getDefendantFullName() %} + +{% block nestedContent %} + {{ headingWithCaption(t,'PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.ADDITIONAL_DOCUMENTS_CAPTION', 'PAGES.CHECK_YOUR_ANSWER.TITLE') }} + {% if claimIdPrettified %} +

+ {{ t('COMMON.CASE_NUMBER') }} + {{ claimIdPrettified }} +

+ {% endif %} + {% if claimantName and defendantName %} +

{{ claimantName }} v {{ defendantName }}

+ {% endif %} + {% if summaryRows %} +
+
+ {{ govukSummaryList({ + rows: summaryRows + }) }} +
+
+ {% endif %} +
+ {{ csrfProtection(csrf) }} +
+ {{ govukButton({ + text: t('COMMON.BUTTONS.SUBMIT') + }) }} + {{ t('COMMON.BUTTONS.CANCEL') }} +
+
+{% endblock %} diff --git a/src/main/views/features/generalApplication/additionalDocuments/upload-additional-documents.njk b/src/main/views/features/generalApplication/additionalDocuments/upload-additional-documents.njk new file mode 100644 index 00000000000..885df29271f --- /dev/null +++ b/src/main/views/features/generalApplication/additionalDocuments/upload-additional-documents.njk @@ -0,0 +1,87 @@ +{% extends "claim-details-tpl-dashboard.njk" %} +{% from "govuk/components/button/macro.njk" import govukButton %} +{% from "govuk/components/summary-list/macro.njk" import govukSummaryList %} +{% from "govuk/components/file-upload/macro.njk" import govukFileUpload %} +{% from "govuk/components/input/macro.njk" import govukInput %} +{% from "../../../macro/page-title.njk" import setPageTitle %} +{% from "../../../macro/csrf.njk" import csrfProtection %} +{% from "../../../macro/heading-with-caption.njk" import headingWithCaption %} +{% from "../../../macro/button.njk" import addButton %} +{% block pageTitle %} + {{ setPageTitle(t, 'PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.UPLOAD_DOCUMENTS_TITLE') }} +{% endblock %} +{% block nestedContent %} + {% set errors = "" %} + {% set idValue = "selectedFile" %} + {% if form.hasErrors() %} + {% set errors = translateErrors(form.getAllErrors(),t)[0] %} + {% set idValue = errors.fieldName %} + {% endif %} + {{ headingWithCaption(t, 'PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.ADDITIONAL_DOCUMENTS_CAPTION', 'PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.UPLOAD_DOCUMENTS_TITLE') }} +

{{ t('PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.ADDITIONAL_DOCUMENTS_ROW1') }}

+

{{ t('PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.ADDITIONAL_DOCUMENTS_ROW2') }}

+

{{ t('PAGES.GENERAL_APPLICATION.UPLOAD_DOCUMENTS.DOCUMENT_TYPE_SIZE') }}

+
+ {{ csrfProtection(csrf) }} +
+ {{ govukInput({ + label: { + text: t('PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.TYPE_OF_DOCUMENT') + }, + hint: { + text: t('PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.TYPE_OF_DOCUMENT_HINT') + }, + id: "typeOfDocument", + name: "typeOfDocument" + }) }} + {{ govukFileUpload({ + id: idValue, + name: "selectedFile", + label: { + html: 'Upload a file' + }, + errorMessage: { text: t(errors.text) } if t(errors.text) else '' + }) }} + {{ govukButton({ + id: 'uploadFileButton', + name: 'action', + value: 'uploadButton', + text: t('COMMON.UPLOAD_FILE'), + classes: "govuk-button--secondary govuk-!-margin-bottom-0" + }) }} +
+ {% if formattedSummary.summaryList.rows.length > 0 %} +

{{ t('PAGES.GENERAL_APPLICATION.UPLOAD_DOCUMENTS.LIST_TITLE') }}

+
+ {% for row in formattedSummary.summaryList.rows %} +
+ {% if row.value.html %} +
+
+ {{ row.key.text }} +
+
+

{{row.value.html}}

+
+
+ {% else %} + + {% endif %} +
+ {% endfor %} + {% endif %} +
+ {{ addButton(t, 'CONTINUE', cancelUrl) }} +
+
+{% endblock %} \ No newline at end of file From af020aeb238fe1cf0c3fd5f64f36f91387b489fd Mon Sep 17 00:00:00 2001 From: jeswanth Date: Thu, 11 Jul 2024 15:54:48 +0100 Subject: [PATCH 02/17] CIV-14228 added code for additional documents --- src/main/common/models/gaEvents/eventDto.ts | 26 ++--- .../UploadAdditionalDocument.ts | 2 +- src/main/modules/i18n/locales/en.json | 6 +- .../checkAnswersController.ts | 38 +++--- .../submittedController.ts | 45 ++++++++ .../uploadAdditionalDocumentsController.ts | 108 +++++++++++++----- .../viewApplicationController.ts | 6 +- src/main/routes/routes.ts | 4 +- src/main/routes/urls.ts | 4 +- .../uploadEvidenceDocumentService.ts | 2 +- .../additionalDocuments/submitted.njk | 26 +++++ .../upload-additional-documents.njk | 11 +- .../generalApplication/view-applications.njk | 2 +- 13 files changed, 215 insertions(+), 65 deletions(-) create mode 100644 src/main/routes/features/generalApplication/additionalDocuments/submittedController.ts create mode 100644 src/main/views/features/generalApplication/additionalDocuments/submitted.njk diff --git a/src/main/common/models/gaEvents/eventDto.ts b/src/main/common/models/gaEvents/eventDto.ts index 4aa14326430..ef8041f1a67 100644 --- a/src/main/common/models/gaEvents/eventDto.ts +++ b/src/main/common/models/gaEvents/eventDto.ts @@ -35,21 +35,21 @@ export interface CCDGeneralApplication extends ClaimUpdate { generalAppStatementOfTruth?: CcdGeneralApplicationStatementOfTruth; generalAppHelpWithFees?: CCDHelpWithFees; caseLink?: CaseLink; - uploadDocument?: AdditionDocDetails[] -} -interface Document { - documentUrl: string; - documentBinaryUrl: string; - documentFileName: string; - documentHash?: string; - categoryID?: string; - uploadTimestamp?: string; + uploadDocument?: any[] } +// interface Document { +// documentUrl: string; +// documentBinaryUrl: string; +// documentFileName: string; +// documentHash?: string; +// categoryID?: string; +// uploadTimestamp?: string; +// } -interface AdditionDocDetails { - documentType: string, - additionalDocument: Document -} +// interface AdditionDocDetails { +// documentType: string, +// additionalDocument: Document +// } // export interface AdditionalDocuments { diff --git a/src/main/common/models/generalApplication/UploadAdditionalDocument.ts b/src/main/common/models/generalApplication/UploadAdditionalDocument.ts index e147d42960c..2d95b7c923b 100644 --- a/src/main/common/models/generalApplication/UploadAdditionalDocument.ts +++ b/src/main/common/models/generalApplication/UploadAdditionalDocument.ts @@ -9,7 +9,7 @@ export class UploadAdditionalDocument { fileUpload: FileUpload; caseDocument: CaseDocument; - @IsNotEmpty({ message: 'You need to tell us what type of document you are uploading.' }) + @IsNotEmpty({ message: 'ERRORS.GENERAL_APPLICATION.TYPE_OF_DOC' }) typeOfDocument: string; constructor(fileUpload?: FileUpload) { diff --git a/src/main/modules/i18n/locales/en.json b/src/main/modules/i18n/locales/en.json index 03b11bd6b46..aeb67103c63 100644 --- a/src/main/modules/i18n/locales/en.json +++ b/src/main/modules/i18n/locales/en.json @@ -2375,7 +2375,9 @@ "ADDITIONAL_DOCUMENTS_ROW1": "You should only upload documents that are relevant to your application, for example if the judge has ordered a hearing and instructed you to provide documents ahead of this.", "ADDITIONAL_DOCUMENTS_ROW2": "Before you upload the document you will need to describe the type of document you are uploading, for example, Bundle, witness statement or costs schedule.", "TYPE_OF_DOCUMENT": "Type of document", - "TYPE_OF_DOCUMENT_HINT": "For example, contract, invoice receipt, email, text message, photo, social media message" + "TYPE_OF_DOCUMENT_HINT": "For example, contract, invoice receipt, email, text message, photo, social media message", + "UPLOADED_ADDITIONAL_DOCS": "You've uploaded additional documents", + "JUDGE_WILL_REVIEW": "A judge will review the additional documents that you’ve uploaded. You’ll receive an update with their decision or next steps." }, "AGREE_TO_ORDER": { "MADE_AWARE": "If you have not been made aware of this application by the other parties, select 'No'.", @@ -4674,7 +4676,9 @@ "NEED_TO_TELL": "You need to tell us if you agree that the court should make the order requested by the other party. Choose option Yes or No", "EXPLAIN_WHY_DISAGREE_APPLICATION": "You need to explain why you disagree with the application" }, + "TYPE_OF_DOC": "You need to tell us what type of document you are uploading.", "UPLOAD_FILE_MESSAGE": "You need to choose a file before clicking 'Upload file'", + "UPLOAD_ONE_FILE": "You need to upload at least one file.", "WANT_TO_ADD_ANOTHER_APPLICATION": "You need to tell us if you want to add another application. Choose option: Yes or No", "WANT_TO_UPLOAD_DOCUMENTS_YES_NO_SELECTION": "You need to tell us if you want to upload documents to support your application. Choose option: Yes or No", "WHY_PREFER_THIS_HEARING_TYPE": "You need to tell us why you would prefer this type of hearing" diff --git a/src/main/routes/features/generalApplication/additionalDocuments/checkAnswersController.ts b/src/main/routes/features/generalApplication/additionalDocuments/checkAnswersController.ts index 14e8c2e99e7..1a4b51b5cbf 100644 --- a/src/main/routes/features/generalApplication/additionalDocuments/checkAnswersController.ts +++ b/src/main/routes/features/generalApplication/additionalDocuments/checkAnswersController.ts @@ -7,10 +7,11 @@ import { caseNumberPrettify } from 'common/utils/stringUtils'; import { NextFunction, RequestHandler, Response, Router } from 'express'; import { getClaimById } from 'modules/utilityService'; import config from 'config'; -import { GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL } from 'routes/urls'; +import { GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL } from 'routes/urls'; import { GaServiceClient } from 'client/gaServiceClient'; import { ApplicationEvent } from 'common/models/gaEvents/applicationEvent'; - +import { getCancelUrl } from 'services/features/generalApplication/generalApplicationService'; +const { v4: uuidv4 } = require('uuid'); const gaAdditionalDocCheckAnswerController = Router(); const viewPath = 'features/generalApplication/additionalDocuments/check-answers'; const generalAppApiBaseUrl = config.get('services.generalApplication.url'); @@ -22,37 +23,42 @@ gaAdditionalDocCheckAnswerController.get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, const claim = await getClaimById(id, req, true); const claimIdPrettified = caseNumberPrettify(id); const gaApplication = Object.assign(new GeneralApplication(), claim.generalApplication) - // const formattedSummary = getSummaryList(gaApplication.uploadAdditionalDocuments, id, gaId) - // const lang = req.query.lang ? req.query.lang : req.cookies.lang; + const cancelUrl = await getCancelUrl(id, claim); + const backLinkUrl = GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', id).replace(':gaId', gaId) const summaryRows = buildSummarySection(gaApplication.uploadAdditionalDocuments, id, gaId) - res.render(viewPath, { claimIdPrettified, claim, summaryRows }); + res.render(viewPath, { backLinkUrl, cancelUrl, claimIdPrettified, claim, summaryRows }); } catch (error) { next(error); } }) as RequestHandler) gaAdditionalDocCheckAnswerController.post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, (async (req: AppRequest, res: Response, next: NextFunction) => { - const { gaId, id } = req.params; console.log(gaId); + console.log(id); const claim = await getClaimById(id, req, true); const gaApplication = Object.assign(new GeneralApplication(), claim.generalApplication); const uploadedDocuments = gaApplication.uploadAdditionalDocuments.map(doc => { - return { - documentType: doc.typeOfDocument, - additionalDocument: { - documentUrl: doc.caseDocument.documentLink.document_url, - documentBinaryUrl: doc.caseDocument.documentLink.document_binary_url, - documentFileName: doc.caseDocument.documentName, + id: uuidv4(), + value: { + typeOfDocument: doc.typeOfDocument, + documentUpload: { + document_url: doc.caseDocument.documentLink.document_url, + document_binary_url: doc.caseDocument.documentLink.document_binary_url, + document_filename: doc.caseDocument.documentName, + } + } } - }) - const data = await gaServiceClient.submitEvent(ApplicationEvent.UPLOAD_ADDL_DOCUMENTS, gaId, { uploadDocument: uploadedDocuments }, req); - console.log(data); - + const generalApplication = { + uploadDocument: uploadedDocuments + }; + await gaServiceClient.submitEvent(ApplicationEvent.UPLOAD_ADDL_DOCUMENTS, gaId, generalApplication, req); + res.redirect(GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL.replace(':id', id).replace(':gaId', gaId)); }) as RequestHandler); + const buildSummarySection = (additionalDocumentsList: UploadAdditionalDocument[], claimId: string, gaId: string) => { const rows: SummaryRow[] = [] additionalDocumentsList.forEach(doc => { diff --git a/src/main/routes/features/generalApplication/additionalDocuments/submittedController.ts b/src/main/routes/features/generalApplication/additionalDocuments/submittedController.ts new file mode 100644 index 00000000000..ed71d9e9724 --- /dev/null +++ b/src/main/routes/features/generalApplication/additionalDocuments/submittedController.ts @@ -0,0 +1,45 @@ +import { AppRequest } from 'common/models/AppRequest'; +import { getLng } from 'common/utils/languageToggleUtils'; +import { NextFunction, Response, Router } from 'express'; +import { deleteDraftClaimFromStore, generateRedisKey } from 'modules/draft-store/draftStoreService'; +import { getClaimById } from 'modules/utilityService'; +import { GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL } from 'routes/urls'; +import { PaymentSuccessfulSectionBuilder } from 'services/features/claim/paymentSuccessfulSectionBuilder'; +import { getCancelUrl } from 'services/features/generalApplication/generalApplicationService'; + +const additionalDocSubmittedController = Router(); +const viewPath = 'features/generalApplication/additionalDocuments/submitted' +additionalDocSubmittedController.get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL, async (req: AppRequest, res: Response, next: NextFunction) => { + const lng = req.query.lang ? req.query.lang : req.cookies.lang; + const { id } = req.params + const claim = await getClaimById(id, req, true); + const redisKey = generateRedisKey(req); + await deleteDraftClaimFromStore(redisKey); + res.render(viewPath, { + gaPaymentSuccessfulPanel: getContentForPanel(lng), + gaPaymentSuccessfulBody: getContentForBody(lng), + gaPaymentSuccessfulButton: getContentForCloseButton(await getCancelUrl(id, claim)), + }) +}) + + +const getContentForPanel = (lng: string) => { + const panelBuilder = new PaymentSuccessfulSectionBuilder(); + panelBuilder.addPanelForConfirmation('PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.UPLOADED_ADDITIONAL_DOCS', getLng(lng)); + return panelBuilder.build(); +} + +const getContentForBody = (lng: string) => { + let contentBuilder = new PaymentSuccessfulSectionBuilder(); + return contentBuilder.addTitle('PAGES.GENERAL_APPLICATION.GA_PAYMENT_SUCCESSFUL.WHAT_HAPPENS_NEXT', { lng: getLng(lng) }) + .addParagraph('PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.JUDGE_WILL_REVIEW', { lng: getLng(lng) }) + .build(); +} + +const getContentForCloseButton = (redirectUrl: string) => { + return new PaymentSuccessfulSectionBuilder() + .addButton('COMMON.BUTTONS.CLOSE_AND_RETURN_TO_DASHBOARD', redirectUrl) + .build(); +} + +export default additionalDocSubmittedController; \ No newline at end of file diff --git a/src/main/routes/features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.ts b/src/main/routes/features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.ts index 5395df7515b..88f89440cc8 100644 --- a/src/main/routes/features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.ts +++ b/src/main/routes/features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.ts @@ -1,7 +1,7 @@ import { GenericForm } from 'common/form/models/genericForm'; import { AppRequest } from 'common/models/AppRequest'; import { NextFunction, RequestHandler, Response, Router } from 'express'; -import { GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL } from 'routes/urls'; +import { GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL, GA_VIEW_APPLICATION_URL } from 'routes/urls'; import multer from 'multer'; import { UploadAdditionalDocument } from 'common/models/generalApplication/UploadAdditionalDocument'; import { TypeOfDocumentSectionMapper } from 'services/features/caseProgression/TypeOfDocumentSectionMapper'; @@ -13,8 +13,14 @@ import { generateRedisKey, saveDraftClaim } from 'modules/draft-store/draftStore import { SummarySection, summarySection } from 'common/models/summaryList/summarySections'; import { summaryRow } from 'common/models/summaryList/summaryList'; import { constructResponseUrlWithIdParams } from 'common/utils/urlFormatter'; +import { translateErrors } from 'services/features/generalApplication/uploadEvidenceDocumentService'; +import { t } from 'i18next'; +import { Claim } from 'common/models/claim'; +import { getCancelUrl } from 'services/features/generalApplication/generalApplicationService'; const uploadAdditionalDocumentsController = Router(); +const { Logger } = require('@hmcts/nodejs-logging'); +const logger = Logger.getLogger('claimantResponseService'); const viewPath = 'features/generalApplication/additionalDocuments/upload-additional-documents'; const civilServiceApiBaseUrl = config.get('services.civilService.url'); const civilServiceClientForDocRetrieve: CivilServiceClient = new CivilServiceClient(civilServiceApiBaseUrl, true); @@ -26,44 +32,65 @@ const upload = multer({ }); uploadAdditionalDocumentsController.get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL, (async (req: AppRequest, res: Response, next: NextFunction) => { - console.log(req.params) + try { const { gaId, id } = req.params - const uploadedDocument = - new UploadAdditionalDocument(); + const uploadedDocument = new UploadAdditionalDocument(); let form = new GenericForm(uploadedDocument); + const redisKey = generateRedisKey(req); const claim = await getClaimById(id, req, true) const gaApplication = Object.assign(new GeneralApplication(), claim.generalApplication) - const formattedSummary = getSummaryList(gaApplication.uploadAdditionalDocuments, id, gaId) - - res.render(viewPath, { form, formattedSummary }) + claim.generalApplication = gaApplication; + if (req?.session?.fileUpload) { + const parsedData = JSON.parse(req?.session?.fileUpload); + form = new GenericForm(uploadedDocument, parsedData); + req.session.fileUpload = undefined; + } + if (req.query?.indexId) { + const index = req.query.indexId; + await removeSelectedDocument(redisKey, claim, Number(index) - 1); + } + const cancelUrl = await getCancelUrl(id, claim); + const backLinkUrl = `${constructResponseUrlWithIdParams(id, GA_VIEW_APPLICATION_URL)}?applicationId=${gaId}`; + const formattedSummary = getSummaryList(gaApplication.uploadAdditionalDocuments, id, gaId) + res.render(viewPath, { cancelUrl, backLinkUrl, form, formattedSummary }) + } catch (err) { + next(err); + } }) as RequestHandler) uploadAdditionalDocumentsController.post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL, upload.single('selectedFile'), (async (req: AppRequest, res: Response, next: NextFunction) => { + try { const { gaId, id } = req.params - const currentUrl = GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', id).replace(':gaId', gaId) - const uploadedDocument = new UploadAdditionalDocument(); + const currentUrl = GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', id).replace(':gaId', gaId) - //let form = new GenericForm(uploadedDocument); - if (req.body.action === 'uploadButton') { - const fileUpload = TypeOfDocumentSectionMapper.mapToSingleFile(req); - uploadedDocument.fileUpload = fileUpload; - uploadedDocument.typeOfDocument = req.body.typeOfDocument; - const form = new GenericForm(uploadedDocument); - form.validateSync() - if (!form.hasErrors()) { - uploadedDocument.caseDocument = await civilServiceClientForDocRetrieve.uploadDocument(req, fileUpload); - const claim = await getClaimById(id, req, true) - const gaApplication = Object.assign(new GeneralApplication(), claim.generalApplication) - gaApplication.uploadAdditionalDocuments.push(uploadedDocument); - claim.generalApplication = gaApplication; - await saveDraftClaim(generateRedisKey(req), claim); + const claim = await getClaimById(id, req, true) + const gaApplication = Object.assign(new GeneralApplication(), claim.generalApplication) + claim.generalApplication = gaApplication; + if (req.body.action === 'uploadButton') { + uploadSelectedFile(req, claim); return res.redirect(`${currentUrl}`); } - //await uploadSelectedFile(req, formattedSummary, claimId); - + if (gaApplication.uploadAdditionalDocuments.length === 0) { + const errors = [{ + target: { + fileUpload: '', + typeOfDocument: '', + }, + value: '', + property: '', + + constraints: { + isNotEmpty: 'ERRORS.GENERAL_APPLICATION.UPLOAD_ONE_FILE' + }, + }] + req.session.fileUpload = JSON.stringify(errors); + return res.redirect(`${currentUrl}`); } res.redirect(constructResponseUrlWithIdParams(id, GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL).replace(':gaId', gaId)); + } catch (err) { + next(err) + } })) export const getSummaryList = (additionalDocumentsList: UploadAdditionalDocument[], claimId: string, gaId: string): SummarySection => { @@ -76,8 +103,37 @@ export const getSummaryList = (additionalDocumentsList: UploadAdditionalDocument additionalDocumentsList.forEach((uploadDocument: UploadAdditionalDocument) => { index = index + 1; formattedSummary.summaryList.rows.push(summaryRow('Type of document', uploadDocument.typeOfDocument)); - formattedSummary.summaryList.rows.push(summaryRow(uploadDocument.caseDocument.documentName, '', `${GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)}+ '?id=' + ${index}`, 'Remove document')); + formattedSummary.summaryList.rows.push(summaryRow(uploadDocument.caseDocument.documentName, '', `${GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)}?indexId=${index}`, 'Remove document')); }); return formattedSummary }; + +export const removeSelectedDocument = async (redisKey: string, claim: Claim, index: number): Promise => { + try { + claim?.generalApplication?.uploadAdditionalDocuments?.splice(index, 1); + await saveDraftClaim(redisKey, claim); + } catch (error) { + logger.error(error); + throw error; + } +}; + +export const uploadSelectedFile = async (req: AppRequest, claim: Claim) => { + const uploadedDocument = new UploadAdditionalDocument(); + const fileUpload = TypeOfDocumentSectionMapper.mapToSingleFile(req); + uploadedDocument.fileUpload = fileUpload; + uploadedDocument.typeOfDocument = req.body.typeOfDocument; + const form = new GenericForm(uploadedDocument); + const uploadAdditionalDocuments = claim.generalApplication.uploadAdditionalDocuments + form.validateSync() + if (!form.hasErrors()) { + uploadedDocument.caseDocument = await civilServiceClientForDocRetrieve.uploadDocument(req, fileUpload); + uploadAdditionalDocuments.push(uploadedDocument); + // claim.generalApplication = gaApplication; + await saveDraftClaim(generateRedisKey(req), claim); + } else { + const errors = translateErrors(form.getAllErrors(), t); + req.session.fileUpload = JSON.stringify(errors); + } +} export default uploadAdditionalDocumentsController; \ No newline at end of file diff --git a/src/main/routes/features/generalApplication/viewApplicationController.ts b/src/main/routes/features/generalApplication/viewApplicationController.ts index 8b735d17aa8..9af7d76d26c 100644 --- a/src/main/routes/features/generalApplication/viewApplicationController.ts +++ b/src/main/routes/features/generalApplication/viewApplicationController.ts @@ -1,8 +1,9 @@ import {NextFunction, RequestHandler, Response, Router} from 'express'; -import {DASHBOARD_URL, GA_VIEW_APPLICATION_URL} from 'routes/urls'; +import { DASHBOARD_URL, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL, GA_VIEW_APPLICATION_URL } from 'routes/urls'; import {AppRequest} from 'common/models/AppRequest'; import {getApplicationSections} from 'services/features/generalApplication/viewApplication/viewApplicationService'; import {queryParamNumber} from 'common/utils/requestUtils'; +import { constructResponseUrlWithIdParams } from 'common/utils/urlFormatter'; const viewApplicationController = Router(); const viewPath = 'features/generalApplication/view-applications'; @@ -15,7 +16,8 @@ viewApplicationController.get(GA_VIEW_APPLICATION_URL, (async (req: AppRequest, const lang = req.query.lang ? req.query.lang : req.cookies.lang; const summaryRows = await getApplicationSections(req, applicationId, lang); const pageTitle = 'PAGES.GENERAL_APPLICATION.VIEW_APPLICATION.PAGE_TITLE'; - res.render(viewPath, {backLinkUrl, summaryRows, pageTitle, dashboardUrl: DASHBOARD_URL, applicationIndex }); + const additionalDocUrl = constructResponseUrlWithIdParams(req.params.id, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL).replace(':gaId', applicationId); + res.render(viewPath, { backLinkUrl, summaryRows, additionalDocUrl, pageTitle, dashboardUrl: DASHBOARD_URL, applicationIndex }); } catch (error) { next(error); } diff --git a/src/main/routes/routes.ts b/src/main/routes/routes.ts index 2059a348573..0892b885c6a 100644 --- a/src/main/routes/routes.ts +++ b/src/main/routes/routes.ts @@ -383,6 +383,7 @@ import backController from 'routes/common/backController'; import applicationFeePaymentConfirmationController from './features/generalApplication/payment/applicationFeePaymentConfirmationController'; import uploadAdditionalDocumentsController from './features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController'; import gaAdditionalDocCheckAnswerController from './features/generalApplication/additionalDocuments/checkAnswersController'; +import additionalDocSubmittedController from './features/generalApplication/additionalDocuments/submittedController'; export default [ homeController, @@ -696,5 +697,6 @@ export default [ backController, applicationFeePaymentConfirmationController, uploadAdditionalDocumentsController, - gaAdditionalDocCheckAnswerController + gaAdditionalDocCheckAnswerController, + additionalDocSubmittedController, ]; diff --git a/src/main/routes/urls.ts b/src/main/routes/urls.ts index e809296d264..1d5c6a21af7 100644 --- a/src/main/routes/urls.ts +++ b/src/main/routes/urls.ts @@ -360,4 +360,6 @@ export const ASSIGN_FRC_BAND_URL = `${DIRECTIONS_QUESTIONNAIRE_URL}/assign-compl export const REASON_FOR_FRC_BAND_URL = `${DIRECTIONS_QUESTIONNAIRE_URL}/reason-for-complexity-band`; export const WHY_NOT_SUBJECT_TO_FRC_URL = `${DIRECTIONS_QUESTIONNAIRE_URL}/why-not-subject-to-frc`; export const GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL = `${BASE_GENERAL_APPLICATION_URL}/:gaId/upload-additional-documents` -export const GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL = `${BASE_GENERAL_APPLICATION_URL}/:gaId/upload-additional-documents/check-and-send` +export const GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL = `${BASE_GENERAL_APPLICATION_URL}/:gaId/upload-additional-documents/check-and-send`; +export const GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL = `${BASE_GENERAL_APPLICATION_URL}/:gaId/upload-additional-documents/submitted`; + diff --git a/src/main/services/features/generalApplication/uploadEvidenceDocumentService.ts b/src/main/services/features/generalApplication/uploadEvidenceDocumentService.ts index ab7df5842dc..db4673244f9 100644 --- a/src/main/services/features/generalApplication/uploadEvidenceDocumentService.ts +++ b/src/main/services/features/generalApplication/uploadEvidenceDocumentService.ts @@ -83,7 +83,7 @@ export const uploadSelectedFile = async (req: AppRequest, summarySection: Summar } }; -const translateErrors = (keys: FormValidationError[], t: (key: string) => string, formatValues?: { keyError: string, keyToReplace: string, valueToReplace: string }[]) => { +export const translateErrors = (keys: FormValidationError[], t: (key: string) => string, formatValues?: { keyError: string, keyToReplace: string, valueToReplace: string }[]) => { return keys.map((key) => { if (formatValues) { const formatValue = formatValues.find(v => v.keyError === key.text); diff --git a/src/main/views/features/generalApplication/additionalDocuments/submitted.njk b/src/main/views/features/generalApplication/additionalDocuments/submitted.njk new file mode 100644 index 00000000000..2ecdac16287 --- /dev/null +++ b/src/main/views/features/generalApplication/additionalDocuments/submitted.njk @@ -0,0 +1,26 @@ +{% extends "claim-details-tpl.njk" %} +{% from "../../../macro/csrf.njk" import csrfProtection %} +{% from "../../dashboard/item-content.njk" import itemContent %} + +{% block content %} +
+
+
+
+ {{ csrfProtection(csrf) }} + {% for content in gaPaymentSuccessfulPanel %} + {{ itemContent(content,t) }} + {% endfor %} + {% for content in gaPaymentSuccessfulBody %} + {{ itemContent(content,t) }} + {% endfor %} +
+ {% for content in gaPaymentSuccessfulButton %} + {{ itemContent(content,t) }} + {% endfor %} +
+
+
+
+
+{% endblock %} diff --git a/src/main/views/features/generalApplication/additionalDocuments/upload-additional-documents.njk b/src/main/views/features/generalApplication/additionalDocuments/upload-additional-documents.njk index 885df29271f..cf1716eb99d 100644 --- a/src/main/views/features/generalApplication/additionalDocuments/upload-additional-documents.njk +++ b/src/main/views/features/generalApplication/additionalDocuments/upload-additional-documents.njk @@ -17,6 +17,9 @@ {% set errors = translateErrors(form.getAllErrors(),t)[0] %} {% set idValue = errors.fieldName %} {% endif %} + {% if errors.text and errors.fieldName and errors.fieldName !== 'typeOfDocument' %} + {% set uploadErrorMsg = errors.text %} + {% endif %} {{ headingWithCaption(t, 'PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.ADDITIONAL_DOCUMENTS_CAPTION', 'PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.UPLOAD_DOCUMENTS_TITLE') }}

{{ t('PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.ADDITIONAL_DOCUMENTS_ROW1') }}

{{ t('PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.ADDITIONAL_DOCUMENTS_ROW2') }}

@@ -32,15 +35,19 @@ text: t('PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.TYPE_OF_DOCUMENT_HINT') }, id: "typeOfDocument", - name: "typeOfDocument" + name: "typeOfDocument", + errorMessage: { + text: t(form.errorFor('typeOfDocument')) + } if t(form.errorFor('typeOfDocument')) else '' }) }} + {{ govukFileUpload({ id: idValue, name: "selectedFile", label: { html: 'Upload a file' }, - errorMessage: { text: t(errors.text) } if t(errors.text) else '' + errorMessage: { text: t(uploadErrorMsg) } if uploadErrorMsg else '' }) }} {{ govukButton({ id: 'uploadFileButton', diff --git a/src/main/views/features/generalApplication/view-applications.njk b/src/main/views/features/generalApplication/view-applications.njk index e0d4158cfd4..708f5345995 100644 --- a/src/main/views/features/generalApplication/view-applications.njk +++ b/src/main/views/features/generalApplication/view-applications.njk @@ -34,7 +34,7 @@

{{ t('PAGES.GENERAL_APPLICATION.VIEW_APPLICATION.SUBMITTED') }}

{{ t('PAGES.GENERAL_APPLICATION.VIEW_APPLICATION.EITHER_PARTIES') }}

{{ t('PAGES.GENERAL_APPLICATION.VIEW_APPLICATION.ADDITIONAL_SECTIONS') }}

-

{{ t('PAGES.GENERAL_APPLICATION.VIEW_APPLICATION.UPLOAD_DOCUMENTS_1')}}{{ t('PAGES.GENERAL_APPLICATION.VIEW_APPLICATION.UPLOAD_DOCUMENTS_2') }}{{t('PAGES.GENERAL_APPLICATION.VIEW_APPLICATION.UPLOAD_DOCUMENTS_3') }}

+

{{ t('PAGES.GENERAL_APPLICATION.VIEW_APPLICATION.UPLOAD_DOCUMENTS_1')}}{{ t('PAGES.GENERAL_APPLICATION.VIEW_APPLICATION.UPLOAD_DOCUMENTS_2') }}{{t('PAGES.GENERAL_APPLICATION.VIEW_APPLICATION.UPLOAD_DOCUMENTS_3') }}

{{ govukDetails({ From 4eb2b9f19d63a4fe28b1b8fd54e1ea9ecb3b734f Mon Sep 17 00:00:00 2001 From: jeswanth Date: Mon, 15 Jul 2024 09:03:18 +0100 Subject: [PATCH 03/17] CIV-14228 added code for additional upload docs --- .../checkAnswersController.ts | 71 ++--- .../submittedController.ts | 52 ++-- .../uploadAdditionalDocumentsController.ts | 90 ++----- .../additionalDocumentService.ts | 124 +++++++++ src/test/a11y/a11y.mock-test.ts | 1 + .../checkAnswersController.test.ts | 94 +++++++ .../submittedController.test.ts | 65 +++++ ...ploadAdditionalDocumentsController.test.ts | 235 +++++++++++++++++ .../additionalDocumentService.test.ts | 245 ++++++++++++++++++ 9 files changed, 821 insertions(+), 156 deletions(-) create mode 100644 src/main/services/features/generalApplication/additionalDocumentService.ts create mode 100644 src/test/unit/routes/features/claim/generalApplication/additionalDocuments/checkAnswersController.test.ts create mode 100644 src/test/unit/routes/features/claim/generalApplication/additionalDocuments/submittedController.test.ts create mode 100644 src/test/unit/routes/features/claim/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.test.ts create mode 100644 src/test/unit/services/features/generalApplication/additionalDocumentService.test.ts diff --git a/src/main/routes/features/generalApplication/additionalDocuments/checkAnswersController.ts b/src/main/routes/features/generalApplication/additionalDocuments/checkAnswersController.ts index 1a4b51b5cbf..cccec6fbd02 100644 --- a/src/main/routes/features/generalApplication/additionalDocuments/checkAnswersController.ts +++ b/src/main/routes/features/generalApplication/additionalDocuments/checkAnswersController.ts @@ -1,17 +1,13 @@ +import { ApplicationEvent } from 'common/models/gaEvents/applicationEvent'; import { AppRequest } from 'common/models/AppRequest'; -import { GeneralApplication } from 'common/models/generalApplication/GeneralApplication'; -import { UploadAdditionalDocument } from 'common/models/generalApplication/UploadAdditionalDocument'; -import { SummaryRow, summaryRow } from 'common/models/summaryList/summaryList'; -import { changeLabel } from 'common/utils/checkYourAnswer/changeButton'; +import { buildSummarySectionForAdditionalDoc, getClaimDetailsById, prepareCCDData } from 'services/features/generalApplication/additionalDocumentService'; import { caseNumberPrettify } from 'common/utils/stringUtils'; -import { NextFunction, RequestHandler, Response, Router } from 'express'; -import { getClaimById } from 'modules/utilityService'; -import config from 'config'; import { GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL } from 'routes/urls'; import { GaServiceClient } from 'client/gaServiceClient'; -import { ApplicationEvent } from 'common/models/gaEvents/applicationEvent'; import { getCancelUrl } from 'services/features/generalApplication/generalApplicationService'; -const { v4: uuidv4 } = require('uuid'); +import { NextFunction, RequestHandler, Response, Router } from 'express'; +import config from 'config'; + const gaAdditionalDocCheckAnswerController = Router(); const viewPath = 'features/generalApplication/additionalDocuments/check-answers'; const generalAppApiBaseUrl = config.get('services.generalApplication.url'); @@ -19,13 +15,12 @@ const gaServiceClient: GaServiceClient = new GaServiceClient(generalAppApiBaseUr gaAdditionalDocCheckAnswerController.get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, (async (req: AppRequest, res: Response, next: NextFunction) => { try { - const { gaId, id } = req.params - const claim = await getClaimById(id, req, true); - const claimIdPrettified = caseNumberPrettify(id); - const gaApplication = Object.assign(new GeneralApplication(), claim.generalApplication) - const cancelUrl = await getCancelUrl(id, claim); - const backLinkUrl = GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', id).replace(':gaId', gaId) - const summaryRows = buildSummarySection(gaApplication.uploadAdditionalDocuments, id, gaId) + const { gaId, id: claimId } = req.params + const claimIdPrettified = caseNumberPrettify(claimId); + const claim = await getClaimDetailsById(req); + const cancelUrl = await getCancelUrl(claimId, claim); + const backLinkUrl = GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId) + const summaryRows = buildSummarySectionForAdditionalDoc(claim.generalApplication.uploadAdditionalDocuments, claimId, gaId) res.render(viewPath, { backLinkUrl, cancelUrl, claimIdPrettified, claim, summaryRows }); } catch (error) { next(error); @@ -33,39 +28,19 @@ gaAdditionalDocCheckAnswerController.get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, }) as RequestHandler) gaAdditionalDocCheckAnswerController.post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, (async (req: AppRequest, res: Response, next: NextFunction) => { - const { gaId, id } = req.params; - console.log(gaId); - console.log(id); - const claim = await getClaimById(id, req, true); - const gaApplication = Object.assign(new GeneralApplication(), claim.generalApplication); - const uploadedDocuments = gaApplication.uploadAdditionalDocuments.map(doc => { - return { - id: uuidv4(), - value: { - typeOfDocument: doc.typeOfDocument, - documentUpload: { - document_url: doc.caseDocument.documentLink.document_url, - document_binary_url: doc.caseDocument.documentLink.document_binary_url, - document_filename: doc.caseDocument.documentName, - } - - } - } - }) - const generalApplication = { - uploadDocument: uploadedDocuments - }; - await gaServiceClient.submitEvent(ApplicationEvent.UPLOAD_ADDL_DOCUMENTS, gaId, generalApplication, req); - res.redirect(GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL.replace(':id', id).replace(':gaId', gaId)); + try { + const { gaId, id: claimId } = req.params; + const claim = await getClaimDetailsById(req); + const uploadedDocuments = prepareCCDData(claim.generalApplication.uploadAdditionalDocuments); + const generalApplication = { + uploadDocument: uploadedDocuments + }; + await gaServiceClient.submitEvent(ApplicationEvent.UPLOAD_ADDL_DOCUMENTS, gaId, generalApplication as unknown, req); + res.redirect(GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL.replace(':id', claimId).replace(':gaId', gaId)); + } catch (error) { + next(error); + } }) as RequestHandler); -const buildSummarySection = (additionalDocumentsList: UploadAdditionalDocument[], claimId: string, gaId: string) => { - const rows: SummaryRow[] = [] - additionalDocumentsList.forEach(doc => { - rows.push(summaryRow('Type of document', doc.typeOfDocument)); - rows.push(summaryRow('Uploaded document', doc.caseDocument.documentName, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId), changeLabel('en'))) - }) - return rows; -} export default gaAdditionalDocCheckAnswerController; \ No newline at end of file diff --git a/src/main/routes/features/generalApplication/additionalDocuments/submittedController.ts b/src/main/routes/features/generalApplication/additionalDocuments/submittedController.ts index ed71d9e9724..4b57c8a0821 100644 --- a/src/main/routes/features/generalApplication/additionalDocuments/submittedController.ts +++ b/src/main/routes/features/generalApplication/additionalDocuments/submittedController.ts @@ -1,45 +1,29 @@ import { AppRequest } from 'common/models/AppRequest'; -import { getLng } from 'common/utils/languageToggleUtils'; -import { NextFunction, Response, Router } from 'express'; +import { NextFunction, RequestHandler, Response, Router } from 'express'; import { deleteDraftClaimFromStore, generateRedisKey } from 'modules/draft-store/draftStoreService'; import { getClaimById } from 'modules/utilityService'; import { GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL } from 'routes/urls'; -import { PaymentSuccessfulSectionBuilder } from 'services/features/claim/paymentSuccessfulSectionBuilder'; +import { getContentForBody, getContentForCloseButton, getContentForPanel } from 'services/features/generalApplication/additionalDocumentService'; import { getCancelUrl } from 'services/features/generalApplication/generalApplicationService'; const additionalDocSubmittedController = Router(); const viewPath = 'features/generalApplication/additionalDocuments/submitted' -additionalDocSubmittedController.get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL, async (req: AppRequest, res: Response, next: NextFunction) => { - const lng = req.query.lang ? req.query.lang : req.cookies.lang; - const { id } = req.params - const claim = await getClaimById(id, req, true); - const redisKey = generateRedisKey(req); - await deleteDraftClaimFromStore(redisKey); - res.render(viewPath, { - gaPaymentSuccessfulPanel: getContentForPanel(lng), - gaPaymentSuccessfulBody: getContentForBody(lng), - gaPaymentSuccessfulButton: getContentForCloseButton(await getCancelUrl(id, claim)), - }) -}) - -const getContentForPanel = (lng: string) => { - const panelBuilder = new PaymentSuccessfulSectionBuilder(); - panelBuilder.addPanelForConfirmation('PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.UPLOADED_ADDITIONAL_DOCS', getLng(lng)); - return panelBuilder.build(); -} - -const getContentForBody = (lng: string) => { - let contentBuilder = new PaymentSuccessfulSectionBuilder(); - return contentBuilder.addTitle('PAGES.GENERAL_APPLICATION.GA_PAYMENT_SUCCESSFUL.WHAT_HAPPENS_NEXT', { lng: getLng(lng) }) - .addParagraph('PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.JUDGE_WILL_REVIEW', { lng: getLng(lng) }) - .build(); -} - -const getContentForCloseButton = (redirectUrl: string) => { - return new PaymentSuccessfulSectionBuilder() - .addButton('COMMON.BUTTONS.CLOSE_AND_RETURN_TO_DASHBOARD', redirectUrl) - .build(); -} +additionalDocSubmittedController.get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL, (async (req: AppRequest, res: Response, next: NextFunction) => { + try { + const lng = req.query.lang ? req.query.lang : req.cookies.lang; + const { id } = req.params + const claim = await getClaimById(id, req, true); + const redisKey = generateRedisKey(req); + await deleteDraftClaimFromStore(redisKey); + res.render(viewPath, { + gaPaymentSuccessfulPanel: getContentForPanel(lng), + gaPaymentSuccessfulBody: getContentForBody(lng), + gaPaymentSuccessfulButton: getContentForCloseButton(await getCancelUrl(id, claim)), + }) + } catch (err) { + next(err); + } +}) as RequestHandler) export default additionalDocSubmittedController; \ No newline at end of file diff --git a/src/main/routes/features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.ts b/src/main/routes/features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.ts index 88f89440cc8..84e84088529 100644 --- a/src/main/routes/features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.ts +++ b/src/main/routes/features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.ts @@ -4,26 +4,14 @@ import { NextFunction, RequestHandler, Response, Router } from 'express'; import { GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL, GA_VIEW_APPLICATION_URL } from 'routes/urls'; import multer from 'multer'; import { UploadAdditionalDocument } from 'common/models/generalApplication/UploadAdditionalDocument'; -import { TypeOfDocumentSectionMapper } from 'services/features/caseProgression/TypeOfDocumentSectionMapper'; -import config from 'config'; -import { CivilServiceClient } from 'client/civilServiceClient'; -import { getClaimById } from 'modules/utilityService'; -import { GeneralApplication } from 'common/models/generalApplication/GeneralApplication'; -import { generateRedisKey, saveDraftClaim } from 'modules/draft-store/draftStoreService'; -import { SummarySection, summarySection } from 'common/models/summaryList/summarySections'; -import { summaryRow } from 'common/models/summaryList/summaryList'; +import { generateRedisKey } from 'modules/draft-store/draftStoreService'; import { constructResponseUrlWithIdParams } from 'common/utils/urlFormatter'; -import { translateErrors } from 'services/features/generalApplication/uploadEvidenceDocumentService'; -import { t } from 'i18next'; -import { Claim } from 'common/models/claim'; import { getCancelUrl } from 'services/features/generalApplication/generalApplicationService'; +import { getClaimDetailsById, getSummaryList, removeSelectedDocument, uploadSelectedFile } from 'services/features/generalApplication/additionalDocumentService'; const uploadAdditionalDocumentsController = Router(); -const { Logger } = require('@hmcts/nodejs-logging'); -const logger = Logger.getLogger('claimantResponseService'); + const viewPath = 'features/generalApplication/additionalDocuments/upload-additional-documents'; -const civilServiceApiBaseUrl = config.get('services.civilService.url'); -const civilServiceClientForDocRetrieve: CivilServiceClient = new CivilServiceClient(civilServiceApiBaseUrl, true); const fileSize = Infinity; const upload = multer({ limits: { @@ -33,13 +21,12 @@ const upload = multer({ uploadAdditionalDocumentsController.get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL, (async (req: AppRequest, res: Response, next: NextFunction) => { try { - const { gaId, id } = req.params + const { gaId, id } = req.params; const uploadedDocument = new UploadAdditionalDocument(); - let form = new GenericForm(uploadedDocument); + let form = new GenericForm(uploadedDocument); const redisKey = generateRedisKey(req); - const claim = await getClaimById(id, req, true) - const gaApplication = Object.assign(new GeneralApplication(), claim.generalApplication) - claim.generalApplication = gaApplication; + const claim = await getClaimDetailsById(req); + const gaDetails = claim.generalApplication; if (req?.session?.fileUpload) { const parsedData = JSON.parse(req?.session?.fileUpload); @@ -52,8 +39,8 @@ uploadAdditionalDocumentsController.get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL, (asy } const cancelUrl = await getCancelUrl(id, claim); const backLinkUrl = `${constructResponseUrlWithIdParams(id, GA_VIEW_APPLICATION_URL)}?applicationId=${gaId}`; - const formattedSummary = getSummaryList(gaApplication.uploadAdditionalDocuments, id, gaId) - res.render(viewPath, { cancelUrl, backLinkUrl, form, formattedSummary }) + const formattedSummary = getSummaryList(gaDetails.uploadAdditionalDocuments, id, gaId); + res.render(viewPath, { cancelUrl, backLinkUrl, form, formattedSummary }); } catch (err) { next(err); } @@ -61,17 +48,15 @@ uploadAdditionalDocumentsController.get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL, (asy uploadAdditionalDocumentsController.post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL, upload.single('selectedFile'), (async (req: AppRequest, res: Response, next: NextFunction) => { try { - const { gaId, id } = req.params + const { gaId, id } = req.params const currentUrl = GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', id).replace(':gaId', gaId) - - const claim = await getClaimById(id, req, true) - const gaApplication = Object.assign(new GeneralApplication(), claim.generalApplication) - claim.generalApplication = gaApplication; + const claim = await getClaimDetailsById(req); + const gaDetails = claim.generalApplication; if (req.body.action === 'uploadButton') { - uploadSelectedFile(req, claim); + await uploadSelectedFile(req, claim); return res.redirect(`${currentUrl}`); } - if (gaApplication.uploadAdditionalDocuments.length === 0) { + if (gaDetails.uploadAdditionalDocuments.length === 0) { const errors = [{ target: { fileUpload: '', @@ -86,54 +71,11 @@ uploadAdditionalDocumentsController.post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL, upl }] req.session.fileUpload = JSON.stringify(errors); return res.redirect(`${currentUrl}`); - } - res.redirect(constructResponseUrlWithIdParams(id, GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL).replace(':gaId', gaId)); + } + res.redirect(constructResponseUrlWithIdParams(id, GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL).replace(':gaId', gaId)); } catch (err) { next(err) } })) -export const getSummaryList = (additionalDocumentsList: UploadAdditionalDocument[], claimId: string, gaId: string): SummarySection => { - let index = 0; - const formattedSummary = summarySection( - { - title: '', - summaryRows: [], - }); - additionalDocumentsList.forEach((uploadDocument: UploadAdditionalDocument) => { - index = index + 1; - formattedSummary.summaryList.rows.push(summaryRow('Type of document', uploadDocument.typeOfDocument)); - formattedSummary.summaryList.rows.push(summaryRow(uploadDocument.caseDocument.documentName, '', `${GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)}?indexId=${index}`, 'Remove document')); - }); - return formattedSummary -}; - -export const removeSelectedDocument = async (redisKey: string, claim: Claim, index: number): Promise => { - try { - claim?.generalApplication?.uploadAdditionalDocuments?.splice(index, 1); - await saveDraftClaim(redisKey, claim); - } catch (error) { - logger.error(error); - throw error; - } -}; - -export const uploadSelectedFile = async (req: AppRequest, claim: Claim) => { - const uploadedDocument = new UploadAdditionalDocument(); - const fileUpload = TypeOfDocumentSectionMapper.mapToSingleFile(req); - uploadedDocument.fileUpload = fileUpload; - uploadedDocument.typeOfDocument = req.body.typeOfDocument; - const form = new GenericForm(uploadedDocument); - const uploadAdditionalDocuments = claim.generalApplication.uploadAdditionalDocuments - form.validateSync() - if (!form.hasErrors()) { - uploadedDocument.caseDocument = await civilServiceClientForDocRetrieve.uploadDocument(req, fileUpload); - uploadAdditionalDocuments.push(uploadedDocument); - // claim.generalApplication = gaApplication; - await saveDraftClaim(generateRedisKey(req), claim); - } else { - const errors = translateErrors(form.getAllErrors(), t); - req.session.fileUpload = JSON.stringify(errors); - } -} export default uploadAdditionalDocumentsController; \ No newline at end of file diff --git a/src/main/services/features/generalApplication/additionalDocumentService.ts b/src/main/services/features/generalApplication/additionalDocumentService.ts new file mode 100644 index 00000000000..f0aca97fedb --- /dev/null +++ b/src/main/services/features/generalApplication/additionalDocumentService.ts @@ -0,0 +1,124 @@ +import { AppRequest } from 'common/models/AppRequest'; +import { Claim } from 'common/models/claim'; +import { UploadAdditionalDocument } from 'common/models/generalApplication/UploadAdditionalDocument'; +import { SummaryRow, summaryRow } from 'common/models/summaryList/summaryList'; +import { SummarySection, summarySection } from 'common/models/summaryList/summarySections'; +import { generateRedisKey, saveDraftClaim } from 'modules/draft-store/draftStoreService'; +import { TypeOfDocumentSectionMapper } from '../caseProgression/TypeOfDocumentSectionMapper'; +import { GenericForm } from 'common/form/models/genericForm'; +import { translateErrors } from './uploadEvidenceDocumentService'; +import { t } from 'i18next'; +import config from 'config'; +import { CivilServiceClient } from 'client/civilServiceClient'; +import { GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL } from 'routes/urls'; +import { getClaimById } from 'modules/utilityService'; +import { GeneralApplication } from 'common/models/generalApplication/GeneralApplication'; +import { changeLabel } from 'common/utils/checkYourAnswer/changeButton'; +import { PaymentSuccessfulSectionBuilder } from '../claim/paymentSuccessfulSectionBuilder'; +import { getLng } from 'common/utils/languageToggleUtils'; + +const { v4: uuIdv4 } = require('uuid'); +const { Logger } = require('@hmcts/nodejs-logging'); +const logger = Logger.getLogger('additionalDocumentService'); +const civilServiceApiBaseUrl = config.get('services.civilService.url'); +const civilServiceClientForDocRetrieve: CivilServiceClient = new CivilServiceClient(civilServiceApiBaseUrl, true); + +export const getSummaryList = (additionalDocumentsList: UploadAdditionalDocument[], claimId: string, gaId: string): SummarySection => { + let index = 0; + const formattedSummary = summarySection( + { + title: '', + summaryRows: [], + }); + additionalDocumentsList.forEach((uploadDocument: UploadAdditionalDocument) => { + index = index + 1; + formattedSummary.summaryList.rows.push(summaryRow('Type of document', uploadDocument.typeOfDocument)); + formattedSummary.summaryList.rows.push(summaryRow(uploadDocument.caseDocument.documentName, '', `${GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)}?indexId=${index}`, 'Remove document')); + }); + return formattedSummary +}; + +export const removeSelectedDocument = async (redisKey: string, claim: Claim, index: number): Promise => { + try { + claim?.generalApplication?.uploadAdditionalDocuments?.splice(index, 1); + await saveDraftClaim(redisKey, claim); + } catch (error) { + logger.error(error); + throw error; + } +}; + +export const uploadSelectedFile = async (req: AppRequest, claim: Claim) => { + const uploadedDocument = new UploadAdditionalDocument(); + const fileUpload = TypeOfDocumentSectionMapper.mapToSingleFile(req); + uploadedDocument.fileUpload = fileUpload; + uploadedDocument.typeOfDocument = req.body.typeOfDocument; + const form = new GenericForm(uploadedDocument); + const uploadAdditionalDocuments = claim.generalApplication.uploadAdditionalDocuments + form.validateSync() + if (!form.hasErrors()) { + uploadedDocument.caseDocument = await civilServiceClientForDocRetrieve.uploadDocument(req, fileUpload); + uploadAdditionalDocuments.push(uploadedDocument); + await saveDraftClaim(generateRedisKey(req), claim); + } else { + const errors = translateErrors(form.getAllErrors(), t); + req.session.fileUpload = JSON.stringify(errors); + } +} + +export const getClaimDetailsById = async (req: AppRequest): Promise => { + try { + const claim = await getClaimById(req.params.id, req, true) + const gaApplication = Object.assign(new GeneralApplication(), claim.generalApplication) + claim.generalApplication = gaApplication; + return claim + } catch (error) { + logger.error(error); + throw error; + } +} + +export const prepareCCDData = (uploadAdditionalDocuments: UploadAdditionalDocument[]) => { + return uploadAdditionalDocuments.map(doc => { + return { + id: uuIdv4(), + value: { + typeOfDocument: doc.typeOfDocument, + documentUpload: { + document_url: doc.caseDocument.documentLink.document_url, + document_binary_url: doc.caseDocument.documentLink.document_binary_url, + document_filename: doc.caseDocument.documentName, + } + + } + } + }) +} + +export const buildSummarySectionForAdditionalDoc = (additionalDocumentsList: UploadAdditionalDocument[], claimId: string, gaId: string) => { + const rows: SummaryRow[] = [] + additionalDocumentsList.forEach(doc => { + rows.push(summaryRow('Type of document', doc.typeOfDocument)); + rows.push(summaryRow('Uploaded document', doc.caseDocument.documentName, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId), changeLabel('en'))) + }) + return rows; +} + +export const getContentForPanel = (lng: string) => { + const panelBuilder = new PaymentSuccessfulSectionBuilder(); + panelBuilder.addPanelForConfirmation('PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.UPLOADED_ADDITIONAL_DOCS', getLng(lng)); + return panelBuilder.build(); +} + +export const getContentForBody = (lng: string) => { + let contentBuilder = new PaymentSuccessfulSectionBuilder(); + return contentBuilder.addTitle('PAGES.GENERAL_APPLICATION.GA_PAYMENT_SUCCESSFUL.WHAT_HAPPENS_NEXT', { lng: getLng(lng) }) + .addParagraph('PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.JUDGE_WILL_REVIEW', { lng: getLng(lng) }) + .build(); +} + +export const getContentForCloseButton = (redirectUrl: string) => { + return new PaymentSuccessfulSectionBuilder() + .addButton('COMMON.BUTTONS.CLOSE_AND_RETURN_TO_DASHBOARD', redirectUrl) + .build(); +} \ No newline at end of file diff --git a/src/test/a11y/a11y.mock-test.ts b/src/test/a11y/a11y.mock-test.ts index 39fe11cd292..00c1c128296 100644 --- a/src/test/a11y/a11y.mock-test.ts +++ b/src/test/a11y/a11y.mock-test.ts @@ -63,6 +63,7 @@ describe('Accessibility', async () => { it('Test of '+url,async () => { app.get(url, (req: any, res: any) => { url = url.replace(':id', '1645882162449409'); + url = url.replace(':gaId', '1720536653906339'); const filePath = translateUrlToFilePath(url); const fileContent = fs.readFileSync(filePath, 'utf8'); res.send(fileContent); diff --git a/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/checkAnswersController.test.ts b/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/checkAnswersController.test.ts new file mode 100644 index 00000000000..a5da665da61 --- /dev/null +++ b/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/checkAnswersController.test.ts @@ -0,0 +1,94 @@ +import config from 'config'; +import nock from 'nock'; +import request from 'supertest'; +import { app } from '../../../../../../../main/app'; +import { isGaForLipsEnabled } from 'app/auth/launchdarkly/launchDarklyClient'; +import { buildSummarySectionForAdditionalDoc, getClaimDetailsById, prepareCCDData } from 'services/features/generalApplication/additionalDocumentService'; +import { getCancelUrl } from 'services/features/generalApplication/generalApplicationService'; +import { GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL } from 'routes/urls'; +import { Claim } from 'common/models/claim'; +import { GeneralApplication } from 'common/models/generalApplication/GeneralApplication'; +import { GaServiceClient } from 'client/gaServiceClient'; +import { ApplicationEvent } from 'common/models/gaEvents/applicationEvent'; + +jest.mock('../../../../../../../main/modules/oidc'); +// jest.mock('../../../../../../../main/modules/draft-store/draftStoreService'); +jest.mock('../../../../../../../main/app/auth/launchdarkly/launchDarklyClient'); +jest.mock('../../../../../../../main/services/features/generalApplication/additionalDocumentService', () => ({ + getClaimDetailsById: jest.fn(), + prepareCCDData: jest.fn(), + buildSummarySectionForAdditionalDoc: jest.fn(), +})); +jest.mock('../../../../../../../main/services/features/generalApplication/generalApplicationService', () => ({ + getCancelUrl: jest.fn(), +})); + +describe('General Application - additional docs check answer controller ', () => { + const citizenRoleToken: string = config.get('citizenRoleToken'); + const idamUrl: string = config.get('idamUrl'); + beforeAll(() => { + nock(idamUrl) + .post('/o/token') + .reply(200, { id_token: citizenRoleToken }); + (isGaForLipsEnabled as jest.Mock).mockResolvedValue(true); + }); + + beforeEach(() => { + jest.clearAllMocks(); + }); + describe('GET check your answers', () => { + it('should render the check answers page with correct data', async () => { + const claimId = '123'; + const gaId = '456'; + const claim = new Claim(); + claim.generalApplication = new GeneralApplication(); + (getClaimDetailsById as jest.Mock).mockResolvedValue(claim); + (getCancelUrl as jest.Mock).mockResolvedValue('/cancel-url'); + (buildSummarySectionForAdditionalDoc as jest.Mock).mockReturnValue([]); + + const res = await request(app).get(`${GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL.replace(':id', claimId).replace(':gaId', gaId)}`); + + expect(res.status).toBe(200); + expect(getClaimDetailsById).toHaveBeenCalledWith(expect.anything()); + expect(getCancelUrl).toHaveBeenCalledWith(claimId, claim); + expect(buildSummarySectionForAdditionalDoc).toHaveBeenCalledWith(claim.generalApplication.uploadAdditionalDocuments, claimId, gaId); + expect(res.text).toContain('Check your answers'); + }); + + it('should handle errors', async () => { + (getClaimDetailsById as jest.Mock).mockRejectedValue(new Error('Error')); + + const res = await request(app).get(`${GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL.replace(':id', '123').replace(':gaId', '456')}`); + + expect(res.status).toBe(500); + }); + }); + + describe('POST /ga-upload-additional-documents-cya', () => { + it('should submit the documents and redirect to submitted page', async () => { + const claimId = '123'; + const gaId = '456'; + const claim = new Claim(); + claim.generalApplication = new GeneralApplication(); + (getClaimDetailsById as jest.Mock).mockResolvedValue(claim); + (prepareCCDData as jest.Mock).mockReturnValue([]); + const mockGaServiceClient = jest.spyOn(GaServiceClient.prototype, 'submitEvent').mockResolvedValueOnce(undefined); + + const res = await request(app).post(`${GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL.replace(':id', claimId).replace(':gaId', gaId)}`); + + expect(res.status).toBe(302); + expect(res.header.location).toBe(GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL.replace(':id', claimId).replace(':gaId', gaId)); + expect(getClaimDetailsById).toHaveBeenCalledWith(expect.anything()); + expect(prepareCCDData).toHaveBeenCalledWith(claim.generalApplication.uploadAdditionalDocuments); + expect(mockGaServiceClient).toHaveBeenCalledWith(ApplicationEvent.UPLOAD_ADDL_DOCUMENTS, gaId, { uploadDocument: [] }, expect.anything()); + }); + + it('should handle errors', async () => { + (getClaimDetailsById as jest.Mock).mockRejectedValue(new Error('Error')); + + const res = await request(app).post(`${GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL.replace(':id', '123').replace(':gaId', '456')}`).send({}); + + expect(res.status).toBe(500); + }); + }); +}) \ No newline at end of file diff --git a/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/submittedController.test.ts b/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/submittedController.test.ts new file mode 100644 index 00000000000..1684f81b4c7 --- /dev/null +++ b/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/submittedController.test.ts @@ -0,0 +1,65 @@ +import config from 'config'; +import nock from 'nock'; +import request from 'supertest'; +import { app } from '../../../../../../../main/app'; +import { isGaForLipsEnabled } from 'app/auth/launchdarkly/launchDarklyClient'; +import { getClaimById } from 'modules/utilityService'; +import { deleteDraftClaimFromStore, generateRedisKey } from 'modules/draft-store/draftStoreService'; +import { getCancelUrl } from 'services/features/generalApplication/generalApplicationService'; +import { GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL } from 'routes/urls'; +import { Claim } from 'common/models/claim'; + +jest.mock('../../../../../../../main/modules/oidc'); +jest.mock('../../../..../../../../../../main/modules/utilityService'); +jest.mock('../../../../../../../main/app/auth/launchdarkly/launchDarklyClient'); +jest.mock('../../../../../../../main/modules/draft-store/draftStoreService', () => ({ + generateRedisKey: jest.fn((key) => key), + deleteDraftClaimFromStore: jest.fn((key) => { }) +})); +jest.mock('../../../../../../../main/services/features/generalApplication/generalApplicationService', () => ({ + getCancelUrl: jest.fn(), +})); + +describe('General Application - additional docs submitted controller', () => { + const citizenRoleToken: string = config.get('citizenRoleToken'); + const idamUrl: string = config.get('idamUrl'); + beforeAll(() => { + nock(idamUrl) + .post('/o/token') + .reply(200, { id_token: citizenRoleToken }); + (isGaForLipsEnabled as jest.Mock).mockResolvedValue(true); + }); + beforeEach(() => { + jest.clearAllMocks(); + }); + describe('GET submit controller', () => { + it('should render the submitted page with correct data', async () => { + const claimId = '123'; + const claim = new Claim(); + const redisKey = 'redis-key'; + const cancelUrl = '/cancel-url'; + + (getClaimById as jest.Mock).mockResolvedValue(claim); + (generateRedisKey as jest.Mock).mockReturnValue(redisKey); + (deleteDraftClaimFromStore as jest.Mock).mockResolvedValue(undefined); + (getCancelUrl as jest.Mock).mockResolvedValue(cancelUrl); + + const res = await request(app).get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL.replace(':id', claimId)); + + expect(res.status).toBe(200); + expect(getClaimById).toHaveBeenCalledWith(claimId, expect.anything(), true); + expect(generateRedisKey).toHaveBeenCalledWith(expect.anything()); + expect(deleteDraftClaimFromStore).toHaveBeenCalledWith(redisKey); + expect(getCancelUrl).toHaveBeenCalledWith(claimId, claim); + expect(res.text).toContain('You\'ve uploaded additional documents'); + }); + + it('should handle errors', async () => { + (getClaimById as jest.Mock).mockRejectedValue(new Error('Error')); + + const res = await request(app).get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL.replace(':id', '123')); + + expect(res.status).toBe(500); + }); + }); +}) \ No newline at end of file diff --git a/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.test.ts b/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.test.ts new file mode 100644 index 00000000000..26a1b250d58 --- /dev/null +++ b/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.test.ts @@ -0,0 +1,235 @@ +import config from 'config'; +import nock from 'nock'; +import request from 'supertest'; +import { app } from '../../../../../../../main/app'; +import { + getClaimDetailsById, + getSummaryList, + removeSelectedDocument, + uploadSelectedFile, +} from 'services/features/generalApplication/additionalDocumentService'; +import { generateRedisKey } from 'modules/draft-store/draftStoreService'; +import { getCancelUrl } from 'services/features/generalApplication/generalApplicationService'; +import { + GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, + GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL, +} from 'routes/urls'; +import { Claim } from 'common/models/claim'; +import { GeneralApplication } from 'common/models/generalApplication/GeneralApplication'; +import { isGaForLipsEnabled } from 'app/auth/launchdarkly/launchDarklyClient'; +import { UploadAdditionalDocument } from 'common/models/generalApplication/UploadAdditionalDocument'; +import { CaseDocument } from 'common/models/document/caseDocument'; +import { FileUpload } from 'common/models/caseProgression/uploadDocumentsUserForm'; +import { Session } from 'express-session'; +import { t } from 'i18next'; + +jest.mock('../../../../../../../main/modules/oidc'); +jest.mock('../../../../../../../main/services/features/generalApplication/additionalDocumentService', () => ({ + getClaimDetailsById: jest.fn(), + getSummaryList: jest.fn(), + uploadSelectedFile: jest.fn(), + removeSelectedDocument: jest.fn(), +})); +jest.mock('../../../../../../../main/app/auth/launchdarkly/launchDarklyClient'); +jest.mock('../../../../../../../main/modules/draft-store/draftStoreService', () => ({ + generateRedisKey: jest.fn((key) => key), +})); + +jest.mock('../../../../../../../main/services/features/generalApplication/generalApplicationService', () => ({ + getCancelUrl: jest.fn(), +})); + + +describe('uploadAdditionalDocumentsController', () => { + const citizenRoleToken: string = config.get('citizenRoleToken'); + const idamUrl: string = config.get('idamUrl'); + const claimId = '123'; + const gaId = '456'; + let claim: Claim; + beforeAll(() => { + nock(idamUrl) + .post('/o/token') + .reply(200, { id_token: citizenRoleToken }); + (isGaForLipsEnabled as jest.Mock).mockResolvedValue(true); + }); + + beforeEach(() => { + claim = new Claim(); + claim.generalApplication = new GeneralApplication(); + jest.clearAllMocks(); + }); + + describe('on Get request', () => { + it('should render the upload additional documents page with correct data', async () => { + const redisKey = 'redis-key'; + const cancelUrl = '/cancel-url'; + const formattedSummaryList = { + title: "", + summaryList: { + rows: [ + { + key: { + text: "Type of document", + }, + value: { + html: "test", + }, + }, + { + key: { + text: "n245form.pdf", + }, + value: { + html: "", + }, + actions: { + items: [ + { + href: "/case/1720536503257495/general-application/1720536653906339/upload-additional-documents?indexId=1", + text: "Remove document", + visuallyHiddenText: "n245form.pdf", + }, + ], + }, + }, + ], + }, + }; + (getClaimDetailsById as jest.Mock).mockResolvedValue(claim); + (generateRedisKey as jest.Mock).mockReturnValue(redisKey); + (getCancelUrl as jest.Mock).mockResolvedValue(cancelUrl); + (getSummaryList as jest.Mock).mockReturnValue(formattedSummaryList); + + const res = await request(app).get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)); + + expect(res.status).toBe(200); + expect(getClaimDetailsById).toHaveBeenCalledWith(expect.anything()); + expect(generateRedisKey).toHaveBeenCalledWith(expect.anything()); + expect(getCancelUrl).toHaveBeenCalledWith(claimId, claim); + expect(getSummaryList).toHaveBeenCalledWith(claim.generalApplication.uploadAdditionalDocuments, claimId, gaId); + expect(res.text).toContain('Type of document'); + expect(res.text).toContain('test') + }); + + it('should remove the selected doc from the store', async () => { + + const additionalDocument = new UploadAdditionalDocument(); + additionalDocument.typeOfDocument = 'testt' + additionalDocument.caseDocument = { + documentLink: { document_binary_url: 'binary_url1', document_filename: 'testDoc', document_url: 'url' }, + documentName: 'testDoc', + documentType: null, + documentSize: 1000, + createdDatetime: new Date(), + } as CaseDocument; + additionalDocument.fileUpload = new FileUpload(); + claim.generalApplication.uploadAdditionalDocuments = [additionalDocument]; + const redisKey = 'redis-key'; + const cancelUrl = '/cancel-url'; + (getClaimDetailsById as jest.Mock).mockResolvedValue(claim); + (generateRedisKey as jest.Mock).mockReturnValue(redisKey); + (getCancelUrl as jest.Mock).mockResolvedValue(cancelUrl); + (getSummaryList as jest.Mock).mockReturnValue({}); + (removeSelectedDocument as jest.Mock).mockReturnValueOnce(void 0); + + const res = await request(app).get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)).query({ indexId: 1 }); + + expect(res.status).toBe(200); + expect(removeSelectedDocument).toHaveBeenCalledWith(redisKey, claim, 0) + }); + + it('should return page with errors when upload file button clicked without choosing file', async () => { + const errors = [ + { + target: {}, + property: 'fileUpload', + constraints: { isNotEmpty: 'ERRORS.VALID_CHOOSE_THE_FILE' }, + fieldName: 'fileUpload', + text: 'Choose the file you want to upload', + href: '#fileUpload', + }, + ]; + const additionalDocument = new UploadAdditionalDocument(); + additionalDocument.typeOfDocument = 'testt' + additionalDocument.caseDocument = { + documentLink: { document_binary_url: 'binary_url1', document_filename: 'testDoc', document_url: 'url' }, + documentName: 'testDoc', + documentType: null, + documentSize: 1000, + createdDatetime: new Date(), + } as CaseDocument; + additionalDocument.fileUpload = new FileUpload(); + claim.generalApplication.uploadAdditionalDocuments = [additionalDocument]; + const redisKey = 'redis-key'; + const cancelUrl = '/cancel-url'; + (getClaimDetailsById as jest.Mock).mockResolvedValue(claim); + (generateRedisKey as jest.Mock).mockReturnValue(redisKey); + (getCancelUrl as jest.Mock).mockResolvedValue(cancelUrl); + (getSummaryList as jest.Mock).mockReturnValue({}); + (removeSelectedDocument as jest.Mock).mockReturnValueOnce(void 0); + app.request.session = { fileUpload: JSON.stringify(errors) } as unknown as Session; + await request(app) + .get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)) + .expect((res) => { + expect(res.status).toBe(200); + expect(res.text).toContain(t('ERRORS.VALID_CHOOSE_THE_FILE')); + }); + }); + + it('should handle errors', async () => { + (getClaimDetailsById as jest.Mock).mockRejectedValue(new Error('Error')); + + const res = await request(app).get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', '123').replace(':gaId', '456')); + + expect(res.status).toBe(500); + }); + }); + + describe('on post request', () => { + it('should handle file upload and redirect to the same page', async () => { + (getClaimDetailsById as jest.Mock).mockResolvedValue(claim); + (uploadSelectedFile as jest.Mock).mockResolvedValueOnce(void 0); + + const res = await request(app) + .post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)) + .field('action', 'uploadButton') + .attach('selectedFile', Buffer.from('file content'), 'test-file.txt'); + + expect(res.status).toBe(302); + expect(res.header['location']).toBe(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)); + expect(uploadSelectedFile).toHaveBeenCalledWith(expect.anything(), claim); + }); + + it('should redirect to CYA page if documents are uploaded', async () => { + const additionalDocument = new UploadAdditionalDocument(); + additionalDocument.typeOfDocument = 'testt' + additionalDocument.caseDocument = { + documentLink: { document_binary_url: 'binary_url1', document_filename: 'testDoc', document_url: 'url' }, + documentName: 'testDoc', + documentType: null, + documentSize: 1000, + createdDatetime: new Date(), + } as CaseDocument; + additionalDocument.fileUpload = new FileUpload(); + claim.generalApplication.uploadAdditionalDocuments = [additionalDocument]; + + (getClaimDetailsById as jest.Mock).mockResolvedValue(claim); + + const res = await request(app) + .post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)); + + expect(res.status).toBe(302); + expect(res.header['location']).toBe(GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL.replace(':id', claimId).replace(':gaId', gaId)); + }); + + it('should handle errors', async () => { + (getClaimDetailsById as jest.Mock).mockRejectedValue(new Error('Error')); + + const res = await request(app) + .post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', '123').replace(':gaId', '456')) + .field('action', 'submit'); + + expect(res.status).toBe(500); + }); + }); +}); diff --git a/src/test/unit/services/features/generalApplication/additionalDocumentService.test.ts b/src/test/unit/services/features/generalApplication/additionalDocumentService.test.ts new file mode 100644 index 00000000000..f433b11e8a3 --- /dev/null +++ b/src/test/unit/services/features/generalApplication/additionalDocumentService.test.ts @@ -0,0 +1,245 @@ +import { CivilServiceClient } from 'client/civilServiceClient'; +import { AppRequest, AppSession } from 'common/models/AppRequest'; +import { FileUpload } from 'common/models/caseProgression/fileUpload'; +import { Claim } from 'common/models/claim'; +import { CaseDocument } from 'common/models/document/caseDocument'; +import { GeneralApplication } from 'common/models/generalApplication/GeneralApplication'; +import { UploadAdditionalDocument } from 'common/models/generalApplication/UploadAdditionalDocument'; +import { summaryRow } from 'common/models/summaryList/summaryList'; +import { generateRedisKey, saveDraftClaim } from 'modules/draft-store/draftStoreService'; +import { getClaimById } from 'modules/utilityService'; +import { GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL } from 'routes/urls'; +import { TypeOfDocumentSectionMapper } from 'services/features/caseProgression/TypeOfDocumentSectionMapper'; +import { getClaimDetailsById, getContentForBody, getContentForCloseButton, getContentForPanel, getSummaryList, prepareCCDData, removeSelectedDocument, uploadSelectedFile } from 'services/features/generalApplication/additionalDocumentService'; + +const { Logger } = require('@hmcts/nodejs-logging'); +const logger = Logger.getLogger('additionalDocumentService'); + +jest.mock('uuid', () => ({ + v4: jest.fn().mockReturnValue('mocked-uuid'), +})); +jest.mock('../../../../../main/modules/draft-store/draftStoreService', () => ({ + saveDraftClaim: jest.fn(), + generateRedisKey: jest.fn(), +})); +jest.mock('../../../../../main/modules/utilityService'); +jest.mock('i18next', () => ({ + t: jest.fn((key) => key), +})); +jest.mock('../../../../../main/services/features/caseProgression/TypeOfDocumentSectionMapper', () => ({ + TypeOfDocumentSectionMapper: { + mapToSingleFile: jest.fn(), + }, +})); + +describe('Additional Documents Service', () => { + let claim: Claim; + beforeEach(() => { + claim = new Claim(); + claim.generalApplication = new GeneralApplication(); + jest.clearAllMocks(); + }); + describe('uploadSelectedFile', () => { + it('should upload file and save draft claim if no errors', async () => { + const req = { + body: { typeOfDocument: 'Type1' }, + session: {} as AppSession, + } as unknown as AppRequest; + const fileUpload = { name: 'file' }; + const uploadedDocument = { + documentName: 'Document1', + createdBy: 'User1', + documentLink: { document_url: 'url', document_filename: 'filename', document_binary_url: 'binaryUrl' }, + documentType: null, + documentSize: 123 + } as CaseDocument; + (TypeOfDocumentSectionMapper.mapToSingleFile as jest.Mock).mockReturnValue(fileUpload); + + + const mockValue = jest.spyOn(CivilServiceClient.prototype, 'uploadDocument').mockResolvedValue(uploadedDocument as any as CaseDocument); + + await uploadSelectedFile(req, claim as Claim); + + expect(TypeOfDocumentSectionMapper.mapToSingleFile).toHaveBeenCalledWith(req); + expect(mockValue).toHaveBeenCalledWith(req, fileUpload); + expect(claim.generalApplication.uploadAdditionalDocuments).toHaveLength(1); + expect(saveDraftClaim).toHaveBeenCalledWith(generateRedisKey(req), claim); + }); + + it('should set errors in session if validation fails', async () => { + const req = { + body: { typeOfDocument: 'Type1' }, + session: { fileUpload: undefined } as AppSession, + } as unknown as AppRequest; + + (TypeOfDocumentSectionMapper.mapToSingleFile as jest.Mock).mockReturnValue(undefined); + + await uploadSelectedFile(req, claim); + + expect(req.session.fileUpload).toBeDefined(); + }); + }); + describe('getSummaryList', () => { + it('should generate a summary list', () => { + const additionalDocumentsList: UploadAdditionalDocument[] = [ + { + typeOfDocument: 'Type1', + caseDocument: { + documentName: 'Document1', + createdBy: 'User1', + documentLink: { document_url: 'ur1', document_filename: 'filename1', document_binary_url: 'binaryUrl1' }, + documentType: null, + documentSize: 123 + } as CaseDocument, + fileUpload: {} as FileUpload + }, + { + typeOfDocument: 'Type2', + caseDocument: { + documentName: 'Document2', + createdBy: 'User2', + documentLink: { document_url: 'ur2', document_filename: 'filename2', document_binary_url: 'binaryUrl2' }, + documentType: null, + documentSize: 123 + } as CaseDocument, + fileUpload: {} as FileUpload + } + ]; + const claimId = '1'; + const gaId = '2'; + + const result = getSummaryList(additionalDocumentsList, claimId, gaId); + + expect(result.summaryList.rows).toHaveLength(4); + expect(result.summaryList.rows[0]).toEqual(summaryRow('Type of document', 'Type1')); + expect(result.summaryList.rows[1]).toEqual(summaryRow('Document1', '', `${GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)}?indexId=1`, 'Remove document')); + }); + }); + + describe('getClaimDetailsById', () => { + it('should retrieve and return claim details', async () => { + const req: AppRequest = { + params: { id: '1' } + } as unknown as AppRequest; + claim.generalApplication = undefined; + (getClaimById as jest.Mock).mockResolvedValue(claim); + + const result = await getClaimDetailsById(req); + + expect(result.generalApplication.uploadAdditionalDocuments).toEqual([]) + expect(getClaimById).toHaveBeenCalledWith(req.params.id, req, true); + }); + }); + describe('prepareCCDData', () => { + it('should correctly map UploadAdditionalDocuments to CCD format', () => { + const uploadAdditionalDocuments: UploadAdditionalDocument[] = [ + { + typeOfDocument: 'Type1', + caseDocument: { + documentName: 'Document1', + createdBy: 'User1', + documentLink: { + document_url: 'url1', + document_binary_url: 'binaryUrl1', + document_filename: 'filename1' + }, + documentType: null, + documentSize: 123 + } as CaseDocument, + fileUpload: {} as FileUpload + }, + { + typeOfDocument: 'Type2', + caseDocument: { + documentName: 'Document2', + createdBy: 'User2', + documentLink: { + document_url: 'url2', + document_binary_url: 'binaryUrl2', + document_filename: 'filename2' + }, + documentType: null, + documentSize: 456 + } as CaseDocument, + fileUpload: {} as FileUpload + } + ]; + + const result = prepareCCDData(uploadAdditionalDocuments); + + expect(result).toHaveLength(2); + result.forEach((item, index) => { + expect(item.id).toBe('mocked-uuid'); + expect(item.value.typeOfDocument).toBe(uploadAdditionalDocuments[index].typeOfDocument); + expect(item.value.documentUpload.document_url).toBe(uploadAdditionalDocuments[index].caseDocument.documentLink.document_url); + expect(item.value.documentUpload.document_binary_url).toBe(uploadAdditionalDocuments[index].caseDocument.documentLink.document_binary_url); + expect(item.value.documentUpload.document_filename).toBe(uploadAdditionalDocuments[index].caseDocument.documentName); + }); + }); + }); + describe('removeSelectedDocument', () => { + it('should remove selected document and save draft claim', async () => { + const redisKey = 'key'; + const claim: Claim = { + generalApplication: { + uploadAdditionalDocuments: [ + { + typeOfDocument: 'Type1', caseDocument: { + documentName: 'Document2', + createdBy: 'User2', + documentLink: { document_url: 'ur2', document_filename: 'filename2', document_binary_url: 'binaryUrl2' }, + documentType: null, + documentSize: 123 + } as CaseDocument, + fileUpload: {} as FileUpload + } + ] + } as GeneralApplication + } as Claim; + const index = 0; + + await removeSelectedDocument(redisKey, claim, index); + + expect(saveDraftClaim).toHaveBeenCalledWith(redisKey, claim); + expect(claim.generalApplication.uploadAdditionalDocuments).toHaveLength(0); + }); + + it('should handle error during document removal', async () => { + const redisKey = 'key'; + claim.generalApplication.uploadAdditionalDocuments.push({ typeOfDocument: 'Type1', caseDocument: { documentName: 'Document1' } as CaseDocument, fileUpload: {} as FileUpload }); + const index = 0; + const error = new Error('Error'); + (saveDraftClaim as jest.Mock).mockRejectedValue(error); + + const loggerErrorSpy = jest.spyOn(logger, 'error'); + + await expect(removeSelectedDocument(redisKey, claim, index)).rejects.toThrow(error); + expect(loggerErrorSpy).toHaveBeenCalledWith(error); + }); + }); + + describe('getContentForPanel', () => { + it('should return built content for panel', () => { + const lng = 'en'; + const result = getContentForPanel(lng); + expect(result).toEqual([{ "data": { "title": "PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.UPLOADED_ADDITIONAL_DOCS" }, "type": "panel" }]); + }); + }); + + describe('getContentForBody', () => { + it('should return built content for body', () => { + const lng = 'en'; + const result = getContentForBody(lng); + + expect(result).toEqual([{ "data": { "classes": undefined, "text": "PAGES.GENERAL_APPLICATION.GA_PAYMENT_SUCCESSFUL.WHAT_HAPPENS_NEXT", "variables": { "lng": "en" } }, "type": "title" }, { "data": { "classes": undefined, "text": "PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.JUDGE_WILL_REVIEW", "variables": { "lng": "en" } }, "type": "p" }]); + }); + }); + + describe('getContentForCloseButton', () => { + it('should return built content for close button', () => { + const redirectUrl = '/redirect-url'; + const result = getContentForCloseButton(redirectUrl); + expect(result).toEqual([{ "data": { "href": "/redirect-url", "text": "COMMON.BUTTONS.CLOSE_AND_RETURN_TO_DASHBOARD" }, "type": "button" }]); + }); + }); +}); From 7b95cdd265b926d5eb367682d5050de22f36c90c Mon Sep 17 00:00:00 2001 From: jeswanth Date: Mon, 15 Jul 2024 09:05:52 +0100 Subject: [PATCH 04/17] CIV-14228 fixed spaceing issues --- .../additionalDocumentService.ts | 142 +++---- .../additionalDocumentService.test.ts | 390 +++++++++--------- 2 files changed, 266 insertions(+), 266 deletions(-) diff --git a/src/main/services/features/generalApplication/additionalDocumentService.ts b/src/main/services/features/generalApplication/additionalDocumentService.ts index f0aca97fedb..5843a3ee5a2 100644 --- a/src/main/services/features/generalApplication/additionalDocumentService.ts +++ b/src/main/services/features/generalApplication/additionalDocumentService.ts @@ -24,101 +24,101 @@ const civilServiceApiBaseUrl = config.get('services.civilService.url'); const civilServiceClientForDocRetrieve: CivilServiceClient = new CivilServiceClient(civilServiceApiBaseUrl, true); export const getSummaryList = (additionalDocumentsList: UploadAdditionalDocument[], claimId: string, gaId: string): SummarySection => { - let index = 0; - const formattedSummary = summarySection( - { - title: '', - summaryRows: [], - }); - additionalDocumentsList.forEach((uploadDocument: UploadAdditionalDocument) => { - index = index + 1; - formattedSummary.summaryList.rows.push(summaryRow('Type of document', uploadDocument.typeOfDocument)); - formattedSummary.summaryList.rows.push(summaryRow(uploadDocument.caseDocument.documentName, '', `${GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)}?indexId=${index}`, 'Remove document')); + let index = 0; + const formattedSummary = summarySection( + { + title: '', + summaryRows: [], }); - return formattedSummary + additionalDocumentsList.forEach((uploadDocument: UploadAdditionalDocument) => { + index = index + 1; + formattedSummary.summaryList.rows.push(summaryRow('Type of document', uploadDocument.typeOfDocument)); + formattedSummary.summaryList.rows.push(summaryRow(uploadDocument.caseDocument.documentName, '', `${GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)}?indexId=${index}`, 'Remove document')); + }); + return formattedSummary }; export const removeSelectedDocument = async (redisKey: string, claim: Claim, index: number): Promise => { - try { - claim?.generalApplication?.uploadAdditionalDocuments?.splice(index, 1); - await saveDraftClaim(redisKey, claim); - } catch (error) { - logger.error(error); - throw error; - } + try { + claim?.generalApplication?.uploadAdditionalDocuments?.splice(index, 1); + await saveDraftClaim(redisKey, claim); + } catch (error) { + logger.error(error); + throw error; + } }; export const uploadSelectedFile = async (req: AppRequest, claim: Claim) => { - const uploadedDocument = new UploadAdditionalDocument(); - const fileUpload = TypeOfDocumentSectionMapper.mapToSingleFile(req); - uploadedDocument.fileUpload = fileUpload; - uploadedDocument.typeOfDocument = req.body.typeOfDocument; - const form = new GenericForm(uploadedDocument); - const uploadAdditionalDocuments = claim.generalApplication.uploadAdditionalDocuments - form.validateSync() - if (!form.hasErrors()) { - uploadedDocument.caseDocument = await civilServiceClientForDocRetrieve.uploadDocument(req, fileUpload); - uploadAdditionalDocuments.push(uploadedDocument); - await saveDraftClaim(generateRedisKey(req), claim); - } else { - const errors = translateErrors(form.getAllErrors(), t); - req.session.fileUpload = JSON.stringify(errors); - } + const uploadedDocument = new UploadAdditionalDocument(); + const fileUpload = TypeOfDocumentSectionMapper.mapToSingleFile(req); + uploadedDocument.fileUpload = fileUpload; + uploadedDocument.typeOfDocument = req.body.typeOfDocument; + const form = new GenericForm(uploadedDocument); + const uploadAdditionalDocuments = claim.generalApplication.uploadAdditionalDocuments + form.validateSync() + if (!form.hasErrors()) { + uploadedDocument.caseDocument = await civilServiceClientForDocRetrieve.uploadDocument(req, fileUpload); + uploadAdditionalDocuments.push(uploadedDocument); + await saveDraftClaim(generateRedisKey(req), claim); + } else { + const errors = translateErrors(form.getAllErrors(), t); + req.session.fileUpload = JSON.stringify(errors); + } } export const getClaimDetailsById = async (req: AppRequest): Promise => { - try { - const claim = await getClaimById(req.params.id, req, true) - const gaApplication = Object.assign(new GeneralApplication(), claim.generalApplication) - claim.generalApplication = gaApplication; - return claim - } catch (error) { - logger.error(error); - throw error; - } + try { + const claim = await getClaimById(req.params.id, req, true) + const gaApplication = Object.assign(new GeneralApplication(), claim.generalApplication) + claim.generalApplication = gaApplication; + return claim + } catch (error) { + logger.error(error); + throw error; + } } export const prepareCCDData = (uploadAdditionalDocuments: UploadAdditionalDocument[]) => { - return uploadAdditionalDocuments.map(doc => { - return { - id: uuIdv4(), - value: { - typeOfDocument: doc.typeOfDocument, - documentUpload: { - document_url: doc.caseDocument.documentLink.document_url, - document_binary_url: doc.caseDocument.documentLink.document_binary_url, - document_filename: doc.caseDocument.documentName, - } - - } + return uploadAdditionalDocuments.map(doc => { + return { + id: uuIdv4(), + value: { + typeOfDocument: doc.typeOfDocument, + documentUpload: { + document_url: doc.caseDocument.documentLink.document_url, + document_binary_url: doc.caseDocument.documentLink.document_binary_url, + document_filename: doc.caseDocument.documentName, } - }) + + } + } + }) } export const buildSummarySectionForAdditionalDoc = (additionalDocumentsList: UploadAdditionalDocument[], claimId: string, gaId: string) => { - const rows: SummaryRow[] = [] - additionalDocumentsList.forEach(doc => { - rows.push(summaryRow('Type of document', doc.typeOfDocument)); - rows.push(summaryRow('Uploaded document', doc.caseDocument.documentName, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId), changeLabel('en'))) - }) - return rows; + const rows: SummaryRow[] = [] + additionalDocumentsList.forEach(doc => { + rows.push(summaryRow('Type of document', doc.typeOfDocument)); + rows.push(summaryRow('Uploaded document', doc.caseDocument.documentName, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId), changeLabel('en'))) + }) + return rows; } export const getContentForPanel = (lng: string) => { - const panelBuilder = new PaymentSuccessfulSectionBuilder(); - panelBuilder.addPanelForConfirmation('PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.UPLOADED_ADDITIONAL_DOCS', getLng(lng)); - return panelBuilder.build(); + const panelBuilder = new PaymentSuccessfulSectionBuilder(); + panelBuilder.addPanelForConfirmation('PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.UPLOADED_ADDITIONAL_DOCS', getLng(lng)); + return panelBuilder.build(); } export const getContentForBody = (lng: string) => { - let contentBuilder = new PaymentSuccessfulSectionBuilder(); - return contentBuilder.addTitle('PAGES.GENERAL_APPLICATION.GA_PAYMENT_SUCCESSFUL.WHAT_HAPPENS_NEXT', { lng: getLng(lng) }) - .addParagraph('PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.JUDGE_WILL_REVIEW', { lng: getLng(lng) }) - .build(); + let contentBuilder = new PaymentSuccessfulSectionBuilder(); + return contentBuilder.addTitle('PAGES.GENERAL_APPLICATION.GA_PAYMENT_SUCCESSFUL.WHAT_HAPPENS_NEXT', { lng: getLng(lng) }) + .addParagraph('PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.JUDGE_WILL_REVIEW', { lng: getLng(lng) }) + .build(); } export const getContentForCloseButton = (redirectUrl: string) => { - return new PaymentSuccessfulSectionBuilder() - .addButton('COMMON.BUTTONS.CLOSE_AND_RETURN_TO_DASHBOARD', redirectUrl) - .build(); + return new PaymentSuccessfulSectionBuilder() + .addButton('COMMON.BUTTONS.CLOSE_AND_RETURN_TO_DASHBOARD', redirectUrl) + .build(); } \ No newline at end of file diff --git a/src/test/unit/services/features/generalApplication/additionalDocumentService.test.ts b/src/test/unit/services/features/generalApplication/additionalDocumentService.test.ts index f433b11e8a3..5f075ad465b 100644 --- a/src/test/unit/services/features/generalApplication/additionalDocumentService.test.ts +++ b/src/test/unit/services/features/generalApplication/additionalDocumentService.test.ts @@ -16,230 +16,230 @@ const { Logger } = require('@hmcts/nodejs-logging'); const logger = Logger.getLogger('additionalDocumentService'); jest.mock('uuid', () => ({ - v4: jest.fn().mockReturnValue('mocked-uuid'), + v4: jest.fn().mockReturnValue('mocked-uuid'), })); jest.mock('../../../../../main/modules/draft-store/draftStoreService', () => ({ - saveDraftClaim: jest.fn(), - generateRedisKey: jest.fn(), + saveDraftClaim: jest.fn(), + generateRedisKey: jest.fn(), })); jest.mock('../../../../../main/modules/utilityService'); jest.mock('i18next', () => ({ - t: jest.fn((key) => key), + t: jest.fn((key) => key), })); jest.mock('../../../../../main/services/features/caseProgression/TypeOfDocumentSectionMapper', () => ({ - TypeOfDocumentSectionMapper: { - mapToSingleFile: jest.fn(), - }, + TypeOfDocumentSectionMapper: { + mapToSingleFile: jest.fn(), + }, })); describe('Additional Documents Service', () => { - let claim: Claim; - beforeEach(() => { - claim = new Claim(); - claim.generalApplication = new GeneralApplication(); - jest.clearAllMocks(); + let claim: Claim; + beforeEach(() => { + claim = new Claim(); + claim.generalApplication = new GeneralApplication(); + jest.clearAllMocks(); + }); + describe('uploadSelectedFile', () => { + it('should upload file and save draft claim if no errors', async () => { + const req = { + body: { typeOfDocument: 'Type1' }, + session: {} as AppSession, + } as unknown as AppRequest; + const fileUpload = { name: 'file' }; + const uploadedDocument = { + documentName: 'Document1', + createdBy: 'User1', + documentLink: { document_url: 'url', document_filename: 'filename', document_binary_url: 'binaryUrl' }, + documentType: null, + documentSize: 123 + } as CaseDocument; + (TypeOfDocumentSectionMapper.mapToSingleFile as jest.Mock).mockReturnValue(fileUpload); + + + const mockValue = jest.spyOn(CivilServiceClient.prototype, 'uploadDocument').mockResolvedValue(uploadedDocument as any as CaseDocument); + + await uploadSelectedFile(req, claim as Claim); + + expect(TypeOfDocumentSectionMapper.mapToSingleFile).toHaveBeenCalledWith(req); + expect(mockValue).toHaveBeenCalledWith(req, fileUpload); + expect(claim.generalApplication.uploadAdditionalDocuments).toHaveLength(1); + expect(saveDraftClaim).toHaveBeenCalledWith(generateRedisKey(req), claim); }); - describe('uploadSelectedFile', () => { - it('should upload file and save draft claim if no errors', async () => { - const req = { - body: { typeOfDocument: 'Type1' }, - session: {} as AppSession, - } as unknown as AppRequest; - const fileUpload = { name: 'file' }; - const uploadedDocument = { - documentName: 'Document1', - createdBy: 'User1', - documentLink: { document_url: 'url', document_filename: 'filename', document_binary_url: 'binaryUrl' }, - documentType: null, - documentSize: 123 - } as CaseDocument; - (TypeOfDocumentSectionMapper.mapToSingleFile as jest.Mock).mockReturnValue(fileUpload); - - const mockValue = jest.spyOn(CivilServiceClient.prototype, 'uploadDocument').mockResolvedValue(uploadedDocument as any as CaseDocument); + it('should set errors in session if validation fails', async () => { + const req = { + body: { typeOfDocument: 'Type1' }, + session: { fileUpload: undefined } as AppSession, + } as unknown as AppRequest; - await uploadSelectedFile(req, claim as Claim); + (TypeOfDocumentSectionMapper.mapToSingleFile as jest.Mock).mockReturnValue(undefined); - expect(TypeOfDocumentSectionMapper.mapToSingleFile).toHaveBeenCalledWith(req); - expect(mockValue).toHaveBeenCalledWith(req, fileUpload); - expect(claim.generalApplication.uploadAdditionalDocuments).toHaveLength(1); - expect(saveDraftClaim).toHaveBeenCalledWith(generateRedisKey(req), claim); - }); + await uploadSelectedFile(req, claim); - it('should set errors in session if validation fails', async () => { - const req = { - body: { typeOfDocument: 'Type1' }, - session: { fileUpload: undefined } as AppSession, - } as unknown as AppRequest; + expect(req.session.fileUpload).toBeDefined(); + }); + }); + describe('getSummaryList', () => { + it('should generate a summary list', () => { + const additionalDocumentsList: UploadAdditionalDocument[] = [ + { + typeOfDocument: 'Type1', + caseDocument: { + documentName: 'Document1', + createdBy: 'User1', + documentLink: { document_url: 'ur1', document_filename: 'filename1', document_binary_url: 'binaryUrl1' }, + documentType: null, + documentSize: 123 + } as CaseDocument, + fileUpload: {} as FileUpload + }, + { + typeOfDocument: 'Type2', + caseDocument: { + documentName: 'Document2', + createdBy: 'User2', + documentLink: { document_url: 'ur2', document_filename: 'filename2', document_binary_url: 'binaryUrl2' }, + documentType: null, + documentSize: 123 + } as CaseDocument, + fileUpload: {} as FileUpload + } + ]; + const claimId = '1'; + const gaId = '2'; + + const result = getSummaryList(additionalDocumentsList, claimId, gaId); + + expect(result.summaryList.rows).toHaveLength(4); + expect(result.summaryList.rows[0]).toEqual(summaryRow('Type of document', 'Type1')); + expect(result.summaryList.rows[1]).toEqual(summaryRow('Document1', '', `${GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)}?indexId=1`, 'Remove document')); + }); + }); - (TypeOfDocumentSectionMapper.mapToSingleFile as jest.Mock).mockReturnValue(undefined); + describe('getClaimDetailsById', () => { + it('should retrieve and return claim details', async () => { + const req: AppRequest = { + params: { id: '1' } + } as unknown as AppRequest; + claim.generalApplication = undefined; + (getClaimById as jest.Mock).mockResolvedValue(claim); - await uploadSelectedFile(req, claim); + const result = await getClaimDetailsById(req); - expect(req.session.fileUpload).toBeDefined(); - }); + expect(result.generalApplication.uploadAdditionalDocuments).toEqual([]) + expect(getClaimById).toHaveBeenCalledWith(req.params.id, req, true); }); - describe('getSummaryList', () => { - it('should generate a summary list', () => { - const additionalDocumentsList: UploadAdditionalDocument[] = [ - { - typeOfDocument: 'Type1', - caseDocument: { - documentName: 'Document1', - createdBy: 'User1', - documentLink: { document_url: 'ur1', document_filename: 'filename1', document_binary_url: 'binaryUrl1' }, - documentType: null, - documentSize: 123 - } as CaseDocument, - fileUpload: {} as FileUpload - }, - { - typeOfDocument: 'Type2', - caseDocument: { - documentName: 'Document2', - createdBy: 'User2', - documentLink: { document_url: 'ur2', document_filename: 'filename2', document_binary_url: 'binaryUrl2' }, - documentType: null, - documentSize: 123 - } as CaseDocument, - fileUpload: {} as FileUpload - } - ]; - const claimId = '1'; - const gaId = '2'; - - const result = getSummaryList(additionalDocumentsList, claimId, gaId); - - expect(result.summaryList.rows).toHaveLength(4); - expect(result.summaryList.rows[0]).toEqual(summaryRow('Type of document', 'Type1')); - expect(result.summaryList.rows[1]).toEqual(summaryRow('Document1', '', `${GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)}?indexId=1`, 'Remove document')); - }); + }); + describe('prepareCCDData', () => { + it('should correctly map UploadAdditionalDocuments to CCD format', () => { + const uploadAdditionalDocuments: UploadAdditionalDocument[] = [ + { + typeOfDocument: 'Type1', + caseDocument: { + documentName: 'Document1', + createdBy: 'User1', + documentLink: { + document_url: 'url1', + document_binary_url: 'binaryUrl1', + document_filename: 'filename1' + }, + documentType: null, + documentSize: 123 + } as CaseDocument, + fileUpload: {} as FileUpload + }, + { + typeOfDocument: 'Type2', + caseDocument: { + documentName: 'Document2', + createdBy: 'User2', + documentLink: { + document_url: 'url2', + document_binary_url: 'binaryUrl2', + document_filename: 'filename2' + }, + documentType: null, + documentSize: 456 + } as CaseDocument, + fileUpload: {} as FileUpload + } + ]; + + const result = prepareCCDData(uploadAdditionalDocuments); + + expect(result).toHaveLength(2); + result.forEach((item, index) => { + expect(item.id).toBe('mocked-uuid'); + expect(item.value.typeOfDocument).toBe(uploadAdditionalDocuments[index].typeOfDocument); + expect(item.value.documentUpload.document_url).toBe(uploadAdditionalDocuments[index].caseDocument.documentLink.document_url); + expect(item.value.documentUpload.document_binary_url).toBe(uploadAdditionalDocuments[index].caseDocument.documentLink.document_binary_url); + expect(item.value.documentUpload.document_filename).toBe(uploadAdditionalDocuments[index].caseDocument.documentName); + }); + }); + }); + describe('removeSelectedDocument', () => { + it('should remove selected document and save draft claim', async () => { + const redisKey = 'key'; + const claim: Claim = { + generalApplication: { + uploadAdditionalDocuments: [ + { + typeOfDocument: 'Type1', caseDocument: { + documentName: 'Document2', + createdBy: 'User2', + documentLink: { document_url: 'ur2', document_filename: 'filename2', document_binary_url: 'binaryUrl2' }, + documentType: null, + documentSize: 123 + } as CaseDocument, + fileUpload: {} as FileUpload + } + ] + } as GeneralApplication + } as Claim; + const index = 0; + + await removeSelectedDocument(redisKey, claim, index); + + expect(saveDraftClaim).toHaveBeenCalledWith(redisKey, claim); + expect(claim.generalApplication.uploadAdditionalDocuments).toHaveLength(0); }); - describe('getClaimDetailsById', () => { - it('should retrieve and return claim details', async () => { - const req: AppRequest = { - params: { id: '1' } - } as unknown as AppRequest; - claim.generalApplication = undefined; - (getClaimById as jest.Mock).mockResolvedValue(claim); + it('should handle error during document removal', async () => { + const redisKey = 'key'; + claim.generalApplication.uploadAdditionalDocuments.push({ typeOfDocument: 'Type1', caseDocument: { documentName: 'Document1' } as CaseDocument, fileUpload: {} as FileUpload }); + const index = 0; + const error = new Error('Error'); + (saveDraftClaim as jest.Mock).mockRejectedValue(error); - const result = await getClaimDetailsById(req); + const loggerErrorSpy = jest.spyOn(logger, 'error'); - expect(result.generalApplication.uploadAdditionalDocuments).toEqual([]) - expect(getClaimById).toHaveBeenCalledWith(req.params.id, req, true); - }); - }); - describe('prepareCCDData', () => { - it('should correctly map UploadAdditionalDocuments to CCD format', () => { - const uploadAdditionalDocuments: UploadAdditionalDocument[] = [ - { - typeOfDocument: 'Type1', - caseDocument: { - documentName: 'Document1', - createdBy: 'User1', - documentLink: { - document_url: 'url1', - document_binary_url: 'binaryUrl1', - document_filename: 'filename1' - }, - documentType: null, - documentSize: 123 - } as CaseDocument, - fileUpload: {} as FileUpload - }, - { - typeOfDocument: 'Type2', - caseDocument: { - documentName: 'Document2', - createdBy: 'User2', - documentLink: { - document_url: 'url2', - document_binary_url: 'binaryUrl2', - document_filename: 'filename2' - }, - documentType: null, - documentSize: 456 - } as CaseDocument, - fileUpload: {} as FileUpload - } - ]; - - const result = prepareCCDData(uploadAdditionalDocuments); - - expect(result).toHaveLength(2); - result.forEach((item, index) => { - expect(item.id).toBe('mocked-uuid'); - expect(item.value.typeOfDocument).toBe(uploadAdditionalDocuments[index].typeOfDocument); - expect(item.value.documentUpload.document_url).toBe(uploadAdditionalDocuments[index].caseDocument.documentLink.document_url); - expect(item.value.documentUpload.document_binary_url).toBe(uploadAdditionalDocuments[index].caseDocument.documentLink.document_binary_url); - expect(item.value.documentUpload.document_filename).toBe(uploadAdditionalDocuments[index].caseDocument.documentName); - }); - }); - }); - describe('removeSelectedDocument', () => { - it('should remove selected document and save draft claim', async () => { - const redisKey = 'key'; - const claim: Claim = { - generalApplication: { - uploadAdditionalDocuments: [ - { - typeOfDocument: 'Type1', caseDocument: { - documentName: 'Document2', - createdBy: 'User2', - documentLink: { document_url: 'ur2', document_filename: 'filename2', document_binary_url: 'binaryUrl2' }, - documentType: null, - documentSize: 123 - } as CaseDocument, - fileUpload: {} as FileUpload - } - ] - } as GeneralApplication - } as Claim; - const index = 0; - - await removeSelectedDocument(redisKey, claim, index); - - expect(saveDraftClaim).toHaveBeenCalledWith(redisKey, claim); - expect(claim.generalApplication.uploadAdditionalDocuments).toHaveLength(0); - }); - - it('should handle error during document removal', async () => { - const redisKey = 'key'; - claim.generalApplication.uploadAdditionalDocuments.push({ typeOfDocument: 'Type1', caseDocument: { documentName: 'Document1' } as CaseDocument, fileUpload: {} as FileUpload }); - const index = 0; - const error = new Error('Error'); - (saveDraftClaim as jest.Mock).mockRejectedValue(error); - - const loggerErrorSpy = jest.spyOn(logger, 'error'); - - await expect(removeSelectedDocument(redisKey, claim, index)).rejects.toThrow(error); - expect(loggerErrorSpy).toHaveBeenCalledWith(error); - }); + await expect(removeSelectedDocument(redisKey, claim, index)).rejects.toThrow(error); + expect(loggerErrorSpy).toHaveBeenCalledWith(error); }); + }); - describe('getContentForPanel', () => { - it('should return built content for panel', () => { - const lng = 'en'; - const result = getContentForPanel(lng); - expect(result).toEqual([{ "data": { "title": "PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.UPLOADED_ADDITIONAL_DOCS" }, "type": "panel" }]); - }); + describe('getContentForPanel', () => { + it('should return built content for panel', () => { + const lng = 'en'; + const result = getContentForPanel(lng); + expect(result).toEqual([{ "data": { "title": "PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.UPLOADED_ADDITIONAL_DOCS" }, "type": "panel" }]); }); + }); - describe('getContentForBody', () => { - it('should return built content for body', () => { - const lng = 'en'; - const result = getContentForBody(lng); + describe('getContentForBody', () => { + it('should return built content for body', () => { + const lng = 'en'; + const result = getContentForBody(lng); - expect(result).toEqual([{ "data": { "classes": undefined, "text": "PAGES.GENERAL_APPLICATION.GA_PAYMENT_SUCCESSFUL.WHAT_HAPPENS_NEXT", "variables": { "lng": "en" } }, "type": "title" }, { "data": { "classes": undefined, "text": "PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.JUDGE_WILL_REVIEW", "variables": { "lng": "en" } }, "type": "p" }]); - }); + expect(result).toEqual([{ "data": { "classes": undefined, "text": "PAGES.GENERAL_APPLICATION.GA_PAYMENT_SUCCESSFUL.WHAT_HAPPENS_NEXT", "variables": { "lng": "en" } }, "type": "title" }, { "data": { "classes": undefined, "text": "PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.JUDGE_WILL_REVIEW", "variables": { "lng": "en" } }, "type": "p" }]); }); + }); - describe('getContentForCloseButton', () => { - it('should return built content for close button', () => { - const redirectUrl = '/redirect-url'; - const result = getContentForCloseButton(redirectUrl); - expect(result).toEqual([{ "data": { "href": "/redirect-url", "text": "COMMON.BUTTONS.CLOSE_AND_RETURN_TO_DASHBOARD" }, "type": "button" }]); - }); + describe('getContentForCloseButton', () => { + it('should return built content for close button', () => { + const redirectUrl = '/redirect-url'; + const result = getContentForCloseButton(redirectUrl); + expect(result).toEqual([{ "data": { "href": "/redirect-url", "text": "COMMON.BUTTONS.CLOSE_AND_RETURN_TO_DASHBOARD" }, "type": "button" }]); }); + }); }); From d737fde3a02367e0e0340724100661c1f4e4e3b6 Mon Sep 17 00:00:00 2001 From: jeswanth Date: Mon, 15 Jul 2024 09:10:15 +0100 Subject: [PATCH 05/17] fixed spacing issues --- .../checkAnswersController.ts | 46 +-- .../submittedController.ts | 28 +- .../uploadAdditionalDocumentsController.ts | 104 ++--- .../checkAnswersController.test.ts | 114 +++--- .../submittedController.test.ts | 74 ++-- ...ploadAdditionalDocumentsController.test.ts | 372 +++++++++--------- 6 files changed, 369 insertions(+), 369 deletions(-) diff --git a/src/main/routes/features/generalApplication/additionalDocuments/checkAnswersController.ts b/src/main/routes/features/generalApplication/additionalDocuments/checkAnswersController.ts index cccec6fbd02..a9912d52546 100644 --- a/src/main/routes/features/generalApplication/additionalDocuments/checkAnswersController.ts +++ b/src/main/routes/features/generalApplication/additionalDocuments/checkAnswersController.ts @@ -14,32 +14,32 @@ const generalAppApiBaseUrl = config.get('services.generalApplication.url const gaServiceClient: GaServiceClient = new GaServiceClient(generalAppApiBaseUrl); gaAdditionalDocCheckAnswerController.get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, (async (req: AppRequest, res: Response, next: NextFunction) => { - try { - const { gaId, id: claimId } = req.params - const claimIdPrettified = caseNumberPrettify(claimId); - const claim = await getClaimDetailsById(req); - const cancelUrl = await getCancelUrl(claimId, claim); - const backLinkUrl = GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId) - const summaryRows = buildSummarySectionForAdditionalDoc(claim.generalApplication.uploadAdditionalDocuments, claimId, gaId) - res.render(viewPath, { backLinkUrl, cancelUrl, claimIdPrettified, claim, summaryRows }); - } catch (error) { - next(error); - } + try { + const { gaId, id: claimId } = req.params + const claimIdPrettified = caseNumberPrettify(claimId); + const claim = await getClaimDetailsById(req); + const cancelUrl = await getCancelUrl(claimId, claim); + const backLinkUrl = GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId) + const summaryRows = buildSummarySectionForAdditionalDoc(claim.generalApplication.uploadAdditionalDocuments, claimId, gaId) + res.render(viewPath, { backLinkUrl, cancelUrl, claimIdPrettified, claim, summaryRows }); + } catch (error) { + next(error); + } }) as RequestHandler) gaAdditionalDocCheckAnswerController.post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, (async (req: AppRequest, res: Response, next: NextFunction) => { - try { - const { gaId, id: claimId } = req.params; - const claim = await getClaimDetailsById(req); - const uploadedDocuments = prepareCCDData(claim.generalApplication.uploadAdditionalDocuments); - const generalApplication = { - uploadDocument: uploadedDocuments - }; - await gaServiceClient.submitEvent(ApplicationEvent.UPLOAD_ADDL_DOCUMENTS, gaId, generalApplication as unknown, req); - res.redirect(GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL.replace(':id', claimId).replace(':gaId', gaId)); - } catch (error) { - next(error); - } + try { + const { gaId, id: claimId } = req.params; + const claim = await getClaimDetailsById(req); + const uploadedDocuments = prepareCCDData(claim.generalApplication.uploadAdditionalDocuments); + const generalApplication = { + uploadDocument: uploadedDocuments + }; + await gaServiceClient.submitEvent(ApplicationEvent.UPLOAD_ADDL_DOCUMENTS, gaId, generalApplication as unknown, req); + res.redirect(GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL.replace(':id', claimId).replace(':gaId', gaId)); + } catch (error) { + next(error); + } }) as RequestHandler); diff --git a/src/main/routes/features/generalApplication/additionalDocuments/submittedController.ts b/src/main/routes/features/generalApplication/additionalDocuments/submittedController.ts index 4b57c8a0821..65a879f893f 100644 --- a/src/main/routes/features/generalApplication/additionalDocuments/submittedController.ts +++ b/src/main/routes/features/generalApplication/additionalDocuments/submittedController.ts @@ -10,20 +10,20 @@ const additionalDocSubmittedController = Router(); const viewPath = 'features/generalApplication/additionalDocuments/submitted' additionalDocSubmittedController.get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL, (async (req: AppRequest, res: Response, next: NextFunction) => { - try { - const lng = req.query.lang ? req.query.lang : req.cookies.lang; - const { id } = req.params - const claim = await getClaimById(id, req, true); - const redisKey = generateRedisKey(req); - await deleteDraftClaimFromStore(redisKey); - res.render(viewPath, { - gaPaymentSuccessfulPanel: getContentForPanel(lng), - gaPaymentSuccessfulBody: getContentForBody(lng), - gaPaymentSuccessfulButton: getContentForCloseButton(await getCancelUrl(id, claim)), - }) - } catch (err) { - next(err); - } + try { + const lng = req.query.lang ? req.query.lang : req.cookies.lang; + const { id } = req.params + const claim = await getClaimById(id, req, true); + const redisKey = generateRedisKey(req); + await deleteDraftClaimFromStore(redisKey); + res.render(viewPath, { + gaPaymentSuccessfulPanel: getContentForPanel(lng), + gaPaymentSuccessfulBody: getContentForBody(lng), + gaPaymentSuccessfulButton: getContentForCloseButton(await getCancelUrl(id, claim)), + }) + } catch (err) { + next(err); + } }) as RequestHandler) export default additionalDocSubmittedController; \ No newline at end of file diff --git a/src/main/routes/features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.ts b/src/main/routes/features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.ts index 84e84088529..f5fc11d67a4 100644 --- a/src/main/routes/features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.ts +++ b/src/main/routes/features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.ts @@ -14,68 +14,68 @@ const uploadAdditionalDocumentsController = Router(); const viewPath = 'features/generalApplication/additionalDocuments/upload-additional-documents'; const fileSize = Infinity; const upload = multer({ - limits: { - fileSize: fileSize, - }, + limits: { + fileSize: fileSize, + }, }); uploadAdditionalDocumentsController.get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL, (async (req: AppRequest, res: Response, next: NextFunction) => { - try { - const { gaId, id } = req.params; - const uploadedDocument = new UploadAdditionalDocument(); - let form = new GenericForm(uploadedDocument); - const redisKey = generateRedisKey(req); - const claim = await getClaimDetailsById(req); - const gaDetails = claim.generalApplication; + try { + const { gaId, id } = req.params; + const uploadedDocument = new UploadAdditionalDocument(); + let form = new GenericForm(uploadedDocument); + const redisKey = generateRedisKey(req); + const claim = await getClaimDetailsById(req); + const gaDetails = claim.generalApplication; - if (req?.session?.fileUpload) { - const parsedData = JSON.parse(req?.session?.fileUpload); - form = new GenericForm(uploadedDocument, parsedData); - req.session.fileUpload = undefined; - } - if (req.query?.indexId) { - const index = req.query.indexId; - await removeSelectedDocument(redisKey, claim, Number(index) - 1); - } - const cancelUrl = await getCancelUrl(id, claim); - const backLinkUrl = `${constructResponseUrlWithIdParams(id, GA_VIEW_APPLICATION_URL)}?applicationId=${gaId}`; - const formattedSummary = getSummaryList(gaDetails.uploadAdditionalDocuments, id, gaId); - res.render(viewPath, { cancelUrl, backLinkUrl, form, formattedSummary }); - } catch (err) { - next(err); + if (req?.session?.fileUpload) { + const parsedData = JSON.parse(req?.session?.fileUpload); + form = new GenericForm(uploadedDocument, parsedData); + req.session.fileUpload = undefined; } + if (req.query?.indexId) { + const index = req.query.indexId; + await removeSelectedDocument(redisKey, claim, Number(index) - 1); + } + const cancelUrl = await getCancelUrl(id, claim); + const backLinkUrl = `${constructResponseUrlWithIdParams(id, GA_VIEW_APPLICATION_URL)}?applicationId=${gaId}`; + const formattedSummary = getSummaryList(gaDetails.uploadAdditionalDocuments, id, gaId); + res.render(viewPath, { cancelUrl, backLinkUrl, form, formattedSummary }); + } catch (err) { + next(err); + } }) as RequestHandler) uploadAdditionalDocumentsController.post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL, upload.single('selectedFile'), (async (req: AppRequest, res: Response, next: NextFunction) => { - try { - const { gaId, id } = req.params - const currentUrl = GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', id).replace(':gaId', gaId) - const claim = await getClaimDetailsById(req); - const gaDetails = claim.generalApplication; - if (req.body.action === 'uploadButton') { - await uploadSelectedFile(req, claim); - return res.redirect(`${currentUrl}`); - } - if (gaDetails.uploadAdditionalDocuments.length === 0) { - const errors = [{ - target: { - fileUpload: '', - typeOfDocument: '', - }, - value: '', - property: '', + try { + const { gaId, id } = req.params + const currentUrl = GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', id).replace(':gaId', gaId) + const claim = await getClaimDetailsById(req); + const gaDetails = claim.generalApplication; + if (req.body.action === 'uploadButton') { + await uploadSelectedFile(req, claim); + return res.redirect(`${currentUrl}`); + } + if (gaDetails.uploadAdditionalDocuments.length === 0) { + const errors = [{ + target: { + fileUpload: '', + typeOfDocument: '', + }, + value: '', + property: '', - constraints: { - isNotEmpty: 'ERRORS.GENERAL_APPLICATION.UPLOAD_ONE_FILE' - }, - }] - req.session.fileUpload = JSON.stringify(errors); - return res.redirect(`${currentUrl}`); - } - res.redirect(constructResponseUrlWithIdParams(id, GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL).replace(':gaId', gaId)); - } catch (err) { - next(err) + constraints: { + isNotEmpty: 'ERRORS.GENERAL_APPLICATION.UPLOAD_ONE_FILE' + }, + }] + req.session.fileUpload = JSON.stringify(errors); + return res.redirect(`${currentUrl}`); } + res.redirect(constructResponseUrlWithIdParams(id, GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL).replace(':gaId', gaId)); + } catch (err) { + next(err) + } })) export default uploadAdditionalDocumentsController; \ No newline at end of file diff --git a/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/checkAnswersController.test.ts b/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/checkAnswersController.test.ts index a5da665da61..7902c673fbe 100644 --- a/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/checkAnswersController.test.ts +++ b/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/checkAnswersController.test.ts @@ -15,80 +15,80 @@ jest.mock('../../../../../../../main/modules/oidc'); // jest.mock('../../../../../../../main/modules/draft-store/draftStoreService'); jest.mock('../../../../../../../main/app/auth/launchdarkly/launchDarklyClient'); jest.mock('../../../../../../../main/services/features/generalApplication/additionalDocumentService', () => ({ - getClaimDetailsById: jest.fn(), - prepareCCDData: jest.fn(), - buildSummarySectionForAdditionalDoc: jest.fn(), + getClaimDetailsById: jest.fn(), + prepareCCDData: jest.fn(), + buildSummarySectionForAdditionalDoc: jest.fn(), })); jest.mock('../../../../../../../main/services/features/generalApplication/generalApplicationService', () => ({ - getCancelUrl: jest.fn(), + getCancelUrl: jest.fn(), })); describe('General Application - additional docs check answer controller ', () => { - const citizenRoleToken: string = config.get('citizenRoleToken'); - const idamUrl: string = config.get('idamUrl'); - beforeAll(() => { - nock(idamUrl) - .post('/o/token') - .reply(200, { id_token: citizenRoleToken }); - (isGaForLipsEnabled as jest.Mock).mockResolvedValue(true); - }); + const citizenRoleToken: string = config.get('citizenRoleToken'); + const idamUrl: string = config.get('idamUrl'); + beforeAll(() => { + nock(idamUrl) + .post('/o/token') + .reply(200, { id_token: citizenRoleToken }); + (isGaForLipsEnabled as jest.Mock).mockResolvedValue(true); + }); - beforeEach(() => { - jest.clearAllMocks(); - }); - describe('GET check your answers', () => { - it('should render the check answers page with correct data', async () => { - const claimId = '123'; - const gaId = '456'; - const claim = new Claim(); - claim.generalApplication = new GeneralApplication(); - (getClaimDetailsById as jest.Mock).mockResolvedValue(claim); - (getCancelUrl as jest.Mock).mockResolvedValue('/cancel-url'); - (buildSummarySectionForAdditionalDoc as jest.Mock).mockReturnValue([]); + beforeEach(() => { + jest.clearAllMocks(); + }); + describe('GET check your answers', () => { + it('should render the check answers page with correct data', async () => { + const claimId = '123'; + const gaId = '456'; + const claim = new Claim(); + claim.generalApplication = new GeneralApplication(); + (getClaimDetailsById as jest.Mock).mockResolvedValue(claim); + (getCancelUrl as jest.Mock).mockResolvedValue('/cancel-url'); + (buildSummarySectionForAdditionalDoc as jest.Mock).mockReturnValue([]); - const res = await request(app).get(`${GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL.replace(':id', claimId).replace(':gaId', gaId)}`); + const res = await request(app).get(`${GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL.replace(':id', claimId).replace(':gaId', gaId)}`); - expect(res.status).toBe(200); - expect(getClaimDetailsById).toHaveBeenCalledWith(expect.anything()); - expect(getCancelUrl).toHaveBeenCalledWith(claimId, claim); - expect(buildSummarySectionForAdditionalDoc).toHaveBeenCalledWith(claim.generalApplication.uploadAdditionalDocuments, claimId, gaId); - expect(res.text).toContain('Check your answers'); - }); + expect(res.status).toBe(200); + expect(getClaimDetailsById).toHaveBeenCalledWith(expect.anything()); + expect(getCancelUrl).toHaveBeenCalledWith(claimId, claim); + expect(buildSummarySectionForAdditionalDoc).toHaveBeenCalledWith(claim.generalApplication.uploadAdditionalDocuments, claimId, gaId); + expect(res.text).toContain('Check your answers'); + }); - it('should handle errors', async () => { - (getClaimDetailsById as jest.Mock).mockRejectedValue(new Error('Error')); + it('should handle errors', async () => { + (getClaimDetailsById as jest.Mock).mockRejectedValue(new Error('Error')); - const res = await request(app).get(`${GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL.replace(':id', '123').replace(':gaId', '456')}`); + const res = await request(app).get(`${GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL.replace(':id', '123').replace(':gaId', '456')}`); - expect(res.status).toBe(500); - }); + expect(res.status).toBe(500); }); + }); - describe('POST /ga-upload-additional-documents-cya', () => { - it('should submit the documents and redirect to submitted page', async () => { - const claimId = '123'; - const gaId = '456'; - const claim = new Claim(); - claim.generalApplication = new GeneralApplication(); - (getClaimDetailsById as jest.Mock).mockResolvedValue(claim); - (prepareCCDData as jest.Mock).mockReturnValue([]); - const mockGaServiceClient = jest.spyOn(GaServiceClient.prototype, 'submitEvent').mockResolvedValueOnce(undefined); + describe('POST /ga-upload-additional-documents-cya', () => { + it('should submit the documents and redirect to submitted page', async () => { + const claimId = '123'; + const gaId = '456'; + const claim = new Claim(); + claim.generalApplication = new GeneralApplication(); + (getClaimDetailsById as jest.Mock).mockResolvedValue(claim); + (prepareCCDData as jest.Mock).mockReturnValue([]); + const mockGaServiceClient = jest.spyOn(GaServiceClient.prototype, 'submitEvent').mockResolvedValueOnce(undefined); - const res = await request(app).post(`${GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL.replace(':id', claimId).replace(':gaId', gaId)}`); + const res = await request(app).post(`${GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL.replace(':id', claimId).replace(':gaId', gaId)}`); - expect(res.status).toBe(302); - expect(res.header.location).toBe(GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL.replace(':id', claimId).replace(':gaId', gaId)); - expect(getClaimDetailsById).toHaveBeenCalledWith(expect.anything()); - expect(prepareCCDData).toHaveBeenCalledWith(claim.generalApplication.uploadAdditionalDocuments); - expect(mockGaServiceClient).toHaveBeenCalledWith(ApplicationEvent.UPLOAD_ADDL_DOCUMENTS, gaId, { uploadDocument: [] }, expect.anything()); - }); + expect(res.status).toBe(302); + expect(res.header.location).toBe(GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL.replace(':id', claimId).replace(':gaId', gaId)); + expect(getClaimDetailsById).toHaveBeenCalledWith(expect.anything()); + expect(prepareCCDData).toHaveBeenCalledWith(claim.generalApplication.uploadAdditionalDocuments); + expect(mockGaServiceClient).toHaveBeenCalledWith(ApplicationEvent.UPLOAD_ADDL_DOCUMENTS, gaId, { uploadDocument: [] }, expect.anything()); + }); - it('should handle errors', async () => { - (getClaimDetailsById as jest.Mock).mockRejectedValue(new Error('Error')); + it('should handle errors', async () => { + (getClaimDetailsById as jest.Mock).mockRejectedValue(new Error('Error')); - const res = await request(app).post(`${GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL.replace(':id', '123').replace(':gaId', '456')}`).send({}); + const res = await request(app).post(`${GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL.replace(':id', '123').replace(':gaId', '456')}`).send({}); - expect(res.status).toBe(500); - }); + expect(res.status).toBe(500); }); + }); }) \ No newline at end of file diff --git a/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/submittedController.test.ts b/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/submittedController.test.ts index 1684f81b4c7..88d837a97e9 100644 --- a/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/submittedController.test.ts +++ b/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/submittedController.test.ts @@ -13,53 +13,53 @@ jest.mock('../../../../../../../main/modules/oidc'); jest.mock('../../../..../../../../../../main/modules/utilityService'); jest.mock('../../../../../../../main/app/auth/launchdarkly/launchDarklyClient'); jest.mock('../../../../../../../main/modules/draft-store/draftStoreService', () => ({ - generateRedisKey: jest.fn((key) => key), - deleteDraftClaimFromStore: jest.fn((key) => { }) + generateRedisKey: jest.fn((key) => key), + deleteDraftClaimFromStore: jest.fn((key) => { }) })); jest.mock('../../../../../../../main/services/features/generalApplication/generalApplicationService', () => ({ - getCancelUrl: jest.fn(), + getCancelUrl: jest.fn(), })); describe('General Application - additional docs submitted controller', () => { - const citizenRoleToken: string = config.get('citizenRoleToken'); - const idamUrl: string = config.get('idamUrl'); - beforeAll(() => { - nock(idamUrl) - .post('/o/token') - .reply(200, { id_token: citizenRoleToken }); - (isGaForLipsEnabled as jest.Mock).mockResolvedValue(true); - }); - beforeEach(() => { - jest.clearAllMocks(); - }); - describe('GET submit controller', () => { - it('should render the submitted page with correct data', async () => { - const claimId = '123'; - const claim = new Claim(); - const redisKey = 'redis-key'; - const cancelUrl = '/cancel-url'; + const citizenRoleToken: string = config.get('citizenRoleToken'); + const idamUrl: string = config.get('idamUrl'); + beforeAll(() => { + nock(idamUrl) + .post('/o/token') + .reply(200, { id_token: citizenRoleToken }); + (isGaForLipsEnabled as jest.Mock).mockResolvedValue(true); + }); + beforeEach(() => { + jest.clearAllMocks(); + }); + describe('GET submit controller', () => { + it('should render the submitted page with correct data', async () => { + const claimId = '123'; + const claim = new Claim(); + const redisKey = 'redis-key'; + const cancelUrl = '/cancel-url'; - (getClaimById as jest.Mock).mockResolvedValue(claim); - (generateRedisKey as jest.Mock).mockReturnValue(redisKey); - (deleteDraftClaimFromStore as jest.Mock).mockResolvedValue(undefined); - (getCancelUrl as jest.Mock).mockResolvedValue(cancelUrl); + (getClaimById as jest.Mock).mockResolvedValue(claim); + (generateRedisKey as jest.Mock).mockReturnValue(redisKey); + (deleteDraftClaimFromStore as jest.Mock).mockResolvedValue(undefined); + (getCancelUrl as jest.Mock).mockResolvedValue(cancelUrl); - const res = await request(app).get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL.replace(':id', claimId)); + const res = await request(app).get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL.replace(':id', claimId)); - expect(res.status).toBe(200); - expect(getClaimById).toHaveBeenCalledWith(claimId, expect.anything(), true); - expect(generateRedisKey).toHaveBeenCalledWith(expect.anything()); - expect(deleteDraftClaimFromStore).toHaveBeenCalledWith(redisKey); - expect(getCancelUrl).toHaveBeenCalledWith(claimId, claim); - expect(res.text).toContain('You\'ve uploaded additional documents'); - }); + expect(res.status).toBe(200); + expect(getClaimById).toHaveBeenCalledWith(claimId, expect.anything(), true); + expect(generateRedisKey).toHaveBeenCalledWith(expect.anything()); + expect(deleteDraftClaimFromStore).toHaveBeenCalledWith(redisKey); + expect(getCancelUrl).toHaveBeenCalledWith(claimId, claim); + expect(res.text).toContain('You\'ve uploaded additional documents'); + }); - it('should handle errors', async () => { - (getClaimById as jest.Mock).mockRejectedValue(new Error('Error')); + it('should handle errors', async () => { + (getClaimById as jest.Mock).mockRejectedValue(new Error('Error')); - const res = await request(app).get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL.replace(':id', '123')); + const res = await request(app).get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL.replace(':id', '123')); - expect(res.status).toBe(500); - }); + expect(res.status).toBe(500); }); + }); }) \ No newline at end of file diff --git a/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.test.ts b/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.test.ts index 26a1b250d58..fb512b39bbb 100644 --- a/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.test.ts +++ b/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.test.ts @@ -3,16 +3,16 @@ import nock from 'nock'; import request from 'supertest'; import { app } from '../../../../../../../main/app'; import { - getClaimDetailsById, - getSummaryList, - removeSelectedDocument, - uploadSelectedFile, + getClaimDetailsById, + getSummaryList, + removeSelectedDocument, + uploadSelectedFile, } from 'services/features/generalApplication/additionalDocumentService'; import { generateRedisKey } from 'modules/draft-store/draftStoreService'; import { getCancelUrl } from 'services/features/generalApplication/generalApplicationService'; import { - GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, - GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL, + GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, + GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL, } from 'routes/urls'; import { Claim } from 'common/models/claim'; import { GeneralApplication } from 'common/models/generalApplication/GeneralApplication'; @@ -25,211 +25,211 @@ import { t } from 'i18next'; jest.mock('../../../../../../../main/modules/oidc'); jest.mock('../../../../../../../main/services/features/generalApplication/additionalDocumentService', () => ({ - getClaimDetailsById: jest.fn(), - getSummaryList: jest.fn(), - uploadSelectedFile: jest.fn(), - removeSelectedDocument: jest.fn(), + getClaimDetailsById: jest.fn(), + getSummaryList: jest.fn(), + uploadSelectedFile: jest.fn(), + removeSelectedDocument: jest.fn(), })); jest.mock('../../../../../../../main/app/auth/launchdarkly/launchDarklyClient'); jest.mock('../../../../../../../main/modules/draft-store/draftStoreService', () => ({ - generateRedisKey: jest.fn((key) => key), + generateRedisKey: jest.fn((key) => key), })); jest.mock('../../../../../../../main/services/features/generalApplication/generalApplicationService', () => ({ - getCancelUrl: jest.fn(), + getCancelUrl: jest.fn(), })); describe('uploadAdditionalDocumentsController', () => { - const citizenRoleToken: string = config.get('citizenRoleToken'); - const idamUrl: string = config.get('idamUrl'); - const claimId = '123'; - const gaId = '456'; - let claim: Claim; - beforeAll(() => { - nock(idamUrl) - .post('/o/token') - .reply(200, { id_token: citizenRoleToken }); - (isGaForLipsEnabled as jest.Mock).mockResolvedValue(true); + const citizenRoleToken: string = config.get('citizenRoleToken'); + const idamUrl: string = config.get('idamUrl'); + const claimId = '123'; + const gaId = '456'; + let claim: Claim; + beforeAll(() => { + nock(idamUrl) + .post('/o/token') + .reply(200, { id_token: citizenRoleToken }); + (isGaForLipsEnabled as jest.Mock).mockResolvedValue(true); + }); + + beforeEach(() => { + claim = new Claim(); + claim.generalApplication = new GeneralApplication(); + jest.clearAllMocks(); + }); + + describe('on Get request', () => { + it('should render the upload additional documents page with correct data', async () => { + const redisKey = 'redis-key'; + const cancelUrl = '/cancel-url'; + const formattedSummaryList = { + title: "", + summaryList: { + rows: [ + { + key: { + text: "Type of document", + }, + value: { + html: "test", + }, + }, + { + key: { + text: "n245form.pdf", + }, + value: { + html: "", + }, + actions: { + items: [ + { + href: "/case/1720536503257495/general-application/1720536653906339/upload-additional-documents?indexId=1", + text: "Remove document", + visuallyHiddenText: "n245form.pdf", + }, + ], + }, + }, + ], + }, + }; + (getClaimDetailsById as jest.Mock).mockResolvedValue(claim); + (generateRedisKey as jest.Mock).mockReturnValue(redisKey); + (getCancelUrl as jest.Mock).mockResolvedValue(cancelUrl); + (getSummaryList as jest.Mock).mockReturnValue(formattedSummaryList); + + const res = await request(app).get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)); + + expect(res.status).toBe(200); + expect(getClaimDetailsById).toHaveBeenCalledWith(expect.anything()); + expect(generateRedisKey).toHaveBeenCalledWith(expect.anything()); + expect(getCancelUrl).toHaveBeenCalledWith(claimId, claim); + expect(getSummaryList).toHaveBeenCalledWith(claim.generalApplication.uploadAdditionalDocuments, claimId, gaId); + expect(res.text).toContain('Type of document'); + expect(res.text).toContain('test') }); - beforeEach(() => { - claim = new Claim(); - claim.generalApplication = new GeneralApplication(); - jest.clearAllMocks(); + it('should remove the selected doc from the store', async () => { + + const additionalDocument = new UploadAdditionalDocument(); + additionalDocument.typeOfDocument = 'testt' + additionalDocument.caseDocument = { + documentLink: { document_binary_url: 'binary_url1', document_filename: 'testDoc', document_url: 'url' }, + documentName: 'testDoc', + documentType: null, + documentSize: 1000, + createdDatetime: new Date(), + } as CaseDocument; + additionalDocument.fileUpload = new FileUpload(); + claim.generalApplication.uploadAdditionalDocuments = [additionalDocument]; + const redisKey = 'redis-key'; + const cancelUrl = '/cancel-url'; + (getClaimDetailsById as jest.Mock).mockResolvedValue(claim); + (generateRedisKey as jest.Mock).mockReturnValue(redisKey); + (getCancelUrl as jest.Mock).mockResolvedValue(cancelUrl); + (getSummaryList as jest.Mock).mockReturnValue({}); + (removeSelectedDocument as jest.Mock).mockReturnValueOnce(void 0); + + const res = await request(app).get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)).query({ indexId: 1 }); + + expect(res.status).toBe(200); + expect(removeSelectedDocument).toHaveBeenCalledWith(redisKey, claim, 0) }); - describe('on Get request', () => { - it('should render the upload additional documents page with correct data', async () => { - const redisKey = 'redis-key'; - const cancelUrl = '/cancel-url'; - const formattedSummaryList = { - title: "", - summaryList: { - rows: [ - { - key: { - text: "Type of document", - }, - value: { - html: "test", - }, - }, - { - key: { - text: "n245form.pdf", - }, - value: { - html: "", - }, - actions: { - items: [ - { - href: "/case/1720536503257495/general-application/1720536653906339/upload-additional-documents?indexId=1", - text: "Remove document", - visuallyHiddenText: "n245form.pdf", - }, - ], - }, - }, - ], - }, - }; - (getClaimDetailsById as jest.Mock).mockResolvedValue(claim); - (generateRedisKey as jest.Mock).mockReturnValue(redisKey); - (getCancelUrl as jest.Mock).mockResolvedValue(cancelUrl); - (getSummaryList as jest.Mock).mockReturnValue(formattedSummaryList); - - const res = await request(app).get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)); - - expect(res.status).toBe(200); - expect(getClaimDetailsById).toHaveBeenCalledWith(expect.anything()); - expect(generateRedisKey).toHaveBeenCalledWith(expect.anything()); - expect(getCancelUrl).toHaveBeenCalledWith(claimId, claim); - expect(getSummaryList).toHaveBeenCalledWith(claim.generalApplication.uploadAdditionalDocuments, claimId, gaId); - expect(res.text).toContain('Type of document'); - expect(res.text).toContain('test') - }); - - it('should remove the selected doc from the store', async () => { - - const additionalDocument = new UploadAdditionalDocument(); - additionalDocument.typeOfDocument = 'testt' - additionalDocument.caseDocument = { - documentLink: { document_binary_url: 'binary_url1', document_filename: 'testDoc', document_url: 'url' }, - documentName: 'testDoc', - documentType: null, - documentSize: 1000, - createdDatetime: new Date(), - } as CaseDocument; - additionalDocument.fileUpload = new FileUpload(); - claim.generalApplication.uploadAdditionalDocuments = [additionalDocument]; - const redisKey = 'redis-key'; - const cancelUrl = '/cancel-url'; - (getClaimDetailsById as jest.Mock).mockResolvedValue(claim); - (generateRedisKey as jest.Mock).mockReturnValue(redisKey); - (getCancelUrl as jest.Mock).mockResolvedValue(cancelUrl); - (getSummaryList as jest.Mock).mockReturnValue({}); - (removeSelectedDocument as jest.Mock).mockReturnValueOnce(void 0); - - const res = await request(app).get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)).query({ indexId: 1 }); - - expect(res.status).toBe(200); - expect(removeSelectedDocument).toHaveBeenCalledWith(redisKey, claim, 0) - }); - - it('should return page with errors when upload file button clicked without choosing file', async () => { - const errors = [ - { - target: {}, - property: 'fileUpload', - constraints: { isNotEmpty: 'ERRORS.VALID_CHOOSE_THE_FILE' }, - fieldName: 'fileUpload', - text: 'Choose the file you want to upload', - href: '#fileUpload', - }, - ]; - const additionalDocument = new UploadAdditionalDocument(); - additionalDocument.typeOfDocument = 'testt' - additionalDocument.caseDocument = { - documentLink: { document_binary_url: 'binary_url1', document_filename: 'testDoc', document_url: 'url' }, - documentName: 'testDoc', - documentType: null, - documentSize: 1000, - createdDatetime: new Date(), - } as CaseDocument; - additionalDocument.fileUpload = new FileUpload(); - claim.generalApplication.uploadAdditionalDocuments = [additionalDocument]; - const redisKey = 'redis-key'; - const cancelUrl = '/cancel-url'; - (getClaimDetailsById as jest.Mock).mockResolvedValue(claim); - (generateRedisKey as jest.Mock).mockReturnValue(redisKey); - (getCancelUrl as jest.Mock).mockResolvedValue(cancelUrl); - (getSummaryList as jest.Mock).mockReturnValue({}); - (removeSelectedDocument as jest.Mock).mockReturnValueOnce(void 0); - app.request.session = { fileUpload: JSON.stringify(errors) } as unknown as Session; - await request(app) - .get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)) - .expect((res) => { - expect(res.status).toBe(200); - expect(res.text).toContain(t('ERRORS.VALID_CHOOSE_THE_FILE')); - }); + it('should return page with errors when upload file button clicked without choosing file', async () => { + const errors = [ + { + target: {}, + property: 'fileUpload', + constraints: { isNotEmpty: 'ERRORS.VALID_CHOOSE_THE_FILE' }, + fieldName: 'fileUpload', + text: 'Choose the file you want to upload', + href: '#fileUpload', + }, + ]; + const additionalDocument = new UploadAdditionalDocument(); + additionalDocument.typeOfDocument = 'testt' + additionalDocument.caseDocument = { + documentLink: { document_binary_url: 'binary_url1', document_filename: 'testDoc', document_url: 'url' }, + documentName: 'testDoc', + documentType: null, + documentSize: 1000, + createdDatetime: new Date(), + } as CaseDocument; + additionalDocument.fileUpload = new FileUpload(); + claim.generalApplication.uploadAdditionalDocuments = [additionalDocument]; + const redisKey = 'redis-key'; + const cancelUrl = '/cancel-url'; + (getClaimDetailsById as jest.Mock).mockResolvedValue(claim); + (generateRedisKey as jest.Mock).mockReturnValue(redisKey); + (getCancelUrl as jest.Mock).mockResolvedValue(cancelUrl); + (getSummaryList as jest.Mock).mockReturnValue({}); + (removeSelectedDocument as jest.Mock).mockReturnValueOnce(void 0); + app.request.session = { fileUpload: JSON.stringify(errors) } as unknown as Session; + await request(app) + .get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)) + .expect((res) => { + expect(res.status).toBe(200); + expect(res.text).toContain(t('ERRORS.VALID_CHOOSE_THE_FILE')); }); + }); - it('should handle errors', async () => { - (getClaimDetailsById as jest.Mock).mockRejectedValue(new Error('Error')); + it('should handle errors', async () => { + (getClaimDetailsById as jest.Mock).mockRejectedValue(new Error('Error')); - const res = await request(app).get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', '123').replace(':gaId', '456')); + const res = await request(app).get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', '123').replace(':gaId', '456')); - expect(res.status).toBe(500); - }); + expect(res.status).toBe(500); }); + }); - describe('on post request', () => { - it('should handle file upload and redirect to the same page', async () => { - (getClaimDetailsById as jest.Mock).mockResolvedValue(claim); - (uploadSelectedFile as jest.Mock).mockResolvedValueOnce(void 0); + describe('on post request', () => { + it('should handle file upload and redirect to the same page', async () => { + (getClaimDetailsById as jest.Mock).mockResolvedValue(claim); + (uploadSelectedFile as jest.Mock).mockResolvedValueOnce(void 0); - const res = await request(app) - .post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)) - .field('action', 'uploadButton') - .attach('selectedFile', Buffer.from('file content'), 'test-file.txt'); + const res = await request(app) + .post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)) + .field('action', 'uploadButton') + .attach('selectedFile', Buffer.from('file content'), 'test-file.txt'); - expect(res.status).toBe(302); - expect(res.header['location']).toBe(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)); - expect(uploadSelectedFile).toHaveBeenCalledWith(expect.anything(), claim); - }); + expect(res.status).toBe(302); + expect(res.header['location']).toBe(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)); + expect(uploadSelectedFile).toHaveBeenCalledWith(expect.anything(), claim); + }); - it('should redirect to CYA page if documents are uploaded', async () => { - const additionalDocument = new UploadAdditionalDocument(); - additionalDocument.typeOfDocument = 'testt' - additionalDocument.caseDocument = { - documentLink: { document_binary_url: 'binary_url1', document_filename: 'testDoc', document_url: 'url' }, - documentName: 'testDoc', - documentType: null, - documentSize: 1000, - createdDatetime: new Date(), - } as CaseDocument; - additionalDocument.fileUpload = new FileUpload(); - claim.generalApplication.uploadAdditionalDocuments = [additionalDocument]; - - (getClaimDetailsById as jest.Mock).mockResolvedValue(claim); - - const res = await request(app) - .post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)); - - expect(res.status).toBe(302); - expect(res.header['location']).toBe(GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL.replace(':id', claimId).replace(':gaId', gaId)); - }); + it('should redirect to CYA page if documents are uploaded', async () => { + const additionalDocument = new UploadAdditionalDocument(); + additionalDocument.typeOfDocument = 'testt' + additionalDocument.caseDocument = { + documentLink: { document_binary_url: 'binary_url1', document_filename: 'testDoc', document_url: 'url' }, + documentName: 'testDoc', + documentType: null, + documentSize: 1000, + createdDatetime: new Date(), + } as CaseDocument; + additionalDocument.fileUpload = new FileUpload(); + claim.generalApplication.uploadAdditionalDocuments = [additionalDocument]; + + (getClaimDetailsById as jest.Mock).mockResolvedValue(claim); + + const res = await request(app) + .post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)); + + expect(res.status).toBe(302); + expect(res.header['location']).toBe(GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL.replace(':id', claimId).replace(':gaId', gaId)); + }); - it('should handle errors', async () => { - (getClaimDetailsById as jest.Mock).mockRejectedValue(new Error('Error')); + it('should handle errors', async () => { + (getClaimDetailsById as jest.Mock).mockRejectedValue(new Error('Error')); - const res = await request(app) - .post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', '123').replace(':gaId', '456')) - .field('action', 'submit'); + const res = await request(app) + .post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', '123').replace(':gaId', '456')) + .field('action', 'submit'); - expect(res.status).toBe(500); - }); + expect(res.status).toBe(500); }); + }); }); From 385ae3b1d8900539d9eeafef52dad0120fd3aab7 Mon Sep 17 00:00:00 2001 From: jeswanth Date: Mon, 15 Jul 2024 10:31:39 +0100 Subject: [PATCH 06/17] CIV-14228 fixed lint issues --- .../additionalDocumentService.test.ts | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/test/unit/services/features/generalApplication/additionalDocumentService.test.ts b/src/test/unit/services/features/generalApplication/additionalDocumentService.test.ts index 5f075ad465b..2fe66d037f2 100644 --- a/src/test/unit/services/features/generalApplication/additionalDocumentService.test.ts +++ b/src/test/unit/services/features/generalApplication/additionalDocumentService.test.ts @@ -51,12 +51,10 @@ describe('Additional Documents Service', () => { createdBy: 'User1', documentLink: { document_url: 'url', document_filename: 'filename', document_binary_url: 'binaryUrl' }, documentType: null, - documentSize: 123 + documentSize: 123, } as CaseDocument; (TypeOfDocumentSectionMapper.mapToSingleFile as jest.Mock).mockReturnValue(fileUpload); - - - const mockValue = jest.spyOn(CivilServiceClient.prototype, 'uploadDocument').mockResolvedValue(uploadedDocument as any as CaseDocument); + const mockValue = jest.spyOn(CivilServiceClient.prototype, 'uploadDocument').mockResolvedValue(uploadedDocument as unknown as CaseDocument); await uploadSelectedFile(req, claim as Claim); @@ -89,9 +87,9 @@ describe('Additional Documents Service', () => { createdBy: 'User1', documentLink: { document_url: 'ur1', document_filename: 'filename1', document_binary_url: 'binaryUrl1' }, documentType: null, - documentSize: 123 + documentSize: 123, } as CaseDocument, - fileUpload: {} as FileUpload + fileUpload: {} as FileUpload, }, { typeOfDocument: 'Type2', @@ -100,10 +98,10 @@ describe('Additional Documents Service', () => { createdBy: 'User2', documentLink: { document_url: 'ur2', document_filename: 'filename2', document_binary_url: 'binaryUrl2' }, documentType: null, - documentSize: 123 + documentSize: 123, } as CaseDocument, fileUpload: {} as FileUpload - } + }, ]; const claimId = '1'; const gaId = '2'; @@ -126,7 +124,7 @@ describe('Additional Documents Service', () => { const result = await getClaimDetailsById(req); - expect(result.generalApplication.uploadAdditionalDocuments).toEqual([]) + expect(result.generalApplication.uploadAdditionalDocuments).toEqual([]); expect(getClaimById).toHaveBeenCalledWith(req.params.id, req, true); }); }); @@ -146,7 +144,7 @@ describe('Additional Documents Service', () => { documentType: null, documentSize: 123 } as CaseDocument, - fileUpload: {} as FileUpload + fileUpload: {} as FileUpload, }, { typeOfDocument: 'Type2', @@ -156,12 +154,12 @@ describe('Additional Documents Service', () => { documentLink: { document_url: 'url2', document_binary_url: 'binaryUrl2', - document_filename: 'filename2' + document_filename: 'filename2', }, documentType: null, documentSize: 456 } as CaseDocument, - fileUpload: {} as FileUpload + fileUpload: {} as FileUpload, } ]; @@ -192,7 +190,7 @@ describe('Additional Documents Service', () => { documentSize: 123 } as CaseDocument, fileUpload: {} as FileUpload - } + }, ] } as GeneralApplication } as Claim; @@ -222,7 +220,7 @@ describe('Additional Documents Service', () => { it('should return built content for panel', () => { const lng = 'en'; const result = getContentForPanel(lng); - expect(result).toEqual([{ "data": { "title": "PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.UPLOADED_ADDITIONAL_DOCS" }, "type": "panel" }]); + expect(result).toEqual([{ 'data': { 'title': 'PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.UPLOADED_ADDITIONAL_DOCS' }, 'type': 'panel' }]); }); }); @@ -231,7 +229,7 @@ describe('Additional Documents Service', () => { const lng = 'en'; const result = getContentForBody(lng); - expect(result).toEqual([{ "data": { "classes": undefined, "text": "PAGES.GENERAL_APPLICATION.GA_PAYMENT_SUCCESSFUL.WHAT_HAPPENS_NEXT", "variables": { "lng": "en" } }, "type": "title" }, { "data": { "classes": undefined, "text": "PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.JUDGE_WILL_REVIEW", "variables": { "lng": "en" } }, "type": "p" }]); + expect(result).toEqual([{ 'data': { 'classes': undefined, 'text': 'PAGES.GENERAL_APPLICATION.GA_PAYMENT_SUCCESSFUL.WHAT_HAPPENS_NEXT', 'variables': { 'lng': 'en' } }, 'type': 'title' }, { 'data': { 'classes': undefined, 'text': 'PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.JUDGE_WILL_REVIEW', 'variables': { 'lng': 'en' } }, 'type': 'p' }]); }); }); @@ -239,7 +237,7 @@ describe('Additional Documents Service', () => { it('should return built content for close button', () => { const redirectUrl = '/redirect-url'; const result = getContentForCloseButton(redirectUrl); - expect(result).toEqual([{ "data": { "href": "/redirect-url", "text": "COMMON.BUTTONS.CLOSE_AND_RETURN_TO_DASHBOARD" }, "type": "button" }]); + expect(result).toEqual([{ 'data': { 'href': '/redirect-url', 'text': 'COMMON.BUTTONS.CLOSE_AND_RETURN_TO_DASHBOARD' }, 'type': 'button' }]); }); }); }); From 268463b70d0dd2ed2ebc802834cf38971ab71350 Mon Sep 17 00:00:00 2001 From: jeswanth Date: Mon, 15 Jul 2024 10:43:48 +0100 Subject: [PATCH 07/17] fixed lint issues --- .../checkAnswersController.ts | 11 +++--- .../submittedController.ts | 10 ++--- .../uploadAdditionalDocumentsController.ts | 14 +++---- src/main/routes/urls.ts | 2 +- .../additionalDocumentService.ts | 37 +++++++++---------- ...ploadAdditionalDocumentsController.test.ts | 27 +++++++------- 6 files changed, 49 insertions(+), 52 deletions(-) diff --git a/src/main/routes/features/generalApplication/additionalDocuments/checkAnswersController.ts b/src/main/routes/features/generalApplication/additionalDocuments/checkAnswersController.ts index a9912d52546..0fe78a5c070 100644 --- a/src/main/routes/features/generalApplication/additionalDocuments/checkAnswersController.ts +++ b/src/main/routes/features/generalApplication/additionalDocuments/checkAnswersController.ts @@ -15,17 +15,17 @@ const gaServiceClient: GaServiceClient = new GaServiceClient(generalAppApiBaseUr gaAdditionalDocCheckAnswerController.get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, (async (req: AppRequest, res: Response, next: NextFunction) => { try { - const { gaId, id: claimId } = req.params + const { gaId, id: claimId } = req.params; const claimIdPrettified = caseNumberPrettify(claimId); const claim = await getClaimDetailsById(req); const cancelUrl = await getCancelUrl(claimId, claim); - const backLinkUrl = GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId) - const summaryRows = buildSummarySectionForAdditionalDoc(claim.generalApplication.uploadAdditionalDocuments, claimId, gaId) + const backLinkUrl = GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId); + const summaryRows = buildSummarySectionForAdditionalDoc(claim.generalApplication.uploadAdditionalDocuments, claimId, gaId); res.render(viewPath, { backLinkUrl, cancelUrl, claimIdPrettified, claim, summaryRows }); } catch (error) { next(error); } -}) as RequestHandler) +}) as RequestHandler); gaAdditionalDocCheckAnswerController.post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, (async (req: AppRequest, res: Response, next: NextFunction) => { try { @@ -33,7 +33,7 @@ gaAdditionalDocCheckAnswerController.post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL const claim = await getClaimDetailsById(req); const uploadedDocuments = prepareCCDData(claim.generalApplication.uploadAdditionalDocuments); const generalApplication = { - uploadDocument: uploadedDocuments + uploadDocument: uploadedDocuments, }; await gaServiceClient.submitEvent(ApplicationEvent.UPLOAD_ADDL_DOCUMENTS, gaId, generalApplication as unknown, req); res.redirect(GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL.replace(':id', claimId).replace(':gaId', gaId)); @@ -42,5 +42,4 @@ gaAdditionalDocCheckAnswerController.post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL } }) as RequestHandler); - export default gaAdditionalDocCheckAnswerController; \ No newline at end of file diff --git a/src/main/routes/features/generalApplication/additionalDocuments/submittedController.ts b/src/main/routes/features/generalApplication/additionalDocuments/submittedController.ts index 65a879f893f..9dade5058e4 100644 --- a/src/main/routes/features/generalApplication/additionalDocuments/submittedController.ts +++ b/src/main/routes/features/generalApplication/additionalDocuments/submittedController.ts @@ -7,23 +7,23 @@ import { getContentForBody, getContentForCloseButton, getContentForPanel } from import { getCancelUrl } from 'services/features/generalApplication/generalApplicationService'; const additionalDocSubmittedController = Router(); -const viewPath = 'features/generalApplication/additionalDocuments/submitted' +const viewPath = 'features/generalApplication/additionalDocuments/submitted'; additionalDocSubmittedController.get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL, (async (req: AppRequest, res: Response, next: NextFunction) => { try { const lng = req.query.lang ? req.query.lang : req.cookies.lang; - const { id } = req.params - const claim = await getClaimById(id, req, true); + const { id: claimId } = req.params; + const claim = await getClaimById(claimId, req, true); const redisKey = generateRedisKey(req); await deleteDraftClaimFromStore(redisKey); res.render(viewPath, { gaPaymentSuccessfulPanel: getContentForPanel(lng), gaPaymentSuccessfulBody: getContentForBody(lng), - gaPaymentSuccessfulButton: getContentForCloseButton(await getCancelUrl(id, claim)), + gaPaymentSuccessfulButton: getContentForCloseButton(await getCancelUrl(claimId, claim)), }) } catch (err) { next(err); } -}) as RequestHandler) +}) as RequestHandler); export default additionalDocSubmittedController; \ No newline at end of file diff --git a/src/main/routes/features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.ts b/src/main/routes/features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.ts index f5fc11d67a4..5f7edf948ea 100644 --- a/src/main/routes/features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.ts +++ b/src/main/routes/features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.ts @@ -44,12 +44,12 @@ uploadAdditionalDocumentsController.get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL, (asy } catch (err) { next(err); } -}) as RequestHandler) +}) as RequestHandler); uploadAdditionalDocumentsController.post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL, upload.single('selectedFile'), (async (req: AppRequest, res: Response, next: NextFunction) => { try { - const { gaId, id } = req.params - const currentUrl = GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', id).replace(':gaId', gaId) + const { gaId, id } = req.params; + const currentUrl = GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', id).replace(':gaId', gaId); const claim = await getClaimDetailsById(req); const gaDetails = claim.generalApplication; if (req.body.action === 'uploadButton') { @@ -66,16 +66,16 @@ uploadAdditionalDocumentsController.post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL, upl property: '', constraints: { - isNotEmpty: 'ERRORS.GENERAL_APPLICATION.UPLOAD_ONE_FILE' + isNotEmpty: 'ERRORS.GENERAL_APPLICATION.UPLOAD_ONE_FILE', }, - }] + }]; req.session.fileUpload = JSON.stringify(errors); return res.redirect(`${currentUrl}`); } res.redirect(constructResponseUrlWithIdParams(id, GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL).replace(':gaId', gaId)); } catch (err) { - next(err) + next(err); } -})) +})); export default uploadAdditionalDocumentsController; \ No newline at end of file diff --git a/src/main/routes/urls.ts b/src/main/routes/urls.ts index 1d5c6a21af7..637264f040f 100644 --- a/src/main/routes/urls.ts +++ b/src/main/routes/urls.ts @@ -359,7 +359,7 @@ export const FRC_BAND_AGREED_URL = `${DIRECTIONS_QUESTIONNAIRE_URL}/frc-band-agr export const ASSIGN_FRC_BAND_URL = `${DIRECTIONS_QUESTIONNAIRE_URL}/assign-complexity-band`; export const REASON_FOR_FRC_BAND_URL = `${DIRECTIONS_QUESTIONNAIRE_URL}/reason-for-complexity-band`; export const WHY_NOT_SUBJECT_TO_FRC_URL = `${DIRECTIONS_QUESTIONNAIRE_URL}/why-not-subject-to-frc`; -export const GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL = `${BASE_GENERAL_APPLICATION_URL}/:gaId/upload-additional-documents` +export const GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL = `${BASE_GENERAL_APPLICATION_URL}/:gaId/upload-additional-documents`; export const GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL = `${BASE_GENERAL_APPLICATION_URL}/:gaId/upload-additional-documents/check-and-send`; export const GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL = `${BASE_GENERAL_APPLICATION_URL}/:gaId/upload-additional-documents/submitted`; diff --git a/src/main/services/features/generalApplication/additionalDocumentService.ts b/src/main/services/features/generalApplication/additionalDocumentService.ts index 5843a3ee5a2..1ab895108ca 100644 --- a/src/main/services/features/generalApplication/additionalDocumentService.ts +++ b/src/main/services/features/generalApplication/additionalDocumentService.ts @@ -35,7 +35,7 @@ export const getSummaryList = (additionalDocumentsList: UploadAdditionalDocument formattedSummary.summaryList.rows.push(summaryRow('Type of document', uploadDocument.typeOfDocument)); formattedSummary.summaryList.rows.push(summaryRow(uploadDocument.caseDocument.documentName, '', `${GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)}?indexId=${index}`, 'Remove document')); }); - return formattedSummary + return formattedSummary; }; export const removeSelectedDocument = async (redisKey: string, claim: Claim, index: number): Promise => { @@ -54,8 +54,8 @@ export const uploadSelectedFile = async (req: AppRequest, claim: Claim) => { uploadedDocument.fileUpload = fileUpload; uploadedDocument.typeOfDocument = req.body.typeOfDocument; const form = new GenericForm(uploadedDocument); - const uploadAdditionalDocuments = claim.generalApplication.uploadAdditionalDocuments - form.validateSync() + const uploadAdditionalDocuments = claim.generalApplication.uploadAdditionalDocuments; + form.validateSync(); if (!form.hasErrors()) { uploadedDocument.caseDocument = await civilServiceClientForDocRetrieve.uploadDocument(req, fileUpload); uploadAdditionalDocuments.push(uploadedDocument); @@ -64,19 +64,19 @@ export const uploadSelectedFile = async (req: AppRequest, claim: Claim) => { const errors = translateErrors(form.getAllErrors(), t); req.session.fileUpload = JSON.stringify(errors); } -} +}; export const getClaimDetailsById = async (req: AppRequest): Promise => { try { - const claim = await getClaimById(req.params.id, req, true) - const gaApplication = Object.assign(new GeneralApplication(), claim.generalApplication) + const claim = await getClaimById(req.params.id, req, true); + const gaApplication = Object.assign(new GeneralApplication(), claim.generalApplication); claim.generalApplication = gaApplication; - return claim + return claim; } catch (error) { logger.error(error); throw error; } -} +}; export const prepareCCDData = (uploadAdditionalDocuments: UploadAdditionalDocument[]) => { return uploadAdditionalDocuments.map(doc => { @@ -88,37 +88,36 @@ export const prepareCCDData = (uploadAdditionalDocuments: UploadAdditionalDocume document_url: doc.caseDocument.documentLink.document_url, document_binary_url: doc.caseDocument.documentLink.document_binary_url, document_filename: doc.caseDocument.documentName, - } - - } + }, + }, } - }) -} + }); +}; export const buildSummarySectionForAdditionalDoc = (additionalDocumentsList: UploadAdditionalDocument[], claimId: string, gaId: string) => { const rows: SummaryRow[] = [] additionalDocumentsList.forEach(doc => { rows.push(summaryRow('Type of document', doc.typeOfDocument)); rows.push(summaryRow('Uploaded document', doc.caseDocument.documentName, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId), changeLabel('en'))) - }) + }); return rows; -} +}; export const getContentForPanel = (lng: string) => { const panelBuilder = new PaymentSuccessfulSectionBuilder(); panelBuilder.addPanelForConfirmation('PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.UPLOADED_ADDITIONAL_DOCS', getLng(lng)); return panelBuilder.build(); -} +}; export const getContentForBody = (lng: string) => { - let contentBuilder = new PaymentSuccessfulSectionBuilder(); + const contentBuilder = new PaymentSuccessfulSectionBuilder(); return contentBuilder.addTitle('PAGES.GENERAL_APPLICATION.GA_PAYMENT_SUCCESSFUL.WHAT_HAPPENS_NEXT', { lng: getLng(lng) }) .addParagraph('PAGES.GENERAL_APPLICATION.ADDITIONAL_DOCUMENTS.JUDGE_WILL_REVIEW', { lng: getLng(lng) }) .build(); -} +}; export const getContentForCloseButton = (redirectUrl: string) => { return new PaymentSuccessfulSectionBuilder() .addButton('COMMON.BUTTONS.CLOSE_AND_RETURN_TO_DASHBOARD', redirectUrl) .build(); -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.test.ts b/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.test.ts index fb512b39bbb..c7b36ca2fd6 100644 --- a/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.test.ts +++ b/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.test.ts @@ -39,7 +39,6 @@ jest.mock('../../../../../../../main/services/features/generalApplication/genera getCancelUrl: jest.fn(), })); - describe('uploadAdditionalDocumentsController', () => { const citizenRoleToken: string = config.get('citizenRoleToken'); const idamUrl: string = config.get('idamUrl'); @@ -64,30 +63,30 @@ describe('uploadAdditionalDocumentsController', () => { const redisKey = 'redis-key'; const cancelUrl = '/cancel-url'; const formattedSummaryList = { - title: "", + title: '', summaryList: { rows: [ { key: { - text: "Type of document", + text: 'Type of document', }, value: { - html: "test", + html: 'test', }, }, { key: { - text: "n245form.pdf", + text: 'n245form.pdf', }, value: { - html: "", + html: '', }, actions: { items: [ { - href: "/case/1720536503257495/general-application/1720536653906339/upload-additional-documents?indexId=1", - text: "Remove document", - visuallyHiddenText: "n245form.pdf", + href: '/case/1720536503257495/general-application/1720536653906339/upload-additional-documents?indexId=1', + text: 'Remove document', + visuallyHiddenText: 'n245form.pdf', }, ], }, @@ -108,13 +107,13 @@ describe('uploadAdditionalDocumentsController', () => { expect(getCancelUrl).toHaveBeenCalledWith(claimId, claim); expect(getSummaryList).toHaveBeenCalledWith(claim.generalApplication.uploadAdditionalDocuments, claimId, gaId); expect(res.text).toContain('Type of document'); - expect(res.text).toContain('test') + expect(res.text).toContain('test'); }); it('should remove the selected doc from the store', async () => { const additionalDocument = new UploadAdditionalDocument(); - additionalDocument.typeOfDocument = 'testt' + additionalDocument.typeOfDocument = 'testt'; additionalDocument.caseDocument = { documentLink: { document_binary_url: 'binary_url1', document_filename: 'testDoc', document_url: 'url' }, documentName: 'testDoc', @@ -135,7 +134,7 @@ describe('uploadAdditionalDocumentsController', () => { const res = await request(app).get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)).query({ indexId: 1 }); expect(res.status).toBe(200); - expect(removeSelectedDocument).toHaveBeenCalledWith(redisKey, claim, 0) + expect(removeSelectedDocument).toHaveBeenCalledWith(redisKey, claim, 0); }); it('should return page with errors when upload file button clicked without choosing file', async () => { @@ -150,7 +149,7 @@ describe('uploadAdditionalDocumentsController', () => { }, ]; const additionalDocument = new UploadAdditionalDocument(); - additionalDocument.typeOfDocument = 'testt' + additionalDocument.typeOfDocument = 'testt'; additionalDocument.caseDocument = { documentLink: { document_binary_url: 'binary_url1', document_filename: 'testDoc', document_url: 'url' }, documentName: 'testDoc', @@ -202,7 +201,7 @@ describe('uploadAdditionalDocumentsController', () => { it('should redirect to CYA page if documents are uploaded', async () => { const additionalDocument = new UploadAdditionalDocument(); - additionalDocument.typeOfDocument = 'testt' + additionalDocument.typeOfDocument = 'testt'; additionalDocument.caseDocument = { documentLink: { document_binary_url: 'binary_url1', document_filename: 'testDoc', document_url: 'url' }, documentName: 'testDoc', From 4dd07eae4d58b9596c2f98aa11ab81ba97bf836d Mon Sep 17 00:00:00 2001 From: jeswanth Date: Mon, 15 Jul 2024 10:51:57 +0100 Subject: [PATCH 08/17] fixed lint issues --- .../additionalDocumentService.ts | 6 +++--- .../checkAnswersController.test.ts | 2 +- .../submittedController.test.ts | 4 ++-- .../additionalDocumentService.test.ts | 20 +++++++++---------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/main/services/features/generalApplication/additionalDocumentService.ts b/src/main/services/features/generalApplication/additionalDocumentService.ts index 1ab895108ca..9c43c096caf 100644 --- a/src/main/services/features/generalApplication/additionalDocumentService.ts +++ b/src/main/services/features/generalApplication/additionalDocumentService.ts @@ -90,15 +90,15 @@ export const prepareCCDData = (uploadAdditionalDocuments: UploadAdditionalDocume document_filename: doc.caseDocument.documentName, }, }, - } + }; }); }; export const buildSummarySectionForAdditionalDoc = (additionalDocumentsList: UploadAdditionalDocument[], claimId: string, gaId: string) => { - const rows: SummaryRow[] = [] + const rows: SummaryRow[] = []; additionalDocumentsList.forEach(doc => { rows.push(summaryRow('Type of document', doc.typeOfDocument)); - rows.push(summaryRow('Uploaded document', doc.caseDocument.documentName, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId), changeLabel('en'))) + rows.push(summaryRow('Uploaded document', doc.caseDocument.documentName, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId), changeLabel('en'))); }); return rows; }; diff --git a/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/checkAnswersController.test.ts b/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/checkAnswersController.test.ts index 7902c673fbe..5c97034c8af 100644 --- a/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/checkAnswersController.test.ts +++ b/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/checkAnswersController.test.ts @@ -91,4 +91,4 @@ describe('General Application - additional docs check answer controller ', () => expect(res.status).toBe(500); }); }); -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/submittedController.test.ts b/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/submittedController.test.ts index 88d837a97e9..b48092c90e8 100644 --- a/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/submittedController.test.ts +++ b/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/submittedController.test.ts @@ -14,7 +14,7 @@ jest.mock('../../../..../../../../../../main/modules/utilityService'); jest.mock('../../../../../../../main/app/auth/launchdarkly/launchDarklyClient'); jest.mock('../../../../../../../main/modules/draft-store/draftStoreService', () => ({ generateRedisKey: jest.fn((key) => key), - deleteDraftClaimFromStore: jest.fn((key) => { }) + deleteDraftClaimFromStore: jest.fn((key) => { key }), })); jest.mock('../../../../../../../main/services/features/generalApplication/generalApplicationService', () => ({ getCancelUrl: jest.fn(), @@ -62,4 +62,4 @@ describe('General Application - additional docs submitted controller', () => { expect(res.status).toBe(500); }); }); -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/test/unit/services/features/generalApplication/additionalDocumentService.test.ts b/src/test/unit/services/features/generalApplication/additionalDocumentService.test.ts index 2fe66d037f2..6fd98fffca1 100644 --- a/src/test/unit/services/features/generalApplication/additionalDocumentService.test.ts +++ b/src/test/unit/services/features/generalApplication/additionalDocumentService.test.ts @@ -100,7 +100,7 @@ describe('Additional Documents Service', () => { documentType: null, documentSize: 123, } as CaseDocument, - fileUpload: {} as FileUpload + fileUpload: {} as FileUpload, }, ]; const claimId = '1'; @@ -117,7 +117,7 @@ describe('Additional Documents Service', () => { describe('getClaimDetailsById', () => { it('should retrieve and return claim details', async () => { const req: AppRequest = { - params: { id: '1' } + params: { id: '1' }, } as unknown as AppRequest; claim.generalApplication = undefined; (getClaimById as jest.Mock).mockResolvedValue(claim); @@ -139,10 +139,10 @@ describe('Additional Documents Service', () => { documentLink: { document_url: 'url1', document_binary_url: 'binaryUrl1', - document_filename: 'filename1' + document_filename: 'filename1', }, documentType: null, - documentSize: 123 + documentSize: 123, } as CaseDocument, fileUpload: {} as FileUpload, }, @@ -157,10 +157,10 @@ describe('Additional Documents Service', () => { document_filename: 'filename2', }, documentType: null, - documentSize: 456 + documentSize: 456, } as CaseDocument, fileUpload: {} as FileUpload, - } + }, ]; const result = prepareCCDData(uploadAdditionalDocuments); @@ -187,12 +187,12 @@ describe('Additional Documents Service', () => { createdBy: 'User2', documentLink: { document_url: 'ur2', document_filename: 'filename2', document_binary_url: 'binaryUrl2' }, documentType: null, - documentSize: 123 + documentSize: 123, } as CaseDocument, - fileUpload: {} as FileUpload + fileUpload: {} as FileUpload, }, - ] - } as GeneralApplication + ], + } as GeneralApplication, } as Claim; const index = 0; From df00cefb2916eff9959c7f25199febd04974996e Mon Sep 17 00:00:00 2001 From: jeswanth Date: Mon, 15 Jul 2024 11:00:17 +0100 Subject: [PATCH 09/17] fixed data issues --- src/main/modules/i18n/locales/cy.json | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/modules/i18n/locales/cy.json b/src/main/modules/i18n/locales/cy.json index 831c5f9c61a..d9c01ee6640 100644 --- a/src/main/modules/i18n/locales/cy.json +++ b/src/main/modules/i18n/locales/cy.json @@ -2370,7 +2370,14 @@ "WHY_NOT_ACCEPT_2": "Why you do not accept the defendant's offer?" }, "ADDITIONAL_DOCUMENTS": { - "ADDITIONAL_DOCUMENTS_CAPTION": "Upload additional documents" + "ADDITIONAL_DOCUMENTS_CAPTION": "Upload additional documents", + "UPLOAD_DOCUMENTS_TITLE": "Upload documents", + "ADDITIONAL_DOCUMENTS_ROW1": "You should only upload documents that are relevant to your application, for example if the judge has ordered a hearing and instructed you to provide documents ahead of this.", + "ADDITIONAL_DOCUMENTS_ROW2": "Before you upload the document you will need to describe the type of document you are uploading, for example, Bundle, witness statement or costs schedule.", + "TYPE_OF_DOCUMENT": "Type of document", + "TYPE_OF_DOCUMENT_HINT": "For example, contract, invoice receipt, email, text message, photo, social media message", + "UPLOADED_ADDITIONAL_DOCS": "You've uploaded additional documents", + "JUDGE_WILL_REVIEW": "A judge will review the additional documents that you’ve uploaded. You’ll receive an update with their decision or next steps." }, "AGREE_TO_ORDER": { "MADE_AWARE": "If you have not been made aware of this application by the other parties, select 'No'.", @@ -4669,7 +4676,9 @@ "NEED_TO_TELL": "You need to tell us if you agree that the court should make the order requested by the other party. Choose option Yes or No", "EXPLAIN_WHY_DISAGREE_APPLICATION": "You need to explain why you disagree with the application" }, + "TYPE_OF_DOC": "You need to tell us what type of document you are uploading.", "UPLOAD_FILE_MESSAGE": "You need to choose a file before clicking 'Upload file'", + "UPLOAD_ONE_FILE": "You need to upload at least one file.", "WANT_TO_ADD_ANOTHER_APPLICATION": "You need to tell us if you want to add another application. Choose option: Yes or No", "WANT_TO_UPLOAD_DOCUMENTS_YES_NO_SELECTION": "You need to tell us if you want to upload documents to support your application. Choose option: Yes or No", "WHY_PREFER_THIS_HEARING_TYPE": "You need to tell us why you would prefer this type of hearing" From 9b643910e9a915c3b7afd633817f67bcfb8e71fb Mon Sep 17 00:00:00 2001 From: jeswanth Date: Mon, 15 Jul 2024 11:08:56 +0100 Subject: [PATCH 10/17] fixed lint issues --- .../UploadAdditionalDocument.ts | 16 ++++++++-------- .../additionalDocuments/submittedController.ts | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/common/models/generalApplication/UploadAdditionalDocument.ts b/src/main/common/models/generalApplication/UploadAdditionalDocument.ts index 2d95b7c923b..2529f9a1780 100644 --- a/src/main/common/models/generalApplication/UploadAdditionalDocument.ts +++ b/src/main/common/models/generalApplication/UploadAdditionalDocument.ts @@ -3,17 +3,17 @@ import { FileUpload } from '../caseProgression/uploadDocumentsUserForm'; import { CaseDocument } from '../document/caseDocument'; export class UploadAdditionalDocument { - @ValidateNested() - @ValidateIf((object) => object.caseDocument === undefined || object.caseDocument === null || object.caseDocument === '') - @IsNotEmpty({ message: 'ERRORS.GENERAL_APPLICATION.UPLOAD_FILE_MESSAGE' }) + @ValidateNested() + @ValidateIf((object) => object.caseDocument === undefined || object.caseDocument === null || object.caseDocument === '') + @IsNotEmpty({ message: 'ERRORS.GENERAL_APPLICATION.UPLOAD_FILE_MESSAGE' }) fileUpload: FileUpload; - caseDocument: CaseDocument; + caseDocument: CaseDocument; - @IsNotEmpty({ message: 'ERRORS.GENERAL_APPLICATION.TYPE_OF_DOC' }) + @IsNotEmpty({ message: 'ERRORS.GENERAL_APPLICATION.TYPE_OF_DOC' }) typeOfDocument: string; - constructor(fileUpload?: FileUpload) { - this.fileUpload = fileUpload; - } + constructor(fileUpload?: FileUpload) { + this.fileUpload = fileUpload; + } } \ No newline at end of file diff --git a/src/main/routes/features/generalApplication/additionalDocuments/submittedController.ts b/src/main/routes/features/generalApplication/additionalDocuments/submittedController.ts index 9dade5058e4..cde5de69d24 100644 --- a/src/main/routes/features/generalApplication/additionalDocuments/submittedController.ts +++ b/src/main/routes/features/generalApplication/additionalDocuments/submittedController.ts @@ -20,7 +20,7 @@ additionalDocSubmittedController.get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_UR gaPaymentSuccessfulPanel: getContentForPanel(lng), gaPaymentSuccessfulBody: getContentForBody(lng), gaPaymentSuccessfulButton: getContentForCloseButton(await getCancelUrl(claimId, claim)), - }) + }); } catch (err) { next(err); } From 2e37bddc25c84a2991e764e45007d78dbd47ec53 Mon Sep 17 00:00:00 2001 From: jeswanth Date: Mon, 15 Jul 2024 11:13:31 +0100 Subject: [PATCH 11/17] fixed lint issues --- .../additionalDocuments/submittedController.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/submittedController.test.ts b/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/submittedController.test.ts index b48092c90e8..b682e104f50 100644 --- a/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/submittedController.test.ts +++ b/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/submittedController.test.ts @@ -14,7 +14,7 @@ jest.mock('../../../..../../../../../../main/modules/utilityService'); jest.mock('../../../../../../../main/app/auth/launchdarkly/launchDarklyClient'); jest.mock('../../../../../../../main/modules/draft-store/draftStoreService', () => ({ generateRedisKey: jest.fn((key) => key), - deleteDraftClaimFromStore: jest.fn((key) => { key }), + deleteDraftClaimFromStore: jest.fn((key) => { key; }), })); jest.mock('../../../../../../../main/services/features/generalApplication/generalApplicationService', () => ({ getCancelUrl: jest.fn(), From 744b9c208ff147fad57413fb78dce8a65d95a0fb Mon Sep 17 00:00:00 2001 From: jeswanth Date: Mon, 15 Jul 2024 11:26:12 +0100 Subject: [PATCH 12/17] added typing for model --- src/main/common/models/gaEvents/eventDto.ts | 30 ++++++++++----------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/main/common/models/gaEvents/eventDto.ts b/src/main/common/models/gaEvents/eventDto.ts index ef8041f1a67..6281ca82f80 100644 --- a/src/main/common/models/gaEvents/eventDto.ts +++ b/src/main/common/models/gaEvents/eventDto.ts @@ -35,22 +35,20 @@ export interface CCDGeneralApplication extends ClaimUpdate { generalAppStatementOfTruth?: CcdGeneralApplicationStatementOfTruth; generalAppHelpWithFees?: CCDHelpWithFees; caseLink?: CaseLink; - uploadDocument?: any[] + uploadDocument?: AdditionalDocuments[] +} +interface DocumentDetails { + document_url: string; + document_binary_url: string; + document_filename: string; } -// interface Document { -// documentUrl: string; -// documentBinaryUrl: string; -// documentFileName: string; -// documentHash?: string; -// categoryID?: string; -// uploadTimestamp?: string; -// } -// interface AdditionDocDetails { -// documentType: string, -// additionalDocument: Document -// } +interface AdditionDocDetails { + typeOfDocument: string, + documentUpload: DocumentDetails +} -// export interface AdditionalDocuments { - -// } +export interface AdditionalDocuments { + id: string; + value: AdditionDocDetails +} From d9697b1ee08db1339104aa40a039bb3f228bec96 Mon Sep 17 00:00:00 2001 From: jeswanth Date: Mon, 15 Jul 2024 13:31:24 +0100 Subject: [PATCH 13/17] added acessbility tests --- ...p_response_admitAll_repaymentPlan_tests.js | 32 +- ...d-additional-documents-check-and-send.html | 542 +++++++++++++++ ...upload-additional-documents-submitted.html | 645 ++++++++++++++++++ ...653906339-upload-additional-documents.html | 592 ++++++++++++++++ 4 files changed, 1795 insertions(+), 16 deletions(-) create mode 100644 src/test/utils/mocks/a11y/mock-case-1645882162449409-general-application-1720536503257495-general-application-1720536653906339-upload-additional-documents-check-and-send.html create mode 100644 src/test/utils/mocks/a11y/mock-case-1645882162449409-general-application-1720536653906339-upload-additional-documents-submitted.html create mode 100644 src/test/utils/mocks/a11y/mock-case-1645882162449409-general-application-1720536653906339-upload-additional-documents.html diff --git a/src/test/functionalTests/tests/prod/LRvLip_response_admitAll_repaymentPlan_tests.js b/src/test/functionalTests/tests/prod/LRvLip_response_admitAll_repaymentPlan_tests.js index 70e2b24a1f3..109918c6de2 100644 --- a/src/test/functionalTests/tests/prod/LRvLip_response_admitAll_repaymentPlan_tests.js +++ b/src/test/functionalTests/tests/prod/LRvLip_response_admitAll_repaymentPlan_tests.js @@ -13,7 +13,7 @@ let caseData; let claimNumber; let securityCode; -Feature('Response with AdmitAll and Repayment plan'); +Feature('Response with AdmitAll and Repayment plan @vjrtest'); Before(async ({api}) => { await createAccount(config.defendantCitizenUser.email, config.defendantCitizenUser.password); @@ -29,19 +29,19 @@ Before(async ({api}) => { await CitizenDashboardSteps.VerifyClaimOnDashboard(claimNumber); }); -Scenario('Response with AdmitAll and Repayment plan @citizenUI @admitAll @nightly', async ({api}) => { - console.log('Response with AdmitAll claimRef --> ' + claimRef); - await ResponseSteps.RespondToClaim(claimRef); - await ResponseSteps.EnterPersonalDetails(claimRef); - await ResponseSteps.EnterYourOptionsForDeadline(claimRef, dontWantMoreTime); - await ResponseSteps.EnterResponseToClaim(claimRef, admitAll); - await ResponseSteps.EnterPaymentOption(claimRef, admitAll, repaymentPlan); - await ResponseSteps.EnterFinancialDetails(claimRef); - await ResponseSteps.EnterRepaymentPlan(claimRef); - await ResponseSteps.CheckAndSubmit(claimRef, admitAll); - // commenting until this is fixed https://tools.hmcts.net/jira/browse/CIV-9655 - // await api.enterBreathingSpace(config.applicantSolicitorUser); - // await api.liftBreathingSpace(config.applicantSolicitorUser); - await api.viewAndRespondToDefence(config.applicantSolicitorUser, config.defenceType.admitAllPayByInstallment, config.claimState.PROCEEDS_IN_HERITAGE_SYSTEM); -}).tag('@regression-cui-r1'); +// Scenario('Response with AdmitAll and Repayment plan @citizenUI @admitAll @nightly', async ({api}) => { +// console.log('Response with AdmitAll claimRef --> ' + claimRef); +// await ResponseSteps.RespondToClaim(claimRef); +// await ResponseSteps.EnterPersonalDetails(claimRef); +// await ResponseSteps.EnterYourOptionsForDeadline(claimRef, dontWantMoreTime); +// await ResponseSteps.EnterResponseToClaim(claimRef, admitAll); +// await ResponseSteps.EnterPaymentOption(claimRef, admitAll, repaymentPlan); +// await ResponseSteps.EnterFinancialDetails(claimRef); +// await ResponseSteps.EnterRepaymentPlan(claimRef); +// await ResponseSteps.CheckAndSubmit(claimRef, admitAll); +// // commenting until this is fixed https://tools.hmcts.net/jira/browse/CIV-9655 +// // await api.enterBreathingSpace(config.applicantSolicitorUser); +// // await api.liftBreathingSpace(config.applicantSolicitorUser); +// await api.viewAndRespondToDefence(config.applicantSolicitorUser, config.defenceType.admitAllPayByInstallment, config.claimState.PROCEEDS_IN_HERITAGE_SYSTEM); +// }).tag('@regression-cui-r1'); diff --git a/src/test/utils/mocks/a11y/mock-case-1645882162449409-general-application-1720536503257495-general-application-1720536653906339-upload-additional-documents-check-and-send.html b/src/test/utils/mocks/a11y/mock-case-1645882162449409-general-application-1720536503257495-general-application-1720536653906339-upload-additional-documents-check-and-send.html new file mode 100644 index 00000000000..86cf64c617a --- /dev/null +++ b/src/test/utils/mocks/a11y/mock-case-1645882162449409-general-application-1720536503257495-general-application-1720536653906339-upload-additional-documents-check-and-send.html @@ -0,0 +1,542 @@ + + + + + + + + + + Check your answers - Your money claims account + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Skip to main content + + + + + + + +
+
+ + +
+ + + + Money Claims + + + + + + +
+ +
+
+ + + + + + +
+ + + +
+

+ + + This is a new service – your feedback will help us to improve it.English + +

+
+ + + + + + Back + + + + + +
+ +
+ +
+
+
+ + +

+ Upload additional documents + Check your answers +

+ + +

+ Case number: + 1720 5365 0325 7495 +

+ + +

Mr Claimant person v mr defendant person

+ + +
+
+ + + + + +
+ + +
+
+ Type of document +
+
+ test +
+ +
+ + + +
+
+ Uploaded document +
+
+ n245form.pdf +
+ +
+ Change Uploaded document + +
+ +
+ + +
+ +
+
+ +
+ + + +
+ + + + + + + + Cancel +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + Contact us for help + + +
+ + + + + + +

Email

+ + + + contactocmc@justice.gov.uk +

+ + + + + + +

Telephone

+ + 0300 123 7050 + + +

Monday to Friday, 8.30am to 5pm.

+ + + Find out about call charges (opens in a new window)

+ + +
+
+ + + +
+
+ +
+
+ + + + + + + + + + + + + + + + diff --git a/src/test/utils/mocks/a11y/mock-case-1645882162449409-general-application-1720536653906339-upload-additional-documents-submitted.html b/src/test/utils/mocks/a11y/mock-case-1645882162449409-general-application-1720536653906339-upload-additional-documents-submitted.html new file mode 100644 index 00000000000..6aa9257125c --- /dev/null +++ b/src/test/utils/mocks/a11y/mock-case-1645882162449409-general-application-1720536653906339-upload-additional-documents-submitted.html @@ -0,0 +1,645 @@ + + + + + + + + + + Your money claims account - Money Claims + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Skip to main content + + + + + + + +
+
+ + +
+ + + + Money Claims + + + + + + +
+ +
+
+ + + + + + +
+ + +
+

+ + + This is a new service – your feedback will help us to improve it.English + +

+
+ + + + + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

+ You've uploaded additional documents +

+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

What happens next

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

A judge will review the additional documents that you’ve uploaded. You’ll receive an update with their decision or next steps.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+ + + + + + + + + + + + + + + diff --git a/src/test/utils/mocks/a11y/mock-case-1645882162449409-general-application-1720536653906339-upload-additional-documents.html b/src/test/utils/mocks/a11y/mock-case-1645882162449409-general-application-1720536653906339-upload-additional-documents.html new file mode 100644 index 00000000000..8ea45009400 --- /dev/null +++ b/src/test/utils/mocks/a11y/mock-case-1645882162449409-general-application-1720536653906339-upload-additional-documents.html @@ -0,0 +1,592 @@ + + + + + + + + + + Upload documents - Your money claims account + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Skip to main content + + + + + + + +
+
+ + +
+ + + + Money Claims + + + + + + +
+ +
+
+ + + + + + +
+ + + +
+

+ + + This is a new service – your feedback will help us to improve it.English + +

+
+ + + + + + Back + + + + + +
+ +
+ +
+
+
+ + + + + + +

+ Upload additional documents + Upload documents +

+ +

You should only upload documents that are relevant to your application, for example if the judge has ordered a hearing and instructed you to provide documents ahead of this.

+

Before you upload the document you will need to describe the type of document you are uploading, for example, Bundle, witness statement or costs schedule.

+

Each document must be less than 100MB. You can upload the following file types: DOC/DOCX (Word), XLS/XLSM (Excel), PPT/PPTX (PowerPoint), PDF, RTF, TXT, CSV, JPG/JPEG, PNG, BMP, TIF/TIFF.

+
+ + + +
+ + + +
+ + + + +
+ For example, contract, invoice receipt, email, text message, photo, social media message +
+ + + + +
+ + + + + + +
+ + + + + + +
+ + + + + + + + + + +
+ +

Uploaded files

+
+ +
+ +
+
+ Type of document +
+
+

test

+
+
+ +
+ +
+ +
+
+

n245form.pdf

+
+
+ + Remove document + n245form.pdf + +
+
+ +
+ + +
+ + +
+ + + + + + + + + + + + Cancel + + + + +
+ + +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + Contact us for help + + +
+ + + + + + +

Email

+ + + + contactocmc@justice.gov.uk +

+ + + + + + +

Telephone

+ + 0300 123 7050 + + +

Monday to Friday, 8.30am to 5pm.

+ + + Find out about call charges (opens in a new window)

+ + +
+
+ + + +
+
+ +
+
+ + + + + + + + + + + + + + + + From 906866345064301c06243bdc4f77dd8dd22345ec Mon Sep 17 00:00:00 2001 From: jeswanth-hmcts <134285996+jeswanth-hmcts@users.noreply.github.com> Date: Mon, 15 Jul 2024 13:42:02 +0100 Subject: [PATCH 14/17] Update LRvLip_response_admitAll_repaymentPlan_tests.js --- ...p_response_admitAll_repaymentPlan_tests.js | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/test/functionalTests/tests/prod/LRvLip_response_admitAll_repaymentPlan_tests.js b/src/test/functionalTests/tests/prod/LRvLip_response_admitAll_repaymentPlan_tests.js index 109918c6de2..70e2b24a1f3 100644 --- a/src/test/functionalTests/tests/prod/LRvLip_response_admitAll_repaymentPlan_tests.js +++ b/src/test/functionalTests/tests/prod/LRvLip_response_admitAll_repaymentPlan_tests.js @@ -13,7 +13,7 @@ let caseData; let claimNumber; let securityCode; -Feature('Response with AdmitAll and Repayment plan @vjrtest'); +Feature('Response with AdmitAll and Repayment plan'); Before(async ({api}) => { await createAccount(config.defendantCitizenUser.email, config.defendantCitizenUser.password); @@ -29,19 +29,19 @@ Before(async ({api}) => { await CitizenDashboardSteps.VerifyClaimOnDashboard(claimNumber); }); -// Scenario('Response with AdmitAll and Repayment plan @citizenUI @admitAll @nightly', async ({api}) => { -// console.log('Response with AdmitAll claimRef --> ' + claimRef); -// await ResponseSteps.RespondToClaim(claimRef); -// await ResponseSteps.EnterPersonalDetails(claimRef); -// await ResponseSteps.EnterYourOptionsForDeadline(claimRef, dontWantMoreTime); -// await ResponseSteps.EnterResponseToClaim(claimRef, admitAll); -// await ResponseSteps.EnterPaymentOption(claimRef, admitAll, repaymentPlan); -// await ResponseSteps.EnterFinancialDetails(claimRef); -// await ResponseSteps.EnterRepaymentPlan(claimRef); -// await ResponseSteps.CheckAndSubmit(claimRef, admitAll); -// // commenting until this is fixed https://tools.hmcts.net/jira/browse/CIV-9655 -// // await api.enterBreathingSpace(config.applicantSolicitorUser); -// // await api.liftBreathingSpace(config.applicantSolicitorUser); -// await api.viewAndRespondToDefence(config.applicantSolicitorUser, config.defenceType.admitAllPayByInstallment, config.claimState.PROCEEDS_IN_HERITAGE_SYSTEM); -// }).tag('@regression-cui-r1'); +Scenario('Response with AdmitAll and Repayment plan @citizenUI @admitAll @nightly', async ({api}) => { + console.log('Response with AdmitAll claimRef --> ' + claimRef); + await ResponseSteps.RespondToClaim(claimRef); + await ResponseSteps.EnterPersonalDetails(claimRef); + await ResponseSteps.EnterYourOptionsForDeadline(claimRef, dontWantMoreTime); + await ResponseSteps.EnterResponseToClaim(claimRef, admitAll); + await ResponseSteps.EnterPaymentOption(claimRef, admitAll, repaymentPlan); + await ResponseSteps.EnterFinancialDetails(claimRef); + await ResponseSteps.EnterRepaymentPlan(claimRef); + await ResponseSteps.CheckAndSubmit(claimRef, admitAll); + // commenting until this is fixed https://tools.hmcts.net/jira/browse/CIV-9655 + // await api.enterBreathingSpace(config.applicantSolicitorUser); + // await api.liftBreathingSpace(config.applicantSolicitorUser); + await api.viewAndRespondToDefence(config.applicantSolicitorUser, config.defenceType.admitAllPayByInstallment, config.claimState.PROCEEDS_IN_HERITAGE_SYSTEM); +}).tag('@regression-cui-r1'); From cd7c8a520052979e1c9fe18ac22d9f8ec26a5320 Mon Sep 17 00:00:00 2001 From: jeswanth Date: Mon, 15 Jul 2024 14:51:56 +0100 Subject: [PATCH 15/17] fixed acessbility issues --- ...0536653906339-upload-additional-documents-check-and-send.html} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/test/utils/mocks/a11y/{mock-case-1645882162449409-general-application-1720536503257495-general-application-1720536653906339-upload-additional-documents-check-and-send.html => mock-case-1645882162449409-general-application-1720536653906339-upload-additional-documents-check-and-send.html} (100%) diff --git a/src/test/utils/mocks/a11y/mock-case-1645882162449409-general-application-1720536503257495-general-application-1720536653906339-upload-additional-documents-check-and-send.html b/src/test/utils/mocks/a11y/mock-case-1645882162449409-general-application-1720536653906339-upload-additional-documents-check-and-send.html similarity index 100% rename from src/test/utils/mocks/a11y/mock-case-1645882162449409-general-application-1720536503257495-general-application-1720536653906339-upload-additional-documents-check-and-send.html rename to src/test/utils/mocks/a11y/mock-case-1645882162449409-general-application-1720536653906339-upload-additional-documents-check-and-send.html From 949b235e66ef89ba227cd30f594dd588cfa866fe Mon Sep 17 00:00:00 2001 From: jeswanth Date: Wed, 17 Jul 2024 15:29:28 +0100 Subject: [PATCH 16/17] CIV-14228 fixed review comments --- src/main/common/utils/urlFormatter.ts | 4 ++++ src/main/modules/i18n/locales/cy.json | 8 ++++---- src/main/modules/i18n/locales/en.json | 8 ++++---- .../checkAnswersController.ts | 13 +++++++------ .../uploadAdditionalDocumentsController.ts | 12 ++++++------ .../viewApplicationController.ts | 4 ++-- src/main/routes/urls.ts | 6 +++--- .../additionalDocumentService.ts | 3 ++- src/test/a11y/a11y.mock-test.ts | 2 +- .../checkAnswersController.test.ts | 16 ++++++++++------ ...ploadAdditionalDocumentsController.test.ts | 19 ++++++++++--------- .../additionalDocumentService.test.ts | 3 ++- 12 files changed, 55 insertions(+), 43 deletions(-) diff --git a/src/main/common/utils/urlFormatter.ts b/src/main/common/utils/urlFormatter.ts index bb4416f0e33..bb71e5dab9c 100644 --- a/src/main/common/utils/urlFormatter.ts +++ b/src/main/common/utils/urlFormatter.ts @@ -4,6 +4,10 @@ export function constructResponseUrlWithIdParams(id: string, path: string): stri return path.replace(/(:id)/i, id); } +export function constructResponseUrlWithIdAndAppIdParams(id: string, appId: string, path: string): string { + return path.replace(/(:id)/i, id).replace(/(:appId)/i, appId); +} + export function constructUrlWithNotEligibleReason(path: string, reason: NotEligibleReason): string { return `${path}?reason=${reason}`; } diff --git a/src/main/modules/i18n/locales/cy.json b/src/main/modules/i18n/locales/cy.json index bda832e9703..59dc5f29c0b 100644 --- a/src/main/modules/i18n/locales/cy.json +++ b/src/main/modules/i18n/locales/cy.json @@ -2577,13 +2577,13 @@ }, "ADDITIONAL_DOCUMENTS": { "ADDITIONAL_DOCUMENTS_CAPTION": "Upload additional documents", - "UPLOAD_DOCUMENTS_TITLE": "Upload documents", "ADDITIONAL_DOCUMENTS_ROW1": "You should only upload documents that are relevant to your application, for example if the judge has ordered a hearing and instructed you to provide documents ahead of this.", "ADDITIONAL_DOCUMENTS_ROW2": "Before you upload the document you will need to describe the type of document you are uploading, for example, Bundle, witness statement or costs schedule.", - "TYPE_OF_DOCUMENT": "Type of document", + "JUDGE_WILL_REVIEW": "A judge will review the additional documents that you’ve uploaded. You’ll receive an update with their decision or next steps.", "TYPE_OF_DOCUMENT_HINT": "For example, contract, invoice receipt, email, text message, photo, social media message", - "UPLOADED_ADDITIONAL_DOCS": "You've uploaded additional documents", - "JUDGE_WILL_REVIEW": "A judge will review the additional documents that you’ve uploaded. You’ll receive an update with their decision or next steps." + "TYPE_OF_DOCUMENT": "Type of document", + "UPLOAD_DOCUMENTS_TITLE": "Upload documents", + "UPLOADED_ADDITIONAL_DOCS": "You've uploaded additional documents" }, "AGREE_TO_ORDER": { "MADE_AWARE": "If you have not been made aware of this application by the other parties, select 'No'.", diff --git a/src/main/modules/i18n/locales/en.json b/src/main/modules/i18n/locales/en.json index ec2e431bba2..6eaa092afd1 100644 --- a/src/main/modules/i18n/locales/en.json +++ b/src/main/modules/i18n/locales/en.json @@ -2577,13 +2577,13 @@ }, "ADDITIONAL_DOCUMENTS": { "ADDITIONAL_DOCUMENTS_CAPTION": "Upload additional documents", - "UPLOAD_DOCUMENTS_TITLE": "Upload documents", "ADDITIONAL_DOCUMENTS_ROW1": "You should only upload documents that are relevant to your application, for example if the judge has ordered a hearing and instructed you to provide documents ahead of this.", "ADDITIONAL_DOCUMENTS_ROW2": "Before you upload the document you will need to describe the type of document you are uploading, for example, Bundle, witness statement or costs schedule.", - "TYPE_OF_DOCUMENT": "Type of document", + "JUDGE_WILL_REVIEW": "A judge will review the additional documents that you’ve uploaded. You’ll receive an update with their decision or next steps.", "TYPE_OF_DOCUMENT_HINT": "For example, contract, invoice receipt, email, text message, photo, social media message", - "UPLOADED_ADDITIONAL_DOCS": "You've uploaded additional documents", - "JUDGE_WILL_REVIEW": "A judge will review the additional documents that you’ve uploaded. You’ll receive an update with their decision or next steps." + "TYPE_OF_DOCUMENT": "Type of document", + "UPLOAD_DOCUMENTS_TITLE": "Upload documents", + "UPLOADED_ADDITIONAL_DOCS": "You've uploaded additional documents" }, "AGREE_TO_ORDER": { "MADE_AWARE": "If you have not been made aware of this application by the other parties, select 'No'.", diff --git a/src/main/routes/features/generalApplication/additionalDocuments/checkAnswersController.ts b/src/main/routes/features/generalApplication/additionalDocuments/checkAnswersController.ts index 0fe78a5c070..7c3c0f9187b 100644 --- a/src/main/routes/features/generalApplication/additionalDocuments/checkAnswersController.ts +++ b/src/main/routes/features/generalApplication/additionalDocuments/checkAnswersController.ts @@ -7,6 +7,7 @@ import { GaServiceClient } from 'client/gaServiceClient'; import { getCancelUrl } from 'services/features/generalApplication/generalApplicationService'; import { NextFunction, RequestHandler, Response, Router } from 'express'; import config from 'config'; +import { constructResponseUrlWithIdAndAppIdParams } from 'common/utils/urlFormatter'; const gaAdditionalDocCheckAnswerController = Router(); const viewPath = 'features/generalApplication/additionalDocuments/check-answers'; @@ -15,12 +16,12 @@ const gaServiceClient: GaServiceClient = new GaServiceClient(generalAppApiBaseUr gaAdditionalDocCheckAnswerController.get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, (async (req: AppRequest, res: Response, next: NextFunction) => { try { - const { gaId, id: claimId } = req.params; + const { appId, id: claimId } = req.params; const claimIdPrettified = caseNumberPrettify(claimId); const claim = await getClaimDetailsById(req); const cancelUrl = await getCancelUrl(claimId, claim); - const backLinkUrl = GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId); - const summaryRows = buildSummarySectionForAdditionalDoc(claim.generalApplication.uploadAdditionalDocuments, claimId, gaId); + const backLinkUrl = constructResponseUrlWithIdAndAppIdParams(claimId, appId, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL); + const summaryRows = buildSummarySectionForAdditionalDoc(claim.generalApplication.uploadAdditionalDocuments, claimId, appId); res.render(viewPath, { backLinkUrl, cancelUrl, claimIdPrettified, claim, summaryRows }); } catch (error) { next(error); @@ -29,14 +30,14 @@ gaAdditionalDocCheckAnswerController.get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, gaAdditionalDocCheckAnswerController.post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, (async (req: AppRequest, res: Response, next: NextFunction) => { try { - const { gaId, id: claimId } = req.params; + const { appId, id: claimId } = req.params; const claim = await getClaimDetailsById(req); const uploadedDocuments = prepareCCDData(claim.generalApplication.uploadAdditionalDocuments); const generalApplication = { uploadDocument: uploadedDocuments, }; - await gaServiceClient.submitEvent(ApplicationEvent.UPLOAD_ADDL_DOCUMENTS, gaId, generalApplication as unknown, req); - res.redirect(GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL.replace(':id', claimId).replace(':gaId', gaId)); + await gaServiceClient.submitEvent(ApplicationEvent.UPLOAD_ADDL_DOCUMENTS, appId, generalApplication as unknown, req); + res.redirect(constructResponseUrlWithIdAndAppIdParams(claimId, appId, GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL)); } catch (error) { next(error); } diff --git a/src/main/routes/features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.ts b/src/main/routes/features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.ts index 5f7edf948ea..df3291c7e86 100644 --- a/src/main/routes/features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.ts +++ b/src/main/routes/features/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.ts @@ -5,7 +5,7 @@ import { GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL, GA_UPLOAD_ADDITIONAL_DOCUMENTS_ import multer from 'multer'; import { UploadAdditionalDocument } from 'common/models/generalApplication/UploadAdditionalDocument'; import { generateRedisKey } from 'modules/draft-store/draftStoreService'; -import { constructResponseUrlWithIdParams } from 'common/utils/urlFormatter'; +import { constructResponseUrlWithIdAndAppIdParams, constructResponseUrlWithIdParams } from 'common/utils/urlFormatter'; import { getCancelUrl } from 'services/features/generalApplication/generalApplicationService'; import { getClaimDetailsById, getSummaryList, removeSelectedDocument, uploadSelectedFile } from 'services/features/generalApplication/additionalDocumentService'; @@ -21,14 +21,14 @@ const upload = multer({ uploadAdditionalDocumentsController.get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL, (async (req: AppRequest, res: Response, next: NextFunction) => { try { - const { gaId, id } = req.params; + const { appId:gaId, id } = req.params; const uploadedDocument = new UploadAdditionalDocument(); let form = new GenericForm(uploadedDocument); const redisKey = generateRedisKey(req); const claim = await getClaimDetailsById(req); const gaDetails = claim.generalApplication; - if (req?.session?.fileUpload) { + if (req.session?.fileUpload) { const parsedData = JSON.parse(req?.session?.fileUpload); form = new GenericForm(uploadedDocument, parsedData); req.session.fileUpload = undefined; @@ -48,8 +48,8 @@ uploadAdditionalDocumentsController.get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL, (asy uploadAdditionalDocumentsController.post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL, upload.single('selectedFile'), (async (req: AppRequest, res: Response, next: NextFunction) => { try { - const { gaId, id } = req.params; - const currentUrl = GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', id).replace(':gaId', gaId); + const { appId, id: claimId } = req.params; + const currentUrl = constructResponseUrlWithIdAndAppIdParams(claimId, appId, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL); const claim = await getClaimDetailsById(req); const gaDetails = claim.generalApplication; if (req.body.action === 'uploadButton') { @@ -72,7 +72,7 @@ uploadAdditionalDocumentsController.post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL, upl req.session.fileUpload = JSON.stringify(errors); return res.redirect(`${currentUrl}`); } - res.redirect(constructResponseUrlWithIdParams(id, GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL).replace(':gaId', gaId)); + res.redirect(constructResponseUrlWithIdAndAppIdParams(claimId, appId, GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL)); } catch (err) { next(err); } diff --git a/src/main/routes/features/generalApplication/viewApplicationController.ts b/src/main/routes/features/generalApplication/viewApplicationController.ts index 9af7d76d26c..b72d6f9ef31 100644 --- a/src/main/routes/features/generalApplication/viewApplicationController.ts +++ b/src/main/routes/features/generalApplication/viewApplicationController.ts @@ -3,7 +3,7 @@ import { DASHBOARD_URL, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL, GA_VIEW_APPLICATION_ import {AppRequest} from 'common/models/AppRequest'; import {getApplicationSections} from 'services/features/generalApplication/viewApplication/viewApplicationService'; import {queryParamNumber} from 'common/utils/requestUtils'; -import { constructResponseUrlWithIdParams } from 'common/utils/urlFormatter'; +import { constructResponseUrlWithIdAndAppIdParams } from 'common/utils/urlFormatter'; const viewApplicationController = Router(); const viewPath = 'features/generalApplication/view-applications'; @@ -16,7 +16,7 @@ viewApplicationController.get(GA_VIEW_APPLICATION_URL, (async (req: AppRequest, const lang = req.query.lang ? req.query.lang : req.cookies.lang; const summaryRows = await getApplicationSections(req, applicationId, lang); const pageTitle = 'PAGES.GENERAL_APPLICATION.VIEW_APPLICATION.PAGE_TITLE'; - const additionalDocUrl = constructResponseUrlWithIdParams(req.params.id, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL).replace(':gaId', applicationId); + const additionalDocUrl = constructResponseUrlWithIdAndAppIdParams(req.params.id, applicationId, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL); res.render(viewPath, { backLinkUrl, summaryRows, additionalDocUrl, pageTitle, dashboardUrl: DASHBOARD_URL, applicationIndex }); } catch (error) { next(error); diff --git a/src/main/routes/urls.ts b/src/main/routes/urls.ts index c321c63fd01..39b463d6e20 100644 --- a/src/main/routes/urls.ts +++ b/src/main/routes/urls.ts @@ -368,9 +368,9 @@ export const FRC_BAND_AGREED_URL = `${DIRECTIONS_QUESTIONNAIRE_URL}/frc-band-agr export const ASSIGN_FRC_BAND_URL = `${DIRECTIONS_QUESTIONNAIRE_URL}/assign-complexity-band`; export const REASON_FOR_FRC_BAND_URL = `${DIRECTIONS_QUESTIONNAIRE_URL}/reason-for-complexity-band`; export const WHY_NOT_SUBJECT_TO_FRC_URL = `${DIRECTIONS_QUESTIONNAIRE_URL}/why-not-subject-to-frc`; -export const GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL = `${BASE_GENERAL_APPLICATION_URL}/:gaId/upload-additional-documents`; -export const GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL = `${BASE_GENERAL_APPLICATION_URL}/:gaId/upload-additional-documents/check-and-send`; -export const GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL = `${BASE_GENERAL_APPLICATION_URL}/:gaId/upload-additional-documents/submitted`; +export const GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL = `${BASE_GENERAL_APPLICATION_URL}/:appId/upload-additional-documents`; +export const GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL = `${BASE_GENERAL_APPLICATION_URL}/:appId/upload-additional-documents/check-and-send`; +export const GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL = `${BASE_GENERAL_APPLICATION_URL}/:appId/upload-additional-documents/submitted`; export const GA_RESPONSE_VIEW_APPLICATION_URL = `${BASE_GENERAL_APPLICATION_RESPONSE_URL}/view-application`; export const GA_RESPONDENT_HEARING_PREFERENCE_URL = `${BASE_GENERAL_APPLICATION_RESPONSE_URL}/hearing-preference`; export const GA_RESPONDENT_WANT_TO_UPLOAD_DOCUMENT_URL = `${BASE_GENERAL_APPLICATION_RESPONSE_URL}/want-to-upload-document`; diff --git a/src/main/services/features/generalApplication/additionalDocumentService.ts b/src/main/services/features/generalApplication/additionalDocumentService.ts index 9c43c096caf..e34f6ffb9b7 100644 --- a/src/main/services/features/generalApplication/additionalDocumentService.ts +++ b/src/main/services/features/generalApplication/additionalDocumentService.ts @@ -16,6 +16,7 @@ import { GeneralApplication } from 'common/models/generalApplication/GeneralAppl import { changeLabel } from 'common/utils/checkYourAnswer/changeButton'; import { PaymentSuccessfulSectionBuilder } from '../claim/paymentSuccessfulSectionBuilder'; import { getLng } from 'common/utils/languageToggleUtils'; +import { constructResponseUrlWithIdAndAppIdParams } from 'common/utils/urlFormatter'; const { v4: uuIdv4 } = require('uuid'); const { Logger } = require('@hmcts/nodejs-logging'); @@ -33,7 +34,7 @@ export const getSummaryList = (additionalDocumentsList: UploadAdditionalDocument additionalDocumentsList.forEach((uploadDocument: UploadAdditionalDocument) => { index = index + 1; formattedSummary.summaryList.rows.push(summaryRow('Type of document', uploadDocument.typeOfDocument)); - formattedSummary.summaryList.rows.push(summaryRow(uploadDocument.caseDocument.documentName, '', `${GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)}?indexId=${index}`, 'Remove document')); + formattedSummary.summaryList.rows.push(summaryRow(uploadDocument.caseDocument.documentName, '', `${constructResponseUrlWithIdAndAppIdParams(claimId, gaId, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL)}?indexId=${index}`, 'Remove document')); }); return formattedSummary; }; diff --git a/src/test/a11y/a11y.mock-test.ts b/src/test/a11y/a11y.mock-test.ts index 00c1c128296..30e95b3bf28 100644 --- a/src/test/a11y/a11y.mock-test.ts +++ b/src/test/a11y/a11y.mock-test.ts @@ -63,7 +63,7 @@ describe('Accessibility', async () => { it('Test of '+url,async () => { app.get(url, (req: any, res: any) => { url = url.replace(':id', '1645882162449409'); - url = url.replace(':gaId', '1720536653906339'); + url = url.replace(':appId', '1720536653906339'); const filePath = translateUrlToFilePath(url); const fileContent = fs.readFileSync(filePath, 'utf8'); res.send(fileContent); diff --git a/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/checkAnswersController.test.ts b/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/checkAnswersController.test.ts index 5c97034c8af..9683efe2fae 100644 --- a/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/checkAnswersController.test.ts +++ b/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/checkAnswersController.test.ts @@ -10,9 +10,9 @@ import { Claim } from 'common/models/claim'; import { GeneralApplication } from 'common/models/generalApplication/GeneralApplication'; import { GaServiceClient } from 'client/gaServiceClient'; import { ApplicationEvent } from 'common/models/gaEvents/applicationEvent'; +import { constructResponseUrlWithIdAndAppIdParams } from 'common/utils/urlFormatter'; jest.mock('../../../../../../../main/modules/oidc'); -// jest.mock('../../../../../../../main/modules/draft-store/draftStoreService'); jest.mock('../../../../../../../main/app/auth/launchdarkly/launchDarklyClient'); jest.mock('../../../../../../../main/services/features/generalApplication/additionalDocumentService', () => ({ getClaimDetailsById: jest.fn(), @@ -46,7 +46,7 @@ describe('General Application - additional docs check answer controller ', () => (getCancelUrl as jest.Mock).mockResolvedValue('/cancel-url'); (buildSummarySectionForAdditionalDoc as jest.Mock).mockReturnValue([]); - const res = await request(app).get(`${GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL.replace(':id', claimId).replace(':gaId', gaId)}`); + const res = await request(app).get(constructResponseUrlWithIdAndAppIdParams(claimId, gaId, GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL)); expect(res.status).toBe(200); expect(getClaimDetailsById).toHaveBeenCalledWith(expect.anything()); @@ -56,9 +56,11 @@ describe('General Application - additional docs check answer controller ', () => }); it('should handle errors', async () => { + const claimId = '123'; + const gaId = '456'; (getClaimDetailsById as jest.Mock).mockRejectedValue(new Error('Error')); - const res = await request(app).get(`${GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL.replace(':id', '123').replace(':gaId', '456')}`); + const res = await request(app).get(constructResponseUrlWithIdAndAppIdParams(claimId, gaId, GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL)); expect(res.status).toBe(500); }); @@ -74,19 +76,21 @@ describe('General Application - additional docs check answer controller ', () => (prepareCCDData as jest.Mock).mockReturnValue([]); const mockGaServiceClient = jest.spyOn(GaServiceClient.prototype, 'submitEvent').mockResolvedValueOnce(undefined); - const res = await request(app).post(`${GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL.replace(':id', claimId).replace(':gaId', gaId)}`); + const res = await request(app).post(constructResponseUrlWithIdAndAppIdParams(claimId, gaId, GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL)); expect(res.status).toBe(302); - expect(res.header.location).toBe(GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL.replace(':id', claimId).replace(':gaId', gaId)); + expect(res.header.location).toBe(constructResponseUrlWithIdAndAppIdParams(claimId, gaId, GA_UPLOAD_ADDITIONAL_DOCUMENTS_SUBMITTED_URL)); expect(getClaimDetailsById).toHaveBeenCalledWith(expect.anything()); expect(prepareCCDData).toHaveBeenCalledWith(claim.generalApplication.uploadAdditionalDocuments); expect(mockGaServiceClient).toHaveBeenCalledWith(ApplicationEvent.UPLOAD_ADDL_DOCUMENTS, gaId, { uploadDocument: [] }, expect.anything()); }); it('should handle errors', async () => { + const claimId = '123'; + const gaId = '456'; (getClaimDetailsById as jest.Mock).mockRejectedValue(new Error('Error')); - const res = await request(app).post(`${GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL.replace(':id', '123').replace(':gaId', '456')}`).send({}); + const res = await request(app).post(constructResponseUrlWithIdAndAppIdParams(claimId, gaId, GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL)).send({}); expect(res.status).toBe(500); }); diff --git a/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.test.ts b/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.test.ts index c7b36ca2fd6..4e1dedcd8ab 100644 --- a/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.test.ts +++ b/src/test/unit/routes/features/claim/generalApplication/additionalDocuments/uploadAdditionalDocumentsController.test.ts @@ -22,6 +22,7 @@ import { CaseDocument } from 'common/models/document/caseDocument'; import { FileUpload } from 'common/models/caseProgression/uploadDocumentsUserForm'; import { Session } from 'express-session'; import { t } from 'i18next'; +import { constructResponseUrlWithIdAndAppIdParams } from 'common/utils/urlFormatter'; jest.mock('../../../../../../../main/modules/oidc'); jest.mock('../../../../../../../main/services/features/generalApplication/additionalDocumentService', () => ({ @@ -99,7 +100,7 @@ describe('uploadAdditionalDocumentsController', () => { (getCancelUrl as jest.Mock).mockResolvedValue(cancelUrl); (getSummaryList as jest.Mock).mockReturnValue(formattedSummaryList); - const res = await request(app).get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)); + const res = await request(app).get(constructResponseUrlWithIdAndAppIdParams(claimId, gaId, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL)); expect(res.status).toBe(200); expect(getClaimDetailsById).toHaveBeenCalledWith(expect.anything()); @@ -131,7 +132,7 @@ describe('uploadAdditionalDocumentsController', () => { (getSummaryList as jest.Mock).mockReturnValue({}); (removeSelectedDocument as jest.Mock).mockReturnValueOnce(void 0); - const res = await request(app).get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)).query({ indexId: 1 }); + const res = await request(app).get(constructResponseUrlWithIdAndAppIdParams(claimId, gaId, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL)).query({ indexId: 1 }); expect(res.status).toBe(200); expect(removeSelectedDocument).toHaveBeenCalledWith(redisKey, claim, 0); @@ -168,7 +169,7 @@ describe('uploadAdditionalDocumentsController', () => { (removeSelectedDocument as jest.Mock).mockReturnValueOnce(void 0); app.request.session = { fileUpload: JSON.stringify(errors) } as unknown as Session; await request(app) - .get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)) + .get(constructResponseUrlWithIdAndAppIdParams(claimId, gaId, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL)) .expect((res) => { expect(res.status).toBe(200); expect(res.text).toContain(t('ERRORS.VALID_CHOOSE_THE_FILE')); @@ -178,7 +179,7 @@ describe('uploadAdditionalDocumentsController', () => { it('should handle errors', async () => { (getClaimDetailsById as jest.Mock).mockRejectedValue(new Error('Error')); - const res = await request(app).get(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', '123').replace(':gaId', '456')); + const res = await request(app).get(constructResponseUrlWithIdAndAppIdParams(claimId, gaId, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL)); expect(res.status).toBe(500); }); @@ -190,12 +191,12 @@ describe('uploadAdditionalDocumentsController', () => { (uploadSelectedFile as jest.Mock).mockResolvedValueOnce(void 0); const res = await request(app) - .post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)) + .post(constructResponseUrlWithIdAndAppIdParams(claimId, gaId, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL)) .field('action', 'uploadButton') .attach('selectedFile', Buffer.from('file content'), 'test-file.txt'); expect(res.status).toBe(302); - expect(res.header['location']).toBe(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)); + expect(res.header['location']).toBe(constructResponseUrlWithIdAndAppIdParams(claimId, gaId, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL)); expect(uploadSelectedFile).toHaveBeenCalledWith(expect.anything(), claim); }); @@ -215,17 +216,17 @@ describe('uploadAdditionalDocumentsController', () => { (getClaimDetailsById as jest.Mock).mockResolvedValue(claim); const res = await request(app) - .post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)); + .post(constructResponseUrlWithIdAndAppIdParams(claimId, gaId, GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL)); expect(res.status).toBe(302); - expect(res.header['location']).toBe(GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL.replace(':id', claimId).replace(':gaId', gaId)); + expect(res.header['location']).toBe(constructResponseUrlWithIdAndAppIdParams(claimId, gaId, GA_UPLOAD_ADDITIONAL_DOCUMENTS_CYA_URL)); }); it('should handle errors', async () => { (getClaimDetailsById as jest.Mock).mockRejectedValue(new Error('Error')); const res = await request(app) - .post(GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', '123').replace(':gaId', '456')) + .post(constructResponseUrlWithIdAndAppIdParams('123', '456', GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL)) .field('action', 'submit'); expect(res.status).toBe(500); diff --git a/src/test/unit/services/features/generalApplication/additionalDocumentService.test.ts b/src/test/unit/services/features/generalApplication/additionalDocumentService.test.ts index 6fd98fffca1..b2b815680e2 100644 --- a/src/test/unit/services/features/generalApplication/additionalDocumentService.test.ts +++ b/src/test/unit/services/features/generalApplication/additionalDocumentService.test.ts @@ -6,6 +6,7 @@ import { CaseDocument } from 'common/models/document/caseDocument'; import { GeneralApplication } from 'common/models/generalApplication/GeneralApplication'; import { UploadAdditionalDocument } from 'common/models/generalApplication/UploadAdditionalDocument'; import { summaryRow } from 'common/models/summaryList/summaryList'; +import { constructResponseUrlWithIdAndAppIdParams } from 'common/utils/urlFormatter'; import { generateRedisKey, saveDraftClaim } from 'modules/draft-store/draftStoreService'; import { getClaimById } from 'modules/utilityService'; import { GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL } from 'routes/urls'; @@ -110,7 +111,7 @@ describe('Additional Documents Service', () => { expect(result.summaryList.rows).toHaveLength(4); expect(result.summaryList.rows[0]).toEqual(summaryRow('Type of document', 'Type1')); - expect(result.summaryList.rows[1]).toEqual(summaryRow('Document1', '', `${GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL.replace(':id', claimId).replace(':gaId', gaId)}?indexId=1`, 'Remove document')); + expect(result.summaryList.rows[1]).toEqual(summaryRow('Document1', '', `${constructResponseUrlWithIdAndAppIdParams(claimId, gaId,GA_UPLOAD_ADDITIONAL_DOCUMENTS_URL)}?indexId=1`, 'Remove document')); }); }); From da5ad7a3fab5fac5fd7b9ae9eed5c2b06fdb5116 Mon Sep 17 00:00:00 2001 From: mounikahmcts <43175082+mounikahmcts@users.noreply.github.com> Date: Thu, 18 Jul 2024 11:25:31 +0100 Subject: [PATCH 17/17] Update Jenkinsfile_CNP --- Jenkinsfile_CNP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile_CNP b/Jenkinsfile_CNP index 2e6383af623..163e450593d 100644 --- a/Jenkinsfile_CNP +++ b/Jenkinsfile_CNP @@ -11,7 +11,7 @@ def camundaBranch = "master" def dmnBranch = "master" def waStandaloneBranch = "master" def ccdBranch = "master" -def generalappCCDBranch = "master" +def generalappCCDBranch = "CIV-14228-GA-Upload-additional-documents" AppPipelineConfig pipelineConf static Map secret(String secretName, String envVariable) {