cucumber-compatibility-kit 9.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +56 -0
- data/features/attachments/attachments.feature +41 -0
- data/features/attachments/attachments.feature.ndjson +77 -0
- data/features/attachments/attachments.feature.rb +51 -0
- data/features/attachments/cucumber.png +0 -0
- data/features/data-tables/data-tables.feature +12 -0
- data/features/data-tables/data-tables.feature.ndjson +15 -0
- data/features/data-tables/data-tables.feature.rb +7 -0
- data/features/examples-tables/examples-tables.feature +28 -0
- data/features/examples-tables/examples-tables.feature.ndjson +68 -0
- data/features/examples-tables/examples-tables.feature.rb +11 -0
- data/features/hooks/cucumber.svg +7 -0
- data/features/hooks/hooks.feature +20 -0
- data/features/hooks/hooks.feature.ndjson +66 -0
- data/features/hooks/hooks.feature.rb +28 -0
- data/features/markdown/markdown.feature.md +46 -0
- data/features/markdown/markdown.feature.md.ndjson +35 -0
- data/features/minimal/minimal.feature +10 -0
- data/features/minimal/minimal.feature.ndjson +12 -0
- data/features/minimal/minimal.feature.rb +2 -0
- data/features/parameter-types/parameter-types.feature +9 -0
- data/features/parameter-types/parameter-types.feature.ndjson +13 -0
- data/features/parameter-types/parameter-types.feature.rb +21 -0
- data/features/pending/pending.feature +19 -0
- data/features/pending/pending.feature.ndjson +30 -0
- data/features/pending/pending.feature.rb +11 -0
- data/features/retry/retry.feature +22 -0
- data/features/retry/retry.feature.ndjson +59 -0
- data/features/retry/retry.feature.rb +23 -0
- data/features/rules/rules.feature +27 -0
- data/features/rules/rules.feature.ndjson +45 -0
- data/features/rules/rules.feature.rb +26 -0
- data/features/skipped/skipped.feature +19 -0
- data/features/skipped/skipped.feature.ndjson +33 -0
- data/features/skipped/skipped.feature.rb +15 -0
- data/features/stack-traces/stack-traces.feature +11 -0
- data/features/stack-traces/stack-traces.feature.ndjson +12 -0
- data/features/stack-traces/stack-traces.feature.rb +3 -0
- data/features/undefined/undefined.feature +17 -0
- data/features/undefined/undefined.feature.ndjson +29 -0
- data/features/undefined/undefined.feature.rb +7 -0
- data/features/unknown-parameter-type/unknown-parameter-type.feature +6 -0
- data/features/unknown-parameter-type/unknown-parameter-type.feature.ndjson +12 -0
- data/features/unknown-parameter-type/unknown-parameter-type.feature.rb +3 -0
- data/lib/cucumber-compatibility-kit.rb +55 -0
- data/lib/keys_checker.rb +24 -0
- data/lib/messages_comparator.rb +83 -0
- data/lib/shared_examples.rb +63 -0
- data/spec/capture_warnings.rb +74 -0
- data/spec/cucumber-compatibility-kit_spec.rb +71 -0
- data/spec/keys_checker_spec.rb +77 -0
- 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,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,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,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,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
|
data/lib/keys_checker.rb
ADDED
@@ -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
|