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 }