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