rack-contrib 0.9.0 → 0.9.2

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.

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