Skip to content

Commit c673d89

Browse files
committed
Allow identical body with distinct described_class
const args are used for described_class and thus are part of the 'metadata' of an example. ``` describe Array do it_behaves_like 'list' end describe Set do it_behaves_like 'list' end ``` should not be considered duplicate tests i wasn't sure how to extract the constant with all its namespaces as a list of symbols, so i just grab the whole constant node
1 parent 0d50317 commit c673d89

File tree

4 files changed

+60
-1
lines changed

4 files changed

+60
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* Add new `RSpec/VariableDefinition` cop. ([@tejasbubane][])
77
* Expand `Capybara/VisibilityMatcher` to support more than just `have_selector`. ([@twalpole][])
88
* Add new `SpecSuffixOnly` option to `RSpec/FilePath` cop. ([@zdennis][])
9+
* Allow `RSpec/RepeatedExampleGroupBody` to differ only by described_class. ([@robotdana][])
910

1011
## 1.39.0 (2020-05-01)
1112

@@ -510,3 +511,4 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
510511
[@tejasbubane]: https://github.com/tejasbubane
511512
[@twalpole]: https://github.com/twalpole
512513
[@zdennis]: https://github.com/zdennis
514+
[@robotdana]: https://github.com/robotdana

lib/rubocop/cop/rspec/repeated_example_group_body.rb

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@ module RSpec
3434
# it { cool_predicate }
3535
# end
3636
#
37+
# # good
38+
# context Array do
39+
# it { is_expected.to respond_to :each }
40+
# end
41+
#
42+
# context Hash do
43+
# it { is_expected.to respond_to :each }
44+
# end
45+
#
3746
class RepeatedExampleGroupBody < Cop
3847
MSG = 'Repeated %<group>s block body on line(s) %<loc>s'
3948

@@ -43,6 +52,7 @@ class RepeatedExampleGroupBody < Cop
4352

4453
def_node_matcher :metadata, '(block (send _ _ _ $...) ...)'
4554
def_node_matcher :body, '(block _ args $...)'
55+
def_node_matcher :const_arg, '(block (send _ _ $const ...) ...)'
4656

4757
def_node_matcher :skip_or_pending?, <<-PATTERN
4858
(block <(send nil? {:skip :pending}) ...>)
@@ -75,7 +85,7 @@ def add_repeated_lines(groups)
7585
end
7686

7787
def signature_keys(group)
78-
[metadata(group), body(group)]
88+
[metadata(group), body(group), const_arg(group)]
7989
end
8090

8191
def message(group, repeats)

manual/cops_rspec.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2665,6 +2665,15 @@ end
26652665
context 'when case y' do
26662666
it { cool_predicate }
26672667
end
2668+
2669+
# good
2670+
context Array do
2671+
it { is_expected.to respond_to :each }
2672+
end
2673+
2674+
context Hash do
2675+
it { is_expected.to respond_to :each }
2676+
end
26682677
```
26692678

26702679
### References

spec/rubocop/cop/rspec/repeated_example_group_body_spec.rb

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,44 @@
7474
RUBY
7575
end
7676

77+
it 'does not register offense if module arg is different' do
78+
expect_no_offenses(<<-RUBY)
79+
describe CSV::Row do
80+
it { is_expected.to respond_to :headers }
81+
end
82+
83+
describe CSV::Table do
84+
it { is_expected.to respond_to :headers }
85+
end
86+
RUBY
87+
end
88+
89+
it 'does not register offense when module arg namespace is different' do
90+
expect_no_offenses(<<-RUBY)
91+
describe CSV::Parser do
92+
it { expect(described_class).to respond_to(:parse) }
93+
end
94+
95+
describe URI::Parser do
96+
it { expect(described_class).to respond_to(:parse) }
97+
end
98+
RUBY
99+
end
100+
101+
it 'registers an offense for when module arg and namespace are identical' do
102+
expect_offense(<<-RUBY)
103+
context Net::HTTP do
104+
^^^^^^^^^^^^^^^^^^^^ Repeated context block body on line(s) [5]
105+
it { expect(described_class).to respond_to :start }
106+
end
107+
108+
context Net::HTTP do
109+
^^^^^^^^^^^^^^^^^^^^ Repeated context block body on line(s) [1]
110+
it { expect(described_class).to respond_to :start }
111+
end
112+
RUBY
113+
end
114+
77115
it 'does not register offense with several docstring' do
78116
expect_no_offenses(<<-RUBY)
79117
describe 'doing x', :json, 'request' do

0 commit comments

Comments
 (0)