rack-test 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1a276395f953e48d223d387a9ca830fec7bc17f4
4
- data.tar.gz: 75368392e7c13919d3073d9b69fb5c0e3c271b10
3
+ metadata.gz: 1c2c9dca5557f9f1d5894f9379e38e660698a178
4
+ data.tar.gz: aabbb52783cc359935090e319d462076cc0ce95c
5
5
  SHA512:
6
- metadata.gz: 874eb9d53b22b2842d9659144acdc4bf222cb18474f4d8b496292e3209bf53d2564a2fcef5d9541dc81a825780766d48da46a1a7643ac8f04807fc41094bba11
7
- data.tar.gz: 17b51e137c7bc2e2b59276bdaf90781dc6a701f082cd17b8faccbc179668c05914e34025474134ab87bd4e5a1c42821a07e0193665444062cfd77a6b24492e7a
6
+ metadata.gz: ed423ebaf4bbdb79a77804f3ed9314f88b5b9e97e9a0eeee0d596c43718bac918f62d4cfd8c1adaa72a0e8fce28f093f5bb7bc3268eec5025c6e47b7ce2556b9
7
+ data.tar.gz: a4ef34a8cb3e12bc432012444485af04c50c2780ec658ead424c337dbd3ecd3805a957065bb804b2b1dd73d495819094dfb018c0784cd9766a4f1be6110d7815
data/History.md CHANGED
@@ -1,3 +1,20 @@
1
+ ## 0.8.0 / 2017-11-20
2
+
3
+ * Minor enhancements
4
+ * Add a required_ruby_version of >= 2.2.2, similar to rack 2.0.1.
5
+ (Samuel Giddins #194)
6
+ * Remove new line from basic auth. (Felix Kleinschmidt #185)
7
+ * Rubocop fixes (Per Lundberg #196)
8
+ * Add how to install rack-test from github to README. (Jun Aruga #189)
9
+ * Update CodeClimate badges (Toshimaru #195)
10
+ * Add the ability to create Test::UploadedFile instances without
11
+ the file system (Adam Milligan #149)
12
+ * Add custom_request, remove duplication (Johannes Barre #184)
13
+ * README.md: Added note about how to post JSON (Per Lundberg #198)
14
+ * README.md: Added version badge (Per Lundberg #199)
15
+ * Bug fixes
16
+ * Bugfix for Cookies with multiple paths (Kyle Welsby #197)
17
+
1
18
  ## 0.7.0 / 2017-07-10
2
19
 
3
20
  * Major enhancements
data/README.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # Rack::Test
2
+ [![Gem Version](https://badge.fury.io/rb/rack-test.svg)](https://badge.fury.io/rb/rack-test)
2
3
  [<img src="https://travis-ci.org/rack-test/rack-test.svg?branch=master" />](https://travis-ci.org/rack-test/rack-test)
3
- [<img src="https://codeclimate.com/github/rack-test/rack-test.png" />](https://codeclimate.com/github/rack-test/rack-test)
4
- [<img src="https://codeclimate.com/github/rack-test/rack-test/coverage.png" />](https://codeclimate.com/github/rack-test/rack-test)
4
+ [![Code Climate](https://codeclimate.com/github/codeclimate/codeclimate/badges/gpa.svg)](https://codeclimate.com/github/codeclimate/codeclimate)
5
+ [![Test Coverage](https://codeclimate.com/github/codeclimate/codeclimate/badges/coverage.svg)](https://codeclimate.com/github/codeclimate/codeclimate/coverage)
5
6
 
6
7
  Code: https://github.com/rack-test/rack-test
7
8
 
@@ -18,7 +19,18 @@ to build on.
18
19
  * Set request headers to be used by all subsequent requests
19
20
  * Small footprint. Approximately 200 LOC
20
21
 
22
+ ## Supported platforms
23
+
24
+ * 2.2.2+
25
+ * 2.3
26
+ * 2.4
27
+ * JRuby 9.1.+
28
+
29
+ If you are using Ruby 1.8, 1.9 or JRuby 1.7, use rack-test 0.6.3.
30
+
21
31
  ## Examples
32
+ (The examples use `Test::Unit` but it's equally possible to use `rack-test` with other testing frameworks like `rspec`.)
33
+
22
34
  ```ruby
23
35
  require "test/unit"
24
36
  require "rack/test"
@@ -33,25 +45,32 @@ class HomepageTest < Test::Unit::TestCase
33
45
  end
34
46
 
35
47
  def test_response_is_ok
36
- get "/"
48
+ get '/'
37
49
 
38
50
  assert last_response.ok?
39
- assert_equal last_response.body, "All responses are OK"
51
+ assert_equal last_response.body, 'All responses are OK'
40
52
  end
41
-
53
+
42
54
  def set_request_headers
43
55
  headers 'Accept-Charset', 'utf-8'
44
- get "/"
56
+ get '/'
45
57
 
46
58
  assert last_response.ok?
47
- assert_equal last_response.body, "All responses are OK"
59
+ assert_equal last_response.body, 'All responses are OK'
48
60
  end
49
61
 
50
62
  def test_response_is_ok_for_other_paths
51
- get "/other_paths"
63
+ get '/other_paths'
52
64
 
53
65
  assert last_response.ok?
54
- assert_equal last_response.body, "All responses are OK"
66
+ assert_equal last_response.body, 'All responses are OK'
67
+ end
68
+
69
+ def post_with_json
70
+ # No assertion in this, we just demonstrate how you can post a JSON-encoded string.
71
+ # By default, Rack::Test will use HTTP form encoding if you pass in a Hash as the
72
+ # parameters, so make sure that `json` below is already a JSON-serialized string.
73
+ post(uri, json, { 'CONTENT_TYPE' => 'application/json' })
55
74
  end
56
75
  end
57
76
  ```
@@ -80,11 +99,21 @@ end
80
99
 
81
100
  To install the latest release as a gem:
82
101
 
83
- `gem install rack-test`
102
+ ```
103
+ gem install rack-test
104
+ ```
84
105
 
85
106
  Or via Bundler:
86
107
 
87
- `gem "rack-test", require: "rack/test"`
108
+ ```
109
+ gem 'rack-test', require: 'rack/test'
110
+ ```
111
+
112
+ Or to install unreleased version via Bundler:
113
+
114
+ ```
115
+ gem 'rack-test', github: 'rack-test', branch: 'master'
116
+ ```
88
117
 
89
118
  ## Authors
90
119
 
@@ -1,5 +1,4 @@
1
1
  module Rack
2
-
3
2
  class MockSession # :nodoc:
4
3
  attr_writer :cookie_jar
5
4
  attr_reader :default_host
@@ -25,16 +24,16 @@ module Rack
25
24
  end
26
25
 
27
26
  def request(uri, env)
28
- env["HTTP_COOKIE"] ||= cookie_jar.for(uri)
27
+ env['HTTP_COOKIE'] ||= cookie_jar.for(uri)
29
28
  @last_request = Rack::Request.new(env)
30
29
  status, headers, body = @app.call(@last_request.env)
31
30
 
32
- @last_response = MockResponse.new(status, headers, body, env["rack.errors"].flush)
31
+ @last_response = MockResponse.new(status, headers, body, env['rack.errors'].flush)
33
32
  body.close if body.respond_to?(:close)
34
33
 
35
- cookie_jar.merge(last_response.headers["Set-Cookie"], uri)
34
+ cookie_jar.merge(last_response.headers['Set-Cookie'], uri)
36
35
 
37
- @after_request.each { |hook| hook.call }
36
+ @after_request.each(&:call)
38
37
 
39
38
  if @last_response.respond_to?(:finish)
40
39
  @last_response.finish
@@ -46,21 +45,19 @@ module Rack
46
45
  # Return the last request issued in the session. Raises an error if no
47
46
  # requests have been sent yet.
48
47
  def last_request
49
- raise Rack::Test::Error.new("No request yet. Request a page first.") unless @last_request
48
+ raise Rack::Test::Error, 'No request yet. Request a page first.' unless @last_request
50
49
  @last_request
51
50
  end
52
51
 
53
52
  # Return the last response received in the session. Raises an error if
54
53
  # no requests have been sent yet.
55
54
  def last_response
56
- raise Rack::Test::Error.new("No response yet. Request a page first.") unless @last_response
55
+ raise Rack::Test::Error, 'No response yet. Request a page first.' unless @last_response
57
56
  @last_response
58
57
  end
59
58
 
60
59
  def cookie_jar
61
60
  @cookie_jar ||= Rack::Test::CookieJar.new([], @default_host)
62
61
  end
63
-
64
62
  end
65
-
66
63
  end
@@ -1,17 +1,17 @@
1
- require "uri"
2
- require "rack"
3
- require "rack/mock_session"
4
- require "rack/test/cookie_jar"
5
- require "rack/test/mock_digest_request"
6
- require "rack/test/utils"
7
- require "rack/test/methods"
8
- require "rack/test/uploaded_file"
9
- require "rack/test/version"
1
+ require 'uri'
2
+ require 'rack'
3
+ require 'rack/mock_session'
4
+ require 'rack/test/cookie_jar'
5
+ require 'rack/test/mock_digest_request'
6
+ require 'rack/test/utils'
7
+ require 'rack/test/methods'
8
+ require 'rack/test/uploaded_file'
9
+ require 'rack/test/version'
10
10
 
11
11
  module Rack
12
12
  module Test
13
- DEFAULT_HOST = "example.org"
14
- MULTIPART_BOUNDARY = "----------XnJLe9ZIbbGUYtzPQJ16u1"
13
+ DEFAULT_HOST = 'example.org'.freeze
14
+ MULTIPART_BOUNDARY = '----------XnJLe9ZIbbGUYtzPQJ16u1'.freeze
15
15
 
16
16
  # The common base class for exceptions raised by Rack::Test
17
17
  class Error < StandardError; end
@@ -38,10 +38,10 @@ module Rack
38
38
  @digest_username = nil
39
39
  @digest_password = nil
40
40
 
41
- if mock_session.is_a?(MockSession)
42
- @rack_mock_session = mock_session
41
+ @rack_mock_session = if mock_session.is_a?(MockSession)
42
+ mock_session
43
43
  else
44
- @rack_mock_session = MockSession.new(mock_session)
44
+ MockSession.new(mock_session)
45
45
  end
46
46
 
47
47
  @default_host = @rack_mock_session.default_host
@@ -55,8 +55,7 @@ module Rack
55
55
  # Example:
56
56
  # get "/"
57
57
  def get(uri, params = {}, env = {}, &block)
58
- env = env_for(uri, env.merge(:method => "GET", :params => params))
59
- process_request(uri, env, &block)
58
+ custom_request('GET', uri, params, env, &block)
60
59
  end
61
60
 
62
61
  # Issue a POST request for the given URI. See #get
@@ -64,8 +63,7 @@ module Rack
64
63
  # Example:
65
64
  # post "/signup", "name" => "Bryan"
66
65
  def post(uri, params = {}, env = {}, &block)
67
- env = env_for(uri, env.merge(:method => "POST", :params => params))
68
- process_request(uri, env, &block)
66
+ custom_request('POST', uri, params, env, &block)
69
67
  end
70
68
 
71
69
  # Issue a PUT request for the given URI. See #get
@@ -73,8 +71,7 @@ module Rack
73
71
  # Example:
74
72
  # put "/"
75
73
  def put(uri, params = {}, env = {}, &block)
76
- env = env_for(uri, env.merge(:method => "PUT", :params => params))
77
- process_request(uri, env, &block)
74
+ custom_request('PUT', uri, params, env, &block)
78
75
  end
79
76
 
80
77
  # Issue a PATCH request for the given URI. See #get
@@ -82,8 +79,7 @@ module Rack
82
79
  # Example:
83
80
  # patch "/"
84
81
  def patch(uri, params = {}, env = {}, &block)
85
- env = env_for(uri, env.merge(:method => "PATCH", :params => params))
86
- process_request(uri, env, &block)
82
+ custom_request('PATCH', uri, params, env, &block)
87
83
  end
88
84
 
89
85
  # Issue a DELETE request for the given URI. See #get
@@ -91,8 +87,7 @@ module Rack
91
87
  # Example:
92
88
  # delete "/"
93
89
  def delete(uri, params = {}, env = {}, &block)
94
- env = env_for(uri, env.merge(:method => "DELETE", :params => params))
95
- process_request(uri, env, &block)
90
+ custom_request('DELETE', uri, params, env, &block)
96
91
  end
97
92
 
98
93
  # Issue an OPTIONS request for the given URI. See #get
@@ -100,8 +95,7 @@ module Rack
100
95
  # Example:
101
96
  # options "/"
102
97
  def options(uri, params = {}, env = {}, &block)
103
- env = env_for(uri, env.merge(:method => "OPTIONS", :params => params))
104
- process_request(uri, env, &block)
98
+ custom_request('OPTIONS', uri, params, env, &block)
105
99
  end
106
100
 
107
101
  # Issue a HEAD request for the given URI. See #get
@@ -109,8 +103,7 @@ module Rack
109
103
  # Example:
110
104
  # head "/"
111
105
  def head(uri, params = {}, env = {}, &block)
112
- env = env_for(uri, env.merge(:method => "HEAD", :params => params))
113
- process_request(uri, env, &block)
106
+ custom_request('HEAD', uri, params, env, &block)
114
107
  end
115
108
 
116
109
  # Issue a request to the Rack app for the given URI and optional Rack
@@ -121,10 +114,21 @@ module Rack
121
114
  # Example:
122
115
  # request "/"
123
116
  def request(uri, env = {}, &block)
117
+ uri = parse_uri(uri, env)
124
118
  env = env_for(uri, env)
125
119
  process_request(uri, env, &block)
126
120
  end
127
121
 
122
+ # Issue a request using the given verb for the given URI. See #get
123
+ #
124
+ # Example:
125
+ # custom_request "LINK", "/"
126
+ def custom_request(verb, uri, params = {}, env = {}, &block)
127
+ uri = parse_uri(uri, env)
128
+ env = env_for(uri, env.merge(method: verb.to_s.upcase, params: params))
129
+ process_request(uri, env, &block)
130
+ end
131
+
128
132
  # Set a header to be included on all subsequent requests through the
129
133
  # session. Use a value of nil to remove a previously configured header.
130
134
  #
@@ -160,11 +164,11 @@ module Rack
160
164
  # Example:
161
165
  # basic_authorize "bryan", "secret"
162
166
  def basic_authorize(username, password)
163
- encoded_login = ["#{username}:#{password}"].pack("m*")
167
+ encoded_login = ["#{username}:#{password}"].pack('m0')
164
168
  header('Authorization', "Basic #{encoded_login}")
165
169
  end
166
170
 
167
- alias_method :authorize, :basic_authorize
171
+ alias authorize basic_authorize
168
172
 
169
173
  # Set the username and password for HTTP Digest authorization, to be
170
174
  # included in subsequent requests in the HTTP_AUTHORIZATION header.
@@ -182,48 +186,52 @@ module Rack
182
186
  # a redirect, an error will be raised.
183
187
  def follow_redirect!
184
188
  unless last_response.redirect?
185
- raise Error.new("Last response was not a redirect. Cannot follow_redirect!")
189
+ raise Error, 'Last response was not a redirect. Cannot follow_redirect!'
186
190
  end
187
191
  if last_response.status == 307
188
- send(last_request.request_method.downcase.to_sym, last_response["Location"], last_request.params, { "HTTP_REFERER" => last_request.url })
192
+ send(last_request.request_method.downcase.to_sym, last_response['Location'], last_request.params, 'HTTP_REFERER' => last_request.url)
189
193
  else
190
- get(last_response["Location"], {}, { "HTTP_REFERER" => last_request.url })
194
+ get(last_response['Location'], {}, 'HTTP_REFERER' => last_request.url)
191
195
  end
192
196
  end
193
197
 
194
- private
198
+ private
195
199
 
196
- def env_for(path, env)
197
- uri = URI.parse(path)
198
- uri.path = "/#{uri.path}" unless uri.path[0] == ?/
199
- uri.host ||= @default_host
200
+ def parse_uri(path, env)
201
+ URI.parse(path).tap do |uri|
202
+ uri.path = "/#{uri.path}" unless uri.path[0] == '/'
203
+ uri.host ||= @default_host
204
+ uri.scheme ||= 'https' if env['HTTPS'] == 'on'
205
+ end
206
+ end
200
207
 
208
+ def env_for(uri, env)
201
209
  env = default_env.merge(env)
202
210
 
203
- env["HTTP_HOST"] ||= [uri.host, (uri.port if uri.port != uri.default_port)].compact.join(":")
211
+ env['HTTP_HOST'] ||= [uri.host, (uri.port if uri.port != uri.default_port)].compact.join(':')
204
212
 
205
- env.update("HTTPS" => "on") if URI::HTTPS === uri
206
- env["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest" if env[:xhr]
213
+ env.update('HTTPS' => 'on') if URI::HTTPS === uri
214
+ env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' if env[:xhr]
207
215
 
208
216
  # TODO: Remove this after Rack 1.1 has been released.
209
217
  # Stringifying and upcasing methods has be commit upstream
210
- env["REQUEST_METHOD"] ||= env[:method] ? env[:method].to_s.upcase : "GET"
218
+ env['REQUEST_METHOD'] ||= env[:method] ? env[:method].to_s.upcase : 'GET'
211
219
 
212
- if ["GET", "DELETE"].include?(env["REQUEST_METHOD"])
220
+ if %w[GET DELETE].include?(env['REQUEST_METHOD'])
213
221
  # merge :params with the query string
214
222
  if params = env[:params]
215
223
  params = parse_nested_query(params) if params.is_a?(String)
216
224
 
217
- uri.query = [uri.query, build_nested_query(params)].compact.reject { |v| v == '' }.join("&")
225
+ uri.query = [uri.query, build_nested_query(params)].compact.reject { |v| v == '' }.join('&')
218
226
  end
219
- elsif !env.has_key?(:input)
220
- env["CONTENT_TYPE"] ||= "application/x-www-form-urlencoded"
227
+ elsif !env.key?(:input)
228
+ env['CONTENT_TYPE'] ||= 'application/x-www-form-urlencoded'
221
229
 
222
230
  if env[:params].is_a?(Hash)
223
231
  if data = build_multipart(env[:params])
224
232
  env[:input] = data
225
- env["CONTENT_LENGTH"] ||= data.length.to_s
226
- env["CONTENT_TYPE"] = "multipart/form-data; boundary=#{MULTIPART_BOUNDARY}"
233
+ env['CONTENT_LENGTH'] ||= data.length.to_s
234
+ env['CONTENT_TYPE'] = "multipart/form-data; boundary=#{MULTIPART_BOUNDARY}"
227
235
  else
228
236
  env[:input] = params_to_string(env[:params])
229
237
  end
@@ -234,25 +242,17 @@ module Rack
234
242
 
235
243
  env.delete(:params)
236
244
 
237
- if env.has_key?(:cookie)
238
- set_cookie(env.delete(:cookie), uri)
239
- end
245
+ set_cookie(env.delete(:cookie), uri) if env.key?(:cookie)
240
246
 
241
247
  Rack::MockRequest.env_for(uri.to_s, env)
242
248
  end
243
249
 
244
250
  def process_request(uri, env)
245
- uri = URI.parse(uri)
246
- uri.host ||= @default_host
247
- uri.scheme ||= "https" if env["HTTPS"] == "on"
248
-
249
251
  @rack_mock_session.request(uri, env)
250
252
 
251
253
  if retry_with_digest_auth?(env)
252
- auth_env = env.merge({
253
- "HTTP_AUTHORIZATION" => digest_auth_header,
254
- "rack-test.digest_auth_retry" => true
255
- })
254
+ auth_env = env.merge('HTTP_AUTHORIZATION' => digest_auth_header,
255
+ 'rack-test.digest_auth_retry' => true)
256
256
  auth_env.delete('rack.request')
257
257
  process_request(uri.path, auth_env)
258
258
  else
@@ -263,26 +263,24 @@ module Rack
263
263
  end
264
264
 
265
265
  def digest_auth_header
266
- challenge = last_response["WWW-Authenticate"].split(" ", 2).last
266
+ challenge = last_response['WWW-Authenticate'].split(' ', 2).last
267
267
  params = Rack::Auth::Digest::Params.parse(challenge)
268
268
 
269
- params.merge!({
270
- "username" => @digest_username,
271
- "nc" => "00000001",
272
- "cnonce" => "nonsensenonce",
273
- "uri" => last_request.fullpath,
274
- "method" => last_request.env["REQUEST_METHOD"],
275
- })
269
+ params.merge!('username' => @digest_username,
270
+ 'nc' => '00000001',
271
+ 'cnonce' => 'nonsensenonce',
272
+ 'uri' => last_request.fullpath,
273
+ 'method' => last_request.env['REQUEST_METHOD'])
276
274
 
277
- params["response"] = MockDigestRequest.new(params).response(@digest_password)
275
+ params['response'] = MockDigestRequest.new(params).response(@digest_password)
278
276
 
279
277
  "Digest #{params}"
280
278
  end
281
279
 
282
280
  def retry_with_digest_auth?(env)
283
281
  last_response.status == 401 &&
284
- digest_auth_configured? &&
285
- !env["rack-test.digest_auth_retry"]
282
+ digest_auth_configured? &&
283
+ !env['rack-test.digest_auth_retry']
286
284
  end
287
285
 
288
286
  def digest_auth_configured?
@@ -290,15 +288,15 @@ module Rack
290
288
  end
291
289
 
292
290
  def default_env
293
- { "rack.test" => true, "REMOTE_ADDR" => "127.0.0.1" }.merge(@env).merge(headers_for_env)
291
+ { 'rack.test' => true, 'REMOTE_ADDR' => '127.0.0.1' }.merge(@env).merge(headers_for_env)
294
292
  end
295
293
 
296
294
  def headers_for_env
297
295
  converted_headers = {}
298
296
 
299
297
  @headers.each do |name, value|
300
- env_key = name.upcase.gsub("-", "_")
301
- env_key = "HTTP_" + env_key unless "CONTENT_TYPE" == env_key
298
+ env_key = name.upcase.tr('-', '_')
299
+ env_key = 'HTTP_' + env_key unless env_key == 'CONTENT_TYPE'
302
300
  converted_headers[env_key] = value
303
301
  end
304
302
 
@@ -308,16 +306,14 @@ module Rack
308
306
  def params_to_string(params)
309
307
  case params
310
308
  when Hash then build_nested_query(params)
311
- when nil then ""
309
+ when nil then ''
312
310
  else params
313
311
  end
314
312
  end
315
-
316
313
  end
317
314
 
318
315
  def self.encoding_aware_strings?
319
- defined?(Encoding) && "".respond_to?(:encode)
316
+ defined?(Encoding) && ''.respond_to?(:encode)
320
317
  end
321
-
322
318
  end
323
319
  end
@@ -1,9 +1,8 @@
1
- require "uri"
2
- require "time"
1
+ require 'uri'
2
+ require 'time'
3
3
 
4
4
  module Rack
5
5
  module Test
6
-
7
6
  class Cookie # :nodoc:
8
7
  include Rack::Utils
9
8
 
@@ -21,8 +20,8 @@ module Rack
21
20
  @name, @value = parse_query(@name_value_raw, ';').to_a.first
22
21
  @options = parse_query(options, ';')
23
22
 
24
- @options["domain"] ||= (uri.host || default_host)
25
- @options["path"] ||= uri.path.sub(/\/[^\/]*\Z/, "")
23
+ @options['domain'] ||= (uri.host || default_host)
24
+ @options['path'] ||= uri.path.sub(/\/[^\/]*\Z/, '')
26
25
  end
27
26
 
28
27
  def replaces?(other)
@@ -41,25 +40,25 @@ module Rack
41
40
 
42
41
  # :api: private
43
42
  def domain
44
- @options["domain"]
43
+ @options['domain']
45
44
  end
46
45
 
47
46
  def secure?
48
- @options.has_key?("secure")
47
+ @options.key?('secure')
49
48
  end
50
49
 
51
50
  def http_only?
52
- @options.has_key?('HttpOnly')
51
+ @options.key?('HttpOnly')
53
52
  end
54
53
 
55
54
  # :api: private
56
55
  def path
57
- @options["path"].strip || "/"
56
+ ([*@options['path']].first.split(',').first || '/').strip
58
57
  end
59
58
 
60
59
  # :api: private
61
60
  def expires
62
- Time.parse(@options["expires"]) if @options["expires"]
61
+ Time.parse(@options['expires']) if @options['expires']
63
62
  end
64
63
 
65
64
  # :api: private
@@ -71,19 +70,17 @@ module Rack
71
70
  def valid?(uri)
72
71
  uri ||= default_uri
73
72
 
74
- if uri.host.nil?
75
- uri.host = @default_host
76
- end
73
+ uri.host = @default_host if uri.host.nil?
77
74
 
78
75
  real_domain = domain =~ /^\./ ? domain[1..-1] : domain
79
- (!secure? || (secure? && uri.scheme == "https")) &&
80
- uri.host =~ Regexp.new("#{Regexp.escape(real_domain)}$", Regexp::IGNORECASE) &&
81
- uri.path =~ Regexp.new("^#{Regexp.escape(path)}")
76
+ (!secure? || (secure? && uri.scheme == 'https')) &&
77
+ uri.host =~ Regexp.new("#{Regexp.escape(real_domain)}$", Regexp::IGNORECASE) &&
78
+ uri.path =~ Regexp.new("^#{Regexp.escape(path)}")
82
79
  end
83
80
 
84
81
  # :api: private
85
82
  def matches?(uri)
86
- ! expired? && valid?(uri)
83
+ !expired? && valid?(uri)
87
84
  end
88
85
 
89
86
  # :api: private
@@ -91,25 +88,24 @@ module Rack
91
88
  # Orders the cookies from least specific to most
92
89
  [name, path, domain.reverse] <=> [other.name, other.path, other.domain.reverse]
93
90
  end
91
+
94
92
  def to_h
95
93
  @options.merge(
96
94
  'value' => @value,
97
95
  'HttpOnly' => http_only?,
98
- 'secure' => secure?,
96
+ 'secure' => secure?
99
97
  )
100
98
  end
101
- alias_method :to_hash, :to_h
99
+ alias to_hash to_h
102
100
 
103
- protected
101
+ protected
104
102
 
105
103
  def default_uri
106
- URI.parse("//" + @default_host + "/")
104
+ URI.parse('//' + @default_host + '/')
107
105
  end
108
-
109
106
  end
110
107
 
111
108
  class CookieJar # :nodoc:
112
-
113
109
  # :api: private
114
110
  def initialize(cookies = [], default_host = DEFAULT_HOST)
115
111
  @default_host = default_host
@@ -128,7 +124,7 @@ module Rack
128
124
  end
129
125
 
130
126
  def get_cookie(name)
131
- hash_for(nil).fetch(name,nil)
127
+ hash_for(nil).fetch(name, nil)
132
128
  end
133
129
 
134
130
  def delete(name)
@@ -142,7 +138,7 @@ module Rack
142
138
 
143
139
  if raw_cookies.is_a? String
144
140
  raw_cookies = raw_cookies.split("\n")
145
- raw_cookies.reject!{|c| c.empty? }
141
+ raw_cookies.reject!(&:empty?)
146
142
  end
147
143
 
148
144
  raw_cookies.each do |raw_cookie|
@@ -162,7 +158,7 @@ module Rack
162
158
 
163
159
  # :api: private
164
160
  def for(uri)
165
- hash_for(uri).values.map { |c| c.raw }.join(';')
161
+ hash_for(uri).values.map(&:raw).join(';')
166
162
  end
167
163
 
168
164
  def to_hash
@@ -172,10 +168,10 @@ module Rack
172
168
  cookies[name] = cookie.value
173
169
  end
174
170
 
175
- return cookies
171
+ cookies
176
172
  end
177
173
 
178
- protected
174
+ protected
179
175
 
180
176
  def hash_for(uri = nil)
181
177
  cookies = {}
@@ -189,10 +185,8 @@ module Rack
189
185
  cookies[cookie.name] = cookie if !uri || cookie.matches?(uri)
190
186
  end
191
187
 
192
- return cookies
188
+ cookies
193
189
  end
194
-
195
190
  end
196
-
197
191
  end
198
192
  end
@@ -1,8 +1,7 @@
1
- require "forwardable"
1
+ require 'forwardable'
2
2
 
3
3
  module Rack
4
4
  module Test
5
-
6
5
  # This module serves as the primary integration point for using Rack::Test
7
6
  # in a testing environment. It depends on an app method being defined in the
8
7
  # same context, and provides the Rack::Test API methods (see Rack::Test::Session
@@ -56,26 +55,27 @@ module Rack
56
55
  @_current_session_names ||= [:default]
57
56
  end
58
57
 
59
- METHODS = [
60
- :request,
61
- :get,
62
- :post,
63
- :put,
64
- :patch,
65
- :delete,
66
- :options,
67
- :head,
68
- :follow_redirect!,
69
- :header,
70
- :env,
71
- :set_cookie,
72
- :clear_cookies,
73
- :authorize,
74
- :basic_authorize,
75
- :digest_authorize,
76
- :last_response,
77
- :last_request
78
- ]
58
+ METHODS = %i[
59
+ request
60
+ get
61
+ post
62
+ put
63
+ patch
64
+ delete
65
+ options
66
+ head
67
+ custom_request
68
+ follow_redirect!
69
+ header
70
+ env
71
+ set_cookie
72
+ clear_cookies
73
+ authorize
74
+ basic_authorize
75
+ digest_authorize
76
+ last_response
77
+ last_request
78
+ ].freeze
79
79
 
80
80
  def_delegators :current_session, *METHODS
81
81
  end
@@ -1,14 +1,12 @@
1
1
  module Rack
2
2
  module Test
3
-
4
3
  class MockDigestRequest # :nodoc:
5
-
6
4
  def initialize(params)
7
5
  @params = params
8
6
  end
9
7
 
10
8
  def method_missing(sym)
11
- if @params.has_key? k = sym.to_s
9
+ if @params.key? k = sym.to_s
12
10
  return @params[k]
13
11
  end
14
12
 
@@ -22,8 +20,6 @@ module Rack
22
20
  def response(password)
23
21
  Rack::Auth::Digest::MD5.new(nil).send :digest, self, password
24
22
  end
25
-
26
23
  end
27
-
28
24
  end
29
25
  end
@@ -1,16 +1,14 @@
1
- require "tempfile"
2
- require "fileutils"
1
+ require 'tempfile'
2
+ require 'fileutils'
3
3
 
4
4
  module Rack
5
5
  module Test
6
-
7
6
  # Wraps a Tempfile with a content type. Including one or more UploadedFile's
8
7
  # in the params causes Rack::Test to build and issue a multipart request.
9
8
  #
10
9
  # Example:
11
10
  # post "/photos", "file" => Rack::Test::UploadedFile.new("me.jpg", "image/jpeg")
12
11
  class UploadedFile
13
-
14
12
  # The filename, *not* including the path, of the "uploaded" file
15
13
  attr_reader :original_filename
16
14
 
@@ -20,33 +18,28 @@ module Rack
20
18
  # The content type of the "uploaded" file
21
19
  attr_accessor :content_type
22
20
 
23
- def initialize(path, content_type = "text/plain", binary = false)
24
- raise "#{path} file does not exist" unless ::File.exist?(path)
25
-
21
+ def initialize(content, content_type = 'text/plain', binary = false, original_filename: nil)
22
+ if content.respond_to?(:read)
23
+ initialize_from_io(content, original_filename)
24
+ else
25
+ initialize_from_file_path(content)
26
+ end
26
27
  @content_type = content_type
27
- @original_filename = ::File.basename(path)
28
-
29
- @tempfile = Tempfile.new([@original_filename, ::File.extname(path)])
30
- @tempfile.set_encoding(Encoding::BINARY) if @tempfile.respond_to?(:set_encoding)
31
28
  @tempfile.binmode if binary
32
-
33
- ObjectSpace.define_finalizer(self, self.class.finalize(@tempfile))
34
-
35
- FileUtils.copy_file(path, @tempfile.path)
36
29
  end
37
30
 
38
31
  def path
39
- @tempfile.path
32
+ tempfile.path
40
33
  end
41
34
 
42
- alias_method :local_path, :path
35
+ alias local_path path
43
36
 
44
37
  def method_missing(method_name, *args, &block) #:nodoc:
45
- @tempfile.__send__(method_name, *args, &block)
38
+ tempfile.public_send(method_name, *args, &block)
46
39
  end
47
40
 
48
- def respond_to?(method_name, include_private = false) #:nodoc:
49
- @tempfile.respond_to?(method_name, include_private) || super
41
+ def respond_to_missing?(method_name, include_private = false) #:nodoc:
42
+ tempfile.respond_to?(method_name, include_private) || super
50
43
  end
51
44
 
52
45
  def self.finalize(file)
@@ -58,7 +51,25 @@ module Rack
58
51
  file.unlink
59
52
  end
60
53
 
61
- end
54
+ private
62
55
 
56
+ def initialize_from_io(io, original_filename)
57
+ @tempfile = io
58
+ @original_filename = original_filename || raise(ArgumentError, 'Missing `original_filename` for IO')
59
+ end
60
+
61
+ def initialize_from_file_path(path)
62
+ raise "#{path} file does not exist" unless ::File.exist?(path)
63
+
64
+ @original_filename = ::File.basename(path)
65
+
66
+ @tempfile = Tempfile.new([@original_filename, ::File.extname(path)])
67
+ @tempfile.set_encoding(Encoding::BINARY) if @tempfile.respond_to?(:set_encoding)
68
+
69
+ ObjectSpace.define_finalizer(self, self.class.finalize(@tempfile))
70
+
71
+ FileUtils.copy_file(path, @tempfile.path)
72
+ end
73
+ end
63
74
  end
64
75
  end
@@ -1,6 +1,5 @@
1
1
  module Rack
2
2
  module Test
3
-
4
3
  module Utils # :nodoc:
5
4
  include Rack::Utils
6
5
  extend Rack::Utils
@@ -12,16 +11,14 @@ module Rack
12
11
  "#{prefix}[]="
13
12
  else
14
13
  value.map do |v|
15
- unless unescape(prefix) =~ /\[\]$/
16
- prefix = "#{prefix}[]"
17
- end
18
- build_nested_query(v, "#{prefix}")
19
- end.join("&")
14
+ prefix = "#{prefix}[]" unless unescape(prefix) =~ /\[\]$/
15
+ build_nested_query(v, prefix.to_s)
16
+ end.join('&')
20
17
  end
21
18
  when Hash
22
19
  value.map do |k, v|
23
20
  build_nested_query(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
24
- end.join("&")
21
+ end.join('&')
25
22
  when NilClass
26
23
  prefix.to_s
27
24
  else
@@ -32,9 +29,7 @@ module Rack
32
29
 
33
30
  def build_multipart(params, first = true, multipart = false)
34
31
  if first
35
- unless params.is_a?(Hash)
36
- raise ArgumentError, "value must be a Hash"
37
- end
32
+ raise ArgumentError, 'value must be a Hash' unless params.is_a?(Hash)
38
33
 
39
34
  query = lambda { |value|
40
35
  case value
@@ -50,7 +45,7 @@ module Rack
50
45
  return nil unless multipart
51
46
  end
52
47
 
53
- flattened_params = Hash.new
48
+ flattened_params = {}
54
49
 
55
50
  params.each do |key, value|
56
51
  k = first ? key.to_s : "[#{key}]"
@@ -58,23 +53,21 @@ module Rack
58
53
  case value
59
54
  when Array
60
55
  value.map do |v|
61
-
62
- if (v.is_a?(Hash))
56
+ if v.is_a?(Hash)
63
57
  nested_params = {}
64
- build_multipart(v, false).each { |subkey, subvalue|
58
+ build_multipart(v, false).each do |subkey, subvalue|
65
59
  nested_params[subkey] = subvalue
66
- }
60
+ end
67
61
  flattened_params["#{k}[]"] ||= []
68
62
  flattened_params["#{k}[]"] << nested_params
69
63
  else
70
64
  flattened_params["#{k}[]"] = value
71
65
  end
72
-
73
66
  end
74
67
  when Hash
75
- build_multipart(value, false).each { |subkey, subvalue|
68
+ build_multipart(value, false).each do |subkey, subvalue|
76
69
  flattened_params[k + subkey] = subvalue
77
- }
70
+ end
78
71
  else
79
72
  flattened_params[k] = value
80
73
  end
@@ -89,24 +82,25 @@ module Rack
89
82
  module_function :build_multipart
90
83
 
91
84
  private
85
+
92
86
  def build_parts(parameters)
93
87
  get_parts(parameters).join + "--#{MULTIPART_BOUNDARY}--\r"
94
88
  end
95
89
  module_function :build_parts
96
90
 
97
91
  def get_parts(parameters)
98
- parameters.map { |name, value|
99
- if name =~ /\[\]\Z/ && value.is_a?(Array) && value.all? {|v| v.is_a?(Hash)}
100
- value.map { |hash|
92
+ parameters.map do |name, value|
93
+ if name =~ /\[\]\Z/ && value.is_a?(Array) && value.all? { |v| v.is_a?(Hash) }
94
+ value.map do |hash|
101
95
  new_value = {}
102
- hash.each { |k, v| new_value[name+k] = v }
96
+ hash.each { |k, v| new_value[name + k] = v }
103
97
  get_parts(new_value).join
104
- }.join
98
+ end.join
105
99
  else
106
100
  if value.respond_to?(:original_filename)
107
101
  build_file_part(name, value)
108
102
 
109
- elsif value.is_a?(Array) and value.all? { |v| v.respond_to?(:original_filename) }
103
+ elsif value.is_a?(Array) && value.all? { |v| v.respond_to?(:original_filename) }
110
104
  value.map do |v|
111
105
  build_file_part(name, v)
112
106
  end.join
@@ -116,14 +110,12 @@ module Rack
116
110
  Rack::Test.encoding_aware_strings? ? primitive_part.force_encoding('BINARY') : primitive_part
117
111
  end
118
112
  end
119
- }
113
+ end
120
114
  end
121
115
  module_function :get_parts
122
116
 
123
117
  def build_primitive_part(parameter_name, value)
124
- unless value.is_a? Array
125
- value = [value]
126
- end
118
+ value = [value] unless value.is_a? Array
127
119
  value.map do |v|
128
120
  <<-EOF
129
121
  --#{MULTIPART_BOUNDARY}\r
@@ -136,21 +128,17 @@ EOF
136
128
  module_function :build_primitive_part
137
129
 
138
130
  def build_file_part(parameter_name, uploaded_file)
139
- ::File.open(uploaded_file.path, "rb") do |physical_file|
140
- physical_file.set_encoding(Encoding::BINARY) if physical_file.respond_to?(:set_encoding)
141
- <<-EOF
131
+ uploaded_file.set_encoding(Encoding::BINARY) if uploaded_file.respond_to?(:set_encoding)
132
+ <<-EOF
142
133
  --#{MULTIPART_BOUNDARY}\r
143
134
  Content-Disposition: form-data; name="#{parameter_name}"; filename="#{escape(uploaded_file.original_filename)}"\r
144
135
  Content-Type: #{uploaded_file.content_type}\r
145
- Content-Length: #{::File.stat(uploaded_file.path).size}\r
136
+ Content-Length: #{uploaded_file.size}\r
146
137
  \r
147
- #{physical_file.read}\r
138
+ #{uploaded_file.read}\r
148
139
  EOF
149
- end
150
140
  end
151
141
  module_function :build_file_part
152
-
153
142
  end
154
-
155
143
  end
156
144
  end
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  module Test
3
- VERSION = '0.7.0'.freeze
3
+ VERSION = '0.8.0'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-test
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bryan Helmkamp
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-10 00:00:00.000000000 Z
11
+ date: 2017-11-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -173,7 +173,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
173
173
  requirements:
174
174
  - - ">="
175
175
  - !ruby/object:Gem::Version
176
- version: '0'
176
+ version: 2.2.2
177
177
  required_rubygems_version: !ruby/object:Gem::Requirement
178
178
  requirements:
179
179
  - - ">="