sax-machine 0.1.0 → 1.3.2

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.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +32 -0
  5. data/Gemfile +13 -2
  6. data/Guardfile +5 -0
  7. data/HISTORY.md +77 -0
  8. data/README.md +207 -0
  9. data/Rakefile +6 -20
  10. data/lib/sax-machine/{sax_ancestor_config.rb → config/sax_ancestor.rb} +3 -7
  11. data/lib/sax-machine/config/sax_attribute.rb +18 -0
  12. data/lib/sax-machine/config/sax_collection.rb +33 -0
  13. data/lib/sax-machine/{sax_element_config.rb → config/sax_element.rb} +23 -31
  14. data/lib/sax-machine/{sax_element_value_config.rb → config/sax_element_value.rb} +7 -8
  15. data/lib/sax-machine/handlers/sax_abstract_handler.rb +199 -0
  16. data/lib/sax-machine/handlers/sax_nokogiri_handler.rb +23 -0
  17. data/lib/sax-machine/handlers/sax_oga_handler.rb +39 -0
  18. data/lib/sax-machine/handlers/sax_ox_handler.rb +56 -0
  19. data/lib/sax-machine/sax_config.rb +13 -9
  20. data/lib/sax-machine/sax_configure.rb +3 -8
  21. data/lib/sax-machine/sax_document.rb +79 -49
  22. data/lib/sax-machine/version.rb +3 -0
  23. data/lib/sax-machine.rb +26 -7
  24. data/sax-machine.gemspec +20 -0
  25. data/spec/fixtures/atom-content.html +15 -0
  26. data/spec/fixtures/atom.xml +165 -0
  27. data/spec/sax-machine/sax_activerecord_spec.rb +21 -0
  28. data/spec/sax-machine/sax_configure_spec.rb +51 -0
  29. data/spec/sax-machine/sax_document_spec.rb +709 -239
  30. data/spec/sax-machine/sax_include_spec.rb +49 -0
  31. data/spec/spec_helper.rb +18 -7
  32. metadata +71 -70
  33. data/README.textile +0 -110
  34. data/lib/sax-machine/sax_attribute_config.rb +0 -40
  35. data/lib/sax-machine/sax_collection_config.rb +0 -45
  36. data/lib/sax-machine/sax_handler.rb +0 -107
  37. data/spec/sax-machine/configure_sax_machine_spec.rb +0 -53
  38. data/spec/sax-machine/include_sax_machine_spec.rb +0 -42
@@ -1,26 +1,30 @@
1
- require File.dirname(__FILE__) + '/../spec_helper'
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
2
 
3
3
  describe "SAXMachine" do
4
4
  describe "element" do
5
5
  describe "when parsing a single element" do
6
- before :each do
6
+ before do
7
7
  @klass = Class.new do
8
8
  include SAXMachine
9
9
  element :title
10
+ ancestor :body
11
+ value :something, required: false
12
+ attribute :anything, required: true
10
13
  end
11
14
  end
12
15
 
13
- it "should provide an accessor" do
14
- document = @klass.new
15
- document.title = "Title"
16
- document.title.should == "Title"
16
+ it "provides mass assignment through initialize method" do
17
+ document = @klass.new(title: "Title")
18
+ expect(document.title).to eq("Title")
17
19
  end
18
20
 
19
- it "should allow introspection of the elements" do
20
- @klass.column_names.should =~ [:title]
21
+ it "provides an accessor" do
22
+ document = @klass.new
23
+ document.title = "Title"
24
+ expect(document.title).to eq("Title")
21
25
  end
22
26
 
23
- it "should not overwrite the getter is there is already one present" do
27
+ it "does not overwrites the getter is there is already one present" do
24
28
  @klass = Class.new do
25
29
  def title
26
30
  "#{@title} ***"
@@ -29,12 +33,13 @@ describe "SAXMachine" do
29
33
  include SAXMachine
30
34
  element :title
31
35
  end
36
+
32
37
  document = @klass.new
33
38
  document.title = "Title"
34
- document.title.should == "Title ***"
39
+ expect(document.title).to eq("Title ***")
35
40
  end
36
41
 
37
- it "should not overwrite the setter if there is already one present" do
42
+ it "does not overwrites the setter if there is already one present" do
38
43
  @klass = Class.new do
39
44
  def title=(val)
40
45
  @title = "#{val} **"
@@ -43,71 +48,363 @@ describe "SAXMachine" do
43
48
  include SAXMachine
44
49
  element :title
45
50
  end
51
+
46
52
  document = @klass.new
47
53
  document.title = "Title"
48
- document.title.should == "Title **"
49
- end
50
- describe "the class attribute" do
51
- before(:each) do
52
- @klass = Class.new do
53
- include SAXMachine
54
- element :date, :class => DateTime
55
- end
56
- @document = @klass.new
57
- @document.date = DateTime.now.to_s
58
- end
59
- it "should be available" do
60
- @klass.data_class(:date).should == DateTime
61
- end
62
- end
63
- describe "the required attribute" do
64
- it "should be available" do
65
- @klass = Class.new do
66
- include SAXMachine
67
- element :date, :required => true
68
- end
69
- @klass.required?(:date).should be_true
70
- end
54
+ expect(document.title).to eq("Title **")
71
55
  end
72
56
 
73
- it "should not overwrite the accessor when the element is not present" do
57
+ it "does not overwrites the accessor when the element is not present" do
74
58
  document = @klass.new
75
59
  document.title = "Title"
76
60
  document.parse("<foo></foo>")
77
- document.title.should == "Title"
61
+ expect(document.title).to eq("Title")
78
62
  end
79
63
 
80
- it "should overwrite the value when the element is present" do
64
+ it "overwrites the value when the element is present" do
81
65
  document = @klass.new
82
66
  document.title = "Old title"
83
67
  document.parse("<title>New title</title>")
84
- document.title.should == "New title"
68
+ expect(document.title).to eq("New title")
85
69
  end
86
70
 
87
- it "should save the element text into an accessor" do
71
+ it "saves the element text into an accessor" do
88
72
  document = @klass.parse("<title>My Title</title>")
89
- document.title.should == "My Title"
73
+ expect(document.title).to eq("My Title")
74
+ end
75
+
76
+ it "keeps the document encoding for elements" do
77
+ data = "<title>My Title</title>"
78
+ data.encode!("utf-8")
79
+
80
+ document = @klass.parse(data)
81
+ expect(document.title.encoding).to eq(data.encoding)
90
82
  end
91
83
 
92
- it "should save cdata into an accessor" do
84
+ it "saves cdata into an accessor" do
93
85
  document = @klass.parse("<title><![CDATA[A Title]]></title>")
