rack-test 0.5.3 → 0.5.4

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 CHANGED
@@ -2,3 +2,4 @@ pkg
2
2
  doc
3
3
  coverage
4
4
  VERSION
5
+ *.rbc
@@ -1,3 +1,12 @@
1
+ == Git
2
+
3
+ * Bug fixes
4
+
5
+ * Don't stomp on Content-Type's supplied via #header (Bryan Helmkamp)
6
+ * Fixed build_multipart to allow for arrays of files (Louis Rose)
7
+ * Don't raise an error if raw cookies contain a blank line (John Reilly)
8
+ * Handle parameter names with brackets properly (Tanner Donovan)
9
+
1
10
  == 0.5.3 / 2009-11-27
2
11
 
3
12
  * Bug fixes
@@ -9,7 +9,7 @@ require "rack/test/uploaded_file"
9
9
 
10
10
  module Rack
11
11
  module Test
12
- VERSION = "0.5.3"
12
+ VERSION = "0.5.4"
13
13
 
14
14
  DEFAULT_HOST = "example.org"
15
15
  MULTIPART_BOUNDARY = "----------XnJLe9ZIbbGUYtzPQJ16u1"
@@ -255,7 +255,8 @@ module Rack
255
255
  converted_headers = {}
256
256
 
257
257
  @headers.each do |name, value|
258
- env_key = "HTTP_" + name.upcase.gsub("-", "_")
258
+ env_key = name.upcase.gsub("-", "_")
259
+ env_key = "HTTP_" + env_key unless "CONTENT_TYPE" == env_key
259
260
  converted_headers[env_key] = value
260
261
  end
261
262
 
@@ -118,7 +118,11 @@ module Rack
118
118
  def merge(raw_cookies, uri = nil)
119
119
  return unless raw_cookies
120
120
 
121
- raw_cookies = raw_cookies.split("\n") if raw_cookies.is_a? String
121
+ if raw_cookies.is_a? String
122
+ raw_cookies = raw_cookies.split("\n")
123
+ raw_cookies.reject!{|c| c.empty? }
124
+ end
125
+
122
126
  raw_cookies.each do |raw_cookie|
123
127
  cookie = Cookie.new(raw_cookie, uri, @default_host)
124
128
  self << cookie if cookie.valid?(uri)
@@ -8,7 +8,10 @@ module Rack
8
8
  case value
9
9
  when Array
10
10
  value.map do |v|
11
- build_nested_query(v, "#{prefix}[]")
11
+ unless unescape(prefix) =~ /\[\]$/
12
+ prefix = "#{prefix}[]"
13
+ end
14
+ build_nested_query(v, "#{prefix}")
12
15
  end.join("&")
13
16
  when Hash
14
17
  value.map do |k, v|
@@ -51,11 +54,17 @@ module Rack
51
54
 
52
55
  case value
53
56
  when Array
54
- value.map { |v|
55
- build_multipart(v, false).each { |subkey, subvalue|
56
- flattened_params["#{k}[]#{subkey}"] = subvalue
57
- }
58
- }
57
+ value.map do |v|
58
+
59
+ if (v.is_a?(Hash))
60
+ build_multipart(v, false).each { |subkey, subvalue|
61
+ flattened_params["#{k}[]#{subkey}"] = subvalue
62
+ }
63
+ else
64
+ flattened_params["#{k}[]"] = value
65
+ end
66
+
67
+ end
59
68
  when Hash
