rack-contrib 0.9.0 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rack-contrib might be problematic. Click here for more details.

@@ -0,0 +1,66 @@
1
+ require 'test/spec'
2
+ require 'rack/mock'
3
+
4
+ begin
5
+ require 'csshttprequest'
6
+ require 'rack/contrib/csshttprequest'
7
+
8
+ context "Rack::CSSHTTPRequest" do
9
+
10
+ before(:each) do
11
+ @test_body = '{"bar":"foo"}'
12
+ @test_headers = {'Content-Type' => 'text/plain'}
13
+ @encoded_body = CSSHTTPRequest.encode(@test_body)
14
+ @app = lambda { |env| [200, @test_headers, [@test_body]] }
15
+ end
16
+
17
+ specify "env['csshttprequest.chr'] should be set to true when \
18
+ PATH_INFO ends with '.chr'" do
19
+ request = Rack::MockRequest.env_for("/blah.chr", :lint => true, :fatal => true)
20
+ Rack::CSSHTTPRequest.new(@app).call(request)
21
+ request['csshttprequest.chr'].should.equal true
22
+ end
23
+
24
+ specify "env['csshttprequest.chr'] should be set to true when \
25
+ request parameter _format == 'chr'" do
26
+ request = Rack::MockRequest.env_for("/?_format=chr", :lint => true, :fatal => true)
27
+ Rack::CSSHTTPRequest.new(@app).call(request)
28
+ request['csshttprequest.chr'].should.equal true
29
+ end
30
+
31
+ specify "should not change the headers or response when !env['csshttprequest.chr']" do
32
+ request = Rack::MockRequest.env_for("/", :lint => true, :fatal => true)
33
+ status, headers, response = Rack::CSSHTTPRequest.new(@app).call(request)
34
+ headers.should.equal @test_headers
35
+ response.join.should.equal @test_body
36
+ end
37
+
38
+ context "when env['csshttprequest.chr']" do
39
+ before(:each) do
40
+ @request = Rack::MockRequest.env_for("/",
41
+ 'csshttprequest.chr' => true, :lint => true, :fatal => true)
42
+ end
43
+
44
+ specify "should modify the content length to the correct value" do
45
+ headers = Rack::CSSHTTPRequest.new(@app).call(@request)[1]
46
+ headers['Content-Length'].should.equal @encoded_body.length.to_s
47
+ end
48
+
49
+ specify "should modify the content type to the correct value" do
50
+ headers = Rack::CSSHTTPRequest.new(@app).call(@request)[1]
51
+ headers['Content-Type'].should.equal 'text/css'
52
+ end
53
+
54
+ specify "should not modify any other headers" do
55
+ headers = Rack::CSSHTTPRequest.new(@app).call(@request)[1]
56
+ headers.should.equal @test_headers.merge({
57
+ 'Content-Type' => 'text/css',
58
+ 'Content-Length' => @encoded_body.length.to_s
59
+ })
60
+ end
61
+ end
62
+
63
+ end
64
+ rescue LoadError => boom
65
+ STDERR.puts "WARN: Skipping Rack::CSSHTTPRequest tests (nbio-csshttprequest not installed)"
66
+ end
@@ -0,0 +1,107 @@
1
+ require 'test/spec'
2
+ require 'rack/mock'
3
+ require 'rack/contrib/deflect'
4
+
5
+ context "Rack::Deflect" do
6
+
7
+ setup do
8
+ @app = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, 'cookies'] }
9
+ @mock_addr_1 = '111.111.111.111'
10
+ @mock_addr_2 = '222.222.222.222'
11
+ @mock_addr_3 = '333.333.333.333'
12
+ end
13
+
14
+ def mock_env remote_addr, path = '/'
15
+ Rack::MockRequest.env_for path, { 'REMOTE_ADDR' => remote_addr }
16
+ end
17
+
18
+ def mock_deflect options = {}
19
+ Rack::Deflect.new @app, options
20
+ end
21
+
22
+ specify "should allow regular requests to follow through" do
23
+ app = mock_deflect
24
+ status, headers, body = app.call mock_env(@mock_addr_1)
25
+ status.should.equal 200
26
+ body.should.equal 'cookies'
27
+ end
28
+
29
+ specify "should deflect requests exceeding the request threshold" do
30
+ log = StringIO.new
31
+ app = mock_deflect :request_threshold => 5, :interval => 10, :block_duration => 10, :log => log
32
+ env = mock_env @mock_addr_1
33
+
34
+ # First 5 should be fine
35
+ 5.times do
36
+ status, headers, body = app.call env
37
+ status.should.equal 200
38
+ body.should.equal 'cookies'
39
+ end
40
+
41
+ # Remaining requests should fail for 10 seconds
42
+ 10.times do
43
+ status, headers, body = app.call env
44
+ status.should.equal 403
45
+ body.should.equal ''
46
+ end
47
+
48
+ # Log should reflect that we have blocked an address
49
+ log.string.should.match(/^deflect\(\d+\/\d+\/\d+\): blocked 111.111.111.111\n/)
50
+ end
51
+
52
+ specify "should expire blocking" do
53
+ log = StringIO.new
54
+ app = mock_deflect :request_threshold => 5, :interval => 2, :block_duration => 2, :log => log
55
+ env = mock_env @mock_addr_1
56
+
57
+ # First 5 should be fine
58
+ 5.times do
59
+ status, headers, body = app.call env
60
+ status.should.equal 200
61
+ body.should.equal 'cookies'
62
+ end
63
+
64
+ # Exceeds request threshold
65
+ status, headers, body = app.call env
66
+ status.should.equal 403
67
+ body.should.equal ''
68
+
69
+ # Allow block to expire
70
+ sleep 3
71
+
72
+ # Another 5 is fine now
73
+ 5.times do
74
+ status, headers, body = app.call env
75
+ status.should.equal 200
76
+ body.should.equal 'cookies'
77
+ end
78
+
79
+ # Log should reflect block and release
80
+ log.string.should.match(/deflect.*: blocked 111\.111\.111\.111\ndeflect.*: released 111\.111\.111\.111\n/)
81
+ end
82
+
83
+ specify "should allow whitelisting of remote addresses" do
84
+ app = mock_deflect :whitelist => [@mock_addr_1], :request_threshold => 5, :interval => 2
85
+ env = mock_env @mock_addr_1
86
+
87
+ # Whitelisted addresses are always fine
88
+ 10.times do
89
+ status, headers, body = app.call env
90
+ status.should.equal 200
91
+ body.should.equal 'cookies'
92
+ end
93
+ end
94
+
95
+ specify "should allow blacklisting of remote addresses" do
96
+ app = mock_deflect :blacklist => [@mock_addr_2]
97
+
98
+ status, headers, body = app.call mock_env(@mock_addr_1)
99
+ status.should.equal 200
100
+ body.should.equal 'cookies'
101
+
102
+ status, headers, body = app.call mock_env(@mock_addr_2)
103
+ status.should.equal 403
104
+ body.should.equal ''
105
+ end
106
+
107
+ end
@@ -3,19 +3,32 @@ require 'rack/mock'
3
3
  require 'rack/contrib/jsonp'
