pennmarc 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +6 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/Gemfile +23 -0
- data/Gemfile.lock +119 -0
- data/README.md +82 -0
- data/legacy/indexer.rb +568 -0
- data/legacy/marc.rb +2964 -0
- data/legacy/test_file_output.json +49 -0
- data/lib/pennmarc/encoding_level.rb +43 -0
- data/lib/pennmarc/enriched_marc.rb +36 -0
- data/lib/pennmarc/heading_control.rb +11 -0
- data/lib/pennmarc/helpers/citation.rb +31 -0
- data/lib/pennmarc/helpers/creator.rb +237 -0
- data/lib/pennmarc/helpers/database.rb +89 -0
- data/lib/pennmarc/helpers/date.rb +85 -0
- data/lib/pennmarc/helpers/edition.rb +90 -0
- data/lib/pennmarc/helpers/format.rb +312 -0
- data/lib/pennmarc/helpers/genre.rb +71 -0
- data/lib/pennmarc/helpers/helper.rb +11 -0
- data/lib/pennmarc/helpers/identifier.rb +134 -0
- data/lib/pennmarc/helpers/language.rb +37 -0
- data/lib/pennmarc/helpers/link.rb +12 -0
- data/lib/pennmarc/helpers/location.rb +97 -0
- data/lib/pennmarc/helpers/note.rb +132 -0
- data/lib/pennmarc/helpers/production.rb +131 -0
- data/lib/pennmarc/helpers/relation.rb +135 -0
- data/lib/pennmarc/helpers/series.rb +118 -0
- data/lib/pennmarc/helpers/subject.rb +304 -0
- data/lib/pennmarc/helpers/title.rb +197 -0
- data/lib/pennmarc/mappings/language.yml +516 -0
- data/lib/pennmarc/mappings/locations.yml +1801 -0
- data/lib/pennmarc/mappings/relator.yml +263 -0
- data/lib/pennmarc/parser.rb +177 -0
- data/lib/pennmarc/util.rb +240 -0
- data/lib/pennmarc.rb +6 -0
- data/pennmarc.gemspec +22 -0
- data/spec/fixtures/marcxml/test.xml +167 -0
- data/spec/lib/pennmarc/helpers/citation_spec.rb +27 -0
- data/spec/lib/pennmarc/helpers/creator_spec.rb +183 -0
- data/spec/lib/pennmarc/helpers/database_spec.rb +60 -0
- data/spec/lib/pennmarc/helpers/date_spec.rb +105 -0
- data/spec/lib/pennmarc/helpers/edition_spec.rb +38 -0
- data/spec/lib/pennmarc/helpers/format_spec.rb +200 -0
- data/spec/lib/pennmarc/helpers/genre_spec.rb +89 -0
- data/spec/lib/pennmarc/helpers/identifer_spec.rb +105 -0
- data/spec/lib/pennmarc/helpers/language_spec.rb +30 -0
- data/spec/lib/pennmarc/helpers/location_spec.rb +70 -0
- data/spec/lib/pennmarc/helpers/note_spec.rb +233 -0
- data/spec/lib/pennmarc/helpers/production_spec.rb +193 -0
- data/spec/lib/pennmarc/helpers/relation_spec.rb +120 -0
- data/spec/lib/pennmarc/helpers/subject_spec.rb +262 -0
- data/spec/lib/pennmarc/helpers/title_spec.rb +169 -0
- data/spec/lib/pennmarc/marc_util_spec.rb +206 -0
- data/spec/lib/pennmarc/parser_spec.rb +13 -0
- data/spec/spec_helper.rb +104 -0
- data/spec/support/marc_spec_helpers.rb +84 -0
- metadata +171 -0
@@ -0,0 +1,262 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe 'PennMARC::Subject' do
|
4
|
+
include MarcSpecHelpers
|
5
|
+
|
6
|
+
let(:helper) { PennMARC::Subject }
|
7
|
+
let(:relator_map) do
|
8
|
+
{ dpc: 'Depicted' }
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '.search' do
|
12
|
+
let(:record) { marc_record fields: fields }
|
13
|
+
let(:values) { helper.search(record, relator_map) }
|
14
|
+
|
15
|
+
context 'with a mix of included and excluded tags' do
|
16
|
+
let(:fields) do
|
17
|
+
[marc_field(tag: '600', indicator2: '5', subfields: { a: 'Excluded Canadian' }),
|
18
|
+
marc_field(tag: '610', indicator2: '0', subfields: { a: 'University of Pennsylvania', b: 'Libraries' }),
|
19
|
+
marc_field(tag: '691', indicator2: '7', subfields: { a: 'Van Pelt Library', '2': 'local' }),
|
20
|
+
marc_field(tag: '696', indicator2: '4', subfields: { a: 'A Developer' }),
|
21
|
+
marc_field(tag: '880', indicator2: '0', subfields: { a: 'Alt. Name', '6': '610' })]
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'includes only values from valid tags' do
|
25
|
+
expect(values).to contain_exactly 'A Developer', 'Alt. Name', 'University of Pennsylvania Libraries',
|
26
|
+
'Van Pelt Library local'
|
27
|
+
expect(values).not_to include 'Excluded Canadian'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'with PRO/CHR values in sf a' do
|
32
|
+
let(:fields) do
|
33
|
+
[marc_field(tag: '650', indicator2: '4', subfields: { a: 'PRO Subject' }),
|
34
|
+
marc_field(tag: '650', indicator2: '4', subfields: { a: '%CHR Heading' })]
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'removes the PRO/CHR designation' do
|
38
|
+
expect(values).to contain_exactly 'Subject', 'Heading'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'with a question mark at the end of sf a' do
|
43
|
+
let(:fields) do
|
44
|
+
[marc_field(tag: '650', indicator2: '4', subfields: { a: 'Potential Subject?' })]
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'removes the question mark' do
|
48
|
+
expect(values).to contain_exactly 'Potential Subject'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'with a relator code specified' do
|
53
|
+
let(:fields) do
|
54
|
+
[marc_field(tag: '650', indicator2: '4', subfields: { a: 'Unicorns', '4': 'dpc' })]
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'includes both the relator code and the mapped value, if found' do
|
58
|
+
expect(values.first).to eq 'Unicorns dpc Depicted'
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe '.facet' do
|
64
|
+
let(:record) { marc_record fields: }
|
65
|
+
let(:values) { helper.facet(record) }
|
66
|
+
|
67
|
+
# TODO: find some more inspiring examples in the corpus
|
68
|
+
context 'for a record with poorly-coded heading values' do
|
69
|
+
let(:fields) { [marc_field(tag: '650', indicator2: '0', subfields: { a: 'Subject - Heading' })] }
|
70
|
+
|
71
|
+
it 'properly normalizes the heading value' do
|
72
|
+
expect(values.first).to eq 'Subject--Heading'
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'for a record with 650 headings with a ǂa that starts with PRO or CHR' do
|
77
|
+
let(:fields) do
|
78
|
+
[marc_field(tag: '650', indicator2: '4', subfields: { a: '%CHR 1998', '5': 'PU' }),
|
79
|
+
marc_field(tag: '650', indicator2: '4', subfields: { a: 'PRO Potok, Adena (donor) (Potok Collection copy)',
|
80
|
+
'5': 'PU' })]
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'does not include the headings' do
|
84
|
+
expect(values).to be_empty
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'for a record with an indicator2 value of 3, 5 or 6' do
|
89
|
+
let(:fields) do
|
90
|
+
[marc_field(tag: '650', indicator2: '3', subfields: { a: 'Nope' }),
|
91
|
+
marc_field(tag: '650', indicator2: '5', subfields: { a: 'Nope' }),
|
92
|
+
marc_field(tag: '650', indicator2: '6', subfields: { a: 'Nope' })]
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'does not include the headings' do
|
96
|
+
expect(values).to be_empty
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'for a record with a valid tag, indicator2 and source specified' do
|
101
|
+
let(:fields) do
|
102
|
+
[marc_field(tag: '650', indicator2: '7',
|
103
|
+
subfields: {
|
104
|
+
a: 'Libraries', x: 'History', e: 'relator', d: '22nd Century',
|
105
|
+
'2': 'fast', '0': 'http://fast.org/libraries'
|
106
|
+
})]
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'properly concatenates heading components' do
|
110
|
+
expect(values.first).to include 'Libraries--History'
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'excludes URI values from ǂ0 or ǂ1' do
|
114
|
+
expect(values.first).not_to include 'http'
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'excludes raw relator term values from ǂe' do
|
118
|
+
expect(values.first).not_to include 'relator'
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'includes active dates from ǂd' do
|
122
|
+
expect(values.first).to include '22nd Century'
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'joins all values in the expected way' do
|
126
|
+
expect(values.first).to eq 'Libraries--History 22nd Century'
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe '.show' do
|
132
|
+
let(:record) { marc_record fields: }
|
133
|
+
let(:values) { helper.facet(record) }
|
134
|
+
|
135
|
+
context 'with a variety of headings' do
|
136
|
+
let(:fields) do
|
137
|
+
[marc_field(tag: '650', indicator2: '0', subfields: { a: 'Nephrology', v: 'Periodicals' }),
|
138
|
+
marc_field(tag: '650', indicator2: '7',
|
139
|
+
subfields: { a: 'Nephrology', '2': 'fast', '0': '(OCoLC)fst01035991' }),
|
140
|
+
marc_field(tag: '650', indicator2: '7', subfields: { a: 'Undesirable Heading', '2': 'exclude' }),
|
141
|
+
marc_field(tag: '650', indicator2: '2', subfields: { a: 'Nephrology' }),
|
142
|
+
marc_field(tag: '650', indicator2: '1', subfields: { a: 'Kidney Diseases' }),
|
143
|
+
marc_field(tag: '690', subfields: { a: 'Local Heading' }),
|
144
|
+
marc_field(tag: '690', subfields: { a: 'Local Heading' })]
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'shows all valid subject headings without duplicates' do
|
148
|
+
expect(helper.show(record)).to match_array ['Nephrology--Periodicals', 'Nephrology',
|
149
|
+
'Kidney Diseases', 'Local Heading']
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
context 'with a robust 650 heading including many subfields' do
|
154
|
+
let(:fields) do
|
155
|
+
[marc_field(tag: '650', indicator2: '0', subfields: {
|
156
|
+
a: 'Subways',
|
157
|
+
z: ['Pennsylvania', 'Philadelphia Metropolitan Area'],
|
158
|
+
v: 'Maps',
|
159
|
+
y: '1989',
|
160
|
+
e: 'relator'
|
161
|
+
})]
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'properly formats the heading parts' do
|
165
|
+
expect(values.first).to eq 'Subways--Pennsylvania--Philadelphia Metropolitan Area--Maps--1989'
|
166
|
+
expect(values.first).not_to include 'relator'
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
context 'with a robust 651 heading including many subfields' do
|
171
|
+
let(:fields) do
|
172
|
+
[marc_field(tag: '651', indicator2: '4', subfields: {
|
173
|
+
a: 'Chicago (Ill.)',
|
174
|
+
x: 'Moral conditions',
|
175
|
+
'3': 'Church minutes',
|
176
|
+
y: '1875-1878',
|
177
|
+
'0': 'http://some.uri/zzz'
|
178
|
+
})]
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'properly formats the heading parts' do
|
182
|
+
expect(values.first).to eq 'Chicago (Ill.)--Moral conditions--Church minutes--1875-1878'
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
context 'with a robust 611 heading including many subfields' do
|
187
|
+
let(:fields) do
|
188
|
+
[marc_field(tag: '611', indicator2: '0', subfields: {
|
189
|
+
a: 'Conference',
|
190
|
+
d: '(2002',
|
191
|
+
n: '2nd',
|
192
|
+
c: ['Johannesburg, South Africa', 'Cape Town, South Africa)']
|
193
|
+
})]
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'properly formats the heading parts' do
|
197
|
+
expect(values.first).to eq 'Conference--2nd (2002 Johannesburg, South Africa Cape Town, South Africa)'
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
context 'with a robust 600 heading including many subfields' do
|
202
|
+
let(:fields) do
|
203
|
+
[marc_field(tag: '600', indicator2: '0', subfields: {
|
204
|
+
a: 'Person, Significant Author',
|
205
|
+
d: '1899-1971',
|
206
|
+
v: 'Early works to 1950',
|
207
|
+
t: 'Collection'
|
208
|
+
})]
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'properly formats the heading parts' do
|
212
|
+
expect(values.first).to eq 'Person, Significant Author--Early works to 1950 1899-1971 Collection'
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
describe '.childrens_show' do
|
218
|
+
let(:record) do
|
219
|
+
marc_record(fields: [
|
220
|
+
marc_field(tag: '650', indicator2: '1', subfields: { a: 'Frogs', v: 'Fiction' }),
|
221
|
+
marc_field(tag: '650', indicator2: '1', subfields: { a: 'Toads', v: 'Fiction' }),
|
222
|
+
marc_field(tag: '650', indicator2: '2', subfields: { a: 'Herpetology' })
|
223
|
+
])
|
224
|
+
end
|
225
|
+
let(:values) { helper.childrens_show(record) }
|
226
|
+
|
227
|
+
it 'includes heading terms only from subject tags with an indicator 2 of "1"' do
|
228
|
+
expect(values).to contain_exactly 'Frogs--Fiction', 'Toads--Fiction'
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
describe '.medical_show' do
|
233
|
+
let(:record) do
|
234
|
+
marc_record(
|
235
|
+
fields: [
|
236
|
+
marc_field(tag: '650', indicator2: '0', subfields: { a: 'Nephhrology', v: 'Periodicals' }),
|
237
|
+
marc_field(tag: '650', indicator2: '7',
|
238
|
+
subfields: { a: 'Nephhrology', '2': 'fast', '0': '(OCoLC)fst01035991' }),
|
239
|
+
marc_field(tag: '650', indicator2: '2', subfields: { a: 'Nephrology' }),
|
240
|
+
marc_field(tag: '650', indicator2: '1', subfields: { a: 'Kidney Diseases' })
|
241
|
+
]
|
242
|
+
)
|
243
|
+
end
|
244
|
+
|
245
|
+
it 'includes heading terms only from subject tags with indicator 2 of "2"' do
|
246
|
+
expect(helper.medical_show(record)).to contain_exactly 'Nephrology'
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
describe '.local_show' do
|
251
|
+
let(:record) do
|
252
|
+
marc_record(fields: [
|
253
|
+
marc_field(tag: '650', indicator2: '4', subfields: { a: 'Local', v: 'Heading' }),
|
254
|
+
marc_field(tag: '690', indicator2: '4', subfields: { a: 'Super Local.' })
|
255
|
+
])
|
256
|
+
end
|
257
|
+
|
258
|
+
it 'includes heading terms only from subject tags with indicator 2 of "4" or in the 69X range' do
|
259
|
+
expect(helper.local_show(record)).to contain_exactly 'Local--Heading', 'Super Local.'
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe 'PennMARC::Title' do
|
4
|
+
include MarcSpecHelpers
|
5
|
+
|
6
|
+
let(:helper) { PennMARC::Title }
|
7
|
+
|
8
|
+
describe '.search' do
|
9
|
+
let(:record) do
|
10
|
+
marc_record fields: [
|
11
|
+
marc_field(tag: '245', subfields: { a: 'Title', b: 'Subtitle', c: 'Responsibility', h: 'Medium' }),
|
12
|
+
marc_field(tag: '880', subfields: { a: 'Linked Title', '6': '245' })
|
13
|
+
]
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'returns search values without ǂc or ǂh content' do
|
17
|
+
values = helper.search(record)
|
18
|
+
expect(values).to contain_exactly 'Linked Title', 'Title Subtitle'
|
19
|
+
expect(values).not_to include 'Responsibility', 'Medium'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
xdescribe '.search_aux'
|
24
|
+
|
25
|
+
describe '.show' do
|
26
|
+
let(:record) { marc_record fields: [marc_field(tag: '245', subfields: subfields)] }
|
27
|
+
|
28
|
+
context 'with ǂa, ǂk and ǂn defined' do
|
29
|
+
let(:subfields) { { a: 'Five Decades of MARC usage', k: 'journals', n: 'Part One' } }
|
30
|
+
|
31
|
+
it 'returns single title value with text from ǂa and ǂn but not ǂk' do
|
32
|
+
expect(helper.show(record)).to eq 'Five Decades of MARC usage Part One'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'with no ǂa but a ǂk and ǂn defined' do
|
37
|
+
let(:subfields) { { k: 'journals', n: 'Part One' } }
|
38
|
+
|
39
|
+
it 'returns single title value with text from ǂk and ǂn' do
|
40
|
+
expect(helper.show(record)).to eq 'journals Part One'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'with ǂa containing an " = "' do
|
45
|
+
let(:subfields) { { a: 'There is a parallel statement = ', b: 'Parallel statement / ' } }
|
46
|
+
|
47
|
+
it 'returns single title value with text from ǂa and ǂb joined with an " = " and other trailing punctuation
|
48
|
+
removed' do
|
49
|
+
expect(helper.show(record)).to eq 'There is a parallel statement = Parallel statement'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'with ǂa containing an " : "' do
|
54
|
+
let(:subfields) { { a: 'There is an other statement : ', b: 'Other statement' } }
|
55
|
+
|
56
|
+
it 'returns single title value with text from ǂa and ǂn' do
|
57
|
+
expect(helper.show(record)).to eq 'There is an other statement : Other statement'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '.sort' do
|
63
|
+
context 'with a record with a valid indicator2 value' do
|
64
|
+
let(:record) do
|
65
|
+
marc_record fields: [
|
66
|
+
marc_field(tag: '245', indicator2: '4', subfields: {
|
67
|
+
a: 'The Record Title',
|
68
|
+
b: 'Remainder', n: 'Number', p: 'Section',
|
69
|
+
h: 'Do not display'
|
70
|
+
})
|
71
|
+
]
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'properly removes and appends the number of characters specified in indicator 2' do
|
75
|
+
value = helper.sort(record)
|
76
|
+
expect(value).to start_with 'Record Title'
|
77
|
+
expect(value).to end_with 'The'
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'includes ǂb, ǂn and ǂp values' do
|
81
|
+
expect(helper.sort(record)).to eq 'Record Title Remainder Number Section The'
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'with a record with no indicator2 value' do
|
86
|
+
let(:record) do
|
87
|
+
marc_record fields: [marc_field(tag: '245', subfields: { a: 'The Record Title' })]
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'does not transform the title value' do
|
91
|
+
expect(helper.sort(record)).to eq 'The Record Title'
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'with a record with no ǂa and no indicator2 value' do
|
96
|
+
let(:record) do
|
97
|
+
marc_record fields: [marc_field(tag: '245', subfields: { k: 'diaries' })]
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'uses ǂk (form) value without transformation' do
|
101
|
+
expect(helper.sort(record)).to eq 'diaries'
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
context 'with a record with a leading bracket' do
|
106
|
+
let(:record) do
|
107
|
+
marc_record fields: [marc_field(tag: '245', subfields: { a: '[The Record Title]' })]
|
108
|
+
end
|
109
|
+
|
110
|
+
# TODO: is this the expected behavior? It would sort right, but looks silly.
|
111
|
+
it 'removes the leading bracket and appends it to the full value' do
|
112
|
+
expect(helper.sort(record)).to eq 'The Record Title] ['
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe '.standardized' do
|
118
|
+
let(:record) do
|
119
|
+
marc_record fields: [
|
120
|
+
marc_field(tag: '130', subfields: { a: 'Uniform Title', f: '2000', '8': 'Not Included' }),
|
121
|
+
marc_field(tag: '240', subfields: { a: 'Another Uniform Title', '0': 'Ugly Control Number' }),
|
122
|
+
marc_field(tag: '730', indicator2: '', subfields: { a: 'Yet Another Uniform Title' }),
|
123
|
+
marc_field(tag: '730', indicator1: '0', indicator2: '2', subfields: { a: 'Not Printed Title' }),
|
124
|
+
marc_field(tag: '730', indicator1: '', subfields: { i: 'Subfield i Title' }),
|
125
|
+
marc_field(tag: '880', subfields: { '6': '240', a: 'Translated Uniform Title' })
|
126
|
+
]
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'returns the expected standardized title display values' do
|
130
|
+
values = helper.standardized(record)
|
131
|
+
expect(values).to contain_exactly(
|
132
|
+
'Another Uniform Title', 'Translated Uniform Title', 'Uniform Title 2000', 'Yet Another Uniform Title'
|
133
|
+
)
|
134
|
+
expect(values).not_to include 'Not Printed Title', 'Subfield i Title'
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe '.other' do
|
139
|
+
let(:record) do
|
140
|
+
marc_record fields: [
|
141
|
+
marc_field(tag: '246', subfields: { a: 'Varied Title', f: '2000', '8': 'Not Included' }),
|
142
|
+
marc_field(tag: '740', indicator2: '0', subfields: { a: 'Uncontrolled Title', '5': 'Penn' }),
|
143
|
+
marc_field(tag: '740', indicator2: '2', subfields: { a: 'A Title We Do Not Like' }),
|
144
|
+
marc_field(tag: '880', subfields: { '6': '246', a: 'Alternate Varied Title' })
|
145
|
+
]
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'returns the expected other title display values' do
|
149
|
+
expect(helper.other(record)).to contain_exactly(
|
150
|
+
'Alternate Varied Title', 'Uncontrolled Title', 'Varied Title 2000'
|
151
|
+
)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe '.former' do
|
156
|
+
let(:record) do
|
157
|
+
marc_record fields: [
|
158
|
+
marc_field(tag: '247', subfields: { a: 'Former Title', n: 'Part', '6': 'Linkage', e: 'Append' }),
|
159
|
+
marc_field(tag: '880', subfields: { a: 'Alt Title', n: 'Part', '6': '247' })
|
160
|
+
]
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'returns the expected former title value' do
|
164
|
+
values = helper.former(record)
|
165
|
+
expect(values).to contain_exactly 'Former Title Part Append', 'Alt Title Part'
|
166
|
+
expect(values).not_to include 'Linkage', '247'
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,206 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe 'PennMARC::Util' do
|
4
|
+
include MarcSpecHelpers
|
5
|
+
|
6
|
+
subject(:util) do
|
7
|
+
Class.new { extend PennMARC::Util }
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '.join_subfields' do
|
11
|
+
let(:field) { marc_field subfields: { a: 'bad', '1': 'join', '3': '', '9': 'subfields' } }
|
12
|
+
|
13
|
+
it 'joins subfield values after selecting values using a block' do
|
14
|
+
subfield_numeric = ->(subfield) { subfield.code =~ /[0-9]/ }
|
15
|
+
expect(util.join_subfields(field, &subfield_numeric)).to eq 'join subfields'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '.subfield_value?' do
|
20
|
+
let(:field) { marc_field subfields: { a: '123' } }
|
21
|
+
|
22
|
+
it 'returns true if the specified subfield value matches the regex' do
|
23
|
+
expect(util.subfield_value?(field, 'a', /123/)).to be_truthy
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'returns false if the subfield value does not match the regex' do
|
27
|
+
expect(util.subfield_value?(field, 'a', /\D/)).to be_falsey
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '.subfield_value_in?' do
|
32
|
+
let(:field) { marc_field subfields: { a: '123' } }
|
33
|
+
|
34
|
+
it 'returns true if value is in array' do
|
35
|
+
expect(util.subfield_value_in?(field, 'a', ['123'])).to be true
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '.subfield_in?' do
|
40
|
+
it 'returns a lambda that checks if a subfield code is a member of the array' do
|
41
|
+
array = %w[a b c]
|
42
|
+
subfield_in = util.subfield_in?(array)
|
43
|
+
|
44
|
+
subfield = marc_subfield('a', 'Value')
|
45
|
+
expect(subfield_in.call(subfield)).to be_truthy
|
46
|
+
|
47
|
+
subfield = marc_subfield('d', 'Value')
|
48
|
+
expect(subfield_in.call(subfield)).to be_falsey
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#subfield_not_in?' do
|
53
|
+
it 'returns a lambda that checks if a subfield code is not a member of the array' do
|
54
|
+
array = %w[a b c]
|
55
|
+
subfield_not_in = util.subfield_not_in?(array)
|
56
|
+
|
57
|
+
subfield = marc_subfield('a', 'Value')
|
58
|
+
expect(subfield_not_in.call(subfield)).to be_falsey
|
59
|
+
|
60
|
+
subfield = marc_subfield('d', 'Value')
|
61
|
+
expect(subfield_not_in.call(subfield)).to be_truthy
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe '.subfield_defined?' do
|
66
|
+
let(:field) { marc_field subfields: { a: 'Defined' } }
|
67
|
+
|
68
|
+
it 'returns true if subfield is present on a field' do
|
69
|
+
expect(util.subfield_defined?(field, :a)).to be_truthy
|
70
|
+
expect(util.subfield_defined?(field, 'a')).to be_truthy
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'returns false if a subfield is not present on a field' do
|
74
|
+
expect(util.subfield_defined?(field, :b)).to be_falsey
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe '.subfield_undefined?' do
|
79
|
+
let(:field) { marc_field subfields: { a: 'Defined' } }
|
80
|
+
|
81
|
+
it 'returns true if subfield is not present on a field' do
|
82
|
+
expect(util.subfield_undefined?(field, :b)).to be_truthy
|
83
|
+
expect(util.subfield_undefined?(field, 'b')).to be_truthy
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'returns false if a subfield is present on a field' do
|
87
|
+
expect(util.subfield_undefined?(field, :a)).to be_falsey
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe '.subfield_values' do
|
92
|
+
let(:field) { marc_field subfields: { a: %w[A B C], b: 'Not Included' } }
|
93
|
+
|
94
|
+
it 'returns subfield values from a given field' do
|
95
|
+
expect(util.subfield_values(field, :a)).to eq %w[A B C]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe '.subfield_values_for' do
|
100
|
+
let(:record) do
|
101
|
+
marc_record fields: [marc_field(tag: '123', subfields: { a: %w[A B C], b: 'Not Included' }),
|
102
|
+
marc_field(tag: '123', subfields: { a: 'D' }),
|
103
|
+
marc_field(tag: '333', subfields: { a: 'Maybe', b: 'Nope' })]
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'returns subfield values from only the specified tag and subfield' do
|
107
|
+
expect(util.subfield_values_for(tag: '123', subfield: :a, record: record)).to eq %w[A B C D]
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'returns subfield values from only the specified tags and subfield' do
|
111
|
+
expect(util.subfield_values_for(tag: %w[123 333], subfield: :a, record: record)).to eq %w[A B C D Maybe]
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe '.trim_trailing' do
|
116
|
+
it 'trims the specified trailer from the string' do
|
117
|
+
expect(util.trim_trailing(:semicolon, 'Hello, world! ;')).to eq('Hello, world!')
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe '.linked_alternate' do
|
122
|
+
let(:record) do
|
123
|
+
marc_record fields: [marc_field(tag: '254', subfields: { a: 'The Bible', b: 'Test' }),
|
124
|
+
marc_field(tag: '880', subfields: { '6': '254', a: 'La Biblia', b: 'Prueba' })]
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'returns the linked alternate' do
|
128
|
+
expect(util.linked_alternate(record, '254', &util.subfield_in?(%w[a b]))).to contain_exactly('La Biblia Prueba')
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe '.linked_alternate_not_6_or_8' do
|
133
|
+
let(:record) do
|
134
|
+
marc_record fields: [marc_field(tag: '510', subfields: { a: 'Perkins', b: 'Test' }),
|
135
|
+
marc_field(tag: '880', subfields: { '6': '510', '8': 'Ignore', a: 'Snikrep', b: 'Tset' })]
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'returns the linked alternate without 6 or 8' do
|
139
|
+
expect(util.linked_alternate_not_6_or_8(record, '510')).to contain_exactly('Snikrep Tset')
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe '.datafield_and_linked_alternate' do
|
144
|
+
let(:record) do
|
145
|
+
marc_record fields: [marc_field(tag: '510', subfields: { a: 'Perkins' }),
|
146
|
+
marc_field(tag: '880', subfields: { '6': '510', a: 'Snikrep' })]
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'returns the datafield and linked alternate' do
|
150
|
+
expect(util.datafield_and_linked_alternate(record, '510')).to contain_exactly('Perkins', 'Snikrep')
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe '.substring_before' do
|
155
|
+
it 'returns the entire substring after the first occurrence of the target' do
|
156
|
+
string = 'string.with.periods'
|
157
|
+
expect(util.substring_before(string, '.')).to eq 'string'
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
describe '.substring_after' do
|
162
|
+
it 'returns the entire substring after the first occurrence of the target' do
|
163
|
+
string = 'string.with.periods'
|
164
|
+
expect(util.substring_after(string, '.')).to eq 'with.periods'
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
describe '.join_and_squish' do
|
169
|
+
it 'joins and squishes' do
|
170
|
+
expect(util.join_and_squish(['ruby ', ' is', ' cool '])).to eq 'ruby is cool'
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
describe '.remove_paren_value_from_subfield_i' do
|
175
|
+
let(:field) { marc_field(tag: '666', subfields: { i: 'Test(Remove).' }) }
|
176
|
+
it 'removes the parentheses value from subfield i' do
|
177
|
+
expect(util.remove_paren_value_from_subfield_i(field)).to eq('Test')
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe '.translate_relator' do
|
182
|
+
let(:mapping) { { aut: 'Author' } }
|
183
|
+
|
184
|
+
it 'translates the code into the relator' do
|
185
|
+
expect(util.translate_relator(:aut, mapping)).to eq('Author')
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
describe '.prefixed_subject_and_alternate' do
|
190
|
+
let(:record) do
|
191
|
+
marc_record fields: [
|
192
|
+
marc_field(tag: '650', indicator2: '4', subfields: { a: 'PRO Heading' }),
|
193
|
+
marc_field(tag: '650', indicator2: '4', subfields: { a: 'Regular Local Heading' }),
|
194
|
+
marc_field(tag: '650', indicator2: '1', subfields: { a: 'LoC Heading' }),
|
195
|
+
marc_field(tag: '880', indicator2: '4', subfields: { '6': '650', a: 'PRO Alt. Heading' }),
|
196
|
+
marc_field(tag: '880', indicator2: '4', subfields: { '6': '999', a: 'Another Alt.' })
|
197
|
+
]
|
198
|
+
end
|
199
|
+
|
200
|
+
it 'only includes valid headings' do
|
201
|
+
values = util.prefixed_subject_and_alternate(record, 'PRO')
|
202
|
+
expect(values).to include 'Heading', 'Alt. Heading'
|
203
|
+
expect(values).not_to include 'Regular Local Heading', 'LoC Heading', 'Another Alt.'
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe PennMARC::Parser do
|
4
|
+
include MarcSpecHelpers
|
5
|
+
|
6
|
+
let(:record) { record_from 'test.xml' }
|
7
|
+
|
8
|
+
subject(:parser) { described_class.new }
|
9
|
+
|
10
|
+
it 'delegates to helper modules properly' do
|
11
|
+
expect { parser.title_show(record) }.not_to raise_exception
|
12
|
+
end
|
13
|
+
end
|