94
- document.title.should == "A Title"
86
+ expect(document.title).to eq("A Title")
95
87
  end
96
88
 
97
- it "should save the element text into an accessor when there are multiple elements" do
89
+ it "saves the element text into an accessor when there are multiple elements" do
98
90
  document = @klass.parse("<xml><title>My Title</title><foo>bar</foo></xml>")
99
- document.title.should == "My Title"
91
+ expect(document.title).to eq("My Title")
100
92
  end
101
93
 
102
- it "should save the first element text when there are multiple of the same element" do
94
+ it "saves the first element text when there are multiple of the same element" do
103
95
  document = @klass.parse("<xml><title>My Title</title><title>bar</title></xml>")
104
- document.title.should == "My Title"
96
+ expect(document.title).to eq("My Title")
97
+ end
98
+
99
+ describe "the introspection" do
100
+ it "allows to get column names" do
101
+ expect(@klass.column_names).to match_array([:title])
102
+ end
103
+
104
+ it "allows to get elements" do
105
+ expect(@klass.sax_config.top_level_elements.values.flatten.map(&:to_s)).to \
106
+ match_array(["name: title dataclass: setter: title= required: value: as:title collection: with: {}"])
107
+ end
108
+
109
+ it "allows to get ancestors" do
110
+ expect(@klass.sax_config.ancestors.map(&:column)).to \
111
+ match_array([:body])
112
+ end
113
+
114
+ it "allows to get values" do
115
+ expect(@klass.sax_config.top_level_element_value.map(&:column)).to \
116
+ match_array([:something])
117
+ expect(@klass.sax_config.top_level_element_value.map(&:required?)).to \
118
+ match_array([false])
119
+ end
120
+
121
+ it "allows to get attributes" do
122
+ expect(@klass.sax_config.top_level_attributes.map(&:column)).to \
123
+ match_array([:anything])
124
+ expect(@klass.sax_config.top_level_attributes.map(&:required?)).to \
125
+ match_array([true])
126
+ expect(@klass.sax_config.top_level_attributes.map(&:collection?)).to \
127
+ match_array([false])
128
+ end
129
+ end
130
+
131
+ describe "the class attribute" do
132
+ before(:each) do
133
+ @klass = Class.new do
134
+ include SAXMachine
135
+ element :date, class: DateTime
136
+ end
137
+
138
+ @document = @klass.new
139
+ @document.date = Time.now.iso8601
140
+ end
141
+
142
+ it "is available" do
143
+ expect(@klass.data_class(:date)).to eq(DateTime)
144
+ end
145
+
146
+ describe "string" do
147
+ before do
148
+ class TestString
149
+ include SAXMachine
150
+ element :number, class: String
151
+ end
152
+
153
+ class TestStringAttribute
154
+ include SAXMachine
155
+ attribute :sub_number, class: String
156
+ end
157
+
158
+ class TestStringWithAttribute
159
+ include SAXMachine
160
+ element :number, class: TestStringAttribute
161
+ end
162
+ end
163
+
164
+ it "is handled in an element" do
165
+ document = TestString.parse("<number>5.5</number>")
166
+ expect(document.number).to eq("5.5")
167
+ end
168
+
169
+ it "is handled in an attribute" do
170
+ document = TestStringWithAttribute.parse("<number sub_number='5.5'></number>")
171
+ expect(document.number.sub_number).to eq("5.5")
172
+ end
173
+ end
174
+
175
+ describe "integer" do
176
+ before do
177
+ class TestInteger
178
+ include SAXMachine
179
+ element :number, class: Integer
180
+ end
181
+
182
+ class TestIntegerAttribute
183
+ include SAXMachine
184
+ attribute :sub_number, class: Integer
185
+ end
186
+
187
+ class TestIntegerWithAttribute
188
+ include SAXMachine
189
+ element :number, class: TestIntegerAttribute
190
+ end
191
+ end
192
+
193
+ it "is handled in an element" do
194
+ document = TestInteger.parse("<number>5</number>")
195
+ expect(document.number).to eq(5)
196
+ end
197
+
198
+ it "is handled in an attribute" do
199
+ document = TestIntegerWithAttribute.parse("<number sub_number='5'></number>")
200
+ expect(document.number.sub_number).to eq(5)
201
+ end
202
+ end
203
+
204
+ describe "float" do
205
+ before do
206
+ class TestFloat
207
+ include SAXMachine
208
+ element :number, class: Float
209
+ end
210
+
211
+ class TestFloatAttribute
212
+ include SAXMachine
213
+ attribute :sub_number, class: Float
214
+ end
215
+
216
+ class TestFloatWithAttribute
217
+ include SAXMachine
218
+ element :number, class: TestFloatAttribute
219
+ end
220
+ end
221
+
222
+ it "is handled in an element with '.' delimiter" do
223
+ document = TestFloat.parse("<number>5.5</number>")
224
+ expect(document.number).to eq(5.5)
225
+ end
226
+
227
+ it "is handled in an element with ',' delimiter" do
228
+ document = TestFloat.parse("<number>5,5</number>")
229
+ expect(document.number).to eq(5.5)
230
+ end
231
+
232
+ it "is handled in an attribute" do
233
+ document = TestFloatWithAttribute.parse("<number sub_number='5.5'>5.5</number>")
234
+ expect(document.number.sub_number).to eq(5.5)
235
+ end
236
+ end
237
+
238
+ describe "symbol" do
239
+ before do
240
+ class TestSymbol
241
+ include SAXMachine
242
+ element :symbol, class: Symbol
243
+ end
244
+
245
+ class TestSymbolAttribute
246
+ include SAXMachine
247
+ attribute :sub_symbol, class: Symbol
248
+ end
249
+
250
+ class TestSymbolWithAttribute
251
+ include SAXMachine
252
+ element :symbol, class: TestSymbolAttribute
253
+ end
254
+ end
255
+
256
+ it "is handled in an element" do
257
+ document = TestSymbol.parse("<symbol>MY_SYMBOL_VALUE</symbol>")
258
+ expect(document.symbol).to eq(:my_symbol_value)
259
+ end
260
+
261
+ it "is handled in an attribute" do
262
+ document = TestSymbolWithAttribute.parse("<symbol sub_symbol='MY_SYMBOL_VALUE'></symbol>")
263
+ expect(document.symbol.sub_symbol).to eq(:my_symbol_value)
264
+ end
265
+ end
266
+
267
+ describe "time" do
268
+ before do
269
+ class TestTime
270
+ include SAXMachine
271
+ element :time, class: Time
272
+ end
273
+
274
+ class TestTimeAttribute
275
+ include SAXMachine
276
+ attribute :sub_time, class: Time
277
+ end
278
+
279
+ class TestTimeWithAttribute
280
+ include SAXMachine
281
+ element :time, class: TestTimeAttribute
282
+ end
283
+ end
284
+
285
+ it "is handled in an element" do
286
+ document = TestTime.parse("<time>1994-02-04T06:20:00Z</time>")
287
+ expect(document.time).to eq(Time.utc(1994, 2, 4, 6, 20, 0, 0))
288
+ end
289
+
290
+ it "is handled in an attribute" do
291
+ document = TestTimeWithAttribute.parse("<time sub_time='1994-02-04T06:20:00Z'>1994-02-04T06:20:00Z</time>")
292
+ expect(document.time.sub_time).to eq(Time.utc(1994, 2, 4, 6, 20, 0, 0))
293
+ end
294
+ end
295
+ end
296
+
297
+ describe "the default attribute" do
298
+ it "is available" do
299
+ @klass = Class.new do
300
+ include SAXMachine
301
+ element :number, class: Integer, default: 0
302
+ end
303
+
304
+ document = @klass.parse("<no>number</no>")
305
+ expect(document.number).to eq(0)
306
+
307
+ document = @klass.parse("<number></number>")
308
+ expect(document.number).to eq(0)
309
+ end
310
+
311
+ it "can be a Boolean" do
312
+ @klass = Class.new do
313
+ include SAXMachine
314
+ element(:bool, default: false) { |v| !!v }
315
+ end
316
+
317
+ document = @klass.parse("<no>bool</no>")
318
+ expect(document.bool).to be false
319
+
320
+ document = @klass.parse("<bool></bool>")
321
+ expect(document.bool).to be false
322
+
323
+ document = @klass.parse("<bool>1</bool>")
324
+ expect(document.bool).to be true
325
+ end
326
+ end
327
+
328
+ describe "the required attribute" do
329
+ it "is available" do
330
+ @klass = Class.new do
331
+ include SAXMachine
332
+ element :date, required: true
333
+ end
334
+ expect(@klass.required?(:date)).to be_truthy
335
+ end
336
+ end
337
+
338
+ describe "the block" do
339
+ before do
340
+ class ElementBlockParser
341
+ include SAXMachine
342
+
343
+ ancestor :parent do |parent|
344
+ parent.class.to_s
345
+ end
346
+
347
+ value :text do |text|
348
+ text.downcase
349
+ end
350
+ end
351
+
352
+ class BlockParser
353
+ include SAXMachine
354
+
355
+ element :title do |title|
356
+ "#{title}!!!"
357
+ end
358
+
359
+ element :scope do |scope|
360
+ "#{title} #{scope}"
361
+ end
362
+
363
+ attribute :id do |id|
364
+ id.to_i
365
+ end
366
+
367
+ element :nested, class: ElementBlockParser
368
+ elements :message, as: :messages do |message|
369
+ "#{message}!"
370
+ end
371
+ end
372
+ end
373
+
374
+ it "has instance as a block context" do
375
+ document = BlockParser.parse("<root><title>SAX</title><scope>something</scope></root>")
376
+ expect(document.scope).to eq("SAX!!! something")
377
+ end
378
+
379
+ it "uses block for element" do
380
+ document = BlockParser.parse("<title>SAX</title>")
381
+ expect(document.title).to eq("SAX!!!")
382
+ end
383
+
384
+ it 'uses block for attribute' do
385
+ document = BlockParser.parse("<title id='345'>SAX</title>")
386
+ expect(document.id).to eq(345)
387
+ end
388
+
389
+ it "uses block for value" do
390
+ document = BlockParser.parse("<title><nested>tEst</nested></title>")
391
+ expect(document.nested.text).to eq("test")
392
+ end
105
393
 
