citeproc 0.0.8 → 0.0.9

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.
@@ -3,11 +3,10 @@ require 'spec_helper'
3
3
  module CiteProc
4
4
  describe Item do
5
5
 
6
- it { should_not be nil }
7
- it { should be_empty }
8
6
 
9
7
  describe '.new' do
10
-
8
+ it { should_not be nil }
9
+
11
10
  it 'creates number variables for number fields' do
12
11
  Item.new(:edition => 23).edition.should be_a(Number)
13
12
  end
@@ -22,6 +21,7 @@ module CiteProc
22
21
 
23
22
  it 'creates names variables for name fields' do
24
23
  Item.new(:editor => { :given => 'Jane' }).editor.should be_a(Names)
24
+ Item.new(:editor => 'Plato and Socrates').editor.should have(2).names
25
25
  end
26
26
 
27
27
  it 'creates text variables for unknown fields' do
@@ -29,7 +29,26 @@ module CiteProc
29
29
  v.should be_a(Variable)
30
30
  v.should == '42'
31
31
  end
32
-
32
+ end
33
+
34
+ describe '#empty' do
35
+ it { should be_empty }
36
+
37
+ it 'returns false when there is at least one variable in the item' do
38
+ Item.new(:title => 'foo').should_not be_empty
39
+ end
40
+ end
41
+
42
+ describe '#each' do
43
+ it 'yields each variable to the given block' do
44
+ Item.new(:title => 'foo', :edition => 2).each.map {|kv| kv.join('-') }.sort.should == %w{edition-2 title-foo}
45
+ end
46
+ end
47
+
48
+ describe '#each_value' do
49
+ it "yields each variable's value to the given block" do
50
+ Item.new(:title => 'foo', :edition => 2).each_value.map(&:to_s).sort.should == %w{2 foo}
51
+ end
33
52
  end
34
53
 
35
54
  describe '#to_citeproc' do
