hashdiff 0.3.7 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/hashdiff/util.rb CHANGED
@@ -1,21 +1,22 @@
1
- module HashDiff
1
+ # frozen_string_literal: true
2
2
 
3
+ module Hashdiff
3
4
  # @private
4
5
  #
5
6
  # judge whether two objects are similar
6
- def self.similar?(a, b, options = {})
7
- return compare_values(a, b, options) unless a.is_a?(Array) || a.is_a?(Hash) || b.is_a?(Array) || b.is_a?(Hash)
8
- opts = { :similarity => 0.8 }.merge(options)
7
+ def self.similar?(obja, objb, options = {})
8
+ return compare_values(obja, objb, options) if !options[:comparison] && !any_hash_or_array?(obja, objb)
9
9
 
10
- count_a = count_nodes(a)
11
- count_b = count_nodes(b)
12
- diffs = count_diff diff(a, b, opts)
10
+ count_a = count_nodes(obja)
11
+ count_b = count_nodes(objb)
13
12
 
14
- if count_a + count_b == 0
15
- return true
16
- else
17
- (1 - diffs.to_f/(count_a + count_b).to_f) >= opts[:similarity]
18
- end
13
+ return true if (count_a + count_b).zero?
14
+
15
+ opts = { similarity: 0.8 }.merge!(options)
16
+
17
+ diffs = count_diff diff(obja, objb, opts)
18
+
19
+ (1 - diffs / (count_a + count_b).to_f) >= opts[:similarity]
19
20
  end
20
21
 
21
22
  # @private
@@ -25,7 +26,7 @@ module HashDiff
25
26
  diffs.inject(0) do |sum, item|
26
27
  old_change_count = count_nodes(item[2])
27
28
  new_change_count = count_nodes(item[3])
28
- sum += (old_change_count + new_change_count)
29
+ sum + (old_change_count + new_change_count)
29
30
  end
30
31
  end
31
32
 
@@ -37,9 +38,9 @@ module HashDiff
37
38
 
38
39
  count = 0
39
40
  if obj.is_a?(Array)
40
- obj.each {|e| count += count_nodes(e) }
41
+ obj.each { |e| count += count_nodes(e) }
41
42
  elsif obj.is_a?(Hash)
42
- obj.each {|k, v| count += count_nodes(v) }
43
+ obj.each_value { |v| count += count_nodes(v) }
43
44
  else
44
45
  return 1
45
46
  end
@@ -54,13 +55,13 @@ module HashDiff
54
55
  # @param [String] delimiter Property-string delimiter
55
56
  #
56
57
  # e.g. "a.b[3].c" => ['a', 'b', 3, 'c']
57
- def self.decode_property_path(path, delimiter='.')
58
+ def self.decode_property_path(path, delimiter = '.')
58
59
  path.split(delimiter).inject([]) do |memo, part|
59
60
  if part =~ /^(.*)\[(\d+)\]$/
60
- if $1.size > 0
61
- memo + [$1, $2.to_i]
61
+ if !Regexp.last_match(1).empty?
62
+ memo + [Regexp.last_match(1), Regexp.last_match(2).to_i]
62
63
  else
63
- memo + [$2.to_i]
64
+ memo + [Regexp.last_match(2).to_i]
64
65
  end
65
66
  else
66
67
  memo + [part]
@@ -83,8 +84,8 @@ module HashDiff
83
84
  #
84
85
  # check for equality or "closeness" within given tolerance
85
86
  def self.compare_values(obj1, obj2, options = {})
86
- if (options[:numeric_tolerance].is_a? Numeric) &&
87
- [obj1, obj2].all? { |v| v.is_a? Numeric }
87
+ if options[:numeric_tolerance].is_a?(Numeric) &&
88
+ obj1.is_a?(Numeric) && obj2.is_a?(Numeric)
88
89
  return (obj1 - obj2).abs <= options[:numeric_tolerance]
89
90
  end
90
91
 
@@ -105,10 +106,10 @@ module HashDiff
105
106
  #
106
107
  # check if objects are comparable
107
108
  def self.comparable?(obj1, obj2, strict = true)
108
- [Array, Hash].each do |type|
109
- return true if obj1.is_a?(type) && obj2.is_a?(type)
110
- end
109
+ return true if (obj1.is_a?(Array) || obj1.is_a?(Hash)) && obj2.is_a?(obj1.class)
110
+ return true if (obj2.is_a?(Array) || obj2.is_a?(Hash)) && obj1.is_a?(obj2.class)
111
111
  return true if !strict && obj1.is_a?(Numeric) && obj2.is_a?(Numeric)
112
+
112
113
  obj1.is_a?(obj2.class) && obj2.is_a?(obj1.class)
113
114
  end
114
115
 
@@ -116,23 +117,20 @@ module HashDiff
116
117
  #
117
118
  # try custom comparison
118
119
  def self.custom_compare(method, key, obj1, obj2)
119
- if method
120
- res = method.call(key, obj1, obj2)
121
-
122
- # nil != false here
123
- if res == false
124
- return [['~', key, obj1, obj2]]
125
- elsif res == true
126
- return []
127
- end
128
- end
120
+ return unless method
121
+
122
+ res = method.call(key, obj1, obj2)
123
+
124
+ # nil != false here
125
+ return [['~', key, obj1, obj2]] if res == false
126
+ return [] if res == true
129
127
  end
130
128
 
131
129
  def self.prefix_append_key(prefix, key, opts)
132
130
  if opts[:array_path]
133
131
  prefix + [key]
134
132
  else
135
- prefix.empty? ? "#{key}" : "#{prefix}#{opts[:delimiter]}#{key}"
133
+ prefix.empty? ? key.to_s : "#{prefix}#{opts[:delimiter]}#{key}"
136
134
  end
137
135
  end
138
136
 
@@ -143,4 +141,15 @@ module HashDiff
143
141
  "#{prefix}[#{array_index}]"
144
142
  end
145
143
  end
