rack-test 0.5.3 → 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
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