hashdiff 1.0.1 → 1.2.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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +27 -0
- data/.rubocop.yml +11 -1
- data/Gemfile +2 -2
- data/README.md +51 -4
- data/changelog.md +44 -17
- data/hashdiff.gemspec +4 -4
- data/lib/hashdiff/compare_hashes.rb +61 -29
- data/lib/hashdiff/diff.rb +9 -1
- data/lib/hashdiff/version.rb +1 -1
- metadata +14 -22
- data/spec/hashdiff/best_diff_spec.rb +0 -75
- data/spec/hashdiff/diff_array_spec.rb +0 -60
- data/spec/hashdiff/diff_spec.rb +0 -360
- data/spec/hashdiff/lcs_spec.rb +0 -76
- data/spec/hashdiff/linear_compare_array_spec.rb +0 -50
- data/spec/hashdiff/patch_spec.rb +0 -185
- data/spec/hashdiff/readme_spec.rb +0 -15
- data/spec/hashdiff/util_spec.rb +0 -116
- data/spec/spec_helper.rb +0 -15
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'spec_helper'
|
|
4
|
-
|
|
5
|
-
describe Hashdiff do
|
|
6
|
-
it 'is able to diff two equal array' do
|
|
7
|
-
a = [1, 2, 3]
|
|
8
|
-
b = [1, 2, 3]
|
|
9
|
-
|
|
10
|
-
diff = described_class.diff_array_lcs(a, b)
|
|
11
|
-
diff.should == []
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
it 'is able to diff two arrays with one element in common' do
|
|
15
|
-
a = [1, 2, 3]
|
|
16
|
-
b = [1, 8, 7]
|
|
17
|
-
|
|
18
|
-
diff = described_class.diff_array_lcs(a, b)
|
|
19
|
-
diff.should == [['-', 2, 3], ['-', 1, 2], ['+', 1, 8], ['+', 2, 7]]
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
it 'is able to diff two arrays with nothing in common' do
|
|
23
|
-
a = [1, 2]
|
|
24
|
-
b = []
|
|
25
|
-
|
|
26
|
-
diff = described_class.diff_array_lcs(a, b)
|
|
27
|
-
diff.should == [['-', 1, 2], ['-', 0, 1]]
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
it 'is able to diff an empty array with an non-empty array' do
|
|
31
|
-
a = []
|
|
32
|
-
b = [1, 2]
|
|
33
|
-
|
|
34
|
-
diff = described_class.diff_array_lcs(a, b)
|
|
35
|
-
diff.should == [['+', 0, 1], ['+', 1, 2]]
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
it 'is able to diff two arrays with two elements in common' do
|
|
39
|
-
a = [1, 3, 5, 7]
|
|
40
|
-
b = [2, 3, 7, 5]
|
|
41
|
-
|
|
42
|
-
diff = described_class.diff_array_lcs(a, b)
|
|
43
|
-
diff.should == [['-', 0, 1], ['+', 0, 2], ['+', 2, 7], ['-', 4, 7]]
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
it 'is able to test two arrays with two common elements in different order' do
|
|
47
|
-
a = [1, 3, 4, 7]
|
|
48
|
-
b = [2, 3, 7, 5]
|
|
49
|
-
|
|
50
|
-
diff = described_class.diff_array_lcs(a, b)
|
|
51
|
-
diff.should == [['-', 0, 1], ['+', 0, 2], ['-', 2, 4], ['+', 3, 5]]
|
|
52
|
-
end
|
|
53
|
-
|
|
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)
|
|
58
|
-
diff.should == [['+', 0, 1], ['-', 2, 3]]
|
|
59
|
-
end
|
|
60
|
-
end
|
data/spec/hashdiff/diff_spec.rb
DELETED
|
@@ -1,360 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'spec_helper'
|
|
4
|
-
|
|
5
|
-
describe Hashdiff do
|
|
6
|
-
it 'is able to diff two empty hashes' do
|
|
7
|
-
diff = described_class.diff({}, {})
|
|
8
|
-
diff.should == []
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
it 'is able to diff an hash with an empty hash' do
|
|
12
|
-
a = { 'a' => 3, 'b' => 2 }
|
|
13
|
-
b = {}
|
|
14
|
-
|
|
15
|
-
diff = described_class.diff(a, b)
|
|
16
|
-
expect(diff).to eq([['-', 'a', 3], ['-', 'b', 2]])
|
|
17
|
-
|
|
18
|
-
diff = described_class.diff(b, a)
|
|
19
|
-
diff.should == [['+', 'a', 3], ['+', 'b', 2]]
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
it 'is able to diff two equal hashes' do
|
|
23
|
-
diff = described_class.diff({ 'a' => 2, 'b' => 2 }, 'a' => 2, 'b' => 2)
|
|
24
|
-
diff.should == []
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
it 'is able to diff two equal hashes with mixed key types' do
|
|
28
|
-
a = { 'a' => 1, :b => 1 }
|
|
29
|
-
diff = described_class.diff(a, a)
|
|
30
|
-
diff.should == []
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
it 'is able to diff if mixed key types are removed' do
|
|
34
|
-
a = { 'a' => 1, :b => 1 }
|
|
35
|
-
b = {}
|
|
36
|
-
diff = described_class.diff(a, b)
|
|
37
|
-
diff.should == [['-', 'a', 1], ['-', 'b', 1]]
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
it 'is able to diff if mixed key types are added' do
|
|
41
|
-
a = { 'a' => 1, :b => 1 }
|
|
42
|
-
b = {}
|
|
43
|
-
diff = described_class.diff(b, a)
|
|
44
|
-
diff.should == [['+', 'a', 1], ['+', 'b', 1]]
|
|
45
|
-
end
|
|
46
|
-
|
|
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)
|
|
49
|
-
diff.should == []
|
|
50
|
-
end
|
|
51
|
-
|
|
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']]
|
|
60
|
-
end
|
|
61
|
-
|
|
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])
|
|
64
|
-
diff.should == [['-', 'b[1]', 2], ['+', 'b[2]', 4]]
|
|
65
|
-
end
|
|
66
|
-
|
|
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 })
|
|
70
|
-
diff.should == [['-', 'a.x', 2], ['-', 'a.z', 4], ['-', 'b.x', 3], ['~', 'b.z', 45, 30], ['+', 'b.y', 3]]
|
|
71
|
-
end
|
|
72
|
-
|
|
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 })
|
|
76
|
-
diff.should == [['-', 'a[0].x', 2], ['-', 'a[0].z', 4], ['-', 'a[1].y', 22], ['-', 'b.x', 3], ['-', 'b.z', 45], ['+', 'b.y', 22]]
|
|
77
|
-
end
|
|
78
|
-
|
|
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 }
|
|
82
|
-
|
|
83
|
-
diff = described_class.diff(a, b)
|
|
84
|
-
expect(diff).to eq([['+', 'g', 300]])
|
|
85
|
-
|
|
86
|
-
diff = described_class.diff(b, a)
|
|
87
|
-
diff.should == [['-', 'g', 300]]
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
it 'is able to diff value type changes' do
|
|
91
|
-
a = { 'a' => 3 }
|
|
92
|
-
b = { 'a' => { 'a1' => 1, 'a2' => 2 } }
|
|
93
|
-
|
|
94
|
-
diff = described_class.diff(a, b)
|
|
95
|
-
expect(diff).to eq([['~', 'a', 3, { 'a1' => 1, 'a2' => 2 }]])
|
|
96
|
-
|
|
97
|
-
diff = described_class.diff(b, a)
|
|
98
|
-
diff.should == [['~', 'a', { 'a1' => 1, 'a2' => 2 }, 3]]
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
it 'is able to diff value changes: array <=> []' do
|
|
102
|
-
a = { 'a' => 1, 'b' => [1, 2] }
|
|
103
|
-
b = { 'a' => 1, 'b' => [] }
|
|
104
|
-
|
|
105
|
-
diff = described_class.diff(a, b)
|
|
106
|
-
diff.should == [['-', 'b[1]', 2], ['-', 'b[0]', 1]]
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
it 'is able to diff value changes: array <=> nil' do
|
|
110
|
-
a = { 'a' => 1, 'b' => [1, 2] }
|
|
111
|
-
b = { 'a' => 1, 'b' => nil }
|
|
112
|
-
|
|
113
|
-
diff = described_class.diff(a, b)
|
|
114
|
-
diff.should == [['~', 'b', [1, 2], nil]]
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
it 'is able to diff value chagnes: remove array completely' do
|
|
118
|
-
a = { 'a' => 1, 'b' => [1, 2] }
|
|
119
|
-
b = { 'a' => 1 }
|
|
120
|
-
|
|
121
|
-
diff = described_class.diff(a, b)
|
|
122
|
-
diff.should == [['-', 'b', [1, 2]]]
|
|
123
|
-
end
|
|
124
|
-
|
|
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 }
|
|
128
|
-
|
|
129
|
-
diff = described_class.diff(a, b)
|
|
130
|
-
diff.should == [['-', 'b', { 'b1' => 1, 'b2' => 2 }]]
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
it 'is able to diff value changes: hash <=> {}' do
|
|
134
|
-
a = { 'a' => 1, 'b' => { 'b1' => 1, 'b2' => 2 } }
|
|
135
|
-
b = { 'a' => 1, 'b' => {} }
|
|
136
|
-
|
|
137
|
-
diff = described_class.diff(a, b)
|
|
138
|
-
diff.should == [['-', 'b.b1', 1], ['-', 'b.b2', 2]]
|
|
139
|
-
end
|
|
140
|
-
|
|
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 }
|
|
144
|
-
|
|
145
|
-
diff = described_class.diff(a, b)
|
|
146
|
-
diff.should == [['~', 'b', { 'b1' => 1, 'b2' => 2 }, nil]]
|
|
147
|
-
end
|
|
148
|
-
|
|
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 }]
|
|
152
|
-
|
|
153
|
-
diff = described_class.diff(a, b)
|
|
154
|
-
diff.should == [['-', '[0].d', 4], ['+', '[0]', 1], ['-', '[2]', 3]]
|
|
155
|
-
end
|
|
156
|
-
|
|
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]
|
|
160
|
-
|
|
161
|
-
diff = described_class.diff(a, b)
|
|
162
|
-
diff.should == [['-', '[0].d', 4], ['-', '[1]', { 'x' => 5, 'y' => 6, 'z' => 3 }]]
|
|
163
|
-
end
|
|
164
|
-
|
|
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]
|
|
168
|
-
|
|
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 }]]
|
|
171
|
-
end
|
|
172
|
-
|
|
173
|
-
context 'when :numeric_tolerance requested' do
|
|
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' }
|
|
177
|
-
|
|
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]])
|
|
180
|
-
|
|
181
|
-
diff = described_class.diff(b, a, numeric_tolerance: 0.01)
|
|
182
|
-
diff.should == [['~', 'b', 'hats', 0.0], ['~', 'c', 0.67, 0.65]]
|
|
183
|
-
end
|
|
184
|
-
|
|
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] }
|
|
188
|
-
|
|
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]])
|
|
191
|
-
|
|
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]]
|
|
194
|
-
end
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
context 'when :strip requested' do
|
|
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']]
|
|
203
|
-
end
|
|
204
|
-
|
|
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']]
|
|
210
|
-
end
|
|
211
|
-
end
|
|
212
|
-
|
|
213
|
-
context 'when :case_insensitive requested' do
|
|
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']]
|
|
219
|
-
end
|
|
220
|
-
|
|
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']]
|
|
226
|
-
end
|
|
227
|
-
end
|
|
228
|
-
|
|
229
|
-
context 'when both :strip and :numeric_tolerance requested' do
|
|
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]]
|
|
235
|
-
end
|
|
236
|
-
end
|
|
237
|
-
|
|
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']]
|
|
244
|
-
end
|
|
245
|
-
end
|
|
246
|
-
|
|
247
|
-
context 'with custom comparison' do
|
|
248
|
-
let(:a) { { 'a' => 'car', 'b' => 'boat', 'c' => 'plane' } }
|
|
249
|
-
let(:b) { { 'a' => 'bus', 'b' => 'truck', 'c' => ' plan' } }
|
|
250
|
-
|
|
251
|
-
it 'compares using proc specified in block' do
|
|
252
|
-
diff = described_class.diff(a, b) do |prefix, obj1, obj2|
|
|
253
|
-
case prefix
|
|
254
|
-
when /a|b|c/
|
|
255
|
-
obj1.length == obj2.length
|
|
256
|
-
end
|
|
257
|
-
end
|
|
258
|
-
diff.should == [['~', 'b', 'boat', 'truck']]
|
|
259
|
-
end
|
|
260
|
-
|
|
261
|
-
it 'yields added keys' do
|
|
262
|
-
x = { 'a' => 'car', 'b' => 'boat' }
|
|
263
|
-
y = { 'a' => 'car' }
|
|
264
|
-
|
|
265
|
-
diff = described_class.diff(x, y) do |prefix, _obj1, _obj2|
|
|
266
|
-
case prefix
|
|
267
|
-
when /b/
|
|
268
|
-
true
|
|
269
|
-
end
|
|
270
|
-
end
|
|
271
|
-
diff.should == []
|
|
272
|
-
end
|
|
273
|
-
|
|
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|
|
|
276
|
-
case prefix
|
|
277
|
-
when 'a'
|
|
278
|
-
obj1.length == obj2.length
|
|
279
|
-
end
|
|
280
|
-
end
|
|
281
|
-
diff.should == [['~', 'b', 'boat', 'truck'], ['~', 'c', 'plane', ' plan']]
|
|
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
|
|
297
|
-
end
|
|
298
|
-
|
|
299
|
-
context 'when :array_path is true' do
|
|
300
|
-
it 'returns the diff path in an array rather than a string' do
|
|
301
|
-
x = { 'a' => 'foo' }
|
|
302
|
-
y = { 'a' => 'bar' }
|
|
303
|
-
diff = described_class.diff(x, y, array_path: true)
|
|
304
|
-
|
|
305
|
-
diff.should == [['~', ['a'], 'foo', 'bar']]
|
|
306
|
-
end
|
|
307
|
-
|
|
308
|
-
it 'shows array indexes in paths' do
|
|
309
|
-
x = { 'a' => [0, 1, 2] }
|
|
310
|
-
y = { 'a' => [0, 1, 2, 3] }
|
|
311
|
-
|
|
312
|
-
diff = described_class.diff(x, y, array_path: true)
|
|
313
|
-
|
|
314
|
-
diff.should == [['+', ['a', 3], 3]]
|
|
315
|
-
end
|
|
316
|
-
|
|
317
|
-
it 'shows differences with string and symbol keys' do
|
|
318
|
-
x = { 'a' => 'foo' }
|
|
319
|
-
y = { a: 'bar' }
|
|
320
|
-
|
|
321
|
-
diff = described_class.diff(x, y, array_path: true)
|
|
322
|
-
diff.should == [['-', ['a'], 'foo'], ['+', [:a], 'bar']]
|
|
323
|
-
end
|
|
324
|
-
|
|
325
|
-
it 'supports other key types' do
|
|
326
|
-
time = Time.now
|
|
327
|
-
x = { time => 'foo' }
|
|
328
|
-
y = { 0 => 'bar' }
|
|
329
|
-
|
|
330
|
-
diff = described_class.diff(x, y, array_path: true)
|
|
331
|
-
diff.should == [['-', [time], 'foo'], ['+', [0], 'bar']]
|
|
332
|
-
end
|
|
333
|
-
end
|
|
334
|
-
|
|
335
|
-
context 'when :use_lcs is false' do
|
|
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)
|
|
340
|
-
|
|
341
|
-
diff.should == [['~', '[0]', :a, :c], ['~', '[1]', :b, :d]]
|
|
342
|
-
end
|
|
343
|
-
|
|
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)
|
|
348
|
-
|
|
349
|
-
diff.should == [['+', 'a[1]', 1]]
|
|
350
|
-
end
|
|
351
|
-
|
|
352
|
-
it 'shows changes to nested arrays' do
|
|
353
|
-
x = { a: [[0, 1]] }
|
|
354
|
-
y = { a: [[1, 2]] }
|
|
355
|
-
diff = described_class.diff(x, y, use_lcs: false)
|
|
356
|
-
|
|
357
|
-
diff.should == [['~', 'a[0][0]', 0, 1], ['~', 'a[0][1]', 1, 2]]
|
|
358
|
-
end
|
|
359
|
-
end
|
|
360
|
-
end
|
data/spec/hashdiff/lcs_spec.rb
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'spec_helper'
|
|
4
|
-
|
|
5
|
-
describe Hashdiff do
|
|
6
|
-
it 'is able to find LCS between two equal array' do
|
|
7
|
-
a = [1, 2, 3]
|
|
8
|
-
b = [1, 2, 3]
|
|
9
|
-
|
|
10
|
-
lcs = described_class.lcs(a, b)
|
|
11
|
-
lcs.should == [[0, 0], [1, 1], [2, 2]]
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
it 'is able to find LCS between two close arrays' do
|
|
15
|
-
a = [1.05, 2, 3.25]
|
|
16
|
-
b = [1.06, 2, 3.24]
|
|
17
|
-
|
|
18
|
-
lcs = described_class.lcs(a, b, numeric_tolerance: 0.1)
|
|
19
|
-
lcs.should == [[0, 0], [1, 1], [2, 2]]
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
it 'strips strings when finding LCS if requested' do
|
|
23
|
-
a = %w[foo bar baz]
|
|
24
|
-
b = [' foo', 'bar', 'zab']
|
|
25
|
-
|
|
26
|
-
lcs = described_class.lcs(a, b, strip: true)
|
|
27
|
-
lcs.should == [[0, 0], [1, 1]]
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
it 'is able to find LCS with one common elements' do
|
|
31
|
-
a = [1, 2, 3]
|
|
32
|
-
b = [1, 8, 7]
|
|
33
|
-
|
|
34
|
-
lcs = described_class.lcs(a, b)
|
|
35
|
-
lcs.should == [[0, 0]]
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
it 'is able to find LCS with two common elements' do
|
|
39
|
-
a = [1, 3, 5, 7]
|
|
40
|
-
b = [2, 3, 7, 5]
|
|
41
|
-
|
|
42
|
-
lcs = described_class.lcs(a, b)
|
|
43
|
-
lcs.should == [[1, 1], [2, 3]]
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
it 'is able to find LCS with two close elements' do
|
|
47
|
-
a = [1, 3.05, 5, 7]
|
|
48
|
-
b = [2, 3.06, 7, 5]
|
|
49
|
-
|
|
50
|
-
lcs = described_class.lcs(a, b, numeric_tolerance: 0.1)
|
|
51
|
-
lcs.should == [[1, 1], [2, 3]]
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
it 'is able to find LCS with two common elements in different ordering' do
|
|
55
|
-
a = [1, 3, 4, 7]
|
|
56
|
-
b = [2, 3, 7, 5]
|
|
57
|
-
|
|
58
|
-
lcs = described_class.lcs(a, b)
|
|
59
|
-
lcs.should == [[1, 1], [3, 2]]
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
it 'is able to find LCS with a similarity value' do
|
|
63
|
-
a = [
|
|
64
|
-
{ 'value' => 'New', 'onclick' => 'CreateNewDoc()' },
|
|
65
|
-
{ 'value' => 'Close', 'onclick' => 'CloseDoc()' }
|
|
66
|
-
]
|
|
67
|
-
b = [
|
|
68
|
-
{ 'value' => 'New1', 'onclick' => 'CreateNewDoc()' },
|
|
69
|
-
{ 'value' => 'Open', 'onclick' => 'OpenDoc()' },
|
|
70
|
-
{ 'value' => 'Close', 'onclick' => 'CloseDoc()' }
|
|
71
|
-
]
|
|
72
|
-
|
|
73
|
-
lcs = described_class.lcs(a, b, similarity: 0.5)
|
|
74
|
-
lcs.should == [[0, 0], [1, 2]]
|
|
75
|
-
end
|
|
76
|
-
end
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'spec_helper'
|
|
4
|
-
|
|
5
|
-
describe Hashdiff::LinearCompareArray do
|
|
6
|
-
it 'finds no differences between two empty arrays' do
|
|
7
|
-
difference = described_class.call([], [])
|
|
8
|
-
difference.should == []
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
it 'finds added items when the old array is empty' do
|
|
12
|
-
difference = described_class.call([], %i[a b])
|
|
13
|
-
difference.should == [['+', '[0]', :a], ['+', '[1]', :b]]
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
it 'finds removed items when the new array is empty' do
|
|
17
|
-
difference = described_class.call(%i[a b], [])
|
|
18
|
-
difference.should == [['-', '[1]', :b], ['-', '[0]', :a]]
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
it 'finds no differences between identical arrays' do
|
|
22
|
-
difference = described_class.call(%i[a b], %i[a b])
|
|
23
|
-
difference.should == []
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
it 'finds added items in an array' do
|
|
27
|
-
difference = described_class.call(%i[a d], %i[a b c d])
|
|
28
|
-
difference.should == [['+', '[1]', :b], ['+', '[2]', :c]]
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
it 'finds removed items in an array' do
|
|
32
|
-
difference = described_class.call(%i[a b c d e f], %i[a d f])
|
|
33
|
-
difference.should == [['-', '[4]', :e], ['-', '[2]', :c], ['-', '[1]', :b]]
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
it 'shows additions and deletions as changed items' do
|
|
37
|
-
difference = described_class.call(%i[a b c], %i[c b a])
|
|
38
|
-
difference.should == [['~', '[0]', :a, :c], ['~', '[2]', :c, :a]]
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
it 'shows changed items in a hash' do
|
|
42
|
-
difference = described_class.call([{ a: :b }], [{ a: :c }])
|
|
43
|
-
difference.should == [['~', '[0].a', :b, :c]]
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
it 'shows changed items and added items' do
|
|
47
|
-
difference = described_class.call([{ a: 1, b: 2 }], [{ a: 2, b: 2 }, :item])
|
|
48
|
-
difference.should == [['~', '[0].a', 1, 2], ['+', '[1]', :item]]
|
|
49
|
-
end
|
|
50
|
-
end
|