class RuboCop::Cop::RSpec::DescribedClass

Checks that tests use `described_class`.

If the first argument of describe is a class, the class is exposed to each example via described_class.

This cop can be configured using the `EnforcedStyle` option

@example `EnforcedStyle: described_class`

# bad
describe MyClass do
  subject { MyClass.do_something }
end

# good
describe MyClass do
  subject { described_class.do_something }
end

@example `EnforcedStyle: explicit`

# bad
describe MyClass do
  subject { described_class.do_something }
end

# good
describe MyClass do
  subject { MyClass.do_something }
end

Constants

DESCRIBED_CLASS
MSG

Public Instance Methods

autocorrect(node) click to toggle source
# File lib/rubocop/cop/rspec/described_class.rb, line 67
def autocorrect(node)
  replacement = if style == :described_class
                  DESCRIBED_CLASS
                else
                  @described_class.const_name
                end
  lambda do |corrector|
    corrector.replace(node.loc.expression, replacement)
  end
end
on_block(node) click to toggle source
# File lib/rubocop/cop/rspec/described_class.rb, line 50
def on_block(node)
  describe, described_class, body = described_constant(node)
  return unless top_level_describe?(describe)

  # in case we explicit style is used, this cop needs to remember what's
  # being described, so to replace described_class with the constant
  @described_class = described_class

  find_usage(body) do |match|
    add_offense(
      match,
      location: :expression,
      message: message(match.const_name)
    )
  end
end

Private Instance Methods

find_usage(node) { |node| ... } click to toggle source
# File lib/rubocop/cop/rspec/described_class.rb, line 80
def find_usage(node, &block)
  yield(node) if offensive?(node)

  return unless node.is_a?(Parser::AST::Node)
  return if scope_change?(node) || node.const_type?

  node.children.each do |child|
    find_usage(child, &block)
  end
end
message(offense) click to toggle source
# File lib/rubocop/cop/rspec/described_class.rb, line 91
def message(offense)
  if style == :described_class
    format(MSG, DESCRIBED_CLASS, offense)
  else
    format(MSG, @described_class.const_name, DESCRIBED_CLASS)
  end
end
offensive?(node) click to toggle source
# File lib/rubocop/cop/rspec/described_class.rb, line 113
def offensive?(node)
  if style == :described_class
    node.eql?(@described_class)
  else
    _receiver, method_name, *_args = *node
    method_name == :described_class
  end
end
scope_change?(node) click to toggle source
# File lib/rubocop/cop/rspec/described_class.rb, line 99
def scope_change?(node)
  scope_changing_syntax?(node)          ||
    common_instance_exec_closure?(node) ||
    skippable_block?(node)
end
skip_blocks?() click to toggle source
# File lib/rubocop/cop/rspec/described_class.rb, line 109
def skip_blocks?
  cop_config['SkipBlocks'].equal?(true)
end
skippable_block?(node) click to toggle source
# File lib/rubocop/cop/rspec/described_class.rb, line 105
def skippable_block?(node)
  node.block_type? && !rspec_block?(node) && skip_blocks?
end