pennmarc 1.0.24 → 1.0.26

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +8 -9
  3. data/lib/pennmarc/enriched.rb +1 -0
  4. data/lib/pennmarc/helpers/access.rb +8 -6
  5. data/lib/pennmarc/helpers/creator.rb +139 -65
  6. data/lib/pennmarc/helpers/edition.rb +5 -3
  7. data/lib/pennmarc/helpers/identifier.rb +12 -0
  8. data/lib/pennmarc/helpers/note.rb +24 -19
  9. data/lib/pennmarc/helpers/production.rb +113 -20
  10. data/lib/pennmarc/helpers/subject.rb +10 -4
  11. data/lib/pennmarc/helpers/title.rb +39 -26
  12. data/lib/pennmarc/test/marc_helpers.rb +83 -0
  13. data/lib/pennmarc/util.rb +98 -69
  14. data/lib/pennmarc/version.rb +1 -1
  15. data/lib/pennmarc.rb +7 -0
  16. data/spec/lib/pennmarc/helpers/access_spec.rb +11 -2
  17. data/spec/lib/pennmarc/helpers/citation_spec.rb +0 -2
  18. data/spec/lib/pennmarc/helpers/classification_spec.rb +0 -2
  19. data/spec/lib/pennmarc/helpers/creator_spec.rb +103 -2
  20. data/spec/lib/pennmarc/helpers/database_spec.rb +0 -2
  21. data/spec/lib/pennmarc/helpers/date_spec.rb +0 -2
  22. data/spec/lib/pennmarc/helpers/edition_spec.rb +4 -2
  23. data/spec/lib/pennmarc/helpers/format_spec.rb +0 -2
  24. data/spec/lib/pennmarc/helpers/genre_spec.rb +0 -2
  25. data/spec/lib/pennmarc/helpers/identifer_spec.rb +14 -2
  26. data/spec/lib/pennmarc/helpers/inventory_spec.rb +0 -2
  27. data/spec/lib/pennmarc/helpers/language_spec.rb +0 -2
  28. data/spec/lib/pennmarc/helpers/link_spec.rb +0 -2
  29. data/spec/lib/pennmarc/helpers/location_spec.rb +0 -2
  30. data/spec/lib/pennmarc/helpers/note_spec.rb +22 -29
  31. data/spec/lib/pennmarc/helpers/production_spec.rb +121 -22
  32. data/spec/lib/pennmarc/helpers/relation_spec.rb +0 -2
  33. data/spec/lib/pennmarc/helpers/series_spec.rb +0 -2
  34. data/spec/lib/pennmarc/helpers/subject_spec.rb +16 -2
  35. data/spec/lib/pennmarc/helpers/title_spec.rb +20 -2
  36. data/spec/lib/pennmarc/marc_util_spec.rb +0 -2
  37. data/spec/lib/pennmarc/parser_spec.rb +1 -1
  38. data/spec/spec_helper.rb +7 -0
  39. data/spec/support/fixture_helpers.rb +10 -0
  40. metadata +4 -3
  41. data/spec/support/marc_spec_helpers.rb +0 -85
data/lib/pennmarc/util.rb CHANGED
@@ -13,16 +13,16 @@ module PennMARC
13
13
  period: /\.\s*$/ }.freeze # TODO: revise to exclude "etc."
14
14
 
15
15
  # Check if a given record has a field present by tag (e.g., '041')
16
- # @param [MARC::Record] record
17
- # @param [String] marc_field
16
+ # @param record [MARC::Record]
17
+ # @param marc_field [String]
18
18
  # @return [Boolean]
19
19
  def field_defined?(record, marc_field)
20
20
  record.select { |field| field.tag == marc_field }.any?
21
21
  end
22
22
 
23
23
  # Join subfields from a field selected based on a provided proc
24
- # @param [MARC::DataField, nil] field
25
- # @param [Proc] selector
24
+ # @param field [MARC::DataField, nil]
25
+ # @param selector [Proc]
26
26
  # @return [String]
27
27
  def join_subfields(field, &selector)
28
28
  return '' unless field
@@ -37,77 +37,75 @@ module PennMARC
37
37
 
38
38
  # returns true if field has a value that matches
39
39
  # passed-in regex and passed in subfield
