lib/rubocop/cop/rspec/empty_example_group.rb in rubocop-rspec-1.43.2 vs lib/rubocop/cop/rspec/empty_example_group.rb in rubocop-rspec-1.44.0
- old
+ new
@@ -31,10 +31,15 @@
# it 'is chunky' do
# expect(bacon.chunky?).to be_truthy
# end
# end
#
+ # # good
+ # describe Bacon do
+ # pending 'will add tests later'
+ # end
+ #
# @example configuration
#
# # .rubocop.yml
# # RSpec/EmptyExampleGroup:
# # CustomIncludeMethods:
@@ -81,15 +86,18 @@
# it { is_expected.to fly }
# describe('non-empty example groups too') { }
# it_behaves_like 'an animal'
# it_behaves_like('a cat') { let(:food) { 'milk' } }
# it_has_root_access
+ # skip
+ # it 'will be implemented later'
#
# @param node [RuboCop::AST::Node]
# @return [Array<RuboCop::AST::Node>] matching nodes
def_node_matcher :example_or_group_or_include?, <<~PATTERN
{
+ #{Examples::ALL.send_pattern}
#{Examples::ALL.block_pattern}
#{ExampleGroups::ALL.block_pattern}
#{Includes::ALL.send_pattern}
#{Includes::ALL.block_pattern}
(send nil? #custom_include? ...)
@@ -150,15 +158,41 @@
(begin <#examples_directly_or_in_block? ...>)
}
PATTERN
def on_block(node)
+ return if node.each_ancestor(:def, :defs).any?
+ return if node.each_ancestor(:block).any? { |block| example?(block) }
+
example_group_body(node) do |body|
- add_offense(node.send_node) unless examples?(body)
+ add_offense(node.send_node) if offensive?(body)
end
end
private
+
+ def offensive?(body)
+ return true unless body
+ return false if conditionals_with_examples?(body)
+
+ if body.if_type?
+ !examples_in_branches?(body)
+ else
+ !examples?(body)
+ end
+ end
+
+ def conditionals_with_examples?(body)
+ return unless body.begin_type?
+
+ body.each_descendant(:if).any? do |if_node|
+ examples_in_branches?(if_node)
+ end
+ end
+
+ def examples_in_branches?(if_node)
+ if_node.branches.any? { |branch| examples?(branch) }
+ end
def custom_include?(method_name)
custom_include_methods.include?(method_name)
end