spec/cc/config/validation/json_spec.rb (270 lines of code) (raw):
require "spec_helper"
describe CC::Config::Validation::JSON do
it "is valid for a complete config" do
validator = validate_json(<<-EOJSON)
{
"version": "2",
"prepare": {
"fetch": [
"http://test.test/rubocop.yml",
{
"url": "http://test.test/myeslint.json",
"path": "eslint.json"
}
]
},
"checks": {
"method-complexity": {
"enabled": false
}
},
"plugins": {
"rubocop": {
"enabled": true,
"channel": "beta",
"config": { "file": "foobar" }
},
"eslint": {
"enabled": true,
"config": "bazfoo"
},
"hlint": true
},
"exclude_patterns": [
"**/*.rb",
"foo/"
]
}
EOJSON
expect(validator).to be_valid
expect(validator.warnings.length).to eq(0)
end
it "handles unparseable json" do
validator = validate_json("{")
expect(validator).not_to be_valid
expect(validator.errors).to include(/Unable to parse:/)
end
it "handles parseable but non-hash json" do
validator = validate_json(%{["foo", "bar"]})
expect(validator).not_to be_valid
expect(validator.errors).to include(/Config file should contain a hash/)
end
it "reports error for hash fetch" do
validator = validate_json(<<-EOJSON)
{
"prepare": {
"fetch": {
"rubocop": "http://test.test/rubocop.yml"
}
}
}
EOJSON
expect(validator).not_to be_valid
expect(validator.errors).to include("prepare section: 'fetch' must be an array")
end
it "reports errors for fetch with invalid URL or missing path" do
validator = validate_json(<<-EOJSON)
{
"prepare": {
"fetch": [
"test.test/rubocop.yml",
{ "url": "http://test.test/myeslint.json" }
]
}
}
EOJSON
expect(validator).not_to be_valid
expect(validator.errors).to include(%r{invalid URL 'test.test/rubocop.yml'})
expect(validator.errors).to include(/must include 'url' & 'path'/)
end
it "reports errors for fetch with invalid paths" do
validator = validate_json(<<-EOJSON)
{
"prepare": {
"fetch": [
{
"url": "http://test.test/myeslint.json",
"path": null
},
{
"url": "http://test.test/myeslint.json",
"path": "/etc/passwd"
},
{
"url": "http://test.test/myeslint.json",
"path": "../../htaccess"
}
]
}
}
EOJSON
expect(validator).not_to be_valid
expect(validator.errors).to include(/'path' cannot be empty/)
expect(validator.errors).to include(%r{absolute path '/etc/passwd' is invalid})
expect(validator.errors).to include(%r{relative path elements in '../../htaccess' are invalid})
end
it "reports errors for array plugins" do
validator = validate_json(<<-EOJSON)
{ "plugins": [ "rubocop" ] }
EOJSON
expect(validator).not_to be_valid
expect(validator.errors).to include(/'plugins' must be a hash/)
end
it "reports errors for invalid stringy engine config" do
validator = validate_json(<<-EOJSON)
{ "plugins": { "rubocop": "foobar" } }
EOJSON
expect(validator).not_to be_valid
expect(validator.errors).to include("engine rubocop: section must be a boolean or a hash")
end
it "reports errors for engine config with invalid contents" do
validator = validate_json(<<-EOJSON)
{
"plugins": {
"rubocop": {
"enabled": "foobar",
"config": false
}
}
}
EOJSON
expect(validator).not_to be_valid
expect(validator.errors).to include("engine rubocop: 'enabled' must be a boolean")
expect(validator.errors).to include("engine rubocop: 'config' must be one of string, hash")
end
it "reports errors for array checks" do
validator = validate_json(<<-EOJSON)
{ "checks": [ "foo" ] }
EOJSON
expect(validator).not_to be_valid
expect(validator.errors).to include(/'checks' must be a hash/)
end
it "reports errors for check with boolean config" do
validator = validate_json(<<-EOJSON)
{ "checks": { "foo": false } }
EOJSON
expect(validator).not_to be_valid
expect(validator.errors).to include("check foo: must be a hash")
end
it "reports errors for check with invalid config" do
validator = validate_json(<<-EOJSON)
{
"checks": {
"foo": {
"enabled": "foobar",
"config": false
}
}
}
EOJSON
expect(validator).not_to be_valid
expect(validator.errors).to include("check foo: 'enabled' must be a boolean")
expect(validator.errors).to include("check foo: 'config' must be a hash")
end
it "reports errors for singular string exclude patterns" do
validator = validate_json(<<-EOJSON)
{ "exclude_patterns": "foobar" }
EOJSON
expect(validator).not_to be_valid
expect(validator.errors).to include("'exclude_patterns' must be an array")
end
it "reports errors for errors within exclude_patterns" do
validator = validate_json(<<-EOJSON)
{
"exclude_patterns": [
{ "foo": "bar" }
]
}
EOJSON
expect(validator).not_to be_valid
expect(validator.errors).to include(/each exclude pattern should be a string/)
end
it "reports warnings for unrecognized keys" do
validator = validate_json(<<-EOJSON)
{
"plugins": {
"rubocop": {
"enalbed": false
}
},
"exclude_pattttttterns": [ "foo" ]
}
EOJSON
expect(validator).to be_valid
expect(validator.warnings).to include("engine rubocop: unrecognized key 'enalbed'")
expect(validator.warnings).to include("unrecognized key 'exclude_pattttttterns'")
end
describe "version validation" do
it "warns about missing version" do
validator = validate_json(<<-EOJSON)
{ "plugins": {} }
EOJSON
expect(validator).to be_valid
expect(validator.warnings).to include(%{missing 'version' key. Please add `"version": "2"`})
end
end
describe "engine checks" do
it "is valid for valid usage" do
validator = validate_json(<<-EOJSON)
{
"plugins": {
"rubocop": {
"checks": {
"Foo": { "enabled": false }
}
}
}
}
EOJSON
expect(validator).to be_valid
end
it "errors for the wrong type" do
validator = validate_json(<<-EOJSON)
{
"plugins": {
"rubocop": {
"checks": [ "Foo" ]
}
}
}
EOJSON
expect(validator).not_to be_valid
expect(validator.errors).to include("engine rubocop: 'checks' must be a hash")
end
end
describe "exclude_fingerprints" do
it "allows valid usage" do
validator = validate_json(<<-EOJSON)
{
"plugins": {
"rubocop": {
"exclude_fingerprints": [ "foo" ]
}
}
}
EOJSON
expect(validator).to be_valid
end
it "errors for the wrong type" do
validator = validate_json(<<-EOJSON)
{
"plugins": {
"rubocop": {
"exclude_fingerprints": "foo"
}
}
}
EOJSON
expect(validator).not_to be_valid
expect(validator.errors).to include("engine rubocop: 'exclude_fingerprints' must be an array")
end
end
def validate_json(json, registry = nil)
Tempfile.open("") do |tmp|
tmp.puts(json)
tmp.rewind
registry ||= double(:engine_registry, fetch_engine_details: {})
described_class.new(tmp.path, registry)
end
end
end