@amiceli/vitest-cucumber
Version:
vitest tools to use Gherkin feature in unit tests
120 lines (119 loc) • 4.75 kB
JavaScript
import fs from 'node:fs/promises';
import { ScenarioOutline } from '../src/parser/models/scenario';
export function generateStep(step) {
if (step.docStrings) {
return ` ${step.type}(\`${step.details}\`, (_, docString: string) => { })`;
}
return ` ${step.type}(\`${step.details}\`, () => { })`;
}
export function generateScenarii(scenarii, forRule = false) {
const fileContent = [''];
for (const scenario of scenarii) {
const isOutline = scenario instanceof ScenarioOutline;
const scenarioStepTypes = [
'Given',
'When',
'Then',
'And',
'But',
].filter((step) => scenario.steps
.map((scenarioSteps) => scenarioSteps.type)
.includes(step));
let scenarioType = 'Scenario';
if (isOutline) {
scenarioType = forRule ? 'RuleScenarioOutline' : 'ScenarioOutline';
}
else {
scenarioType = forRule ? 'RuleScenario' : 'Scenario';
}
if (isOutline) {
fileContent.push(` ${scenarioType}(\`${scenario.description}\`, ({ ${scenarioStepTypes.join(', ')} }, variables) => {`);
}
else {
fileContent.push(` ${scenarioType}(\`${scenario.description}\`, ({ ${scenarioStepTypes.join(', ')} }) => {`);
}
for (const step of scenario.steps) {
fileContent.push(generateStep(step));
}
fileContent.push(` })`);
}
return fileContent;
}
export function generateBackground(back, forRule = false) {
const fileContent = [''];
const scenarioStepTypes = ['Given', 'When', 'Then', 'And', 'But'].filter((step) => back.steps
.map((scenarioSteps) => scenarioSteps.type.toString())
.includes(step));
const scenarioType = forRule ? 'RuleBackground' : 'Background';
fileContent.push(` ${scenarioType}(({ ${scenarioStepTypes.join(', ')} }) => {`);
for (const step of back.steps) {
fileContent.push(` ${step.type}(\`${step.details}\`, () => { })`);
}
fileContent.push(` })`);
return fileContent;
}
export function generateRules(rules) {
const fileContent = [];
for (const r of rules) {
const rulesHook = [];
if (r.background) {
rulesHook.push('RuleBackground');
}
if (r.scenarii.some((s) => s instanceof ScenarioOutline)) {
rulesHook.push('RuleScenarioOutline');
}
if (r.scenarii.some((s) => !(s instanceof ScenarioOutline))) {
rulesHook.push('RuleScenario');
}
fileContent.push('');
fileContent.push(` Rule(\`${r.name}\`, ({ ${rulesHook.join(', ')} }) => {`);
if (r.background) {
fileContent.push(...generateBackground(r.background, true));
}
fileContent.push(...generateScenarii(r.scenarii, true));
fileContent.push('');
fileContent.push(` })`);
}
return fileContent;
}
export async function writeSpecFile({ feature, specFilePath, featureFilePath, }) {
const featureHasBackground = feature.background !== null;
const featureHasScenario = feature.scenarii.some((s) => !(s instanceof ScenarioOutline));
const featureHasScenarioOutline = feature.scenarii.some((s) => s instanceof ScenarioOutline);
const fileContentLines = [];
const describeHook = [
'BeforeAllScenarios',
'AfterAllScenarios',
'BeforeEachScenario',
'AfterEachScenario',
];
const describeFeatureArgs = [...describeHook];
if (featureHasBackground) {
describeFeatureArgs.push('Background');
}
if (featureHasScenarioOutline) {
describeFeatureArgs.push('ScenarioOutline');
}
if (featureHasScenario) {
describeFeatureArgs.push('Scenario');
}
if (feature.rules.length > 0) {
describeFeatureArgs.push('Rule');
}
fileContentLines.push('import { loadFeature, describeFeature } from "@amiceli/vitest-cucumber"');
fileContentLines.push('');
fileContentLines.push(`const feature = await loadFeature('${featureFilePath}')`);
fileContentLines.push('');
fileContentLines.push(`describeFeature(feature, ({ ${describeFeatureArgs.join(', ')} }) => {`);
for (const s of describeHook) {
fileContentLines.push(` ${s}(() => {})`);
}
if (featureHasBackground) {
// biome-ignore lint/style/noNonNullAssertion: <explanation>
fileContentLines.push(...generateBackground(feature.background));
}
fileContentLines.push(...generateScenarii(feature.scenarii), ...generateRules(feature.rules));
fileContentLines.push('');
fileContentLines.push(`})`);
await fs.writeFile(specFilePath, fileContentLines.join('\n'));
}