diff --git a/lib/html_proofer.rb b/lib/html_proofer.rb index ca79c06e..1790aa16 100644 --- a/lib/html_proofer.rb +++ b/lib/html_proofer.rb @@ -25,7 +25,7 @@ def check_file(file, options = {}) raise ArgumentError unless file.is_a?(String) raise ArgumentError, "#{file} does not exist" unless File.exist?(file) - options[:type] = :file + options = prepare_options(options, :file) HTMLProofer::Runner.new(file, options) end @@ -33,14 +33,14 @@ def check_directory(directory, options = {}) raise ArgumentError unless directory.is_a?(String) raise ArgumentError, "#{directory} does not exist" unless Dir.exist?(directory) - options[:type] = :directory + options = prepare_options(options, :directory) HTMLProofer::Runner.new([directory], options) end def check_directories(directories, options = {}) raise ArgumentError unless directories.is_a?(Array) - options[:type] = :directory + options = prepare_options(options, :directory) directories.each do |directory| raise ArgumentError, "#{directory} does not exist" unless Dir.exist?(directory) end @@ -50,9 +50,20 @@ def check_directories(directories, options = {}) def check_links(links, options = {}) raise ArgumentError unless links.is_a?(Array) - options[:type] = :links + options = prepare_options(options, :links) HTMLProofer::Runner.new(links, options) end + + private + + def prepare_options(options, type) + options = {} if options.nil? + + raise ArgumentError, "Options must be a Hash" unless options.is_a?(Hash) + + options[:type] = type + options + end end end diff --git a/lib/html_proofer/configuration.rb b/lib/html_proofer/configuration.rb index e49d6ede..a5593b49 100644 --- a/lib/html_proofer/configuration.rb +++ b/lib/html_proofer/configuration.rb @@ -49,6 +49,8 @@ module Configuration class << self def generate_defaults(opts) + validate_options(default_options, opts) + options = PROOFER_DEFAULTS.merge(opts) options[:typhoeus] = HTMLProofer::Configuration::TYPHOEUS_DEFAULTS.merge(opts[:typhoeus] || {}) @@ -86,6 +88,24 @@ def parse_json_option(option_name, config, symbolize_names: true) raise ArgumentError, "Option '#{option_name} did not contain valid JSON." end end + + private + + def default_options + PROOFER_DEFAULTS.merge(typhoeus: TYPHOEUS_DEFAULTS).merge(hydra: HYDRA_DEFAULTS).merge(parallel: PARALLEL_DEFAULTS) + end + + def validate_options(defaults, options) + defaults.each do |key, default_value| + next unless options.key?(key) + + value = options[key] + raise TypeError, "Invalid value for '#{key}': '#{value}'. Expected #{default_value.class}." unless value.is_a?(default_value.class) + + # Iterate over nested hashes + validate_options(default_value, value) if default_value.is_a?(Hash) + end + end end end end diff --git a/spec/html-proofer/proofer_spec.rb b/spec/html-proofer/proofer_spec.rb index ba1e7260..433e90ba 100644 --- a/spec/html-proofer/proofer_spec.rb +++ b/spec/html-proofer/proofer_spec.rb @@ -44,6 +44,29 @@ typhoeus: { verbose: true, headers: { "User-Agent" => "Mozilla/5.0 (compatible; My New User-Agent)" } }) expect(http["request"]["headers"]["User-Agent"]).to(eq(["Mozilla/5.0 (compatible; My New User-Agent)"])) end + + it "does not fail on nil options" do + github_hash = File.join(FIXTURES_DIR, "links", "github_hash.html") + HTMLProofer.check_file(github_hash, nil) + end + + it "fails with friendly error on non-Hash options" do + links_dir = File.join(FIXTURES_DIR, "links") + expect { HTMLProofer.check_directory(links_dir, "abc") }.to(raise_error(ArgumentError, "Options must be a Hash")) + end + + it "fails with friendly error invalid option values" do + options = { + assume_extension: true, + typhoeus: "abc", + enforce_https: :yes_please, + hydra: { max_concurrency: false }, + } + options.each do |key, value| + links_dir = File.join(FIXTURES_DIR, "links") + expect { HTMLProofer.check_directory(links_dir, key => value).run }.to(raise_error(TypeError, /^Invalid value for '.*': '.*'\. Expected .*\./)) + end + end end describe "file ignores" do