394
+ it "uses block for ancestor" do
395
+ document = BlockParser.parse("<title><nested>SAX</nested></title>")
396
+ expect(document.nested.parent).to eq("BlockParser")
397
+ end
398
+
399
+ it "uses block for elements" do
400
+ document = BlockParser.parse("<title><message>hi</message><message>world</message></title>")
401
+ expect(document.messages).to eq(["hi!", "world!"])
402
+ end
106
403
  end
107
404
  end
108
405
 
109
406
  describe "when parsing multiple elements" do
110
- before :each do
407
+ before do
111
408
  @klass = Class.new do
112
409
  include SAXMachine
113
410
  element :title
@@ -115,14 +412,13 @@ describe "SAXMachine" do
115
412
  end
116
413
  end
117
414
 
118
- it "should save the element text for a second tag" do
415
+ it "saves the element text for a second tag" do
119
416
  document = @klass.parse("<xml><title>My Title</title><name>Paul</name></xml>")
120
- document.name.should == "Paul"
121
- document.title.should == "My Title"
417
+ expect(document.name).to eq("Paul")
418
+ expect(document.title).to eq("My Title")
122
419
  end
123
420
 
124
-
125
- it "should not overwrite the getter is there is already one present" do
421
+ it "does not overwrites the getter is there is already one present" do
126
422
  @klass = Class.new do
127
423
  def items
128
424
  []
@@ -131,12 +427,13 @@ describe "SAXMachine" do
131
427
  include SAXMachine
132
428
  elements :items
133
429
  end
430
+
134
431
  document = @klass.new
135
432
  document.items = [1, 2, 3, 4]
136
- document.items.should == []
433
+ expect(document.items).to eq([])
137
434
  end
138
435
 
139
- it "should not overwrite the setter if there is already one present" do
436
+ it "does not overwrites the setter if there is already one present" do
140
437
  @klass = Class.new do
141
438
  def items=(val)
142
439
  @items = [1, *val]
@@ -145,226 +442,255 @@ describe "SAXMachine" do
145
442
  include SAXMachine
146
443
  elements :items
147
444
  end
445
+
148
446
  document = @klass.new
149
447
  document.items = [2, 3]
150
- document.items.should == [1, 2, 3]
448
+ expect(document.items).to eq([1, 2, 3])
151
449
  end
152
-
153
450
  end
154
451
 
155
452
  describe "when using options for parsing elements" do
156
453
  describe "using the 'as' option" do
157
- before :each do
454
+ before do
158
455
  @klass = Class.new do
159
456
  include SAXMachine
160
- element :description, :as => :summary
457
+ element :description, as: :summary
161
458
  end
162
459
  end
163
460
 
164
- it "should provide an accessor using the 'as' name" do
461
+ it "provides an accessor using the 'as' name" do
165
462
  document = @klass.new
166
463
  document.summary = "a small summary"
167
- document.summary.should == "a small summary"
464
+ expect(document.summary).to eq("a small summary")
168
465
  end
169
466
 
