@@ -272,7 +272,35 @@ func (s bySceStatus) Swap(i, j int) {
272272}
273273
274274func (s bySceStatus ) Less (i , j int ) bool {
275- return getSceState (s [i ]) < getSceState (s [j ])
275+ // If both scenarios are scenario-table-driven with the same heading, maintain their order by row index
276+ if s [i ].IsScenarioTableDriven && s [j ].IsScenarioTableDriven && s [i ].Heading == s [j ].Heading {
277+ return s [i ].ScenarioTableRowIndex < s [j ].ScenarioTableRowIndex
278+ }
279+
280+ stateI := s .getEffectiveState (i )
281+ stateJ := s .getEffectiveState (j )
282+
283+ return stateI < stateJ
284+ }
285+
286+ // getEffectiveState returns the worst state for a scenario, when the scenario is scenario-table-driven.
287+ func (s bySceStatus ) getEffectiveState (index int ) int {
288+ scenario := s [index ]
289+
290+ if ! scenario .IsScenarioTableDriven {
291+ return getSceState (scenario )
292+ }
293+
294+ worstState := getSceState (scenario )
295+ for _ , otherScenario := range s {
296+ if otherScenario .IsScenarioTableDriven && otherScenario .Heading == scenario .Heading {
297+ state := getSceState (otherScenario )
298+ if state < worstState {
299+ worstState = state
300+ }
301+ }
302+ }
303+ return worstState
276304}
277305
278306func getSceState (s * scenario ) int {
@@ -366,9 +394,14 @@ func toSpec(res *gm.ProtoSpecResult, projectRoot string) *spec {
366394 spec .Datatable = toTable (item .GetTable ())
367395 isTableScanned = true
368396 case gm .ProtoItem_Scenario :
369- spec .Scenarios = append (spec .Scenarios , toScenario (item .GetScenario (), - 1 ))
397+ spec .Scenarios = append (spec .Scenarios , toScenario (item .GetScenario (), - 1 , nil ))
370398 case gm .ProtoItem_TableDrivenScenario :
371- spec .Scenarios = append (spec .Scenarios , toScenario (item .GetTableDrivenScenario ().GetScenario (), int (item .GetTableDrivenScenario ().GetTableRowIndex ())))
399+ tableDrivenScenario := item .GetTableDrivenScenario ()
400+ if tableDrivenScenario .GetIsScenarioTableDriven () && ! tableDrivenScenario .GetIsSpecTableDriven () {
401+ spec .Scenarios = append (spec .Scenarios , toScenario (tableDrivenScenario .GetScenario (), - 1 , tableDrivenScenario ))
402+ } else {
403+ spec .Scenarios = append (spec .Scenarios , toScenario (tableDrivenScenario .GetScenario (), int (item .TableDrivenScenario .GetTableRowIndex ()), tableDrivenScenario ))
404+ }
372405 }
373406 }
374407 for _ , preHookFailure := range res .GetProtoSpec ().GetPreHookFailures () {
@@ -381,11 +414,12 @@ func toSpec(res *gm.ProtoSpecResult, projectRoot string) *spec {
381414 if res .GetProtoSpec ().GetIsTableDriven () && isTableScanned {
382415 computeTableDrivenStatuses (spec )
383416 }
417+ computeScenarioTableStatuses (spec )
384418 p , f , s := computeScenarioStatistics (spec )
385419 spec .PassedScenarioCount = p
386420 spec .FailedScenarioCount = f
387421 spec .SkippedScenarioCount = s
388- sort .Sort (bySceStatus (spec .Scenarios ))
422+ sort .Stable (bySceStatus (spec .Scenarios ))
389423 return spec
390424}
391425
@@ -428,6 +462,9 @@ func hasParseErrors(errors []*gm.Error) bool {
428462}
429463
430464func computeTableDrivenStatuses (spec * spec ) {
465+ if spec .Datatable == nil || len (spec .Datatable .Rows ) == 0 {
466+ return
467+ }
431468 for _ , r := range spec .Datatable .Rows {
432469 r .Result = skip
433470 }
@@ -453,13 +490,47 @@ func SetRowFailures(failures []*hookFailure, spec *spec) {
453490 }
454491}
455492
493+ func computeScenarioTableStatuses (spec * spec ) {
494+ // Group scenarios, key: scenario heading, value: scenarios with same table
495+ scenarioTables := make (map [string ][]* scenario )
496+ for _ , s := range spec .Scenarios {
497+ if s .IsScenarioTableDriven {
498+ key := s .Heading
499+ scenarioTables [key ] = append (scenarioTables [key ], s )
500+ }
501+ }
502+ // Update row statuses based on scenario execution results
503+ for _ , scenarios := range scenarioTables {
504+ if len (scenarios ) == 0 || scenarios [0 ].ScenarioDataTable == nil {
505+ continue
506+ }
507+ table := scenarios [0 ].ScenarioDataTable
508+ for _ , s := range scenarios {
509+ if s .ScenarioTableRowIndex >= 0 && s .ScenarioTableRowIndex < len (table .Rows ) {
510+ row := table .Rows [s .ScenarioTableRowIndex ]
511+ row .Result = s .ExecutionStatus
512+ if s .BeforeScenarioHookFailure != nil {
513+ row .Result = fail
514+ }
515+ if s .AfterScenarioHookFailure != nil {
516+ row .Result = fail
517+ }
518+ }
519+ }
520+ // Clear table reference for all subsequent scenarios to prevent duplicate table rendering in template
521+ for i := 1 ; i < len (scenarios ); i ++ {
522+ scenarios [i ].ScenarioDataTable = nil
523+ }
524+ }
525+ }
526+
456527func toScenarioSummary (s * spec ) * summary {
457528 var sum = summary {Failed : s .FailedScenarioCount , Passed : s .PassedScenarioCount , Skipped : s .SkippedScenarioCount }
458529 sum .Total = sum .Failed + sum .Passed + sum .Skipped
459530 return & sum
460531}
461532
462- func toScenario (scn * gm.ProtoScenario , tableRowIndex int ) * scenario {
533+ func toScenario (scn * gm.ProtoScenario , tableRowIndex int , tableDrivenScenario * gm. ProtoTableDrivenScenario ) * scenario {
463534 scenario := & scenario {
464535 Heading : scn .GetScenarioHeading (),
465536 ExecutionTime : formatTime (scn .GetExecutionTime ()),
@@ -475,6 +546,12 @@ func toScenario(scn *gm.ProtoScenario, tableRowIndex int) *scenario {
475546 PostHookMessages : scn .GetPostHookMessages (),
476547 RetriesCount : int (scn .RetriesCount ),
477548 }
549+ if tableDrivenScenario .GetIsScenarioTableDriven () {
550+ scenario .IsScenarioTableDriven = tableDrivenScenario .GetIsScenarioTableDriven ()
551+ scenario .ScenarioTableRowIndex = int (tableDrivenScenario .GetScenarioTableRowIndex ())
552+ scenario .ScenarioDataTable = toTable (tableDrivenScenario .GetScenarioDataTable ())
553+ scenario .ScenarioTableRow = toTable (tableDrivenScenario .GetScenarioTableRow ())
554+ }
478555 for _ , s := range scn .GetPreHookScreenshotFiles () {
479556 scenario .PreHookScreenshotFiles = append (scenario .PreHookScreenshotFiles , s )
480557 screenshotFiles = append (screenshotFiles , s )
0 commit comments