Module: RSpec::JsonApi::CompareHash

Extended by:
CompareHash
Included in:
CompareHash
Defined in:
lib/rspec/json_api/compare_hash.rb

Constant Summary collapse

SUPPORTED_OPTIONS =
%i[allow_blank type value min max inclusion regex lambda].freeze

Instance Method Summary collapse

Instance Method Details

#compare(actual, expected) ⇒ Object



10
11
12
13
14
15
16
# File 'lib/rspec/json_api/compare_hash.rb', line 10

def compare(actual, expected)
  return false if actual.blank? && expected.present?

  keys = expected.deep_key_paths | actual.deep_key_paths

  compare_key_paths_and_values(keys, actual, expected)
end

#compare_array(actual_value, expected_value) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/rspec/json_api/compare_hash.rb', line 83

def compare_array(actual_value, expected_value)
  if simple_type?(expected_value)
    type = expected_value[0]

    actual_value.all? { |elem| compare_class(elem, type) }
  elsif interface?(expected_value)
    interface = expected_value[0]

    actual_value.all? { |elem| compare(elem, interface) }
  else
    return false if actual_value&.size != expected_value&.size

    expected_value.each_with_index.all? do |elem, index|
      elem.is_a?(Hash) ? compare(actual_value[index], elem) : compare_simple_value(actual_value[index], elem)
    end
  end
end

#compare_class(actual_value, expected_value) ⇒ Object



42
43
44
# File 'lib/rspec/json_api/compare_hash.rb', line 42

def compare_class(actual_value, expected_value)
  actual_value.instance_of?(expected_value)
end

#compare_key_paths_and_values(keys, actual, expected) ⇒ Object



18
19
20
21
22
23
24
25
# File 'lib/rspec/json_api/compare_hash.rb', line 18

def compare_key_paths_and_values(keys, actual, expected)
  keys.all? do |key_path|
    actual_value = actual.dig(*key_path)
    expected_value = expected.dig(*key_path)

    compare_values(actual_value, expected_value)
  end
end

#compare_proc(actual_value, expected_value) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/rspec/json_api/compare_hash.rb', line 50

def compare_proc(actual_value, expected_value)
  payload = expected_value.call
  payload.sanitize!(SUPPORTED_OPTIONS)
  payload = payload.sort_by { |k, _v| k == :allow_blank ? 0 : 1 }.to_h

  payload.all? do |condition_key, condition_value|
    case condition_key
    when :allow_blank
      return true if actual_value.blank? && condition_value

      true
    when :type
      compare_class(actual_value, condition_value)
    when :value
      compare_simple_value(actual_value, condition_value)
    when :inclusion
      condition_value.include?(actual_value)
    when :min
      return false if !condition_value.is_a?(Numeric) || !actual_value.is_a?(Numeric)

      actual_value >= condition_value
    when :max
      return false if !condition_value.is_a?(Numeric) || !actual_value.is_a?(Numeric)

      actual_value <= condition_value
    when :regex
      compare_regexp(actual_value, condition_value)
    when :lambda
      condition_value.call(actual_value)
    end
  end
end

#compare_regexp(actual_value, expected_value) ⇒ Object



46
47
48
# File 'lib/rspec/json_api/compare_hash.rb', line 46

def compare_regexp(actual_value, expected_value)
  actual_value.to_s =~ expected_value
end

#compare_simple_value(actual_value, expected_value) ⇒ Object



101
102
103
# File 'lib/rspec/json_api/compare_hash.rb', line 101

def compare_simple_value(actual_value, expected_value)
  actual_value == expected_value
end

#compare_values(actual_value, expected_value) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/rspec/json_api/compare_hash.rb', line 27

def compare_values(actual_value, expected_value)
  case expected_value
  when Class
    compare_class(actual_value, expected_value)
  when Regexp
    compare_regexp(actual_value, expected_value)
  when Proc
    compare_proc(actual_value, expected_value)
  when Array
    compare_array(actual_value, expected_value)
  else
    compare_simple_value(actual_value, expected_value)
  end
end

#interface?(expected_value) ⇒ Boolean

Returns:

  • (Boolean)


109
110
111
# File 'lib/rspec/json_api/compare_hash.rb', line 109

def interface?(expected_value)
  expected_value.size == 1 && expected_value[0].is_a?(Hash)
end

#simple_type?(expected_value) ⇒ Boolean

Returns:

  • (Boolean)


105
106
107
# File 'lib/rspec/json_api/compare_hash.rb', line 105

def simple_type?(expected_value)
  expected_value.size == 1 && expected_value[0].instance_of?(Class)
end