diff --git a/CHANGELOG.md b/CHANGELOG.md index 63b843d20..4e88b3368 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Support asserts with messages in `Rspec/BeEmpty`. ([@G-Rath]) - Add support for `assert_empty`, `assert_not_empty` and `refute_empty` to `RSpec/Rails/MinitestAssertions`. ([@ydah]) - Support correcting some `*_predicate` assertions in `RSpec/Rails/MinitestAssertions`. ([@G-Rath]) +- Support correcting `*_in_delta` assertions in `RSpec/Rails/MinitestAssertions`. ([@G-Rath]) - Support correcting `*_match` assertions in `RSpec/Rails/MinitestAssertions`. ([@G-Rath]) - Support correcting `*_instance_of` assertions in `RSpec/Rails/MinitestAssertions`. ([@G-Rath]) - Support correcting `*_includes` assertions in `RSpec/Rails/MinitestAssertions`. ([@G-Rath]) diff --git a/lib/rubocop/cop/rspec/rails/minitest_assertions.rb b/lib/rubocop/cop/rspec/rails/minitest_assertions.rb index 2b0dcf07d..e4d533b4a 100644 --- a/lib/rubocop/cop/rspec/rails/minitest_assertions.rb +++ b/lib/rubocop/cop/rspec/rails/minitest_assertions.rb @@ -127,6 +127,39 @@ def assertion end end + # :nodoc: + class InDeltaAssertion < BasicAssertion + MATCHERS = %i[ + assert_in_delta + assert_not_in_delta + refute_in_delta + ].freeze + + NODE_MATCHER_PATTERN = <<~PATTERN + (send nil? {:assert_in_delta :assert_not_in_delta :refute_in_delta} $_ $_ $!{sym str}? $_?) + PATTERN + + def self.match(expected, actual, delta, failure_message) + return nil if delta.empty? && !failure_message.empty? + + new(expected, actual, delta.first, failure_message.first) + end + + def initialize(expected, actual, delta, fail_message) + super(expected, actual, fail_message) + + @delta = delta&.source || '0.001' + end + + def negated?(node) + !node.method?(:assert_in_delta) + end + + def assertion + "be_within(#{@delta}).of(#{@expected})" + end + end + # :nodoc: class PredicateAssertion < BasicAssertion MATCHERS = %i[ diff --git a/spec/rubocop/cop/rspec/rails/minitest_assertions_spec.rb b/spec/rubocop/cop/rspec/rails/minitest_assertions_spec.rb index 0fdbe8af5..ac427b063 100644 --- a/spec/rubocop/cop/rspec/rails/minitest_assertions_spec.rb +++ b/spec/rubocop/cop/rspec/rails/minitest_assertions_spec.rb @@ -271,6 +271,127 @@ end end + context 'with in_delta assertions' do + it 'registers an offense when using `assert_in_delta`' do + expect_offense(<<~RUBY) + assert_in_delta(a, b) + ^^^^^^^^^^^^^^^^^^^^^ Use `expect(b).to be_within(0.001).of(a)`. + RUBY + + expect_correction(<<~RUBY) + expect(b).to be_within(0.001).of(a) + RUBY + end + + it 'registers an offense when using `assert_in_delta` with ' \ + 'no parentheses' do + expect_offense(<<~RUBY) + assert_in_delta a, b + ^^^^^^^^^^^^^^^^^^^^ Use `expect(b).to be_within(0.001).of(a)`. + RUBY + + expect_correction(<<~RUBY) + expect(b).to be_within(0.001).of(a) + RUBY + end + + it 'registers an offense when using `assert_in_delta` with ' \ + 'a custom delta' do + expect_offense(<<~RUBY) + assert_in_delta a, b, 1 + ^^^^^^^^^^^^^^^^^^^^^^^ Use `expect(b).to be_within(1).of(a)`. + RUBY + + expect_correction(<<~RUBY) + expect(b).to be_within(1).of(a) + RUBY + end + + it 'registers an offense when using `assert_in_delta` with ' \ + 'a custom delta from a variable' do + expect_offense(<<~RUBY) + delta = 1 + + assert_in_delta a, b, delta + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `expect(b).to be_within(delta).of(a)`. + RUBY + + expect_correction(<<~RUBY) + delta = 1 + + expect(b).to be_within(delta).of(a) + RUBY + end + + it 'registers an offense when using `assert_in_delta` with ' \ + 'a custom delta and a failure message' do + expect_offense(<<~RUBY) + assert_in_delta a, b, 1, "must be within delta" + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `expect(b).to(be_within(1).of(a), "must be within delta")`. + RUBY + + expect_correction(<<~RUBY) + expect(b).to(be_within(1).of(a), "must be within delta") + RUBY + end + + it 'registers an offense when using `assert_in_delta` with ' \ + 'multi-line arguments' do + expect_offense(<<~RUBY) + assert_in_delta(a, + ^^^^^^^^^^^^^^^^^^ Use `expect(b).to be_within(1).of(a)`. + b, + 1) + RUBY + + expect_correction(<<~RUBY) + expect(b).to be_within(1).of(a) + RUBY + end + + it 'registers an offense when using `assert_not_in_delta`' do + expect_offense(<<~RUBY) + assert_not_in_delta a, b + ^^^^^^^^^^^^^^^^^^^^^^^^ Use `expect(b).not_to be_within(0.001).of(a)`. + RUBY + + expect_correction(<<~RUBY) + expect(b).not_to be_within(0.001).of(a) + RUBY + end + + it 'registers an offense when using `refute_in_delta`' do + expect_offense(<<~RUBY) + refute_in_delta a, b + ^^^^^^^^^^^^^^^^^^^^ Use `expect(b).not_to be_within(0.001).of(a)`. + RUBY + + expect_correction(<<~RUBY) + expect(b).not_to be_within(0.001).of(a) + RUBY + end + + it 'does not register an offense when ' \ + 'using `expect(b).to be_within(1).of(a)`' do + expect_no_offenses(<<~RUBY) + expect(b).to be_within(1).of(a) + RUBY + end + + it 'does not register an offense when ' \ + 'using `expect(b).not_to be_within(1).of(a)`' do + expect_no_offenses(<<~RUBY) + expect(b).not_to be_within(1).of(a) + RUBY + end + + it 'does not register an offense when the delta is missing' do + expect_no_offenses(<<~RUBY) + assert_in_delta a, b, "whoops, we forgot about the actual delta!" + RUBY + end + end + context 'with match assertions' do it 'registers an offense when using `assert_match`' do expect_offense(<<~RUBY)