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.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +4 -0
  5. data/Gemfile +2 -0
  6. data/LICENSE +23 -0
  7. data/README.md +166 -0
  8. data/Rakefile +12 -0
  9. data/VERSION +1 -0
  10. data/lib/active_support/ordered_hash.rb +147 -0
  11. data/lib/iiif/hash_behaviours.rb +150 -0
  12. data/lib/iiif/presentation.rb +25 -0
  13. data/lib/iiif/presentation/abstract_resource.rb +75 -0
  14. data/lib/iiif/presentation/annotation.rb +25 -0
  15. data/lib/iiif/presentation/annotation_list.rb +28 -0
  16. data/lib/iiif/presentation/canvas.rb +45 -0
  17. data/lib/iiif/presentation/collection.rb +29 -0
  18. data/lib/iiif/presentation/image_resource.rb +115 -0
  19. data/lib/iiif/presentation/layer.rb +34 -0
  20. data/lib/iiif/presentation/manifest.rb +39 -0
  21. data/lib/iiif/presentation/range.rb +32 -0
  22. data/lib/iiif/presentation/resource.rb +21 -0
  23. data/lib/iiif/presentation/sequence.rb +35 -0
  24. data/lib/iiif/service.rb +418 -0
  25. data/osullivan.gemspec +27 -0
  26. data/spec/fixtures/manifests/complete_from_spec.json +171 -0
  27. data/spec/fixtures/manifests/minimal.json +40 -0
  28. data/spec/fixtures/manifests/service_only.json +11 -0
  29. data/spec/fixtures/vcr_cassettes/pul_loris_cassette.json +159 -0
  30. data/spec/integration/iiif/presentation/image_resource_spec.rb +123 -0
  31. data/spec/integration/iiif/service_spec.rb +211 -0
  32. data/spec/spec_helper.rb +104 -0
  33. data/spec/unit/active_support/ordered_hash_spec.rb +155 -0
  34. data/spec/unit/iiif/hash_behaviours_spec.rb +569 -0
  35. data/spec/unit/iiif/presentation/abstract_resource_spec.rb +133 -0
  36. data/spec/unit/iiif/presentation/annotation_list_spec.rb +7 -0
  37. data/spec/unit/iiif/presentation/annotation_spec.rb +7 -0
  38. data/spec/unit/iiif/presentation/canvas_spec.rb +40 -0
  39. data/spec/unit/iiif/presentation/collection_spec.rb +54 -0
  40. data/spec/unit/iiif/presentation/image_resource_spec.rb +13 -0
  41. data/spec/unit/iiif/presentation/layer_spec.rb +38 -0
  42. data/spec/unit/iiif/presentation/manifest_spec.rb +89 -0
  43. data/spec/unit/iiif/presentation/range_spec.rb +43 -0
  44. data/spec/unit/iiif/presentation/resource_spec.rb +16 -0
  45. data/spec/unit/iiif/presentation/sequence_spec.rb +110 -0
  46. data/spec/unit/iiif/presentation/shared_examples/abstract_resource_only_keys.rb +43 -0
  47. data/spec/unit/iiif/presentation/shared_examples/any_type_keys.rb +33 -0
  48. data/spec/unit/iiif/presentation/shared_examples/array_only_keys.rb +44 -0
  49. data/spec/unit/iiif/presentation/shared_examples/int_only_keys.rb +49 -0
  50. data/spec/unit/iiif/presentation/shared_examples/string_only_keys.rb +29 -0
  51. data/spec/unit/iiif/service_spec.rb +10 -0
  52. 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
+