60
69
  build_multipart(value, false).each { |subkey, subvalue|
61
70
  flattened_params[k + subkey] = subvalue
@@ -66,35 +75,55 @@ module Rack
66
75
  end
67
76
 
68
77
  if first
69
- flattened_params.map { |name, file|
70
- if file.respond_to?(:original_filename)
71
- ::File.open(file.path, "rb") do |f|
72
- f.set_encoding(Encoding::BINARY) if f.respond_to?(:set_encoding)
78
+ build_parts(flattened_params)
79
+ else
80
+ flattened_params
81
+ end
82
+ end
83
+
84
+ module_function :build_multipart
85
+
86
+ private
87
+ def build_parts(parameters)
88
+ parameters.map { |name, value|
89
+ if value.respond_to?(:original_filename)
90
+ build_file_part(name, value)
91
+
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
96
+
97
+ else
98
+ build_primitive_part(name, value)
99
+ end
100
+
101
+ }.join + "--#{MULTIPART_BOUNDARY}--\r"
102
+ end
103
+
104
+ def build_primitive_part(parameter_name, value)
73
105
  <<-EOF
74
106
  --#{MULTIPART_BOUNDARY}\r
75
- Content-Disposition: form-data; name="#{name}"; filename="#{escape(file.original_filename)}"\r
76
- Content-Type: #{file.content_type}\r
77
- Content-Length: #{::File.stat(file.path).size}\r
107
+ Content-Disposition: form-data; name="#{parameter_name}"\r
78
108
  \r
79
- #{f.read}\r
109
+ #{value}\r
80
110
  EOF
81
- end
82
- else
111
+ end
112
+
113
+ def build_file_part(parameter_name, uploaded_file)
114
+ ::File.open(uploaded_file.path, "rb") do |physical_file|
115
+ physical_file.set_encoding(Encoding::BINARY) if physical_file.respond_to?(:set_encoding)
83
116
  <<-EOF
84
117
  --#{MULTIPART_BOUNDARY}\r
85
- Content-Disposition: form-data; name="#{name}"\r
118
+ Content-Disposition: form-data; name="#{parameter_name}"; filename="#{escape(uploaded_file.original_filename)}"\r
119
+ Content-Type: #{uploaded_file.content_type}\r
120
+ Content-Length: #{::File.stat(uploaded_file.path).size}\r
86
121
  \r
87
- #{file}\r
122
+ #{physical_file.read}\r
88
123
  EOF
89
- end
90
- }.join + "--#{MULTIPART_BOUNDARY}--\r"
91
- else
92
- flattened_params
93
124
  end
94
125
  end
95
126
 
96
- module_function :build_multipart
97
-
98
127
  end
99
128
 
100
129
  end
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{rack-test}
5
- s.version = "0.5.3"
5
+ s.version = "0.5.4"
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 = %q{2009-11-27}
9
+ s.date = %q{2010-05-26}
10
10
  s.description = %q{Rack::Test is a small, simple testing API for Rack apps. It can be used on its
11
11
  own or as a reusable starting point for Web frameworks and testing libraries
12
12
  to build on. Most of its initial functionality is an extraction of Merb 1.0's
@@ -32,6 +32,7 @@ request helpers feature.}
32
32
  "lib/rack/test/uploaded_file.rb",
33
33
  "lib/rack/test/utils.rb",
34
34
  "rack-test.gemspec",
35
+ "spec/fixtures/bar.txt",
35
36
  "spec/fixtures/config.ru",
36
37
  "spec/fixtures/fake_app.rb",
37
38
  "spec/fixtures/foo.txt",
@@ -46,7 +47,7 @@ request helpers feature.}
46
47
  s.homepage = %q{http://github.com/brynary/rack-test}
47
48
  s.require_paths = ["lib"]
48
49
  s.rubyforge_project = %q{rack-test}
49
- s.rubygems_version = %q{1.3.5}
50
+ s.rubygems_version = %q{1.3.7}
50
51
  s.summary = %q{Simple testing API built on Rack}
51
52
  s.test_files = [
52
53
  "spec/fixtures/fake_app.rb",
@@ -62,7 +63,7 @@ request helpers feature.}
62
63
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
63
64
  s.specification_version = 3
64
65
 
65
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
66
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
66
67
  s.add_runtime_dependency(%q<rack>, [">= 1.0"])
67
68
  else
68
69
  s.add_dependency(%q<rack>, [">= 1.0"])
@@ -0,0 +1 @@
1
+ baz
@@ -3,7 +3,7 @@ require "sinatra/base"
3
3
  module Rack
4
4
  module Test
5
5
 
6
- class FakeApp < Sinatra::Default
6
+ class FakeApp < Sinatra::Base
7
7
  head "/" do
8
8
  "meh"
9
9
  end
@@ -161,6 +161,12 @@ describe Rack::Test::Session do
161
161
  last_request.cookies.should == { "value" => "10", "foo" => "bar" }
162
162
  end
163
163
 
164
+ it "skips emtpy string cookies" do
165
+ set_cookie "value=10\n\nfoo=bar"
166
+ get "/cookies/show"
167
+ last_request.cookies.should == { "value" => "10", "foo" => "bar" }
168
+ end
169
+
164
170
  it "parses multiple cookies properly" do
165
171
  get "/cookies/set-multiple"
166
172
  get "/cookies/show"
@@ -6,10 +6,18 @@ describe Rack::Test::Session do
6
6
  File.dirname(__FILE__) + "/../../fixtures/foo.txt"
7
7
  end
8
8
 
9
+ def second_test_file_path
10
+ File.dirname(__FILE__) + "/../../fixtures/bar.txt"
11
+ end
12
+
9
13
  def uploaded_file
10
14
  Rack::Test::UploadedFile.new(test_file_path)
11
15
  end
12
16
 
17
+ def second_uploaded_file
18
+ Rack::Test::UploadedFile.new(second_test_file_path)
19
+ end
20
+
13
21
  context "uploading a file" do
14
22
  it "sends the multipart/form-data content type" do
15
23
  post "/", "photo" => uploaded_file
@@ -84,4 +92,43 @@ describe Rack::Test::Session do
84
92
  end
85
93
  end
86
94
 
95
+
96
+ context "uploading two files" do
97
+ it "sends the multipart/form-data content type" do
98
+ post "/", "photos" => [uploaded_file, second_uploaded_file]
99
+ last_request.env["CONTENT_TYPE"].should include("multipart/form-data;")
100
+ end
101
+
102
+ it "sends files with the filename" do
103
+ post "/", "photos" => [uploaded_file, second_uploaded_file]
104
+ last_request.POST["photos"].collect{|photo| photo[:filename]}.should == ["foo.txt", "bar.txt"]
105
+ end
106
+
107
+ it "sends files with the text/plain MIME type by default" do
108
+ post "/", "photos" => [uploaded_file, second_uploaded_file]
109
+ last_request.POST["photos"].collect{|photo| photo[:type]}.should == ["text/plain", "text/plain"]
110
+ end
111
+
112
+ it "sends files with the right names" do
113
+ post "/", "photos" => [uploaded_file, second_uploaded_file]
114
+ last_request.POST["photos"].all?{|photo| photo[:name].should == "photos[]" }
115
+ end
116
+
117
+ it "allows mixed content types" do
118
+ image_file = Rack::Test::UploadedFile.new(test_file_path, "image/jpeg")
119
+
120
+ post "/", "photos" => [uploaded_file, image_file]
121
+ last_request.POST["photos"].collect{|photo| photo[:type]}.should == ["text/plain", "image/jpeg"]
122
+ end
123
+
124
+ it "sends files with a Content-Length in the header" do
125
+ post "/", "photos" => [uploaded_file, second_uploaded_file]
126
+ last_request.POST["photos"].all?{|photo| photo[:head].should include("Content-Length: 4") }
127
+ end
128
+
129
+ it "sends both files as Tempfiles" do
130
+ post "/", "photos" => [uploaded_file, second_uploaded_file]
131
+ last_request.POST["photos"].all?{|photo| photo[:tempfile].should be_a(::Tempfile) }
132
+ end
133
+ end
87
134
  end
@@ -33,6 +33,10 @@ describe Rack::Test::Utils do
33
33
  build_nested_query(:a => [1, 2]).should == "a[]=1&a[]=2"
34
34
  end
35
35
 
36
+ it "converts arrays with brackets '[]' in the name" do
37
+ build_nested_query("a[]" => [1, 2]).should == "a%5B%5D=1&a%5B%5D=2"
38
+ end
39
+
36
40
  it "converts nested hashes" do
37
41
  build_nested_query(:a => { :b => 1 }).should == "a[b]=1"
38
42
  end
@@ -63,6 +67,26 @@ describe Rack::Test::Utils do
63
67
  params["files"][:tempfile].read.should == "bar\n"
64
68
  end
65
69
 
70
+ it "builds multipart bodies from array of files" do
71
+ files = [Rack::Test::UploadedFile.new(multipart_file("foo.txt")), Rack::Test::UploadedFile.new(multipart_file("bar.txt"))]
72
+ data = build_multipart("submit-name" => "Larry", "files" => files)
73
+
74
+ options = {
75
+ "CONTENT_TYPE" => "multipart/form-data; boundary=#{Rack::Test::MULTIPART_BOUNDARY}",
76
+ "CONTENT_LENGTH" => data.length.to_s,
77
+ :input => StringIO.new(data)
78
+ }
79
+ env = Rack::MockRequest.env_for("/", options)
80
+ params = Rack::Utils::Multipart.parse_multipart(env)
81
+ check params["submit-name"].should == "Larry"
82
+
83
+ check params["files"][0][:filename].should == "foo.txt"
84
+ params["files"][0][:tempfile].read.should == "bar\n"
85
+
86
+ check params["files"][1][:filename].should == "bar.txt"
87
+ params["files"][1][:tempfile].read.should == "baz\n"
88
+ end
89
+
66
90
  it "builds nested multipart bodies" do
67
91
  files = Rack::Test::UploadedFile.new(multipart_file("foo.txt"))
68
92
  data = build_multipart("people" => [{"submit-name" => "Larry", "files" => files}])
@@ -212,6 +212,13 @@ describe Rack::Test::Session do
212
212
  last_request.env["HTTP_USER_AGENT"].should == "Firefox"
213
213
  end
214
214
 
215
+ it "sets a Content-Type to be sent with requests" do
216
+ header "Content-Type", "application/json"
217
+ request "/"
218
+
219
+ last_request.env["CONTENT_TYPE"].should == "application/json"
220
+ end
221
+
215
222
  it "persists across multiple requests" do
216
223
  header "User-Agent", "Firefox"
217
224
  request "/"
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-test
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.3
4
+ hash: 3
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 5
9
+ - 4
10
+ version: 0.5.4
5
11
  platform: ruby
6
12
  authors:
7
13
  - Bryan Helmkamp
@@ -9,19 +15,24 @@ autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
17
 
12
- date: 2009-11-27 00:00:00 -05:00
18
+ date: 2010-05-26 00:00:00 -04:00
13
19
  default_executable:
14
20
  dependencies:
15
21
  - !ruby/object:Gem::Dependency
16
22
  name: rack
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
20
26
  requirements:
21
27
  - - ">="
22
28
  - !ruby/object:Gem::Version
29
+ hash: 15
30
+ segments:
31
+ - 1
32
+ - 0
23
33
  version: "1.0"
24
- version:
34
+ type: :runtime
35
+ version_requirements: *id001
25
36
  description: |-
26
37
  Rack::Test is a small, simple testing API for Rack apps. It can be used on its
27
38
  own or as a reusable starting point for Web frameworks and testing libraries
@@ -51,6 +62,7 @@ files:
51
62
  - lib/rack/test/uploaded_file.rb
52
63
  - lib/rack/test/utils.rb
53
64
  - rack-test.gemspec
65
+ - spec/fixtures/bar.txt
54
66
  - spec/fixtures/config.ru
55
67
  - spec/fixtures/fake_app.rb
56
68
  - spec/fixtures/foo.txt
@@ -71,21 +83,27 @@ rdoc_options: []
71
83
  require_paths:
72
84
  - lib
73
85
  required_ruby_version: !ruby/object:Gem::Requirement
86
+ none: false
74
87
  requirements:
75
88
  - - ">="
76
89
  - !ruby/object:Gem::Version
90
+ hash: 3
91
+ segments:
92
+ - 0
77
93
  version: "0"
78
- version:
79
94
  required_rubygems_version: !ruby/object:Gem::Requirement
95
+ none: false
80
96
  requirements:
81
97
  - - ">="
82
98
  - !ruby/object:Gem::Version
99
+ hash: 3
100
+ segments:
101
+ - 0
83
102
  version: "0"
84
- version:
85
103
  requirements: []
86
104
 
87
105
  rubyforge_project: rack-test
88
- rubygems_version: 1.3.5
106
+ rubygems_version: 1.3.7
89
107
  signing_key:
90
108
  specification_version: 3
91
109
  summary: Simple testing API built on Rack