hydra-works 0.16.0 → 2.0.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.
Files changed (62) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +59 -0
  3. data/.gitignore +3 -1
  4. data/.rubocop.yml +2 -6
  5. data/.rubocop_todo.yml +5 -0
  6. data/.solr_wrapper +1 -0
  7. data/CHANGELOG.md +621 -0
  8. data/CODE_OF_CONDUCT.md +36 -0
  9. data/CONTRIBUTING.md +23 -21
  10. data/Gemfile +11 -3
  11. data/LICENSE +14 -16
  12. data/README.md +54 -12
  13. data/SUPPORT.md +5 -0
  14. data/hydra-works.gemspec +15 -13
  15. data/lib/hydra/works/characterization.rb +5 -4
  16. data/lib/hydra/works/characterization/fits_document.rb +348 -144
  17. data/lib/hydra/works/characterization/schema/audio_schema.rb +2 -0
  18. data/lib/hydra/works/characterization/schema/video_schema.rb +2 -0
  19. data/lib/hydra/works/models/concerns/collection_behavior.rb +44 -0
  20. data/lib/hydra/works/models/concerns/file_set_behavior.rb +20 -0
  21. data/lib/hydra/works/models/concerns/work_behavior.rb +54 -0
  22. data/lib/hydra/works/services/add_external_file_to_file_set.rb +1 -1
  23. data/lib/hydra/works/services/add_file_to_file_set.rb +1 -1
  24. data/lib/hydra/works/services/characterization_service.rb +5 -0
  25. data/lib/hydra/works/services/determine_original_name.rb +1 -1
  26. data/lib/hydra/works/version.rb +1 -1
  27. data/lib/hydra/works/virus_scanner.rb +18 -2
  28. data/spec/fixtures/fits_0.8.5_tiff.xml +78 -0
  29. data/spec/fixtures/fits_1.2.0_avi.xml +83 -0
  30. data/spec/fixtures/fits_1.2.0_jpg.xml +76 -0
  31. data/spec/fixtures/fits_1.2.0_mp3.xml +51 -0
  32. data/spec/fixtures/fits_1.2.0_mp4.xml +88 -0
  33. data/spec/fixtures/fits_netcdf_two_mimetypes.xml +35 -0
  34. data/spec/hydra/works/characterization_spec.rb +12 -5
  35. data/spec/hydra/works/models/collection_spec.rb +162 -0
  36. data/spec/hydra/works/models/concerns/file_set/contained_files_spec.rb +3 -16
  37. data/spec/hydra/works/models/file_set_spec.rb +47 -0
  38. data/spec/hydra/works/models/work_spec.rb +213 -7
  39. data/spec/hydra/works/services/characterization_service_spec.rb +90 -27
  40. data/spec/hydra/works/services/persist_derivatives_spec.rb +6 -6
  41. data/spec/hydra/works/virus_scanner_spec.rb +31 -0
  42. data/use-cases/princeton_book_use_case.md +1 -1
  43. metadata +77 -67
  44. data/.travis.yml +0 -15
  45. data/lib/hydra/works/characterization/fits_mapper.rb +0 -0
  46. data/solr/config/_rest_managed.json +0 -3
  47. data/solr/config/admin-extra.html +0 -31
  48. data/solr/config/elevate.xml +0 -36
  49. data/solr/config/mapping-ISOLatin1Accent.txt +0 -246
  50. data/solr/config/protwords.txt +0 -21
  51. data/solr/config/schema.xml +0 -372
  52. data/solr/config/scripts.conf +0 -24
  53. data/solr/config/solrconfig.xml +0 -419
  54. data/solr/config/spellings.txt +0 -2
  55. data/solr/config/stopwords.txt +0 -58
  56. data/solr/config/stopwords_en.txt +0 -58
  57. data/solr/config/synonyms.txt +0 -31
  58. data/solr/config/xslt/example.xsl +0 -132
  59. data/solr/config/xslt/example_atom.xsl +0 -67
  60. data/solr/config/xslt/example_rss.xsl +0 -66
  61. data/solr/config/xslt/luke.xsl +0 -337
  62. data/spec/fixtures/eicar.txt +0 -1
