cloudfoundry/cloud_controller_ng

View on GitHub
spec/support/matchers/match_object.rb

Summary

Maintainability
A
1 hr
Test Coverage
RSpec::Matchers.define :match_object do |expected|
  match do |actual|
    expected == actual
  end

  failure_message do |actual|
    break if actual == expected

    object_eq(actual, expected)
    @error_message.join("\n")
  end

  def object_eq(actual, expected, path=[])
    @error_message ||= []

    types = [actual, expected].map(&:class).uniq

    if types == [Hash]
      compare_arrays(actual.keys, expected.keys, path, actual)
      expected.each do |k, expected_val|
        object_eq(actual[k], expected_val, path + [k])
      end

    elsif types == [Array]
      if compare_arrays(actual, expected, path)
        expected.each_with_index do |expected_el, i|
          object_eq(actual[i], expected_el, path + ["[#{i}]"])
        end
      end

    elsif types.size == 1 # same class
      @error_message << "Mismatched values in #{path}:"
      @error_message << "\t  actual=#{actual}"
      @error_message << "\texpected=#{expected}"

    else
      @error_message << "Mismatched types in #{path}:"
      @error_message << "\t  actual=#{types[0]} value=#{actual.inspect}"
      @error_message << "\texpected=#{types[1]} value=#{expected.inspect}"
    end
  end

  def compare_arrays(actual, expected, path, context=actual)
    if expected.size == actual.size
      true
    else
      @error_message << "Extra/missing elements in #{path}:"
      @error_message << "\tactual=#{actual.size} expected=#{expected.size}"
      @error_message << "\textra=#{actual - expected}"
      @error_message << "\tmissing=#{expected - actual}"
      @error_message << "\tcontext=#{context}"
      false
    end
  end
end