cucumber-compatibility-kit 9.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +56 -0
  3. data/features/attachments/attachments.feature +41 -0
  4. data/features/attachments/attachments.feature.ndjson +77 -0
  5. data/features/attachments/attachments.feature.rb +51 -0
  6. data/features/attachments/cucumber.png +0 -0
  7. data/features/data-tables/data-tables.feature +12 -0
  8. data/features/data-tables/data-tables.feature.ndjson +15 -0
  9. data/features/data-tables/data-tables.feature.rb +7 -0
  10. data/features/examples-tables/examples-tables.feature +28 -0
  11. data/features/examples-tables/examples-tables.feature.ndjson +68 -0
  12. data/features/examples-tables/examples-tables.feature.rb +11 -0
  13. data/features/hooks/cucumber.svg +7 -0
  14. data/features/hooks/hooks.feature +20 -0
  15. data/features/hooks/hooks.feature.ndjson +66 -0
  16. data/features/hooks/hooks.feature.rb +28 -0
  17. data/features/markdown/markdown.feature.md +46 -0
  18. data/features/markdown/markdown.feature.md.ndjson +35 -0
  19. data/features/minimal/minimal.feature +10 -0
  20. data/features/minimal/minimal.feature.ndjson +12 -0
  21. data/features/minimal/minimal.feature.rb +2 -0
  22. data/features/parameter-types/parameter-types.feature +9 -0
  23. data/features/parameter-types/parameter-types.feature.ndjson +13 -0
  24. data/features/parameter-types/parameter-types.feature.rb +21 -0
  25. data/features/pending/pending.feature +19 -0
  26. data/features/pending/pending.feature.ndjson +30 -0
  27. data/features/pending/pending.feature.rb +11 -0
  28. data/features/retry/retry.feature +22 -0
  29. data/features/retry/retry.feature.ndjson +59 -0
  30. data/features/retry/retry.feature.rb +23 -0
  31. data/features/rules/rules.feature +27 -0
  32. data/features/rules/rules.feature.ndjson +45 -0
  33. data/features/rules/rules.feature.rb +26 -0
  34. data/features/skipped/skipped.feature +19 -0
  35. data/features/skipped/skipped.feature.ndjson +33 -0
  36. data/features/skipped/skipped.feature.rb +15 -0
  37. data/features/stack-traces/stack-traces.feature +11 -0
  38. data/features/stack-traces/stack-traces.feature.ndjson +12 -0
  39. data/features/stack-traces/stack-traces.feature.rb +3 -0
  40. data/features/undefined/undefined.feature +17 -0
  41. data/features/undefined/undefined.feature.ndjson +29 -0
  42. data/features/undefined/undefined.feature.rb +7 -0
  43. data/features/unknown-parameter-type/unknown-parameter-type.feature +6 -0
  44. data/features/unknown-parameter-type/unknown-parameter-type.feature.ndjson +12 -0
  45. data/features/unknown-parameter-type/unknown-parameter-type.feature.rb +3 -0
  46. data/lib/cucumber-compatibility-kit.rb +55 -0
  47. data/lib/keys_checker.rb +24 -0
  48. data/lib/messages_comparator.rb +83 -0
  49. data/lib/shared_examples.rb +63 -0
  50. data/spec/capture_warnings.rb +74 -0
  51. data/spec/cucumber-compatibility-kit_spec.rb +71 -0
  52. data/spec/keys_checker_spec.rb +77 -0
  53. metadata +165 -0
