Skip to content

Commit

Permalink
Ignore groups with include_examples in LetBeforeExamples
Browse files Browse the repository at this point in the history
  • Loading branch information
pirj committed Oct 20, 2022
1 parent 532b8b9 commit 80d09ed
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 12 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
* Update `RSpec/ExampleWording` cop to raise error for insufficient descriptions. ([@akrox58][])
* Add new `RSpec/Capybara/NegationMatcher` cop. ([@ydah][])
* Add `AllowedPatterns` configuration option to `RSpec/NoExpectationExample`. ([@ydah][])
* Improve `RSpec/NoExpectationExample` cop to ignore examples skipped or pending via metatada. ([@pirj][])
* Improve `RSpec/NoExpectationExample` cop to ignore examples skipped or pending via metadata. ([@pirj][])
* Add `RSpec/FactoryBot/ConsistentParenthesesStyle` cop. ([@Liberatys][])
* Add `RSpec/Rails/InferredSpecType` cop. ([@r7kamura][])
* Add new `RSpec/Capybara/SpecificActions` cop. ([@ydah][])
* Update `config/default.yml` removing deprecated option to make the config correctable by users. ([@ignaciovillaverde][])
* Do not attempt to auto-correct example groups with `include_examples` in `RSpec/LetBeforeExamples`. ([@pirj][])

## 2.13.2 (2022-09-23)

Expand Down
16 changes: 15 additions & 1 deletion lib/rubocop/cop/rspec/let_before_examples.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ class LetBeforeExamples < Base
}
PATTERN

# @!method include_examples?(node)
def_node_matcher :include_examples?, <<~PATTERN
{
#{block_pattern(':include_examples')}
#{send_pattern(':include_examples')}
}
PATTERN

def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
return unless example_group_with_body?(node)

Expand All @@ -51,6 +59,10 @@ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler

private

def example_group_with_include_examples?(body)
body.children.any? { |sibling| include_examples?(sibling) }
end

def multiline_block?(block)
block.begin_type?
end
Expand All @@ -59,11 +71,13 @@ def check_let_declarations(node)
first_example = find_first_example(node)
return unless first_example

correct = !example_group_with_include_examples?(node)

first_example.right_siblings.each do |sibling|
next unless let?(sibling)

add_offense(sibling) do |corrector|
autocorrect(corrector, sibling, first_example)
autocorrect(corrector, sibling, first_example) if correct
end
end
end
Expand Down
36 changes: 26 additions & 10 deletions spec/rubocop/cop/rspec/let_before_examples_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,26 @@
RUBY
end

it 'flags `let` after `include_examples`' do
it 'flags `let` after `include_examples`, but does not autocorrect' do
# NOTE: include_examples may define the same variable as `let`,
# and changing the order may break the spec due to order dependency
# if `let` is moved above.
expect_offense(<<-RUBY)
RSpec.describe User do
include_examples('should be after let')
include_examples('should be BEFORE let as it defines `let(:foo)`, too')
let(:foo) { 'bar' }
^^^^^^^^^^^^^^^^^^^ Move `let` before the examples in the group.
end
RUBY

expect_no_corrections
end

it 'flags `let` after `it_behaves_like`' do
expect_offense(<<-RUBY)
RSpec.describe User do
it_behaves_like('should be after let')
let(:foo) { bar }
^^^^^^^^^^^^^^^^^ Move `let` before the examples in the group.
Expand All @@ -54,7 +70,7 @@
expect_correction(<<-RUBY)
RSpec.describe User do
let(:foo) { bar }
include_examples('should be after let')
it_behaves_like('should be after let')
end
RUBY
Expand All @@ -63,7 +79,7 @@
it 'flags `let` with proc argument' do
expect_offense(<<-RUBY)
RSpec.describe User do
include_examples('should be after let')
it_behaves_like('should be after let')
let(:user, &args[:build_user])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Move `let` before the examples in the group.
Expand All @@ -73,7 +89,7 @@
expect_correction(<<-RUBY)
RSpec.describe User do
let(:user, &args[:build_user])
include_examples('should be after let')
it_behaves_like('should be after let')
end
RUBY
Expand All @@ -82,7 +98,7 @@
it 'flags `let` with a heredoc argument' do
expect_offense(<<-RUBY)
RSpec.describe User do
include_examples('should be after let')
it_behaves_like('should be after let')
let(:foo) { (<<-SOURCE) }
^^^^^^^^^^^^^^^^^^^^^^^^^ Move `let` before the examples in the group.
Expand All @@ -96,7 +112,7 @@
let(:foo) { (<<-SOURCE) }
some long text here
SOURCE
include_examples('should be after let')
it_behaves_like('should be after let')
end
RUBY
Expand All @@ -113,7 +129,7 @@
it { is_expected.to work }
end
include_examples('everything is fine')
it_behaves_like('everything is fine')
end
RUBY
end
Expand All @@ -128,7 +144,7 @@
it { is_expected.to work }
end
include_examples('everything is fine')
it_behaves_like('everything is fine')
end
RUBY
end
Expand All @@ -146,7 +162,7 @@
it 'ignores single-line example blocks' do
expect_no_offenses(<<-RUBY)
RSpec.describe User do
include_examples 'special user' do
it_behaves_like 'special user' do
let(:foo) { bar }
end
end
Expand Down

0 comments on commit 80d09ed

Please sign in to comment.