mods 2.4.1 → 3.0.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +24 -0
  3. data/.gitignore +1 -0
  4. data/README.md +0 -1
  5. data/lib/mods/marc_country_codes.rb +12 -10
  6. data/lib/mods/nom_terminology.rb +108 -844
  7. data/lib/mods/reader.rb +9 -39
  8. data/lib/mods/record.rb +13 -28
  9. data/lib/mods/version.rb +1 -1
  10. data/mods.gemspec +2 -2
  11. data/spec/fixture_data/hp566jq8781.xml +334 -0
  12. data/spec/integration/parker_spec.rb +217 -0
  13. data/spec/{date_spec.rb → lib/date_spec.rb} +0 -0
  14. data/spec/lib/language_spec.rb +123 -0
  15. data/spec/lib/location_spec.rb +175 -0
  16. data/spec/lib/name_spec.rb +366 -0
  17. data/spec/lib/origin_info_spec.rb +134 -0
  18. data/spec/lib/part_spec.rb +162 -0
  19. data/spec/lib/physical_description_spec.rb +72 -0
  20. data/spec/{reader_spec.rb → lib/reader_spec.rb} +1 -41
  21. data/spec/lib/record_info_spec.rb +114 -0
  22. data/spec/lib/record_spec.rb +287 -0
  23. data/spec/lib/related_item_spec.rb +124 -0
  24. data/spec/lib/subject_spec.rb +427 -0
  25. data/spec/lib/title_spec.rb +108 -0
  26. data/spec/lib/top_level_elmnts_simple_spec.rb +169 -0
  27. data/spec/spec_helper.rb +86 -5
  28. data/spec/support/fixtures.rb +9 -0
  29. metadata +51 -46
  30. data/.travis.yml +0 -16
  31. data/spec/language_spec.rb +0 -118
  32. data/spec/location_spec.rb +0 -295
  33. data/spec/name_spec.rb +0 -759
  34. data/spec/origin_info_spec.rb +0 -447
  35. data/spec/part_spec.rb +0 -471
  36. data/spec/physical_description_spec.rb +0 -144
  37. data/spec/record_info_spec.rb +0 -493
  38. data/spec/record_spec.rb +0 -356
  39. data/spec/related_item_spec.rb +0 -305
  40. data/spec/subject_spec.rb +0 -809
  41. data/spec/title_spec.rb +0 -226
  42. data/spec/top_level_elmnts_simple_spec.rb +0 -369
