Skip to content

Commit 3030ba8

Browse files
authored
Merge pull request #932 from andrykonchin/add-top-level-group-callback
RSpec/SubjectStub. Add top level group callback
2 parents e970b6a + 38fa7f3 commit 3030ba8

File tree

4 files changed

+90
-9
lines changed

4 files changed

+90
-9
lines changed

lib/rubocop-rspec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
require_relative 'rubocop/rspec/wording'
1414
require_relative 'rubocop/rspec/language'
1515
require_relative 'rubocop/rspec/language/node_pattern'
16+
require_relative 'rubocop/rspec/top_level_group'
1617
require_relative 'rubocop/rspec/concept'
1718
require_relative 'rubocop/rspec/example_group'
1819
require_relative 'rubocop/rspec/example'

lib/rubocop/cop/rspec/subject_stub.rb

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ module RSpec
2222
# end
2323
#
2424
class SubjectStub < Cop
25+
include RuboCop::RSpec::TopLevelGroup
26+
2527
MSG = 'Do not stub methods of the object under test.'
2628

2729
# @!method subject(node)
@@ -75,11 +77,7 @@ class SubjectStub < Cop
7577
} ...)
7678
PATTERN
7779

78-
def on_block(node)
79-
return unless example_group?(node)
80-
return if (processed_example_groups & node.ancestors).any?
81-
82-
processed_example_groups << node
80+
def on_top_level_group(node)
8381
@explicit_subjects = find_all_explicit_subjects(node)
8482

8583
find_subject_expectations(node) do |stub|
@@ -89,10 +87,6 @@ def on_block(node)
8987

9088
private
9189

92-
def processed_example_groups
93-
@processed_example_groups ||= Set.new
94-
end
95-
9690
def find_all_explicit_subjects(node)
9791
node.each_descendant(:block).with_object({}) do |child, h|
9892
name = subject(child)
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# frozen_string_literal: true
2+
3+
module RuboCop
4+
module RSpec
5+
# Helper methods for top level example group cops
6+
module TopLevelGroup
7+
extend RuboCop::NodePattern::Macros
8+
include RuboCop::RSpec::Language
9+
10+
def_node_matcher :example_or_shared_group?,
11+
(ExampleGroups::ALL + SharedGroups::ALL).block_pattern
12+
13+
def on_block(node)
14+
return unless respond_to?(:on_top_level_group)
15+
return unless top_level_group?(node)
16+
17+
on_top_level_group(node)
18+
end
19+
20+
private
21+
22+
def top_level_group?(node)
23+
top_level_groups.include?(node)
24+
end
25+
26+
def top_level_groups
27+
@top_level_groups ||=
28+
top_level_nodes.select { |n| example_or_shared_group?(n) }
29+
end
30+
31+
def top_level_nodes
32+
if root_node.begin_type?
33+
root_node.children
34+
else
35+
[root_node]
36+
end
37+
end
38+
39+
def root_node
40+
processed_source.ast
41+
end
42+
end
43+
end
44+
end

spec/rubocop/cop/rspec/subject_stub_spec.rb

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,4 +321,46 @@
321321
end
322322
RUBY
323323
end
324+
325+
it 'flags when there are several top level example groups' do
326+
expect_offense(<<-RUBY)
327+
RSpec.describe Foo do
328+
subject(:foo) { described_class.new }
329+
330+
specify do
331+
expect(foo).to eq(foo)
332+
end
333+
end
334+
335+
RSpec.describe Bar do
336+
subject(:bar) { described_class.new }
337+
338+
specify do
339+
allow(bar).to receive(:bar)
340+
^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub methods of the object under test.
341+
end
342+
end
343+
RUBY
344+
end
345+
346+
describe 'top level example groups' do
347+
%i[
348+
describe xdescribe fdescribe
349+
context xcontext fcontext
350+
feature xfeature ffeature
351+
example_group
352+
shared_examples shared_examples_for shared_context
353+
].each do |method|
354+
it "flags in top level #{method}" do
355+
expect_offense(<<-RUBY)
356+
RSpec.#{method} '#{method}' do
357+
it 'uses an implicit subject' do
358+
expect(subject).to receive(:bar)
359+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub methods of the object under test.
360+
end
361+
end
362+
RUBY
363+
end
364+
end
365+
end
324366
end

0 commit comments

Comments
 (0)