httparty 0.2.10 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of httparty might be problematic. Click here for more details.
- data/History +6 -0
- data/Manifest +9 -2
- data/README +2 -2
- data/Rakefile +0 -1
- data/bin/httparty +13 -29
- data/httparty.gemspec +4 -7
- data/lib/core_extensions.rb +42 -220
- data/lib/httparty.rb +76 -16
- data/lib/httparty/cookie_hash.rb +1 -1
- data/lib/httparty/exceptions.rb +3 -0
- data/lib/httparty/module_inheritable_attributes.rb +25 -0
- data/lib/httparty/parsers.rb +4 -0
- data/lib/httparty/parsers/json.rb +67 -0
- data/lib/httparty/parsers/xml.rb +209 -0
- data/lib/httparty/request.rb +19 -13
- data/lib/httparty/response.rb +3 -2
- data/lib/httparty/version.rb +2 -2
- data/spec/hash_spec.rb +44 -0
- data/spec/httparty/parsers/json_spec.rb +41 -0
- data/spec/httparty/parsers/xml_spec.rb +445 -0
- data/spec/httparty/response_spec.rb +53 -0
- data/spec/string_spec.rb +27 -0
- metadata +15 -15
- data/lib/module_level_inheritable_attributes.rb +0 -25
- data/spec/as_buggery_spec.rb +0 -16
data/lib/httparty/request.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'uri'
|
2
2
|
|
3
3
|
module HTTParty
|
4
|
-
class Request
|
4
|
+
class Request #:nodoc:
|
5
5
|
SupportedHTTPMethods = [Net::HTTP::Get, Net::HTTP::Post, Net::HTTP::Put, Net::HTTP::Delete]
|
6
6
|
|
7
7
|
attr_accessor :http_method, :path, :options
|
@@ -21,7 +21,12 @@ module HTTParty
|
|
21
21
|
|
22
22
|
def uri
|
23
23
|
new_uri = path.relative? ? URI.parse("#{options[:base_uri]}#{path}") : path
|
24
|
-
|
24
|
+
|
25
|
+
# avoid double query string on redirects [#12]
|
26
|
+
unless @redirect
|
27
|
+
new_uri.query = query_string(new_uri)
|
28
|
+
end
|
29
|
+
|
25
30
|
new_uri
|
26
31
|
end
|
27
32
|
|
@@ -30,13 +35,13 @@ module HTTParty
|
|
30
35
|
end
|
31
36
|
|
32
37
|
def perform
|
33
|
-
validate
|
38
|
+
validate
|
34
39
|
setup_raw_request
|
35
|
-
handle_response
|
40
|
+
handle_response(get_response)
|
36
41
|
end
|
37
42
|
|
38
43
|
private
|
39
|
-
def http
|
44
|
+
def http
|
40
45
|
http = Net::HTTP.new(uri.host, uri.port, options[:http_proxyaddr], options[:http_proxyport])
|
41
46
|
http.use_ssl = (uri.port == 443)
|
42
47
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
@@ -64,13 +69,13 @@ module HTTParty
|
|
64
69
|
http.request(@raw_request)
|
65
70
|
end
|
66
71
|
|
67
|
-
def get_response
|
72
|
+
def get_response
|
68
73
|
response = perform_actual_request
|
69
74
|
options[:format] ||= format_from_mimetype(response['content-type'])
|
70
75
|
response
|
71
76
|
end
|
72
77
|
|
73
|
-
def query_string(uri)
|
78
|
+
def query_string(uri)
|
74
79
|
query_string_parts = []
|
75
80
|
query_string_parts << uri.query unless uri.query.blank?
|
76
81
|
|
@@ -85,11 +90,12 @@ module HTTParty
|
|
85
90
|
end
|
86
91
|
|
87
92
|
# Raises exception Net::XXX (http error code) if an http error occured
|
88
|
-
def handle_response
|
93
|
+
def handle_response(response)
|
89
94
|
case response
|
90
95
|
when Net::HTTPRedirection
|
91
96
|
options[:limit] -= 1
|
92
97
|
self.path = response['location']
|
98
|
+
@redirect = true
|
93
99
|
perform
|
94
100
|
else
|
95
101
|
parsed_response = parse_response(response.body)
|
@@ -97,13 +103,13 @@ module HTTParty
|
|
97
103
|
end
|
98
104
|
end
|
99
105
|
|
100
|
-
def parse_response(body)
|
106
|
+
def parse_response(body)
|
101
107
|
return nil if body.nil? or body.empty?
|
102
108
|
case format
|
103
109
|
when :xml
|
104
|
-
|
110
|
+
HTTParty::Parsers::XML.parse(body)
|
105
111
|
when :json
|
106
|
-
JSON.
|
112
|
+
HTTParty::Parsers::JSON.decode(body)
|
107
113
|
else
|
108
114
|
body
|
109
115
|
end
|
@@ -111,12 +117,12 @@ module HTTParty
|
|
111
117
|
|
112
118
|
# Uses the HTTP Content-Type header to determine the format of the response
|
113
119
|
# It compares the MIME type returned to the types stored in the AllowedFormats hash
|
114
|
-
def format_from_mimetype(mimetype)
|
120
|
+
def format_from_mimetype(mimetype)
|
115
121
|
return nil if mimetype.nil?
|
116
122
|
AllowedFormats.each { |k, v| return v if mimetype.include?(k) }
|
117
123
|
end
|
118
124
|
|
119
|
-
def validate
|
125
|
+
def validate
|
120
126
|
raise HTTParty::RedirectionTooDeep, 'HTTP redirects too deep' if options[:limit].to_i <= 0
|
121
127
|
raise ArgumentError, 'only get, post, put and delete methods are supported' unless SupportedHTTPMethods.include?(http_method)
|
122
128
|
raise ArgumentError, ':headers must be a hash' if options[:headers] && !options[:headers].is_a?(Hash)
|
data/lib/httparty/response.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
module HTTParty
|
2
|
-
class Response < BlankSlate
|
2
|
+
class Response < BlankSlate #:nodoc:
|
3
3
|
attr_accessor :body, :code, :headers
|
4
|
+
attr_reader :delegate
|
4
5
|
|
5
|
-
def initialize(delegate, body, code, headers)
|
6
|
+
def initialize(delegate, body, code, headers={})
|
6
7
|
@delegate = delegate
|
7
8
|
@body = body
|
8
9
|
@code = code
|
data/lib/httparty/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
module HTTParty
|
2
|
-
Version = '0.
|
1
|
+
module HTTParty #:nodoc:
|
2
|
+
Version = '0.3.0'
|
3
3
|
end
|
data/spec/hash_spec.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe Hash, "to_xml_attributes" do
|
4
|
+
before do
|
5
|
+
@hash = { :one => "ONE", "two" => "TWO" }
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should turn the hash into xml attributes" do
|
9
|
+
attrs = @hash.to_xml_attributes
|
10
|
+
attrs.should match(/one="ONE"/m)
|
11
|
+
attrs.should match(/two="TWO"/m)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should preserve _ in hash keys' do
|
15
|
+
attrs = {
|
16
|
+
:some_long_attribute => "with short value",
|
17
|
+
:crash => :burn,
|
18
|
+
:merb => "uses extlib"
|
19
|
+
}.to_xml_attributes
|
20
|
+
|
21
|
+
attrs.should =~ /some_long_attribute="with short value"/
|
22
|
+
attrs.should =~ /merb="uses extlib"/
|
23
|
+
attrs.should =~ /crash="burn"/
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
describe Hash, 'to_params' do
|
29
|
+
{
|
30
|
+
{ "foo" => "bar", "baz" => "bat" } => "foo=bar&baz=bat",
|
31
|
+
{ "foo" => [ "bar", "baz" ] } => "foo[]=bar&foo[]=baz",
|
32
|
+
{ "foo" => [ {"bar" => "1"}, {"bar" => 2} ] } => "foo[][bar]=1&foo[][bar]=2",
|
33
|
+
{ "foo" => { "bar" => [ {"baz" => 1}, {"baz" => "2"} ] } } => "foo[bar][][baz]=1&foo[bar][][baz]=2",
|
34
|
+
{ "foo" => {"1" => "bar", "2" => "baz"} } => "foo[1]=bar&foo[2]=baz"
|
35
|
+
}.each do |hash, params|
|
36
|
+
it "should covert hash: #{hash.inspect} to params: #{params.inspect}" do
|
37
|
+
hash.to_params.split('&').sort.should == params.split('&').sort
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should not leave a trailing &' do
|
42
|
+
{ :name => 'Bob', :address => { :street => '111 Ruby Ave.', :city => 'Ruby Central', :phones => ['111-111-1111', '222-222-2222'] } }.to_params.should_not match(/&$/)
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
|
2
|
+
|
3
|
+
describe HTTParty::Parsers::JSON do
|
4
|
+
TESTS = {
|
5
|
+
%q({"returnTo":{"\/categories":"\/"}}) => {"returnTo" => {"/categories" => "/"}},
|
6
|
+
%q({returnTo:{"\/categories":"\/"}}) => {"returnTo" => {"/categories" => "/"}},
|
7
|
+
%q({"return\\"To\\":":{"\/categories":"\/"}}) => {"return\"To\":" => {"/categories" => "/"}},
|
8
|
+
%q({"returnTo":{"\/categories":1}}) => {"returnTo" => {"/categories" => 1}},
|
9
|
+
%({"returnTo":[1,"a"]}) => {"returnTo" => [1, "a"]},
|
10
|
+
%({"returnTo":[1,"\\"a\\",", "b"]}) => {"returnTo" => [1, "\"a\",", "b"]},
|
11
|
+
%({a: "'", "b": "5,000"}) => {"a" => "'", "b" => "5,000"},
|
12
|
+
%({a: "a's, b's and c's", "b": "5,000"}) => {"a" => "a's, b's and c's", "b" => "5,000"},
|
13
|
+
%({a: "2007-01-01"}) => {'a' => Date.new(2007, 1, 1)},
|
14
|
+
%({a: "2007-01-01 01:12:34 Z"}) => {'a' => Time.utc(2007, 1, 1, 1, 12, 34)},
|
15
|
+
# no time zone
|
16
|
+
%({a: "2007-01-01 01:12:34"}) => {'a' => "2007-01-01 01:12:34"},
|
17
|
+
%([]) => [],
|
18
|
+
%({}) => {},
|
19
|
+
%(1) => 1,
|
20
|
+
%("") => "",
|
21
|
+
%("\\"") => "\"",
|
22
|
+
%(null) => nil,
|
23
|
+
%(true) => true,
|
24
|
+
%(false) => false,
|
25
|
+
%q("http:\/\/test.host\/posts\/1") => "http://test.host/posts/1"
|
26
|
+
}
|
27
|
+
|
28
|
+
TESTS.each do |json, expected|
|
29
|
+
it "should decode json (#{json})" do
|
30
|
+
lambda {
|
31
|
+
HTTParty::Parsers::JSON.decode(json).should == expected
|
32
|
+
}.should_not raise_error
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should raise error for failed decoding" do
|
37
|
+
lambda {
|
38
|
+
HTTParty::Parsers::JSON.decode(%({: 1}))
|
39
|
+
}.should raise_error(HTTParty::Parsers::JSON::ParseError)
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,445 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
|
2
|
+
|
3
|
+
require "date"
|
4
|
+
require 'bigdecimal'
|
5
|
+
|
6
|
+
describe HTTParty::Parsers::XML, "#parse" do
|
7
|
+
it "should transform a simple tag with content" do
|
8
|
+
xml = "<tag>This is the contents</tag>"
|
9
|
+
HTTParty::Parsers::XML.parse(xml).should == { 'tag' => 'This is the contents' }
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should work with cdata tags" do
|
13
|
+
xml = <<-END
|
14
|
+
<tag>
|
15
|
+
<![CDATA[
|
16
|
+
text inside cdata
|
17
|
+
]]>
|
18
|
+
</tag>
|
19
|
+
END
|
20
|
+
HTTParty::Parsers::XML.parse(xml)["tag"].strip.should == "text inside cdata"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should transform a simple tag with attributes" do
|
24
|
+
xml = "<tag attr1='1' attr2='2'></tag>"
|
25
|
+
hash = { 'tag' => { 'attr1' => '1', 'attr2' => '2' } }
|
26
|
+
HTTParty::Parsers::XML.parse(xml).should == hash
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should transform repeating siblings into an array" do
|
30
|
+
xml =<<-XML
|
31
|
+
<opt>
|
32
|
+
<user login="grep" fullname="Gary R Epstein" />
|
33
|
+
<user login="stty" fullname="Simon T Tyson" />
|
34
|
+
</opt>
|
35
|
+
XML
|
36
|
+
|
37
|
+
HTTParty::Parsers::XML.parse(xml)['opt']['user'].should be_an_instance_of(Array)
|
38
|
+
|
39
|
+
hash = {
|
40
|
+
'opt' => {
|
41
|
+
'user' => [{
|
42
|
+
'login' => 'grep',
|
43
|
+
'fullname' => 'Gary R Epstein'
|
44
|
+
},{
|
45
|
+
'login' => 'stty',
|
46
|
+
'fullname' => 'Simon T Tyson'
|
47
|
+
}]
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
HTTParty::Parsers::XML.parse(xml).should == hash
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should not transform non-repeating siblings into an array" do
|
55
|
+
xml =<<-XML
|
56
|
+
<opt>
|
57
|
+
<user login="grep" fullname="Gary R Epstein" />
|
58
|
+
</opt>
|
59
|
+
XML
|
60
|
+
|
61
|
+
HTTParty::Parsers::XML.parse(xml)['opt']['user'].should be_an_instance_of(Hash)
|
62
|
+
|
63
|
+
hash = {
|
64
|
+
'opt' => {
|
65
|
+
'user' => {
|
66
|
+
'login' => 'grep',
|
67
|
+
'fullname' => 'Gary R Epstein'
|
68
|
+
}
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
72
|
+
HTTParty::Parsers::XML.parse(xml).should == hash
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should typecast an integer" do
|
76
|
+
xml = "<tag type='integer'>10</tag>"
|
77
|
+
HTTParty::Parsers::XML.parse(xml)['tag'].should == 10
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should typecast a true boolean" do
|
81
|
+
xml = "<tag type='boolean'>true</tag>"
|
82
|
+
HTTParty::Parsers::XML.parse(xml)['tag'].should be_true
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should typecast a false boolean" do
|
86
|
+
["false"].each do |w|
|
87
|
+
HTTParty::Parsers::XML.parse("<tag type='boolean'>#{w}</tag>")['tag'].should be_false
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should typecast a datetime" do
|
92
|
+
xml = "<tag type='datetime'>2007-12-31 10:32</tag>"
|
93
|
+
HTTParty::Parsers::XML.parse(xml)['tag'].should == Time.parse( '2007-12-31 10:32' ).utc
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should typecast a date" do
|
97
|
+
xml = "<tag type='date'>2007-12-31</tag>"
|
98
|
+
HTTParty::Parsers::XML.parse(xml)['tag'].should == Date.parse('2007-12-31')
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should unescape html entities" do
|
102
|
+
values = {
|
103
|
+
"<" => "<",
|
104
|
+
">" => ">",
|
105
|
+
'"' => """,
|
106
|
+
"'" => "'",
|
107
|
+
"&" => "&"
|
108
|
+
}
|
109
|
+
values.each do |k,v|
|
110
|
+
xml = "<tag>Some content #{v}</tag>"
|
111
|
+
HTTParty::Parsers::XML.parse(xml)['tag'].should match(Regexp.new(k))
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should undasherize keys as tags" do
|
116
|
+
xml = "<tag-1>Stuff</tag-1>"
|
117
|
+
HTTParty::Parsers::XML.parse(xml).keys.should include( 'tag_1' )
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should undasherize keys as attributes" do
|
121
|
+
xml = "<tag1 attr-1='1'></tag1>"
|
122
|
+
HTTParty::Parsers::XML.parse(xml)['tag1'].keys.should include( 'attr_1')
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should undasherize keys as tags and attributes" do
|
126
|
+
xml = "<tag-1 attr-1='1'></tag-1>"
|
127
|
+
HTTParty::Parsers::XML.parse(xml).keys.should include( 'tag_1' )
|
128
|
+
HTTParty::Parsers::XML.parse(xml)['tag_1'].keys.should include( 'attr_1')
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should render nested content correctly" do
|
132
|
+
xml = "<root><tag1>Tag1 Content <em><strong>This is strong</strong></em></tag1></root>"
|
133
|
+
HTTParty::Parsers::XML.parse(xml)['root']['tag1'].should == "Tag1 Content <em><strong>This is strong</strong></em>"
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should render nested content with split text nodes correctly" do
|
137
|
+
xml = "<root>Tag1 Content<em>Stuff</em> Hi There</root>"
|
138
|
+
HTTParty::Parsers::XML.parse(xml)['root'].should == "Tag1 Content<em>Stuff</em> Hi There"
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should ignore attributes when a child is a text node" do
|
142
|
+
xml = "<root attr1='1'>Stuff</root>"
|
143
|
+
HTTParty::Parsers::XML.parse(xml).should == { "root" => "Stuff" }
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should ignore attributes when any child is a text node" do
|
147
|
+
xml = "<root attr1='1'>Stuff <em>in italics</em></root>"
|
148
|
+
HTTParty::Parsers::XML.parse(xml).should == { "root" => "Stuff <em>in italics</em>" }
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should correctly transform multiple children" do
|
152
|
+
xml = <<-XML
|
153
|
+
<user gender='m'>
|
154
|
+
<age type='integer'>35</age>
|
155
|
+
<name>Home Simpson</name>
|
156
|
+
<dob type='date'>1988-01-01</dob>
|
157
|
+
<joined-at type='datetime'>2000-04-28 23:01</joined-at>
|
158
|
+
<is-cool type='boolean'>true</is-cool>
|
159
|
+
</user>
|
160
|
+
XML
|
161
|
+
|
162
|
+
hash = {
|
163
|
+
"user" => {
|
164
|
+
"gender" => "m",
|
165
|
+
"age" => 35,
|
166
|
+
"name" => "Home Simpson",
|
167
|
+
"dob" => Date.parse('1988-01-01'),
|
168
|
+
"joined_at" => Time.parse("2000-04-28 23:01"),
|
169
|
+
"is_cool" => true
|
170
|
+
}
|
171
|
+
}
|
172
|
+
|
173
|
+
HTTParty::Parsers::XML.parse(xml).should == hash
|
174
|
+
end
|
175
|
+
|
176
|
+
it "should properly handle nil values (ActiveSupport Compatible)" do
|
177
|
+
topic_xml = <<-EOT
|
178
|
+
<topic>
|
179
|
+
<title></title>
|
180
|
+
<id type="integer"></id>
|
181
|
+
<approved type="boolean"></approved>
|
182
|
+
<written-on type="date"></written-on>
|
183
|
+
<viewed-at type="datetime"></viewed-at>
|
184
|
+
<content type="yaml"></content>
|
185
|
+
<parent-id></parent-id>
|
186
|
+
</topic>
|
187
|
+
EOT
|
188
|
+
|
189
|
+
expected_topic_hash = {
|
190
|
+
'title' => nil,
|
191
|
+
'id' => nil,
|
192
|
+
'approved' => nil,
|
193
|
+
'written_on' => nil,
|
194
|
+
'viewed_at' => nil,
|
195
|
+
'content' => nil,
|
196
|
+
'parent_id' => nil
|
197
|
+
}
|
198
|
+
HTTParty::Parsers::XML.parse(topic_xml)["topic"].should == expected_topic_hash
|
199
|
+
end
|
200
|
+
|
201
|
+
it "should handle a single record from xml (ActiveSupport Compatible)" do
|
202
|
+
topic_xml = <<-EOT
|
203
|
+
<topic>
|
204
|
+
<title>The First Topic</title>
|
205
|
+
<author-name>David</author-name>
|
206
|
+
<id type="integer">1</id>
|
207
|
+
<approved type="boolean"> true </approved>
|
208
|
+
<replies-count type="integer">0</replies-count>
|
209
|
+
<replies-close-in type="integer">2592000000</replies-close-in>
|
210
|
+
<written-on type="date">2003-07-16</written-on>
|
211
|
+
<viewed-at type="datetime">2003-07-16T09:28:00+0000</viewed-at>
|
212
|
+
<content type="yaml">--- \n1: should be an integer\n:message: Have a nice day\narray: \n- should-have-dashes: true\n should_have_underscores: true\n</content>
|
213
|
+
<author-email-address>david@loudthinking.com</author-email-address>
|
214
|
+
<parent-id></parent-id>
|
215
|
+
<ad-revenue type="decimal">1.5</ad-revenue>
|
216
|
+
<optimum-viewing-angle type="float">135</optimum-viewing-angle>
|
217
|
+
<resident type="symbol">yes</resident>
|
218
|
+
</topic>
|
219
|
+
EOT
|
220
|
+
|
221
|
+
expected_topic_hash = {
|
222
|
+
'title' => "The First Topic",
|
223
|
+
'author_name' => "David",
|
224
|
+
'id' => 1,
|
225
|
+
'approved' => true,
|
226
|
+
'replies_count' => 0,
|
227
|
+
'replies_close_in' => 2592000000,
|
228
|
+
'written_on' => Date.new(2003, 7, 16),
|
229
|
+
'viewed_at' => Time.utc(2003, 7, 16, 9, 28),
|
230
|
+
# Changed this line where the key is :message. The yaml specifies this as a symbol, and who am I to change what you specify
|
231
|
+
# The line in ActiveSupport is
|
232
|
+
# 'content' => { 'message' => "Have a nice day", 1 => "should be an integer", "array" => [{ "should-have-dashes" => true, "should_have_underscores" => true }] },
|
233
|
+
'content' => { :message => "Have a nice day", 1 => "should be an integer", "array" => [{ "should-have-dashes" => true, "should_have_underscores" => true }] },
|
234
|
+
'author_email_address' => "david@loudthinking.com",
|
235
|
+
'parent_id' => nil,
|
236
|
+
'ad_revenue' => BigDecimal("1.50"),
|
237
|
+
'optimum_viewing_angle' => 135.0,
|
238
|
+
'resident' => :yes
|
239
|
+
}
|
240
|
+
|
241
|
+
HTTParty::Parsers::XML.parse(topic_xml)["topic"].each do |k,v|
|
242
|
+
v.should == expected_topic_hash[k]
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
it "should handle multiple records (ActiveSupport Compatible)" do
|
247
|
+
topics_xml = <<-EOT
|
248
|
+
<topics type="array">
|
249
|
+
<topic>
|
250
|
+
<title>The First Topic</title>
|
251
|
+
<author-name>David</author-name>
|
252
|
+
<id type="integer">1</id>
|
253
|
+
<approved type="boolean">false</approved>
|
254
|
+
<replies-count type="integer">0</replies-count>
|
255
|
+
<replies-close-in type="integer">2592000000</replies-close-in>
|
256
|
+
<written-on type="date">2003-07-16</written-on>
|
257
|
+
<viewed-at type="datetime">2003-07-16T09:28:00+0000</viewed-at>
|
258
|
+
<content>Have a nice day</content>
|
259
|
+
<author-email-address>david@loudthinking.com</author-email-address>
|
260
|
+
<parent-id nil="true"></parent-id>
|
261
|
+
</topic>
|
262
|
+
<topic>
|
263
|
+
<title>The Second Topic</title>
|
264
|
+
<author-name>Jason</author-name>
|
265
|
+
<id type="integer">1</id>
|
266
|
+
<approved type="boolean">false</approved>
|
267
|
+
<replies-count type="integer">0</replies-count>
|
268
|
+
<replies-close-in type="integer">2592000000</replies-close-in>
|
269
|
+
<written-on type="date">2003-07-16</written-on>
|
270
|
+
<viewed-at type="datetime">2003-07-16T09:28:00+0000</viewed-at>
|
271
|
+
<content>Have a nice day</content>
|
272
|
+
<author-email-address>david@loudthinking.com</author-email-address>
|
273
|
+
<parent-id></parent-id>
|
274
|
+
</topic>
|
275
|
+
</topics>
|
276
|
+
EOT
|
277
|
+
|
278
|
+
expected_topic_hash = {
|
279
|
+
'title' => "The First Topic",
|
280
|
+
'author_name' => "David",
|
281
|
+
'id' => 1,
|
282
|
+
'approved' => false,
|
283
|
+
'replies_count' => 0,
|
284
|
+
'replies_close_in' => 2592000000,
|
285
|
+
'written_on' => Date.new(2003, 7, 16),
|
286
|
+
'viewed_at' => Time.utc(2003, 7, 16, 9, 28),
|
287
|
+
'content' => "Have a nice day",
|
288
|
+
'author_email_address' => "david@loudthinking.com",
|
289
|
+
'parent_id' => nil
|
290
|
+
}
|
291
|
+
# puts HTTParty::Parsers::XML.parse(topics_xml)['topics'].first.inspect
|
292
|
+
HTTParty::Parsers::XML.parse(topics_xml)["topics"].first.each do |k,v|
|
293
|
+
v.should == expected_topic_hash[k]
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
it "should handle a single record from_xml with attributes other than type (ActiveSupport Compatible)" do
|
298
|
+
topic_xml = <<-EOT
|
299
|
+
<rsp stat="ok">
|
300
|
+
<photos page="1" pages="1" perpage="100" total="16">
|
301
|
+
<photo id="175756086" owner="55569174@N00" secret="0279bf37a1" server="76" title="Colored Pencil PhotoBooth Fun" ispublic="1" isfriend="0" isfamily="0"/>
|
302
|
+
</photos>
|
303
|
+
</rsp>
|
304
|
+
EOT
|
305
|
+
|
306
|
+
expected_topic_hash = {
|
307
|
+
'id' => "175756086",
|
308
|
+
'owner' => "55569174@N00",
|
309
|
+
'secret' => "0279bf37a1",
|
310
|
+
'server' => "76",
|
311
|
+
'title' => "Colored Pencil PhotoBooth Fun",
|
312
|
+
'ispublic' => "1",
|
313
|
+
'isfriend' => "0",
|
314
|
+
'isfamily' => "0",
|
315
|
+
}
|
316
|
+
HTTParty::Parsers::XML.parse(topic_xml)["rsp"]["photos"]["photo"].each do |k,v|
|
317
|
+
v.should == expected_topic_hash[k]
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
it "should handle an emtpy array (ActiveSupport Compatible)" do
|
322
|
+
blog_xml = <<-XML
|
323
|
+
<blog>
|
324
|
+
<posts type="array"></posts>
|
325
|
+
</blog>
|
326
|
+
XML
|
327
|
+
expected_blog_hash = {"blog" => {"posts" => []}}
|
328
|
+
HTTParty::Parsers::XML.parse(blog_xml).should == expected_blog_hash
|
329
|
+
end
|
330
|
+
|
331
|
+
it "should handle empty array with whitespace from xml (ActiveSupport Compatible)" do
|
332
|
+
blog_xml = <<-XML
|
333
|
+
<blog>
|
334
|
+
<posts type="array">
|
335
|
+
</posts>
|
336
|
+
</blog>
|
337
|
+
XML
|
338
|
+
expected_blog_hash = {"blog" => {"posts" => []}}
|
339
|
+
HTTParty::Parsers::XML.parse(blog_xml).should == expected_blog_hash
|
340
|
+
end
|
341
|
+
|
342
|
+
it "should handle array with one entry from_xml (ActiveSupport Compatible)" do
|
343
|
+
blog_xml = <<-XML
|
344
|
+
<blog>
|
345
|
+
<posts type="array">
|
346
|
+
<post>a post</post>
|
347
|
+
</posts>
|
348
|
+
</blog>
|
349
|
+
XML
|
350
|
+
expected_blog_hash = {"blog" => {"posts" => ["a post"]}}
|
351
|
+
HTTParty::Parsers::XML.parse(blog_xml).should == expected_blog_hash
|
352
|
+
end
|
353
|
+
|
354
|
+
it "should handle array with multiple entries from xml (ActiveSupport Compatible)" do
|
355
|
+
blog_xml = <<-XML
|
356
|
+
<blog>
|
357
|
+
<posts type="array">
|
358
|
+
<post>a post</post>
|
359
|
+
<post>another post</post>
|
360
|
+
</posts>
|
361
|
+
</blog>
|
362
|
+
XML
|
363
|
+
expected_blog_hash = {"blog" => {"posts" => ["a post", "another post"]}}
|
364
|
+
HTTParty::Parsers::XML.parse(blog_xml).should == expected_blog_hash
|
365
|
+
end
|
366
|
+
|
367
|
+
it "should handle file types (ActiveSupport Compatible)" do
|
368
|
+
blog_xml = <<-XML
|
369
|
+
<blog>
|
370
|
+
<logo type="file" name="logo.png" content_type="image/png">
|
371
|
+
</logo>
|
372
|
+
</blog>
|
373
|
+
XML
|
374
|
+
hash = HTTParty::Parsers::XML.parse(blog_xml)
|
375
|
+
hash.should have_key('blog')
|
376
|
+
hash['blog'].should have_key('logo')
|
377
|
+
|
378
|
+
file = hash['blog']['logo']
|
379
|
+
file.original_filename.should == 'logo.png'
|
380
|
+
file.content_type.should == 'image/png'
|
381
|
+
end
|
382
|
+
|
383
|
+
it "should handle file from xml with defaults (ActiveSupport Compatible)" do
|
384
|
+
blog_xml = <<-XML
|
385
|
+
<blog>
|
386
|
+
<logo type="file">
|
387
|
+
</logo>
|
388
|
+
</blog>
|
389
|
+
XML
|
390
|
+
file = HTTParty::Parsers::XML.parse(blog_xml)['blog']['logo']
|
391
|
+
file.original_filename.should == 'untitled'
|
392
|
+
file.content_type.should == 'application/octet-stream'
|
393
|
+
end
|
394
|
+
|
395
|
+
it "should handle xsd like types from xml (ActiveSupport Compatible)" do
|
396
|
+
bacon_xml = <<-EOT
|
397
|
+
<bacon>
|
398
|
+
<weight type="double">0.5</weight>
|
399
|
+
<price type="decimal">12.50</price>
|
400
|
+
<chunky type="boolean"> 1 </chunky>
|
401
|
+
<expires-at type="dateTime">2007-12-25T12:34:56+0000</expires-at>
|
402
|
+
<notes type="string"></notes>
|
403
|
+
<illustration type="base64Binary">YmFiZS5wbmc=</illustration>
|
404
|
+
</bacon>
|
405
|
+
EOT
|
406
|
+
|
407
|
+
expected_bacon_hash = {
|
408
|
+
'weight' => 0.5,
|
409
|
+
'chunky' => true,
|
410
|
+
'price' => BigDecimal("12.50"),
|
411
|
+
'expires_at' => Time.utc(2007,12,25,12,34,56),
|
412
|
+
'notes' => "",
|
413
|
+
'illustration' => "babe.png"
|
414
|
+
}
|
415
|
+
|
416
|
+
HTTParty::Parsers::XML.parse(bacon_xml)["bacon"].should == expected_bacon_hash
|
417
|
+
end
|
418
|
+
|
419
|
+
it "should let type trickle through when unknown (ActiveSupport Compatible)" do
|
420
|
+
product_xml = <<-EOT
|
421
|
+
<product>
|
422
|
+
<weight type="double">0.5</weight>
|
423
|
+
<image type="ProductImage"><filename>image.gif</filename></image>
|
424
|
+
|
425
|
+
</product>
|
426
|
+
EOT
|
427
|
+
|
428
|
+
expected_product_hash = {
|
429
|
+
'weight' => 0.5,
|
430
|
+
'image' => {'type' => 'ProductImage', 'filename' => 'image.gif' },
|
431
|
+
}
|
432
|
+
|
433
|
+
HTTParty::Parsers::XML.parse(product_xml)["product"].should == expected_product_hash
|
434
|
+
end
|
435
|
+
|
436
|
+
it "should handle unescaping from xml (ActiveResource Compatible)" do
|
437
|
+
xml_string = '<person><bare-string>First & Last Name</bare-string><pre-escaped-string>First &amp; Last Name</pre-escaped-string></person>'
|
438
|
+
expected_hash = {
|
439
|
+
'bare_string' => 'First & Last Name',
|
440
|
+
'pre_escaped_string' => 'First & Last Name'
|
441
|
+
}
|
442
|
+
|
443
|
+
HTTParty::Parsers::XML.parse(xml_string)['person'].should == expected_hash
|
444
|
+
end
|
445
|
+
end
|