hydra-works 0.16.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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