4
4
 
5
5
  context "Rack::JSONP" do
6
-
7
- specify "should wrap the response body in the Javascript callback when provided" do
8
- app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, '{"bar":"foo"}'] }
9
- request = Rack::MockRequest.env_for("/", :input => "foo=bar&callback=foo")
10
- body = Rack::JSONP.new(app).call(request).last
11
- body.should == 'foo({"bar":"foo"})'
6
+
7
+ context "when a callback parameter is provided" do
8
+ specify "should wrap the response body in the Javascript callback" do
9
+ test_body = '{"bar":"foo"}'
10
+ callback = 'foo'
11
+ app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, [test_body]] }
12
+ request = Rack::MockRequest.env_for("/", :input => "foo=bar&callback=#{callback}")
13
+ body = Rack::JSONP.new(app).call(request).last
14
+ body.join.should.equal "#{callback}(#{test_body})"
15
+ end
16
+
17
+ specify "should modify the content length to the correct value" do
18
+ test_body = '{"bar":"foo"}'
19
+ callback = 'foo'
20
+ app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, [test_body]] }
21
+ request = Rack::MockRequest.env_for("/", :input => "foo=bar&callback=#{callback}")
22
+ headers = Rack::JSONP.new(app).call(request)[1]
23
+ headers['Content-Length'].should.equal((test_body.length + callback.length + 2).to_s) # 2 parentheses
24
+ end
12
25
  end
