@@ -2522,11 +2522,81 @@ describe('runSteps', () => {
25222522 // timestamps come from RunStepDto.createdAt
25232523 expect ( first . capturedAt ) . toBe ( '2026-06-01T10:00:05.000Z' ) ;
25242524 expect ( first . updatedAt ) . toBe ( '2026-06-01T10:00:05.000Z' ) ;
2525+ expect ( first . stepType ) . toBe ( 'action' ) ;
2526+ expect ( first . error ) . toBeNull ( ) ;
25252527 // outcomeContributesToFailure: null when run passed (failedStepIndex is null)
25262528 expect ( first . outcomeContributesToFailure ) . toBeNull ( ) ;
25272529 // JSON output should be parseable with 2 items
2528- const printed = JSON . parse ( out [ 0 ] ! ) as { items : unknown [ ] } ;
2530+ const printed = JSON . parse ( out [ 0 ] ! ) as {
2531+ items : Array < { stepType ?: string ; error ?: string | null } > ;
2532+ } ;
25292533 expect ( printed . items ) . toHaveLength ( 2 ) ;
2534+ expect ( printed . items [ 0 ] ! . stepType ) . toBe ( 'action' ) ;
2535+ expect ( printed . items [ 0 ] ! . error ) . toBeNull ( ) ;
2536+ } ) ;
2537+
2538+ it ( '--run-id preserves per-step error text in JSON output' , async ( ) => {
2539+ const { credentialsPath } = makeCreds ( ) ;
2540+ const runWithStepError = {
2541+ ...RUN_WITH_STEPS ,
2542+ status : 'failed' as const ,
2543+ failedStepIndex : 2 ,
2544+ stepSummary : { total : 2 , completed : 2 , passedCount : 1 , failedCount : 1 } ,
2545+ steps : RUN_WITH_STEPS . steps . map ( step =>
2546+ step . stepIndex === '0002'
2547+ ? {
2548+ ...step ,
2549+ status : 'failed' as const ,
2550+ error : 'AssertionError: expected heading to be visible' ,
2551+ }
2552+ : step ,
2553+ ) ,
2554+ } ;
2555+ const fetchImpl = makeFetch ( ( ) => ( { body : runWithStepError } ) ) ;
2556+ const out : string [ ] = [ ] ;
2557+
2558+ await runSteps (
2559+ { profile : 'default' , output : 'json' , debug : false , testId : 'test_fe' , runId : 'run_scoped' } ,
2560+ { credentialsPath, fetchImpl, stdout : line => out . push ( line ) } ,
2561+ ) ;
2562+
2563+ const printed = JSON . parse ( out [ 0 ] ! ) as {
2564+ items : Array < { stepIndex : number ; stepType ?: string ; error ?: string | null } > ;
2565+ } ;
2566+ const failedStep = printed . items . find ( step => step . stepIndex === 2 ) ! ;
2567+ expect ( failedStep . stepType ) . toBe ( 'assertion' ) ;
2568+ expect ( failedStep . error ) . toBe ( 'AssertionError: expected heading to be visible' ) ;
2569+ } ) ;
2570+
2571+ it ( '--run-id prints per-step error text under failed rows in text mode' , async ( ) => {
2572+ const { credentialsPath } = makeCreds ( ) ;
2573+ const runWithStepError = {
2574+ ...RUN_WITH_STEPS ,
2575+ status : 'failed' as const ,
2576+ failedStepIndex : 2 ,
2577+ stepSummary : { total : 2 , completed : 2 , passedCount : 1 , failedCount : 1 } ,
2578+ steps : RUN_WITH_STEPS . steps . map ( step =>
2579+ step . stepIndex === '0002'
2580+ ? {
2581+ ...step ,
2582+ status : 'failed' as const ,
2583+ error : 'AssertionError: expected heading to be visible' ,
2584+ }
2585+ : step ,
2586+ ) ,
2587+ } ;
2588+ const fetchImpl = makeFetch ( ( ) => ( { body : runWithStepError } ) ) ;
2589+ const out : string [ ] = [ ] ;
2590+
2591+ await runSteps (
2592+ { profile : 'default' , output : 'text' , debug : false , testId : 'test_fe' , runId : 'run_scoped' } ,
2593+ { credentialsPath, fetchImpl, stdout : line => out . push ( line ) } ,
2594+ ) ;
2595+
2596+ const block = out . join ( '\n' ) ;
2597+ expect ( block ) . toContain ( 'assert heading' ) ;
2598+ expect ( block ) . toContain ( 'failed' ) ;
2599+ expect ( block ) . toContain ( ' error: AssertionError: expected heading to be visible' ) ;
25302600 } ) ;
25312601
25322602 it ( '--run-id: outcomeContributesToFailure=true on the failedStepIndex step' , async ( ) => {
0 commit comments