rack-test 0.6.2 → 0.6.3

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/Gemfile CHANGED
@@ -1,6 +1,8 @@
1
- source :rubygems
1
+ source 'https://rubygems.org'
2
2
 
3
3
  gem 'rspec'
4
4
  gem "rack"
5
5
  gem "sinatra"
6
6
  gem 'rake'
7
+
8
+ gem "codeclimate-test-reporter", group: :test, require: nil
@@ -1,30 +1,40 @@
1
1
  GEM
2
- remote: http://rubygems.org/
2
+ remote: https://rubygems.org/
3
3
  specs:
4
- diff-lcs (1.1.3)
5
- rack (1.4.0)
6
- rack-protection (1.2.0)
4
+ codeclimate-test-reporter (0.3.0)
5
+ simplecov (>= 0.7.1, < 1.0.0)
6
+ diff-lcs (1.2.3)
7
+ docile (1.1.3)
8
+ multi_json (1.9.0)
9
+ rack (1.5.2)
10
+ rack-protection (1.5.0)
7
11
  rack
8
- rake (0.9.2)
9
- rspec (2.8.0)
10
- rspec-core (~> 2.8.0)
11
- rspec-expectations (~> 2.8.0)
12
- rspec-mocks (~> 2.8.0)
13
- rspec-core (2.8.0)
14
- rspec-expectations (2.8.0)
15
- diff-lcs (~> 1.1.2)
16
- rspec-mocks (2.8.0)
17
- sinatra (1.3.2)
18
- rack (~> 1.3, >= 1.3.6)
19
- rack-protection (~> 1.2)
20
- tilt (~> 1.3, >= 1.3.3)
21
- tilt (1.3.3)
12
+ rake (10.0.4)
13
+ rspec (2.13.0)
14
+ rspec-core (~> 2.13.0)
15
+ rspec-expectations (~> 2.13.0)
16
+ rspec-mocks (~> 2.13.0)
17
+ rspec-core (2.13.1)
18
+ rspec-expectations (2.13.0)
19
+ diff-lcs (>= 1.1.3, < 2.0)
20
+ rspec-mocks (2.13.1)
21
+ simplecov (0.8.2)
22
+ docile (~> 1.1.0)
23
+ multi_json
24
+ simplecov-html (~> 0.8.0)
25
+ simplecov-html (0.8.0)
26
+ sinatra (1.4.2)
27
+ rack (~> 1.5, >= 1.5.2)
28
+ rack-protection (~> 1.4)
29
+ tilt (~> 1.3, >= 1.3.4)
30
+ tilt (1.3.7)
22
31
 
23
32
  PLATFORMS
24
33
  java
25
34
  ruby
26
35
 
27
36
  DEPENDENCIES
37
+ codeclimate-test-reporter
28
38
  rack
29
39
  rake
30
40
  rspec
