Class: RuboCop::Cop::RSpec::ExpectActual

Inherits:
Base
  • Object
show all
Extended by:
AutoCorrector
Defined in:
lib/rubocop/cop/rspec/expect_actual.rb

Overview

Checks for ‘expect(…)` calls containing literal values.

Autocorrection is performed when the expected is not a literal.

Examples:

# bad
expect(5).to eq(price)
expect(/foo/).to eq(pattern)
expect("John").to eq(name)

# good
expect(price).to eq(5)
expect(pattern).to eq(/foo/)
expect(name).to eq("John")

# bad (not supported autocorrection)
expect(false).to eq(true)

Constant Summary collapse

MSG =
'Provide the actual value you are testing to `expect(...)`.'
RESTRICT_ON_SEND =
Runners.all
SIMPLE_LITERALS =
%i[
  true
  false
  nil
  int
  float
  str
  sym
  complex
  rational
  regopt
].freeze
COMPLEX_LITERALS =
%i[
  array
  hash
  pair
  irange
  erange
  regexp
].freeze
SKIPPED_MATCHERS =
%i[route_to be_routable].freeze
CORRECTABLE_MATCHERS =
%i[eq eql equal be].freeze

Instance Method Summary collapse

Methods inherited from Base

inherited, #on_new_investigation

Methods included from RSpec::Language::NodePattern

#block_or_numblock_pattern, #block_pattern, #numblock_pattern, #send_pattern

Methods included from RSpec::Language

#example?, #example_group?, #example_group_with_body?, #explicit_rspec?, #hook?, #include?, #let?, #rspec?, #shared_group?, #spec_group?, #subject?

Instance Method Details

#expect_literal(node) ⇒ Object



57
58
59
60
61
62
63
64
65
66
# File 'lib/rubocop/cop/rspec/expect_actual.rb', line 57

def_node_matcher :expect_literal, <<~PATTERN
  (send
    (send nil? :expect $#literal?)
    #Runners.all
    ${
      (send (send nil? $:be) :== $_)
      (send nil? $_ $_ ...)
    }
  )
PATTERN

#on_send(node) ⇒ Object

rubocop:disable Metrics/MethodLength



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/rubocop/cop/rspec/expect_actual.rb', line 68

def on_send(node) # rubocop:disable Metrics/MethodLength
  expect_literal(node) do |actual, send_node, matcher, expected|
    next if SKIPPED_MATCHERS.include?(matcher)

    add_offense(actual.source_range) do |corrector|
      next unless CORRECTABLE_MATCHERS.include?(matcher)
      next if literal?(expected)

      corrector.replace(actual, expected.source)
      if matcher == :be
        corrector.replace(expected, actual.source)
      else
        corrector.replace(send_node, "#{matcher}(#{actual.source})")
      end
    end
  end
end