Class: Minicrest::Contains

Inherits:
Matcher
  • Object
show all
Defined in:
lib/minicrest/contains.rb

Overview

Matcher that checks if a collection contains exactly the specified items in any order.

For arrays: checks that the array has exactly the specified elements (order doesn’t matter) For hashes: checks that the hash has exactly the specified key-value pairs

Examples:

With arrays

contains(1, 2, 3).matches?([3, 1, 2])  # => true
contains(1, 2).matches?([1, 2, 3])      # => false (extra element)

With hashes

contains(a: 1, b: 2).matches?({b: 2, a: 1})  # => true

Instance Method Summary collapse

Methods inherited from Matcher

#&, #|

Constructor Details

#initialize(*items) ⇒ Contains

Creates a new contains matcher.

Parameters:

  • items (Array)

    the items that must be contained (and no others)



19
20
21
22
23
24
# File 'lib/minicrest/contains.rb', line 19

def initialize(*items)
  super()
  @items = items
  @is_hash = items.length == 1 && items.first.is_a?(Hash)
  @expected_hash = @is_hash ? items.first : nil
end

Instance Method Details

#descriptionString

Returns a description of what this matcher expects.

Returns:

  • (String)

    description



46
47
48
49
50
51
52
# File 'lib/minicrest/contains.rb', line 46

def description
  if @is_hash
    "contains exactly #{format_hash(@expected_hash)} (in any order)"
  else
    "contains exactly #{@items.map(&:inspect).join(', ')} (in any order)"
  end
end

#failure_message(actual) ⇒ String

Returns the failure message when the match fails.

Parameters:

  • actual (Array, Hash)

    the collection that was checked

Returns:

  • (String)

    failure message showing differences



58
59
60
61
62
63
64
65
66
67
68
# File 'lib/minicrest/contains.rb', line 58

def failure_message(actual)
  if @is_hash && actual.is_a?(Hash)
    missing = @expected_hash.reject { |k, v| actual[k] == v }
    extra = actual.reject { |k, v| @expected_hash[k] == v }
    build_hash_failure_message(actual, missing, extra)
  else
    missing = @items - actual.to_a
    extra = actual.to_a - @items
    build_array_failure_message(actual, missing, extra)
  end
end

#matches?(actual) ⇒ Boolean

Checks if actual contains exactly the expected items.

Parameters:

  • actual (Array, Hash)

    the collection to check

Returns:

  • (Boolean)

    true if collections have same items



30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/minicrest/contains.rb', line 30

def matches?(actual)
  if @is_hash && actual.is_a?(Hash)
    actual == @expected_hash
  elsif actual.is_a?(Hash)
    false # Can't compare non-hash items to hash
  else
    actual.sort == @items.sort
  end
rescue ArgumentError
  # Sort may fail for uncomparable items, fall back to counting
  count_match?(actual)
end

#negated_failure_message(actual) ⇒ String

Returns the failure message when a negated match fails.

Parameters:

  • actual (Array, Hash)

    the collection that was checked

Returns:

  • (String)

    message indicating unexpected match



74
75
76
77
78
79
80
81
82
83
84
# File 'lib/minicrest/contains.rb', line 74

def negated_failure_message(actual)
  if @is_hash
    <<~MSG.chomp
      expected #{format_hash(actual)} not to contain exactly #{format_hash(@expected_hash)} (in any order), but it did
    MSG
  else
    <<~MSG.chomp
      expected #{actual.inspect} not to contain exactly #{@items.map(&:inspect).join(', ')} (in any order), but it did
    MSG
  end
end