UNPKG

gherkin-lint

Version:

A Gherkin linter/validator written in javascript

100 lines (85 loc) 3 kB
"use strict"; const rule = 'no-unused-variables'; function run(feature) { if (!feature) { return []; } let errors = []; const stepVariableRegex = /<([^>]*)>/gu; feature.children.forEach(child => { 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.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 => { if (cell.value) { examplesVariables[cell.value] = cell.location.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]] = child.scenario.location.line; } child.scenario.steps.forEach(step => { // 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) { step.dataTable.rows.forEach(row => { row.cells.forEach(cell => { if (cell.value) { while ((match = stepVariableRegex.exec(cell.value)) != null) { scenarioVariables[match[1]] = cell.location.line; } } }); }); } else if (step.docString) { while ((match = stepVariableRegex.exec(step.docString.content)) != null) { scenarioVariables[match[1]] = step.location.line; } } // Collect variables from the steps themselves while ((match = stepVariableRegex.exec(step.text)) != null) { scenarioVariables[match[1]] = step.location.line; } }); for (const exampleVariable in examplesVariables) { if (!scenarioVariables[exampleVariable]) { errors.push({ message: 'Examples table variable "' + exampleVariable + '" is not used in any step', rule: rule, line: examplesVariables[exampleVariable] }); } } for (const scenarioVariable in scenarioVariables) { if (!examplesVariables[scenarioVariable]) { errors.push({ message: 'Step variable "' + scenarioVariable + '" does not exist in the examples table', rule: rule, line: scenarioVariables[scenarioVariable] }); } } }); return errors; } module.exports = { name: rule, run: run };