github.com/getgauge/gauge@v1.6.9/parser/dataTableSpecs.go (about)

     1  /*----------------------------------------------------------------
     2   *  Copyright (c) ThoughtWorks, Inc.
     3   *  Licensed under the Apache License, Version 2.0
     4   *  See LICENSE in the project root for license information.
     5   *----------------------------------------------------------------*/
     6  
     7  package parser
     8  
     9  import (
    10  	"github.com/getgauge/gauge/env"
    11  	"github.com/getgauge/gauge/gauge"
    12  )
    13  
    14  // GetSpecsForDataTableRows creates a spec for each data table row
    15  func GetSpecsForDataTableRows(s []*gauge.Specification, errMap *gauge.BuildErrors) (specs []*gauge.Specification) {
    16  	for _, spec := range s {
    17  		if spec.DataTable.IsInitialized() {
    18  			if spec.UsesArgsInContextTeardown(spec.DataTable.Table.Headers...) {
    19  				specs = append(specs, createSpecsForTableRows(spec, spec.Scenarios, errMap)...)
    20  			} else {
    21  				nonTableRelatedScenarios, tableRelatedScenarios := FilterTableRelatedScenarios(spec.Scenarios, func(scenario *gauge.Scenario) bool {
    22  					return scenario.UsesArgsInSteps(spec.DataTable.Table.Headers...)
    23  				})
    24  				if len(tableRelatedScenarios) > 0 {
    25  					s := createSpecsForTableRows(spec, tableRelatedScenarios, errMap)
    26  					s[0].Scenarios = append(s[0].Scenarios, nonTableRelatedScenarios...)
    27  					for _, scn := range nonTableRelatedScenarios { // nolint
    28  						s[0].Items = append(s[0].Items, scn)
    29  					}
    30  					specs = append(specs, s...)
    31  				} else {
    32  					specs = append(specs, createSpec(copyScenarios(nonTableRelatedScenarios, gauge.Table{}, 0, errMap), &gauge.Table{}, spec, errMap))
    33  				}
    34  			}
    35  		} else {
    36  			specs = append(specs, createSpec(copyScenarios(spec.Scenarios, gauge.Table{}, 0, errMap), &gauge.Table{}, spec, errMap))
    37  		}
    38  	}
    39  	return
    40  }
    41  
    42  func createSpecsForTableRows(spec *gauge.Specification, scns []*gauge.Scenario, errMap *gauge.BuildErrors) (specs []*gauge.Specification) {
    43  	for i := range spec.DataTable.Table.Rows() {
    44  		t := getTableWithOneRow(spec.DataTable.Table, i)
    45  		newSpec := createSpec(copyScenarios(scns, *t, i, errMap), t, spec, errMap)
    46  		specs = append(specs, newSpec)
    47  	}
    48  	return
    49  }
    50  
    51  func createSpec(scns []*gauge.Scenario, table *gauge.Table, spec *gauge.Specification, errMap *gauge.BuildErrors) *gauge.Specification {
    52  	dt := &gauge.DataTable{Table: table, Value: spec.DataTable.Value, LineNo: spec.DataTable.LineNo, IsExternal: spec.DataTable.IsExternal}
    53  	s := &gauge.Specification{DataTable: *dt, FileName: spec.FileName, Heading: spec.Heading, Scenarios: scns, Contexts: spec.Contexts, TearDownSteps: spec.TearDownSteps, Tags: spec.Tags}
    54  	index := 0
    55  	for _, item := range spec.Items {
    56  		if item.Kind() == gauge.DataTableKind {
    57  			item = dt
    58  		} else if item.Kind() == gauge.ScenarioKind {
    59  			if len(scns) <= index {
    60  				continue
    61  			}
    62  			item = scns[index]
    63  			index++
    64  		}
    65  		s.Items = append(s.Items, item)
    66  	}
    67  	for i := index; i < len(scns); i++ {
    68  		s.Items = append(s.Items, scns[i])
    69  	}
    70  	if len(errMap.SpecErrs[spec]) > 0 {
    71  		errMap.SpecErrs[s] = errMap.SpecErrs[spec]
    72  	}
    73  	return s
    74  }
    75  
    76  func copyScenarios(scenarios []*gauge.Scenario, table gauge.Table, i int, errMap *gauge.BuildErrors) (scns []*gauge.Scenario) {
    77  	var create = func(scn *gauge.Scenario, scnTableRow gauge.Table, scnTableRowIndex int) *gauge.Scenario {
    78  		newScn := &gauge.Scenario{
    79  			Steps:                 scn.Steps,
    80  			Items:                 scn.Items,
    81  			Heading:               scn.Heading,
    82  			SpecDataTableRow:      table,
    83  			SpecDataTableRowIndex: i,
    84  			Tags:                  scn.Tags,
    85  			Comments:              scn.Comments,
    86  			Span:                  scn.Span,
    87  		}
    88  		if scnTableRow.IsInitialized() {
    89  			newScn.ScenarioDataTableRow = scnTableRow
    90  			newScn.ScenarioDataTableRowIndex = scnTableRowIndex
    91  		}
    92  		if len(errMap.ScenarioErrs[scn]) > 0 {
    93  			errMap.ScenarioErrs[newScn] = errMap.ScenarioErrs[scn]
    94  		}
    95  		return newScn
    96  	}
    97  	for _, scn := range scenarios {
    98  		if scn.DataTable.IsInitialized() && env.AllowScenarioDatatable() {
    99  			for i := range scn.DataTable.Table.Rows() {
   100  				t := getTableWithOneRow(scn.DataTable.Table, i)
   101  				scns = append(scns, create(scn, *t, i))
   102  			}
   103  		} else {
   104  			scns = append(scns, create(scn, gauge.Table{}, 0))
   105  		}
   106  	}
   107  	return
   108  }
   109  
   110  func getTableWithOneRow(t *gauge.Table, i int) *gauge.Table {
   111  	var row [][]gauge.TableCell
   112  	for _, c := range t.Columns {
   113  		row = append(row, []gauge.TableCell{c[i]})
   114  	}
   115  	return gauge.NewTable(t.Headers, row, t.LineNo)
   116  }
   117  
   118  // FilterTableRelatedScenarios filters Scenarios that are using dynamic params from data table.
   119  func FilterTableRelatedScenarios(scenarios []*gauge.Scenario, fun func(*gauge.Scenario) bool) (otherScenarios, tableRelatedScenarios []*gauge.Scenario) {
   120  	for _, scenario := range scenarios {
   121  		if fun(scenario) {
   122  			tableRelatedScenarios = append(tableRelatedScenarios, scenario)
   123  		} else {
   124  			otherScenarios = append(otherScenarios, scenario)
   125  		}
   126  	}
   127  	return
   128  }