partigirb 0.2.7
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/.gitignore +5 -0
- data/LICENSE +20 -0
- data/README.markdown +110 -0
- data/Rakefile +56 -0
- data/VERSION +1 -0
- data/examples/last_reviews_summary.rb +34 -0
- data/examples/who_ignores_me.rb +35 -0
- data/lib/partigirb/client.rb +190 -0
- data/lib/partigirb/core_ext.rb +78 -0
- data/lib/partigirb/handlers/atom_handler.rb +24 -0
- data/lib/partigirb/handlers/json_handler.rb +10 -0
- data/lib/partigirb/handlers/string_handler.rb +9 -0
- data/lib/partigirb/handlers/xml_handler.rb +111 -0
- data/lib/partigirb/transport.rb +160 -0
- data/lib/partigirb.rb +27 -0
- data/partigirb.gemspec +76 -0
- data/test/atom_handler_test.rb +61 -0
- data/test/client_test.rb +209 -0
- data/test/fixtures/alvaro_friends.atom.xml +80 -0
- data/test/fixtures/pulp_fiction.atom.xml +99 -0
- data/test/json_handler_test.rb +7 -0
- data/test/mocks/net_http_mock.rb +12 -0
- data/test/mocks/response_mock.rb +12 -0
- data/test/mocks/transport_mock.rb +15 -0
- data/test/test_helper.rb +47 -0
- data/test/transport_test.rb +8 -0
- data/test/xml_handler_test.rb +180 -0
- metadata +95 -0
@@ -0,0 +1,160 @@
|
|
1
|
+
module Partigirb
|
2
|
+
|
3
|
+
class Response #:nodoc:
|
4
|
+
attr_accessor :method, :request_uri, :status, :body
|
5
|
+
|
6
|
+
def initialize(method,request_uri,status,body)
|
7
|
+
self.method = method
|
8
|
+
self.request_uri = request_uri
|
9
|
+
self.status = status
|
10
|
+
self.body = body
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Transport
|
15
|
+
|
16
|
+
attr_accessor :debug
|
17
|
+
|
18
|
+
CRLF = "\r\n"
|
19
|
+
|
20
|
+
def req_class(method)
|
21
|
+
case method
|
22
|
+
when :get then Net::HTTP::Get
|
23
|
+
when :post then Net::HTTP::Post
|
24
|
+
when :put then Net::HTTP::Put
|
25
|
+
when :delete then Net::HTTP::Delete
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Options are one of
|
30
|
+
# - :params - a hash of parameters to be sent with the request. If a File is a parameter value, \
|
31
|
+
# a multipart request will be sent. If a Time is included, .httpdate will be called on it.
|
32
|
+
# - :headers - a hash of headers to send with the request
|
33
|
+
def request(method, string_url, options={})
|
34
|
+
params = stringify_params(options[:params])
|
35
|
+
if method == :get && params
|
36
|
+
string_url << query_string(params)
|
37
|
+
end
|
38
|
+
url = URI.parse(string_url)
|
39
|
+
begin
|
40
|
+
execute_request(method,url,options)
|
41
|
+
rescue Timeout::Error
|
42
|
+
raise "Timeout while #{method}ing #{url.to_s}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def execute_request(method,url,options={})
|
47
|
+
conn = Net::HTTP.new(url.host, url.port)
|
48
|
+
#conn.use_ssl = (url.scheme == 'https')
|
49
|
+
conn.start do |http|
|
50
|
+
req = req_class(method).new(url.request_uri)
|
51
|
+
|
52
|
+
add_headers(req,options[:headers])
|
53
|
+
if file_param?(options[:params])
|
54
|
+
add_multipart_data(req,options[:params])
|
55
|
+
else
|
56
|
+
add_form_data(req,options[:params])
|
57
|
+
end
|
58
|
+
|
59
|
+
dump_request(req) if debug
|
60
|
+
res = http.request(req)
|
61
|
+
dump_response(res) if debug
|
62
|
+
res
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def query_string(params)
|
67
|
+
query = case params
|
68
|
+
when Hash then params.map{|key,value| url_encode_param(key,value) }.join("&")
|
69
|
+
else url_encode(params.to_s)
|
70
|
+
end
|
71
|
+
if !(query == nil || query.length == 0) && query[0,1] != '?'
|
72
|
+
query = "?#{query}"
|
73
|
+
end
|
74
|
+
query
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
def stringify_params(params)
|
79
|
+
return nil unless params
|
80
|
+
params.inject({}) do |h, pair|
|
81
|
+
key, value = pair
|
82
|
+
if value.respond_to? :httpdate
|
83
|
+
value = value.httpdate
|
84
|
+
end
|
85
|
+
h[key] = value
|
86
|
+
h
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def file_param?(params)
|
91
|
+
return false unless params
|
92
|
+
params.any? {|key,value| value.respond_to? :read }
|
93
|
+
end
|
94
|
+
|
95
|
+
def url_encode(value)
|
96
|
+
require 'cgi' unless defined?(CGI) && defined?(CGI::escape)
|
97
|
+
CGI.escape(value.to_s)
|
98
|
+
end
|
99
|
+
|
100
|
+
def url_encode_param(key,value)
|
101
|
+
"#{url_encode(key)}=#{url_encode(value)}"
|
102
|
+
end
|
103
|
+
|
104
|
+
def add_headers(req,headers)
|
105
|
+
if headers
|
106
|
+
headers.each do |header, value|
|
107
|
+
req[header] = value
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def add_form_data(req,params)
|
113
|
+
if req.request_body_permitted? && params
|
114
|
+
req.set_form_data(params)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def add_multipart_data(req,params)
|
119
|
+
boundary = Time.now.to_i.to_s(16)
|
120
|
+
req["Content-Type"] = "multipart/form-data; boundary=#{boundary}"
|
121
|
+
body = ""
|
122
|
+
params.each do |key,value|
|
123
|
+
esc_key = url_encode(key)
|
124
|
+
body << "--#{boundary}#{CRLF}"
|
125
|
+
if value.respond_to?(:read)
|
126
|
+
mime_type = MIME::Types.type_for(value.path)[0] || MIME::Types["application/octet-stream"][0]
|
127
|
+
body << "Content-Disposition: form-data; name=\"#{esc_key}\"; filename=\"#{File.basename(value.path)}\"#{CRLF}"
|
128
|
+
body << "Content-Type: #{mime_type.simplified}#{CRLF*2}"
|
129
|
+
body << value.read
|
130
|
+
else
|
131
|
+
body << "Content-Disposition: form-data; name=\"#{esc_key}\"#{CRLF*2}#{value}"
|
132
|
+
end
|
133
|
+
body << CRLF
|
134
|
+
end
|
135
|
+
body << "--#{boundary}--#{CRLF*2}"
|
136
|
+
req.body = body
|
137
|
+
req["Content-Length"] = req.body.size
|
138
|
+
end
|
139
|
+
|
140
|
+
private
|
141
|
+
|
142
|
+
def dump_request(req)
|
143
|
+
puts "Sending Request"
|
144
|
+
puts"#{req.method} #{req.path}"
|
145
|
+
dump_headers(req)
|
146
|
+
end
|
147
|
+
|
148
|
+
def dump_response(res)
|
149
|
+
puts "Received Response"
|
150
|
+
dump_headers(res)
|
151
|
+
puts res.body
|
152
|
+
end
|
153
|
+
|
154
|
+
def dump_headers(msg)
|
155
|
+
msg.each_header do |key, value|
|
156
|
+
puts "\t#{key}=#{value}"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
data/lib/partigirb.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module Partigirb
|
2
|
+
VERSION='0.1.0'
|
3
|
+
CURRENT_API_VERSION=1
|
4
|
+
end
|
5
|
+
|
6
|
+
$:.unshift File.dirname(__FILE__)
|
7
|
+
|
8
|
+
require 'rubygems'
|
9
|
+
|
10
|
+
require 'open-uri'
|
11
|
+
require 'net/http'
|
12
|
+
require 'base64'
|
13
|
+
require 'digest'
|
14
|
+
require 'rexml/document'
|
15
|
+
require 'mime/types'
|
16
|
+
require 'ostruct'
|
17
|
+
|
18
|
+
require 'partigirb/core_ext'
|
19
|
+
|
20
|
+
require 'partigirb/handlers/xml_handler'
|
21
|
+
require 'partigirb/handlers/atom_handler'
|
22
|
+
require 'partigirb/handlers/json_handler'
|
23
|
+
require 'partigirb/handlers/string_handler'
|
24
|
+
|
25
|
+
require 'partigirb/transport'
|
26
|
+
require 'partigirb/client'
|
27
|
+
|
data/partigirb.gemspec
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{partigirb}
|
8
|
+
s.version = "0.2.7"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Alvaro Bautista", "Fernando Blat"]
|
12
|
+
s.date = %q{2009-10-28}
|
13
|
+
s.email = ["alvarobp@gmail.com", "ferblape@gmail.com"]
|
14
|
+
s.extra_rdoc_files = [
|
15
|
+
"LICENSE",
|
16
|
+
"README.markdown"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".gitignore",
|
20
|
+
"LICENSE",
|
21
|
+
"README.markdown",
|
22
|
+
"Rakefile",
|
23
|
+
"VERSION",
|
24
|
+
"examples/last_reviews_summary.rb",
|
25
|
+
"examples/who_ignores_me.rb",
|
26
|
+
"lib/partigirb.rb",
|
27
|
+
"lib/partigirb/client.rb",
|
28
|
+
"lib/partigirb/core_ext.rb",
|
29
|
+
"lib/partigirb/handlers/atom_handler.rb",
|
30
|
+
"lib/partigirb/handlers/json_handler.rb",
|
31
|
+
"lib/partigirb/handlers/string_handler.rb",
|
32
|
+
"lib/partigirb/handlers/xml_handler.rb",
|
33
|
+
"lib/partigirb/transport.rb",
|
34
|
+
"partigirb.gemspec",
|
35
|
+
"test/atom_handler_test.rb",
|
36
|
+
"test/client_test.rb",
|
37
|
+
"test/fixtures/alvaro_friends.atom.xml",
|
38
|
+
"test/fixtures/pulp_fiction.atom.xml",
|
39
|
+
"test/json_handler_test.rb",
|
40
|
+
"test/mocks/net_http_mock.rb",
|
41
|
+
"test/mocks/response_mock.rb",
|
42
|
+
"test/mocks/transport_mock.rb",
|
43
|
+
"test/test_helper.rb",
|
44
|
+
"test/transport_test.rb",
|
45
|
+
"test/xml_handler_test.rb"
|
46
|
+
]
|
47
|
+
s.homepage = %q{http://github.com/partigi/partigirb}
|
48
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
49
|
+
s.require_paths = ["lib"]
|
50
|
+
s.rubygems_version = %q{1.3.5}
|
51
|
+
s.summary = %q{A Ruby wrapper for the Partigi API}
|
52
|
+
s.test_files = [
|
53
|
+
"test/atom_handler_test.rb",
|
54
|
+
"test/client_test.rb",
|
55
|
+
"test/json_handler_test.rb",
|
56
|
+
"test/mocks/net_http_mock.rb",
|
57
|
+
"test/mocks/response_mock.rb",
|
58
|
+
"test/mocks/transport_mock.rb",
|
59
|
+
"test/test_helper.rb",
|
60
|
+
"test/transport_test.rb",
|
61
|
+
"test/xml_handler_test.rb",
|
62
|
+
"examples/last_reviews_summary.rb",
|
63
|
+
"examples/who_ignores_me.rb"
|
64
|
+
]
|
65
|
+
|
66
|
+
if s.respond_to? :specification_version then
|
67
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
68
|
+
s.specification_version = 3
|
69
|
+
|
70
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
71
|
+
else
|
72
|
+
end
|
73
|
+
else
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class AtomHandlerTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@handler = Partigirb::Handlers::AtomHandler.new
|
6
|
+
end
|
7
|
+
|
8
|
+
should "return a PartigiStruct with entry elements for feeds with just one entry" do
|
9
|
+
xmls = build_xml_string do |xml|
|
10
|
+
xml.instruct!
|
11
|
+
|
12
|
+
xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
|
13
|
+
xml.title "A feed"
|
14
|
+
xml.id "http://the.feed.url.com"
|
15
|
+
xml.updated "2009-07-24T10:40:22Z"
|
16
|
+
|
17
|
+
xml.entry({"xmlns:ptUser" => 'http://schemas.partigi.com/v1.0/ptUser'}) do
|
18
|
+
xml.category({:scheme => "http://schemas.partigi.com/v1.0#kind", :term => "http://schemas.partigi.com/v1.0#user"})
|
19
|
+
xml.id "http://the.feed.url2.com"
|
20
|
+
xml.title "User entry"
|
21
|
+
xml.ptUser :id, 321
|
22
|
+
xml.ptUser :login, "user_login"
|
23
|
+
xml.ptUser :name, "User Name"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
res = @handler.decode_response(xmls)
|
29
|
+
assert res.is_a?(Partigirb::PartigiStruct)
|
30
|
+
|
31
|
+
assert_equal "User entry", res.title
|
32
|
+
assert_equal "http://the.feed.url2.com", res.id
|
33
|
+
assert_equal 321, res.ptUser_id
|
34
|
+
assert_equal "user_login", res.ptUser_login
|
35
|
+
assert_equal "User Name", res.ptUser_name
|
36
|
+
assert_nil res.updated
|
37
|
+
end
|
38
|
+
|
39
|
+
should "return an array of PartigiStruct with PartigiStruct of each entry in the feed" do
|
40
|
+
xmls = build_xml_string do |xml|
|
41
|
+
xml.instruct!
|
42
|
+
|
43
|
+
xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
|
44
|
+
xml.title "A feed"
|
45
|
+
xml.entry({"xmlns:ptUser" => 'http://schemas.partigi.com/v1.0/ptUser'}) do
|
46
|
+
xml.ptUser :id, 321
|
47
|
+
end
|
48
|
+
xml.entry({"xmlns:ptUser" => 'http://schemas.partigi.com/v1.0/ptUser'}) do
|
49
|
+
xml.ptUser :id, 123
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
res = @handler.decode_response(xmls)
|
55
|
+
assert res.is_a?(Array)
|
56
|
+
assert_equal 2, res.size
|
57
|
+
|
58
|
+
assert_equal 321, res[0].ptUser_id
|
59
|
+
assert_equal 123, res[1].ptUser_id
|
60
|
+
end
|
61
|
+
end
|
data/test/client_test.rb
ADDED
@@ -0,0 +1,209 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class ClientTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@client = new_client
|
6
|
+
end
|
7
|
+
|
8
|
+
should "use GET method by default" do
|
9
|
+
@client.users.show.xml
|
10
|
+
|
11
|
+
assert_equal(:get, @client.transport.method)
|
12
|
+
end
|
13
|
+
|
14
|
+
should "use GET method for methods ending with ?" do
|
15
|
+
@client.users.show.xml?
|
16
|
+
|
17
|
+
assert_equal(:get, @client.transport.method)
|
18
|
+
end
|
19
|
+
|
20
|
+
should "not make a request if format is missing" do
|
21
|
+
MockTransport.any_instance.expects(:request).never
|
22
|
+
|
23
|
+
@client.users.show
|
24
|
+
|
25
|
+
assert_nil @client.transport.url
|
26
|
+
end
|
27
|
+
|
28
|
+
should "use POST method for methods ending with !" do
|
29
|
+
@client.users.show.xml!
|
30
|
+
|
31
|
+
assert_equal(:post, @client.transport.method)
|
32
|
+
end
|
33
|
+
|
34
|
+
should "use POST method and default format for methods ending with !" do
|
35
|
+
@client.friendships.create!
|
36
|
+
|
37
|
+
assert_equal(:post, @client.transport.method)
|
38
|
+
assert @client.transport.url.path.include?("/friendships/create.atom")
|
39
|
+
end
|
40
|
+
|
41
|
+
should "request to the Partigi API host through HTTP protocol" do
|
42
|
+
@client.users.show.xml
|
43
|
+
|
44
|
+
assert_equal('http', @client.transport.url.scheme)
|
45
|
+
assert_equal(Partigirb::Client::PARTIGI_API_HOST, @client.transport.url.host)
|
46
|
+
end
|
47
|
+
|
48
|
+
should "use the current API version by default" do
|
49
|
+
@client.users.show.xml
|
50
|
+
|
51
|
+
assert_equal(Partigirb::CURRENT_API_VERSION, @client.api_version)
|
52
|
+
end
|
53
|
+
|
54
|
+
should "put the requested API version in the request url" do
|
55
|
+
@client = new_client(200, '', {:api_version => 3})
|
56
|
+
@client.users.show.xml
|
57
|
+
|
58
|
+
assert_equal '/api/v3/users/show.xml', @client.transport.url.path
|
59
|
+
end
|
60
|
+
|
61
|
+
should "add paremeters to url on GET" do
|
62
|
+
@client.items.index.xml :type => 'film', :page => 1, :per_page => 20
|
63
|
+
|
64
|
+
assert_equal 3, request_query.size
|
65
|
+
assert request_query.include?('type=film')
|
66
|
+
assert request_query.include?('page=1')
|
67
|
+
assert request_query.include?('per_page=20')
|
68
|
+
end
|
69
|
+
|
70
|
+
should "add parameters to request body on POST" do
|
71
|
+
@client.reviews.create! :item_id => 'star-wars', :type => 'film', :status => 2, :text => 'My favorite movie', :rating => '5'
|
72
|
+
|
73
|
+
assert_equal 5, post_data.size
|
74
|
+
assert post_data.include?('item_id=star-wars')
|
75
|
+
assert post_data.include?('type=film')
|
76
|
+
assert post_data.include?('status=2')
|
77
|
+
assert post_data.include?('text=My%20favorite%20movie')
|
78
|
+
assert post_data.include?('rating=5')
|
79
|
+
end
|
80
|
+
|
81
|
+
should "add any headers to the HTTP requests" do
|
82
|
+
@client = new_client(200, '', {:headers => {'Useless' => 'void', 'Fake' => 'header'}})
|
83
|
+
@client.user.show.xml
|
84
|
+
|
85
|
+
assert_not_nil Net::HTTP.request['Useless']
|
86
|
+
assert_equal 'void', Net::HTTP.request['Useless']
|
87
|
+
assert_not_nil Net::HTTP.request['Fake']
|
88
|
+
assert_equal 'header', Net::HTTP.request['Fake']
|
89
|
+
end
|
90
|
+
|
91
|
+
should "add authentication headers when login and secret are provided" do
|
92
|
+
@client = new_client(200, '', :auth => {:login => 'auser', :api_secret => 'his_api_secret'})
|
93
|
+
|
94
|
+
@client.friendships.update! :id => 321
|
95
|
+
|
96
|
+
assert_not_nil Net::HTTP.request['Authorization']
|
97
|
+
assert_equal "WSSE realm=\"#{Partigirb::Client::PARTIGI_API_HOST}\", profile=\"UsernameToken\"", Net::HTTP.request['Authorization']
|
98
|
+
|
99
|
+
assert_not_nil Net::HTTP.request['X-WSSE']
|
100
|
+
assert_match /UsernameToken Username="auser", PasswordDigest="[^"]+", Nonce="[^"]+", Created="[^"]+"/, Net::HTTP.request['X-WSSE']
|
101
|
+
end
|
102
|
+
|
103
|
+
should "not add authentication headers if no auth params are provided" do
|
104
|
+
@client.friendships.update! :id => 321
|
105
|
+
|
106
|
+
assert_nil Net::HTTP.request['Authorization']
|
107
|
+
assert_nil Net::HTTP.request['X-WSSE']
|
108
|
+
end
|
109
|
+
|
110
|
+
should "use given nonce for authentication" do
|
111
|
+
@client = new_client(200, '', :auth => {:login => 'auser', :api_secret => 'his_api_secret', :nonce => '123456789101112'})
|
112
|
+
@client.friendships.update! :id => 321
|
113
|
+
|
114
|
+
assert_equal "WSSE realm=\"#{Partigirb::Client::PARTIGI_API_HOST}\", profile=\"UsernameToken\"", Net::HTTP.request['Authorization']
|
115
|
+
assert_match /UsernameToken Username="auser", PasswordDigest="[^"]+", Nonce="123456789101112", Created="[^"]+"/, Net::HTTP.request['X-WSSE']
|
116
|
+
end
|
117
|
+
|
118
|
+
should "use given timestamp string for authentication" do
|
119
|
+
@client = new_client(200, '', :auth => {:login => 'auser', :api_secret => 'his_api_secret', :timestamp => '2009-07-15T14:43:07Z'})
|
120
|
+
@client.friendships.update! :id => 321
|
121
|
+
|
122
|
+
assert_equal "WSSE realm=\"#{Partigirb::Client::PARTIGI_API_HOST}\", profile=\"UsernameToken\"", Net::HTTP.request['Authorization']
|
123
|
+
assert_match /UsernameToken Username="auser", PasswordDigest="[^"]+", Nonce="[^"]+", Created="2009-07-15T14:43:07Z"/, Net::HTTP.request['X-WSSE']
|
124
|
+
end
|
125
|
+
|
126
|
+
should "use given Time object as timestamp for authentication" do
|
127
|
+
timestamp = Time.now
|
128
|
+
@client = new_client(200, '', :auth => {:login => 'auser', :api_secret => 'his_api_secret', :timestamp => timestamp})
|
129
|
+
@client.friendships.update! :id => 321
|
130
|
+
|
131
|
+
assert_equal "WSSE realm=\"#{Partigirb::Client::PARTIGI_API_HOST}\", profile=\"UsernameToken\"", Net::HTTP.request['Authorization']
|
132
|
+
assert_match /UsernameToken Username="auser", PasswordDigest="[^"]+", Nonce="[^"]+", Created="#{timestamp.strftime(Partigirb::Client::TIMESTAMP_FORMAT)}"/, Net::HTTP.request['X-WSSE']
|
133
|
+
end
|
134
|
+
|
135
|
+
should "use the PasswordDigest from given parameters" do
|
136
|
+
@client = new_client(200, '', :auth => {:login => 'auser', :api_secret => 'his_api_secret', :nonce => '123456789101112', :timestamp => '2009-07-15T14:43:07Z'})
|
137
|
+
@client.friendships.update! :id => 321
|
138
|
+
|
139
|
+
pdigest = Base64.encode64(Digest::SHA1.hexdigest("1234567891011122009-07-15T14:43:07Zauserhis_api_secret")).chomp
|
140
|
+
|
141
|
+
assert_equal "WSSE realm=\"#{Partigirb::Client::PARTIGI_API_HOST}\", profile=\"UsernameToken\"", Net::HTTP.request['Authorization']
|
142
|
+
assert_match /UsernameToken Username="auser", PasswordDigest="#{pdigest}", Nonce="123456789101112", Created="2009-07-15T14:43:07Z"/, Net::HTTP.request['X-WSSE']
|
143
|
+
end
|
144
|
+
|
145
|
+
context "generate_nonce method" do
|
146
|
+
should "generate random strings" do
|
147
|
+
@client.instance_eval do
|
148
|
+
nonces = []
|
149
|
+
1.upto(25) do
|
150
|
+
assert !nonces.include?(generate_nonce)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
should "process XML response by XML handler" do
|
157
|
+
Partigirb::Handlers::XMLHandler.any_instance.expects(:decode_response).once
|
158
|
+
Partigirb::Handlers::AtomHandler.any_instance.expects(:decode_response).never
|
159
|
+
Partigirb::Handlers::JSONHandler.any_instance.expects(:decode_response).never
|
160
|
+
@client.items.xml
|
161
|
+
end
|
162
|
+
|
163
|
+
should "process Atom response by Atom handler" do
|
164
|
+
Partigirb::Handlers::XMLHandler.any_instance.expects(:decode_response).never
|
165
|
+
Partigirb::Handlers::AtomHandler.any_instance.expects(:decode_response).once
|
166
|
+
Partigirb::Handlers::JSONHandler.any_instance.expects(:decode_response).never
|
167
|
+
@client.items.atom
|
168
|
+
end
|
169
|
+
|
170
|
+
should "process JSON response by JSON handler" do
|
171
|
+
Partigirb::Handlers::XMLHandler.any_instance.expects(:decode_response).never
|
172
|
+
Partigirb::Handlers::AtomHandler.any_instance.expects(:decode_response).never
|
173
|
+
Partigirb::Handlers::JSONHandler.any_instance.expects(:decode_response).once
|
174
|
+
@client.items.json
|
175
|
+
end
|
176
|
+
|
177
|
+
should "raise a PartigiError with response error text as the message when http response codes are other than 200" do
|
178
|
+
client = new_client(400, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>Partigi::BadAPIRequestRequiredParams</error>\n")
|
179
|
+
|
180
|
+
begin
|
181
|
+
client.items.show.xml :id => 'madeup'
|
182
|
+
rescue Exception => e
|
183
|
+
assert e.is_a?(Partigirb::PartigiError)
|
184
|
+
assert_equal 'Partigi::BadAPIRequestRequiredParams', e.message
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
# Copied from Grackle
|
189
|
+
should "clear the request path on clear" do
|
190
|
+
client = new_client(200,'[{"id":1,"text":"test 1"}]')
|
191
|
+
client.some.url.that.does.not.exist
|
192
|
+
assert_equal('/some/url/that/does/not/exist',client.send(:request).path,"An unexecuted path should be build up")
|
193
|
+
client.clear
|
194
|
+
assert_equal('',client.send(:request).path,"The path shoudl be cleared")
|
195
|
+
end
|
196
|
+
|
197
|
+
should "use multipart encoding when using a file param" do
|
198
|
+
client = new_client(200,'')
|
199
|
+
client.account.update_profile_image! :image=>File.new(__FILE__)
|
200
|
+
assert_match(/multipart\/form-data/,Net::HTTP.request['Content-Type'])
|
201
|
+
end
|
202
|
+
|
203
|
+
should "escape and encode time param" do
|
204
|
+
client = new_client(200,'')
|
205
|
+
time = Time.now-60*60
|
206
|
+
client.statuses.public_timeline? :since=>time
|
207
|
+
assert_equal("/api/v#{Partigirb::CURRENT_API_VERSION}/statuses/public_timeline.atom?since=#{CGI::escape(time.httpdate)}", Net::HTTP.request.path)
|
208
|
+
end
|
209
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<feed xmlns="http://www.w3.org/2005/Atom">
|
3
|
+
<title>user/7/friends » Partigi</title>
|
4
|
+
<id>http://www.partigi.com/api/v1/friends/show/7.atom</id>
|
5
|
+
<updated>2009-07-23T10:08:14Z</updated>
|
6
|
+
<link type="application/atom+xml" href="http://www.partigi.com/api/v1/friends/show/7.atom" rel="self"/>
|
7
|
+
<link type="text/html" href="http://www.partigi.com/alvarobp/friends/follows" rel="alternate"/>
|
8
|
+
<author>
|
9
|
+
<name>Partigi</name>
|
10
|
+
</author>
|
11
|
+
<entry xmlns:ptUser="http://schemas.partigi.com/v1.0/ptUser">
|
12
|
+
<category scheme="http://schemas.partigi.com/v1.0#kind" term="http://schemas.partigi.com/v1.0#user"/>
|
13
|
+
<id>http://www.partigi.com/friend1</id>
|
14
|
+
<title>Friend 1</title>
|
15
|
+
<updated>2009-07-24T19:16:14Z</updated>
|
16
|
+
<published>2009-07-23T10:07:49Z</published>
|
17
|
+
<link type="text/html" href="http://www.partigi.com/friend1" rel="alternate"/>
|
18
|
+
<link type="application/atom+xml" href="http://www.partigi.com/api/v1/users/show.atom?id=friend1" rel="self"/>
|
19
|
+
<ptUser:id>440</ptUser:id>
|
20
|
+
<ptUser:login>friend1</ptUser:login>
|
21
|
+
<ptUser:name>Friend 1</ptUser:name>
|
22
|
+
<ptUser:surname>Surname 1</ptUser:surname>
|
23
|
+
<ptUser:country>ES</ptUser:country>
|
24
|
+
</entry>
|
25
|
+
<entry xmlns:ptUser="http://schemas.partigi.com/v1.0/ptUser">
|
26
|
+
<category scheme="http://schemas.partigi.com/v1.0#kind" term="http://schemas.partigi.com/v1.0#user"/>
|
27
|
+
<id>http://www.partigi.com/friend2</id>
|
28
|
+
<title>Friend 2</title>
|
29
|
+
<updated>2009-07-23T10:15:18Z</updated>
|
30
|
+
<published>2009-07-03T04:20:09Z</published>
|
31
|
+
<link type="text/html" href="http://www.partigi.com/friend2" rel="alternate"/>
|
32
|
+
<link type="application/atom+xml" href="http://www.partigi.com/api/v1/users/show.atom?id=friend2" rel="self"/>
|
33
|
+
<ptUser:id>357</ptUser:id>
|
34
|
+
<ptUser:login>friend2</ptUser:login>
|
35
|
+
<ptUser:name>Friend 2</ptUser:name>
|
36
|
+
<ptUser:surname>Surname 2</ptUser:surname>
|
37
|
+
<ptUser:country>ES</ptUser:country>
|
38
|
+
</entry>
|
39
|
+
<entry xmlns:ptUser="http://schemas.partigi.com/v1.0/ptUser">
|
40
|
+
<category scheme="http://schemas.partigi.com/v1.0#kind" term="http://schemas.partigi.com/v1.0#user"/>
|
41
|
+
<id>http://www.partigi.com/friend3</id>
|
42
|
+
<title>Friend 3</title>
|
43
|
+
<updated>2009-07-18T17:05:42Z</updated>
|
44
|
+
<published>2009-07-18T17:04:43Z</published>
|
45
|
+
<link type="text/html" href="http://www.partigi.com/friend3" rel="alternate"/>
|
46
|
+
<link type="application/atom+xml" href="http://www.partigi.com/api/v1/users/show.atom?id=friend3" rel="self"/>
|
47
|
+
<ptUser:id>408</ptUser:id>
|
48
|
+
<ptUser:login>friend3</ptUser:login>
|
49
|
+
<ptUser:name>Friend 3</ptUser:name>
|
50
|
+
<ptUser:surname>Surname 3</ptUser:surname>
|
51
|
+
<ptUser:country>ES</ptUser:country>
|
52
|
+
</entry>
|
53
|
+
<entry xmlns:ptUser="http://schemas.partigi.com/v1.0/ptUser">
|
54
|
+
<category scheme="http://schemas.partigi.com/v1.0#kind" term="http://schemas.partigi.com/v1.0#user"/>
|
55
|
+
<id>http://www.partigi.com/friend4</id>
|
56
|
+
<title>Friend 4</title>
|
57
|
+
<updated>2009-07-18T12:35:46Z</updated>
|
58
|
+
<published>2009-05-20T13:51:09Z</published>
|
59
|
+
<link type="text/html" href="http://www.partigi.com/friend4" rel="alternate"/>
|
60
|
+
<link type="application/atom+xml" href="http://www.partigi.com/api/v1/users/show.atom?id=friend4" rel="self"/>
|
61
|
+
<ptUser:id>183</ptUser:id>
|
62
|
+
<ptUser:login>friend4</ptUser:login>
|
63
|
+
<ptUser:name>Friend 4</ptUser:name>
|
64
|
+
<ptUser:surname>Surname 4</ptUser:surname>
|
65
|
+
</entry>
|
66
|
+
<entry xmlns:ptUser="http://schemas.partigi.com/v1.0/ptUser">
|
67
|
+
<category scheme="http://schemas.partigi.com/v1.0#kind" term="http://schemas.partigi.com/v1.0#user"/>
|
68
|
+
<id>http://www.partigi.com/friend5</id>
|
69
|
+
<title>Friend 5</title>
|
70
|
+
<updated>2009-07-19T17:27:53Z</updated>
|
71
|
+
<published>2009-06-04T11:37:17Z</published>
|
72
|
+
<link type="text/html" href="http://www.partigi.com/friend5" rel="alternate"/>
|
73
|
+
<link type="application/atom+xml" href="http://www.partigi.com/api/v1/users/show.atom?id=friend5" rel="self"/>
|
74
|
+
<ptUser:id>249</ptUser:id>
|
75
|
+
<ptUser:login>friend5</ptUser:login>
|
76
|
+
<ptUser:name>Friend 5</ptUser:name>
|
77
|
+
<ptUser:surname>Surname 5</ptUser:surname>
|
78
|
+
<ptUser:country>ES</ptUser:country>
|
79
|
+
</entry>
|
80
|
+
</feed>
|