hashdiff 0.3.7 → 0.3.8
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +21 -0
- data/.travis.yml +2 -5
- data/Gemfile +1 -1
- data/README.md +1 -1
- data/Rakefile +7 -4
- data/changelog.md +4 -0
- data/hashdiff.gemspec +13 -11
- data/lib/hashdiff/diff.rb +56 -64
- data/lib/hashdiff/lcs.rb +23 -28
- data/lib/hashdiff/linear_compare_array.rb +4 -2
- data/lib/hashdiff/patch.rb +2 -4
- data/lib/hashdiff/util.rb +27 -31
- data/lib/hashdiff/version.rb +1 -1
- data/spec/hash_diff/best_diff_spec.rb +73 -0
- data/spec/hash_diff/diff_array_spec.rb +58 -0
- data/spec/hash_diff/diff_spec.rb +339 -0
- data/spec/hash_diff/lcs_spec.rb +74 -0
- data/spec/hash_diff/linear_compare_array_spec.rb +48 -0
- data/spec/hash_diff/patch_spec.rb +183 -0
- data/spec/hash_diff/util_spec.rb +85 -0
- metadata +55 -26
- data/spec/hashdiff/best_diff_spec.rb +0 -74
- data/spec/hashdiff/diff_array_spec.rb +0 -60
- data/spec/hashdiff/diff_spec.rb +0 -339
- data/spec/hashdiff/lcs_spec.rb +0 -75
- data/spec/hashdiff/linear_compare_array_spec.rb +0 -48
- data/spec/hashdiff/patch_spec.rb +0 -183
- data/spec/hashdiff/util_spec.rb +0 -78
data/spec/hashdiff/lcs_spec.rb
DELETED
@@ -1,75 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe HashDiff do
|
4
|
-
it "should be able to find LCS between two equal array" do
|
5
|
-
a = [1, 2, 3]
|
6
|
-
b = [1, 2, 3]
|
7
|
-
|
8
|
-
lcs = HashDiff.lcs(a, b)
|
9
|
-
lcs.should == [[0, 0], [1, 1], [2, 2]]
|
10
|
-
end
|
11
|
-
|
12
|
-
it "should be able to find LCS between two close arrays" do
|
13
|
-
a = [1.05, 2, 3.25]
|
14
|
-
b = [1.06, 2, 3.24]
|
15
|
-
|
16
|
-
lcs = HashDiff.lcs(a, b, :numeric_tolerance => 0.1)
|
17
|
-
lcs.should == [[0, 0], [1, 1], [2, 2]]
|
18
|
-
end
|
19
|
-
|
20
|
-
it "should strip strings when finding LCS if requested" do
|
21
|
-
a = ['foo', 'bar', 'baz']
|
22
|
-
b = [' foo', 'bar', 'zab']
|
23
|
-
|
24
|
-
lcs = HashDiff.lcs(a, b, :strip => true)
|
25
|
-
lcs.should == [[0, 0], [1, 1]]
|
26
|
-
end
|
27
|
-
|
28
|
-
it "should be able to find LCS with one common elements" do
|
29
|
-
a = [1, 2, 3]
|
30
|
-
b = [1, 8, 7]
|
31
|
-
|
32
|
-
lcs = HashDiff.lcs(a, b)
|
33
|
-
lcs.should == [[0, 0]]
|
34
|
-
end
|
35
|
-
|
36
|
-
it "should be able to find LCS with two common elements" do
|
37
|
-
a = [1, 3, 5, 7]
|
38
|
-
b = [2, 3, 7, 5]
|
39
|
-
|
40
|
-
lcs = HashDiff.lcs(a, b)
|
41
|
-
lcs.should == [[1, 1], [2, 3]]
|
42
|
-
end
|
43
|
-
|
44
|
-
it "should be able to find LCS with two close elements" do
|
45
|
-
a = [1, 3.05, 5, 7]
|
46
|
-
b = [2, 3.06, 7, 5]
|
47
|
-
|
48
|
-
lcs = HashDiff.lcs(a, b, :numeric_tolerance => 0.1)
|
49
|
-
lcs.should == [[1, 1], [2, 3]]
|
50
|
-
end
|
51
|
-
|
52
|
-
it "should be able to find LCS with two common elements in different ordering" do
|
53
|
-
a = [1, 3, 4, 7]
|
54
|
-
b = [2, 3, 7, 5]
|
55
|
-
|
56
|
-
lcs = HashDiff.lcs(a, b)
|
57
|
-
lcs.should == [[1, 1], [3, 2]]
|
58
|
-
end
|
59
|
-
|
60
|
-
it "should be able to find LCS with a similarity value" do
|
61
|
-
a = [
|
62
|
-
{"value" => "New", "onclick" => "CreateNewDoc()"},
|
63
|
-
{"value" => "Close", "onclick" => "CloseDoc()"}
|
64
|
-
]
|
65
|
-
b = [
|
66
|
-
{"value" => "New1", "onclick" => "CreateNewDoc()"},
|
67
|
-
{"value" => "Open", "onclick" => "OpenDoc()"},
|
68
|
-
{"value" => "Close", "onclick" => "CloseDoc()"}
|
69
|
-
]
|
70
|
-
|
71
|
-
lcs = HashDiff.lcs(a, b, :similarity => 0.5)
|
72
|
-
lcs.should == [[0, 0], [1, 2]]
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
@@ -1,48 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe HashDiff::LinearCompareArray do
|
4
|
-
it "should find no differences between two empty arrays" do
|
5
|
-
difference = described_class.call([], [])
|
6
|
-
difference.should == []
|
7
|
-
end
|
8
|
-
|
9
|
-
it "should find added items when the old array is empty" do
|
10
|
-
difference = described_class.call([], [:a, :b])
|
11
|
-
difference.should == [['+', '[0]', :a], ['+', '[1]', :b]]
|
12
|
-
end
|
13
|
-
|
14
|
-
it "should find removed items when the new array is empty" do
|
15
|
-
difference = described_class.call([:a, :b], [])
|
16
|
-
difference.should == [['-', '[1]', :b], ['-', '[0]', :a]]
|
17
|
-
end
|
18
|
-
|
19
|
-
it "should find no differences between identical arrays" do
|
20
|
-
difference = described_class.call([:a, :b], [:a, :b])
|
21
|
-
difference.should == []
|
22
|
-
end
|
23
|
-
|
24
|
-
it "should find added items in an array" do
|
25
|
-
difference = described_class.call([:a, :d], [:a, :b, :c, :d])
|
26
|
-
difference.should == [['+', '[1]', :b], ['+', '[2]', :c]]
|
27
|
-
end
|
28
|
-
|
29
|
-
it "should find removed items in an array" do
|
30
|
-
difference = described_class.call([:a, :b, :c, :d, :e, :f], [:a, :d, :f])
|
31
|
-
difference.should == [['-', '[4]', :e], ['-', '[2]', :c], ['-', '[1]', :b]]
|
32
|
-
end
|
33
|
-
|
34
|
-
it "should show additions and deletions as changed items" do
|
35
|
-
difference = described_class.call([:a, :b, :c], [:c, :b, :a])
|
36
|
-
difference.should == [['~', '[0]', :a, :c], ['~', '[2]', :c, :a]]
|
37
|
-
end
|
38
|
-
|
39
|
-
it "should show changed items in a hash" do
|
40
|
-
difference = described_class.call([{ :a => :b }], [{ :a => :c }])
|
41
|
-
difference.should == [['~', '[0].a', :b, :c]]
|
42
|
-
end
|
43
|
-
|
44
|
-
it "should show changed items and added items" do
|
45
|
-
difference = described_class.call([{ :a => 1, :b => 2 }], [{ :a => 2, :b => 2 }, :item])
|
46
|
-
difference.should == [['~', '[0].a', 1, 2], ['+', '[1]', :item]]
|
47
|
-
end
|
48
|
-
end
|
data/spec/hashdiff/patch_spec.rb
DELETED
@@ -1,183 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe HashDiff do
|
4
|
-
it "it should be able to patch key addition" do
|
5
|
-
a = {"a"=>3, "c"=>11, "d"=>45, "e"=>100, "f"=>200}
|
6
|
-
b = {"a"=>3, "c"=>11, "d"=>45, "e"=>100, "f"=>200, "g"=>300}
|
7
|
-
diff = HashDiff.diff(a, b)
|
8
|
-
|
9
|
-
HashDiff.patch!(a, diff).should == b
|
10
|
-
|
11
|
-
a = {"a"=>3, "c"=>11, "d"=>45, "e"=>100, "f"=>200}
|
12
|
-
b = {"a"=>3, "c"=>11, "d"=>45, "e"=>100, "f"=>200, "g"=>300}
|
13
|
-
HashDiff.unpatch!(b, diff).should == a
|
14
|
-
end
|
15
|
-
|
16
|
-
it "should be able to patch value type changes" do
|
17
|
-
a = {"a" => 3}
|
18
|
-
b = {"a" => {"a1" => 1, "a2" => 2}}
|
19
|
-
diff = HashDiff.diff(a, b)
|
20
|
-
|
21
|
-
HashDiff.patch!(a, diff).should == b
|
22
|
-
|
23
|
-
a = {"a" => 3}
|
24
|
-
b = {"a" => {"a1" => 1, "a2" => 2}}
|
25
|
-
HashDiff.unpatch!(b, diff).should == a
|
26
|
-
end
|
27
|
-
|
28
|
-
it "should be able to patch value array <=> []" do
|
29
|
-
a = {"a" => 1, "b" => [1, 2]}
|
30
|
-
b = {"a" => 1, "b" => []}
|
31
|
-
diff = HashDiff.diff(a, b)
|
32
|
-
|
33
|
-
HashDiff.patch!(a, diff).should == b
|
34
|
-
|
35
|
-
a = {"a" => 1, "b" => [1, 2]}
|
36
|
-
b = {"a" => 1, "b" => []}
|
37
|
-
HashDiff.unpatch!(b, diff).should == a
|
38
|
-
end
|
39
|
-
|
40
|
-
it "should be able to patch value array <=> nil" do
|
41
|
-
a = {"a" => 1, "b" => [1, 2]}
|
42
|
-
b = {"a" => 1, "b" => nil}
|
43
|
-
diff = HashDiff.diff(a, b)
|
44
|
-
|
45
|
-
HashDiff.patch!(a, diff).should == b
|
46
|
-
|
47
|
-
a = {"a" => 1, "b" => [1, 2]}
|
48
|
-
b = {"a" => 1, "b" => nil}
|
49
|
-
HashDiff.unpatch!(b, diff).should == a
|
50
|
-
end
|
51
|
-
|
52
|
-
it "should be able to patch array value removal" do
|
53
|
-
a = {"a" => 1, "b" => [1, 2]}
|
54
|
-
b = {"a" => 1}
|
55
|
-
diff = HashDiff.diff(a, b)
|
56
|
-
|
57
|
-
HashDiff.patch!(a, diff).should == b
|
58
|
-
|
59
|
-
a = {"a" => 1, "b" => [1, 2]}
|
60
|
-
b = {"a" => 1}
|
61
|
-
HashDiff.unpatch!(b, diff).should == a
|
62
|
-
end
|
63
|
-
|
64
|
-
it "should be able to patch array under hash key with non-word characters" do
|
65
|
-
a = {"a" => 1, "b-b" => [1, 2]}
|
66
|
-
b = {"a" => 1, "b-b" => [2, 1]}
|
67
|
-
diff = HashDiff.diff(a, b)
|
68
|
-
|
69
|
-
HashDiff.patch!(a, diff).should == b
|
70
|
-
|
71
|
-
a = {"a" => 1, "b-b" => [1, 2]}
|
72
|
-
b = {"a" => 1, "b-b" => [2, 1]}
|
73
|
-
HashDiff.unpatch!(b, diff).should == a
|
74
|
-
end
|
75
|
-
|
76
|
-
it "should be able to patch hash value removal" do
|
77
|
-
a = {"a" => 1, "b" => {"b1" => 1, "b2" =>2}}
|
78
|
-
b = {"a" => 1}
|
79
|
-
diff = HashDiff.diff(a, b)
|
80
|
-
|
81
|
-
HashDiff.patch!(a, diff).should == b
|
82
|
-
|
83
|
-
a = {"a" => 1, "b" => {"b1" => 1, "b2" =>2}}
|
84
|
-
b = {"a" => 1}
|
85
|
-
HashDiff.unpatch!(b, diff).should == a
|
86
|
-
end
|
87
|
-
|
88
|
-
it "should be able to patch value hash <=> {}" do
|
89
|
-
a = {"a" => 1, "b" => {"b1" => 1, "b2" =>2}}
|
90
|
-
b = {"a" => 1, "b" => {}}
|
91
|
-
diff = HashDiff.diff(a, b)
|
92
|
-
|
93
|
-
HashDiff.patch!(a, diff).should == b
|
94
|
-
|
95
|
-
a = {"a" => 1, "b" => {"b1" => 1, "b2" =>2}}
|
96
|
-
b = {"a" => 1, "b" => {}}
|
97
|
-
HashDiff.unpatch!(b, diff).should == a
|
98
|
-
end
|
99
|
-
|
100
|
-
it "should be able to patch value hash <=> nil" do
|
101
|
-
a = {"a" => 1, "b" => {"b1" => 1, "b2" =>2}}
|
102
|
-
b = {"a" => 1, "b" => nil}
|
103
|
-
diff = HashDiff.diff(a, b)
|
104
|
-
|
105
|
-
HashDiff.patch!(a, diff).should == b
|
106
|
-
|
107
|
-
a = {"a" => 1, "b" => {"b1" => 1, "b2" =>2}}
|
108
|
-
b = {"a" => 1, "b" => nil}
|
109
|
-
HashDiff.unpatch!(b, diff).should == a
|
110
|
-
end
|
111
|
-
|
112
|
-
it "should be able to patch value nil removal" do
|
113
|
-
a = {"a" => 1, "b" => nil}
|
114
|
-
b = {"a" => 1}
|
115
|
-
diff = HashDiff.diff(a, b)
|
116
|
-
|
117
|
-
HashDiff.patch!(a, diff).should == b
|
118
|
-
|
119
|
-
a = {"a" => 1, "b" => nil}
|
120
|
-
b = {"a" => 1}
|
121
|
-
HashDiff.unpatch!(b, diff).should == a
|
122
|
-
end
|
123
|
-
|
124
|
-
it "should be able to patch similar objects between arrays" do
|
125
|
-
a = [{'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5}, 3]
|
126
|
-
b = [1, {'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5}]
|
127
|
-
|
128
|
-
diff = HashDiff.diff(a, b)
|
129
|
-
HashDiff.patch!(a, diff).should == b
|
130
|
-
|
131
|
-
a = [{'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5}, 3]
|
132
|
-
b = [1, {'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5}]
|
133
|
-
HashDiff.unpatch!(b, diff).should == a
|
134
|
-
end
|
135
|
-
|
136
|
-
it "should be able to patch similar & equal objects between arrays" do
|
137
|
-
a = [{'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5}, {'x' => 5, 'y' => 6, 'z' => 3}, 1]
|
138
|
-
b = [1, {'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5}]
|
139
|
-
|
140
|
-
diff = HashDiff.diff(a, b)
|
141
|
-
HashDiff.patch!(a, diff).should == b
|
142
|
-
|
143
|
-
a = [{'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5}, {'x' => 5, 'y' => 6, 'z' => 3}, 1]
|
144
|
-
b = [1, {'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5}]
|
145
|
-
HashDiff.unpatch!(b, diff).should == a
|
146
|
-
end
|
147
|
-
|
148
|
-
it "should be able to patch hash value removal with custom delimiter" do
|
149
|
-
a = {"a" => 1, "b" => {"b1" => 1, "b2" =>2}}
|
150
|
-
b = {"a" => 1, "b" => {"b1" => 3} }
|
151
|
-
diff = HashDiff.diff(a, b, :delimiter => "\n")
|
152
|
-
|
153
|
-
HashDiff.patch!(a, diff, :delimiter => "\n").should == b
|
154
|
-
|
155
|
-
a = {"a" => 1, "b" => {"b1" => 1, "b2" =>2}}
|
156
|
-
b = {"a" => 1, "b" => {"b1" => 3} }
|
157
|
-
HashDiff.unpatch!(b, diff, :delimiter => "\n").should == a
|
158
|
-
end
|
159
|
-
|
160
|
-
it "should be able to patch when the diff is generated with an array_path" do
|
161
|
-
a = {"a" => 1, "b" => 1}
|
162
|
-
b = {"a" => 1, "b" => 2}
|
163
|
-
diff = HashDiff.diff(a, b, :array_path => true)
|
164
|
-
|
165
|
-
HashDiff.patch!(a, diff).should == b
|
166
|
-
|
167
|
-
a = {"a" => 1, "b" => 1}
|
168
|
-
b = {"a" => 1, "b" => 2}
|
169
|
-
HashDiff.unpatch!(b, diff).should == a
|
170
|
-
end
|
171
|
-
|
172
|
-
it "should be able to use non string keys when diff is generated with an array_path" do
|
173
|
-
a = {"a" => 1, :a => 2, 0 => 3}
|
174
|
-
b = {"a" => 5, :a => 6, 0 => 7}
|
175
|
-
diff = HashDiff.diff(a, b, :array_path => true)
|
176
|
-
|
177
|
-
HashDiff.patch!(a, diff).should == b
|
178
|
-
|
179
|
-
a = {"a" => 1, :a => 2, 0 => 3}
|
180
|
-
b = {"a" => 5, :a => 6, 0 => 7}
|
181
|
-
HashDiff.unpatch!(b, diff).should == a
|
182
|
-
end
|
183
|
-
end
|
data/spec/hashdiff/util_spec.rb
DELETED
@@ -1,78 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe HashDiff do
|
4
|
-
it "should be able to decode property path" do
|
5
|
-
decoded = HashDiff.send(:decode_property_path, "a.b[0].c.city[5]")
|
6
|
-
decoded.should == ['a', 'b', 0, 'c', 'city', 5]
|
7
|
-
end
|
8
|
-
|
9
|
-
it "should be able to decode property path with custom delimiter" do
|
10
|
-
decoded = HashDiff.send(:decode_property_path, "a\tb[0]\tc\tcity[5]", "\t")
|
11
|
-
decoded.should == ['a', 'b', 0, 'c', 'city', 5]
|
12
|
-
end
|
13
|
-
|
14
|
-
it "should be able to tell similiar hash" do
|
15
|
-
a = {'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5}
|
16
|
-
b = {'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5}
|
17
|
-
HashDiff.similar?(a, b).should be true
|
18
|
-
HashDiff.similar?(a, b, :similarity => 1).should be false
|
19
|
-
end
|
20
|
-
|
21
|
-
it "should be able to tell similiar hash with values within tolerance" do
|
22
|
-
a = {'a' => 1.5, 'b' => 2.25, 'c' => 3, 'd' => 4, 'e' => 5}
|
23
|
-
b = {'a' => 1.503, 'b' => 2.22, 'c' => 3, 'e' => 5}
|
24
|
-
HashDiff.similar?(a, b, :numeric_tolerance => 0.05).should be true
|
25
|
-
HashDiff.similar?(a, b).should be false
|
26
|
-
end
|
27
|
-
|
28
|
-
it "should be able to tell numbers and strings" do
|
29
|
-
HashDiff.similar?(1, 2).should be false
|
30
|
-
HashDiff.similar?("a", "b").should be false
|
31
|
-
HashDiff.similar?("a", [1, 2, 3]).should be false
|
32
|
-
HashDiff.similar?(1, {'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5}).should be false
|
33
|
-
end
|
34
|
-
|
35
|
-
it "should be able to tell true when similarity == 0.5" do
|
36
|
-
a = {"value" => "New1", "onclick" => "CreateNewDoc()"}
|
37
|
-
b = {"value" => "New", "onclick" => "CreateNewDoc()"}
|
38
|
-
|
39
|
-
HashDiff.similar?(a, b, :similarity => 0.5).should be true
|
40
|
-
end
|
41
|
-
|
42
|
-
it "should be able to tell false when similarity == 0.5" do
|
43
|
-
a = {"value" => "New1", "onclick" => "open()"}
|
44
|
-
b = {"value" => "New", "onclick" => "CreateNewDoc()"}
|
45
|
-
|
46
|
-
HashDiff.similar?(a, b, :similarity => 0.5).should be false
|
47
|
-
end
|
48
|
-
|
49
|
-
describe '.compare_values' do
|
50
|
-
it "should compare numeric values exactly when no tolerance" do
|
51
|
-
expect(HashDiff.compare_values(10.004, 10.003)).to be false
|
52
|
-
end
|
53
|
-
|
54
|
-
it "should allow tolerance with numeric values" do
|
55
|
-
expect(HashDiff.compare_values(10.004, 10.003, :numeric_tolerance => 0.01)).to be true
|
56
|
-
end
|
57
|
-
|
58
|
-
it "should compare other objects with or without tolerance" do
|
59
|
-
expect(HashDiff.compare_values('hats', 'ninjas')).to be false
|
60
|
-
expect(HashDiff.compare_values('hats', 'ninjas', :numeric_tolerance => 0.01)).to be false
|
61
|
-
expect(HashDiff.compare_values('horse', 'horse')).to be true
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'should compare strings exactly by default' do
|
65
|
-
expect(HashDiff.compare_values(' horse', 'horse')).to be false
|
66
|
-
expect(HashDiff.compare_values('horse', 'Horse')).to be false
|
67
|
-
end
|
68
|
-
|
69
|
-
it 'should strip strings before comparing when requested' do
|
70
|
-
expect(HashDiff.compare_values(' horse', 'horse', :strip => true)).to be true
|
71
|
-
end
|
72
|
-
|
73
|
-
it "should ignore string case when requested" do
|
74
|
-
expect(HashDiff.compare_values('horse', 'Horse', :case_insensitive => true)).to be true
|
75
|
-
end
|
76
|
-
|
77
|
-
end
|
78
|
-
end
|