diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index eef920c77..99d9bf300 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,15 +1,11 @@ # This configuration was generated by # `rubocop --auto-gen-config --no-offense-counts --no-auto-gen-timestamp` -# using RuboCop version 1.63.4. +# using RuboCop version 1.68.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. -Lint/ToEnumArguments: - Exclude: - - 'lib/rubocop/cop/rspec/multiple_expectations.rb' - Rake/MethodDefinitionInTask: Exclude: - 'tasks/cut_release.rake' diff --git a/.simplecov b/.simplecov index 37e9f727f..81ecd5fae 100644 --- a/.simplecov +++ b/.simplecov @@ -2,7 +2,7 @@ SimpleCov.start do enable_coverage :branch - minimum_coverage line: 100, branch: 97.43 + minimum_coverage line: 100, branch: 97.94 add_filter '/spec/' add_filter '/vendor/bundle/' end diff --git a/lib/rubocop/rspec/hook.rb b/lib/rubocop/rspec/hook.rb index d0272c156..90116a75e 100644 --- a/lib/rubocop/rspec/hook.rb +++ b/lib/rubocop/rspec/hook.rb @@ -45,7 +45,7 @@ def metadata private def valid_scope?(node) - node&.sym_type? && Language::HookScopes.all(node.value) + node.sym_type? && Language::HookScopes.all(node.value) end def transform_metadata(meta) diff --git a/spec/rubocop/cop/rspec/instance_spy_spec.rb b/spec/rubocop/cop/rspec/instance_spy_spec.rb index 9807003b2..94f0d360f 100644 --- a/spec/rubocop/cop/rspec/instance_spy_spec.rb +++ b/spec/rubocop/cop/rspec/instance_spy_spec.rb @@ -44,6 +44,16 @@ end RUBY end + + it 'ignores instance_double when expect is called on another variable' do + expect_no_offenses(<<~RUBY) + it do + foo = instance_double(Foo).as_null_object + bar = instance_spy(Bar).as_null_object + expect(bar).to have_received(:baz) + end + RUBY + end end context 'when not used with `have_received`' do diff --git a/spec/rubocop/rspec/hook_spec.rb b/spec/rubocop/rspec/hook_spec.rb index ad9493527..9cf2e59b4 100644 --- a/spec/rubocop/rspec/hook_spec.rb +++ b/spec/rubocop/rspec/hook_spec.rb @@ -45,6 +45,11 @@ def hook(source) .to be(:each) end + it 'ignores invalid hooks' do + expect(hook('before(:invalid) { example_setup }').scope) + .to be_nil + end + it 'classifies :each as an example hook' do expect(hook('before(:each) { }').example?).to be(true) end @@ -75,9 +80,13 @@ def metadata(source) end if RUBY_VERSION >= '3.4' + let(:expected_focus) { 's(:sym, :focus) => true' } + let(:expected_invalid) { '{s(:sym, :invalid) => true}' } let(:expected_special) { 's(:sym, :special) => true' } let(:expected_symbol) { 's(:sym, :symbol) => true' } else + let(:expected_focus) { 's(:sym, :focus)=>true' } + let(:expected_invalid) { '{s(:sym, :invalid)=>true}' } let(:expected_special) { 's(:sym, :special)=>true' } let(:expected_symbol) { 's(:sym, :symbol)=>true' } end @@ -103,8 +112,29 @@ def metadata(source) end it 'withstands no arguments' do - expect(metadata('before { foo }')) - .to be_empty + expect(metadata('before { foo }')).to be_empty + end + + it 'returns the symbol even when an invalid symbol scope is provided' do + expect(metadata('before(:invalid) { foo }')).to eq(expected_invalid) + end + + it 'extracts multiple symbol metadata' do + expect(metadata('before(:example, :special, :focus) { foo }')) + .to eq("{#{expected_special}, #{expected_focus}}") + end + + it 'extracts multiple hash metadata' do + expect(metadata('before(:example, special: true, focus: true) { foo }')) + .to eq("{#{expected_special}, #{expected_focus}}") + end + + it 'combines multiple symbol and hash metadata' do + expect( + metadata( + 'before(:example, :symbol, special: true, focus: true) { foo }' + ) + ).to eq("{#{expected_symbol}, #{expected_special}, #{expected_focus}}") end end end diff --git a/spec/rubocop/rspec/inject_spec.rb b/spec/rubocop/rspec/inject_spec.rb new file mode 100644 index 000000000..44f98070f --- /dev/null +++ b/spec/rubocop/rspec/inject_spec.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +RSpec.describe RuboCop::RSpec::Inject do + describe '.defaults!' do + let(:config_loader) { class_double(RuboCop::ConfigLoader).as_stubbed_const } + + before do + rubocop_config = instance_double(RuboCop::Config) + allow(config_loader).to receive(:send) + .with(:load_yaml_configuration, any_args) + .and_return({}) + allow(RuboCop::Config).to receive(:new).and_return(rubocop_config) + allow(config_loader).to receive(:merge_with_default) + .and_return(rubocop_config) + allow(config_loader).to receive(:instance_variable_set) + end + + context 'when ConfigLoader.debug? is true' do + before do + allow(config_loader).to receive(:debug?).and_return(true) + end + + it 'puts the configuration path' do + expect { described_class.defaults! }.to output( + %r{configuration from .*rubocop-rspec/config/default.yml} + ).to_stdout + end + end + + context 'when ConfigLoader.debug? is false' do + before do + allow(config_loader).to receive(:debug?).and_return(false) + end + + it 'does not put the configuration path' do + expect { described_class.defaults! }.not_to output.to_stdout + end + end + end +end