gplint
Version:
A Gherkin linter/validator written in Javascript.
95 lines • 3.63 kB
JavaScript
import * as gherkinUtils from './utils/gherkin.js';
import { featureSpread } from './utils/gherkin.js';
import _ from 'lodash';
export const name = 'keywords-in-logical-order';
export const availableConfigs = {
'detectMissingKeywords': false,
};
export function run({ feature }, configuration) {
if (!feature) {
return [];
}
const mergedConfiguration = _.merge({}, availableConfigs, configuration);
const { detectMissingKeywords } = mergedConfiguration;
const errors = [];
const { children } = featureSpread(feature);
children.forEach(child => {
const node = child.background ?? child.scenario;
const keywordList = ['given', 'when', 'then'];
let maxKeywordPosition = 0;
const existsKeyword = {
given: false,
when: false,
then: false,
};
node.steps.forEach((step) => {
const keyword = gherkinUtils.getLanguageInsensitiveKeyword(step, feature.language);
const keywordPosition = keywordList.indexOf(keyword);
if (keywordPosition === -1) {
// not found
return;
}
if (keywordPosition < maxKeywordPosition) {
const maxKeyword = keywordList[maxKeywordPosition];
errors.push(createError(maxKeyword, step, undefined));
}
existsKeyword[keywordList[keywordPosition]] = true;
maxKeywordPosition =
Math.max(maxKeywordPosition, keywordPosition) || keywordPosition;
});
if (detectMissingKeywords && child.scenario && !Object.values(existsKeyword).every((value) => value)) {
const keys = [];
Object.entries(existsKeyword).forEach(([key, value]) => {
if (!value) {
keys.push(key);
}
});
errors.push(createError(keys.join(', '), undefined, child.scenario));
}
});
return errors;
}
function createError(keyword, ...[step, scenario]) {
let message, node;
if (scenario != null) {
message = `The scenario "${scenario.name}" does not have the following keywords: ${keyword}`;
node = scenario;
}
else {
message = `Step "${step.keyword}${step.text}" should not appear after step using keyword ${keyword}`;
node = step;
}
return {
message,
rule: name,
line: node.location.line,
column: node.location.column,
};
}
export const documentation = {
description: 'Allows the user to maintain the wording order by using the scenario keywords, following the `Given`, `When`, `Then` sequence.',
configuration: [{
name: 'detectMissingKeywords',
type: 'boolean',
description: 'Whether to ignore the lack of some keyword that violates the structure.',
default: availableConfigs.detectMissingKeywords,
}],
examples: [{
title: 'Don\'t detect missing keywords',
description: 'Enable rule, without reporting missing keywords (Default behaviour).',
config: {
[name]: ['error', {
'detectMissingKeywords': false,
}],
},
}, {
title: 'Detect missing keywords',
description: 'Enable rule, reporting missing keywords.',
config: {
[name]: ['error', {
'detectMissingKeywords': true,
}],
},
}],
};
//# sourceMappingURL=keywords-in-logical-order.js.map