citeproc 0.0.8 → 0.0.9

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