Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
173 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
/** | ||
* @fileoverview Validates rule options. | ||
* @author Brandon Mills | ||
* @copyright 2015 Brandon Mills | ||
*/ | ||
|
||
"use strict"; | ||
|
||
var rules = require("./rules"), | ||
validator = require("is-my-json-valid"); | ||
|
||
var validators = Object.create(null); // Cache generated schema validators | ||
|
||
/** | ||
* Converts a rule's exported, abbreviated schema into a full schema. | ||
* @param {object} options Exported schema from a rule. | ||
* @returns {object} Full schema ready for validation. | ||
*/ | ||
function makeSchema(options) { | ||
|
||
// If no schema, only validate warning level, and permit anything after | ||
if (!options) { | ||
return { | ||
"type": "array", | ||
"items": [ | ||
{ | ||
"enum": [0, 1, 2] | ||
} | ||
], | ||
"minItems": 1 | ||
}; | ||
} | ||
|
||
// Given a tuple of schemas, insert warning level at the beginning | ||
if (Array.isArray(options)) { | ||
return { | ||
"type": "array", | ||
"items": [ | ||
{ | ||
"enum": [0, 1, 2] | ||
} | ||
].concat(options), | ||
"minItems": 1, | ||
"maxItems": options.length + 1 | ||
}; | ||
} | ||
|
||
// Given a full schema, leave it alone | ||
return options; | ||
} | ||
|
||
/** | ||
* Gets an options schema for a rule. | ||
* @param {string} id The rule's unique name. | ||
* @returns {object} vJSON Schema for the rule's options. | ||
*/ | ||
function getRuleSchema(id) { | ||
var rule = rules.get(id); | ||
return makeSchema(rule && rule.schema); | ||
} | ||
|
||
/** | ||
* Validates a rule's options against its schema. | ||
* @param {string} id The rule's unique name. | ||
* @param {object} config The given options for the rule. | ||
* @param {string} source The name of the configuration source. | ||
* @returns {void} | ||
*/ | ||
module.exports = function (id, config, source) { | ||
var validate = validators[id], | ||
message; | ||
|
||
if (!validate) { | ||
validate = validator(getRuleSchema(id), { verbose: true }); | ||
validators[id] = validate; | ||
} | ||
|
||
if (typeof config === "number") { | ||
config = [config]; | ||
} | ||
|
||
validate(config); | ||
|
||
if (validate.errors) { | ||
message = [ | ||
source, ":\n", | ||
"\tConfiguration for rule \"", id, "\" is invalid:\n" | ||
]; | ||
validate.errors.forEach(function (error) { | ||
message.push( | ||
"\tValue \"", error.value, "\" ", error.message, ".\n" | ||
); | ||
}); | ||
|
||
throw new Error(message.join("")); | ||
} | ||
}; | ||
|
||
module.exports.getRuleSchema = getRuleSchema; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/** | ||
* @fileoverview Tests for validate-options. | ||
* @author Brandon Mills | ||
* @copyright 2015 Brandon Mills | ||
*/ | ||
|
||
"use strict"; | ||
|
||
//------------------------------------------------------------------------------ | ||
// Requirements | ||
//------------------------------------------------------------------------------ | ||
|
||
var assert = require("chai").assert, | ||
eslint = require("../../lib/eslint"), | ||
validate = require("../../lib/validate-options"); | ||
|
||
//------------------------------------------------------------------------------ | ||
// Tests | ||
//------------------------------------------------------------------------------ | ||
|
||
function mockRule(context) { | ||
return { | ||
"Program": function(node) { | ||
context.report(node, "Expected a validation error."); | ||
} | ||
}; | ||
} | ||
|
||
mockRule.schema = [ | ||
{ | ||
"enum": ["single", "double", "backtick"] | ||
}, | ||
{ | ||
"enum": ["avoid-escape"] | ||
} | ||
]; | ||
|
||
describe("ValidateOptions", function() { | ||
|
||
beforeEach(function() { | ||
eslint.defineRule("mock-rule", mockRule); | ||
}); | ||
|
||
it("should throw for incorrect warning level", function() { | ||
var fn = validate.bind(null, "mock-rule", 3, "tests"); | ||
|
||
assert.throws(fn, "tests:\n\tConfiguration for rule \"mock-rule\" is invalid:\n\tValue \"3\" must be an enum value.\n"); | ||
}); | ||
|
||
it("should only check warning level for nonexistent rules", function() { | ||
var fn = validate.bind(null, "non-existent-rule", [3, "foobar"], "tests"); | ||
|
||
assert.throws(fn, "tests:\n\tConfiguration for rule \"non-existent-rule\" is invalid:\n\tValue \"3\" must be an enum value.\n"); | ||
}); | ||
|
||
it("should only check warning level for plugin rules", function() { | ||
var fn = validate.bind(null, "plugin/rule", 3, "tests"); | ||
|
||
assert.throws(fn, "tests:\n\tConfiguration for rule \"plugin/rule\" is invalid:\n\tValue \"3\" must be an enum value.\n"); | ||
}); | ||
|
||
it("should throw for incorrect configuration values", function() { | ||
var fn = validate.bind(null, "mock-rule", [2, "doulbe", "avoidEscape"], "tests"); | ||
|
||
assert.throws(fn, "tests:\n\tConfiguration for rule \"mock-rule\" is invalid:\n\tValue \"doulbe\" must be an enum value.\n\tValue \"avoidEscape\" must be an enum value.\n"); | ||
}); | ||
|
||
it("should throw for too many configuration values", function() { | ||
var fn = validate.bind(null, "mock-rule", [2, "single", "avoid-escape", "extra"], "tests"); | ||
|
||
assert.throws(fn, "tests:\n\tConfiguration for rule \"mock-rule\" is invalid:\n\tValue \"2,single,avoid-escape,extra\" has more items than allowed.\n"); | ||
}); | ||
|
||
}); |