citeproc 0.0.2 → 0.0.3

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,36 +3,49 @@ require 'spec_helper'
3
3
  module CiteProc
4
4
  describe Attributes do
5
5
 
6
- before(:each) { Object.instance_eval { include Attributes } }
6
+ before(:all) do
7
+ A = Class.new { include Attributes }
8
+ end
7
9
 
8
- let(:instance) { o = Object.new }
9
- let(:other) { o = Object.new; o.attributes[:foo] = 'bar'; o }
10
+ let(:instance) do
11
+ o = A.new
12
+ o[:bar] = 'foo'
13
+ o
14
+ end
15
+
16
+ let(:other) do
17
+ o = A.new
18
+ o[:foo] = 'bar'
19
+ o
20
+ end
10
21
 
11
22
  it { should_not be_nil }
12
23
 
13
24
  describe '.attr_fields' do
14
25
 
15
- # before(:all) { class Object; attr_fields :value, %w[ is-numeric punctuation-mode ]; end }
26
+ # before(:all) do
27
+ # A.instance_eval { attr_fields :value, %w[ is-numeric punctuation-mode ] }
28
+ # end
16
29
 
17
30
  it 'generates setters for attr_field values' do
18
31
  # pending
19
- # lambda { Object.new.is_numeric }.should_not raise_error
32
+ # lambda { A.new.is_numeric }.should_not raise_error
20
33
  end
21
34
 
22
35
  it 'generates no other setters' do
23
- lambda { Object.new.some_other_value }.should raise_error
36
+ lambda { A.new.some_other_value }.should raise_error
24
37
  end
25
38
  end
26
39
 
27
40
  describe '#merge' do
28
41
 
29
42
  it 'merges non-existent values from other object' do
30
- Object.new.merge(other).attributes[:foo].should == 'bar'
43
+ A.new.merge(other)[:foo].should == 'bar'
31
44
  end
32
45
 
33
- # it 'does not overwrite existing values when merging other object' do
34
- # instance.merge(other)['foo'].should == 'bar'
35
- # end
46
+ it 'does not overwrite existing values when merging other object' do
47
+ instance.merge(other)[:bar].should == 'foo'
48
+ end
36
49
 
37
50
  end
