class RSpec::Matchers::BuiltIn::Include

@api private Provides the implementation for `include`. Not intended to be instantiated directly.

Attributes

expecteds[R]

@private

Public Class Methods

new(*expecteds) click to toggle source
# File lib/rspec/matchers/built_in/include.rb, line 11
def initialize(*expecteds)
  @expecteds = expecteds
end

Public Instance Methods

description() click to toggle source

@api private @return [String]

# File lib/rspec/matchers/built_in/include.rb, line 31
def description
  improve_hash_formatting("include#{readable_list_of(expecteds)}")
end
diffable?() click to toggle source

@api private @return [Boolean]

# File lib/rspec/matchers/built_in/include.rb, line 49
def diffable?
  !diff_would_wrongly_highlight_matched_item?
end
does_not_match?(actual) click to toggle source

@api private @return [Boolean]

# File lib/rspec/matchers/built_in/include.rb, line 24
def does_not_match?(actual)
  actual = actual.to_hash if convert_to_hash?(actual)
  perform_match(actual) { |v| !v }
end
expected() click to toggle source

@api private @return [Array, Hash]

# File lib/rspec/matchers/built_in/include.rb, line 55
def expected
  if expecteds.one? && Hash === expecteds.first
    expecteds.first
  else
    expecteds
  end
end
failure_message() click to toggle source

@api private @return [String]

# File lib/rspec/matchers/built_in/include.rb, line 37
def failure_message
  format_failure_message("to") { super }
end
failure_message_when_negated() click to toggle source

@api private @return [String]

# File lib/rspec/matchers/built_in/include.rb, line 43
def failure_message_when_negated
  format_failure_message("not to") { super }
end
matches?(actual) click to toggle source

@api private @return [Boolean]

# File lib/rspec/matchers/built_in/include.rb, line 17
def matches?(actual)
  actual = actual.to_hash if convert_to_hash?(actual)
  perform_match(actual) { |v| v }
end

Private Instance Methods

actual_collection_includes?(expected_item) click to toggle source
# File lib/rspec/matchers/built_in/include.rb, line 125
def actual_collection_includes?(expected_item)
  return true if actual.include?(expected_item)

  # String lacks an `any?` method...
  return false unless actual.respond_to?(:any?)

  actual.any? { |value| values_match?(expected_item, value) }
end
actual_hash_has_key?(expected_key) click to toggle source
# File lib/rspec/matchers/built_in/include.rb, line 118
def actual_hash_has_key?(expected_key)
  # We check `key?` first for perf:
  # `key?` is O(1), but `any?` is O(N).
  actual.key?(expected_key) ||
  actual.keys.any? { |key| values_match?(expected_key, key) }
end
actual_hash_includes?(expected_key, expected_value) click to toggle source
# File lib/rspec/matchers/built_in/include.rb, line 109
def actual_hash_includes?(expected_key, expected_value)
  actual_value = actual.fetch(expected_key) { return false }
  values_match?(expected_value, actual_value)
end
comparing_hash_keys?(expected_item) click to toggle source
# File lib/rspec/matchers/built_in/include.rb, line 114
def comparing_hash_keys?(expected_item)
  actual.is_a?(Hash) && !expected_item.is_a?(Hash)
end
comparing_hash_to_a_subset?(expected_item) click to toggle source
# File lib/rspec/matchers/built_in/include.rb, line 105
def comparing_hash_to_a_subset?(expected_item)
  actual.is_a?(Hash) && expected_item.is_a?(Hash)
end
convert_to_hash?(obj) click to toggle source
# File lib/rspec/matchers/built_in/include.rb, line 143
def convert_to_hash?(obj)
  !obj.respond_to?(:include?) && obj.respond_to?(:to_hash)
end
diff_would_wrongly_highlight_matched_item?() click to toggle source
# File lib/rspec/matchers/built_in/include.rb, line 134
def diff_would_wrongly_highlight_matched_item?
  return false unless actual.is_a?(String) && expected.is_a?(Array)

  lines = actual.split("\n")
  expected.any? do |str|
    actual.include?(str) && lines.none? { |line| line == str }
  end
end
excluded_from_actual() { |actual_hash_includes?(key, value)| ... } click to toggle source
# File lib/rspec/matchers/built_in/include.rb, line 88
def excluded_from_actual
  return [] unless @actual.respond_to?(:include?)

  expecteds.inject([]) do |memo, expected_item|
    if comparing_hash_to_a_subset?(expected_item)
      expected_item.each do |(key, value)|
        memo << { key => value } unless yield actual_hash_includes?(key, value)
      end
    elsif comparing_hash_keys?(expected_item)
      memo << expected_item unless yield actual_hash_has_key?(expected_item)
    else
      memo << expected_item unless yield actual_collection_includes?(expected_item)
    end
    memo
  end
end
format_failure_message(preposition) { || ... } click to toggle source
# File lib/rspec/matchers/built_in/include.rb, line 65
def format_failure_message(preposition)
  if actual.respond_to?(:include?)
    improve_hash_formatting("expected #{description_of @actual} #{preposition} include#{readable_list_of @divergent_items}")
  else
    improve_hash_formatting(yield) + ", but it does not respond to `include?`"
  end
end
perform_match(actual, &block) click to toggle source
# File lib/rspec/matchers/built_in/include.rb, line 82
def perform_match(actual, &block)
  @actual = actual
  @divergent_items = excluded_from_actual(&block)
  actual.respond_to?(:include?) && @divergent_items.empty?
end
readable_list_of(items) click to toggle source
# File lib/rspec/matchers/built_in/include.rb, line 73
def readable_list_of(items)
  described_items = surface_descriptions_in(items)
  if described_items.all? { |item| item.is_a?(Hash) }
    " #{described_items.inject(:merge).inspect}"
  else
    EnglishPhrasing.list(described_items)
  end
end