class JsonRspecMatchMaker::Base

Base class that abstracts away all of the work of using the @match_definition

Attributes

expected[R]

The object being expected against @api private @return [Object]

match_definition[R]

Data structure that specifies how instance values relate to JSON values @api private @return [Hash]

target[R]

The json being tested @api private @return [Hash]

Public Class Methods

new(expected, match_definition, prefix: '') click to toggle source

Create a new JSON matcher @api public @param expected [Object] The object being serialized into JSON @example

JsonRspecMatchMaker.new(active_record_model)
JsonRspecMatchMaker.new(presenter_instance)
# File lib/json_rspec_match_maker/base.rb, line 27
def initialize(expected, match_definition, prefix: '')
  @expected = expected
  @match_definition = expand_definition(match_definition)
  @errors = {}
  @prefix = prefix
end

Public Instance Methods

failure_message() click to toggle source

Error reporting method called by RSpec @api public @return [String] @example

match_maker.failure_message #=> 'Mismatch in field name: expected (Freddy) got (Harold)'
# File lib/json_rspec_match_maker/base.rb, line 51
def failure_message
  @errors.values.join('\n')
end
matches?(target) click to toggle source

Match method called by RSpec @api public @return [Bool] @example

JsonRspecMatchMaker.new(user).matches?(user.to_json) #=> true
JsonRspecMatchMaker.new(dog).matches?(cat.to_json) #=> false
# File lib/json_rspec_match_maker/base.rb, line 40
def matches?(target)
  @target = target
  check_target_against_expected
  @errors.empty?
end

Private Instance Methods

add_error(expected_value, target_value) click to toggle source

Adds an erorr to the list when a mismatch is detected @api private @return [String] the error message

# File lib/json_rspec_match_maker/base.rb, line 134
    def add_error(expected_value, target_value)
      @errors[target_value.error_key] = <<-MSG

        Mismatch in field: '#{target_value.error_key}'
          expected: '#{expected_value.value}'
          received: '#{target_value.value}'

      MSG
    end
check_definition(definition, current_expected, current_key = nil) click to toggle source
# File lib/json_rspec_match_maker/base.rb, line 88
def check_definition(definition, current_expected, current_key = nil)
  definition.each do |error_key, match_def|
    if match_def.is_a? Hash
      key = [current_key, error_key].compact.join('.')
      check_each(key, match_def, current_expected)
    else
      check_values(current_key, error_key, match_def, current_expected)
    end
  end
end
check_each(error_key, each_definition, current_expected) click to toggle source

Iterates through a list of objects while checking fields @api private @param error_key [String]

the first name of the field reported in the error
each errors are reported #{error_key}[#{idx}].#{each_key}

@param each_definition [Hash]

:each is a function that returns the list of items
:attributes is a hash with the same structure as the top-level match_def hash

@return [nil] returns nothing, adds to error list as side effect

# File lib/json_rspec_match_maker/base.rb, line 108
def check_each(error_key, each_definition, current_expected)
  enumerable = each_definition[:each].call(current_expected)
  enumerable.each_with_index do |each_instance, idx|
    full_key = [error_key, idx].join('.')
    check_definition(each_definition[:attributes], each_instance, full_key)
  end
end
check_target_against_expected() click to toggle source

Walks through the match definition, collecting errors for each field @api private @raise [MatchDefinitionNotFound] if child class does not set @match_definition @return [nil] returns nothing, adds to error list as side effect

# File lib/json_rspec_match_maker/base.rb, line 84
def check_target_against_expected
  check_definition(@match_definition, expected)
end
check_values(key_prefix, error_key, match_function, expected_instance = expected) click to toggle source

Checks fields on a single instance @api private @param error_key [String] the name of the field reported in the error @param match_function [Hash]

a function returning the value for the key for the object being serialized

@param expected_instance [Object]

the top level instance, or an each instance from #check_each

the index if iterating through a list, otherwise nil @return [nil] returns nothing, adds to error list as side effect

# File lib/json_rspec_match_maker/base.rb, line 125
def check_values(key_prefix, error_key, match_function, expected_instance = expected)
  expected_value = ExpectedValue.new(match_function, expected_instance, error_key, @prefix)
  target_value = TargetValue.new([key_prefix, error_key].compact.join('.'), target)
  add_error(expected_value, target_value) unless expected_value == target_value
end
expand_definition(definition) click to toggle source

expands simple arrays into full hash definitions @api private

# File lib/json_rspec_match_maker/base.rb, line 59
def expand_definition(definition)
  return definition if definition.is_a? Hash
  definition.each_with_object({}) do |key, result|
    if key.is_a? String
      result[key] = :default
    elsif key.is_a? Hash
      result.merge!(expand_sub_definitions(key))
    end
  end
end
expand_sub_definitions(sub_definitions) click to toggle source

expands nested simple definition into a full hash @api private

# File lib/json_rspec_match_maker/base.rb, line 72
def expand_sub_definitions(sub_definitions)
  sub_definitions.each_with_object({}) do |(subkey, value), result|
    result[subkey] = value
    next if value.respond_to? :call
    result[subkey][:attributes] = expand_definition(value[:attributes])
  end
end