170
- it "should save the element text into the 'as' accessor" do
467
+ it "saves the element text into the 'as' accessor" do
171
468
  document = @klass.parse("<description>here is a description</description>")
172
- document.summary.should == "here is a description"
469
+ expect(document.summary).to eq("here is a description")
173
470
  end
174
471
  end
175
472
 
176
473
  describe "using the :with option" do
177
474
  describe "and the :value option" do
178
- before :each do
475
+ before do
179
476
  @klass = Class.new do
180
477
  include SAXMachine
181
- element :link, :value => :href, :with => {:foo => "bar"}
478
+ element :link, value: :href, with: { foo: "bar" }
182
479
  end
183
480
  end
184
481
 
185
- it "should save the value of a matching element" do
482
+ it "saves the value of a matching element" do
186
483
  document = @klass.parse("<link href='test' foo='bar'>asdf</link>")
187
- document.link.should == "test"
484
+ expect(document.link).to eq("test")
188
485
  end
189
486
 
190
- it "should save the value of the first matching element" do
487
+ it "saves the value of the first matching element" do
191
488
  document = @klass.parse("<xml><link href='first' foo='bar' /><link href='second' foo='bar' /></xml>")
192
- document.link.should == "first"
489
+ expect(document.link).to eq("first")
193
490
  end
194
491
 
195
492
  describe "and the :as option" do
196
- before :each do
493
+ before do
197
494
  @klass = Class.new do
198
495
  include SAXMachine
199
- element :link, :value => :href, :as => :url, :with => {:foo => "bar"}
200
- element :link, :value => :href, :as => :second_url, :with => {:asdf => "jkl"}
496
+ element :link, value: :href, as: :url, with: { foo: "bar" }
497
+ element :link, value: :href, as: :second_url, with: { asdf: "jkl" }
201
498
  end
202
499
  end
203
500
 
204
- it "should save the value of the first matching element" do
501
+ it "saves the value of the first matching element" do
205
502
  document = @klass.parse("<xml><link href='first' foo='bar' /><link href='second' asdf='jkl' /><link href='second' foo='bar' /></xml>")
206
- document.url.should == "first"
207
- document.second_url.should == "second"
503
+ expect(document.url).to eq("first")
504
+ expect(document.second_url).to eq("second")
208
505
  end
209
-
210
506
  end
211
507
  end
212
508
 
213
509
  describe "with only one element" do
214
- before :each do
510
+ before do
215
511
  @klass = Class.new do
216
512
  include SAXMachine
217
- element :link, :with => {:foo => "bar"}
513
+ element :link, with: { foo: "bar" }
218
514
  end
219
515
  end
220
516
 
221
- it "should save the text of an element that has matching attributes" do
517
+ it "saves the text of an element that has matching attributes" do
222
518
  document = @klass.parse("<link foo=\"bar\">match</link>")
223
- document.link.should == "match"
519
+ expect(document.link).to eq("match")
224
520
  end
225
521
 
226
- it "should not save the text of an element that doesn't have matching attributes" do
522
+ it "does not saves the text of an element that doesn't have matching attributes" do
227
523
  document = @klass.parse("<link>no match</link>")
228
- document.link.should be_nil
524
+ expect(document.link).to be_nil
229
525
  end
230
526
 
231
- it "should save the text of an element that has matching attributes when it is the second of that type" do
527
+ it "saves the text of an element that has matching attributes when it is the second of that type" do
232
528
  document = @klass.parse("<xml><link>no match</link><link foo=\"bar\">match</link></xml>")
233
- document.link.should == "match"
234
-
529
+ expect(document.link).to eq("match")
235
530
  end
236
531
 
237
- it "should save the text of an element that has matching attributes plus a few more" do
532
+ it "saves the text of an element that has matching attributes plus a few more" do
238
533
  document = @klass.parse("<xml><link>no match</link><link asdf='jkl' foo='bar'>match</link>")
239
- document.link.should == "match"
534
+ expect(document.link).to eq("match")
240
535
  end
241
536
  end
242
537
 
243
538
  describe "with multiple elements of same tag" do
244
- before :each do
539
+ before do
245
540
  @klass = Class.new do
246
541
  include SAXMachine
247
- element :link, :as => :first, :with => {:foo => "bar"}
248
- element :link, :as => :second, :with => {:asdf => "jkl"}
542
+ element :link, as: :first, with: { foo: "bar" }
543
+ element :link, as: :second, with: { asdf: "jkl" }
249
544
  end
250
545
  end
251
546
 
252
- it "should match the first element" do
547
+ it "matches the first element" do
253
548
  document = @klass.parse("<xml><link>no match</link><link foo=\"bar\">first match</link><link>no match</link></xml>")
254
- document.first.should == "first match"
549
+ expect(document.first).to eq("first match")
255
550
  end
256
551
 
257
- it "should match the second element" do
552
+ it "matches the second element" do
258
553
  document = @klass.parse("<xml><link>no match</link><link foo='bar'>first match</link><link asdf='jkl'>second match</link><link>hi</link></xml>")
259
- document.second.should == "second match"
554
+ expect(document.second).to eq("second match")
555
+ end
556
+ end
557
+
558
+ describe "with only one element as a regular expression" do
559
+ before do
560
+ @klass = Class.new do
561
+ include SAXMachine
562
+ element :link, with: { foo: /ar$/ }
563
+ end
564
+ end
565
+
566
+ it "saves the text of an element that has matching attributes" do
567
+ document = @klass.parse("<link foo=\"bar\">match</link>")
568
+ expect(document.link).to eq("match")
569
+ end
570
+
571
+ it "does not saves the text of an element that doesn't have matching attributes" do
572
+ document = @klass.parse("<link>no match</link>")
573
+ expect(document.link).to be_nil
574
+ end
575
+
576
+ it "saves the text of an element that has matching attributes when it is the second of that type" do
577
+ document = @klass.parse("<xml><link>no match</link><link foo=\"bar\">match</link></xml>")
578
+ expect(document.link).to eq("match")
579
+ end
580
+
581
+ it "saves the text of an element that has matching attributes plus a few more" do
582
+ document = @klass.parse("<xml><link>no match</link><link asdf='jkl' foo='bar'>match</link>")
583
+ expect(document.link).to eq("match")
260
584
  end
261
585
  end
262
- end # using the 'with' option
586
+ end
263
587
 
264
588
  describe "using the 'value' option" do
265
- before :each do
589
+ before do
266
590
  @klass = Class.new do
267
591
  include SAXMachine
268
- element :link, :value => :foo
592
+ element :link, value: :foo
269
593
  end
270
594
  end
271
595
 
272
- it "should save the attribute value" do
596
+ it "saves the attribute value" do
273
597
  document = @klass.parse("<link foo='test'>hello</link>")
