Skip to content

Commit

Permalink
Merge branch 'master' into change_path
Browse files Browse the repository at this point in the history
  • Loading branch information
ydah authored Jul 17, 2023
2 parents bf5f642 + 1da31d1 commit 0dc19dd
Show file tree
Hide file tree
Showing 10 changed files with 258 additions and 4 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
- Fix a false negative for `RSpec/Pending` when `it` without body. ([@ydah])
- Add new `RSpec/ReceiveMessages` cop. ([@ydah])
- Change default.yml path to use `**/spec/*` instead of `spec/*`. ([@ydah])
- Add `AllowedIdentifiers` and `AllowedPatterns` configuration option to `RSpec/IndexedLet`. ([@ydah])
- Fix `RSpec/NamedSubject` when block has no body. ([@splattael])
- Fix `RSpec/LetBeforeExamples` autocorrect incompatible with `RSpec/ScatteredLet` autocorrect. ([@ydah])

## 2.22.0 (2023-05-06)

Expand Down Expand Up @@ -867,6 +870,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
[@seanpdoyle]: https://github.com/seanpdoyle
[@sl4vr]: https://github.com/sl4vr
[@smcgivern]: https://github.com/smcgivern
[@splattael]: https://github.com/splattael
[@stephannv]: https://github.com/stephannv
[@t3h2mas]: https://github.com/t3h2mas
[@tdeo]: https://github.com/tdeo
Expand Down
3 changes: 3 additions & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -515,8 +515,11 @@ RSpec/IndexedLet:
Description: Do not set up test data using indexes (e.g., `item_1`, `item_2`).
Enabled: pending
VersionAdded: '2.20'
VersionChanged: "<<next>>"
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/IndexedLet
Max: 1
AllowedIdentifiers: []
AllowedPatterns: []

RSpec/InstanceSpy:
Description: Checks for `instance_double` used with `have_received`.
Expand Down
31 changes: 30 additions & 1 deletion docs/modules/ROOT/pages/cops_rspec.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2464,14 +2464,17 @@ it { expect(named_subject).to be_truthy }
| Yes
| No
| 2.20
| -
| <<next>>
|===

Do not set up test data using indexes (e.g., `item_1`, `item_2`).

It makes reading the test harder because it's not clear what exactly
is tested by this particular example.

The configurable options `AllowedIdentifiers` and `AllowedPatterns`
will also read those set in `Naming/VariableNumber`.

=== Examples

==== `Max: 1 (default)`
Expand Down Expand Up @@ -2505,6 +2508,24 @@ let(:item_1) { create(:item) }
let(:item_2) { create(:item) }
----

==== `AllowedIdentifiers: ['item_1', 'item_2']`

[source,ruby]
----
# good
let(:item_1) { create(:item) }
let(:item_2) { create(:item) }
----

==== `AllowedPatterns: ['item']`

[source,ruby]
----
# good
let(:item_1) { create(:item) }
let(:item_2) { create(:item) }
----

=== Configurable attributes

|===
Expand All @@ -2513,6 +2534,14 @@ let(:item_2) { create(:item) }
| Max
| `1`
| Integer

| AllowedIdentifiers
| `[]`
| Array

| AllowedPatterns
| `[]`
| Array
|===

=== References
Expand Down
33 changes: 32 additions & 1 deletion lib/rubocop/cop/rspec/indexed_let.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ module RSpec
# It makes reading the test harder because it's not clear what exactly
# is tested by this particular example.
#
# The configurable options `AllowedIdentifiers` and `AllowedPatterns`
# will also read those set in `Naming/VariableNumber`.
#
# @example `Max: 1 (default)`
# # bad
# let(:item_1) { create(:item) }
Expand All @@ -31,7 +34,20 @@ module RSpec
# let(:item_1) { create(:item) }
# let(:item_2) { create(:item) }
#
# @example `AllowedIdentifiers: ['item_1', 'item_2']`
# # good
# let(:item_1) { create(:item) }
# let(:item_2) { create(:item) }
#
# @example `AllowedPatterns: ['item']`
# # good
# let(:item_1) { create(:item) }
# let(:item_2) { create(:item) }
#
class IndexedLet < Base
include AllowedIdentifiers
include AllowedPattern

