File tree Expand file tree Collapse file tree 4 files changed +90
-9
lines changed Expand file tree Collapse file tree 4 files changed +90
-9
lines changed Original file line number Diff line number Diff line change 1313require_relative 'rubocop/rspec/wording'
1414require_relative 'rubocop/rspec/language'
1515require_relative 'rubocop/rspec/language/node_pattern'
16+ require_relative 'rubocop/rspec/top_level_group'
1617require_relative 'rubocop/rspec/concept'
1718require_relative 'rubocop/rspec/example_group'
1819require_relative 'rubocop/rspec/example'
Original file line number Diff line number Diff 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 )
Original file line number Diff line number Diff line change 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
Original file line number Diff line number Diff line change 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
324366end
You can’t perform that action at this time.
0 commit comments