274
- document.link.should == 'test'
598
+ expect(document.link).to eq("test")
275
599
  end
276
600
 
277
- it "should save the attribute value when there is no text enclosed by the tag" do
601
+ it "saves the attribute value when there is no text enclosed by the tag" do
278
602
  document = @klass.parse("<link foo='test'></link>")
279
- document.link.should == 'test'
603
+ expect(document.link).to eq("test")
280
604
  end
281
605
 
282
- it "should save the attribute value when the tag close is in the open" do
606
+ it "saves the attribute value when the tag close is in the open" do
283
607
  document = @klass.parse("<link foo='test'/>")
284
- document.link.should == 'test'
608
+ expect(document.link).to eq("test")
285
609
  end
286
610
 
287
- it "should save two different attribute values on a single tag" do
611
+ it "saves two different attribute values on a single tag" do
288
612
  @klass = Class.new do
289
613
  include SAXMachine
290
- element :link, :value => :foo, :as => :first
291
- element :link, :value => :bar, :as => :second
614
+ element :link, value: :foo, as: :first
615
+ element :link, value: :bar, as: :second
292
616
  end
617
+
293
618
  document = @klass.parse("<link foo='foo value' bar='bar value'></link>")
294
- document.first.should == "foo value"
295
- document.second.should == "bar value"
619
+ expect(document.first).to eq("foo value")
620
+ expect(document.second).to eq("bar value")
296
621
  end
297
622
 
298
- it "should not fail if one of the attribute hasn't been defined" do
623
+ it "does not fail if one of the attribute hasn't been defined" do
299
624
  @klass = Class.new do
300
625
  include SAXMachine
301
- element :link, :value => :foo, :as => :first
302
- element :link, :value => :bar, :as => :second
626
+ element :link, value: :foo, as: :first
627
+ element :link, value: :bar, as: :second
303
628
  end
629
+
304
630
  document = @klass.parse("<link foo='foo value'></link>")
305
- document.first.should == "foo value"
306
- document.second.should be_nil
631
+ expect(document.first).to eq("foo value")
632
+ expect(document.second).to be_nil
307
633
  end
308
634
  end
309
635
 
310
636
  describe "when desiring both the content and attributes of an element" do
311
- before :each do
637
+ before do
312
638
  @klass = Class.new do
313
639
  include SAXMachine
314
640
  element :link
315
- element :link, :value => :foo, :as => :link_foo
316
- element :link, :value => :bar, :as => :link_bar
641
+ element :link, value: :foo, as: :link_foo
642
+ element :link, value: :bar, as: :link_bar
317
643
  end
318
644
  end
319
645
 
320
- it "should parse the element and attribute values" do
646
+ it "parses the element and attribute values" do
321
647
  document = @klass.parse("<link foo='test1' bar='test2'>hello</link>")
322
- document.link.should == 'hello'
323
- document.link_foo.should == 'test1'
324
- document.link_bar.should == 'test2'
648
+ expect(document.link).to eq("hello")
649
+ expect(document.link_foo).to eq("test1")
650
+ expect(document.link_bar).to eq("test2")
325
651
  end
326
652
  end
327
-
328
653
  end
329
654
  end
330
655
 
331
656
  describe "elements" do
332
657
  describe "when parsing multiple elements" do
333
- before :each do
658
+ before do
334
659
  @klass = Class.new do
335
660
  include SAXMachine
336
- elements :entry, :as => :entries
661
+ elements :entry, as: :entries
337
662
  end
338
663
  end
339
664
 
340
- it "should provide a collection accessor" do
665
+ it "provides a collection accessor" do
341
666
  document = @klass.new
342
667
  document.entries << :foo
343
- document.entries.should == [:foo]
668
+ expect(document.entries).to eq([:foo])
344
669
  end
345
670
 
346
- it "should parse a single element" do
671
+ it "parses a single element" do
347
672
  document = @klass.parse("<entry>hello</entry>")
348
- document.entries.should == ["hello"]
673
+ expect(document.entries).to eq(["hello"])
349
674
  end
350
675
 
351
- it "should parse multiple elements" do
676
+ it "parses multiple elements" do
352
677
  document = @klass.parse("<xml><entry>hello</entry><entry>world</entry></xml>")
353
- document.entries.should == ["hello", "world"]
678
+ expect(document.entries).to eq(["hello", "world"])
354
679
  end
355
680
 
356
- it "should parse multiple elements when taking an attribute value" do
681
+ it "parses multiple elements when taking an attribute value" do
357
682
  attribute_klass = Class.new do
358
683
  include SAXMachine
359
- elements :entry, :as => :entries, :value => :foo
684
+ elements :entry, as: :entries, value: :foo
360
685
  end
686
+
361
687
  doc = attribute_klass.parse("<xml><entry foo='asdf' /><entry foo='jkl' /></xml>")
362
- doc.entries.should == ["asdf", "jkl"]
688
+ expect(doc.entries).to eq(["asdf", "jkl"])
363
689
  end
364
690
  end
365
691
 
366
692
  describe "when using the with and class options" do
367
- before :each do
693
+ before do
368
694
  class Bar
369
695
  include SAXMachine
370
696
  element :title
@@ -377,93 +703,110 @@ describe "SAXMachine" do
377
703
 
378
704
  class Item
379
705
  include SAXMachine
380
-
381
706
  end
707
+
382
708
  @klass = Class.new do
383
709
  include SAXMachine
384
- elements :item, :as => :items, :with => {:type => 'Bar'}, :class => Bar
385
- elements :item, :as => :items, :with => {:type => 'Foo'}, :class => Foo
710
+ elements :item, as: :items, with: { type: "Bar" }, class: Bar
711
+ elements :item, as: :items, with: { type: /Foo/ }, class: Foo
386
712
  end
387
713
  end
388
714
 
389
- it "should cast into the correct class" do
715
+ it "casts into the correct class" do
390
716
  document = @klass.parse("<items><item type=\"Bar\"><title>Bar title</title></item><item type=\"Foo\"><title>Foo title</title></item></items>")
391
- document.items.size.should == 2
392
- document.items.first.should be_a(Bar)
393
- document.items.first.title.should == "Bar title"
394
- document.items.last.should be_a(Foo)
395
- document.items.last.title.should == "Foo title"
717
+ expect(document.items.size).to eq(2)
718
+ expect(document.items.first).to be_a(Bar)
719
+ expect(document.items.first.title).to eq("Bar title")
720
+ expect(document.items.last).to be_a(Foo)
721
+ expect(document.items.last.title).to eq("Foo title")
396
722
  end
397
723
  end
398
724
 
399
725
  describe "when using the class option" do
