crack 0.4.3 → 0.4.6

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.
data/test/xml_test.rb DELETED
@@ -1,514 +0,0 @@
1
- require 'test_helper'
2
-
3
- describe Crack::XML do
4
- it "should transform a simple tag with content" do
5
- xml = "<tag>This is the contents</tag>"
6
- Crack::XML.parse(xml).must_equal({ 'tag' => 'This is the contents' })
7
- end
8
-
9
- it "should work with cdata tags" do
10
- xml = <<-END
11
- <tag>
12
- <![CDATA[
13
- text inside cdata
14
- ]]>
15
- </tag>
16
- END
17
- Crack::XML.parse(xml)["tag"].strip.must_equal "text inside cdata"
18
- end
19
-
20
- it "should transform a simple tag with attributes" do
21
- xml = "<tag attr1='1' attr2='2'></tag>"
22
- hash = { 'tag' => { 'attr1' => '1', 'attr2' => '2' } }
23
- Crack::XML.parse(xml).must_equal hash
24
- end
25
-
26
- it "should transform repeating siblings into an array" do
27
- xml =<<-XML
28
- <opt>
29
- <user login="grep" fullname="Gary R Epstein" />
30
- <user login="stty" fullname="Simon T Tyson" />
31
- </opt>
32
- XML
33
-
34
- Crack::XML.parse(xml)['opt']['user'].class.must_equal Array
35
-
36
- hash = {
37
- 'opt' => {
38
- 'user' => [{
39
- 'login' => 'grep',
40
- 'fullname' => 'Gary R Epstein'
41
- },{
42
- 'login' => 'stty',
43
- 'fullname' => 'Simon T Tyson'
44
- }]
45
- }
46
- }
47
-
48
- Crack::XML.parse(xml).must_equal hash
49
- end
50
-
51
- it "should not transform non-repeating siblings into an array" do
52
- xml =<<-XML
53
- <opt>
54
- <user login="grep" fullname="Gary R Epstein" />
55
- </opt>
56
- XML
57
-
58
- Crack::XML.parse(xml)['opt']['user'].class.must_equal Hash
59
-
60
- hash = {
61
- 'opt' => {
62
- 'user' => {
63
- 'login' => 'grep',
64
- 'fullname' => 'Gary R Epstein'
65
- }
66
- }
67
- }
68
-
69
- Crack::XML.parse(xml).must_equal hash
70
- end
71
-
72
- describe "Parsing xml with text and attributes" do
73
- before do
74
- xml =<<-XML
75
- <opt>
76
- <user login="grep">Gary R Epstein</user>
77
- <user>Simon T Tyson</user>
78
- </opt>
79
- XML
80
- @data = Crack::XML.parse(xml)
81
- end
82
-
83
- it "correctly parse text nodes" do
84
- @data.must_equal({
85
- 'opt' => {
86
- 'user' => [
87
- 'Gary R Epstein',
88
- 'Simon T Tyson'
89
- ]
90
- }
91
- })
92
- end
93
-
94
- it "be parse attributes for text node if present" do
95
- @data['opt']['user'][0].attributes.must_equal({'login' => 'grep'})
96
- end
97
-
98
- it "default attributes to empty hash if not present" do
99
- @data['opt']['user'][1].attributes.must_equal({})
100
- end
101
-
102
- it "add 'attributes' accessor methods to parsed instances of String" do
103
- @data['opt']['user'][0].respond_to?(:attributes).must_equal(true)
104
- @data['opt']['user'][0].respond_to?(:attributes=).must_equal(true)
105
- end
106
-
107
- it "not add 'attributes' accessor methods to all instances of String" do
108
- "some-string".respond_to?(:attributes).must_equal(false)
109
- "some-string".respond_to?(:attributes=).must_equal(false)
110
- end
111
- end
112
-
113
- it "should typecast an integer" do
114
- xml = "<tag type='integer'>10</tag>"
115
- Crack::XML.parse(xml)['tag'].must_equal 10
116
- end
117
-
118
- it "should typecast a true boolean" do
119
- xml = "<tag type='boolean'>true</tag>"
120
- Crack::XML.parse(xml)['tag'].must_equal(true)
121
- end
122
-
123
- it "should typecast a false boolean" do
124
- ["false"].each do |w|
125
- Crack::XML.parse("<tag type='boolean'>#{w}</tag>")['tag'].must_equal(false)
126
- end
127
- end
128
-
129
- it "should typecast a datetime" do
130
- xml = "<tag type='datetime'>2007-12-31 10:32</tag>"
131
- Crack::XML.parse(xml)['tag'].must_equal Time.parse( '2007-12-31 10:32' ).utc
132
- end
133
-
134
- it "should typecast a date" do
135
- xml = "<tag type='date'>2007-12-31</tag>"
136
- Crack::XML.parse(xml)['tag'].must_equal Date.parse('2007-12-31')
137
- end
138
-
139
- xml_entities = {
140
- "<" => "&lt;",
141
- ">" => "&gt;",
142
- '"' => "&quot;",
143
- "'" => "&apos;",
144
- "&" => "&amp;"
145
- }
146
- it "should unescape html entities" do
147
- xml_entities.each do |k,v|
148
- xml = "<tag>Some content #{v}</tag>"
149
- Crack::XML.parse(xml)['tag'].must_match Regexp.new(k)
150
- end
151
- end
152
-
153
- it "should unescape XML entities in attributes" do
154
- xml_entities.each do |k,v|
155
- xml = "<tag attr='Some content #{v}'></tag>"
156
- Crack::XML.parse(xml)['tag']['attr'].must_match Regexp.new(k)
157
- end
158
- end
159
-
160
- it "should undasherize keys as tags" do
161
- xml = "<tag-1>Stuff</tag-1>"
162
- Crack::XML.parse(xml).keys.must_include( 'tag_1' )
163
- end
164
-
165
- it "should undasherize keys as attributes" do
166
- xml = "<tag1 attr-1='1'></tag1>"
167
- Crack::XML.parse(xml)['tag1'].keys.must_include( 'attr_1')
168
- end
169
-
170
- it "should undasherize keys as tags and attributes" do
171
- xml = "<tag-1 attr-1='1'></tag-1>"
172
- Crack::XML.parse(xml).keys.must_include( 'tag_1' )
173
- Crack::XML.parse(xml)['tag_1'].keys.must_include( 'attr_1')
174
- end
175
-
176
- it "should render nested content correctly" do
177
- xml = "<root><tag1>Tag1 Content <em><strong>This is strong</strong></em></tag1></root>"
178
- Crack::XML.parse(xml)['root']['tag1'].must_equal "Tag1 Content <em><strong>This is strong</strong></em>"
179
- end
180
-
181
- it "should render nested content with splshould text nodes correctly" do
182
- xml = "<root>Tag1 Content<em>Stuff</em> Hi There</root>"
183
- Crack::XML.parse(xml)['root'].must_equal "Tag1 Content<em>Stuff</em> Hi There"
184
- end
185
-
186
- it "should ignore attributes when a child is a text node" do
187
- xml = "<root attr1='1'>Stuff</root>"
188
- Crack::XML.parse(xml).must_equal({ "root" => "Stuff" })
189
- end
190
-
191
- it "should ignore attributes when any child is a text node" do
192
- xml = "<root attr1='1'>Stuff <em>in italics</em></root>"
193
- Crack::XML.parse(xml).must_equal({ "root" => "Stuff <em>in italics</em>" })
194
- end
195
-
196
- it "should correctly transform multiple children" do
197
- xml = <<-XML
198
- <user gender='m'>
199
- <age type='integer'>35</age>
200
- <name>Home Simpson</name>
201
- <dob type='date'>1988-01-01</dob>
202
- <joined-at type='datetime'>2000-04-28 23:01</joined-at>
203
- <is-cool type='boolean'>true</is-cool>
204
- </user>
205
- XML
206
-
207
- hash = {
208
- "user" => {
209
- "gender" => "m",
210
- "age" => 35,
211
- "name" => "Home Simpson",
212
- "dob" => Date.parse('1988-01-01'),
213
- "joined_at" => Time.parse("2000-04-28 23:01"),
214
- "is_cool" => true
215
- }
216
- }
217
-
218
- Crack::XML.parse(xml).must_equal hash
219
- end
220
-
221
- it "should properly handle nil values (ActiveSupport Compatible)" do
222
- topic_xml = <<-EOT
223
- <topic>
224
- <title></title>
225
- <id type="integer"></id>
226
- <approved type="boolean"></approved>
227
- <written-on type="date"></written-on>
228
- <viewed-at type="datetime"></viewed-at>
229
- <parent-id></parent-id>
230
- </topic>
231
- EOT
232
-
233
- expected_topic_hash = {
234
- 'title' => nil,
235
- 'id' => nil,
236
- 'approved' => nil,
237
- 'written_on' => nil,
238
- 'viewed_at' => nil,
239
- 'parent_id' => nil
240
- }
241
- Crack::XML.parse(topic_xml)["topic"].must_equal expected_topic_hash
242
- end
243
-
244
- it "should handle a single record from xml (ActiveSupport Compatible)" do
245
- topic_xml = <<-EOT
246
- <topic>
247
- <title>The First Topic</title>
248
- <author-name>David</author-name>
249
- <id type="integer">1</id>
250
- <approved type="boolean"> true </approved>
251
- <replies-count type="integer">0</replies-count>
252
- <replies-close-in type="integer">2592000000</replies-close-in>
253
- <written-on type="date">2003-07-16</written-on>
254
- <viewed-at type="datetime">2003-07-16T09:28:00+0000</viewed-at>
255
- <author-email-address>david@loudthinking.com</author-email-address>
256
- <parent-id></parent-id>
257
- <ad-revenue type="decimal">1.5</ad-revenue>
258
- <optimum-viewing-angle type="float">135</optimum-viewing-angle>
259
- <resident type="symbol">yes</resident>
260
- </topic>
261
- EOT
262
-
263
- expected_topic_hash = {
264
- 'title' => "The First Topic",
265
- 'author_name' => "David",
266
- 'id' => 1,
267
- 'approved' => true,
268
- 'replies_count' => 0,
269
- 'replies_close_in' => 2592000000,
270
- 'written_on' => Date.new(2003, 7, 16),
271
- 'viewed_at' => Time.utc(2003, 7, 16, 9, 28),
272
- 'author_email_address' => "david@loudthinking.com",
273
- 'parent_id' => nil,
274
- 'ad_revenue' => BigDecimal("1.50"),
275
- 'optimum_viewing_angle' => 135.0,
276
- 'resident' => 'yes',
277
- }
278
-
279
- Crack::XML.parse(topic_xml)["topic"].each do |k,v|
280
- v.must_equal expected_topic_hash[k]
281
- end
282
- end
283
-
284
- it "should handle multiple records (ActiveSupport Compatible)" do
285
- topics_xml = <<-EOT
286
- <topics type="array">
287
- <topic>
288
- <title>The First Topic</title>
289
- <author-name>David</author-name>
290
- <id type="integer">1</id>
291
- <approved type="boolean">false</approved>
292
- <replies-count type="integer">0</replies-count>
293
- <replies-close-in type="integer">2592000000</replies-close-in>
294
- <written-on type="date">2003-07-16</written-on>
295
- <viewed-at type="datetime">2003-07-16T09:28:00+0000</viewed-at>
296
- <content>Have a nice day</content>
297
- <author-email-address>david@loudthinking.com</author-email-address>
298
- <parent-id nil="true"></parent-id>
299
- </topic>
300
- <topic>
301
- <title>The Second Topic</title>
302
- <author-name>Jason</author-name>
303
- <id type="integer">1</id>
304
- <approved type="boolean">false</approved>
305
- <replies-count type="integer">0</replies-count>
306
- <replies-close-in type="integer">2592000000</replies-close-in>
307
- <written-on type="date">2003-07-16</written-on>
308
- <viewed-at type="datetime">2003-07-16T09:28:00+0000</viewed-at>
309
- <content>Have a nice day</content>
310
- <author-email-address>david@loudthinking.com</author-email-address>
311
- <parent-id></parent-id>
312
- </topic>
313
- </topics>
314
- EOT
315
-
316
- expected_topic_hash = {
317
- 'title' => "The First Topic",
318
- 'author_name' => "David",
319
- 'id' => 1,
320
- 'approved' => false,
321
- 'replies_count' => 0,
322
- 'replies_close_in' => 2592000000,
323
- 'written_on' => Date.new(2003, 7, 16),
324
- 'viewed_at' => Time.utc(2003, 7, 16, 9, 28),
325
- 'content' => "Have a nice day",
326
- 'author_email_address' => "david@loudthinking.com",
327
- 'parent_id' => nil
328
- }
329
- # puts Crack::XML.parse(topics_xml)['topics'].first.inspect
330
- Crack::XML.parse(topics_xml)["topics"].first.each do |k,v|
331
- v.must_equal expected_topic_hash[k]
332
- end
333
- end
334
-
335
- it "should handle a single record from_xml with attributes other than type (ActiveSupport Compatible)" do
336
- topic_xml = <<-EOT
337
- <rsp stat="ok">
338
- <photos page="1" pages="1" perpage="100" total="16">
339
- <photo id="175756086" owner="55569174@N00" secret="0279bf37a1" server="76" title="Colored Pencil PhotoBooth Fun" ispublic="1" isfriend="0" isfamily="0"/>
340
- </photos>
341
- </rsp>
342
- EOT
343
-
344
- expected_topic_hash = {
345
- 'id' => "175756086",
346
- 'owner' => "55569174@N00",
347
- 'secret' => "0279bf37a1",
348
- 'server' => "76",
349
- 'title' => "Colored Pencil PhotoBooth Fun",
350
- 'ispublic' => "1",
351
- 'isfriend' => "0",
352
- 'isfamily' => "0",
353
- }
354
- Crack::XML.parse(topic_xml)["rsp"]["photos"]["photo"].each do |k,v|
355
- v.must_equal expected_topic_hash[k]
356
- end
357
- end
358
-
359
- it "should handle an emtpy array (ActiveSupport Compatible)" do
360
- blog_xml = <<-XML
361
- <blog>
362
- <posts type="array"></posts>
363
- </blog>
364
- XML
365
- expected_blog_hash = {"blog" => {"posts" => []}}
366
- Crack::XML.parse(blog_xml).must_equal expected_blog_hash
367
- end
368
-
369
- it "should handle empty array with whitespace from xml (ActiveSupport Compatible)" do
370
- blog_xml = <<-XML
371
- <blog>
372
- <posts type="array">
373
- </posts>
374
- </blog>
375
- XML
376
- expected_blog_hash = {"blog" => {"posts" => []}}
377
- Crack::XML.parse(blog_xml).must_equal expected_blog_hash
378
- end
379
-
380
- it "should handle array with one entry from_xml (ActiveSupport Compatible)" do
381
- blog_xml = <<-XML
382
- <blog>
383
- <posts type="array">
384
- <post>a post</post>
385
- </posts>
386
- </blog>
387
- XML
388
- expected_blog_hash = {"blog" => {"posts" => ["a post"]}}
389
- Crack::XML.parse(blog_xml).must_equal expected_blog_hash
390
- end
391
-
392
- it "should handle array with multiple entries from xml (ActiveSupport Compatible)" do
393
- blog_xml = <<-XML
394
- <blog>
395
- <posts type="array">
396
- <post>a post</post>
397
- <post>another post</post>
398
- </posts>
399
- </blog>
400
- XML
401
- expected_blog_hash = {"blog" => {"posts" => ["a post", "another post"]}}
402
- Crack::XML.parse(blog_xml).must_equal expected_blog_hash
403
- end
404
-
405
- it "should handle file types (ActiveSupport Compatible)" do
406
- blog_xml = <<-XML
407
- <blog>
408
- <logo type="file" name="logo.png" content_type="image/png">
409
- </logo>
410
- </blog>
411
- XML
412
- hash = Crack::XML.parse(blog_xml)
413
- hash.keys.must_include('blog')
414
- hash['blog'].keys.must_include('logo')
415
-
416
- file = hash['blog']['logo']
417
- file.original_filename.must_equal 'logo.png'
418
- file.content_type.must_equal 'image/png'
419
- end
420
-
421
- it "should handle file from xml with defaults (ActiveSupport Compatible)" do
422
- blog_xml = <<-XML
423
- <blog>
424
- <logo type="file">
425
- </logo>
426
- </blog>
427
- XML
428
- file = Crack::XML.parse(blog_xml)['blog']['logo']
429
- file.original_filename.must_equal 'untitled'
430
- file.content_type.must_equal 'application/octet-stream'
431
- end
432
-
433
- it "should handle xsd like types from xml (ActiveSupport Compatible)" do
434
- bacon_xml = <<-EOT
435
- <bacon>
436
- <weight type="double">0.5</weight>
437
- <price type="decimal">12.50</price>
438
- <chunky type="boolean"> 1 </chunky>
439
- <expires-at type="dateTime">2007-12-25T12:34:56+0000</expires-at>
440
- <notes type="string"></notes>
441
- <illustration type="base64Binary">YmFiZS5wbmc=</illustration>
442
- </bacon>
443
- EOT
444
-
445
- expected_bacon_hash = {
446
- 'weight' => 0.5,
447
- 'chunky' => true,
448
- 'price' => BigDecimal("12.50"),
449
- 'expires_at' => Time.utc(2007,12,25,12,34,56),
450
- 'notes' => "",
451
- 'illustration' => "babe.png"
452
- }
453
-
454
- Crack::XML.parse(bacon_xml)["bacon"].must_equal expected_bacon_hash
455
- end
456
-
457
- it "should let type trickle through when unknown (ActiveSupport Compatible)" do
458
- product_xml = <<-EOT
459
- <product>
460
- <weight type="double">0.5</weight>
461
- <image type="ProductImage"><filename>image.gif</filename></image>
462
-
463
- </product>
464
- EOT
465
-
466
- expected_product_hash = {
467
- 'weight' => 0.5,
468
- 'image' => {'type' => 'ProductImage', 'filename' => 'image.gif' },
469
- }
470
-
471
- Crack::XML.parse(product_xml)["product"].must_equal expected_product_hash
472
- end
473
-
474
- it "should handle unescaping from xml (ActiveResource Compatible)" do
475
- xml_string = '<person><bare-string>First &amp; Last Name</bare-string><pre-escaped-string>First &amp;amp; Last Name</pre-escaped-string></person>'
476
- expected_hash = {
477
- 'bare_string' => 'First & Last Name',
478
- 'pre_escaped_string' => 'First &amp; Last Name'
479
- }
480
-
481
- Crack::XML.parse(xml_string)['person'].must_equal expected_hash
482
- end
483
-
484
- it "handle an empty xml string" do
485
- Crack::XML.parse('').must_equal({})
486
- end
487
-
488
- # As returned in the response body by the unfuddle XML API when creating objects
489
- it "handle an xml string containing a single space" do
490
- Crack::XML.parse(' ').must_equal({})
491
- end
492
-
493
- it "can dump parsed xml" do
494
- xml = <<-XML
495
- <blog>
496
- <posts language="english">I like big butts and I cannot Lie</posts>
497
- </blog>
498
- XML
499
-
500
- Marshal.dump(Crack::XML.parse(xml))
501
- end
502
-
503
- it "properly handles a node with type == file that has children" do
504
- # Example is an excerpt from a problematic kvm domain config file
505
- example_xml = <<-EOT
506
- <disk type='file' device='cdrom'>
507
- <driver name='qemu' type='raw' cache='none' io='native'/>
508
- <source file='/tmp/cdrom.iso'/>
509
- </disk>
510
- EOT
511
-
512
- Crack::XML.parse(example_xml).must_equal({"disk"=>{"driver"=>{"name"=>"qemu", "type"=>"raw", "cache"=>"none", "io"=>"native"}, "source"=>{"file"=>"/tmp/cdrom.iso"}, "type"=>"file", "device"=>"cdrom"}})
513
- end
514
- end