38
51
 
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+
3
+ module CiteProc
4
+
5
+ describe Bibliography do
6
+
7
+ it { should be_empty }
8
+ it { should_not have_errors }
9
+
10
+ describe '#to_citeproc conversion' do
11
+
12
+ it 'returns an array' do
13
+ subject.to_citeproc.should be_a(Array)
14
+ end
15
+
16
+ it 'returns exactly two elements' do
17
+ subject.to_citeproc.should have(2).elements
18
+ end
19
+
20
+ it 'returns formatting options as the first element' do
21
+ subject.to_citeproc.first.should be_a(Hash)
22
+ end
23
+
24
+ describe 'the formatting options' do
25
+ let(:options) { subject.to_citeproc[0] }
26
+
27
+ it 'contains a the error list' do
28
+ options.should have_key('bibliography_errors')
29
+ options['bibliography_errors'].should be_empty
30
+ end
31
+
32
+ end
33
+
34
+ it 'returns the list of references as the second element' do
35
+ subject.to_citeproc.last.should be_a(Array)
36
+ end
37
+
38
+ end
39
+
40
+ describe '.parse (citeproc parser)' do
41
+ let(:js) { <<-JS_END }
42
+ [
43
+ {
44
+ "maxoffset": 0,
45
+ "entryspacing": 0,
46
+ "linespacing": 0,
47
+ "hangingindent": 0,
48
+ "second-field-align": true,
49
+ "bibstart": "<div class=\\"csl-bib-body\\">\\n",
50
+ "bibend": "</div>",
51
+ "bibliography_errors": []
52
+ },
53
+ [
54
+ "<div class=\\"csl-entry\\">Book A</div>",
55
+ "<div class=\\"csl-entry\\">Book C</div>"
56
+ ]
57
+ ]
58
+ JS_END
59
+
60
+ it 'parses citeproc/json strings' do
61
+ b = Bibliography.parse(js)
62
+ b.should be_a(Bibliography)
63
+ b.should have(2).references
64
+ b.should_not have_errors
65
+ b.options[:align].should be true
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+
72
+ end
@@ -0,0 +1,94 @@
1
+ require 'spec_helper'
2
+
3
+ module CiteProc
4
+
5
+ describe 'citation input' do
6
+
7
+ let(:hash) {{
8
+ "citationItems" => [
9
+ {
10
+ "id" => "ITEM-1"
11
+ }
12
+ ],
13
+ "properties" => {
14
+ "noteIndex" => 1
15
+ }
16
+ }}
17
+
18
+ let(:json) { MultiJson.encode(hash) }
19
+
20
+
21
+
22
+ describe CitationData do
23
+
24
+ it { should_not be nil }
25
+ it { should be_empty }
26
+
27
+ it 'has not been processed by default' do
28
+ CitationData.new.should_not be_processed
29
+ end
30
+
31
+ describe '.new' do
32
+
33
+ it 'accepts a citeproc hash' do
34
+ d = CitationData.new(hash)
35
+ d.should be_footnote
36
+ d.should_not be_empty
37
+ d[0].should be_a(CitationItem)
38
+ d.index.should == 1
39
+ end
40
+
41
+ it 'accepts an array of items' do
42
+ CitationData.new([CitationItem.new(:id => 'id')]).should have(1).items
43
+ end
44
+
45
+ it 'accepts an array of hashes' do
46
+ CitationData.new([{:id => 'id'}])[0].should be_a(CitationItem)
47
+ end
48
+
49
+ end
50
+
51
+ describe '#to_citeproc' do
52
+
53
+ it 'returns empty an empty/default citation data element by default' do
54
+ CitationData.new.to_citeproc.should == { 'citationItems' => [], 'properties' => { 'noteIndex' => 0}}
55
+ end
56
+
57
+
58
+ end
59
+
60
+ end
61
+
62
+ describe CitationItem do
63
+
64
+ it { should_not be nil }
65
+ it { should be_empty }
66
+
67
+ describe '.new' do
68
+
69
+ it 'accepts a hash as input' do
70
+ CitationItem.new(:label => 'chapter').should have_label
71
+ end
72
+
73
+ end
74
+
75
+ describe '#to_citeproc' do
76
+
77
+ it 'returns empty citation data by default' do
78
+ CitationItem.new.to_citeproc.should == {}
79
+ end
80
+
81
+ it 'returns a hash with stringified keys' do
82
+ CitationItem.new(:type => :article).to_citeproc.should have_key('type')
83
+ end
84
+
85
+ it 'returns a hash with stringified values' do
86
+ CitationItem.new(:type => :article).to_citeproc.should have_value('article')
87
+ end
88
+
89
+ end
90
+
91
+ end
92
+
93
+ end
94
+ end
@@ -3,6 +3,15 @@ require 'spec_helper'
3
3
  module CiteProc
4
4
  describe Date do
5
5
 
6
+ let(:ad2k) { Date.create('date-parts' => [[2000]])}
7
+ let(:may) { Date.create('date-parts' => [[2000, 5]])}
8
+ let(:first_of_may) { Date.create('date-parts' => [[2000, 5, 1]])}
9
+
10
+ let(:bc100) { Date.create('date-parts' => [[-100]]) }
11
+ let(:bc50) { Date.create('date-parts' => [[-50]]) }
12
+ let(:ad50) { Date.create('date-parts' => [[50]]) }
13
+ let(:ad100) { Date.create('date-parts' => [[100]]) }
14
+
6
15
  it { should_not be nil }
7
16
 
8
17
  it { should_not be_numeric }
@@ -11,6 +20,18 @@ module CiteProc
11
20
 
12
21
  end
13
22
 
23
+ describe '.parse' do
24
+
25
+ it 'returns nil by default' do
26
+ Date.parse('').should be nil
27
+ Date.parse(nil).should be nil
28
+ end
29
+
30
+ it 'parses date strings' do
31
+ Date.parse('2004-10-26').year.should == 2004
32
+ end
33
+ end
34
+
14
35
  describe '.create' do
15
36
  it 'should accept parameters and return a new instance' do
16
37
  Date.create('date-parts' => [[2001, 1]]).year.should == 2001
@@ -40,15 +61,6 @@ module CiteProc
40
61
 
41
62
  describe 'sorting' do
42
63
 
43
- let(:ad2k) { Date.create('date-parts' => [[2000]])}
44
- let(:may) { Date.create('date-parts' => [[2000, 5]])}
45
- let(:first_of_may) { Date.create('date-parts' => [[2000, 5, 1]])}
46
-
47
- let(:bc100) { Date.create('date-parts' => [[-100]]) }
48
- let(:bc50) { Date.create('date-parts' => [[-50]]) }
49
- let(:ad50) { Date.create('date-parts' => [[50]]) }
50
- let(:ad100) { Date.create('date-parts' => [[100]]) }
51
-
52
64
  it 'dates with more date-parts will come after those with fewer parts' do
