@@ -8,17 +8,43 @@ import { RUN_COMPLETE, RUN_LOG } from '../../src/events';
88import { createRunState } from '../../src/util' ;
99import { createPlan } from '../util' ;
1010
11- test ( 'should send a run:complete event' , async ( t ) => {
11+ test ( 'should send a run:complete event with final_dataclip_id for single leaf ' , async ( t ) => {
1212 const result = { answer : 42 } ;
1313 const plan = createPlan ( ) ;
1414
1515 const state = createRunState ( plan ) ;
16+ state . leafDataclipIds = [ 'clip-1' ] ;
17+
18+ const channel = mockChannel ( {
19+ [ RUN_LOG ] : ( ) => true ,
20+ [ RUN_COMPLETE ] : ( evt ) => {
21+ t . is ( evt . final_dataclip_id , 'clip-1' ) ;
22+ t . falsy ( evt . final_state ) ;
23+ t . falsy ( evt . time ) ;
24+ } ,
25+ } ) ;
26+
27+ const event : any = { state : result } ;
28+
29+ const context : any = { channel, state, onFinish : ( ) => { } } ;
30+ await handleRunComplete ( context , event ) ;
31+ } ) ;
32+
33+ test ( 'should send final_state when there are multiple leaves' , async ( t ) => {
34+ const result = {
35+ 'job-a' : { data : { a : true } } ,
36+ 'job-b' : { data : { b : true } } ,
37+ } ;
38+ const plan = createPlan ( ) ;
39+
40+ const state = createRunState ( plan ) ;
41+ state . leafDataclipIds = [ 'clip-1' , 'clip-2' ] ;
1642
1743 const channel = mockChannel ( {
1844 [ RUN_LOG ] : ( ) => true ,
1945 [ RUN_COMPLETE ] : ( evt ) => {
2046 t . deepEqual ( evt . final_state , result ) ;
21- t . falsy ( evt . time ) ; // if no timestamp in the engine event, no timestamp in the worker one
47+ t . falsy ( evt . final_dataclip_id ) ;
2248 } ,
2349 } ) ;
2450
@@ -240,9 +266,11 @@ test('should call onFinish even if the lightning event timesout', async (t) => {
240266 await handleRunComplete ( context , event ) ;
241267} ) ;
242268
243- test ( 'should send final_state for a linear workflow' , async ( t ) => {
269+ test ( 'should send final_dataclip_id for a single-leaf workflow' , async ( t ) => {
244270 const plan = createPlan ( ) ;
245271 const state = createRunState ( plan ) ;
272+ state . leafDataclipIds = [ 'abc-123' ] ;
273+
246274 const finalResult = { data : { count : 100 } , references : [ ] } ;
247275
248276 let completeEvent : any ;
@@ -264,15 +292,16 @@ test('should send final_state for a linear workflow', async (t) => {
264292
265293 await handleRunComplete ( context , event ) ;
266294
267- t . deepEqual ( completeEvent . final_state , finalResult ) ;
295+ t . is ( completeEvent . final_dataclip_id , 'abc-123' ) ;
296+ t . falsy ( completeEvent . final_state ) ;
268297 t . is ( completeEvent . reason , 'success' ) ;
269298} ) ;
270299
271300test ( 'should send final_state for a branching workflow with multiple leaf nodes' , async ( t ) => {
272301 const plan = createPlan ( ) ;
273302 const state = createRunState ( plan ) ;
303+ state . leafDataclipIds = [ 'clip-1' , 'clip-2' , 'clip-3' ] ;
274304
275- // Simulate a branching workflow with multiple final states
276305 const branchedResult = {
277306 'job-1' : { data : { path : 'A' , value : 42 } } ,
278307 'job-2' : { data : { path : 'B' , value : 84 } } ,
@@ -292,7 +321,6 @@ test('should send final_state for a branching workflow with multiple leaf nodes'
292321 channel,
293322 state,
294323 onFinish : ( { state : finalState } : any ) => {
295- // Verify that onFinish receives the branched result
296324 t . deepEqual ( finalState , branchedResult ) ;
297325 } ,
298326 } ;
@@ -301,33 +329,18 @@ test('should send final_state for a branching workflow with multiple leaf nodes'
301329
302330 await handleRunComplete ( context , event ) ;
303331
304- // Verify the event contains the full branched state structure
305332 t . deepEqual ( completeEvent . final_state , branchedResult ) ;
333+ t . falsy ( completeEvent . final_dataclip_id ) ;
306334 t . is ( completeEvent . reason , 'success' ) ;
307- t . truthy ( completeEvent . final_state [ 'job-1' ] ) ;
308- t . truthy ( completeEvent . final_state [ 'job-2' ] ) ;
309- t . truthy ( completeEvent . final_state [ 'job-3' ] ) ;
310335} ) ;
311336
312- test ( 'should properly serialize final_state as JSON ' , async ( t ) => {
337+ test ( 'should send final_state when single leaf dataclip was withheld ' , async ( t ) => {
313338 const plan = createPlan ( ) ;
314339 const state = createRunState ( plan ) ;
340+ state . leafDataclipIds = [ 'clip-1' ] ;
341+ state . withheldDataclips = { 'clip-1' : true } ;
315342
316- // Test with complex state including nested objects, arrays, and special values
317- const complexState = {
318- data : {
319- users : [
320- { id : 1 , name : 'Alice' } ,
321- { id : 2 , name : 'Bob' } ,
322- ] ,
323- metadata : {
324- timestamp : new Date ( '2024-01-01' ) . toISOString ( ) ,
325- nested : { deeply : { value : 42 } } ,
326- } ,
327- } ,
328- configuration : { setting : true } ,
329- references : [ ] ,
330- } ;
343+ const result = { data : { big : 'data' } } ;
331344
332345 let completeEvent : any ;
333346
@@ -344,28 +357,23 @@ test('should properly serialize final_state as JSON', async (t) => {
344357 onFinish : ( ) => { } ,
345358 } ;
346359
347- const event : any = { state : complexState } ;
360+ const event : any = { state : result } ;
348361
349362 await handleRunComplete ( context , event ) ;
350363
351- // Verify the state is properly preserved
352- t . deepEqual ( completeEvent . final_state , complexState ) ;
353- t . deepEqual ( completeEvent . final_state . data . users [ 0 ] , { id : 1 , name : 'Alice' } ) ;
354- t . is ( completeEvent . final_state . data . metadata . nested . deeply . value , 42 ) ;
355-
356- // Verify it can be stringified (simulating what happens when sent over the wire)
357- const jsonString = JSON . stringify ( completeEvent . final_state ) ;
358- const parsed = JSON . parse ( jsonString ) ;
359- t . deepEqual ( parsed , complexState ) ;
364+ t . deepEqual ( completeEvent . final_state , result ) ;
365+ t . falsy ( completeEvent . final_dataclip_id ) ;
360366} ) ;
361367
362- test ( 'should handle Uint8Array in final_state ' , async ( t ) => {
368+ test ( 'should send final_state when a single leaf node is reached by two paths ' , async ( t ) => {
363369 const plan = createPlan ( ) ;
364370 const state = createRunState ( plan ) ;
371+ // Same node executed twice via different paths produces two leaf dataclips
372+ state . leafDataclipIds = [ 'clip-1' , 'clip-2' ] ;
365373
366- // Test with Uint8Array which needs special handling
367- const stateWithBinary = {
368- data : { buffer : new Uint8Array ( [ 1 , 2 , 3 , 4 , 5 ] ) } ,
374+ const result = {
375+ x : { data : { from : 'a' } } ,
376+ 'x-1' : { data : { from : 'b' } } ,
369377 } ;
370378
371379 let completeEvent : any ;
@@ -383,10 +391,10 @@ test('should handle Uint8Array in final_state', async (t) => {
383391 onFinish : ( ) => { } ,
384392 } ;
385393
386- const event : any = { state : stateWithBinary } ;
394+ const event : any = { state : result } ;
387395
388396 await handleRunComplete ( context , event ) ;
389397
390- // Verify the Uint8Array is preserved in the event
391- t . deepEqual ( completeEvent . final_state . data . buffer , new Uint8Array ( [ 1 , 2 , 3 , 4 , 5 ] ) ) ;
398+ t . deepEqual ( completeEvent . final_state , result ) ;
399+ t . falsy ( completeEvent . final_dataclip_id ) ;
392400} ) ;
0 commit comments