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 +1 -0
- data/History.txt +9 -0
- data/lib/rack/test.rb +3 -2
- data/lib/rack/test/cookie_jar.rb +5 -1
- data/lib/rack/test/utils.rb +53 -24
- data/rack-test.gemspec +5 -4
- data/spec/fixtures/bar.txt +1 -0
- data/spec/fixtures/fake_app.rb +1 -1
- data/spec/rack/test/cookie_spec.rb +6 -0
- data/spec/rack/test/multipart_spec.rb +47 -0
- data/spec/rack/test/utils_spec.rb +24 -0
- data/spec/rack/test_spec.rb +7 -0
- metadata +27 -9
data/.gitignore
CHANGED
data/History.txt
CHANGED
@@ -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
|
data/lib/rack/test.rb
CHANGED
@@ -9,7 +9,7 @@ require "rack/test/uploaded_file"
|
|
9
9
|
|
10
10
|
module Rack
|
11
11
|
module Test
|
12
|
-
VERSION = "0.5.
|
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 =
|
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
|
|
data/lib/rack/test/cookie_jar.rb
CHANGED
@@ -118,7 +118,11 @@ module Rack
|
|
118
118
|
def merge(raw_cookies, uri = nil)
|
119
119
|
return unless raw_cookies
|
120
120
|
|
121
|
-
|
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)
|
data/lib/rack/test/utils.rb
CHANGED
@@ -8,7 +8,10 @@ module Rack
|
|
8
8
|
case value
|
9
9
|
when Array
|
10
10
|
value.map do |v|
|
11
|
-
|
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
|
55
|
-
|
56
|
-
|
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
|
70
|
-
|
71
|
-
|
72
|
-
|
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="#{
|
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
|
-
#{
|
109
|
+
#{value}\r
|
80
110
|
EOF
|
81
|
-
|
82
|
-
|
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="#{
|
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
|
-
#{
|
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
|
data/rack-test.gemspec
CHANGED
@@ -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.
|
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{
|
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.
|
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::
|
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
|
data/spec/fixtures/fake_app.rb
CHANGED
@@ -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}])
|
data/spec/rack/test_spec.rb
CHANGED
@@ -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
|
-
|
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:
|
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
|
-
|
18
|
-
|
19
|
-
|
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
|
-
|
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.
|
106
|
+
rubygems_version: 1.3.7
|
89
107
|
signing_key:
|
90
108
|
specification_version: 3
|
91
109
|
summary: Simple testing API built on Rack
|