gherkin-lint
Advanced tools
Comparing version 2.0.0 to 2.1.0
{ | ||
"name": "gherkin-lint", | ||
"version": "2.0.0", | ||
"version": "2.1.0", | ||
"description": "A Gherkin linter/validator written in javascript", | ||
@@ -5,0 +5,0 @@ "author": "Vasiliki Siakka", |
@@ -44,2 +44,3 @@ # Gherkin lint | ||
| `no-scenario-outlines-without-examples` | Disallows scenario outlines without examples | yes | | ||
| `use-and` | Disallows repeated step names requiring use of And instead| yes | | ||
@@ -46,0 +47,0 @@ \* These rules cannot be turned off because they detect undocumented cucumber functionality that causes the [gherkin](https://github.com/cucumber/gherkin-javascript) parser to crash. |
@@ -11,7 +11,12 @@ var fs = require('fs'); | ||
files.forEach(function(fileName) { | ||
var file = fs.readFileSync(fileName, 'utf-8'); | ||
var fileContent = fs.readFileSync(fileName, 'utf-8'); | ||
var file = { | ||
name: fileName, | ||
lines: fileContent.split(/\r\n|\r|\n/) | ||
}; | ||
var errors = []; | ||
try { | ||
var parsedFile = parser.parse(file).feature || {}; | ||
errors = rules.runAllEnabledRules(parsedFile, fileName, configuration); | ||
var feature = parser.parse(fileContent).feature || {}; | ||
errors = rules.runAllEnabledRules(feature, file, configuration); | ||
} catch(e) { | ||
@@ -18,0 +23,0 @@ if(e.errors) { |
@@ -33,3 +33,3 @@ // Operations on rules | ||
function runAllEnabledRules(parsedFile, fileName, configuration) { | ||
function runAllEnabledRules(feature, file, configuration) { | ||
var errors = []; | ||
@@ -42,3 +42,3 @@ var ignoreFutureErrors = false; | ||
var ruleConfig = Array.isArray(configuration[rule.name]) ? configuration[rule.name][1] : {}; | ||
var error = rule.run(parsedFile, fileName, ruleConfig); | ||
var error = rule.run(feature, file, ruleConfig); | ||
@@ -45,0 +45,0 @@ if (error) { |
@@ -35,7 +35,7 @@ var _ = require('lodash'); | ||
function indentation(parsedFile, unused, configuration) { | ||
if (!parsedFile || Object.keys(parsedFile).length === 0) { | ||
function indentation(feature, unused, configuration) { | ||
if (!feature || Object.keys(feature).length === 0) { | ||
return; | ||
} | ||
var language = languageMapping[parsedFile.language]; | ||
var language = languageMapping[feature.language]; | ||
var mergedConfiguration = _.merge(availableConfigs, configuration); | ||
@@ -45,5 +45,5 @@ errors = []; | ||
// Check Feature indentation | ||
test(parsedFile.location, mergedConfiguration, 'Feature'); | ||
test(feature.location, mergedConfiguration, 'Feature'); | ||
parsedFile.children.forEach(function(child) { | ||
feature.children.forEach(function(child) { | ||
switch(child.type) { | ||
@@ -50,0 +50,0 @@ case 'Background': |
@@ -20,4 +20,4 @@ var _ = require('lodash'); | ||
function nameLength(parsedFile, unused, configuration) { | ||
if (!parsedFile || Object.keys(parsedFile).length === 0) { | ||
function nameLength(feature, unused, configuration) { | ||
if (!feature || Object.keys(feature).length === 0) { | ||
return; | ||
@@ -29,5 +29,5 @@ } | ||
// Check Feature name length | ||
test(parsedFile.name, parsedFile.location, mergedConfiguration, 'Feature'); | ||
test(feature.name, feature.location, mergedConfiguration, 'Feature'); | ||
parsedFile.children.forEach(function(child) { | ||
feature.children.forEach(function(child) { | ||
switch(child.type) { | ||
@@ -34,0 +34,0 @@ case 'Scenario': |
@@ -1,2 +0,1 @@ | ||
var fs = require('fs'); | ||
var _ = require('lodash'); | ||
@@ -10,3 +9,3 @@ var rule = 'new-line-at-eof'; | ||
function newLineAtEOF(unused, fileName, configuration) { | ||
function newLineAtEOF(unused, file, configuration) { | ||
if (_.indexOf(availableConfigs, configuration) === -1) { | ||
@@ -16,4 +15,3 @@ throw new Error(rule + ' requires an extra configuration value.\nAvailable configurations: ' + availableConfigs.join(', ') + '\nFor syntax please look at the documentation.'); | ||
var fileContent = fs.readFileSync(fileName).toString(); | ||
var hasNewLineAtEOF = fileContent.match(/\r\n|\r|\n$/); | ||
var hasNewLineAtEOF = _.last(file.lines) === ''; | ||
var errormsg = ''; | ||
@@ -30,3 +28,3 @@ if (hasNewLineAtEOF && configuration === 'no') | ||
rule : rule, | ||
line : fileContent.split(/\r\n|\r|\n/).length}; | ||
line : file.lines.length}; | ||
} | ||
@@ -33,0 +31,0 @@ } |
var rule = 'no-dupe-feature-names'; | ||
var features = []; | ||
function noDuplicateFeatureNames(parsedFile, fileName) { | ||
if (parsedFile.name) { | ||
if (parsedFile.name in features) { | ||
var dupes = features[parsedFile.name].files.join(', '); | ||
features[parsedFile.name].files.push(fileName); | ||
function noDuplicateFeatureNames(feature, file) { | ||
if (feature.name) { | ||
if (feature.name in features) { | ||
var dupes = features[feature.name].files.join(', '); | ||
features[feature.name].files.push(file.name); | ||
return {message: 'Feature name is already used in: ' + dupes, | ||
rule : rule, | ||
line : parsedFile.location.line}; | ||
line : feature.location.line}; | ||
} else { | ||
features[parsedFile.name] = {files: [fileName]}; | ||
features[feature.name] = {files: [file.name]}; | ||
} | ||
@@ -15,0 +15,0 @@ } |
var rule = 'no-dupe-scenario-names'; | ||
var scenarios = []; | ||
function noDuplicateScenarioNames(parsedFile, fileName) { | ||
if(parsedFile.children) { | ||
function noDuplicateScenarioNames(feature, file) { | ||
if(feature.children) { | ||
var errors = []; | ||
parsedFile.children.forEach(function(scenario) { | ||
feature.children.forEach(function(scenario) { | ||
if (scenario.name) { | ||
if (scenario.name in scenarios) { | ||
var dupes = getFileLinePairsAsStr(scenarios[scenario.name].locations); | ||
scenarios[scenario.name].locations.push({file: fileName, line: scenario.location.line}); | ||
scenarios[scenario.name].locations.push({file: file.name, line: scenario.location.line}); | ||
errors.push({message: 'Scenario name is already used in: ' + dupes, | ||
@@ -16,3 +16,3 @@ rule : rule, | ||
} else { | ||
scenarios[scenario.name] = {locations: [{file: fileName, line: scenario.location.line}]}; | ||
scenarios[scenario.name] = {locations: [{file: file.name, line: scenario.location.line}]}; | ||
} | ||
@@ -19,0 +19,0 @@ } |
@@ -5,4 +5,4 @@ var _ = require('lodash'); | ||
function noEmptyFiles(parsedFile) { | ||
if (_.isEmpty(parsedFile)) { | ||
function noEmptyFiles(feature) { | ||
if (_.isEmpty(feature)) { | ||
return {message: 'Empty feature files are disallowed', | ||
@@ -9,0 +9,0 @@ rule : rule, |
@@ -7,4 +7,4 @@ var rule = 'no-files-without-scenarios'; | ||
function noFilesWithoutScenarios(parsedFile) { | ||
if (!parsedFile.children || !parsedFile.children.some(filterScenarios)) { | ||
function noFilesWithoutScenarios(feature) { | ||
if (!feature.children || !feature.children.some(filterScenarios)) { | ||
return {message: 'Feature file does not have any Scenarios', | ||
@@ -11,0 +11,0 @@ rule : rule, |
@@ -1,9 +0,7 @@ | ||
var fs = require('fs'); | ||
var rule = 'no-multiple-empty-lines'; | ||
function noMulitpleEmptyLines(unused, fileName) { | ||
function noMulitpleEmptyLines(unused, file) { | ||
var errors = []; | ||
var lines = fs.readFileSync(fileName).toString().split(/\r\n|\r|\n/); | ||
for (var i = 0; i < lines.length - 1; i++) { | ||
if (lines[i].trim() === '' && lines[i + 1].trim() == '') { | ||
for (var i = 0; i < file.lines.length - 1; i++) { | ||
if (file.lines[i].trim() === '' && file.lines[i + 1].trim() == '') { | ||
errors.push({message: 'Multiple empty lines are not allowed', | ||
@@ -10,0 +8,0 @@ rule : rule, |
var rule = 'no-partially-commented-tag-lines'; | ||
function noPartiallyCommentedTagLines(parsedFile) { | ||
function noPartiallyCommentedTagLines(feature) { | ||
var errors = []; | ||
if (parsedFile.children) { | ||
parsedFile.children.forEach(function(scenario) { | ||
if (feature.children) { | ||
feature.children.forEach(function(scenario) { | ||
if (scenario.tags) { | ||
@@ -8,0 +8,0 @@ scenario.tags.forEach(function(tag) { |
var rule = 'no-scenario-outlines-without-examples'; | ||
function noScenarioOutlinesWithoutExamples(parsedFile) { | ||
if (parsedFile.children) { | ||
function noScenarioOutlinesWithoutExamples(feature) { | ||
if (feature.children) { | ||
var errors = []; | ||
parsedFile.children.forEach(function(scenario) { | ||
feature.children.forEach(function(scenario) { | ||
if (scenario.type === 'ScenarioOutline' && !scenario.examples.length) { | ||
@@ -8,0 +8,0 @@ errors.push({message: 'Scenario Outline does not have any Examples', |
@@ -1,10 +0,8 @@ | ||
var fs = require('fs'); | ||
var rule = 'no-trailing-spaces'; | ||
function noTrailingSpaces(parsedFile, fileName) { | ||
function noTrailingSpaces(unused, file) { | ||
var errors = []; | ||
var lines = fs.readFileSync(fileName).toString().split('\n'); | ||
var lineNo = 1; | ||
lines.forEach(function(line) { | ||
if (/[\t ]+[\n\r]*$/.test(line)) { | ||
file.lines.forEach(function(line) { | ||
if (/[\t ]+$/.test(line)) { | ||
errors.push({message: 'Trailing spaces are not allowed', | ||
@@ -11,0 +9,0 @@ rule : rule, |
var rule = 'no-unnamed-features'; | ||
function noUnNamedFeatures(parsedFile) { | ||
if (!parsedFile || !parsedFile.name) { | ||
function noUnNamedFeatures(feature) { | ||
if (!feature || !feature.name) { | ||
return {message: 'Missing Feature name', | ||
rule : rule, | ||
line : parsedFile.location && parsedFile.location.line || 0}; | ||
line : feature.location && feature.location.line || 0}; | ||
} | ||
@@ -9,0 +9,0 @@ } |
var rule = 'no-unnamed-scenarios'; | ||
function noUnNamedScenarios(parsedFile) { | ||
if (parsedFile.children) { | ||
function noUnNamedScenarios(feature) { | ||
if (feature.children) { | ||
var errors = []; | ||
parsedFile.children.forEach(function(scenario) { | ||
feature.children.forEach(function(scenario) { | ||
if (!scenario.name && scenario.type === 'Scenario') { | ||
@@ -8,0 +8,0 @@ errors.push({message: 'Missing Scenario name', |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
51579
68
1042
97
7