@@ -1,21 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Hydra::Works::ContainedFiles do
4
- let(:file_set) do
5
- Hydra::Works::FileSet.create
6
- end
7
-
8
- let(:thumbnail) do
9
- file = file_set.files.build
10
- Hydra::PCDM::AddTypeToFile.call(file, pcdm_thumbnail_uri)
11
- end
12
-
13
- let(:file) { file_set.files.build }
14
- let(:pcdm_thumbnail_uri) { ::RDF::URI('http://pcdm.org/use#ThumbnailImage') }
15
-
16
- before do
17
- file_set.files = [file]
18
- end
4
+ let(:file_set) { Hydra::Works::FileSet.create }
5
+ let(:pcdm_thumbnail_uri) { ::RDF::URI('http://pcdm.org/use#ThumbnailImage') }
19
6
 
20
7
  describe '#thumbnail' do
21
8
  context 'when a thumbnail is present' do
@@ -63,7 +50,7 @@ describe Hydra::Works::ContainedFiles do
63
50
  end
64
51
  it 'retains origin pcdm.File RDF type' do
65
52
  expect(subject.metadata_node.type).to include(::RDF::URI('http://pcdm.org/use#OriginalFile'))
66
- expect(file_set.original_file.metadata_node.type).to include(Hydra::PCDM::Vocab::PCDMTerms.File)
53
+ expect(subject.metadata_node.type).to include(Hydra::PCDM::Vocab::PCDMTerms.File)
67
54
  end
68
55
  end
69
56
 
@@ -48,6 +48,17 @@ describe Hydra::Works::FileSet do
48
48
  it { is_expected.to eq [work] }
49
49
  end
50
50
 
51
+ describe '#in_work_ids' do
52
+ subject { file_set.in_work_ids }
53
+ let(:work) { Hydra::Works::Work.create }
54
+ before do
55
+ work.ordered_members << file_set
56
+ work.save
57
+ end
58
+
59
+ it { is_expected.to eq [work.id] }
60
+ end
61
+
51
62
  describe '#destroy' do
52
63
  let(:work) { Hydra::Works::Work.create }
53
64
  before do
@@ -86,4 +97,40 @@ describe Hydra::Works::FileSet do
86
97
  expect(file_set.collection?).to be false
87
98
  end
88
99
  end
100
+
101
+ context 'relationships' do
102
+ context '#parent_works and #parent_work_ids' do
103
+ let(:parent_work) { Hydra::Works::Work.new(id: 'parent_work') }
104
+ let(:child_file_set1) { described_class.new(id: 'child_file_set1') }
105
+ let(:child_file_set2) { described_class.new(id: 'child_file_set2') }
106
+
107
+ context 'when parent work knows about child file sets' do
108
+ before do
109
+ parent_work.members = [child_file_set1, child_file_set2]
110
+ child_file_set1.save
111
+ child_file_set2.save
112
+ parent_work.save
113
+ end
114
+
115
+ it 'gets parent work' do
116
+ expect(child_file_set1.parent_works).to match_array [parent_work]
117
+ expect(child_file_set1.parent_work_ids).to match_array [parent_work.id]
118
+ end
119
+ end
120
+
121
+ context 'when child works know about parent works' do
122
+ # before do
123
+ # # NOOP: The :member_of relationship is not defined for works. It only uses the :members relationship.
124
+ # child_file_set1.member_of = [parent_work]
125
+ # child_file_set2.member_of = [parent_work]
126
+ # end
127
+
128
+ it 'gets parent work' do
129
+ skip 'Pending implementation of the :member_of relationship for works'
130
+ expect(child_file_set1.parent_works).to match_array [parent_work]
131
+ expect(child_file_set1.parent_work_ids).to match_array [parent_work.id]
132
+ end
133
+ end
134
+ end
135
+ end
89
136
  end
@@ -3,14 +3,14 @@ require 'spec_helper'
3
3
  describe Hydra::Works::Work do
4
4
  subject { described_class.new }
5
5
 
6
- let(:work1) { described_class.new }
7
- let(:work2) { described_class.new }
8
- let(:work3) { described_class.new }
9
- let(:work4) { described_class.new }
10
- let(:work5) { described_class.new }
6
+ let(:work1) { described_class.new(id: 'wk1') }
7
+ let(:work2) { described_class.new(id: 'wk2') }
8
+ let(:work3) { described_class.new(id: 'wk3') }
9
+ let(:work4) { described_class.new(id: 'wk4') }
10
+ let(:work5) { described_class.new(id: 'wk5') }
11
11
 
