Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add :restore_registry context and stub_cop_class helper class #8578

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -13,6 +13,7 @@
* [#8472](https://github.com/rubocop-hq/rubocop/issues/8472): Add new `Lint/UselessMethodDefinition` cop. ([@fatkodima][])
* [#8531](https://github.com/rubocop-hq/rubocop/issues/8531): Add new `Lint/EmptyFile` cop. ([@fatkodima][])
* Add new `Lint/TrailingCommaInAttributeDeclaration` cop. ([@drenmi][])
* [#8578](https://github.com/rubocop-hq/rubocop/pull/8578): Add `:restore_registry` context and `stub_cop_class` helper class. ([@marcandre][])

### Bug fixes

Expand Down
12 changes: 12 additions & 0 deletions lib/rubocop/rspec/shared_contexts.rb
Expand Up @@ -40,6 +40,18 @@
end
end

RSpec.shared_context 'maintain registry', :restore_registry do
around(:each) do |example|
RuboCop::Cop::Registry.with_temporary_global { example.run }
end

def stub_cop_class(name, inherit: RuboCop::Cop::Base, &block)
klass = Class.new(inherit, &block)
stub_const(name, klass)
klass
end
end

# This context assumes nothing and defines `cop`, among others.
RSpec.shared_context 'config', :config do # rubocop:disable Metrics/BlockLength
### Meant to be overridden at will
Expand Down
6 changes: 1 addition & 5 deletions spec/rubocop/config_loader_spec.rb
Expand Up @@ -621,11 +621,7 @@ def enabled?(cop)
include_examples 'resolves enabled/disabled for all cops', true, false
end

context 'when a third party require defines a new gem' do
around do |example|
RuboCop::Cop::Registry.with_temporary_global { example.run }
end

context 'when a third party require defines a new gem', :restore_registry do
context 'when the gem is not loaded' do
before do
create_file('.rubocop.yml', <<~YAML)
Expand Down
10 changes: 2 additions & 8 deletions spec/rubocop/config_spec.rb
Expand Up @@ -845,22 +845,16 @@ def cop_enabled(cop_class)
end
end

describe '#for_department' do
describe '#for_department', :restore_registry do
let(:hash) do
{
'Foo' => { 'Bar' => 42, 'Baz' => true },
'Foo/Foo' => { 'Bar' => 42, 'Qux' => true }
}
end

around do |test|
RuboCop::Cop::Registry.with_temporary_global do
test.run
end
end

before do
stub_const('RuboCop::Foo::Foo', Class.new(RuboCop::Cop::Base))
stub_cop_class('RuboCop::Foo::Foo')
end

it "always returns the department's config" do
Expand Down
5 changes: 2 additions & 3 deletions spec/rubocop/cop/cop_spec.rb
Expand Up @@ -166,12 +166,11 @@
end
end

context 'when cop supports autocorrection' do
context 'when cop supports autocorrection', :restore_registry do
let(:cop_class) do
stub_cop = Class.new(RuboCop::Cop::Cop) do
stub_cop_class('RuboCop::Cop::Test::StubCop', inherit: described_class) do
def autocorrect(node); end
end
stub_const('RuboCop::Cop::Test::StubCop', stub_cop)
end

context 'when offense was corrected' do
Expand Down
14 changes: 2 additions & 12 deletions spec/rubocop/cop/mixin/enforce_superclass_spec.rb
@@ -1,15 +1,14 @@
# frozen_string_literal: true

# rubocop:disable RSpec/FilePath
RSpec.describe RuboCop::Cop::EnforceSuperclass do
RSpec.describe RuboCop::Cop::EnforceSuperclass, :restore_registry do
subject(:cop) { cop_class.new }

let(:cop_class) { RuboCop::Cop::RSpec::ApplicationRecord }
let(:msg) { 'Models should subclass `ApplicationRecord`' }

before do
stub_const('RuboCop::Cop::RSpec::ApplicationRecord',
Class.new(RuboCop::Cop::Cop))
stub_cop_class('RuboCop::Cop::RSpec::ApplicationRecord')
stub_const("#{cop_class}::MSG",
'Models should subclass `ApplicationRecord`')
stub_const("#{cop_class}::SUPERCLASS", 'ApplicationRecord')
Expand All @@ -18,15 +17,6 @@
RuboCop::Cop::RSpec::ApplicationRecord.include(described_class)
end

# `RuboCop::Cop::Cop` mutates its `registry` when inherited from.
# This can introduce nondeterministic failures in other parts of the
# specs if this mutation occurs before code that depends on this global cop
# store. The workaround is to replace the global cop store with a temporary
# store during these tests
around do |test|
RuboCop::Cop::Registry.with_temporary_global { test.run }
end

shared_examples 'no offense' do |code|
it "registers no offenses for `#{code}`" do
expect_no_offenses(code)
Expand Down
25 changes: 12 additions & 13 deletions spec/rubocop/cop/team_spec.rb
Expand Up @@ -211,13 +211,13 @@ def a
end
end

context 'when done twice' do
context 'when done twice', :restore_registry do
let(:persisting_cop_class) do
klass = Class.new(RuboCop::Cop::Base)
klass.exclude_from_registry
klass.define_singleton_method(:support_multiple_source?) { true }
stub_const('Test::Persisting', klass)
klass
stub_cop_class('Test::Persisting') do
def self.support_multiple_source?
true
end
end
end
let(:cop_classes) { [persisting_cop_class, RuboCop::Cop::Base] }

Expand Down Expand Up @@ -358,14 +358,13 @@ def a
end
end

context 'when cop with different checksum joins' do
context 'when cop with different checksum joins', :restore_registry do
before do
stub_const('Test::CopWithExternalDeps',
Class.new(::RuboCop::Cop::Cop) do
def external_dependency_checksum
'something other than nil'
end
end)
stub_cop_class('Test::CopWithExternalDeps') do
def external_dependency_checksum
'something other than nil'
end
end
end

let(:new_cop_classes) do
Expand Down
11 changes: 4 additions & 7 deletions spec/rubocop/formatter/disabled_config_formatter_spec.rb
Expand Up @@ -249,14 +249,11 @@ def io.path
end
end

context 'with auto-correct supported cop' do
context 'with auto-correct supported cop', :restore_registry do
before do
stub_const('Test::Cop3',
Class.new(::RuboCop::Cop::Cop) do
def autocorrect
# Dummy method to respond to #support_autocorrect?
end
end)
stub_cop_class('Test::Cop3') do
extend RuboCop::Cop::AutoCorrector
end

formatter.started(['test_auto_correct.rb'])
formatter.file_started('test_auto_correct.rb', {})
Expand Down