-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix: Define Steps produces incorrect cucumber expression for step definition (#28) #29
Fix: Define Steps produces incorrect cucumber expression for step definition (#28) #29
Conversation
@gasparnagy please review. My regex skills are not as good as yours. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thx! Please check my comments and the ref for the cucumber expression syntax specs.
@@ -28,7 +28,7 @@ protected override string GetExpression(AnalyzedStepText stepText) | |||
|
|||
private string EscapeCucumberExpression(string text) | |||
{ | |||
var escapedCukeEx = text.Replace(@"\", @"\\").Replace(@"{", @"\{").Replace("(", @"\"); | |||
var escapedCukeEx = Regex.Escape(text).Replace("\"", "\"\"").Replace(@"\ ", @" "); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code supposed to produce valid cucumber expressions and cucumber expressions are different from regex from the escaping perspective.
The cucumber expression escaping is defined at https://github.com/cucumber/cucumber-expressions?tab=readme-ov-file#escaping and it only allows escaping for: {
, (
, /
and \
.
Therefore we cannot use Regex.Escape(text)
as it uses the regex escaping that is far more greedy than necessary. I think we would just need to fix the original code to match the specs: the .Replace("(", @"\")
is clearly buggy, as it should be .Replace("(", @"\(")
and the escaping for /
is missing (so one more replace).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the reference.
Two follow-up questions then:
- In the original code, lines 31 and 32 both contain a Replace(@"", @"\"). Is that intentional?
- When escaping the forward slash ('/'), C# doesn't recognize @"/" as a valid escape sequence. I will attempt testing without escaping it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re: question 2 above, in my experimentation, I see now that / is meant to convey alternatives and so the use of a / in an example text fed into our snippet provider should treat that as a literal and should be escaped.
Since C# doesn't recognize that as a proper escape sequence, should the snippet provider generate the string as a strictly literal string (with the prepended @ sign)? Such as:
[Given(@"I have {int} cucumber\(s) in my \/ belly")]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I see that number 1 and 2 are related. When I leave line 32 as originally written, the example I'm using in number 2 is generated as
[Given("I have {int} cucumber\\(s) in my \\/ belly")]
which is handled gracefully by the C# compiler without the prepended @ sign.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@clrudolphi I agree. Let's keep it this way. Switching over to @ strings (verbatim string) just complicates the things.
When I invoke the "Define Steps" command | ||
Then the define steps dialog should be opened with the following step definition skeletons | ||
| type | expression | | ||
| When | I call the integer\\.ToString\\(\\) method | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The proper escaped version of I call the integer.ToString() method
would be I call the integer.ToString\() method
(the .
should not be escaped). See above.
Maybe we can find a better example, so that it shows all escaped characters, like When I use (parenthesis), {curly braces} and/or \ backslash
, where the escaped should be When I use \(parenthesis), \{curly braces} and\/or \\ backslash
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the Regex snippet provider behaving correctly as-is? It does escape the period, which if I'm not mistaken is required because it could otherwise be mistaken for a Regex pattern character. Correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, correct.
…ode review comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thx!
🤔 What's changed?
Modified the set of character escapes conducted within the CucumberExpressionSkeletonProvider such that the default set of characters needing escaping are escaped (such as was done within the Regex skeleton provider.
⚡️ What's your motivation?
This addresses the problem identified in GH28 in which empty parentheses resulted in an improper cucumber expression.
🏷️ What kind of change is this?
♻️ Anything particular you want feedback on?
@gasparnagy please confirm that these character escapes won't cause other problems with Cucumber expressions and they remain compliant with Cucumber syntax and semantics.
📋 Checklist:
This text was originally taken from the template of the Cucumber project, then edited by hand. You can modify the template here.