lib/rubocop/cop/rspec/described_class.rb in rubocop-rspec-1.35.0 vs lib/rubocop/cop/rspec/described_class.rb in rubocop-rspec-1.36.0

- old
+ new

@@ -6,11 +6,12 @@ # 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 + # This cop can be configured using the `EnforcedStyle` and `SkipBlocks` + # options. # # @example `EnforcedStyle: described_class` # # bad # describe MyClass do # subject { MyClass.do_something } @@ -30,10 +31,31 @@ # # good # describe MyClass do # subject { MyClass.do_something } # end # + # There's a known caveat with rspec-rails's `controller` helper that + # runs its block in a different context, and `described_class` is not + # available to it. `SkipBlocks` option excludes detection in all + # non-RSpec related blocks. + # + # To narrow down this setting to only a specific directory, it is + # possible to use an overriding configuration file local to that + # directory. + # + # @example `SkipBlocks: true` + # # spec/controllers/.rubocop.yml + # # RSpec/DescribedClass: + # # SkipBlocks: true + # + # # acceptable + # describe MyConcern do + # controller(ApplicationController) do + # include MyConcern + # end + # end + # class DescribedClass < Cop include ConfigurableEnforcedStyle DESCRIBED_CLASS = 'described_class' MSG = 'Use `%<replacement>s` instead of `%<src>s`.' @@ -49,10 +71,14 @@ def_node_matcher :described_constant, <<-PATTERN (block (send _ :describe $(const ...) ...) (args) $_) PATTERN + def_node_search :contains_described_class?, <<-PATTERN + (send nil? :described_class) + PATTERN + def on_block(node) # In case the explicit style is used, we need to remember what's # being described. @described_class, body = described_constant(node) @@ -117,9 +143,11 @@ end end def offensive_described_class?(node) return unless node.const_type? + # E.g. `described_class::CONSTANT` + return if contains_described_class?(node) nearest_described_class, = node.each_ancestor(:block) .map { |ancestor| described_constant(ancestor) }.find(&:itself) return if nearest_described_class.equal?(node)