lib/mocha/parameter_matchers/includes.rb
require 'mocha/parameter_matchers/all_of' require 'mocha/parameter_matchers/base' module Mocha module ParameterMatchers # Matches any object that responds with +true+ to +include?(item)+ # for all items. # # @param [*Array] items expected items. # @return [Includes] parameter matcher. # # @see Expectation#with # # @example Actual parameter includes all items. # object = mock() # object.expects(:method_1).with(includes('foo', 'bar')) # object.method_1(['foo', 'bar', 'baz']) # # no error raised # # @example Actual parameter does not include all items. # object.method_1(['foo', 'baz']) # # error raised, because ['foo', 'baz'] does not include 'bar'. # # @example Actual parameter includes item which matches nested matcher. # object = mock() # object.expects(:method_1).with(includes(has_key(:key))) # object.method_1(['foo', 'bar', {key: 'baz'}]) # # no error raised # # @example Actual parameter does not include item matching nested matcher. # object.method_1(['foo', 'bar', {:other_key => 'baz'}]) # # error raised, because no element matches `has_key(:key)` matcher # # @example Actual parameter is a String including substring. # object = mock() # object.expects(:method_1).with(includes('bar')) # object.method_1('foobarbaz') # # no error raised # # @example Actual parameter is a String not including substring. # object.method_1('foobaz') # # error raised, because 'foobaz' does not include 'bar' # # @example Actual parameter is a Hash including the given key. # object = mock() # object.expects(:method_1).with(includes(:bar)) # object.method_1({foo: 1, bar: 2}) # # no error raised # # @example Actual parameter is a Hash without the given key. # object.method_1({foo: 1, baz: 2}) # # error raised, because hash does not include key 'bar' # # @example Actual parameter is a Hash with a key matching the given matcher. # object = mock() # object.expects(:method_1).with(includes(regexp_matches(/ar/))) # object.method_1({'foo' => 1, 'bar' => 2}) # # no error raised # # @example Actual parameter is a Hash no key matching the given matcher. # object.method_1({'foo' => 1, 'baz' => 3}) # # error raised, because hash does not include a key matching /ar/ def includes(*items) Includes.new(*items) end # Parameter matcher which matches when actual parameter includes expected values. class Includes < Base # @private def initialize(*items) @items = items end # @private # rubocop:disable Metrics/PerceivedComplexity def matches?(available_parameters) parameter = available_parameters.shift return false unless parameter.respond_to?(:include?) if @items.size == 1 # rubocop:disable Style/GuardClause if parameter.respond_to?(:any?) && !parameter.is_a?(String) parameter = parameter.keys if parameter.is_a?(Hash) return parameter.any? { |p| @items.first.to_matcher.matches?([p]) } else return parameter.include?(@items.first) end # rubocop:enable Style/GuardClause else includes_matchers = @items.map { |item| Includes.new(item) } AllOf.new(*includes_matchers).matches?([parameter]) end end # rubocop:enable Metrics/PerceivedComplexity # @private def mocha_inspect item_descriptions = @items.map(&:mocha_inspect) "includes(#{item_descriptions.join(', ')})" end end end end