module DhEasy::Test::Helper

Public Class Methods

collection_diff(items_a, items_b, opts = {}) click to toggle source

Generate a diff over 2 collections.

@param [Array] items_a List of items to diff. @param [Array] items_b List of items to diff. @param [Hash] opts ({}) Configuration options. @option opts [Boolean] :exact_match (true) Fragmenent should match

element exactly.

@option opts [Boolean] :deep_stringify If `true` then stringify all hash

keys including sublevels before matching.

@option opts [Boolean] :sanitize (true) Sanitize element and filters

when `true`.

@option opts [Array,nil] :skip_keys (nil) Keys to skip on match. @option opts [Symbol] :compare_way (:both) Comparison way sense:

* `:both` Compare left and right.
* `:right` Compare if `items_a` are inside `items_b`.
* `:left` Compare if `items_b` are inside `items_a`.

@return [Hash] Diff results as follows:

* `[Array] :items_a` Diff items on `items_a` collection.
* `[Array] :items_b` Diff items on `items_b` collection.
* `[Boolean] :match` `true` when all items match else `false`.
# File lib/dh_easy/test/helper.rb, line 121
def self.collection_diff items_a, items_b, opts = {}
  # TODO: Improve this function
  #raise NotImplementedError.new('Current status WIP, don\'t use it for now.')
  opts = {
    exact_match: true,
    deep_stringify: true,
    sanitize: true,
    skip_keys: nil,
    compare_way: :both
  }.merge opts

  # Match collections items
  match = nil
  compare_right = opts[:compare_way] == :right || opts[:compare_way] == :both
  compare_left = opts[:compare_way] == :left || opts[:compare_way] == :both
  items_a = items_a.sort{|a,b|b.keys.count <=> a.keys.count}
  items_b = items_b.sort{|a,b|b.keys.count <=> a.keys.count}
  remaining_items = items_b + []
  not_found = []
  items_a.each do |item_a|
    found = remaining_items.find do |item_b|
      match = false
      match ||= match?(item_a, item_b, opts) if compare_left
      match ||= match?(item_b, item_a, opts) if compare_right
      match
    end

    # Save diff
    not_found << item_a if found.nil?
    remaining_items.delete found
  end

  # Send diff results
  {
    items_a: not_found,
    items_b: remaining_items,
    match: (not_found.count < 1 && remaining_items.count < 1)
  }
end
collection_match?(fragment, universe, opts = {}) click to toggle source

Validate when an item collection match universe item collection.

@param [Array] fragment Fragment of universe items to match. @param [Array] universe List of items. @param [Hash] opts ({}) Configuration options. @option opts [Boolean] :exact_match (true) Fragmenent should match

element exactly.

@option opts [Boolean] :same_count (true) Fragment item count should

match universe item count exactly.

@option opts [Boolean] :deep_stringify If `true` then stringify all hash

keys including sublevels before matching.

@option opts [Boolean] :sanitize (true) Sanitize element and filters

when `true`.

@option opts [Array,nil] :skip_keys (nil) Keys to skip on match. @option opts [Symbol] :compare_way (:both) Comparison way sense:

* `:both` Compare left and right.
* `:right` Compare if `items_a` are inside `items_b`.
* `:left` Compare if `items_b` are inside `items_a`.

@return [Boolean]

# File lib/dh_easy/test/helper.rb, line 181
def self.collection_match? fragment, universe, opts = {}
  opts = {
    exact_match: true,
    same_count: true,
    deep_stringify: true,
    sanitize: true,
    skip_keys: nil,
    compare_way: :both
  }.merge opts

  # False when item collections count are different
  return false if (opts[:match_quantity]) && fragment.count != universe.count

  diff = collection_diff fragment, universe, opts
  match = diff[:items_a].count < 1 && diff[:items_b].count < 1
  match
end
delete_keys_from!(hash, keys) click to toggle source

Delete keys from a hash.

@param [Hash] hash Base hash to exclude from. @param [Array] keys Keys to exclude.

@return [Hash]

# File lib/dh_easy/test/helper.rb, line 33
def self.delete_keys_from! hash, keys
  return hash if keys.nil?
  keys.each{|k|hash.delete k}
  hash
