joebadmo-rack-test 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ bar
@@ -0,0 +1,211 @@
1
+ require "spec_helper"
2
+
3
+ describe Rack::Test::Session do
4
+
5
+ context "cookies" do
6
+ it "keeps a cookie jar" do
7
+ get "/cookies/show"
8
+ check last_request.cookies.should == {}
9
+
10
+ get "/cookies/set", "value" => "1"
11
+ get "/cookies/show"
12
+ last_request.cookies.should == { "value" => "1" }
13
+ end
14
+
15
+ it "doesn't send expired cookies" do
16
+ get "/cookies/set", "value" => "1"
17
+ now = Time.now
18
+ Time.stub!(:now => now + 60)
19
+ get "/cookies/show"
20
+ last_request.cookies.should == {}
21
+ end
22
+
23
+ it "cookie path defaults to the uri of the document that was requested" do
24
+ pending "See issue rack-test github issue #50" do
25
+ post "/cookies/default-path", "value" => "cookie"
26
+ get "/cookies/default-path"
27
+ check last_request.cookies.should == { "simple"=>"cookie" }
28
+ get "/cookies/show"
29
+ check last_request.cookies.should == { }
30
+ end
31
+ end
32
+
33
+ it "escapes cookie values" do
34
+ jar = Rack::Test::CookieJar.new
35
+ jar["value"] = "foo;abc"
36
+ jar["value"].should == "foo;abc"
37
+ end
38
+
39
+ it "doesn't send cookies with the wrong domain" do
40
+ get "http://www.example.com/cookies/set", "value" => "1"
41
+ get "http://www.other.example/cookies/show"
42
+ last_request.cookies.should == {}
43
+ end
44
+
45
+ it "doesn't send cookies with the wrong path" do
46
+ get "/cookies/set", "value" => "1"
47
+ get "/not-cookies/show"
48
+ last_request.cookies.should == {}
49
+ end
50
+
51
+ it "persists cookies across requests that don't return any cookie headers" do
52
+ get "/cookies/set", "value" => "1"
53
+ get "/void"
54
+ get "/cookies/show"
55
+ last_request.cookies.should == { "value" => "1" }
56
+ end
57
+
58
+ it "deletes cookies" do
59
+ get "/cookies/set", "value" => "1"
60
+ get "/cookies/delete"
61
+ get "/cookies/show"
62
+ last_request.cookies.should == { }
63
+ end
64
+
65
+ it "respects cookie domains when no domain is explicitly set" do
66
+ pending "FIXME: www.example.org should not get the first cookie" do
67
+ request("http://example.org/cookies/count").should have_body("1")
68
+ request("http://www.example.org/cookies/count").should have_body("1")
69
+ request("http://example.org/cookies/count").should have_body("2")
70
+ request("http://www.example.org/cookies/count").should have_body("2")
71
+ end
72
+ end
73
+
74
+ it "treats domains case insensitively" do
75
+ get "http://example.com/cookies/set", "value" => "1"
76
+ get "http://EXAMPLE.COM/cookies/show"
77
+ last_request.cookies.should == { "value" => "1" }
78
+ end
79
+
80
+ it "treats paths case sensitively" do
81
+ get "/cookies/set", "value" => "1"
82
+ get "/COOKIES/show"
83
+ last_request.cookies.should == {}
84
+ end
85
+
86
+ it "prefers more specific cookies" do
87
+ get "http://example.com/cookies/set", "value" => "domain"
88
+ get "http://sub.example.com/cookies/set", "value" => "sub"
89
+
90
+ get "http://sub.example.com/cookies/show"
91
+ check last_request.cookies.should == { "value" => "sub" }
92
+
93
+ get "http://example.com/cookies/show"
94
+ last_request.cookies.should == { "value" => "domain" }
95
+ end
96
+
97
+ it "treats cookie names case insensitively" do
98
+ get "/cookies/set", "value" => "lowercase"
99
+ get "/cookies/set-uppercase", "value" => "UPPERCASE"
100
+ get "/cookies/show"
101
+ last_request.cookies.should == { "VALUE" => "UPPERCASE" }
102
+ end
103
+
104
+ it "defaults the domain to the request domain" do
105
+ get "http://example.com/cookies/set-simple", "value" => "cookie"
106
+ get "http://example.com/cookies/show"
107
+ check last_request.cookies.should == { "simple" => "cookie" }
108
+
109
+ get "http://other.example/cookies/show"
110
+ last_request.cookies.should == {}
111
+ end
112
+
113
+ it "defaults the domain to the request path up to the last slash" do
114
+ get "/cookies/set-simple", "value" => "1"
115
+ get "/not-cookies/show"
116
+ last_request.cookies.should == {}
117
+ end
118
+
119
+ it "supports secure cookies" do
120
+ get "https://example.com/cookies/set-secure", "value" => "set"
121
+ get "http://example.com/cookies/show"
122
+ check last_request.cookies.should == {}
123
+
124
+ get "https://example.com/cookies/show"
125
+ last_request.cookies.should == { "secure-cookie" => "set" }
126
+ rack_mock_session.cookie_jar['secure-cookie'].should == 'set'
127
+ end
128
+
129
+ it "keeps separate cookie jars for different domains" do
130
+ get "http://example.com/cookies/set", "value" => "example"
131
+ get "http://example.com/cookies/show"
132
+ check last_request.cookies.should == { "value" => "example" }
133
+
134
+ get "http://other.example/cookies/set", "value" => "other"
135
+ get "http://other.example/cookies/show"
136
+ check last_request.cookies.should == { "value" => "other" }
137
+
138
+ get "http://example.com/cookies/show"
139
+ last_request.cookies.should == { "value" => "example" }
140
+ end
141
+
142
+ it "keeps one cookie jar for domain and its subdomains" do
143
+ get "http://example.org/cookies/subdomain"
144
+ get "http://example.org/cookies/subdomain"
145
+ last_request.cookies.should == { "count" => "1" }
146
+
147
+ get "http://foo.example.org/cookies/subdomain"
148
+ last_request.cookies.should == { "count" => "2" }
149
+ end
150
+
151
+ it "allows cookies to be cleared" do
152
+ get "/cookies/set", "value" => "1"
153
+ clear_cookies
154
+ get "/cookies/show"
155
+ last_request.cookies.should == {}
156
+ end
157
+
158
+ it "allow cookies to be set" do
159
+ set_cookie "value=10"
160
+ get "/cookies/show"
161
+ last_request.cookies.should == { "value" => "10" }
162
+ end
163
+
164
+ it "allows an array of cookies to be set" do
165
+ set_cookie ["value=10", "foo=bar"]
166
+ get "/cookies/show"
167
+ last_request.cookies.should == { "value" => "10", "foo" => "bar" }
168
+ end
169
+
170
+ it "skips emtpy string cookies" do
171
+ set_cookie "value=10\n\nfoo=bar"
172
+ get "/cookies/show"
173
+ last_request.cookies.should == { "value" => "10", "foo" => "bar" }
174
+ end
175
+
176
+ it "parses multiple cookies properly" do
177
+ get "/cookies/set-multiple"
178
+ get "/cookies/show"
179
+ last_request.cookies.should == { "key1" => "value1", "key2" => "value2" }
180
+ end
181
+
182
+ it "supports multiple sessions" do
183
+ with_session(:first) do
184
+ get "/cookies/set", "value" => "1"
185
+ get "/cookies/show"
186
+ last_request.cookies.should == { "value" => "1" }
187
+ end
188
+
189
+ with_session(:second) do
190
+ get "/cookies/show"
191
+ last_request.cookies.should == { }
192
+ end
193
+ end
194
+
195
+ it "uses :default as the default session name" do
196
+ get "/cookies/set", "value" => "1"
197
+ get "/cookies/show"
198
+ check last_request.cookies.should == { "value" => "1" }
199
+
200
+ with_session(:default) do
201
+ get "/cookies/show"
202
+ last_request.cookies.should == { "value" => "1" }
203
+ end
204
+ end
205
+
206
+ it "accepts explicitly provided cookies" do
207
+ request "/cookies/show", :cookie => "value=1"
208
+ last_request.cookies.should == { "value" => "1" }
209
+ end
210
+ end
211
+ end
@@ -0,0 +1,46 @@
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
+ it 'incorrectly authenticates GETs' do
16
+ digest_authorize 'foo', 'bar'
17
+ get '/'
18
+ last_response.should be_challenge
19
+ end
20
+
21
+ it "correctly authenticates GETs" do
22
+ digest_authorize "alice", "correct-password"
23
+ response = get "/"
24
+ response.should be_ok
25
+ end
26
+
27
+ it "correctly authenticates GETs with params" do
28
+ digest_authorize "alice", "correct-password"
29
+ response = get "/", "foo" => "bar"
30
+ response.should be_ok
31
+ end
32
+
33
+ it "correctly authenticates POSTs" do
34
+ digest_authorize "alice", "correct-password"
35
+ response = post "/"
36
+ response.should be_ok
37
+ end
38
+
39
+ it "returns a re-challenge if authenticating incorrectly" do
40
+ digest_authorize "alice", "incorrect-password"
41
+ response = get "/"
42
+ response.should be_challenge
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,145 @@
1
+ # encoding: UTF-8
2
+
3
+ require "spec_helper"
4
+
5
+ describe Rack::Test::Session do
6
+
7
+ def test_file_path
8
+ File.dirname(__FILE__) + "/../../fixtures/foo.txt"
9
+ end
10
+
11
+ def second_test_file_path
12
+ File.dirname(__FILE__) + "/../../fixtures/bar.txt"
13
+ end
14
+
15
+ def uploaded_file
16
+ Rack::Test::UploadedFile.new(test_file_path)
17
+ end
18
+
19
+ def second_uploaded_file
20
+ Rack::Test::UploadedFile.new(second_test_file_path)
21
+ end
22
+
23
+ context "uploading a file" do
24
+ it "sends the multipart/form-data content type" do
25
+ post "/", "photo" => uploaded_file
26
+ last_request.env["CONTENT_TYPE"].should include("multipart/form-data;")
27
+ end
28
+
29
+ it "sends regular params" do
30
+ post "/", "photo" => uploaded_file, "foo" => "bar"
31
+ last_request.POST["foo"].should == "bar"
32
+ end
33
+
34
+ it "sends nested params" do
35
+ post "/", "photo" => uploaded_file, "foo" => {"bar" => "baz"}
36
+ last_request.POST["foo"]["bar"].should == "baz"
37
+ end
38
+
39
+ it "sends multiple nested params" do
40
+ post "/", "photo" => uploaded_file, "foo" => {"bar" => {"baz" => "bop"}}
41
+ last_request.POST["foo"]["bar"]["baz"].should == "bop"
42
+ end
43
+
44
+ it "sends params with arrays" do
45
+ post "/", "photo" => uploaded_file, "foo" => ["1", "2"]
46
+ last_request.POST["foo"].should == ["1", "2"]
47
+ end
48
+
49
+ it "sends params with encoding sensitive values" do
50
+ post "/", "photo" => uploaded_file, "foo" => "bar? baz"
51
+ last_request.POST["foo"].should == "bar? baz"
52
+ end
53
+
54
+ it "sends params encoded as ISO-8859-1" do
55
+ post "/", "photo" => uploaded_file, "foo" => "bar", "utf8" => "☃"
56
+ last_request.POST["foo"].should == "bar"
57
+
58
+ if Rack::Test.encoding_aware_strings?
59
+ last_request.POST["utf8"].should == "☃"
60
+ else
61
+ last_request.POST["utf8"].should == "\xE2\x98\x83"
62
+ end
63
+ end
64
+
65
+ it "sends params with parens in names" do
66
+ post "/", "photo" => uploaded_file, "foo(1i)" => "bar"
67
+ last_request.POST["foo(1i)"].should == "bar"
68
+ end
69
+
70
+ it "sends params with encoding sensitive names" do
71
+ post "/", "photo" => uploaded_file, "foo bar" => "baz"
72
+ last_request.POST["foo bar"].should == "baz"
73
+ end
74
+
75
+ it "sends files with the filename" do
76
+ post "/", "photo" => uploaded_file
77
+ last_request.POST["photo"][:filename].should == "foo.txt"
78
+ end
79
+
80
+ it "sends files with the text/plain MIME type by default" do
81
+ post "/", "photo" => uploaded_file
82
+ last_request.POST["photo"][:type].should == "text/plain"
83
+ end
84
+
85
+ it "sends files with the right name" do
86
+ post "/", "photo" => uploaded_file
87
+ last_request.POST["photo"][:name].should == "photo"
88
+ end
89
+
90
+ it "allows overriding the content type" do
91
+ post "/", "photo" => Rack::Test::UploadedFile.new(test_file_path, "image/jpeg")
92
+ last_request.POST["photo"][:type].should == "image/jpeg"
93
+ end
94
+
95
+ it "sends files with a Content-Length in the header" do
96
+ post "/", "photo" => uploaded_file
97
+ last_request.POST["photo"][:head].should include("Content-Length: 4")
98
+ end
99
+
100
+ it "sends files as Tempfiles" do
101
+ post "/", "photo" => uploaded_file
102
+ last_request.POST["photo"][:tempfile].should be_a(::Tempfile)
103
+ end
104
+ end
105
+
106
+
107
+ context "uploading two files" do
108
+ it "sends the multipart/form-data content type" do
109
+ post "/", "photos" => [uploaded_file, second_uploaded_file]
110
+ last_request.env["CONTENT_TYPE"].should include("multipart/form-data;")
111
+ end
112
+
113
+ it "sends files with the filename" do
114
+ post "/", "photos" => [uploaded_file, second_uploaded_file]
115
+ last_request.POST["photos"].collect{|photo| photo[:filename]}.should == ["foo.txt", "bar.txt"]
116
+ end
117
+
118
+ it "sends files with the text/plain MIME type by default" do
119
+ post "/", "photos" => [uploaded_file, second_uploaded_file]
120
+ last_request.POST["photos"].collect{|photo| photo[:type]}.should == ["text/plain", "text/plain"]
121
+ end
122
+
123
+ it "sends files with the right names" do
124
+ post "/", "photos" => [uploaded_file, second_uploaded_file]
125
+ last_request.POST["photos"].all?{|photo| photo[:name].should == "photos[]" }
126
+ end
127
+
128
+ it "allows mixed content types" do
129
+ image_file = Rack::Test::UploadedFile.new(test_file_path, "image/jpeg")
130
+
131
+ post "/", "photos" => [uploaded_file, image_file]
132
+ last_request.POST["photos"].collect{|photo| photo[:type]}.should == ["text/plain", "image/jpeg"]
133
+ end
134
+
135
+ it "sends files with a Content-Length in the header" do
136
+ post "/", "photos" => [uploaded_file, second_uploaded_file]
137
+ last_request.POST["photos"].all?{|photo| photo[:head].should include("Content-Length: 4") }
138
+ end
139
+
140
+ it "sends both files as Tempfiles" do
141
+ post "/", "photos" => [uploaded_file, second_uploaded_file]
142
+ last_request.POST["photos"].all?{|photo| photo[:tempfile].should be_a(::Tempfile) }
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,22 @@
1
+ require "spec_helper"
2
+
3
+ describe Rack::Test::UploadedFile do
4
+ def test_file_path
5
+ File.dirname(__FILE__) + "/../../fixtures/foo.txt"
6
+ end
7
+
8
+ it "responds to things that Tempfile responds to" do
9
+ uploaded_file = Rack::Test::UploadedFile.new(test_file_path)
10
+
11
+ uploaded_file.should respond_to(:close)
12
+ uploaded_file.should respond_to(:close!)
13
+ uploaded_file.should respond_to(:delete)
14
+ uploaded_file.should respond_to(:length)
15
+ uploaded_file.should respond_to(:open)
16
+ uploaded_file.should respond_to(:path)
17
+ uploaded_file.should respond_to(:size)
18
+ uploaded_file.should respond_to(:unlink)
19
+ uploaded_file.should respond_to(:read)
20
+ end
21
+
22
+ end
@@ -0,0 +1,122 @@
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 an empty string" do
12
+ build_nested_query(nil).should == ""
13
+ end
14
+
15
+ it "converts hashes with nil values" do
16
+ build_nested_query(:a => nil).should == "a"
17
+ end
18
+
19
+ it "converts hashes" do
20
+ build_nested_query(:a => 1).should == "a=1"
21
+ end
22
+
23
+ it "converts hashes with multiple keys" do
24
+ hash = { :a => 1, :b => 2 }
25
+ ["a=1&b=2", "b=2&a=1"].should include(build_nested_query(hash))
26
+ end
27
+
28
+ it "converts arrays with one element" do
29
+ build_nested_query(:a => [1]).should == "a[]=1"
30
+ end
31
+
32
+ it "converts arrays with multiple elements" do
33
+ build_nested_query(:a => [1, 2]).should == "a[]=1&a[]=2"
34
+ end
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
+
40
+ it "converts nested hashes" do
41
+ build_nested_query(:a => { :b => 1 }).should == "a[b]=1"
42
+ end
43
+
44
+ it "converts arrays nested in a hash" do
45
+ build_nested_query(:a => { :b => [1, 2] }).should == "a[b][]=1&a[b][]=2"
46
+ end
47
+
48
+ it "converts arrays of hashes" do
49
+ build_nested_query(:a => [{ :b => 2}, { :c => 3}]).should == "a[][b]=2&a[][c]=3"
50
+ end
51
+ end
52
+
53
+ describe "build_multipart" do
54
+ it "builds multipart bodies" do
55
+ files = Rack::Test::UploadedFile.new(multipart_file("foo.txt"))
56
+ data = build_multipart("submit-name" => "Larry", "files" => files)
57
+
58
+ options = {
59
+ "CONTENT_TYPE" => "multipart/form-data; boundary=#{Rack::Test::MULTIPART_BOUNDARY}",
60
+ "CONTENT_LENGTH" => data.length.to_s,
61
+ :input => StringIO.new(data)
62
+ }
63
+ env = Rack::MockRequest.env_for("/", options)
64
+ params = Rack::Utils::Multipart.parse_multipart(env)
65
+ check params["submit-name"].should == "Larry"
66
+ check params["files"][:filename].should == "foo.txt"
67
+ params["files"][:tempfile].read.should == "bar\n"
68
+ end
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
+
90
+ it "builds nested multipart bodies" do
91
+ files = Rack::Test::UploadedFile.new(multipart_file("foo.txt"))
92
+ data = build_multipart("people" => [{"submit-name" => "Larry", "files" => files}], "foo" => ['1', '2'])
93
+
94
+ options = {
95
+ "CONTENT_TYPE" => "multipart/form-data; boundary=#{Rack::Test::MULTIPART_BOUNDARY}",
96
+ "CONTENT_LENGTH" => data.length.to_s,
97
+ :input => StringIO.new(data)
98
+ }
99
+ env = Rack::MockRequest.env_for("/", options)
100
+ params = Rack::Utils::Multipart.parse_multipart(env)
101
+ check params["people"][0]["submit-name"].should == "Larry"
102
+ check params["people"][0]["files"][:filename].should == "foo.txt"
103
+ params["people"][0]["files"][:tempfile].read.should == "bar\n"
104
+ check params["foo"].should == ["1", "2"]
105
+ end
106
+
107
+ it "returns nil if no UploadedFiles were used" do
108
+ data = build_multipart("people" => [{"submit-name" => "Larry", "files" => "contents"}])
109
+ data.should be_nil
110
+ end
111
+
112
+ it "raises ArgumentErrors if params is not a Hash" do
113
+ lambda {
114
+ build_multipart("foo=bar")
115
+ }.should raise_error(ArgumentError, "value must be a Hash")
116
+ end
117
+
118
+ def multipart_file(name)
119
+ File.join(File.dirname(__FILE__), "..", "..", "fixtures", name.to_s)
120
+ end
121
+ end
122
+ end