berkeley_library-av-core 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +7 -0
  2. data/.dockerignore +391 -0
  3. data/.github/workflows/build.yml +30 -0
  4. data/.gitignore +388 -0
  5. data/.idea/av_core.iml +146 -0
  6. data/.idea/codeStyles/Project.xml +12 -0
  7. data/.idea/codeStyles/codeStyleConfig.xml +5 -0
  8. data/.idea/go.imports.xml +6 -0
  9. data/.idea/inspectionProfiles/Project_Default.xml +37 -0
  10. data/.idea/misc.xml +6 -0
  11. data/.idea/modules.xml +8 -0
  12. data/.idea/vcs.xml +6 -0
  13. data/.rubocop.yml +241 -0
  14. data/.ruby-version +1 -0
  15. data/.simplecov +8 -0
  16. data/CHANGES.md +38 -0
  17. data/Gemfile +3 -0
  18. data/Jenkinsfile +16 -0
  19. data/LICENSE.md +21 -0
  20. data/README.md +20 -0
  21. data/Rakefile +20 -0
  22. data/av_core.gemspec +49 -0
  23. data/lib/berkeley_library/av/config.rb +238 -0
  24. data/lib/berkeley_library/av/constants.rb +30 -0
  25. data/lib/berkeley_library/av/core/module_info.rb +18 -0
  26. data/lib/berkeley_library/av/core.rb +7 -0
  27. data/lib/berkeley_library/av/marc/util.rb +114 -0
  28. data/lib/berkeley_library/av/marc.rb +52 -0
  29. data/lib/berkeley_library/av/metadata/README.md +5 -0
  30. data/lib/berkeley_library/av/metadata/field.rb +110 -0
  31. data/lib/berkeley_library/av/metadata/fields.rb +130 -0
  32. data/lib/berkeley_library/av/metadata/link.rb +28 -0
  33. data/lib/berkeley_library/av/metadata/readers/alma.rb +54 -0
  34. data/lib/berkeley_library/av/metadata/readers/base.rb +53 -0
  35. data/lib/berkeley_library/av/metadata/readers/tind.rb +52 -0
  36. data/lib/berkeley_library/av/metadata/readers.rb +2 -0
  37. data/lib/berkeley_library/av/metadata/source.rb +93 -0
  38. data/lib/berkeley_library/av/metadata/tind_html_metadata_da.json +2076 -0
  39. data/lib/berkeley_library/av/metadata/value.rb +121 -0
  40. data/lib/berkeley_library/av/metadata.rb +103 -0
  41. data/lib/berkeley_library/av/record.rb +86 -0
  42. data/lib/berkeley_library/av/record_id.rb +121 -0
  43. data/lib/berkeley_library/av/record_not_found.rb +7 -0
  44. data/lib/berkeley_library/av/restrictions.rb +36 -0
  45. data/lib/berkeley_library/av/track.rb +132 -0
  46. data/lib/berkeley_library/av/types/duration.rb +67 -0
  47. data/lib/berkeley_library/av/types/file_type.rb +84 -0
  48. data/lib/berkeley_library/av/util.rb +65 -0
  49. data/rakelib/bundle.rake +8 -0
  50. data/rakelib/coverage.rake +11 -0
  51. data/rakelib/gem.rake +54 -0
  52. data/rakelib/rubocop.rake +18 -0
  53. data/rakelib/spec.rake +12 -0
  54. data/spec/.rubocop.yml +116 -0
  55. data/spec/data/10.23.19.JessieLaCavalier.02.mrc +3 -0
  56. data/spec/data/alma/991005939359706532-sru.xml +123 -0
  57. data/spec/data/alma/991034756419706532-sru.xml +162 -0
  58. data/spec/data/alma/991047179369706532-sru.xml +210 -0
  59. data/spec/data/alma/991054360089706532-sru.xml +186 -0
  60. data/spec/data/alma/b11082434-sru.xml +165 -0
  61. data/spec/data/alma/b18538031-sru.xml +123 -0
  62. data/spec/data/alma/b20786580-sru.xml +123 -0
  63. data/spec/data/alma/b22139647-sru.xml +171 -0
  64. data/spec/data/alma/b22139658-sru.xml +282 -0
  65. data/spec/data/alma/b23161018-sru.xml +182 -0
  66. data/spec/data/alma/b23305522-sru.xml +144 -0
  67. data/spec/data/alma/b24071548-sru.xml +136 -0
  68. data/spec/data/alma/b24659129-sru.xml +210 -0
  69. data/spec/data/alma/b25207857-sru.xml +217 -0
  70. data/spec/data/alma/b25716973-sru.xml +186 -0
  71. data/spec/data/alma/b25742488-sru.xml +246 -0
  72. data/spec/data/record-(cityarts)00002.xml +78 -0
  73. data/spec/data/record-(cityarts)00773.xml +94 -0
  74. data/spec/data/record-(clir)00020.xml +153 -0
  75. data/spec/data/record-(miscmat)00615.xml +45 -0
  76. data/spec/data/record-(pacradio)00107.xml +85 -0
  77. data/spec/data/record-(pacradio)01469.xml +82 -0
  78. data/spec/data/record-empty-result.xml +4 -0
  79. data/spec/data/record-multiple-998s-disordered.xml +178 -0
  80. data/spec/data/record-multiple-998s.xml +178 -0
  81. data/spec/data/record-physcolloquia-bk00169017b.xml +78 -0
  82. data/spec/data/record-ragged-998-subfields.xml +122 -0
  83. data/spec/data/record-ragged-998s-multiple-fields.xml +160 -0
  84. data/spec/data/record-redirect-to-login.html +288 -0
  85. data/spec/data/record_id/bibs_with_check_digits.txt +151 -0
  86. data/spec/data/search-1993.xml +158 -0
  87. data/spec/data/search-b23305516.xml +81 -0
  88. data/spec/lib/berkeley_library/av/av_spec.rb +12 -0
  89. data/spec/lib/berkeley_library/av/config_spec.rb +250 -0
  90. data/spec/lib/berkeley_library/av/marc/util_spec.rb +150 -0
  91. data/spec/lib/berkeley_library/av/marc_spec.rb +62 -0
  92. data/spec/lib/berkeley_library/av/metadata/field_spec.rb +81 -0
  93. data/spec/lib/berkeley_library/av/metadata/fields_spec.rb +180 -0
  94. data/spec/lib/berkeley_library/av/metadata/metadata_spec.rb +274 -0
  95. data/spec/lib/berkeley_library/av/metadata/source_spec.rb +261 -0
  96. data/spec/lib/berkeley_library/av/metadata/value_spec.rb +29 -0
  97. data/spec/lib/berkeley_library/av/record_id_spec.rb +72 -0
  98. data/spec/lib/berkeley_library/av/record_spec.rb +284 -0
  99. data/spec/lib/berkeley_library/av/track_spec.rb +335 -0
  100. data/spec/lib/berkeley_library/av/types/duration_spec.rb +91 -0
  101. data/spec/lib/berkeley_library/av/types/file_type_spec.rb +98 -0
  102. data/spec/lib/berkeley_library/av/util_spec.rb +30 -0
  103. data/spec/spec_helper.rb +63 -0
  104. metadata +499 -0
