github.com/ezbuy/gauge@v0.9.4-0.20171013092048-7ac5bd3931cd/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 "path/filepath" 22 "strings" 23 24 "github.com/getgauge/gauge/config" 25 "github.com/getgauge/gauge/gauge" 26 . "gopkg.in/check.v1" 27 ) 28 29 func assertStepEqual(c *C, expected, actual *gauge.Step) { 30 c.Assert(expected.LineNo, Equals, actual.LineNo) 31 c.Assert(expected.Value, Equals, actual.Value) 32 c.Assert(expected.LineText, Equals, actual.LineText) 33 } 34 35 func (s *MySuite) TearDownTest(c *C) { 36 config.ProjectRoot = "" 37 } 38 39 func (s *MySuite) TestConceptDictionaryAdd(c *C) { 40 dictionary := gauge.NewConceptDictionary() 41 step1Text := "test concept step 1" 42 step2Text := "test concept step 2" 43 step1 := &gauge.Step{Value: step1Text, LineNo: 1, IsConcept: true, LineText: step1Text} 44 step2 := &gauge.Step{Value: step2Text, LineNo: 4, IsConcept: true, LineText: step2Text} 45 path, _ := filepath.Abs(filepath.Join("testdata", "concept.cpt")) 46 47 concepts, errs := AddConcepts([]string{path}, dictionary) 48 49 c.Assert(len(concepts), Equals, 2) 50 c.Assert(len(errs), Equals, 0) 51 assertStepEqual(c, dictionary.ConceptsMap[step1Text].ConceptStep, step1) 52 c.Assert(dictionary.ConceptsMap[step1Text].FileName, Equals, path) 53 assertStepEqual(c, dictionary.ConceptsMap[step2Text].ConceptStep, step2) 54 c.Assert(dictionary.ConceptsMap[step2Text].FileName, Equals, path) 55 } 56 57 func (s *MySuite) TestConceptDictionaryAddDuplicateConcept(c *C) { 58 dictionary := gauge.NewConceptDictionary() 59 path, _ := filepath.Abs(filepath.Join("testdata", "err", "cpt", "duplicate_concept.cpt")) 60 61 concepts, errs := AddConcepts([]string{path}, dictionary) 62 63 c.Assert(len(concepts), Equals, 2) 64 c.Assert(len(errs) > 0, Equals, true) 65 if !(hasParseError("Duplicate concept definition found => 'test concept step 5' => at\n\t"+path+":4\n\t"+path+":1", errs) || 66 hasParseError("Duplicate concept definition found => 'test concept step 5' => at\n\t"+path+":1\n\t"+path+":4", errs)) { 67 c.Fail() 68 } 69 } 70 71 func hasParseError(eMessage string, errs []ParseError) bool { 72 for _, e := range errs { 73 if e.Message == eMessage { 74 return true 75 } 76 } 77 return false 78 } 79 80 func (s *MySuite) TestDuplicateConceptsinMultipleFile(c *C) { 81 dictionary := gauge.NewConceptDictionary() 82 cpt1, _ := filepath.Abs(filepath.Join("testdata", "err", "cpt", "concept.cpt")) 83 cpt2, _ := filepath.Abs(filepath.Join("testdata", "err", "cpt", "duplicate.cpt")) 84 85 AddConcepts([]string{cpt1}, dictionary) 86 concepts, errs := AddConcepts([]string{cpt2}, dictionary) 87 88 c.Assert(len(concepts), Equals, 2) 89 c.Assert(len(errs), Equals, 2) 90 if !(hasParseError("Duplicate concept definition found => 'test concept step 1' => at\n\t"+cpt2+":1\n\t"+cpt1+":1", errs) || 91 hasParseError("Duplicate concept definition found => 'test concept step 1' => at\n\t"+cpt1+":1\n\t"+cpt2+":1", errs)) { 92 c.Fail() 93 } 94 } 95 96 func (s *MySuite) TestCreateConceptDictionaryGivesAllParseErrors(c *C) { 97 config.ProjectRoot, _ = filepath.Abs(filepath.Join("testdata", "err", "cpt")) 98 99 _, res := CreateConceptsDictionary() 100 101 c.Assert(res.Ok, Equals, false) 102 c.Assert(len(res.ParseErrors), Equals, 5) 103 } 104 105 func (s *MySuite) TestCreateConceptDictionary(c *C) { 106 config.ProjectRoot, _ = filepath.Abs(filepath.Join("testdata", "dir1")) 107 108 dict, res := CreateConceptsDictionary() 109 110 c.Assert(res.Ok, Equals, true) 111 c.Assert(dict, NotNil) 112 c.Assert(len(dict.ConceptsMap), Equals, 1) 113 } 114 115 func (s *MySuite) TestConceptDictionaryWithNestedConcepts(c *C) { 116 dictionary := gauge.NewConceptDictionary() 117 path, _ := filepath.Abs(filepath.Join("testdata", "nested_concept.cpt")) 118 119 AddConcepts([]string{path}, dictionary) 120 concept := dictionary.Search("test concept step 1") 121 122 c.Assert(len(concept.ConceptStep.ConceptSteps), Equals, 1) 123 124 actualNestedConcept := concept.ConceptStep.ConceptSteps[0] 125 c.Assert(actualNestedConcept.IsConcept, Equals, true) 126 c.Assert(len(actualNestedConcept.ConceptSteps), Equals, 1) 127 c.Assert(actualNestedConcept.ConceptSteps[0].Value, Equals, "step 2") 128 } 129 130 func (s *MySuite) TestConceptDictionaryWithNestedConceptsWithDynamicParameters(c *C) { 131 conceptDictionary := gauge.NewConceptDictionary() 132 path, _ := filepath.Abs(filepath.Join("testdata", "dynamic_param_concept.cpt")) 133 134 AddConcepts([]string{path}, conceptDictionary) 135 concept := conceptDictionary.Search("create user {} {} and {}") 136 c.Assert(len(concept.ConceptStep.ConceptSteps), Equals, 1) 137 actualNestedConcept := concept.ConceptStep.ConceptSteps[0] 138 c.Assert(actualNestedConcept.IsConcept, Equals, true) 139 140 c.Assert(len(actualNestedConcept.ConceptSteps), Equals, 2) 141 c.Assert(actualNestedConcept.ConceptSteps[0].Value, Equals, "add id {}") 142 c.Assert(actualNestedConcept.ConceptSteps[0].Args[0].ArgType, Equals, gauge.Dynamic) 143 c.Assert(actualNestedConcept.ConceptSteps[0].Args[0].Value, Equals, "userid") 144 145 c.Assert(actualNestedConcept.ConceptSteps[1].Value, Equals, "add name {}") 146 c.Assert(actualNestedConcept.ConceptSteps[1].Args[0].ArgType, Equals, gauge.Dynamic) 147 c.Assert(actualNestedConcept.ConceptSteps[1].Args[0].Value, Equals, "username") 148 } 149 150 func (s *MySuite) TestConceptDictionaryWithNestedConceptsWithStaticParameters(c *C) { 151 conceptDictionary := gauge.NewConceptDictionary() 152 path, _ := filepath.Abs(filepath.Join("testdata", "static_param_concept.cpt")) 153 154 AddConcepts([]string{path}, conceptDictionary) 155 concept := conceptDictionary.Search("create user {} {} and {}") 156 c.Assert(len(concept.ConceptStep.ConceptSteps), Equals, 2) 157 actualNestedConcept := concept.ConceptStep.ConceptSteps[0] 158 c.Assert(actualNestedConcept.IsConcept, Equals, true) 159 160 c.Assert(actualNestedConcept.Args[0].ArgType, Equals, gauge.Dynamic) 161 c.Assert(actualNestedConcept.Args[0].Value, Equals, "user-id") 162 163 c.Assert(actualNestedConcept.Args[1].ArgType, Equals, gauge.Static) 164 c.Assert(actualNestedConcept.Args[1].Value, Equals, "static-value") 165 c.Assert(actualNestedConcept.Lookup.GetArg("userid").Value, Equals, "user-id") 166 c.Assert(actualNestedConcept.Lookup.GetArg("userid").ArgType, Equals, gauge.Dynamic) 167 c.Assert(actualNestedConcept.Lookup.GetArg("username").Value, Equals, "static-value") 168 c.Assert(actualNestedConcept.Lookup.GetArg("username").ArgType, Equals, gauge.Static) 169 170 c.Assert(len(actualNestedConcept.ConceptSteps), Equals, 2) 171 c.Assert(actualNestedConcept.ConceptSteps[0].Value, Equals, "add id {}") 172 c.Assert(actualNestedConcept.ConceptSteps[0].Args[0].ArgType, Equals, gauge.Dynamic) 173 c.Assert(actualNestedConcept.ConceptSteps[0].Args[0].Value, Equals, "userid") 174 175 c.Assert(actualNestedConcept.ConceptSteps[1].Value, Equals, "add name {}") 176 c.Assert(actualNestedConcept.ConceptSteps[1].Args[0].ArgType, Equals, gauge.Dynamic) 177 c.Assert(actualNestedConcept.ConceptSteps[1].Args[0].Value, Equals, "username") 178 } 179 180 func (s *MySuite) TestConceptHavingItemsWithComments(c *C) { 181 conceptDictionary := gauge.NewConceptDictionary() 182 path, _ := filepath.Abs(filepath.Join("testdata", "dynamic_param_concept.cpt")) 183 184 AddConcepts([]string{path}, conceptDictionary) 185 concept := conceptDictionary.Search("create user {} {} and {}") 186 187 c.Assert(len(concept.ConceptStep.Items), Equals, 3) 188 c.Assert(concept.ConceptStep.Items[2].(*gauge.Comment).Value, Equals, "Comments") 189 190 concept = conceptDictionary.Search("assign id {} and name {}") 191 192 c.Assert(len(concept.ConceptStep.Items), Equals, 4) 193 c.Assert(concept.ConceptStep.Items[3].(*gauge.Comment).Value, Equals, "Comment1") 194 } 195 196 func (s *MySuite) TestConceptHavingItemsWithTablesAndComments(c *C) { 197 conceptDictionary := gauge.NewConceptDictionary() 198 path, _ := filepath.Abs(filepath.Join("testdata", "tabular_concept.cpt")) 199 200 AddConcepts([]string{path}, conceptDictionary) 201 202 concept := conceptDictionary.Search("my concept {}") 203 c.Assert(len(concept.ConceptStep.Items), Equals, 3) 204 c.Assert(len(concept.ConceptStep.PreComments), Equals, 1) 205 c.Assert(concept.ConceptStep.PreComments[0].Value, Equals, "COMMENT") 206 c.Assert(concept.ConceptStep.Items[2].(*gauge.Comment).Value, Equals, " comment") 207 } 208 209 func (s *MySuite) TestMultiLevelConcept(c *C) { 210 conceptDictionary := gauge.NewConceptDictionary() 211 path, _ := filepath.Abs(filepath.Join("testdata", "nested_concept2.cpt")) 212 213 AddConcepts([]string{path}, conceptDictionary) 214 actualTopLevelConcept := conceptDictionary.Search("top level concept") 215 c.Assert(len(actualTopLevelConcept.ConceptStep.ConceptSteps), Equals, 2) 216 actualNestedConcept := actualTopLevelConcept.ConceptStep.ConceptSteps[0] 217 c.Assert(actualNestedConcept.IsConcept, Equals, true) 218 c.Assert(len(actualNestedConcept.ConceptSteps), Equals, 2) 219 c.Assert(actualNestedConcept.ConceptSteps[0].Value, Equals, "another nested concept") 220 c.Assert(actualNestedConcept.ConceptSteps[1].Value, Equals, "normal step 2") 221 c.Assert(actualTopLevelConcept.ConceptStep.ConceptSteps[1].Value, Equals, "normal step 1") 222 223 actualAnotherNestedConcept := conceptDictionary.Search("another nested concept") 224 c.Assert(len(actualAnotherNestedConcept.ConceptStep.ConceptSteps), Equals, 1) 225 step := actualAnotherNestedConcept.ConceptStep.ConceptSteps[0] 226 c.Assert(step.IsConcept, Equals, false) 227 c.Assert(step.Value, Equals, "normal step 3") 228 229 nestedConcept2 := conceptDictionary.Search("nested concept") 230 c.Assert(len(nestedConcept2.ConceptStep.ConceptSteps), Equals, 2) 231 actualAnotherNestedConcept2 := nestedConcept2.ConceptStep.ConceptSteps[0] 232 c.Assert(actualAnotherNestedConcept2.IsConcept, Equals, true) 233 c.Assert(len(actualAnotherNestedConcept2.ConceptSteps), Equals, 1) 234 c.Assert(actualAnotherNestedConcept2.ConceptSteps[0].Value, Equals, "normal step 3") 235 c.Assert(nestedConcept2.ConceptStep.ConceptSteps[1].Value, Equals, "normal step 2") 236 } 237 238 func (s *MySuite) TestParsingSimpleConcept(c *C) { 239 parser := new(ConceptParser) 240 concepts, parseRes := parser.Parse("# my concept \n * first step \n * second step ", "") 241 242 c.Assert(len(parseRes.ParseErrors), Equals, 0) 243 c.Assert(len(concepts), Equals, 1) 244 245 concept := concepts[0] 246 247 c.Assert(concept.IsConcept, Equals, true) 248 c.Assert(len(concept.ConceptSteps), Equals, 2) 249 c.Assert(concept.ConceptSteps[0].Value, Equals, "first step") 250 c.Assert(concept.ConceptSteps[1].Value, Equals, "second step") 251 } 252 253 func (s *MySuite) TestParsingConceptRetainsStepSuffix(c *C) { 254 parser := new(ConceptParser) 255 concepts, parseRes := parser.Parse("# my concept \n * first step \n * second step \n\n", "") 256 257 c.Assert(len(parseRes.ParseErrors), Equals, 0) 258 c.Assert(len(concepts), Equals, 1) 259 260 concept := concepts[0] 261 262 c.Assert(concept.IsConcept, Equals, true) 263 c.Assert(len(concept.ConceptSteps), Equals, 2) 264 c.Assert(concept.ConceptSteps[0].Value, Equals, "first step") 265 c.Assert(concept.ConceptSteps[1].Value, Equals, "second step") 266 c.Assert(concept.ConceptSteps[0].Suffix, Equals, "") 267 c.Assert(concept.ConceptSteps[1].Suffix, Equals, "\n") 268 } 269 270 func (s *MySuite) TestErrorParsingConceptHeadingWithStaticOrSpecialParameter(c *C) { 271 parser := new(ConceptParser) 272 _, parseRes := parser.Parse("# my concept with \"parameter\" \n * first step \n * second step ", "foo.spec") 273 c.Assert(len(parseRes.ParseErrors), Not(Equals), 0) 274 c.Assert(parseRes.ParseErrors[0].Error(), Equals, "foo.spec:1 Concept heading can have only Dynamic Parameters => 'my concept with \"parameter\"'") 275 276 _, parseRes = parser.Parse("# my concept with <table: foo> \n * first step \n * second step ", "foo2.spec") 277 c.Assert(len(parseRes.ParseErrors), Not(Equals), 0) 278 c.Assert(parseRes.ParseErrors[0].Error(), Equals, "foo2.spec:1 Dynamic parameter <table: foo> could not be resolved => 'my concept with <table: foo>'") 279 } 280 281 func (s *MySuite) TestErrorParsingConceptWithoutHeading(c *C) { 282 parser := new(ConceptParser) 283 284 _, parseRes := parser.Parse("* first step \n * second step ", "") 285 286 c.Assert(len(parseRes.ParseErrors), Not(Equals), 0) 287 c.Assert(parseRes.ParseErrors[0].Message, Equals, "Step is not defined inside a concept heading") 288 } 289 290 func (s *MySuite) TestErrorParsingConceptWithoutSteps(c *C) { 291 parser := new(ConceptParser) 292 293 _, parseRes := parser.Parse("# my concept with \n", "") 294 295 c.Assert(len(parseRes.ParseErrors), Not(Equals), 0) 296 c.Assert(parseRes.ParseErrors[0].Message, Equals, "Concept should have atleast one step") 297 } 298 299 func (s *MySuite) TestParsingSimpleConceptWithParameters(c *C) { 300 parser := new(ConceptParser) 301 concepts, parseRes := parser.Parse("# my concept with <param0> and <param1> \n * first step using <param0> \n * second step using \"value\" and <param1> ", "") 302 303 c.Assert(len(parseRes.ParseErrors), Equals, 0) 304 c.Assert(len(concepts), Equals, 1) 305 306 concept := concepts[0] 307 c.Assert(concept.IsConcept, Equals, true) 308 c.Assert(len(concept.ConceptSteps), Equals, 2) 309 // c.Assert(len(concept.Lookup.paramValue), Equals, 2) 310 c.Assert(concept.Lookup.ContainsArg("param0"), Equals, true) 311 c.Assert(concept.Lookup.ContainsArg("param1"), Equals, true) 312 313 firstConcept := concept.ConceptSteps[0] 314 c.Assert(firstConcept.Value, Equals, "first step using {}") 315 c.Assert(len(firstConcept.Args), Equals, 1) 316 c.Assert(firstConcept.Args[0].ArgType, Equals, gauge.Dynamic) 317 c.Assert(firstConcept.Args[0].Value, Equals, "param0") 318 319 secondConcept := concept.ConceptSteps[1] 320 c.Assert(secondConcept.Value, Equals, "second step using {} and {}") 321 c.Assert(len(secondConcept.Args), Equals, 2) 322 c.Assert(secondConcept.Args[0].ArgType, Equals, gauge.Static) 323 c.Assert(secondConcept.Args[0].Value, Equals, "value") 324 c.Assert(secondConcept.Args[1].ArgType, Equals, gauge.Dynamic) 325 c.Assert(secondConcept.Args[1].Value, Equals, "param1") 326 327 } 328 329 func (s *MySuite) TestErrorParsingConceptStepWithInvalidParameters(c *C) { 330 parser := new(ConceptParser) 331 _, parseRes := parser.Parse("# my concept with <param0> and <param1> \n * first step using <param3> \n * second step using \"value\" and <param1> ", "") 332 333 c.Assert(len(parseRes.ParseErrors), Not(Equals), 0) 334 c.Assert(parseRes.ParseErrors[0].Message, Equals, "Dynamic parameter <param3> could not be resolved") 335 } 336 337 func (s *MySuite) TestParsingMultipleConcept(c *C) { 338 parser := new(ConceptParser) 339 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 ", "") 340 341 c.Assert(len(parseRes.ParseErrors), Equals, 0) 342 c.Assert(len(concepts), Equals, 3) 343 344 firstConcept := concepts[0] 345 secondConcept := concepts[1] 346 thirdConcept := concepts[2] 347 348 c.Assert(firstConcept.IsConcept, Equals, true) 349 c.Assert(len(firstConcept.ConceptSteps), Equals, 2) 350 c.Assert(firstConcept.ConceptSteps[0].Value, Equals, "first step") 351 c.Assert(firstConcept.ConceptSteps[1].Value, Equals, "second step") 352 353 c.Assert(secondConcept.IsConcept, Equals, true) 354 c.Assert(len(secondConcept.ConceptSteps), Equals, 1) 355 c.Assert(secondConcept.ConceptSteps[0].Value, Equals, "next step") 356 357 c.Assert(thirdConcept.IsConcept, Equals, true) 358 c.Assert(len(thirdConcept.ConceptSteps), Equals, 1) 359 c.Assert(thirdConcept.ConceptSteps[0].Value, Equals, "next step {} and {}") 360 c.Assert(len(thirdConcept.ConceptSteps[0].Args), Equals, 2) 361 c.Assert(thirdConcept.ConceptSteps[0].Args[0].ArgType, Equals, gauge.Dynamic) 362 c.Assert(thirdConcept.ConceptSteps[0].Args[1].ArgType, Equals, gauge.Static) 363 364 // c.Assert(len(thirdConcept.Lookup.paramValue), Equals, 1) 365 c.Assert(thirdConcept.Lookup.ContainsArg("param0"), Equals, true) 366 367 } 368 369 func (s *MySuite) TestParsingConceptStepWithInlineTable(c *C) { 370 parser := new(ConceptParser) 371 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", "") 372 373 c.Assert(len(parseRes.ParseErrors), Equals, 0) 374 c.Assert(len(concepts), Equals, 1) 375 376 concept := concepts[0] 377 378 c.Assert(concept.IsConcept, Equals, true) 379 c.Assert(len(concept.ConceptSteps), Equals, 1) 380 c.Assert(concept.ConceptSteps[0].Value, Equals, "first step with {} and inline table {}") 381 382 tableArgument := concept.ConceptSteps[0].Args[1] 383 c.Assert(tableArgument.ArgType, Equals, gauge.TableArg) 384 385 inlineTable := tableArgument.Table 386 c.Assert(inlineTable.IsInitialized(), Equals, true) 387 c.Assert(len(inlineTable.Get("id")), Equals, 2) 388 c.Assert(len(inlineTable.Get("name")), Equals, 2) 389 c.Assert(inlineTable.Get("id")[0].Value, Equals, "1") 390 c.Assert(inlineTable.Get("id")[0].CellType, Equals, gauge.Static) 391 c.Assert(inlineTable.Get("id")[1].Value, Equals, "2") 392 c.Assert(inlineTable.Get("id")[1].CellType, Equals, gauge.Static) 393 c.Assert(inlineTable.Get("name")[0].Value, Equals, "vishnu") 394 c.Assert(inlineTable.Get("name")[0].CellType, Equals, gauge.Static) 395 c.Assert(inlineTable.Get("name")[1].Value, Equals, "prateek") 396 c.Assert(inlineTable.Get("name")[1].CellType, Equals, gauge.Static) 397 } 398 399 func (s *MySuite) TestErrorParsingConceptWithInvalidInlineTable(c *C) { 400 parser := new(ConceptParser) 401 _, parseRes := parser.Parse("# my concept \n |id|name|\n|1|vishnu|\n|2|prateek|\n", "") 402 403 c.Assert(len(parseRes.ParseErrors), Not(Equals), 0) 404 c.Assert(parseRes.ParseErrors[0].Message, Equals, "Table doesn't belong to any step") 405 } 406 407 func (s *MySuite) TestNestedConceptLooksUpArgsFromParent(c *C) { 408 parser := new(SpecParser) 409 specText := SpecBuilder().specHeading("A spec heading"). 410 scenarioHeading("First flow"). 411 step("create user \"foo\" \"doo\""). 412 step("another step").String() 413 414 dictionary := gauge.NewConceptDictionary() 415 path, _ := filepath.Abs(filepath.Join("testdata", "param_nested_concept.cpt")) 416 417 AddConcepts([]string{path}, dictionary) 418 tokens, _ := parser.GenerateTokens(specText, "") 419 spec, parseResult := parser.CreateSpecification(tokens, dictionary, "") 420 421 c.Assert(parseResult.Ok, Equals, true) 422 firstStepInSpec := spec.Scenarios[0].Steps[0] 423 nestedConcept := firstStepInSpec.ConceptSteps[0] 424 nestedConceptArg1 := nestedConcept.GetArg("baz") 425 c.Assert(nestedConceptArg1.Value, Equals, "foo") 426 nestedConceptArg2 := nestedConcept.GetArg("boo") 427 c.Assert(nestedConceptArg2.Value, Equals, "doo") 428 } 429 430 func (s *MySuite) TestNestedConceptLooksUpDataTableArgs(c *C) { 431 parser := new(SpecParser) 432 specText := SpecBuilder().specHeading("A spec heading"). 433 tableHeader("id", "name", "phone"). 434 tableHeader("123", "prateek", "8800"). 435 tableHeader("456", "apoorva", "9800"). 436 tableHeader("789", "srikanth", "7900"). 437 scenarioHeading("First scenario"). 438 step("create user <id> <name>"). 439 step("another step").String() 440 441 dictionary := gauge.NewConceptDictionary() 442 path, _ := filepath.Abs(filepath.Join("testdata", "param_nested_concept.cpt")) 443 444 AddConcepts([]string{path}, dictionary) 445 446 tokens, _ := parser.GenerateTokens(specText, "") 447 spec, parseResult := parser.CreateSpecification(tokens, dictionary, "") 448 449 c.Assert(parseResult.Ok, Equals, true) 450 451 firstStepInSpec := spec.Scenarios[0].Steps[0] 452 c.Assert(firstStepInSpec.IsConcept, Equals, true) 453 c.Assert(firstStepInSpec.GetArg("bar").ArgType, Equals, gauge.Dynamic) 454 c.Assert(firstStepInSpec.GetArg("far").ArgType, Equals, gauge.Dynamic) 455 c.Assert(firstStepInSpec.GetArg("bar").Value, Equals, "id") 456 c.Assert(firstStepInSpec.GetArg("far").Value, Equals, "name") 457 458 nestedConcept := firstStepInSpec.ConceptSteps[0] 459 c.Assert(nestedConcept.GetArg("baz").ArgType, Equals, gauge.Dynamic) 460 c.Assert(nestedConcept.GetArg("boo").ArgType, Equals, gauge.Dynamic) 461 c.Assert(nestedConcept.GetArg("baz").Value, Equals, "id") 462 c.Assert(nestedConcept.GetArg("boo").Value, Equals, "name") 463 464 } 465 466 func (s *MySuite) TestNestedConceptLooksUpWhenParameterPlaceholdersAreSame(c *C) { 467 parser := new(SpecParser) 468 specText := SpecBuilder().specHeading("A spec heading"). 469 tableHeader("id", "name", "phone"). 470 tableHeader("123", "prateek", "8800"). 471 tableHeader("456", "apoorva", "9800"). 472 tableHeader("789", "srikanth", "7900"). 473 scenarioHeading("First scenario"). 474 step("create user <id> <name> and <phone>"). 475 step("another step").String() 476 477 dictionary := gauge.NewConceptDictionary() 478 path, _ := filepath.Abs(filepath.Join("testdata", "param_nested_concept2.cpt")) 479 480 AddConcepts([]string{path}, dictionary) 481 482 tokens, _ := parser.GenerateTokens(specText, "") 483 spec, parseResult := parser.CreateSpecification(tokens, dictionary, "") 484 485 c.Assert(parseResult.Ok, Equals, true) 486 487 firstStepInSpec := spec.Scenarios[0].Steps[0] 488 c.Assert(firstStepInSpec.IsConcept, Equals, true) 489 c.Assert(firstStepInSpec.GetArg("user-id").ArgType, Equals, gauge.Dynamic) 490 c.Assert(firstStepInSpec.GetArg("user-name").ArgType, Equals, gauge.Dynamic) 491 c.Assert(firstStepInSpec.GetArg("user-phone").ArgType, Equals, gauge.Dynamic) 492 c.Assert(firstStepInSpec.GetArg("user-id").Value, Equals, "id") 493 c.Assert(firstStepInSpec.GetArg("user-name").Value, Equals, "name") 494 c.Assert(firstStepInSpec.GetArg("user-phone").Value, Equals, "phone") 495 496 nestedConcept := firstStepInSpec.ConceptSteps[0] 497 c.Assert(nestedConcept.GetArg("user-id").ArgType, Equals, gauge.Dynamic) 498 c.Assert(nestedConcept.GetArg("user-name").ArgType, Equals, gauge.Dynamic) 499 c.Assert(nestedConcept.GetArg("user-id").Value, Equals, "id") 500 c.Assert(nestedConcept.GetArg("user-name").Value, Equals, "name") 501 502 } 503 504 func (s *MySuite) TestErrorOnCircularReferenceInConcept(c *C) { 505 cd := gauge.NewConceptDictionary() 506 cd.ConceptsMap["concept"] = &gauge.Concept{ConceptStep: &gauge.Step{LineText: "concept", Value: "concept", IsConcept: true, ConceptSteps: []*gauge.Step{&gauge.Step{LineText: "concept", Value: "concept", IsConcept: true}}}, FileName: "filename.cpt"} 507 508 res := ValidateConcepts(cd) 509 510 c.Assert(containsAny(res.ParseErrors, "Circular reference found"), Equals, true) 511 } 512 513 func (s *MySuite) TestValidateConceptShouldRemoveCircularConceptsFromDictionary(c *C) { 514 cd := gauge.NewConceptDictionary() 515 cd.ConceptsMap["concept"] = &gauge.Concept{ConceptStep: &gauge.Step{LineText: "concept", Value: "concept", IsConcept: true, ConceptSteps: []*gauge.Step{&gauge.Step{LineText: "concept", Value: "concept", IsConcept: true}}}, FileName: "filename.cpt"} 516 cd.ConceptsMap["concept2"] = &gauge.Concept{ConceptStep: &gauge.Step{LineText: "concept2", Value: "concept2", IsConcept: true, ConceptSteps: []*gauge.Step{&gauge.Step{LineText: "concept", Value: "concept", IsConcept: true}}}, FileName: "filename.cpt"} 517 518 res := ValidateConcepts(cd) 519 520 c.Assert(cd.ConceptsMap["concept"], Equals, (*gauge.Concept)(nil)) 521 c.Assert(len(cd.ConceptsMap["concept2"].ConceptStep.ConceptSteps), Equals, 0) 522 c.Assert(len(res.ParseErrors), Equals, 1) 523 c.Assert(containsAny(res.ParseErrors, "Circular reference found"), Equals, true) 524 } 525 526 func (s *MySuite) TestRemoveAllReferences(c *C) { 527 cd := gauge.NewConceptDictionary() 528 cpt1 := &gauge.Concept{ConceptStep: &gauge.Step{LineText: "concept", Value: "concept", IsConcept: true, ConceptSteps: []*gauge.Step{&gauge.Step{LineText: "concept", Value: "concept", IsConcept: true}}}, FileName: "filename.cpt"} 529 cd.ConceptsMap["concept"] = cpt1 530 cd.ConceptsMap["concept2"] = &gauge.Concept{ConceptStep: &gauge.Step{LineText: "concept2", Value: "concept2", IsConcept: true, ConceptSteps: []*gauge.Step{&gauge.Step{LineText: "concept", Value: "concept", IsConcept: true}}}, FileName: "filename.cpt"} 531 532 c.Assert(len(cd.ConceptsMap["concept2"].ConceptStep.ConceptSteps), Equals, 1) 533 534 removeAllReferences(cd, cpt1) 535 536 c.Assert(len(cd.ConceptsMap["concept2"].ConceptStep.ConceptSteps), Equals, 0) 537 } 538 539 func (s *MySuite) TestReplaceNestedConceptsWithCircularReference(c *C) { 540 lookup := gauge.ArgLookup{} 541 lookup.AddArgName("a") 542 lookup.AddArgValue("a", &gauge.StepArg{Name: "", Value: "a", ArgType: gauge.Static}) 543 lookup.ParamIndexMap = make(map[string]int) 544 lookup.ParamIndexMap["a"] = 0 545 546 cd := gauge.NewConceptDictionary() 547 path, _ := filepath.Abs(filepath.Join("testdata", "err", "cpt", "circular_concept.cpt")) 548 549 AddConcepts([]string{path}, cd) 550 concept := cd.Search("concept1 {}") 551 552 c.Assert(concept.ConceptStep.ConceptSteps[0].Lookup, DeepEquals, lookup) 553 } 554 555 func (s *MySuite) TestErrorParsingConceptWithRecursiveCallToConcept(c *C) { 556 cd := gauge.NewConceptDictionary() 557 cd.ConceptsMap["concept"] = &gauge.Concept{ConceptStep: &gauge.Step{LineText: "concept", Value: "concept", IsConcept: true, ConceptSteps: []*gauge.Step{&gauge.Step{LineText: "concept", Value: "concept", IsConcept: false}}}, FileName: "filename.cpt"} 558 559 res := ValidateConcepts(cd) 560 561 c.Assert(len(res.ParseErrors), Not(Equals), 0) 562 c.Assert(containsAny(res.ParseErrors, "Circular reference found"), Equals, true) 563 } 564 565 func (s *MySuite) TestConceptHavingDynamicParameters(c *C) { 566 conceptText := SpecBuilder(). 567 specHeading("create user <user:id> <user:name> and <file>"). 568 step("a step <user:id>").String() 569 step, _ := new(ConceptParser).Parse(conceptText, "") 570 c.Assert(step[0].LineText, Equals, "create user <user:id> <user:name> and <file>") 571 c.Assert(step[0].Args[0].ArgType, Equals, gauge.Dynamic) 572 c.Assert(step[0].Args[1].ArgType, Equals, gauge.Dynamic) 573 c.Assert(step[0].Args[2].ArgType, Equals, gauge.Dynamic) 574 } 575 576 func (s *MySuite) TestConceptHavingInvalidSpecialParameters(c *C) { 577 conceptText := SpecBuilder(). 578 specHeading("create user <user:id> <table:name> and <file>"). 579 step("a step <user:id>").String() 580 _, parseRes := new(ConceptParser).Parse(conceptText, "") 581 c.Assert(parseRes.ParseErrors[0].Message, Equals, "Dynamic parameter <table:name> could not be resolved") 582 } 583 584 func (s *MySuite) TestConceptHavingStaticParameters(c *C) { 585 conceptText := SpecBuilder(). 586 specHeading("create user <user:id> \"abc\" and <file>"). 587 step("a step <user:id>").String() 588 _, parseRes := new(ConceptParser).Parse(conceptText, "") 589 c.Assert(parseRes.ParseErrors[0].Message, Equals, "Concept heading can have only Dynamic Parameters") 590 } 591 592 func (s *MySuite) TestConceptFileHavingScenarioHeadingGivesParseError(c *C) { 593 conceptText := SpecBuilder(). 594 specHeading("create user"). 595 step("a step"). 596 scenarioHeading("Scenario Heading"). 597 step("a step1"). 598 String() 599 600 scenarioHeading := SpecBuilder(). 601 scenarioHeading("Scenario Heading"). 602 String() 603 _, res := new(ConceptParser).Parse(conceptText, "") 604 605 c.Assert(len(res.ParseErrors), Not(Equals), 0) 606 c.Assert(res.ParseErrors[0].Message, Equals, "Scenario Heading is not allowed in concept file") 607 c.Assert(res.ParseErrors[0].LineText, Equals, strings.TrimSpace(scenarioHeading)) 608 } 609 610 func (s *MySuite) TestConceptFileHavingStaticParamsInHeadingShouldGiveParseError(c *C) { 611 conceptText := SpecBuilder(). 612 specHeading("Concept Heading37a"). 613 step("a step"). 614 specHeading("testinghjk \"sdf\""). 615 step("a step1"). 616 String() 617 618 _, res := new(ConceptParser).Parse(conceptText, "") 619 620 c.Assert(len(res.ParseErrors), Not(Equals), 0) 621 c.Assert(res.ParseErrors[0].Message, Equals, "Concept heading can have only Dynamic Parameters") 622 c.Assert(res.ParseErrors[0].LineText, Equals, "testinghjk \"sdf\"") 623 } 624 625 func (s *MySuite) TestConceptFileHavingTableAfterConceptHeadingShouldGiveParseError(c *C) { 626 conceptText := SpecBuilder(). 627 specHeading("Concept Heading37a"). 628 step("a step"). 629 specHeading("testinghjk "). 630 text("|sdfsdf|"). 631 text("|----|"). 632 text("|wer|"). 633 step("a step1"). 634 String() 635 636 _, res := new(ConceptParser).Parse(conceptText, "") 637 638 c.Assert(len(res.ParseErrors), Not(Equals), 0) 639 c.Assert(res.ParseErrors[0].Message, Equals, "Table doesn't belong to any step") 640 c.Assert(res.ParseErrors[0].LineText, Equals, "|sdfsdf|") 641 } 642 643 func (s *MySuite) TestMultipleConceptsInAFileHavingErrorsShouldBeConsolidated(c *C) { 644 conceptText := SpecBuilder(). 645 specHeading("1<werwer>"). 646 step("self <werwe1r>"). 647 specHeading("2 <werwer> two"). 648 step("self <werwer>"). 649 String() 650 651 _, res := new(ConceptParser).Parse(conceptText, "") 652 653 c.Assert(len(res.ParseErrors), Not(Equals), 0) 654 c.Assert(res.ParseErrors[0].Message, Equals, "Dynamic parameter <werwe1r> could not be resolved") 655 c.Assert(res.ParseErrors[0].LineText, Equals, "self <werwe1r>") 656 } 657 658 func (s *MySuite) TestConceptFileHavingItemsWithDuplicateTableHeaders(c *C) { 659 conceptDictionary := gauge.NewConceptDictionary() 660 path, _ := filepath.Abs(filepath.Join("testdata", "tabular_concept1.cpt")) 661 662 AddConcepts([]string{path}, conceptDictionary) 663 concept := conceptDictionary.Search("my concept {}") 664 concept1 := conceptDictionary.Search("my {}") 665 666 c.Assert(concept, Not(Equals), nil) 667 c.Assert(concept1, Not(Equals), nil) 668 } 669 670 func (s *MySuite) TestConceptParserShouldNotAddTableAsArgIfCommentsArePresentBetweenStepAndTable(c *C) { 671 conceptText := SpecBuilder(). 672 specHeading("create user"). 673 step("a step"). 674 text("adasdasd\n\n"). 675 text("|sdfsdf|"). 676 text("|----|"). 677 text("|wer|"). 678 step("a step1"). 679 String() 680 steps, _ := new(ConceptParser).Parse(conceptText, "") 681 c.Assert(steps[0].ConceptSteps[0].GetLineText(), Equals, "a step") 682 } 683 684 func (s *MySuite) TestErrorParsingConceptWithNoSteps(c *C) { 685 parser := new(ConceptParser) 686 _, parseRes := parser.Parse("# my concept\n# second concept\n* first step ", "foo.cpt") 687 c.Assert(len(parseRes.ParseErrors), Equals, 1) 688 c.Assert(parseRes.ParseErrors[0].Error(), Equals, "foo.cpt:1 Concept should have atleast one step => 'my concept'") 689 } 690 691 func containsAny(errs []ParseError, msg string) bool { 692 for _, err := range errs { 693 if strings.Contains(err.Message, msg) { 694 return true 695 } 696 } 697 return false 698 }