josh-rack-test 0.4.1
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/.document +4 -0
- data/.gitignore +3 -0
- data/History.txt +75 -0
- data/MIT-LICENSE.txt +19 -0
- data/README.rdoc +57 -0
- data/Rakefile +53 -0
- data/lib/rack/mock_session.rb +57 -0
- data/lib/rack/test.rb +245 -0
- data/lib/rack/test/cookie_jar.rb +170 -0
- data/lib/rack/test/methods.rb +73 -0
- data/lib/rack/test/mock_digest_request.rb +27 -0
- data/lib/rack/test/uploaded_file.rb +36 -0
- data/lib/rack/test/utils.rb +99 -0
- data/rack-test.gemspec +70 -0
- data/spec/fixtures/config.ru +3 -0
- data/spec/fixtures/fake_app.rb +115 -0
- data/spec/fixtures/foo.txt +1 -0
- data/spec/rack/test/cookie_spec.rb +182 -0
- data/spec/rack/test/digest_auth_spec.rb +48 -0
- data/spec/rack/test/multipart_spec.rb +85 -0
- data/spec/rack/test/utils_spec.rb +93 -0
- data/spec/rack/test_spec.rb +368 -0
- data/spec/rcov.opts +1 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +48 -0
- metadata +84 -0
@@ -0,0 +1,115 @@
|
|
1
|
+
require "sinatra/base"
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
module Test
|
5
|
+
|
6
|
+
class FakeApp < Sinatra::Default
|
7
|
+
head "/" do
|
8
|
+
"meh"
|
9
|
+
end
|
10
|
+
|
11
|
+
get "/" do
|
12
|
+
"Hello, GET: #{params.inspect}"
|
13
|
+
end
|
14
|
+
|
15
|
+
get "/redirect" do
|
16
|
+
redirect "/redirected"
|
17
|
+
end
|
18
|
+
|
19
|
+
get "/redirected" do
|
20
|
+
"You've been redirected"
|
21
|
+
end
|
22
|
+
|
23
|
+
get "/void" do
|
24
|
+
[200, {}, ""]
|
25
|
+
end
|
26
|
+
|
27
|
+
get "/cookies/show" do
|
28
|
+
request.cookies.inspect
|
29
|
+
end
|
30
|
+
|
31
|
+
get "/COOKIES/show" do
|
32
|
+
request.cookies.inspect
|
33
|
+
end
|
34
|
+
|
35
|
+
get "/not-cookies/show" do
|
36
|
+
request.cookies.inspect
|
37
|
+
end
|
38
|
+
|
39
|
+
get "/cookies/set-secure" do
|
40
|
+
raise if params["value"].nil?
|
41
|
+
|
42
|
+
response.set_cookie("secure-cookie", :value => params["value"], :secure => true)
|
43
|
+
"Set"
|
44
|
+
end
|
45
|
+
|
46
|
+
get "/cookies/set-simple" do
|
47
|
+
raise if params["value"].nil?
|
48
|
+
|
49
|
+
response.set_cookie "simple", params["value"]
|
50
|
+
"Set"
|
51
|
+
end
|
52
|
+
|
53
|
+
get "/cookies/delete" do
|
54
|
+
response.delete_cookie "value"
|
55
|
+
end
|
56
|
+
|
57
|
+
get "/cookies/count" do
|
58
|
+
old_value = request.cookies["count"].to_i || 0
|
59
|
+
new_value = (old_value + 1).to_s
|
60
|
+
|
61
|
+
response.set_cookie("count", :value => new_value)
|
62
|
+
new_value
|
63
|
+
end
|
64
|
+
|
65
|
+
get "/cookies/set" do
|
66
|
+
raise if params["value"].nil?
|
67
|
+
|
68
|
+
response.set_cookie("value", {
|
69
|
+
:value => params["value"],
|
70
|
+
:path => "/cookies",
|
71
|
+
:expires => Time.now + 10
|
72
|
+
})
|
73
|
+
"Set"
|
74
|
+
end
|
75
|
+
|
76
|
+
get "/cookies/domain" do
|
77
|
+
old_value = request.cookies["count"].to_i || 0
|
78
|
+
new_value = (old_value + 1).to_s
|
79
|
+
|
80
|
+
response.set_cookie("count", :value => new_value, :domain => "localhost.com")
|
81
|
+
new_value
|
82
|
+
end
|
83
|
+
|
84
|
+
get "/cookies/set-uppercase" do
|
85
|
+
raise if params["value"].nil?
|
86
|
+
|
87
|
+
response.set_cookie("VALUE", {
|
88
|
+
:value => params["value"],
|
89
|
+
:path => "/cookies",
|
90
|
+
:expires => Time.now + 10
|
91
|
+
})
|
92
|
+
"Set"
|
93
|
+
end
|
94
|
+
|
95
|
+
get "/cookies/set-multiple" do
|
96
|
+
response.set_cookie("key1", :value => "value1")
|
97
|
+
response.set_cookie("key2", :value => "value2")
|
98
|
+
"Set"
|
99
|
+
end
|
100
|
+
|
101
|
+
post "/" do
|
102
|
+
"Hello, POST: #{params.inspect}"
|
103
|
+
end
|
104
|
+
|
105
|
+
put "/" do
|
106
|
+
"Hello, PUT: #{params.inspect}"
|
107
|
+
end
|
108
|
+
|
109
|
+
delete "/" do
|
110
|
+
"Hello, DELETE: #{params.inspect}"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
bar
|
@@ -0,0 +1,182 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Rack::Test::Session do
|
4
|
+
def have_body(string)
|
5
|
+
simple_matcher "have body #{string.inspect}" do |response|
|
6
|
+
response.body.should == string
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
context "cookies" do
|
11
|
+
it "keeps a cookie jar" do
|
12
|
+
get "/cookies/show"
|
13
|
+
last_request.cookies.should == {}
|
14
|
+
|
15
|
+
get "/cookies/set", "value" => "1"
|
16
|
+
get "/cookies/show"
|
17
|
+
last_request.cookies.should == { "value" => "1" }
|
18
|
+
end
|
19
|
+
|
20
|
+
it "doesn't send expired cookies" do
|
21
|
+
get "/cookies/set", "value" => "1"
|
22
|
+
now = Time.now
|
23
|
+
Time.stub!(:now => now + 60)
|
24
|
+
get "/cookies/show"
|
25
|
+
last_request.cookies.should == {}
|
26
|
+
end
|
27
|
+
|
28
|
+
it "doesn't send cookies with the wrong domain" do
|
29
|
+
get "http://www.example.com/cookies/set", "value" => "1"
|
30
|
+
get "http://www.other.example/cookies/show"
|
31
|
+
last_request.cookies.should == {}
|
32
|
+
end
|
33
|
+
|
34
|
+
it "doesn't send cookies with the wrong path" do
|
35
|
+
get "/cookies/set", "value" => "1"
|
36
|
+
get "/not-cookies/show"
|
37
|
+
last_request.cookies.should == {}
|
38
|
+
end
|
39
|
+
|
40
|
+
it "persists cookies across requests that don't return any cookie headers" do
|
41
|
+
get "/cookies/set", "value" => "1"
|
42
|
+
get "/void"
|
43
|
+
get "/cookies/show"
|
44
|
+
last_request.cookies.should == { "value" => "1" }
|
45
|
+
end
|
46
|
+
|
47
|
+
it "deletes cookies" do
|
48
|
+
get "/cookies/set", "value" => "1"
|
49
|
+
get "/cookies/delete"
|
50
|
+
get "/cookies/show"
|
51
|
+
last_request.cookies.should == { }
|
52
|
+
end
|
53
|
+
|
54
|
+
xit "respects cookie domains when no domain is explicitly set" do
|
55
|
+
request("http://example.org/cookies/count").should have_body("1")
|
56
|
+
request("http://www.example.org/cookies/count").should have_body("1")
|
57
|
+
request("http://example.org/cookies/count").should have_body("2")
|
58
|
+
request("http://www.example.org/cookies/count").should have_body("2")
|
59
|
+
end
|
60
|
+
|
61
|
+
it "treats domains case insensitively" do
|
62
|
+
get "http://example.com/cookies/set", "value" => "1"
|
63
|
+
get "http://EXAMPLE.COM/cookies/show"
|
64
|
+
last_request.cookies.should == { "value" => "1" }
|
65
|
+
end
|
66
|
+
|
67
|
+
it "treats paths case sensitively" do
|
68
|
+
get "/cookies/set", "value" => "1"
|
69
|
+
get "/COOKIES/show"
|
70
|
+
last_request.cookies.should == {}
|
71
|
+
end
|
72
|
+
|
73
|
+
it "prefers more specific cookies" do
|
74
|
+
get "http://example.com/cookies/set", "value" => "domain"
|
75
|
+
get "http://sub.example.com/cookies/set", "value" => "sub"
|
76
|
+
|
77
|
+
get "http://sub.example.com/cookies/show"
|
78
|
+
last_request.cookies.should == { "value" => "sub" }
|
79
|
+
|
80
|
+
get "http://example.com/cookies/show"
|
81
|
+
last_request.cookies.should == { "value" => "domain" }
|
82
|
+
end
|
83
|
+
|
84
|
+
it "treats cookie names case insensitively" do
|
85
|
+
get "/cookies/set", "value" => "lowercase"
|
86
|
+
get "/cookies/set-uppercase", "value" => "UPPERCASE"
|
87
|
+
get "/cookies/show"
|
88
|
+
last_request.cookies.should == { "VALUE" => "UPPERCASE" }
|
89
|
+
end
|
90
|
+
|
91
|
+
it "defaults the domain to the request domain" do
|
92
|
+
get "http://example.com/cookies/set-simple", "value" => "cookie"
|
93
|
+
get "http://example.com/cookies/show"
|
94
|
+
last_request.cookies.should == { "simple" => "cookie" }
|
95
|
+
|
96
|
+
get "http://other.example/cookies/show"
|
97
|
+
last_request.cookies.should == {}
|
98
|
+
end
|
99
|
+
|
100
|
+
it "defaults the domain to the request path up to the last slash" do
|
101
|
+
get "/cookies/set-simple", "value" => "1"
|
102
|
+
get "/not-cookies/show"
|
103
|
+
last_request.cookies.should == {}
|
104
|
+
end
|
105
|
+
|
106
|
+
it "supports secure cookies" do
|
107
|
+
get "https://example.com/cookies/set-secure", "value" => "set"
|
108
|
+
get "http://example.com/cookies/show"
|
109
|
+
last_request.cookies.should == {}
|
110
|
+
|
111
|
+
get "https://example.com/cookies/show"
|
112
|
+
last_request.cookies.should == { "secure-cookie" => "set" }
|
113
|
+
end
|
114
|
+
|
115
|
+
it "keeps separate cookie jars for different domains" do
|
116
|
+
get "http://example.com/cookies/set", "value" => "example"
|
117
|
+
get "http://example.com/cookies/show"
|
118
|
+
last_request.cookies.should == { "value" => "example" }
|
119
|
+
|
120
|
+
get "http://other.example/cookies/set", "value" => "other"
|
121
|
+
get "http://other.example/cookies/show"
|
122
|
+
last_request.cookies.should == { "value" => "other" }
|
123
|
+
|
124
|
+
get "http://example.com/cookies/show"
|
125
|
+
last_request.cookies.should == { "value" => "example" }
|
126
|
+
end
|
127
|
+
|
128
|
+
it "allows cookies to be cleared" do
|
129
|
+
get "/cookies/set", "value" => "1"
|
130
|
+
clear_cookies
|
131
|
+
get "/cookies/show"
|
132
|
+
last_request.cookies.should == {}
|
133
|
+
end
|
134
|
+
|
135
|
+
it "allow cookies to be set" do
|
136
|
+
set_cookie "value=10"
|
137
|
+
get "/cookies/show"
|
138
|
+
last_request.cookies.should == { "value" => "10" }
|
139
|
+
end
|
140
|
+
|
141
|
+
it "allows an array of cookies to be set" do
|
142
|
+
set_cookie ["value=10", "foo=bar"]
|
143
|
+
get "/cookies/show"
|
144
|
+
last_request.cookies.should == { "value" => "10", "foo" => "bar" }
|
145
|
+
end
|
146
|
+
|
147
|
+
it "parses multiple cookies properly" do
|
148
|
+
get "/cookies/set-multiple"
|
149
|
+
get "/cookies/show"
|
150
|
+
last_request.cookies.should == { "key1" => "value1", "key2" => "value2" }
|
151
|
+
end
|
152
|
+
|
153
|
+
it "supports multiple sessions" do
|
154
|
+
with_session(:first) do
|
155
|
+
get "/cookies/set", "value" => "1"
|
156
|
+
get "/cookies/show"
|
157
|
+
last_request.cookies.should == { "value" => "1" }
|
158
|
+
end
|
159
|
+
|
160
|
+
with_session(:second) do
|
161
|
+
get "/cookies/show"
|
162
|
+
last_request.cookies.should == { }
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
it "uses :default as the default session name" do
|
167
|
+
get "/cookies/set", "value" => "1"
|
168
|
+
get "/cookies/show"
|
169
|
+
last_request.cookies.should == { "value" => "1" }
|
170
|
+
|
171
|
+
with_session(:default) do
|
172
|
+
get "/cookies/show"
|
173
|
+
last_request.cookies.should == { "value" => "1" }
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
it "accepts explicitly provided cookies" do
|
178
|
+
request "/cookies/show", :cookie => "value=1"
|
179
|
+
last_request.cookies.should == { "value" => "1" }
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Rack::Test::Session do
|
4
|
+
context "HTTP Digest authentication" do
|
5
|
+
|
6
|
+
def app
|
7
|
+
app = Rack::Auth::Digest::MD5.new(Rack::Test::FakeApp.new) do |username|
|
8
|
+
{ 'alice' => 'correct-password' }[username]
|
9
|
+
end
|
10
|
+
app.realm = 'WallysWorld'
|
11
|
+
app.opaque = 'this-should-be-secret'
|
12
|
+
app
|
13
|
+
end
|
14
|
+
|
15
|
+
def be_challenge
|
16
|
+
simple_matcher "a HTTP Digest challenge response" do |response|
|
17
|
+
response.status == 401 &&
|
18
|
+
response['WWW-Authenticate'] =~ /^Digest / &&
|
19
|
+
response.body.empty?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'incorrectly authenticates GETs' do
|
24
|
+
digest_authorize 'foo', 'bar'
|
25
|
+
get '/'
|
26
|
+
last_response.should be_challenge
|
27
|
+
end
|
28
|
+
|
29
|
+
it "correctly authenticates GETs" do
|
30
|
+
digest_authorize "alice", "correct-password"
|
31
|
+
response = get "/"
|
32
|
+
response.should be_ok
|
33
|
+
end
|
34
|
+
|
35
|
+
it "correctly authenticates POSTs" do
|
36
|
+
digest_authorize "alice", "correct-password"
|
37
|
+
response = post "/"
|
38
|
+
response.should be_ok
|
39
|
+
end
|
40
|
+
|
41
|
+
it "returns a re-challenge if authenticating incorrectly" do
|
42
|
+
digest_authorize "alice", "incorrect-password"
|
43
|
+
response = get "/"
|
44
|
+
response.should be_challenge
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Rack::Test::Session do
|
4
|
+
|
5
|
+
def test_file_path
|
6
|
+
File.dirname(__FILE__) + "/../../fixtures/foo.txt"
|
7
|
+
end
|
8
|
+
|
9
|
+
def uploaded_file
|
10
|
+
Rack::Test::UploadedFile.new(test_file_path)
|
11
|
+
end
|
12
|
+
|
13
|
+
context "uploading a file" do
|
14
|
+
it "sends the multipart/form-data content type" do
|
15
|
+
post "/", "photo" => uploaded_file
|
16
|
+
last_request.env["CONTENT_TYPE"].should include("multipart/form-data;")
|
17
|
+
end
|
18
|
+
|
19
|
+
it "sends regular params" do
|
20
|
+
post "/", "photo" => uploaded_file, "foo" => "bar"
|
21
|
+
last_request.POST["foo"].should == "bar"
|
22
|
+
end
|
23
|
+
|
24
|
+
it "sends nested params" do
|
25
|
+
post "/", "photo" => uploaded_file, "foo" => {"bar" => "baz"}
|
26
|
+
last_request.POST["foo"]["bar"].should == "baz"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "sends multiple nested params" do
|
30
|
+
post "/", "photo" => uploaded_file, "foo" => {"bar" => {"baz" => "bop"}}
|
31
|
+
last_request.POST["foo"]["bar"]["baz"].should == "bop"
|
32
|
+
end
|
33
|
+
|
34
|
+
xit "sends params with arrays" do
|
35
|
+
post "/", "photo" => uploaded_file, "foo" => ["1", "2"]
|
36
|
+
last_request.POST["foo[]"].should == ["1", "2"]
|
37
|
+
end
|
38
|
+
|
39
|
+
it "sends params with encoding sensitive values" do
|
40
|
+
post "/", "photo" => uploaded_file, "foo" => "bar? baz"
|
41
|
+
last_request.POST["foo"].should == "bar? baz"
|
42
|
+
end
|
43
|
+
|
44
|
+
it "sends params with parens in names" do
|
45
|
+
post "/", "photo" => uploaded_file, "foo(1i)" => "bar"
|
46
|
+
last_request.POST["foo(1i)"].should == "bar"
|
47
|
+
end
|
48
|
+
|
49
|
+
it "sends params with encoding sensitive names" do
|
50
|
+
post "/", "photo" => uploaded_file, "foo bar" => "baz"
|
51
|
+
last_request.POST["foo bar"].should == "baz"
|
52
|
+
end
|
53
|
+
|
54
|
+
it "sends files with the filename" do
|
55
|
+
post "/", "photo" => uploaded_file
|
56
|
+
last_request.POST["photo"][:filename].should == "foo.txt"
|
57
|
+
end
|
58
|
+
|
59
|
+
it "sends files with the text/plain MIME type by default" do
|
60
|
+
post "/", "photo" => uploaded_file
|
61
|
+
last_request.POST["photo"][:type].should == "text/plain"
|
62
|
+
end
|
63
|
+
|
64
|
+
it "sends files with the right name" do
|
65
|
+
post "/", "photo" => uploaded_file
|
66
|
+
last_request.POST["photo"][:name].should == "photo"
|
67
|
+
end
|
68
|
+
|
69
|
+
it "allows overriding the content type" do
|
70
|
+
post "/", "photo" => Rack::Test::UploadedFile.new(test_file_path, "image/jpeg")
|
71
|
+
last_request.POST["photo"][:type].should == "image/jpeg"
|
72
|
+
end
|
73
|
+
|
74
|
+
it "sends files with a Content-Length in the header" do
|
75
|
+
post "/", "photo" => uploaded_file
|
76
|
+
last_request.POST["photo"][:head].should include("Content-Length: 4")
|
77
|
+
end
|
78
|
+
|
79
|
+
it "sends files as Tempfiles" do
|
80
|
+
post "/", "photo" => uploaded_file
|
81
|
+
last_request.POST["photo"][:tempfile].should be_a(::Tempfile)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Rack::Test::Utils do
|
4
|
+
include Rack::Test::Utils
|
5
|
+
|
6
|
+
describe "build_nested_query" do
|
7
|
+
it "converts empty strings to =" do
|
8
|
+
build_nested_query("").should == "="
|
9
|
+
end
|
10
|
+
|
11
|
+
it "converts nil to =" do
|
12
|
+
build_nested_query(nil).should == "="
|
13
|
+
end
|
14
|
+
|
15
|
+
it "converts hashes" do
|
16
|
+
build_nested_query(:a => 1).should == "a=1"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "converts hashes with multiple keys" do
|
20
|
+
hash = { :a => 1, :b => 2 }
|
21
|
+
["a=1&b=2", "b=2&a=1"].should include(build_nested_query(hash))
|
22
|
+
end
|
23
|
+
|
24
|
+
it "converts arrays with one element" do
|
25
|
+
build_nested_query(:a => [1]).should == "a[]=1"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "converts arrays with multiple elements" do
|
29
|
+
build_nested_query(:a => [1, 2]).should == "a[]=1&a[]=2"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "converts nested hashes" do
|
33
|
+
build_nested_query(:a => { :b => 1 }).should == "a[b]=1"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "converts arrays nested in a hash" do
|
37
|
+
build_nested_query(:a => { :b => [1, 2] }).should == "a[b][]=1&a[b][]=2"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "converts arrays of hashes" do
|
41
|
+
build_nested_query(:a => [{ :b => 2}, { :c => 3}]).should == "a[][b]=2&a[][c]=3"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "build_multipart" do
|
46
|
+
it "builds multipart bodies" do
|
47
|
+
files = Rack::Test::UploadedFile.new(multipart_file("foo.txt"))
|
48
|
+
data = build_multipart("submit-name" => "Larry", "files" => files)
|
49
|
+
|
50
|
+
options = {
|
51
|
+
"CONTENT_TYPE" => "multipart/form-data; boundary=#{Rack::Test::MULTIPART_BOUNDARY}",
|
52
|
+
"CONTENT_LENGTH" => data.length.to_s,
|
53
|
+
:input => StringIO.new(data)
|
54
|
+
}
|
55
|
+
env = Rack::MockRequest.env_for("/", options)
|
56
|
+
params = Rack::Utils::Multipart.parse_multipart(env)
|
57
|
+
params["submit-name"].should == "Larry"
|
58
|
+
params["files"][:filename].should == "foo.txt"
|
59
|
+
params["files"][:tempfile].read.should == "bar\n"
|
60
|
+
end
|
61
|
+
|
62
|
+
it "builds nested multipart bodies" do
|
63
|
+
files = Rack::Test::UploadedFile.new(multipart_file("foo.txt"))
|
64
|
+
data = build_multipart("people" => [{"submit-name" => "Larry", "files" => files}])
|
65
|
+
|
66
|
+
options = {
|
67
|
+
"CONTENT_TYPE" => "multipart/form-data; boundary=#{Rack::Test::MULTIPART_BOUNDARY}",
|
68
|
+
"CONTENT_LENGTH" => data.length.to_s,
|
69
|
+
:input => StringIO.new(data)
|
70
|
+
}
|
71
|
+
env = Rack::MockRequest.env_for("/", options)
|
72
|
+
params = Rack::Utils::Multipart.parse_multipart(env)
|
73
|
+
params["people"][0]["submit-name"].should == "Larry"
|
74
|
+
params["people"][0]["files"][:filename].should == "foo.txt"
|
75
|
+
params["people"][0]["files"][:tempfile].read.should == "bar\n"
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should return nil if no UploadedFiles were used" do
|
79
|
+
data = build_multipart("people" => [{"submit-name" => "Larry", "files" => "contents"}])
|
80
|
+
data.should be_nil
|
81
|
+
end
|
82
|
+
|
83
|
+
it "raises ArgumentErrors if params is not a Hash" do
|
84
|
+
lambda {
|
85
|
+
build_multipart("foo=bar")
|
86
|
+
}.should raise_error(ArgumentError, "value must be a Hash")
|
87
|
+
end
|
88
|
+
|
89
|
+
def multipart_file(name)
|
90
|
+
File.join(File.dirname(__FILE__), "..", "..", "fixtures", name.to_s)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|