12
- let(:file_set1) { Hydra::Works::FileSet.new }
13
- let(:file_set2) { Hydra::Works::FileSet.new }
12
+ let(:file_set1) { Hydra::Works::FileSet.new(id: 'fs1') }
13
+ let(:file_set2) { Hydra::Works::FileSet.new(id: 'fs2') }
14
14
 
15
15
  let(:object1) { Hydra::PCDM::Object.new }
16
16
  let(:object2) { Hydra::PCDM::Object.new }
@@ -262,9 +262,11 @@ describe Hydra::Works::Work do
262
262
  end
263
263
  it 'has a parent collection' do
264
264
  expect(work2.in_collections).to eq [collection1]
265
+ expect(work2.in_collection_ids).to eq [collection1.id]
265
266
  end
266
267
  it 'has a parent work' do
267
268
  expect(work2.in_works).to eq [work1]
269
+ expect(work2.in_work_ids).to eq [work1.id]
268
270
  end
269
271
  end
270
272
 
@@ -279,4 +281,208 @@ describe Hydra::Works::Work do
279
281
  expect(work1.member_of_collection_ids).to eq [collection1.id]
280
282
  end
281
283
  end
284
+
285
+ context 'relationships' do
286
+ context '#parent_collections and #parent_collection_ids' do
287
+ let(:col1) { Hydra::Works::Collection.new(id: 'col1') }
288
+ let(:col2) { Hydra::Works::Collection.new(id: 'col2') }
289
+
290
+ context 'when parents collection knows about child works' do
291
+ before do
292
+ col1.members = [work1]
293
+ col2.members = [work1]
294
+ work1.save
295
+ col1.save
296
+ col2.save
297
+ end
298
+
299
+ it 'get both parent collections' do
300
+ expect(work1.parent_collections).to match_array [col1, col2]
301
+ expect(work1.parent_collection_ids).to match_array [col1.id, col2.id]
302
+ end
303
+ end
304
+
305
+ context 'when child works knows about parent collections' do
306
+ before do
307
+ work1.member_of_collections = [col1, col2]
308
+ end
309
+
310
+ it 'gets both parent collections' do
311
+ expect(work1.parent_collections).to match_array [col1, col2]
312
+ expect(work1.parent_collection_ids).to match_array [col1.id, col2.id]
313
+ end
314
+ end
315
+
316
+ context 'when some children know about parent and some parents know about child' do
317
+ before do
318
+ col1.members = [work1]
319
+ work1.member_of_collections = [col2]
320
+ work1.save
321
+ col1.save
322
+ end
323
+
324
+ it 'gets both parent collections' do
325
+ expect(work1.parent_collections).to match_array [col1, col2]
326
+ expect(work1.parent_collection_ids).to match_array [col1.id, col2.id]
327
+ end
328
+ end
329
+ end
330
+
331
+ context '#parent_works and #parent_work_ids' do
332
+ let(:parent_col1) { Hydra::Works::Collection.new(id: 'col1') }
333
+ let(:parent_work1) { work1 }
334
+ let(:parent_work2) { work2 }
335
+ let(:child_work) { work3 }
336
+
337
+ context 'when parent work knows about child works' do
338
+ before do
339
+ parent_col1.members = [child_work] # collection is included to make sure parent_works only returns works
340
+ parent_work1.members = [child_work]
341
+ parent_work2.members = [child_work]
342
+ child_work.save
343
+ parent_col1.save
344
+ parent_work1.save
345
+ parent_work2.save
346
+ end
347
+
348
+ it 'gets both parent works' do
349
+ expect(child_work.parent_works).to match_array [parent_work1, parent_work2]
350
+ expect(child_work.parent_work_ids).to match_array [parent_work1.id, parent_work2.id]
351
+ end
352
+ end
353
+
354
+ context 'when child works know about parent works' do
355
+ # before do
356
+ # # NOOP: The :member_of relationship is not defined for works. It only uses the :members relationship.
357
+ # child_work.member_of = [parent_work1, parent_work2]
358
+ # end
359
+
360
+ it 'gets both parent works' do
361
+ skip 'Pending implementation of the :member_of relationship for works'
362
+ expect(child_work.parent_works).to match_array [parent_work1, parent_work2]
363
+ expect(child_work.parent_work_ids).to match_array [parent_work1.id, parent_work2.id]
364
+ end
365
+ end
366
+
367
+ context 'when some children know about parent and some parents know about child' do
368
+ # before do
369
+ # parent_work1.members = [child_work]
370
+ # child_work.save
371
+ # parent_work1.save
372
+ # # NOOP: The :member_of relationship is not defined for works. It only uses the :members relationship.
373
+ # child_work.member_of = [parent_work2]
374
+ # end
375
+
376
+ it 'gets both parent works' do
377
+ skip 'Pending implementation of the :member_of relationship for works'
378
+ expect(child_work.parent_works).to match_array [parent_work1, parent_work2]
379
+ expect(child_work.parent_work_ids).to match_array [parent_work1.id, parent_work2.id]
380
+ end
381
+ end
382
+ end
383
+
384
+ context '#child_works and #child_work_ids' do
385
+ context 'when parent works know about child works' do
386
+ let(:child_work1) { work1 }
387
+ let(:child_work2) { work2 }
388
+ let(:parent_work) { work3 }
389
+ let(:child_fileset) { file_set1 } # fileset is included to make sure child_works only returns works
390
+
391
+ before do
392
+ parent_work.members = [child_work1, child_work2, child_fileset]
393
+ parent_work.save
394
+ end
395
+
396
+ it 'gets both child works' do
397
+ expect(parent_work.child_works).to match_array [child_work1, child_work2]
398
+ expect(parent_work.child_work_ids).to match_array [child_work1.id, child_work2.id]
399
+ end
400
+ end
401
+
402
+ context 'when child knows about parent' do
403
+ before do
404
+ # before do
405
+ # # NOOP: The :member_of relationship is not defined for works. It only uses the :members relationship.
406
+ # child_work1.member_of = [parent_work]
407
+ # child_work2.member_of = [parent_work]
408
+ # end
409
+ end
410
+
411
+ it 'gets both child works' do
412
+ skip 'Pending implementation of the :member_of relationship for works'
413
+ expect(parent_work.child_works).to match_array [child_work1, child_work2]
414
+ expect(parent_work.child_work_ids).to match_array [child_work1.id, child_work2.id]
415
+ end
416
+ end
417
+
418
+ context 'when some children know about parent and some parents know about child' do
419
+ before do
420
+ # before do
421
+ # # NOOP: The :member_of relationship is not defined for works. It only uses the :members relationship.
422
+ # child_work1.member_of = [parent_work]
423
+ # parent_work.members = [child_work2, child_fileset]
424
+ # parent_work.save
425
+ # end
426
+ end
427
+
428
+ it 'gets both child works' do
429
+ skip 'Pending implementation of the :member_of relationship for works'
430
+ expect(parent_work.child_works).to match_array [child_work1, child_work2]
431
+ expect(parent_work.child_work_ids).to match_array [child_work1.id, child_work2.id]
432
+ end
433
+ end
434
+ end
435
+
436
+ context '#child_file_sets and #child_file_set_ids' do
437
+ context 'when parents knows about child' do
438
+ let(:child_fileset1) { file_set1 }
439
+ let(:child_fileset2) { file_set2 }
440
+ let(:parent_work) { work1 }
441
+ let(:child_work) { work2 } # work is included to make sure child_file_sets only returns file_sets
442
+
443
+ before do
444
+ parent_work.members = [child_fileset1, child_fileset2, child_work]
445
+ parent_work.save
446
+ end
447
+
448
+ it 'gets both child filesets' do
449
+ expect(parent_work.child_file_sets).to match_array [child_fileset1, child_fileset2]
450
+ expect(parent_work.child_file_set_ids).to match_array [child_fileset1.id, child_fileset2.id]
451
+ end
452
+ end
453
+
454
+ context 'when child knows about parent' do
455
+ before do
456
+ # before do
457
+ # # NOOP: The :member_of relationship is not defined for file sets. It only uses the :members relationship.
458
+ # child_fileset1.member_of = [parent_work]
459
+ # child_fileset2.member_of = [parent_work]
460
+ # end
461
+ end
462
+
463
+ it 'gets both child filesets' do
464
+ skip 'Pending implementation of the :member_of relationship for works'
465
+ expect(parent_work.child_file_sets).to match_array [child_fileset1, child_fileset2]
466
+ expect(parent_work.child_file_set_ids).to match_array [child_fileset1.id, child_fileset2.id]
467
+ end
468
+ end
469
+
470
+ context 'when some children know about parent and some parents know about child' do
471
+ before do
472
+ # before do
473
+ # # NOOP: The :member_of relationship is not defined for file sets. It only uses the :members relationship.
474
+ # child_fileset1.member_of = [parent_work]
475
+ # parent_work.members = [child_fileset2, child_work]
476
+ # parent_work.save
477
+ # end
478
+ end
479
+
480
+ it 'gets both child filesets' do
481
+ skip 'Pending implementation of the :member_of relationship for works'
482
+ expect(parent_work.child_file_sets).to match_array [child_fileset1, child_fileset2]
483
+ expect(parent_work.child_file_set_ids).to match_array [child_fileset1.id, child_fileset2.id]
484
+ end
485
+ end
486
+ end
487
+ end
282
488
  end