40
- # @todo example usage
41
- # @param [MARC::DataField] field
42
- # @param [String|Integer|Symbol] subfield
43
- # @param [Regexp] regex
44
- # @return [TrueClass, FalseClass]
40
+ # @param field [MARC::DataField]
41
+ # @param subfield [String|Integer|Symbol]
42
+ # @param regex [Regexp]
43
+ # @return [Boolean, nil]
45
44
  def subfield_value?(field, subfield, regex)
46
45
  field&.any? { |sf| sf.code == subfield.to_s && sf.value =~ regex }
47
46
  end
48
47
 
49
48
  # returns true if field has no value that matches
50
49
  # passed-in regex and passed in subfield
51
- # @param [MARC::DataField] field
52
- # @param [String|Integer|Symbol] subfield
53
- # @param [Regexp] regex
54
- # @return [TrueClass, FalseClass, nil]
50
+ # @param field [MARC::DataField]
51
+ # @param subfield [String|Integer|Symbol]
52
+ # @param regex [Regexp]
53
+ # @return [Boolean, nil]
55
54
  def no_subfield_value_matches?(field, subfield, regex)
56
55
  field&.none? { |sf| sf.code == subfield.to_s && sf.value =~ regex }
57
56
  end
58
57
 
59
58
  # returns true if a given field has a given subfield value in a given array
60
- # TODO: example usage
61
- # @param [MARC:DataField] field
62
- # @param [String|Integer|Symbol] subfield
63
- # @param [Array] array
64
- # @return [TrueClass, FalseClass]
59
+ # @param field [MARC:DataField]
60
+ # @param subfield [String|Integer|Symbol]
61
+ # @param array [Array]
62
+ # @return [Boolean]
65
63
  def subfield_value_in?(field, subfield, array)
66
64
  field.any? { |sf| sf.code == subfield.to_s && sf.value.in?(array) }
67
65
  end
68
66
 
69
67
  # returns true if a given field does not have a given subfield value in a given array
70
- # @param [MARC:DataField] field
71
- # @param [String|Integer|Symbol] subfield
72
- # @param [Array] array
73
- # @return [TrueClass, FalseClass
68
+ # @param field [MARC:DataField]
69
+ # @param subfield [String|Integer|Symbol]
70
+ # @param array [Array]
71
+ # @return [Boolean]
74
72
  def subfield_value_not_in?(field, subfield, array)
75
73
  field.none? { |sf| sf.code == subfield.to_s && sf.value.in?(array) }
76
74
  end
77
75
 
78
76
  # returns a lambda checking if passed-in subfield's code is a member of array
79
- # @param [Array] array
77
+ # @param array [Array]
80
78
  # @return [Proc]
81
79
  def subfield_in?(array)
82
80
  ->(subfield) { array.member?(subfield.code) }
83
81
  end
84
82
 
85
83
  # returns a lambda checking if passed-in subfield's code is NOT a member of array
86
- # @param [Array] array
84
+ # @param array [Array]
87
85
  # @return [Proc]
88
86
  def subfield_not_in?(array)
89
87
  ->(subfield) { !array.member?(subfield.code) }
90
88
  end
91
89
 
92
90
  # Check if a field has a given subfield defined
93
- # @param [MARC::DataField] field
94
- # @param [String|Symbol|Integer] subfield
95
- # @return [TrueClass, FalseClass]
91
+ # @param field [MARC::DataField]
92
+ # @param subfield [String|Symbol|Integer]
93
+ # @return [Boolean]
96
94
  def subfield_defined?(field, subfield)
97
95
  field.any? { |sf| sf.code == subfield.to_s }
98
96
  end
99
97
 
100
98
  # Check if a field does not have a given subfield defined
101
- # @param [MARC::DataField] field
102
- # @param [String|Symbol|Integer] subfield
103
- # @return [TrueClass, FalseClass]
99
+ # @param field [MARC::DataField]
100
+ # @param subfield [String|Symbol|Integer]
101
+ # @return [Boolean]
104
102
  def subfield_undefined?(field, subfield)
105
103
  field.none? { |sf| sf.code == subfield.to_s }
106
104
  end
107
105
 
108
106
  # Gets all subfield values for a subfield in a given field
