github.com/mattdotmatt/gauge@v0.3.2-0.20160421115137-425a4cdccb62/parser/conceptParser_test.go (about)

     1  // Copyright 2015 ThoughtWorks, Inc.
     2  
     3  // This file is part of Gauge.
     4  
     5  // Gauge is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  
    10  // Gauge is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU General Public License for more details.
    14  
    15  // You should have received a copy of the GNU General Public License
    16  // along with Gauge.  If not, see <http://www.gnu.org/licenses/>.
    17  
    18  package parser
    19  
    20  import (
    21  	"os"
    22  	"path/filepath"
    23  	"strings"
    24  
    25  	"github.com/getgauge/gauge/config"
    26  	"github.com/getgauge/gauge/gauge"
    27  
    28  	. "gopkg.in/check.v1"
    29  )
    30  
    31  func assertStepEqual(c *C, expected, actual *gauge.Step) {
    32  	c.Assert(expected.LineNo, Equals, actual.LineNo)
    33  	c.Assert(expected.Value, Equals, actual.Value)
    34  	c.Assert(expected.LineText, Equals, actual.LineText)
    35  }
    36  
    37  func (s *MySuite) TestConceptDictionaryAdd(c *C) {
    38  	dictionary := gauge.NewConceptDictionary()
    39  	step1Text := "test concept step 1"
    40  	step2Text := "test concept step 2"
    41  	step1 := &gauge.Step{Value: step1Text, LineNo: 1, IsConcept: true, LineText: step1Text}
    42  	step2 := &gauge.Step{Value: step2Text, LineNo: 4, IsConcept: true, LineText: step2Text}
    43  	path, _ := filepath.Abs(filepath.Join("testdata", "concept.cpt"))
    44  
    45  	err := AddConcepts(path, dictionary)
    46  
    47  	c.Assert(err, IsNil)
    48  	assertStepEqual(c, dictionary.ConceptsMap[step1Text].ConceptStep, step1)
    49  	c.Assert(dictionary.ConceptsMap[step1Text].FileName, Equals, path)
    50  	assertStepEqual(c, dictionary.ConceptsMap[step2Text].ConceptStep, step2)
    51  	c.Assert(dictionary.ConceptsMap[step2Text].FileName, Equals, path)
    52  }
    53  
    54  func (s *MySuite) TestConceptDictionaryAddDuplicateConcept(c *C) {
    55  	dictionary := gauge.NewConceptDictionary()
    56  	path, _ := filepath.Abs(filepath.Join("testdata", "duplicate_concept.cpt"))
    57  
    58  	err := AddConcepts(path, dictionary)
    59  
    60  	c.Assert(err, NotNil)
    61  	c.Assert(err.Message, Equals, "Duplicate concept definition found")
    62  }
    63  
    64  func (s *MySuite) TestCreateConceptDictionary(c *C) {
    65  	config.ProjectRoot, _ = filepath.Abs("testdata")
    66  	oldWd, _ := os.Getwd()
    67  	os.Chdir(config.ProjectRoot)
    68  	cpt := "dir1"
    69  
    70  	dict, res := CreateConceptsDictionary(false, []string{cpt, cpt})
    71  	os.Chdir(oldWd)
    72  
    73  	c.Assert(res.Ok, Equals, true)
    74  	c.Assert(dict, NotNil)
    75  	c.Assert(len(dict.ConceptsMap), Equals, 1)
    76  }
    77  
    78  func (s *MySuite) TestConceptDictionaryWithNestedConcepts(c *C) {
    79  	dictionary := gauge.NewConceptDictionary()
    80  	path, _ := filepath.Abs(filepath.Join("testdata", "nested_concept.cpt"))
    81  
    82  	AddConcepts(path, dictionary)
    83  	concept := dictionary.Search("test concept step 1")
    84  
    85  	c.Assert(len(concept.ConceptStep.ConceptSteps), Equals, 1)
    86  
    87  	actualNestedConcept := concept.ConceptStep.ConceptSteps[0]
    88  	c.Assert(actualNestedConcept.IsConcept, Equals, true)
    89  	c.Assert(len(actualNestedConcept.ConceptSteps), Equals, 1)
    90  	c.Assert(actualNestedConcept.ConceptSteps[0].Value, Equals, "step 2")
    91  }
    92  
    93  func (s *MySuite) TestConceptDictionaryWithNestedConceptsWithDynamicParameters(c *C) {
    94  	conceptDictionary := gauge.NewConceptDictionary()
    95  	path, _ := filepath.Abs(filepath.Join("testdata", "dynamic_param_concept.cpt"))
    96  
    97  	AddConcepts(path, conceptDictionary)
    98  	concept := conceptDictionary.Search("create user {} {} and {}")
    99  	c.Assert(len(concept.ConceptStep.ConceptSteps), Equals, 1)
   100  	actualNestedConcept := concept.ConceptStep.ConceptSteps[0]
   101  	c.Assert(actualNestedConcept.IsConcept, Equals, true)
   102  
   103  	c.Assert(len(actualNestedConcept.ConceptSteps), Equals, 2)
   104  	c.Assert(actualNestedConcept.ConceptSteps[0].Value, Equals, "add id {}")
   105  	c.Assert(actualNestedConcept.ConceptSteps[0].Args[0].ArgType, Equals, gauge.Dynamic)
   106  	c.Assert(actualNestedConcept.ConceptSteps[0].Args[0].Value, Equals, "userid")
   107  
   108  	c.Assert(actualNestedConcept.ConceptSteps[1].Value, Equals, "add name {}")
   109  	c.Assert(actualNestedConcept.ConceptSteps[1].Args[0].ArgType, Equals, gauge.Dynamic)
   110  	c.Assert(actualNestedConcept.ConceptSteps[1].Args[0].Value, Equals, "username")
   111  }
   112  
   113  func (s *MySuite) TestConceptDictionaryWithNestedConceptsWithStaticParameters(c *C) {
   114  	conceptDictionary := gauge.NewConceptDictionary()
   115  	path, _ := filepath.Abs(filepath.Join("testdata", "static_param_concept.cpt"))
   116  
   117  	AddConcepts(path, conceptDictionary)
   118  	concept := conceptDictionary.Search("create user {} {} and {}")
   119  	c.Assert(len(concept.ConceptStep.ConceptSteps), Equals, 2)
   120  	actualNestedConcept := concept.ConceptStep.ConceptSteps[0]
   121  	c.Assert(actualNestedConcept.IsConcept, Equals, true)
   122  
   123  	c.Assert(actualNestedConcept.Args[0].ArgType, Equals, gauge.Dynamic)
   124  	c.Assert(actualNestedConcept.Args[0].Value, Equals, "user-id")
   125  
   126  	c.Assert(actualNestedConcept.Args[1].ArgType, Equals, gauge.Static)
   127  	c.Assert(actualNestedConcept.Args[1].Value, Equals, "static-value")
   128  	c.Assert(actualNestedConcept.Lookup.GetArg("userid").Value, Equals, "user-id")
   129  	c.Assert(actualNestedConcept.Lookup.GetArg("userid").ArgType, Equals, gauge.Dynamic)
   130  	c.Assert(actualNestedConcept.Lookup.GetArg("username").Value, Equals, "static-value")
   131  	c.Assert(actualNestedConcept.Lookup.GetArg("username").ArgType, Equals, gauge.Static)
   132  
   133  	c.Assert(len(actualNestedConcept.ConceptSteps), Equals, 2)
   134  	c.Assert(actualNestedConcept.ConceptSteps[0].Value, Equals, "add id {}")
   135  	c.Assert(actualNestedConcept.ConceptSteps[0].Args[0].ArgType, Equals, gauge.Dynamic)
   136  	c.Assert(actualNestedConcept.ConceptSteps[0].Args[0].Value, Equals, "userid")
   137  
   138  	c.Assert(actualNestedConcept.ConceptSteps[1].Value, Equals, "add name {}")
   139  	c.Assert(actualNestedConcept.ConceptSteps[1].Args[0].ArgType, Equals, gauge.Dynamic)
   140  	c.Assert(actualNestedConcept.ConceptSteps[1].Args[0].Value, Equals, "username")
   141  }
   142  
   143  func (s *MySuite) TestConceptHavingItemsWithComments(c *C) {
   144  	conceptDictionary := gauge.NewConceptDictionary()
   145  	path, _ := filepath.Abs(filepath.Join("testdata", "dynamic_param_concept.cpt"))
   146  
   147  	AddConcepts(path, conceptDictionary)
   148  	concept := conceptDictionary.Search("create user {} {} and {}")
   149  
   150  	c.Assert(len(concept.ConceptStep.Items), Equals, 3)
   151  	c.Assert(concept.ConceptStep.Items[2].(*gauge.Comment).Value, Equals, "Comments")
   152  
   153  	concept = conceptDictionary.Search("assign id {} and name {}")
   154  
   155  	c.Assert(len(concept.ConceptStep.Items), Equals, 4)
   156  	c.Assert(concept.ConceptStep.Items[3].(*gauge.Comment).Value, Equals, "Comment1")
   157  }
   158  
   159  func (s *MySuite) TestConceptHavingItemsWithTablesAndComments(c *C) {
   160  	conceptDictionary := gauge.NewConceptDictionary()
   161  	path, _ := filepath.Abs(filepath.Join("testdata", "tabular_concept.cpt"))
   162  
   163  	AddConcepts(path, conceptDictionary)
   164  
   165  	concept := conceptDictionary.Search("my concept {}")
   166  	c.Assert(len(concept.ConceptStep.Items), Equals, 3)
   167  	c.Assert(len(concept.ConceptStep.PreComments), Equals, 1)
   168  	c.Assert(concept.ConceptStep.PreComments[0].Value, Equals, "COMMENT")
   169  	c.Assert(concept.ConceptStep.Items[2].(*gauge.Comment).Value, Equals, "   comment")
   170  }
   171  
   172  func (s *MySuite) TestMultiLevelConcept(c *C) {
   173  	conceptDictionary := gauge.NewConceptDictionary()
   174  	path, _ := filepath.Abs(filepath.Join("testdata", "nested_concept2.cpt"))
   175  
   176  	AddConcepts(path, conceptDictionary)
   177  	actualTopLevelConcept := conceptDictionary.Search("top level concept")
   178  	c.Assert(len(actualTopLevelConcept.ConceptStep.ConceptSteps), Equals, 2)
   179  	actualNestedConcept := actualTopLevelConcept.ConceptStep.ConceptSteps[0]
   180  	c.Assert(actualNestedConcept.IsConcept, Equals, true)
   181  	c.Assert(len(actualNestedConcept.ConceptSteps), Equals, 2)
   182  	c.Assert(actualNestedConcept.ConceptSteps[0].Value, Equals, "another nested concept")
   183  	c.Assert(actualNestedConcept.ConceptSteps[1].Value, Equals, "normal step 2")
   184  	c.Assert(actualTopLevelConcept.ConceptStep.ConceptSteps[1].Value, Equals, "normal step 1")
   185  
   186  	actualAnotherNestedConcept := conceptDictionary.Search("another nested concept")
   187  	c.Assert(len(actualAnotherNestedConcept.ConceptStep.ConceptSteps), Equals, 1)
   188  	step := actualAnotherNestedConcept.ConceptStep.ConceptSteps[0]
   189  	c.Assert(step.IsConcept, Equals, false)
   190  	c.Assert(step.Value, Equals, "normal step 3")
   191  
   192  	nestedConcept2 := conceptDictionary.Search("nested concept")
   193  	c.Assert(len(nestedConcept2.ConceptStep.ConceptSteps), Equals, 2)
   194  	actualAnotherNestedConcept2 := nestedConcept2.ConceptStep.ConceptSteps[0]
   195  	c.Assert(actualAnotherNestedConcept2.IsConcept, Equals, true)
   196  	c.Assert(len(actualAnotherNestedConcept2.ConceptSteps), Equals, 1)
   197  	c.Assert(actualAnotherNestedConcept2.ConceptSteps[0].Value, Equals, "normal step 3")
   198  	c.Assert(nestedConcept2.ConceptStep.ConceptSteps[1].Value, Equals, "normal step 2")
   199  }
   200  
   201  func (s *MySuite) TestParsingSimpleConcept(c *C) {
   202  	parser := new(ConceptParser)
   203  	concepts, parseRes := parser.Parse("# my concept \n * first step \n * second step ")
   204  
   205  	c.Assert(parseRes.Error, IsNil)
   206  	c.Assert(len(concepts), Equals, 1)
   207  
   208  	concept := concepts[0]
   209  
   210  	c.Assert(concept.IsConcept, Equals, true)
   211  	c.Assert(len(concept.ConceptSteps), Equals, 2)
   212  	c.Assert(concept.ConceptSteps[0].Value, Equals, "first step")
   213  	c.Assert(concept.ConceptSteps[1].Value, Equals, "second step")
   214  
   215  }
   216  
   217  func (s *MySuite) TestErrorParsingConceptHeadingWithStaticOrSpecialParameter(c *C) {
   218  	parser := new(ConceptParser)
   219  	_, parseRes := parser.Parse("# my concept with \"paratemer\" \n * first step \n * second step ")
   220  	c.Assert(parseRes.Error, NotNil)
   221  	c.Assert(parseRes.Error.Message, Equals, "Concept heading can have only Dynamic Parameters")
   222  
   223  	_, parseRes = parser.Parse("# my concept with <table: foo> \n * first step \n * second step ")
   224  	c.Assert(parseRes.Error, NotNil)
   225  	c.Assert(parseRes.Error.Message, Equals, "Dynamic parameter <table: foo> could not be resolved")
   226  
   227  }
   228  
   229  func (s *MySuite) TestErrorParsingConceptWithoutHeading(c *C) {
   230  	parser := new(ConceptParser)
   231  
   232  	_, parseRes := parser.Parse("* first step \n * second step ")
   233  
   234  	c.Assert(parseRes.Error, NotNil)
   235  	c.Assert(parseRes.Error.Message, Equals, "Step is not defined inside a concept heading")
   236  }
   237  
   238  func (s *MySuite) TestErrorParsingConceptWithoutSteps(c *C) {
   239  	parser := new(ConceptParser)
   240  
   241  	_, parseRes := parser.Parse("# my concept with \n")
   242  
   243  	c.Assert(parseRes.Error, NotNil)
   244  	c.Assert(parseRes.Error.Message, Equals, "Concept should have atleast one step")
   245  }
   246  
   247  func (s *MySuite) TestParsingSimpleConceptWithParameters(c *C) {
   248  	parser := new(ConceptParser)
   249  	concepts, parseRes := parser.Parse("# my concept with <param0> and <param1> \n * first step using <param0> \n * second step using \"value\" and <param1> ")
   250  
   251  	c.Assert(parseRes.Error, IsNil)
   252  	c.Assert(len(concepts), Equals, 1)
   253  
   254  	concept := concepts[0]
   255  	c.Assert(concept.IsConcept, Equals, true)
   256  	c.Assert(len(concept.ConceptSteps), Equals, 2)
   257  	// c.Assert(len(concept.Lookup.paramValue), Equals, 2)
   258  	c.Assert(concept.Lookup.ContainsArg("param0"), Equals, true)
   259  	c.Assert(concept.Lookup.ContainsArg("param1"), Equals, true)
   260  
   261  	firstConcept := concept.ConceptSteps[0]
   262  	c.Assert(firstConcept.Value, Equals, "first step using {}")
   263  	c.Assert(len(firstConcept.Args), Equals, 1)
   264  	c.Assert(firstConcept.Args[0].ArgType, Equals, gauge.Dynamic)
   265  	c.Assert(firstConcept.Args[0].Value, Equals, "param0")
   266  
   267  	secondConcept := concept.ConceptSteps[1]
   268  	c.Assert(secondConcept.Value, Equals, "second step using {} and {}")
   269  	c.Assert(len(secondConcept.Args), Equals, 2)
   270  	c.Assert(secondConcept.Args[0].ArgType, Equals, gauge.Static)
   271  	c.Assert(secondConcept.Args[0].Value, Equals, "value")
   272  	c.Assert(secondConcept.Args[1].ArgType, Equals, gauge.Dynamic)
   273  	c.Assert(secondConcept.Args[1].Value, Equals, "param1")
   274  
   275  }
   276  
   277  func (s *MySuite) TestErrorParsingConceptWithRecursiveCallToConcept(c *C) {
   278  	parser := new(ConceptParser)
   279  	_, parseRes := parser.Parse("# my concept \n * first step using \n * my concept ")
   280  
   281  	c.Assert(parseRes.Error, NotNil)
   282  	c.Assert(parseRes.Error.Message, Equals, "Cyclic dependancy found. Step is calling concept again.")
   283  }
   284  
   285  func (s *MySuite) TestErrorParsingConceptStepWithInvalidParameters(c *C) {
   286  	parser := new(ConceptParser)
   287  	_, parseRes := parser.Parse("# my concept with <param0> and <param1> \n * first step using <param3> \n * second step using \"value\" and <param1> ")
   288  
   289  	c.Assert(parseRes.Error, NotNil)
   290  	c.Assert(parseRes.Error.Message, Equals, "Dynamic parameter <param3> could not be resolved")
   291  }
   292  
   293  func (s *MySuite) TestParsingMultipleConcept(c *C) {
   294  	parser := new(ConceptParser)
   295  	concepts, parseRes := parser.Parse("# my concept \n * first step \n * second step \n# my second concept \n* next step\n # my third concept <param0>\n * next step <param0> and \"value\"\n  ")
   296  
   297  	c.Assert(parseRes.Error, IsNil)
   298  	c.Assert(len(concepts), Equals, 3)
   299  
   300  	firstConcept := concepts[0]
   301  	secondConcept := concepts[1]
   302  	thirdConcept := concepts[2]
   303  
   304  	c.Assert(firstConcept.IsConcept, Equals, true)
   305  	c.Assert(len(firstConcept.ConceptSteps), Equals, 2)
   306  	c.Assert(firstConcept.ConceptSteps[0].Value, Equals, "first step")
   307  	c.Assert(firstConcept.ConceptSteps[1].Value, Equals, "second step")
   308  
   309  	c.Assert(secondConcept.IsConcept, Equals, true)
   310  	c.Assert(len(secondConcept.ConceptSteps), Equals, 1)
   311  	c.Assert(secondConcept.ConceptSteps[0].Value, Equals, "next step")
   312  
   313  	c.Assert(thirdConcept.IsConcept, Equals, true)
   314  	c.Assert(len(thirdConcept.ConceptSteps), Equals, 1)
   315  	c.Assert(thirdConcept.ConceptSteps[0].Value, Equals, "next step {} and {}")
   316  	c.Assert(len(thirdConcept.ConceptSteps[0].Args), Equals, 2)
   317  	c.Assert(thirdConcept.ConceptSteps[0].Args[0].ArgType, Equals, gauge.Dynamic)
   318  	c.Assert(thirdConcept.ConceptSteps[0].Args[1].ArgType, Equals, gauge.Static)
   319  
   320  	// c.Assert(len(thirdConcept.Lookup.paramValue), Equals, 1)
   321  	c.Assert(thirdConcept.Lookup.ContainsArg("param0"), Equals, true)
   322  
   323  }
   324  
   325  func (s *MySuite) TestParsingConceptStepWithInlineTable(c *C) {
   326  	parser := new(ConceptParser)
   327  	concepts, parseRes := parser.Parse("# my concept <foo> \n * first step with <foo> and inline table\n |id|name|\n|1|vishnu|\n|2|prateek|\n")
   328  
   329  	c.Assert(parseRes.Error, IsNil)
   330  	c.Assert(len(concepts), Equals, 1)
   331  
   332  	concept := concepts[0]
   333  
   334  	c.Assert(concept.IsConcept, Equals, true)
   335  	c.Assert(len(concept.ConceptSteps), Equals, 1)
   336  	c.Assert(concept.ConceptSteps[0].Value, Equals, "first step with {} and inline table {}")
   337  
   338  	tableArgument := concept.ConceptSteps[0].Args[1]
   339  	c.Assert(tableArgument.ArgType, Equals, gauge.TableArg)
   340  
   341  	inlineTable := tableArgument.Table
   342  	c.Assert(inlineTable.IsInitialized(), Equals, true)
   343  	c.Assert(len(inlineTable.Get("id")), Equals, 2)
   344  	c.Assert(len(inlineTable.Get("name")), Equals, 2)
   345  	c.Assert(inlineTable.Get("id")[0].Value, Equals, "1")
   346  	c.Assert(inlineTable.Get("id")[0].CellType, Equals, gauge.Static)
   347  	c.Assert(inlineTable.Get("id")[1].Value, Equals, "2")
   348  	c.Assert(inlineTable.Get("id")[1].CellType, Equals, gauge.Static)
   349  	c.Assert(inlineTable.Get("name")[0].Value, Equals, "vishnu")
   350  	c.Assert(inlineTable.Get("name")[0].CellType, Equals, gauge.Static)
   351  	c.Assert(inlineTable.Get("name")[1].Value, Equals, "prateek")
   352  	c.Assert(inlineTable.Get("name")[1].CellType, Equals, gauge.Static)
   353  }
   354  
   355  func (s *MySuite) TestErrorParsingConceptWithInvalidInlineTable(c *C) {
   356  	parser := new(ConceptParser)
   357  	_, parseRes := parser.Parse("# my concept \n |id|name|\n|1|vishnu|\n|2|prateek|\n")
   358  
   359  	c.Assert(parseRes.Error, NotNil)
   360  	c.Assert(parseRes.Error.Message, Equals, "Table doesn't belong to any step")
   361  }
   362  
   363  func (s *MySuite) TestNestedConceptLooksUpArgsFromParent(c *C) {
   364  	parser := new(SpecParser)
   365  	specText := SpecBuilder().specHeading("A spec heading").
   366  		scenarioHeading("First flow").
   367  		step("create user \"foo\" \"doo\"").
   368  		step("another step").String()
   369  
   370  	dictionary := gauge.NewConceptDictionary()
   371  	path, _ := filepath.Abs(filepath.Join("testdata", "param_nested_concept.cpt"))
   372  
   373  	AddConcepts(path, dictionary)
   374  	tokens, _ := parser.GenerateTokens(specText)
   375  	spec, parseResult := parser.CreateSpecification(tokens, dictionary)
   376  
   377  	c.Assert(parseResult.Ok, Equals, true)
   378  	firstStepInSpec := spec.Scenarios[0].Steps[0]
   379  	nestedConcept := firstStepInSpec.ConceptSteps[0]
   380  	nestedConceptArg1 := nestedConcept.GetArg("baz")
   381  	c.Assert(nestedConceptArg1.Value, Equals, "foo")
   382  	nestedConceptArg2 := nestedConcept.GetArg("boo")
   383  	c.Assert(nestedConceptArg2.Value, Equals, "doo")
   384  }
   385  
   386  func (s *MySuite) TestNestedConceptLooksUpDataTableArgs(c *C) {
   387  	parser := new(SpecParser)
   388  	specText := SpecBuilder().specHeading("A spec heading").
   389  		tableHeader("id", "name", "phone").
   390  		tableHeader("123", "prateek", "8800").
   391  		tableHeader("456", "apoorva", "9800").
   392  		tableHeader("789", "srikanth", "7900").
   393  		scenarioHeading("First scenario").
   394  		step("create user <id> <name>").
   395  		step("another step").String()
   396  
   397  	dictionary := gauge.NewConceptDictionary()
   398  	path, _ := filepath.Abs(filepath.Join("testdata", "param_nested_concept.cpt"))
   399  
   400  	AddConcepts(path, dictionary)
   401  
   402  	tokens, _ := parser.GenerateTokens(specText)
   403  	spec, parseResult := parser.CreateSpecification(tokens, dictionary)
   404  
   405  	c.Assert(parseResult.Ok, Equals, true)
   406  
   407  	firstStepInSpec := spec.Scenarios[0].Steps[0]
   408  	c.Assert(firstStepInSpec.IsConcept, Equals, true)
   409  	c.Assert(firstStepInSpec.GetArg("bar").ArgType, Equals, gauge.Dynamic)
   410  	c.Assert(firstStepInSpec.GetArg("far").ArgType, Equals, gauge.Dynamic)
   411  	c.Assert(firstStepInSpec.GetArg("bar").Value, Equals, "id")
   412  	c.Assert(firstStepInSpec.GetArg("far").Value, Equals, "name")
   413  
   414  	nestedConcept := firstStepInSpec.ConceptSteps[0]
   415  	c.Assert(nestedConcept.GetArg("baz").ArgType, Equals, gauge.Dynamic)
   416  	c.Assert(nestedConcept.GetArg("boo").ArgType, Equals, gauge.Dynamic)
   417  	c.Assert(nestedConcept.GetArg("baz").Value, Equals, "id")
   418  	c.Assert(nestedConcept.GetArg("boo").Value, Equals, "name")
   419  
   420  }
   421  
   422  func (s *MySuite) TestNestedConceptLooksUpWhenParameterPlaceholdersAreSame(c *C) {
   423  	parser := new(SpecParser)
   424  	specText := SpecBuilder().specHeading("A spec heading").
   425  		tableHeader("id", "name", "phone").
   426  		tableHeader("123", "prateek", "8800").
   427  		tableHeader("456", "apoorva", "9800").
   428  		tableHeader("789", "srikanth", "7900").
   429  		scenarioHeading("First scenario").
   430  		step("create user <id> <name> and <phone>").
   431  		step("another step").String()
   432  
   433  	dictionary := gauge.NewConceptDictionary()
   434  	path, _ := filepath.Abs(filepath.Join("testdata", "param_nested_concept2.cpt"))
   435  
   436  	AddConcepts(path, dictionary)
   437  
   438  	tokens, _ := parser.GenerateTokens(specText)
   439  	spec, parseResult := parser.CreateSpecification(tokens, dictionary)
   440  
   441  	c.Assert(parseResult.Ok, Equals, true)
   442  
   443  	firstStepInSpec := spec.Scenarios[0].Steps[0]
   444  	c.Assert(firstStepInSpec.IsConcept, Equals, true)
   445  	c.Assert(firstStepInSpec.GetArg("user-id").ArgType, Equals, gauge.Dynamic)
   446  	c.Assert(firstStepInSpec.GetArg("user-name").ArgType, Equals, gauge.Dynamic)
   447  	c.Assert(firstStepInSpec.GetArg("user-phone").ArgType, Equals, gauge.Dynamic)
   448  	c.Assert(firstStepInSpec.GetArg("user-id").Value, Equals, "id")
   449  	c.Assert(firstStepInSpec.GetArg("user-name").Value, Equals, "name")
   450  	c.Assert(firstStepInSpec.GetArg("user-phone").Value, Equals, "phone")
   451  
   452  	nestedConcept := firstStepInSpec.ConceptSteps[0]
   453  	c.Assert(nestedConcept.GetArg("user-id").ArgType, Equals, gauge.Dynamic)
   454  	c.Assert(nestedConcept.GetArg("user-name").ArgType, Equals, gauge.Dynamic)
   455  	c.Assert(nestedConcept.GetArg("user-id").Value, Equals, "id")
   456  	c.Assert(nestedConcept.GetArg("user-name").Value, Equals, "name")
   457  
   458  }
   459  
   460  func (s *MySuite) TestErrorOnCircularReferenceInConcept(c *C) {
   461  	dictionary := gauge.NewConceptDictionary()
   462  	path, _ := filepath.Abs(filepath.Join("testdata", "circular_concept.cpt"))
   463  
   464  	err := AddConcepts(path, dictionary)
   465  
   466  	c.Assert(err, NotNil)
   467  	c.Assert(true, Equals, strings.Contains(err.Message, "Circular reference found in concept"))
   468  }
   469  
   470  func (s *MySuite) TestConceptHavingDynamicParameters(c *C) {
   471  	conceptText := SpecBuilder().
   472  		specHeading("create user <user:id> <user:name> and <file>").
   473  		step("a step <user:id>").String()
   474  	step, _ := new(ConceptParser).Parse(conceptText)
   475  	c.Assert(step[0].LineText, Equals, "create user <user:id> <user:name> and <file>")
   476  	c.Assert(step[0].Args[0].ArgType, Equals, gauge.Dynamic)
   477  	c.Assert(step[0].Args[1].ArgType, Equals, gauge.Dynamic)
   478  	c.Assert(step[0].Args[2].ArgType, Equals, gauge.Dynamic)
   479  }
   480  
   481  func (s *MySuite) TestConceptHavingInvalidSpecialParameters(c *C) {
   482  	conceptText := SpecBuilder().
   483  		specHeading("create user <user:id> <table:name> and <file>").
   484  		step("a step <user:id>").String()
   485  	_, parseRes := new(ConceptParser).Parse(conceptText)
   486  	c.Assert(parseRes.Error.Message, Equals, "Dynamic parameter <table:name> could not be resolved")
   487  }
   488  
   489  func (s *MySuite) TestConceptHavingStaticParameters(c *C) {
   490  	conceptText := SpecBuilder().
   491  		specHeading("create user <user:id> \"abc\" and <file>").
   492  		step("a step <user:id>").String()
   493  	_, parseRes := new(ConceptParser).Parse(conceptText)
   494  	c.Assert(parseRes.Error.Message, Equals, "Concept heading can have only Dynamic Parameters")
   495  }
   496  
   497  func (s *MySuite) TestConceptFileHavingScenarioHeadingGivesParseError(c *C) {
   498  	conceptText := SpecBuilder().
   499  		specHeading("create user").
   500  		step("a step").
   501  		scenarioHeading("Scenario Heading").
   502  		step("a step1").
   503  		String()
   504  
   505  	scenarioHeading := SpecBuilder().
   506  		scenarioHeading("Scenario Heading").
   507  		String()
   508  	_, res := new(ConceptParser).Parse(conceptText)
   509  
   510  	var nilErr *ParseError
   511  	c.Assert(res.Error, Not(Equals), nilErr)
   512  	c.Assert(res.Error.Message, Equals, "Scenario Heading is not allowed in concept file")
   513  	c.Assert(res.Error.LineText, Equals, strings.TrimSpace(scenarioHeading))
   514  }