Skip to content

Commit 529e16f

Browse files
authored
Slice hook and attachment samples more thinly (#122)
With smaller samples it becomes easier to analyse failures in the CCK and makes it easier to work towards incremental conformance when features are not supported. This splits the hooks sample into: * A sample purely about hooks * A sample about conditional hooks * A sample about using hooks with attachments * A sample about using attachments in hooks The attachments sample is split into: * A sample purely about attachments * A sample about attachments in example tables The naming is a bit arbitrary, but I thought hooks and example tables are more fundamental, so I put those first. Closes: #121
1 parent ab5a4e2 commit 529e16f

21 files changed

+309
-190
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
66
and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
9+
### Changed
10+
- [Devkit] Slice hook and attachment samples more thinly ([#122](https://github.com/cucumber/compatibility-kit/pull/122))
911

1012
## [17.0.1] - 2025-01-29
1113
### Fixed

devkit/samples/attachments/attachments.feature

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,6 @@ Feature: Attachments
3636
Scenario: Attaching PNG images
3737
When a PNG image is attached
3838

39-
Scenario Outline: Attaching images in an examples table
40-
When a <type> image is attached
41-
42-
Examples:
43-
| type |
44-
| JPEG |
45-
| PNG |
46-
4739
Scenario: Attaching PDFs with a different filename
4840
When a PDF document is attached and renamed
4941

devkit/samples/attachments/attachments.feature.ndjson

Lines changed: 68 additions & 82 deletions
Large diffs are not rendered by default.
1.41 KB
Loading
1.7 KB
Loading
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Feature: Examples Tables - With attachments
2+
It is sometimes useful to take a screenshot while a scenario runs.
3+
Or capture some logs.
4+
5+
This can also be done in an examples table.
6+
7+
Scenario Outline: Attaching images in an examples table
8+
When a <type> image is attached
9+
10+
Examples:
11+
| type |
12+
| JPEG |
13+
| PNG |
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"linux","version":"6.8.0-52-generic"},"protocolVersion":"27.2.0","runtime":{"name":"node.js","version":"18.19.1"}}}
2+
{"source":{"data":"Feature: Examples Tables - With attachments\n It is sometimes useful to take a screenshot while a scenario runs.\n Or capture some logs.\n\n This can also be done in an examples table.\n\n Scenario Outline: Attaching images in an examples table\n When a <type> image is attached\n\n Examples:\n | type |\n | JPEG |\n | PNG |\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/examples-tables-attachment/examples-tables-attachment.feature"}}
3+
{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[{"description":"","id":"6","keyword":"Examples","location":{"column":5,"line":10},"name":"","tableBody":[{"cells":[{"location":{"column":9,"line":12},"value":"JPEG"}],"id":"4","location":{"column":7,"line":12}},{"cells":[{"location":{"column":9,"line":13},"value":"PNG"}],"id":"5","location":{"column":7,"line":13}}],"tableHeader":{"cells":[{"location":{"column":9,"line":11},"value":"type"}],"id":"3","location":{"column":7,"line":11}},"tags":[]}],"id":"7","keyword":"Scenario Outline","location":{"column":3,"line":7},"name":"Attaching images in an examples table","steps":[{"id":"2","keyword":"When ","keywordType":"Action","location":{"column":5,"line":8},"text":"a <type> image is attached"}],"tags":[]}}],"description":" It is sometimes useful to take a screenshot while a scenario runs.\n Or capture some logs.\n\n This can also be done in an examples table.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Examples Tables - With attachments","tags":[]},"uri":"samples/examples-tables-attachment/examples-tables-attachment.feature"}}
4+
{"pickle":{"astNodeIds":["7","4"],"id":"9","language":"en","name":"Attaching images in an examples table","steps":[{"astNodeIds":["2","4"],"id":"8","text":"a JPEG image is attached","type":"Action"}],"tags":[],"uri":"samples/examples-tables-attachment/examples-tables-attachment.feature"}}
5+
{"pickle":{"astNodeIds":["7","5"],"id":"11","language":"en","name":"Attaching images in an examples table","steps":[{"astNodeIds":["2","5"],"id":"10","text":"a PNG image is attached","type":"Action"}],"tags":[],"uri":"samples/examples-tables-attachment/examples-tables-attachment.feature"}}
6+
{"stepDefinition":{"id":"0","pattern":{"source":"a JPEG image is attached","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":4},"uri":"samples/examples-tables-attachment/examples-tables-attachment.feature.ts"}}}
7+
{"stepDefinition":{"id":"1","pattern":{"source":"a PNG image is attached","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":8},"uri":"samples/examples-tables-attachment/examples-tables-attachment.feature.ts"}}}
8+
{"testRunStarted":{"id":"12","timestamp":{"nanos":0,"seconds":0}}}
9+
{"testCase":{"id":"14","pickleId":"9","testRunStartedId":"12","testSteps":[{"id":"13","pickleStepId":"8","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}}
10+
{"testCase":{"id":"16","pickleId":"11","testRunStartedId":"12","testSteps":[{"id":"15","pickleStepId":"10","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}}
11+
{"testCaseStarted":{"attempt":0,"id":"17","testCaseId":"14","timestamp":{"nanos":1000000,"seconds":0}}}
12+
{"testStepStarted":{"testCaseStartedId":"17","testStepId":"13","timestamp":{"nanos":2000000,"seconds":0}}}
13+
{"attachment":{"body":"/9j/4AAQSkZJRgABAQAAAQABAAD//gAfQ29tcHJlc3NlZCBieSBqcGVnLXJlY29tcHJlc3P/2wCEAAQEBAQEBAQEBAQGBgUGBggHBwcHCAwJCQkJCQwTDA4MDA4MExEUEA8QFBEeFxUVFx4iHRsdIiolJSo0MjRERFwBBAQEBAQEBAQEBAYGBQYGCAcHBwcIDAkJCQkJDBMMDgwMDgwTERQQDxAUER4XFRUXHiIdGx0iKiUlKjQyNEREXP/CABEIAC4AKQMBIgACEQEDEQH/xAAcAAABBAMBAAAAAAAAAAAAAAAIBAUGBwABAwL/2gAIAQEAAAAAOESYe+lPPw0bK2mvU5gRhNkM/tNMGeuJM5msiEjujvC+s0ApSWvn/8QAFgEBAQEAAAAAAAAAAAAAAAAABQME/9oACAECEAAAADs6pclK4E//xAAWAQEBAQAAAAAAAAAAAAAAAAAHBgT/2gAIAQMQAAAAMJZbKcF1XHit/8QANhAAAQQBAgQDBAcJAAAAAAAAAgEDBAUGABEHEiExEyJREEFCUhRTYXFzgZIVFiMyMzRVY3L/2gAIAQEAAT8AzLMqPBKOReXb6gy3sDbYdXXnS/labH3mWrrMOIWdGb063fxyoPq1XVp8klQ/3v8Aff7E0eCY86fjPtynn99/GclOq5v6782quZnOGmEnEcrmPNN96y1cWTFcH5BUurf5a4bcTKzP6x9QjlBuIKo1YVzq7mwfuJF+IC9y+zPLc8z4kWiuHz1GLuLAht/AU3u+6qfMK+XUuV4TbrTBtFNVoyYZM0RTJE6dO+2+oGcWZY1fzp0URsq5wGuXkUU3dLlHmH1FdYvMs59HCmW7SBKdQiVEHl3Hfyqqe7dNFbOYRlNDnkQlBth9uHaoPZ2C+SCSl9oL1HX0qN9c3+pNY6pkeSG9/XO/sie9fEV5d9Z5FxdbKNKsbeREsUbHZGAVxeQV6Lt8K6gtMPQYzhD43istETjzaC45sm6EaeulzOgC1Kmdkm1KF3wvO2Qjz+m+syECxe7Q+30ZV/NF3TX7dyv5nv06zGpPDOJd/WvAoV+QvHb1znwk8f8AcN/9c3XUuhp5s1qyl17L0poUQDNN+3VN07LqDTZdNg5fLsFdanyxAI4c/wBUSnsGy9B9w6x+kWwrq2blFW2VtHVUF11P4qiC+RT27r9+r6E9kUyiwmDusq8nNMny924zZc7rv3Cia/dSg/xTH6dcQMDpc/oSqbLmZeaNHoUxro9GfHs4C6uoGZYC4cXM6Z+TCb6BdV7avRjH1dEerRagWEO0iNToDyOx3N+Q0RU32XZehbLq4u4VMyByFI33VQI8ZpOZ5416IICnVdcHuHNjUOSs3y5lByGwaRpiL3Svid0b/EL4vavbXDDBM5ymjjRKi3qK2vZ5lOSYOvykRw1Lyhsgawbg9jGGSUtzJ63v1TzWU/zuB+CPZtPb/8QAJREAAgEDBAEEAwAAAAAAAAAAAQIDAAQRBRITIVEUMTJhI0Fx/9oACAECAQE/ALy8eNxb2/z63N4zTy6hbbpJJ9wV9uCdwPWaglFxEkqDGeiPBFSv6bUZJXLhXGQVx3kfdPBbpyvLNyDOAEbsEjOfsVpJ4rUlx83JH8FSwxTqElTI/R9iKGkBJm5X/GGO1R7kV0AABgAYA8Cv/8QAJREAAgIBBAEDBQAAAAAAAAAAAQIDBAUABhESMSFRcRMVIjJB/9oACAEDAQE/AN1bpuJcbFYt+hXgSSDzydG9uLFF7T3yekwjKl+wY8dvHtrAZlMzjo7RAWQHrIvsw1k+2I3LdksmZVcsymPjlg/z/NTU6MIsy2bf1x26hYnHKsy9ufXyB41sWnN9rmlPKrJNyvwBxrL4LH5mMLbj/Nf1dfRhqjsKaa27WZgtRZD1APLsuq1aGpBHXgQLGihVA1//2Q==","contentEncoding":"BASE64","mediaType":"image/jpeg","testCaseStartedId":"17","testStepId":"13"}}
14+
{"testStepFinished":{"testCaseStartedId":"17","testStepId":"13","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}}
15+
{"testCaseFinished":{"testCaseStartedId":"17","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}}
16+
{"testCaseStarted":{"attempt":0,"id":"18","testCaseId":"16","timestamp":{"nanos":5000000,"seconds":0}}}
17+
{"testStepStarted":{"testCaseStartedId":"18","testStepId":"15","timestamp":{"nanos":6000000,"seconds":0}}}
18+
{"attachment":{"body":"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","contentEncoding":"BASE64","mediaType":"image/png","testCaseStartedId":"18","testStepId":"15"}}
19+
{"testStepFinished":{"testCaseStartedId":"18","testStepId":"15","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}}
20+
{"testCaseFinished":{"testCaseStartedId":"18","timestamp":{"nanos":8000000,"seconds":0},"willBeRetried":false}}
21+
{"testRunFinished":{"success":true,"testRunStartedId":"12","timestamp":{"nanos":9000000,"seconds":0}}}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { When } from '@cucumber/fake-cucumber'
2+
import fs from 'fs'
3+
4+
When('a JPEG image is attached', async function () {
5+
await this.attach(fs.createReadStream(__dirname + '/cucumber.jpeg'), 'image/jpeg')
6+
})
7+
8+
When('a PNG image is attached', async function () {
9+
await this.attach(fs.createReadStream(__dirname + '/cucumber.png'), 'image/png')
10+
})
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Feature: Hooks - Attachments
2+
Hooks are special steps that run before or after each scenario's steps.
3+
4+
Like regular steps, it is possible to attach a file to the output.
5+
6+
Scenario: With an valid attachment in the hook and a passed step
7+
When a step passes
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"18.0.0"},"os":{"name":"linux","version":"6.8.0-52-generic"},"protocolVersion":"27.2.0","runtime":{"name":"node.js","version":"18.19.1"}}}
2+
{"source":{"data":"Feature: Hooks - Attachments\n Hooks are special steps that run before or after each scenario's steps.\n\n Like regular steps, it is possible to attach a file to the output.\n\n Scenario: With an valid attachment in the hook and a passed step\n When a step passes\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/hooks-attachment/hooks-attachment.feature"}}
3+
{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"4","keyword":"Scenario","location":{"column":3,"line":6},"name":"With an valid attachment in the hook and a passed step","steps":[{"id":"3","keyword":"When ","keywordType":"Action","location":{"column":5,"line":7},"text":"a step passes"}],"tags":[]}}],"description":" Hooks are special steps that run before or after each scenario's steps.\n\n Like regular steps, it is possible to attach a file to the output.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Hooks - Attachments","tags":[]},"uri":"samples/hooks-attachment/hooks-attachment.feature"}}
4+
{"pickle":{"astNodeIds":["4"],"id":"6","language":"en","name":"With an valid attachment in the hook and a passed step","steps":[{"astNodeIds":["3"],"id":"5","text":"a step passes","type":"Action"}],"tags":[],"uri":"samples/hooks-attachment/hooks-attachment.feature"}}
5+
{"stepDefinition":{"id":"1","pattern":{"source":"a step passes","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":9},"uri":"samples/hooks-attachment/hooks-attachment.feature.ts"}}}
6+
{"hook":{"id":"0","sourceReference":{"location":{"line":4},"uri":"samples/hooks-attachment/hooks-attachment.feature.ts"},"type":"BEFORE_TEST_CASE"}}
7+
{"hook":{"id":"2","sourceReference":{"location":{"line":13},"uri":"samples/hooks-attachment/hooks-attachment.feature.ts"},"type":"AFTER_TEST_CASE"}}
8+
{"testRunStarted":{"id":"7","timestamp":{"nanos":0,"seconds":0}}}
9+
{"testCase":{"id":"11","pickleId":"6","testRunStartedId":"7","testSteps":[{"hookId":"0","id":"8"},{"id":"9","pickleStepId":"5","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"hookId":"2","id":"10"}]}}
10+
{"testCaseStarted":{"attempt":0,"id":"12","testCaseId":"11","timestamp":{"nanos":1000000,"seconds":0}}}
11+
{"testStepStarted":{"testCaseStartedId":"12","testStepId":"8","timestamp":{"nanos":2000000,"seconds":0}}}
12+
{"testStepFinished":{"testCaseStartedId":"12","testStepId":"8","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"ENOENT: no such file or directory, open '/home/mpkorstanje/Projects/cucumber/compatibility-kit/devkit/samples/hooks-attachment/cucumber.svg'","type":"Error"},"message":"ENOENT: no such file or directory, open '/home/mpkorstanje/Projects/cucumber/compatibility-kit/devkit/samples/hooks-attachment/cucumber.svg'\nsamples/hooks-attachment/hooks-attachment.feature:6","status":"FAILED"},"timestamp":{"nanos":3000000,"seconds":0}}}
13+
{"testStepStarted":{"testCaseStartedId":"12","testStepId":"9","timestamp":{"nanos":4000000,"seconds":0}}}
14+
{"testStepFinished":{"testCaseStartedId":"12","testStepId":"9","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":5000000,"seconds":0}}}
15+
{"testStepStarted":{"testCaseStartedId":"12","testStepId":"10","timestamp":{"nanos":6000000,"seconds":0}}}
16+
{"testStepFinished":{"testCaseStartedId":"12","testStepId":"10","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"ENOENT: no such file or directory, open '/home/mpkorstanje/Projects/cucumber/compatibility-kit/devkit/samples/hooks-attachment/cucumber.svg'","type":"Error"},"message":"ENOENT: no such file or directory, open '/home/mpkorstanje/Projects/cucumber/compatibility-kit/devkit/samples/hooks-attachment/cucumber.svg'\nsamples/hooks-attachment/hooks-attachment.feature:6","status":"FAILED"},"timestamp":{"nanos":7000000,"seconds":0}}}
17+
{"testCaseFinished":{"testCaseStartedId":"12","timestamp":{"nanos":8000000,"seconds":0},"willBeRetried":false}}
18+
{"testRunFinished":{"success":false,"testRunStartedId":"7","timestamp":{"nanos":9000000,"seconds":0}}}

0 commit comments

Comments
 (0)