spec/happymapper_spec.rb in happymapper-0.1.7 vs spec/happymapper_spec.rb in happymapper-0.2.0
- old
+ new
@@ -1,10 +1,129 @@
require File.dirname(__FILE__) + '/spec_helper.rb'
+require 'pp'
-class Place
+class Feature
include HappyMapper
+ element :name, String, :tag => '.|.//text()'
+end
+class FeatureBullet
+ include HappyMapper
+
+ tag 'features_bullets'
+ has_many :features, Feature
+ element :bug, String
+end
+
+class Product
+ include HappyMapper
+
+ element :title, String
+ has_one :feature_bullets, FeatureBullet
+end
+
+module FamilySearch
+ class Person
+ include HappyMapper
+
+ attribute :version, String
+ attribute :modified, Time
+ attribute :id, String
+ end
+
+ class Persons
+ include HappyMapper
+ has_many :person, Person
+ end
+
+ class FamilyTree
+ include HappyMapper
+
+ tag 'familytree', :root => true
+ attribute :version, String
+ attribute :status_message, String, :tag => 'statusMessage'
+ attribute :status_code, String, :tag => 'statusCode'
+ has_one :persons, Persons
+ end
+end
+
+module FedEx
+ class Address
+ include HappyMapper
+
+ tag 'Address'
+ element :city, String, :tag => 'City'
+ element :state, String, :tag => 'StateOrProvinceCode'
+ element :zip, String, :tag => 'PostalCode'
+ element :countrycode, String, :tag => 'CountryCode'
+ element :residential, Boolean, :tag => 'Residential'
+ end
+
+ class Event
+ include HappyMapper
+
+ tag 'Events'
+ element :timestamp, String, :tag => 'Timestamp'
+ element :eventtype, String, :tag => 'EventType'
+ element :eventdescription, String, :tag => 'EventDescription'
+ has_one :address, Address
+ end
+
+ class PackageWeight
+ include HappyMapper
+
+ tag 'PackageWeight'
+ element :units, String, :tag => 'Units'
+ element :value, Integer, :tag => 'Value'
+ end
+
+ class TrackDetails
+ include HappyMapper
+
+ tag 'TrackDetails'
+ element :tracking_number, String, :tag => 'TrackingNumber'
+ element :status_code, String, :tag => 'StatusCode'
+ element :status_desc, String, :tag => 'StatusDescription'
+ element :carrier_code, String, :tag => 'CarrierCode'
+ element :service_info, String, :tag => 'ServiceInfo'
+ has_one :weight, PackageWeight, :tag => 'PackageWeight'
+ element :est_delivery, String, :tag => 'EstimatedDeliveryTimestamp'
+ has_many :events, Event
+ end
+
+ class Notification
+ include HappyMapper
+
+ tag 'Notifications'
+ element :severity, String, :tag => 'Severity'
+ element :source, String, :tag => 'Source'
+ element :code, Integer, :tag => 'Code'
+ element :message, String, :tag => 'Message'
+ element :localized_message, String, :tag => 'LocalizedMessage'
+ end
+
+ class TransactionDetail
+ include HappyMapper
+
+ tag 'TransactionDetail'
+ element :cust_tran_id, String, :tag => 'CustomerTransactionId'
+ end
+
+ class TrackReply
+ include HappyMapper
+
+ tag 'TrackReply', :root => true
+ element :highest_severity, String, :tag => 'HighestSeverity'
+ element :more_data, Boolean, :tag => 'MoreData'
+ has_many :notifications, Notification, :tag => 'Notifications'
+ has_many :trackdetails, TrackDetails, :tag => 'TrackDetails'
+ has_one :tran_detail, TransactionDetail, :tab => 'TransactionDetail'
+ end
+end
+
+class Place
+ include HappyMapper
element :name, String
end
class Radar
include HappyMapper
@@ -51,19 +170,21 @@
has_one :user, User
end
class CurrentWeather
include HappyMapper
- tag 'aws:ob'
- element :temperature, Integer, :tag => 'aws:temp'
- element :feels_like, Integer, :tag => 'aws:feels-like'
- element :current_condition, String, :tag => 'aws:current-condition', :attributes => {:icon => String}
+
+ tag 'ob'
+ element :temperature, Integer, :tag => 'temp'
+ element :feels_like, Integer, :tag => 'feels-like'
+ element :current_condition, String, :tag => 'current-condition', :attributes => {:icon => String}
end
class Address
include HappyMapper
+ tag 'address', :root => true
element :street, String
element :postcode, String
element :housenumber, String
element :city, String
element :country, String
@@ -91,12 +212,11 @@
module GitHub
class Commit
include HappyMapper
- tag "commit"
-
+ tag "commit", :root => true
element :url, String
element :tree, String
element :message, String
element :id, String
element :'committed-date', Date
@@ -169,14 +289,19 @@
element.name.should == 'users'
element.type.should == User
element.options[:single] = false
end
- it "should default tag name to class" do
+ it "should default tag name to lowercase class" do
Foo.get_tag_name.should == 'foo'
end
+ it "should default tag name of class in modules to the last constant lowercase" do
+ module Bar; class Baz; include HappyMapper; end; end
+ Bar::Baz.get_tag_name.should == 'baz'
+ end
+
it "should allow setting tag name" do
Foo.tag('FooBar')
Foo.get_tag_name.should == 'FooBar'
end
@@ -197,141 +322,174 @@
Post.elements.size.should == 0
Status.elements.size.should == 9
end
end
- describe "#parse (with xml attributes mapping to ruby attributes)" do
- before do
- @posts = Post.parse(File.read(File.dirname(__FILE__) + '/fixtures/posts.xml'))
- end
-
- it "should get the correct number of elements" do
- @posts.size.should == 20
- end
-
- it "should properly create objects" do
- first = @posts.first
- first.href.should == 'http://roxml.rubyforge.org/'
- first.hash.should == '19bba2ab667be03a19f67fb67dc56917'
- first.description.should == 'ROXML - Ruby Object to XML Mapping Library'
- first.tag.should == 'ruby xml gems mapping'
- first.time.should == Time.utc(2008, 8, 9, 5, 24, 20)
- first.others.should == 56
- 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.'
- end
+ it "should parse xml attributes into ruby objects" do
+ posts = Post.parse(fixture_file('posts.xml'))
+ posts.size.should == 20
+ first = posts.first
+ first.href.should == 'http://roxml.rubyforge.org/'
+ first.hash.should == '19bba2ab667be03a19f67fb67dc56917'
+ first.description.should == 'ROXML - Ruby Object to XML Mapping Library'
+ first.tag.should == 'ruby xml gems mapping'
+ first.time.should == Time.utc(2008, 8, 9, 5, 24, 20)
+ first.others.should == 56
+ 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.'
end
- describe "#parse (with xml elements mapping to ruby attributes)" do
- before do
- @statuses = Status.parse(File.read(File.dirname(__FILE__) + '/fixtures/statuses.xml'))
- end
-
- it "should get the correct number of elements" do
- @statuses.size.should == 20
- end
-
- it "should properly create objects" do
- first = @statuses.first
- first.id.should == 882281424
- first.created_at.should == Time.utc(2008, 8, 9, 5, 38, 12)
- first.source.should == 'web'
- first.truncated.should be_false
- first.in_reply_to_status_id.should == 1234
- first.in_reply_to_user_id.should == 12345
- first.favorited.should be_false
- first.user.id.should == 4243
- first.user.name.should == 'John Nunemaker'
- first.user.screen_name.should == 'jnunemaker'
- first.user.location.should == 'Mishawaka, IN, US'
- first.user.description.should == 'Loves his wife, ruby, notre dame football and iu basketball'
- first.user.profile_image_url.should == 'http://s3.amazonaws.com/twitter_production/profile_images/53781608/Photo_75_normal.jpg'
- first.user.url.should == 'http://addictedtonew.com'
- first.user.protected.should be_false
- first.user.followers_count.should == 486
- end
+ it "should parse xml elements to ruby objcts" do
+ statuses = Status.parse(fixture_file('statuses.xml'))
+ statuses.size.should == 20
+ first = statuses.first
+ first.id.should == 882281424
+ first.created_at.should == Time.utc(2008, 8, 9, 5, 38, 12)
+ first.source.should == 'web'
+ first.truncated.should be_false
+ first.in_reply_to_status_id.should == 1234
+ first.in_reply_to_user_id.should == 12345
+ first.favorited.should be_false
+ first.user.id.should == 4243
+ first.user.name.should == 'John Nunemaker'
+ first.user.screen_name.should == 'jnunemaker'
+ first.user.location.should == 'Mishawaka, IN, US'
+ first.user.description.should == 'Loves his wife, ruby, notre dame football and iu basketball'
+ first.user.profile_image_url.should == 'http://s3.amazonaws.com/twitter_production/profile_images/53781608/Photo_75_normal.jpg'
+ first.user.url.should == 'http://addictedtonew.com'
+ first.user.protected.should be_false
+ first.user.followers_count.should == 486
end
-
- describe "#parse (with xml containing the desired element as root node)" do
- before do
- file_contents = File.read(File.dirname(__FILE__) + '/fixtures/address.xml')
- @address = Address.parse(file_contents, :single => true)
- end
-
- it "should properly create objects" do
- @address.street.should == 'Milchstrasse'
- @address.postcode.should == '26131'
- @address.housenumber.should == '23'
- @address.city.should == 'Oldenburg'
- @address.country.should == 'Germany'
- end
- end
- # TODO: someone please get xml with namespaces working, kthxbai
- describe "#parse (with xml that has namespace)" do
- before do
- file_contents = File.read(File.dirname(__FILE__) + '/fixtures/pita.xml')
- @items = PITA::Items.parse(file_contents, :single => true, :use_default_namespace => true)
- end
-
- it "should properly create objects" do
- @items.total_results.should == 22
- @items.total_pages.should == 3
- first = @items.items[0]
- second = @items.items[1]
- first.asin.should == '0321480791'
- first.detail_page_url.should == 'http://www.amazon.com/gp/redirect.html%3FASIN=0321480791%26tag=ws%26lcode=xm2%26cID=2025%26ccmID=165953%26location=/o/ASIN/0321480791%253FSubscriptionId=dontbeaswoosh'
- first.manufacturer.should == 'Addison-Wesley Professional'
- second.asin.should == '047022388X'
- second.manufacturer.should == 'Wrox'
- end
+ it "should parse xml containing the desired element as root node" do
+ address = Address.parse(fixture_file('address.xml'), :single => true)
+ address.street.should == 'Milchstrasse'
+ address.postcode.should == '26131'
+ address.housenumber.should == '23'
+ address.city.should == 'Oldenburg'
+ address.country.should == 'Germany'
end
- describe "#parse (with xml that has attributes of elements)" do
- before do
- file_contents = File.read(File.dirname(__FILE__) + '/fixtures/current_weather.xml')
- @items = CurrentWeather.parse(file_contents)
- end
-
- it "should properly create objects" do
- @first = @items[0]
- @first.temperature.should == 51
- @first.feels_like.should == 51
- @first.current_condition.should == 'Sunny'
- @first.current_condition.icon.should == 'http://deskwx.weatherbug.com/images/Forecast/icons/cond007.gif'
- end
+ it "should parse xml with default namespace (amazon)" do
+ file_contents = fixture_file('pita.xml')
+ items = PITA::Items.parse(file_contents, :single => true)
+ items.total_results.should == 22
+ items.total_pages.should == 3
+ first = items.items[0]
+ second = items.items[1]
+ first.asin.should == '0321480791'
+ first.detail_page_url.should == 'http://www.amazon.com/gp/redirect.html%3FASIN=0321480791%26tag=ws%26lcode=xm2%26cID=2025%26ccmID=165953%26location=/o/ASIN/0321480791%253FSubscriptionId=dontbeaswoosh'
+ first.manufacturer.should == 'Addison-Wesley Professional'
+ second.asin.should == '047022388X'
+ second.manufacturer.should == 'Wrox'
end
- describe "#parse (with xml that has nested elements)" do
- before do
- file_contents = File.read(File.dirname(__FILE__) + '/fixtures/radar.xml')
- @radars = Radar.parse(file_contents)
- end
-
- it "should properly create objects" do
- @first = @radars[0]
- @first.places.size.should == 1
- @first.places[0].name.should == 'Store'
- @second = @radars[1]
- @second.places.size.should == 0
- @third = @radars[2]
- @third.places.size.should == 2
- @third.places[0].name.should == 'Work'
- @third.places[1].name.should == 'Home'
- end
+ it "should parse xml that has attributes of elements" do
+ items = CurrentWeather.parse(fixture_file('current_weather.xml'))
+ first = items[0]
+ first.temperature.should == 51
+ first.feels_like.should == 51
+ first.current_condition.should == 'Sunny'
+ first.current_condition.icon.should == 'http://deskwx.weatherbug.com/images/Forecast/icons/cond007.gif'
end
- describe "#parse (with xml that has elements with dashes in them)" do
- before do
- file_contents = File.read(File.dirname(__FILE__) + '/fixtures/commit.xml')
- @commit = GitHub::Commit.parse(file_contents).first
- end
-
- it "should properly create objects" do
- @commit.message.should == "move commands.rb and helpers.rb into commands/ dir"
- @commit.url.should == "http://github.com/defunkt/github-gem/commit/c26d4ce9807ecf57d3f9eefe19ae64e75bcaaa8b"
- @commit.id.should == "c26d4ce9807ecf57d3f9eefe19ae64e75bcaaa8b"
- @commit.committed_date.should == Date.parse("2008-03-02T16:45:41-08:00")
- @commit.tree.should == "28a1a1ca3e663d35ba8bf07d3f1781af71359b76"
- end
-
+ it "should parse xml with nested elements" do
+ radars = Radar.parse(fixture_file('radar.xml'))
+ first = radars[0]
+ first.places.size.should == 1
+ first.places[0].name.should == 'Store'
+ second = radars[1]
+ second.places.size.should == 0
+ third = radars[2]
+ third.places.size.should == 2
+ third.places[0].name.should == 'Work'
+ third.places[1].name.should == 'Home'
+ end
+
+ it "should parse xml that has elements with dashes" do
+ commit = GitHub::Commit.parse(fixture_file('commit.xml'))
+ commit.message.should == "move commands.rb and helpers.rb into commands/ dir"
+ commit.url.should == "http://github.com/defunkt/github-gem/commit/c26d4ce9807ecf57d3f9eefe19ae64e75bcaaa8b"
+ commit.id.should == "c26d4ce9807ecf57d3f9eefe19ae64e75bcaaa8b"
+ commit.committed_date.should == Date.parse("2008-03-02T16:45:41-08:00")
+ commit.tree.should == "28a1a1ca3e663d35ba8bf07d3f1781af71359b76"
+ end
+
+ it "should parse xml with no namespace" do
+ product = Product.parse(fixture_file('product_no_namespace.xml'), :single => true)
+ product.title.should == "A Title"
+ product.feature_bullets.bug.should == 'This is a bug'
+ product.feature_bullets.features.size.should == 2
+ product.feature_bullets.features[0].name.should == 'This is feature text 1'
+ product.feature_bullets.features[1].name.should == 'This is feature text 2'
+ end
+
+ it "should parse xml with default namespace" do
+ product = Product.parse(fixture_file('product_default_namespace.xml'), :single => true)
+ product.title.should == "A Title"
+ product.feature_bullets.bug.should == 'This is a bug'
+ product.feature_bullets.features.size.should == 2
+ product.feature_bullets.features[0].name.should == 'This is feature text 1'
+ product.feature_bullets.features[1].name.should == 'This is feature text 2'
+ end
+
+ it "should parse xml with single namespace" do
+ product = Product.parse(fixture_file('product_single_namespace.xml'), :single => true)
+ product.title.should == "A Title"
+ product.feature_bullets.bug.should == 'This is a bug'
+ product.feature_bullets.features.size.should == 2
+ product.feature_bullets.features[0].name.should == 'This is feature text 1'
+ product.feature_bullets.features[1].name.should == 'This is feature text 2'
+ end
+
+ it "should parse xml with multiple namespaces" do
+ track = FedEx::TrackReply.parse(fixture_file('multiple_namespaces.xml'))
+ track.highest_severity.should == 'SUCCESS'
+ track.more_data.should be_false
+ notification = track.notifications.first
+ notification.code.should == 0
+ notification.localized_message.should == 'Request was successfully processed.'
+ notification.message.should == 'Request was successfully processed.'
+ notification.severity.should == 'SUCCESS'
+ notification.source.should == 'trck'
+ detail = track.trackdetails.first
+ detail.carrier_code.should == 'FDXG'
+ detail.est_delivery.should == '2009-01-02T00:00:00'
+ detail.service_info.should == 'Ground-Package Returns Program-Domestic'
+ detail.status_code.should == 'OD'
+ detail.status_desc.should == 'On FedEx vehicle for delivery'
+ detail.tracking_number.should == '9611018034267800045212'
+ detail.weight.units.should == 'LB'
+ detail.weight.value.should == 2
+ events = detail.events
+ events.size.should == 10
+ first_event = events[0]
+ first_event.eventdescription.should == 'On FedEx vehicle for delivery'
+ first_event.eventtype.should == 'OD'
+ first_event.timestamp.should == '2009-01-02T06:00:00'
+ first_event.address.city.should == 'WICHITA'
+ first_event.address.countrycode.should == 'US'
+ first_event.address.residential.should be_false
+ first_event.address.state.should == 'KS'
+ first_event.address.zip.should == '67226'
+ last_event = events[-1]
+ last_event.eventdescription.should == 'In FedEx possession'
+ last_event.eventtype.should == 'IP'
+ last_event.timestamp.should == '2008-12-27T09:40:00'
+ last_event.address.city.should == 'LONGWOOD'
+ last_event.address.countrycode.should == 'US'
+ last_event.address.residential.should be_false
+ last_event.address.state.should == 'FL'
+ last_event.address.zip.should == '327506398'
+ track.tran_detail.cust_tran_id.should == '20090102-111321'
+ end
+
+ xit "should parse family search xml" do
+ tree = FamilySearch::FamilyTree.parse(fixture_file('family_tree.xml'))
+ tree.version.should == '1.0.20071213.942'
+ tree.status_message.should == 'OK'
+ tree.status_code.should == '200'
+ # tree.people.size.should == 1
+ # tree.people.first.version.should == '1199378491000'
+ # tree.people.first.modified.should == Time.utc(2008, 1, 3, 16, 41, 31) # 2008-01-03T09:41:31-07:00
+ # tree.people.first.id.should == 'KWQS-BBQ'
end
end