Module: JSONSpectacular::DiffDescriptions
- Included in:
- Matcher
- Defined in:
- lib/json_spectacular/diff_descriptions.rb
Class Method Summary collapse
-
.included(base) ⇒ Object
rubocop:disable Metrics/MethodLength.
Class Method Details
.included(base) ⇒ Object
rubocop:disable Metrics/MethodLength
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/json_spectacular/diff_descriptions.rb', line 7 def self.included(base) # rubocop:disable Metrics/MethodLength base.class_eval do # rubocop:disable Metrics/BlockLength # Adds diff descriptions to the failure message until the all the nodes of the # expected and actual values have been compared, and all the differences (and the # paths to them) have been included. # # For Hashes and Arrays, it recursively calls itself to compare all nodes and # elements. # # @param [String, Number, Boolean, Array, Hash] actual_value current node of the # actual value being compared to the corresponding node of the expected # value # @param [String, Number, Boolean, Array, Hash] expected_value current node of # the expected value being compared to the corresponding node of the # actual value # @param [String] path path to the current nodes being compared, relative to the # root full objects # @return void Diff descriptions are appended directly to message def (actual_value, expected_value, path = '') diffs_sorted_by_name = Hashdiff .diff(actual_value, expected_value) .sort_by { |a| a[1] } diffs_grouped_by_name = diffs_sorted_by_name.each_with_object({}) do |diff, memo| operator, name, value = diff memo[name] ||= {} memo[name][operator] = value end diffs_grouped_by_name.each do |name, difference| resolve_and_append_diff_to( path, name, expected_value, actual_value, difference ) end end def resolve_and_append_diff_to( path, name, expected_value, actual_value, difference ) extra_value, missing_value, different_value = resolve_changes(difference, expected_value, actual_value, name) full_path = !path.empty? ? "#{path}.#{name}" : name if non_empty_hash?(missing_value) && non_empty_hash?(extra_value) (missing_value, extra_value, full_path) elsif non_empty_array?(missing_value) && non_empty_array?(extra_value) [missing_value.length, extra_value.length].max.times do |i| (missing_value[i], extra_value[i], full_path) end elsif difference.key?('~') value = value_at_path(expected_value, name) (full_path, value, different_value) else (full_path, extra_value, missing_value) end end def resolve_changes(difference, expected_value, actual_value, name) missing_value = difference['-'] || value_at_path(actual_value, name) extra_value = difference['+'] || value_at_path(expected_value, name) different_value = difference['~'] [extra_value, missing_value, different_value] end def (path, expected, actual) ( path, get_diff(path, expected: expected, actual: actual) ) end def non_empty_hash?(target) target.is_a?(Hash) && target.any? end def non_empty_array?(target) target.is_a?(Array) && target.any? end def (attribute, diff_description) return if already_reported_difference?(attribute) += diff_description @reported_differences[attribute] = true end def already_reported_difference?(attribute) @reported_differences.key?(attribute) end def value_at_path(target, attribute_path) keys = attribute_path.split(/[\[\].]/) keys = keys.map do |key| if key.to_i.zero? && key != '0' key else key.to_i end end result = target keys.each do |key| result = result[key] unless key == '' end result end def get_diff(attribute, = {}) diff_description = '' diff_description += "#{attribute}\n" diff_description += "Expected: #{format_value(options[:expected])}\n" diff_description + "Actual: #{format_value(options[:actual])}\n\n" end def format_value(value) if value.is_a?(String) "'#{value}'" else value end end end end |