UNPKG

gplint

Version:

A Gherkin linter/validator written in Javascript.

136 lines 5.74 kB
import * as gherkinUtils from './utils/gherkin.js'; import { featureSpread } from './utils/gherkin.js'; import _ from 'lodash'; import { StepKeywordType } from '@cucumber/messages'; export const name = 'max-keywords'; export const availableConfigs = { given: -1, when: -1, then: -1, onlyContiguous: false, ignoreConjunctions: false, }; export function run({ feature }, configuration) { if (!feature) { return []; } const mergedConfiguration = _.merge({}, availableConfigs, configuration); const errors = []; const { children } = featureSpread(feature); children.forEach(child => { const node = child.background ?? child.scenario; const keywordStepsCount = []; let lastKeyword; node.steps.forEach((step) => { const keyword = gherkinUtils.getLanguageInsensitiveKeyword(step, feature.language); if ([StepKeywordType.CONJUNCTION, StepKeywordType.UNKNOWN].includes(step.keywordType)) { if (mergedConfiguration.ignoreConjunctions || lastKeyword == null) { return; } (mergedConfiguration.onlyContiguous ? keywordStepsCount[keywordStepsCount.length - 1] : keywordStepsCount.find(d => d[0] === lastKeyword))[2]++; } else if (lastKeyword === keyword) { (mergedConfiguration.onlyContiguous ? keywordStepsCount[keywordStepsCount.length - 1] : keywordStepsCount.find(d => d[0] === lastKeyword))[2]++; } else { lastKeyword = keyword; if (mergedConfiguration.onlyContiguous) { keywordStepsCount.push([keyword, step.location, 1]); } else { const prevKeywordData = keywordStepsCount.find(d => d[0] === keyword); if (prevKeywordData) { prevKeywordData[2]++; } else { keywordStepsCount.push([keyword, step.location, 1]); } } } }); for (const [keyword, location, count] of keywordStepsCount) { const maxAllowed = mergedConfiguration[keyword]; if (maxAllowed !== -1 && count > maxAllowed) { errors.push(createError(keyword, location, count, maxAllowed, mergedConfiguration.onlyContiguous)); } } }); return errors; } function createError(keyword, location, count, expected, contiguous) { return { message: `There are too many${contiguous ? ' contiguous ' : ' '}steps for "${keyword}". Found ${count}, maximum allowed ${expected}.`, rule: name, line: location.line, column: location.column, }; } export const documentation = { description: 'Allow to limit the amount of steps of the specified keywords. The keywords `And`, `But`, or `*` counts as the previous keyword.', configuration: [{ name: 'given', type: 'number', description: 'Max allowed steps for Given. 0 means is not allowed and a negative value (or undefined) means unlimited.', default: availableConfigs.given, }, { name: 'when', type: 'number', description: 'Max allowed steps for When. 0 means is not allowed and a negative value (or undefined) means unlimited.', default: availableConfigs.when, }, { name: 'then', type: 'number', description: 'Max allowed steps for Then. 0 means is not allowed and a negative value (or undefined) means unlimited.', default: availableConfigs.then, }, { name: 'onlyContiguous', type: 'boolean', description: 'If true, only counts contiguous steps, resetting the limit if another keyword is used.', default: availableConfigs.onlyContiguous, }, { name: 'ignoreConjunctions', type: 'boolean', description: 'If true, only counts the main keywords, ignoring conjunctions (`And`, `But`, `*`).', default: availableConfigs.onlyContiguous, }], examples: [{ title: 'Limit `When` to 1 occurrence', description: '`When` is limited to one occurrence. `Given` and `Then` are not defined, which means there are no limit for them.', config: { [name]: ['error', { 'when': 1, }], }, }, { title: 'Limit `When` to 3 occurrence, and Given to 1', description: '`Given` is limited to one occurrence, and `When` is limited to three occurrences. `Then` is not defined, which means there is no limit for it.', config: { [name]: ['error', { 'given': 1, 'when': 3, }], }, }, { title: 'Forbid the use of `Given` step', description: 'Do not allow to use the step `Given`.', config: { [name]: ['error', { 'given': 0, }], }, }, { title: 'Limit `When` to 1 when are put together.', description: 'Limit `When` to 1, but only if there are not other keywords between.', config: { [name]: ['error', { 'when': 1, 'onlyContiguous': true, }], }, }], }; //# sourceMappingURL=max-keywords.js.map