MSG = 'This `let` statement uses index in its name. Please give it ' \
'a meaningful name.'

Expand Down Expand Up @@ -69,12 +85,27 @@ def filter_indexed_lets(candidates)
end

def indexed_let?(node)
let?(node) && SUFFIX_INDEX_REGEX.match?(let_name(node))
let?(node) &&
SUFFIX_INDEX_REGEX.match?(let_name(node)) &&
!allowed_identifier?(let_name(node).to_s) &&
!matches_allowed_pattern?(let_name(node).to_s)
end

def let_name_stripped_index(node)
let_name(node).to_s.gsub(INDEX_REGEX, '')
end

def cop_config_patterns_values
Array(config.for_cop('Naming/VariableNumber')
.fetch('AllowedPatterns', [])) +
Array(cop_config.fetch('AllowedPatterns', []))
end

def allowed_identifiers
Array(config.for_cop('Naming/VariableNumber')
.fetch('AllowedIdentifiers', [])) +
Array(cop_config.fetch('AllowedIdentifiers', []))
end
end
end
end
Expand Down
4 changes: 4 additions & 0 deletions lib/rubocop/cop/rspec/let_before_examples.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ class LetBeforeExamples < Base
}
PATTERN

def self.autocorrect_incompatible_with
[RSpec::ScatteredLet]
end

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

Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/rspec/named_subject.rb
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ def nearest_subject(node)
end

def find_subject(block_node)
block_node.body.child_nodes.find { |send_node| subject?(send_node) }
block_node.body&.child_nodes&.find { |send_node| subject?(send_node) }
end
end
end
Expand Down
45 changes: 45 additions & 0 deletions spec/rubocop/cli/autocorrect_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,49 @@
RUBY
end
end

context 'when corrects `RSpec/LetBeforeExamples` with ' \
'`RSpec/ScatteredLet`' do
before do
RuboCop::ConfigLoader
.default_configuration
.for_all_cops['SuggestExtensions'] = false

create_file('spec/example.rb', <<~RUBY)
RSpec.describe 'Foo' do
let(:params) { {} }
specify do
expect(true).to be true
end
let(:attributes) { %i[first_name last_name] }
end
RUBY
end

it 'rubocop terminates with a success' do
expect(cli.run(['-A', '--only',
'RSpec/LetBeforeExamples,' \
'RSpec/ScatteredLet'])).to eq(0)
end

it 'autocorrects be compatible with each other' do
cli.run(['-A', '--only',
'RSpec/LetBeforeExamples,' \
'RSpec/ScatteredLet'])

expect(File.read('spec/example.rb')).to eq(<<~RUBY)
RSpec.describe 'Foo' do
let(:params) { {} }
let(:attributes) { %i[first_name last_name] }
specify do
expect(true).to be true
end
end
RUBY
end
end
end
94 changes: 94 additions & 0 deletions spec/rubocop/cli/run_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# frozen_string_literal: true

RSpec.describe 'RuboCop::CLI run', :isolated_environment do # rubocop:disable RSpec/DescribeClass
subject(:cli) { RuboCop::CLI.new }

include_context 'when cli spec behavior'

context 'when set option `AllowedIdentifiers` for ' \
'`RSpec/IndexedLet` and `Naming/VariableNumber`' do
let(:exit_code) do
cli.run(%w[--format simple --only RSpec/IndexedLet,Naming/VariableNumber])
end

it 'does not offense for `RSpec/IndexedLet` ' \
'when set `AllowedIdentifiers` in `Naming/VariableNumber`' do
create_file('.rubocop.yml', <<~YAML)
RSpec/IndexedLet:
Enabled: true
AllowedPatterns:
- foo
Naming/VariableNumber:
Enabled: true
AllowedIdentifiers:
- bar_1
- bar_2
YAML
create_file('spec/example.rb', <<~RUBY)
describe SomeService do
let(:foo_1) { create(:foo) }
let(:foo_2) { create(:foo) }
let(:bar_1) { create(:bar) }
let(:bar_2) { create(:bar) }
let(:baz_1) { create(:baz) }
let(:baz_2) { create(:baz) }
end
RUBY
expect(exit_code).to eq(1)
expect($stdout.string).to eq(<<~OUTPUT)
== spec/example.rb ==
C: 2: 7: Naming/VariableNumber: Use normalcase for symbol numbers.
C: 3: 7: Naming/VariableNumber: Use normalcase for symbol numbers.
C: 6: 3: RSpec/IndexedLet: This let statement uses index in its name. Please give it a meaningful name.
C: 6: 7: Naming/VariableNumber: Use normalcase for symbol numbers.
C: 7: 3: RSpec/IndexedLet: This let statement uses index in its name. Please give it a meaningful name.
C: 7: 7: Naming/VariableNumber: Use normalcase for symbol numbers.
1 file inspected, 6 offenses detected
OUTPUT
end
end

