class RSpec::JsonExpectations::JsonTraverser
This class allows to traverse a json actual value along with json expected value for inclusion and check if they match. Errors are accumulated in errors hash for each json atom paths.
Constants
- HANDLED_BY_SIMPLE_VALUE_HANDLER
- RSPECMATCHERS
- SUPPORTED_VALUES
Public Class Methods
traverse(errors, expected, actual, negate=false, prefix=[], options={})
click to toggle source
# File lib/rspec/json_expectations/json_traverser.rb, line 17 def traverse(errors, expected, actual, negate=false, prefix=[], options={}) [ handle_hash(errors, expected, actual, negate, prefix), handle_array(errors, expected, actual, negate, prefix), handle_unordered(errors, expected, actual, negate, prefix, options), handle_value(errors, expected, actual, negate, prefix), handle_regex(errors, expected, actual, negate, prefix), handle_rspec_matcher(errors, expected, actual, negate, prefix), handle_unsupported(expected) ].any? end
Private Class Methods
conditionally_negate(value, negate=false)
click to toggle source
# File lib/rspec/json_expectations/json_traverser.rb, line 158 def conditionally_negate(value, negate=false) value ^ negate end
fetch(actual, key, default=nil)
click to toggle source
# File lib/rspec/json_expectations/json_traverser.rb, line 148 def fetch(actual, key, default=nil) if actual.is_a?(Hash) actual.has_key?(key) ? actual[key] : actual[key.to_s] elsif actual.is_a?(Array) actual[key] else default end end
handle_array(errors, expected, actual, negate=false, prefix=[])
click to toggle source
# File lib/rspec/json_expectations/json_traverser.rb, line 49 def handle_array(errors, expected, actual, negate=false, prefix=[]) return nil unless expected.is_a?(Array) transformed_expected = expected.each_with_index.map { |v, k| [k, v] } handle_keyvalue(errors, transformed_expected, actual, negate, prefix) end
handle_hash(errors, expected, actual, negate=false, prefix=[])
click to toggle source
# File lib/rspec/json_expectations/json_traverser.rb, line 43 def handle_hash(errors, expected, actual, negate=false, prefix=[]) return nil unless expected.is_a?(Hash) handle_keyvalue(errors, expected, actual, negate, prefix) end
handle_keyvalue(errors, expected, actual, negate=false, prefix=[])
click to toggle source
# File lib/rspec/json_expectations/json_traverser.rb, line 31 def handle_keyvalue(errors, expected, actual, negate=false, prefix=[]) expected.map do |key, value| new_prefix = prefix + [key] if has_key?(actual, key) traverse(errors, value, fetch(actual, key), negate, new_prefix) else errors[new_prefix.join("/")] = :no_key unless negate conditionally_negate(false, negate) end end.all? || false end
handle_regex(errors, expected, actual, negate=false, prefix=[])
click to toggle source
# File lib/rspec/json_expectations/json_traverser.rb, line 101 def handle_regex(errors, expected, actual, negate=false, prefix=[]) return nil unless expected.is_a?(Regexp) if conditionally_negate(!!expected.match(actual.to_s), negate) true else errors[prefix.join("/")] = { actual: actual, expected: expected } false end end
handle_rspec_matcher(errors, expected, actual, negate=false, prefix=[])
click to toggle source
# File lib/rspec/json_expectations/json_traverser.rb, line 115 def handle_rspec_matcher(errors, expected, actual, negate=false, prefix=[]) return nil unless defined?(RSpec::Matchers) return nil unless expected.is_a?(RSpec::Matchers::BuiltIn::BaseMatcher) || expected.is_a?(RSpec::Matchers::AliasedMatcher) if conditionally_negate(!!expected.matches?(actual), negate) true else errors[prefix.join("/")] = { actual: actual, expected: expected.description } false end end
handle_unordered(errors, expected, actual, negate=false, prefix=[], options={})
click to toggle source
# File lib/rspec/json_expectations/json_traverser.rb, line 56 def handle_unordered(errors, expected, actual, negate=false, prefix=[], options={}) return nil unless expected.is_a?(Matchers::UnorderedArrayMatcher) match_size_assertion_result = \ match_size_of_collection(errors, expected, actual, prefix, options) if match_size_assertion_result == false conditionally_negate(false, negate) else conditionally_negate(expected.match(errors, actual, prefix), negate) end end
handle_unsupported(expected)
click to toggle source
# File lib/rspec/json_expectations/json_traverser.rb, line 131 def handle_unsupported(expected) unless SUPPORTED_VALUES.any? { |type| expected.is_a?(type) } raise NotImplementedError, "#{expected} expectation is not supported" end end
handle_value(errors, expected, actual, negate=false, prefix=[])
click to toggle source
# File lib/rspec/json_expectations/json_traverser.rb, line 83 def handle_value(errors, expected, actual, negate=false, prefix=[]) return nil unless handled_by_simple_value?(expected) if conditionally_negate(actual == expected, negate) true else errors[prefix.join("/")] = { actual: actual, expected: expected } false end end
handled_by_simple_value?(expected)
click to toggle source
# File lib/rspec/json_expectations/json_traverser.rb, line 97 def handled_by_simple_value?(expected) HANDLED_BY_SIMPLE_VALUE_HANDLER.any? { |type| type === expected } end
has_key?(actual, key)
click to toggle source
# File lib/rspec/json_expectations/json_traverser.rb, line 138 def has_key?(actual, key) if actual.is_a?(Hash) actual.has_key?(key) || actual.has_key?(key.to_s) elsif actual.is_a?(Array) actual.count > key else false end end
match_size_of_collection(errors, expected, actual, prefix, options)
click to toggle source
# File lib/rspec/json_expectations/json_traverser.rb, line 69 def match_size_of_collection(errors, expected, actual, prefix, options) match_size = options[:match_size] return nil unless match_size return nil if expected.size == actual.size errors[prefix.join("/")] = { _size_mismatch_error: true, expected: expected.unwrap_array, actual: actual, extra_elements: actual - expected.unwrap_array, } false end