@amiceli/vitest-cucumber
Version:
vitest tools to use Gherkin feature in unit tests
130 lines (129 loc) • 4.12 kB
JavaScript
import { RequiredTitleError, SpokenKeywordError } from '../../errors/errors';
import { StepTypes } from '../models/step';
import availableLanguages from './lang.json';
// biome-ignore lint/complexity/noStaticOnlyClass: <explanation>
export class SpokenParserFactory {
static fromLang(lang) {
const details = lang in availableLanguages
? availableLanguages[lang]
: availableLanguages.en;
return new SpokenParser(details);
}
}
export class SpokenParser {
details;
constructor(details) {
this.details = details;
}
getFeatureName(line) {
return this.getMatchKey({
line,
keys: this.details.feature,
titleRequired: true,
});
}
getScenarioName(line) {
return this.getMatchKey({
line,
keys: this.details.scenario,
titleRequired: true,
});
}
getScenarioOutlineName(line) {
return this.getMatchKey({
line,
keys: this.details.scenarioOutline,
titleRequired: true,
});
}
getRuleName(line) {
return this.getMatchKey({
line,
keys: this.details.rule,
titleRequired: true,
});
}
getBackgroundKeyWord(line) {
return this.getMatchKey({
line,
keys: this.details.background,
}).keyword;
}
getMatchKey(options) {
const foundKeyword = options.keys.find((featureKey) => options.line.trim().startsWith(`${featureKey}:`));
if (!foundKeyword) {
throw new SpokenKeywordError(options.line, options.keys);
}
const title = options.line.split(`${foundKeyword}:`).at(1)?.trim();
if (!title && options.titleRequired) {
throw new RequiredTitleError(options.line.trim(), foundKeyword);
}
return {
keyword: foundKeyword.trim(),
title: title || '',
};
}
// match line
isRule(line) {
return this.lineStartsWithOneOf(this.details.rule, line);
}
isExamples(line) {
return this.lineStartsWithOneOf(this.details.examples, line);
}
isFeature(line) {
return this.lineStartsWithOneOf(this.details.feature, line);
}
isScenarioOutline(line) {
return this.lineStartsWithOneOf(this.details.scenarioOutline, line);
}
isScenario(line) {
return this.lineStartsWithOneOf(this.details.scenario, line);
}
isBackground(line) {
return this.lineStartsWithOneOf(this.details.background, line);
}
isStep(line) {
return this.foundStep(line) !== undefined;
}
getStepDetails(line, type) {
const matches = this.stepsMatch.find((s) => s.type === type);
const foundMatch = matches?.keys.find((stepKey) => {
return line.trim().startsWith(stepKey);
});
if (foundMatch) {
return {
keyword: foundMatch.trim(),
title: line.trim().split(foundMatch)[1].trim(),
};
}
throw new SpokenKeywordError(line, matches?.keys || []);
}
getStepType(line) {
const foundStep = this.foundStep(line);
if (foundStep) {
return foundStep.type;
}
throw new Error('Type not found');
}
foundStep(line) {
return this.stepsMatch.find((stepDetails) => {
return stepDetails.keys.some((stepKey) => {
return line.trim().startsWith(stepKey);
});
});
}
lineStartsWithOneOf(keys, line) {
return (keys.find((value) => {
return line.trim().startsWith(`${value}:`);
}) !== undefined);
}
get stepsMatch() {
return [
{ type: StepTypes.GIVEN, keys: this.details.given },
{ type: StepTypes.WHEN, keys: this.details.when },
{ type: StepTypes.THEN, keys: this.details.then },
{ type: StepTypes.AND, keys: this.details.and },
{ type: StepTypes.BUT, keys: this.details.but },
];
}
}