53
65
  (ad2k < may && may < first_of_may).should be true
54
66
  end
@@ -65,6 +77,50 @@ module CiteProc
65
77
  end
66
78
  end
67
79
 
80
+ describe 'b.c. and a.d.' do
81
+
82
+ it 'the year 993 is a.d.' do
83
+ Date.new(993).should be_ad
84
+ end
85
+
86
+ it 'the year 1000 is not a.d.' do
87
+ Date.new(1000).should_not be_ad
88
+ end
89
+
90
+ it 'the year 993 is not b.c.' do
91
+ Date.new(993).should_not be_bc
92
+ end
93
+
94
+ it 'the year 0 is a.d.' do
95
+ Date.new(0).should be_ad
96
+ end
97
+
98
+ it 'the year 0 is not b.c.' do
99
+ Date.new(0).should_not be_bc
100
+ end
101
+
102
+ it 'the year -33 is not a.d.' do
103
+ Date.new(-33).should_not be_ad
104
+ end
105
+
106
+ it 'the year -33 is b.c.' do
107
+ Date.new(-33).should be_bc
108
+ end
109
+
110
+ it 'today is not a.d.' do
111
+ Date.today.should_not be_ad
112
+ end
113
+
114
+ it 'today is not b.c.' do
115
+ Date.today.should_not be_bc
116
+ end
117
+
118
+ it 'the year 2000 is not a.d.' do
119
+ ad2k.should_not be_ad
120
+ end
121
+
122
+ end
123
+
68
124
  describe '#to_json' do
69
125
  it 'supports simple parts' do
70
126
  Date.new(%w{2000 1 15}).to_json.should == '{"date-parts":[[2000,1,15]]}'
@@ -53,4 +53,37 @@ describe Hash do
53
53
  end
54
54
 
55
55
  end
56
+
57
+ end
58
+
59
+ describe Array do
60
+
61
+ describe '#compact_join' do
62
+
63
+ it 'is equivalent to #join when there are no blank elements' do
64
+ [1,2,3].compact_join(' ').should == [1,2,3].join(' ')
65
+ end
66
+
67
+ it 'is equivalent to #compact and #join when there are no empty elements' do
68
+ [1,2,3,nil,nil,4].compact_join(' ').should == [1,2,3,nil,nil,4].compact.join(' ')
69
+ end
70
+
71
+ it 'returns an empty string if the array is empty' do
72
+ [].compact_join(' ').should == ''
73
+ end
74
+
75
+ it 'returns an empty string if there are only nil elements' do
76
+ [nil,nil,nil].compact_join(' ').should == ''
77
+ end
78
+
79
+ it 'returns an empty string if there are only empty elements' do
80
+ ['','',''].compact_join(' ').should == ''
81
+ end
82
+
83
+ it 'returns an empty string if there are only blank elements' do
84
+ ['','',nil,'',nil].compact_join(' ').should == ''
85
+ end
86
+
87
+ end
88
+
56
89
  end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ module CiteProc
4
+ describe Item do
5
+
6
+ it { should_not be nil }
7
+ it { should be_empty }
8
+
9
+ describe '.new' do
10
+
11
+ it 'creates number variables for number fields' do
12
+ Item.new(:edition => 23).edition.should be_a(Number)
13
+ end
14
+
15
+ it 'creates text variable for text fields' do
16
+ Item.new(:ISBN => 23).isbn.should be_a(Text)
17
+ end
18
+
19
+ it 'creates date variables for date fields' do
20
+ Item.new(:accessed => Time.now).accessed.should be_a(CiteProc::Date)
21
+ end
22
+
23
+ it 'creates names variables for name fields' do
24
+ Item.new(:editor => { :given => 'Jane' }).editor.should be_a(Names)
25
+ end
26
+
27
+ it 'creates text variables for unknown fields' do
28
+ v = Item.new(:unknown => 42)[:unknown]
29
+ v.should be_a(Variable)
30
+ v.should == '42'
31
+ end
32
+
33
+ end
34
+
35
+ describe '#to_citeproc' do
36
+
37
+ it 'returns an empty hash by default' do
38
+ Item.new.to_citeproc.should == {}
39
+ end
40
+
41
+ it 'returns a hash with stringified keys' do
42
+ Item.new(:issue => 42).to_citeproc.should have_key('issue')
43
+ end
44
+
45
+ it 'returns a hash with stringified values' do
46
+ Item.new(:issue => 42).to_citeproc.values[0].should == '42'
47
+ end
48
+
49
+
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,492 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
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
+
492
+ end