144
+
145
+ class << self
146
+ private
147
+
148
+ # @private
149
+ #
150
+ # checks if both objects are Arrays or Hashes
151
+ def any_hash_or_array?(obja, objb)
152
+ obja.is_a?(Array) || obja.is_a?(Hash) || objb.is_a?(Array) || objb.is_a?(Hash)
153
+ end
154
+ end
146
155
  end
@@ -1,3 +1,5 @@
1
- module HashDiff
2
- VERSION = '0.3.7'
1
+ # frozen_string_literal: true
2
+
3
+ module Hashdiff
4
+ VERSION = '1.0.1'.freeze
3
5
  end
@@ -1,74 +1,75 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
- describe HashDiff do
4
- it "should be able to best diff" do
5
- a = {'x' => [{'a' => 1, 'c' => 3, 'e' => 5}, {'y' => 3}]}
6
- b = {'x' => [{'a' => 1, 'b' => 2, 'e' => 5}] }
5
+ describe Hashdiff do
6
+ it 'is able to best diff' do
7
+ a = { 'x' => [{ 'a' => 1, 'c' => 3, 'e' => 5 }, { 'y' => 3 }] }
8
+ b = { 'x' => [{ 'a' => 1, 'b' => 2, 'e' => 5 }] }
7
9
 
8
- diff = HashDiff.best_diff(a, b)
9
- diff.should == [["-", "x[0].c", 3], ["+", "x[0].b", 2], ["-", "x[1]", {"y"=>3}]]
10
+ diff = described_class.best_diff(a, b)
11
+ diff.should == [['-', 'x[0].c', 3], ['+', 'x[0].b', 2], ['-', 'x[1]', { 'y' => 3 }]]
10
12
  end
11
13
 
12
- it "should use custom delimiter when provided" do
13
- a = {'x' => [{'a' => 1, 'c' => 3, 'e' => 5}, {'y' => 3}]}
14
- b = {'x' => [{'a' => 1, 'b' => 2, 'e' => 5}] }
14
+ it 'uses custom delimiter when provided' do
15
+ a = { 'x' => [{ 'a' => 1, 'c' => 3, 'e' => 5 }, { 'y' => 3 }] }
16
+ b = { 'x' => [{ 'a' => 1, 'b' => 2, 'e' => 5 }] }
15
17
 
16
- diff = HashDiff.best_diff(a, b, :delimiter => "\t")
17
- diff.should == [["-", "x[0]\tc", 3], ["+", "x[0]\tb", 2], ["-", "x[1]", {"y"=>3}]]
18
+ diff = described_class.best_diff(a, b, delimiter: "\t")
19
+ diff.should == [['-', "x[0]\tc", 3], ['+', "x[0]\tb", 2], ['-', 'x[1]', { 'y' => 3 }]]
18
20
  end
19
21
 
20
- it "should use custom comparison when provided" do
21
- a = {'x' => [{'a' => 'foo', 'c' => 'goat', 'e' => 'snake'}, {'y' => 'baz'}]}
22
- b = {'x' => [{'a' => 'bar', 'b' => 'cow', 'e' => 'puppy'}] }
22
+ it 'uses custom comparison when provided' do
23
+ a = { 'x' => [{ 'a' => 'foo', 'c' => 'goat', 'e' => 'snake' }, { 'y' => 'baz' }] }
24
+ b = { 'x' => [{ 'a' => 'bar', 'b' => 'cow', 'e' => 'puppy' }] }
23
25
 
24
- diff = HashDiff.best_diff(a, b) do |path, obj1, obj2|
26
+ diff = described_class.best_diff(a, b) do |path, obj1, obj2|
25
27
  case path
26
28
  when /^x\[.\]\..$/
27
- obj1.length == obj2.length if obj1 and obj2
29
+ obj1.length == obj2.length if obj1 && obj2
28
30
  end
29
31
  end
30
32
 
31
- diff.should == [["-", "x[0].c", 'goat'], ["+", "x[0].b", 'cow'], ["-", "x[1]", {"y"=>'baz'}]]
33
+ diff.should == [['-', 'x[0].c', 'goat'], ['+', 'x[0].b', 'cow'], ['-', 'x[1]', { 'y' => 'baz' }]]
32
34
  end
33
35
 