13
-
14
- specify "should not change anything if no :callback param is provided" do
26
+
27
+ specify "should not change anything if no callback param is provided" do
15
28
  app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, '{"bar":"foo"}'] }
16
29
  request = Rack::MockRequest.env_for("/", :input => "foo=bar")
17
30
  body = Rack::JSONP.new(app).call(request).last
18
- body.should == '{"bar":"foo"}'
31
+ body.join.should.equal '{"bar":"foo"}'
19
32
  end
20
-
33
+
21
34
  end
@@ -8,7 +8,7 @@ context "Rack::LighttpdScriptNameFix" do
8
8
  "PATH_INFO" => "/foo/bar/baz",
9
9
  "SCRIPT_NAME" => "/hello"
10
10
  }
11
- app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
11
+ app = lambda { |_| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
12
12
  response = Rack::LighttpdScriptNameFix.new(app).call(env)
13
13
  env['SCRIPT_NAME'].should.be.empty
14
14
  env['PATH_INFO'].should.equal '/hello/foo/bar/baz'
@@ -0,0 +1,17 @@
1
+ require 'test/spec'
2
+ require 'rack/mock'
3
+ require 'rack/contrib/not_found'
4
+
5
+ context "Rack::NotFound" do
6
+
7
+ specify "should render the file at the given path for all requests" do
8
+ app = Rack::Builder.new do
9
+ use Rack::Lint
10
+ run Rack::NotFound.new('test/404.html')
11
+ end
12
+ response = Rack::MockRequest.new(app).get('/')
13
+ response.body.should.equal('Not Found')
14
+ response.status.should.equal(404)
15
+ end
16
+
17
+ end
@@ -3,9 +3,9 @@ require 'rack/mock'
3
3
 
4
4
  begin
5
5
  require 'rack/contrib/post_body_content_type_parser'
6
-
6
+
7
7
  context "Rack::PostBodyContentTypeParser" do
8
-
8
+
9
9
  specify "should handle requests with POST body Content-Type of application/json" do
10
10
  app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, Rack::Request.new(env).POST] }
11
11
  env = env_for_post_with_headers('/', {'Content_Type'.upcase => 'application/json'}, {:body => "asdf", :status => "12"}.to_json)
@@ -13,16 +13,16 @@ begin
13
13
  body['body'].should.equal "asdf"
14
14
  body['status'].should.equal "12"
15
15
  end
16
-
16
+
17
17
  specify "should change nothing when the POST body content type isn't application/json" do
18
18
  app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, Rack::Request.new(env).POST] }
19
19
  body = app.call(Rack::MockRequest.env_for("/", :input => "body=asdf&status=12")).last
20
20
  body['body'].should.equal "asdf"
21
21
  body['status'].should.equal "12"
22
22
  end
23
-
23
+
24
24
  end
25
-
25
+
26
26
  def env_for_post_with_headers(path, headers, body)
27
27
  Rack::MockRequest.env_for(path, {:method => "POST", :input => body}.merge(headers))
28
28
  end
@@ -1,32 +1,37 @@
1
1
  require 'test/spec'
2
2
  require 'rack/mock'
3
- require 'rack/contrib/profiler'
4
3
 
