From 210ce10e0c0a37ae8bd07736ae16f8015a00c747 Mon Sep 17 00:00:00 2001 From: David Goss Date: Mon, 11 Apr 2022 08:07:42 +0100 Subject: [PATCH 1/4] add failing test --- .../javascript_snippet_syntax_spec.ts | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/formatter/step_definition_snippet_builder/javascript_snippet_syntax_spec.ts b/src/formatter/step_definition_snippet_builder/javascript_snippet_syntax_spec.ts index 7d76edb94..dc6434f31 100644 --- a/src/formatter/step_definition_snippet_builder/javascript_snippet_syntax_spec.ts +++ b/src/formatter/step_definition_snippet_builder/javascript_snippet_syntax_spec.ts @@ -145,6 +145,33 @@ describe('JavascriptSnippetSyntax', () => { }) }) + describe('pattern contains escapes', () => { + it('returns the proper snippet', () => { + // Arrange + const syntax = new JavascriptSnippetSyntax(SnippetInterface.Synchronous) + const buildOptions: ISnippetSyntaxBuildOptions = { + comment: 'comment', + functionName: 'functionName', + generatedExpressions: generateExpressions( + 'the user (with permissions) executes the action' + ), + stepParameterNames: [], + } + + // Act + const result = syntax.build(buildOptions) + + // Assert + expect(result).to.eql( + reindent(` + functionName('the user \\\\(with permissions) executes the action', function () { + // comment + return 'pending'; + });`) + ) + }) + }) + describe('multiple patterns', () => { it('returns the snippet with the other choices commented out', function () { // Arrange From 9f6c04560faea756c96cac3a8b501261b01d1d39 Mon Sep 17 00:00:00 2001 From: David Goss Date: Mon, 11 Apr 2022 08:18:38 +0100 Subject: [PATCH 2/4] implement --- .../javascript_snippet_syntax.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/formatter/step_definition_snippet_builder/javascript_snippet_syntax.ts b/src/formatter/step_definition_snippet_builder/javascript_snippet_syntax.ts index 128904e96..09dd4b949 100644 --- a/src/formatter/step_definition_snippet_builder/javascript_snippet_syntax.ts +++ b/src/formatter/step_definition_snippet_builder/javascript_snippet_syntax.ts @@ -1,3 +1,4 @@ +import { GeneratedExpression } from '@cucumber/cucumber-expressions' import { ISnippetSnytax, ISnippetSyntaxBuildOptions, @@ -43,9 +44,8 @@ export default class JavaScriptSnippetSyntax implements ISnippetSnytax { if (this.snippetInterface === SnippetInterface.Callback) { allParameterNames.push(CALLBACK_NAME) } - return `${prefix + functionName}('${generatedExpression.source.replace( - /'/g, - "\\'" + return `${prefix + functionName}('${this.escapeSpecialCharacters( + generatedExpression )}', ${functionKeyword}(${allParameterNames.join(', ')}) {\n` } ) @@ -56,4 +56,13 @@ export default class JavaScriptSnippetSyntax implements ISnippetSnytax { '});' ) } + + private escapeSpecialCharacters(generatedExpression: GeneratedExpression) { + let source = generatedExpression.source + // double up any backslashes because we're in a javascript string + source = source.replace(/\\/g, '\\\\') + // escape any single quotes because that's our quote delimiter + source = source.replace(/'/g, "\\'") + return source + } } From a816db74260b49e2a0be40fe7b438217ff871000 Mon Sep 17 00:00:00 2001 From: David Goss Date: Mon, 11 Apr 2022 08:23:19 +0100 Subject: [PATCH 3/4] add feature test --- features/step_definition_snippets.feature | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/features/step_definition_snippets.feature b/features/step_definition_snippets.feature index 7163441b9..beab9d03d 100644 --- a/features/step_definition_snippets.feature +++ b/features/step_definition_snippets.feature @@ -70,3 +70,20 @@ Feature: step definition snippets return 'pending'; }); """ + + Scenario: a step resulting in special characters in the expression + Given a file named "features/number.feature" with: + """ + Feature: a feature + Scenario: a scenario + Given a person's (secret) desires + """ + When I run cucumber-js + Then it fails + And the output contains the text: + """ + Given('a person\'s \\(secret) desires', function () { + // Write code here that turns the phrase above into concrete actions + return 'pending'; + }); + """ From 641adf8667f23fa84e8df5153f7e6a0140fbe7f4 Mon Sep 17 00:00:00 2001 From: David Goss Date: Mon, 11 Apr 2022 08:42:10 +0100 Subject: [PATCH 4/4] update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31bc8bcbc..5f41380cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). Please see [CONTRIBUTING.md](https://github.com/cucumber/cucumber/blob/master/CONTRIBUTING.md) on how to contribute to Cucumber. ## [Unreleased] +### Fixed +- Correctly escape backslashes in generated expressions for snippets ([#1324](https://github.com/cucumber/cucumber-js/issues/1324) [#1995](https://github.com/cucumber/cucumber-js/pull/1995)) ## [8.0.0] - 2022-04-06 ### Changed