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