@@ -1,3 +1,16 @@
1
+ == 0.6.3 / 2015-01-09
2
+
3
+ * Minor enhancements
4
+
5
+ * Expose an env helper for persistently configuring the env as needed
6
+ (Darío Javier Cravero #80)
7
+ * Expose the tempfile of UploadedFile (Sytse Sijbrandij #67)
8
+
9
+ * Bug fixes
10
+
11
+ * Improve support for arrays of hashes in multipart forms (Murray Steele #69)
12
+ * Improve test for query strings (Paul Grayson #66)
13
+
1
14
  == 0.6.2 / 2012-09-27
2
15
 
3
16
  * Minor enhancements
@@ -1,4 +1,4 @@
1
- = Rack::Test {<img src="https://codeclimate.com/badge.png" />}[https://codeclimate.com/github/brynary/rack-test]
1
+ = Rack::Test {<img src="https://codeclimate.com/github/brynary/rack-test.png" />}[https://codeclimate.com/github/brynary/rack-test] {<img src="https://codeclimate.com/github/brynary/rack-test/coverage.png" />}[https://codeclimate.com/github/brynary/rack-test]
2
2
 
3
3
  - Code: http://github.com/brynary/rack-test
4
4
 
@@ -9,7 +9,7 @@ require "rack/test/uploaded_file"
9
9
 
10
10
  module Rack
11
11
  module Test
12
- VERSION = "0.6.2"
12
+ VERSION = "0.6.3"
13
13
 
14
14
  DEFAULT_HOST = "example.org"
15
15
  MULTIPART_BOUNDARY = "----------XnJLe9ZIbbGUYtzPQJ16u1"
@@ -35,6 +35,7 @@ module Rack
35
35
  # (See README.rdoc for an example)
36
36
  def initialize(mock_session)
37
37
  @headers = {}
38
+ @env = {}
38
39
 
39
40
  if mock_session.is_a?(MockSession)
40
41
  @rack_mock_session = mock_session
@@ -139,6 +140,19 @@ module Rack
139
140
  end
140
141
  end
141
142
 
143
+ # Set an env var to be included on all subsequent requests through the
144
+ # session. Use a value of nil to remove a previously configured env.
145
+ #
146
+ # Example:
147
+ # env "rack.session", {:csrf => 'token'}
148
+ def env(name, value)
149
+ if value.nil?
150
+ @env.delete(name)
151
+ else
152
+ @env[name] = value
153
+ end
154
+ end
155
+
142
156
  # Set the username and password for HTTP Basic authorization, to be
143
157
  # included in subsequent requests in the HTTP_AUTHORIZATION header.
144
158
  #
@@ -271,7 +285,7 @@ module Rack
271
285
  end
272
286
 
273
287
  def default_env
274
- { "rack.test" => true, "REMOTE_ADDR" => "127.0.0.1" }.merge(headers_for_env)
288
+ { "rack.test" => true, "REMOTE_ADDR" => "127.0.0.1" }.merge(@env).merge(headers_for_env)
275
289
  end
276
290
 
277
291
  def headers_for_env
@@ -67,6 +67,7 @@ module Rack
67
67
  :head,
68
68
  :follow_redirect!,
69
69
  :header,
70
+ :env,
70
71
  :set_cookie,
71
72
  :clear_cookies,
72
73
  :authorize,
@@ -14,6 +14,9 @@ module Rack
14
14
  # The filename, *not* including the path, of the "uploaded" file
15
15
  attr_reader :original_filename
16
16
 
17
+ # The tempfile
18
+ attr_reader :tempfile
19
+
17
20
  # The content type of the "uploaded" file
18
21
  attr_accessor :content_type
19
22
 
@@ -57,9 +57,12 @@ module Rack
57
57
  value.map do |v|
58
58
 
59
59
  if (v.is_a?(Hash))
60
+ nested_params = {}
60
61
  build_multipart(v, false).each { |subkey, subvalue|
61
- flattened_params["#{k}[]#{subkey}"] = subvalue
62
+ nested_params[subkey] = subvalue
62
63
  }
64
+ flattened_params["#{k}[]"] ||= []
65
+ flattened_params["#{k}[]"] << nested_params
63
66
  else
64
67
  flattened_params["#{k}[]"] = value
65
68
  end
@@ -85,21 +88,32 @@ module Rack
85
88
 
86
89
  private
87
90
  def build_parts(parameters)
91
+ get_parts(parameters).join + "--#{MULTIPART_BOUNDARY}--\r"
92
+ end
93
+
94
+ def get_parts(parameters)
88
95
  parameters.map { |name, value|
89
- if value.respond_to?(:original_filename)
90
- build_file_part(name, value)
96
+ if name =~ /\[\]\Z/ && value.is_a?(Array) && value.all? {|v| v.is_a?(Hash)}
97
+ value.map { |hash|
98
+ new_value = {}
99
+ hash.each { |k, v| new_value[name+k] = v }
100
+ get_parts(new_value).join
101
+ }.join
102
+ else
103
+ if value.respond_to?(:original_filename)
104
+ build_file_part(name, value)
91
105
 
92
- elsif value.is_a?(Array) and value.all? { |v| v.respond_to?(:original_filename) }
93
- value.map do |v|
94
- build_file_part(name, v)
95
- end.join
106
+ elsif value.is_a?(Array) and value.all? { |v| v.respond_to?(:original_filename) }
107
+ value.map do |v|
108
+ build_file_part(name, v)
109
+ end.join
96
110
 
97
- else
98
- primitive_part = build_primitive_part(name, value)
99
- Rack::Test.encoding_aware_strings? ? primitive_part.force_encoding('BINARY') : primitive_part
111
+ else
112
+ primitive_part = build_primitive_part(name, value)
113
+ Rack::Test.encoding_aware_strings? ? primitive_part.force_encoding('BINARY') : primitive_part
114
+ end
100
115
  end
101
-
102
- }.join + "--#{MULTIPART_BOUNDARY}--\r"
116
+ }
103
117
  end
104
118
 
105
119
  def build_primitive_part(parameter_name, value)
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "rack-test"
5
- s.version = "0.6.2"
5
+ s.version = "0.6.3"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Bryan Helmkamp"]
9
- s.date = "2012-09-27"
9
+ s.date = "2015-01-09"
10
10
  s.description = "Rack::Test is a small, simple testing API for Rack apps. It can be used on its\nown or as a reusable starting point for Web frameworks and testing libraries\nto build on. Most of its initial functionality is an extraction of Merb 1.0's\nrequest helpers feature."
11
11
  s.email = "bryan@brynary.com"
12
12
  s.extra_rdoc_files = [
@@ -17,6 +17,8 @@ describe Rack::Test::UploadedFile do
17
17
  uploaded_file.should respond_to(:size)
18
18
  uploaded_file.should respond_to(:unlink)
19
19
  uploaded_file.should respond_to(:read)
20
+ uploaded_file.should respond_to(:original_filename)
21
+ uploaded_file.should respond_to(:tempfile) # Allows calls to params[:file].tempfile
20
22
  end
21
23
 
22
24
  end
@@ -104,6 +104,77 @@ describe Rack::Test::Utils do
104
104
  check params["foo"].should == ["1", "2"]
105
105
  end
106
106
 
107
+ it "builds nested multipart bodies with an array of hashes" do
108
+ files = Rack::Test::UploadedFile.new(multipart_file("foo.txt"))
109
+ data = build_multipart("files" => files, "foo" => [{"id" => "1", "name" => 'Dave'}, {"id" => "2", "name" => 'Steve'}])
110
+
111
+ options = {
112
+ "CONTENT_TYPE" => "multipart/form-data; boundary=#{Rack::Test::MULTIPART_BOUNDARY}",
113
+ "CONTENT_LENGTH" => data.length.to_s,
114
+ :input => StringIO.new(data)
115
+ }
116
+ env = Rack::MockRequest.env_for("/", options)
117
+ params = Rack::Utils::Multipart.parse_multipart(env)
118
+ check params["files"][:filename].should == "foo.txt"
119
+ params["files"][:tempfile].read.should == "bar\n"
120
+ check params["foo"].should == [{"id" => "1", "name" => "Dave"}, {"id" => "2", "name" => "Steve"}]
121
+ end
122
+
123
+ it "builds nested multipart bodies with arbitrarily nested array of hashes" do
124
+ files = Rack::Test::UploadedFile.new(multipart_file("foo.txt"))
125
+ data = build_multipart("files" => files, "foo" => {"bar" => [{"id" => "1", "name" => 'Dave'},
126
+ {"id" => "2", "name" => 'Steve', "qux" => [{"id" => '3', "name" => 'mike'},
127
+ {"id" => '4', "name" => 'Joan'}]}]})
128
+
129
+ options = {
130
+ "CONTENT_TYPE" => "multipart/form-data; boundary=#{Rack::Test::MULTIPART_BOUNDARY}",
131
+ "CONTENT_LENGTH" => data.length.to_s,
132
+ :input => StringIO.new(data)
133
+ }
134
+ env = Rack::MockRequest.env_for("/", options)
135
+ params = Rack::Utils::Multipart.parse_multipart(env)
136
+ check params["files"][:filename].should == "foo.txt"
137
+ params["files"][:tempfile].read.should == "bar\n"
138
+ check params["foo"].should == {"bar" => [{"id" => "1", "name" => "Dave"},
139
+ {"id" => "2", "name" => "Steve", "qux" => [{"id" => '3', "name" => 'mike'},
140
+ {"id" => '4', "name" => 'Joan'}]}]}
141
+ end
142
+
143
+ it 'does not break with params that look nested, but are not' do
144
+ files = Rack::Test::UploadedFile.new(multipart_file("foo.txt"))
145
+ data = build_multipart("foo[]" => "1", "bar[]" => {"qux" => "2"}, "files[]" => files)
146
+
147
+ options = {
148
+ "CONTENT_TYPE" => "multipart/form-data; boundary=#{Rack::Test::MULTIPART_BOUNDARY}",
149
+ "CONTENT_LENGTH" => data.length.to_s,
150
+ :input => StringIO.new(data)
151
+ }
152
+ env = Rack::MockRequest.env_for("/", options)
153
+ params = Rack::Utils::Multipart.parse_multipart(env)
154
+ check params["files"][0][:filename].should == "foo.txt"
155
+ params["files"][0][:tempfile].read.should == "bar\n"
156
+ check params["foo"][0].should == "1"
157
+ check params["bar"][0].should == {"qux" => "2"}
158
+ end
159
+
160
+ it 'allows for nested files' do
161
+ files = Rack::Test::UploadedFile.new(multipart_file("foo.txt"))
162
+ data = build_multipart("foo" => [{"id" => "1", "data" => files},
163
+ {"id" => "2", "data" => ["3", "4"]}])
164
+
165
+ options = {
166
+ "CONTENT_TYPE" => "multipart/form-data; boundary=#{Rack::Test::MULTIPART_BOUNDARY}",
167
+ "CONTENT_LENGTH" => data.length.to_s,
168
+ :input => StringIO.new(data)
169
+ }
170
+ env = Rack::MockRequest.env_for("/", options)
171
+ params = Rack::Utils::Multipart.parse_multipart(env)
172
+ check params["foo"][0]["id"].should == "1"
173
+ check params["foo"][0]["data"][:filename].should == "foo.txt"
174
+ params["foo"][0]["data"][:tempfile].read.should == "bar\n"
175
+ check params["foo"][1].should == {"id" => "2", "data" => ["3", "4"]}
176
+ end
177
+
107
178
  it "returns nil if no UploadedFiles were used" do
108
179
  data = build_multipart("people" => [{"submit-name" => "Larry", "files" => "contents"}])
109
180
  data.should be_nil
@@ -123,8 +123,8 @@ describe Rack::Test::Session do
123
123
  end
124
124
 
125
125
  it "does not rewrite a GET query string when :params is not supplied" do
126
- request "/foo?a=1&b=2&c=3&e=4&d=5"
127
- last_request.query_string.should == "a=1&b=2&c=3&e=4&d=5"
126
+ request "/foo?a=1&b=2&c=3&e=4&d=5+%20"
127
+ last_request.query_string.should == "a=1&b=2&c=3&e=4&d=5+%20"
128
128
  end
129
129
 
130
130
  it "accepts params and builds url encoded params for POST requests" do
@@ -289,6 +289,46 @@ describe Rack::Test::Session do
289
289
  end
290
290
  end
291
291
 
292
+ describe "#env" do
293
+ it "sets the env to be sent with requests" do
294
+ env "rack.session", {:csrf => 'token'}
295
+ request "/"
296
+
297
+ last_request.env["rack.session"].should == {:csrf => 'token'}
298
+ end
299
+
300
+ it "persists across multiple requests" do
301
+ env "rack.session", {:csrf => 'token'}
302
+ request "/"
303
+ request "/"
304
+
305
+ last_request.env["rack.session"].should == {:csrf => 'token'}
306
+ end
307
+
308
+ it "overwrites previously set envs" do
309
+ env "rack.session", {:csrf => 'token'}
310
+ env "rack.session", {:some => :thing}
311
+ request "/"
312
+
313
+ last_request.env["rack.session"].should == {:some => :thing}
314
+ end
315
+
316
+ it "can be used to clear a env" do
317
+ env "rack.session", {:csrf => 'token'}
318
+ env "rack.session", nil
319
+ request "/"
320
+
321
+ last_request.env.should_not have_key("X_CSRF_TOKEN")
322
+ end
323
+
324
+ it "is overridden by envs sent during the request" do
325
+ env "rack.session", {:csrf => 'token'}
326
+ request "/", "rack.session" => {:some => :thing}
327
+
328
+ last_request.env["rack.session"].should == {:some => :thing}
329
+ end
330
+ end
331
+
292
332
  describe "#authorize" do
293
333
  it "sets the HTTP_AUTHORIZATION header" do
294
334
  authorize "bryan", "secret"
@@ -1,6 +1,9 @@
1
1
  require "rubygems"
2
2
  require "bundler/setup"
3
3
 
4
+ require "codeclimate-test-reporter"
5
+ CodeClimate::TestReporter.start
6
+
4
7
  require "rack"
5
8
  require "rspec"
6
9
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-test
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.6.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-27 00:00:00.000000000 Z
12
+ date: 2015-01-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack
@@ -92,7 +92,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
92
92
  version: '0'
93
93
  requirements: []
94
94
  rubyforge_project: rack-test
95
- rubygems_version: 1.8.23
95
+ rubygems_version: 1.8.23.2
96
96
  signing_key:
97
97
  specification_version: 3
98
98
  summary: Simple testing API built on Rack