109
- # @param [MARC::DataField] field
110
- # @param [String|Symbol] subfield as a string or symbol
107
+ # @param field [MARC::DataField]
108
+ # @param subfield [String|Symbol] as a string or symbol
111
109
  # @return [Array] subfield values for given subfield code
112
110
  def subfield_values(field, subfield)
113
111
  field.filter_map do |sf|
@@ -120,9 +118,9 @@ module PennMARC
120
118
  end
121
119
 
122
120
  # Get all subfield values for a provided subfield from any occurrence of a provided tag/tags
123
- # @param [String|Array] tag tags to consider
124
- # @param [String|Symbol] subfield to take the values from
125
- # @param [MARC::Record] record source
121
+ # @param tag [String|Array] tags to consider
122
+ # @param subfield [String|Symbol] to take the values from
123
+ # @param record [MARC::Record]
126
124
  # @return [Array] array of subfield values
127
125
  def subfield_values_for(tag:, subfield:, record:)
128
126
  record.fields(tag).flat_map do |field|
@@ -130,24 +128,43 @@ module PennMARC
130
128
  end
131
129
  end
132
130
 
133
- # @param [Symbol|String] trailer to target for removal
134
- # @param [String] string to modify
131
+ # Trim punctuation method extracted from Traject macro, to ensure consistent output
132
+ # @param string [String]
133
+ # @return [String] string with relevant punctuation removed
134
+ def trim_punctuation(string)
135
+ return string unless string
136
+
137
+ string = string.sub(%r{ *[ ,/;:] *\Z}, '')
138
+
139
+ # trailing period if it is preceded by at least three letters (possibly preceded and followed by whitespace)
140
+ string = string.sub(/( *[[:word:]]{3,})\. *\Z/, '\1')
141
+
142
+ # single square bracket characters if they are the start and/or end chars and there are no internal square
143
+ # brackets.
144
+ string = string.sub(/\A\[?([^\[\]]+)\]?\Z/, '\1')
145
+
146
+ # trim any leading or trailing whitespace
147
+ string.strip
148
+ end
149
+
150
+ # @param trailer [Symbol|String] to target for removal
151
+ # @param string [String] to modify
135
152
  # @return [String]
136
153
  def trim_trailing(trailer, string)
137
154
  string.sub TRAILING_PUNCTUATIONS_PATTERNS[trailer.to_sym], ''
138
155
  end
139
156
 
140
157
  # trim trailing punctuation, manipulating string in place
141
- # @param [Symbol|String] trailer to target for removal
142
- # @param [String] string to modify
158
+ # @param trailer [Symbol|String] to target for removal
159
+ # @param string [String] to modify
143
160
  # @return [String, Nil] string to modify
144
161
  def trim_trailing!(trailer, string)
145
162
  string.sub! TRAILING_PUNCTUATIONS_PATTERNS[trailer.to_sym], ''
146
163
  end
147
164
 
148
165
  # Intelligently append given punctuation to the end of a string
149
- # @param [Symbol] trailer
150
- # @param [String] string
166
+ # @param trailer [Symbol]
167
+ # @param string [String]
151
168
  # @return [String]
152
169
  def append_trailing(trailer, string)
153
170
  return string if string.end_with?('.', '-')
@@ -165,9 +182,9 @@ module PennMARC
165
182
  # translations of title values. A common need is to extract subfields as selected by
166
183
  # passed-in block from 880 datafield that has a particular subfield 6 value.
167
184
  # See: https://www.loc.gov/marc/bibliographic/bd880.html
168
- # @param [MARC::Record] record
169
- # @param [String|Array] subfield6_value either a string to look for in sub6 or an array of them
170
- # @param [Proc] selector takes a subfield as argument, returns a boolean
185
+ # @param record [MARC::Record]
186
+ # @param subfield6_value [String|Array] either a string to look for in sub6 or an array of them
187
+ # @param selector [Proc] takes a subfield as argument, returns a boolean
171
188
  # @return [Array] array of linked alternates
172
189
  def linked_alternate(record, subfield6_value, &selector)
173
190
  record.fields('880').filter_map do |field|
@@ -180,8 +197,8 @@ module PennMARC
180
197
  # Common case of wanting to extract all the subfields besides 6 or 8,
