raus22-happymapper 0.3.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.
@@ -0,0 +1,21 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe HappyMapper::Attribute do
4
+ describe "initialization" do
5
+ before do
6
+ @attr = HappyMapper::Attribute.new(:foo, String)
7
+ end
8
+
9
+ it 'should know that it is an attribute' do
10
+ @attr.attribute?.should be_true
11
+ end
12
+
13
+ it 'should know that it is NOT an element' do
14
+ @attr.element?.should be_false
15
+ end
16
+
17
+ it 'should know that it is NOT a text node' do
18
+ @attr.text_node?.should be_false
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe HappyMapper::Element do
4
+ describe "initialization" do
5
+ before do
6
+ @attr = HappyMapper::Element.new(:foo, String)
7
+ end
8
+
9
+ it 'should know that it is an element' do
10
+ @attr.element?.should be_true
11
+ end
12
+
13
+ it 'should know that it is NOT an attribute' do
14
+ @attr.attribute?.should be_false
15
+ end
16
+
17
+ it 'should know that it is NOT a text node' do
18
+ @attr.text_node?.should be_false
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,115 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ module Foo
4
+ class Bar; end
5
+ end
6
+
7
+ describe HappyMapper::Item do
8
+
9
+ describe "new instance" do
10
+ before do
11
+ @item = HappyMapper::Item.new(:foo, String, :tag => 'foobar')
12
+ end
13
+
14
+ it "should accept a name" do
15
+ @item.name.should == 'foo'
16
+ end
17
+
18
+ it 'should accept a type' do
19
+ @item.type.should == String
20
+ end
21
+
22
+ it 'should accept :tag as an option' do
23
+ @item.tag.should == 'foobar'
24
+ end
25
+
26
+ it "should have a method_name" do
27
+ @item.method_name.should == 'foo'
28
+ end
29
+ end
30
+
31
+ describe "#constant" do
32
+ it "should just use type if constant" do
33
+ item = HappyMapper::Item.new(:foo, String)
34
+ item.constant.should == String
35
+ end
36
+
37
+ it "should convert string type to constant" do
38
+ item = HappyMapper::Item.new(:foo, 'String')
39
+ item.constant.should == String
40
+ end
41
+
42
+ it "should convert string with :: to constant" do
43
+ item = HappyMapper::Item.new(:foo, 'Foo::Bar')
44
+ item.constant.should == Foo::Bar
45
+ end
46
+ end
47
+
48
+ describe "#method_name" do
49
+ it "should convert dashes to underscores" do
50
+ item = HappyMapper::Item.new(:'foo-bar', String, :tag => 'foobar')
51
+ item.method_name.should == 'foo_bar'
52
+ end
53
+ end
54
+
55
+ describe "#xpath" do
56
+ it "should default to tag" do
57
+ item = HappyMapper::Item.new(:foo, String, :tag => 'foobar')
58
+ item.xpath.should == 'foobar'
59
+ end
60
+
61
+ it "should prepend with .// if options[:deep] true" do
62
+ item = HappyMapper::Item.new(:foo, String, :tag => 'foobar', :deep => true)
63
+ item.xpath.should == './/foobar'
64
+ end
65
+
66
+ it "should prepend namespace if namespace exists" do
67
+ item = HappyMapper::Item.new(:foo, String, :tag => 'foobar')
68
+ item.namespace = 'v2'
69
+ item.xpath.should == 'v2:foobar'
70
+ end
71
+ end
72
+
73
+ describe "typecasting" do
74
+ it "should work with Strings" do
75
+ item = HappyMapper::Item.new(:foo, String)
76
+ [21, '21'].each do |a|
77
+ item.typecast(a).should == '21'
78
+ end
79
+ end
80
+
81
+ it "should work with Integers" do
82
+ item = HappyMapper::Item.new(:foo, Integer)
83
+ [21, 21.0, '21'].each do |a|
84
+ item.typecast(a).should == 21
85
+ end
86
+ end
87
+
88
+ it "should work with Floats" do
89
+ item = HappyMapper::Item.new(:foo, Float)
90
+ [21, 21.0, '21'].each do |a|
91
+ item.typecast(a).should == 21.0
92
+ end
93
+ end
94
+
95
+ it "should work with Times" do
96
+ item = HappyMapper::Item.new(:foo, Time)
97
+ item.typecast('2000-01-01 01:01:01.123456').should == Time.local(2000, 1, 1, 1, 1, 1, 123456)
98
+ end
99
+
100
+ it "should work with Dates" do
101
+ item = HappyMapper::Item.new(:foo, Date)
102
+ item.typecast('2000-01-01').should == Date.new(2000, 1, 1)
103
+ end
104
+
105
+ it "should work with DateTimes" do
106
+ item = HappyMapper::Item.new(:foo, DateTime)
107
+ item.typecast('2000-01-01 00:00:00').should == DateTime.new(2000, 1, 1, 0, 0, 0)
108
+ end
109
+
110
+ it "should work with Boolean" do
111
+ item = HappyMapper::Item.new(:foo, Boolean)
112
+ item.typecast('false').should == false
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,735 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+ require 'pp'
3
+ require 'uri'
4
+
5
+ module Analytics
6
+ class Property
7
+ include HappyMapper
8
+
9
+ tag 'property'
10
+ namespace 'dxp'
11
+ attribute :name, String
12
+ attribute :value, String
13
+ end
14
+
15
+ class Entry
16
+ include HappyMapper
17
+
18
+ tag 'entry'
19
+ element :id, String
20
+ element :updated, DateTime
21
+ element :title, String
22
+ element :table_id, String, :namespace => 'dxp', :tag => 'tableId'
23
+ has_many :properties, Property
24
+ end
25
+
26
+ class Feed
27
+ include HappyMapper
28
+
29
+ tag 'feed'
30
+ element :id, String
31
+ element :updated, DateTime
32
+ element :title, String
33
+ has_many :entries, Entry
34
+ end
35
+ end
36
+
37
+ class Address
38
+ include HappyMapper
39
+
40
+ tag 'address'
41
+ element :street, String
42
+ element :postcode, String
43
+ element :housenumber, String
44
+ element :city, String
45
+ element :country, String
46
+ end
47
+
48
+ class Feature
49
+ include HappyMapper
50
+ element :name, String, :tag => '.|.//text()'
51
+ end
52
+
53
+ class FeatureBullet
54
+ include HappyMapper
55
+
56
+ tag 'features_bullets'
57
+ has_many :features, Feature
58
+ element :bug, String
59
+ end
60
+
61
+ class Product
62
+ include HappyMapper
63
+
64
+ element :title, String
65
+ has_one :feature_bullets, FeatureBullet
66
+ has_one :address, Address
67
+ end
68
+
69
+ module FamilySearch
70
+ class AlternateIds
71
+ include HappyMapper
72
+
73
+ tag 'alternateIds'
74
+ has_many :ids, String, :tag => 'id'
75
+ end
76
+
77
+ class Information
78
+ include HappyMapper
79
+
80
+ has_one :alternateIds, AlternateIds
81
+ end
82
+
83
+ class Person
84
+ include HappyMapper
85
+
86
+ attribute :version, String
87
+ attribute :modified, Time
88
+ attribute :id, String
89
+ has_one :information, Information
90
+ end
91
+
92
+ class Persons
93
+ include HappyMapper
94
+ has_many :person, Person
95
+ end
96
+
97
+ class FamilyTree
98
+ include HappyMapper
99
+
100
+ tag 'familytree'
101
+ attribute :version, String
102
+ attribute :status_message, String, :tag => 'statusMessage'
103
+ attribute :status_code, String, :tag => 'statusCode'
104
+ has_one :persons, Persons
105
+ end
106
+ end
107
+
108
+ module FedEx
109
+ class Address
110
+ include HappyMapper
111
+
112
+ tag 'Address'
113
+ namespace 'v2'
114
+ element :city, String, :tag => 'City'
115
+ element :state, String, :tag => 'StateOrProvinceCode'
116
+ element :zip, String, :tag => 'PostalCode'
117
+ element :countrycode, String, :tag => 'CountryCode'
118
+ element :residential, Boolean, :tag => 'Residential'
119
+ end
120
+
121
+ class Event
122
+ include HappyMapper
123
+
124
+ tag 'Events'
125
+ namespace 'v2'
126
+ element :timestamp, String, :tag => 'Timestamp'
127
+ element :eventtype, String, :tag => 'EventType'
128
+ element :eventdescription, String, :tag => 'EventDescription'
129
+ has_one :address, Address
130
+ end
131
+
132
+ class PackageWeight
133
+ include HappyMapper
134
+
135
+ tag 'PackageWeight'
136
+ namespace 'v2'
137
+ element :units, String, :tag => 'Units'
138
+ element :value, Integer, :tag => 'Value'
139
+ end
140
+
141
+ class TrackDetails
142
+ include HappyMapper
143
+
144
+ tag 'TrackDetails'
145
+ namespace 'v2'
146
+ element :tracking_number, String, :tag => 'TrackingNumber'
147
+ element :status_code, String, :tag => 'StatusCode'
148
+ element :status_desc, String, :tag => 'StatusDescription'
149
+ element :carrier_code, String, :tag => 'CarrierCode'
150
+ element :service_info, String, :tag => 'ServiceInfo'
151
+ has_one :weight, PackageWeight, :tag => 'PackageWeight'
152
+ element :est_delivery, String, :tag => 'EstimatedDeliveryTimestamp'
153
+ has_many :events, Event
154
+ end
155
+
156
+ class Notification
157
+ include HappyMapper
158
+
159
+ tag 'Notifications'
160
+ namespace 'v2'
161
+ element :severity, String, :tag => 'Severity'
162
+ element :source, String, :tag => 'Source'
163
+ element :code, Integer, :tag => 'Code'
164
+ element :message, String, :tag => 'Message'
165
+ element :localized_message, String, :tag => 'LocalizedMessage'
166
+ end
167
+
168
+ class TransactionDetail
169
+ include HappyMapper
170
+
171
+ tag 'TransactionDetail'
172
+ namespace 'v2'
173
+ element :cust_tran_id, String, :tag => 'CustomerTransactionId'
174
+ end
175
+
176
+ class TrackReply
177
+ include HappyMapper
178
+
179
+ tag 'TrackReply'
180
+ namespace 'v2'
181
+ element :highest_severity, String, :tag => 'HighestSeverity'
182
+ element :more_data, Boolean, :tag => 'MoreData'
183
+ has_many :notifications, Notification, :tag => 'Notifications'
184
+ has_many :trackdetails, TrackDetails, :tag => 'TrackDetails'
185
+ has_one :tran_detail, TransactionDetail, :tab => 'TransactionDetail'
186
+ end
187
+ end
188
+
189
+ class Place
190
+ include HappyMapper
191
+ element :name, String
192
+ end
193
+
194
+ class Radar
195
+ include HappyMapper
196
+ has_many :places, Place, :tag => :place
197
+ end
198
+
199
+ class Post
200
+ include HappyMapper
201
+
202
+ attribute :href, String
203
+ attribute :hash, String
204
+ attribute :description, String
205
+ attribute :tag, String
206
+ attribute :time, Time
207
+ attribute :others, Integer
208
+ attribute :extended, String
209
+ end
210
+
211
+ class User
212
+ include HappyMapper
213
+
214
+ element :id, Integer
215
+ element :name, String
216
+ element :screen_name, String
217
+ element :location, String
218
+ element :description, String
219
+ element :profile_image_url, String
220
+ element :url, String
221
+ element :protected, Boolean
222
+ element :followers_count, Integer
223
+ end
224
+
225
+ class Status
226
+ include HappyMapper
227
+
228
+ element :id, Integer
229
+ element :text, String
230
+ element :created_at, Time
231
+ element :source, String
232
+ element :truncated, Boolean
233
+ element :in_reply_to_status_id, Integer
234
+ element :in_reply_to_user_id, Integer
235
+ element :favorited, Boolean
236
+ element :non_existent, String, :tag => 'dummy', :namespace => 'fake'
237
+ has_one :user, User
238
+ end
239
+
240
+ class CurrentWeather
241
+ include HappyMapper
242
+
243
+ tag 'ob'
244
+ namespace 'aws'
245
+ element :temperature, Integer, :tag => 'temp'
246
+ element :feels_like, Integer, :tag => 'feels-like'
247
+ element :current_condition, String, :tag => 'current-condition', :attributes => {:icon => String}
248
+ end
249
+
250
+ class Country
251
+ include HappyMapper
252
+
253
+ attribute :code, String
254
+ text_node :name, String
255
+ end
256
+
257
+ class Address
258
+ include HappyMapper
259
+
260
+ tag 'address'
261
+ element :street, String
262
+ element :postcode, String
263
+ element :housenumber, String
264
+ element :city, String
265
+ has_one :country, Country
266
+ end
267
+
268
+ # for type coercion
269
+ class ProductGroup < String; end
270
+
271
+ module PITA
272
+ class Item
273
+ include HappyMapper
274
+
275
+ tag 'Item' # if you put class in module you need tag
276
+ element :asin, String, :tag => 'ASIN'
277
+ element :detail_page_url, URI, :tag => 'DetailPageURL', :parser => :parse
278
+ element :manufacturer, String, :tag => 'Manufacturer', :deep => true
279
+ element :point, String, :tag => 'point', :namespace => 'georss'
280
+ element :product_group, ProductGroup, :tag => 'ProductGroup', :deep => true, :parser => :new, :raw => true
281
+ end
282
+
283
+ class Items
284
+ include HappyMapper
285
+
286
+ tag 'Items' # if you put class in module you need tag
287
+ element :total_results, Integer, :tag => 'TotalResults'
288
+ element :total_pages, Integer, :tag => 'TotalPages'
289
+ has_many :items, Item
290
+ end
291
+ end
292
+
293
+ module GitHub
294
+ class Commit
295
+ include HappyMapper
296
+
297
+ tag "commit"
298
+ element :url, String
299
+ element :tree, String
300
+ element :message, String
301
+ element :id, String
302
+ element :'committed-date', Date
303
+ end
304
+ end
305
+
306
+ module QuarterTest
307
+ class Quarter
308
+ include HappyMapper
309
+
310
+ element :start, String
311
+ end
312
+
313
+ class Details
314
+ include HappyMapper
315
+
316
+ element :round, Integer
317
+ element :quarter, Integer
318
+ end
319
+
320
+ class Game
321
+ include HappyMapper
322
+
323
+ # in an ideal world, the following elements would all be
324
+ # called 'quarter' with an attribute indicating which quarter
325
+ # it represented, but the refactoring that allows a single class
326
+ # to be used for all these differently named elements is the next
327
+ # best thing
328
+ has_one :details, QuarterTest::Details
329
+ has_one :q1, QuarterTest::Quarter, :tag => 'q1'
330
+ has_one :q2, QuarterTest::Quarter, :tag => 'q2'
331
+ has_one :q3, QuarterTest::Quarter, :tag => 'q3'
332
+ has_one :q4, QuarterTest::Quarter, :tag => 'q4'
333
+ end
334
+ end
335
+
336
+ # To check for multiple primitives
337
+ class Artist
338
+ include HappyMapper
339
+
340
+ tag 'artist'
341
+ element :images, String, :tag => "image", :single => false
342
+ element :name, String
343
+ end
344
+
345
+ class Location
346
+ include HappyMapper
347
+
348
+ tag 'point'
349
+ namespace "geo"
350
+ element :latitude, String, :tag => "lat"
351
+ end
352
+
353
+ # Testing the XmlContent type
354
+ module Dictionary
355
+ class Variant
356
+ include HappyMapper
357
+ tag 'var'
358
+ has_xml_content
359
+
360
+ def to_html
361
+ xml_content.gsub('<tag>','<em>').gsub('</tag>','</em>')
362
+ end
363
+ end
364
+
365
+ class Definition
366
+ include HappyMapper
367
+
368
+ tag 'def'
369
+ element :text, XmlContent, :tag => 'dtext'
370
+ end
371
+
372
+ class Record
373
+ include HappyMapper
374
+
375
+ tag 'record'
376
+ has_many :definitions, Definition
377
+ has_many :variants, Variant, :tag => 'var'
378
+ end
379
+ end
380
+
381
+ describe HappyMapper do
382
+
383
+ describe "being included into another class" do
384
+ before do
385
+ @klass = Class.new do
386
+ include HappyMapper
387
+
388
+ def self.to_s
389
+ 'Foo'
390
+ end
391
+ end
392
+ end
393
+
394
+ class Foo; include HappyMapper end
395
+
396
+ it "should set attributes to an array" do
397
+ @klass.attributes.should == []
398
+ end
399
+
400
+ it "should set @elements to a hash" do
401
+ @klass.elements.should == []
402
+ end
403
+
404
+ it "should allow adding an attribute" do
405
+ lambda {
406
+ @klass.attribute :name, String
407
+ }.should change(@klass, :attributes)
408
+ end
409
+
410
+ it "should allow adding an attribute containing a dash" do
411
+ lambda {
412
+ @klass.attribute :'bar-baz', String
413
+ }.should change(@klass, :attributes)
414
+ end
415
+
416
+ it "should be able to get all attributes in array" do
417
+ @klass.attribute :name, String
418
+ @klass.attributes.size.should == 1
419
+ end
420
+
421
+ it "should allow adding an element" do
422
+ lambda {
423
+ @klass.element :name, String
424
+ }.should change(@klass, :elements)
425
+ end
426
+
427
+ it "should allow adding an element containing a dash" do
428
+ lambda {
429
+ @klass.element :'bar-baz', String
430
+ }.should change(@klass, :elements)
431
+
432
+ end
433
+
434
+ it "should be able to get all elements in array" do
435
+ @klass.element(:name, String)
436
+ @klass.elements.size.should == 1
437
+ end
438
+
439
+ it "should allow has one association" do
440
+ @klass.has_one(:user, User)
441
+ element = @klass.elements.first
442
+ element.name.should == 'user'
443
+ element.type.should == User
444
+ element.options[:single] = true
445
+ end
446
+
447
+ it "should allow has many association" do
448
+ @klass.has_many(:users, User)
449
+ element = @klass.elements.first
450
+ element.name.should == 'users'
451
+ element.type.should == User
452
+ element.options[:single] = false
453
+ end
454
+
455
+ it "should default tag name to lowercase class" do
456
+ @klass.tag_name.should == 'foo'
457
+ end
458
+
459
+ it "should default tag name of class in modules to the last constant lowercase" do
460
+ module Bar; class Baz; include HappyMapper; end; end
461
+ Bar::Baz.tag_name.should == 'baz'
462
+ end
463
+
464
+ it "should allow setting tag name" do
465
+ @klass.tag('FooBar')
466
+ @klass.tag_name.should == 'FooBar'
467
+ end
468
+
469
+ it "should allow setting a namespace" do
470
+ @klass.namespace(namespace = "foo")
471
+ @klass.namespace.should == namespace
472
+ end
473
+
474
+ it "should provide #parse" do
475
+ @klass.should respond_to(:parse)
476
+ end
477
+ end
478
+
479
+ describe "#attributes" do
480
+ it "should only return attributes for the current class" do
481
+ Post.attributes.size.should == 7
482
+ Status.attributes.size.should == 0
483
+ end
484
+ end
485
+
486
+ describe "#elements" do
487
+ it "should only return elements for the current class" do
488
+ Post.elements.size.should == 0
489
+ Status.elements.size.should == 10
490
+ end
491
+ end
492
+
493
+ it "should parse xml attributes into ruby objects" do
494
+ posts = Post.parse(fixture_file('posts.xml'))
495
+ posts.size.should == 20
496
+ first = posts.first
497
+ first.href.should == 'http://roxml.rubyforge.org/'
498
+ first.hash.should == '19bba2ab667be03a19f67fb67dc56917'
499
+ first.description.should == 'ROXML - Ruby Object to XML Mapping Library'
500
+ first.tag.should == 'ruby xml gems mapping'
501
+ first.time.should == Time.utc(2008, 8, 9, 5, 24, 20)
502
+ first.others.should == 56
503
+ first.extended.should == 'ROXML is a Ruby library designed to make it easier for Ruby developers to work with XML. Using simple annotations, it enables Ruby classes to be custom-mapped to XML. ROXML takes care of the marshalling and unmarshalling of mapped attributes so that developers can focus on building first-class Ruby classes.'
504
+ end
505
+
506
+ it "should parse xml elements to ruby objcts" do
507
+ statuses = Status.parse(fixture_file('statuses.xml'))
508
+ statuses.size.should == 20
509
+ first = statuses.first
510
+ first.id.should == 882281424
511
+ first.created_at.should == Time.utc(2008, 8, 9, 5, 38, 12)
512
+ first.source.should == 'web'
513
+ first.truncated.should be_false
514
+ first.in_reply_to_status_id.should == 1234
515
+ first.in_reply_to_user_id.should == 12345
516
+ first.favorited.should be_false
517
+ first.user.id.should == 4243
518
+ first.user.name.should == 'John Nunemaker'
519
+ first.user.screen_name.should == 'jnunemaker'
520
+ first.user.location.should == 'Mishawaka, IN, US'
521
+ first.user.description.should == 'Loves his wife, ruby, notre dame football and iu basketball'
522
+ first.user.profile_image_url.should == 'http://s3.amazonaws.com/twitter_production/profile_images/53781608/Photo_75_normal.jpg'
523
+ first.user.url.should == 'http://addictedtonew.com'
524
+ first.user.protected.should be_false
525
+ first.user.followers_count.should == 486
526
+ end
527
+
528
+ it "should parse xml containing the desired element as root node" do
529
+ address = Address.parse(fixture_file('address.xml'), :single => true)
530
+ address.street.should == 'Milchstrasse'
531
+ address.postcode.should == '26131'
532
+ address.housenumber.should == '23'
533
+ address.city.should == 'Oldenburg'
534
+ address.country.class.should == Country
535
+ end
536
+
537
+ it "should parse text node correctly" do
538
+ address = Address.parse(fixture_file('address.xml'), :single => true)
539
+ address.country.name.should == 'Germany'
540
+ address.country.code.should == 'de'
541
+ end
542
+
543
+ it "should parse xml with default namespace (amazon)" do
544
+ file_contents = fixture_file('pita.xml')
545
+ items = PITA::Items.parse(file_contents, :single => true)
546
+ items.total_results.should == 22
547
+ items.total_pages.should == 3
548
+ first = items.items[0]
549
+ second = items.items[1]
550
+ first.asin.should == '0321480791'
551
+ first.point.should == '38.5351715088 -121.7948684692'
552
+ first.detail_page_url.should be_a_kind_of(URI)
553
+ first.detail_page_url.to_s.should == 'http://www.amazon.com/gp/redirect.html%3FASIN=0321480791%26tag=ws%26lcode=xm2%26cID=2025%26ccmID=165953%26location=/o/ASIN/0321480791%253FSubscriptionId=dontbeaswoosh'
554
+ first.manufacturer.should == 'Addison-Wesley Professional'
555
+ first.product_group.should == '<ProductGroup>Book</ProductGroup>'
556
+ second.asin.should == '047022388X'
557
+ second.manufacturer.should == 'Wrox'
558
+ end
559
+
560
+ it "should parse xml that has attributes of elements" do
561
+ items = CurrentWeather.parse(fixture_file('current_weather.xml'))
562
+ first = items[0]
563
+ first.temperature.should == 51
564
+ first.feels_like.should == 51
565
+ first.current_condition.should == 'Sunny'
566
+ first.current_condition.icon.should == 'http://deskwx.weatherbug.com/images/Forecast/icons/cond007.gif'
567
+ end
568
+
569
+ it "should parse xml with nested elements" do
570
+ radars = Radar.parse(fixture_file('radar.xml'))
571
+ first = radars[0]
572
+ first.places.size.should == 1
573
+ first.places[0].name.should == 'Store'
574
+ second = radars[1]
575
+ second.places.size.should == 0
576
+ third = radars[2]
577
+ third.places.size.should == 2
578
+ third.places[0].name.should == 'Work'
579
+ third.places[1].name.should == 'Home'
580
+ end
581
+
582
+ it "should parse xml with element name different to class name" do
583
+ game = QuarterTest::Game.parse(fixture_file('quarters.xml'))
584
+ game.q1.start.should == '4:40:15 PM'
585
+ game.q2.start.should == '5:18:53 PM'
586
+ end
587
+
588
+ it "should parse xml that has elements with dashes" do
589
+ commit = GitHub::Commit.parse(fixture_file('commit.xml'))
590
+ commit.message.should == "move commands.rb and helpers.rb into commands/ dir"
591
+ commit.url.should == "http://github.com/defunkt/github-gem/commit/c26d4ce9807ecf57d3f9eefe19ae64e75bcaaa8b"
592
+ commit.id.should == "c26d4ce9807ecf57d3f9eefe19ae64e75bcaaa8b"
593
+ commit.committed_date.should == Date.parse("2008-03-02T16:45:41-08:00")
594
+ commit.tree.should == "28a1a1ca3e663d35ba8bf07d3f1781af71359b76"
595
+ end
596
+
597
+ it "should parse xml with no namespace" do
598
+ product = Product.parse(fixture_file('product_no_namespace.xml'), :single => true)
599
+ product.title.should == "A Title"
600
+ product.feature_bullets.bug.should == 'This is a bug'
601
+ product.feature_bullets.features.size.should == 2
602
+ product.feature_bullets.features[0].name.should == 'This is feature text 1'
603
+ product.feature_bullets.features[1].name.should == 'This is feature text 2'
604
+ end
605
+
606
+ it "should parse xml with default namespace" do
607
+ product = Product.parse(fixture_file('product_default_namespace.xml'), :single => true)
608
+ product.title.should == "A Title"
609
+ product.feature_bullets.bug.should == 'This is a bug'
610
+ product.feature_bullets.features.size.should == 2
611
+ product.feature_bullets.features[0].name.should == 'This is feature text 1'
612
+ product.feature_bullets.features[1].name.should == 'This is feature text 2'
613
+ end
614
+
615
+ it "should parse xml with single namespace" do
616
+ product = Product.parse(fixture_file('product_single_namespace.xml'), :single => true)
617
+ product.title.should == "A Title"
618
+ product.feature_bullets.bug.should == 'This is a bug'
619
+ product.feature_bullets.features.size.should == 2
620
+ product.feature_bullets.features[0].name.should == 'This is feature text 1'
621
+ product.feature_bullets.features[1].name.should == 'This is feature text 2'
622
+ end
623
+
624
+ it "should parse xml with multiple namespaces" do
625
+ track = FedEx::TrackReply.parse(fixture_file('multiple_namespaces.xml'))
626
+ track.highest_severity.should == 'SUCCESS'
627
+ track.more_data.should be_false
628
+ notification = track.notifications.first
629
+ notification.code.should == 0
630
+ notification.localized_message.should == 'Request was successfully processed.'
631
+ notification.message.should == 'Request was successfully processed.'
632
+ notification.severity.should == 'SUCCESS'
633
+ notification.source.should == 'trck'
634
+ detail = track.trackdetails.first
635
+ detail.carrier_code.should == 'FDXG'
636
+ detail.est_delivery.should == '2009-01-02T00:00:00'
637
+ detail.service_info.should == 'Ground-Package Returns Program-Domestic'
638
+ detail.status_code.should == 'OD'
639
+ detail.status_desc.should == 'On FedEx vehicle for delivery'
640
+ detail.tracking_number.should == '9611018034267800045212'
641
+ detail.weight.units.should == 'LB'
642
+ detail.weight.value.should == 2
643
+ events = detail.events
644
+ events.size.should == 10
645
+ first_event = events[0]
646
+ first_event.eventdescription.should == 'On FedEx vehicle for delivery'
647
+ first_event.eventtype.should == 'OD'
648
+ first_event.timestamp.should == '2009-01-02T06:00:00'
649
+ first_event.address.city.should == 'WICHITA'
650
+ first_event.address.countrycode.should == 'US'
651
+ first_event.address.residential.should be_false
652
+ first_event.address.state.should == 'KS'
653
+ first_event.address.zip.should == '67226'
654
+ last_event = events[-1]
655
+ last_event.eventdescription.should == 'In FedEx possession'
656
+ last_event.eventtype.should == 'IP'
657
+ last_event.timestamp.should == '2008-12-27T09:40:00'
658
+ last_event.address.city.should == 'LONGWOOD'
659
+ last_event.address.countrycode.should == 'US'
660
+ last_event.address.residential.should be_false
661
+ last_event.address.state.should == 'FL'
662
+ last_event.address.zip.should == '327506398'
663
+ track.tran_detail.cust_tran_id.should == '20090102-111321'
664
+ end
665
+
666
+ it "should be able to parse google analytics api xml" do
667
+ data = Analytics::Feed.parse(fixture_file('analytics.xml'))
668
+ data.id.should == 'http://www.google.com/analytics/feeds/accounts/nunemaker@gmail.com'
669
+ data.entries.size.should == 4
670
+
671
+ entry = data.entries[0]
672
+ entry.title.should == 'addictedtonew.com'
673
+ entry.properties.size.should == 4
674
+
675
+ property = entry.properties[0]
676
+ property.name.should == 'ga:accountId'
677
+ property.value.should == '85301'
678
+ end
679
+
680
+ it "should allow instantiating with a string" do
681
+ module StringFoo
682
+ class Bar
683
+ include HappyMapper
684
+ has_many :things, 'StringFoo::Thing'
685
+ end
686
+
687
+ class Thing
688
+ include HappyMapper
689
+ end
690
+ end
691
+ end
692
+
693
+ xit "should parse family search xml" do
694
+ tree = FamilySearch::FamilyTree.parse(fixture_file('family_tree.xml'))
695
+ tree.version.should == '1.0.20071213.942'
696
+ tree.status_message.should == 'OK'
697
+ tree.status_code.should == '200'
698
+ tree.persons.person.size.should == 1
699
+ tree.persons.person.first.version.should == '1199378491000'
700
+ tree.persons.person.first.modified.should == Time.utc(2008, 1, 3, 16, 41, 31) # 2008-01-03T09:41:31-07:00
701
+ tree.persons.person.first.id.should == 'KWQS-BBQ'
702
+ tree.persons.person.first.information.alternateIds.ids.should_not be_kind_of(String)
703
+ tree.persons.person.first.information.alternateIds.ids.size.should == 8
704
+ end
705
+
706
+ it "should parse multiple images" do
707
+ artist = Artist.parse(fixture_file('multiple_primitives.xml'))
708
+ artist.name.should == "value"
709
+ artist.images.size.should == 2
710
+ end
711
+
712
+ it "should parse lastfm namespaces" do
713
+ l = Location.parse(fixture_file('lastfm.xml'))
714
+ l.first.latitude.should == "51.53469"
715
+ end
716
+
717
+ describe 'Xml Content' do
718
+ before(:each) do
719
+ file_contents = fixture_file('dictionary.xml')
720
+ @records = Dictionary::Record.parse(file_contents)
721
+ end
722
+
723
+ it "should parse XmlContent" do
724
+ @records.first.definitions.first.text.should ==
725
+ 'a large common parrot, <bn>Cacatua galerita</bn>, predominantly white, with yellow on the undersides of wings and tail and a forward curving yellow crest, found in Australia, New Guinea and nearby islands.'
726
+ end
727
+
728
+ it "should save object's xml content" do
729
+ @records.first.variants.first.xml_content.should ==
730
+ 'white <tag>cockatoo</tag>'
731
+ @records.first.variants.last.to_html.should ==
732
+ '<em>white</em> cockatoo'
733
+ end
734
+ end
735
+ end