5
- context 'Rack::Profiler' do
6
-
7
- app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, 'Oh hai der'] }
8
- request = Rack::MockRequest.env_for("/", :input => "profile=process_time")
9
-
10
- specify 'printer defaults to RubyProf::CallTreePrinter' do
11
- profiler = Rack::Profiler.new(nil)
12
- profiler.instance_variable_get('@printer').should == RubyProf::CallTreePrinter
13
- profiler.instance_variable_get('@times').should == 1
14
- end
15
-
16
- specify 'CallTreePrinter has correct headers' do
17
- headers = Rack::Profiler.new(app).call(request)[1]
18
- headers.should == {"Content-Disposition"=>"attachment; filename=\"/.process_time.tree\"", "Content-Type"=>"application/octet-stream"}
19
- end
20
-
21
- specify 'FlatPrinter and GraphPrinter has Content-Type text/plain' do
22
- %w(flat graph).each do |printer|
23
- headers = Rack::Profiler.new(app, :printer => printer.to_sym).call(request)[1]
24
- headers.should == {"Content-Type"=>"text/plain"}
4
+ begin
5
+ require 'rack/contrib/profiler'
6
+
7
+ context 'Rack::Profiler' do
8
+ app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, 'Oh hai der'] }
9
+ request = Rack::MockRequest.env_for("/", :input => "profile=process_time")
10
+
11
+ specify 'printer defaults to RubyProf::CallTreePrinter' do
12
+ profiler = Rack::Profiler.new(nil)
13
+ profiler.instance_variable_get('@printer').should.equal RubyProf::CallTreePrinter
14
+ profiler.instance_variable_get('@times').should.equal 1
15
+ end
16
+
17
+ specify 'CallTreePrinter has correct headers' do
18
+ headers = Rack::Profiler.new(app).call(request)[1]
19
+ headers.should.equal "Content-Disposition"=>"attachment; filename=\"/.process_time.tree\"", "Content-Type"=>"application/octet-stream"
20
+ end
21
+
22
+ specify 'FlatPrinter and GraphPrinter has Content-Type text/plain' do
23
+ %w(flat graph).each do |printer|
24
+ headers = Rack::Profiler.new(app, :printer => printer.to_sym).call(request)[1]
25
+ headers.should.equal "Content-Type"=>"text/plain"
26
+ end
27
+ end
28
+
29
+ specify 'GraphHtmlPrinter has Content-Type text/html' do
30
+ headers = Rack::Profiler.new(app, :printer => :graph_html).call(request)[1]
31
+ headers.should.equal "Content-Type"=>"text/html"
25
32
  end
26
33
  end
27
-
28
- specify 'GraphHtmlPrinter has Content-Type text/html' do
29
- headers = Rack::Profiler.new(app, :printer => :graph_html).call(request)[1]
30
- headers.should == {"Content-Type"=>"text/html"}
31
- end
34
+
35
+ rescue LoadError => boom
36
+ $stderr.puts "WARN: Skipping Rack::Profiler tests (ruby-prof not installed)"
32
37
  end
