diff --git a/CHANGELOG.md b/CHANGELOG.md index 955f483..8b805ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,11 @@ # main +* Added autocorrection for `RSpec/MultipleExpectations`. + (Fix [#59](https://github.com/petalmd/rubocop-petal/issues/59)). ([#74](https://github.com/petalmd/rubocop-petal/pull/74)) * Update rubocop dependencies and minimum Ruby version. (Fix [#68](https://github.com/petalmd/rubocop-petal/issues/68)). ([#75](https://github.com/petalmd/rubocop-petal/pull/75)) * Enabled `RSpec/MultipleExpectations`. ([#73](https://github.com/petalmd/rubocop-petal/pull/73)) -* Added new cops from test-prod RSpec/AggregateExamples (Fix [#59](https://github.com/petalmd/rubocop-petal/issues/59)). ([#72](https://github.com/petalmd/rubocop-petal/pull/72)) +* Added new cops from test-prod RSpec/AggregateExamples. ([#72](https://github.com/petalmd/rubocop-petal/pull/72)) # v1.2.0 (2023-09-28) diff --git a/lib/rubocop/cop/rspec/multiple_expectations_auto_correct.rb b/lib/rubocop/cop/rspec/multiple_expectations_auto_correct.rb new file mode 100644 index 0000000..4320ff7 --- /dev/null +++ b/lib/rubocop/cop/rspec/multiple_expectations_auto_correct.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +require 'rubocop-rspec' + +module RuboCop + module Cop + module RSpec + module MultipleExpectationsAutoCorrect + def self.prepended(base) + base.extend(AutoCorrector) + end + + private + + def flag_example(node, expectation_count:) + add_offense( + node.send_node, + message: format( + MultipleExpectations::MSG, + total: expectation_count, + max: max_expectations + ) + ) do |corrector| + autocorrect(node, corrector) + end + end + + def autocorrect(node, corrector) + if (args = node.children.first.arguments.first) + corrector.insert_after(args, ', :aggregate_failures') + else + corrector.insert_after(node.children.first, ' :aggregate_failures') + end + end + end + end + end +end + +RuboCop::Cop::RSpec::MultipleExpectations + .prepend(RuboCop::Cop::RSpec::MultipleExpectationsAutoCorrect) diff --git a/spec/rubocop/cop/rspec/multiple_expectations_spec.rb b/spec/rubocop/cop/rspec/multiple_expectations_spec.rb new file mode 100644 index 0000000..f3eb493 --- /dev/null +++ b/spec/rubocop/cop/rspec/multiple_expectations_spec.rb @@ -0,0 +1,101 @@ +# frozen_string_literal: true + +# Test the cop directly +RSpec.describe RuboCop::Cop::RSpec::MultipleExpectations, :config do + it 'autocorrects multiple expectations with aggregate_failures' do + expect_offense(<<~RUBY) + describe Foo do + it 'uses expect twice' do + ^^^^^^^^^^^^^^^^^^^^^^ Example has too many expectations [2/1]. + expect(foo).to eq(bar) + expect(baz).to eq(bar) + end + end + RUBY + + expect_correction(<<~RUBY) + describe Foo do + it 'uses expect twice', :aggregate_failures do + expect(foo).to eq(bar) + expect(baz).to eq(bar) + end + end + RUBY + + expect_offense(<<~RUBY) + describe Foo do + it do + ^^ Example has too many expectations [2/1]. + expect(foo).to eq(bar) + expect(baz).to eq(bar) + end + end + RUBY + + expect_correction(<<~RUBY) + describe Foo do + it :aggregate_failures do + expect(foo).to eq(bar) + expect(baz).to eq(bar) + end + end + RUBY + + expect_offense(<<~RUBY) + describe Foo do + it('uses expect twice') do + ^^^^^^^^^^^^^^^^^^^^^^^ Example has too many expectations [2/1]. + expect(foo).to eq(bar) + expect(baz).to eq(bar) + end + end + RUBY + + expect_correction(<<~RUBY) + describe Foo do + it('uses expect twice', :aggregate_failures) do + expect(foo).to eq(bar) + expect(baz).to eq(bar) + end + end + RUBY + + expect_offense(<<~RUBY) + describe Foo do + it 'uses expect twice', timecop: true do + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Example has too many expectations [2/1]. + expect(foo).to eq(bar) + expect(baz).to eq(bar) + end + end + RUBY + + expect_correction(<<~RUBY) + describe Foo do + it 'uses expect twice', :aggregate_failures, timecop: true do + expect(foo).to eq(bar) + expect(baz).to eq(bar) + end + end + RUBY + + expect_offense(<<~RUBY) + describe Foo do + it('uses expect twice', timecop: true) do + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Example has too many expectations [2/1]. + expect(foo).to eq(bar) + expect(baz).to eq(bar) + end + end + RUBY + + expect_correction(<<~RUBY) + describe Foo do + it('uses expect twice', :aggregate_failures, timecop: true) do + expect(foo).to eq(bar) + expect(baz).to eq(bar) + end + end + RUBY + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 28f5e17..f3d0866 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -2,6 +2,7 @@ require 'rubocop-petal' require 'rubocop/rspec/support' +require 'rubocop/rspec/shared_contexts/default_rspec_language_config_context' RSpec.configure do |config| config.include RuboCop::RSpec::ExpectOffense @@ -13,4 +14,10 @@ config.order = :random Kernel.srand config.seed + + config.define_derived_metadata(file_path: %r{/spec/rubocop/cop/rspec/}) do |metadata| + metadata[:type] = :rspec_cops + end + + config.include_context 'with default RSpec/Language config', type: :rspec_cops end