hashdiff 1.1.0 → 1.2.0

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.
@@ -1,375 +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
- context 'with the ignore_keys option' do
53
- a = { a: 1, b: { d: 2, a: 3 }, c: 4 }
54
- b = { a: 2, b: { d: 2, a: 7 }, c: 5 }
55
-
56
- it 'ignores a single key' do
57
- diff = described_class.diff(a, b, ignore_keys: :a)
58
- diff.should == [['~', 'c', 4, 5]]
59
- end
60
-
61
- it 'ignores an array of keys' do
62
- diff = described_class.diff(a, b, ignore_keys: %i[a c])
63
- diff.should == []
64
- end
65
- end
66
-
67
- it 'ignores string vs symbol differences, when indifferent is true' do
68
- diff = described_class.diff({ 'a' => 2, :b => 2 }, { :a => 2, 'b' => 2, :c => 3 }, indifferent: true)
69
- diff.should == [['+', 'c', 3]]
70
- end
71
-
72
- it 'is able to diff changes in hash value' do
73
- diff = described_class.diff({ 'a' => 2, 'b' => 3, 'c' => ' hello' }, 'a' => 2, 'b' => 4, 'c' => 'hello')
74
- diff.should == [['~', 'b', 3, 4], ['~', 'c', ' hello', 'hello']]
75
- end
76
-
77
- it 'is able to diff changes in hash value which is array' do
78
- diff = described_class.diff({ 'a' => 2, 'b' => [1, 2, 3] }, 'a' => 2, 'b' => [1, 3, 4])
79
- diff.should == [['-', 'b[1]', 2], ['+', 'b[2]', 4]]
80
- end
81
-
82
- it 'is able to diff changes in hash value which is hash' do
83
- diff = described_class.diff({ 'a' => { 'x' => 2, 'y' => 3, 'z' => 4 }, 'b' => { 'x' => 3, 'z' => 45 } },
84
- 'a' => { 'y' => 3 }, 'b' => { 'y' => 3, 'z' => 30 })
85
- diff.should == [['-', 'a.x', 2], ['-', 'a.z', 4], ['-', 'b.x', 3], ['~', 'b.z', 45, 30], ['+', 'b.y', 3]]
86
- end
87
-
88
- it 'is able to best diff similar objects in array' do
89
- diff = described_class.best_diff({ 'a' => [{ 'x' => 2, 'y' => 3, 'z' => 4 }, { 'x' => 11, 'y' => 22, 'z' => 33 }], 'b' => { 'x' => 3, 'z' => 45 } },
90
- 'a' => [{ 'y' => 3 }, { 'x' => 11, 'z' => 33 }], 'b' => { 'y' => 22 })
91
- diff.should == [['-', 'a[0].x', 2], ['-', 'a[0].z', 4], ['-', 'a[1].y', 22], ['-', 'b.x', 3], ['-', 'b.z', 45], ['+', 'b.y', 22]]
92
- end
93
-
94
- it 'is able to diff addition of key value pair' do
95
- a = { 'a' => 3, 'c' => 11, 'd' => 45, 'e' => 100, 'f' => 200 }
96
- b = { 'a' => 3, 'c' => 11, 'd' => 45, 'e' => 100, 'f' => 200, 'g' => 300 }
97
-
98
- diff = described_class.diff(a, b)
99
- expect(diff).to eq([['+', 'g', 300]])
100
-
101
- diff = described_class.diff(b, a)
102
- diff.should == [['-', 'g', 300]]
103
- end
104
-
105
- it 'is able to diff value type changes' do
106
- a = { 'a' => 3 }
107
- b = { 'a' => { 'a1' => 1, 'a2' => 2 } }
108
-
109
- diff = described_class.diff(a, b)
110
- expect(diff).to eq([['~', 'a', 3, { 'a1' => 1, 'a2' => 2 }]])
111
-
112
- diff = described_class.diff(b, a)
113
- diff.should == [['~', 'a', { 'a1' => 1, 'a2' => 2 }, 3]]
114
- end
115
-
116
- it 'is able to diff value changes: array <=> []' do
117
- a = { 'a' => 1, 'b' => [1, 2] }
118
- b = { 'a' => 1, 'b' => [] }
119
-
120
- diff = described_class.diff(a, b)
121
- diff.should == [['-', 'b[1]', 2], ['-', 'b[0]', 1]]
122
- end
123
-
124
- it 'is able to diff value changes: array <=> nil' do
125
- a = { 'a' => 1, 'b' => [1, 2] }
126
- b = { 'a' => 1, 'b' => nil }
127
-
128
- diff = described_class.diff(a, b)
129
- diff.should == [['~', 'b', [1, 2], nil]]
130
- end
131
-
132
- it 'is able to diff value chagnes: remove array completely' do
133
- a = { 'a' => 1, 'b' => [1, 2] }
134
- b = { 'a' => 1 }
135
-
136
- diff = described_class.diff(a, b)
137
- diff.should == [['-', 'b', [1, 2]]]
138
- end
139
-
140
- it 'is able to diff value changes: remove whole hash' do
141
- a = { 'a' => 1, 'b' => { 'b1' => 1, 'b2' => 2 } }
142
- b = { 'a' => 1 }
143
-
144
- diff = described_class.diff(a, b)
145
- diff.should == [['-', 'b', { 'b1' => 1, 'b2' => 2 }]]
146
- end
147
-
148
- it 'is able to diff value changes: hash <=> {}' do
149
- a = { 'a' => 1, 'b' => { 'b1' => 1, 'b2' => 2 } }
150
- b = { 'a' => 1, 'b' => {} }
151
-
152
- diff = described_class.diff(a, b)
153
- diff.should == [['-', 'b.b1', 1], ['-', 'b.b2', 2]]
154
- end
155
-
156
- it 'is able to diff value changes: hash <=> nil' do
157
- a = { 'a' => 1, 'b' => { 'b1' => 1, 'b2' => 2 } }
158
- b = { 'a' => 1, 'b' => nil }
159
-
160
- diff = described_class.diff(a, b)
161
- diff.should == [['~', 'b', { 'b1' => 1, 'b2' => 2 }, nil]]
162
- end
163
-
164
- it 'is able to diff similar objects in array' do
165
- a = [{ 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5 }, 3]
166
- b = [1, { 'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5 }]
167
-
168
- diff = described_class.diff(a, b)
169
- diff.should == [['-', '[0].d', 4], ['+', '[0]', 1], ['-', '[2]', 3]]
170
- end
171
-
172
- it 'is able to diff similar & equal objects in array' do
173
- a = [{ 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5 }, { 'x' => 5, 'y' => 6, 'z' => 3 }, 3]
174
- b = [{ 'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5 }, 3]
175
-
176
- diff = described_class.diff(a, b)
177
- diff.should == [['-', '[0].d', 4], ['-', '[1]', { 'x' => 5, 'y' => 6, 'z' => 3 }]]
178
- end
179
-
180
- it 'uses custom delimiter when provided' do
181
- a = [{ 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5 }, { 'x' => 5, 'y' => 6, 'z' => 3 }, 3]
182
- b = [{ 'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5 }, 3]
183
-
184
- diff = described_class.diff(a, b, similarity: 0.8, delimiter: "\t")
185
- diff.should == [['-', "[0]\td", 4], ['-', '[1]', { 'x' => 5, 'y' => 6, 'z' => 3 }]]
186
- end
187
-
188
- context 'when :numeric_tolerance requested' do
189
- it 'is able to diff changes in hash value' do
190
- a = { 'a' => 0.558, 'b' => 0.0, 'c' => 0.65, 'd' => 'fin' }
191
- b = { 'a' => 0.557, 'b' => 'hats', 'c' => 0.67, 'd' => 'fin' }
192
-
193
- diff = described_class.diff(a, b, numeric_tolerance: 0.01)
194
- expect(diff).to eq([['~', 'b', 0.0, 'hats'], ['~', 'c', 0.65, 0.67]])
195
-
196
- diff = described_class.diff(b, a, numeric_tolerance: 0.01)
197
- diff.should == [['~', 'b', 'hats', 0.0], ['~', 'c', 0.67, 0.65]]
198
- end
199
-
200
- it 'is able to diff changes in nested values' do
201
- a = { 'a' => { 'x' => 0.4, 'y' => 0.338 }, 'b' => [13, 68.03] }
202
- b = { 'a' => { 'x' => 0.6, 'y' => 0.341 }, 'b' => [14, 68.025] }
203
-
204
- diff = described_class.diff(a, b, numeric_tolerance: 0.01)
205
- expect(diff).to eq([['~', 'a.x', 0.4, 0.6], ['-', 'b[0]', 13], ['+', 'b[0]', 14]])
206
-
207
- diff = described_class.diff(b, a, numeric_tolerance: 0.01)
208
- diff.should == [['~', 'a.x', 0.6, 0.4], ['-', 'b[0]', 14], ['+', 'b[0]', 13]]
209
- end
210
- end
211
-
212
- context 'when :strip requested' do
213
- it 'strips strings before comparing' do
214
- a = { 'a' => ' foo', 'b' => 'fizz buzz' }
215
- b = { 'a' => 'foo', 'b' => 'fizzbuzz' }
216
- diff = described_class.diff(a, b, strip: true)
217
- diff.should == [['~', 'b', 'fizz buzz', 'fizzbuzz']]
218
- end
219
-
220
- it 'strips nested strings before comparing' do
221
- a = { 'a' => { 'x' => ' foo' }, 'b' => ['fizz buzz', 'nerf'] }
222
- b = { 'a' => { 'x' => 'foo' }, 'b' => %w[fizzbuzz nerf] }
223
- diff = described_class.diff(a, b, strip: true)
224
- diff.should == [['-', 'b[0]', 'fizz buzz'], ['+', 'b[0]', 'fizzbuzz']]
225
- end
226
- end
227
-
228
- context 'when :case_insensitive requested' do
229
- it 'strips strings before comparing' do
230
- a = { 'a' => 'Foo', 'b' => 'fizz buzz' }
231
- b = { 'a' => 'foo', 'b' => 'fizzBuzz' }
232
- diff = described_class.diff(a, b, case_insensitive: true)
233
- diff.should == [['~', 'b', 'fizz buzz', 'fizzBuzz']]
234
- end
235
-
236
- it 'ignores case on nested strings before comparing' do
237
- a = { 'a' => { 'x' => 'Foo' }, 'b' => ['fizz buzz', 'nerf'] }
238
- b = { 'a' => { 'x' => 'foo' }, 'b' => %w[fizzbuzz nerf] }
239
- diff = described_class.diff(a, b, case_insensitive: true)
240
- diff.should == [['-', 'b[0]', 'fizz buzz'], ['+', 'b[0]', 'fizzbuzz']]
241
- end
242
- end
243
-
244
- context 'when both :strip and :numeric_tolerance requested' do
245
- it 'applies filters to proper object types' do
246
- a = { 'a' => ' foo', 'b' => 35, 'c' => 'bar', 'd' => 'baz' }
247
- b = { 'a' => 'foo', 'b' => 35.005, 'c' => 'bar', 'd' => 18.5 }
248
- diff = described_class.diff(a, b, strict: false, numeric_tolerance: 0.01, strip: true)
249
- diff.should == [['~', 'd', 'baz', 18.5]]
250
- end
251
- end
252
-
253
- context 'when both :strip and :case_insensitive requested' do
254
- it 'applies both filters to strings' do
255
- a = { 'a' => ' Foo', 'b' => 'fizz buzz' }
256
- b = { 'a' => 'foo', 'b' => 'fizzBuzz' }
257
- diff = described_class.diff(a, b, case_insensitive: true, strip: true)
258
- diff.should == [['~', 'b', 'fizz buzz', 'fizzBuzz']]
259
- end
260
- end
261
-
262
- context 'with custom comparison' do
263
- let(:a) { { 'a' => 'car', 'b' => 'boat', 'c' => 'plane' } }
264
- let(:b) { { 'a' => 'bus', 'b' => 'truck', 'c' => ' plan' } }
265
-
266
- it 'compares using proc specified in block' do
267
- diff = described_class.diff(a, b) do |prefix, obj1, obj2|
268
- case prefix
269
- when /a|b|c/
270
- obj1.length == obj2.length
271
- end
272
- end
273
- diff.should == [['~', 'b', 'boat', 'truck']]
274
- end
275
-
276
- it 'yields added keys' do
277
- x = { 'a' => 'car', 'b' => 'boat' }
278
- y = { 'a' => 'car' }
279
-
280
- diff = described_class.diff(x, y) do |prefix, _obj1, _obj2|
281
- case prefix
282
- when /b/
283
- true
284
- end
285
- end
286
- diff.should == []
287
- end
288
-
289
- it 'compares with both proc and :strip when both provided' do
290
- diff = described_class.diff(a, b, strip: true) do |prefix, obj1, obj2|
291
- case prefix
292
- when 'a'
293
- obj1.length == obj2.length
294
- end
295
- end
296
- diff.should == [['~', 'b', 'boat', 'truck'], ['~', 'c', 'plane', ' plan']]
297
- end
298
-
299
- it 'compares nested arrays using proc specified in block' do
300
- a = { a: 'car', b: %w[boat plane] }
301
- b = { a: 'bus', b: ['truck', ' plan'] }
302
-
303
- diff = described_class.diff(a, b) do |path, obj1, obj2|
304
- case path
305
- when 'b[*]'
306
- obj1.length == obj2.length
307
- end
308
- end
309
-
310
- expect(diff).to eq [['~', 'a', 'car', 'bus'], ['~', 'b[1]', 'plane', ' plan'], ['-', 'b[0]', 'boat'], ['+', 'b[0]', 'truck']]
311
- end
312
- end
313
-
314
- context 'when :array_path is true' do
315
- it 'returns the diff path in an array rather than a string' do
316
- x = { 'a' => 'foo' }
317
- y = { 'a' => 'bar' }
318
- diff = described_class.diff(x, y, array_path: true)
319
-
320
- diff.should == [['~', ['a'], 'foo', 'bar']]
321
- end
322
-
323
- it 'shows array indexes in paths' do
324
- x = { 'a' => [0, 1, 2] }
325
- y = { 'a' => [0, 1, 2, 3] }
326
-
327
- diff = described_class.diff(x, y, array_path: true)
328
-
329
- diff.should == [['+', ['a', 3], 3]]
330
- end
331
-
332
- it 'shows differences with string and symbol keys' do
333
- x = { 'a' => 'foo' }
334
- y = { a: 'bar' }
335
-
336
- diff = described_class.diff(x, y, array_path: true)
337
- diff.should == [['-', ['a'], 'foo'], ['+', [:a], 'bar']]
338
- end
339
-
340
- it 'supports other key types' do
341
- time = Time.now
342
- x = { time => 'foo' }
343
- y = { 0 => 'bar' }
344
-
345
- diff = described_class.diff(x, y, array_path: true)
346
- diff.should == [['-', [time], 'foo'], ['+', [0], 'bar']]
347
- end
348
- end
349
-
350
- context 'when :use_lcs is false' do
351
- it 'shows items in an array as changed' do
352
- x = %i[a b]
353
- y = %i[c d]
354
- diff = described_class.diff(x, y, use_lcs: false)
355
-
356
- diff.should == [['~', '[0]', :a, :c], ['~', '[1]', :b, :d]]
357
- end
358
-
359
- it 'shows additions to arrays' do
360
- x = { a: [0] }
361
- y = { a: [0, 1] }
362
- diff = described_class.diff(x, y, use_lcs: false)
363
-
364
- diff.should == [['+', 'a[1]', 1]]
365
- end
366
-
367
- it 'shows changes to nested arrays' do
368
- x = { a: [[0, 1]] }
369
- y = { a: [[1, 2]] }
370
- diff = described_class.diff(x, y, use_lcs: false)
371
-
372
- diff.should == [['~', 'a[0][0]', 0, 1], ['~', 'a[0][1]', 1, 2]]
373
- end
374
- end
375
- end
@@ -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
@@ -1,185 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- describe Hashdiff do
6
- it 'is able to patch key addition' do
7
- a = { 'a' => 3, 'c' => 11, 'd' => 45, 'e' => 100, 'f' => 200 }
8
- b = { 'a' => 3, 'c' => 11, 'd' => 45, 'e' => 100, 'f' => 200, 'g' => 300 }
9
- diff = described_class.diff(a, b)
10
-
11
- expect(described_class.patch!(a, diff)).to eq(b)
12
-
13
- a = { 'a' => 3, 'c' => 11, 'd' => 45, 'e' => 100, 'f' => 200 }
14
- b = { 'a' => 3, 'c' => 11, 'd' => 45, 'e' => 100, 'f' => 200, 'g' => 300 }
15
- described_class.unpatch!(b, diff).should == a
16
- end
17
-
18
- it 'is able to patch value type changes' do
19
- a = { 'a' => 3 }
20
- b = { 'a' => { 'a1' => 1, 'a2' => 2 } }
21
- diff = described_class.diff(a, b)
22
-
23
- expect(described_class.patch!(a, diff)).to eq(b)
24
-
25
- a = { 'a' => 3 }
26
- b = { 'a' => { 'a1' => 1, 'a2' => 2 } }
27
- described_class.unpatch!(b, diff).should == a
28
- end
29
-
30
- it 'is able to patch value array <=> []' do
31
- a = { 'a' => 1, 'b' => [1, 2] }
32
- b = { 'a' => 1, 'b' => [] }
33
- diff = described_class.diff(a, b)
34
-
35
- expect(described_class.patch!(a, diff)).to eq(b)
36
-
37
- a = { 'a' => 1, 'b' => [1, 2] }
38
- b = { 'a' => 1, 'b' => [] }
39
- described_class.unpatch!(b, diff).should == a
40
- end
41
-
42
- it 'is able to patch value array <=> nil' do
43
- a = { 'a' => 1, 'b' => [1, 2] }
44
- b = { 'a' => 1, 'b' => nil }
45
- diff = described_class.diff(a, b)
46
-
47
- expect(described_class.patch!(a, diff)).to eq(b)
48
-
49
- a = { 'a' => 1, 'b' => [1, 2] }
50
- b = { 'a' => 1, 'b' => nil }
51
- described_class.unpatch!(b, diff).should == a
52
- end
53
-
54
- it 'is able to patch array value removal' do
55
- a = { 'a' => 1, 'b' => [1, 2] }
56
- b = { 'a' => 1 }
57
- diff = described_class.diff(a, b)
58
-
59
- expect(described_class.patch!(a, diff)).to eq(b)
60
-
61
- a = { 'a' => 1, 'b' => [1, 2] }
62
- b = { 'a' => 1 }
63
- described_class.unpatch!(b, diff).should == a
64
- end
65
-
66
- it 'is able to patch array under hash key with non-word characters' do
67
- a = { 'a' => 1, 'b-b' => [1, 2] }
68
- b = { 'a' => 1, 'b-b' => [2, 1] }
69
- diff = described_class.diff(a, b)
70
-
71
- expect(described_class.patch!(a, diff)).to eq(b)
72
-
73
- a = { 'a' => 1, 'b-b' => [1, 2] }
74
- b = { 'a' => 1, 'b-b' => [2, 1] }
75
- described_class.unpatch!(b, diff).should == a
76
- end
77
-
78
- it 'is able to patch hash value removal' do
79
- a = { 'a' => 1, 'b' => { 'b1' => 1, 'b2' => 2 } }
80
- b = { 'a' => 1 }
81
- diff = described_class.diff(a, b)
82
-
83
- expect(described_class.patch!(a, diff)).to eq(b)
84
-
85
- a = { 'a' => 1, 'b' => { 'b1' => 1, 'b2' => 2 } }
86
- b = { 'a' => 1 }
87
- described_class.unpatch!(b, diff).should == a
88
- end
89
-
90
- it 'is able to patch value hash <=> {}' do
91
- a = { 'a' => 1, 'b' => { 'b1' => 1, 'b2' => 2 } }
92
- b = { 'a' => 1, 'b' => {} }
93
- diff = described_class.diff(a, b)
94
-
95
- expect(described_class.patch!(a, diff)).to eq(b)
96
-
97
- a = { 'a' => 1, 'b' => { 'b1' => 1, 'b2' => 2 } }
98
- b = { 'a' => 1, 'b' => {} }
99
- described_class.unpatch!(b, diff).should == a
100
- end
101
-
102
- it 'is able to patch value hash <=> nil' do
103
- a = { 'a' => 1, 'b' => { 'b1' => 1, 'b2' => 2 } }
104
- b = { 'a' => 1, 'b' => nil }
105
- diff = described_class.diff(a, b)
106
-
107
- expect(described_class.patch!(a, diff)).to eq(b)
108
-
109
- a = { 'a' => 1, 'b' => { 'b1' => 1, 'b2' => 2 } }
110
- b = { 'a' => 1, 'b' => nil }
111
- described_class.unpatch!(b, diff).should == a
112
- end
113
-
114
- it 'is able to patch value nil removal' do
115
- a = { 'a' => 1, 'b' => nil }
116
- b = { 'a' => 1 }
117
- diff = described_class.diff(a, b)
118
-
119
- expect(described_class.patch!(a, diff)).to eq(b)
120
-
121
- a = { 'a' => 1, 'b' => nil }
122
- b = { 'a' => 1 }
123
- described_class.unpatch!(b, diff).should == a
124
- end
125
-
126
- it 'is able to patch similar objects between arrays' do
127
- a = [{ 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5 }, 3]
128
- b = [1, { 'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5 }]
129
-
130
- diff = described_class.diff(a, b)
131
- expect(described_class.patch!(a, diff)).to eq(b)
132
-
133
- a = [{ 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5 }, 3]
134
- b = [1, { 'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5 }]
135
- described_class.unpatch!(b, diff).should == a
136
- end
137
-
138
- it 'is able to patch similar & equal objects between arrays' do
139
- a = [{ 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5 }, { 'x' => 5, 'y' => 6, 'z' => 3 }, 1]
140
- b = [1, { 'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5 }]
141
-
142
- diff = described_class.diff(a, b)
143
- expect(described_class.patch!(a, diff)).to eq(b)
144
-
145
- a = [{ 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5 }, { 'x' => 5, 'y' => 6, 'z' => 3 }, 1]
146
- b = [1, { 'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5 }]
147
- described_class.unpatch!(b, diff).should == a
148
- end
149
-
150
- it 'is able to patch hash value removal with custom delimiter' do
151
- a = { 'a' => 1, 'b' => { 'b1' => 1, 'b2' => 2 } }
152
- b = { 'a' => 1, 'b' => { 'b1' => 3 } }
153
- diff = described_class.diff(a, b, delimiter: "\n")
154
-
155
- expect(described_class.patch!(a, diff, delimiter: "\n")).to eq(b)
156
-
157
- a = { 'a' => 1, 'b' => { 'b1' => 1, 'b2' => 2 } }
158
- b = { 'a' => 1, 'b' => { 'b1' => 3 } }
159
- described_class.unpatch!(b, diff, delimiter: "\n").should == a
160
- end
161
-
162
- it 'is able to patch when the diff is generated with an array_path' do
163
- a = { 'a' => 1, 'b' => 1 }
164
- b = { 'a' => 1, 'b' => 2 }
165
- diff = described_class.diff(a, b, array_path: true)
166
-
167
- expect(described_class.patch!(a, diff)).to eq(b)
168
-
169
- a = { 'a' => 1, 'b' => 1 }
170
- b = { 'a' => 1, 'b' => 2 }
171
- described_class.unpatch!(b, diff).should == a
172
- end
173
-
174
- it 'is able to use non string keys when diff is generated with an array_path' do
175
- a = { 'a' => 1, :a => 2, 0 => 3 }
176
- b = { 'a' => 5, :a => 6, 0 => 7 }
177
- diff = described_class.diff(a, b, array_path: true)
178
-
179
- expect(described_class.patch!(a, diff)).to eq(b)
180
-
181
- a = { 'a' => 1, :a => 2, 0 => 3 }
182
- b = { 'a' => 5, :a => 6, 0 => 7 }
183
- described_class.unpatch!(b, diff).should == a
184
- end
185
- end