Skip to content

Commit

Permalink
Fix: Fix false negative for RSpec/Dialect when specified Capybara-s…
Browse files Browse the repository at this point in the history
…pecific methods

fixed #1951

`RuboCop::Cop::RSpec::Dialect#rspec_method?` detects if node's second child is an RSpec block using `RuboCop::RSpec::Language::ALL.all`. However, `RuboCop::Cop::RSpec::Dialect#rspec_method?` returned nil because the following Capybara-specific methods were not set in config/default.yml.

- given
- given!
- background

I remove the line that checks if it’s a `rspec_method?` and add a `inside_example_group?` check.

cf. #1951 (comment)

Due to the above, it wouldn't filter out are calls with an explicit receiver where the receiver is not RSpec, eg `foo.describe`. so the following examples were removed.

- allows calling methods named xxx in examples
  • Loading branch information
sanfrecce-osaka committed Aug 26, 2024
1 parent e02576f commit fa5da43
Show file tree
Hide file tree
Showing 3 changed files with 177 additions and 48 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Master (Unreleased)

- Fix false-negative and error for `RSpec/MetadataStyle` when non-literal args are used in metadata in `EnforceStyle: hash`. ([@cbliard])
- Fix false negative for `RSpec/Dialect` when specified Capybara-specific methods. ([@sanfrecce-osaka])

## 3.0.4 (2024-08-05)

Expand Down Expand Up @@ -1004,6 +1005,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
[@rspeicher]: https://github.com/rspeicher
[@rst-j]: https://github.com/RST-J
[@samrjenkins]: https://github.com/samrjenkins
[@sanfrecce-osaka]: https://github.com/sanfrecce-osaka
[@schmijos]: https://github.com/schmijos
[@seanpdoyle]: https://github.com/seanpdoyle
[@sl4vr]: https://github.com/sl4vr
Expand Down
6 changes: 2 additions & 4 deletions lib/rubocop/cop/rspec/dialect.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,12 @@ module RSpec
class Dialect < Base
extend AutoCorrector
include MethodPreference
include InsideExampleGroup

MSG = 'Prefer `%<prefer>s` over `%<current>s`.'

# @!method rspec_method?(node)
def_node_matcher :rspec_method?, '(send #rspec? #ALL.all ...)'

def on_send(node)
return unless rspec_method?(node)
return unless inside_example_group?(node)
return unless preferred_methods[node.method_name]

msg = format(MSG, prefer: preferred_method(node.method_name),
Expand Down
217 changes: 173 additions & 44 deletions spec/rubocop/cop/rspec/dialect_spec.rb
Original file line number Diff line number Diff line change
@@ -1,59 +1,186 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::RSpec::Dialect do
let(:cop_config) do
{
'PreferredMethods' => {
'context' => 'describe'
}
}
end
context 'with preferred methods' do
context 'when `describe` is preferred to `context`' do
let(:cop_config) do
{
'PreferredMethods' => {
'context' => 'describe'
}
}
end

it 'allows describe blocks' do
expect_no_offenses(<<~RUBY)
describe 'display name presence' do
it 'allows describe blocks' do
expect_no_offenses(<<~RUBY)
RSpec.describe 'context' do
describe 'display name presence' do
end
end
RUBY
end
RUBY
end

it 'allows calling methods named context in examples' do
expect_no_offenses(<<~RUBY)
it 'tests common context invocations' do
expect(request.context).to be_empty?
it 'registers an offense for context blocks' do
expect_offense(<<~RUBY)
RSpec.describe 'context' do
context 'display name presence' do
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `describe` over `context`.
end
end
RUBY

expect_correction(<<~RUBY)
RSpec.describe 'context' do
describe 'display name presence' do
end
end
RUBY
end
RUBY
end
end

it 'registers an offense for context blocks' do
expect_offense(<<~RUBY)
context 'display name presence' do
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `describe` over `context`.
context 'when `describe` is preferred to `feature`' do
let(:cop_config) do
{
'PreferredMethods' => {
'feature' => 'describe'
}
}
end
RUBY

expect_correction(<<~RUBY)
describe 'display name presence' do
it 'allows describe blocks' do
expect_no_offenses(<<~RUBY)
RSpec.describe 'context' do
describe 'display name presence' do
end
end
RUBY
end
RUBY
end

it 'registers an offense for RSpec.context blocks' do
expect_offense(<<~RUBY)
RSpec.context 'context' do
^^^^^^^^^^^^^^^^^^^^^^^ Prefer `describe` over `context`.
it 'tests common context invocations' do
expect(request.context).to be_empty?
end
it 'registers an offense for feature blocks' do
expect_offense(<<~RUBY)
RSpec.describe 'context' do
feature 'display name presence' do
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `describe` over `feature`.
end
end
RUBY

expect_correction(<<~RUBY)
RSpec.describe 'context' do
describe 'display name presence' do
end
end
RUBY
end
RUBY
end

expect_correction(<<~RUBY)
RSpec.describe 'context' do
it 'tests common context invocations' do
expect(request.context).to be_empty?
end
context 'when `let` is preferred to `given`' do
let(:cop_config) do
{
'PreferredMethods' => {
'given' => 'let'
}
}
end

it 'allows let blocks' do
expect_no_offenses(<<~RUBY)
RSpec.describe 'context' do
let do
end
end
RUBY
end
RUBY

it 'registers an offense for given blocks' do
expect_offense(<<~RUBY)
RSpec.describe 'context' do
given do
^^^^^ Prefer `let` over `given`.
end
end
RUBY

expect_correction(<<~RUBY)
RSpec.describe 'context' do
let do
end
end
RUBY
end
end

context 'when `let!` is preferred to `given!`' do
let(:cop_config) do
{
'PreferredMethods' => {
'given!' => 'let!'
}
}
end

it 'allows let! blocks' do
expect_no_offenses(<<~RUBY)
RSpec.describe 'context' do
let! do
end
end
RUBY
end

it 'registers an offense for given! blocks' do
expect_offense(<<~RUBY)
RSpec.describe 'context' do
given! do
^^^^^^ Prefer `let!` over `given!`.
end
end
RUBY

expect_correction(<<~RUBY)
RSpec.describe 'context' do
let! do
end
end
RUBY
end
end

context 'when `before` is preferred to `background`' do
let(:cop_config) do
{
'PreferredMethods' => {
'background' => 'before'
}
}
end

it 'allows before blocks' do
expect_no_offenses(<<~RUBY)
RSpec.describe 'context' do
before do
end
end
RUBY
end

it 'registers an offense for background blocks' do
expect_offense(<<~RUBY)
RSpec.describe 'context' do
background do
^^^^^^^^^^ Prefer `before` over `background`.
end
end
RUBY

expect_correction(<<~RUBY)
RSpec.describe 'context' do
before do
end
end
RUBY
end
end
end

context 'without preferred methods' do
Expand All @@ -65,9 +192,11 @@

it 'allows all methods blocks' do
expect_no_offenses(<<~RUBY)
context 'is important' do
specify 'for someone to work' do
everyone.should have_some_leeway
RSpec.describe 'context' do
context 'is important' do
specify 'for someone to work' do
everyone.should have_some_leeway
end
end
end
RUBY
Expand Down

0 comments on commit fa5da43

Please sign in to comment.