#577: Fix Gherkin importer dropping a scenario after a preceding tagged one - #590
Merged
redcatbear merged 2 commits intoSep 9, 2026
Conversation
Collaborator
|
Please add a change log entry. |
redcatbear
requested changes
Sep 8, 2026
redcatbear
left a comment
Collaborator
There was a problem hiding this comment.
Please add a change log entry to 4.10.0.
…eding tagged one GherkinLineConsumer.readLine() only ends the current scenario (and starts looking for the next one's metadata) on a Scenario/Feature/Rule/Background/ Examples boundary line. A `@id:` tag line matches none of those, so while a scenario's steps are still being streamed into its description, an `@id:` tag for the next scenario falls into the same branch as an ordinary step line and gets appended as more of the current scenario's description instead of being read as metadata. The next scenario is then left without a pending id and is silently skipped on its Scenario: line. This only shows up when two tagged scenarios are consecutive, i.e. nothing Gherkin considers a block boundary sits between them - the documented workaround is inserting a throwaway `Rule:` line, which is exactly such a boundary. dsn~gherkin.streaming-import~1 defines "until a Gherkin block boundary" as the streaming condition, and a tag line is a boundary in that sense: it is where dsn~gherkin.id-detection~1's "immediately preceding @id: tag" for the next scenario begins. So a tag line encountered while still streaming a scenario now ends that scenario and is then handed to the normal metadata reader, instead of being swallowed as description text. This is why extending the BOUNDARY regex with `@` doesn't work as a fix on its own: that branch returns immediately after clearing metadata, so the tag itself would still never be read as an id. Adds a regression test reproducing the issue's exact repro shape (two consecutive tagged scenarios, no boundary between them), asserting both import with the correct ids and neither description is corrupted by the leaked tag line.
adityaanikam
force-pushed
the
fix-gherkin-consecutive-tagged-scenarios-577
branch
from
September 8, 2026 21:54
577ff0e to
d3db4c7
Compare
Collaborator
|
Thank you @adityaanikam for your contribution! |
redcatbear
approved these changes
Sep 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #577
Root cause
GherkinLineConsumer.readLine()only ends the current scenario (and goes back to looking for the next scenario's metadata) when it sees aScenario/Scenario Outline/Feature/Rule/Background/Examplesboundary line. A@id:tag line matches none of those.So while a scenario's steps are still being streamed into its description, a
@id:tag line for the next scenario falls into the same branch as an ordinary step line and gets appended to the current scenario's description instead of being read as metadata:The next scenario is then left without a pending id, and is silently skipped when its
Scenario:line is reached (beginScenariobails out whenpendingId == null). This only shows up when two tagged scenarios are consecutive — i.e. nothing Gherkin considers a block boundary sits between them — which is exactly why the documented workaround (inserting a throwawayRule:line) works: aRule:line is such a boundary.Fix
dsn~gherkin.streaming-import~1defines the streaming condition as running "until a Gherkin block boundary", anddsn~gherkin.id-detection~1requires the@id:tag to be the "immediately preceding" tag for a scenario. A tag line is a boundary in exactly that sense — it's where the next scenario's metadata begins. So a tag line encountered while still streaming a scenario should end the current scenario and be handed to the normal metadata reader, instead of being swallowed as description text:I also checked the more obvious-looking alternative of adding
@to theBOUNDARYregex, since that's the pattern already used for the other boundary keywords. That doesn't actually work here: theBOUNDARYbranch callsclearMetadata()and returns immediately, soreadMetadatawould never run on that same line and the tag line's own@id:would still never get captured — it would just trade "swallowed as description" for "silently dropped". Ending the scenario and then explicitly falling through toreadMetadatafor that line is what makes the tag itself get read.Testing
Added
testImportsConsecutiveTaggedScenariosWithoutAnInterveningBoundary, reproducing the issue's exact repro shape (two consecutive tagged scenarios, nothing but a blank line between them), asserting both scenarios import with the correct ids and that neither scenario's description is corrupted by a leaked tag line.I verified this test fails for the right reason against the pre-fix code (temporarily reverting only the new
@-line branch, keeping the test): it fails on all three counts — the second scenario is missing from the result, the first scenario's description is"Given a precondition\r\n@id:scn~second~1"(the tag line leaking in exactly as the root-cause analysis above describes), and indexing the missing second item throws. Restoring the fix returns the suite to green (29/29).AI assistance disclosure
Per CONTRIBUTING.md's AI-assisted-coding policy: I used an AI coding agent (Claude Code) to help find the root cause of this issue — tracing through
GherkinLineConsumer's state machine against the exact reported repro to identify the mechanism. All code changes (the fix and the test) were made manually.