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

Improved shared context. Refactor & simplify some specs. #7970

Merged
merged 2 commits into from May 21, 2020
Merged
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
70 changes: 55 additions & 15 deletions lib/rubocop/rspec/shared_contexts.rb
Expand Up @@ -38,26 +38,66 @@
end
end

# `cop_config` must be declared with #let.
RSpec.shared_context 'config', :config do
let(:config) do
# Module#<
raise '`config` must be used in `describe SomeCopClass do .. end`' unless described_class < RuboCop::Cop::Cop

hash = { 'AllCops' => { 'TargetRubyVersion' => ruby_version } }
hash['AllCops']['TargetRailsVersion'] = rails_version if rails_version
if respond_to?(:cop_config)
cop_name = described_class.cop_name
hash[cop_name] = RuboCop::ConfigLoader
.default_configuration[cop_name]
.merge('Enabled' => true) # in case it is 'pending'
.merge(cop_config)
# This context assumes nothing and defines `cop`, among others.
RSpec.shared_context 'config', :config do # rubocop:disable Metrics/BlockLength
### Meant to be overriden at will

let(:source) { 'code = {some: :ruby}' }

let(:cop_class) do
if described_class.is_a?(Class) && described_class < RuboCop::Cop::Cop
described_class
else
RuboCop::Cop::Cop
end
end

let(:cop_config) { {} }

let(:other_cops) { {} }

let(:cop_options) { {} }

### Utilities

def source_range(range, buffer: source_buffer)
Parser::Source::Range.new(buffer, range.begin,
range.exclude_end? ? range.end : range.end + 1)
end

hash = other_cops.merge hash if respond_to?(:other_cops)
### Usefull intermediary steps (less likely to be overriden)

let(:processed_source) { parse_source(source, 'test') }

let(:source_buffer) { processed_source.buffer }

let(:all_cops_config) do
rails = { 'TargetRubyVersion' => ruby_version }
rails['TargetRailsVersion'] = rails_version if rails_version
rails
end

let(:cur_cop_config) do
RuboCop::ConfigLoader
.default_configuration.for_cop(cop_class)
.merge({
'Enabled' => true, # in case it is 'pending'
'AutoCorrect' => true # in case defaults set it to false
})
.merge(cop_config)
end

let(:config) do
hash = { 'AllCops' => all_cops_config,
cop_class.cop_name => cur_cop_config }.merge!(other_cops)

RuboCop::Config.new(hash, "#{Dir.pwd}/.rubocop.yml")
end

let(:cop) do
cop_class.new(config, cop_options)
.tap { |cop| cop.processed_source = processed_source }
end
end

RSpec.shared_context 'mock console output' do
Expand Down
4 changes: 2 additions & 2 deletions spec/rubocop/cop/alignment_corrector_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::AlignmentCorrector do
let(:cop) { RuboCop::Cop::Test::AlignmentDirective.new }
RSpec.describe RuboCop::Cop::AlignmentCorrector, :config do
let(:cop_class) { RuboCop::Cop::Test::AlignmentDirective }

describe '#correct' do
context 'simple indentation' do
Expand Down
2 changes: 0 additions & 2 deletions spec/rubocop/cop/bundler/duplicated_gem_spec.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Bundler::DuplicatedGem, :config do
subject(:cop) { described_class.new(config) }

let(:cop_config) { { 'Include' => ['**/Gemfile'] } }

context 'when investigating Ruby files' do
Expand Down
2 changes: 0 additions & 2 deletions spec/rubocop/cop/bundler/gem_comment_spec.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Bundler::GemComment, :config do
subject(:cop) { described_class.new(config) }