@@ -19,7 +19,7 @@ describe Hydra::Works::CharacterizationService do
19
19
  # Persist our file with some content and reload
20
20
  file.content = "junk"
21
21
  expect(file.save).to be true
22
- expect(file.reload).to eq({})
22
+ expect(file.reload).to be_empty
23
23
  # Re-check property values
24
24
  expect(file.file_size).to eq(["7618"])
25
25
  expect(file.file_title).to eq(["sample-file"])
@@ -81,20 +81,24 @@ describe Hydra::Works::CharacterizationService do
81
81
  end
82
82
 
83
83
  context "passing an object that does not have matching properties" do
84
- let!(:current_schemas) { ActiveFedora::WithMetadata::DefaultMetadataClassFactory.file_metadata_schemas }
85
-
86
84
  let(:characterization) { class_double("Hydra::FileCharacterization").as_stubbed_const }
87
85
  let(:fits_filename) { 'fits_0.8.5_pdf.xml' }
88
86
  let(:fits_response) { IO.read(File.join(fixture_path, fits_filename)) }
89
87
  let(:file_content) { 'dummy content' }
90
88
  let(:file) { Hydra::PCDM::File.new { |f| f.content = file_content } }
91
89
 
92
- before do
90
+ around do |example|
91
+ @current_schemas = ActiveFedora::WithMetadata::DefaultMetadataClassFactory.file_metadata_schemas
92
+ @metadata_schema = Hydra::PCDM::File::GeneratedMetadataSchema
93
93
  ActiveFedora::WithMetadata::DefaultMetadataClassFactory.file_metadata_schemas = [ActiveFedora::WithMetadata::DefaultSchema]