34
- it "should be able to best diff array in hash" do
35
- a = {"menu" => {
36
- "id" => "file",
37
- "value" => "File",
38
- "popup" => {
39
- "menuitem" => [
40
- {"value" => "New", "onclick" => "CreateNewDoc()"},
41
- {"value" => "Close", "onclick" => "CloseDoc()"}
36
+ it 'is able to best diff array in hash' do
37
+ a = { 'menu' => {
38
+ 'id' => 'file',
39
+ 'value' => 'File',
40
+ 'popup' => {
41
+ 'menuitem' => [
42
+ { 'value' => 'New', 'onclick' => 'CreateNewDoc()' },
43
+ { 'value' => 'Close', 'onclick' => 'CloseDoc()' }
42
44
  ]
43
45
  }
44
- }}
46
+ } }
45
47
 
46
- b = {"menu" => {
47
- "id" => "file 2",
48
- "value" => "File",
49
- "popup" => {
50
- "menuitem" => [
51
- {"value" => "New1", "onclick" => "CreateNewDoc()"},
52
- {"value" => "Open", "onclick" => "OpenDoc()"},
53
- {"value" => "Close", "onclick" => "CloseDoc()"}
48
+ b = { 'menu' => {
49
+ 'id' => 'file 2',
50
+ 'value' => 'File',
51
+ 'popup' => {
52
+ 'menuitem' => [
53
+ { 'value' => 'New1', 'onclick' => 'CreateNewDoc()' },
54
+ { 'value' => 'Open', 'onclick' => 'OpenDoc()' },
55
+ { 'value' => 'Close', 'onclick' => 'CloseDoc()' }
54
56
  ]
55
57
  }
56
- }}
58
+ } }
57
59
 
58
- diff = HashDiff.best_diff(a, b)
60
+ diff = described_class.best_diff(a, b)
59
61
  diff.should == [
60
62
  ['~', 'menu.id', 'file', 'file 2'],
61
63
  ['~', 'menu.popup.menuitem[0].value', 'New', 'New1'],
62
- ['+', 'menu.popup.menuitem[1]', {"value" => "Open", "onclick" => "OpenDoc()"}]
64
+ ['+', 'menu.popup.menuitem[1]', { 'value' => 'Open', 'onclick' => 'OpenDoc()' }]
63
65
  ]
64
66
  end
65
67
 
66
- it "should be able to have an array_path specified" do
67
- a = {'x' => [{'a' => 1, 'c' => 3, 'e' => 5}, {'y' => 3}]}
68
- b = {'x' => [{'a' => 1, 'b' => 2, 'e' => 5}] }
68
+ it 'is able to have an array_path specified' do
69
+ a = { 'x' => [{ 'a' => 1, 'c' => 3, 'e' => 5 }, { 'y' => 3 }] }
70
+ b = { 'x' => [{ 'a' => 1, 'b' => 2, 'e' => 5 }] }
69
71
 
70
- diff = HashDiff.best_diff(a, b, :array_path => true)
71
- diff.should == [["-", ["x", 0, "c"], 3], ["+", ["x", 0, "b"], 2], ["-", ["x", 1], {"y"=>3}]]
72
+ diff = described_class.best_diff(a, b, array_path: true)
73
+ diff.should == [['-', ['x', 0, 'c'], 3], ['+', ['x', 0, 'b'], 2], ['-', ['x', 1], { 'y' => 3 }]]
72
74
  end
73
-
74
75
  end
@@ -1,60 +1,60 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
- describe HashDiff do
4
- it "should be able to diff two equal array" do
5
+ describe Hashdiff do
6
+ it 'is able to diff two equal array' do
5
7
  a = [1, 2, 3]
6
8
  b = [1, 2, 3]
7
9
 
8
- diff = HashDiff.diff_array_lcs(a, b)
10
+ diff = described_class.diff_array_lcs(a, b)
9
11
  diff.should == []
10
12
  end
11
13
 
12
- it "should be able to diff two arrays with one element in common" do
14
+ it 'is able to diff two arrays with one element in common' do
13
15
  a = [1, 2, 3]
14
16
  b = [1, 8, 7]
15
17
 
16
- diff = HashDiff.diff_array_lcs(a, b)
18
+ diff = described_class.diff_array_lcs(a, b)
17
19
  diff.should == [['-', 2, 3], ['-', 1, 2], ['+', 1, 8], ['+', 2, 7]]
18
20
  end
19
21
 
20
- it "should be able to diff two arrays with nothing in common" do
22
+ it 'is able to diff two arrays with nothing in common' do
21
23
  a = [1, 2]
22
24
  b = []
23
25
 
24
- diff = HashDiff.diff_array_lcs(a, b)
26
+ diff = described_class.diff_array_lcs(a, b)
25
27
  diff.should == [['-', 1, 2], ['-', 0, 1]]
26
28
  end
27
29
 
28
- it "should be able to diff an empty array with an non-empty array" do
30
+ it 'is able to diff an empty array with an non-empty array' do
29
31
  a = []
30
32
  b = [1, 2]
31
33
 
32
- diff = HashDiff.diff_array_lcs(a, b)
34
+ diff = described_class.diff_array_lcs(a, b)
33
35
  diff.should == [['+', 0, 1], ['+', 1, 2]]
34
36
  end
35
37
 
36
- it "should be able to diff two arrays with two elements in common" do
38
+ it 'is able to diff two arrays with two elements in common' do
37
39
  a = [1, 3, 5, 7]
38
40
  b = [2, 3, 7, 5]
39
41
 
40
- diff = HashDiff.diff_array_lcs(a, b)
42
+ diff = described_class.diff_array_lcs(a, b)
41
43
  diff.should == [['-', 0, 1], ['+', 0, 2], ['+', 2, 7], ['-', 4, 7]]
42
44
  end
43
45
 
44
- it "should be able to test two arrays with two common elements in different order" do
46
+ it 'is able to test two arrays with two common elements in different order' do
45
47
  a = [1, 3, 4, 7]
46
48
  b = [2, 3, 7, 5]
47
49
 
48
- diff = HashDiff.diff_array_lcs(a, b)
50
+ diff = described_class.diff_array_lcs(a, b)
49
51
  diff.should == [['-', 0, 1], ['+', 0, 2], ['-', 2, 4], ['+', 3, 5]]
50
52
  end
51
53
 
52
- it "should be able to diff two arrays with similar elements" do
53
- a = [{'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5}, 3]
54
- b = [1, {'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5}]
55
- diff = HashDiff.diff_array_lcs(a, b)
54
+ it 'is able to diff two arrays with similar elements' do
55
+ a = [{ 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5 }, 3]
56
+ b = [1, { 'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5 }]
57
+ diff = described_class.diff_array_lcs(a, b)
56
58
  diff.should == [['+', 0, 1], ['-', 2, 3]]
57
59
  end
58
-
59
60
  end
60
-
@@ -1,248 +1,255 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
- describe HashDiff do
4
- it "should be able to diff two empty hashes" do
5
- diff = HashDiff.diff({}, {})
5
+ describe Hashdiff do
6
+ it 'is able to diff two empty hashes' do
7
+ diff = described_class.diff({}, {})
6
8
  diff.should == []
7
9
  end
8
10
 
9
- it "should be able to diff an hash with an empty hash" do
11
+ it 'is able to diff an hash with an empty hash' do
10
12
  a = { 'a' => 3, 'b' => 2 }
11
13
  b = {}
12
14
 
13
- diff = HashDiff.diff(a, b)
14
- diff.should == [['-', 'a', 3], ['-', 'b', 2]]
15
+ diff = described_class.diff(a, b)
16
+ expect(diff).to eq([['-', 'a', 3], ['-', 'b', 2]])
15
17
 
16
- diff = HashDiff.diff(b, a)
18
+ diff = described_class.diff(b, a)
17
19
  diff.should == [['+', 'a', 3], ['+', 'b', 2]]
18
20
  end
19
21
 
20
- it "should be able to diff two equal hashes" do
21
- diff = HashDiff.diff({ 'a' => 2, 'b' => 2}, { 'a' => 2, 'b' => 2 })
22
+ it 'is able to diff two equal hashes' do
23
+ diff = described_class.diff({ 'a' => 2, 'b' => 2 }, 'a' => 2, 'b' => 2)
22
24
  diff.should == []
23
25
  end
24
26
 
25
- it "should be able to diff two equal hashes with mixed key types" do
27
+ it 'is able to diff two equal hashes with mixed key types' do
26
28
  a = { 'a' => 1, :b => 1 }
27
- diff = HashDiff.diff(a, a)
29
+ diff = described_class.diff(a, a)
28
30
  diff.should == []
29
31
  end
30
32
 
31
- it "should be able to diff if mixed key types are removed" do
33
+ it 'is able to diff if mixed key types are removed' do
32
34
  a = { 'a' => 1, :b => 1 }
33
35
  b = {}
34
- diff = HashDiff.diff(a, b)
35
- diff.should == [["-", "a", 1], ["-", "b", 1]]
36
+ diff = described_class.diff(a, b)
37
+ diff.should == [['-', 'a', 1], ['-', 'b', 1]]
36
38
  end
37
39
 
38
- it "should be able to diff if mixed key types are added" do
40
+ it 'is able to diff if mixed key types are added' do
39
41
  a = { 'a' => 1, :b => 1 }
40
42
  b = {}
41
- diff = HashDiff.diff(b, a)
42
- diff.should == [["+", "a", 1], ["+", "b", 1]]
43
+ diff = described_class.diff(b, a)
44
+ diff.should == [['+', 'a', 1], ['+', 'b', 1]]
43
45
  end
44
46
 
45
- it "should be able to diff two hashes with equivalent numerics, when strict is false" do
46
- diff = HashDiff.diff({ 'a' => 2.0, 'b' => 2 }, { 'a' => 2, 'b' => 2.0 }, :strict => false)
47
+ it 'is able to diff two hashes with equivalent numerics, when strict is false' do
48
+ diff = described_class.diff({ 'a' => 2.0, 'b' => 2 }, { 'a' => 2, 'b' => 2.0 }, strict: false)
47
49
  diff.should == []
48
50
  end
49
51
 
50
- it "should be able to diff changes in hash value" do
51
- diff = HashDiff.diff({ 'a' => 2, 'b' => 3, 'c' => " hello" }, { 'a' => 2, 'b' => 4, 'c' => "hello" })
52
- diff.should == [['~', 'b', 3, 4], ['~', 'c', " hello", "hello"]]
52
+ it 'ignores string vs symbol differences, when indifferent is true' do
53
+ diff = described_class.diff({ 'a' => 2, :b => 2 }, { :a => 2, 'b' => 2, :c => 3 }, indifferent: true)
54
+ diff.should == [['+', 'c', 3]]
55
+ end
56
+
57
+ it 'is able to diff changes in hash value' do
58
+ diff = described_class.diff({ 'a' => 2, 'b' => 3, 'c' => ' hello' }, 'a' => 2, 'b' => 4, 'c' => 'hello')
59
+ diff.should == [['~', 'b', 3, 4], ['~', 'c', ' hello', 'hello']]
53
60
  end
54
61
 
55
- it "should be able to diff changes in hash value which is array" do
56
- diff = HashDiff.diff({ 'a' => 2, 'b' => [1, 2, 3] }, { 'a' => 2, 'b' => [1, 3, 4]})
62
+ it 'is able to diff changes in hash value which is array' do
63
+ diff = described_class.diff({ 'a' => 2, 'b' => [1, 2, 3] }, 'a' => 2, 'b' => [1, 3, 4])
57
64
  diff.should == [['-', 'b[1]', 2], ['+', 'b[2]', 4]]
58
65
  end
59
66
 
60
- it "should be able to diff changes in hash value which is hash" do
61
- diff = HashDiff.diff({ 'a' => { 'x' => 2, 'y' => 3, 'z' => 4 }, 'b' => { 'x' => 3, 'z' => 45 } },
62
- { 'a' => { 'y' => 3 }, 'b' => { 'y' => 3, 'z' => 30 } })
67
+ it 'is able to diff changes in hash value which is hash' do
68
+ diff = described_class.diff({ 'a' => { 'x' => 2, 'y' => 3, 'z' => 4 }, 'b' => { 'x' => 3, 'z' => 45 } },
69
+ 'a' => { 'y' => 3 }, 'b' => { 'y' => 3, 'z' => 30 })
63
70
  diff.should == [['-', 'a.x', 2], ['-', 'a.z', 4], ['-', 'b.x', 3], ['~', 'b.z', 45, 30], ['+', 'b.y', 3]]
64
71
  end
65
72
 
66
- it "should be able to diff similar objects in array" do
67
- diff = HashDiff.best_diff({ 'a' => [{ 'x' => 2, 'y' => 3, 'z' => 4 }, { 'x' => 11, 'y' => 22, 'z' => 33 }], 'b' => { 'x' => 3, 'z' => 45 } },
68
- { 'a' => [{ 'y' => 3 }, { 'x' => 11, 'z' => 33 }], 'b' => { 'y' => 22 } })
73
+ it 'is able to best diff similar objects in array' do
74
+ diff = described_class.best_diff({ 'a' => [{ 'x' => 2, 'y' => 3, 'z' => 4 }, { 'x' => 11, 'y' => 22, 'z' => 33 }], 'b' => { 'x' => 3, 'z' => 45 } },
75
+ 'a' => [{ 'y' => 3 }, { 'x' => 11, 'z' => 33 }], 'b' => { 'y' => 22 })
69
76
  diff.should == [['-', 'a[0].x', 2], ['-', 'a[0].z', 4], ['-', 'a[1].y', 22], ['-', 'b.x', 3], ['-', 'b.z', 45], ['+', 'b.y', 22]]
70
77
  end
71
78
 
72
- it 'should be able to diff addition of key value pair' do
73
- a = {"a"=>3, "c"=>11, "d"=>45, "e"=>100, "f"=>200}
74
- b = {"a"=>3, "c"=>11, "d"=>45, "e"=>100, "f"=>200, "g"=>300}
79
+ it 'is able to diff addition of key value pair' do
80
+ a = { 'a' => 3, 'c' => 11, 'd' => 45, 'e' => 100, 'f' => 200 }
81
+ b = { 'a' => 3, 'c' => 11, 'd' => 45, 'e' => 100, 'f' => 200, 'g' => 300 }
75
82
 
76
- diff = HashDiff.diff(a, b)
77
- diff.should == [['+', 'g', 300]]
83
+ diff = described_class.diff(a, b)
84
+ expect(diff).to eq([['+', 'g', 300]])
78
85
 
79
- diff = HashDiff.diff(b, a)
86
+ diff = described_class.diff(b, a)
80
87
  diff.should == [['-', 'g', 300]]
81
88
  end
82
89
 
83
- it 'should be able to diff value type changes' do
84
- a = {"a" => 3}
85
- b = {"a" => {"a1" => 1, "a2" => 2}}
90
+ it 'is able to diff value type changes' do
91
+ a = { 'a' => 3 }
92
+ b = { 'a' => { 'a1' => 1, 'a2' => 2 } }
86
93
 
87
- diff = HashDiff.diff(a, b)
88
- diff.should == [['~', 'a', 3, {"a1" => 1, "a2" => 2}]]
94
+ diff = described_class.diff(a, b)
95
+ expect(diff).to eq([['~', 'a', 3, { 'a1' => 1, 'a2' => 2 }]])
89
96
 
90
- diff = HashDiff.diff(b, a)
91
- diff.should == [['~', 'a', {"a1" => 1, "a2" => 2}, 3]]
97
+ diff = described_class.diff(b, a)
98
+ diff.should == [['~', 'a', { 'a1' => 1, 'a2' => 2 }, 3]]
92
99
  end
93
100
 
94
- it "should be able to diff value changes: array <=> []" do
95
- a = {"a" => 1, "b" => [1, 2]}
96
- b = {"a" => 1, "b" => []}
101
+ it 'is able to diff value changes: array <=> []' do
102
+ a = { 'a' => 1, 'b' => [1, 2] }
103
+ b = { 'a' => 1, 'b' => [] }
97
104
 
98
- diff = HashDiff.diff(a, b)
105
+ diff = described_class.diff(a, b)
99
106
  diff.should == [['-', 'b[1]', 2], ['-', 'b[0]', 1]]
100
107
  end
101
108
 
102
- it "should be able to diff value changes: array <=> nil" do
103
- a = {"a" => 1, "b" => [1, 2]}
104
- b = {"a" => 1, "b" => nil}
109
+ it 'is able to diff value changes: array <=> nil' do
110
+ a = { 'a' => 1, 'b' => [1, 2] }
111
+ b = { 'a' => 1, 'b' => nil }
105
112
 
106
- diff = HashDiff.diff(a, b)
107
- diff.should == [["~", "b", [1, 2], nil]]
113
+ diff = described_class.diff(a, b)
114
+ diff.should == [['~', 'b', [1, 2], nil]]
108
115
  end
109
116
 
110
- it "should be able to diff value chagnes: remove array completely" do
111
- a = {"a" => 1, "b" => [1, 2]}
112
- b = {"a" => 1}
117
+ it 'is able to diff value chagnes: remove array completely' do
118
+ a = { 'a' => 1, 'b' => [1, 2] }
119
+ b = { 'a' => 1 }
113
120
 
114
- diff = HashDiff.diff(a, b)
115
- diff.should == [["-", "b", [1, 2]]]
121
+ diff = described_class.diff(a, b)
122
+ diff.should == [['-', 'b', [1, 2]]]
116
123
  end
117
124
 
118
- it "should be able to diff value changes: remove whole hash" do
119
- a = {"a" => 1, "b" => {"b1" => 1, "b2" =>2}}
120
- b = {"a" => 1}
125
+ it 'is able to diff value changes: remove whole hash' do
126
+ a = { 'a' => 1, 'b' => { 'b1' => 1, 'b2' => 2 } }
127
+ b = { 'a' => 1 }
121
128
 
122
- diff = HashDiff.diff(a, b)
123
- diff.should == [["-", "b", {"b1"=>1, "b2"=>2}]]
129
+ diff = described_class.diff(a, b)
130
+ diff.should == [['-', 'b', { 'b1' => 1, 'b2' => 2 }]]
124
131
  end
125
132
 
126
- it "should be able to diff value changes: hash <=> {}" do
127
- a = {"a" => 1, "b" => {"b1" => 1, "b2" =>2}}
128
- b = {"a" => 1, "b" => {}}
133
+ it 'is able to diff value changes: hash <=> {}' do
134
+ a = { 'a' => 1, 'b' => { 'b1' => 1, 'b2' => 2 } }
135
+ b = { 'a' => 1, 'b' => {} }
129
136
 
130
- diff = HashDiff.diff(a, b)
137
+ diff = described_class.diff(a, b)
131
138
  diff.should == [['-', 'b.b1', 1], ['-', 'b.b2', 2]]
132
139
  end
133
140
 
134
- it "should be able to diff value changes: hash <=> nil" do
135
- a = {"a" => 1, "b" => {"b1" => 1, "b2" =>2}}
136
- b = {"a" => 1, "b" => nil}
141
+ it 'is able to diff value changes: hash <=> nil' do
142
+ a = { 'a' => 1, 'b' => { 'b1' => 1, 'b2' => 2 } }
143
+ b = { 'a' => 1, 'b' => nil }
137
144
 
138
- diff = HashDiff.diff(a, b)
139
- diff.should == [["~", "b", {"b1"=>1, "b2"=>2}, nil]]
145
+ diff = described_class.diff(a, b)
146
+ diff.should == [['~', 'b', { 'b1' => 1, 'b2' => 2 }, nil]]
140
147
  end
141
148
 
142
- it "should be able to diff similar objects in array" do
143
- a = [{'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5}, 3]
144
- b = [1, {'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5}]
149
+ it 'is able to diff similar objects in array' do
150
+ a = [{ 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5 }, 3]
151
+ b = [1, { 'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5 }]
145
152
 
146
- diff = HashDiff.diff(a, b)
153
+ diff = described_class.diff(a, b)
147
154
  diff.should == [['-', '[0].d', 4], ['+', '[0]', 1], ['-', '[2]', 3]]
148
155
  end
149
156
 
150
- it "should be able to diff similar & equal objects in array" do
151
- a = [{'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5}, {'x' => 5, 'y' => 6, 'z' => 3}, 3]
152
- b = [{'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5}, 3]
157
+ it 'is able to diff similar & equal objects in array' do
158
+ a = [{ 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5 }, { 'x' => 5, 'y' => 6, 'z' => 3 }, 3]
159
+ b = [{ 'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5 }, 3]
153
160
 
154
- diff = HashDiff.diff(a, b)
155
- diff.should == [["-", "[0].d", 4], ["-", "[1]", {"x"=>5, "y"=>6, "z"=>3}]]
161
+ diff = described_class.diff(a, b)
162
+ diff.should == [['-', '[0].d', 4], ['-', '[1]', { 'x' => 5, 'y' => 6, 'z' => 3 }]]
156
163
  end
157
164
 
158
- it "should use custom delimiter when provided" do
159
- a = [{'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5}, {'x' => 5, 'y' => 6, 'z' => 3}, 3]
160
- b = [{'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5}, 3]
165
+ it 'uses custom delimiter when provided' do
166
+ a = [{ 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5 }, { 'x' => 5, 'y' => 6, 'z' => 3 }, 3]
167
+ b = [{ 'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5 }, 3]
161
168
 
162
- diff = HashDiff.diff(a, b, :similarity => 0.8, :delimiter => "\t")
163
- diff.should == [["-", "[0]\td", 4], ["-", "[1]", {"x"=>5, "y"=>6, "z"=>3}]]
169
+ diff = described_class.diff(a, b, similarity: 0.8, delimiter: "\t")
170
+ diff.should == [['-', "[0]\td", 4], ['-', '[1]', { 'x' => 5, 'y' => 6, 'z' => 3 }]]
164
171
  end
165
172
 
166
173
  context 'when :numeric_tolerance requested' do
167
- it "should be able to diff changes in hash value" do
168
- a = {'a' => 0.558, 'b' => 0.0, 'c' => 0.65, 'd' => 'fin'}
169
- b = {'a' => 0.557, 'b' => 'hats', 'c' => 0.67, 'd' => 'fin'}
174
+ it 'is able to diff changes in hash value' do
175
+ a = { 'a' => 0.558, 'b' => 0.0, 'c' => 0.65, 'd' => 'fin' }
176
+ b = { 'a' => 0.557, 'b' => 'hats', 'c' => 0.67, 'd' => 'fin' }
170
177
 
171
- diff = HashDiff.diff(a, b, :numeric_tolerance => 0.01)
172
- diff.should == [["~", "b", 0.0, 'hats'], ["~", "c", 0.65, 0.67]]
178
+ diff = described_class.diff(a, b, numeric_tolerance: 0.01)
179
+ expect(diff).to eq([['~', 'b', 0.0, 'hats'], ['~', 'c', 0.65, 0.67]])
173
180
 
174
- diff = HashDiff.diff(b, a, :numeric_tolerance => 0.01)
175
- diff.should == [["~", "b", 'hats', 0.0], ["~", "c", 0.67, 0.65]]
181
+ diff = described_class.diff(b, a, numeric_tolerance: 0.01)
182
+ diff.should == [['~', 'b', 'hats', 0.0], ['~', 'c', 0.67, 0.65]]
176
183
  end
177
184
 
178
- it "should be able to diff changes in nested values" do
179
- a = {'a' => {'x' => 0.4, 'y' => 0.338}, 'b' => [13, 68.03]}
180
- b = {'a' => {'x' => 0.6, 'y' => 0.341}, 'b' => [14, 68.025]}
185
+ it 'is able to diff changes in nested values' do
186
+ a = { 'a' => { 'x' => 0.4, 'y' => 0.338 }, 'b' => [13, 68.03] }
187
+ b = { 'a' => { 'x' => 0.6, 'y' => 0.341 }, 'b' => [14, 68.025] }
181
188
 
182
- diff = HashDiff.diff(a, b, :numeric_tolerance => 0.01)
183
- diff.should == [["~", "a.x", 0.4, 0.6], ["-", "b[0]", 13], ["+", "b[0]", 14]]
189
+ diff = described_class.diff(a, b, numeric_tolerance: 0.01)
190
+ expect(diff).to eq([['~', 'a.x', 0.4, 0.6], ['-', 'b[0]', 13], ['+', 'b[0]', 14]])
184
191
 
185
- diff = HashDiff.diff(b, a, :numeric_tolerance => 0.01)
186
- diff.should == [["~", "a.x", 0.6, 0.4], ["-", "b[0]", 14], ["+", "b[0]", 13]]
192
+ diff = described_class.diff(b, a, numeric_tolerance: 0.01)
193
+ diff.should == [['~', 'a.x', 0.6, 0.4], ['-', 'b[0]', 14], ['+', 'b[0]', 13]]
187
194
  end
188
195
  end
189
196
 
190
197
  context 'when :strip requested' do
191
- it "should strip strings before comparing" do
192
- a = { 'a' => " foo", 'b' => "fizz buzz"}
193
- b = { 'a' => "foo", 'b' => "fizzbuzz"}
194
- diff = HashDiff.diff(a, b, :strip => true)
195
- diff.should == [['~', 'b', "fizz buzz", "fizzbuzz"]]
198
+ it 'strips strings before comparing' do
199
+ a = { 'a' => ' foo', 'b' => 'fizz buzz' }
200
+ b = { 'a' => 'foo', 'b' => 'fizzbuzz' }
201
+ diff = described_class.diff(a, b, strip: true)
202
+ diff.should == [['~', 'b', 'fizz buzz', 'fizzbuzz']]
196
203
  end
197
204
 
198
- it "should strip nested strings before comparing" do
199
- a = { 'a' => { 'x' => " foo" }, 'b' => ["fizz buzz", "nerf"] }
200
- b = { 'a' => { 'x' => "foo" }, 'b' => ["fizzbuzz", "nerf"] }
201
- diff = HashDiff.diff(a, b, :strip => true)
202
- diff.should == [['-', 'b[0]', "fizz buzz"], ['+', 'b[0]', "fizzbuzz"]]
205
+ it 'strips nested strings before comparing' do
206
+ a = { 'a' => { 'x' => ' foo' }, 'b' => ['fizz buzz', 'nerf'] }
207
+ b = { 'a' => { 'x' => 'foo' }, 'b' => %w[fizzbuzz nerf] }
208
+ diff = described_class.diff(a, b, strip: true)
209
+ diff.should == [['-', 'b[0]', 'fizz buzz'], ['+', 'b[0]', 'fizzbuzz']]
203
210
  end
204
211
  end
205
212
 
206
213
  context 'when :case_insensitive requested' do
207
- it "should strip strings before comparing" do
208
- a = { 'a' => "Foo", 'b' => "fizz buzz"}
209
- b = { 'a' => "foo", 'b' => "fizzBuzz"}
210
- diff = HashDiff.diff(a, b, :case_insensitive => true)
211
- diff.should == [['~', 'b', "fizz buzz", "fizzBuzz"]]
214
+ it 'strips strings before comparing' do
215
+ a = { 'a' => 'Foo', 'b' => 'fizz buzz' }
216
+ b = { 'a' => 'foo', 'b' => 'fizzBuzz' }
217
+ diff = described_class.diff(a, b, case_insensitive: true)
218
+ diff.should == [['~', 'b', 'fizz buzz', 'fizzBuzz']]
212
219
  end
213
220
 
214
- it "should ignore case on nested strings before comparing" do
215
- a = { 'a' => { 'x' => "Foo" }, 'b' => ["fizz buzz", "nerf"] }
216
- b = { 'a' => { 'x' => "foo" }, 'b' => ["fizzbuzz", "nerf"] }
217
- diff = HashDiff.diff(a, b, :case_insensitive => true)
218
- diff.should == [['-', 'b[0]', "fizz buzz"], ['+', 'b[0]', "fizzbuzz"]]
221
+ it 'ignores case on nested strings before comparing' do
222
+ a = { 'a' => { 'x' => 'Foo' }, 'b' => ['fizz buzz', 'nerf'] }
223
+ b = { 'a' => { 'x' => 'foo' }, 'b' => %w[fizzbuzz nerf] }
224
+ diff = described_class.diff(a, b, case_insensitive: true)
225
+ diff.should == [['-', 'b[0]', 'fizz buzz'], ['+', 'b[0]', 'fizzbuzz']]
219
226
  end
220
227
  end
221
228
 
222
229
  context 'when both :strip and :numeric_tolerance requested' do
223
- it 'should apply filters to proper object types' do
224
- a = { 'a' => " foo", 'b' => 35, 'c' => 'bar', 'd' => 'baz' }
225
- b = { 'a' => "foo", 'b' => 35.005, 'c' => 'bar', 'd' => 18.5}
226
- diff = HashDiff.diff(a, b, :strict => false, :numeric_tolerance => 0.01, :strip => true)
227
- diff.should == [['~', 'd', "baz", 18.5]]
230
+ it 'applies filters to proper object types' do
231
+ a = { 'a' => ' foo', 'b' => 35, 'c' => 'bar', 'd' => 'baz' }
232
+ b = { 'a' => 'foo', 'b' => 35.005, 'c' => 'bar', 'd' => 18.5 }
233
+ diff = described_class.diff(a, b, strict: false, numeric_tolerance: 0.01, strip: true)
234
+ diff.should == [['~', 'd', 'baz', 18.5]]
228
235
  end
229
236
  end
230
237
 
231
- context "when both :strip and :case_insensitive requested" do
232
- it "should apply both filters to strings" do
233
- a = { 'a' => " Foo", 'b' => "fizz buzz"}
234
- b = { 'a' => "foo", 'b' => "fizzBuzz"}
235
- diff = HashDiff.diff(a, b, :case_insensitive => true, :strip => true)
236
- diff.should == [['~', 'b', "fizz buzz", "fizzBuzz"]]
238
+ context 'when both :strip and :case_insensitive requested' do
239
+ it 'applies both filters to strings' do
240
+ a = { 'a' => ' Foo', 'b' => 'fizz buzz' }
241
+ b = { 'a' => 'foo', 'b' => 'fizzBuzz' }
242
+ diff = described_class.diff(a, b, case_insensitive: true, strip: true)
243
+ diff.should == [['~', 'b', 'fizz buzz', 'fizzBuzz']]
237
244
  end
238
245
  end
239
246
 
240
247
  context 'with custom comparison' do
241
- let(:a) { { 'a' => 'car', 'b' => 'boat', 'c' => 'plane'} }
242
- let(:b) { { 'a' => 'bus', 'b' => 'truck', 'c' => ' plan'} }
248
+ let(:a) { { 'a' => 'car', 'b' => 'boat', 'c' => 'plane' } }
249
+ let(:b) { { 'a' => 'bus', 'b' => 'truck', 'c' => ' plan' } }
243
250
 
244
- it 'should compare using proc specified in block' do
245
- diff = HashDiff.diff(a, b) do |prefix, obj1, obj2|
251
+ it 'compares using proc specified in block' do
252
+ diff = described_class.diff(a, b) do |prefix, obj1, obj2|
246
253
  case prefix
247
254
  when /a|b|c/
248
255
  obj1.length == obj2.length
@@ -251,11 +258,11 @@ describe HashDiff do
251
258
  diff.should == [['~', 'b', 'boat', 'truck']]
252
259
  end
253
260
 
254
- it 'should yield added keys' do
255
- x = { 'a' => 'car', 'b' => 'boat'}
261
+ it 'yields added keys' do
262
+ x = { 'a' => 'car', 'b' => 'boat' }
256
263
  y = { 'a' => 'car' }
257
264
 
258
- diff = HashDiff.diff(x, y) do |prefix, obj1, obj2|
265
+ diff = described_class.diff(x, y) do |prefix, _obj1, _obj2|
259
266
  case prefix
260
267
  when /b/
261
268
  true
@@ -264,8 +271,8 @@ describe HashDiff do
264
271
  diff.should == []
265
272
  end
266
273
 
267
- it 'should compare with both proc and :strip when both provided' do
268
- diff = HashDiff.diff(a, b, :strip => true) do |prefix, obj1, obj2|
274
+ it 'compares with both proc and :strip when both provided' do
275
+ diff = described_class.diff(a, b, strip: true) do |prefix, obj1, obj2|
269
276
  case prefix
270
277
  when 'a'
271
278
  obj1.length == obj2.length
@@ -273,65 +280,79 @@ describe HashDiff do
273
280
  end
274
281
  diff.should == [['~', 'b', 'boat', 'truck'], ['~', 'c', 'plane', ' plan']]
275
282
  end
283
+
284
+ it 'compares nested arrays using proc specified in block' do
285
+ a = { a: 'car', b: %w[boat plane] }
286
+ b = { a: 'bus', b: ['truck', ' plan'] }
287
+
288
+ diff = described_class.diff(a, b) do |path, obj1, obj2|
289
+ case path
290
+ when 'b[*]'
291
+ obj1.length == obj2.length
292
+ end
293
+ end
294
+
295
+ expect(diff).to eq [['~', 'a', 'car', 'bus'], ['~', 'b[1]', 'plane', ' plan'], ['-', 'b[0]', 'boat'], ['+', 'b[0]', 'truck']]
296
+ end
276
297
  end
277
298
 
278
299
  context 'when :array_path is true' do
279
- it 'should return the diff path in an array rather than a string' do
300
+ it 'returns the diff path in an array rather than a string' do
280
301
  x = { 'a' => 'foo' }
281
302
  y = { 'a' => 'bar' }
282
- diff = HashDiff.diff(x, y, :array_path => true)
303
+ diff = described_class.diff(x, y, array_path: true)
283
304
 
284
305
  diff.should == [['~', ['a'], 'foo', 'bar']]
285
306
  end
286
307
 
287
- it 'should show array indexes in paths' do
308
+ it 'shows array indexes in paths' do
288
309
  x = { 'a' => [0, 1, 2] }
289
310
  y = { 'a' => [0, 1, 2, 3] }
290
311
 
291
- diff = HashDiff.diff(x, y, :array_path => true)
312
+ diff = described_class.diff(x, y, array_path: true)
292
313
 
293
314
  diff.should == [['+', ['a', 3], 3]]
294
315
  end
295
316
 
296
- it 'should show differences with string and symbol keys' do
317
+ it 'shows differences with string and symbol keys' do
297
318
  x = { 'a' => 'foo' }
298
- y = { :a => 'bar' }
319
+ y = { a: 'bar' }
299
320
 
300
- diff = HashDiff.diff(x, y, :array_path => true)
321
+ diff = described_class.diff(x, y, array_path: true)
301
322
  diff.should == [['-', ['a'], 'foo'], ['+', [:a], 'bar']]
302
323
  end
303
324
 
304
- it 'should support other key types' do
325
+ it 'supports other key types' do
305
326
  time = Time.now
306
327
  x = { time => 'foo' }
307
328
  y = { 0 => 'bar' }
308
329
 
309
- diff = HashDiff.diff(x, y, :array_path => true)
330
+ diff = described_class.diff(x, y, array_path: true)
310
331
  diff.should == [['-', [time], 'foo'], ['+', [0], 'bar']]
311
332
  end
312
333
  end
313
334
 
314
335
  context 'when :use_lcs is false' do
315
- it 'should show items in an array as changed' do
316
- x = [:a, :b]
317
- y = [:c, :d]
318
- diff = HashDiff.diff(x, y, :use_lcs => false)
336
+ it 'shows items in an array as changed' do
337
+ x = %i[a b]
338
+ y = %i[c d]
339
+ diff = described_class.diff(x, y, use_lcs: false)
319
340
 
320
341
  diff.should == [['~', '[0]', :a, :c], ['~', '[1]', :b, :d]]
321
342
  end
322
343
 
323
- it 'should show additions to arrays' do
324
- x = { :a => [0] }
325
- y = { :a => [0, 1] }
326
- diff = HashDiff.diff(x, y, :use_lcs => false)
344
+ it 'shows additions to arrays' do
345
+ x = { a: [0] }
346
+ y = { a: [0, 1] }
347
+ diff = described_class.diff(x, y, use_lcs: false)
327
348
 
328
349
  diff.should == [['+', 'a[1]', 1]]
329
350
  end
330
351
 
331
352
  it 'shows changes to nested arrays' do
332
- x = { :a => [[0, 1]] }
333
- y = { :a => [[1, 2]] }
334
- diff = HashDiff.diff(x, y, :use_lcs => false)
353
+ x = { a: [[0, 1]] }
354
+ y = { a: [[1, 2]] }
355
+ diff = described_class.diff(x, y, use_lcs: false)
335
356
 
336
357
  diff.should == [['~', 'a[0][0]', 0, 1], ['~', 'a[0][1]', 1, 2]]
337
358
  end