181
198
  # from 880 datafield that has a particular subfield 6 value. We exclude 6 because
182
199
  # that value is the linkage ID itself and 8 because... IDK
183
- # @param [MARC::Record] record
184
- # @param [String|Array] subfield6_value either a string to look for in sub6 or an array of them
200
+ # @param record [MARC::Record]
201
+ # @param subfield6_value [String|Array] either a string to look for in sub6 or an array of them
185
202
  # @return [Array] array of linked alternates without 8 or 6 values
186
203
  def linked_alternate_not_6_or_8(record, subfield6_value)
187
204
  excluded_subfields = %w[6 8]
@@ -191,8 +208,8 @@ module PennMARC
191
208
  end
192
209
 
193
210
  # Returns the non-6,8 subfields from a datafield and its 880 link.
194
- # @param [MARC::Record] record
195
- # @param [String] tag
211
+ # @param record [MARC::Record]
212
+ # @param tag [String]
196
213
  # @return [Array<String>] values
197
214
  def datafield_and_linked_alternate(record, tag)
198
215
  record.fields(tag).filter_map { |field|
@@ -201,23 +218,23 @@ module PennMARC
201
218
  end
202
219
 
203
220
  # Get the substring of a string up to a given target character
204
- # @param [Object] string to split
205
- # @param [Object] target character to split upon
221
+ # @param string [Object] to split
222
+ # @param target [Object] character to split upon
206
223
  # @return [String (frozen)]
207
224
  def substring_before(string, target)
208
225
  string.scan(target).present? ? string.split(target, 2).first : ''
209
226
  end
210
227
 
211
228
  # Get the substring of a string after the first occurrence of a target character
212
- # @param [Object] string to split
213
- # @param [Object] target character to split upon
229
+ # @param string [Object] to split
230
+ # @param target [Object] character to split upon
214
231
  # @return [String (frozen)]
215
232
  def substring_after(string, target)
216
233
  string.scan(target).present? ? string.split(target, 2).second : ''
217
234
  end
218
235
 
219
236
  # Join array and normalizing extraneous spaces
220
- # @param [Array] array
237
+ # @param array [Array]
221
238
  # @return [String]
222
239
  def join_and_squish(array)
223
240
  array.join(' ').squish
@@ -225,7 +242,7 @@ module PennMARC
225
242
 
226
243
  # If there's a subfield i, extract its value, and if there's something
227
244
  # in parentheses in that value, extract that.
228
- # @param [MARC::Field] field
245
+ # @param field [MARC::Field]
229
246
  # @return [String] subfield i without parentheses value
230
247
  def remove_paren_value_from_subfield_i(field)
231
248
  val = field.filter_map { |sf|
@@ -243,19 +260,19 @@ module PennMARC
243
260
 
244
261
  # Translate a relator code using mapping
245
262
  # @todo handle case of receiving a URI? E.g., http://loc.gov/relator/aut
246
- # @param [String, NilClass] relator_code
247
- # @param [Hash] mapping
263
+ # @param relator_code [String, NilClass]
264
+ # @param mapping [Hash]
248
265
  # @return [String, NilClass] full relator string
249
266
  def translate_relator(relator_code, mapping)
250
267
  return if relator_code.blank?
251
268
 
252
- mapping[relator_code.to_sym]
269
+ mapping[relator_code&.to_sym]
253
270
  end
254
271
 
255
272
  # Get 650 & 880 for Provenance and Chronology: prefix should be 'PRO' or 'CHR' and may be preceded by a '%'
256
273
  # @note 11/2018: do not display $5 in PRO or CHR subjs
257
- # @param [MARC::Record] record
258
- # @param [String] prefix to select from subject field
274
+ # @param record [MARC::Record]
275
+ # @param prefix [String] to select from subject field
259
276
  # @return [Array] array of values
260
277
  def prefixed_subject_and_alternate(record, prefix)
261
278
  record.fields(%w[650 880]).filter_map { |field|
@@ -273,16 +290,16 @@ module PennMARC
273
290
 
274
291
  # Does the given field specify an allowed source code?
275
292
  #
276
- # @param [MARC::DataField] field
293
+ # @param field [MARC::DataField]
277
294
  # @return [Boolean]
278
295
  def valid_subject_genre_source_code?(field)
279
296
  subfield_value_in?(field, '2', PennMARC::HeadingControl::ALLOWED_SOURCE_CODES)
280
297
  end
281
298
 
282
299
  # Does a field or its linked alternate match any of the specified tags?
283
- # @param [MARC::Field] field
284
- # @param [Array<String>] tags
285
- # @return [TrueClass, FalseClass]
300
+ # @param field [MARC::Field]
301
+ # @param tags [Array<String>]
302
+ # @return [Boolean]
286
303
  def field_or_its_linked_alternate?(field, tags)
287
304
  return true if field.tag.in? tags
288
305
  return true if field.tag == '880' && subfield_value?(field, '6', /^(#{tags.join('|')})/)
@@ -291,7 +308,7 @@ module PennMARC
291
308
  end
292
309
 
293
310
  # Match any open dates ending a given string to determine join separator for relator term in 1xx/7xx fields.
294
- # @param [String] str
311
+ # @param str [String]
295
312
  # @return [String (frozen)]
296
313
  def relator_join_separator(str)
297
314
  /\b\d+-\z/.match?(str) ? ' ' : ', '
@@ -302,7 +319,7 @@ module PennMARC
302
319
  # {https://www.loc.gov/marc/bibliographic/bd111.html 111}, {https://www.loc.gov/marc/bibliographic/bd411.html 411},
303
320
  # {https://www.loc.gov/marc/bibliographic/bd611.html 611}, {https://www.loc.gov/marc/bibliographic/bd711.html 711},
304
321
  # {https://www.loc.gov/marc/bibliographic/bd811.html 811}
305
- # @param [MARC:Field] field
322
+ # @param field [MARC:Field]
306
323
  # @return [String (frozen)]
307
324
  def relator_term_subfield(field)
308
325
  field_or_its_linked_alternate?(field, %w[111 411 611 711 811]) ? 'j' : 'e'
@@ -311,10 +328,10 @@ module PennMARC
311
328
  # Appends a relator value to the given string. It prioritizes relator codes found in subfield $4
312
329
  # and falls back to the specified relator term subfield (defaulting to 'e') if no valid codes are found in $4.
313
330
  # Use with 1xx/7xx fields.
314
- # @param [MARC::Field] field where relator values are stored
315
- # @param [String] joined_subfields the string to which the relator is appended
316
- # @param [String] relator_term_sf MARC subfield that stores relator term
317
- # @param [Hash] relator_map
331
+ # @param field [MARC::Field] where relator values are stored
332
+ # @param joined_subfields [String] the string to which the relator is appended
333
+ # @param relator_term_sf [String] MARC subfield that stores relator term
334
+ # @param relator_map [Hash]
318
335
  # @return [String]
319
336
  def append_relator(field:, joined_subfields:, relator_term_sf:, relator_map: Mappers.relator)
320
337
  joined_subfields = trim_trailing(:comma, joined_subfields)
@@ -329,5 +346,17 @@ module PennMARC
329
346
 
330
347
  [joined_subfields, relator].compact_blank.join(join_separator).squish
331
348
  end
349
+
350
+ # Returns a relator value of the given field. Like append_relator, it prioritizes relator codes found in subfileld
351
+ # $4 and falls back to the specified relator term subfield relator_term_sf if no valid codes are found in $4
352
+ # @param [MARC::Field] field where relator values are stored
353
+ # @param [String] relator_term_sf MARC subfield that stores relator term
354
+ # @param [Hash] relator_map
355
+ # @return [String]
356
+ def relator(field:, relator_term_sf:, relator_map: Mappers.relator)
357
+ relator = subfield_values(field, '4').filter_map { |code| translate_relator(code, relator_map) }
358
+ relator = subfield_values(field, relator_term_sf) if relator.blank?
359
+ relator.join
360
+ end
332
361
  end
333
362
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PennMARC
4
- VERSION = '1.0.24'
4
+ VERSION = '1.0.26'
5
5
  end
data/lib/pennmarc.rb CHANGED
@@ -2,5 +2,12 @@
2
2
 
3
3
  $LOAD_PATH.unshift(__dir__) unless $LOAD_PATH.include?(__dir__)
4
4
 
5
+ module PennMARC
6
+ # Autoload MARC helpers
7
+ module Test
8
+ autoload :MarcHelpers, 'pennmarc/test/marc_helpers'
9
+ end
10
+ end
11
+
5
12
  require_relative 'pennmarc/parser'
6
13
  require 'library_stdnums'
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  describe 'PennMARC::Access' do
4
- include MarcSpecHelpers
5
-
6
4
  let(:helper) { PennMARC::Access }
7
5
 
8
6
  describe '.facet' do
@@ -69,6 +67,17 @@ describe 'PennMARC::Access' do
69
67
  { z: 'Finding aid', u: 'http://hdl.library.upenn.edu/1017/d/pacscl/UPENN_RBML_MsColl200' }
70
68
  end
71
69
 
70
+ it 'does not include online access' do
71
+ expect(helper.facet(record)).to contain_exactly(PennMARC::Access::AT_THE_LIBRARY)
72
+ end
73
+ end
74
+
75
+ context 'with an 856 describing a resource link' do
76
+ let(:indicators) { { indicator1: '4', indicator2: '1' } }
77
+ let(:location_and_access_subfields) do
78
+ { z: 'Connect to resource', u: 'http://hdl.library.upenn.edu/1234' }
79
+ end
80
+
72
81
  it 'includes online access' do
73
82
  expect(helper.facet(record)).to contain_exactly(PennMARC::Access::ONLINE, PennMARC::Access::AT_THE_LIBRARY)
74
83
  end
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  describe 'PennMARC::Citation' do
4
- include MarcSpecHelpers
5
-
6
4
  let(:helper) { PennMARC::Citation }
7
5
 
8
6
  describe '.cited_in_show' do
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  describe 'PennMARC::Classification' do
4
- include MarcSpecHelpers
5
-
6
4
  let(:helper) { PennMARC::Classification }
7
5
  let(:record) do
8
6
  marc_record fields: [marc_field(tag: tag,
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  describe 'PennMARC::Creator' do
4
- include MarcSpecHelpers
5
-
6
4
  let(:helper) { PennMARC::Creator }
7
5
  let(:mapping) { { aut: 'Author' } }
8
6
 
@@ -95,6 +93,91 @@ describe 'PennMARC::Creator' do
95
93
  end
96
94
  end
97
95
 
96
+ describe '.authors_list' do
97
+ let(:record) { marc_record fields: fields }
98
+
99
+ context 'with two author records' do
100
+ let(:fields) do
101
+ [marc_field(tag: '100', subfields: { a: 'Surname, Name', '0': 'http://cool.uri/12345', d: '1900-2000',
102
+ e: 'author.', '4': 'http://cool.uri/vocabulary/relators/aut' }),
103
+ marc_field(tag: '700', subfields: { a: 'Surname, Alternative', '6': '100', d: '1970-' })]
104
+ end
105
+
106
+ it 'returns single author values with no URIs anywhere' do
107
+ values = helper.authors_list(record)
108
+ expect(values).to contain_exactly 'Surname, Name', 'Surname, Alternative'
109
+ end
110
+ end
111
+
112
+ context 'with three author records - abbreviated names' do
113
+ let(:fields) do
114
+ [marc_field(tag: '100', subfields: { a: 'Surname, Alex', '0': 'http://cool.uri/12345', d: '1900-2000',
115
+ e: 'author.', '4': 'http://cool.uri/vocabulary/relators/aut' }),
116
+ marc_field(tag: '110', subfields: { a: 'Second, NameX', '0': 'http://cool.uri/12345', d: '1901-2010',
117
+ e: 'author.', '4': 'http://cool.uri/vocabulary/relators/aut' }),
118
+ marc_field(tag: '700', subfields: { a: 'Alt, Alternative', '6': '100', d: '1970-' })]
119
+ end
120
+
121
+ it 'returns single author values with no URIs anywhere' do
122
+ values = helper.authors_list(record, first_initial_only: true)
123
+ expect(values).to contain_exactly 'Surname, A.', 'Second, N.', 'Alt, A.'
124
+ end
125
+ end
126
+ end
127
+
128
+ describe '.contributors_list' do
129
+ let(:record) { marc_record fields: fields }
130
+
131
+ context 'with two authors and four contributors records, names only' do
132
+ let(:fields) do
133
+ [marc_field(tag: '100', subfields: { a: 'Hamilton, Alex', '0': 'http://cool.uri/12345', d: '1900-2000',
134
+ e: 'author.' }),
135
+ marc_field(tag: '100', subfields: { a: 'Lincoln, Abraham', b: 'I', c: 'laureate', d: '1968', e: 'author',
136
+ j: 'pseud', q: 'Fuller Name', u: 'affiliation', '3': 'materials',
137
+ '4': 'aut' }),
138
+ marc_field(tag: '700', subfields: { a: 'Einstein, Albert', '6': '100', d: '1970-', '4': 'trl',
139
+ e: 'translator' }),
140
+ marc_field(tag: '700', subfields: { a: 'Franklin, Ben', '6': '100', d: '1970-', '4': 'edt' }),
141
+ marc_field(tag: '710', subfields: { a: 'Jefferson, Thomas', '6': '100', d: '1870-', '4': 'edt' }),
142
+ marc_field(tag: '700', subfields: { a: 'Dickens, Charles', '6': '100', d: '1970-', '4': 'com' })]
143
+ end
144
+
145
+ it 'returns two authors and four contributors' do
146
+ values = helper.contributors_list(record)
147
+ expect(values).to contain_exactly ['Author', ['Hamilton, Alex', 'Lincoln, Abraham']],
148
+ ['Compiler', ['Dickens, Charles']],
149
+ ['Editor', ['Franklin, Ben', 'Jefferson, Thomas']],
150
+ ['Translator', ['Einstein, Albert']]
151
+ end
152
+ end
153
+
154
+ context 'with two authors and four contributors records, with full information and relator' do
155
+ let(:fields) do
156
+ [marc_field(tag: '100', subfields: { a: 'Hamilton, Alex', '0': 'http://cool.uri/12345', d: '1900-2000',
157
+ e: 'author.', '4': 'aut' }),
158
+ marc_field(tag: '100', subfields: { a: 'Lincoln, Abraham', b: 'I', c: 'laureate', d: '1968', e: 'author',
159
+ j: 'pseud', q: 'Fuller Name', u: 'affiliation', '3': 'materials',
160
+ '4': 'aut' }),
161
+ marc_field(tag: '700', subfields: { a: 'Einstein, Albert', '6': '100', d: '1970-', '4': 'trl',
162
+ e: 'translator' }),
163
+ marc_field(tag: '700', subfields: { a: 'Franklin, Ben', '6': '100', d: '1970-', '4': 'edt' }),
164
+ marc_field(tag: '710', subfields: { a: 'Jefferson, Thomas', '6': '100', d: '1870-', '4': 'edt' }),
165
+ marc_field(tag: '700', subfields: { a: 'Dickens, Charles', '6': '100', d: '1970-', '4': 'com' }),
166
+ marc_field(tag: '880', subfields: { a: '狄更斯', '6': '700', d: '1970-', '4': 'com' }),
167
+ marc_field(tag: '700', subfields: { a: 'Twain, Mark', '6': '100', d: '1870-' })]
168
+ end
169
+
170
+ it 'returns four contributors' do
171
+ values = helper.contributors_list(record, include_authors: false, name_only: false, vernacular: true)
172
+ expect(values).to contain_exactly ['Compiler', ['Dickens, Charles 1970-, Compiler', '狄更斯 1970-, Compiler']],
173
+ ['Contributor', ['Twain, Mark 1870-, Contributor']],
174
+ ['Editor',
175
+ ['Franklin, Ben 1970-, Editor', 'Jefferson, Thomas 1870-, Editor']],
176
+ ['Translator', ['Einstein, Albert 1970-, Translator']]
177
+ end
178
+ end
179
+ end
180
+
98
181
  describe '.show_facet_map' do
99
182
  let(:record) do
100
183
  marc_record fields: [
@@ -302,6 +385,24 @@ describe 'PennMARC::Creator' do
302
385
  end
303
386
  end
304
387
 
388
+ describe '.corporate_search' do
389
+ let(:record) do
390
+ marc_record fields: [
391
+ marc_field(tag: '110', subfields: { a: 'Penn Libraries', b: 'Digital Library Development' }),
392
+ marc_field(tag: '710', subfields: { a: 'Working Group on Digital Repository Infrastructure' }),
393
+ marc_field(tag: '810', subfields: { a: 'Constellation of Repositories Strategic Team' })
394
+ ]
395
+ end
396
+
397
+ it 'returns expected values' do
398
+ expect(helper.corporate_search(record)).to contain_exactly(
399
+ 'Constellation of Repositories Strategic Team',
400
+ 'Penn Libraries Digital Library Development',
401
+ 'Working Group on Digital Repository Infrastructure'
402
+ )
403
+ end
404
+ end
405
+
305
406
  describe '.contributor_show' do
306
407
  let(:record) { marc_record fields: fields }
307
408
 
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  describe 'PennMARC::Database' do
4
- include MarcSpecHelpers
5
-
6
4
  let(:helper) { PennMARC::Database }
7
5
  let(:record) do
8
6
  marc_record(fields: [
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  describe 'PennMARC::Date' do
4
- include MarcSpecHelpers
5
-
6
4
  let(:helper) { PennMARC::Date }
7
5
  let(:record) { marc_record fields: fields }
8
6
 
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  describe 'PennMARC::Edition' do
4
- include MarcSpecHelpers
5
-
6
4
  let(:helper) { PennMARC::Edition }
7
5
  let(:mapping) { { aut: 'Author' } }
8
6
  let(:record) do
@@ -18,6 +16,10 @@ describe 'PennMARC::Edition' do
18
16
  it 'returns the editions' do
19
17
  expect(helper.show(record)).to contain_exactly('5th Edition Remastered', 'رمستر')
20
18
  end
19
+
20
+ it 'returns the editions without alternate' do
21
+ expect(helper.show(record, with_alternate: false)).to contain_exactly('5th Edition Remastered')
22
+ end
21
23
  end
22
24
 
23
25
  describe '.values' do
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  describe 'PennMARC::Format' do
4
- include MarcSpecHelpers
5
-
6
4
  let(:helper) { PennMARC::Format }
7
5
 
8
6
  describe '.facet' do
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  describe 'PennMARC::Genre' do
4
- include MarcSpecHelpers
5
-
6
4
  let(:helper) { PennMARC::Genre }
7
5
  let(:record) { marc_record fields: fields }
8
6
 
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  describe 'PennMARC::Identifier' do
4
- include MarcSpecHelpers
5
-
6
4
  let(:helper) { PennMARC::Identifier }
7
5
 
8
6
  describe '.mmsid' do
@@ -161,4 +159,18 @@ describe 'PennMARC::Identifier' do
161
159
  '10.1038/sdata.2016.18', '10.18574/9781479842865')
162
160
  end
163
161
  end
162
+
163
+ describe '.host_record_id' do
164
+ let(:record) do
165
+ marc_record fields: [
166
+ marc_field(tag: PennMARC::Enriched::Pub::RELATED_RECORD_TAG, subfields: { w: '123456789', c: 'Contains',
167
+ a: 'Title' }),
168
+ marc_field(tag: PennMARC::Enriched::Pub::RELATED_RECORD_TAG, subfields: { w: '666666666', c: 'Contained In' })
169
+ ]
170
+ end
171
+
172
+ it 'returns only the desired host record MMS ID values' do
173
+ expect(helper.host_record_id(record)).to contain_exactly '123456789'
174
+ end
175
+ end
164
176
  end
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  describe 'PennMARC::Inventory' do
4
- include MarcSpecHelpers
5
-
6
4
  let(:helper) { PennMARC::Inventory }
7
5
  let(:record) do
8
6
  marc_record fields: fields
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  describe 'PennMARC::Language' do
4
- include MarcSpecHelpers
5
-
6
4
  let(:helper) { PennMARC::Language }
7
5
  let(:iso_639_2_mapping) do
8
6
  { eng: 'English', und: 'Undetermined', fre: 'French', ger: 'German', ulw: 'Ulwa' }
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  describe 'PennMARC::Link' do
4
- include MarcSpecHelpers
5
-
6
4
  let(:helper) { PennMARC::Link }
7
5
 
8
6
  describe '.full_text_link' do