@amiceli/vitest-cucumber
Version:
vitest tools to use Gherkin feature in unit tests
102 lines (101 loc) • 3.88 kB
JavaScript
import { exec } from 'node:child_process';
import { promisify } from 'node:util';
import { SyntaxKind } from 'ts-morph';
import { writeSpecFile } from '../../../scripts/generateFile';
import { VitestsCucumberError } from '../../errors/errors';
import { FeatureFileReader } from '../../parser/readfile';
import { getVitestCucumberConfiguration } from '../../vitest/configuration';
import { AstUtils } from './AstUtils';
import { BackgroundAst } from './BackgroundAst';
import { BaseAst } from './BaseAst';
import { RuleAst } from './RuleAst';
import { ScenarioAst } from './ScenarioAst';
export class FeatureAst extends BaseAst {
feature = null;
constructor(options) {
super(options);
}
static fromOptions(options) {
return new FeatureAst(options);
}
async loadFeautreFromFile() {
const [feature] = await FeatureFileReader.fromPath({
featureFilePath: this.options.featureFilePath,
callerFileDir: null,
options: getVitestCucumberConfiguration(),
}).parseFile();
return feature;
}
async updateSpecFile() {
try {
this.feature = await this.loadFeautreFromFile();
await this.handleDescribeFeature();
this.handleFeature();
await this.formatAndSave();
if (this.options.formatCommand) {
const execPromise = promisify(exec);
await execPromise(`${this.options.formatCommand} ${this.options.specFilePath}`);
}
}
catch (e) {
throw new VitestsCucumberError(`FeatureAst error: ${e.message}`);
}
}
async handleDescribeFeature() {
if (!this.describeFeature && this.feature) {
await writeSpecFile({
feature: this.feature,
specFilePath: this.options.specFilePath,
featureFilePath: this.options.featureFilePath,
});
this.resetProject();
}
}
handleFeature() {
if (this.describeFeatureCallback && this.feature) {
ScenarioAst.fromOptions({
...this.options,
stepableParent: this.feature,
stepableParentFunction: this.describeFeatureCallback,
}).handleScenarii();
RuleAst.fromOptions({
...this.options,
ruleParent: this.feature,
ruleParentFunction: this.describeFeatureCallback,
}).handleRules();
BackgroundAst.fromOptions({
...this.options,
stepableParent: this.feature,
stepableParentFunction: this.describeFeatureCallback,
}).handleBackground();
this.updateFeatureArguments(this.feature, this.describeFeatureCallback);
}
}
updateFeatureArguments(feature, featureArrowFunction) {
const featureRequiredArgs = [
feature.background !== null ? 'Background' : undefined,
feature.hasScenarioOutline ? 'ScenarioOutline' : undefined,
feature.hasScenario ? 'Scenario' : undefined,
feature.rules.length > 0 ? 'Rule' : undefined,
].filter((a) => a !== undefined);
this.updateSyntaxListChild(featureArrowFunction, featureRequiredArgs);
}
async formatAndSave() {
this.sourceFile.formatText();
await this.sourceFile.save();
}
get describeFeature() {
return AstUtils.fromSourceFile(this.sourceFile)
.listDescendantCallExpressions()
.matchExpressionName('describeFeature')
.getOne();
}
get describeFeatureCallback() {
if (this.describeFeature) {
return this.describeFeature
.getArguments()
.find((arg) => arg.isKind(SyntaxKind.ArrowFunction));
}
return undefined;
}
}