gherkin-lint
Advanced tools
Comparing version 2.7.0 to 2.8.0
{ | ||
"name": "gherkin-lint", | ||
"version": "2.7.0", | ||
"version": "2.8.0", | ||
"description": "A Gherkin linter/validator written in javascript", | ||
@@ -5,0 +5,0 @@ "author": "Vasiliki Siakka", |
@@ -88,7 +88,9 @@ # Gherkin lint | ||
"and": 2, | ||
"but": 2 | ||
"but": 2, | ||
"feature tag": 0, | ||
"scenario tag": 0 | ||
} | ||
] | ||
} | ||
There is no need to override all the defaults, as is done above, instead they can be overriden only where required. `Step` will be used as a fallback if the keyword of the step, eg. 'given', is not specified. | ||
There is no need to override all the defaults, as is done above, instead they can be overriden only where required. `Step` will be used as a fallback if the keyword of the step, eg. 'given', is not specified. If `feature tag` is not set then `Feature` is used as a fallback, and if `scenario tag` is not set then `Scenario` is used as a fallback. | ||
@@ -95,0 +97,0 @@ This feature is able to handle all localizations of the gherkin steps. |
@@ -5,3 +5,3 @@ var _ = require('lodash'); | ||
var availableConfigs = { | ||
var defaultConfig = { | ||
'Feature': 0, | ||
@@ -20,56 +20,82 @@ 'Background': 0, | ||
var errors = []; | ||
var availableConfigs = _.merge({}, defaultConfig, { | ||
// The values here are unused by the config parsing logic. | ||
'feature tag': -1, | ||
'scenario tag': -1 | ||
}); | ||
function test(parsedLocation, configuration, type) { | ||
// location.column is 1 index based so, when we compare with the expected indentation we need to subtract 1 | ||
if (--parsedLocation.column !== configuration[type]) { | ||
errors.push({message: 'Wrong indentation for "' + type + | ||
'", expected indentation level of ' + configuration[type] + | ||
', but got ' + parsedLocation.column, | ||
rule : rule, | ||
line : parsedLocation.line}); | ||
function mergeConfiguration(configuration) { | ||
var mergedConfiguration = _.merge({}, defaultConfig, configuration); | ||
if (!Object.prototype.hasOwnProperty.call(mergedConfiguration, 'feature tag')) { | ||
mergedConfiguration['feature tag'] = mergedConfiguration['Feature']; | ||
} | ||
if (!Object.prototype.hasOwnProperty.call(mergedConfiguration, 'scenario tag')) { | ||
mergedConfiguration['scenario tag'] = mergedConfiguration['Scenario']; | ||
} | ||
return mergedConfiguration; | ||
} | ||
function testStep(step, language, configuration, mergedConfiguration) { | ||
var keyword = step.keyword; | ||
var stepType = _.findKey(language, function(values) { | ||
return values instanceof Array && values.indexOf(keyword) !== -1; | ||
}); | ||
stepType = stepType in configuration ? stepType : 'Step'; | ||
test(step.location, mergedConfiguration, stepType); | ||
} | ||
function testFeature(feature, configuration, mergedConfiguration) { | ||
var errors = []; | ||
function testScenarioOutline(scenarioOutline, mergedConfiguration) { | ||
test(scenarioOutline.location, mergedConfiguration, 'Scenario'); | ||
scenarioOutline.examples.forEach(function(examples) { | ||
test(examples.location, mergedConfiguration, 'Examples'); | ||
test(examples.tableHeader.location, mergedConfiguration, 'example'); | ||
examples.tableBody.forEach(function(row) { | ||
test(row.location, mergedConfiguration, 'example'); | ||
function test(parsedLocation, type) { | ||
// location.column is 1 index based so, when we compare with the expected | ||
// indentation we need to subtract 1 | ||
if (--parsedLocation.column !== mergedConfiguration[type]) { | ||
errors.push({message: 'Wrong indentation for "' + type + | ||
'", expected indentation level of ' + mergedConfiguration[type] + | ||
', but got ' + parsedLocation.column, | ||
rule : rule, | ||
line : parsedLocation.line}); | ||
} | ||
} | ||
function testStep(step) { | ||
var keyword = step.keyword; | ||
var stepType = _.findKey(languageMapping[feature.language], function(values) { | ||
return values instanceof Array && values.indexOf(keyword) !== -1; | ||
}); | ||
}); | ||
} | ||
stepType = stepType in configuration ? stepType : 'Step'; | ||
test(step.location, stepType); | ||
} | ||
function indentation(feature, unused, configuration) { | ||
if (!feature || Object.keys(feature).length === 0) { | ||
return; | ||
function testScenarioOutline(scenarioOutline) { | ||
test(scenarioOutline.location, 'Scenario'); | ||
scenarioOutline.examples.forEach(function(examples) { | ||
test(examples.location, 'Examples'); | ||
test(examples.tableHeader.location, 'example'); | ||
examples.tableBody.forEach(function(row) { | ||
test(row.location, 'example'); | ||
}); | ||
}); | ||
} | ||
var language = languageMapping[feature.language]; | ||
var mergedConfiguration = _.merge(availableConfigs, configuration); | ||
errors = []; | ||
// Check Feature indentation | ||
test(feature.location, mergedConfiguration, 'Feature'); | ||
function testTags(tags, type) { | ||
_(tags).map(function(tag) { | ||
return tag.location; | ||
}).groupBy(function(tagLocation) { | ||
return tagLocation.line; | ||
}).forEach(function(locationsPerLine) { | ||
var firstLocation = locationsPerLine.sort(function(location) { | ||
return -location.column; | ||
})[0]; | ||
test(firstLocation, type); | ||
}); | ||
} | ||
test(feature.location, 'Feature'); | ||
testTags(feature.tags, 'feature tag'); | ||
feature.children.forEach(function(child) { | ||
switch(child.type) { | ||
case 'Background': | ||
test(child.location, mergedConfiguration, 'Background'); | ||
test(child.location, 'Background'); | ||
break; | ||
case 'Scenario': | ||
test(child.location, mergedConfiguration, 'Scenario'); | ||
test(child.location, 'Scenario'); | ||
testTags(child.tags, 'scenario tag'); | ||
break; | ||
case 'ScenarioOutline': | ||
testScenarioOutline(child, mergedConfiguration); | ||
testScenarioOutline(child); | ||
testTags(child.tags, 'scenario tag'); | ||
break; | ||
@@ -83,6 +109,3 @@ default: | ||
child.steps.forEach(function(step) { | ||
// Check Step indentation | ||
testStep(step, language, configuration, mergedConfiguration); | ||
}); | ||
child.steps.forEach(testStep); | ||
}); | ||
@@ -93,6 +116,15 @@ | ||
function run(feature, unused, configuration) { | ||
if (!feature || Object.keys(feature).length === 0) { | ||
return; | ||
} | ||
var mergedConfiguration = mergeConfiguration(configuration); | ||
return testFeature(feature, configuration, mergedConfiguration); | ||
} | ||
module.exports = { | ||
name: rule, | ||
run: indentation, | ||
run: run, | ||
availableConfigs: availableConfigs | ||
}; |
@@ -8,30 +8,45 @@ var ruleTestBase = require('../rule-test-base'); | ||
messageElements: {element: 'Feature', expected: 0, actual: 1}, | ||
line: 2 | ||
},{ | ||
messageElements: {element: 'feature tag', expected: 0, actual: 1}, | ||
line: 1 | ||
},{ | ||
messageElements: {element: 'Background', expected: 0, actual: 4}, | ||
line: 3 | ||
line: 4 | ||
},{ | ||
messageElements: {element: 'Step', expected: 2, actual: 0}, | ||
line: 4 | ||
line: 5 | ||
},{ | ||
messageElements: {element: 'Scenario', expected: 0, actual: 1}, | ||
line: 6 | ||
line: 9 | ||
},{ | ||
messageElements: {element: 'Step', expected: 2, actual: 3}, | ||
messageElements: {element: 'scenario tag', expected: 0, actual: 1}, | ||
line: 7 | ||
},{ | ||
messageElements: {element: 'scenario tag', expected: 0, actual: 1}, | ||
line: 8 | ||
},{ | ||
messageElements: {element: 'Step', expected: 2, actual: 3}, | ||
line: 10 | ||
},{ | ||
messageElements: {element: 'Scenario', expected: 0, actual: 3}, | ||
line: 9 | ||
line: 14 | ||
},{ | ||
messageElements: {element: 'Examples', expected: 0, actual: 2}, | ||
line: 11 | ||
line: 16 | ||
},{ | ||
messageElements: {element: 'example', expected: 2, actual:4}, | ||
messageElements: {element: 'example', expected: 2, actual: 4}, | ||
line: 17 | ||
},{ | ||
messageElements: {element: 'example', expected: 2, actual: 4}, | ||
line: 18 | ||
},{ | ||
messageElements: {element: 'scenario tag', expected: 0, actual: 3}, | ||
line: 12 | ||
},{ | ||
messageElements: {element: 'example', expected: 2, actual:4}, | ||
messageElements: {element: 'scenario tag', expected: 0, actual: 4}, | ||
line: 13 | ||
},{ | ||
messageElements: {element: 'Step', expected: 2, actual: 3}, | ||
line: 10 | ||
line: 15 | ||
}]; | ||
@@ -59,34 +74,62 @@ | ||
messageElements: {element: 'Feature', expected: 0, actual: 4}, | ||
line: 3 | ||
},{ | ||
messageElements: {element: 'feature tag', expected: 0, actual: 4}, | ||
line: 2 | ||
},{ | ||
messageElements: {element: 'Background', expected: 0, actual: 4}, | ||
line: 4 | ||
line: 5 | ||
},{ | ||
messageElements: {element: 'Step', expected: 2, actual: 0}, | ||
line: 5 | ||
line: 6 | ||
},{ | ||
messageElements: {element: 'Scenario', expected: 0, actual: 4}, | ||
line: 7 | ||
line: 10 | ||
},{ | ||
messageElements: {element: 'Step', expected: 2, actual: 12}, | ||
messageElements: {element: 'scenario tag', expected: 0, actual: 4}, | ||
line: 8 | ||
},{ | ||
messageElements: {element: 'scenario tag', expected: 0, actual: 1}, | ||
line: 9 | ||
},{ | ||
messageElements: {element: 'Step', expected: 2, actual: 12}, | ||
line: 11 | ||
},{ | ||
messageElements: {element: 'Scenario', expected: 0, actual: 12}, | ||
line: 10 | ||
line: 15 | ||
},{ | ||
messageElements: {element: 'Examples', expected: 0, actual: 7}, | ||
line: 12 | ||
line: 17 | ||
},{ | ||
messageElements: {element: 'example', expected: 2, actual: 15}, | ||
line: 18 | ||
},{ | ||
messageElements: {element: 'example', expected: 2, actual: 15}, | ||
line: 19 | ||
},{ | ||
messageElements: {element: 'scenario tag', expected: 0, actual: 4}, | ||
line: 13 | ||
},{ | ||
messageElements: {element: 'example', expected: 2, actual: 15}, | ||
messageElements: {element: 'scenario tag', expected: 0, actual: 1}, | ||
line: 14 | ||
},{ | ||
messageElements: {element: 'Step', expected: 2, actual: 11}, | ||
line: 11 | ||
line: 16 | ||
}]); | ||
}); | ||
it('defaults the tag indentation settings when they are not set', function() { | ||
runTest('indentation/CorrectIndentationWithFeatureAndScenarioOverrides.feature', { | ||
'Feature': 1, | ||
'Scenario': 3 | ||
}, []); | ||
}); | ||
it('observe tag indentation settings when they are overriden', function() { | ||
runTest('indentation/CorrectIndentationWithScenarioTagOverrides.feature', { | ||
'scenario tag': 3 | ||
}, []); | ||
}); | ||
// TODO: add tests for partial configurations and fallbacks (eg rule for Step is used for Given, Then etc is rule for Given, Then, etc has not been specified) | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
99626
117
2270
159
11