activeresource 2.3.9.pre → 2.3.9

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activeresource might be problematic. Click here for more details.

data/CHANGELOG CHANGED
@@ -1,4 +1,4 @@
1
- *2.3.9 (August 29, 2010)*
1
+ *2.3.9 (September 4, 2010)*
2
2
  *2.3.8 (May 24, 2010)*
3
3
  *2.3.7 (May 24, 2010)*
4
4
 
@@ -29,7 +29,8 @@ module ActiveResource
29
29
  #
30
30
  # In order for a mock to deliver its content, the incoming request must match by the <tt>http_method</tt>,
31
31
  # +path+ and <tt>request_headers</tt>. If no match is found an InvalidRequestError exception
32
- # will be raised letting you know you need to create a new mock for that request.
32
+ # will be raised showing you what request it could not find a response for and also what requests and response
33
+ # pairs have been recorded so you can create a new mock for that request.
33
34
  #
34
35
  # ==== Example
35
36
  # def setup
@@ -97,10 +98,79 @@ module ActiveResource
97
98
  @@responses ||= []
98
99
  end
99
100
 
100
- # Accepts a block which declares a set of requests and responses for the HttpMock to respond to. See the main
101
- # ActiveResource::HttpMock description for a more detailed explanation.
102
- def respond_to(pairs = {}) #:yields: mock
103
- reset!
101
+ # Accepts a block which declares a set of requests and responses for the HttpMock to respond to in
102
+ # the following format:
103
+ #
104
+ # mock.http_method(path, request_headers = {}, body = nil, status = 200, response_headers = {})
105
+ #
106
+ # === Example
107
+ #
108
+ # @matz = { :id => 1, :name => "Matz" }.to_xml(:root => "person")
109
+ # ActiveResource::HttpMock.respond_to do |mock|
110
+ # mock.post "/people.xml", {}, @matz, 201, "Location" => "/people/1.xml"
111
+ # mock.get "/people/1.xml", {}, @matz
112
+ # mock.put "/people/1.xml", {}, nil, 204
113
+ # mock.delete "/people/1.xml", {}, nil, 200
114
+ # end
115
+ #
116
+ # Alternatively, accepts a hash of <tt>{Request => Response}</tt> pairs allowing you to generate
117
+ # these the following format:
118
+ #
119
+ # ActiveResource::Request.new(method, path, body, request_headers)
120
+ # ActiveResource::Response.new(body, status, response_headers)
121
+ #
122
+ # === Example
123
+ #
124
+ # Request.new(:#{method}, path, nil, request_headers)
125
+ #
126
+ # @matz = { :id => 1, :name => "Matz" }.to_xml(:root => "person")
127
+ #
128
+ # create_matz = ActiveResource::Request.new(:post, '/people.xml', @matz, {})
129
+ # created_response = ActiveResource::Response.new("", 201, {"Location" => "/people/1.xml"})
130
+ # get_matz = ActiveResource::Request.new(:get, '/people/1.xml', nil)
131
+ # ok_response = ActiveResource::Response.new("", 200, {})
132
+ #
133
+ # pairs = {create_matz => created_response, get_matz => ok_response}
134
+ #
135
+ # ActiveResource::HttpMock.respond_to(pairs)
136
+ #
137
+ # Note, by default, every time you call +respond_to+, any previous request and response pairs stored
138
+ # in HttpMock will be deleted giving you a clean slate to work on.
139
+ #
140
+ # If you want to override this behaviour, pass in +false+ as the last argument to +respond_to+
141
+ #
142
+ # === Example
143
+ #
144
+ # ActiveResource::HttpMock.respond_to do |mock|
145
+ # mock.send(:get, "/people/1", {}, "XML1")
146
+ # end
147
+ # ActiveResource::HttpMock.responses.length #=> 1
148
+ #
149
+ # ActiveResource::HttpMock.respond_to(false) do |mock|
150
+ # mock.send(:get, "/people/2", {}, "XML2")
151
+ # end
152
+ # ActiveResource::HttpMock.responses.length #=> 2
153
+ #
154
+ # This also works with passing in generated pairs of requests and responses, again, just pass in false
155
+ # as the last argument:
156
+ #
157
+ # === Example
158
+ #
159
+ # ActiveResource::HttpMock.respond_to do |mock|
160
+ # mock.send(:get, "/people/1", {}, "XML1")
161
+ # end
162
+ # ActiveResource::HttpMock.responses.length #=> 1
163
+ #
164
+ # get_matz = ActiveResource::Request.new(:get, '/people/1.xml', nil)
165
+ # ok_response = ActiveResource::Response.new("", 200, {})
166
+ #
167
+ # pairs = {get_matz => ok_response}
168
+ #
169
+ # ActiveResource::HttpMock.respond_to(pairs, false)
170
+ # ActiveResource::HttpMock.responses.length #=> 2
171
+ def respond_to(*args) #:yields: mock
172
+ pairs = args.first || {}
173
+ reset! if args.last.class != FalseClass
104
174
  responses.concat pairs.to_a