400
- before :each do
726
+ before do
401
727
  class Foo
402
728
  include SAXMachine
403
729
  element :title
404
730
  end
731
+
405
732
  @klass = Class.new do
406
733
  include SAXMachine
407
- elements :entry, :as => :entries, :class => Foo
734
+ elements :entry, as: :entries, class: Foo
408
735
  end
409
736
  end
410
737
 
411
- it "should parse a single element with children" do
738
+ it "parses a single element with children" do
412
739
  document = @klass.parse("<entry><title>a title</title></entry>")
413
- document.entries.size.should == 1
414
- document.entries.first.title.should == "a title"
740
+ expect(document.entries.size).to eq(1)
741
+ expect(document.entries.first.title).to eq("a title")
415
742
  end
416
743
 
417
- it "should parse multiple elements with children" do
744
+ it "parses multiple elements with children" do
418
745
  document = @klass.parse("<xml><entry><title>title 1</title></entry><entry><title>title 2</title></entry></xml>")
419
- document.entries.size.should == 2
420
- document.entries.first.title.should == "title 1"
421
- document.entries.last.title.should == "title 2"
746
+ expect(document.entries.size).to eq(2)
747
+ expect(document.entries.first.title).to eq("title 1")
748
+ expect(document.entries.last.title).to eq("title 2")
422
749
  end
423
750
 
424
- it "should not parse a top level element that is specified only in a child" do
751
+ it "does not parse a top level element that is specified only in a child" do
425
752
  document = @klass.parse("<xml><title>no parse</title><entry><title>correct title</title></entry></xml>")
426
- document.entries.size.should == 1
427
- document.entries.first.title.should == "correct title"
753
+ expect(document.entries.size).to eq(1)
754
+ expect(document.entries.first.title).to eq("correct title")
428
755
  end
429
756
 
430
- it "should parse elements, and make attributes and inner text available" do
757
+ it "parses elements, and make attributes and inner text available" do
431
758
  class Related
432
759
  include SAXMachine
433
- element 'related', :as=>:item
434
- element 'related', :as=>:attr, :value=>'attr'
760
+ element "related", as: :item
761
+ element "related", as: :attr, value: "attr"
435
762
  end
763
+
436
764
  class Foo
437
- elements 'related', :as=>'items', :class=>Related
765
+ elements "related", as: "items", class: Related
438
766
  end
439
767
 
440
768
  doc = Foo.parse(%{<xml><collection><related attr='baz'>something</related><related>somethingelse</related></collection></xml>})
441
- doc.items.first.should_not be_nil
442
- doc.items.size.should == 2
443
- doc.items.first.item.should == 'something'
444
- doc.items.last.item.should == 'somethingelse'
769
+ expect(doc.items.first).not_to be_nil
770
+ expect(doc.items.size).to eq(2)
771
+ expect(doc.items.first.item).to eq("something")
772
+ expect(doc.items.last.item).to eq("somethingelse")
445
773
  end
446
774
 
447
- it "should parse out an attribute value from the tag that starts the collection" do
775
+ it "parses out an attribute value from the tag that starts the collection" do
448
776
  class Foo
449
- element :entry, :value => :href, :as => :url
777
+ element :entry, value: :href, as: :url
450
778
  end
779
+
451
780
  document = @klass.parse("<xml><entry href='http://pauldix.net'><title>paul</title></entry></xml>")
452
- document.entries.size.should == 1
453
- document.entries.first.title.should == "paul"
454
- document.entries.first.url.should == "http://pauldix.net"
781
+ expect(document.entries.size).to eq(1)
782
+ expect(document.entries.first.title).to eq("paul")
783
+ expect(document.entries.first.url).to eq("http://pauldix.net")
784
+ end
785
+ end
786
+ end
787
+
788
+ describe "when dealing with element names containing dashes" do
789
+ it "converts dashes to underscores" do
790
+ class Dashes
791
+ include SAXMachine
792
+ element :dashed_element
455
793
  end
794
+
795
+ parsed = Dashes.parse("<dashed-element>Text</dashed-element>")
796
+ expect(parsed.dashed_element).to eq "Text"
456
797
  end
457
798
  end
458
799
 
459
800
  describe "full example" do
460
- before :each do
461
- @xml = File.read('spec/sax-machine/atom.xml')
801
+ before do
802
+ @xml = File.read("spec/fixtures/atom.xml")
803
+
462
804
  class AtomEntry
463
805
  include SAXMachine
464
806
  element :title
465
- element :name, :as => :author
466
- element "feedburner:origLink", :as => :url
807
+ element :name, as: :author
808
+ element "feedburner:origLink", as: :url
809
+ element :link, as: :alternate, value: :href, with: { type: "text/html", rel: "alternate" }
467
810
  element :summary
468
811
  element :content
469
812
  element :published
@@ -472,15 +815,25 @@ describe "SAXMachine" do
472
815
  class Atom
473
816
  include SAXMachine
474
817
  element :title
475
- element :link, :value => :href, :as => :url, :with => {:type => "text/html"}
476
- element :link, :value => :href, :as => :feed_url, :with => {:type => "application/atom+xml"}
477
- elements :entry, :as => :entries, :class => AtomEntry
818
+ element :link, value: :href, as: :url, with: { type: "text/html" }
819
+ element :link, value: :href, as: :feed_url, with: { type: "application/atom+xml" }
820
+ elements :entry, as: :entries, class: AtomEntry
478
821
  end
479
- end # before
480
822
 
481
- it "should parse the url" do
482
- f = Atom.parse(@xml)
483
- f.url.should == "http://www.pauldix.net/"
823
+ @feed = Atom.parse(@xml)
824
+ end
825
+
826
+ it "parses the url" do
827
+ expect(@feed.url).to eq("http://www.pauldix.net/")
828
+ end
829
+
830
+ it "parses entry url" do
831
+ expect(@feed.entries.first.url).to eq("http://www.pauldix.net/2008/09/marshal-data-to.html?param1=1&param2=2")
832
+ expect(@feed.entries.first.alternate).to eq("http://feeds.feedburner.com/~r/PaulDixExplainsNothing/~3/383536354/marshal-data-to.html?param1=1&param2=2")
833
+ end
834
+
835
+ it "parses content" do
836
+ expect(@feed.entries.first.content.strip).to eq(File.read("spec/fixtures/atom-content.html").strip)
484
837
  end
485
838
  end
486
839
 
@@ -498,32 +851,35 @@ describe "SAXMachine" do
498
851
  </category>
499
852
  </categories>
500
853
  ]
501
- class CategoryCollection;
502
- end
854
+
855
+ class CategoryCollection; end
856
+
503
857
  class Category