94
- allow(characterization).to receive(:characterize).and_return(fits_response)
94
+ example.run
95
+ ActiveFedora::WithMetadata::DefaultMetadataClassFactory.file_metadata_schemas = @current_schemas
96
+ # This next line required to force resetting the metadata schema class used by Hydra::PCDM::File
97
+ Hydra::PCDM::File.instance_variable_set(:@metadata_schema, @metadata_schema)
95
98
  end
96
- after do
97
- ActiveFedora::WithMetadata::DefaultMetadataClassFactory.file_metadata_schemas = [current_schemas]
99
+
100
+ before do
101
+ allow(characterization).to receive(:characterize).and_return(fits_response)
98
102
  end
99
103
 
100
104
  it 'does not explode with an error' do
@@ -123,39 +127,98 @@ describe Hydra::Works::CharacterizationService do
123
127
  end
124
128
  end
125
129
 
130
+ context 'using netCDF metadata' do
131
+ let(:fits_filename) { 'fits_netcdf_two_mimetypes.xml' }
132
+ let(:fits_response) { IO.read(File.join(fixture_path, fits_filename)) }
133
+
134
+ it 'reports the correct, single MIME type' do
135
+ expect(file.mime_type).to eq("application/netcdf")
136
+ end
137
+ end
138
+
126
139
  context 'using image metadata' do
127
- let(:fits_filename) { 'fits_0.8.5_jp2.xml' }
128
140
  let(:fits_response) { IO.read(File.join(fixture_path, fits_filename)) }
129
141
 
