gherkin-lint-ts
Version:
Gherkin features linter written in Typescript
100 lines • 4.55 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.run = exports.name = void 0;
const chalk_1 = __importDefault(require("chalk"));
exports.name = "no-unused-variables";
function run(feature) {
var _a;
if (!feature) {
return [];
}
const errors = [];
const stepVariableRegex = /<([^>]*)>/gu;
(_a = feature.children) === null || _a === void 0 ? void 0 : _a.forEach(child => {
var _a, _b;
if (!child.scenario) {
// Variables are a feature of Scenarios (as of Gherkin 9?) and Scenario Outlines only
return;
}
const examples = child.scenario.examples;
if (!(examples === null || examples === void 0 ? void 0 : examples.length)) {
// If there is no examples table, the rule doesn't apply
return;
}
// Maps of variableName -> lineNo
const examplesVariables = {};
const scenarioVariables = {};
let match;
// Collect all the entries of the examples table
examples.forEach(example => {
if (example.tableHeader && example.tableHeader.cells) {
example.tableHeader.cells.forEach(cell => {
var _a;
if (cell.value) {
examplesVariables[cell.value] = (_a = cell.location) === null || _a === void 0 ? void 0 : _a.line;
}
});
}
});
// Collect the variables used in the scenario outline
// Scenario names can include variables
while ((match = stepVariableRegex.exec(child.scenario.name || "")) != null) {
scenarioVariables[match[1]] = (_a = child.scenario.location) === null || _a === void 0 ? void 0 : _a.line;
}
(_b = child.scenario.steps) === null || _b === void 0 ? void 0 : _b.forEach(step => {
var _a, _b, _c;
// Steps can take arguments and their argument can include variables.
// The arguments can be of type:
// - DocString
// - DataTable
// For more details, see https://docs.cucumber.io/gherkin/reference/#step-arguments
// Collect variables from step arguments
if (step.dataTable) {
(_a = step.dataTable.rows) === null || _a === void 0 ? void 0 : _a.forEach(row => {
var _a;
(_a = row.cells) === null || _a === void 0 ? void 0 : _a.forEach(cell => {
var _a;
if (cell.value) {
while ((match = stepVariableRegex.exec(cell.value)) != null) {
scenarioVariables[match[1]] = (_a = cell.location) === null || _a === void 0 ? void 0 : _a.line;
}
}
});
});
}
else if (step.docString) {
while ((match = stepVariableRegex.exec(step.docString.content || "")) != null) {
scenarioVariables[match[1]] = (_b = step.location) === null || _b === void 0 ? void 0 : _b.line;
}
}
// Collect variables from the steps themselves
while ((match = stepVariableRegex.exec(step.text || "")) != null) {
scenarioVariables[match[1]] = (_c = step.location) === null || _c === void 0 ? void 0 : _c.line;
}
});
for (const exampleVariable in examplesVariables) {
if (!scenarioVariables[exampleVariable]) {
errors.push({
message: `Examples table variable "${chalk_1.default.yellow(exampleVariable)}" is not used in any step`,
rule: exports.name,
line: examplesVariables[exampleVariable],
});
}
}
for (const scenarioVariable in scenarioVariables) {
if (!examplesVariables[scenarioVariable]) {
errors.push({
message: `Step variable "${chalk_1.default.yellow(scenarioVariable)}" does not exist in the examples table`,
rule: exports.name,
line: scenarioVariables[scenarioVariable],
});
}
}
});
return errors;
}
exports.run = run;
//# sourceMappingURL=no-unused-variables.js.map