@@ -3,490 +3,605 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  module CiteProc
6
-
7
- describe 'CiteProc Names' do
8
-
9
- let(:poe) { Name.new(:family => 'Poe', :given => 'Edgar Allen') }
10
- let(:joe) { Name.new(:given => 'Joe') }
11
- let(:plato) { Name.new(:given => 'Plato') }
12
- let(:aristotle) { Name.new(:given => 'Ἀριστοτέλης') }
13
- let(:dostoyevksy) { Name.new(:given => 'Фёдор Михайлович', :family => 'Достоевский') }
14
-
15
- let(:utf) { Name.new(
16
- :given => 'Gérard',
17
- :'dropping-particle' => 'de',
18
- :'non-dropping-particle' => 'la',
19
- :family => 'Martinière',
20
- :suffix => 'III')
21
- }
22
-
23
- let(:markup) { Name.new(
24
- :given => '<b>Gérard</b>',
25
- :'dropping-particle' => 'd<i>e</i>',
26
- :'non-dropping-particle' => 'la',
27
- :family => 'Mar<strong>tinière</strong>',
28
- :suffix => 'III')
29
- }
30
-
31
-
32
- let(:japanese) { Name.new(
33
- "family" => "穂積",
34
- "given" => "陳重")
35
- }
36
-
37
- let(:saunders) { Name.new("family" => "Saunders", "given" => "John Bertrand de Cusance Morant") }
38
-
39
- let(:humboldt) { Name.new(
40
- "family" => "Humboldt",
41
- "given" => "Alexander",
42
- "dropping-particle" => "von")
43
- }
44
-
45
- let(:van_gogh) { Name.new(
46
- "family" => "Gogh",
47
- "given" => "Vincent",
48
- "non-dropping-particle" => "van")
49
- }
50
-
51
- let(:jr) { Name.new(
52
- "family" => "Stephens",
53
- "given" => "James",
54
- "suffix" => "Jr.")
55
- }
56
-
57
- let(:frank) { Name.new(
58
- "family" => "Bennett",
59
- "given" => "Frank G.",
60
- "suffix" => "Jr.",
61
- "comma-suffix" => "true")
62
- }
63
-
64
- let(:ramses) { Name.new(
65
- :family => 'Ramses',
66
- :given => 'Horatio',
67
- :suffix => 'III')
68
- }
69
-
70
-
71
- describe Name do
72
-
73
-
74
- it { should_not be_nil }
75
-
76
- describe 'formatting options' do
77
-
78
- it 'does not always demote particle by default' do
79
- Name.new.always_demote_particle?.should be false
80
- Name.new.always_demote_non_dropping_particle?.should be false
81
- end
82
-
83
- it 'does not demote particle by default' do
84
- Name.new.demote_particle?.should be false
85
- Name.new.demote_non_dropping_particle?.should be false
86
- end
87
-
88
- it 'does not demote particle in sort order by default' do
89
- Name.new.sort_order!.demote_particle?.should be false
90
- Name.new.sort_order!.demote_non_dropping_particle?.should be false
91
- end
92
-
93
- it 'always demotes particle if option is set' do
94
- Name.new({}, :'demote-non-dropping-particle' => 'display-and-sort').always_demote_particle?.should be true
95
- Name.new({}, :'demote-non-dropping-particle' => 'display-and-sort').always_demote_non_dropping_particle?.should be true
96
- end
97
-
98
- it 'demotes particle in sort order if option is set to sort-only' do
99
- Name.new({}, :'demote-non-dropping-particle' => 'display-and-sort').sort_order!.demote_particle?.should be true
100
- end
101
-
102
- it 'never demotes particle by default' do
103
- Name.new.never_demote_particle?.should be true
104
- Name.new.never_demote_non_dropping_particle?.should be true
105
- end
106
-
107
- it 'is not in sort order by default' do
108
- Name.new.sort_order?.should be false
109
- end
110
-
111
- it 'uses the long form by default' do
112
- Name.new.should be_long_form
113
- end
114
-
115
- it 'does not use short form by default' do
116
- Name.new.should_not be_short_form
117
- end
118
-
119
- end
120
-
121
- describe 'constructing' do
122
-
123
- describe '.new' do
124
-
125
- it 'accepts a symbolized hash' do
126
- Name.new(:family => 'Doe').to_s.should == 'Doe'
127
- end
128
-
129
- it 'accepts a stringified hash' do
130
- Name.new('family' => 'Doe').to_s.should == 'Doe'
131
- end
132
-
133
-
134
- end
135
-
136
- end
137
-
138
- describe '#dup' do
139
-
140
- it 'returns a new name copied by value' do
141
- poe.dup.upcase!.to_s.should_not == poe.to_s
142
- end
143
-
144
- end
145
-
146
- describe 'script awareness' do
147
-
148
- it 'english names are romanesque' do
149
- frank.should be_romanesque
150
- end
151
-
152
- it 'ancient greek names are romanesque' do
153
- aristotle.should be_romanesque
154
- end
155
-
156
- it 'russian names are romanesque' do
157
- dostoyevksy.should be_romanesque
158
- end
159
-
160
- it 'japanese names are not romanesque' do
161
- japanese.should_not be_romanesque
162
- end
163
-
164
- it 'german names are romanesque' do
165
- Name.new(:given => 'Firedrich', :family => 'Hölderlin').should be_romanesque
166
- end
167
-
168
- it 'french names are romanesque' do
169
- utf.should be_romanesque
170
- end
171
-
172
- it 'markup does not interfere with romanesque test' do
173
- markup.should be_romanesque
174
- end
175
-
176
- end
177
-
178
- describe 'literals' do
179
-
180
- it 'is a literal if the literal attribute is set' do
181
- Name.new(:literal => 'GNU/Linux').should be_literal
182
- end
183
-
184
- it 'is not literal by default' do
185
- Name.new.should_not be_literal
186
- end
187
-
188
- it 'is literal even if other name parts are set' do
189
- Name.new(:family => 'Tux', :literal => 'GNU/Linux').should be_literal
190
- end
191
-
192
- end
193
-
194
- describe 'in-place manipulation (bang! methods)' do
195
-
196
- it 'delegates to string for family name' do
197
- plato.swapcase!.to_s.should == 'pLATO'
198
- end
199
-
200
- it 'delegates to string for given name' do
201
- humboldt.gsub!(/^Alex\w*/, 'Wilhelm').to_s.should == 'Wilhelm von Humboldt'
202
- end
203
-
204
- it 'delegates to string for dropping particle' do
205
- humboldt.upcase!.dropping_particle.should == 'VON'
206
- end
207
-
208
- it 'delegates to string for non dropping particle' do
209
- van_gogh.upcase!.non_dropping_particle.should == 'VAN'
210
- end
211
-
212
- it 'delegates to string for suffix' do
213
- frank.sub!(/jr./i, 'Sr.').to_s.should == 'Frank G. Bennett, Sr.'
214
- end
215
-
216
- it 'returns the name object' do
217
- poe.upcase!.should be_a(Name)
218
- end
219
-
220
- end
221
-
222
-
223
- describe '#to_s' do
224
-
225
- it 'returns an empty string by default' do
226
- Name.new.to_s.should be_empty
227
- end
228
-
229
- it 'returns the last name if only last name is set' do
230
- Name.new(:family => 'Doe').to_s.should == 'Doe'
231
- end
232
-
233
- it 'returns the first name if only the first name is set' do
234
- Name.new(:given => 'John').to_s.should == 'John'
235
- end
236
-
237
- it 'prints japanese names using static ordering' do
238
- japanese.to_s.should == '穂積 陳重'
239
- end
240
-
241
- it 'returns the literal if the name is a literal' do
242
- Name.new(:literal => 'GNU/Linux').to_s == 'GNU/Linux'
243
- end
244
-
245
- it 'returns the name in display order by default' do
246
- Name.new(:family => 'Doe', :given => 'John').to_s.should == 'John Doe'
247
- end
248
-
249
- it 'returns the name in sort order if the sort order option is active' do
250
- Name.new(:family => 'Doe', :given => 'John').sort_order!.to_s.should == 'Doe, John'
251
- end
252
-
253
- it 'returns the full given name' do
254
- saunders.to_s.should == 'John Bertrand de Cusance Morant Saunders'
255
- end
256
-
257
- it 'includes dropping particles' do
258
- humboldt.to_s.should == 'Alexander von Humboldt'
259
- end
260
-
261
- it 'includes non dropping particles' do
262
- van_gogh.to_s.should == 'Vincent van Gogh'
263
- end
264
-
265
- it 'includes suffices' do
266
- jr.to_s.should == 'James Stephens Jr.'
267
- end
268
-
269
- it 'uses the comma suffix option' do
270
- frank.to_s.should == 'Frank G. Bennett, Jr.'
271
- end
272
-
273
- it 'prints unicode characters' do
274
- utf.to_s.should == "Gérard de la Martinière III"
275
- end
276
-
277
- it 'prints russian names normally' do
278
- dostoyevksy.to_s.should == 'Фёдор Михайлович Достоевский'
279
- end
280
-
281
- describe 'when static ordering is active' do
282
-
283
- it 'always prints the family name first' do
284
- poe.static_order!.to_s.should == 'Poe Edgar Allen'
285
- end
286
-
287
- end
288
-
289
- describe 'when the sort order option is active' do
290
-
291
- it 'returns an empty string by default' do
292
- Name.new.sort_order!.to_s.should be_empty
293
- end
294
-
295
- it 'returns the last name if only last name is set' do
296
- Name.new({:family => 'Doe'}, { :'name-as-sort-order' => true }).to_s.should == 'Doe'
297
- end
298
-
299
- it 'returns the first name if only the first name is set' do
300
- Name.new(:given => 'John').sort_order!.to_s.should == 'John'
301
- end
302
-
303
- it 'prints japanese names using static ordering' do
304
- japanese.sort_order!.to_s.should == '穂積 陳重'
305
- end
306
-
307
- it 'returns the literal if the name is a literal' do
308
- Name.new(:literal => 'GNU/Linux').sort_order!.to_s == 'GNU/Linux'
309
- end
310
-
311
- it 'uses comma for suffix if comma suffix is set' do
312
- frank.sort_order!.to_s.should == 'Bennett, Frank G., Jr.'
313
- end
314
-
315
- it 'also uses comma for suffix if comma suffix is *not* set' do
316
- jr.sort_order!.to_s.should == 'Stephens, James, Jr.'
317
- end
318
-
319
- it 'for normal names it prints them as "family, given"' do
320
- poe.sort_order!.to_s.should == 'Poe, Edgar Allen'
321
- end
322
-
323
- it 'particles come after given name by default' do
324
- van_gogh.sort_order!.to_s.should == 'van Gogh, Vincent'
325
- end
326
-
327
- it 'particles come after given name if demote option is active' do
328
- van_gogh.sort_order!.demote_particle!.to_s.should == 'Gogh, Vincent van'
329
- end
330
-
331
- it 'dropping particles come after given name' do
332
- humboldt.sort_order!.to_s.should == 'Humboldt, Alexander von'
333
- end
334
-
335
- it 'by default if all parts are set they are returned as "particle family, first dropping-particle, suffix"' do
336
- utf.sort_order!.to_s.should == 'la Martinière, Gérard de, III'
337
- end
338
-
339
- end
340
-
341
- end
342
-
343
- describe '#sort_order' do
344
-
345
- it 'returns only a single token for literal names' do
346
- Name.new(:literal => 'ACME Corp.').sort_order.should have(1).element
347
- end
348
-
349
- it 'strips leading "the" off literal names' do
350
- Name.new(:literal => 'The ACME Corp.').sort_order[0].should == 'ACME Corp.'
351
- end
352
-
353
- it 'strips leading "a" off literal names' do
354
- Name.new(:literal => 'A Company').sort_order[0].should == 'Company'
355
- end
356
-
357
- it 'strips leading "an" off literal names' do
358
- Name.new(:literal => 'an ACME Corp.').sort_order[0].should == 'ACME Corp.'
359
- end
360
-
361
- it 'strips leading "l\'" off literal names' do
362
- Name.new(:literal => "L'Augustine").sort_order[0].should == 'Augustine'
363
- end
364
-
365
- it 'always returns four tokens for non literal names' do
366
- poe.sort_order.should have(4).elements
367
- joe.sort_order.should have(4).elements
368
- aristotle.sort_order.should have(4).elements
369
- utf.sort_order.should have(4).elements
370
- frank.sort_order.should have(4).elements
371
- japanese.sort_order.should have(4).elements
372
- end
373
-
374
- it 'demotes non dropping particles if option is set' do
375
- van_gogh.demote_particle!.sort_order.should == ['Gogh', 'van', 'Vincent', '']
376
- end
377
-
378
- it 'does not demote non dropping particles by default' do
379
- van_gogh.sort_order.should == ['van Gogh', '', 'Vincent', '']
380
- end
381
-
382
- it 'does not demote non dropping particles by default but dropping particles are demoted' do
383
- utf.sort_order.should == ['la Martinière', 'de', 'Gérard', 'III']
384
- end
385
-
386
- it 'demotes dropping particles' do
387
- humboldt.sort_order.should == ['Humboldt', 'von', 'Alexander', '']
388
- end
389
-
390
- it 'combines non dropping particles with family name if option demote-non-dropping-particles is not active' do
391
- van_gogh.never_demote_particle!.sort_order.should == ['van Gogh', '', 'Vincent', '']
392
- end
393
-
394
- end
395
-
396
- describe 'sorting' do
397
-
398
- it 'sorts by sort order by default' do
399
- [poe, utf, joe, plato].sort.should == [joe, plato, utf, poe]
400
- end
401
-
402
- end
403
-
404
-
405
- end
406
-
407
- describe Names do
408
-
409
- it { should_not be nil }
410
- it { should_not be_numeric }
411
-
412
- describe 'constructing' do
413
-
414
- it 'accepts a single name' do
415
- lambda { Names.new(joe) }.should_not raise_error
416
- end
417
-
418
- it 'accepts a single name as hash' do
419
- Names.new(:given => 'Jim').should have(1).name
420
- end
421
-
422
- it 'accepts two names' do
423
- Names.new(joe, poe).should have(2).names
424
- end
425
-
426
- it 'accepts two names as hash' do
427
- Names.new({:given => 'Jim'}, {:family => 'Jameson'}).should have(2).names
428
- end
429
-
430
- it 'accepts an array of names' do
431
- Names.new([joe, poe]).should have(2).names
432
- end
433
-
434
- end
435
-
436
- describe '#strip_markup' do
437
-
438
- it 'strips markup off string representation' do
439
- Names.new(markup).strip_markup.should == utf.to_s
440
- end
441
-
442
- it 'when using the bang! version, strips markup off each name part' do
443
- Names.new(markup).strip_markup![0].should == utf
444
- end
445
-
446
-
447
- end
448
-
449
- describe 'bang! methods' do
450
-
451
- it 'delegate to the individual names and return self' do
452
- Names.new(poe, plato, joe).upcase!.map(&:given).should == ['EDGAR ALLEN', 'PLATO', 'JOE']
453
- end
454
-
455
- end
456
-
457
- describe '#to_bibtex' do
458
-
459
- describe 'when there is only a single name' do
460
- it 'prints the name in sort order' do
461
- Names.new(poe).to_bibtex.should == 'Poe, Edgar Allen'
462
- end
463
- end
464
-
465
- describe 'when there are two or more names' do
466
- it 'prints the names in sort order connected with the word "and"' do
467
- Names.new(poe, plato, humboldt).to_bibtex.should == 'Poe, Edgar Allen and Plato and Humboldt, Alexander von'
468
- end
469
- end
470
-
471
- end
472
-
473
- describe '#to_s' do
474
-
475
- describe 'when the number of names exceeds the et-al-min option' do
476
-
477
- it 'prints only the et-al-use-first names'
478
- it 'adds et-al at the end'
479
- it 'adds the delimiter before et-al only in the right circumstances'
480
-
481
- end
482
-
483
- end
484
-
485
- describe 'sorting' do
486
- end
487
-
488
- end
489
-
490
- end
491
-
6
+
7
+ describe 'CiteProc Names' do
8
+
9
+ let(:poe) { Name.new(:family => 'Poe', :given => 'Edgar Allen') }
10
+ let(:joe) { Name.new(:given => 'Joe') }
11
+ let(:plato) { Name.new(:given => 'Plato') }
12
+ let(:aristotle) { Name.new(:given => 'Ἀριστοτέλης') }
13
+ let(:dostoyevksy) { Name.new(:given => 'Фёдор Михайлович', :family => 'Достоевский') }
14
+
15
+ let(:utf) { Name.new(
16
+ :given => 'Gérard',
17
+ :'dropping-particle' => 'de',
18
+ :'non-dropping-particle' => 'la',
19
+ :family => 'Martinière',
20
+ :suffix => 'III')
21
+ }
22
+
23
+ let(:markup) { Name.new(
24
+ :given => '<b>Gérard</b>',
25
+ :'dropping-particle' => 'd<i>e</i>',
26
+ :'non-dropping-particle' => 'la',
27
+ :family => 'Mar<strong>tinière</strong>',
28
+ :suffix => 'III')
29
+ }
30
+
31
+
32
+ let(:japanese) { Name.new(
33
+ "family" => "穂積",
34
+ "given" => "陳重")
35
+ }
36
+
37
+ let(:saunders) { Name.new("family" => "Saunders", "given" => "John Bertrand de Cusance Morant") }
38
+
39
+ let(:humboldt) { Name.new(
40
+ "family" => "Humboldt",
41
+ "given" => "Alexander",
42
+ "dropping-particle" => "von")
43
+ }
44
+
45
+ let(:van_gogh) { Name.new(
46
+ "family" => "Gogh",
47
+ "given" => "Vincent",
48
+ "non-dropping-particle" => "van")
49
+ }
50
+
51
+ let(:jr) { Name.new(
52
+ "family" => "Stephens",
53
+ "given" => "James",
54
+ "suffix" => "Jr.")
55
+ }
56
+
57
+ let(:frank) { Name.new(
58
+ "family" => "Bennett",
59
+ "given" => "Frank G.",
60
+ "suffix" => "Jr.",
61
+ "comma-suffix" => "true")
62
+ }
63
+
64
+ let(:ramses) { Name.new(
65
+ :family => 'Ramses',
66
+ :given => 'Horatio',
67
+ :suffix => 'III')
68
+ }
69
+
70
+ describe Name do
71
+
72
+
73
+ it { should_not be_nil }
74
+
75
+ describe 'formatting options' do
76
+
77
+ it 'does not always demote particle by default' do
78
+ Name.new.always_demote_particle?.should be false
79
+ Name.new.always_demote_non_dropping_particle?.should be false
80
+ end
81
+
82
+ it 'does not demote particle by default' do
83
+ Name.new.demote_particle?.should be false
84
+ Name.new.demote_non_dropping_particle?.should be false
85
+ end
86
+
87
+ it 'does not demote particle in sort order by default' do
88
+ Name.new.sort_order!.demote_particle?.should be false
89
+ Name.new.sort_order!.demote_non_dropping_particle?.should be false
90
+ end
91
+
92
+ it 'always demotes particle if option is set' do
93
+ Name.new({}, :'demote-non-dropping-particle' => 'display-and-sort').always_demote_particle?.should be true
94
+ Name.new({}, :'demote-non-dropping-particle' => 'display-and-sort').always_demote_non_dropping_particle?.should be true
95
+ end
96
+
97
+ it 'demotes particle in sort order if option is set to sort-only' do
98
+ Name.new({}, :'demote-non-dropping-particle' => 'display-and-sort').sort_order!.demote_particle?.should be true
99
+ end
100
+
101
+ it 'never demotes particle by default' do
102
+ Name.new.never_demote_particle?.should be true
103
+ Name.new.never_demote_non_dropping_particle?.should be true
104
+ end
105
+
106
+ it 'is not in sort order by default' do
107
+ Name.new.sort_order?.should be false
108
+ end
109
+
110
+ it 'uses the long form by default' do
111
+ Name.new.should be_long_form
112
+ end
113
+
114
+ it 'does not use short form by default' do
115
+ Name.new.should_not be_short_form
116
+ end
117
+
118
+ end
119
+
120
+ describe 'constructing' do
121
+
122
+ describe '.new' do
123
+
124
+ it 'accepts a symbolized hash' do
125
+ Name.new(:family => 'Doe').to_s.should == 'Doe'
126
+ end
127
+
128
+ it 'accepts a stringified hash' do
129
+ Name.new('family' => 'Doe').to_s.should == 'Doe'
130
+ end
131
+
132
+
133
+ end
134
+
135
+ end
136
+
137
+ describe '#dup' do
138
+
139
+ it 'returns a new name copied by value' do
140
+ poe.dup.upcase!.to_s.should_not == poe.to_s
141
+ end
142
+
143
+ end
144
+
145
+ describe 'script awareness' do
146
+
147
+ it 'english names are romanesque' do
148
+ frank.should be_romanesque
149
+ end
150
+
151
+ if CiteProc.oniguruma?
152
+ it 'ancient greek names are romanesque' do
153
+ aristotle.should be_romanesque
154
+ end
155
+
156
+ it 'russian names are romanesque' do
157
+ dostoyevksy.should be_romanesque
158
+ end
159
+ end
160
+
161
+ it 'japanese names are not romanesque' do
162
+ japanese.should_not be_romanesque
163
+ end
164
+
165
+ it 'german names are romanesque' do
166
+ Name.new(:given => 'Firedrich', :family => 'Hölderlin').should be_romanesque
167
+ end
168
+
169
+ it 'french names are romanesque' do
170
+ utf.should be_romanesque
171
+ end
172
+
173
+ it 'markup does not interfere with romanesque test' do
174
+ markup.should be_romanesque
175
+ end
176
+
177
+ end
178
+
179
+ describe 'literals' do
180
+
181
+ it 'is a literal if the literal attribute is set' do
182
+ Name.new(:literal => 'GNU/Linux').should be_literal
183
+ end
184
+
185
+ it 'is not literal by default' do
186
+ Name.new.should_not be_literal
187
+ end
188
+
189
+ it 'is literal even if other name parts are set' do
190
+ Name.new(:family => 'Tux', :literal => 'GNU/Linux').should be_literal
191
+ end
192
+
193
+ end
194
+
195
+ describe 'in-place manipulation (bang! methods)' do
196
+
197
+ it 'delegates to string for family name' do
198
+ plato.swapcase!.to_s.should == 'pLATO'
199
+ end
200
+
201
+ it 'delegates to string for given name' do
202
+ humboldt.gsub!(/^Alex\w*/, 'Wilhelm').to_s.should == 'Wilhelm von Humboldt'
203
+ end
204
+
205
+ it 'delegates to string for dropping particle' do
206
+ humboldt.upcase!.dropping_particle.should == 'VON'
207
+ end
208
+
209
+ it 'delegates to string for non dropping particle' do
210
+ van_gogh.upcase!.non_dropping_particle.should == 'VAN'
211
+ end
212
+
213
+ it 'delegates to string for suffix' do
214
+ frank.sub!(/jr./i, 'Sr.').to_s.should == 'Frank G. Bennett, Sr.'
215
+ end
216
+
217
+ it 'returns the name object' do
218
+ poe.upcase!.should be_a(Name)
219
+ end
220
+
221
+ end
222
+
223
+
224
+ describe '#to_s' do
225
+
226
+ it 'returns an empty string by default' do
227
+ Name.new.to_s.should be_empty
228
+ end
229
+
230
+ it 'returns the last name if only last name is set' do
231
+ Name.new(:family => 'Doe').to_s.should == 'Doe'
232
+ end
233
+
234
+ it 'returns the first name if only the first name is set' do
235
+ Name.new(:given => 'John').to_s.should == 'John'
236
+ end
237
+
238
+ it 'prints japanese names using static ordering' do
239
+ japanese.to_s.should == '穂積 陳重'
240
+ end
241
+
242
+ it 'returns the literal if the name is a literal' do
243
+ Name.new(:literal => 'GNU/Linux').to_s == 'GNU/Linux'
244
+ end
245
+
246
+ it 'returns the name in display order by default' do
247
+ Name.new(:family => 'Doe', :given => 'John').to_s.should == 'John Doe'
248
+ end
249
+
250
+ it 'returns the name in sort order if the sort order option is active' do
251
+ Name.new(:family => 'Doe', :given => 'John').sort_order!.to_s.should == 'Doe, John'
252
+ end
253
+
254
+ it 'returns the full given name' do
255
+ saunders.to_s.should == 'John Bertrand de Cusance Morant Saunders'
256
+ end
257
+
258
+ it 'includes dropping particles' do
259
+ humboldt.to_s.should == 'Alexander von Humboldt'
260
+ end
261
+
262
+ it 'includes non dropping particles' do
263
+ van_gogh.to_s.should == 'Vincent van Gogh'
264
+ end
265
+
266
+ it 'includes suffices' do
267
+ jr.to_s.should == 'James Stephens Jr.'
268
+ end
269
+
270
+ it 'uses the comma suffix option' do
271
+ frank.to_s.should == 'Frank G. Bennett, Jr.'
272
+ end
273
+
274
+ it 'prints unicode characters' do
275
+ utf.to_s.should == "Gérard de la Martinière III"
276
+ end
277
+
278
+ if CiteProc.oniguruma?
279
+ it 'prints russian names normally' do
280
+ dostoyevksy.to_s.should == 'Фёдор Михайлович Достоевский'
281
+ end
282
+ end
283
+
284
+ describe 'when static ordering is active' do
285
+
286
+ it 'always prints the family name first' do
287
+ poe.static_order!.to_s.should == 'Poe Edgar Allen'
288
+ end
289
+
290
+ end
291
+
292
+ describe 'when the sort order option is active' do
293
+
294
+ it 'returns an empty string by default' do
295
+ Name.new.sort_order!.to_s.should be_empty
296
+ end
297
+
298
+ it 'returns the last name if only last name is set' do
299
+ Name.new({:family => 'Doe'}, { :'name-as-sort-order' => true }).to_s.should == 'Doe'
300
+ end
301
+
302
+ it 'returns the first name if only the first name is set' do
303
+ Name.new(:given => 'John').sort_order!.to_s.should == 'John'
304
+ end
305
+
306
+ it 'prints japanese names using static ordering' do
307
+ japanese.sort_order!.to_s.should == '穂積 陳重'
308
+ end
309
+
310
+ it 'returns the literal if the name is a literal' do
311
+ Name.new(:literal => 'GNU/Linux').sort_order!.to_s == 'GNU/Linux'
312
+ end
313
+
314
+ it 'uses comma for suffix if comma suffix is set' do
315
+ frank.sort_order!.to_s.should == 'Bennett, Frank G., Jr.'
316
+ end
317
+
318
+ it 'also uses comma for suffix if comma suffix is *not* set' do
319
+ jr.sort_order!.to_s.should == 'Stephens, James, Jr.'
320
+ end
321
+
322
+ it 'for normal names it prints them as "family, given"' do
323
+ poe.sort_order!.to_s.should == 'Poe, Edgar Allen'
324
+ end
325
+
326
+ it 'particles come after given name by default' do
327
+ van_gogh.sort_order!.to_s.should == 'van Gogh, Vincent'
328
+ end
329
+
330
+ it 'particles come after given name if demote option is active' do
331
+ van_gogh.sort_order!.demote_particle!.to_s.should == 'Gogh, Vincent van'
332
+ end
333
+
334
+ it 'dropping particles come after given name' do
335
+ humboldt.sort_order!.to_s.should == 'Humboldt, Alexander von'
336
+ end
337
+
338
+ it 'by default if all parts are set they are returned as "particle family, first dropping-particle, suffix"' do
339
+ utf.sort_order!.to_s.should == 'la Martinière, Gérard de, III'
340
+ end
341
+
342
+ end
343
+
344
+ end
345
+
346
+ describe '#sort_order' do
347
+
348
+ it 'returns only a single token for literal names' do
349
+ Name.new(:literal => 'ACME Corp.').sort_order.should have(1).element
350
+ end
351
+
352
+ it 'strips leading "the" off literal names' do
353
+ Name.new(:literal => 'The ACME Corp.').sort_order[0].should == 'ACME Corp.'
354
+ end
355
+
356
+ it 'strips leading "a" off literal names' do
357
+ Name.new(:literal => 'A Company').sort_order[0].should == 'Company'
358
+ end
359
+
360
+ it 'strips leading "an" off literal names' do
361
+ Name.new(:literal => 'an ACME Corp.').sort_order[0].should == 'ACME Corp.'
362
+ end
363
+
364
+ it 'strips leading "l\'" off literal names' do
365
+ Name.new(:literal => "L'Augustine").sort_order[0].should == 'Augustine'
366
+ end
367
+
368
+ it 'always returns four tokens for non literal names' do
369
+ poe.sort_order.should have(4).elements
370
+ joe.sort_order.should have(4).elements
371
+ aristotle.sort_order.should have(4).elements
372
+ utf.sort_order.should have(4).elements
373
+ frank.sort_order.should have(4).elements
374
+ japanese.sort_order.should have(4).elements
375
+ end
376
+
377
+ it 'demotes non dropping particles if option is set' do
378
+ van_gogh.demote_particle!.sort_order.should == ['Gogh', 'van', 'Vincent', '']
379
+ end
380
+
381
+ it 'does not demote non dropping particles by default' do
382
+ van_gogh.sort_order.should == ['van Gogh', '', 'Vincent', '']
383
+ end
384
+
385
+ it 'does not demote non dropping particles by default but dropping particles are demoted' do
386
+ utf.sort_order.should == ['la Martinière', 'de', 'Gérard', 'III']
387
+ end
388
+
389
+ it 'demotes dropping particles' do
390
+ humboldt.sort_order.should == ['Humboldt', 'von', 'Alexander', '']
391
+ end
392
+
393
+ it 'combines non dropping particles with family name if option demote-non-dropping-particles is not active' do
394
+ van_gogh.never_demote_particle!.sort_order.should == ['van Gogh', '', 'Vincent', '']
395
+ end
396
+
397
+ end
398
+
399
+ describe 'sorting' do
400
+
401
+ it 'sorts by sort order by default' do
402
+ [poe, utf, joe, plato].sort.should == [joe, plato, utf, poe]
403
+ end
404
+
405
+ end
406
+
407
+
408
+ end
409
+
410
+ describe Names do
411
+
412
+ let(:gang_of_four) {
413
+ Names.parse!('Erich Gamma and Richard Helm and Ralph Johnson and John Vlissides')
414
+ }
415
+
416
+ it { should_not be nil }
417
+ it { should_not be_numeric }
418
+
419
+ describe 'constructing' do
420
+
421
+ it 'accepts a single name' do
422
+ lambda { Names.new(joe) }.should_not raise_error
423
+ end
424
+
425
+ it 'accepts a single name as hash' do
426
+ Names.new(:given => 'Jim').should have(1).names
427
+ end
428
+
429
+ it 'accepts two names' do
430
+ Names.new(joe, poe).should have(2).names
431
+ end
432
+
433
+ it 'accepts two names as hash' do
434
+ Names.new({:given => 'Jim'}, {:family => 'Jameson'}).should have(2).names
435
+ end
436
+
437
+ it 'accepts an array of names' do
438
+ Names.new([joe, poe]).should have(2).names
439
+ end
440
+
441
+ end
442
+
443
+ describe 'parsing' do
444
+ it 'accepts a single name as a string' do
445
+ Names.parse('Edgar A. Poe').should have(1).names
446
+ end
447
+
448
+ it 'accepts multiple names as a string' do
449
+ Names.parse('Edgar A. Poe and Hawthorne, Nathaniel and Herman Melville').should have(3).names
450
+ end
451
+
452
+ it 'parses the passed-in family names' do
453
+ Names.parse('Edgar A. Poe and Hawthorne, Nathaniel and Herman Melville').map { |n|
454
+ n.values_at(:family) }.flatten.should == %w{ Poe Hawthorne Melville }
455
+ end
456
+
457
+ it '#parse returns nil on error' do
458
+ Names.parse(23).should be_nil
459
+ end
460
+
461
+ it '#parse! raises an error on bad input' do
462
+ expect { Names.parse!('A,B,C,D,E') }.to raise_error(ParseError)
463
+ end
464
+
465
+ end
466
+
467
+ describe '#strip_markup' do
468
+
469
+ it 'strips markup off string representation' do
470
+ Names.new(markup).strip_markup.should == utf.to_s
471
+ end
472
+
473
+ it 'when using the bang! version, strips markup off each name part' do
474
+ Names.new(markup).strip_markup![0].should == utf
475
+ end
476
+
477
+
478
+ end
479
+
480
+ describe 'bang! methods' do
481
+ it 'delegate to the individual names and return self' do
482
+ Names.new(poe, plato, joe).upcase!.map(&:given).should == ['EDGAR ALLEN', 'PLATO', 'JOE']
483
+ end
484
+ end
485
+
486
+ [:never, :always, :contextually].each do |setting|
487
+ setter = "delimiter_#{setting}_precedes_last!"
488
+ predicate = "delimiter_#{setting}_precedes_last?"
489
+
490
+ describe "##{setter}" do
491
+ it 'sets the delimiter precedes last option accordingly' do
492
+ Names.new.send(setter).send(predicate).should == true
493
+ end
494
+ end
495
+ end
496
+
497
+ describe '#delimiter_precedes_last' do
498
+ it 'returns false by default' do
499
+ Names.new(joe).should_not be_delimiter_precedes_last
500
+ end
501
+
502
+ it 'returns false by default for a single name' do
503
+ Names.new(joe).should_not be_delimiter_precedes_last
504
+ end
505
+
506
+ it 'returns false by default for two names' do
507
+ Names.new(joe, poe).should_not be_delimiter_precedes_last
508
+ end
509
+
510
+ it 'returns true for two names when option set to always' do
511
+ Names.new(joe, poe).delimiter_always_precedes_last!.should be_delimiter_precedes_last
512
+ end
513
+
514
+ it 'returns true by default for three names' do
515
+ Names.new(joe, poe, plato).should be_delimiter_precedes_last
516
+ end
517
+
518
+ it 'returns false for three names when option set to :never' do
519
+ Names.new(joe, poe, plato).delimiter_never_precedes_last!.should_not be_delimiter_precedes_last
520
+ end
521
+ end
522
+
523
+ describe '#to_bibtex' do
524
+
525
+ describe 'when there is only a single name' do
526
+ it 'prints the name in sort order' do
527
+ Names.new(poe).to_bibtex.should == 'Poe, Edgar Allen'
528
+ end
529
+ end
530
+
531
+ describe 'when there are two or more names' do
532
+ it 'prints the names in sort order connected with the word "and"' do
533
+ Names.new(poe, plato, humboldt).to_bibtex.should == 'Poe, Edgar Allen and Plato and Humboldt, Alexander von'
534
+ end
535
+ end
536
+
537
+ end
538
+
539
+ describe '#to_s' do
540
+
541
+ describe 'when the number of names exceeds the et-al-min option' do
542
+ before do
543
+ gang_of_four.options[:'et-al-min'] = 3
544
+ gang_of_four.options[:'et-al-use-first'] = 2
545
+ gang_of_four.options[:'et-al'] = 'FOO'
546
+ end
547
+
548
+ it 'prints only the et-al-use-first names' do
549
+ gang_of_four.to_s.should match(/gamma.+helm/i)
550
+ gang_of_four.to_s.should_not match(/johnson|vlissides/i)
551
+ end
552
+
553
+ it 'adds et-al at the end' do
554
+ gang_of_four.to_s.should end_with('FOO')
555
+ end
556
+
557
+ it 'adds the delimiter before et-al when multiple names are printed' do
558
+ gang_of_four.to_s.should end_with(', FOO')
559
+ end
560
+
561
+ it 'does not add the delimiter before et-al when only one name is printed' do
562
+ gang_of_four.options[:'et-al-use-first'] = 1
563
+ gang_of_four.to_s.should_not end_with(', FOO')
564
+ end
565
+
566
+ end
567
+
568
+ it 'squeezes multiple whitespace between delimiter and connector' do
569
+ Names.new(poe, humboldt, van_gogh, joe).to_s.should_not match(/\s{2}/)
570
+ end
571
+ end
572
+
573
+ describe '#each' do
574
+ it 'returns an enumerator when no block given' do
575
+ gang_of_four.each.should respond_to(:each)
576
+ end
577
+ end
578
+
579
+ describe '#to_citeproc' do
580
+ it 'returns a list of hashes' do
581
+ gang_of_four.to_citeproc.map(&:class).uniq.should == [Hash]
582
+ end
583
+ end
584
+
585
+ describe 'sorting' do
586
+ it 'accepts other Names instance' do
587
+ (Names.new(poe, plato) <=> Names.new(plato)).should equal(1)
588
+ (Names.new(plato) <=> Names.new(poe, plato)).should equal(-1)
589
+ end
590
+
591
+ it 'accepts other list of names' do
592
+ (Names.new(poe, plato) <=> [plato]).should equal(1)
593
+ (Names.new(plato) <=> [poe, plato]).should equal(-1)
594
+ end
595
+ end
596
+
597
+ describe '#inspect' do
598
+ it 'returns a string' do
599
+ gang_of_four.inspect.should be_a(String)
600
+ end
601
+ end
602
+
603
+ end
604
+
605
+ end
606
+
492
607
  end