Skip to content

Commit 45d70ce

Browse files
taylordowns2000josephjclark
authored andcommitted
moar
1 parent 831b8ac commit 45d70ce

1 file changed

Lines changed: 77 additions & 0 deletions

File tree

packages/ws-worker/test/events/step-complete.test.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,23 @@ test('track leaf dataclip when step has no downstream jobs', async (t) => {
301301
t.is(state.leafDataclipIds.length, 1);
302302
});
303303

304+
test('track leaf dataclip when step has undefined next', async (t) => {
305+
const plan = createPlan();
306+
307+
const state = createRunState(plan);
308+
state.activeJob = 'job-1';
309+
state.activeStep = 'b';
310+
311+
const channel = mockChannel({
312+
[STEP_COMPLETE]: () => true,
313+
});
314+
315+
const event = { state: { x: 10 } } as any;
316+
await handleStepComplete({ channel, state } as any, event);
317+
318+
t.is(state.leafDataclipIds.length, 1);
319+
});
320+
304321
test('do not track leaf dataclip when step has downstream jobs', async (t) => {
305322
const plan = createPlan();
306323

@@ -317,3 +334,63 @@ test('do not track leaf dataclip when step has downstream jobs', async (t) => {
317334

318335
t.is(state.leafDataclipIds.length, 0);
319336
});
337+
338+
// Multiple leaf nodes: start → job-a (leaf), start → job-b (leaf)
339+
test('accumulate multiple leaf dataclips for branching workflow', async (t) => {
340+
const plan = createPlan();
341+
const state = createRunState(plan);
342+
343+
const channel = mockChannel({
344+
[STEP_COMPLETE]: () => true,
345+
});
346+
347+
// First leaf completes
348+
state.activeJob = 'job-a';
349+
state.activeStep = 'step-a';
350+
await handleStepComplete(
351+
{ channel, state } as any,
352+
{ state: { a: true }, next: [] } as any
353+
);
354+
355+
// Second leaf completes
356+
state.activeJob = 'job-b';
357+
state.activeStep = 'step-b';
358+
await handleStepComplete(
359+
{ channel, state } as any,
360+
{ state: { b: true }, next: [] } as any
361+
);
362+
363+
t.is(state.leafDataclipIds.length, 2);
364+
// Each leaf gets a distinct dataclip id
365+
t.not(state.leafDataclipIds[0], state.leafDataclipIds[1]);
366+
});
367+
368+
// Single leaf reached by two paths: start → a → x, start → b → x
369+
// x executes twice, both times with no downstream
370+
test('accumulate two leaf dataclips when same node reached by two paths', async (t) => {
371+
const plan = createPlan();
372+
const state = createRunState(plan);
373+
374+
const channel = mockChannel({
375+
[STEP_COMPLETE]: () => true,
376+
});
377+
378+
// x completes first time (via path a)
379+
state.activeJob = 'job-x';
380+
state.activeStep = 'step-x';
381+
await handleStepComplete(
382+
{ channel, state } as any,
383+
{ state: { from: 'a' }, next: [] } as any
384+
);
385+
386+
// x completes second time (via path b)
387+
state.activeJob = 'job-x';
388+
state.activeStep = 'step-x-1';
389+
await handleStepComplete(
390+
{ channel, state } as any,
391+
{ state: { from: 'b' }, next: [] } as any
392+
);
393+
394+
t.is(state.leafDataclipIds.length, 2);
395+
t.not(state.leafDataclipIds[0], state.leafDataclipIds[1]);
396+
});

0 commit comments

Comments
 (0)