Module: AeEasy::Test::Helper

Defined in:
lib/ae_easy/test/helper.rb

Class Method Summary collapse

Class Method Details

.collection_diff(items_a, items_b, opts = {}) ⇒ Hash

Generate a diff over 2 collections.

Parameters:

  • items_a (Array)

    List of items to diff.

  • items_b (Array)

    List of items to diff.

  • opts (Hash) (defaults to: {})

    ({}) Configuration options.

Options Hash (opts):

  • :exact_match (Boolean) — default: true

    Fragmenent should match element exactly.

  • :deep_stringify (Boolean)

    If `true` then stringify all hash keys including sublevels before matching.

  • :sanitize (Boolean) — default: true

    Sanitize element and filters when `true`.

  • :skip_keys (Array, nil) — default: nil

    Keys to skip on match.

  • :compare_way (Symbol) — default: :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`.

Returns:

  • (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`.



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/ae_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 = {}) ⇒ Boolean

Validate when an item collection match universe item collection.

Parameters:

  • fragment (Array)

    Fragment of universe items to match.

  • universe (Array)

    List of items.

  • opts (Hash) (defaults to: {})

    ({}) Configuration options.

Options Hash (opts):

  • :exact_match (Boolean) — default: true

    Fragmenent should match element exactly.

  • :same_count (Boolean) — default: true

    Fragment item count should match universe item count exactly.

  • :deep_stringify (Boolean)

    If `true` then stringify all hash keys including sublevels before matching.

  • :sanitize (Boolean) — default: true

    Sanitize element and filters when `true`.

  • :skip_keys (Array, nil) — default: nil

    Keys to skip on match.

  • :compare_way (Symbol) — default: :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`.

Returns:

  • (Boolean)


181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/ae_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) ⇒ Hash

Delete keys from a hash.

Parameters:

  • hash (Hash)

    Base hash to exclude from.

  • keys (Array)

    Keys to exclude.

Returns:

  • (Hash)


33
34
35
36
37
# File 'lib/ae_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) ⇒ String?

Load and return file contents when exists.

Parameters:

  • file_path (String)

    File path to load.

  • should_exists (Boolean) (defaults to: false)

    (false) Enforce file existance validation.

Returns:

  • (String, nil)

    File contents.



10
11
12
13
# File 'lib/ae_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) ⇒ Hash?

Load and return file contents as json when exists.

Parameters:

  • file_path (String)

    File path to load.

  • should_exists (Boolean) (defaults to: false)

    (false) Enforce file existance validation.

Returns:

  • (Hash, nil)

    Json file contents.



21
22
23
24
25
# File 'lib/ae_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 = {}) ⇒ Boolean

Check if an hash element match the filter.

Parameters:

  • element (Hash)

    Element to match.

  • filter (Hash)

    Filters to apply.

  • opts (Hash) (defaults to: {})

    ({}) Configuration options.

Options Hash (opts):

  • :sanitize (Boolean) — default: true

    Sanitize element and filters when `true`.

  • :deep_stringify (Boolean)

    If `true` then stringify all hash keys including sublevels before matching.

  • :exact_match (Boolean) — default: true

    Filter should match element exactly.

  • :skip_keys (Array, nil) — default: nil

    Keys to skip on match.

Returns:

  • (Boolean)

    `true` when element match filters, else `false`.



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
# File 'lib/ae_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 = {}) ⇒ Hash

Match two collections and calculate diff.

Parameters:

  • items_a (Array)

    Item collection to match.

  • items_b (Array)

    Item collection to match.

  • opts (Hash) (defaults to: {})

    ({}) Configuration options.

Options Hash (opts):

  • :skip (Array) — default: nil

    Keys to skip on match.

  • :compare_way (Symbol) — default: :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`.

Returns:

  • (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`.



213
214
215
216
217
218
219
220
221
222
# File 'lib/ae_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) ⇒ Hash

Sanitize a copy of the hash provided.

Parameters:

  • raw_hash (Hash)

    Hash to sanitize.

  • opts (Hash)

    ({}) Configuration options.

Options Hash (opts):

  • :deep_stringify (Boolean)

    If `true` then stringify all hash keys including sublevels.

  • :skip_keys (Array, nil) — default: nil

    Key array to delete from sanitized hash clone.

Returns:

  • (Hash)

    Sanitized hash clone.



49
50
51
52
53
54
55
56
57
58
# File 'lib/ae_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]) ?
    AeEasy::Core.deep_stringify_keys(raw_hash) :
    AeEasy::Core.deep_clone(raw_hash)
  delete_keys_from! hash, opts[:skip_keys]
end