11import dbHandler from '__tests__/unit/backend/helpers/jest-db'
22import { ObjectId } from 'bson'
3- import { okAsync } from 'neverthrow'
3+ import { errAsync , okAsync } from 'neverthrow'
44import {
55 BasicField ,
66 FieldResponsesV3 ,
@@ -29,6 +29,7 @@ import {
2929 performMultiRespondentPostSubmissionUpdateActions ,
3030 sendNextStepReminderEmail ,
3131} from '../multirespondent-submission.service'
32+ import { AutoreplyPdfGenerationError } from 'src/app/services/mail/mail.errors'
3233
3334jest . mock ( 'src/app/modules/datadog/datadog.utils' )
3435jest . mock ( 'src/app/services/mail/mail.utils' )
@@ -46,15 +47,18 @@ const MOCK_SUBMISSION_ATTACHMENTS = [
4647 fieldId : new ObjectId ( ) . toHexString ( ) ,
4748 } ,
4849]
49- MockMailUtils . generateAutoreplyPdf . mockReturnValue (
50- okAsync ( Buffer . from ( 'mock pdf buffer' ) ) ,
51- )
5250
5351describe ( 'multirespondent-submission.service' , ( ) => {
5452 beforeAll ( async ( ) => {
5553 await dbHandler . connect ( )
5654 } )
5755
56+ beforeEach ( ( ) => {
57+ MockMailUtils . generateAutoreplyPdf . mockReturnValue (
58+ okAsync ( Buffer . from ( 'mock pdf buffer' ) ) ,
59+ )
60+ } )
61+
5862 afterEach ( async ( ) => {
5963 jest . clearAllMocks ( )
6064 await dbHandler . clearDatabase ( )
@@ -706,6 +710,86 @@ describe('multirespondent-submission.service', () => {
706710 // Assert
707711 expect ( sendMrfRespondentCopyEmailSpy ) . not . toHaveBeenCalled ( )
708712 } )
713+
714+ it ( 'sends respondent copy despite pdf generation error' , async ( ) => {
715+ // Arrange
716+ MockMailUtils . generateAutoreplyPdf . mockReturnValue (
717+ errAsync ( new AutoreplyPdfGenerationError ( ) ) ,
718+ )
719+ const sendMrfRespondentCopyEmailSpy = jest . spyOn (
720+ MailService ,
721+ 'sendMrfRespondentCopyEmail' ,
722+ )
723+ const emailFieldWithFormSummaryStep1 = {
724+ _id : new ObjectId ( ) . toHexString ( ) ,
725+ fieldType : BasicField . Email ,
726+ title : 'Step 1 Email Field' ,
727+ autoReplyOptions : {
728+ hasAutoReply : true ,
729+ includeFormSummary : true ,
730+ autoReplySubject : 'Test Subject' ,
731+ autoReplyMessage : 'Test Message' ,
732+ autoReplySender : 'Test Sender' ,
733+ } ,
734+ }
735+
736+ const workflow = [
737+ {
738+ _id : new ObjectId ( ) . toHexString ( ) ,
739+ workflow_type : WorkflowType . Static ,
740+ emails : [ ] ,
741+ edit : [ emailFieldWithFormSummaryStep1 . _id ] ,
742+ } ,
743+ ]
744+
745+ // Act
746+ await performMultiRespondentPostSubmissionCreateActions ( {
747+ submission : {
748+ _id : mockSubmissionId ,
749+ } as unknown as IMultirespondentSubmissionSchema ,
750+ submissionId : mockSubmissionId ,
751+ form : {
752+ _id : mockFormId ,
753+ title : 'Test Form' ,
754+ form_fields : [ emailFieldWithFormSummaryStep1 ] ,
755+ stepsToNotify : [ workflow [ 0 ] . _id ] ,
756+ workflow,
757+ admin : {
758+ agency : {
759+ fullName : 'Government Technology Agency' ,
760+ } ,
761+ } ,
762+ } as unknown as IPopulatedMultirespondentForm ,
763+ encryptedPayload : {
764+ encryptedContent : 'encryptedContent' ,
765+ version : 1 ,
766+ submissionPublicKey : 'submissionPublicKey' ,
767+ encryptedSubmissionSecretKey : 'encryptedSubmissionSecretKey' ,
768+ responses : {
769+ [ emailFieldWithFormSummaryStep1 . _id ] : {
770+ fieldType : BasicField . Email ,
771+ answer : {
772+ 773+ } ,
774+ } ,
775+ } ,
776+ } as MultirespondentSubmissionDto ,
777+ logMeta : { } as any ,
778+ attachments : MOCK_SUBMISSION_ATTACHMENTS ,
779+ } )
780+
781+ // Assert
782+ // that sent to correct destination emails
783+ expect ( sendMrfRespondentCopyEmailSpy ) . toHaveBeenCalledTimes ( 1 )
784+ expect (
785+ sendMrfRespondentCopyEmailSpy . mock . calls [ 0 ] [ 0 ] . autoReplyMailData
786+ . email ,
787+ 788+ // still sends without pdf attachment
789+ expect (
790+ sendMrfRespondentCopyEmailSpy . mock . calls [ 0 ] [ 0 ] . attachments ,
791+ ) . toEqual ( [ ...MOCK_SUBMISSION_ATTACHMENTS ] )
792+ } )
709793 } )
710794
711795 describe ( 'subsequent steps' , ( ) => {
@@ -2101,6 +2185,62 @@ describe('multirespondent-submission.service', () => {
21012185 } )
21022186
21032187 describe ( 'mrf completion email notification when no approval step exists' , ( ) => {
2188+ it ( 'sends completion email without pdf attachment when pdf generation fails' , async ( ) => {
2189+ // Arrange
2190+ MockMailUtils . generateAutoreplyPdf . mockReturnValue (
2191+ errAsync ( new AutoreplyPdfGenerationError ( ) ) ,
2192+ )
2193+ const sendMrfWorkflowCompletionEmailSpy = jest . spyOn (
2194+ MailService ,
2195+ 'sendMrfWorkflowCompletionEmail' ,
2196+ )
2197+ const singleStepWorkflow : FormWorkflowStepDto [ ] = [
2198+ {
2199+ _id : new ObjectId ( ) . toHexString ( ) ,
2200+ workflow_type : WorkflowType . Static ,
2201+ emails : [ ] ,
2202+ edit : [ ] ,
2203+ } ,
2204+ ]
2205+
2206+ // Act
2207+ await performMultiRespondentPostSubmissionCreateActions ( {
2208+ submission : {
2209+ _id : mockSubmissionId ,
2210+ } as unknown as IMultirespondentSubmissionSchema ,
2211+ submissionId : mockSubmissionId ,
2212+ form : {
2213+ _id : mockFormId ,
2214+ workflow : singleStepWorkflow ,
2215+ 2216+ } as IPopulatedMultirespondentForm ,
2217+ encryptedPayload : {
2218+ encryptedContent : 'encryptedContent' ,
2219+ version : 1 ,
2220+ submissionPublicKey : 'submissionPublicKey' ,
2221+ encryptedSubmissionSecretKey : 'encryptedSubmissionSecretKey' ,
2222+ } as MultirespondentSubmissionDto ,
2223+ attachments : MOCK_SUBMISSION_ATTACHMENTS ,
2224+ logMeta : { } as any ,
2225+ } )
2226+
2227+ // Assert
2228+ expect ( sendMrfWorkflowCompletionEmailSpy ) . toHaveBeenCalledTimes ( 1 )
2229+ // pdf generation is invoked
2230+ expect ( MockMailUtils . generateAutoreplyPdf ) . toHaveBeenCalledTimes ( 1 )
2231+ // submission attachments is sent without pdf attachment
2232+ expect (
2233+ sendMrfWorkflowCompletionEmailSpy . mock . calls [ 0 ] [ 0 ] . attachments ,
2234+ ) . toEqual ( [ ...MOCK_SUBMISSION_ATTACHMENTS ] )
2235+ // the correct destination emails are included
2236+ expect (
2237+ sendMrfWorkflowCompletionEmailSpy . mock . calls [ 0 ] [ 0 ] . emails ,
2238+ ) . toContainValues ( [ '[email protected] ' ] ) 2239+ expect (
2240+ sendMrfWorkflowCompletionEmailSpy . mock . calls [ 0 ] [ 0 ] . emails . length ,
2241+ ) . toBe ( 1 )
2242+ } )
2243+
21042244 it ( 'sends completion email with pdf attachment when single step mrf is completed' , async ( ) => {
21052245 // Arrange
21062246 const sendMrfWorkflowCompletionEmailSpy = jest . spyOn (
0 commit comments