Skip to content

Commit

Permalink
fix(main): problems with Scenario Outline rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
dnotes committed Nov 8, 2024
1 parent 5d20acc commit db82746
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 30 deletions.
11 changes: 11 additions & 0 deletions .changeset/dull-balloons-punch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"quickpickle": patch
---

Fixed problems with Scenario Outline rendering; under the following conditions,
and probably some others, the renderer would fail.

- If a parameter were named "context"
- Any regex characters (e.g. *) in a parameter name
- Having a ton of examples
- If a parameter name started with a number
14 changes: 7 additions & 7 deletions packages/main/gherkin-example/example.feature
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ Feature: QuickPickle's Comprehensive Gherkin Syntax Example
Then a verifiable outcome is achieved'

@concurrent
Scenario Outline: Parameterized scenario for <parameter>, '<another_parameter>', "<expected_result>"
Scenario Outline: Parameterized scenario for <parameter>, '<5>', "<expected_result*>"
Given a 'precondition' with <parameter>
When an "action" is taken with <another_parameter>
Then the `outcome` is <expected_result>
When an "action" is taken with <5>
Then the `outcome` is <expected_result*>

Examples:
| parameter | another_parameter | expected_result |
| value1' | value2' | result1' |
| value3` | value4` | result2` |
| value5" | value6" | result3" |
| parameter | 5 | expected_result* |
| value1' | value2' | result1' |
| value3` | value4` | result2` |
| value5" | value6" | result3" |

@data_table
Scenario: Scenario with various DataTable types
Expand Down
18 changes: 9 additions & 9 deletions packages/main/gherkin-example/example.feature.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 7 additions & 8 deletions packages/main/src/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { type QuickPickleConfig } from '.'

import * as Gherkin from '@cucumber/gherkin';
import * as Messages from '@cucumber/messages';
import { fromPairs, intersection, pick } from "lodash-es";
import { fromPairs, intersection, pick, escapeRegExp } from "lodash-es";

const uuidFn = Messages.IdGenerator.uuid();
const builder = new Gherkin.AstBuilder(uuidFn);
Expand Down Expand Up @@ -156,14 +156,14 @@ function renderScenario(child:FeatureChild, config:QuickPickleConfig, tags:strin
// For Scenario Outlines with examples
if (child.scenario!.examples?.[0]?.tableHeader && child.scenario!.examples?.[0]?.tableBody) {

let paramNames = child.scenario?.examples?.[0].tableHeader?.cells?.map(c => c.value) || []
let origParamNames = child.scenario?.examples?.[0]?.tableHeader?.cells?.map(c => c.value) || []
let paramValues = child.scenario?.examples?.[0].tableBody.map((r) => {
return fromPairs(r.cells.map((c,i) => [ paramNames![i], c.value ]))
return fromPairs(r.cells.map((c,i) => [ '_'+i, c.value ]))
})

function replaceParamNames(t:string, withBraces?:boolean) {
paramNames.forEach(p => {
t = t.replace(new RegExp(`<${p}>`, 'g'), (withBraces ? `$\{${p}\}` : `$${p}`))
origParamNames.forEach((p,i) => {
t = t.replace(new RegExp(`<${escapeRegExp(p)}>`, 'g'), (withBraces ? `$\{_${i}\}` : `$_${i}`))
})
return t
}
Expand All @@ -183,11 +183,10 @@ ${sp} ${paramValues?.map(line => {
}).join(',\n' + sp + ' ')}
${sp}])(
${sp} '${q(child.scenario?.keyword || '')}: ${describe}${tagTextForVitest}',
${sp} async ({ ${paramNames?.join(', ')} }, context) => {
${sp} async ({ ${origParamNames.map((p,i) => '_'+i)?.join(', ')} }, context) => {
${sp} let state = await ${initFn}(context, \`${name}\`, ['${tags.join("', '") || ''}'], [${examples?.map(s => '`'+s+'`').join(',')}]);
${child.scenario?.steps.map((step,idx) => {
let text = step.text.replace(/`/g, '\\`')
text = replaceParamNames(text,true)
let text = replaceParamNames(step.text,true).replace(/`/g, '\\`')
return `${sp} await gherkinStep(\`${text}\`, state, ${step.location.line}, ${idx+1}${isExploded ? `, ${explodedIdx + 1}` : ''});`
}).join('\n')
}
Expand Down
18 changes: 12 additions & 6 deletions packages/main/tests/renderer.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { expect, test } from 'vitest'
import { expect, test, describe } from 'vitest'
import { renderGherkin } from '../src/render'
import { defaultConfig, normalizeTags } from '../src'
import fs from 'node:fs'

const featureFile = fs.readFileSync(__dirname + '/../gherkin-example/example.feature', 'utf8')
const jsFile = fs.readFileSync(__dirname + '/../gherkin-example/example.feature.js', 'utf8')

test('rendering the example feature file', () => {
expect(jsFile).toEqual(renderGherkin(featureFile, {...defaultConfig, failTags: normalizeTags('fail, fails'), explodeTags: [normalizeTags('1a,1b'),normalizeTags('2a,2b')] }))
})
const featureFile = fs.readFileSync(__dirname + '/../gherkin-example/example.feature', 'utf8')
const jsFile = fs.readFileSync(__dirname + '/../gherkin-example/example.feature.js', 'utf8')
const testJs = renderGherkin(featureFile, {...defaultConfig, failTags: normalizeTags('fail, fails'), explodeTags: [normalizeTags('1a,1b'),normalizeTags('2a,2b')] })
try {
expect(jsFile).toEqual(testJs)
}
catch(e) {
fs.writeFileSync(__dirname + '/../gherkin-example/example.feature.diff.js', testJs)
throw e
}
})

0 comments on commit db82746

Please sign in to comment.