@@ -0,0 +1,366 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe "Mods <name> Element" do
4
+ context 'with a record with a provided language' do
5
+ subject(:record) do
6
+ mods_record(<<-XML)
7
+ <name type='personal'><namePart xml:lang='fr-FR' type='given'>Jean</namePart><namePart xml:lang='en-US' type='given'>John</namePart></name>
8
+ XML
9
+ end
10
+
11
+ it "has the expected attributes" do
12
+ expect(record.personal_name.namePart).to match_array([
13
+ have_attributes(text: 'Jean', lang: 'fr-FR', type_at: 'given'),
14
+ have_attributes(text: 'John', lang: 'en-US', type_at: 'given'),
15
+ ])
16
+ end
17
+ end
18
+
19
+ context 'with a recod without a role' do
20
+ subject(:record) do
21
+ mods_record(<<-XML)
22
+ <name type='personal'><namePart>Crusty</namePart></name>
23
+ XML
24
+ end
25
+
26
+ it 'does not have a role' do
27
+ expect(record.personal_name.role).to be_empty
28
+ expect(record.personal_name.role.code).to be_empty
29
+ expect(record.personal_name.role.authority).to be_empty
30
+ end
31
+ end
32
+
33
+ context 'with a record with a text role' do
34
+ subject(:record) do
35
+ mods_record(<<-XML)
36
+ <name type='personal'><namePart>Crusty</namePart>
37
+ <role><roleTerm authority='marcrelator' type='text'>creator</roleTerm><role></name>
38
+ XML
39
+ end
40
+
41
+ it 'has the expected attributes' do
42
+ expect(record.plain_name.first).to have_attributes(
43
+ type_at: 'personal',
44
+ namePart: match_array([
45
+ have_attributes(text: 'Crusty')
46
+ ]),
47
+ role: have_attributes(
48
+ roleTerm: have_attributes(
49
+ text: 'creator',
50
+ type_at: ['text'],
51
+ authority: ['marcrelator']
52
+ ),
53
+ authority: ['marcrelator'],
54
+ code: [],
55
+ value: ['creator']
56
+ )
57
+ )
58
+ end
59
+ end
60
+
61
+ context 'with a record with a code role' do
62
+ subject(:record) do
63
+ mods_record(<<-XML)
64
+ <name type='personal'>
65
+ <namePart type='given'>John</namePart>
66
+ <namePart type='family'>Huston</namePart>
67
+ <role>
68
+ <roleTerm type='code' authority='marcrelator'>drt</roleTerm>
69
+ </role>
70
+ </name>
71
+ XML
72
+ end
73
+
74
+ it 'has the expected attributes' do
75
+ expect(record.plain_name.first).to have_attributes(
76
+ type_at: 'personal',
77
+ display_value: 'Huston, John',
78
+ namePart: match_array([
79
+ have_attributes(text: 'John', type_at: 'given'),
80
+ have_attributes(text: 'Huston', type_at: 'family'),
81
+ ]),
82
+ role: have_attributes(
83
+ roleTerm: have_attributes(
84
+ text: 'drt',
85
+ type_at: ['code'],
86
+ authority: ['marcrelator'],
87
+ value: ['Director']
88
+ ),
89
+ authority: ['marcrelator'],
90
+ code: ['drt'],
91
+ value: ['Director']
92
+ )
93
+ )
94
+ end
95
+ end
96
+
97
+ context 'with an alternate name' do
98
+ subject(:record) do
99
+ mods_record(<<-XML)
100
+ <name>
101
+ <namePart>Claudia Alta Johnson</namePart>
102
+ <alternativeName altType="nickname">
103
+ <namePart>Lady Bird Johnson</namePart>
104
+ </alternativeName>
105
+ </name>
106
+ XML
107
+ end
108
+
109
+ it 'has the expected attributes' do
110
+ expect(record.plain_name.first).to have_attributes(
111
+ namePart: have_attributes(text: 'Claudia Alta Johnson'),
112
+ alternative_name: match_array([
113
+ have_attributes(
114
+ altType: 'nickname',
115
+ namePart: have_attributes(text: 'Lady Bird Johnson')
116
+ )
117
+ ])
118
+ )
119
+ end
120
+ end
121
+
122
+ context 'with both a personal and corporate name' do
123
+ subject(:record) do
124
+ mods_record(<<-XML)
125
+ <name type='corporate'><namePart>ABC Corp</namePart></name>
126
+ <name type='personal'><namePart>Crusty</namePart></name>
127
+ XML
128
+ end
129
+
130
+ describe '#personal_name' do
131
+ it 'selects the name with the type "personal"' do
132
+ expect(record.personal_name).to match_array([
133
+ have_attributes(text: 'Crusty')
134
+ ])
135
+ end
136
+ end
137
+
138
+ describe '#corporate_name' do
139
+ it 'selects the name with the type "corporate"' do
140
+ expect(record.corporate_name).to match_array([
141
+ have_attributes(text: 'ABC Corp')
142
+ ])
143
+ end
144
+ end
145
+ end
146
+
147
+ context 'with a role with both text and a code' do
148
+ subject(:record) do
149
+ mods_record <<-XML
150
+ <name><namePart>anyone</namePart>
151
+ <role>
152
+ <roleTerm type='text' authority='marcrelator'>CreatorFake</roleTerm>
153
+ <roleTerm type='code' authority='marcrelator'>cre</roleTerm>
154
+ </role>
155
+ </name>
156
+ XML
157
+ end
158
+
159
+ it 'prefers the value of the text term' do
160
+ expect(record.plain_name.role.value).to eq ['CreatorFake']
161
+ end
162
+
163
+ it 'can return the code' do
164
+ expect(record.plain_name.role.code).to eq ['cre']
165
+ end
166
+ end
167
+
168
+ context 'with multiple roles' do
169
+ subject(:record) do
170
+ mods_record <<-XML
171
+ <name><namePart>Fats Waller</namePart>
172
+ <role>
173
+ <roleTerm type='text' authority='marcrelator'>CreatorFake</roleTerm>
174
+ <roleTerm type='code' authority='marcrelator'>cre</roleTerm>
175
+ </role>
176
+ <role>
177
+ <roleTerm type='text'>Performer</roleTerm>
178
+ </role>
179
+ </name>
180
+ XML
181
+ end
182
+
183
+ it 'returns both values' do
184
+ expect(record.plain_name.role.value).to eq ['CreatorFake', 'Performer']
185
+ end
186
+
187
+ it 'can return the code' do
188
+ expect(record.plain_name.role.code).to eq ['cre']
189
+ end
190
+ end
191
+
192
+ context 'with additional name metadata' do
193
+ subject(:record) do
194
+ mods_record <<-XML
195
+ <name>
196
+ <namePart>Exciting Prints</namePart>
197
+ <affiliation>whatever</affiliation>
198
+ <description>anything</description>
199
+ <role><roleTerm type='text'>some role</roleTerm></role>
200
+ </name>
201
+ XML
202
+ end
203
+
204
+ describe '#display_value' do
205
+ it 'has the expected value' do
206
+ expect(record.plain_name.first.display_value).to eq 'Exciting Prints'
207
+ end
208
+ end
209
+ end
210
+
211
+ context 'with an empty name' do
212
+ subject(:record) do
213
+ mods_record <<-XML
214
+ <name>
215
+ <namePart></namePart>
216
+ </name>
217
+ XML
218
+ end
219
+
220
+ describe '#display_value' do
221
+ it 'is blank' do
222
+ expect(record.plain_name.first.display_value).to be_nil
223
+ end
224
+ end
225
+ end
226
+
227
+ context 'with a displayForm' do
228
+ subject(:record) do
229
+ mods_record <<-XML
230
+ <name type='personal'>
231
+ <namePart>Alterman, Eric</namePart>
232
+ <displayForm>Eric Alterman</displayForm>
233
+ </name>
234
+ XML
235
+ end
236
+
237
+ describe '#display_value' do
238
+ it 'is the displayForm' do
239
+ expect(record.plain_name.first.display_value).to eq 'Eric Alterman'
240
+ end
241
+ end
242
+ end
243
+
244
+ context 'with a record with a displayForm that includes some dates' do
245
+ subject(:record) do
246
+ mods_record <<-XML
247
+ <name>
248
+ <namePart>Woolf, Virginia</namePart>
249
+ <namePart type='date'>1882-1941</namePart>
250
+ <displayForm>Woolf, Virginia, 1882-1941</namePart>
251
+ </name>
252
+ XML
253
+ end
254
+
255
+ describe '#display_value_w_dates' do
256
+ it 'does not duplicate the dates' do
257
+ expect(record.plain_name.first.display_value).to eq 'Woolf, Virginia, 1882-1941'
258
+ expect(record.plain_name.first.display_value_w_date).to eq 'Woolf, Virginia, 1882-1941'
259
+ end
260
+ end
261
+ end
262
+
263
+ context 'with a record with a namePart for dates' do
264
+ subject(:record) do
265
+ mods_record(<<-XML)
266
+ <name>
267
+ <namePart>Suzy</namePart>
268
+ <namePart type='date'>1920-</namePart>
269
+ </name>
270
+ XML
271
+ end
272
+
273
+ it 'has the expected attributes' do
274
+ expect(record.plain_name.first).to have_attributes(
275
+ display_value: 'Suzy',
276
+ display_value_w_date: 'Suzy, 1920-'
277
+ )
278
+ end
279
+ end
280
+
281
+ context 'without a family name and given name' do
282
+ subject(:record) do
283
+ mods_record("<name type='personal'>
284
+ <namePart type='given'>John Paul</namePart>
285
+ <namePart type='termsOfAddress'>II</namePart>
286
+ <namePart type='termsOfAddress'>Pope</namePart>
287
+ <namePart type='date'>1920-2005</namePart>
288
+ </name>")
289
+ end
290
+
291
+ describe '#display_value' do
292
+ it 'just concatenates the name parts' do
293
+ expect(record.personal_name.first.display_value).to eq 'John Paul II, Pope'
294
+ end
295
+ end
296
+
297
+ describe '#display_value_w_date' do
298
+ it 'includes the dates' do
299
+ expect(record.personal_name.first.display_value_w_date).to eq 'John Paul II, Pope, 1920-2005'
300
+ end
301
+ end
302
+ end
303
+
304
+ context 'with a bunch of untyped name parts' do
305
+ subject(:record) do
306
+ mods_record("<name type='personal'>
307
+ <namePart>Crusty</namePart>
308
+ <namePart>The Clown</namePart>
309
+ <namePart type='date'>1920-2005</namePart>
310
+ </name>")
311
+ end
312
+
313
+ describe '#display_value' do
314
+ it 'concatenates the untyped name parts' do
315
+ expect(record.personal_name.first.display_value).to eq('Crusty The Clown')
316
+ end
317
+ end
318
+ end
319
+
320
+ context 'with a corporate name' do
321
+ subject(:record) do
322
+ mods_record("<name type='corporate'>
323
+ <namePart>United States</namePart>
324
+ <namePart>Court of Appeals (2nd Circuit)</namePart>
325
+ </name>")
326
+ end
327
+
328
+ it 'concatenates the untyped name parts' do
329
+ expect(record.corporate_name.first.display_value).to eq('United States Court of Appeals (2nd Circuit)')
330
+ end
331
+ end
332
+
333
+ context 'with a complex example' do
334
+ subject(:record) do
335
+ mods_record <<-XML
336
+ <name>
337
+ <namePart>Sean Connery</namePart>
338
+ <role><roleTerm type='code' authority='marcrelator'>drt</roleTerm></role>
339
+ </name>
340
+ <name>
341
+ <namePart>Pierce Brosnan</namePart>
342
+ <role>
343
+ <roleTerm type='text'>CreatorFake</roleTerm>
344
+ <roleTerm type='code' authority='marcrelator'>cre</roleTerm>
345
+ </role>
346
+ <role><roleTerm type='text' authority='marcrelator'>Actor</roleTerm></role>
347
+ </name>
348
+ <name>
349
+ <namePart>Daniel Craig</namePart>
350
+ <role>
351
+ <roleTerm type='text' authority='marcrelator'>Actor</roleTerm>
352
+ <roleTerm type='code' authority='marcrelator'>cre</roleTerm>
353
+ </role>
354
+ </name>
355
+ XML
356
+ end
357
+
358
+ it 'has the expected attributes' do
359
+ expect(record.plain_name).to match_array([
360
+ have_attributes(role: have_attributes(value: ['Director'], code: ['drt'], authority: ['marcrelator'], size: 1)),
361
+ have_attributes(role: have_attributes(value: ['CreatorFake', 'Actor'], code: ['cre'], authority: ['marcrelator', 'marcrelator'], size: 2)),
362
+ have_attributes(role: have_attributes(value: ['Actor'], code: ['cre'], authority: ['marcrelator'], size: 1)),
363
+ ])
364
+ end
365
+ end
366
+ end
@@ -0,0 +1,134 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe "Mods <originInfo> Element" do
5
+ describe "#place" do
6
+ describe "#place_term" do
7
+ context 'with a single value' do
8
+ let(:terms) do
9
+ mods_record(<<-XML).origin_info.place.placeTerm
10
+ <originInfo><place><placeTerm authority='marccountry' type='code'>fr</placeTerm></place></originInfo>
11
+ XML
12
+ end
13
+
14
+ it 'has the expected attributes' do
15
+ expect(terms.first).to have_attributes(
16
+ authority: 'marccountry',
17
+ type_at: 'code',
18
+ text: 'fr'
19
+ )
20
+ end
21
+ end
22
+
23
+ context 'with a multi-valued place' do
24
+ let(:terms) do
25
+ mods_record(<<-XML).origin_info.place.placeTerm
26
+ <originInfo>
27
+ <place><placeTerm>France</placeTerm></place>
28
+ <place><placeTerm>Italy</placeTerm></place>
29
+ </originInfo>
30
+ XML
31
+ end
32
+
33
+ it 'has elements for each place' do
34
+ expect(terms.map(&:text)).to eq ['France', 'Italy']
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ describe "#publisher" do
41
+ subject(:publishers) do
42
+ mods_record(<<-XML).origin_info.publisher
43
+ <originInfo><publisher>Olney</publisher></origin_info>
44
+ XML
45
+ end
46
+
47
+ it "should get element values" do
48
+ expect(publishers.map(&:text)).to eq(["Olney"])
49
+ end
50
+ end
51
+
52
+ describe '#as_object' do
53
+ describe '#key_dates' do
54
+ it 'should extract the date with the keyDate attribute' do
55
+ origin_info = mods_record("<originInfo><dateCreated>other date</dateCreated><dateCreated keyDate='yes'>key date</dateCreated></originInfo>").origin_info
56
+ expect(origin_info.as_object.first.key_dates.first.text).to eq 'key date'
57
+ end
58
+ it 'should extract a date range when the keyDate attribute is on the start of the range' do
59
+ origin_info = mods_record("<originInfo><dateCreated point='end'>other date</dateCreated><dateCreated keyDate='yes' point='start'>key date</dateCreated></originInfo>").origin_info
60
+ expect(origin_info.as_object.first.key_dates.map(&:text)).to eq ['key date', 'other date']
61
+ end
62
+ end
63
+ end
64
+
65
+ Mods::ORIGIN_INFO_DATE_ELEMENTS.each do |elname|
66
+ context "<#{elname}> child elements" do
67
+ it "should recognize each element" do
68
+ origin_info = mods_record("<originInfo><#{elname}>date</#{elname}></originInfo>").origin_info.send(elname.to_sym)
69
+ expect(origin_info.map(&:text)).to eq(["date"])
70
+ end
71
+ it "should recognize encoding attribute on each element" do
72
+ origin_info = mods_record("<originInfo><#{elname} encoding='foo'>date</#{elname}></originInfo>").origin_info.send(elname.to_sym)
73
+ expect(origin_info.encoding).to eq(["foo"])
74
+ end
75
+ it "should recognize keyDate attribute" do
76
+ origin_info = mods_record("<originInfo><#{elname} keyDate='foo'>date</#{elname}></originInfo>").origin_info.send(elname.to_sym)
77
+ expect(origin_info.keyDate).to eq(["foo"])
78
+ end
79
+ it "should recognize point attribute" do
80
+ # NOTE: values allowed are 'start' and 'end'
81
+ origin_info = mods_record("<originInfo><#{elname} point='foo'>date</#{elname}></originInfo>").origin_info.send(elname.to_sym)
82
+ expect(origin_info.point).to eq(["foo"])
83
+ end
84
+ it "should recognize qualifier attribute" do
85
+ origin_info = mods_record("<originInfo><#{elname} qualifier='foo'>date</#{elname}></originInfo>").origin_info.send(elname.to_sym)
86
+ expect(origin_info.qualifier).to eq(["foo"])
87
+ end
88
+ it "should recognize type attribute only on dateOther" do
89
+ origin_info = mods_record("<originInfo><#{elname} type='foo'>date</#{elname}></originInfo>").origin_info.send(elname.to_sym)
90
+ if elname == 'dateOther'
91
+ expect(origin_info.type_at).to eq(["foo"])
92
+ else
93
+ expect { origin_info.type_at}.to raise_exception(NoMethodError, /type_at/)
94
+ end
95
+ end
96
+ end # <xxxDate> child elements
97
+ end
98
+
99
+ context 'edition' do
100
+ subject(:origin_info) do
101
+ mods_record(<<-XML).origin_info
102
+ <originInfo><edition>7th ed.</edition></originInfo>
103
+ XML
104
+ end
105
+
106
+ it "gets element value" do
107
+ expect(origin_info.edition).to have_attributes(text: '7th ed.')
108
+ end
109
+ end
110
+
111
+ context "<issuance> child element" do
112
+ subject(:origin_info) do
113
+ mods_record(<<-XML).origin_info
114
+ <originInfo><issuance>monographic</issuance></originInfo>
115
+ XML
116
+ end
117
+
118
+ it "gets element value" do
119
+ expect(origin_info.issuance).to have_attributes(text: 'monographic')
120
+ end
121
+ end
122
+
123
+ context "<frequency> child element" do
124
+ subject(:origin_info) do
125
+ mods_record(<<-XML).origin_info
126
+ <originInfo><frequency authority='marcfrequency'>Annual</frequency></originInfo>
127
+ XML
128
+ end
129
+
130
+ it "has the right attributes" do
131
+ expect(origin_info.frequency).to have_attributes(text: 'Annual', authority: ['marcfrequency'])
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,162 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe "Mods <part> Element" do
4
+ context 'with a basicpart' do
5
+ subject(:part) do
6
+ mods_record("<part>
7
+ <detail>
8
+ <title>Wayfarers (Poem)</title>
9
+ </detail>
10
+ <extent unit='pages'>
11
+ <start>97</start>
12
+ <end>98</end>
13
+ </extent>
14
+ </part>").part
15
+ end
16
+
17
+ it 'has the expected attributes' do
18
+ expect(part.first).to have_attributes(
19
+ detail: match_array([
20
+ have_attributes(
21
+ title: match_array([have_attributes(text: 'Wayfarers (Poem)')]),
22
+ number: [],
23
+ )
24
+ ]),
25
+ extent: match_array([
26
+ have_attributes(
27
+ unit: 'pages',
28
+ start: have_attributes(text: '97'),
29
+ end: have_attributes(text: '98'),
30
+ )
31
+ ])
32
+ )
33
+ end
34
+ end
35
+ context 'with a part with a detail number' do
36
+ subject(:part) do
37
+ mods_record("<part>
38
+ <detail type='page number'>
39
+ <number>3</number>
40
+ </detail>
41
+ <extent unit='pages'>
42
+ <start>3</start>
43
+ </extent>
44
+ </part>").part
45
+ end
46
+
47
+ it 'has the expected attributes' do
48
+ expect(part.first).to have_attributes(
49
+ detail: match_array([
50
+ have_attributes(
51
+ type_at: 'page number',
52
+ number: match_array([have_attributes(text: '3')])
53
+ )
54
+ ]),
55
+ extent: match_array([
56
+ have_attributes(
57
+ unit: 'pages',
58
+ start: have_attributes(text: '3')
59
+ )
60
+ ])
61
+ )
62
+ end
63
+ end
64
+ context 'with a part with a number and caption' do
65
+ subject(:part) do
66
+ mods_record("<part>
67
+ <detail type='issue'>
68
+ <number>1</number>
69
+ <caption>no.</caption>
70
+ </detail>
71
+ </part>").part
72
+ end
73
+
74
+ it 'has the expected attributes' do
75
+ expect(part.first).to have_attributes(
76
+ detail: match_array([
77
+ have_attributes(
78
+ type_at: 'issue',
79
+ number: match_array([have_attributes(text: '1')]),
80
+ caption: match_array([have_attributes(text: 'no.')])
81
+ )
82
+ ])
83
+ )
84
+ end
85
+ end
86
+
87
+ context 'with a typed part' do
88
+ subject(:part) do
89
+ mods_record("<part ID='p1' order='1' type='paragraph'>anything</part>").part
90
+ end
91
+
92
+ it 'has the expected attributes' do
93
+ expect(part.first).to have_attributes(
94
+ id_at: 'p1',
95
+ order: '1',
96
+ type_at: 'paragraph',
97
+ text: 'anything'
98
+ )
99
+ end
100
+ end
101
+
102
+ context 'with a level attribute' do
103
+ subject(:part) { mods_record("<part><detail level='val'>anything</detail></part>").part }
104
+
105
+ it 'has the expected attributes' do
106
+ expect(part.first).to have_attributes(
107
+ detail: match_array([have_attributes(level: 'val')])
108
+ )
109
+ end
110
+ end
111
+
112
+ context 'with a total element' do
113
+ subject(:part) { mods_record("<part><extent><total>anything</total></extent></part>").part }
114
+
115
+ it 'has the expected attributes' do
116
+ expect(part.first).to have_attributes(
117
+ extent: match_array([have_attributes(total: match_array([have_attributes(text: 'anything')]))])
118
+ )
119
+ end
120
+ end
121
+
122
+ context 'with a list element' do
123
+ subject(:part) { mods_record("<part><extent><list>anything</list></extent></part>").part }
124
+
125
+ it 'has the expected attributes' do
126
+ expect(part.first).to have_attributes(
127
+ extent: match_array([have_attributes(list: match_array([have_attributes(text: 'anything')]))])
128
+ )
129
+ end
130
+ end
131
+
132
+ context "<date> child element" do
133
+ subject(:date) do
134
+ mods_record("<part><date encoding='w3cdtf'>1999</date></part>").part.date
135
+ end
136
+
137
+ it 'has the expected date attributes' do
138
+ expect(date.first).to have_attributes(
139
+ encoding: 'w3cdtf',
140
+ text: '1999',
141
+ point: [],
142
+ qualifier: []
143
+ )
144
+ end
145
+
146
+ it 'does not have a keyDate attribute' do
147
+ expect(date.first).not_to respond_to(:keyDate)
148
+ end
149
+ end
150
+
151
+ context "<text> child element as .text_el term" do
152
+ subject(:part) do
153
+ mods_record("<part><text type='bar' displayLabel='foo'>1999</text></part>").part
154
+ end
155
+
156
+ describe '#text_el' do
157
+ it "has the expected attributes" do
158
+ expect(part.first.text_el).to have_attributes(text: '1999', displayLabel: ['foo'], type_at: ['bar'])
159
+ end
160
+ end
161
+ end
162
+ end