weary 0.5.1 → 0.6.0
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/README.md +31 -36
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/examples/repo.rb +12 -15
- data/examples/status.rb +5 -4
- data/lib/weary.rb +35 -232
- data/lib/weary/base.rb +126 -0
- data/lib/weary/request.rb +4 -8
- data/lib/weary/resource.rb +92 -88
- data/lib/weary/response.rb +0 -11
- data/spec/spec_helper.rb +3 -2
- data/spec/weary/base_spec.rb +321 -0
- data/spec/weary/request_spec.rb +2 -0
- data/spec/weary/resource_spec.rb +230 -74
- data/spec/weary/response_spec.rb +7 -11
- data/spec/weary_spec.rb +0 -157
- data/weary.gemspec +11 -4
- metadata +15 -2
data/lib/weary/base.rb
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
module Weary
|
2
|
+
class Base
|
3
|
+
@@resources = {}
|
4
|
+
|
5
|
+
attr_accessor :defaults
|
6
|
+
|
7
|
+
# Assign credentials to be used when authenticating to a Resource.
|
8
|
+
# Can be a username/password combo, or an OAuth::AccessToken
|
9
|
+
def credentials(username,password='')
|
10
|
+
if username.is_a?(OAuth::AccessToken)
|
11
|
+
@credentials = username
|
12
|
+
else
|
13
|
+
@credentials = {:username => username, :password => password}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Each Weary::Base object has its own set of Resources
|
18
|
+
def resources
|
19
|
+
@resources = Marshal.load(Marshal.dump(@@resources)) if !@resources
|
20
|
+
@resources
|
21
|
+
end
|
22
|
+
|
23
|
+
# Make changes to a Resource given and rebuild the Request method for this object
|
24
|
+
def modify_resource(name)
|
25
|
+
yield resources[name] if block_given?
|
26
|
+
rebuild_method(resources[name])
|
27
|
+
end
|
28
|
+
|
29
|
+
# Rebuild the Request Method for a given Resource. This only affects the current instance.
|
30
|
+
def rebuild_method(resource)
|
31
|
+
instance_eval %Q{
|
32
|
+
def #{resource.name}(params={})
|
33
|
+
resources[:#{resource.name}].build!(params, @defaults, @credentials)
|
34
|
+
end
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
class << self
|
39
|
+
|
40
|
+
# Getter for class-level resources
|
41
|
+
def resources
|
42
|
+
@@resources
|
43
|
+
end
|
44
|
+
|
45
|
+
# Declare a resource. Use it with a block to setup the resource
|
46
|
+
#
|
47
|
+
# Methods that are understood are:
|
48
|
+
# [<tt>via</tt>] Get, Post, etc. Defaults to a GET request
|
49
|
+
# [<tt>with</tt>] An array of parameters that will be passed to the body or query of the request. If you pass a hash, it will define default <tt>values</tt> for params <tt>keys</tt>
|
50
|
+
# [<tt>requires</tt>] Array of members of <tt>:with</tt> that are required by the resource.
|
51
|
+
# [<tt>authenticates</tt>] Boolean value; does the resource require authentication?
|
52
|
+
# [<tt>url</tt>] The url of the resource. You can use the same flags as #construct_url
|
53
|
+
# [<tt>follows</tt>] Boolean; Does this follow redirects? Defaults to true
|
54
|
+
# [<tt>headers</tt>] Set headers for the HTTP Request
|
55
|
+
def get(name,&block)
|
56
|
+
build_resource(name, :get, block)
|
57
|
+
end
|
58
|
+
alias declare get
|
59
|
+
|
60
|
+
# Declares a Resource to be requested via POST
|
61
|
+
def post(name,&block)
|
62
|
+
build_resource(name, :post, block)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Declares a Resource to be requested via PUT
|
66
|
+
def put(name,&block)
|
67
|
+
build_resource(name, :put, block)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Declares a Resource to be requested via DELETE
|
71
|
+
def delete(name,&block)
|
72
|
+
build_resource(name, :delete, block)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Set custom default Headers for your Request
|
76
|
+
def headers(headers)
|
77
|
+
@headers = headers
|
78
|
+
end
|
79
|
+
|
80
|
+
# Sets the domain to be used to build default url's
|
81
|
+
def domain(dom)
|
82
|
+
domain = URI.extract(dom)
|
83
|
+
raise ArgumentError, 'The domain must be a URL.' if domain.blank?
|
84
|
+
@domain = URI.parse(domain[0]).normalize.to_s
|
85
|
+
end
|
86
|
+
|
87
|
+
# Sets a default format, used to build default Resource url's
|
88
|
+
def format(format)
|
89
|
+
@format = format
|
90
|
+
end
|
91
|
+
|
92
|
+
# Prepare and store the Resource
|
93
|
+
def build_resource(name,verb,block=nil)
|
94
|
+
resource = prepare_resource(name,verb)
|
95
|
+
block.call(resource) if block
|
96
|
+
store_resource(resource)
|
97
|
+
build_method(resource)
|
98
|
+
resource
|
99
|
+
end
|
100
|
+
|
101
|
+
# Prepare a Resource with set defaults
|
102
|
+
def prepare_resource(name,via = :get)
|
103
|
+
preparation = Weary::Resource.new(name)
|
104
|
+
preparation.via = via
|
105
|
+
preparation.headers = @headers unless @headers.blank?
|
106
|
+
preparation.url = "#{@domain}#{preparation.name}." + (@format || :json).to_s if @domain
|
107
|
+
preparation
|
108
|
+
end
|
109
|
+
|
110
|
+
# Store the resource for future use
|
111
|
+
def store_resource(resource)
|
112
|
+
@@resources[resource.name.to_sym] = resource
|
113
|
+
resource
|
114
|
+
end
|
115
|
+
|
116
|
+
# Build a method to form a Request for the given Resource
|
117
|
+
def build_method(resource)
|
118
|
+
define_method resource.name.to_sym do |*args|
|
119
|
+
args.blank? ? params = {} : params = args[0]
|
120
|
+
resource.build!(params, @defaults, @credentials)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
data/lib/weary/request.rb
CHANGED
@@ -30,15 +30,11 @@ module Weary
|
|
30
30
|
def perform
|
31
31
|
req = http.request(request)
|
32
32
|
response = Response.new(req, @http_verb)
|
33
|
-
|
34
|
-
if
|
35
|
-
|
36
|
-
else
|
37
|
-
response
|
38
|
-
end
|
39
|
-
else
|
40
|
-
response
|
33
|
+
if response.redirected?
|
34
|
+
return response if options[:no_follow]
|
35
|
+
response.follow_redirect
|
41
36
|
end
|
37
|
+
response
|
42
38
|
end
|
43
39
|
|
44
40
|
private
|
data/lib/weary/resource.rb
CHANGED
@@ -1,22 +1,21 @@
|
|
1
1
|
module Weary
|
2
2
|
class Resource
|
3
|
-
|
3
|
+
attr_reader :name, :via, :with, :requires, :url
|
4
|
+
attr_accessor :headers
|
4
5
|
|
5
6
|
def initialize(name)
|
6
7
|
self.name = name
|
7
8
|
self.via = :get
|
8
9
|
self.authenticates = false
|
9
10
|
self.follows = true
|
10
|
-
self.with = []
|
11
|
-
self.requires = []
|
12
|
-
self.oauth = false
|
13
11
|
end
|
14
12
|
|
13
|
+
# The name of the Resource. Will be a lowercase string, whitespace replaced with underscores.
|
15
14
|
def name=(resource_name)
|
16
|
-
|
17
|
-
@name = resource_name.downcase.strip.gsub(/\s/,'_')
|
15
|
+
@name = resource_name.to_s.downcase.strip.gsub(/\s/,'_')
|
18
16
|
end
|
19
17
|
|
18
|
+
# The HTTP Method used to fetch the Resource
|
20
19
|
def via=(http_verb)
|
21
20
|
verb = HTTPVerb.new(http_verb).normalize
|
22
21
|
@via = if Methods.include?(verb)
|
@@ -26,109 +25,114 @@ module Weary
|
|
26
25
|
end
|
27
26
|
end
|
28
27
|
|
29
|
-
|
30
|
-
type = type.downcase if type.is_a?(String)
|
31
|
-
@format = case type
|
32
|
-
when *ContentTypes[:json]
|
33
|
-
:json
|
34
|
-
when *ContentTypes[:xml]
|
35
|
-
:xml
|
36
|
-
when *ContentTypes[:html]
|
37
|
-
:html
|
38
|
-
when *ContentTypes[:yaml]
|
39
|
-
:yaml
|
40
|
-
when *ContentTypes[:plain]
|
41
|
-
:plain
|
42
|
-
else
|
43
|
-
raise ArgumentError, "#{type} is not a recognized format."
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
28
|
+
# Optional params. Should be an array. Merges with requires if that is set.
|
47
29
|
def with=(params)
|
48
|
-
|
49
|
-
|
50
|
-
@with = params
|
51
|
-
else
|
52
|
-
if @requires.nil?
|
53
|
-
@with = params.collect {|x| x.to_sym}
|
54
|
-
else
|
55
|
-
@with = params.collect {|x| x.to_sym} | @requires
|
56
|
-
end
|
57
|
-
end
|
30
|
+
@with = [params].flatten.collect {|x| x.to_sym}
|
31
|
+
@with = (requires | @with) if requires
|
58
32
|
end
|
59
33
|
|
34
|
+
# Required params. Should be an array. Merges with `with` or sets `with`.
|
60
35
|
def requires=(params)
|
61
|
-
|
62
|
-
|
63
|
-
@requires = params.collect {|x| x.to_sym}
|
64
|
-
else
|
65
|
-
@with = @with | params.collect {|x| x.to_sym}
|
66
|
-
@requires = params.collect {|x| x.to_sym}
|
67
|
-
end
|
36
|
+
@requires = [params].flatten.collect {|x| x.to_sym}
|
37
|
+
with ? @with = (with | @requires) : (@with = @requires)
|
68
38
|
end
|
69
39
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
pattern = pattern.gsub("<domain>", @domain)
|
74
|
-
end
|
75
|
-
pattern = pattern.gsub("<resource>", @name)
|
76
|
-
pattern = pattern.gsub("<format>", @format.to_s)
|
77
|
-
@url = pattern
|
40
|
+
# Sets whether the Resource requires authentication. Always sets to a boolean value.
|
41
|
+
def authenticates=(bool)
|
42
|
+
@authenticates = bool ? true : false
|
78
43
|
end
|
79
44
|
|
80
|
-
|
81
|
-
|
82
|
-
@
|
83
|
-
true
|
84
|
-
else
|
85
|
-
false
|
86
|
-
end
|
45
|
+
# Does the Resource require authentication?
|
46
|
+
def authenticates?
|
47
|
+
@authenticates
|
87
48
|
end
|
88
49
|
|
89
|
-
|
90
|
-
|
91
|
-
@
|
92
|
-
true
|
93
|
-
else
|
94
|
-
false
|
95
|
-
end
|
50
|
+
# Sets whether the Resource should follow redirection. Always sets to a boolean value.
|
51
|
+
def follows=(bool)
|
52
|
+
@follows = (bool ? true : false)
|
96
53
|
end
|
97
54
|
|
98
|
-
|
99
|
-
|
55
|
+
# Should the resource follow redirection?
|
56
|
+
def follows?
|
57
|
+
@follows
|
100
58
|
end
|
101
59
|
|
102
|
-
|
103
|
-
|
60
|
+
# Set the Resource's URL as a URI
|
61
|
+
def url=(uri)
|
62
|
+
@url = URI.parse(uri)
|
104
63
|
end
|
105
64
|
|
106
|
-
|
107
|
-
|
108
|
-
@
|
109
|
-
|
65
|
+
# A hash representation of the Resource
|
66
|
+
def to_hash
|
67
|
+
{@name.to_sym => { :via => via,
|
68
|
+
:with => with,
|
69
|
+
:requires => requires,
|
70
|
+
:follows => follows?,
|
71
|
+
:authenticates => authenticates?,
|
72
|
+
:url => url,
|
73
|
+
:headers => headers}}
|
74
|
+
end
|
75
|
+
|
76
|
+
# Take parameters, default params, and credentials and build a Request object for this Resource
|
77
|
+
def build!(params={}, defaults=nil, credentials=nil)
|
78
|
+
uri = @url
|
79
|
+
parameters = setup_parameters(params, defaults)
|
80
|
+
request_opts = setup_options(parameters, credentials)
|
81
|
+
uri.query = request_opts[:query].to_params if request_opts[:query]
|
82
|
+
Weary::Request.new(uri.normalize.to_s, @via, request_opts)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Setup the parameters to make the Request with
|
86
|
+
def setup_parameters(params={}, defaults=nil)
|
87
|
+
params = defaults ? defaults.merge(params) : params
|
88
|
+
find_missing_requirements(params)
|
89
|
+
remove_unnecessary_params(params)
|
110
90
|
end
|
111
91
|
|
112
|
-
|
113
|
-
|
114
|
-
|
92
|
+
# Search the given parameters to see if they are missing any required params
|
93
|
+
def find_missing_requirements(params)
|
94
|
+
if (@requires && !@requires.empty?)
|
95
|
+
missing_requirements = @requires - params.keys
|
96
|
+
raise ArgumentError, "This resource is missing required parameters: '#{missing_requirements.inspect}'" unless missing_requirements.empty?
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Remove params that have not been specified with #with
|
101
|
+
def remove_unnecessary_params(params)
|
102
|
+
params.delete_if {|k,v| !@with.include?(k) } if (@with && !@with.empty?)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Setup the options to be passed into the Request
|
106
|
+
def setup_options(params={}, credentials=nil)
|
107
|
+
options = {}
|
108
|
+
prepare_request_body(params, options)
|
109
|
+
setup_authentication(options, credentials)
|
110
|
+
options[:no_follow] = true if !follows?
|
111
|
+
options[:headers] = @headers if !@headers.blank?
|
112
|
+
options
|
113
|
+
end
|
114
|
+
|
115
|
+
# Prepare the Request query or body depending on the HTTP method
|
116
|
+
def prepare_request_body(params, options={})
|
117
|
+
if (@via == :post || @via == :put)
|
118
|
+
options[:body] = params unless params.blank?
|
115
119
|
else
|
116
|
-
|
120
|
+
options[:query] = params unless params.blank?
|
117
121
|
end
|
122
|
+
options
|
118
123
|
end
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
:access_token => @access_token}}
|
124
|
+
|
125
|
+
# Prepare authentication credentials for the Request
|
126
|
+
def setup_authentication(options, credentials=nil)
|
127
|
+
if authenticates?
|
128
|
+
raise ArgumentError, "This resource requires authentication and no credentials were given." if credentials.blank?
|
129
|
+
if credentials.is_a?(OAuth::AccessToken)
|
130
|
+
options[:oauth] = credentials
|
131
|
+
else
|
132
|
+
options[:basic_auth] = credentials
|
133
|
+
end
|
134
|
+
end
|
135
|
+
options
|
132
136
|
end
|
133
137
|
|
134
138
|
end
|
data/lib/weary/response.rb
CHANGED
@@ -75,17 +75,6 @@ module Weary
|
|
75
75
|
parse[key]
|
76
76
|
end
|
77
77
|
|
78
|
-
# Search the body with a CSS/XPath selector with Nokogiri.
|
79
|
-
# If the document is not XMLish, fall back to #parse and ditch the selector.
|
80
|
-
def search(selector)
|
81
|
-
if @format == (:xml || :html)
|
82
|
-
doc = Nokogiri.parse(@body)
|
83
|
-
doc.search(selector)
|
84
|
-
else
|
85
|
-
parse
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
78
|
private
|
90
79
|
def handle_errors
|
91
80
|
case @code
|
data/spec/spec_helper.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
|
1
3
|
require 'rubygems'
|
2
|
-
gem 'rspec'
|
3
4
|
require 'spec'
|
4
|
-
require
|
5
|
+
require 'weary'
|
5
6
|
|
6
7
|
def get_fixture(filename)
|
7
8
|
open(File.join(File.dirname(__FILE__), 'fixtures', "#{filename.to_s}")).read
|
@@ -0,0 +1,321 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
2
|
+
|
3
|
+
describe Weary::Base do
|
4
|
+
describe 'Class' do
|
5
|
+
|
6
|
+
describe 'Resource Defaults' do
|
7
|
+
before do
|
8
|
+
@headers = {"User-Agent" => Weary::UserAgents["Safari 4.0.2 - Mac"]}
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'sets default headers' do
|
12
|
+
test = Class.new(Weary::Base)
|
13
|
+
test.headers @headers
|
14
|
+
test.instance_variable_get(:@headers).should == @headers
|
15
|
+
end
|
16
|
+
|
17
|
+
it "sets a domain to be used in default url's" do
|
18
|
+
test = Class.new(Weary::Base)
|
19
|
+
test.domain 'http://github.com'
|
20
|
+
test.instance_variable_get(:@domain).should == 'http://github.com/'
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'panics when a domain that is not a url is given' do
|
24
|
+
test = Class.new(Weary::Base)
|
25
|
+
lambda { test.domain 'foobar' }.should raise_error
|
26
|
+
end
|
27
|
+
|
28
|
+
it "sets a format to use in default url's" do
|
29
|
+
test = Class.new(Weary::Base)
|
30
|
+
test.format(:json)
|
31
|
+
test.instance_variable_get(:@format).should == :json
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'Resource Preparation' do
|
36
|
+
before do
|
37
|
+
@headers = {"User-Agent" => Weary::UserAgents["Safari 4.0.2 - Mac"]}
|
38
|
+
prepTest = Class.new(Weary::Base)
|
39
|
+
prepTest.headers @headers
|
40
|
+
prepTest.domain 'http://foobar.com'
|
41
|
+
prepTest.format :xml
|
42
|
+
@t = prepTest.prepare_resource("test",:get)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'prepares a Resource' do
|
46
|
+
@t.class.should == Weary::Resource
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'has a name' do
|
50
|
+
@t.name.should == "test"
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'has an http method' do
|
54
|
+
@t.via.should == :get
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'has headers' do
|
58
|
+
@t.headers.should == @headers
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'builds a default url if a domain is provided' do
|
62
|
+
@t.url.normalize.to_s.should == 'http://foobar.com/test.xml'
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'builds a default url with a json extension if no format is explicitly named' do
|
66
|
+
t = Class.new(Weary::Base)
|
67
|
+
t.domain 'http://foobar.com'
|
68
|
+
p = t.prepare_resource("test",:get)
|
69
|
+
p.url.normalize.to_s.should == 'http://foobar.com/test.json'
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'ignores the url if no domain is provided' do
|
73
|
+
t = Class.new(Weary::Base).prepare_resource("test",:get)
|
74
|
+
t.url.should == nil
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'ignores headers if no headers are defined' do
|
78
|
+
t = Class.new(Weary::Base).prepare_resource("test",:get)
|
79
|
+
t.headers.should == nil
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe 'Resource Storage' do
|
84
|
+
before do
|
85
|
+
@headers = {"User-Agent" => Weary::UserAgents["Safari 4.0.2 - Mac"]}
|
86
|
+
@restest = Class.new(Weary::Base)
|
87
|
+
@restest.headers @headers
|
88
|
+
@restest.domain 'http://foobar.com'
|
89
|
+
@r = @restest.prepare_resource("test",:get)
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'has a store for resources' do
|
93
|
+
@restest.class_variable_defined?(:@@resources).should == true
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'stores the resource for future use' do
|
97
|
+
@restest.store_resource(@r).should == @r
|
98
|
+
@restest.resources.include?(:test).should == true
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe 'Resource Construction' do
|
103
|
+
before do
|
104
|
+
@contest = Class.new(Weary::Base)
|
105
|
+
@contest.domain 'http://foobar.com'
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'prepares a resource to be used' do
|
109
|
+
r = @contest.build_resource "test", :post
|
110
|
+
r.name.should == "test"
|
111
|
+
r.via.should == :post
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'passes the resource into a block for further refinement' do
|
115
|
+
r = @contest.build_resource("test", :post, Proc.new {|res| res.via = :put })
|
116
|
+
r.name.should == "test"
|
117
|
+
r.via.should == :put
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'stores the resource' do
|
121
|
+
r = @contest.build_resource("test 2", :get)
|
122
|
+
@contest.resources.include?(:test_2).should == true
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'builds the method for the resource' do
|
126
|
+
r = @contest.build_resource("test 3", :get)
|
127
|
+
@contest.public_method_defined?(:test_3).should == true
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe 'Resource Declaration' do
|
132
|
+
before do
|
133
|
+
@dectest = Class.new(Weary::Base)
|
134
|
+
@dectest.domain 'http://foobar.com'
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'gets a resource' do
|
138
|
+
r = @dectest.get "get test"
|
139
|
+
r.via.should == :get
|
140
|
+
r.name.should == "get_test"
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'posts a resource' do
|
144
|
+
r = @dectest.post "post test"
|
145
|
+
r.via.should == :post
|
146
|
+
r.name.should == "post_test"
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'puts a resource' do
|
150
|
+
r = @dectest.put "put test"
|
151
|
+
r.via.should == :put
|
152
|
+
r.name.should == "put_test"
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'deletes a resource' do
|
156
|
+
r = @dectest.delete "del test"
|
157
|
+
r.via.should == :delete
|
158
|
+
r.name.should == "del_test"
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'declares a resource' do
|
162
|
+
r = @dectest.declare "generic test"
|
163
|
+
r.via.should == :get
|
164
|
+
r.name.should == "generic_test"
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'stores the resource' do
|
168
|
+
@dectest.get "storage test"
|
169
|
+
@dectest.resources.include?(:storage_test).should == true
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
describe 'Method Building' do
|
174
|
+
before do
|
175
|
+
@methtest = Class.new(Weary::Base)
|
176
|
+
@methtest.domain 'http://foobar.com'
|
177
|
+
|
178
|
+
r = @methtest.prepare_resource("method_test",:get)
|
179
|
+
@methtest.build_method(r)
|
180
|
+
|
181
|
+
a = @methtest.prepare_resource("authentication_test",:post)
|
182
|
+
a.authenticates = true
|
183
|
+
@methtest.build_method(a)
|
184
|
+
|
185
|
+
d = @methtest.prepare_resource("params_test",:post)
|
186
|
+
d.requires = :id
|
187
|
+
d.with = [:message, :user]
|
188
|
+
@methtest.build_method(d)
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'builds a method with the name of the resource' do
|
192
|
+
n = @methtest.new
|
193
|
+
n.respond_to?(:method_test).should == true
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'forms a Request according to the guidelines of the Resource' do
|
197
|
+
n = @methtest.new
|
198
|
+
n.method_test.class.should == Weary::Request
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'passes in authentication credentials if defined' do
|
202
|
+
n = @methtest.new
|
203
|
+
cred = {:username => 'mwunsch', :password => 'secret'}
|
204
|
+
lambda { n.authentication_test }.should raise_error
|
205
|
+
n.credentials cred[:username], cred[:password]
|
206
|
+
n.authentication_test.options[:basic_auth].should == cred
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'passes in default parameters if defined' do
|
210
|
+
n = @methtest.new
|
211
|
+
defaults = {:id => 1234, :message => "Hello world"}
|
212
|
+
lambda { n.params_test }.should raise_error
|
213
|
+
n.defaults = defaults
|
214
|
+
n.params_test.options[:body].should == defaults
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'accepts parameters when given' do
|
218
|
+
n = @methtest.new
|
219
|
+
req = n.params_test :id => 1234, :message => "Hello world", :foo => "Bar"
|
220
|
+
req.options[:body].should == {:id => 1234, :message => "Hello world"}
|
221
|
+
req.options[:body].has_key?(:foo).should == false
|
222
|
+
end
|
223
|
+
|
224
|
+
|
225
|
+
end
|
226
|
+
|
227
|
+
end
|
228
|
+
|
229
|
+
describe 'Object' do
|
230
|
+
before do
|
231
|
+
@klass = Class.new(Weary::Base)
|
232
|
+
@klass.domain 'http://foobar.com'
|
233
|
+
@klass.format :xml
|
234
|
+
@klass.headers({"User-Agent" => Weary::UserAgents["Safari 4.0.2 - Mac"]})
|
235
|
+
@klass.get "thing" do |r|
|
236
|
+
r.requires = :id
|
237
|
+
r.with = [:message, :user]
|
238
|
+
end
|
239
|
+
@klass.post "important" do |r|
|
240
|
+
r.requires = :id
|
241
|
+
r.authenticates = true
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
it 'has methods defined by the class' do
|
246
|
+
obj = @klass.new
|
247
|
+
obj.respond_to?(:thing).should == true
|
248
|
+
obj.respond_to?(:important).should == true
|
249
|
+
end
|
250
|
+
|
251
|
+
it 'can set authentication credentials' do
|
252
|
+
obj = @klass.new
|
253
|
+
|
254
|
+
obj.credentials "username", "password"
|
255
|
+
obj.instance_variable_get(:@credentials).should == {:username => "username", :password => "password"}
|
256
|
+
obj.important(:id => 1234).options[:basic_auth].should == obj.instance_variable_get(:@credentials)
|
257
|
+
end
|
258
|
+
|
259
|
+
it 'credentials can be an OAuth access token' do
|
260
|
+
oauth_consumer = OAuth::Consumer.new("consumer_token","consumer_secret",{:site => 'http://foo.bar'})
|
261
|
+
oauth_token = OAuth::AccessToken.new(oauth_consumer, "token", "secret")
|
262
|
+
obj = @klass.new
|
263
|
+
|
264
|
+
obj.credentials oauth_token
|
265
|
+
obj.instance_variable_get(:@credentials).class.should == OAuth::AccessToken
|
266
|
+
obj.important(:id => 1234).options.has_key?(:oauth).should == true
|
267
|
+
obj.important(:id => 1234).options.has_key?(:basic_auth).should == false
|
268
|
+
end
|
269
|
+
|
270
|
+
it 'can set defaults to pass into requests' do
|
271
|
+
obj = @klass.new
|
272
|
+
|
273
|
+
obj.defaults = {:user => "mwunsch", :message => "hello world"}
|
274
|
+
obj.defaults.should == {:user => "mwunsch", :message => "hello world"}
|
275
|
+
obj.thing(:id => 1234).options[:query].should == {:user => "mwunsch", :message => "hello world", :id => 1234}
|
276
|
+
end
|
277
|
+
|
278
|
+
it 'has a list of resources' do
|
279
|
+
obj = @klass.new
|
280
|
+
|
281
|
+
obj.resources == @klass.resources
|
282
|
+
end
|
283
|
+
|
284
|
+
it 'should keep its resources separate' do
|
285
|
+
obj = @klass.new
|
286
|
+
|
287
|
+
obj.resources[:foo] = 'bar'
|
288
|
+
obj.resources.has_key?(:foo).should == true
|
289
|
+
@klass.resources.has_key?(:foo).should == false
|
290
|
+
obj.resources.delete(:foo)
|
291
|
+
end
|
292
|
+
|
293
|
+
it 'is able to rebuild its request method, like a singleton' do
|
294
|
+
obj1 = @klass.new
|
295
|
+
require 'pp'
|
296
|
+
|
297
|
+
obj1.resources[:thing].follows = false
|
298
|
+
obj1.rebuild_method(obj1.resources[:thing])
|
299
|
+
|
300
|
+
obj1.thing(:id => 1234).options[:no_follow].should == true
|
301
|
+
@klass.new.thing(:id => 1234).options[:no_follow].should == nil
|
302
|
+
end
|
303
|
+
|
304
|
+
it 'can modify a resource without modifying the resources of its class' do
|
305
|
+
obj = @klass.new
|
306
|
+
|
307
|
+
obj.modify_resource(:thing) {|r| r.url = "http://bar.foo" }
|
308
|
+
obj.resources[:thing].url.normalize.to_s.should == "http://bar.foo/"
|
309
|
+
obj.class.resources[:thing].url.normalize.to_s.should_not == "http://bar.foo/"
|
310
|
+
end
|
311
|
+
|
312
|
+
it 'modifying a resource rebuilds the method' do
|
313
|
+
obj = @klass.new
|
314
|
+
|
315
|
+
obj.credentials "username", "password"
|
316
|
+
obj.modify_resource(:important) {|r| r.follows = false }
|
317
|
+
obj.important(:id => 1234).options[:no_follow].should == true
|
318
|
+
end
|
319
|
+
|
320
|
+
end
|
321
|
+
end
|