504
858
  include SAXMachine
505
859
  attr_accessor :id
506
- element :category, :value => :id, :as => :id
860
+ element :category, value: :id, as: :id
507
861
  element :title
508
- element :categories, :as => :collection, :class => CategoryCollection
862
+ element :categories, as: :collection, class: CategoryCollection
509
863
  ancestor :ancestor
510
864
  end
865
+
511
866
  class CategoryCollection
512
867
  include SAXMachine
513
- elements :category, :as => :categories, :class => Category
868
+ elements :category, as: :categories, class: Category
514
869
  end
870
+
515
871
  @collection = CategoryCollection.parse(@xml)
516
872
  end
517
873
 
518
- it "should parse the first category" do
519
- @collection.categories.first.id.should == "1"
520
- @collection.categories.first.title.should == "First"
521
- @collection.categories.first.ancestor.should == @collection
874
+ it "parses the first category" do
875
+ expect(@collection.categories.first.id).to eq("1")
876
+ expect(@collection.categories.first.title).to eq("First")
877
+ expect(@collection.categories.first.ancestor).to eq(@collection)
522
878
  end
523
879
 
524
- it "should parse the nested category" do
525
- @collection.categories.first.collection.categories.first.id.should == "2"
526
- @collection.categories.first.collection.categories.first.title.should == "Second"
880
+ it "parses the nested category" do
881
+ expect(@collection.categories.first.collection.categories.first.id).to eq("2")
882
+ expect(@collection.categories.first.collection.categories.first.title).to eq("Second")
527
883
  end
528
884
  end
529
885
 
@@ -541,24 +897,26 @@ describe "SAXMachine" do
541
897
  </category>
542
898
  </categories>
543
899
  ]
900
+
544
901
  class CategoryTree
545
902
  include SAXMachine
546
903
  attr_accessor :id
547
- element :category, :value => :id, :as => :id
904
+ element :category, value: :id, as: :id
548
905
  element :title
549
- elements :category, :as => :categories, :class => CategoryTree
906
+ elements :category, as: :categories, class: CategoryTree
550
907
  end
908
+
551
909
  @collection = CategoryTree.parse(@xml)
552
910
  end
553
911
 
554
- it "should parse the first category" do
555
- @collection.categories.first.id.should == "1"
556
- @collection.categories.first.title.should == "First"
912
+ it "parses the first category" do
913
+ expect(@collection.categories.first.id).to eq("1")
914
+ expect(@collection.categories.first.title).to eq("First")
557
915
  end
558
916
 
559
- it "should parse the nested category" do
560
- @collection.categories.first.categories.first.id.should == "2"
561
- @collection.categories.first.categories.first.title.should == "Second"
917
+ it "parses the nested category" do
918
+ expect(@collection.categories.first.categories.first.id).to eq("2")
919
+ expect(@collection.categories.first.categories.first.title).to eq("Second")
562
920
  end
563
921
  end
564
922
 
@@ -571,21 +929,23 @@ describe "SAXMachine" do
571
929
  </texts>
572
930
  </item>
573
931
  ]
932
+
574
933
  @klass = Class.new do
575
934
  include SAXMachine
576
935
  attr_accessor :id
577
- element :item, :value => "id", :as => :id
936
+ element :item, value: "id", as: :id
578
937
  element :title
579
938
  end
939
+
580
940
  @item = @klass.parse(@xml)
581
941
  end
582
942
 
583
- it "should have an id" do
584
- @item.id.should == "1"
943
+ it "has an id" do
944
+ expect(@item.id).to eq("1")
585
945
  end
586
946
 
587
- it "should have a title" do
588
- @item.title.should == "Hello"
947
+ it "has a title" do
948
+ expect(@item.title).to eq("Hello")
589
949
  end
590
950
  end
591
951
 
@@ -596,28 +956,31 @@ describe "SAXMachine" do
596
956
  <author name="John Doe" role="writer" />
597
957
  </item>
598
958
  ]
959
+
599
960
  class AuthorElement
600
961
  include SAXMachine
601
962
  attribute :name
602
963
  attribute :role
603
964
  end
965
+
604
966
  class ItemElement
605
967
  include SAXMachine
606
- element :author, :class => AuthorElement
968
+ element :author, class: AuthorElement
607
969
  end
970
+
608
971
  @item = ItemElement.parse(@xml)
609
972
  end
610
973
 
611
- it 'should have the child element' do
612
- @item.author.should_not be_nil
974
+ it "has the child element" do
975
+ expect(@item.author).not_to be_nil
613
976
  end
614
977
 
615
- it 'should have the author name' do
616
- @item.author.name.should == 'John Doe'
978
+ it "has the author name" do
979
+ expect(@item.author.name).to eq("John Doe")
617
980
  end
618
981
 
619
- it 'should have the author role' do
620
- @item.author.role.should == 'writer'
982
+ it "has the author role" do
983
+ expect(@item.author.role).to eq("writer")
621
984
  end
622
985
  end
623
986
 
@@ -629,31 +992,34 @@ describe "SAXMachine" do
629
992
  <author name="Jane Doe" role="artist" />
630
993
  </item>
631
994
  ]
995
+
632
996
  class AuthorElement2
633
997
  include SAXMachine
634
998
  attribute :name
635
999
  attribute :role
636
1000
  end
1001
+
637
1002
  class ItemElement2
638
1003
  include SAXMachine
639
- elements :author, :as => :authors, :class => AuthorElement2
1004
+ elements :author, as: :authors, class: AuthorElement2
640
1005
  end
1006
+
641
1007
  @item = ItemElement2.parse(@xml)
642
1008
  end
643
1009
 
644
- it 'should have the child elements' do
645
- @item.authors.should_not be_nil
646
- @item.authors.count.should == 2
1010
+ it "has the child elements" do
1011
+ expect(@item.authors).not_to be_nil
1012
+ expect(@item.authors.count).to eq(2)
647
1013
  end
648
1014
 
649
- it 'should have the author names' do
650
- @item.authors.first.name.should == 'John Doe'
651
- @item.authors.last.name.should == 'Jane Doe'
1015
+ it "has the author names" do
1016
+ expect(@item.authors.first.name).to eq("John Doe")
1017
+ expect(@item.authors.last.name).to eq("Jane Doe")
652
1018
  end
653
1019
 
654
- it 'should have the author roles' do
655
- @item.authors.first.role.should == 'writer'
656
- @item.authors.last.role.should == 'artist'
1020
+ it "has the author roles" do
1021
+ expect(@item.authors.first.role).to eq("writer")
1022
+ expect(@item.authors.last.role).to eq("artist")
657
1023
  end
658
1024
  end
659
1025
 
