123456789_123456789_123456789_123456789_123456789_

Class: RSpec::Matchers::BuiltIn::Include Private

Do not use. This class is for internal use only.
Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, BaseMatcher
Instance Chain:
Inherits: RSpec::Matchers::BuiltIn::BaseMatcher
Defined in: rspec-expectations/lib/rspec/matchers/built_in/include.rb

Overview

Provides the implementation for RSpec::Matchers#include. Not intended to be instantiated directly.

Constant Summary

BaseMatcher - Inherited

UNDEFINED

Class Method Summary

BaseMatcher - Inherited

.matcher_name, .new,
.underscore

Borrowed from ActiveSupport.

Instance Attribute Summary

CountExpectation - Included

BaseMatcher - Inherited

#actual,
#diffable?

::RSpec::Matchers are not diffable by default.

#expected, #expects_call_stack_jump?, #matcher_name, #matcher_name=, #rescued_exception,
#supports_block_expectations?

Most matchers are value matchers (i.e. meant to work with ‘expect(value)`) rather than block matchers (i.e. meant to work with `expect { }`), so this defaults to false.

#supports_value_expectations?

BaseMatcher::StringEncodingFormatting - Included

Instance Method Summary

CountExpectation - Included

#at_least

Specifies the minimum number of times the method is expected to match.

#at_most

Specifies the maximum number of times the method is expected to match.

#exactly

Specifies that the method is expected to match the given number of times.

#once

Specifies that the method is expected to match once.

#thrice

Specifies that the method is expected to match thrice.

#times

No-op.

#twice

Specifies that the method is expected to match twice.

#count_constraint_to_number, #count_expectation_description, #count_failure_reason,
#cover?

:nocov:

#expected_count_matches?, #human_readable_count, #human_readable_expectation_type, #raise_impossible_count_expectation, #raise_unsupported_count_expectation, #set_expected_count, #unsupported_count_expectation?

BaseMatcher - Inherited

#actual_formatted,
#description

Generates a description using ::RSpec::Matchers::EnglishPhrasing.

#expected_formatted,
#match_unless_raises

Used to wrap a block of code that will indicate failure by raising one of the named exceptions.

#matches?

Indicates if the match is successful.

BaseMatcher::DefaultFailureMessages - Included

#failure_message

Provides a good generic failure message.

#failure_message_when_negated

Provides a good generic negative failure message.

BaseMatcher::StringEncodingFormatting - Included

#format_encoding

Formats a String’s encoding as a human readable string :nocov:

BaseMatcher::HashFormatting - Included

#improve_hash_formatting

‘{ :a => 5, :b => 2 }.inspect` produces:

::RSpec::Matchers::Composable - Included

#&

Alias for Composable#and.

#===

Delegates to #matches?.

#and

Creates a compound and expectation.

#description_of

Returns the description of the given object in a way that is aware of composed matchers.

#or

Creates a compound or expectation.

#values_match?

This provides a generic way to fuzzy-match an expected value against an actual value.

#|

Alias for Composable#or.

#should_enumerate?

We should enumerate arrays as long as they are not recursive.

#surface_descriptions_in

Transforms the given data structure (typically a hash or array) into a new data structure that, when #inspect is called on it, will provide descriptions of any contained matchers rather than the normal #inspect output.

#unreadable_io?,
#with_matchers_cloned

Historically, a single matcher instance was only checked against a single value.

Instance Attribute Details

#check_expected_count?Boolean (readonly, private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/include.rb', line 84

def check_expected_count?
  case
  when !has_expected_count?
    return false
  when expecteds.size != 1
    raise NotImplementedError, 'Count constraint supported only when testing for a single value being included'
  when actual.is_a?(Hash)
    raise NotImplementedError, 'Count constraint on hash keys not implemented'
  end
  true
end

#diff_would_wrongly_highlight_matched_item?Boolean (readonly, private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/include.rb', line 202

def diff_would_wrongly_highlight_matched_item?
  return false unless actual.is_a?(String) && expected.is_a?(Array)
  return false if Regexp === expecteds.first

  lines = actual.split("\n")
  expected.any? do |str|
    actual.include?(str) && lines.none? { |line| line == str }
  end
end

#diffable?Boolean (readonly)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/include.rb', line 62

def diffable?
  !diff_would_wrongly_highlight_matched_item?
end

#expecteds (readonly)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/include.rb', line 12

attr_reader :expecteds

Instance Method Details

#actual_collection_includes?(expected_item) ⇒ Boolean (private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/include.rb', line 168

def actual_collection_includes?(expected_item)
  return actual.scan(expected_item).size > 0 if Regexp === expected_item && String === actual
  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) ⇒ Boolean (private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/include.rb', line 154

def actual_hash_has_key?(expected_key)
  # We check `key?` first for perf:
  # `key?` is O(1), but `any?` is O(N).

  has_exact_key =
    begin
      actual.key?(expected_key)
    rescue
      false
    end

  has_exact_key || actual.keys.any? { |key| values_match?(expected_key, key) }
end

#actual_hash_includes?(expected_key, expected_value) ⇒ Boolean (private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/include.rb', line 142

def actual_hash_includes?(expected_key, expected_value)
  actual_value =
    actual.fetch(expected_key) do
      actual.find(Proc.new { return false }) { |actual_key, _| values_match?(expected_key, actual_key) }[1]
    end
  values_match?(expected_value, actual_value)
end

#check_actual?(actual) ⇒ Boolean (private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/include.rb', line 78

def check_actual?(actual)
  actual = actual.to_hash if convert_to_hash?(actual)
  @actual = actual
  @actual.respond_to?(:include?)
end

#comparing_hash_keys?(expected_item) ⇒ Boolean (private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/include.rb', line 150

def comparing_hash_keys?(expected_item)
  actual.is_a?(Hash) && !expected_item.is_a?(Hash)
end

#comparing_hash_to_a_subset?(expected_item) ⇒ Boolean (private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/include.rb', line 138

def comparing_hash_to_a_subset?(expected_item)
  actual.is_a?(Hash) && expected_item.is_a?(Hash)
end

#convert_to_hash?(obj) ⇒ Boolean (private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/include.rb', line 212

def convert_to_hash?(obj)
  !obj.respond_to?(:include?) && obj.respond_to?(:to_hash)
end

#count_enumerable(expected_item) (private)

:nocov:

See additional method definition at line 180.

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/include.rb', line 185

def count_enumerable(expected_item)
  actual.select { |value| values_match?(expected_item, value) }.size
end

#count_inclusions (private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/include.rb', line 190

def count_inclusions
  @divergent_items = expected
  case actual
  when String
    actual.scan(expected.first).length
  when Enumerable
    count_enumerable(Hash === expected ? expected : expected.first)
  else
    raise NotImplementedError, 'Count constraints are implemented for Enumerable and String values only'
  end
end

#descriptionString

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/include.rb', line 44

def description
  improve_hash_formatting("include#{readable_list_of(expecteds)}#{count_expectation_description}")
end

#does_not_match?(actual) ⇒ Boolean

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/include.rb', line 33

def does_not_match?(actual)
  check_actual?(actual) &&
    if check_expected_count?
      !expected_count_matches?(count_inclusions)
    else
      perform_match { |v| !v }
    end
end

#excluded_from_actual (private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/include.rb', line 121

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

#expectedArray, Hash

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/include.rb', line 68

def expected
  if expecteds.one? && Hash === expecteds.first
    expecteds.first
  else
    expecteds
  end
end

#failure_messageString

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/include.rb', line 50

def failure_message
  format_failure_message("to") { super }
end

#failure_message_when_negatedString

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/include.rb', line 56

def failure_message_when_negated
  format_failure_message("not to") { super }
end

#format_failure_message(preposition) (private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/include.rb', line 96

def format_failure_message(preposition)
  msg = if actual.respond_to?(:include?)
          "expected #{description_of @actual} #{preposition}" \
          " include#{readable_list_of @divergent_items}" \
          "#{count_failure_reason('it is included') if has_expected_count?}"
        else
          "#{yield}, but it does not respond to `include?`"
        end
  improve_hash_formatting(msg)
end

#matches?(actual) ⇒ Boolean

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/include.rb', line 22

def matches?(actual)
  check_actual?(actual) &&
    if check_expected_count?
      expected_count_matches?(count_inclusions)
    else
      perform_match { |v| v }
    end
end

#perform_match(&block) (private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/include.rb', line 116

def perform_match(&block)
  @divergent_items = excluded_from_actual(&block)
  @divergent_items.empty?
end

#readable_list_of(items) (private)

[ GitHub ]

  
# File 'rspec-expectations/lib/rspec/matchers/built_in/include.rb', line 107

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