let(:cop_config) do
{
'Include' => ['**/Gemfile'],
Expand Down
2 changes: 0 additions & 2 deletions spec/rubocop/cop/bundler/ordered_gems_spec.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Bundler::OrderedGems, :config do
subject(:cop) { described_class.new(config) }

let(:cop_config) do
{
'TreatCommentsAsGroupSeparators' => treat_comments_as_group_separators,
Expand Down
94 changes: 45 additions & 49 deletions spec/rubocop/cop/cop_spec.rb
@@ -1,12 +1,8 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Cop do
subject(:cop) { described_class.new }

RSpec.describe RuboCop::Cop::Cop, :config do
let(:location) do
source_buffer = Parser::Source::Buffer.new('test', 1)
source_buffer.source = "a\n"
Parser::Source::Range.new(source_buffer, 0, 1)
source_range(0...1)
end

it 'initially has 0 offenses' do
Expand Down Expand Up @@ -90,32 +86,41 @@
.to output(/Warning: Invalid severity 'superbad'./).to_stderr
end

it 'will set offense as disabled if ignore_disable_comments is false' do
comment_config = instance_double(RuboCop::CommentConfig,
cop_enabled_at_line?: false)
processed_source = instance_double(RuboCop::ProcessedSource,
comment_config: comment_config)
cop.processed_source = processed_source
cop.instance_variable_set(:@options, ignore_disable_comments: false)
cop.add_offense(nil, location: location, message: 'message')
expect(cop.offenses.first.status).to eq :disabled
end
context 'when disabled by a comment' do
subject(:offense_status) do
cop.add_offense(nil, location: location, message: 'message')
cop.offenses.first.status
end

it 'will not set offense as disabled if ignore_disable_comments is true' do
comment_config = instance_double(RuboCop::CommentConfig,
cop_enabled_at_line?: false)
processed_source = instance_double(RuboCop::ProcessedSource,
comment_config: comment_config)
cop.processed_source = processed_source
cop.instance_variable_set(:@options, ignore_disable_comments: true)
cop.add_offense(nil, location: location, message: 'message')
expect(cop.offenses.first.status).not_to eq :disabled
before do
allow(processed_source.comment_config).to receive(:cop_enabled_at_line?)
.and_return(false)
end

context 'ignore_disable_comments is false' do
let(:cop_options) { { ignore_disable_comments: false } }

it 'will set offense as disabled' do
expect(offense_status).to eq :disabled
end
end

context 'ignore_disable_comments is true' do
let(:cop_options) { { ignore_disable_comments: true } }

it 'will not set offense as disabled' do
expect(offense_status).not_to eq :disabled
end
end
end

it 'registers offense with its name' do
cop = RuboCop::Cop::Style::For.new
cop.add_offense(nil, location: location, message: 'message')
expect(cop.offenses.first.cop_name).to eq('Style/For')
describe 'for a cop with a name' do
let(:cop_class) { RuboCop::Cop::Style::For }

it 'registers offense with its name' do
cop.add_offense(nil, location: location, message: 'message')
expect(cop.offenses.first.cop_name).to eq('Style/For')
end
end

describe 'setting of Offense#corrected attribute' do
Expand Down Expand Up @@ -161,7 +166,7 @@
end

context 'when cop supports autocorrection' do
let(:cop) { RuboCop::Cop::Style::Alias.new }
let(:cop_class) { RuboCop::Cop::Style::Alias }

context 'when offense was corrected' do
before do
Expand Down Expand Up @@ -201,24 +206,22 @@
end

context 'with no submodule' do
subject(:cop) { described_class }

it('has right name') { expect(cop.cop_name).to eq('Cop/Cop') }
it('has right department') { expect(cop.department).to eq(:Cop) }
it('has right name') { expect(cop_class.cop_name).to eq('Cop/Cop') }
it('has right department') { expect(cop_class.department).to eq(:Cop) }
end

context 'with style cops' do
subject(:cop) { RuboCop::Cop::Style::For }
let(:cop_class) { RuboCop::Cop::Style::For }

it('has right name') { expect(cop.cop_name).to eq('Style/For') }
it('has right department') { expect(cop.department).to eq(:Style) }
it('has right name') { expect(cop_class.cop_name).to eq('Style/For') }
it('has right department') { expect(cop_class.department).to eq(:Style) }
end

context 'with lint cops' do
subject(:cop) { RuboCop::Cop::Lint::Loop }
let(:cop_class) { RuboCop::Cop::Lint::Loop }

it('has right name') { expect(cop.cop_name).to eq('Lint/Loop') }
it('has right department') { expect(cop.department).to eq(:Lint) }
it('has right name') { expect(cop_class.cop_name).to eq('Lint/Loop') }
it('has right department') { expect(cop_class.department).to eq(:Lint) }
end

describe 'Registry' do
Expand Down Expand Up @@ -262,8 +265,6 @@

subject { cop.autocorrect? }

let(:config) { RuboCop::Config.new({}) }
let(:cop) { described_class.new(config, options) }
let(:support_autocorrect) { true }
let(:disable_uncorrectable) { false }

Expand All @@ -279,7 +280,7 @@
end

context 'when the option is given' do
let(:options) { { auto_correct: true } }
let(:cop_options) { { auto_correct: true } }

it { is_expected.to be(true) }

Expand All @@ -296,9 +297,7 @@
end

context 'when the cop is set to not autocorrect' do
let(:config) do
RuboCop::Config.new('Cop/Cop' => { 'AutoCorrect' => false })
end
let(:cop_options) { { 'AutoCorrect' => false } }

it { is_expected.to be(false) }
end
Expand All @@ -308,9 +307,6 @@
describe '#safe_autocorrect?' do
subject { cop.safe_autocorrect? }

let(:config) { RuboCop::Config.new('Cop/Cop' => cop_config) }
let(:cop) { described_class.new(config) }

context 'when cop is declared unsafe' do
let(:cop_config) { { 'Safe' => false } }

Expand Down
2 changes: 0 additions & 2 deletions spec/rubocop/cop/gemspec/ordered_dependencies_spec.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Gemspec::OrderedDependencies, :config do
subject(:cop) { described_class.new(config) }

let(:cop_config) do
{
'TreatCommentsAsGroupSeparators' => treat_comments_as_group_separators,
Expand Down
2 changes: 0 additions & 2 deletions spec/rubocop/cop/gemspec/required_ruby_version_spec.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Gemspec::RequiredRubyVersion, :config do
subject(:cop) { described_class.new(config) }

context 'target ruby version > 2.7', :ruby27 do
it 'registers an offense when `required_ruby_version` is lower than ' \
'`TargetRubyVersion`' do
Expand Down
2 changes: 0 additions & 2 deletions spec/rubocop/cop/gemspec/ruby_version_globals_usage_spec.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Gemspec::RubyVersionGlobalsUsage, :config do
subject(:cop) { described_class.new(config) }

it 'registers an offense when using `RUBY_VERSION`' do
expect_offense(<<~RUBY, '/path/to/foo.gemspec')
Gem::Specification.new do |spec|
Expand Down
2 changes: 0 additions & 2 deletions spec/rubocop/cop/layout/assignment_indentation_spec.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Layout::AssignmentIndentation, :config do
subject(:cop) { described_class.new(config) }

let(:config) do
RuboCop::Config.new('Layout/AssignmentIndentation' => {
'IndentationWidth' => cop_indent
Expand Down
2 changes: 0 additions & 2 deletions spec/rubocop/cop/layout/block_alignment_spec.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Layout::BlockAlignment, :config do
subject(:cop) { described_class.new(config) }

let(:cop_config) do
{ 'EnforcedStyleAlignWith' => 'either' }
end
Expand Down
2 changes: 0 additions & 2 deletions spec/rubocop/cop/layout/class_structure_spec.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Layout::ClassStructure, :config do
subject(:cop) { described_class.new(config) }

let(:config) do
RuboCop::Config.new(
'Layout/ClassStructure' => {
Expand Down
2 changes: 0 additions & 2 deletions spec/rubocop/cop/layout/def_end_alignment_spec.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Layout::DefEndAlignment, :config do
subject(:cop) { described_class.new(config) }

let(:source) do
<<~RUBY
foo def a
Expand Down
2 changes: 0 additions & 2 deletions spec/rubocop/cop/layout/dot_position_spec.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Layout::DotPosition, :config do
subject(:cop) { described_class.new(config) }

context 'Leading dots style' do
let(:cop_config) { { 'EnforcedStyle' => 'leading' } }

Expand Down
2 changes: 0 additions & 2 deletions spec/rubocop/cop/layout/empty_comment_spec.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Layout::EmptyComment, :config do
subject(:cop) { described_class.new(config) }

let(:cop_config) do
{ 'AllowBorderComment' => true, 'AllowMarginComment' => true }
end
Expand Down
2 changes: 0 additions & 2 deletions spec/rubocop/cop/layout/empty_line_between_defs_spec.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Layout::EmptyLineBetweenDefs, :config do
subject(:cop) { described_class.new(config) }

let(:cop_config) { { 'AllowAdjacentOneLineDefs' => false } }

it 'finds offenses in inner classes' do
Expand Down
@@ -1,8 +1,6 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Layout::EmptyLinesAroundAccessModifier, :config do
subject(:cop) { described_class.new(config) }

context 'EnforcedStyle is `around`' do
let(:cop_config) { { 'EnforcedStyle' => 'around' } }

Expand Down
2 changes: 0 additions & 2 deletions spec/rubocop/cop/layout/empty_lines_around_arguments_spec.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Layout::EmptyLinesAroundArguments, :config do
subject(:cop) { described_class.new(config) }

context 'when extra lines' do
it 'registers offense for empty line before arg' do
inspect_source(<<~RUBY)
Expand Down
2 changes: 0 additions & 2 deletions spec/rubocop/cop/layout/empty_lines_around_block_body_spec.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Layout::EmptyLinesAroundBlockBody, :config do
subject(:cop) { described_class.new(config) }

# Test blocks using both {} and do..end
[%w[{ }], %w[do end]].each do |open, close|
context "when EnforcedStyle is no_empty_lines for #{open} #{close} block" do
Expand Down