From 7e046a0ac79f1f82b77687e073c51b98c71460ed Mon Sep 17 00:00:00 2001 From: Tejas Bubane Date: Wed, 29 Apr 2020 13:27:52 +0530 Subject: [PATCH] Fix multiple cops to detect `let` with proc argument Affected cops: 1. `RSpec/ScatteredLet` 2. `RSpec/AlignLeftLetBrace` 3. `RSpec/AlignRightLetBrace` 4. `RSpec/LeadingSubject` 5. `RSpec/EmptyLineAfterFinalLet` 6. `RSpec/LetBeforeExamples` Closes #771 --- CHANGELOG.md | 2 ++ lib/rubocop/rspec/language.rb | 8 ++++++++ lib/rubocop/rspec/language/node_pattern.rb | 2 +- .../cop/rspec/align_left_let_brace_spec.rb | 6 ++++++ .../cop/rspec/align_right_let_brace_spec.rb | 6 ++++++ .../rspec/empty_line_after_final_let_spec.rb | 20 +++++++++++++++++++ .../rubocop/cop/rspec/leading_subject_spec.rb | 19 ++++++++++++++++++ .../cop/rspec/let_before_examples_spec.rb | 19 ++++++++++++++++++ spec/rubocop/cop/rspec/scattered_let_spec.rb | 11 ++++++++++ 9 files changed, 92 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5a0d3230..606fedadc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * Add new `Capybara/VisibilityMatcher` cop. ([@aried3r][]) * Ignore String constants by `RSpec/Describe`. ([@AlexWayfer][]) * Drop support for ruby 2.3. ([@bquorning][]) +* Fix multiple cops to detect `let` with proc argument. ([@tejasbubane][]) ## 1.38.1 (2020-02-15) @@ -497,3 +498,4 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features. [@eitoball]: https://github.com/eitoball [@aried3r]: https://github.com/aried3r [@AlexWayfer]: https://github.com/AlexWayfer +[@tejasbubane]: https://github.com/tejasbubane diff --git a/lib/rubocop/rspec/language.rb b/lib/rubocop/rspec/language.rb index 60e182a82..1e5ef49db 100644 --- a/lib/rubocop/rspec/language.rb +++ b/lib/rubocop/rspec/language.rb @@ -28,6 +28,14 @@ def block_pattern "(block #{send_pattern} ...)" end + def block_pass_pattern + "(send #{RSPEC} #{node_pattern_union} _ block_pass)" + end + + def block_or_block_pass_pattern + "{#{block_pattern} #{block_pass_pattern}}" + end + def send_pattern "(send #{RSPEC} #{node_pattern_union} ...)" end diff --git a/lib/rubocop/rspec/language/node_pattern.rb b/lib/rubocop/rspec/language/node_pattern.rb index 63378fd42..665b7ad70 100644 --- a/lib/rubocop/rspec/language/node_pattern.rb +++ b/lib/rubocop/rspec/language/node_pattern.rb @@ -17,7 +17,7 @@ module NodePattern def_node_matcher :hook?, Hooks::ALL.block_pattern - def_node_matcher :let?, Helpers::ALL.block_pattern + def_node_matcher :let?, Helpers::ALL.block_or_block_pass_pattern def_node_matcher :subject?, Subject::ALL.block_pattern end diff --git a/spec/rubocop/cop/rspec/align_left_let_brace_spec.rb b/spec/rubocop/cop/rspec/align_left_let_brace_spec.rb index e923f8003..67106a4d2 100644 --- a/spec/rubocop/cop/rspec/align_left_let_brace_spec.rb +++ b/spec/rubocop/cop/rspec/align_left_let_brace_spec.rb @@ -45,6 +45,12 @@ end # rubocop:enable RSpec/ExampleLength + it 'does not register offense for let with proc argument' do + expect_no_offenses(<<-RUBY) + let(:user, &args[:build_user]) + RUBY + end + it 'works with empty file' do expect_no_offenses('') end diff --git a/spec/rubocop/cop/rspec/align_right_let_brace_spec.rb b/spec/rubocop/cop/rspec/align_right_let_brace_spec.rb index 6a2c0028a..1fa350c6b 100644 --- a/spec/rubocop/cop/rspec/align_right_let_brace_spec.rb +++ b/spec/rubocop/cop/rspec/align_right_let_brace_spec.rb @@ -45,6 +45,12 @@ end # rubocop:enable RSpec/ExampleLength + it 'does not register offense for let with proc argument' do + expect_no_offenses(<<-RUBY) + let(:user, &args[:build_user]) + RUBY + end + it 'works with empty file' do expect_no_offenses('') end diff --git a/spec/rubocop/cop/rspec/empty_line_after_final_let_spec.rb b/spec/rubocop/cop/rspec/empty_line_after_final_let_spec.rb index d43a2fea3..777b6f510 100644 --- a/spec/rubocop/cop/rspec/empty_line_after_final_let_spec.rb +++ b/spec/rubocop/cop/rspec/empty_line_after_final_let_spec.rb @@ -47,6 +47,26 @@ RUBY end + it 'checks for empty line after let with proc argument' do + expect_offense(<<-RUBY) + RSpec.describe User do + let(:a) { a } + let(:user, &args[:build_user]) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Add an empty line after the last `let` block. + it { expect(a).to eq(b) } + end + RUBY + + expect_correction(<<-RUBY) + RSpec.describe User do + let(:a) { a } + let(:user, &args[:build_user]) + + it { expect(a).to eq(b) } + end + RUBY + end + it 'approves empty line after let' do expect_no_offenses(<<-RUBY) RSpec.describe User do diff --git a/spec/rubocop/cop/rspec/leading_subject_spec.rb b/spec/rubocop/cop/rspec/leading_subject_spec.rb index 20c6fe72a..d214b3e76 100644 --- a/spec/rubocop/cop/rspec/leading_subject_spec.rb +++ b/spec/rubocop/cop/rspec/leading_subject_spec.rb @@ -41,6 +41,25 @@ RUBY end + it 'checks subject below let with proc argument' do + expect_offense(<<-RUBY) + RSpec.describe User do + let(:user, &args[:build_user]) + + subject { described_class.new } + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Declare `subject` above any other `let` declarations. + end + RUBY + + expect_correction(<<-RUBY) + RSpec.describe User do + subject { described_class.new } + let(:user, &args[:build_user]) + + end + RUBY + end + it 'approves of subject above let' do expect_no_offenses(<<-RUBY) RSpec.describe User do diff --git a/spec/rubocop/cop/rspec/let_before_examples_spec.rb b/spec/rubocop/cop/rspec/let_before_examples_spec.rb index a2a1077b0..1fc106d37 100644 --- a/spec/rubocop/cop/rspec/let_before_examples_spec.rb +++ b/spec/rubocop/cop/rspec/let_before_examples_spec.rb @@ -62,6 +62,25 @@ RUBY end + it 'flags `let` with proc argument' do + expect_offense(<<-RUBY) + RSpec.describe User do + include_examples('should be after let') + + let(:user, &args[:build_user]) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Move `let` before the examples in the group. + end + RUBY + + expect_correction(<<-RUBY) + RSpec.describe User do + let(:user, &args[:build_user]) + include_examples('should be after let') + + end + RUBY + end + it 'does not flag `let` before the examples' do expect_no_offenses(<<-RUBY) RSpec.describe User do diff --git a/spec/rubocop/cop/rspec/scattered_let_spec.rb b/spec/rubocop/cop/rspec/scattered_let_spec.rb index 09ecb4cf0..9044b5bc6 100644 --- a/spec/rubocop/cop/rspec/scattered_let_spec.rb +++ b/spec/rubocop/cop/rspec/scattered_let_spec.rb @@ -25,4 +25,15 @@ end RUBY end + + it 'flags `let` with proc argument' do + expect_offense(<<-RUBY) + RSpec.describe User do + let(:a) { a } + subject { User } + let(:user, &args[:build_user]) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Group all let/let! blocks in the example group together. + end + RUBY + end end