diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 98714b8..761a986 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -201,7 +201,11 @@ RSpec/SpecFilePathFormat: - 'spec/ruby-link-checker/callbacks_spec.rb' - 'spec/ruby-link-checker/checker_spec.rb' - 'spec/ruby-link-checker/config_spec.rb' + - 'spec/ruby-link-checker/errors/redirect_loop_error_spec.rb' - 'spec/ruby-link-checker/net/http/checker_spec.rb' + - 'spec/ruby-link-checker/result_error_spec.rb' + - 'spec/ruby-link-checker/result_spec.rb' + - 'spec/ruby-link-checker/task_spec.rb' - 'spec/ruby-link-checker/tasks_spec.rb' - 'spec/ruby-link-checker/typhoeus/hydra/checker_spec.rb' - 'spec/ruby-link-checker/version_spec.rb' diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c56200..bace02e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * [#19](https://github.com/dblock/ruby-link-checker/pull/19): Added `LinkChecker::Async::HTTP`, a link checker based on [async-http](https://github.com/socketry/async-http) - [@dblock](https://github.com/dblock), [@Copilot](https://github.com/Copilot). * [#19](https://github.com/dblock/ruby-link-checker/pull/19): Dropped support for Ruby < 3.3 - [@dblock](https://github.com/dblock), [@Copilot](https://github.com/Copilot). * [#20](https://github.com/dblock/ruby-link-checker/pull/20): Added support for custom headers - [@dblock](https://github.com/dblock), [@Copilot](https://github.com/Copilot). +* [#21](https://github.com/dblock/ruby-link-checker/pull/21): Improved test coverage to 100% and fixed Danger dry_run failure by unpinning `danger-changelog` - [@dblock](https://github.com/dblock), [@Copilot](https://github.com/Copilot). * Your contribution here. ### 0.3.0 (2025-07-05) diff --git a/Gemfile b/Gemfile index ee2e76c..a415ca3 100644 --- a/Gemfile +++ b/Gemfile @@ -8,7 +8,7 @@ gem 'rake' group :development, :test do gem 'danger' - gem 'danger-changelog', '0.6.1' + gem 'danger-changelog', '0.8.0' gem 'danger-pr-comment' gem 'danger-toc', '0.2.0' gem 'rspec', '~> 3.0' diff --git a/spec/ruby-link-checker/async/http/checker_spec.rb b/spec/ruby-link-checker/async/http/checker_spec.rb index 04db2d7..8b06f02 100644 --- a/spec/ruby-link-checker/async/http/checker_spec.rb +++ b/spec/ruby-link-checker/async/http/checker_spec.rb @@ -35,6 +35,12 @@ def check(url, options = {}) describe AsyncTestLinkChecker::LinkChecker do it_behaves_like 'a link checker' + describe '.config' do + it 'returns the Config module' do + expect(LinkChecker::Async::HTTP.config).to eq LinkChecker::Async::HTTP::Config + end + end + context 'with timeout options', vcr: { cassette_name: '200' } do before do LinkChecker::Async::HTTP.configure do |config| @@ -80,4 +86,14 @@ def check(url, options = {}) end end end + + describe LinkChecker::Async::HTTP::Result do + describe '#code' do + it 'returns -1 when there is no response' do + request = instance_double(Protocol::HTTP::Request) + result = described_class.new(URI('https://www.example.org'), 'GET', nil, request, nil, {}) + expect(result.code).to eq(-1) + end + end + end end diff --git a/spec/ruby-link-checker/callbacks_spec.rb b/spec/ruby-link-checker/callbacks_spec.rb index 41047be..c861668 100644 --- a/spec/ruby-link-checker/callbacks_spec.rb +++ b/spec/ruby-link-checker/callbacks_spec.rb @@ -6,6 +6,10 @@ subject do Class.new do include LinkChecker::Callbacks + + def logger + @logger ||= Logger.new(nil) + end end.new end @@ -40,4 +44,33 @@ expect(subject).to have_received(:called!).with(:bar) end end + + context 'method_missing' do + it 'invokes callback for a bang method' do + allow(subject).to receive(:called!) + subject.on :foo do |data| + subject.called! data + end + subject.foo! :foo + expect(subject).to have_received(:called!).with(:foo) + end + + it 'raises NoMethodError for a non-bang method' do + expect { subject.foo }.to raise_error NoMethodError + end + end + + context 'when a callback raises an error' do + before do + subject.on :foo do + raise StandardError, 'oops' + end + end + + it 'rescues and logs the error' do + allow(subject.logger).to receive(:error) + expect(subject.send(:callback, :foo)).to be false + expect(subject.logger).to have_received(:error) + end + end end diff --git a/spec/ruby-link-checker/errors/redirect_loop_error_spec.rb b/spec/ruby-link-checker/errors/redirect_loop_error_spec.rb new file mode 100644 index 0000000..33132e5 --- /dev/null +++ b/spec/ruby-link-checker/errors/redirect_loop_error_spec.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe LinkChecker::Errors::RedirectLoopError do + subject(:error) do + described_class.new(['https://www.example.org', 'https://www.example.org/redirect']) + end + + it 'returns the last url' do + expect(error.url).to eq 'https://www.example.org/redirect' + end + + it 'formats a message with all urls' do + expect(error.message) + .to eq 'Redirect loop: https://www.example.org -> https://www.example.org/redirect.' + end +end diff --git a/spec/ruby-link-checker/net/http/checker_spec.rb b/spec/ruby-link-checker/net/http/checker_spec.rb index 04f44b6..cb2faeb 100644 --- a/spec/ruby-link-checker/net/http/checker_spec.rb +++ b/spec/ruby-link-checker/net/http/checker_spec.rb @@ -15,6 +15,12 @@ it_behaves_like 'a link checker' + describe '.config' do + it 'returns the Config module' do + expect(LinkChecker::Net::HTTP.config).to eq LinkChecker::Net::HTTP::Config + end + end + context 'with timeout options', vcr: { cassette_name: '200' } do before do LinkChecker::Net::HTTP.configure do |config| @@ -58,4 +64,15 @@ end end end + + describe LinkChecker::Net::HTTP::Result do + describe '#code' do + it 'returns -1 when the response raises' do + response = instance_double(Net::HTTPResponse) + allow(response).to receive(:code).and_raise(StandardError) + result = described_class.new(URI('https://www.example.org'), 'GET', nil, nil, response, {}) + expect(result.code).to eq(-1) + end + end + end end diff --git a/spec/ruby-link-checker/result_error_spec.rb b/spec/ruby-link-checker/result_error_spec.rb new file mode 100644 index 0000000..44d4897 --- /dev/null +++ b/spec/ruby-link-checker/result_error_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe LinkChecker::ResultError do + subject(:result) do + described_class.new('https://www.example.org', 'GET', 'https://www.example.org', StandardError.new('oops')) + end + + it 'is an error' do + expect(result.error?).to be true + end + + it 'returns the error class name as code' do + expect(result.code).to eq 'StandardError' + end +end diff --git a/spec/ruby-link-checker/result_spec.rb b/spec/ruby-link-checker/result_spec.rb new file mode 100644 index 0000000..9001584 --- /dev/null +++ b/spec/ruby-link-checker/result_spec.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe LinkChecker::Result do + subject(:result) do + described_class.new('https://www.example.org', 'GET', 'https://www.example.org') + end + + it 'defaults to not successful' do + expect(result.success?).to be false + end + + it 'defaults to not a failure' do + expect(result.failure?).to be false + end + + it 'defaults to not an error' do + expect(result.error?).to be false + end + + it 'defaults to not a redirect' do + expect(result.redirect?).to be false + end + + it 'defaults redirect_to to nil' do + expect(result.redirect_to).to be_nil + end + + it 'defaults request_headers to an empty hash' do + expect(result.request_headers).to eq({}) + end + + it 'defaults code to nil' do + expect(result.code).to be_nil + end + + it 'defaults error to nil' do + expect(result.error).to be_nil + end +end diff --git a/spec/ruby-link-checker/task_spec.rb b/spec/ruby-link-checker/task_spec.rb new file mode 100644 index 0000000..d8e6806 --- /dev/null +++ b/spec/ruby-link-checker/task_spec.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe LinkChecker::Task do + subject(:task) do + described_class.new( + LinkChecker::Net::HTTP::Checker.new, + 'https://www.example.org', + 'GET', + 'https://www.example.org' + ) + end + + describe '#run!' do + it 'raises NotImplementedError' do + expect { task.run! }.to raise_error NotImplementedError + end + end +end diff --git a/spec/ruby-link-checker/tasks_spec.rb b/spec/ruby-link-checker/tasks_spec.rb index 3de3dca..fbec879 100644 --- a/spec/ruby-link-checker/tasks_spec.rb +++ b/spec/ruby-link-checker/tasks_spec.rb @@ -33,4 +33,15 @@ end end end + + describe '#retries' do + let(:checker) { LinkChecker::Net::HTTP::Checker.new(methods: ['GET'], retries: 2) } + let(:task_klass) { LinkChecker::Net::HTTP::Task } + let(:url) { 'https://www.example.org' } + + it 'delegates to the checker' do + tasks = described_class.new(checker, task_klass, url, ['GET']) + expect(tasks.send(:retries)).to eq 2 + end + end end diff --git a/spec/ruby-link-checker/typhoeus/hydra/checker_spec.rb b/spec/ruby-link-checker/typhoeus/hydra/checker_spec.rb index 7baa9e4..025a35b 100644 --- a/spec/ruby-link-checker/typhoeus/hydra/checker_spec.rb +++ b/spec/ruby-link-checker/typhoeus/hydra/checker_spec.rb @@ -22,6 +22,12 @@ def check(url, options = {}) describe TyphoeusTestLinkChecker::LinkChecker do it_behaves_like 'a link checker' + describe '.config' do + it 'returns the Config module' do + expect(LinkChecker::Typhoeus::Hydra.config).to eq LinkChecker::Typhoeus::Hydra::Config + end + end + context 'with timeout options', vcr: { cassette_name: '200' } do before do LinkChecker::Typhoeus::Hydra.configure do |config| @@ -64,4 +70,24 @@ def check(url, options = {}) end end end + + describe LinkChecker::Typhoeus::Hydra::Result do + describe '#code' do + it 'returns -1 when the response raises' do + request = instance_double(Typhoeus::Request) + response = instance_double(Typhoeus::Response) + allow(response).to receive(:code).and_raise(StandardError) + result = described_class.new(URI('https://www.example.org'), 'GET', nil, request, response, {}) + expect(result.code).to eq(-1) + end + end + end + + describe '#run' do + it 'delegates to the hydra' do + checker = described_class.new + expect(checker.instance_variable_get(:@hydra)).to receive(:run) + checker.run + end + end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 0c5eb57..4a5d139 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -5,7 +5,9 @@ require 'rubygems' require 'simplecov' -SimpleCov.start +SimpleCov.start do + add_filter '/spec/' +end require 'rspec' require 'ruby-link-checker'