@@ -73,6 +73,7 @@ describe('EventsConsumer', () => {
7373 await waitForNextTick ( ) ;
7474
7575 expect ( callback ) . toHaveBeenCalledWith ( event ) ;
76+ // Without auto-advance, callback is only called once
7677 expect ( callback ) . toHaveBeenCalledTimes ( 1 ) ;
7778 } ) ;
7879 } ) ;
@@ -87,6 +88,7 @@ describe('EventsConsumer', () => {
8788 await waitForNextTick ( ) ;
8889
8990 expect ( callback ) . toHaveBeenCalledWith ( event ) ;
91+ // Without auto-advance, callback is only called once
9092 expect ( callback ) . toHaveBeenCalledTimes ( 1 ) ;
9193 } ) ;
9294
@@ -109,23 +111,27 @@ describe('EventsConsumer', () => {
109111 consumer . subscribe ( callback ) ;
110112 await waitForNextTick ( ) ;
111113
114+ // callback finishes at event1, index advances to 1
115+ // Without auto-advance, event2 is NOT processed
112116 expect ( consumer . eventIndex ) . toBe ( 1 ) ;
113117 expect ( consumer . callbacks ) . toHaveLength ( 0 ) ;
114118 } ) ;
115119
116- it ( 'should not increment event index when callback returns false ' , async ( ) => {
120+ it ( 'should NOT auto-advance when all callbacks return NotConsumed ' , async ( ) => {
117121 const event = createMockEvent ( ) ;
118122 const consumer = new EventsConsumer ( [ event ] ) ;
119123 const callback = vi . fn ( ) . mockReturnValue ( EventConsumerResult . NotConsumed ) ;
120124
121125 consumer . subscribe ( callback ) ;
122126 await waitForNextTick ( ) ;
127+ await waitForNextTick ( ) ; // Extra tick to confirm no auto-advance
123128
129+ // Without auto-advance, eventIndex stays at 0
124130 expect ( consumer . eventIndex ) . toBe ( 0 ) ;
125131 expect ( consumer . callbacks ) . toContain ( callback ) ;
126132 } ) ;
127133
128- it ( 'should process multiple callbacks until one returns true ' , async ( ) => {
134+ it ( 'should process multiple callbacks until one returns Consumed or Finished ' , async ( ) => {
129135 const event = createMockEvent ( ) ;
130136 const consumer = new EventsConsumer ( [ event ] ) ;
131137 const callback1 = vi
@@ -140,15 +146,17 @@ describe('EventsConsumer', () => {
140146 consumer . subscribe ( callback2 ) ;
141147 consumer . subscribe ( callback3 ) ;
142148 await waitForNextTick ( ) ;
149+ await waitForNextTick ( ) ; // For next event processing
143150
144151 expect ( callback1 ) . toHaveBeenCalledWith ( event ) ;
145152 expect ( callback2 ) . toHaveBeenCalledWith ( event ) ;
153+ // callback3 sees the next event (null since we only have one event)
146154 expect ( callback3 ) . toHaveBeenCalledWith ( null ) ;
147155 expect ( consumer . eventIndex ) . toBe ( 1 ) ;
148156 expect ( consumer . callbacks ) . toEqual ( [ callback1 , callback3 ] ) ;
149157 } ) ;
150158
151- it ( 'should process all callbacks when none return true ' , async ( ) => {
159+ it ( 'should NOT advance when all callbacks return NotConsumed ' , async ( ) => {
152160 const event = createMockEvent ( ) ;
153161 const consumer = new EventsConsumer ( [ event ] ) ;
154162 const callback1 = vi
@@ -169,6 +177,7 @@ describe('EventsConsumer', () => {
169177 expect ( callback1 ) . toHaveBeenCalledWith ( event ) ;
170178 expect ( callback2 ) . toHaveBeenCalledWith ( event ) ;
171179 expect ( callback3 ) . toHaveBeenCalledWith ( event ) ;
180+ // Without auto-advance, eventIndex stays at 0
172181 expect ( consumer . eventIndex ) . toBe ( 0 ) ;
173182 expect ( consumer . callbacks ) . toEqual ( [ callback1 , callback2 , callback3 ] ) ;
174183 } ) ;
@@ -211,7 +220,7 @@ describe('EventsConsumer', () => {
211220 expect ( callback2 ) . toHaveBeenCalledWith ( null ) ;
212221 } ) ;
213222
214- it ( 'should handle complex event processing scenario ' , async ( ) => {
223+ it ( 'should handle complex event processing with multiple consumers ' , async ( ) => {
215224 const events = [
216225 createMockEvent ( { id : 'event-1' , event_type : 'type-a' } ) ,
217226 createMockEvent ( { id : 'event-2' , event_type : 'type-b' } ) ,
@@ -241,13 +250,14 @@ describe('EventsConsumer', () => {
241250 consumer . subscribe ( typeBCallback ) ;
242251 await waitForNextTick ( ) ;
243252 await waitForNextTick ( ) ; // Wait for recursive processing
244- await waitForNextTick ( ) ; // Wait for final processing
245253
246- // typeACallback processes event-1 and gets removed, so it won't process event-3
254+ // typeACallback processes event-1 and gets removed
247255 expect ( typeACallback ) . toHaveBeenCalledTimes ( 1 ) ; // Called for event-1 only
256+ // typeBCallback processes event-2 and gets removed
248257 expect ( typeBCallback ) . toHaveBeenCalledTimes ( 1 ) ; // Called for event-2
249- expect ( consumer . eventIndex ) . toBe ( 2 ) ; // Only 2 events processed (event-3 remains)
250- expect ( consumer . callbacks ) . toHaveLength ( 0 ) ; // Both callbacks removed after consuming their events
258+ // eventIndex is at 2 (after event-1 and event-2 were consumed)
259+ expect ( consumer . eventIndex ) . toBe ( 2 ) ;
260+ expect ( consumer . callbacks ) . toHaveLength ( 0 ) ;
251261 } ) ;
252262 } ) ;
253263
@@ -297,8 +307,9 @@ describe('EventsConsumer', () => {
297307 consumer . subscribe ( callback3 ) ;
298308 await waitForNextTick ( ) ;
299309
300- // callback2 should be removed when it returns true
310+ // callback2 should be removed when it returns Finished
301311 expect ( consumer . callbacks ) . toEqual ( [ callback1 , callback3 ] ) ;
312+ // callback3 is called with the next event (null after event-1)
302313 expect ( callback3 ) . toHaveBeenCalledWith ( null ) ;
303314 } ) ;
304315
@@ -314,25 +325,6 @@ describe('EventsConsumer', () => {
314325 expect ( consumer . eventIndex ) . toBe ( 1 ) ;
315326 } ) ;
316327
317- it ( 'should handle multiple subscriptions happening in sequence' , async ( ) => {
318- const event1 = createMockEvent ( { id : 'event-1' } ) ;
319- const event2 = createMockEvent ( { id : 'event-2' } ) ;
320- const consumer = new EventsConsumer ( [ event1 , event2 ] ) ;
321-
322- const callback1 = vi . fn ( ) . mockReturnValue ( EventConsumerResult . Finished ) ;
323- const callback2 = vi . fn ( ) . mockReturnValue ( EventConsumerResult . Finished ) ;
324-
325- consumer . subscribe ( callback1 ) ;
326- await waitForNextTick ( ) ;
327-
328- consumer . subscribe ( callback2 ) ;
329- await waitForNextTick ( ) ;
330-
331- expect ( callback1 ) . toHaveBeenCalledWith ( event1 ) ;
332- expect ( callback2 ) . toHaveBeenCalledWith ( event2 ) ;
333- expect ( consumer . eventIndex ) . toBe ( 2 ) ;
334- } ) ;
335-
336328 it ( 'should handle empty events array gracefully' , async ( ) => {
337329 const consumer = new EventsConsumer ( [ ] ) ;
338330 const callback = vi . fn ( ) . mockReturnValue ( EventConsumerResult . NotConsumed ) ;
@@ -343,5 +335,49 @@ describe('EventsConsumer', () => {
343335 expect ( callback ) . toHaveBeenCalledWith ( null ) ;
344336 expect ( consumer . eventIndex ) . toBe ( 0 ) ;
345337 } ) ;
338+
339+ it ( 'should process events in order with proper consumers' , async ( ) => {
340+ // This test simulates the workflow scenario:
341+ // - run_created consumer consumes it
342+ // - step consumer gets step_created, step_completed
343+ const events = [
344+ createMockEvent ( { id : 'run-created' , event_type : 'run_created' } ) ,
345+ createMockEvent ( { id : 'step-created' , event_type : 'step_created' } ) ,
346+ createMockEvent ( { id : 'step-completed' , event_type : 'step_completed' } ) ,
347+ ] ;
348+ const consumer = new EventsConsumer ( events ) ;
349+
350+ // Run lifecycle consumer - consumes run_created
351+ const runConsumer = vi . fn ( ) . mockImplementation ( ( event : Event | null ) => {
352+ if ( event ?. event_type === 'run_created' ) {
353+ return EventConsumerResult . Consumed ;
354+ }
355+ return EventConsumerResult . NotConsumed ;
356+ } ) ;
357+
358+ // Step consumer - consumes step_created, finishes on step_completed
359+ const stepConsumer = vi . fn ( ) . mockImplementation ( ( event : Event | null ) => {
360+ if ( event ?. event_type === 'step_created' ) {
361+ return EventConsumerResult . Consumed ;
362+ }
363+ if ( event ?. event_type === 'step_completed' ) {
364+ return EventConsumerResult . Finished ;
365+ }
366+ return EventConsumerResult . NotConsumed ;
367+ } ) ;
368+
369+ consumer . subscribe ( runConsumer ) ;
370+ consumer . subscribe ( stepConsumer ) ;
371+ await waitForNextTick ( ) ;
372+ await waitForNextTick ( ) ;
373+ await waitForNextTick ( ) ;
374+
375+ // runConsumer consumes run_created
376+ expect ( runConsumer ) . toHaveBeenCalledWith ( events [ 0 ] ) ;
377+ // stepConsumer consumes step_created, then finishes on step_completed
378+ expect ( stepConsumer ) . toHaveBeenCalledWith ( events [ 1 ] ) ;
379+ expect ( stepConsumer ) . toHaveBeenCalledWith ( events [ 2 ] ) ;
380+ expect ( consumer . eventIndex ) . toBe ( 3 ) ;
381+ } ) ;
346382 } ) ;
347383} ) ;
0 commit comments