multi_xml 0.2.2 → 0.3.0

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.

Potentially problematic release.


This version of multi_xml might be problematic. Click here for more details.

@@ -0,0 +1,550 @@
1
+ shared_examples_for "a parser" do |parser|
2
+
3
+ before do
4
+ begin
5
+ MultiXml.parser = parser
6
+ rescue LoadError
7
+ pending "Parser #{parser} couldn't be loaded"
8
+ end
9
+ end
10
+
11
+ describe ".parse" do
12
+ context "a blank string" do
13
+ before do
14
+ @xml = ''
15
+ end
16
+
17
+ it "should return an empty Hash" do
18
+ MultiXml.parse(@xml).should == {}
19
+ end
20
+ end
21
+
22
+ context "a whitespace string" do
23
+ before do
24
+ @xml = ' '
25
+ end
26
+
27
+ it "should return an empty Hash" do
28
+ MultiXml.parse(@xml).should == {}
29
+ end
30
+ end
31
+
32
+ context "an invalid XML document" do
33
+ before do
34
+ @xml = '<open></close>'
35
+ end
36
+
37
+ it "should raise MultiXml::ParseError" do
38
+ lambda do
39
+ MultiXml.parse(@xml)
40
+ end.should raise_error(MultiXml::ParseError)
41
+ end
42
+ end
43
+
44
+ context "a valid XML document" do
45
+ before do
46
+ @xml = '<user/>'
47
+ end
48
+
49
+ it "should parse correctly" do
50
+ MultiXml.parse(@xml).should == {'user' => nil}
51
+ end
52
+
53
+ context "with CDATA" do
54
+ before do
55
+ @xml = '<user><![CDATA[Erik Michaels-Ober]]></user>'
56
+ end
57
+
58
+ it "should return the correct CDATA" do
59
+ MultiXml.parse(@xml)['user'].should == "Erik Michaels-Ober"
60
+ end
61
+ end
62
+
63
+ context "with content" do
64
+ before do
65
+ @xml = '<user>Erik Michaels-Ober</user>'
66
+ end
67
+
68
+ it "should return the correct content" do
69
+ MultiXml.parse(@xml)['user'].should == "Erik Michaels-Ober"
70
+ end
71
+ end
72
+
73
+ context "with an attribute" do
74
+ before do
75
+ @xml = '<user name="Erik Michaels-Ober"/>'
76
+ end
77
+
78
+ it "should return the correct attribute" do
79
+ MultiXml.parse(@xml)['user']['name'].should == "Erik Michaels-Ober"
80
+ end
81
+ end
82
+
83
+ context "with multiple attributes" do
84
+ before do
85
+ @xml = '<user name="Erik Michaels-Ober" screen_name="sferik"/>'
86
+ end
87
+
88
+ it "should return the correct attributes" do
89
+ MultiXml.parse(@xml)['user']['name'].should be == "Erik Michaels-Ober"
90
+ MultiXml.parse(@xml)['user']['screen_name'].should be == "sferik"
91
+ end
92
+ end
93
+
94
+ context "with :symbolize_keys => true" do
95
+ before do
96
+ @xml = '<user><name>Erik Michaels-Ober</name></user>'
97
+ end
98
+
99
+ it "should symbolize keys" do
100
+ MultiXml.parse(@xml, :symbolize_keys => true).should == {:user => {:name => "Erik Michaels-Ober"}}
101
+ end
102
+ end
103
+
104
+ context "when value is true" do
105
+ before do
106
+ pending
107
+ @xml = '<tag>true</tag>'
108
+ end
109
+
110
+ it "should return true" do
111
+ MultiXml.parse(@xml)['tag'].should be_true
112
+ end
113
+ end
114
+
115
+ context "when value is false" do
116
+ before do
117
+ pending
118
+ @xml = '<tag>false</tag>'
119
+ end
120
+
121
+ it "should return false" do
122
+ MultiXml.parse(@xml)['tag'].should be_false
123
+ end
124
+ end
125
+
126
+ context "when key is id" do
127
+ before do
128
+ pending
129
+ @xml = '<id>1</id>'
130
+ end
131
+
132
+ it "should return a Fixnum" do
133
+ MultiXml.parse(@xml)['id'].should be_a(Fixnum)
134
+ end
135
+
136
+ it "should return the correct number" do
137
+ MultiXml.parse(@xml)['id'].should == 1
138
+ end
139
+ end
140
+
141
+ context "when key contains _id" do
142
+ before do
143
+ pending
144
+ @xml = '<tag_id>1</tag_id>'
145
+ end
146
+
147
+ it "should return a Fixnum" do
148
+ MultiXml.parse(@xml)['tag_id'].should be_a(Fixnum)
149
+ end
150
+
151
+ it "should return the correct number" do
152
+ MultiXml.parse(@xml)['tag_id'].should == 1
153
+ end
154
+ end
155
+
156
+ context "with an attribute type=\"boolean\"" do
157
+ %w(true false).each do |boolean|
158
+ context "when #{boolean}" do
159
+ it "should return #{boolean}" do
160
+ xml = "<tag type=\"boolean\">#{boolean}</tag>"
161
+ MultiXml.parse(xml)['tag'].should instance_eval("be_#{boolean}")
162
+ end
163
+ end
164
+ end
165
+
166
+ context "when 1" do
167
+ before do
168
+ @xml = '<tag type="boolean">1</tag>'
169
+ end
170
+
171
+ it "should return true" do
172
+ MultiXml.parse(@xml)['tag'].should be_true
173
+ end
174
+ end
175
+
176
+ context "when 0" do
177
+ before do
178
+ @xml = '<tag type="boolean">0</tag>'
179
+ end
180
+
181
+ it "should return false" do
182
+ MultiXml.parse(@xml)['tag'].should be_false
183
+ end
184
+ end
185
+ end
186
+
187
+ context "with an attribute type=\"integer\"" do
188
+ context "with a positive integer" do
189
+ before do
190
+ @xml = '<tag type="integer">1</tag>'
191
+ end
192
+
193
+ it "should return a Fixnum" do
194
+ MultiXml.parse(@xml)['tag'].should be_a(Fixnum)
195
+ end
196
+
197
+ it "should return a positive number" do
198
+ MultiXml.parse(@xml)['tag'].should > 0
199
+ end
200
+
201
+ it "should return the correct number" do
202
+ MultiXml.parse(@xml)['tag'].should == 1
203
+ end
204
+ end
205
+
206
+ context "with a negative integer" do
207
+ before do
208
+ @xml = '<tag type="integer">-1</tag>'
209
+ end
210
+
211
+ it "should return a Fixnum" do
212
+ MultiXml.parse(@xml)['tag'].should be_a(Fixnum)
213
+ end
214
+
215
+ it "should return a negative number" do
216
+ MultiXml.parse(@xml)['tag'].should < 0
217
+ end
218
+
219
+ it "should return the correct number" do
220
+ MultiXml.parse(@xml)['tag'].should == -1
221
+ end
222
+ end
223
+ end
224
+
225
+ context "with an attribute type=\"string\"" do
226
+ before do
227
+ @xml = '<tag type="string"></tag>'
228
+ end
229
+
230
+ it "should return a String" do
231
+ MultiXml.parse(@xml)['tag'].should be_a(String)
232
+ end
233
+
234
+ it "should return the correct string" do
235
+ MultiXml.parse(@xml)['tag'].should == ""
236
+ end
237
+ end
238
+
239
+ context "with an attribute type=\"date\"" do
240
+ before do
241
+ @xml = '<tag type="date">1970-01-01</tag>'
242
+ end
243
+
244
+ it "should return a Date" do
245
+ MultiXml.parse(@xml)['tag'].should be_a(Date)
246
+ end
247
+
248
+ it "should return the correct date" do
249
+ MultiXml.parse(@xml)['tag'].should == Date.parse('1970-01-01')
250
+ end
251
+ end
252
+
253
+ context "with an attribute type=\"datetime\"" do
254
+ before do
255
+ @xml = '<tag type="datetime">1970-01-01 00:00</tag>'
256
+ end
257
+
258
+ it "should return a Time" do
259
+ MultiXml.parse(@xml)['tag'].should be_a(Time)
260
+ end
261
+
262
+ it "should return the correct time" do
263
+ MultiXml.parse(@xml)['tag'].should == Time.parse('1970-01-01 00:00')
264
+ end
265
+ end
266
+
267
+ context "with an attribute type=\"dateTime\"" do
268
+ before do
269
+ @xml = '<tag type="datetime">1970-01-01 00:00</tag>'
270
+ end
271
+
272
+ it "should return a Time" do
273
+ MultiXml.parse(@xml)['tag'].should be_a(Time)
274
+ end
275
+
276
+ it "should return the correct time" do
277
+ MultiXml.parse(@xml)['tag'].should == Time.parse('1970-01-01 00:00')
278
+ end
279
+ end
280
+
281
+ context "with an attribute type=\"double\"" do
282
+ before do
283
+ @xml = '<tag type="double">3.14159265358979</tag>'
284
+ end
285
+
286
+ it "should return a Float" do
287
+ MultiXml.parse(@xml)['tag'].should be_a(Float)
288
+ end
289
+
290
+ it "should return the correct number" do
291
+ MultiXml.parse(@xml)['tag'].should == 3.14159265358979
292
+ end
293
+ end
294
+
295
+ context "with an attribute type=\"decimal\"" do
296
+ before do
297
+ @xml = '<tag type="decimal">3.14159265358979323846264338327950288419716939937510</tag>'
298
+ end
299
+
300
+ it "should return a BigDecimal" do
301
+ MultiXml.parse(@xml)['tag'].should be_a(BigDecimal)
302
+ end
303
+
304
+ it "should return the correct number" do
305
+ MultiXml.parse(@xml)['tag'].should == 3.14159265358979323846264338327950288419716939937510
306
+ end
307
+ end
308
+
309
+ context "with an attribute type=\"base64Binary\"" do
310
+ before do
311
+ @xml = '<tag type="base64Binary">aW1hZ2UucG5n</tag>'
312
+ end
313
+
314
+ it "should return a String" do
315
+ MultiXml.parse(@xml)['tag'].should be_a(String)
316
+ end
317
+
318
+ it "should return the correct string" do
319
+ MultiXml.parse(@xml)['tag'].should == "image.png"
320
+ end
321
+ end
322
+
323
+ context "with an attribute type=\"yaml\"" do
324
+ before do
325
+ @xml = "<tag type=\"yaml\">--- \n1: should return an integer\n:message: Have a nice day\narray: \n- should-have-dashes: true\n should_have_underscores: true\n</tag>"
326
+ end
327
+
328
+ it "should return a Hash" do
329
+ MultiXml.parse(@xml)['tag'].should be_a(Hash)
330
+ end
331
+
332
+ it "should return the correctly parsed YAML" do
333
+ MultiXml.parse(@xml)['tag'].should == {:message => "Have a nice day", 1 => "should return an integer", "array" => [{"should-have-dashes" => true, "should_have_underscores" => true}]}
334
+ end
335
+ end
336
+
337
+ context "with an attribute type=\"file\"" do
338
+ before do
339
+ @xml = '<tag type="file" name="data.txt" content_type="text/plain">ZGF0YQ==</tag>'
340
+ end
341
+
342
+ it "should return a StringIO" do
343
+ MultiXml.parse(@xml)['tag'].should be_a(StringIO)
344
+ end
345
+
346
+ it "should be decoded correctly" do
347
+ MultiXml.parse(@xml)['tag'].string.should == 'data'
348
+ end
349
+
350
+ it "should have the correct file name" do
351
+ MultiXml.parse(@xml)['tag'].original_filename.should == 'data.txt'
352
+ end
353
+
354
+ it "should have the correct content type" do
355
+ MultiXml.parse(@xml)['tag'].content_type.should == 'text/plain'
356
+ end
357
+
358
+ context "with missing name and content type" do
359
+ before do
360
+ @xml = '<tag type="file">ZGF0YQ==</tag>'
361
+ end
362
+
363
+ it "should return a StringIO" do
364
+ MultiXml.parse(@xml)['tag'].should be_a(StringIO)
365
+ end
366
+
367
+ it "should be decoded correctly" do
368
+ MultiXml.parse(@xml)['tag'].string.should == 'data'
369
+ end
370
+
371
+ it "should have the default file name" do
372
+ MultiXml.parse(@xml)['tag'].original_filename.should == 'untitled'
373
+ end
374
+
375
+ it "should have the default content type" do
376
+ MultiXml.parse(@xml)['tag'].content_type.should == 'application/octet-stream'
377
+ end
378
+ end
379
+ end
380
+
381
+ context "with an attribute type=\"array\"" do
382
+ before do
383
+ @xml = '<users type="array"><user>Erik Michaels-Ober</user><user>Wynn Netherland</user></users>'
384
+ end
385
+
386
+ it "should return an Array" do
387
+ MultiXml.parse(@xml)['users'].should be_a(Array)
388
+ end
389
+
390
+ it "should return the correct array" do
391
+ MultiXml.parse(@xml)['users'].should == ["Erik Michaels-Ober", "Wynn Netherland"]
392
+ end
393
+ end
394
+
395
+ %w(integer boolean date datetime yaml file).each do |type|
396
+ context "with an empty attribute type=\"#{type}\"" do
397
+ before do
398
+ @xml = "<tag type=\"#{type}\"/>"
399
+ end
400
+
401
+ it "should return nil" do
402
+ MultiXml.parse(@xml)['tag'].should be_nil
403
+ end
404
+ end
405
+ end
406
+
407
+ context "with an empty attribute type=\"array\"" do
408
+ before do
409
+ @xml = '<tag type="array"/>'
410
+ end
411
+
412
+ it "should return an empty Array" do
413
+ MultiXml.parse(@xml)['tag'].should == []
414
+ end
415
+
416
+ context "with whitespace" do
417
+ before do
418
+ @xml = '<tag type="array"> </tag>'
419
+ end
420
+
421
+ it "should return an empty Array" do
422
+ MultiXml.parse(@xml)['tag'].should == []
423
+ end
424
+ end
425
+ end
426
+
427
+ context "with XML entities" do
428
+ before do
429
+ @xml_entities = {
430
+ "<" => "&lt;",
431
+ ">" => "&gt;",
432
+ '"' => "&quot;",
433
+ "'" => "&apos;",
434
+ "&" => "&amp;"
435
+ }
436
+ end
437
+
438
+ context "in content" do
439
+ it "should return unescaped XML entities" do
440
+ @xml_entities.each do |key, value|
441
+ xml = "<tag>#{value}</tag>"
442
+ MultiXml.parse(xml)['tag'].should == key
443
+ end
444
+ end
445
+ end
446
+
447
+ context "in attribute" do
448
+ it "should return unescaped XML entities" do
449
+ @xml_entities.each do |key, value|
450
+ xml = "<tag attribute=\"#{value}\"/>"
451
+ MultiXml.parse(xml)['tag']['attribute'].should == key
452
+ end
453
+ end
454
+ end
455
+ end
456
+
457
+ context "with dasherized tag" do
458
+ before do
459
+ @xml = '<tag-1/>'
460
+ end
461
+
462
+ it "should return undasherize tag" do
463
+ MultiXml.parse(@xml).keys.should include('tag_1')
464
+ end
465
+ end
466
+
467
+ context "with dasherized attribute" do
468
+ before do
469
+ @xml = '<tag attribute-1="1"></tag>'
470
+ end
471
+
472
+ it "should return undasherize attribute" do
473
+ MultiXml.parse(@xml)['tag'].keys.should include('attribute_1')
474
+ end
475
+ end
476
+
477
+ context "with children" do
478
+ context "with attributes" do
479
+ before do
480
+ @xml = '<users><user name="Erik Michaels-Ober"/></users>'
481
+ end
482
+
483
+ it "should return the correct attributes" do
484
+ MultiXml.parse(@xml)['users']['user']['name'].should == "Erik Michaels-Ober"
485
+ end
486
+ end
487
+
488
+ context "with text" do
489
+ before do
490
+ @xml = '<user><name>Erik Michaels-Ober</name></user>'
491
+ end
492
+
493
+ it "should return the correct text" do
494
+ MultiXml.parse(@xml)['user']['name'].should == "Erik Michaels-Ober"
495
+ end
496
+ end
497
+
498
+ context "with an unrecognized attribute type" do
499
+ before do
500
+ @xml = '<user type="admin"><name>Erik Michaels-Ober</name></user>'
501
+ end
502
+
503
+ it "should pass through the type" do
504
+ MultiXml.parse(@xml)['user']['type'].should == 'admin'
505
+ end
506
+ end
507
+
508
+ context "with newlines and whitespace" do
509
+ before do
510
+ @xml = <<-XML
511
+ <user>
512
+ <name>Erik Michaels-Ober</name>
513
+ </user>
514
+ XML
515
+ end
516
+
517
+ it "should parse correctly" do
518
+ MultiXml.parse(@xml).should == {"user" => {"name" => "Erik Michaels-Ober"}}
519
+ end
520
+ end
521
+
522
+ # Babies having babies
523
+ context "with children" do
524
+ before do
525
+ @xml = '<users><user name="Erik Michaels-Ober"><status text="Hello"/></user></users>'
526
+ end
527
+
528
+ it "should parse correctly" do
529
+ MultiXml.parse(@xml).should == {"users" => {"user" => {"name" => "Erik Michaels-Ober", "status" => {"text" => "Hello"}}}}
530
+ end
531
+ end
532
+ end
533
+
534
+ context "with sibling children" do
535
+ before do
536
+ @xml = '<users><user>Erik Michaels-Ober</user><user>Wynn Netherland</user></users>'
537
+ end
538
+
539
+ it "should return an Array" do
540
+ MultiXml.parse(@xml)['users']['user'].should be_a(Array)
541
+ end
542
+
543
+ it "should parse correctly" do
544
+ MultiXml.parse(@xml).should == {"users" => {"user" => ["Erik Michaels-Ober", "Wynn Netherland"]}}
545
+ end
546
+ end
547
+ end
548
+ end
549
+
550
+ end