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