@@ -0,0 +1,261 @@
1
+ require 'spec_helper'
2
+
3
+ # TODO: break some of this out into a Metadata::Reader spec
4
+ module BerkeleyLibrary
5
+ module AV
6
+ class Metadata
7
+ describe Source do
8
+ before do
9
+ allow(BerkeleyLibrary::Logging).to receive(:logger).and_return(Logger.new(File::NULL))
10
+ end
11
+
12
+ describe :for_record_id do
13
+ it 'returns ALMA for a Millennium bib number' do
14
+ expect(Source.for_record_id('b12345678')).to be(Source::ALMA)
15
+ end
16
+
17
+ it 'returns ALMA for a Millennium bib number with check digit' do
18
+ expect(Source.for_record_id('b12345678a')).to be(Source::ALMA)
19
+ end
20
+
21
+ it "returns TIND for something that looks a little like a Millennium bib but isn't" do
22
+ expect(Source.for_record_id('b1234567')).to be(Source::TIND)
23
+ expect(Source.for_record_id('b123456789abcdef')).to be(Source::TIND)
24
+ end
25
+
26
+ it 'returns TIND for a TIND record number' do
27
+ expect(Source.for_record_id('(coll)12345')).to be(Source::TIND)
28
+ end
29
+
30
+ it 'returns TIND for an OCLC number' do
31
+ expect(Source.for_record_id('o12345678')).to be(Source::TIND)
32
+ end
33
+
34
+ it 'returns ALMA for an Alma MMS ID' do
35
+ expect(Source.for_record_id('991054360089706532')).to be(Source::ALMA)
36
+ end
37
+ end
38
+
39
+ describe :catalog_link_text do
40
+ it 'returns TIND text for a TIND record' do
41
+ expect(Source::TIND.catalog_link_text).to eq(Source::LINK_TEXT_TIND)
42
+ end
43
+
44
+ it 'returns Alma text for an Alma record' do
45
+ expect(Source::ALMA.catalog_link_text).to eq(Source::LINK_TEXT_ALMA)
46
+ end
47
+ end
48
+
49
+ describe 'ALMA' do
50
+
51
+ before do
52
+ Config.avplayer_base_uri = 'https://avplayer.lib.berkeley.edu'
53
+ Config.tind_base_uri = 'https://digicoll.lib.berkeley.edu'
54
+ Config.alma_sru_host = 'berkeley.alma.exlibrisgroup.com'
55
+ Config.alma_institution_code = '01UCS_BER'
56
+ Config.alma_primo_host = 'search.library.berkeley.edu'
57
+ Config.alma_permalink_key = 'iqob43'
58
+ end
59
+
60
+ describe :marc_uri_for do
61
+ it 'returns the search URI for an Alma MMS ID' do
62
+ mms_id = '991054360089706532'
63
+ url_expected = "#{sru_url_base}alma.mms_id%3D#{mms_id}"
64
+ uri_expected = URI.parse(url_expected)
65
+ uri_actual = Source::ALMA.marc_uri_for(mms_id)
66
+ expect(uri_actual).to eq(uri_expected)
67
+ end
68
+
69
+ it 'returns the search URI for a Millennium bib number with or without check digit' do
70
+ full_bib = 'b257169738'
71
+ url_expected = "#{sru_url_base}alma.other_system_number%3DUCB-#{full_bib}-01ucs_ber"
72
+ uri_expected = URI.parse(url_expected)
73
+ aggregate_failures do
74
+ %w[b25716973 b257169738 b25716973a].each do |bib|
75
+ uri_actual = Source::ALMA.marc_uri_for(bib)
76
+ expect(uri_actual).to eq(uri_expected)
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ describe :display_uri_for do
83
+ it 'returns the Primo permalink' do
84
+ mms_id = '991054360089706532'
85
+ marc_record = MARC::XMLReader.new("spec/data/alma/#{mms_id}-sru.xml").first
86
+ uri_expected = URI.parse("#{permalink_base}#{mms_id}")
87
+
88
+ metadata = Metadata.new(
89
+ record_id: mms_id,
90
+ source: Source::ALMA,
91
+ marc_record:
92
+ )
93
+
94
+ uri_actual = Source::ALMA.display_uri_for(metadata)
95
+ expect(uri_actual).to eq(uri_expected)
96
+ end
97
+
98
+ it 'raises ArgumentError for a TIND identifier' do
99
+ marc_xml = File.read('spec/data/record-(pacradio)00107.xml')
100
+
101
+ metadata = Metadata.new(
102
+ record_id: '(pacradio)00107',
103
+ source: Source::TIND,
104
+ marc_record: AV::Marc.from_xml(marc_xml)
105
+ )
106
+
107
+ expect { Source::ALMA.display_uri_for(metadata) }.to raise_error(ArgumentError)
108
+ end
109
+ end
110
+
111
+ describe :bib_number do
112
+ it 'finds the bib number' do
113
+ mms_id = '991054360089706532'
114
+ marc_record = MARC::XMLReader.new("spec/data/alma/#{mms_id}-sru.xml").first
115
+
116
+ metadata = Metadata.new(
117
+ record_id: mms_id,
118
+ source: Source::ALMA,
119
+ marc_record:
120
+ )
121
+ expect(metadata.bib_number).to eq('b25716973')
122
+ end
123
+ end
124
+
125
+ describe :record_for do
126
+ it 'loads a record from an MMS ID' do
127
+ mms_id = '991054360089706532'
128
+ marc_xml_path = "spec/data/alma/#{mms_id}-sru.xml"
129
+ sru_url = "#{sru_url_base}alma.mms_id%3D#{mms_id}"
130
+ marc_xml = File.read(marc_xml_path)
131
+ stub_request(:get, sru_url).to_return(status: 200, body: marc_xml)
132
+
133
+ marc_record = Source::ALMA.record_for(mms_id)
134
+ expect(marc_record).to eq(MARC::XMLReader.new(marc_xml_path).first)
135
+ end
136
+
137
+ it 'loads a record from a bib number' do
138
+ short_bib = 'b25716973'
139
+ full_bib = RecordId.ensure_check_digit(short_bib)
140
+ marc_xml_path = "spec/data/alma/#{short_bib}-sru.xml"
141
+ marc_xml = File.read(marc_xml_path)
142
+ sru_url = "#{sru_url_base}alma.other_system_number%3DUCB-#{full_bib}-01ucs_ber"
143
+ stub_request(:get, sru_url).to_return(status: 200, body: marc_xml)
144
+
145
+ aggregate_failures do
146
+ %w[b25716973 b257169738 b25716973a].each do |bib|
147
+ marc_record = Source::ALMA.record_for(bib)
148
+ expect(marc_record).to eq(MARC::XMLReader.new(marc_xml_path).first)
149
+ end
150
+ end
151
+ end
152
+
153
+ it 'raises ArgumentError for the wrong type of ID' do
154
+ expect { Source::ALMA.record_for('(pacradio)00107') }.to raise_error(AV::RecordNotFound)
155
+ end
156
+ end
157
+ end
158
+
159
+ describe 'TIND' do
160
+ attr_reader :record_url
161
+
162
+ before do
163
+ AV::Config.tind_base_uri = 'https://digicoll.lib.berkeley.edu'
164
+ @record_url = 'https://digicoll.lib.berkeley.edu/search?p=035__a%3A%22%28pacradio%2900107%22&of=xm'
165
+ end
166
+
167
+ after do
168
+ Config.send(:clear!)
169
+ end
170
+
171
+ describe :marc_uri_for do
172
+ it 'returns the search URI' do
173
+ uri_expected = URI.parse(record_url)
174
+ uri_actual = Source::TIND.marc_uri_for('(pacradio)00107')
175
+ expect(uri_actual).to eq(uri_expected)
176
+ end
177
+ end
178
+
179
+ describe :display_uri_for do
180
+ it 'returns the record display page URI' do
181
+ marc_xml = File.read('spec/data/record-(pacradio)00107.xml')
182
+ stub_request(:get, record_url).to_return(status: 200, body: marc_xml)
183
+
184
+ metadata = Metadata.new(
185
+ record_id: '(pacradio)00107',
186
+ source: Source::TIND,
187
+ marc_record: Source::TIND.record_for('(pacradio)00107')
188
+ )
189
+
190
+ uri_expected = URI.parse('https://digicoll.lib.berkeley.edu/record/19816')
191
+ uri_actual = Source::TIND.display_uri_for(metadata)
192
+ expect(uri_actual).to eq(uri_expected)
193
+ end
194
+
195
+ it 'raises ArgumentError for the wrong type of record' do
196
+ marc_xml = File.read('spec/data/alma/b20786580-sru.xml')
197
+ marc_record = AV::Marc.from_xml(marc_xml)
198
+
199
+ metadata = Metadata.new(
200
+ record_id: '(pacradio)00107',
201
+ source: Source::ALMA,
202
+ marc_record:
203
+ )
204
+
205
+ expect { Source::TIND.display_uri_for(metadata) }.to raise_error(ArgumentError)
206
+ end
207
+ end
208
+
209
+ describe :record_for do
210
+ it 'finds a MARC record' do
211
+ marc_xml = File.read('spec/data/record-(pacradio)00107.xml')
212
+ stub_request(:get, record_url).to_return(status: 200, body: marc_xml)
213
+
214
+ marc_record = Source::TIND.record_for('(pacradio)00107')
215
+ expect(marc_record).not_to be_nil
216
+ expect(marc_record).to be_a(MARC::Record)
217
+
218
+ fields_001 = marc_record.fields('001')
219
+ expect(fields_001.size).to eq(1)
220
+ expect(fields_001[0].value).to eq('19816')
221
+ end
222
+
223
+ it "raises #{AV::RecordNotFound} if the record cannot be found" do
224
+ stub_request(:get, record_url).to_return(status: 404, body: '')
225
+
226
+ expect { Source::TIND.record_for('(pacradio)00107') }.to raise_error(AV::RecordNotFound)
227
+ end
228
+
229
+ it "raises #{AV::RecordNotFound} if the record cannot be parsed" do
230
+ stub_request(:get, record_url).to_return(status: 200, body: '<? this is not valid MARCXML>')
231
+
232
+ expect { Source::TIND.record_for('(pacradio)00107') }.to raise_error(AV::RecordNotFound)
233
+ end
234
+
235
+ it "raises #{AV::RecordNotFound} if no records are returned" do
236
+ empty_result = File.read('spec/data/record-empty-result.xml')
237
+ stub_request(:get, record_url).to_return(status: 200, body: empty_result)
238
+
239
+ expect { Source::TIND.record_for('(pacradio)00107') }.to raise_error(AV::RecordNotFound)
240
+ end
241
+
242
+ it "raises #{AV::RecordNotFound} on a redirect to login" do
243
+ redirect_to_login = File.read('spec/data/record-redirect-to-login.html')
244
+ stub_request(:get, record_url).to_return(status: 200, body: redirect_to_login)
245
+
246
+ expect { Source::TIND.record_for('(pacradio)00107') }.to raise_error(AV::RecordNotFound)
247
+ end
248
+
249
+ it "raises #{AV::RecordNotFound} if TIND returns a weird HTTP status" do
250
+ marc_xml = File.read('spec/data/record-(pacradio)00107.xml')
251
+ stub_request(:get, record_url).to_return(status: 207, body: marc_xml)
252
+
253
+ expect { Source::TIND.record_for('(pacradio)00107') }.to raise_error(AV::RecordNotFound)
254
+ end
255
+ end
256
+
257
+ end
258
+ end
259
+ end
260
+ end
261
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ module BerkeleyLibrary
4
+ module AV
5
+ class Metadata
6
+ describe Value do
7
+ describe :<=> do
8
+ it 'can compare text with links' do
9
+ v1 = Value.new(tag: '956', label: 'test', entries: ['test'], order: 1)
10
+ v2 = Value.new(tag: '956', label: 'test', entries: [Link.new(body: 'test', url: 'http://example.org')], order: 1)
11
+ actual = v1 <=> v2
12
+ expect(actual).not_to eq(0)
13
+ expect(actual).to eq(v1.entries.to_s <=> v2.entries.to_s)
14
+ end
15
+
16
+ it 'returns nil for nil' do
17
+ v = Value.new(tag: '956', label: 'test', entries: ['test'], order: 1)
18
+ expect(v <=> nil).to be_nil
19
+ end
20
+
21
+ it 'returns nil for things that are not Values' do
22
+ v = Value.new(tag: '956', label: 'test', entries: ['test'], order: 1)
23
+ expect(v <=> v.to_s).to be_nil
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+
3
+ module BerkeleyLibrary
4
+ module AV
5
+ describe RecordId do
6
+
7
+ describe :hash do
8
+ it 'returns the same hash for identical objects' do
9
+ id1 = RecordId.new('991054360089706532')
10
+ id2 = RecordId.new('991054360089706532')
11
+ expect(id1.hash).to eq(id2.hash)
12
+ end
13
+ end
14
+
15
+ describe :inspect do
16
+ it 'includes the ID and type' do
17
+ mms_id = '991054360089706532'
18
+ id = RecordId.new(mms_id)
19
+ expect(id.inspect).to include(mms_id)
20
+ expect(id.inspect).to include(id.type.to_s)
21
+ end
22
+ end
23
+
24
+ describe :ensure_check_digit do
25
+ let(:expected_check_digits_by_bib) do
26
+ infile = 'spec/data/record_id/bibs_with_check_digits.txt'
27
+ File.readlines(infile, chomp: true).each_with_object({}) do |bib, x|
28
+ x[bib[0, 9]] = bib[9]
29
+ end
30
+ end
31
+
32
+ it 'produces the expected check digit' do
33
+ aggregate_failures 'check digit' do
34
+ expected_check_digits_by_bib.each do |bib_expected, cd_expected|
35
+ bib_with_cd = RecordId.ensure_check_digit(bib_expected)
36
+ expect(bib_with_cd[0, 9]).to eq(bib_expected) # just to be sure
37
+
38
+ cd_actual = bib_with_cd[9]
39
+ expect(cd_actual).to eq(cd_expected), "Wrong check digit for #{bib_expected}; should be #{cd_expected}, was #{cd_actual}"
40
+ end
41
+ end
42
+ end
43
+
44
+ it 'raises an error if passed an invalid check digit' do
45
+ aggregate_failures 'bad check digit' do
46
+ expected_check_digits_by_bib.each do |bib, cd|
47
+ cd_i = cd == 'x' ? 10 : cd.to_i
48
+ bad_cd = cd_i == '0' ? 'x' : (cd_i - 1).to_s
49
+ bad_bib = "#{bib}#{bad_cd}"
50
+ expect { RecordId.ensure_check_digit(bad_bib) }.to raise_error(ArgumentError), "#{bib}: No error raised for #{bad_cd} (should be #{cd})"
51
+ end
52
+ end
53
+ end
54
+
55
+ it 'ignores a wildcard "a" check digit, but returns the correct digit' do
56
+ aggregate_failures 'check digit "a"' do
57
+ expected_check_digits_by_bib.each do |bib, cd|
58
+ wildcard = "#{bib}a"
59
+ expected = "#{bib}#{cd}"
60
+ begin
61
+ actual = RecordId.ensure_check_digit(wildcard)
62
+ expect(actual).to eq(expected)
63
+ rescue ArgumentError => e
64
+ raise("Expected #{wildcard} not to raise error, got #{e.class}: #{e}")
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,284 @@
1
+ require 'spec_helper'
2
+
3
+ module BerkeleyLibrary
4
+ module AV
5
+ describe Record do
6
+ before do
7
+ Config.avplayer_base_uri = 'https://avplayer.lib.berkeley.edu'
8
+ Config.tind_base_uri = 'https://digicoll.lib.berkeley.edu'
9
+ Config.alma_sru_host = 'berkeley.alma.exlibrisgroup.com'
10
+ Config.alma_institution_code = '01UCS_BER'
11
+ Config.alma_primo_host = 'search.library.berkeley.edu'
12
+ Config.alma_permalink_key = 'iqob43'
13
+ end
14
+
15
+ after do
16
+ Config.send(:clear!)
17
+ end
18
+
19
+ describe :new do
20
+ it 'sorts the tracks' do
21
+ t1 = Track.new(sort_order: 1, title: 'Part 1', path: 'MRCAudio/frost-read1.mp3')
22
+ t2 = Track.new(sort_order: 2, title: 'Part 2', path: 'MRCAudio/frost-read2.mp3')
23
+ record = Record.new(
24
+ collection: 'MRCAudio',
25
+ tracks: [t2, t1],
26
+ metadata: instance_double(Metadata)
27
+ )
28
+ tracks = record.tracks
29
+ expect(tracks[0]).to eq(t1)
30
+ expect(tracks[1]).to eq(t2)
31
+ end
32
+ end
33
+
34
+ describe :player_uri do
35
+ it 'returns a player URI based on the bib number for Millennium records' do
36
+ bib_number = 'b22139658'
37
+ stub_sru_request(bib_number)
38
+
39
+ collection = 'MRCVideo'
40
+ record = Record.from_metadata(collection:, record_id: bib_number)
41
+
42
+ expected_uri = URI.parse("https://avplayer.lib.berkeley.edu/#{collection}/#{bib_number}")
43
+ expect(record.player_uri).to eq(expected_uri)
44
+ end
45
+
46
+ it 'returns a player URI based on the record ID for TIND records' do
47
+ tind_035 = '(pacradio)01469'
48
+ marc_xml = File.read("spec/data/record-#{tind_035}.xml")
49
+ search_url = "https://digicoll.lib.berkeley.edu/search?p=035__a%3A%22#{CGI.escape(tind_035)}%22&of=xm"
50
+ stub_request(:get, search_url).to_return(status: 200, body: marc_xml)
51
+
52
+ collection = 'Pacifica'
53
+ record = Record.from_metadata(collection:, record_id: tind_035)
54
+
55
+ expected_uri = URI.parse("https://avplayer.lib.berkeley.edu/#{collection}/#{tind_035}")
56
+ expect(record.player_uri).to eq(expected_uri)
57
+ end
58
+
59
+ it 'generates the player URI' do
60
+ collection = 'MRCAudio'
61
+ bib_number = 'b11082434'
62
+
63
+ metadata = instance_double(Metadata)
64
+ expect(metadata).to receive(:record_id).and_return(bib_number)
65
+
66
+ record = Record.new(collection:, tracks: [], metadata:)
67
+
68
+ expected_uri = URI.parse("https://avplayer.lib.berkeley.edu/#{collection}/#{bib_number}")
69
+ expect(record.player_uri).to eq(expected_uri)
70
+ end
71
+ end
72
+
73
+ describe :display_uri do
74
+ it 'returns the display URI' do
75
+ collection = 'MRCAudio'
76
+ bib_number = 'b11082434'
77
+ expected_uri = URI.parse("http://oskicat.example.edu/record=#{bib_number}")
78
+
79
+ metadata = instance_double(Metadata)
80
+ expect(metadata).to receive(:display_uri).and_return(expected_uri)
81
+
82
+ record = Record.new(collection:, tracks: [], metadata:)
83
+ expect(record.display_uri).to eq(expected_uri)
84
+ end
85
+ end
86
+
87
+ describe :type_label do
88
+ it 'handles audio' do
89
+ t1 = Track.new(sort_order: 1, title: 'Part 1', path: 'MRCAudio/frost-read1.mp3')
90
+ t2 = Track.new(sort_order: 2, title: 'Part 2', path: 'MRCAudio/frost-read2.mp3')
91
+ record = Record.new(
92
+ collection: 'MRCAudio',
93
+ tracks: [t2, t1],
94
+ metadata: instance_double(Metadata)
95
+ )
96
+
97
+ expect(record.type_label).to eq('Audio')
98
+ end
99
+
100
+ it 'handles video' do
101
+ t1 = Track.new(sort_order: 1, title: 'Part 1', path: 'MRCAudio/frost-read1.mp4')
102
+ t2 = Track.new(sort_order: 2, title: 'Part 2', path: 'MRCAudio/frost-read2.mp4')
103
+ record = Record.new(
104
+ collection: 'MRCVideo',
105
+ tracks: [t2, t1],
106
+ metadata: instance_double(Metadata)
107
+ )
108
+
109
+ expect(record.type_label).to eq('Video')
110
+ end
111
+
112
+ it 'handles mixed records' do
113
+ t1 = Track.new(sort_order: 1, title: 'Part 1', path: 'MRCAudio/frost-read1.mp3')
114
+ t2 = Track.new(sort_order: 2, title: 'Part 2', path: 'MRCAudio/frost-read2.mp4')
115
+ record = Record.new(
116
+ collection: 'MRCAudioVideo',
117
+ tracks: [t2, t1],
118
+ metadata: instance_double(Metadata)
119
+ )
120
+
121
+ expect(record.type_label).to eq('Audio / Video')
122
+ end
123
+ end
124
+
125
+ describe :description do
126
+ it 'gets the description from the 520 tag' do
127
+ bib_number = 'b22139658'
128
+ stub_sru_request(bib_number)
129
+
130
+ marc_record = alma_marc_record_for(bib_number)
131
+ expected_desc = marc_record['520']['a']
132
+
133
+ record = Record.from_metadata(collection: 'MRCVideo', record_id: bib_number)
134
+ expect(record.description).to eq(expected_desc)
135
+ end
136
+ end
137
+
138
+ describe :tind_id do
139
+ it 'returns nil for Millennium records' do
140
+ bib_number = 'b22139658'
141
+ stub_sru_request(bib_number)
142
+ record = Record.from_metadata(collection: 'MRCVideo', record_id: bib_number)
143
+ expect(record.tind_id).to be_nil
144
+ end
145
+
146
+ it 'returns the TIND ID for TIND records' do
147
+ marc_xml = File.read('spec/data/record-(pacradio)01469.xml')
148
+ search_url = 'https://digicoll.lib.berkeley.edu/search?p=035__a%3A%22%28pacradio%2901469%22&of=xm'
149
+ stub_request(:get, search_url).to_return(status: 200, body: marc_xml)
150
+
151
+ record = Record.from_metadata(
152
+ collection: 'Pacifica',
153
+ record_id: '(pacradio)01469'
154
+ )
155
+ expected_id = RecordId.new('21178')
156
+ expect(record.tind_id).to eq(expected_id)
157
+ end
158
+ end
159
+
160
+ describe :bib_number do
161
+ it 'returns nil for Alma records with no bib number' do
162
+ mms_id = '991034756419706532'
163
+ stub_sru_request(mms_id)
164
+ record = Record.from_metadata(collection: 'Video-Public-Bancroft', record_id: mms_id)
165
+ expect(record.bib_number).to be_nil
166
+ end
167
+
168
+ it 'returns nil for TIND records with no bib number' do
169
+ tind_id = '(clir)00020'
170
+ marc_xml = File.read('spec/data/record-(clir)00020.xml')
171
+ search_url = 'https://digicoll.lib.berkeley.edu/search?p=035__a%3A%22%28clir%2900020%22&of=xm'
172
+ stub_request(:get, search_url).to_return(status: 200, body: marc_xml)
173
+
174
+ record = Record.from_metadata(collection: 'Video-Public-Bancroft', record_id: tind_id)
175
+ expect(record.bib_number).to be_nil
176
+ end
177
+ end
178
+
179
+ describe :from_metadata do
180
+ it 'loads the metadata' do
181
+ marc_xml = File.read('spec/data/record-(pacradio)01469.xml')
182
+ search_url = 'https://digicoll.lib.berkeley.edu/search?p=035__a%3A%22%28pacradio%2901469%22&of=xm'
183
+ stub_request(:get, search_url).to_return(status: 200, body: marc_xml)
184
+
185
+ record = Record.from_metadata(collection: 'Pacifica', record_id: '(pacradio)01469')
186
+
187
+ tracks = record.tracks
188
+ expect(tracks.size).to eq(1)
189
+ track = tracks[0]
190
+ expect(track.sort_order).to eq(0)
191
+ expect(track.title).to be_nil
192
+ expect(track.path).to eq('Pacifica/PRA_NHPRC1_AZ1084_00_000_00.mp3')
193
+ expect(track.duration).to eq(AV::Types::Duration.from_string('00:54:03'))
194
+
195
+ record.metadata.tap do |metadata|
196
+ expect(metadata.bib_number).to eq('b23305522')
197
+ values = metadata.values_by_field.values
198
+
199
+ expected = [
200
+ 'Title (245): Wanda Coleman',
201
+ 'Description (520): Poet Opal Palmer Adisa interviews writer/poet Wanda Coleman, author of Mad Dog, Black Lady, African Sleeping Sickness and Hand Dance, among other books. Coleman discusses when she found her poetic voice, talks about the function of poetry, her personal encounters with anti-Black discrimination, and about the reluctance of white liberals to discuss issues that affect the Black community. She also talks about the plight of the African American community in South Central Los Angeles. The poems Coleman reads are A civilized plague, David Polion, Notes of a cultural terrorist and Jazz wazz.',
202
+ 'Creator (700): Coleman, Wanda. interviewee. Adisa, Opal Palmer. interviewer.',
203
+ 'Creator (710): Pacifica Radio Archive. KPFA (Radio station : Berkeley, Calif.).',
204
+ 'Published (260): Los Angeles, Pacifica Radio Archives, 1993.',
205
+ 'Full Collection Name (982): Pacifica Radio Archives Social Activism Sound Recording Project',
206
+ 'Type (336): Audio',
207
+ 'Extent (300): 1 online resource.',
208
+ 'Archive (852): The Library',
209
+ "Grant Information (536): Sponsored by the National Historical Publications and Records Commission at the National Archives and Records Administration as part of Pacifica's American Women Making History and Culture: 1963-1982 grant preservation project.",
210
+ 'Usage Statement (540): RESTRICTED. Permissions, licensing requests, and all other inquiries should be directed in writing to: Director of the Archives, Pacifica Radio Archives, 3729 Cahuenga Blvd. West, North Hollywood, CA 91604, 800-735-0230 x 263, fax 818-506-1084, info@pacificaradioarchives.org, http://www.pacificaradioarchives.org',
211
+ 'Collection (982): Pacifica Radio Archives',
212
+ 'Tracks (998): PRA_NHPRC1_AZ1084_00_000_00.mp3 00:54:03',
213
+ 'Linked Resources (856): [View record in Digital Collections.](https://digicoll.lib.berkeley.edu/record/21178)'
214
+ ]
215
+ expect(values.size).to eq(expected.size)
216
+ aggregate_failures 'fields' do
217
+ values.each_with_index { |f, i| expect(f.to_s).to eq(expected[i]) }
218
+ end
219
+
220
+ expect(record.title).to eq(metadata.title)
221
+ expect(record.bib_number).to eq(metadata.bib_number)
222
+ end
223
+ end
224
+
225
+ it "raises #{AV::RecordNotFound} if the record cannot be found" do
226
+ search_url = 'https://digicoll.lib.berkeley.edu/search?p=035__a%3A%22%28pacradio%2901469%22&of=xm'
227
+ stub_request(:get, search_url).to_return(status: 404)
228
+ expect do
229
+ Record.from_metadata(
230
+ collection: 'Pacifica',
231
+ record_id: '(pacradio)01469'
232
+ )
233
+ end.to raise_error(AV::RecordNotFound)
234
+ end
235
+ end
236
+
237
+ describe :calnet_or_ip? do
238
+ it 'returns true for restricted, false for unrestricted' do
239
+ restricted = %w[b18538031 b24071548 (cityarts)00002 (cityarts)00773]
240
+ unrestricted = %w[b22139658 b23161018 (pacradio)00107 (pacradio)01469]
241
+ (restricted + unrestricted).each do |record_id|
242
+ source = Metadata::Source.for_record_id(record_id)
243
+ if source == Metadata::Source::TIND
244
+ test_data = "spec/data/record-#{record_id}.xml"
245
+ stub_request(:get, source.marc_uri_for(record_id)).to_return(status: 200, body: File.read(test_data))
246
+ else
247
+ stub_sru_request(record_id)
248
+ end
249
+ end
250
+
251
+ aggregate_failures 'restrictions' do
252
+ restricted.each do |record_id|
253
+ record = Record.from_metadata(collection: 'test', record_id:)
254
+ expect(record.calnet_or_ip?).to eq(true), "Expected #{record_id} to be restricted, was not"
255
+ end
256
+
257
+ unrestricted.each do |record_id|
258
+ record = Record.from_metadata(collection: 'test', record_id:)
259
+ expect(record.calnet_or_ip?).to eq(false), "Expected #{record_id} not to be restricted, was"
260
+ end
261
+ end
262
+ end
263
+ end
264
+
265
+ describe :calnet_only? do
266
+ it 'returns true for CalNet-only records' do
267
+ mms_id = '991047179369706532'
268
+ stub_sru_request(mms_id)
269
+ record = Record.from_metadata(collection: 'test', record_id: mms_id)
270
+ expect(record.calnet_or_ip?).to eq(true)
271
+ expect(record.calnet_only?).to eq(true)
272
+ end
273
+
274
+ it 'returns false for records open to UCB IP addresses' do
275
+ mms_id = '991054360089706532'
276
+ stub_sru_request(mms_id)
277
+ record = Record.from_metadata(collection: 'test', record_id: mms_id)
278
+ expect(record.calnet_or_ip?).to eq(true)
279
+ expect(record.calnet_only?).to eq(false)
280
+ end
281
+ end
282
+ end
283
+ end
284
+ end