lib/rubocop/cop/rspec/multiple_expectations.rb



# frozen_string_literal: true

module RuboCop
  module Cop
    module RSpec
      # Checks if examples contain too many `expect` calls.
      #
      # @see http://betterspecs.org/#single Single expectation test
      #
      # This cop is configurable using the `Max` option
      # and works with `--auto-gen-config`.
      #
      # @example
      #
      #   # bad
      #   describe UserCreator do
      #     it 'builds a user' do
      #       expect(user.name).to eq("John")
      #       expect(user.age).to eq(22)
      #     end
      #   end
      #
      #   # good
      #   describe UserCreator do
      #     it 'sets the users name' do
      #       expect(user.name).to eq("John")
      #     end
      #
      #     it 'sets the users age'
      #       expect(user.age).to eq(22)
      #     end
      #   end
      #
      # @example configuration
      #
      #   # .rubocop.yml
      #   RSpec/MultipleExpectations:
      #     Max: 2
      #
      #   # not flagged by rubocop
      #   describe UserCreator do
      #     it 'builds a user' do
      #       expect(user.name).to eq("John")
      #       expect(user.age).to eq(22)
      #     end
      #   end
      #
      class MultipleExpectations < Cop
        include ConfigurableMax

        MSG = 'Too many expectations.'.freeze

        def_node_matcher :example?, Examples::ALL.block_pattern

        def_node_search :expect, '(send _ :expect ...)'

        def on_block(node)
          return unless example?(node) && (expectations = expect(node))

          return if expectations.count <= max_expectations

          self.max = expectations.count

          flag_example(node, expectation_count: expectations.count)
        end

        private

        def flag_example(node, expectation_count:)
          method, = *node

          add_offense(
            method,
            :expression,
            MSG % { total: expectation_count, max: max_expectations }
          )
        end

        def max_expectations
          Integer(cop_config.fetch(parameter_name, 1))
        end
      end
    end
  end
end