130
- it 'assigns expected values to image properties.' do
131
- expect(file.file_size).to eq(["11043"])
132
- expect(file.byte_order).to eq(["big endian"])
133
- expect(file.compression).to contain_exactly("JPEG 2000 Lossless", "JPEG 2000")
134
- expect(file.width).to eq(["512"])
135
- expect(file.height).to eq(["465"])
136
- expect(file.color_space).to eq(["sRGB"])
142
+ context 'with fits_0.8.5' do
143
+ let(:fits_filename) { 'fits_0.8.5_jp2.xml' }
144
+ it 'assigns expected values to image properties.' do
145
+ expect(file.file_size).to eq(["11043"])
146
+ expect(file.byte_order).to eq(["big endian"])
147
+ expect(file.compression).to contain_exactly("JPEG 2000 Lossless", "JPEG 2000")
148
+ expect(file.width).to eq(["512"])
149
+ expect(file.height).to eq(["465"])
150
+ expect(file.color_space).to eq(["sRGB"])
151
+ end
152
+ end
153
+
154
+ context 'with fits_1.2.0' do
155
+ let(:fits_filename) { 'fits_1.2.0_jpg.xml' }
156
+ it 'ensures duplicate values are not returned for exifVersion, dateCreated, dateModified.' do
157
+ expect(file.exif_version).to eq(["0221"])
158
+ expect(file.date_created).to eq(["2009:02:04 11:05:25.36-06:00"])
159
+ expect(file.date_modified).to eq(["2009:02:04 16:10:47"])
160
+ end
137
161
  end
138
162
  end
163
+
139
164
  context 'using video metadata' do
140
- let(:fits_filename) { 'fits_0.8.5_avi.xml' }
141
165
  let(:fits_response) { IO.read(File.join(fixture_path, fits_filename)) }
142
166
 
143
- it 'assigns expected values to video properties.' do
144
- expect(file.height).to eq(["264"])
145
- expect(file.width).to eq(["356"])
146
- expect(file.duration).to eq(["14.10 s"])
147
- expect(file.frame_rate).to eq(["10"])
148
- expect(file.sample_rate).to eq(["11025"])
167
+ context 'with fits_0.8.5' do
168
+ let(:fits_filename) { 'fits_0.8.5_avi.xml' }
169
+ it 'assigns expected values to video properties.' do
170
+ expect(file.height).to eq(["264"])
171
+ expect(file.width).to eq(["356"])
172
+ expect(file.duration).to eq(["14.10 s"])
173
+ expect(file.frame_rate).to eq(["10"])
174
+ expect(file.sample_rate).to eq(["11025"])
175
+ end
176
+ end
177
+
178
+ context 'with fits_1.2.0' do
179
+ let(:fits_filename) { 'fits_1.2.0_avi.xml' }
180
+ it 'assigns expected values to video properties.' do
181
+ expect(file.height).to eq(["264"])
182
+ expect(file.width).to eq(["356"])
183
+ expect(file.duration).to eq(["14148"])
184
+ expect(file.frame_rate).to eq(["10.000"])
185
+ expect(file.bit_rate).to eq(["409204"])
186
+ expect(file.aspect_ratio).to eq(["4:3"])
187
+ end
149
188
  end
150
189
  end
190
+
151
191
  context 'using audio metadata' do
152
- let(:fits_filename) { 'fits_0.8.5_mp3.xml' }
153
192
  let(:fits_response) { IO.read(File.join(fixture_path, fits_filename)) }
154
193
 
155
- it 'assigns expected values to audio properties.' do
156
- expect(file.mime_type).to eq("audio/mpeg")
157
- expect(file.duration).to eq(["0:0:15:261"])
158
- expect(file.sample_rate).to eq(["44100"])
194
+ context 'with fits_0.8.5' do
195
+ let(:fits_filename) { 'fits_0.8.5_mp3.xml' }
196
+ it 'assigns expected values to audio properties.' do
197
+ expect(file.mime_type).to eq("audio/mpeg")
198
+ expect(file.duration).to eq(["0:0:15:261"])
199
+ expect(file.bit_rate).to include("192000")
200
+ expect(file.sample_rate).to eq(["44100"])
201
+ end
202
+ end
203
+
204
+ context 'with fits_1.2.0' do
205
+ let(:fits_filename) { 'fits_1.2.0_mp3.xml' }
206
+ it 'assigns expected values to audio properties.' do
207
+ expect(file.mime_type).to eq("audio/mpeg")
208
+ expect(file.duration).to eq(["0:0:15:261"])
209
+ expect(file.bit_rate).to include("192000")
210
+ expect(file.sample_rate).to eq(["44100"])
211
+ end
212
+ end
213
+ end
214
+
215
+ context 'using multi-layer tiff metadata' do
216
+ let(:fits_filename) { 'fits_0.8.5_tiff.xml' }
217
+ let(:fits_response) { IO.read(File.join(fixture_path, fits_filename)) }
218
+
219
+ it 'assigns single largest value to width, height' do
220
+ expect(file.width).to eq(["2226"])
221
+ expect(file.height).to eq(["1650"])
159
222
  end
160
223
  end
161
224
  end