spec/cc/config/validation/yaml_spec.rb (289 lines of code) (raw):
require "spec_helper"
describe CC::Config::Validation::YAML do
it "is valid for a complete config" do
validator = validate_yaml(<<-EOYAML)
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
exclude_patterns:
- foo
config:
file: "foobar"
eslint:
enabled: true
config: "bazfoo"
hlint: true
exclude_patterns:
- "**/*.rb"
- foo/
EOYAML
expect(validator).to be_valid
expect(validator.warnings.length).to eq(0)
end
it "handles legacy config with engine excludes" do
validator = validate_yaml(<<-EOYAML)
engines:
rubocop:
exclude_paths:
- foo
exclude_paths:
- bar
EOYAML
expect(validator).to be_valid
expect(validator.warnings).not_to include(a_string_matching(/unrecognized key/))
expect(validator.warnings).to include(a_string_starting_with(
"engine rubocop: 'exclude_paths' has been deprecated"
))
end
it "handles legacy config with engine excludes as a string" do
validator = validate_yaml(<<-EOYAML)
engines:
rubocop:
exclude_paths:
foo
exclude_paths:
bar
EOYAML
validator.valid?
expect(validator).to be_valid
expect(validator.warnings).not_to include(a_string_matching(/unrecognized key/))
end
it "handles unparseable yaml" do
validator = validate_yaml("yargle: poskgp;aerwet ;rgr: ")
expect(validator).not_to be_valid
expect(validator.errors).to include(/Unable to parse:/)
end
it "handles parseable but non-hash yaml" do
validator = validate_yaml("- foo\n- bar\n")
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_yaml(<<-EOYAML)
prepare:
fetch:
rubocop: http://test.test/rubocop.yml
EOYAML
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_yaml(<<-EOYAML)
prepare:
fetch:
- test.test/rubocop.yml
- url: http://test.test/myeslint.json
EOYAML
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_yaml(<<-EOYAML)
prepare:
fetch:
- url: http://test.test/myeslint.json
path:
- url: http://test.test/myeslint.json
path: /etc/passwd
- url: http://test.test/myeslint.json
path: ../../htaccess
EOYAML
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_yaml(<<-EOYAML)
plugins:
- rubocop
EOYAML
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_yaml(<<-EOYAML)
plugins:
rubocop: foobar
EOYAML
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_yaml(<<-EOYAML)
plugins:
rubocop:
enabled: foobar
config: false
exclude_patterns: nope
EOYAML
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")
expect(validator.errors).to include("engine rubocop: 'exclude_patterns' must be an array")
end
it "reports errors for array checks" do
validator = validate_yaml(<<-EOYAML)
checks:
- foo
EOYAML
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_yaml(<<-EOYAML)
checks:
foo: false
EOYAML
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_yaml(<<-EOYAML)
checks:
foo:
enabled: foobar
config: false
EOYAML
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_yaml(<<-EOYAML)
exclude_patterns: foobar
EOYAML
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_yaml(<<-EOYAML)
exclude_patterns:
- foo: bar
EOYAML
expect(validator).not_to be_valid
expect(validator.errors).to include(/each exclude pattern should be a string/)
end
it "reports errors for conflicting keys" do
validator = validate_yaml(<<-EOYAML)
engines:
rubocop:
enabled: true
plugins:
eslint:
enabled: true
exclude_paths:
- bar
exclude_patterns:
- foo
EOYAML
expect(validator).not_to be_valid
expect(validator.errors).to include("only use one of 'engines', 'plugins'")
expect(validator.errors).to include("only use one of 'exclude_paths', 'exclude_patterns'")
end
it "reports warnings for deprecated keys" do
validator = validate_yaml(<<-EOYAML)
engines:
rubocop:
enabled: true
ratings:
paths:
- foo
exclude_paths:
- bar
EOYAML
expect(validator).to be_valid
expect(validator.warnings).to include("'ratings' has been deprecated, and will not be used")
expect(validator.warnings).to include("'engines' has been deprecated, please use 'plugins' instead")
expect(validator.warnings).to include("'exclude_paths' has been deprecated, please use 'exclude_patterns' instead")
end
it "reports warnings for unrecognized keys" do
validator = validate_yaml(<<-EOYAML)
engines:
rubocop:
enabbled: false
exclude_pattttttterns:
- foo
EOYAML
expect(validator).to be_valid
expect(validator.warnings).to include("engine rubocop: unrecognized key 'enabbled'")
expect(validator.warnings).to include("unrecognized key 'exclude_pattttttterns'")
end
describe "version validation" do
it "does not warn about version for v1 schema" do
validator = validate_yaml(<<-EOYAML)
engines: {}
EOYAML
expect(validator).to be_valid
expect(validator.warnings).not_to include(%{missing 'version' key. Please add `version: "2"`})
end
it "does warn about version for v2 schema" do
validator = validate_yaml(<<-EOYAML)
plugins: {}
EOYAML
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_yaml(<<-EOYAML)
plugins:
rubocop:
checks:
Foo:
enabled: false
EOYAML
expect(validator).to be_valid
end
it "errors for the wrong type" do
validator = validate_yaml(<<-EOYAML)
plugins:
rubocop:
checks:
- Foo
EOYAML
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_yaml(<<-EOYAML)
plugins:
rubocop:
exclude_fingerprints:
- foo
EOYAML
expect(validator).to be_valid
end
it "errors for the wrong type" do
validator = validate_yaml(<<-EOYAML)
plugins:
rubocop:
exclude_fingerprints: Foo
EOYAML
expect(validator).not_to be_valid
expect(validator.errors).to include("engine rubocop: 'exclude_fingerprints' must be an array")
end
end
def validate_yaml(yaml, registry = nil)
Tempfile.open("") do |tmp|
tmp.puts(yaml)
tmp.rewind
registry ||= double(:engine_registry, fetch_engine_details: {})
described_class.new(tmp.path, registry)
end
end
end