Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Master (Unreleased)

- Fix a false negative for constants with constant base in `RSpec/DescribedClass`. ([@lovro-bikic])

## 3.8.0 (2025-11-12)

- Add new cop `RSpec/LeakyLocalVariable`. ([@lovro-bikic])
Expand Down
5 changes: 5 additions & 0 deletions docs/modules/ROOT/pages/cops_rspec.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1031,6 +1031,11 @@ end
describe MyClass do
subject { MyClass::CONSTANT }
end

# good
describe MyClass do
subject { described_class::CONSTANT }
end
----

[#_enforcedstyle_-explicit_-rspecdescribedclass]
Expand Down
11 changes: 9 additions & 2 deletions lib/rubocop/cop/rspec/described_class.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ module RSpec
# subject { MyClass::CONSTANT }
# end
#
# # good
# describe MyClass do
# subject { described_class::CONSTANT }
# end
Comment on lines +53 to +56
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this because I think a "good" example was missing here

#
# @example `EnforcedStyle: explicit`
# # bad
# describe MyClass do
Expand Down Expand Up @@ -205,13 +210,15 @@ def full_const_name(node)
# @return [Array<Symbol>]
# @example
# # nil represents base constant
# collapse_namespace([], [:C]) # => [:C]
# collapse_namespace([], [:C]) # => [nil, :C]
# collapse_namespace([:A, :B], [:C]) # => [:A, :B, :C]
# collapse_namespace([:A, :B], [:B, :C]) # => [:A, :B, :C]
# collapse_namespace([:A, :B], [nil, :C]) # => [nil, :C]
# collapse_namespace([:A, :B], [nil, :B, :C]) # => [nil, :B, :C]
def collapse_namespace(namespace, const)
return const if namespace.empty? || const.first.nil?
return const if const.nil?

namespace = [nil] if namespace.empty?

start = [0, (namespace.length - const.length)].max
max = namespace.length
Expand Down
60 changes: 60 additions & 0 deletions spec/rubocop/cop/rspec/described_class_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,56 @@
RUBY
end

it 'flags when references use constant base and described class does not' do
expect_offense(<<~RUBY)
describe MyClass do
include ::MyClass
^^^^^^^^^ Use `described_class` instead of `MyClass`.

subject { ::MyClass.do_something }
^^^^^^^^^ Use `described_class` instead of `MyClass`.

before { ::MyClass.do_something }
^^^^^^^^^ Use `described_class` instead of `MyClass`.
end
RUBY

expect_correction(<<~RUBY)
describe MyClass do
include described_class

subject { described_class.do_something }

before { described_class.do_something }
end
RUBY
end

it 'flags when described class uses constant base and references do not' do
expect_offense(<<~RUBY)
describe ::MyClass do
include MyClass
^^^^^^^ Use `described_class` instead of `MyClass`.

subject { MyClass.do_something }
^^^^^^^ Use `described_class` instead of `MyClass`.

before { MyClass.do_something }
^^^^^^^ Use `described_class` instead of `MyClass`.
end
RUBY

expect_correction(<<~RUBY)
describe ::MyClass do
include described_class

subject { described_class.do_something }

before { described_class.do_something }
end
RUBY
end

it 'allows accessing constants from variables when in a nested namespace' do
expect_no_offenses(<<~RUBY)
module Foo
Expand Down Expand Up @@ -438,6 +488,16 @@ module SomeGem
end
RUBY
end

it 'ignores parenthesized namespaces within modules - begin_types' do
expect_no_offenses(<<~RUBY)
module Foo
describe MyClass do
subject { (MyNamespace)::MyClass }
end
end
RUBY
end
Comment on lines +492 to +500
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is currently failing on master

end

context 'when EnforcedStyle is :explicit' do
Expand Down