end
load_file(file_path, should_exists = false) click to toggle source

Load and return file contents when exists.

@param [String] file_path File path to load. @param [Boolean] should_exists (false) Enforce file existance validation.

@return [String,nil] File contents.

# File lib/dh_easy/test/helper.rb, line 10
def self.load_file file_path, should_exists = false
  return nil unless should_exists || File.exists?(file_path)
  File.open(file_path, 'r', encoding: 'UTF-8').read
end
load_json_file(file_path, should_exists = false) click to toggle source

Load and return file contents as json when exists.

@param [String] file_path File path to load. @param [Boolean] should_exists (false) Enforce file existance validation.

@return [Hash,nil] Json file contents.

# File lib/dh_easy/test/helper.rb, line 21
def self.load_json_file file_path, should_exists = false
  file_content = load_file file_path, should_exists
  return nil if file_content.nil? || file_content.to_s.strip == ''
  JSON.parse(file_content)
end
match?(element, filter, opts = {}) click to toggle source

Check if an hash element match the filter.

@param [Hash] element Element to match. @param [Hash] filter Filters to apply. @param [Hash] opts ({}) Configuration options. @option opts [Boolean] :sanitize (true) Sanitize element and filters

when `true`.

@option opts [Boolean] :deep_stringify If `true` then stringify all hash

keys including sublevels before matching.

@option opts [Boolean] :exact_match (true) Filter should match element

exactly.

@option opts [Array,nil] :skip_keys (nil) Keys to skip on match.

@return [Boolean] `true` when element match filters, else `false`.

# File lib/dh_easy/test/helper.rb, line 74
def self.match? element, filter, opts = {}
  opts = {
    sanitize: true,
    deep_stringify: true,
    exact_match: true,
    skip_keys: nil
  }.merge opts

  # Sanitize element and filter when need
  if opts[:sanitize]
    element = sanitize element, opts
    filter = sanitize filter, opts
  end

  # Validate exact match when need
  exact_match = opts[:exact_match]
  return false if exact_match && element.keys.count != filter.keys.count

  # Match element filter
  filter.each do |k,v|
    return false if exact_match && !element.has_key?(k)
    return false if element[k] != v
  end
  true
end
match_collections(items_a, items_b, opts = {}) click to toggle source

Match two collections and calculate diff.

@param [Array] items_a Item collection to match. @param [Array] items_b Item collection to match. @param [Hash] opts ({}) Configuration options. @option opts [Array] :skip (nil) Keys to skip on match. @option opts [Symbol] :compare_way (:left) Comparison way sense:

* `:both` Compare left and right.
* `:right` Compare if `items_a` are inside `items_b`.
* `:left` Compare if `items_b` are inside `items_a`.

@return [Hash] A hash with the following key pairs:

* `[Hash] :diff` Diff results with `:items_a` and `:items_b` keys.
* `[Boolean] :match` `true` when match else `false`.
# File lib/dh_easy/test/helper.rb, line 213
def self.match_collections items_a, items_b, opts = {}
  diff = collection_diff(
    items_a,
    items_b,
    skip_keys: opts[:skip],
    compare_way: :both
  )
  match = (diff[:items_a].count < 1 && diff[:items_b].count < 1)
  {diff: diff, match: diff[:match]}
end
sanitize(raw_hash, opts) click to toggle source

Sanitize a copy of the hash provided.

@param [Hash] raw_hash Hash to sanitize. @param [Hash] opts ({}) Configuration options. @option opts [Boolean] :deep_stringify If `true` then stringify all hash

keys including sublevels.

@option opts [Array,nil] :skip_keys (nil) Key array to delete from

sanitized hash clone.

@return [Hash] Sanitized hash clone.

# File lib/dh_easy/test/helper.rb, line 49
def self.sanitize raw_hash, opts
  opts = {
    deep_stringify: true,
    skip_keys: nil
  }.merge opts
  hash = (opts[:deep_stringify]) ?
    DhEasy::Core.deep_stringify_keys(raw_hash) :
    DhEasy::Core.deep_clone(raw_hash)
  delete_keys_from! hash, opts[:skip_keys]
end