@@ -33,7 +33,7 @@ jest.unstable_mockModule("../src/sqs", () => {
3333
3434import { Logger } from "@aws-lambda-powertools/logger"
3535
36- import { createMockPostModifiedDataItem } from "./testUtils"
36+ import { createMockPostModifiedDataItem } from "./testUtils.test "
3737import { BatchProcessingResult , PostDatedSQSMessage } from "../src/types"
3838
3939// Import the orchestration module after mocking dependencies
@@ -43,6 +43,10 @@ const logger = new Logger({serviceName: "postDatedLambdaTEST"})
4343
4444describe ( "orchestration" , ( ) => {
4545 describe ( "processMessages" , ( ) => {
46+ beforeEach ( ( ) => {
47+ jest . clearAllMocks ( )
48+ } )
49+
4650 it ( "should process messages and categorize them correctly" , async ( ) => {
4751 const mockMessages : Array < PostDatedSQSMessage > = [
4852 { MessageId : "1" , Body : "Message 1" , prescriptionData : createMockPostModifiedDataItem ( { } ) } ,
@@ -69,6 +73,51 @@ describe("orchestration", () => {
6973
7074 expect ( result . maturedPrescriptionUpdates ) . toHaveLength ( 0 )
7175 expect ( result . immaturePrescriptionUpdates ) . toHaveLength ( 0 )
76+ expect ( mockEnrichMessagesWithExistingRecords ) . not . toHaveBeenCalled ( )
77+ } )
78+
79+ it ( "should log errors and mark messages immature when processing throws" , async ( ) => {
80+ const mockMessages : Array < PostDatedSQSMessage > = [
81+ { MessageId : "1" , Body : "Message 1" , prescriptionData : createMockPostModifiedDataItem ( { } ) } ,
82+ { MessageId : "2" , Body : "Message 2" , prescriptionData : createMockPostModifiedDataItem ( { } ) }
83+ ]
84+
85+ mockEnrichMessagesWithExistingRecords . mockReturnValueOnce ( mockMessages )
86+ mockProcessMessage
87+ . mockReturnValueOnce ( true )
88+ . mockImplementationOnce ( async ( ) => {
89+ throw new Error ( "processing failed" )
90+ } )
91+
92+ const errorSpy = jest . spyOn ( logger , "error" )
93+ const result = await processMessages ( mockMessages , logger )
94+
95+ expect ( result . maturedPrescriptionUpdates ) . toHaveLength ( 1 )
96+ expect ( result . immaturePrescriptionUpdates ) . toHaveLength ( 1 )
97+ expect ( result . immaturePrescriptionUpdates [ 0 ] . MessageId ) . toBe ( "2" )
98+ expect ( errorSpy ) . toHaveBeenCalledWith (
99+ "Error processing message" ,
100+ expect . objectContaining ( { messageId : "2" } )
101+ )
102+ errorSpy . mockRestore ( )
103+ } )
104+
105+ it ( "should pass enriched records into processMessage" , async ( ) => {
106+ const mockMessages : Array < PostDatedSQSMessage > = [
107+ { MessageId : "1" , Body : "Message 1" , prescriptionData : createMockPostModifiedDataItem ( { } ) }
108+ ]
109+
110+ const enrichedMessage = {
111+ ...mockMessages [ 0 ] ,
112+ existingRecords : [ { prescriptionId : "abc" } ]
113+ }
114+
115+ mockEnrichMessagesWithExistingRecords . mockReturnValueOnce ( [ enrichedMessage ] )
116+ mockProcessMessage . mockReturnValue ( true )
117+
118+ await processMessages ( mockMessages , logger )
119+
120+ expect ( mockProcessMessage ) . toHaveBeenCalledWith ( logger , enrichedMessage )
72121 } )
73122 } )
74123
@@ -138,5 +187,56 @@ describe("orchestration", () => {
138187 expect ( mockReportQueueStatus ) . toHaveBeenCalled ( )
139188 jest . useRealTimers ( )
140189 } )
190+
191+ it ( "should continue processing batches until message count drops below threshold" , async ( ) => {
192+ const createBatch = ( ids : Array < string > ) =>
193+ ids . map ( ( id ) => ( {
194+ MessageId : id ,
195+ Body : `Message ${ id } ` ,
196+ prescriptionData : createMockPostModifiedDataItem ( { } )
197+ } ) )
198+
199+ const batch1 = createBatch ( [ "1" , "2" , "3" ] )
200+ const batch2 = createBatch ( [ "4" , "5" , "6" ] )
201+ const batch3 = createBatch ( [ "7" ] )
202+
203+ const enrich = ( messages : Array < PostDatedSQSMessage > ) =>
204+ messages . map ( ( message ) => ( {
205+ ...message ,
206+ existingRecords : [ ]
207+ } ) )
208+
209+ mockReceivePostDatedSQSMessages
210+ . mockReturnValueOnce ( batch1 )
211+ . mockReturnValueOnce ( batch2 )
212+ . mockReturnValueOnce ( batch3 )
213+ mockEnrichMessagesWithExistingRecords
214+ . mockReturnValueOnce ( enrich ( batch1 ) )
215+ . mockReturnValueOnce ( enrich ( batch2 ) )
216+ . mockReturnValueOnce ( enrich ( batch3 ) )
217+ mockProcessMessage . mockReturnValue ( true )
218+
219+ await processPostDatedQueue ( logger )
220+
221+ expect ( mockReceivePostDatedSQSMessages ) . toHaveBeenCalledTimes ( 3 )
222+ expect ( mockHandleProcessedMessages ) . toHaveBeenCalledTimes ( 3 )
223+ expect ( mockReportQueueStatus ) . not . toHaveBeenCalled ( )
224+ const totalMessages = batch1 . length + batch2 . length + batch3 . length
225+ expect ( mockProcessMessage ) . toHaveBeenCalledTimes ( totalMessages )
226+ } )
227+
228+ it ( "should treat empty receives as drained batches" , async ( ) => {
229+ mockReceivePostDatedSQSMessages . mockReturnValueOnce ( [ ] )
230+
231+ await processPostDatedQueue ( logger )
232+
233+ expect ( mockEnrichMessagesWithExistingRecords ) . not . toHaveBeenCalled ( )
234+ expect ( mockProcessMessage ) . not . toHaveBeenCalled ( )
235+ expect ( mockHandleProcessedMessages ) . toHaveBeenCalledTimes ( 1 )
236+ const [ result ] = mockHandleProcessedMessages . mock . calls [ 0 ] as [ BatchProcessingResult ]
237+ expect ( result . maturedPrescriptionUpdates ) . toHaveLength ( 0 )
238+ expect ( result . immaturePrescriptionUpdates ) . toHaveLength ( 0 )
239+ expect ( mockReportQueueStatus ) . not . toHaveBeenCalled ( )
240+ } )
141241 } )
142242} )
0 commit comments