class RuboCop::Cop::RSpec::LeadingSubject

Enforce that subject is the first definition in the test.

@example

# bad
  let(:params) { blah }
  subject { described_class.new(params) }

  before { do_something }
  subject { described_class.new(params) }

  it { expect_something }
  subject { described_class.new(params) }
  it { expect_something_else }

# good
  subject { described_class.new(params) }
  let(:params) { blah }

# good
  subject { described_class.new(params) }
  before { do_something }

# good
  subject { described_class.new(params) }
  it { expect_something }
  it { expect_something_else }

Constants

MSG

Public Instance Methods

autocorrect(node) click to toggle source
# File lib/rubocop/cop/rspec/leading_subject.rb, line 59
def autocorrect(node)
  lambda do |corrector|
    first_node = find_first_offending_node(node)
    first_node_position = first_node.loc.expression
    indent = "\n" + ' ' * first_node.loc.column
    corrector.insert_before(first_node_position, node.source + indent)
    corrector.remove(node_range(node))
  end
end
check_previous_nodes(node) click to toggle source
# File lib/rubocop/cop/rspec/leading_subject.rb, line 45
def check_previous_nodes(node)
  node.parent.each_child_node do |sibling|
    if offending?(sibling)
      add_offense(
        node,
        location: :expression,
        message: format(MSG, offending: sibling.method_name)
      )
    end

    break if offending?(sibling) || sibling.equal?(node)
  end
end
on_block(node) click to toggle source
# File lib/rubocop/cop/rspec/leading_subject.rb, line 39
def on_block(node)
  return unless subject?(node) && !in_spec_block?(node)

  check_previous_nodes(node)
end

Private Instance Methods

find_first_offending_node(node) click to toggle source
# File lib/rubocop/cop/rspec/leading_subject.rb, line 75
def find_first_offending_node(node)
  node.parent.children.find { |sibling| offending?(sibling) }
end
in_spec_block?(node) click to toggle source
# File lib/rubocop/cop/rspec/leading_subject.rb, line 83
def in_spec_block?(node)
  node.each_ancestor(:block).any? do |ancestor|
    example?(ancestor)
  end
end
node_range(node) click to toggle source
# File lib/rubocop/cop/rspec/leading_subject.rb, line 79
def node_range(node)
  range_by_whole_lines(node.source_range, include_final_newline: true)
end
offending?(node) click to toggle source
# File lib/rubocop/cop/rspec/leading_subject.rb, line 71
def offending?(node)
  let?(node) || hook?(node) || example?(node)
end