osullivan 0.0.2
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 +7 -0
- data/.gitignore +4 -0
- data/.rspec +3 -0
- data/.travis.yml +4 -0
- data/Gemfile +2 -0
- data/LICENSE +23 -0
- data/README.md +166 -0
- data/Rakefile +12 -0
- data/VERSION +1 -0
- data/lib/active_support/ordered_hash.rb +147 -0
- data/lib/iiif/hash_behaviours.rb +150 -0
- data/lib/iiif/presentation.rb +25 -0
- data/lib/iiif/presentation/abstract_resource.rb +75 -0
- data/lib/iiif/presentation/annotation.rb +25 -0
- data/lib/iiif/presentation/annotation_list.rb +28 -0
- data/lib/iiif/presentation/canvas.rb +45 -0
- data/lib/iiif/presentation/collection.rb +29 -0
- data/lib/iiif/presentation/image_resource.rb +115 -0
- data/lib/iiif/presentation/layer.rb +34 -0
- data/lib/iiif/presentation/manifest.rb +39 -0
- data/lib/iiif/presentation/range.rb +32 -0
- data/lib/iiif/presentation/resource.rb +21 -0
- data/lib/iiif/presentation/sequence.rb +35 -0
- data/lib/iiif/service.rb +418 -0
- data/osullivan.gemspec +27 -0
- data/spec/fixtures/manifests/complete_from_spec.json +171 -0
- data/spec/fixtures/manifests/minimal.json +40 -0
- data/spec/fixtures/manifests/service_only.json +11 -0
- data/spec/fixtures/vcr_cassettes/pul_loris_cassette.json +159 -0
- data/spec/integration/iiif/presentation/image_resource_spec.rb +123 -0
- data/spec/integration/iiif/service_spec.rb +211 -0
- data/spec/spec_helper.rb +104 -0
- data/spec/unit/active_support/ordered_hash_spec.rb +155 -0
- data/spec/unit/iiif/hash_behaviours_spec.rb +569 -0
- data/spec/unit/iiif/presentation/abstract_resource_spec.rb +133 -0
- data/spec/unit/iiif/presentation/annotation_list_spec.rb +7 -0
- data/spec/unit/iiif/presentation/annotation_spec.rb +7 -0
- data/spec/unit/iiif/presentation/canvas_spec.rb +40 -0
- data/spec/unit/iiif/presentation/collection_spec.rb +54 -0
- data/spec/unit/iiif/presentation/image_resource_spec.rb +13 -0
- data/spec/unit/iiif/presentation/layer_spec.rb +38 -0
- data/spec/unit/iiif/presentation/manifest_spec.rb +89 -0
- data/spec/unit/iiif/presentation/range_spec.rb +43 -0
- data/spec/unit/iiif/presentation/resource_spec.rb +16 -0
- data/spec/unit/iiif/presentation/sequence_spec.rb +110 -0
- data/spec/unit/iiif/presentation/shared_examples/abstract_resource_only_keys.rb +43 -0
- data/spec/unit/iiif/presentation/shared_examples/any_type_keys.rb +33 -0
- data/spec/unit/iiif/presentation/shared_examples/array_only_keys.rb +44 -0
- data/spec/unit/iiif/presentation/shared_examples/int_only_keys.rb +49 -0
- data/spec/unit/iiif/presentation/shared_examples/string_only_keys.rb +29 -0
- data/spec/unit/iiif/service_spec.rb +10 -0
- metadata +246 -0
@@ -0,0 +1,569 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../../spec_helper')
|
2
|
+
require 'active_support/ordered_hash'
|
3
|
+
describe IIIF::HashBehaviours do
|
4
|
+
|
5
|
+
let(:hash_like_class) do
|
6
|
+
Class.new do
|
7
|
+
include IIIF::HashBehaviours
|
8
|
+
attr_accessor :data # Accessible for easier expects...not sure you'd do this in a real class
|
9
|
+
def initialize()
|
10
|
+
@data = ActiveSupport::OrderedHash.new
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# TODO: let(:init_data)...rather than repeating so much below
|
16
|
+
subject { hash_like_class.new }
|
17
|
+
|
18
|
+
describe '#[]=' do
|
19
|
+
it 'assigns a new k and value to the node' do
|
20
|
+
subject['foo'] = 'bar'
|
21
|
+
expect(subject.data).to eq({'foo' => 'bar'})
|
22
|
+
end
|
23
|
+
it 'always puts new entries at the end' do
|
24
|
+
subject['baz'] = 'qux'
|
25
|
+
subject['quux'] = 'corge'
|
26
|
+
subject['grault'] = 'garply'
|
27
|
+
expect(subject.data[subject.data.keys.last]).to eq 'garply'
|
28
|
+
end
|
29
|
+
it 'replaces keys that already exist in the same place' do
|
30
|
+
subject['waldo'] = 'fred'
|
31
|
+
subject['plugh'] = 'xyzzy'
|
32
|
+
subject['thud'] = 'wibble'
|
33
|
+
subject['plugh'] = 'wobble'
|
34
|
+
expect(subject.data.select {|k,v| k == 'plugh'}).to eq({'plugh'=>'wobble'})
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#[]' do
|
39
|
+
it 'retrieves the expected value' do
|
40
|
+
subject['wibble'] = 'wobble'
|
41
|
+
subject['wubble'] = 'fred'
|
42
|
+
expect(subject['wibble']).to eq 'wobble'
|
43
|
+
end
|
44
|
+
it 'returns nil if the key is not found' do
|
45
|
+
subject['wibble'] = 'wobble'
|
46
|
+
subject['wubble'] = 'fred'
|
47
|
+
expect(subject['flob']).to be_nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '#clear' do
|
52
|
+
it 'clears all properties' do
|
53
|
+
subject['wibble'] = 'wobble'
|
54
|
+
subject['wubble'] = 'fred'
|
55
|
+
subject.clear
|
56
|
+
expect(subject.keys).to eq []
|
57
|
+
end
|
58
|
+
it 'returns the instance on which it was called' do
|
59
|
+
subject['wibble'] = 'wobble'
|
60
|
+
subject['wubble'] = 'fred'
|
61
|
+
expect(subject.clear).to eq subject
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe '#delete' do
|
66
|
+
it 'removes an entry from the object' do
|
67
|
+
subject['waldo'] = 'fred'
|
68
|
+
subject['plugh'] = 'xyzzy'
|
69
|
+
subject.delete('waldo')
|
70
|
+
expect(subject.data).to eq({'plugh' => 'xyzzy'})
|
71
|
+
end
|
72
|
+
it 'returns the value of the entry that was removed' do
|
73
|
+
subject['waldo'] = 'fred'
|
74
|
+
subject['plugh'] = 'xyzzy'
|
75
|
+
expect(subject.delete('waldo')).to eq 'fred'
|
76
|
+
end
|
77
|
+
it 'can take a block as well' do
|
78
|
+
subject['waldo'] = 'fred'
|
79
|
+
subject['plugh'] = 'xyzzy'
|
80
|
+
expect { |b| subject.delete('wubble', &b) }.to yield_with_args
|
81
|
+
expect(subject.delete('foo') {|e| e.reverse }).to eq 'oof'
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe '#delete_if' do
|
86
|
+
it 'can take a block' do
|
87
|
+
subject['wibble'] = 'foo'
|
88
|
+
subject['waldo'] = 'fred'
|
89
|
+
subject['plugh'] = 'xyzzy'
|
90
|
+
expect { |b| subject.delete_if(&b) }.to yield_successive_args(['wibble', 'foo'], ['waldo', 'fred'], ['plugh', 'xyzzy'])
|
91
|
+
end
|
92
|
+
it 'returns the instance' do
|
93
|
+
subject['wibble'] = 'foo'
|
94
|
+
subject['waldo'] = 'fred'
|
95
|
+
subject['plugh'] = 'xyzzy'
|
96
|
+
expect( subject.delete_if { |k,v| k.start_with?('w') } ).to eq subject
|
97
|
+
end
|
98
|
+
it 'works' do
|
99
|
+
subject['wibble'] = 'foo'
|
100
|
+
subject['waldo'] = 'fred'
|
101
|
+
subject['plugh'] = 'xyzzy'
|
102
|
+
subject.delete_if { |k,v| k.start_with?('w') }
|
103
|
+
expect(subject.data).to eq({'plugh' => 'xyzzy'})
|
104
|
+
end
|
105
|
+
it 'returns an enumerator if no block is supplied' do
|
106
|
+
subject['wibble'] = 'foo'
|
107
|
+
subject['waldo'] = 'fred'
|
108
|
+
subject['plugh'] = 'xyzzy'
|
109
|
+
expect(subject.delete_if).to be_a Enumerator
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe '#each' do
|
114
|
+
it 'yields' do
|
115
|
+
subject['plugh'] = 'xyzzy'
|
116
|
+
expect { |b| subject.each(&b) }.to yield_with_args
|
117
|
+
end
|
118
|
+
it 'returns the instance' do
|
119
|
+
subject.data['waldo'] = 'fred'
|
120
|
+
subject.data['plugh'] = 'xyzzy'
|
121
|
+
expect(subject.each { |k,v| nil }).to eq subject
|
122
|
+
end
|
123
|
+
it 'loops as expected' do
|
124
|
+
subject.data['wibble'] = 'foo'
|
125
|
+
subject.data['waldo'] = 'fred'
|
126
|
+
subject.data['plugh'] = 'xyzzy'
|
127
|
+
capped_keys = []
|
128
|
+
subject.each { |k,v| capped_keys << k.capitalize }
|
129
|
+
expect(capped_keys).to eq ['Wibble', 'Waldo', 'Plugh']
|
130
|
+
end
|
131
|
+
it 'returns an enumerator if no block is supplied' do
|
132
|
+
subject['wibble'] = 'foo'
|
133
|
+
subject['waldo'] = 'fred'
|
134
|
+
subject['plugh'] = 'xyzzy'
|
135
|
+
expect(subject.delete_if).to be_a Enumerator
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe '#each_key' do
|
140
|
+
it 'yields' do
|
141
|
+
subject['plugh'] = 'xyzzy'
|
142
|
+
expect { |b| subject.each_key(&b) }.to yield_with_args
|
143
|
+
end
|
144
|
+
it 'returns the instance' do
|
145
|
+
subject.data['waldo'] = 'fred'
|
146
|
+
subject.data['plugh'] = 'xyzzy'
|
147
|
+
expect(subject.each_key { |k| nil }).to eq subject
|
148
|
+
end
|
149
|
+
it 'loops as expected' do
|
150
|
+
subject['wibble'] = 'foo'
|
151
|
+
subject['waldo'] = 'fred'
|
152
|
+
subject['plugh'] = 'xyzzy'
|
153
|
+
key_accumulator = []
|
154
|
+
subject.each_key { |k| key_accumulator << k }
|
155
|
+
expect(key_accumulator).to eq ['wibble', 'waldo', 'plugh']
|
156
|
+
end
|
157
|
+
it 'returns an enumerator if no block is supplied' do
|
158
|
+
subject['wibble'] = 'foo'
|
159
|
+
subject['waldo'] = 'fred'
|
160
|
+
subject['plugh'] = 'xyzzy'
|
161
|
+
expect(subject.each_key).to be_a Enumerator
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
describe '#each_value' do
|
166
|
+
it 'yields' do
|
167
|
+
subject['plugh'] = 'xyzzy'
|
168
|
+
expect { |b| subject.each_value(&b) }.to yield_with_args
|
169
|
+
end
|
170
|
+
it 'returns the instance' do
|
171
|
+
subject.data['waldo'] = 'fred'
|
172
|
+
subject.data['plugh'] = 'xyzzy'
|
173
|
+
expect(subject.each_value { |v| nil }).to eq subject
|
174
|
+
end
|
175
|
+
it 'loops as expected' do
|
176
|
+
subject['wibble'] = 'foo'
|
177
|
+
subject['waldo'] = 'fred'
|
178
|
+
subject['plugh'] = 'xyzzy'
|
179
|
+
value_accumulator = []
|
180
|
+
subject.each_value { |v| value_accumulator << v }
|
181
|
+
expect(value_accumulator).to eq ['foo', 'fred', 'xyzzy']
|
182
|
+
end
|
183
|
+
it 'returns an enumerator if no block is supplied' do
|
184
|
+
subject['wibble'] = 'foo'
|
185
|
+
subject['waldo'] = 'fred'
|
186
|
+
subject['plugh'] = 'xyzzy'
|
187
|
+
expect(subject.each_value).to be_a Enumerator
|
188
|
+
end
|
189
|
+
|
190
|
+
end
|
191
|
+
|
192
|
+
describe '#empty' do
|
193
|
+
it 'returns true when there are no entries' do
|
194
|
+
expect(subject.empty?).to be_truthy
|
195
|
+
end
|
196
|
+
it 'returns false when we have data' do
|
197
|
+
subject['waldo'] = 'fred'
|
198
|
+
expect(subject.empty?).to be_falsey
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
describe '#fetch' do
|
203
|
+
it 'retrieves the expected value' do
|
204
|
+
subject['wibble'] = 'wobble'
|
205
|
+
subject['wubble'] = 'fred'
|
206
|
+
expect(subject.fetch('wibble')).to eq 'wobble'
|
207
|
+
end
|
208
|
+
it 'returns the default if the key is not found and one is supplied' do
|
209
|
+
subject['wibble'] = 'wobble'
|
210
|
+
subject['wubble'] = 'fred'
|
211
|
+
expect(subject.fetch('flob', 'waldo')).to eq 'waldo'
|
212
|
+
end
|
213
|
+
it 'raises a KeyError if the key is not found and no default is supplied' do
|
214
|
+
expect { subject.fetch('flob') }.to raise_error KeyError
|
215
|
+
end
|
216
|
+
it 'can take a block as well' do
|
217
|
+
subject['wibble'] = 'wobble'
|
218
|
+
subject['wubble'] = 'fred'
|
219
|
+
expect(subject.fetch('wubble') {|e| e.capitalize }).to eq 'fred' # value takes precence
|
220
|
+
expect { |b| subject.fetch('foo', &b) }.to yield_with_args
|
221
|
+
expect(subject.fetch('foo') {|e| e.reverse }).to eq 'oof'
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
describe '#has_key? (and aliases)' do
|
226
|
+
it 'is true when the key exists' do
|
227
|
+
subject['wibble'] = 'wobble'
|
228
|
+
expect(subject.has_key? 'wibble').to be_truthy
|
229
|
+
end
|
230
|
+
it 'is false when the key does not exist' do
|
231
|
+
expect(subject.has_key? 'wibble').to be_falsey
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
describe '#has_value? (and aliases)' do
|
236
|
+
it 'is true when the value exists' do
|
237
|
+
subject['wibble'] = 'wobble'
|
238
|
+
expect(subject.has_value? 'wobble').to be_truthy
|
239
|
+
end
|
240
|
+
it 'is false when the value does not exist' do
|
241
|
+
expect(subject.has_value? 'wobble').to be_falsey
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
describe '#keep_if' do
|
246
|
+
it 'can take a block' do
|
247
|
+
subject['wibble'] = 'foo'
|
248
|
+
subject['waldo'] = 'fred'
|
249
|
+
subject['plugh'] = 'xyzzy'
|
250
|
+
expect { |b| subject.keep_if(&b) }.to yield_successive_args(['wibble', 'foo'], ['waldo', 'fred'], ['plugh', 'xyzzy'])
|
251
|
+
end
|
252
|
+
it 'returns the instance' do
|
253
|
+
subject['wibble'] = 'foo'
|
254
|
+
subject['waldo'] = 'fred'
|
255
|
+
subject['plugh'] = 'xyzzy'
|
256
|
+
expect( subject.keep_if { |k,v| k.start_with?('w') } ).to eq subject
|
257
|
+
end
|
258
|
+
it 'works' do
|
259
|
+
subject['wibble'] = 'foo'
|
260
|
+
subject['waldo'] = 'fred'
|
261
|
+
subject['plugh'] = 'xyzzy'
|
262
|
+
subject.keep_if { |k,v| k.start_with?('w') }
|
263
|
+
expect(subject.data).to eq({'wibble'=>'foo', 'waldo'=>'fred'})
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
describe '#key' do
|
268
|
+
it 'is the key associated with a value' do
|
269
|
+
subject['thud'] = 'wibble'
|
270
|
+
subject['plugh'] = 'wobble'
|
271
|
+
expect(subject.key 'wibble').to eq 'thud'
|
272
|
+
expect(subject.key 'wobble').to eq 'plugh'
|
273
|
+
end
|
274
|
+
it 'is nil if the value is not found' do
|
275
|
+
subject['thud'] = 'wibble'
|
276
|
+
subject['plugh'] = 'wobble'
|
277
|
+
expect(subject.key 'foo').to be_nil
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
describe '#keys' do
|
282
|
+
it 'is an array of all of the keys in the object' do
|
283
|
+
subject['foo'] = 'bar'
|
284
|
+
subject['waldo'] = 'fred'
|
285
|
+
subject['plugh'] = 'xyzzy'
|
286
|
+
expect(subject.keys).to eq ['foo', 'waldo', 'plugh']
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
describe '#length' do
|
291
|
+
it 'works' do
|
292
|
+
subject['wibble'] = 'foo'
|
293
|
+
subject['waldo'] = 'fred'
|
294
|
+
expect(subject.length).to eq 2
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
describe '#merge' do
|
299
|
+
it 'returns a new instance of the calling class' do
|
300
|
+
subject['wibble'] = 'foo'
|
301
|
+
another = hash_like_class.new
|
302
|
+
another['waldo'] = 'fred'
|
303
|
+
merged = subject.merge(another)
|
304
|
+
# clear them all to confirm we're not testing equality of anything other
|
305
|
+
# than that we have different instances
|
306
|
+
subject.data.clear
|
307
|
+
another.data.clear
|
308
|
+
merged.data.clear
|
309
|
+
expect(subject.merge(another).class).to eq subject.class # same class but'
|
310
|
+
expect(merged).to_not be subject # different instance
|
311
|
+
expect(merged).to_not be another # different instance
|
312
|
+
end
|
313
|
+
# it 'adds new entries to the end' do
|
314
|
+
# subject['wibble'] = 'foo'
|
315
|
+
# subject['plugh'] = 'xyzzy'
|
316
|
+
# another = hash_like_class.new
|
317
|
+
# another['waldo'] = 'fred'
|
318
|
+
# new_instance = subject.merge(another)
|
319
|
+
# expect(new_instance.data.last).to eq ['waldo', 'fred']
|
320
|
+
# end
|
321
|
+
it 'retains the index position for existing entries, replacing the value' do
|
322
|
+
subject['wibble'] = 'foo'
|
323
|
+
subject['plugh'] = 'xyzzy'
|
324
|
+
subject['foo'] = 'bar'
|
325
|
+
another = hash_like_class.new
|
326
|
+
another['plugh'] = 'fred'
|
327
|
+
new_instance = subject.merge(another)
|
328
|
+
expect(new_instance['plugh']).to eq 'fred'
|
329
|
+
expect(new_instance[new_instance.keys[1]]).to eq 'fred'
|
330
|
+
end
|
331
|
+
it 'takes a block' do
|
332
|
+
subject['wibble'] = 'foo'
|
333
|
+
subject['plugh'] = 'xyzzy'
|
334
|
+
subject['foo'] = 'bar'
|
335
|
+
another = hash_like_class.new
|
336
|
+
another['plugh'] = 'fred'
|
337
|
+
# e.g. give a block that turns common keys into an Array
|
338
|
+
new_instance = subject.merge(another) { |k, old_val,new_val| [old_val, new_val] }
|
339
|
+
expect(new_instance['wibble']).to eq 'foo'
|
340
|
+
expect(new_instance['plugh']).to eq ['xyzzy', 'fred']
|
341
|
+
expect(new_instance['foo']).to eq 'bar'
|
342
|
+
expect(new_instance.data).to eq({'wibble'=>'foo', 'plugh'=>['xyzzy', 'fred'], 'foo'=>'bar'})
|
343
|
+
end
|
344
|
+
describe 'takes anything that implements `#each { |k,v| block }` and #has_key?' do
|
345
|
+
it 'returns a new instance of the calling class' do
|
346
|
+
subject['wibble'] = 'foo'
|
347
|
+
another = {'waldo' => 'fred'}
|
348
|
+
merged = subject.merge(another)
|
349
|
+
# clear them all to confirm we're not testing equality of anything other
|
350
|
+
# than that we have different instances
|
351
|
+
subject.data.clear
|
352
|
+
another.clear
|
353
|
+
merged.data.clear
|
354
|
+
expect(subject.merge(another).class).to eq subject.class # same class but'
|
355
|
+
expect(merged).to_not be subject # different instance
|
356
|
+
expect(merged).to_not be another # different instance
|
357
|
+
end
|
358
|
+
# it 'adds new entries to the end' do
|
359
|
+
# subject['wibble'] = 'foo'
|
360
|
+
# subject['plugh'] = 'xyzzy'
|
361
|
+
# another = {'waldo' => 'fred'}
|
362
|
+
# new_instance = subject.merge(another)
|
363
|
+
# expect(new_instance.data.last).to eq ['waldo', 'fred']
|
364
|
+
# end
|
365
|
+
it 'retains the index position for existing entries, replacing the value' do
|
366
|
+
subject['wibble'] = 'foo'
|
367
|
+
subject['plugh'] = 'xyzzy'
|
368
|
+
subject['foo'] = 'bar'
|
369
|
+
another = {'plugh' => 'fred' }
|
370
|
+
another['plugh'] = 'fred'
|
371
|
+
new_instance = subject.merge(another)
|
372
|
+
expect(new_instance['plugh']).to eq 'fred'
|
373
|
+
expect(new_instance[new_instance.keys[1]]).to eq 'fred'
|
374
|
+
end
|
375
|
+
it 'takes a block' do
|
376
|
+
subject['wibble'] = 'foo'
|
377
|
+
subject['plugh'] = 'xyzzy'
|
378
|
+
subject['foo'] = 'bar'
|
379
|
+
another = {'plugh' => 'fred'}
|
380
|
+
# e.g. give a block that turns common keys into an Array
|
381
|
+
new_instance = subject.merge(another) { |k, old_val,new_val| [old_val, new_val] }
|
382
|
+
expect(new_instance['wibble']).to eq 'foo'
|
383
|
+
expect(new_instance['plugh']).to eq ['xyzzy', 'fred']
|
384
|
+
expect(new_instance['foo']).to eq 'bar'
|
385
|
+
expect(new_instance.data).to eq({'wibble'=>'foo', 'plugh'=>['xyzzy', 'fred'], 'foo'=>'bar'})
|
386
|
+
end
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
describe '#merge!' do
|
391
|
+
it 'returns the instance on which is was called' do
|
392
|
+
subject['wibble'] = 'foo'
|
393
|
+
another = hash_like_class.new
|
394
|
+
another['waldo'] = 'fred'
|
395
|
+
expect(subject.merge!(another)).to eq subject # same instance
|
396
|
+
end
|
397
|
+
it 'adds new entries to the end' do
|
398
|
+
subject['wibble'] = 'foo'
|
399
|
+
subject['plugh'] = 'xyzzy'
|
400
|
+
another = hash_like_class.new
|
401
|
+
another['waldo'] = 'fred'
|
402
|
+
subject.merge!(another)
|
403
|
+
expect(subject.data[subject.data.keys.last]).to eq 'fred'
|
404
|
+
end
|
405
|
+
it 'retains the index position for existing entries, replacing the value' do
|
406
|
+
subject['wibble'] = 'foo'
|
407
|
+
subject['plugh'] = 'xyzzy'
|
408
|
+
subject['foo'] = 'bar'
|
409
|
+
another = hash_like_class.new
|
410
|
+
another['plugh'] = 'fred'
|
411
|
+
subject.merge!(another)
|
412
|
+
expect(subject['plugh']).to eq 'fred'
|
413
|
+
expect(subject.data[subject.keys[1]]).to eq 'fred'
|
414
|
+
end
|
415
|
+
it 'takes a block' do
|
416
|
+
subject['wibble'] = 'foo'
|
417
|
+
subject['plugh'] = 'xyzzy'
|
418
|
+
subject['foo'] = 'bar'
|
419
|
+
another = hash_like_class.new
|
420
|
+
another['plugh'] = 'fred'
|
421
|
+
# e.g. give a block that turns common keys into an Array
|
422
|
+
subject.merge!(another) { |k, old_val,new_val| [old_val, new_val] }
|
423
|
+
expect(subject['wibble']).to eq 'foo'
|
424
|
+
expect(subject['plugh']).to eq ['xyzzy', 'fred']
|
425
|
+
expect(subject['foo']).to eq 'bar'
|
426
|
+
expect(subject.data).to eq({'wibble'=>'foo', 'plugh'=>['xyzzy', 'fred'], 'foo'=>'bar'})
|
427
|
+
end
|
428
|
+
describe 'takes anything that implements `#each { |k,v| block }` and #has_key?' do
|
429
|
+
it 'returns a new instance of the calling class' do
|
430
|
+
subject['wibble'] = 'foo'
|
431
|
+
another = {'waldo' => 'fred'}
|
432
|
+
expect(subject.merge!(another)).to eq subject # same instance
|
433
|
+
end
|
434
|
+
it 'adds new entries to the end' do
|
435
|
+
subject['wibble'] = 'foo'
|
436
|
+
subject['plugh'] = 'xyzzy'
|
437
|
+
another = {'waldo' => 'fred'}
|
438
|
+
subject.merge!(another)
|
439
|
+
expect(subject.data[subject.data.keys.last]).to eq 'fred'
|
440
|
+
end
|
441
|
+
it 'retains the index position for existing entries, replacing the value' do
|
442
|
+
subject['wibble'] = 'foo'
|
443
|
+
subject['plugh'] = 'xyzzy'
|
444
|
+
subject['foo'] = 'bar'
|
445
|
+
another = {'plugh' => 'fred' }
|
446
|
+
subject.merge!(another)
|
447
|
+
expect(subject['plugh']).to eq 'fred'
|
448
|
+
expect(subject.data[subject.keys[1]]).to eq 'fred'
|
449
|
+
end
|
450
|
+
it 'takes a block' do
|
451
|
+
subject['wibble'] = 'foo'
|
452
|
+
subject['plugh'] = 'xyzzy'
|
453
|
+
subject['foo'] = 'bar'
|
454
|
+
another = {'plugh' => 'fred'}
|
455
|
+
subject.merge!(another) { |k, old_val,new_val| "#{k}, #{old_val}, #{new_val}" }
|
456
|
+
expect(subject['wibble']).to eq 'foo'
|
457
|
+
expect(subject['plugh']).to eq 'plugh, xyzzy, fred'
|
458
|
+
expect(subject['foo']).to eq 'bar'
|
459
|
+
expect(subject.data).to eq({'wibble'=>'foo', 'plugh'=>'plugh, xyzzy, fred', 'foo'=>'bar'})
|
460
|
+
end
|
461
|
+
end
|
462
|
+
end
|
463
|
+
|
464
|
+
describe '#reject!' do
|
465
|
+
it 'can take a block' do
|
466
|
+
subject['wibble'] = 'foo'
|
467
|
+
subject['waldo'] = 'fred'
|
468
|
+
subject['plugh'] = 'xyzzy'
|
469
|
+
expect { |b| subject.reject!(&b) }.to yield_successive_args(['wibble', 'foo'], ['waldo', 'fred'], ['plugh', 'xyzzy'])
|
470
|
+
end
|
471
|
+
it 'returns the instance if there were changes' do
|
472
|
+
subject['wibble'] = 'foo'
|
473
|
+
subject['waldo'] = 'fred'
|
474
|
+
subject['plugh'] = 'xyzzy'
|
475
|
+
expect( subject.reject! { |k| k.start_with?('w') } ).to be subject
|
476
|
+
end
|
477
|
+
it 'returns nil if there were no changes' do
|
478
|
+
subject['wibble'] = 'foo'
|
479
|
+
subject['waldo'] = 'fred'
|
480
|
+
subject['plugh'] = 'xyzzy'
|
481
|
+
expect( subject.reject! { |k| k.start_with?('X') } ).to be_nil
|
482
|
+
end
|
483
|
+
it 'works' do
|
484
|
+
subject['wibble'] = 'foo'
|
485
|
+
subject['waldo'] = 'fred'
|
486
|
+
subject['plugh'] = 'xyzzy'
|
487
|
+
subject.reject! { |k| k.start_with?('w') }
|
488
|
+
expect(subject.data).to eq({'plugh' => 'xyzzy'})
|
489
|
+
end
|
490
|
+
end
|
491
|
+
|
492
|
+
describe '#select' do
|
493
|
+
it 'yields' do
|
494
|
+
subject['thud'] = 'wibble'
|
495
|
+
subject['plugh'] = 'wobble'
|
496
|
+
subject['waldo'] = 'fred'
|
497
|
+
expect { |b| subject.select(&b) }.to yield_successive_args(['thud', 'wibble'], ['plugh', 'wobble'], ['waldo', 'fred'])
|
498
|
+
end
|
499
|
+
it 'returns a new instance of the class' do
|
500
|
+
subject['thud'] = 'wibble'
|
501
|
+
subject['plugh'] = 'wobble'
|
502
|
+
subject['waldo'] = 'fred'
|
503
|
+
expect( subject.select{ |k,v| true }.class ).to eq subject.class
|
504
|
+
expect( subject.select{ |k,v| true } ).to_not eq subject
|
505
|
+
end
|
506
|
+
it 'selects but doesn\'t delete from the original instance' do
|
507
|
+
subject['thud'] = 'wibble'
|
508
|
+
subject['plugh'] = 'wobble'
|
509
|
+
subject['waldo'] = 'fred'
|
510
|
+
expect( subject.select{ |k,v| k.include?('u') }.data ).to eq({'thud'=>'wibble', 'plugh'=>'wobble'})
|
511
|
+
expect( subject.data ).to eq subject.data
|
512
|
+
end
|
513
|
+
end
|
514
|
+
|
515
|
+
describe '#select!' do
|
516
|
+
it 'can take a block' do
|
517
|
+
subject['wibble'] = 'foo'
|
518
|
+
subject['waldo'] = 'fred'
|
519
|
+
subject['plugh'] = 'xyzzy'
|
520
|
+
expect { |b| subject.select!(&b) }.to yield_successive_args(['wibble', 'foo'], ['waldo', 'fred'], ['plugh', 'xyzzy'])
|
521
|
+
end
|
522
|
+
it 'returns nil if there were no changes' do
|
523
|
+
subject['wibble'] = 'foo'
|
524
|
+
subject['waldo'] = 'fred'
|
525
|
+
subject['wobble'] = 'xyzzy'
|
526
|
+
expect( subject.select! { |k,v| k.start_with?('w') } ).to be_nil
|
527
|
+
end
|
528
|
+
it 'returns the instance if there were changes' do
|
529
|
+
subject['wibble'] = 'foo'
|
530
|
+
subject['waldo'] = 'fred'
|
531
|
+
subject['plugh'] = 'xyzzy'
|
532
|
+
expect( subject.select! { |k,v| k.start_with?('w') } ).to eq subject
|
533
|
+
end
|
534
|
+
it 'works' do
|
535
|
+
subject['wibble'] = 'foo'
|
536
|
+
subject['waldo'] = 'fred'
|
537
|
+
subject['plugh'] = 'xyzzy'
|
538
|
+
subject.select! { |k,v| k.start_with?('p') }
|
539
|
+
expect(subject.data).to eq({'plugh' => 'xyzzy'})
|
540
|
+
end
|
541
|
+
end
|
542
|
+
|
543
|
+
describe '#shift' do
|
544
|
+
it 'returns the first element in the hash without a param' do
|
545
|
+
subject['thud'] = 'wibble'
|
546
|
+
subject['plugh'] = 'wobble'
|
547
|
+
expect(subject.shift).to eq ['thud','wibble']
|
548
|
+
expect(subject.data).to eq({'plugh' => 'wobble'})
|
549
|
+
end
|
550
|
+
end
|
551
|
+
|
552
|
+
describe 'store' do
|
553
|
+
it 'works as an alias for []=' do
|
554
|
+
subject.store('foo', 'bar')
|
555
|
+
expect(subject.data).to eq({'foo' => 'bar'})
|
556
|
+
end
|
557
|
+
end
|
558
|
+
|
559
|
+
describe '#values' do
|
560
|
+
it 'is an array of all of the keys in the object' do
|
561
|
+
subject['foo'] = 'bar'
|
562
|
+
subject['waldo'] = 'fred'
|
563
|
+
subject['plugh'] = 'xyzzy'
|
564
|
+
expect(subject.values).to eq ['bar', 'fred', 'xyzzy']
|
565
|
+
end
|
566
|
+
end
|
567
|
+
|
568
|
+
end
|
569
|
+
|