github.com/getgauge/gauge@v1.6.9/parser/specparser_test.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  	"path/filepath"
    11  	"strings"
    12  	"testing"
    13  
    14  	"github.com/getgauge/gauge/env"
    15  	"github.com/getgauge/gauge/gauge"
    16  
    17  	. "gopkg.in/check.v1"
    18  )
    19  
    20  // Hook up gocheck into the "go test" runner.
    21  func Test(t *testing.T) { TestingT(t) }
    22  
    23  type MySuite struct{}
    24  
    25  var _ = Suite(&MySuite{})
    26  
    27  func (s *MySuite) TestToCheckTagsInSpecLevel(c *C) {
    28  	tokens := []*Token{
    29  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
    30  		{Kind: gauge.TagKind, Args: []string{"tag1", "tag2"}, LineNo: 2},
    31  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 3},
    32  		{Kind: gauge.StepKind, Value: "my step"},
    33  	}
    34  
    35  	spec, result, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
    36  	c.Assert(err, IsNil)
    37  	c.Assert(result.Ok, Equals, true)
    38  
    39  	c.Assert(len(spec.Tags.Values()), Equals, 2)
    40  	c.Assert(spec.Tags.Values()[0], Equals, "tag1")
    41  	c.Assert(spec.Tags.Values()[1], Equals, "tag2")
    42  }
    43  
    44  func (s *MySuite) TestToCheckTagsInScenarioLevel(c *C) {
    45  	tokens := []*Token{
    46  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
    47  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 2},
    48  		{Kind: gauge.TagKind, Args: []string{"tag1", "tag2"}, LineNo: 3},
    49  		{Kind: gauge.StepKind, Value: "my step"},
    50  	}
    51  
    52  	spec, result, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
    53  	c.Assert(err, IsNil)
    54  	c.Assert(result.Ok, Equals, true)
    55  
    56  	c.Assert(len(spec.Scenarios[0].Tags.Values()), Equals, 2)
    57  	c.Assert(spec.Scenarios[0].Tags.Values()[0], Equals, "tag1")
    58  	c.Assert(spec.Scenarios[0].Tags.Values()[1], Equals, "tag2")
    59  }
    60  
    61  func (s *MySuite) TestParsingConceptInSpec(c *C) {
    62  	parser := new(SpecParser)
    63  	specText := newSpecBuilder().specHeading("A spec heading").
    64  		scenarioHeading("First flow").
    65  		step("test concept step 1").
    66  		step("another step").String()
    67  	conceptDictionary := gauge.NewConceptDictionary()
    68  	path, _ := filepath.Abs(filepath.Join("testdata", "concept.cpt"))
    69  	_, _, err := AddConcepts([]string{path}, conceptDictionary)
    70  	c.Assert(err, IsNil)
    71  	tokens, errs := parser.GenerateTokens(specText, "")
    72  	c.Assert(errs, IsNil)
    73  	spec, parseResult, e := parser.CreateSpecification(tokens, conceptDictionary, "")
    74  	c.Assert(e, IsNil)
    75  	c.Assert(parseResult.Ok, Equals, true)
    76  	firstStepInSpec := spec.Scenarios[0].Steps[0]
    77  	secondStepInSpec := spec.Scenarios[0].Steps[1]
    78  	c.Assert(firstStepInSpec.ConceptSteps[0].Parent, Equals, firstStepInSpec)
    79  	c.Assert(firstStepInSpec.Parent, IsNil)
    80  	c.Assert(secondStepInSpec.Parent, IsNil)
    81  }
    82  
    83  func (s *MySuite) TestTableInputFromInvalidFileAndDataTableNotInitialized(c *C) {
    84  	parser := new(SpecParser)
    85  	specText := newSpecBuilder().specHeading("Spec heading").text("table: inputinvalid.csv").text("comment").scenarioHeading("Sce heading").step("my step").String()
    86  
    87  	_, parseRes, err := parser.Parse(specText, gauge.NewConceptDictionary(), "")
    88  	c.Assert(err, IsNil)
    89  	c.Assert(parseRes.ParseErrors[0].Message, Equals, "Could not resolve table. File inputinvalid.csv doesn't exist.")
    90  	c.Assert(parseRes.Ok, Equals, false)
    91  }
    92  
    93  func (s *MySuite) TestTableInputFromFile(c *C) {
    94  	parser := new(SpecParser)
    95  	specText := newSpecBuilder().specHeading("Spec heading").text("Table: inputinvalid.csv").text("comment").scenarioHeading("Sce heading").step("my step").String()
    96  
    97  	_, parseRes, err := parser.Parse(specText, gauge.NewConceptDictionary(), "")
    98  	c.Assert(err, IsNil)
    99  	c.Assert(parseRes.ParseErrors[0].Message, Equals, "Could not resolve table. File inputinvalid.csv doesn't exist.")
   100  	c.Assert(parseRes.Ok, Equals, false)
   101  }
   102  
   103  func (s *MySuite) TestTableInputFromFileIfPathNotSpecified(c *C) {
   104  	parser := new(SpecParser)
   105  	specText := newSpecBuilder().specHeading("Spec heading").text("Table: ").scenarioHeading("Sce heading").step("my step").String()
   106  
   107  	_, parseRes, err := parser.Parse(specText, gauge.NewConceptDictionary(), "")
   108  	c.Assert(err, IsNil)
   109  	c.Assert(parseRes.ParseErrors[0].Message, Equals, "Table location not specified")
   110  	c.Assert(parseRes.Ok, Equals, false)
   111  }
   112  
   113  func (s *MySuite) TestToSplitTagNames(c *C) {
   114  	allTags := splitAndTrimTags("tag1 , tag2,   tag3")
   115  	c.Assert(allTags[0], Equals, "tag1")
   116  	c.Assert(allTags[1], Equals, "tag2")
   117  	c.Assert(allTags[2], Equals, "tag3")
   118  }
   119  
   120  func (s *MySuite) TestThrowsErrorForMultipleSpecHeading(c *C) {
   121  	tokens := []*Token{
   122  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
   123  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 2},
   124  		{Kind: gauge.StepKind, Value: "Example step", LineNo: 3},
   125  		{Kind: gauge.SpecKind, Value: "Another Heading", LineNo: 4},
   126  	}
   127  
   128  	_, result, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
   129  	c.Assert(err, IsNil)
   130  	c.Assert(result.Ok, Equals, false)
   131  
   132  	c.Assert(result.ParseErrors[0].Message, Equals, "Multiple spec headings found in same file")
   133  	c.Assert(result.ParseErrors[0].LineNo, Equals, 4)
   134  }
   135  
   136  func (s *MySuite) TestThrowsErrorForScenarioWithoutSpecHeading(c *C) {
   137  	tokens := []*Token{
   138  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 1},
   139  		{Kind: gauge.StepKind, Value: "Example step", LineNo: 2},
   140  		{Kind: gauge.CommentKind, Value: "Comment", LineNo: 3},
   141  	}
   142  
   143  	_, result, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
   144  	c.Assert(err, IsNil)
   145  	c.Assert(result.Ok, Equals, false)
   146  	c.Assert(len(result.ParseErrors), Equals, 2)
   147  
   148  	c.Assert(result.ParseErrors[0].Message, Equals, "Spec heading not found")
   149  	c.Assert(result.ParseErrors[0].LineNo, Equals, 1)
   150  	c.Assert(result.ParseErrors[1].Message, Equals, "Scenario should be defined after the spec heading")
   151  	c.Assert(result.ParseErrors[1].LineNo, Equals, 1)
   152  
   153  }
   154  
   155  func (s *MySuite) TestThrowsErrorForDuplicateScenariosWithinTheSameSpec(c *C) {
   156  	tokens := []*Token{
   157  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
   158  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 2},
   159  		{Kind: gauge.StepKind, Value: "Example step", LineNo: 3},
   160  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 4},
   161  	}
   162  
   163  	_, result, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
   164  	c.Assert(err, IsNil)
   165  	c.Assert(result.Ok, Equals, false)
   166  
   167  	c.Assert(result.ParseErrors[0].Message, Equals, "Duplicate scenario definition 'Scenario Heading' found in the same specification")
   168  	c.Assert(result.ParseErrors[0].LineNo, Equals, 4)
   169  }
   170  
   171  func (s *MySuite) TestSpecWithHeadingAndSimpleSteps(c *C) {
   172  	tokens := []*Token{
   173  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
   174  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 2},
   175  		{Kind: gauge.StepKind, Value: "Example step", LineNo: 3},
   176  	}
   177  
   178  	spec, result, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
   179  	c.Assert(err, IsNil)
   180  	c.Assert(len(spec.Items), Equals, 1)
   181  	c.Assert(spec.Items[0], Equals, spec.Scenarios[0])
   182  	scenarioItems := (spec.Items[0]).(*gauge.Scenario).Items
   183  	c.Assert(scenarioItems[0], Equals, spec.Scenarios[0].Steps[0])
   184  
   185  	c.Assert(result.Ok, Equals, true)
   186  	c.Assert(spec.Heading.LineNo, Equals, 1)
   187  	c.Assert(spec.Heading.Value, Equals, "Spec Heading")
   188  
   189  	c.Assert(len(spec.Scenarios), Equals, 1)
   190  	c.Assert(spec.Scenarios[0].Heading.LineNo, Equals, 2)
   191  	c.Assert(spec.Scenarios[0].Heading.Value, Equals, "Scenario Heading")
   192  	c.Assert(len(spec.Scenarios[0].Steps), Equals, 1)
   193  	c.Assert(spec.Scenarios[0].Steps[0].Value, Equals, "Example step")
   194  }
   195  
   196  func (s *MySuite) TestStepsAndComments(c *C) {
   197  	tokens := []*Token{
   198  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
   199  		{Kind: gauge.CommentKind, Value: "A comment with some text and **bold** characters", LineNo: 2},
   200  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 3},
   201  		{Kind: gauge.CommentKind, Value: "Another comment", LineNo: 4},
   202  		{Kind: gauge.StepKind, Value: "Example step", LineNo: 5},
   203  		{Kind: gauge.CommentKind, Value: "Third comment", LineNo: 6},
   204  	}
   205  
   206  	spec, result, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
   207  	c.Assert(err, IsNil)
   208  	c.Assert(len(spec.Items), Equals, 2)
   209  	c.Assert(spec.Items[0], Equals, spec.Comments[0])
   210  	c.Assert(spec.Items[1], Equals, spec.Scenarios[0])
   211  
   212  	scenarioItems := (spec.Items[1]).(*gauge.Scenario).Items
   213  	c.Assert(3, Equals, len(scenarioItems))
   214  	c.Assert(scenarioItems[0], Equals, spec.Scenarios[0].Comments[0])
   215  	c.Assert(scenarioItems[1], Equals, spec.Scenarios[0].Steps[0])
   216  	c.Assert(scenarioItems[2], Equals, spec.Scenarios[0].Comments[1])
   217  
   218  	c.Assert(result.Ok, Equals, true)
   219  	c.Assert(spec.Heading.Value, Equals, "Spec Heading")
   220  
   221  	c.Assert(len(spec.Comments), Equals, 1)
   222  	c.Assert(spec.Comments[0].LineNo, Equals, 2)
   223  	c.Assert(spec.Comments[0].Value, Equals, "A comment with some text and **bold** characters")
   224  
   225  	c.Assert(len(spec.Scenarios), Equals, 1)
   226  	scenario := spec.Scenarios[0]
   227  
   228  	c.Assert(2, Equals, len(scenario.Comments))
   229  	c.Assert(scenario.Comments[0].LineNo, Equals, 4)
   230  	c.Assert(scenario.Comments[0].Value, Equals, "Another comment")
   231  
   232  	c.Assert(scenario.Comments[1].LineNo, Equals, 6)
   233  	c.Assert(scenario.Comments[1].Value, Equals, "Third comment")
   234  
   235  	c.Assert(scenario.Heading.Value, Equals, "Scenario Heading")
   236  	c.Assert(len(scenario.Steps), Equals, 1)
   237  }
   238  
   239  func (s *MySuite) TestTableFromInvalidFile(c *C) {
   240  	parser := new(SpecParser)
   241  	specText := newSpecBuilder().specHeading("Spec heading").text("table: inputinvalid.csv").text("comment").scenarioHeading("Sce heading").step("my step").String()
   242  
   243  	tokens, _ := parser.GenerateTokens(specText, "")
   244  	_, res, err := parser.CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
   245  	c.Assert(err, IsNil)
   246  	c.Assert(len(res.ParseErrors) > 0, Equals, true)
   247  	c.Assert(res.ParseErrors[0].Message, Equals, "Could not resolve table. File inputinvalid.csv doesn't exist.")
   248  }
   249  
   250  func (s *MySuite) TestStepsWithParam(c *C) {
   251  	tokens := []*Token{
   252  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
   253  		{Kind: gauge.TableHeader, Args: []string{"id"}, LineNo: 2},
   254  		{Kind: gauge.TableRow, Args: []string{"1"}, LineNo: 3},
   255  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 4},
   256  		{Kind: gauge.StepKind, Value: "enter {static} with {dynamic}", LineNo: 5, Args: []string{"user \\n foo", "id"}},
   257  		{Kind: gauge.StepKind, Value: "sample \\{static\\}", LineNo: 6},
   258  	}
   259  
   260  	spec, result, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
   261  	c.Assert(err, IsNil)
   262  	c.Assert(result.Ok, Equals, true)
   263  	step := spec.Scenarios[0].Steps[0]
   264  	c.Assert(step.Value, Equals, "enter {} with {}")
   265  	c.Assert(step.LineNo, Equals, 5)
   266  	c.Assert(len(step.Args), Equals, 2)
   267  	c.Assert(step.Args[0].Value, Equals, "user \\n foo")
   268  	c.Assert(step.Args[0].ArgType, Equals, gauge.Static)
   269  	c.Assert(step.Args[1].Value, Equals, "id")
   270  	c.Assert(step.Args[1].ArgType, Equals, gauge.Dynamic)
   271  	c.Assert(step.Args[1].Name, Equals, "id")
   272  
   273  	escapedStep := spec.Scenarios[0].Steps[1]
   274  	c.Assert(escapedStep.Value, Equals, "sample \\{static\\}")
   275  	c.Assert(len(escapedStep.Args), Equals, 0)
   276  }
   277  
   278  func (s *MySuite) TestStepsWithKeywords(c *C) {
   279  	tokens := []*Token{
   280  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
   281  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 2},
   282  		{Kind: gauge.StepKind, Value: "sample {static} and {dynamic}", LineNo: 3, Args: []string{"name"}},
   283  	}
   284  
   285  	_, result, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
   286  	c.Assert(err, IsNil)
   287  	c.Assert(result, NotNil)
   288  	c.Assert(result.Ok, Equals, false)
   289  	c.Assert(result.ParseErrors[0].Message, Equals, "Scenario should have atleast one step")
   290  	c.Assert(result.ParseErrors[0].LineNo, Equals, 2)
   291  	c.Assert(result.ParseErrors[1].Message, Equals, "Step text should not have '{static}' or '{dynamic}' or '{special}'")
   292  	c.Assert(result.ParseErrors[1].LineNo, Equals, 3)
   293  }
   294  
   295  func (s *MySuite) TestContextWithKeywords(c *C) {
   296  	tokens := []*Token{
   297  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
   298  		{Kind: gauge.StepKind, Value: "sample {static} and {dynamic}", LineNo: 3, Args: []string{"name"}},
   299  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 2},
   300  		{Kind: gauge.StepKind, Value: "Step"},
   301  	}
   302  
   303  	_, result, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
   304  	c.Assert(err, IsNil)
   305  	c.Assert(result, NotNil)
   306  	c.Assert(result.Ok, Equals, false)
   307  	c.Assert(result.ParseErrors[0].Message, Equals, "Step text should not have '{static}' or '{dynamic}' or '{special}'")
   308  	c.Assert(result.ParseErrors[0].LineNo, Equals, 3)
   309  }
   310  
   311  func (s *MySuite) TestSpecWithDataTable(c *C) {
   312  	tokens := []*Token{
   313  		{Kind: gauge.SpecKind, Value: "Spec Heading"},
   314  		{Kind: gauge.CommentKind, Value: "Comment before data table"},
   315  		{Kind: gauge.TableHeader, Args: []string{"id", "name"}},
   316  		{Kind: gauge.TableRow, Args: []string{"1", "foo"}},
   317  		{Kind: gauge.TableRow, Args: []string{"2", "bar"}},
   318  		{Kind: gauge.CommentKind, Value: "Comment before data table"},
   319  		{Kind: gauge.ScenarioKind, Value: "Scenario heading"},
   320  		{Kind: gauge.StepKind, Value: "my step"},
   321  	}
   322  
   323  	spec, result, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
   324  	c.Assert(err, IsNil)
   325  	c.Assert(len(spec.Items), Equals, 4)
   326  	c.Assert(spec.Items[0], Equals, spec.Comments[0])
   327  	c.Assert(spec.Items[1], DeepEquals, &spec.DataTable)
   328  	c.Assert(spec.Items[2], Equals, spec.Comments[1])
   329  
   330  	c.Assert(result.Ok, Equals, true)
   331  	c.Assert(spec.DataTable, NotNil)
   332  	idCells, _ := spec.DataTable.Table.Get("id")
   333  	nameCells, _ := spec.DataTable.Table.Get("name")
   334  	c.Assert(len(idCells), Equals, 2)
   335  	c.Assert(len(nameCells), Equals, 2)
   336  	c.Assert(idCells[0].Value, Equals, "1")
   337  	c.Assert(idCells[0].CellType, Equals, gauge.Static)
   338  	c.Assert(idCells[1].Value, Equals, "2")
   339  	c.Assert(idCells[1].CellType, Equals, gauge.Static)
   340  	c.Assert(nameCells[0].Value, Equals, "foo")
   341  	c.Assert(nameCells[0].CellType, Equals, gauge.Static)
   342  	c.Assert(nameCells[1].Value, Equals, "bar")
   343  	c.Assert(nameCells[1].CellType, Equals, gauge.Static)
   344  }
   345  
   346  func TestScenarioWithDataTable(t *testing.T) {
   347  	var subject = func() *gauge.Scenario {
   348  		tokens := []*Token{
   349  			{Kind: gauge.SpecKind, Value: "Spec Heading"},
   350  			{Kind: gauge.CommentKind, Value: "Comment before data table"},
   351  			{Kind: gauge.ScenarioKind, Value: "Scenario heading"},
   352  			{Kind: gauge.CommentKind, Value: "Comment before data table"},
   353  			{Kind: gauge.TableHeader, Args: []string{"id", "name"}},
   354  			{Kind: gauge.TableRow, Args: []string{"1", "foo"}},
   355  			{Kind: gauge.TableRow, Args: []string{"2", "bar"}},
   356  			{Kind: gauge.StepKind, Value: "my step"},
   357  		}
   358  		spec, result, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
   359  		if err != nil {
   360  			t.Error(err)
   361  		}
   362  		v := len(spec.Items)
   363  		if v != 2 {
   364  			t.Errorf("expected spec to have 2 items. got %d", v)
   365  		}
   366  		if !result.Ok {
   367  			t.Errorf("parse failed, err %s", strings.Join(result.Errors(), ","))
   368  		}
   369  
   370  		return spec.Scenarios[0]
   371  	}
   372  
   373  	t.Run("Scenario with datatable when AllowScenarioDatatable=True", func(t *testing.T) {
   374  		env.AllowScenarioDatatable = func() bool { return true }
   375  		s := subject()
   376  		if s.DataTable.Table == nil {
   377  			t.Error("expected scenario datatable to be not nil")
   378  		}
   379  		v := len(s.Items)
   380  		if v != 3 {
   381  			t.Errorf("expected scenario to have 3 items, got %d", v)
   382  		}
   383  
   384  		idCells, _ := s.DataTable.Table.Get("id")
   385  		nameCells, _ := s.DataTable.Table.Get("name")
   386  
   387  		var assertEqual = func(e, a interface{}) {
   388  			if e != a {
   389  				t.Errorf("expected %v got %v", e, a)
   390  			}
   391  		}
   392  		assertEqual(len(idCells), 2)
   393  		assertEqual(len(nameCells), 2)
   394  		assertEqual(idCells[0].Value, "1")
   395  		assertEqual(idCells[0].CellType, gauge.Static)
   396  		assertEqual(idCells[1].Value, "2")
   397  		assertEqual(idCells[1].CellType, gauge.Static)
   398  		assertEqual(nameCells[0].Value, "foo")
   399  		assertEqual(nameCells[0].CellType, gauge.Static)
   400  		assertEqual(nameCells[1].Value, "bar")
   401  		assertEqual(nameCells[1].CellType, gauge.Static)
   402  	})
   403  	t.Run("Parse Scenario with datatable when AllowScenarioDatatable=False", func(t *testing.T) {
   404  		env.AllowScenarioDatatable = func() bool { return false }
   405  		s := subject()
   406  		if s.DataTable.Table.IsInitialized() {
   407  			t.Error("expected scenario to have no datatable, got one")
   408  		}
   409  	})
   410  
   411  }
   412  
   413  func (s *MySuite) TestSpecWithDataTableHavingEmptyRowAndNoSeparator(c *C) {
   414  	tokens := []*Token{
   415  		{Kind: gauge.SpecKind, Value: "Spec Heading"},
   416  		{Kind: gauge.CommentKind, Value: "Comment before data table"},
   417  		{Kind: gauge.TableHeader, Args: []string{"id", "name"}},
   418  		{Kind: gauge.TableRow, Args: []string{"1", "foo"}},
   419  		{Kind: gauge.TableRow, Args: []string{"", ""}},
   420  		{Kind: gauge.TableRow, Args: []string{"2", "bar"}},
   421  		{Kind: gauge.CommentKind, Value: "Comment before data table"},
   422  		{Kind: gauge.ScenarioKind, Value: "Scenario heading"},
   423  		{Kind: gauge.StepKind, Value: "my step"},
   424  	}
   425  
   426  	spec, result, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
   427  	c.Assert(err, IsNil)
   428  	c.Assert(len(spec.Items), Equals, 4)
   429  	c.Assert(spec.Items[0], Equals, spec.Comments[0])
   430  	c.Assert(spec.Items[1], DeepEquals, &spec.DataTable)
   431  	c.Assert(spec.Items[2], Equals, spec.Comments[1])
   432  
   433  	c.Assert(result.Ok, Equals, true)
   434  	c.Assert(spec.DataTable, NotNil)
   435  	c.Assert(spec.DataTable.Table.GetRowCount(), Equals, 3)
   436  	idCells, _ := spec.DataTable.Table.Get("id")
   437  	nameCells, _ := spec.DataTable.Table.Get("name")
   438  	c.Assert(len(idCells), Equals, 3)
   439  	c.Assert(len(nameCells), Equals, 3)
   440  	c.Assert(idCells[0].Value, Equals, "1")
   441  	c.Assert(idCells[0].CellType, Equals, gauge.Static)
   442  	c.Assert(idCells[1].Value, Equals, "")
   443  	c.Assert(idCells[1].CellType, Equals, gauge.Static)
   444  	c.Assert(idCells[2].Value, Equals, "2")
   445  	c.Assert(idCells[2].CellType, Equals, gauge.Static)
   446  	c.Assert(nameCells[0].Value, Equals, "foo")
   447  	c.Assert(nameCells[0].CellType, Equals, gauge.Static)
   448  	c.Assert(nameCells[1].Value, Equals, "")
   449  	c.Assert(nameCells[1].CellType, Equals, gauge.Static)
   450  	c.Assert(nameCells[2].Value, Equals, "bar")
   451  	c.Assert(nameCells[2].CellType, Equals, gauge.Static)
   452  }
   453  
   454  func (s *MySuite) TestSpecWithStepUsingInlineTableWhichUsagesDynamicParamFromScenarioDataTable(c *C) {
   455  	env.AllowScenarioDatatable = func() bool { return true }
   456  	specText := `# Specification heading
   457  
   458  ## Scenario Heading
   459  
   460  	|name   |
   461  	|-------|
   462  	|someone|
   463  
   464  * step with
   465  	|id    |
   466  	|------|
   467  	|<name>|
   468  `
   469  	_, _, err := new(SpecParser).Parse(specText, gauge.NewConceptDictionary(), "foo.spec")
   470  	c.Assert(err, IsNil)
   471  }
   472  
   473  func (s *MySuite) TestStepWithInlineTable(c *C) {
   474  	tokens := []*Token{
   475  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
   476  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 2},
   477  		{Kind: gauge.StepKind, Value: "Step with inline table", LineNo: 3},
   478  		{Kind: gauge.TableHeader, Args: []string{"id", "name"}},
   479  		{Kind: gauge.TableRow, Args: []string{"1", "foo"}},
   480  		{Kind: gauge.TableRow, Args: []string{"2", "bar"}},
   481  	}
   482  
   483  	spec, result, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
   484  	c.Assert(err, IsNil)
   485  	c.Assert(result.Ok, Equals, true)
   486  	step := spec.Scenarios[0].Steps[0]
   487  
   488  	c.Assert(step.Args[0].ArgType, Equals, gauge.TableArg)
   489  	inlineTable := step.Args[0].Table
   490  	c.Assert(inlineTable, NotNil)
   491  
   492  	c.Assert(step.Value, Equals, "Step with inline table {}")
   493  	c.Assert(step.HasInlineTable, Equals, true)
   494  	idCells, _ := inlineTable.Get("id")
   495  	nameCells, _ := inlineTable.Get("name")
   496  	c.Assert(len(idCells), Equals, 2)
   497  	c.Assert(len(nameCells), Equals, 2)
   498  	c.Assert(idCells[0].Value, Equals, "1")
   499  	c.Assert(idCells[0].CellType, Equals, gauge.Static)
   500  	c.Assert(idCells[1].Value, Equals, "2")
   501  	c.Assert(idCells[1].CellType, Equals, gauge.Static)
   502  	c.Assert(nameCells[0].Value, Equals, "foo")
   503  	c.Assert(nameCells[0].CellType, Equals, gauge.Static)
   504  	c.Assert(nameCells[1].Value, Equals, "bar")
   505  	c.Assert(nameCells[1].CellType, Equals, gauge.Static)
   506  }
   507  
   508  func (s *MySuite) TestStepWithInlineTableWithDynamicParam(c *C) {
   509  	tokens := []*Token{
   510  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
   511  		{Kind: gauge.TableHeader, Args: []string{"type1", "type2"}},
   512  		{Kind: gauge.TableRow, Args: []string{"1", "2"}},
   513  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 2},
   514  		{Kind: gauge.StepKind, Value: "Step with inline table", LineNo: 3},
   515  		{Kind: gauge.TableHeader, Args: []string{"id", "name"}},
   516  		{Kind: gauge.TableRow, Args: []string{"1", "<type1>"}},
   517  		{Kind: gauge.TableRow, Args: []string{"2", "<type2>"}},
   518  		{Kind: gauge.TableRow, Args: []string{"<2>", "<type3>"}},
   519  	}
   520  
   521  	spec, result, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
   522  	c.Assert(err, IsNil)
   523  
   524  	c.Assert(result.Ok, Equals, true)
   525  	step := spec.Scenarios[0].Steps[0]
   526  
   527  	c.Assert(step.Args[0].ArgType, Equals, gauge.TableArg)
   528  	inlineTable := step.Args[0].Table
   529  	c.Assert(inlineTable, NotNil)
   530  
   531  	c.Assert(step.Value, Equals, "Step with inline table {}")
   532  	idCells, _ := inlineTable.Get("id")
   533  	nameCells, _ := inlineTable.Get("name")
   534  	c.Assert(len(idCells), Equals, 3)
   535  	c.Assert(len(nameCells), Equals, 3)
   536  	c.Assert(idCells[0].Value, Equals, "1")
   537  	c.Assert(idCells[0].CellType, Equals, gauge.Static)
   538  	c.Assert(idCells[1].Value, Equals, "2")
   539  	c.Assert(idCells[1].CellType, Equals, gauge.Static)
   540  	c.Assert(idCells[2].Value, Equals, "<2>")
   541  	c.Assert(idCells[2].CellType, Equals, gauge.Static)
   542  
   543  	c.Assert(nameCells[0].Value, Equals, "type1")
   544  	c.Assert(nameCells[0].CellType, Equals, gauge.Dynamic)
   545  	c.Assert(nameCells[1].Value, Equals, "type2")
   546  	c.Assert(nameCells[1].CellType, Equals, gauge.Dynamic)
   547  	c.Assert(nameCells[2].Value, Equals, "<type3>")
   548  	c.Assert(nameCells[2].CellType, Equals, gauge.Static)
   549  }
   550  
   551  func (s *MySuite) TestStepWithInlineTableWithUnResolvableDynamicParam(c *C) {
   552  	tokens := []*Token{
   553  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
   554  		{Kind: gauge.TableHeader, Args: []string{"type1", "type2"}},
   555  		{Kind: gauge.TableRow, Args: []string{"1", "2"}},
   556  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 2},
   557  		{Kind: gauge.StepKind, Value: "Step with inline table", LineNo: 3},
   558  		{Kind: gauge.TableHeader, Args: []string{"id", "name"}},
   559  		{Kind: gauge.TableRow, Args: []string{"1", "<invalid>"}},
   560  		{Kind: gauge.TableRow, Args: []string{"2", "<type2>"}},
   561  	}
   562  
   563  	spec, result, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
   564  	c.Assert(err, IsNil)
   565  	c.Assert(result.Ok, Equals, true)
   566  	idCells, _ := spec.Scenarios[0].Steps[0].Args[0].Table.Get("id")
   567  	c.Assert(idCells[0].Value, Equals, "1")
   568  	nameCells, _ := spec.Scenarios[0].Steps[0].Args[0].Table.Get("name")
   569  	c.Assert(nameCells[0].Value, Equals, "<invalid>")
   570  	c.Assert(result.Warnings[0].Message, Equals, "Dynamic param <invalid> could not be resolved, Treating it as static param")
   571  }
   572  
   573  func (s *MySuite) TestContextWithInlineTable(c *C) {
   574  	tokens := []*Token{
   575  		{Kind: gauge.SpecKind, Value: "Spec Heading"},
   576  		{Kind: gauge.StepKind, Value: "Context with inline table"},
   577  		{Kind: gauge.TableHeader, Args: []string{"id", "name"}},
   578  		{Kind: gauge.TableRow, Args: []string{"1", "foo"}},
   579  		{Kind: gauge.TableRow, Args: []string{"2", "bar"}},
   580  		{Kind: gauge.TableRow, Args: []string{"3", "not a <dynamic>"}},
   581  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading"},
   582  		{Kind: gauge.StepKind, Value: "Step"},
   583  	}
   584  
   585  	spec, result, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
   586  	c.Assert(err, IsNil)
   587  	c.Assert(len(spec.Items), Equals, 2)
   588  	c.Assert(spec.Items[0], DeepEquals, spec.Contexts[0])
   589  	c.Assert(spec.Items[1], Equals, spec.Scenarios[0])
   590  
   591  	c.Assert(result.Ok, Equals, true)
   592  	context := spec.Contexts[0]
   593  
   594  	c.Assert(context.Args[0].ArgType, Equals, gauge.TableArg)
   595  	inlineTable := context.Args[0].Table
   596  
   597  	c.Assert(inlineTable, NotNil)
   598  	c.Assert(context.Value, Equals, "Context with inline table {}")
   599  	idCells, _ := inlineTable.Get("id")
   600  	nameCells, _ := inlineTable.Get("name")
   601  	c.Assert(len(idCells), Equals, 3)
   602  	c.Assert(len(nameCells), Equals, 3)
   603  	c.Assert(idCells[0].Value, Equals, "1")
   604  	c.Assert(idCells[0].CellType, Equals, gauge.Static)
   605  	c.Assert(idCells[1].Value, Equals, "2")
   606  	c.Assert(idCells[1].CellType, Equals, gauge.Static)
   607  	c.Assert(idCells[2].Value, Equals, "3")
   608  	c.Assert(idCells[2].CellType, Equals, gauge.Static)
   609  	c.Assert(nameCells[0].Value, Equals, "foo")
   610  	c.Assert(nameCells[0].CellType, Equals, gauge.Static)
   611  	c.Assert(nameCells[1].Value, Equals, "bar")
   612  	c.Assert(nameCells[1].CellType, Equals, gauge.Static)
   613  	c.Assert(nameCells[2].Value, Equals, "not a <dynamic>")
   614  	c.Assert(nameCells[2].CellType, Equals, gauge.Static)
   615  }
   616  
   617  func (s *MySuite) TestErrorWhenDataTableHasOnlyHeader(c *C) {
   618  	tokens := []*Token{
   619  		{Kind: gauge.SpecKind, Value: "Spec Heading"},
   620  		{Kind: gauge.TableHeader, Args: []string{"id", "name"}, LineNo: 3},
   621  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading"},
   622  	}
   623  
   624  	_, result, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
   625  	c.Assert(err, IsNil)
   626  	c.Assert(result.Ok, Equals, false)
   627  	c.Assert(result.ParseErrors[0].Message, Equals, "Data table should have at least 1 data row")
   628  	c.Assert(result.ParseErrors[0].LineNo, Equals, 3)
   629  }
   630  
   631  func (s *MySuite) TestWarningWhenParsingMultipleDataTable(c *C) {
   632  	tokens := []*Token{
   633  		{Kind: gauge.SpecKind, Value: "Spec Heading"},
   634  		{Kind: gauge.CommentKind, Value: "Comment before data table"},
   635  		{Kind: gauge.TableHeader, Args: []string{"id", "name"}},
   636  		{Kind: gauge.TableRow, Args: []string{"1", "foo"}},
   637  		{Kind: gauge.TableRow, Args: []string{"2", "bar"}},
   638  		{Kind: gauge.CommentKind, Value: "Comment before data table"},
   639  		{Kind: gauge.TableHeader, Args: []string{"phone"}, LineNo: 7},
   640  		{Kind: gauge.TableRow, Args: []string{"1"}},
   641  		{Kind: gauge.TableRow, Args: []string{"2"}},
   642  		{Kind: gauge.ScenarioKind, Value: "Scenario heading"},
   643  		{Kind: gauge.StepKind, Value: "my step"},
   644  	}
   645  
   646  	_, result, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "foo.spec")
   647  	c.Assert(err, IsNil)
   648  	c.Assert(result.Ok, Equals, true)
   649  	c.Assert(len(result.Warnings), Equals, 1)
   650  	c.Assert(result.Warnings[0].String(), Equals, "foo.spec:7 Multiple data table present, ignoring table")
   651  
   652  }
   653  
   654  func (s *MySuite) TestParseErrorWhenCouldNotResolveExternalDataTable(c *C) {
   655  	tokens := []*Token{
   656  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
   657  		{Kind: gauge.CommentKind, Value: "Comment before data table", LineNo: 2},
   658  		{Kind: gauge.DataTableKind, Value: "table: foo", LineNo: 3, Lines: []string{"table: foo"}},
   659  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 4},
   660  		{Kind: gauge.StepKind, Value: "Step", LineNo: 5},
   661  	}
   662  
   663  	_, result, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "foo.spec")
   664  	c.Assert(err, IsNil)
   665  	c.Assert(result.Ok, Equals, false)
   666  	c.Assert(len(result.Warnings), Equals, 0)
   667  	c.Assert(result.Errors()[0], Equals, "[ParseError] foo.spec:3 Could not resolve table. File foo doesn't exist. => 'table: foo'")
   668  
   669  }
   670  
   671  func (s *MySuite) TestAddSpecTags(c *C) {
   672  	tokens := []*Token{
   673  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
   674  		{Kind: gauge.TagKind, Args: []string{"tag1", "tag2"}, LineNo: 2},
   675  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 3},
   676  		{Kind: gauge.StepKind, Value: "Step"},
   677  	}
   678  
   679  	spec, result, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
   680  	c.Assert(err, IsNil)
   681  	c.Assert(result.Ok, Equals, true)
   682  	c.Assert(len(spec.Tags.Values()), Equals, 2)
   683  	c.Assert(spec.Tags.Values()[0], Equals, "tag1")
   684  	c.Assert(spec.Tags.Values()[1], Equals, "tag2")
   685  }
   686  
   687  func (s *MySuite) TestAddSpecTagsAndScenarioTags(c *C) {
   688  	tokens := []*Token{
   689  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
   690  		{Kind: gauge.TagKind, Args: []string{"tag1", "tag2"}, LineNo: 2},
   691  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 3},
   692  		{Kind: gauge.TagKind, Args: []string{"tag3", "tag4"}, LineNo: 2},
   693  		{Kind: gauge.StepKind, Value: "Step"},
   694  	}
   695  
   696  	spec, result, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
   697  	c.Assert(err, IsNil)
   698  	c.Assert(result.Ok, Equals, true)
   699  
   700  	c.Assert(len(spec.Tags.Values()), Equals, 2)
   701  	c.Assert(spec.Tags.Values()[0], Equals, "tag1")
   702  	c.Assert(spec.Tags.Values()[1], Equals, "tag2")
   703  
   704  	tags := spec.Scenarios[0].Tags
   705  	c.Assert(len(tags.Values()), Equals, 2)
   706  	c.Assert(tags.Values()[0], Equals, "tag3")
   707  	c.Assert(tags.Values()[1], Equals, "tag4")
   708  }
   709  
   710  func (s *MySuite) TestErrorOnAddingDynamicParamterWithoutADataTable(c *C) {
   711  	tokens := []*Token{
   712  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
   713  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 2},
   714  		{Kind: gauge.StepKind, Value: "Step with a {dynamic}", Args: []string{"foo"}, LineNo: 3, Lines: []string{"*Step with a <foo>"}},
   715  		{Kind: gauge.StepKind, Value: "Step"},
   716  	}
   717  
   718  	_, result, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
   719  	c.Assert(err, IsNil)
   720  	c.Assert(result.Ok, Equals, false)
   721  	c.Assert(result.ParseErrors[0].Message, Equals, "Dynamic parameter <foo> could not be resolved")
   722  	c.Assert(result.ParseErrors[0].LineNo, Equals, 3)
   723  }
   724  
   725  func (s *MySuite) TestErrorOnAddingDynamicParamterWithoutDataTableHeaderValue(c *C) {
   726  	tokens := []*Token{
   727  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
   728  		{Kind: gauge.TableHeader, Args: []string{"id, name"}, LineNo: 2},
   729  		{Kind: gauge.TableRow, Args: []string{"123, hello"}, LineNo: 3},
   730  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 4},
   731  		{Kind: gauge.StepKind, Value: "Step with a {dynamic}", Args: []string{"foo"}, LineNo: 5, Lines: []string{"*Step with a <foo>"}},
   732  		{Kind: gauge.StepKind, Value: "Step"},
   733  	}
   734  
   735  	_, result, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
   736  	c.Assert(err, IsNil)
   737  	c.Assert(result.Ok, Equals, false)
   738  	c.Assert(result.ParseErrors[0].Message, Equals, "Dynamic parameter <foo> could not be resolved")
   739  	c.Assert(result.ParseErrors[0].LineNo, Equals, 5)
   740  }
   741  
   742  func (s *MySuite) TestResolveScenarioDataTableAsDynamicParams(c *C) {
   743  	env.AllowScenarioDatatable = func() bool { return true }
   744  	tokens := []*Token{
   745  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
   746  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 4},
   747  		{Kind: gauge.TableHeader, Args: []string{"id", "name"}, LineNo: 2},
   748  		{Kind: gauge.TableRow, Args: []string{"123", "hello"}, LineNo: 3},
   749  		{Kind: gauge.StepKind, Value: "Step with a {dynamic}", Args: []string{"id"}, LineNo: 5, Lines: []string{"*Step with a <id>"}},
   750  		{Kind: gauge.StepKind, Value: "Step"},
   751  	}
   752  
   753  	_, result, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
   754  	c.Assert(err, IsNil)
   755  	c.Assert(result.Ok, Equals, true)
   756  }
   757  
   758  func (s *MySuite) TestCreateStepFromSimpleConcept(c *C) {
   759  	tokens := []*Token{
   760  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
   761  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 2},
   762  		{Kind: gauge.StepKind, Value: "test concept step 1", LineNo: 3},
   763  	}
   764  
   765  	conceptDictionary := gauge.NewConceptDictionary()
   766  	path, _ := filepath.Abs(filepath.Join("testdata", "concept.cpt"))
   767  	_, _, err := AddConcepts([]string{path}, conceptDictionary)
   768  	c.Assert(err, IsNil)
   769  	spec, result, err := new(SpecParser).CreateSpecification(tokens, conceptDictionary, "")
   770  	c.Assert(err, IsNil)
   771  	c.Assert(result.Ok, Equals, true)
   772  
   773  	c.Assert(len(spec.Scenarios[0].Steps), Equals, 1)
   774  	specConceptStep := spec.Scenarios[0].Steps[0]
   775  	c.Assert(specConceptStep.IsConcept, Equals, true)
   776  	assertStepEqual(c, &gauge.Step{LineNo: 2, Value: "step 1", LineText: "step 1"}, specConceptStep.ConceptSteps[0])
   777  }
   778  
   779  func (s *MySuite) TestCreateStepFromConceptWithParameters(c *C) {
   780  	tokens := []*Token{
   781  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
   782  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 2},
   783  		{Kind: gauge.StepKind, Value: "assign id {static} and name {static}", Args: []string{"foo", "foo1"}, LineNo: 3},
   784  		{Kind: gauge.StepKind, Value: "assign id {static} and name {static}", Args: []string{"bar", "bar1"}, LineNo: 4},
   785  	}
   786  
   787  	conceptDictionary := gauge.NewConceptDictionary()
   788  	path, _ := filepath.Abs(filepath.Join("testdata", "dynamic_param_concept.cpt"))
   789  	_, _, err := AddConcepts([]string{path}, conceptDictionary)
   790  	c.Assert(err, IsNil)
   791  
   792  	spec, result, err := new(SpecParser).CreateSpecification(tokens, conceptDictionary, "")
   793  	c.Assert(err, IsNil)
   794  	c.Assert(result.Ok, Equals, true)
   795  
   796  	c.Assert(len(spec.Scenarios[0].Steps), Equals, 2)
   797  
   798  	firstConceptStep := spec.Scenarios[0].Steps[0]
   799  	c.Assert(firstConceptStep.IsConcept, Equals, true)
   800  	c.Assert(firstConceptStep.ConceptSteps[0].Value, Equals, "add id {}")
   801  	c.Assert(firstConceptStep.ConceptSteps[0].Args[0].Value, Equals, "userid")
   802  	c.Assert(firstConceptStep.ConceptSteps[1].Value, Equals, "add name {}")
   803  	c.Assert(firstConceptStep.ConceptSteps[1].Args[0].Value, Equals, "username")
   804  	usernameArg, _ := firstConceptStep.GetArg("username")
   805  	c.Assert(usernameArg.Value, Equals, "foo1")
   806  	useridArg, _ := firstConceptStep.GetArg("userid")
   807  	c.Assert(useridArg.Value, Equals, "foo")
   808  
   809  	secondConceptStep := spec.Scenarios[0].Steps[1]
   810  	c.Assert(secondConceptStep.IsConcept, Equals, true)
   811  	c.Assert(secondConceptStep.ConceptSteps[0].Value, Equals, "add id {}")
   812  	c.Assert(secondConceptStep.ConceptSteps[0].Args[0].Value, Equals, "userid")
   813  	c.Assert(secondConceptStep.ConceptSteps[1].Value, Equals, "add name {}")
   814  	c.Assert(secondConceptStep.ConceptSteps[1].Args[0].Value, Equals, "username")
   815  	usernameArg2, _ := secondConceptStep.GetArg("username")
   816  	c.Assert(usernameArg2.Value, Equals, "bar1")
   817  	useridArg2, _ := secondConceptStep.GetArg("userid")
   818  	c.Assert(useridArg2.Value, Equals, "bar")
   819  
   820  }
   821  
   822  func (s *MySuite) TestCreateStepFromConceptWithDynamicParameters(c *C) {
   823  	tokens := []*Token{
   824  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
   825  		{Kind: gauge.TableHeader, Args: []string{"id", "description"}, LineNo: 2},
   826  		{Kind: gauge.TableRow, Args: []string{"123", "Admin fellow"}, LineNo: 3},
   827  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 4},
   828  		{Kind: gauge.StepKind, Value: "assign id {dynamic} and name {dynamic}", Args: []string{"id", "description"}, LineNo: 5},
   829  	}
   830  
   831  	conceptDictionary := gauge.NewConceptDictionary()
   832  	path, _ := filepath.Abs(filepath.Join("testdata", "dynamic_param_concept.cpt"))
   833  	_, _, err := AddConcepts([]string{path}, conceptDictionary)
   834  	c.Assert(err, IsNil)
   835  	spec, result, err := new(SpecParser).CreateSpecification(tokens, conceptDictionary, "")
   836  	c.Assert(err, IsNil)
   837  	c.Assert(result.Ok, Equals, true)
   838  
   839  	c.Assert(len(spec.Items), Equals, 2)
   840  	c.Assert(spec.Items[0], DeepEquals, &spec.DataTable)
   841  	c.Assert(spec.Items[1], Equals, spec.Scenarios[0])
   842  
   843  	scenarioItems := (spec.Items[1]).(*gauge.Scenario).Items
   844  	c.Assert(scenarioItems[0], Equals, spec.Scenarios[0].Steps[0])
   845  
   846  	c.Assert(len(spec.Scenarios[0].Steps), Equals, 1)
   847  
   848  	firstConcept := spec.Scenarios[0].Steps[0]
   849  	c.Assert(firstConcept.IsConcept, Equals, true)
   850  	c.Assert(firstConcept.ConceptSteps[0].Value, Equals, "add id {}")
   851  	c.Assert(firstConcept.ConceptSteps[0].Args[0].ArgType, Equals, gauge.Dynamic)
   852  	c.Assert(firstConcept.ConceptSteps[0].Args[0].Value, Equals, "userid")
   853  	c.Assert(firstConcept.ConceptSteps[1].Value, Equals, "add name {}")
   854  	c.Assert(firstConcept.ConceptSteps[1].Args[0].Value, Equals, "username")
   855  	c.Assert(firstConcept.ConceptSteps[1].Args[0].ArgType, Equals, gauge.Dynamic)
   856  
   857  	arg1, _ := firstConcept.Lookup.GetArg("userid")
   858  	c.Assert(arg1.Value, Equals, "id")
   859  	c.Assert(arg1.ArgType, Equals, gauge.Dynamic)
   860  
   861  	arg2, _ := firstConcept.Lookup.GetArg("username")
   862  	c.Assert(arg2.Value, Equals, "description")
   863  	c.Assert(arg2.ArgType, Equals, gauge.Dynamic)
   864  }
   865  
   866  func (s *MySuite) TestCreateStepFromConceptWithInlineTable(c *C) {
   867  	tokens := []*Token{
   868  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
   869  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 4},
   870  		{Kind: gauge.StepKind, Value: "assign id {static} and name", Args: []string{"sdf"}, LineNo: 3},
   871  		{Kind: gauge.TableHeader, Args: []string{"id", "description"}, LineNo: 4},
   872  		{Kind: gauge.TableRow, Args: []string{"123", "Admin"}, LineNo: 5},
   873  		{Kind: gauge.TableRow, Args: []string{"456", "normal fellow"}, LineNo: 6},
   874  	}
   875  
   876  	conceptDictionary := gauge.NewConceptDictionary()
   877  	path, _ := filepath.Abs(filepath.Join("testdata", "dynamic_param_concept.cpt"))
   878  	_, _, err := AddConcepts([]string{path}, conceptDictionary)
   879  	c.Assert(err, IsNil)
   880  	spec, result, err := new(SpecParser).CreateSpecification(tokens, conceptDictionary, "")
   881  	c.Assert(err, IsNil)
   882  	c.Assert(result.Ok, Equals, true)
   883  
   884  	steps := spec.Scenarios[0].Steps
   885  	c.Assert(len(steps), Equals, 1)
   886  	c.Assert(steps[0].IsConcept, Equals, true)
   887  	c.Assert(steps[0].Value, Equals, "assign id {} and name {}")
   888  	c.Assert(len(steps[0].Args), Equals, 2)
   889  	c.Assert(steps[0].Args[1].ArgType, Equals, gauge.TableArg)
   890  	c.Assert(len(steps[0].ConceptSteps), Equals, 2)
   891  }
   892  
   893  func (s *MySuite) TestCreateStepFromConceptWithInlineTableHavingDynamicParam(c *C) {
   894  	tokens := []*Token{
   895  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
   896  		{Kind: gauge.TableHeader, Args: []string{"id", "description"}, LineNo: 2},
   897  		{Kind: gauge.TableRow, Args: []string{"123", "Admin"}, LineNo: 3},
   898  		{Kind: gauge.TableRow, Args: []string{"456", "normal fellow"}, LineNo: 4},
   899  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 5},
   900  		{Kind: gauge.StepKind, Value: "assign id {static} and name", Args: []string{"sdf"}, LineNo: 6},
   901  		{Kind: gauge.TableHeader, Args: []string{"user-id", "description", "name"}, LineNo: 7},
   902  		{Kind: gauge.TableRow, Args: []string{"<id>", "<description>", "root"}, LineNo: 8},
   903  	}
   904  
   905  	conceptDictionary := gauge.NewConceptDictionary()
   906  	path, _ := filepath.Abs(filepath.Join("testdata", "dynamic_param_concept.cpt"))
   907  	_, _, err := AddConcepts([]string{path}, conceptDictionary)
   908  	c.Assert(err, IsNil)
   909  	spec, result, err := new(SpecParser).CreateSpecification(tokens, conceptDictionary, "")
   910  	c.Assert(err, IsNil)
   911  	c.Assert(result.Ok, Equals, true)
   912  
   913  	steps := spec.Scenarios[0].Steps
   914  	c.Assert(len(steps), Equals, 1)
   915  	c.Assert(steps[0].IsConcept, Equals, true)
   916  	c.Assert(steps[0].Value, Equals, "assign id {} and name {}")
   917  	c.Assert(len(steps[0].Args), Equals, 2)
   918  	c.Assert(steps[0].Args[1].ArgType, Equals, gauge.TableArg)
   919  	table := steps[0].Args[1].Table
   920  	userIDCells, _ := table.Get("user-id")
   921  	descriptionCells, _ := table.Get("description")
   922  	nameCells, _ := table.Get("name")
   923  	c.Assert(userIDCells[0].Value, Equals, "id")
   924  	c.Assert(userIDCells[0].CellType, Equals, gauge.Dynamic)
   925  	c.Assert(descriptionCells[0].Value, Equals, "description")
   926  	c.Assert(descriptionCells[0].CellType, Equals, gauge.Dynamic)
   927  	c.Assert(nameCells[0].Value, Equals, "root")
   928  	c.Assert(nameCells[0].CellType, Equals, gauge.Static)
   929  	c.Assert(len(steps[0].ConceptSteps), Equals, 2)
   930  }
   931  
   932  func (s *MySuite) TestCreateInValidSpecialArgInStep(c *C) {
   933  	tokens := []*Token{
   934  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
   935  		{Kind: gauge.TableHeader, Args: []string{"unknown:foo", "description"}, LineNo: 2},
   936  		{Kind: gauge.TableRow, Args: []string{"123", "Admin"}, LineNo: 3},
   937  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 2},
   938  		{Kind: gauge.StepKind, Value: "Example {special} step", LineNo: 3, Args: []string{"unknown:foo"}},
   939  	}
   940  	spec, parseResults, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
   941  	c.Assert(err, IsNil)
   942  	c.Assert(spec.Scenarios[0].Steps[0].Args[0].ArgType, Equals, gauge.Dynamic)
   943  	c.Assert(len(parseResults.Warnings), Equals, 1)
   944  	c.Assert(parseResults.Warnings[0].Message, Equals, "Could not resolve special param type <unknown:foo>. Treating it as dynamic param.")
   945  }
   946  
   947  func (s *MySuite) TestTearDownSteps(c *C) {
   948  	tokens := []*Token{
   949  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
   950  		{Kind: gauge.CommentKind, Value: "A comment with some text and **bold** characters", LineNo: 2},
   951  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 3},
   952  		{Kind: gauge.CommentKind, Value: "Another comment", LineNo: 4},
   953  		{Kind: gauge.StepKind, Value: "Example step", LineNo: 5},
   954  		{Kind: gauge.CommentKind, Value: "Third comment", LineNo: 6},
   955  		{Kind: gauge.TearDownKind, Value: "____", LineNo: 7},
   956  		{Kind: gauge.StepKind, Value: "Example step1", LineNo: 8},
   957  		{Kind: gauge.CommentKind, Value: "Fourth comment", LineNo: 9},
   958  		{Kind: gauge.StepKind, Value: "Example step2", LineNo: 10},
   959  	}
   960  
   961  	spec, _, err := new(SpecParser).CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
   962  	c.Assert(err, IsNil)
   963  	c.Assert(len(spec.TearDownSteps), Equals, 2)
   964  	c.Assert(spec.TearDownSteps[0].Value, Equals, "Example step1")
   965  	c.Assert(spec.TearDownSteps[0].LineNo, Equals, 8)
   966  	c.Assert(spec.TearDownSteps[1].Value, Equals, "Example step2")
   967  	c.Assert(spec.TearDownSteps[1].LineNo, Equals, 10)
   968  }
   969  
   970  func (s *MySuite) TestParsingOfTableWithHyphens(c *C) {
   971  	p := new(SpecParser)
   972  
   973  	text := newSpecBuilder().specHeading("My Spec Heading").text("|id|").text("|--|").text("|1 |").text("|- |").String()
   974  	tokens, _ := p.GenerateTokens(text, "")
   975  
   976  	spec, _, err := p.CreateSpecification(tokens, gauge.NewConceptDictionary(), "")
   977  	c.Assert(err, IsNil)
   978  	idCells, _ := spec.DataTable.Table.Get("id")
   979  	c.Assert((len(idCells)), Equals, 2)
   980  	c.Assert(idCells[0].Value, Equals, "1")
   981  	c.Assert(idCells[1].Value, Equals, "-")
   982  }
   983  
   984  func (s *MySuite) TestCreateStepWithNewlineBetweenTextAndTable(c *C) {
   985  	tokens := []*Token{
   986  		{Kind: gauge.SpecKind, Value: "Spec Heading", LineNo: 1},
   987  		{Kind: gauge.ScenarioKind, Value: "Scenario Heading", LineNo: 2},
   988  		{Kind: gauge.StepKind, Value: "some random step\n", LineNo: 3},
   989  		{Kind: gauge.TableHeader, Args: []string{"id", "description"}, LineNo: 5},
   990  		{Kind: gauge.TableRow, Args: []string{"123", "Admin"}, LineNo: 6},
   991  		{Kind: gauge.TableRow, Args: []string{"456", "normal fellow"}, LineNo: 7},
   992  	}
   993  
   994  	conceptDictionary := gauge.NewConceptDictionary()
   995  	spec, _, err := new(SpecParser).CreateSpecification(tokens, conceptDictionary, "")
   996  	c.Assert(err, IsNil)
   997  	c.Assert(spec.Scenarios[0].Steps[0].HasInlineTable, Equals, true)
   998  }
   999  
  1000  func (s *MySuite) TestSpecParsingWhenSpecHeadingIsNotPresentAndDynamicParseError(c *C) {
  1001  	p := new(SpecParser)
  1002  
  1003  	_, res, err := p.Parse(`#
  1004  Scenario Heading
  1005  ----------------
  1006  * def <a>
  1007  `, gauge.NewConceptDictionary(), "foo.spec")
  1008  	c.Assert(err, IsNil)
  1009  	c.Assert(len(res.ParseErrors), Equals, 2)
  1010  	c.Assert(res.ParseErrors[0].Error(), Equals, "foo.spec:1 Spec heading should have at least one character => ''")
  1011  	c.Assert(res.ParseErrors[1].Error(), Equals, "foo.spec:4 Dynamic parameter <a> could not be resolved => 'def <a>'")
  1012  }
  1013  
  1014  func (s *MySuite) TestSpecParsingWhenSpecHeadingIsNotPresent(c *C) {
  1015  	p := new(SpecParser)
  1016  
  1017  	_, res, err := p.Parse(`#
  1018  Scenario Heading
  1019  ----------------
  1020  * def "sad"
  1021  `, gauge.NewConceptDictionary(), "foo.spec")
  1022  	c.Assert(err, IsNil)
  1023  	c.Assert(len(res.ParseErrors), Equals, 1)
  1024  	c.Assert(res.ParseErrors[0].Error(), Equals, "foo.spec:1 Spec heading should have at least one character => ''")
  1025  }
  1026  
  1027  func (s *MySuite) TestSpecParsingWhenUnderlinedSpecHeadingIsNotPresent(c *C) {
  1028  	p := new(SpecParser)
  1029  
  1030  	_, res, err := p.Parse(`======
  1031  Scenario Heading
  1032  ----------------
  1033  * def "sd"
  1034  `, gauge.NewConceptDictionary(), "foo.spec")
  1035  	c.Assert(err, IsNil)
  1036  	c.Assert(len(res.ParseErrors), Equals, 2)
  1037  	c.Assert(res.ParseErrors[0].Error(), Equals, "foo.spec:1 Spec heading not found => ''")
  1038  	c.Assert(res.ParseErrors[1].Error(), Equals, "foo.spec:2 Scenario should be defined after the spec heading => 'Scenario Heading'")
  1039  }
  1040  
  1041  func (s *MySuite) TestProcessingTokensGivesErrorWhenSpecHeadingHasOnlySpaces(c *C) {
  1042  	p := new(SpecParser)
  1043  
  1044  	_, res, err := p.Parse("#"+"           "+`
  1045  Scenario Heading
  1046  ----------------
  1047  * def "sd"
  1048  `, gauge.NewConceptDictionary(), "foo.spec")
  1049  	c.Assert(err, IsNil)
  1050  	c.Assert(len(res.ParseErrors), Equals, 1)
  1051  	c.Assert(res.ParseErrors[0].Error(), Equals, "foo.spec:1 Spec heading should have at least one character => ''")
  1052  }
  1053  
  1054  func (s *MySuite) TestProcessingTokensGivesErrorWhenScenarioHeadingIsEmpty(c *C) {
  1055  	p := new(SpecParser)
  1056  
  1057  	_, res, err := p.Parse(`# dfgdfg
  1058  ##
  1059  * def "sd"
  1060  `, gauge.NewConceptDictionary(), "foo.spec")
  1061  	c.Assert(err, IsNil)
  1062  	c.Assert(len(res.ParseErrors), Equals, 1)
  1063  	c.Assert(res.ParseErrors[0].Error(), Equals, "foo.spec:2 Scenario heading should have at least one character => ''")
  1064  }
  1065  
  1066  func (s *MySuite) TestProcessingTokensGivesErrorWhenScenarioHeadingHasOnlySpaces(c *C) {
  1067  	p := new(SpecParser)
  1068  
  1069  	_, res, err := p.Parse(`# dfgs
  1070  ##`+"           "+`
  1071  * def "sd"
  1072  `, gauge.NewConceptDictionary(), "foo.spec")
  1073  	c.Assert(err, IsNil)
  1074  	c.Assert(len(res.ParseErrors), Equals, 1)
  1075  	c.Assert(res.ParseErrors[0].Error(), Equals, "foo.spec:2 Scenario heading should have at least one character => ''")
  1076  }
  1077  
  1078  func (s *MySuite) TestScenarioProcessingToHaveScenarioSpan(c *C) {
  1079  	p := new(SpecParser)
  1080  
  1081  	spec, _, err := p.Parse(`# Spec 1
  1082  ## Scenario 1
  1083  * def "sd"
  1084  comment1
  1085  * def "sd"
  1086  
  1087  
  1088  ## Scenario 2
  1089  * def "sd"
  1090  comment2
  1091  * def "sd"
  1092  
  1093  
  1094  ## Scenario 3
  1095  * def "sd"
  1096  comment3
  1097  * def "sd"
  1098  `, gauge.NewConceptDictionary(), "")
  1099  	c.Assert(err, IsNil)
  1100  	c.Assert(len(spec.Scenarios), Equals, 3)
  1101  	c.Assert(spec.Scenarios[0].Span.Start, Equals, 2)
  1102  	c.Assert(spec.Scenarios[0].Span.End, Equals, 7)
  1103  	c.Assert(spec.Scenarios[1].Span.Start, Equals, 8)
  1104  	c.Assert(spec.Scenarios[1].Span.End, Equals, 13)
  1105  	c.Assert(spec.Scenarios[2].Span.Start, Equals, 14)
  1106  	c.Assert(spec.Scenarios[2].Span.End, Equals, 17)
  1107  }
  1108  
  1109  func TestParseScenarioWithDataTable(t *testing.T) {
  1110  	p := new(SpecParser)
  1111  	var subject = func() *gauge.Scenario {
  1112  		spec, _, err := p.Parse(`Specification Heading
  1113  		=====================
  1114  		* Vowels in English language are "aeiou".
  1115  		
  1116  		Vowel counts in single word
  1117  		---------------------------
  1118  		
  1119  			|Word  |Vowel Count|
  1120  			|------|-----------|
  1121  			|Gauge |3          |
  1122  			|Mingle|2          |
  1123  			|Snap  |1          |
  1124  			|GoCD  |1          |
  1125  			|Rhythm|0          |
  1126  		
  1127  		* The word <Word> has <Vowel Count> vowels.
  1128  		
  1129  		`, gauge.NewConceptDictionary(), "")
  1130  		if err != nil {
  1131  			t.Error(err)
  1132  		}
  1133  		return spec.Scenarios[0]
  1134  	}
  1135  
  1136  	t.Run("Parse Scenario with datatable when AllowScenarioDatatable=True", func(t *testing.T) {
  1137  		env.AllowScenarioDatatable = func() bool { return true }
  1138  		s := subject()
  1139  		v := len(s.DataTable.Table.Rows())
  1140  		if v != 5 {
  1141  			t.Errorf("expected scenario to have 5 rows, got %d", v)
  1142  		}
  1143  		v = len(s.DataTable.Table.Columns)
  1144  		if v != 2 {
  1145  			t.Errorf("expected scenario to have 2 columns, got %d", v)
  1146  		}
  1147  	})
  1148  
  1149  	t.Run("Parse Scenario with datatable when AllowScenarioDatatable=False", func(t *testing.T) {
  1150  		env.AllowScenarioDatatable = func() bool { return false }
  1151  		s := subject()
  1152  		v := len(s.DataTable.Table.Rows())
  1153  		if v != 0 {
  1154  			t.Errorf("expected scenario to have no rows, got %d", v)
  1155  		}
  1156  	})
  1157  }
  1158  
  1159  func TestParseScenarioWithExternalDataTable(t *testing.T) {
  1160  	p := new(SpecParser)
  1161  	var subject = func() *gauge.Scenario {
  1162  		spec, _, err := p.Parse(`Specification Heading
  1163  =====================
  1164  * Vowels in English language are "aeiou".
  1165  
  1166  Vowel counts in single word
  1167  ---------------------------
  1168  table:testdata/data.csv
  1169  
  1170  * The word <Word> has <Vowel Count> vowels.
  1171  
  1172  `, gauge.NewConceptDictionary(), "")
  1173  		if err != nil {
  1174  			t.Error(err)
  1175  		}
  1176  		return spec.Scenarios[0]
  1177  	}
  1178  
  1179  	t.Run("Parse Scenario with external datatable when AllowScenarioDatatable=True", func(t *testing.T) {
  1180  		env.AllowScenarioDatatable = func() bool { return true }
  1181  		s := subject()
  1182  		v := len(s.DataTable.Table.Rows())
  1183  		if v != 5 {
  1184  			t.Errorf("expected scenario to have 5 rows, got %d", v)
  1185  		}
  1186  		v = len(s.DataTable.Table.Columns)
  1187  		if v != 2 {
  1188  			t.Errorf("expected scenario to have 2 columns, got %d", v)
  1189  		}
  1190  	})
  1191  
  1192  	t.Run("Parse Scenario with datatable when AllowScenarioDatatable=False", func(t *testing.T) {
  1193  		env.AllowScenarioDatatable = func() bool { return false }
  1194  		s := subject()
  1195  		v := len(s.DataTable.Table.Rows())
  1196  		if v != 0 {
  1197  			t.Errorf("expected scenario to have no rows, got %d", v)
  1198  		}
  1199  	})
  1200  }
  1201  
  1202  func (s *MySuite) TestParsingWhenTearDownHAsOnlyTable(c *C) {
  1203  	p := new(SpecParser)
  1204  
  1205  	spec, _, err := p.Parse(`Specification Heading
  1206  =====================
  1207  * Vowels in English language are "aeiou".
  1208  
  1209  Vowel counts in single word
  1210  ---------------------------
  1211  * The word "gauge" has "3" vowels.
  1212  ___
  1213       |Word  |Vowel Count|
  1214       |------|-----------|
  1215       |Gauge |3          |
  1216       |Mingle|2          |
  1217       |Snap  |1          |
  1218       |GoCD  |1          |
  1219       |Rhythm|0          |
  1220  
  1221  `, gauge.NewConceptDictionary(), "")
  1222  	c.Assert(err, IsNil)
  1223  	c.Assert(len(spec.TearDownSteps), Equals, 0)
  1224  	c.Assert(len(spec.Comments), Equals, 7)
  1225  }
  1226  
  1227  func (s *MySuite) TestSpecWithRepeatedTagDefinitions(c *C) {
  1228  	p := new(SpecParser)
  1229  	spec, parseRes, err := p.Parse(`Spec Heading
  1230  ==============
  1231  tags: foo, bar
  1232  
  1233  * step
  1234  tags: blah
  1235  
  1236  Scenario
  1237  --------
  1238  * step
  1239  	`, gauge.NewConceptDictionary(), "")
  1240  	c.Assert(err, IsNil)
  1241  	c.Assert(len(parseRes.ParseErrors), Equals, 1)
  1242  	c.Assert(parseRes.ParseErrors[0].Message, Equals, "Tags can be defined only once per specification")
  1243  	c.Assert(len(spec.Tags.Values()), Equals, 2)
  1244  	c.Assert(spec.Tags.Values()[0], Equals, "foo")
  1245  	c.Assert(spec.Tags.Values()[1], Equals, "bar")
  1246  }
  1247  
  1248  func (s *MySuite) TestScenarioWithRepeatedTagDefinitions(c *C) {
  1249  	p := new(SpecParser)
  1250  	spec, parseRes, err := p.Parse(`Spec Heading
  1251  ==============
  1252  tags: tag1
  1253  
  1254  * step
  1255  
  1256  Scenario
  1257  --------
  1258  tags: foo, bar
  1259  * step
  1260  tags: blah
  1261  	`, gauge.NewConceptDictionary(), "")
  1262  	c.Assert(err, IsNil)
  1263  	c.Assert(len(parseRes.ParseErrors), Equals, 1)
  1264  	c.Assert(parseRes.ParseErrors[0].Message, Equals, "Tags can be defined only once per scenario")
  1265  	c.Assert(len(spec.Scenarios[0].Tags.Values()), Equals, 2)
  1266  	c.Assert(spec.Scenarios[0].Tags.Values()[0], Equals, "foo")
  1267  	c.Assert(spec.Scenarios[0].Tags.Values()[1], Equals, "bar")
  1268  	c.Assert(len(spec.Tags.Values()), Equals, 1)
  1269  	c.Assert(spec.Tags.Values()[0], Equals, "tag1")
  1270  }
  1271  
  1272  func (s *MySuite) TestDatatTableWithEmptyHeaders(c *C) {
  1273  	p := new(SpecParser)
  1274  	_, parseRes, err := p.Parse(`Something
  1275  =========
  1276  
  1277       ||a|||a|
  1278       |-------|
  1279       |dsf|dsf|dsf|dsf|dsf|
  1280  
  1281  Scenario Heading
  1282  ----------------
  1283  * Vowels in English language are "aeiou".
  1284  `, gauge.NewConceptDictionary(), "")
  1285  	c.Assert(err, IsNil)
  1286  	c.Assert(len(parseRes.ParseErrors), Equals, 4)
  1287  	c.Assert(parseRes.ParseErrors[0].Message, Equals, "Table header should not be blank")
  1288  	c.Assert(parseRes.ParseErrors[1].Message, Equals, "Table header should not be blank")
  1289  	c.Assert(parseRes.ParseErrors[2].Message, Equals, "Table header should not be blank")
  1290  	c.Assert(parseRes.ParseErrors[3].Message, Equals, "Table header cannot have repeated column values")
  1291  }
  1292  
  1293  func (s *MySuite) TestExtractStepArgsFromToken(c *C) {
  1294  	token := &Token{Kind: gauge.StepKind, Lines: []string{`my step with "Static" and <Dynamic> params`}, Value: `my step with {static} and {dynamic} params`, Args: []string{"Static", "Dynamic"}}
  1295  
  1296  	args, err := ExtractStepArgsFromToken(token)
  1297  	if err != nil {
  1298  		c.Fatalf("Error while extracting step args : %s", err.Error())
  1299  	}
  1300  	c.Assert(len(args), Equals, 2)
  1301  	c.Assert(args[0].Value, Equals, "Static")
  1302  	c.Assert(args[0].ArgType, Equals, gauge.Static)
  1303  	c.Assert(args[1].Value, Equals, "Dynamic")
  1304  	c.Assert(args[1].ArgType, Equals, gauge.Dynamic)
  1305  }
  1306  
  1307  func (s *MySuite) TestParsingTableParameterWithSpecialString(c *C) {
  1308  	parser := new(SpecParser)
  1309  	specText := newSpecBuilder().specHeading("Spec Heading").scenarioHeading("First scenario").step("my step").text("|name|id|").text("|---|---|").text("|john|123|").text("|james|<file:testdata/foo.txt>|").String()
  1310  
  1311  	spec, res := parser.ParseSpecText(specText, "")
  1312  	c.Assert(res.Ok, Equals, true)
  1313  	c.Assert(spec.Scenarios[0].Steps[0].Args[0].ArgType, Equals, gauge.TableArg)
  1314  
  1315  	c.Assert(spec.Scenarios[0].Steps[0].Args[0].Table.Columns[0][0].Value, Equals, "john")
  1316  	c.Assert(spec.Scenarios[0].Steps[0].Args[0].Table.Columns[0][0].CellType, Equals, gauge.Static)
  1317  
  1318  	c.Assert(spec.Scenarios[0].Steps[0].Args[0].Table.Columns[0][1].Value, Equals, "james")
  1319  	c.Assert(spec.Scenarios[0].Steps[0].Args[0].Table.Columns[0][1].CellType, Equals, gauge.Static)
  1320  
  1321  	c.Assert(spec.Scenarios[0].Steps[0].Args[0].Table.Columns[1][0].Value, Equals, "123")
  1322  	c.Assert(spec.Scenarios[0].Steps[0].Args[0].Table.Columns[1][0].CellType, Equals, gauge.Static)
  1323  
  1324  	c.Assert(spec.Scenarios[0].Steps[0].Args[0].Table.Columns[1][1].Value, Equals, "file:testdata/foo.txt")
  1325  	c.Assert(spec.Scenarios[0].Steps[0].Args[0].Table.Columns[1][1].CellType, Equals, gauge.SpecialString)
  1326  }
  1327  
  1328  func (s *MySuite) TestParsingDataTableWithSpecialString(c *C) {
  1329  	parser := new(SpecParser)
  1330  	specText := newSpecBuilder().specHeading("Spec heading").text("|name|id|").text("|---|---|").text("|john|123|").text("|james|<file:testdata/foo.txt>|").String()
  1331  
  1332  	specs, res := parser.ParseSpecText(specText, "")
  1333  	c.Assert(res.Ok, Equals, true)
  1334  	c.Assert(specs.DataTable.Table.Columns[0][0].Value, Equals, "john")
  1335  	c.Assert(specs.DataTable.Table.Columns[0][0].CellType, Equals, gauge.Static)
  1336  
  1337  	c.Assert(specs.DataTable.Table.Columns[0][1].Value, Equals, "james")
  1338  	c.Assert(specs.DataTable.Table.Columns[0][1].CellType, Equals, gauge.Static)
  1339  
  1340  	c.Assert(specs.DataTable.Table.Columns[1][0].Value, Equals, "123")
  1341  	c.Assert(specs.DataTable.Table.Columns[1][0].CellType, Equals, gauge.Static)
  1342  
  1343  	c.Assert(specs.DataTable.Table.Columns[1][1].Value, Equals, "file:testdata/foo.txt")
  1344  	c.Assert(specs.DataTable.Table.Columns[1][1].CellType, Equals, gauge.SpecialString)
  1345  }
  1346  
  1347  func (s *MySuite) TestTableForSpecialParameterWhenFileIsNotFound(c *C) {
  1348  	parser := new(SpecParser)
  1349  	specText := newSpecBuilder().specHeading("Spec Heading").scenarioHeading("First scenario").step("my step").text("|name|id|").text("|---|---|").text("|john|123|").text("|james|<file:notFound.txt>|").String()
  1350  
  1351  	_, res := parser.ParseSpecText(specText, "")
  1352  
  1353  	c.Assert(res.Ok, Equals, false)
  1354  	c.Assert(res.ParseErrors[0].Message, Equals, "Dynamic param <file:notFound.txt> could not be resolved, Missing file: notFound.txt")
  1355  	c.Assert(res.ParseErrors[0].LineText, Equals, "|james|<file:notFound.txt>|")
  1356  }
  1357  
  1358  func (s *MySuite) TestDataTableForSpecialParameterWhenFileIsNotFound(c *C) {
  1359  	parser := new(SpecParser)
  1360  	specText := newSpecBuilder().specHeading("Spec heading").text("|name|id|").text("|---|---|").text("|john|123|").text("|james|<file:notFound.txt>|").String()
  1361  
  1362  	_, res := parser.ParseSpecText(specText, "")
  1363  
  1364  	c.Assert(res.Ok, Equals, false)
  1365  	c.Assert(res.ParseErrors[0].Message, Equals, "Dynamic param <file:notFound.txt> could not be resolved, Missing file: notFound.txt")
  1366  	c.Assert(res.ParseErrors[0].LineText, Equals, "|james|<file:notFound.txt>|")
  1367  }