context 'when set option `AllowedPatterns` for ' \
'`RSpec/IndexedLet` and `Naming/VariableNumber`' do
let(:exit_code) do
cli.run(%w[--format simple --only RSpec/IndexedLet,Naming/VariableNumber])
end

it 'does not offense for `RSpec/IndexedLet` ' \
'when set `AllowedPatterns` in `Naming/VariableNumber`' do
create_file('.rubocop.yml', <<~YAML)
RSpec/IndexedLet:
Enabled: true
AllowedPatterns:
- foo
Naming/VariableNumber:
Enabled: true
AllowedPatterns:
- bar
YAML
create_file('spec/example.rb', <<~RUBY)
describe SomeService do
let(:foo_1) { create(:foo) }
let(:foo_2) { create(:foo) }
let(:bar_1) { create(:bar) }
let(:bar_2) { create(:bar) }
let(:baz_1) { create(:baz) }
let(:baz_2) { create(:baz) }
end
RUBY
expect(exit_code).to eq(1)
expect($stdout.string).to eq(<<~OUTPUT)
== spec/example.rb ==
C: 2: 7: Naming/VariableNumber: Use normalcase for symbol numbers.
C: 3: 7: Naming/VariableNumber: Use normalcase for symbol numbers.
C: 6: 3: RSpec/IndexedLet: This let statement uses index in its name. Please give it a meaningful name.
C: 6: 7: Naming/VariableNumber: Use normalcase for symbol numbers.
C: 7: 3: RSpec/IndexedLet: This let statement uses index in its name. Please give it a meaningful name.
C: 7: 7: Naming/VariableNumber: Use normalcase for symbol numbers.
1 file inspected, 6 offenses detected
OUTPUT
end
end
end
36 changes: 35 additions & 1 deletion spec/rubocop/cop/rspec/indexed_let_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,15 @@

RSpec.describe RuboCop::Cop::RSpec::IndexedLet do
let(:max) { 1 }
let(:cop_config) { { 'Max' => max } }
let(:allowed_patterns) { [] }
let(:allowed_identifiers) { [] }
let(:cop_config) do
{
'Max' => max,
'AllowedIdentifiers' => allowed_identifiers,
'AllowedPatterns' => allowed_patterns
}
end

it 'flags repeated symbol names' do
expect_offense(<<~RUBY)
Expand Down Expand Up @@ -131,4 +139,30 @@
RUBY
end
end

context 'when AllowedIdentifiers is set' do
let(:allowed_identifiers) { %w[item_1 item_2] }

it 'not flags allowed indexed let' do
expect_no_offenses(<<~RUBY)
describe SomeService do
let(:item_1) { create(:item) }
let(:item_2) { create(:item) }
end
RUBY
end
end

context 'when AllowedPatterns is set' do
let(:allowed_patterns) { %w[item] }

it 'not flags allowed indexed let' do
expect_no_offenses(<<~RUBY)
describe SomeService do
let(:item_1) { create(:item) }
let(:item_2) { create(:item) }
end
RUBY
end
end
end
10 changes: 10 additions & 0 deletions spec/rubocop/cop/rspec/named_subject_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,16 @@ def foo
end
RUBY
end

it 'ignores subject when block has no body' do
expect_no_offenses(<<-RUBY)
it "is a User" do
subject.each do
# empty body
end
end
RUBY
end
end

context 'when IgnoreSharedExamples is false' do
Expand Down

0 comments on commit 0dc19dd

Please sign in to comment.