@@ -0,0 +1,78 @@
1
+ require 'test/spec'
2
+ require 'rack/mock'
3
+ require 'rack/contrib/relative_redirect'
4
+ require 'fileutils'
5
+
6
+ context Rack::RelativeRedirect do
7
+ def request(opts={}, &block)
8
+ @def_status = opts[:status] if opts[:status]
9
+ @def_location = opts[:location] if opts[:location]
10
+ yield Rack::MockRequest.new(Rack::RelativeRedirect.new(@def_app, &opts[:block])).get(opts[:path]||@def_path, opts[:headers]||{})
11
+ end
12
+
13
+ setup do
14
+ @def_path = '/path/to/blah'
15
+ @def_status = 301
16
+ @def_location = '/redirect/to/blah'
17
+ @def_app = lambda { |env| [@def_status, {'Location' => @def_location}, [""]]}
18
+ end
19
+
20
+ specify "should make the location url an absolute url if currently a relative url" do
21
+ request do |r|
22
+ r.status.should.equal(301)
23
+ r.headers['Location'].should.equal('http://example.org/redirect/to/blah')
24
+ end
25
+ request(:status=>302, :location=>'/redirect') do |r|
26
+ r.status.should.equal(302)
27
+ r.headers['Location'].should.equal('http://example.org/redirect')
28
+ end
29
+ end
30
+
31
+ specify "should use the request path if the relative url is given and doesn't start with a slash" do
32
+ request(:status=>303, :location=>'redirect/to/blah') do |r|
33
+ r.status.should.equal(303)
34
+ r.headers['Location'].should.equal('http://example.org/path/to/redirect/to/blah')
35
+ end
36
+ request(:status=>303, :location=>'redirect') do |r|
37
+ r.status.should.equal(303)
38
+ r.headers['Location'].should.equal('http://example.org/path/to/redirect')
39
+ end
40
+ end
41
+
42
+ specify "should use a given block to make the url absolute" do
43
+ request(:block=>proc{|env, res| "https://example.org"}) do |r|
44
+ r.status.should.equal(301)
45
+ r.headers['Location'].should.equal('https://example.org/redirect/to/blah')
46
+ end
47
+ request(:status=>303, :location=>'/redirect', :block=>proc{|env, res| "https://e.org:9999/blah"}) do |r|
48
+ r.status.should.equal(303)
49
+ r.headers['Location'].should.equal('https://e.org:9999/blah/redirect')
50
+ end
51
+ end
52
+
53
+ specify "should not modify the location url unless the response is a redirect" do
54
+ status = 200
55
+ @def_app = lambda { |env| [status, {'Content-Type' => "text/html"}, [""]]}
56
+ request do |r|
57
+ r.status.should.equal(200)
58
+ r.headers.should.not.include?('Location')
59
+ end
60
+ status = 404
61
+ @def_app = lambda { |env| [status, {'Content-Type' => "text/html", 'Location' => 'redirect'}, [""]]}
62
+ request do |r|
63
+ r.status.should.equal(404)
64
+ r.headers['Location'].should.equal('redirect')
65
+ end
66
+ end
67
+
68
+ specify "should not modify the location url if it is already an absolute url" do
69
+ request(:location=>'https://example.org/') do |r|
70
+ r.status.should.equal(301)
71
+ r.headers['Location'].should.equal('https://example.org/')
72
+ end
73
+ request(:status=>302, :location=>'https://e.org:9999/redirect') do |r|
74
+ r.status.should.equal(302)
75
+ r.headers['Location'].should.equal('https://e.org:9999/redirect')
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,137 @@
1
+ require 'test/spec'
2
+ require 'rack/mock'
3
+ require 'rack/contrib/response_cache'
4
+ require 'fileutils'
5
+
6
+ context Rack::ResponseCache do
7
+ F = ::File
8
+
9
+ def request(opts={}, &block)
10
+ Rack::MockRequest.new(Rack::ResponseCache.new(block||@def_app, opts[:cache]||@cache, &opts[:rc_block])).send(opts[:meth]||:get, opts[:path]||@def_path, opts[:headers]||{})
11
+ end
12
+
13
+ setup do
14
+ @cache = {}
15
+ @def_disk_cache = F.join(F.dirname(__FILE__), 'response_cache_test_disk_cache')
16
+ @def_value = ["rack-response-cache"]
17
+ @def_path = '/path/to/blah'
18
+ @def_app = lambda { |env| [200, {'Content-Type' => env['CT'] || 'text/html'}, @def_value]}
19
+ end
20
+ teardown do
21
+ FileUtils.rm_rf(@def_disk_cache)
22
+ end
23
+
24
+ specify "should cache results to disk if cache is a string" do
25
+ request(:cache=>@def_disk_cache)
26
+ F.read(F.join(@def_disk_cache, 'path', 'to', 'blah.html')).should.equal @def_value.first
27
+ request(:path=>'/path/3', :cache=>@def_disk_cache)
28
+ F.read(F.join(@def_disk_cache, 'path', '3.html')).should.equal @def_value.first
29
+ end
30
+
31
+ specify "should cache results to given cache if cache is not a string" do
32
+ request
33
+ @cache.should.equal('/path/to/blah.html'=>@def_value)
34
+ request(:path=>'/path/3')
35
+ @cache.should.equal('/path/to/blah.html'=>@def_value, '/path/3.html'=>@def_value)
36
+ end
37
+
38
+ specify "should not CACHE RESults if request method is not GET" do
39
+ request(:meth=>:post)
40
+ @cache.should.equal({})
41
+ request(:meth=>:put)
42
+ @cache.should.equal({})
43
+ request(:meth=>:delete)
44
+ @cache.should.equal({})
45
+ end
46
+
47
+ specify "should not cache results if there is a query string" do
48
+ request(:path=>'/path/to/blah?id=1')
49
+ @cache.should.equal({})
50
+ request(:path=>'/path/to/?id=1')
51
+ @cache.should.equal({})
52
+ request(:path=>'/?id=1')
53
+ @cache.should.equal({})
54
+ end
55
+
56
+ specify "should cache results if there is an empty query string" do
57
+ request(:path=>'/?')
58
+ @cache.should.equal('/index.html'=>@def_value)
59
+ end
60
+
61
+ specify "should not cache results if the request is not sucessful (status 200)" do
62
+ request{|env| [404, {'Content-Type' => 'text/html'}, ['']]}
63
+ @cache.should.equal({})
64
+ request{|env| [500, {'Content-Type' => 'text/html'}, ['']]}
65
+ @cache.should.equal({})
66
+ request{|env| [302, {'Content-Type' => 'text/html'}, ['']]}
67
+ @cache.should.equal({})
68
+ end
69
+
70
+ specify "should not cache results if the block returns nil or false" do
71
+ request(:rc_block=>proc{false})
72
+ @cache.should.equal({})
73
+ request(:rc_block=>proc{nil})
74
+ @cache.should.equal({})
75
+ end
76
+
77
+ specify "should cache results to path returned by block" do
78
+ request(:rc_block=>proc{"1"})
79
+ @cache.should.equal("1"=>@def_value)
80
+ request(:rc_block=>proc{"2"})
81
+ @cache.should.equal("1"=>@def_value, "2"=>@def_value)
82
+ end
83
+
84
+ specify "should pass the environment and response to the block" do
85
+ e, r = nil, nil
86
+ request(:rc_block=>proc{|env,res| e, r = env, res; nil})
87
+ e['PATH_INFO'].should.equal @def_path
88
+ e['REQUEST_METHOD'].should.equal 'GET'
89
+ e['QUERY_STRING'].should.equal ''
90
+ r.should.equal([200, {"Content-Type"=>"text/html"}, ["rack-response-cache"]])
91
+ end
92
+
93
+ specify "should unescape the path by default" do
94
+ request(:path=>'/path%20with%20spaces')
95
+ @cache.should.equal('/path with spaces.html'=>@def_value)
96
+ request(:path=>'/path%3chref%3e')
97
+ @cache.should.equal('/path with spaces.html'=>@def_value, '/path<href>.html'=>@def_value)
98
+ end
99
+
100
+ specify "should cache html, css, and xml responses by default" do
101
+ request(:path=>'/a')
102
+ @cache.should.equal('/a.html'=>@def_value)
103
+ request(:path=>'/b', :headers=>{'CT'=>'text/xml'})
104
+ @cache.should.equal('/a.html'=>@def_value, '/b.xml'=>@def_value)
105
+ request(:path=>'/c', :headers=>{'CT'=>'text/css'})
106
+ @cache.should.equal('/a.html'=>@def_value, '/b.xml'=>@def_value, '/c.css'=>@def_value)
107
+ end
108
+
109
+ specify "should cache responses by default with the extension added if not already present" do
110
+ request(:path=>'/a.html')
111
+ @cache.should.equal('/a.html'=>@def_value)
112
+ request(:path=>'/b.xml', :headers=>{'CT'=>'text/xml'})
113
+ @cache.should.equal('/a.html'=>@def_value, '/b.xml'=>@def_value)
114
+ request(:path=>'/c.css', :headers=>{'CT'=>'text/css'})
115
+ @cache.should.equal('/a.html'=>@def_value, '/b.xml'=>@def_value, '/c.css'=>@def_value)
116
+ end
117
+
118
+ specify "should not delete existing extensions" do
119
+ request(:path=>'/d.css', :headers=>{'CT'=>'text/html'})
120
+ @cache.should.equal('/d.css.html'=>@def_value)
121
+ end
122
+
123
+ specify "should cache html responses with empty basename to index.html by default" do
124
+ request(:path=>'/')
125
+ @cache.should.equal('/index.html'=>@def_value)
126
+ request(:path=>'/blah/')
127
+ @cache.should.equal('/index.html'=>@def_value, '/blah/index.html'=>@def_value)
128
+ request(:path=>'/blah/2/')
129
+ @cache.should.equal('/index.html'=>@def_value, '/blah/index.html'=>@def_value, '/blah/2/index.html'=>@def_value)
130
+ end
131
+
132
+ specify "should raise an error if a cache argument is not provided" do
133
+ app = Rack::Builder.new{use Rack::ResponseCache; run lambda { |env| [200, {'Content-Type' => 'text/plain'}, Rack::Request.new(env).POST]}}
134
+ proc{Rack::MockRequest.new(app).get('/')}.should.raise(ArgumentError)
135
+ end
136
+
137
+ end