105
175
  if block_given?
106
176
  yield Responder.new(responses)
@@ -123,13 +193,21 @@ module ActiveResource
123
193
  # def post(path, body, headers)
124
194
  # request = ActiveResource::Request.new(:post, path, body, headers)
125
195
  # self.class.requests << request
126
- # self.class.responses.assoc(request).try(:second) || raise(InvalidRequestError.new("Could not find a response recorded for #{request.to_s} - Responses recorded are: - #{inspect_responses}"))
196
+ # if response = self.class.responses.assoc(request)
197
+ # response[1]
198
+ # else
199
+ # raise InvalidRequestError.new("Could not find a response recorded for #{request.to_s} - Responses recorded are: - #{inspect_responses}")
200
+ # end
127
201
  # end
128
202
  module_eval <<-EOE, __FILE__, __LINE__ + 1
129
203
  def #{method}(path, #{'body, ' if has_body}headers)
130
204
  request = ActiveResource::Request.new(:#{method}, path, #{has_body ? 'body, ' : 'nil, '}headers)
131
205
  self.class.requests << request
132
- self.class.responses.assoc(request).try(:second) || raise(InvalidRequestError.new("Could not find a response recorded for \#{request.to_s} - Responses recorded are: - \#{inspect_responses}"))
206
+ if response = self.class.responses.assoc(request)
207
+ response[1]
208
+ else
209
+ raise InvalidRequestError.new("Could not find a response recorded for \#{request.to_s} - Responses recorded are: \#{inspect_responses}")
210
+ end
133
211
  end
134
212
  EOE
135
213
  end
@@ -148,16 +226,29 @@ module ActiveResource
148
226
  attr_accessor :path, :method, :body, :headers
149
227
 
150
228
  def initialize(method, path, body = nil, headers = {})
151
- @method, @path, @body, @headers = method, path, body, headers.merge(ActiveResource::Connection::HTTP_FORMAT_HEADER_NAMES[method] => 'application/xml')
229
+ @method, @path, @body, @headers = method, path, body, headers
152
230
  end
153
231
 
154
232
  def ==(req)
155
- path == req.path && method == req.method && headers == req.headers
233
+ path == req.path && method == req.method && headers_match?(req)
156
234
  end
157
235
 
158
236
  def to_s
159
237
  "<#{method.to_s.upcase}: #{path} [#{headers}] (#{body})>"
160
238
  end
239
+
240
+ private
241
+
242
+ def headers_match?(req)
243
+ # Ignore format header on equality if it's not defined
244
+ format_header = ActiveResource::Connection::HTTP_FORMAT_HEADER_NAMES[method]
245
+ if headers[format_header].present? || req.headers[format_header].blank?
246
+ headers == req.headers
247
+ else
248
+ headers.dup.merge(format_header => req.headers[format_header]) == req.headers
249
+ end
250
+ end
251
+
161
252
  end
162
253
 
163
254
  class Response
@@ -0,0 +1,155 @@
1
+ require 'abstract_unit'
2
+
3
+ class HttpMockTest < ActiveSupport::TestCase
4
+ def setup
5
+ @http = ActiveResource::HttpMock.new("http://example.com")
6
+ end
7
+
8
+ FORMAT_HEADER = { :get => 'Accept',
9
+ :put => 'Content-Type',
10
+ :post => 'Content-Type',
11
+ :delete => 'Accept',
12
+ :head => 'Accept'
13
+ }
14
+
15
+ [:post, :put, :get, :delete, :head].each do |method|
16
+ test "responds to simple #{method} request" do
17
+ ActiveResource::HttpMock.respond_to do |mock|
18
+ mock.send(method, "/people/1", {FORMAT_HEADER[method] => "application/xml"}, "Response")
19
+ end
20
+
21
+ assert_equal "Response", request(method, "/people/1", FORMAT_HEADER[method] => "application/xml").body
22
+ end
23
+
24
+ test "adds format header by default to #{method} request" do
25
+ ActiveResource::HttpMock.respond_to do |mock|
26
+ mock.send(method, "/people/1", {}, "Response")
27
+ end
28
+
29
+ assert_equal "Response", request(method, "/people/1", FORMAT_HEADER[method] => "application/xml").body
30
+ end
31
+
32
+ test "respond only when headers match header by default to #{method} request" do
33
+ ActiveResource::HttpMock.respond_to do |mock|
34
+ mock.send(method, "/people/1", {"X-Header" => "X"}, "Response")
35
+ end
36
+
37
+ assert_equal "Response", request(method, "/people/1", "X-Header" => "X").body
38
+ assert_raise(ActiveResource::InvalidRequestError) { request(method, "/people/1") }
39
+ end
40
+
41
+ test "does not overwrite format header to #{method} request" do
42
+ ActiveResource::HttpMock.respond_to do |mock|
43
+ mock.send(method, "/people/1", {FORMAT_HEADER[method] => "application/json"}, "Response")
44
+ end
45
+
46
+ assert_equal "Response", request(method, "/people/1", FORMAT_HEADER[method] => "application/json").body
47
+ end
48
+
49
+ test "ignores format header when there is only one response to same url in a #{method} request" do
50
+ ActiveResource::HttpMock.respond_to do |mock|
51
+ mock.send(method, "/people/1", {}, "Response")
52
+ end
53
+
54
+ assert_equal "Response", request(method, "/people/1", FORMAT_HEADER[method] => "application/json").body
55
+ assert_equal "Response", request(method, "/people/1", FORMAT_HEADER[method] => "application/xml").body
56
+ end
57
+
58
+ test "responds correctly when format header is given to #{method} request" do
59
+ ActiveResource::HttpMock.respond_to do |mock|
60
+ mock.send(method, "/people/1", {FORMAT_HEADER[method] => "application/xml"}, "XML")
61
+ mock.send(method, "/people/1", {FORMAT_HEADER[method] => "application/json"}, "Json")
62
+ end
63
+
64
+ assert_equal "XML", request(method, "/people/1", FORMAT_HEADER[method] => "application/xml").body
65
+ assert_equal "Json", request(method, "/people/1", FORMAT_HEADER[method] => "application/json").body
66
+ end
67
+
68
+ test "raises InvalidRequestError if no response found for the #{method} request" do
69
+ ActiveResource::HttpMock.respond_to do |mock|
70
+ mock.send(method, "/people/1", {FORMAT_HEADER[method] => "application/xml"}, "XML")
71
+ end
72
+
73
+ assert_raise(::ActiveResource::InvalidRequestError) do
74
+ request(method, "/people/1", FORMAT_HEADER[method] => "application/json")
75
+ end
76
+ end
77
+
78
+ end
79
+
80
+ test "allows you to send in pairs directly to the respond_to method" do
81
+ matz = { :id => 1, :name => "Matz" }.to_xml(:root => "person")
82
+
83
+ create_matz = ActiveResource::Request.new(:post, '/people.xml', matz, {})
84
+ created_response = ActiveResource::Response.new("", 201, {"Location" => "/people/1.xml"})
85
+ get_matz = ActiveResource::Request.new(:get, '/people/1.xml', nil)
86
+ ok_response = ActiveResource::Response.new(matz, 200, {})
87
+
88
+ pairs = {create_matz => created_response, get_matz => ok_response}
89
+
90
+ ActiveResource::HttpMock.respond_to(pairs)
91
+ assert_equal 2, ActiveResource::HttpMock.responses.length
92
+ assert_equal "", ActiveResource::HttpMock.responses.assoc(create_matz)[1].body
93
+ assert_equal matz, ActiveResource::HttpMock.responses.assoc(get_matz)[1].body
94
+ end
95
+
96
+ test "resets all mocked responses on each call to respond_to with a block by default" do
97
+ ActiveResource::HttpMock.respond_to do |mock|
98
+ mock.send(:get, "/people/1", {}, "XML1")
99
+ end
100
+ assert_equal 1, ActiveResource::HttpMock.responses.length
101
+
102
+ ActiveResource::HttpMock.respond_to do |mock|
103
+ mock.send(:get, "/people/2", {}, "XML2")
104
+ end
105
+ assert_equal 1, ActiveResource::HttpMock.responses.length
106
+ end
107
+
108
+ test "resets all mocked responses on each call to respond_to by passing pairs by default" do
109
+ ActiveResource::HttpMock.respond_to do |mock|
110
+ mock.send(:get, "/people/1", {}, "XML1")
111
+ end
112
+ assert_equal 1, ActiveResource::HttpMock.responses.length
113
+
114
+ matz = { :id => 1, :name => "Matz" }.to_xml(:root => "person")
115
+ get_matz = ActiveResource::Request.new(:get, '/people/1.xml', nil)
116
+ ok_response = ActiveResource::Response.new(matz, 200, {})
117
+ ActiveResource::HttpMock.respond_to({get_matz => ok_response})
118
+
119
+ assert_equal 1, ActiveResource::HttpMock.responses.length
120
+ end
121
+
122
+ test "allows you to add new responses to the existing responses by calling a block" do
123
+ ActiveResource::HttpMock.respond_to do |mock|
124
+ mock.send(:get, "/people/1", {}, "XML1")
125
+ end
126
+ assert_equal 1, ActiveResource::HttpMock.responses.length
127
+
128
+ ActiveResource::HttpMock.respond_to(false) do |mock|
129
+ mock.send(:get, "/people/2", {}, "XML2")
130
+ end
131
+ assert_equal 2, ActiveResource::HttpMock.responses.length
132
+ end
133
+
134
+ test "allows you to add new responses to the existing responses by passing pairs" do
135
+ ActiveResource::HttpMock.respond_to do |mock|
136
+ mock.send(:get, "/people/1", {}, "XML1")
137
+ end
138
+ assert_equal 1, ActiveResource::HttpMock.responses.length
139
+
140
+ matz = { :id => 1, :name => "Matz" }.to_xml(:root => "person")
141
+ get_matz = ActiveResource::Request.new(:get, '/people/1.xml', nil)
142
+ ok_response = ActiveResource::Response.new(matz, 200, {})
143
+ ActiveResource::HttpMock.respond_to({get_matz => ok_response}, false)
144
+
145
+ assert_equal 2, ActiveResource::HttpMock.responses.length
146
+ end
147
+
148
+ def request(method, path, headers = {}, body = nil)
149
+ if [:put, :post].include? method
150
+ @http.send(method, path, body, headers)
151
+ else
152
+ @http.send(method, path, headers)
153
+ end
154
+ end
155
+ end
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activeresource
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: true
4
+ prerelease: false
5
5
  segments:
6
6
  - 2
7
7
  - 3
8
8
  - 9
9
- - pre
10
- version: 2.3.9.pre
9
+ version: 2.3.9
11
10
  platform: ruby
12
11
  authors:
13
12
  - David Heinemeier Hansson
@@ -15,7 +14,7 @@ autorequire: active_resource
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2010-08-29 00:00:00 -07:00
17
+ date: 2010-09-04 00:00:00 -07:00
19
18
  default_executable:
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency
@@ -29,8 +28,7 @@ dependencies:
29
28
  - 2
30
29
  - 3
31
30
  - 9
32
- - pre
33
- version: 2.3.9.pre
31
+ version: 2.3.9
34
32
  type: :runtime
35
33
  version_requirements: *id001
36
34
  description: Wraps web resources in model classes that can be manipulated through XML over REST.
@@ -72,6 +70,7 @@ files:
72
70
  - test/fixtures/proxy.rb
73
71
  - test/fixtures/street_address.rb
74
72
  - test/format_test.rb
73
+ - test/http_mock_test.rb
75
74
  - test/setter_trap.rb
76
75
  has_rdoc: true
77
76
  homepage: http://www.rubyonrails.org
@@ -92,13 +91,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
92
91
  version: "0"
93
92
  required_rubygems_version: !ruby/object:Gem::Requirement
94
93
  requirements:
95
- - - ">"
94
+ - - ">="
96
95
  - !ruby/object:Gem::Version
97
96
  segments:
98
- - 1
99
- - 3
100
- - 1
101
- version: 1.3.1
97
+ - 0
98
+ version: "0"
102
99
  requirements: []
103
100
 
104
101
  rubyforge_project: activeresource