class RuboCop::Cop::RSpec::Yield

This cop checks for calling a block within a stub.

@example

# bad
allow(foo).to receive(:bar) { |&block| block.call(1) }

# good
expect(foo).to be(:bar).and_yield(1)

Constants

MSG

Public Instance Methods

on_block(node) click to toggle source
# File lib/rubocop/cop/rspec/yield.rb, line 29
def on_block(node)
  return unless method_on_stub?(node.send_node)

  block_arg(node.arguments) do |block|
    if calling_block?(node.body, block)
      range = block_range(node)

      add_offense(range) do |corrector|
        autocorrect(corrector, node, range)
      end
    end
  end
end

Private Instance Methods

autocorrect(corrector, node, range) click to toggle source
# File lib/rubocop/cop/rspec/yield.rb, line 45
def autocorrect(corrector, node, range)
  corrector.replace(
    range_with_surrounding_space(range: range, side: :left),
    generate_replacement(node.body)
  )
end
block_range(node) click to toggle source
# File lib/rubocop/cop/rspec/yield.rb, line 60
def block_range(node)
  node.loc.begin.with(end_pos: node.loc.end.end_pos)
end
calling_block?(node, block) click to toggle source
# File lib/rubocop/cop/rspec/yield.rb, line 52
def calling_block?(node, block)
  if node.begin_type?
    node.each_child_node.all? { |child| block_call?(child, block) }
  else
    block_call?(node, block)
  end
end
convert_block_to_yield(node) click to toggle source
# File lib/rubocop/cop/rspec/yield.rb, line 72
def convert_block_to_yield(node)
  args = node.arguments
  replacement = '.and_yield'
  replacement += "(#{args.map(&:source).join(', ')})" if args.any?
  replacement
end
generate_replacement(node) click to toggle source
# File lib/rubocop/cop/rspec/yield.rb, line 64
def generate_replacement(node)
  if node.begin_type?
    node.children.map { |child| convert_block_to_yield(child) }.join
  else
    convert_block_to_yield(node)
  end
end