From 874ad163a4d56e170bf8c6f548ac9e7bef0603e4 Mon Sep 17 00:00:00 2001 From: Douglas Eichelberger Date: Sun, 5 Jan 2020 17:50:13 -0800 Subject: [PATCH] Add autocorrect for RSpec/ExpectActual --- CHANGELOG.md | 2 + lib/rubocop/cop/rspec/expect_actual.rb | 16 ++++ manual/cops_rspec.md | 2 +- spec/rubocop/cop/rspec/expect_actual_spec.rb | 85 ++++++++++++++++++++ 4 files changed, 104 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c29237243..c1d0f1395 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Fix `RSpec/InstanceVariable` detection inside custom matchers. ([@pirj][]) * Fix `RSpec/ScatteredSetup` to distinguish hooks with different metadata. ([@pirj][]) +* Add autocorrect support for `RSpec/ExpectActual` cop. ([@dduugg][]) ## 1.37.1 (2019-12-16) @@ -475,3 +476,4 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features. [@mkrawc]: https://github.com/mkrawc [@jfragoulis]: https://github.com/jfragoulis [@ybiquitous]: https://github.com/ybiquitous +[@dduugg]: https://github.com/dduugg diff --git a/lib/rubocop/cop/rspec/expect_actual.rb b/lib/rubocop/cop/rspec/expect_actual.rb index c945499fd..8491ff756 100644 --- a/lib/rubocop/cop/rspec/expect_actual.rb +++ b/lib/rubocop/cop/rspec/expect_actual.rb @@ -49,6 +49,17 @@ def on_send(node) end end + def autocorrect(node) + lambda do |corrector| + expectation = node.parent.parent + rhs = expectation.children.last + return unless rhs.is_a?(RuboCop::AST::MethodDispatchNode) + return if rhs.method_name != :eq + + swap_order(corrector, node, rhs.children.last) + end + end + private # This is not implement using a NodePattern because it seems @@ -65,6 +76,11 @@ def complex_literal?(node) COMPLEX_LITERALS.include?(node.type) && node.each_child_node.all?(&method(:literal?)) end + + def swap_order(corrector, lhs_arg, rhs_arg) + corrector.replace(lhs_arg.source_range, rhs_arg.source) + corrector.replace(rhs_arg.source_range, lhs_arg.source) + end end end end diff --git a/manual/cops_rspec.md b/manual/cops_rspec.md index 6d586c324..1aec29405 100644 --- a/manual/cops_rspec.md +++ b/manual/cops_rspec.md @@ -977,7 +977,7 @@ IgnoredWords | `[]` | Array Enabled by default | Supports autocorrection --- | --- -Enabled | No +Enabled | Yes Checks for `expect(...)` calls containing literal values. diff --git a/spec/rubocop/cop/rspec/expect_actual_spec.rb b/spec/rubocop/cop/rspec/expect_actual_spec.rb index 503fe8fff..91ac8bbe7 100644 --- a/spec/rubocop/cop/rspec/expect_actual_spec.rb +++ b/spec/rubocop/cop/rspec/expect_actual_spec.rb @@ -18,6 +18,17 @@ end end RUBY + + expect_correction(<<-RUBY) + describe Foo do + it 'uses expect incorrectly' do + expect(bar).to eq(123) + expect(bar).to eq(12.3) + expect(bar).to eq(1i) + expect(bar).to eq(1r) + end + end + RUBY end it 'flags boolean literal values within expect(...)' do @@ -31,6 +42,15 @@ end end RUBY + + expect_correction(<<-RUBY) + describe Foo do + it 'uses expect incorrectly' do + expect(bar).to eq(true) + expect(bar).to eq(false) + end + end + RUBY end it 'flags string and symbol literal values within expect(...)' do @@ -44,6 +64,15 @@ end end RUBY + + expect_correction(<<-RUBY) + describe Foo do + it 'uses expect incorrectly' do + expect(bar).to eq("foo") + expect(bar).to eq(:foo) + end + end + RUBY end it 'flags literal nil value within expect(...)' do @@ -55,6 +84,14 @@ end end RUBY + + expect_correction(<<-RUBY) + describe Foo do + it 'uses expect incorrectly' do + expect(bar).to eq(nil) + end + end + RUBY end it 'does not flag dynamic values within expect(...)' do @@ -80,6 +117,15 @@ end end RUBY + + expect_correction(<<-RUBY) + describe Foo do + it 'uses expect incorrectly' do + expect(bar).to eq([123]) + expect(bar).to eq([[123]]) + end + end + RUBY end it 'flags hashes containing only literal values within expect(...)' do @@ -93,6 +139,15 @@ end end RUBY + + expect_correction(<<-RUBY) + describe Foo do + it 'uses expect incorrectly' do + expect(bar).to eq(foo: 1, bar: 2) + expect(bar).to eq(foo: 1, bar: [{}]) + end + end + RUBY end it 'flags ranges containing only literal values within expect(...)' do @@ -106,6 +161,15 @@ end end RUBY + + expect_correction(<<-RUBY) + describe Foo do + it 'uses expect incorrectly' do + expect(bar).to eq(1..2) + expect(bar).to eq(1...2) + end + end + RUBY end it 'flags regexps containing only literal values within expect(...)' do @@ -117,6 +181,14 @@ end end RUBY + + expect_correction(<<-RUBY) + describe Foo do + it 'uses expect incorrectly' do + expect(bar).to eq(/foo|bar/) + end + end + RUBY end it 'does not flag complex values with dynamic parts within expect(...)' do @@ -135,6 +207,19 @@ RUBY end + it 'flags but does not autocorrect violations without eq' do + expect_offense(<<-RUBY) + describe Foo do + it 'uses expect incorrectly' do + expect([1,2,3]).to include(a) + ^^^^^^^ Provide the actual you are testing to `expect(...)`. + end + end + RUBY + + expect_no_corrections + end + context 'when inspecting rspec-rails routing specs' do let(:cop_config) { {} }