@@ -259,6 +259,93 @@ public void LoadFromFile_ParallelMissingBranches_ThrowsInvalidOperation()
259259 }
260260 }
261261
262+ [ Fact ]
263+ public void LoadFromFile_UsePipelineStep_ParsesCorrectly ( )
264+ {
265+ var yaml = """
266+ pipeline:
267+ name: Composition Test
268+ steps:
269+ - name: Run child
270+ use_pipeline: ./child.yml
271+ inputs:
272+ source: "some value"
273+ output_key: child_result
274+ """ ;
275+
276+ var path = Path . Combine ( Path . GetTempPath ( ) , $ "test-{ Guid . NewGuid ( ) } .yaml") ;
277+ File . WriteAllText ( path , yaml ) ;
278+ try
279+ {
280+ var config = PipelineConfigLoader . LoadFromFile ( path ) ;
281+
282+ config . Steps . Should ( ) . HaveCount ( 1 ) ;
283+ config . Steps [ 0 ] . IsUsePipeline . Should ( ) . BeTrue ( ) ;
284+ config . Steps [ 0 ] . IsSimpleStep . Should ( ) . BeFalse ( ) ;
285+ config . Steps [ 0 ] . Name . Should ( ) . Be ( "Run child" ) ;
286+ config . Steps [ 0 ] . UsePipeline . Should ( ) . Be ( "./child.yml" ) ;
287+ config . Steps [ 0 ] . Inputs . Should ( ) . ContainKey ( "source" ) ;
288+ config . Steps [ 0 ] . Inputs ! [ "source" ] . Should ( ) . Be ( "some value" ) ;
289+ config . Steps [ 0 ] . OutputKey . Should ( ) . Be ( "child_result" ) ;
290+ }
291+ finally
292+ {
293+ File . Delete ( path ) ;
294+ }
295+ }
296+
297+ [ Fact ]
298+ public void LoadFromFile_UsePipelineMissingName_ThrowsInvalidOperation ( )
299+ {
300+ var yaml = """
301+ pipeline:
302+ name: Bad
303+ steps:
304+ - use_pipeline: ./child.yml
305+ """ ;
306+
307+ var path = Path . Combine ( Path . GetTempPath ( ) , $ "test-{ Guid . NewGuid ( ) } .yaml") ;
308+ File . WriteAllText ( path , yaml ) ;
309+ try
310+ {
311+ var act = ( ) => PipelineConfigLoader . LoadFromFile ( path ) ;
312+
313+ act . Should ( ) . Throw < InvalidOperationException > ( )
314+ . WithMessage ( "*missing a 'name'*" ) ;
315+ }
316+ finally
317+ {
318+ File . Delete ( path ) ;
319+ }
320+ }
321+
322+ [ Fact ]
323+ public void LoadFromFile_UsePipelineWithOptional_ParsesCorrectly ( )
324+ {
325+ var yaml = """
326+ pipeline:
327+ name: Optional Test
328+ steps:
329+ - name: Optional child
330+ use_pipeline: ./child.yml
331+ optional: true
332+ """ ;
333+
334+ var path = Path . Combine ( Path . GetTempPath ( ) , $ "test-{ Guid . NewGuid ( ) } .yaml") ;
335+ File . WriteAllText ( path , yaml ) ;
336+ try
337+ {
338+ var config = PipelineConfigLoader . LoadFromFile ( path ) ;
339+
340+ config . Steps [ 0 ] . IsUsePipeline . Should ( ) . BeTrue ( ) ;
341+ config . Steps [ 0 ] . Optional . Should ( ) . BeTrue ( ) ;
342+ }
343+ finally
344+ {
345+ File . Delete ( path ) ;
346+ }
347+ }
348+
262349 [ Fact ]
263350 public void LoadFromFile_WithInputsAndOutputs_ParsesCorrectly ( )
264351 {
0 commit comments