class RuboCop::Cop::RSpec::ReceiveCounts

Check for `once` and `twice` receive counts matchers usage.

@example

# bad
expect(foo).to receive(:bar).exactly(1).times
expect(foo).to receive(:bar).exactly(2).times
expect(foo).to receive(:bar).at_least(1).times
expect(foo).to receive(:bar).at_least(2).times
expect(foo).to receive(:bar).at_most(1).times
expect(foo).to receive(:bar).at_most(2).times

# good
expect(foo).to receive(:bar).once
expect(foo).to receive(:bar).twice
expect(foo).to receive(:bar).at_least(:once)
expect(foo).to receive(:bar).at_least(:twice)
expect(foo).to receive(:bar).at_most(:once)
expect(foo).to receive(:bar).at_most(:twice).times

Constants

MSG
RESTRICT_ON_SEND

Public Instance Methods

on_send(node) click to toggle source
# File lib/rubocop/cop/rspec/receive_counts.rb, line 41
def on_send(node)
  receive_counts(node) do |offending_node|
    return unless stub?(offending_node.receiver)

    offending_range = range(node, offending_node)

    msg = message_for(offending_node, offending_range.source)
    add_offense(offending_range, message: msg) do |corrector|
      autocorrect(corrector, offending_node, offending_range)
    end
  end
end

Private Instance Methods

autocorrect(corrector, node, range) click to toggle source
# File lib/rubocop/cop/rspec/receive_counts.rb, line 56
def autocorrect(corrector, node, range)
  replacement = matcher_for(
    node.method_name,
    node.first_argument.source.to_i
  )

  corrector.replace(range, replacement)
end
matcher_for(method, count) click to toggle source
# File lib/rubocop/cop/rspec/receive_counts.rb, line 73
def matcher_for(method, count)
  matcher = count == 1 ? 'once' : 'twice'
  if method == :exactly
    ".#{matcher}"
  else
    ".#{method}(:#{matcher})"
  end
end
message_for(node, source) click to toggle source
# File lib/rubocop/cop/rspec/receive_counts.rb, line 65
def message_for(node, source)
  alternative = matcher_for(
    node.method_name,
    node.first_argument.source.to_i
  )
  format(MSG, alternative: alternative, original: source)
end
range(node, offending_node) click to toggle source
# File lib/rubocop/cop/rspec/receive_counts.rb, line 82
def range(node, offending_node)
  offending_node.loc.dot.with(
    end_pos: node.loc.expression.end_pos
  )
end