@@ -664,28 +1030,31 @@ describe "SAXMachine" do
664
1030
  <author role="writer">John Doe</author>
665
1031
  </item>
666
1032
  ]
1033
+
667
1034
  class AuthorElement3
668
1035
  include SAXMachine
669
1036
  value :name
670
1037
  attribute :role
671
1038
  end
1039
+
672
1040
  class ItemElement3
673
1041
  include SAXMachine
674
- element :author, :class => AuthorElement3
1042
+ element :author, class: AuthorElement3
675
1043
  end
1044
+
676
1045
  @item = ItemElement3.parse(@xml)
677
1046
  end
678
1047
 
679
- it 'should have the child elements' do
680
- @item.author.should_not be_nil
1048
+ it "has the child elements" do
1049
+ expect(@item.author).not_to be_nil
681
1050
  end
682
1051
 
683
- it 'should have the author names' do
684
- @item.author.name.should == 'John Doe'
1052
+ it "has the author names" do
1053
+ expect(@item.author.name).to eq("John Doe")
685
1054
  end
686
1055
 
687
- it 'should have the author roles' do
688
- @item.author.role.should == 'writer'
1056
+ it "has the author roles" do
1057
+ expect(@item.author.role).to eq("writer")
689
1058
  end
690
1059
  end
691
1060
 
@@ -698,41 +1067,142 @@ describe "SAXMachine" do
698
1067
  <author role="artist">Jane Doe</author>
699
1068
  </item>
700
1069
  ]
1070
+
701
1071
  class AuthorElement4
702
1072
  include SAXMachine
703
1073
  value :name
704
1074
  attribute :role
705
1075
  end
1076
+
706
1077
  class ItemElement4
707
1078
  include SAXMachine
708
1079
  element :title
709
- elements :author, :as => :authors, :class => AuthorElement4
1080
+ elements :author, as: :authors, class: AuthorElement4
710
1081
 
711
1082
  def title=(blah)
712
- #raise 'woo'
713
1083
  @title = blah
714
1084
  end
715
1085
  end
1086
+
716
1087
  @item = ItemElement4.parse(@xml)
717
1088
  end
718
1089
 
719
- it 'should have the title' do
720
- @item.title.should == 'sweet'
1090
+ it "has the title" do
1091
+ expect(@item.title).to eq("sweet")
1092
+ end
1093
+
1094
+ it "has the child elements" do
1095
+ expect(@item.authors).not_to be_nil
1096
+ expect(@item.authors.count).to eq(2)
1097
+ end
1098
+
1099
+ it "has the author names" do
1100
+ expect(@item.authors.first.name).to eq("John Doe")
1101
+ expect(@item.authors.last.name).to eq("Jane Doe")
721
1102
  end
722
1103
 
723
- it 'should have the child elements' do
724
- @item.authors.should_not be_nil
725
- @item.authors.count.should == 2
1104
+ it "has the author roles" do
1105
+ expect(@item.authors.first.role).to eq("writer")
1106
+ expect(@item.authors.last.role).to eq("artist")
726
1107
  end
1108
+ end
1109
+
1110
+ describe "with multiple elements with the same alias" do
1111
+ let(:item) { ItemElement5.parse(xml) }
1112
+
1113
+ before do
1114
+ class ItemElement5
1115
+ include SAXMachine
1116
+ element :pubDate, as: :published
1117
+ element :"dc:date", as: :published
1118
+ end
1119
+ end
1120
+
1121
+ describe "only first defined" do
1122
+ let(:xml) { "<item xmlns:dc='http://www.example.com'><pubDate>first value</pubDate></item>" }
1123
+
1124
+ it "has first value" do
1125
+ expect(item.published).to eq("first value")
1126
+ end
1127
+ end
1128
+
1129
+ describe "only last defined" do
1130
+ let(:xml) { "<item xmlns:dc='http://www.example.com'><dc:date>last value</dc:date></item>" }
1131
+
1132
+ it "has last value" do
1133
+ expect(item.published).to eq("last value")
1134
+ end
1135
+ end
1136
+
1137
+ describe "both defined" do
1138
+ let(:xml) { "<item xmlns:dc='http://www.example.com'><pubDate>first value</pubDate><dc:date>last value</dc:date></item>" }
1139
+
1140
+ it "has last value" do
1141
+ expect(item.published).to eq("last value")
1142
+ end
1143
+ end
1144
+
1145
+ describe "both defined but order is reversed" do
1146
+ let(:xml) { "<item xmlns:dc='http://www.example.com'><dc:date>last value</dc:date><pubDate>first value</pubDate></item>" }
1147
+
1148
+ it "has first value" do
1149
+ expect(item.published).to eq("first value")
1150
+ end
1151
+ end
1152
+
1153
+ describe "both defined but last is empty" do
1154
+ let(:xml) { "<item xmlns:dc='http://www.example.com'><pubDate>first value</pubDate><dc:date></dc:date></item>" }
1155
+
1156
+ it "has first value" do
1157
+ expect(item.published).to eq("first value")
1158
+ end
1159
+ end
1160
+ end
1161
+
1162
+ describe "with error handling" do
1163
+ before do
1164
+ @xml = %[
1165
+ <item id="1">
1166
+ <title>sweet</title>
1167
+ ]
1168
+
1169
+ class ItemElement5
1170
+ include SAXMachine
1171
+ element :title
1172
+ end
1173
+
1174
+ @errors = []
1175
+ @warnings = []
1176
+ @item = ItemElement5.parse(
1177
+ @xml,
1178
+ ->(x) { @errors << x },
1179
+ ->(x) { @warnings << x },
1180
+ )
1181
+ end
1182
+
1183
+ it "has error" do
1184
+ expect(@errors.uniq.size).to eq(1)
1185
+ end
1186
+
1187
+ it "has no warning" do
1188
+ expect(@warnings.uniq.size).to eq(0)
1189
+ end
1190
+ end
1191
+
1192
+ describe "with io as a input" do
1193
+ before do
1194
+ @io = StringIO.new('<item id="1"><title>sweet</title></item>')
1195
+
1196
+ class IoParser
1197
+ include SAXMachine
1198
+ element :title
1199
+ end
727
1200
 
728
- it 'should have the author names' do
729
- @item.authors.first.name.should == 'John Doe'
730
- @item.authors.last.name.should == 'Jane Doe'
1201
+ @item = ItemElement5.parse(@io)
731
1202
  end
732
1203
 
733
- it 'should have the author roles' do
734
- @item.authors.first.role.should == 'writer'
735
- @item.authors.last.role.should == 'artist'
1204
+ it "parses" do
1205
+ expect(@item.title).to eq("sweet")
736
1206
  end
737
1207
  end
738
1208
  end