@@ -0,0 +1,45 @@
1
+ {"meta":{"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"15.0.0"},"os":{"name":"linux","version":"5.11.0-34-generic"},"protocolVersion":"17.1.1","runtime":{"name":"node.js","version":"14.17.3"}}}
2
+ {"source":{"data":"Feature: Rules\n You can place scenarios inside rules. This makes is possible to structure\n Gherkin documents in the same way as [example maps](https://cucumber.io/blog/bdd/example-mapping-introduction/).\n You can also use the Examples synonym for Scenario to make them even more similar.\n\n Rule: a sale cannot happen if change cannot be returned\n # sad path\n Example: no change\n Given there are 5 0.20 coins inside\n When the customer tries to buy a 0.85 chocolate with a 1 coin\n Then the sale should not happen\n\n # happy path\n Example: exact change\n Given there are 5 0.20 coins inside\n And there are 3 chocolates inside\n When the customer tries to buy a 0.80 chocolate with a 1 coin\n Then the customer's change should be 1 0.20 coin\n\n @some-tag\n Rule: a sale cannot happen if we're out of stock\n # sad path\n Example: no chocolates left\n Given there are no chocolates inside\n But there are 10 0.5 coins inside\n When the customer tries to buy a 0.85 chocolate with a 1 coin\n Then the sale should not happen\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"features/rules/rules.feature"}}
3
+ {"gherkinDocument":{"comments":[{"location":{"column":1,"line":7},"text":" # sad path"},{"location":{"column":1,"line":13},"text":" # happy path"},{"location":{"column":1,"line":22},"text":" # sad path"}],"feature":{"children":[{"rule":{"children":[{"scenario":{"description":"","examples":[],"id":"9","keyword":"Example","location":{"column":5,"line":8},"name":"no change","steps":[{"id":"6","keyword":"Given ","location":{"column":7,"line":9},"text":"there are 5 0.20 coins inside"},{"id":"7","keyword":"When ","location":{"column":7,"line":10},"text":"the customer tries to buy a 0.85 chocolate with a 1 coin"},{"id":"8","keyword":"Then ","location":{"column":7,"line":11},"text":"the sale should not happen"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"14","keyword":"Example","location":{"column":5,"line":14},"name":"exact change","steps":[{"id":"10","keyword":"Given ","location":{"column":7,"line":15},"text":"there are 5 0.20 coins inside"},{"id":"11","keyword":"And ","location":{"column":7,"line":16},"text":"there are 3 chocolates inside"},{"id":"12","keyword":"When ","location":{"column":7,"line":17},"text":"the customer tries to buy a 0.80 chocolate with a 1 coin"},{"id":"13","keyword":"Then ","location":{"column":7,"line":18},"text":"the customer's change should be 1 0.20 coin"}],"tags":[]}}],"description":"","id":"15","keyword":"Rule","location":{"column":3,"line":6},"name":"a sale cannot happen if change cannot be returned","tags":[]}},{"rule":{"children":[{"scenario":{"description":"","examples":[],"id":"20","keyword":"Example","location":{"column":5,"line":23},"name":"no chocolates left","steps":[{"id":"16","keyword":"Given ","location":{"column":7,"line":24},"text":"there are no chocolates inside"},{"id":"17","keyword":"But ","location":{"column":7,"line":25},"text":"there are 10 0.5 coins inside"},{"id":"18","keyword":"When ","location":{"column":7,"line":26},"text":"the customer tries to buy a 0.85 chocolate with a 1 coin"},{"id":"19","keyword":"Then ","location":{"column":7,"line":27},"text":"the sale should not happen"}],"tags":[]}}],"description":"","id":"22","keyword":"Rule","location":{"column":3,"line":21},"name":"a sale cannot happen if we're out of stock","tags":[{"id":"21","location":{"column":3,"line":20},"name":"@some-tag"}]}}],"description":" You can place scenarios inside rules. This makes is possible to structure\n Gherkin documents in the same way as [example maps](https://cucumber.io/blog/bdd/example-mapping-introduction/).\n You can also use the Examples synonym for Scenario to make them even more similar.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Rules","tags":[]},"uri":"features/rules/rules.feature"}}
4
+ {"pickle":{"astNodeIds":["9"],"id":"26","language":"en","name":"no change","steps":[{"astNodeIds":["6"],"id":"23","text":"there are 5 0.20 coins inside"},{"astNodeIds":["7"],"id":"24","text":"the customer tries to buy a 0.85 chocolate with a 1 coin"},{"astNodeIds":["8"],"id":"25","text":"the sale should not happen"}],"tags":[],"uri":"features/rules/rules.feature"}}
5
+ {"pickle":{"astNodeIds":["14"],"id":"31","language":"en","name":"exact change","steps":[{"astNodeIds":["10"],"id":"27","text":"there are 5 0.20 coins inside"},{"astNodeIds":["11"],"id":"28","text":"there are 3 chocolates inside"},{"astNodeIds":["12"],"id":"29","text":"the customer tries to buy a 0.80 chocolate with a 1 coin"},{"astNodeIds":["13"],"id":"30","text":"the customer's change should be 1 0.20 coin"}],"tags":[],"uri":"features/rules/rules.feature"}}
6
+ {"pickle":{"astNodeIds":["20"],"id":"36","language":"en","name":"no chocolates left","steps":[{"astNodeIds":["16"],"id":"32","text":"there are no chocolates inside"},{"astNodeIds":["17"],"id":"33","text":"there are 10 0.5 coins inside"},{"astNodeIds":["18"],"id":"34","text":"the customer tries to buy a 0.85 chocolate with a 1 coin"},{"astNodeIds":["19"],"id":"35","text":"the sale should not happen"}],"tags":[{"astNodeId":"21","name":"@some-tag"}],"uri":"features/rules/rules.feature"}}
7
+ {"stepDefinition":{"id":"0","pattern":{"source":"there are {int} {float} coins inside","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":4},"uri":"features/rules/rules.feature.ts"}}}
8
+ {"stepDefinition":{"id":"1","pattern":{"source":"there are no chocolates inside","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":10},"uri":"features/rules/rules.feature.ts"}}}
9
+ {"stepDefinition":{"id":"2","pattern":{"source":"there are {int} chocolates inside","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":14},"uri":"features/rules/rules.feature.ts"}}}
10
+ {"stepDefinition":{"id":"3","pattern":{"source":"the customer tries to buy a {float} chocolate with a {float} coin","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":19},"uri":"features/rules/rules.feature.ts"}}}
11
+ {"stepDefinition":{"id":"4","pattern":{"source":"the sale should not happen","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":25},"uri":"features/rules/rules.feature.ts"}}}
12
+ {"stepDefinition":{"id":"5","pattern":{"source":"the customer's change should be {int} {float} coin(s)","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":29},"uri":"features/rules/rules.feature.ts"}}}
13
+ {"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}}
14
+ {"testCase":{"id":"40","pickleId":"26","testSteps":[{"id":"37","pickleStepId":"23","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"5"},"parameterTypeName":"int"},{"group":{"children":[],"start":12,"value":"0.20"},"parameterTypeName":"float"}]}]},{"id":"38","pickleStepId":"24","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":28,"value":"0.85"},"parameterTypeName":"float"},{"group":{"children":[],"start":50,"value":"1"},"parameterTypeName":"float"}]}]},{"id":"39","pickleStepId":"25","stepDefinitionIds":["4"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}}
15
+ {"testCase":{"id":"45","pickleId":"31","testSteps":[{"id":"41","pickleStepId":"27","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"5"},"parameterTypeName":"int"},{"group":{"children":[],"start":12,"value":"0.20"},"parameterTypeName":"float"}]}]},{"id":"42","pickleStepId":"28","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"3"},"parameterTypeName":"int"}]}]},{"id":"43","pickleStepId":"29","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":28,"value":"0.80"},"parameterTypeName":"float"},{"group":{"children":[],"start":50,"value":"1"},"parameterTypeName":"float"}]}]},{"id":"44","pickleStepId":"30","stepDefinitionIds":["5"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":32,"value":"1"},"parameterTypeName":"int"},{"group":{"children":[],"start":34,"value":"0.20"},"parameterTypeName":"float"}]}]}]}}
16
+ {"testCase":{"id":"50","pickleId":"36","testSteps":[{"id":"46","pickleStepId":"32","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"47","pickleStepId":"33","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"10"},"parameterTypeName":"int"},{"group":{"children":[],"start":13,"value":"0.5"},"parameterTypeName":"float"}]}]},{"id":"48","pickleStepId":"34","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":28,"value":"0.85"},"parameterTypeName":"float"},{"group":{"children":[],"start":50,"value":"1"},"parameterTypeName":"float"}]}]},{"id":"49","pickleStepId":"35","stepDefinitionIds":["4"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}}
17
+ {"testCaseStarted":{"attempt":0,"id":"51","testCaseId":"40","timestamp":{"nanos":1000000,"seconds":0}}}
18
+ {"testStepStarted":{"testCaseStartedId":"51","testStepId":"37","timestamp":{"nanos":2000000,"seconds":0}}}
19
+ {"testStepFinished":{"testCaseStartedId":"51","testStepId":"37","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}}
20
+ {"testStepStarted":{"testCaseStartedId":"51","testStepId":"38","timestamp":{"nanos":4000000,"seconds":0}}}
21
+ {"testStepFinished":{"testCaseStartedId":"51","testStepId":"38","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}}
22
+ {"testStepStarted":{"testCaseStartedId":"51","testStepId":"39","timestamp":{"nanos":6000000,"seconds":0}}}
23
+ {"testStepFinished":{"testCaseStartedId":"51","testStepId":"39","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}}
24
+ {"testCaseFinished":{"testCaseStartedId":"51","timestamp":{"nanos":8000000,"seconds":0},"willBeRetried":false}}
25
+ {"testCaseStarted":{"attempt":0,"id":"52","testCaseId":"45","timestamp":{"nanos":9000000,"seconds":0}}}
26
+ {"testStepStarted":{"testCaseStartedId":"52","testStepId":"41","timestamp":{"nanos":10000000,"seconds":0}}}
27
+ {"testStepFinished":{"testCaseStartedId":"52","testStepId":"41","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":11000000,"seconds":0}}}
28
+ {"testStepStarted":{"testCaseStartedId":"52","testStepId":"42","timestamp":{"nanos":12000000,"seconds":0}}}
29
+ {"testStepFinished":{"testCaseStartedId":"52","testStepId":"42","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":13000000,"seconds":0}}}
30
+ {"testStepStarted":{"testCaseStartedId":"52","testStepId":"43","timestamp":{"nanos":14000000,"seconds":0}}}
31
+ {"testStepFinished":{"testCaseStartedId":"52","testStepId":"43","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":15000000,"seconds":0}}}
32
+ {"testStepStarted":{"testCaseStartedId":"52","testStepId":"44","timestamp":{"nanos":16000000,"seconds":0}}}
33
+ {"testStepFinished":{"testCaseStartedId":"52","testStepId":"44","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":17000000,"seconds":0}}}
34
+ {"testCaseFinished":{"testCaseStartedId":"52","timestamp":{"nanos":18000000,"seconds":0},"willBeRetried":false}}
35
+ {"testCaseStarted":{"attempt":0,"id":"53","testCaseId":"50","timestamp":{"nanos":19000000,"seconds":0}}}
36
+ {"testStepStarted":{"testCaseStartedId":"53","testStepId":"46","timestamp":{"nanos":20000000,"seconds":0}}}
37
+ {"testStepFinished":{"testCaseStartedId":"53","testStepId":"46","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":21000000,"seconds":0}}}
38
+ {"testStepStarted":{"testCaseStartedId":"53","testStepId":"47","timestamp":{"nanos":22000000,"seconds":0}}}
39
+ {"testStepFinished":{"testCaseStartedId":"53","testStepId":"47","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":23000000,"seconds":0}}}
40
+ {"testStepStarted":{"testCaseStartedId":"53","testStepId":"48","timestamp":{"nanos":24000000,"seconds":0}}}
41
+ {"testStepFinished":{"testCaseStartedId":"53","testStepId":"48","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":25000000,"seconds":0}}}
42
+ {"testStepStarted":{"testCaseStartedId":"53","testStepId":"49","timestamp":{"nanos":26000000,"seconds":0}}}
43
+ {"testStepFinished":{"testCaseStartedId":"53","testStepId":"49","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":27000000,"seconds":0}}}
44
+ {"testCaseFinished":{"testCaseStartedId":"53","timestamp":{"nanos":28000000,"seconds":0},"willBeRetried":false}}
45
+ {"testRunFinished":{"success":true,"timestamp":{"nanos":29000000,"seconds":0}}}
@@ -0,0 +1,26 @@
1
+ Given('there are {int} {float} coins inside') do |count, coin_type|
2
+ expect(count).not_to be_nil
3
+ expect(coin_type.to_s).not_to be_empty
4
+ end
5
+
6
+ When('the customer tries to buy a {float} chocolate with a {int} coin') do |count, coin_type|
7
+ expect(count).not_to be_nil
8
+ expect(coin_type.to_s).not_to be_empty
9
+ end
10
+
11
+ Then('the sale should not happen') do
12
+ true
13
+ end
14
+
15
+ Given('there are {int} chocolates inside') do |count|
16
+ expect(count).not_to be_nil
17
+ end
18
+
19
+ Then("the customer's change should be {int} {float} coin") do |count, coin_type|
20
+ expect(count).not_to be_nil
21
+ expect(coin_type.to_s).not_to be_empty
22
+ end
23
+
24
+ Given('there are no chocolates inside') do
25
+ true
26
+ end
@@ -0,0 +1,19 @@
1
+ Feature: Skipping scenarios
2
+
3
+ Hooks and step definitions are able to signal at runtime that the scenario should
4
+ be skipped by returning or throwing a particular value.
5
+
6
+ This can be useful when e.g. the current environment doesn't have the right conditions
7
+ for running the scenario.
8
+
9
+ @skip
10
+ Scenario: Skipping from a Before hook
11
+ Given a step that we expect to be skipped
12
+
13
+ Scenario: Skipping from a step doesn't affect the previous steps
14
+ Given an implemented step
15
+ When a step that skips
16
+
17
+ Scenario: Skipping from a step causes the rest of the scenario to be skipped
18
+ Given a step that skips
19
+ When a step that we expect to be skipped
@@ -0,0 +1,33 @@
1
+ {"meta":{"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"15.0.0"},"os":{"name":"linux","version":"5.11.0-34-generic"},"protocolVersion":"17.1.1","runtime":{"name":"node.js","version":"14.17.3"}}}
2
+ {"source":{"data":"Feature: Skipping scenarios\n\n Hooks and step definitions are able to signal at runtime that the scenario should\n be skipped by returning or throwing a particular value.\n\n This can be useful when e.g. the current environment doesn't have the right conditions\n for running the scenario.\n\n @skip\n Scenario: Skipping from a Before hook\n Given a step that we expect to be skipped\n\n Scenario: Skipping from a step doesn't affect the previous steps\n Given an implemented step\n When a step that skips\n\n Scenario: Skipping from a step causes the rest of the scenario to be skipped\n Given a step that skips\n When a step that we expect to be skipped\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"features/skipped/skipped.feature"}}
3
+ {"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"6","keyword":"Scenario","location":{"column":3,"line":10},"name":"Skipping from a Before hook","steps":[{"id":"4","keyword":"Given ","location":{"column":5,"line":11},"text":"a step that we expect to be skipped"}],"tags":[{"id":"5","location":{"column":3,"line":9},"name":"@skip"}]}},{"scenario":{"description":"","examples":[],"id":"9","keyword":"Scenario","location":{"column":3,"line":13},"name":"Skipping from a step doesn't affect the previous steps","steps":[{"id":"7","keyword":"Given ","location":{"column":5,"line":14},"text":"an implemented step"},{"id":"8","keyword":"When ","location":{"column":5,"line":15},"text":"a step that skips"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"12","keyword":"Scenario","location":{"column":3,"line":17},"name":"Skipping from a step causes the rest of the scenario to be skipped","steps":[{"id":"10","keyword":"Given ","location":{"column":5,"line":18},"text":"a step that skips"},{"id":"11","keyword":"When ","location":{"column":5,"line":19},"text":"a step that we expect to be skipped"}],"tags":[]}}],"description":" Hooks and step definitions are able to signal at runtime that the scenario should\n be skipped by returning or throwing a particular value.\n\n This can be useful when e.g. the current environment doesn't have the right conditions\n for running the scenario.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Skipping scenarios","tags":[]},"uri":"features/skipped/skipped.feature"}}
4
+ {"pickle":{"astNodeIds":["6"],"id":"14","language":"en","name":"Skipping from a Before hook","steps":[{"astNodeIds":["4"],"id":"13","text":"a step that we expect to be skipped"}],"tags":[{"astNodeId":"5","name":"@skip"}],"uri":"features/skipped/skipped.feature"}}
5
+ {"pickle":{"astNodeIds":["9"],"id":"17","language":"en","name":"Skipping from a step doesn't affect the previous steps","steps":[{"astNodeIds":["7"],"id":"15","text":"an implemented step"},{"astNodeIds":["8"],"id":"16","text":"a step that skips"}],"tags":[],"uri":"features/skipped/skipped.feature"}}
6
+ {"pickle":{"astNodeIds":["12"],"id":"20","language":"en","name":"Skipping from a step causes the rest of the scenario to be skipped","steps":[{"astNodeIds":["10"],"id":"18","text":"a step that skips"},{"astNodeIds":["11"],"id":"19","text":"a step that we expect to be skipped"}],"tags":[],"uri":"features/skipped/skipped.feature"}}
7
+ {"stepDefinition":{"id":"1","pattern":{"source":"an implemented step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":7},"uri":"features/skipped/skipped.feature.ts"}}}
8
+ {"stepDefinition":{"id":"2","pattern":{"source":"a step that we expect to be skipped","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":11},"uri":"features/skipped/skipped.feature.ts"}}}
9
+ {"stepDefinition":{"id":"3","pattern":{"source":"a step that skips","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":15},"uri":"features/skipped/skipped.feature.ts"}}}
10
+ {"hook":{"id":"0","sourceReference":{"location":{"line":3},"uri":"features/skipped/skipped.feature.ts"},"tagExpression":"@skip"}}
11
+ {"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}}
12
+ {"testCase":{"id":"23","pickleId":"14","testSteps":[{"hookId":"0","id":"21"},{"id":"22","pickleStepId":"13","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}}
13
+ {"testCase":{"id":"26","pickleId":"17","testSteps":[{"id":"24","pickleStepId":"15","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"25","pickleStepId":"16","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}}
14
+ {"testCase":{"id":"29","pickleId":"20","testSteps":[{"id":"27","pickleStepId":"18","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"28","pickleStepId":"19","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}}
15
+ {"testCaseStarted":{"attempt":0,"id":"30","testCaseId":"23","timestamp":{"nanos":1000000,"seconds":0}}}
16
+ {"testStepStarted":{"testCaseStartedId":"30","testStepId":"21","timestamp":{"nanos":2000000,"seconds":0}}}
17
+ {"testStepFinished":{"testCaseStartedId":"30","testStepId":"21","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":3000000,"seconds":0}}}
18
+ {"testStepStarted":{"testCaseStartedId":"30","testStepId":"22","timestamp":{"nanos":4000000,"seconds":0}}}
19
+ {"testStepFinished":{"testCaseStartedId":"30","testStepId":"22","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":5000000,"seconds":0}}}
20
+ {"testCaseFinished":{"testCaseStartedId":"30","timestamp":{"nanos":6000000,"seconds":0},"willBeRetried":false}}
21
+ {"testCaseStarted":{"attempt":0,"id":"31","testCaseId":"26","timestamp":{"nanos":7000000,"seconds":0}}}
22
+ {"testStepStarted":{"testCaseStartedId":"31","testStepId":"24","timestamp":{"nanos":8000000,"seconds":0}}}
23
+ {"testStepFinished":{"testCaseStartedId":"31","testStepId":"24","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":9000000,"seconds":0}}}
24
+ {"testStepStarted":{"testCaseStartedId":"31","testStepId":"25","timestamp":{"nanos":10000000,"seconds":0}}}
25
+ {"testStepFinished":{"testCaseStartedId":"31","testStepId":"25","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":11000000,"seconds":0}}}
26
+ {"testCaseFinished":{"testCaseStartedId":"31","timestamp":{"nanos":12000000,"seconds":0},"willBeRetried":false}}
27
+ {"testCaseStarted":{"attempt":0,"id":"32","testCaseId":"29","timestamp":{"nanos":13000000,"seconds":0}}}
28
+ {"testStepStarted":{"testCaseStartedId":"32","testStepId":"27","timestamp":{"nanos":14000000,"seconds":0}}}
29
+ {"testStepFinished":{"testCaseStartedId":"32","testStepId":"27","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":15000000,"seconds":0}}}
30
+ {"testStepStarted":{"testCaseStartedId":"32","testStepId":"28","timestamp":{"nanos":16000000,"seconds":0}}}
31
+ {"testStepFinished":{"testCaseStartedId":"32","testStepId":"28","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":17000000,"seconds":0}}}
32
+ {"testCaseFinished":{"testCaseStartedId":"32","timestamp":{"nanos":18000000,"seconds":0},"willBeRetried":false}}
33
+ {"testRunFinished":{"success":true,"timestamp":{"nanos":19000000,"seconds":0}}}
@@ -0,0 +1,15 @@
1
+ After('@skip') do
2
+ 'skipped'
3
+ end
4
+
5
+ Given('an implemented step') do
6
+ # no-op
7
+ end
8
+
9
+ Given('a step that we expect to be skipped') do
10
+ # no-op
11
+ end
12
+
13
+ Given('a step that skips') do
14
+ 'skipped'
15
+ end
@@ -0,0 +1,11 @@
1
+ Feature: Stack traces
2
+ Nothing beats stack traces when it comes to diagnosing the source of a bug.
3
+ Cucumber provides helpful stack traces that:
4
+
5
+ - Include a stack frame from the Gherkin document
6
+ - Remove uninteresting frames by default
7
+
8
+ The first line of the stack trace must contain the feature file.
9
+
10
+ Scenario: A failing step
11
+ When a step throws an exception
@@ -0,0 +1,12 @@
1
+ {"meta":{"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"15.0.0"},"os":{"name":"linux","version":"5.11.0-34-generic"},"protocolVersion":"17.1.1","runtime":{"name":"node.js","version":"14.17.3"}}}
2
+ {"source":{"data":"Feature: Stack traces\n Nothing beats stack traces when it comes to diagnosing the source of a bug.\n Cucumber provides helpful stack traces that:\n \n - Include a stack frame from the Gherkin document\n - Remove uninteresting frames by default\n\n The first line of the stack trace must contain the feature file.\n\n Scenario: A failing step\n When a step throws an exception\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"features/stack-traces/stack-traces.feature"}}
3
+ {"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"2","keyword":"Scenario","location":{"column":3,"line":10},"name":"A failing step","steps":[{"id":"1","keyword":"When ","location":{"column":5,"line":11},"text":"a step throws an exception"}],"tags":[]}}],"description":" Nothing beats stack traces when it comes to diagnosing the source of a bug.\n Cucumber provides helpful stack traces that:\n \n - Include a stack frame from the Gherkin document\n - Remove uninteresting frames by default\n\n The first line of the stack trace must contain the feature file.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Stack traces","tags":[]},"uri":"features/stack-traces/stack-traces.feature"}}
4
+ {"pickle":{"astNodeIds":["2"],"id":"4","language":"en","name":"A failing step","steps":[{"astNodeIds":["1"],"id":"3","text":"a step throws an exception"}],"tags":[],"uri":"features/stack-traces/stack-traces.feature"}}
5
+ {"stepDefinition":{"id":"0","pattern":{"source":"a step throws an exception","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":3},"uri":"features/stack-traces/stack-traces.feature.ts"}}}
6
+ {"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}}
7
+ {"testCase":{"id":"6","pickleId":"4","testSteps":[{"id":"5","pickleStepId":"3","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}}
8
+ {"testCaseStarted":{"attempt":0,"id":"7","testCaseId":"6","timestamp":{"nanos":1000000,"seconds":0}}}
9
+ {"testStepStarted":{"testCaseStartedId":"7","testStepId":"5","timestamp":{"nanos":2000000,"seconds":0}}}
10
+ {"testStepFinished":{"testCaseStartedId":"7","testStepId":"5","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"message":"BOOM\nfeatures/stack-traces/stack-traces.feature:11","status":"FAILED"},"timestamp":{"nanos":3000000,"seconds":0}}}
11
+ {"testCaseFinished":{"testCaseStartedId":"7","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}}
12
+ {"testRunFinished":{"success":false,"timestamp":{"nanos":5000000,"seconds":0}}}
@@ -0,0 +1,3 @@
1
+ When('a step throws an exception') do
2
+ raise StandardError, 'An exception is raised here'
3
+ end
@@ -0,0 +1,17 @@
1
+ Feature: Undefined steps
2
+
3
+ At runtime, Cucumber may encounter a step in a scenario that it cannot match to a
4
+ step definition. In these cases, the scenario cannot run and so the step status
5
+ will be UNDEFINED, with subsequent steps being skipped and the overall result treated
6
+ as a failure.
7
+
8
+ Scenario: Undefined step causes failure
9
+ Given a step that isnt implemented yet
10
+
11
+ Scenario: Steps before undefined steps are executed
12
+ Given an implemented step
13
+ When a step that isnt implemented yet
14
+
15
+ Scenario: Steps after undefined steps are skipped
16
+ Given a step that isnt implemented yet
17
+ Then a step that we expect to be skipped
@@ -0,0 +1,29 @@
1
+ {"meta":{"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"15.0.0"},"os":{"name":"linux","version":"5.11.0-34-generic"},"protocolVersion":"17.1.1","runtime":{"name":"node.js","version":"14.17.3"}}}
2
+ {"source":{"data":"Feature: Undefined steps\n\n At runtime, Cucumber may encounter a step in a scenario that it cannot match to a\n step definition. In these cases, the scenario cannot run and so the step status\n will be UNDEFINED, with subsequent steps being skipped and the overall result treated\n as a failure.\n\n Scenario: Undefined step causes failure\n Given a step that isnt implemented yet\n\n Scenario: Steps before undefined steps are executed\n Given an implemented step\n When a step that isnt implemented yet\n\n Scenario: Steps after undefined steps are skipped\n Given a step that isnt implemented yet\n Then a step that we expect to be skipped\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"features/undefined/undefined.feature"}}
3
+ {"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"3","keyword":"Scenario","location":{"column":3,"line":8},"name":"Undefined step causes failure","steps":[{"id":"2","keyword":"Given ","location":{"column":5,"line":9},"text":"a step that isnt implemented yet"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"6","keyword":"Scenario","location":{"column":3,"line":11},"name":"Steps before undefined steps are executed","steps":[{"id":"4","keyword":"Given ","location":{"column":5,"line":12},"text":"an implemented step"},{"id":"5","keyword":"When ","location":{"column":5,"line":13},"text":"a step that isnt implemented yet"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"9","keyword":"Scenario","location":{"column":3,"line":15},"name":"Steps after undefined steps are skipped","steps":[{"id":"7","keyword":"Given ","location":{"column":5,"line":16},"text":"a step that isnt implemented yet"},{"id":"8","keyword":"Then ","location":{"column":5,"line":17},"text":"a step that we expect to be skipped"}],"tags":[]}}],"description":" At runtime, Cucumber may encounter a step in a scenario that it cannot match to a\n step definition. In these cases, the scenario cannot run and so the step status\n will be UNDEFINED, with subsequent steps being skipped and the overall result treated\n as a failure.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Undefined steps","tags":[]},"uri":"features/undefined/undefined.feature"}}
4
+ {"pickle":{"astNodeIds":["3"],"id":"11","language":"en","name":"Undefined step causes failure","steps":[{"astNodeIds":["2"],"id":"10","text":"a step that isnt implemented yet"}],"tags":[],"uri":"features/undefined/undefined.feature"}}
5
+ {"pickle":{"astNodeIds":["6"],"id":"14","language":"en","name":"Steps before undefined steps are executed","steps":[{"astNodeIds":["4"],"id":"12","text":"an implemented step"},{"astNodeIds":["5"],"id":"13","text":"a step that isnt implemented yet"}],"tags":[],"uri":"features/undefined/undefined.feature"}}
6
+ {"pickle":{"astNodeIds":["9"],"id":"17","language":"en","name":"Steps after undefined steps are skipped","steps":[{"astNodeIds":["7"],"id":"15","text":"a step that isnt implemented yet"},{"astNodeIds":["8"],"id":"16","text":"a step that we expect to be skipped"}],"tags":[],"uri":"features/undefined/undefined.feature"}}
7
+ {"stepDefinition":{"id":"0","pattern":{"source":"an implemented step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":3},"uri":"features/undefined/undefined.feature.ts"}}}
8
+ {"stepDefinition":{"id":"1","pattern":{"source":"a step that we expect to be skipped","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":7},"uri":"features/undefined/undefined.feature.ts"}}}
9
+ {"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}}
10
+ {"testCase":{"id":"19","pickleId":"11","testSteps":[{"id":"18","pickleStepId":"10","stepDefinitionIds":[],"stepMatchArgumentsLists":[]}]}}
11
+ {"testCase":{"id":"22","pickleId":"14","testSteps":[{"id":"20","pickleStepId":"12","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"21","pickleStepId":"13","stepDefinitionIds":[],"stepMatchArgumentsLists":[]}]}}
12
+ {"testCase":{"id":"25","pickleId":"17","testSteps":[{"id":"23","pickleStepId":"15","stepDefinitionIds":[],"stepMatchArgumentsLists":[]},{"id":"24","pickleStepId":"16","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}}
13
+ {"testCaseStarted":{"attempt":0,"id":"26","testCaseId":"19","timestamp":{"nanos":1000000,"seconds":0}}}
14
+ {"testStepStarted":{"testCaseStartedId":"26","testStepId":"18","timestamp":{"nanos":2000000,"seconds":0}}}
15
+ {"testStepFinished":{"testCaseStartedId":"26","testStepId":"18","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":3000000,"seconds":0}}}
16
+ {"testCaseFinished":{"testCaseStartedId":"26","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}}
17
+ {"testCaseStarted":{"attempt":0,"id":"27","testCaseId":"22","timestamp":{"nanos":5000000,"seconds":0}}}
18
+ {"testStepStarted":{"testCaseStartedId":"27","testStepId":"20","timestamp":{"nanos":6000000,"seconds":0}}}
19
+ {"testStepFinished":{"testCaseStartedId":"27","testStepId":"20","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}}
20
+ {"testStepStarted":{"testCaseStartedId":"27","testStepId":"21","timestamp":{"nanos":8000000,"seconds":0}}}
21
+ {"testStepFinished":{"testCaseStartedId":"27","testStepId":"21","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":9000000,"seconds":0}}}
22
+ {"testCaseFinished":{"testCaseStartedId":"27","timestamp":{"nanos":10000000,"seconds":0},"willBeRetried":false}}
23
+ {"testCaseStarted":{"attempt":0,"id":"28","testCaseId":"25","timestamp":{"nanos":11000000,"seconds":0}}}
24
+ {"testStepStarted":{"testCaseStartedId":"28","testStepId":"23","timestamp":{"nanos":12000000,"seconds":0}}}
25
+ {"testStepFinished":{"testCaseStartedId":"28","testStepId":"23","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":13000000,"seconds":0}}}
26
+ {"testStepStarted":{"testCaseStartedId":"28","testStepId":"24","timestamp":{"nanos":14000000,"seconds":0}}}
27
+ {"testStepFinished":{"testCaseStartedId":"28","testStepId":"24","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":15000000,"seconds":0}}}
28
+ {"testCaseFinished":{"testCaseStartedId":"28","timestamp":{"nanos":16000000,"seconds":0},"willBeRetried":false}}
29
+ {"testRunFinished":{"success":false,"timestamp":{"nanos":17000000,"seconds":0}}}
@@ -0,0 +1,7 @@
1
+ Given('an implemented step') do
2
+ # no-op
3
+ end
4
+
5
+ Given('a step that we expect to be skipped') do
6
+ # no-op
7
+ end
@@ -0,0 +1,6 @@
1
+ Feature: Parameter Types
2
+ Cucumber will generate an error message if a step definition registers
3
+ an unknown parameter type, but the suite will run.
4
+
5
+ Scenario: undefined parameter type
6
+ Given CDG is closed because of a strike
@@ -0,0 +1,12 @@
1
+ {"meta":{"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"15.0.0"},"os":{"name":"linux","version":"5.11.0-34-generic"},"protocolVersion":"17.1.1","runtime":{"name":"node.js","version":"14.17.3"}}}
2
+ {"source":{"data":"Feature: Parameter Types\n Cucumber will generate an error message if a step definition registers\n an unknown parameter type, but the suite will run.\n\n Scenario: undefined parameter type\n Given CDG is closed because of a strike","mediaType":"text/x.cucumber.gherkin+plain","uri":"features/unknown-parameter-type/unknown-parameter-type.feature"}}
3
+ {"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"1","keyword":"Scenario","location":{"column":3,"line":5},"name":"undefined parameter type","steps":[{"id":"0","keyword":"Given ","location":{"column":5,"line":6},"text":"CDG is closed because of a strike"}],"tags":[]}}],"description":" Cucumber will generate an error message if a step definition registers\n an unknown parameter type, but the suite will run.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Parameter Types","tags":[]},"uri":"features/unknown-parameter-type/unknown-parameter-type.feature"}}
4
+ {"pickle":{"astNodeIds":["1"],"id":"3","language":"en","name":"undefined parameter type","steps":[{"astNodeIds":["0"],"id":"2","text":"CDG is closed because of a strike"}],"tags":[],"uri":"features/unknown-parameter-type/unknown-parameter-type.feature"}}
5
+ {"undefinedParameterType":{"expression":"{airport} is closed because of a strike","name":"airport"}}
6
+ {"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}}
7
+ {"testCase":{"id":"5","pickleId":"3","testSteps":[{"id":"4","pickleStepId":"2","stepDefinitionIds":[],"stepMatchArgumentsLists":[]}]}}
8
+ {"testCaseStarted":{"attempt":0,"id":"6","testCaseId":"5","timestamp":{"nanos":1000000,"seconds":0}}}
9
+ {"testStepStarted":{"testCaseStartedId":"6","testStepId":"4","timestamp":{"nanos":2000000,"seconds":0}}}
10
+ {"testStepFinished":{"testCaseStartedId":"6","testStepId":"4","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":3000000,"seconds":0}}}
11
+ {"testCaseFinished":{"testCaseStartedId":"6","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}}
12
+ {"testRunFinished":{"success":false,"timestamp":{"nanos":5000000,"seconds":0}}}
@@ -0,0 +1,3 @@
1
+ Given('{airport} is closed because of a strike') do |airport|
2
+ raise StandardError, 'Should not be called because airport type not defined'
3
+ end
@@ -0,0 +1,55 @@
1
+ require 'shared_examples'
2
+
3
+ module Cucumber::CompatibilityKit
4
+ class << self
5
+ def all_examples
6
+ gherkin_examples + markdown_examples
7
+ end
8
+
9
+ def gherkin_examples
10
+ Dir
11
+ .entries(examples_path)
12
+ .select do |file|
13
+ folder = File.join(examples_path, file)
14
+
15
+ file != '.' && file != '..' &&
16
+ File.directory?(folder) &&
17
+ is_gherkin_example?(folder)
18
+ end
19
+ end
20
+
21
+ def markdown_examples
22
+ Dir
23
+ .entries(examples_path)
24
+ .select do |file|
25
+ folder = File.join(examples_path, file)
26
+
27
+ file != '.' && file != '..' &&
28
+ File.directory?(folder) &&
29
+ is_markdown_example?(folder)
30
+ end
31
+ end
32
+
33
+ def examples_path
34
+ File.expand_path("#{File.dirname(__FILE__)}/../features/")
35
+ end
36
+
37
+ def example_path(example_name)
38
+ path = File.join(examples_path, example_name)
39
+
40
+ return path if File.directory?(path)
41
+
42
+ raise ArgumentError.new
43
+ end
44
+
45
+ private
46
+
47
+ def is_gherkin_example?(example_folder)
48
+ Dir.entries(example_folder).select { |file| File.extname(file) == '.feature' }.count > 0
49
+ end
50
+
51
+ def is_markdown_example?(example_folder)
52
+ Dir.entries(example_folder).select { |file| File.extname(file) == '.md' }.count > 0
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,24 @@
1
+ module CCK
2
+ class KeysChecker
3
+ def self.compare(found, expected)
4
+ KeysChecker.new.compare(found, expected)
5
+ end
6
+
7
+ def compare(found, expected)
8
+ errors = []
9
+
10
+ found_keys = found.to_h(reject_nil_values: true).keys
11
+ expected_keys = expected.to_h(reject_nil_values: true).keys
12
+
13
+ return errors if found_keys.sort == expected_keys.sort
14
+
15
+ missing_keys = (expected_keys - found_keys)
16
+
17
+ extra_keys = (found_keys - expected_keys)
18
+
19
+ errors << "Found extra keys in message #{found.class.name}: #{extra_keys}" unless extra_keys.empty?
20
+ errors << "Missing keys in message #{found.class.name}: #{missing_keys}" unless missing_keys.empty?
21
+ errors
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,83 @@
1
+ require_relative 'keys_checker'
2
+
3
+ module CCK
4
+ class MessagesComparator
5
+ def initialize(validator, found, expected)
6
+ @all_errors = []
7
+ @compared = []
8
+ @validator = validator
9
+
10
+ compare(found, expected)
11
+ end
12
+
13
+ def errors
14
+ @all_errors.flatten
15
+ end
16
+
17
+ def debug
18
+ # puts 'Compared the following type of message:'
19
+ # puts @compared.uniq.map { |m| " - #{m}" }.join("\n")
20
+ # puts ''
21
+ puts errors.uniq.join("\n")
22
+ end
23
+
24
+ private
25
+
26
+ def compare(found, expected)
27
+ found_by_type = messages_by_type(found)
28
+ expected_by_type = messages_by_type(expected)
29
+
30
+ found_by_type.keys.each do |type|
31
+ compare_list(found_by_type[type], expected_by_type[type])
32
+ end
33
+ end
34
+
35
+ def messages_by_type(messages)
36
+ by_type = Hash.new { |h, k| h[k] = [] }
37
+ messages.each do |msg|
38
+ by_type[message_type(msg)] << remove_envelope(msg)
39
+ end
40
+ by_type
41
+ end
42
+
43
+ def message_type(message)
44
+ message.to_h.each do |key, value|
45
+ return key unless value.nil?
46
+ end
47
+ end
48
+
49
+ def remove_envelope(message)
50
+ message.send(message_type(message))
51
+ end
52
+
53
+ def compare_list(found, expected)
54
+ found.each_with_index do |message, index|
55
+ compare_message(message, expected[index])
56
+ end
57
+ end
58
+
59
+ def compare_message(found, expected)
60
+ return unless found.is_a?(Cucumber::Messages::Message)
61
+ return if found.is_a?(Cucumber::Messages::GherkinDocument)
62
+ return if found.is_a?(Cucumber::Messages::Pickle)
63
+ return if found.is_a?(Cucumber::Messages::Timestamp) && expected.is_a?(Cucumber::Messages::Timestamp)
64
+ return if found.is_a?(Cucumber::Messages::Duration) && expected.is_a?(Cucumber::Messages::Duration)
65
+
66
+ @compared << found.class.name
67
+ @all_errors << @validator.compare(found, expected)
68
+ compare_sub_messages(found, expected)
69
+ end
70
+
71
+ def compare_sub_messages(found, expected)
72
+ return unless expected.respond_to? :to_h
73
+ expected.to_h.keys.each do |key|
74
+ value = expected.send(key)
75
+ if value.is_a?(Array)
76
+ compare_list(found.send(key), value)
77
+ else
78
+ compare_message(found.send(key), value)
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,63 @@
1
+ require 'json'
2
+ require 'rspec'
3
+ require 'cucumber/messages'
4
+
5
+ require 'messages_comparator'
6
+ require 'keys_checker'
7
+
8
+ RSpec.shared_examples 'cucumber compatibility kit' do
9
+ # Note: to use those examples, you need to define:
10
+ # let(:example) { } # the name of the example to test
11
+ # let(:messages) { } # the messages to validate
12
+
13
+ let(:example) { raise "`example` missing: add `let(:example) { example_name }` to your spec" }
14
+ let(:messages) { raise "`messages` missing: add `let(:messages) { ndjson }` to your spec" }
15
+
16
+ let(:example_path) { Cucumber::CompatibilityKit.example_path(example) }
17
+
18
+ let(:parsed_original) { parse_ndjson_file("#{example_path}/#{example}.feature.ndjson") }
19
+ let(:parsed_generated) { parse_ndjson(messages) }
20
+
21
+ let(:original_messages_types) { parsed_original.map { |msg| message_type(msg) } }
22
+ let(:generated_messages_types) { parsed_generated.map { |msg| message_type(msg) } }
23
+
24
+ it 'generates valid message types' do
25
+ debug_lists(original_messages_types, generated_messages_types)
26
+ expect(generated_messages_types).to contain_exactly(*original_messages_types)
27
+ end
28
+
29
+ it 'generates valid message structure' do
30
+ comparator = CCK::MessagesComparator.new(CCK::KeysChecker, parsed_generated, parsed_original)
31
+ comparator.debug if ENV['VERBOSE']
32
+
33
+ if comparator.errors.any?
34
+ fail "There were comparison errors: #{comparator.errors}"
35
+ end
36
+ end
37
+ end
38
+
39
+ def parse_ndjson_file(path)
40
+ parse_ndjson(File.read(path))
41
+ end
42
+
43
+ def parse_ndjson(ndjson)
44
+ Cucumber::Messages::NdjsonToMessageEnumerator.new(ndjson)
45
+ end
46
+
47
+ def message_type(message)
48
+ message.to_h.keys.first
49
+ end
50
+
51
+ def debug_lists(expected, obtained)
52
+ return unless ENV['VERBOSE']
53
+ return if expected.sort == obtained.sort
54
+
55
+ to_read = expected.count > obtained.count ? expected : obtained
56
+ columnize = "\t\t\t\t | \t\t\t\t"
57
+
58
+ puts " | Expected #{columnize} GOT"
59
+ to_read.each_with_index do |_, index|
60
+ ok = expected[index] == obtained[index] ? 'v' : 'x'
61
+ puts "[#{ok}] | #{expected[index]} #{columnize} #{obtained[index]}"
62
+ end
63
+ end