edgar-rack 1.2.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.
Files changed (138) hide show
  1. data/COPYING +18 -0
  2. data/KNOWN-ISSUES +21 -0
  3. data/README +401 -0
  4. data/Rakefile +101 -0
  5. data/SPEC +171 -0
  6. data/bin/rackup +4 -0
  7. data/contrib/rack_logo.svg +111 -0
  8. data/example/lobster.ru +4 -0
  9. data/example/protectedlobster.rb +14 -0
  10. data/example/protectedlobster.ru +8 -0
  11. data/lib/rack.rb +81 -0
  12. data/lib/rack/auth/abstract/handler.rb +37 -0
  13. data/lib/rack/auth/abstract/request.rb +43 -0
  14. data/lib/rack/auth/basic.rb +58 -0
  15. data/lib/rack/auth/digest/md5.rb +124 -0
  16. data/lib/rack/auth/digest/nonce.rb +51 -0
  17. data/lib/rack/auth/digest/params.rb +53 -0
  18. data/lib/rack/auth/digest/request.rb +40 -0
  19. data/lib/rack/builder.rb +80 -0
  20. data/lib/rack/cascade.rb +41 -0
  21. data/lib/rack/chunked.rb +52 -0
  22. data/lib/rack/commonlogger.rb +49 -0
  23. data/lib/rack/conditionalget.rb +63 -0
  24. data/lib/rack/config.rb +15 -0
  25. data/lib/rack/content_length.rb +29 -0
  26. data/lib/rack/content_type.rb +23 -0
  27. data/lib/rack/deflater.rb +96 -0
  28. data/lib/rack/directory.rb +157 -0
  29. data/lib/rack/etag.rb +59 -0
  30. data/lib/rack/file.rb +118 -0
  31. data/lib/rack/handler.rb +88 -0
  32. data/lib/rack/handler/cgi.rb +61 -0
  33. data/lib/rack/handler/evented_mongrel.rb +8 -0
  34. data/lib/rack/handler/fastcgi.rb +90 -0
  35. data/lib/rack/handler/lsws.rb +61 -0
  36. data/lib/rack/handler/mongrel.rb +90 -0
  37. data/lib/rack/handler/scgi.rb +59 -0
  38. data/lib/rack/handler/swiftiplied_mongrel.rb +8 -0
  39. data/lib/rack/handler/thin.rb +17 -0
  40. data/lib/rack/handler/webrick.rb +73 -0
  41. data/lib/rack/head.rb +19 -0
  42. data/lib/rack/lint.rb +567 -0
  43. data/lib/rack/lobster.rb +65 -0
  44. data/lib/rack/lock.rb +44 -0
  45. data/lib/rack/logger.rb +18 -0
  46. data/lib/rack/methodoverride.rb +27 -0
  47. data/lib/rack/mime.rb +210 -0
  48. data/lib/rack/mock.rb +185 -0
  49. data/lib/rack/nulllogger.rb +18 -0
  50. data/lib/rack/recursive.rb +61 -0
  51. data/lib/rack/reloader.rb +109 -0
  52. data/lib/rack/request.rb +307 -0
  53. data/lib/rack/response.rb +151 -0
  54. data/lib/rack/rewindable_input.rb +104 -0
  55. data/lib/rack/runtime.rb +27 -0
  56. data/lib/rack/sendfile.rb +139 -0
  57. data/lib/rack/server.rb +289 -0
  58. data/lib/rack/session/abstract/id.rb +348 -0
  59. data/lib/rack/session/cookie.rb +152 -0
  60. data/lib/rack/session/memcache.rb +93 -0
  61. data/lib/rack/session/pool.rb +79 -0
  62. data/lib/rack/showexceptions.rb +378 -0
  63. data/lib/rack/showstatus.rb +113 -0
  64. data/lib/rack/static.rb +53 -0
  65. data/lib/rack/urlmap.rb +55 -0
  66. data/lib/rack/utils.rb +698 -0
  67. data/rack.gemspec +39 -0
  68. data/test/cgi/lighttpd.conf +25 -0
  69. data/test/cgi/rackup_stub.rb +6 -0
  70. data/test/cgi/sample_rackup.ru +5 -0
  71. data/test/cgi/test +9 -0
  72. data/test/cgi/test.fcgi +8 -0
  73. data/test/cgi/test.ru +5 -0
  74. data/test/gemloader.rb +6 -0
  75. data/test/multipart/bad_robots +259 -0
  76. data/test/multipart/binary +0 -0
  77. data/test/multipart/empty +10 -0
  78. data/test/multipart/fail_16384_nofile +814 -0
  79. data/test/multipart/file1.txt +1 -0
  80. data/test/multipart/filename_and_modification_param +7 -0
  81. data/test/multipart/filename_with_escaped_quotes +6 -0
  82. data/test/multipart/filename_with_escaped_quotes_and_modification_param +7 -0
  83. data/test/multipart/filename_with_percent_escaped_quotes +6 -0
  84. data/test/multipart/filename_with_unescaped_quotes +6 -0
  85. data/test/multipart/ie +6 -0
  86. data/test/multipart/nested +10 -0
  87. data/test/multipart/none +9 -0
  88. data/test/multipart/semicolon +6 -0
  89. data/test/multipart/text +15 -0
  90. data/test/rackup/config.ru +31 -0
  91. data/test/spec_auth_basic.rb +70 -0
  92. data/test/spec_auth_digest.rb +241 -0
  93. data/test/spec_builder.rb +123 -0
  94. data/test/spec_cascade.rb +45 -0
  95. data/test/spec_cgi.rb +102 -0
  96. data/test/spec_chunked.rb +60 -0
  97. data/test/spec_commonlogger.rb +56 -0
  98. data/test/spec_conditionalget.rb +86 -0
  99. data/test/spec_config.rb +23 -0
  100. data/test/spec_content_length.rb +36 -0
  101. data/test/spec_content_type.rb +29 -0
  102. data/test/spec_deflater.rb +125 -0
  103. data/test/spec_directory.rb +57 -0
  104. data/test/spec_etag.rb +75 -0
  105. data/test/spec_fastcgi.rb +107 -0
  106. data/test/spec_file.rb +92 -0
  107. data/test/spec_handler.rb +49 -0
  108. data/test/spec_head.rb +30 -0
  109. data/test/spec_lint.rb +515 -0
  110. data/test/spec_lobster.rb +43 -0
  111. data/test/spec_lock.rb +142 -0
  112. data/test/spec_logger.rb +28 -0
  113. data/test/spec_methodoverride.rb +58 -0
  114. data/test/spec_mock.rb +241 -0
  115. data/test/spec_mongrel.rb +182 -0
  116. data/test/spec_nulllogger.rb +12 -0
  117. data/test/spec_recursive.rb +69 -0
  118. data/test/spec_request.rb +774 -0
  119. data/test/spec_response.rb +245 -0
  120. data/test/spec_rewindable_input.rb +118 -0
  121. data/test/spec_runtime.rb +39 -0
  122. data/test/spec_sendfile.rb +83 -0
  123. data/test/spec_server.rb +8 -0
  124. data/test/spec_session_abstract_id.rb +43 -0
  125. data/test/spec_session_cookie.rb +171 -0
  126. data/test/spec_session_memcache.rb +289 -0
  127. data/test/spec_session_pool.rb +200 -0
  128. data/test/spec_showexceptions.rb +87 -0
  129. data/test/spec_showstatus.rb +79 -0
  130. data/test/spec_static.rb +48 -0
  131. data/test/spec_thin.rb +86 -0
  132. data/test/spec_urlmap.rb +213 -0
  133. data/test/spec_utils.rb +678 -0
  134. data/test/spec_webrick.rb +141 -0
  135. data/test/testrequest.rb +78 -0
  136. data/test/unregistered_handler/rack/handler/unregistered.rb +7 -0
  137. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +7 -0
  138. metadata +329 -0
@@ -0,0 +1,43 @@
1
+ require 'rack/lobster'
2
+ require 'rack/mock'
3
+
4
+ describe Rack::Lobster::LambdaLobster do
5
+ should "be a single lambda" do
6
+ Rack::Lobster::LambdaLobster.should.be.kind_of Proc
7
+ end
8
+
9
+ should "look like a lobster" do
10
+ res = Rack::MockRequest.new(Rack::Lobster::LambdaLobster).get("/")
11
+ res.should.be.ok
12
+ res.body.should.include "(,(,,(,,,("
13
+ res.body.should.include "?flip"
14
+ end
15
+
16
+ should "be flippable" do
17
+ res = Rack::MockRequest.new(Rack::Lobster::LambdaLobster).get("/?flip")
18
+ res.should.be.ok
19
+ res.body.should.include "(,,,(,,(,("
20
+ end
21
+ end
22
+
23
+ describe Rack::Lobster do
24
+ should "look like a lobster" do
25
+ res = Rack::MockRequest.new(Rack::Lobster.new).get("/")
26
+ res.should.be.ok
27
+ res.body.should.include "(,(,,(,,,("
28
+ res.body.should.include "?flip"
29
+ res.body.should.include "crash"
30
+ end
31
+
32
+ should "be flippable" do
33
+ res = Rack::MockRequest.new(Rack::Lobster.new).get("/?flip=left")
34
+ res.should.be.ok
35
+ res.body.should.include "(,,,(,,(,("
36
+ end
37
+
38
+ should "provide crashing for testing purposes" do
39
+ lambda {
40
+ Rack::MockRequest.new(Rack::Lobster.new).get("/?flip=crash")
41
+ }.should.raise
42
+ end
43
+ end
@@ -0,0 +1,142 @@
1
+ require 'rack/lock'
2
+ require 'rack/mock'
3
+
4
+ class Lock
5
+ attr_reader :synchronized
6
+
7
+ def initialize
8
+ @synchronized = false
9
+ end
10
+
11
+ def synchronize
12
+ @synchronized = true
13
+ yield
14
+ end
15
+
16
+ def lock
17
+ @synchronized = true
18
+ end
19
+
20
+ def unlock
21
+ @synchronized = false
22
+ end
23
+ end
24
+
25
+ describe Rack::Lock do
26
+ describe 'Proxy' do
27
+ should 'delegate each' do
28
+ lock = Lock.new
29
+ env = Rack::MockRequest.env_for("/")
30
+ response = Class.new {
31
+ attr_accessor :close_called
32
+ def initialize; @close_called = false; end
33
+ def each; %w{ hi mom }.each { |x| yield x }; end
34
+ }.new
35
+
36
+ app = Rack::Lock.new(lambda { |inner_env| [200, {}, response] }, lock)
37
+ response = app.call(env)[2]
38
+ list = []
39
+ response.each { |x| list << x }
40
+ list.should.equal %w{ hi mom }
41
+ end
42
+
43
+ should 'delegate to_path' do
44
+ lock = Lock.new
45
+ env = Rack::MockRequest.env_for("/")
46
+
47
+ res = ['Hello World']
48
+ def res.to_path ; "/tmp/hello.txt" ; end
49
+
50
+ app = Rack::Lock.new(lambda { |inner_env| [200, {}, res] }, lock)
51
+ body = app.call(env)[2]
52
+
53
+ body.should.respond_to :to_path
54
+ body.to_path.should.equal "/tmp/hello.txt"
55
+ end
56
+
57
+ should 'not delegate to_path if body does not implement it' do
58
+ lock = Lock.new
59
+ env = Rack::MockRequest.env_for("/")
60
+
61
+ res = ['Hello World']
62
+
63
+ app = Rack::Lock.new(lambda { |inner_env| [200, {}, res] }, lock)
64
+ body = app.call(env)[2]
65
+
66
+ body.should.not.respond_to :to_path
67
+ end
68
+ end
69
+
70
+ should 'call super on close' do
71
+ lock = Lock.new
72
+ env = Rack::MockRequest.env_for("/")
73
+ response = Class.new {
74
+ attr_accessor :close_called
75
+ def initialize; @close_called = false; end
76
+ def close; @close_called = true; end
77
+ }.new
78
+
79
+ app = Rack::Lock.new(lambda { |inner_env| [200, {}, response] }, lock)
80
+ app.call(env)
81
+ response.close_called.should.equal false
82
+ response.close
83
+ response.close_called.should.equal true
84
+ end
85
+
86
+ should "not unlock until body is closed" do
87
+ lock = Lock.new
88
+ env = Rack::MockRequest.env_for("/")
89
+ response = Object.new
90
+ app = Rack::Lock.new(lambda { |inner_env| [200, {}, response] }, lock)
91
+ lock.synchronized.should.equal false
92
+ response = app.call(env)[2]
93
+ lock.synchronized.should.equal true
94
+ response.close
95
+ lock.synchronized.should.equal false
96
+ end
97
+
98
+ should "return value from app" do
99
+ lock = Lock.new
100
+ env = Rack::MockRequest.env_for("/")
101
+ body = [200, {}, %w{ hi mom }]
102
+ app = Rack::Lock.new(lambda { |inner_env| body }, lock)
103
+ app.call(env).should.equal body
104
+ end
105
+
106
+ should "call synchronize on lock" do
107
+ lock = Lock.new
108
+ env = Rack::MockRequest.env_for("/")
109
+ app = Rack::Lock.new(lambda { |inner_env|
110
+ [200, {}, %w{ a b c }]
111
+ }, lock)
112
+ lock.synchronized.should.equal false
113
+ app.call(env)
114
+ lock.synchronized.should.equal true
115
+ end
116
+
117
+ should "unlock if the app raises" do
118
+ lock = Lock.new
119
+ env = Rack::MockRequest.env_for("/")
120
+ app = Rack::Lock.new(lambda { raise Exception }, lock)
121
+ lambda { app.call(env) }.should.raise(Exception)
122
+ lock.synchronized.should.equal false
123
+ end
124
+
125
+ should "set multithread flag to false" do
126
+ app = Rack::Lock.new(lambda { |env|
127
+ env['rack.multithread'].should.equal false
128
+ [200, {}, %w{ a b c }]
129
+ })
130
+ app.call(Rack::MockRequest.env_for("/"))
131
+ end
132
+
133
+ should "reset original multithread flag when exiting lock" do
134
+ app = Class.new(Rack::Lock) {
135
+ def call(env)
136
+ env['rack.multithread'].should.equal true
137
+ super
138
+ end
139
+ }.new(lambda { |env| [200, {}, %w{ a b c }] })
140
+ app.call(Rack::MockRequest.env_for("/"))
141
+ end
142
+ end
@@ -0,0 +1,28 @@
1
+ require 'stringio'
2
+ require 'rack/logger'
3
+
4
+ describe Rack::Logger do
5
+ app = lambda { |env|
6
+ log = env['rack.logger']
7
+ log.debug("Created logger")
8
+ log.info("Program started")
9
+ log.warn("Nothing to do!")
10
+
11
+ [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]]
12
+ }
13
+
14
+ should "log to rack.errors" do
15
+ errors = StringIO.new
16
+ Rack::Logger.new(app).call('rack.errors' => errors)
17
+ errors.string.should.match(/INFO -- : Program started/)
18
+ errors.string.should.match(/WARN -- : Nothing to do/)
19
+ end
20
+
21
+ should "conform to Rack::Lint" do
22
+ errors = StringIO.new
23
+ a = Rack::Lint.new(Rack::Logger.new(app))
24
+ Rack::MockRequest.new(a).get('/', 'rack.errors' => errors)
25
+ errors.string.should.match(/INFO -- : Program started/)
26
+ errors.string.should.match(/WARN -- : Nothing to do/)
27
+ end
28
+ end
@@ -0,0 +1,58 @@
1
+ require 'stringio'
2
+ require 'rack/methodoverride'
3
+ require 'rack/mock'
4
+
5
+ describe Rack::MethodOverride do
6
+ should "not affect GET requests" do
7
+ env = Rack::MockRequest.env_for("/?_method=delete", :method => "GET")
8
+ app = Rack::MethodOverride.new(lambda{|envx| Rack::Request.new(envx) })
9
+ req = app.call(env)
10
+
11
+ req.env["REQUEST_METHOD"].should.equal "GET"
12
+ end
13
+
14
+ should "modify REQUEST_METHOD for POST requests when _method parameter is set" do
15
+ env = Rack::MockRequest.env_for("/", :method => "POST", :input => "_method=put")
16
+ app = Rack::MethodOverride.new(lambda{|envx| Rack::Request.new(envx) })
17
+ req = app.call(env)
18
+
19
+ req.env["REQUEST_METHOD"].should.equal "PUT"
20
+ end
21
+
22
+ should "modify REQUEST_METHOD for POST requests when X-HTTP-Method-Override is set" do
23
+ env = Rack::MockRequest.env_for("/",
24
+ :method => "POST",
25
+ "HTTP_X_HTTP_METHOD_OVERRIDE" => "PUT"
26
+ )
27
+ app = Rack::MethodOverride.new(lambda{|envx| Rack::Request.new(envx) })
28
+ req = app.call(env)
29
+
30
+ req.env["REQUEST_METHOD"].should.equal "PUT"
31
+ end
32
+
33
+ should "not modify REQUEST_METHOD if the method is unknown" do
34
+ env = Rack::MockRequest.env_for("/", :method => "POST", :input => "_method=foo")
35
+ app = Rack::MethodOverride.new(lambda{|envx| Rack::Request.new(envx) })
36
+ req = app.call(env)
37
+
38
+ req.env["REQUEST_METHOD"].should.equal "POST"
39
+ end
40
+
41
+ should "not modify REQUEST_METHOD when _method is nil" do
42
+ env = Rack::MockRequest.env_for("/", :method => "POST", :input => "foo=bar")
43
+ app = Rack::MethodOverride.new(lambda{|envx| Rack::Request.new(envx) })
44
+ req = app.call(env)
45
+
46
+ req.env["REQUEST_METHOD"].should.equal "POST"
47
+ end
48
+
49
+ should "store the original REQUEST_METHOD prior to overriding" do
50
+ env = Rack::MockRequest.env_for("/",
51
+ :method => "POST",
52
+ :input => "_method=options")
53
+ app = Rack::MethodOverride.new(lambda{|envx| Rack::Request.new(envx) })
54
+ req = app.call(env)
55
+
56
+ req.env["rack.methodoverride.original_method"].should.equal "POST"
57
+ end
58
+ end
@@ -0,0 +1,241 @@
1
+ require 'yaml'
2
+ require 'rack/mock'
3
+
4
+ app = lambda { |env|
5
+ req = Rack::Request.new(env)
6
+
7
+ env["mock.postdata"] = env["rack.input"].read
8
+ if req.GET["error"]
9
+ env["rack.errors"].puts req.GET["error"]
10
+ env["rack.errors"].flush
11
+ end
12
+
13
+ Rack::Response.new(env.to_yaml,
14
+ req.GET["status"] || 200,
15
+ "Content-Type" => "text/yaml").finish
16
+ }
17
+
18
+ describe Rack::MockRequest do
19
+ should "return a MockResponse" do
20
+ res = Rack::MockRequest.new(app).get("")
21
+ res.should.be.kind_of Rack::MockResponse
22
+ end
23
+
24
+ should "be able to only return the environment" do
25
+ env = Rack::MockRequest.env_for("")
26
+ env.should.be.kind_of Hash
27
+ env.should.include "rack.version"
28
+ end
29
+
30
+ should "provide sensible defaults" do
31
+ res = Rack::MockRequest.new(app).request
32
+
33
+ env = YAML.load(res.body)
34
+ env["REQUEST_METHOD"].should.equal "GET"
35
+ env["SERVER_NAME"].should.equal "example.org"
36
+ env["SERVER_PORT"].should.equal "80"
37
+ env["QUERY_STRING"].should.equal ""
38
+ env["PATH_INFO"].should.equal "/"
39
+ env["SCRIPT_NAME"].should.equal ""
40
+ env["rack.url_scheme"].should.equal "http"
41
+ env["mock.postdata"].should.be.empty
42
+ end
43
+
44
+ should "allow GET/POST/PUT/DELETE" do
45
+ res = Rack::MockRequest.new(app).get("", :input => "foo")
46
+ env = YAML.load(res.body)
47
+ env["REQUEST_METHOD"].should.equal "GET"
48
+
49
+ res = Rack::MockRequest.new(app).post("", :input => "foo")
50
+ env = YAML.load(res.body)
51
+ env["REQUEST_METHOD"].should.equal "POST"
52
+
53
+ res = Rack::MockRequest.new(app).put("", :input => "foo")
54
+ env = YAML.load(res.body)
55
+ env["REQUEST_METHOD"].should.equal "PUT"
56
+
57
+ res = Rack::MockRequest.new(app).delete("", :input => "foo")
58
+ env = YAML.load(res.body)
59
+ env["REQUEST_METHOD"].should.equal "DELETE"
60
+
61
+ Rack::MockRequest.env_for("/", :method => "OPTIONS")["REQUEST_METHOD"].
62
+ should.equal "OPTIONS"
63
+ end
64
+
65
+ should "set content length" do
66
+ env = Rack::MockRequest.env_for("/", :input => "foo")
67
+ env["CONTENT_LENGTH"].should.equal "3"
68
+ end
69
+
70
+ should "allow posting" do
71
+ res = Rack::MockRequest.new(app).get("", :input => "foo")
72
+ env = YAML.load(res.body)
73
+ env["mock.postdata"].should.equal "foo"
74
+
75
+ res = Rack::MockRequest.new(app).post("", :input => StringIO.new("foo"))
76
+ env = YAML.load(res.body)
77
+ env["mock.postdata"].should.equal "foo"
78
+ end
79
+
80
+ should "use all parts of an URL" do
81
+ res = Rack::MockRequest.new(app).
82
+ get("https://bla.example.org:9292/meh/foo?bar")
83
+ res.should.be.kind_of Rack::MockResponse
84
+
85
+ env = YAML.load(res.body)
86
+ env["REQUEST_METHOD"].should.equal "GET"
87
+ env["SERVER_NAME"].should.equal "bla.example.org"
88
+ env["SERVER_PORT"].should.equal "9292"
89
+ env["QUERY_STRING"].should.equal "bar"
90
+ env["PATH_INFO"].should.equal "/meh/foo"
91
+ env["rack.url_scheme"].should.equal "https"
92
+ end
93
+
94
+ should "set SSL port and HTTP flag on when using https" do
95
+ res = Rack::MockRequest.new(app).
96
+ get("https://example.org/foo")
97
+ res.should.be.kind_of Rack::MockResponse
98
+
99
+ env = YAML.load(res.body)
100
+ env["REQUEST_METHOD"].should.equal "GET"
101
+ env["SERVER_NAME"].should.equal "example.org"
102
+ env["SERVER_PORT"].should.equal "443"
103
+ env["QUERY_STRING"].should.equal ""
104
+ env["PATH_INFO"].should.equal "/foo"
105
+ env["rack.url_scheme"].should.equal "https"
106
+ env["HTTPS"].should.equal "on"
107
+ end
108
+
109
+ should "prepend slash to uri path" do
110
+ res = Rack::MockRequest.new(app).
111
+ get("foo")
112
+ res.should.be.kind_of Rack::MockResponse
113
+
114
+ env = YAML.load(res.body)
115
+ env["REQUEST_METHOD"].should.equal "GET"
116
+ env["SERVER_NAME"].should.equal "example.org"
117
+ env["SERVER_PORT"].should.equal "80"
118
+ env["QUERY_STRING"].should.equal ""
119
+ env["PATH_INFO"].should.equal "/foo"
120
+ env["rack.url_scheme"].should.equal "http"
121
+ end
122
+
123
+ should "properly convert method name to an uppercase string" do
124
+ res = Rack::MockRequest.new(app).request(:get)
125
+ env = YAML.load(res.body)
126
+ env["REQUEST_METHOD"].should.equal "GET"
127
+ end
128
+
129
+ should "accept params and build query string for GET requests" do
130
+ res = Rack::MockRequest.new(app).get("/foo?baz=2", :params => {:foo => {:bar => "1"}})
131
+ env = YAML.load(res.body)
132
+ env["REQUEST_METHOD"].should.equal "GET"
133
+ env["QUERY_STRING"].should.include "baz=2"
134
+ env["QUERY_STRING"].should.include "foo[bar]=1"
135
+ env["PATH_INFO"].should.equal "/foo"
136
+ env["mock.postdata"].should.equal ""
137
+ end
138
+
139
+ should "accept raw input in params for GET requests" do
140
+ res = Rack::MockRequest.new(app).get("/foo?baz=2", :params => "foo[bar]=1")
141
+ env = YAML.load(res.body)
142
+ env["REQUEST_METHOD"].should.equal "GET"
143
+ env["QUERY_STRING"].should.include "baz=2"
144
+ env["QUERY_STRING"].should.include "foo[bar]=1"
145
+ env["PATH_INFO"].should.equal "/foo"
146
+ env["mock.postdata"].should.equal ""
147
+ end
148
+
149
+ should "accept params and build url encoded params for POST requests" do
150
+ res = Rack::MockRequest.new(app).post("/foo", :params => {:foo => {:bar => "1"}})
151
+ env = YAML.load(res.body)
152
+ env["REQUEST_METHOD"].should.equal "POST"
153
+ env["QUERY_STRING"].should.equal ""
154
+ env["PATH_INFO"].should.equal "/foo"
155
+ env["CONTENT_TYPE"].should.equal "application/x-www-form-urlencoded"
156
+ env["mock.postdata"].should.equal "foo[bar]=1"
157
+ end
158
+
159
+ should "accept raw input in params for POST requests" do
160
+ res = Rack::MockRequest.new(app).post("/foo", :params => "foo[bar]=1")
161
+ env = YAML.load(res.body)
162
+ env["REQUEST_METHOD"].should.equal "POST"
163
+ env["QUERY_STRING"].should.equal ""
164
+ env["PATH_INFO"].should.equal "/foo"
165
+ env["CONTENT_TYPE"].should.equal "application/x-www-form-urlencoded"
166
+ env["mock.postdata"].should.equal "foo[bar]=1"
167
+ end
168
+
169
+ should "accept params and build multipart encoded params for POST requests" do
170
+ files = Rack::Utils::Multipart::UploadedFile.new(File.join(File.dirname(__FILE__), "multipart", "file1.txt"))
171
+ res = Rack::MockRequest.new(app).post("/foo", :params => { "submit-name" => "Larry", "files" => files })
172
+ env = YAML.load(res.body)
173
+ env["REQUEST_METHOD"].should.equal "POST"
174
+ env["QUERY_STRING"].should.equal ""
175
+ env["PATH_INFO"].should.equal "/foo"
176
+ env["CONTENT_TYPE"].should.equal "multipart/form-data; boundary=AaB03x"
177
+ env["mock.postdata"].length.should.equal 206
178
+ end
179
+
180
+ should "behave valid according to the Rack spec" do
181
+ lambda {
182
+ Rack::MockRequest.new(app).
183
+ get("https://bla.example.org:9292/meh/foo?bar", :lint => true)
184
+ }.should.not.raise(Rack::Lint::LintError)
185
+ end
186
+ end
187
+
188
+ describe Rack::MockResponse do
189
+ should "provide access to the HTTP status" do
190
+ res = Rack::MockRequest.new(app).get("")
191
+ res.should.be.successful
192
+ res.should.be.ok
193
+
194
+ res = Rack::MockRequest.new(app).get("/?status=404")
195
+ res.should.not.be.successful
196
+ res.should.be.client_error
197
+ res.should.be.not_found
198
+
199
+ res = Rack::MockRequest.new(app).get("/?status=501")
200
+ res.should.not.be.successful
201
+ res.should.be.server_error
202
+
203
+ res = Rack::MockRequest.new(app).get("/?status=307")
204
+ res.should.be.redirect
205
+
206
+ res = Rack::MockRequest.new(app).get("/?status=201", :lint => true)
207
+ res.should.be.empty
208
+ end
209
+
210
+ should "provide access to the HTTP headers" do
211
+ res = Rack::MockRequest.new(app).get("")
212
+ res.should.include "Content-Type"
213
+ res.headers["Content-Type"].should.equal "text/yaml"
214
+ res.original_headers["Content-Type"].should.equal "text/yaml"
215
+ res["Content-Type"].should.equal "text/yaml"
216
+ res.content_type.should.equal "text/yaml"
217
+ res.content_length.should.not.equal 0
218
+ res.location.should.be.nil
219
+ end
220
+
221
+ should "provide access to the HTTP body" do
222
+ res = Rack::MockRequest.new(app).get("")
223
+ res.body.should =~ /rack/
224
+ res.should =~ /rack/
225
+ res.should.match(/rack/)
226
+ res.should.satisfy { |r| r.match(/rack/) }
227
+ end
228
+
229
+ should "provide access to the Rack errors" do
230
+ res = Rack::MockRequest.new(app).get("/?error=foo", :lint => true)
231
+ res.should.be.ok
232
+ res.errors.should.not.be.empty
233
+ res.errors.should.include "foo"
234
+ end
235
+
236
+ should "optionally make Rack errors fatal" do
237
+ lambda {
238
+ Rack::MockRequest.new(app).get("/?error=foo", :fatal => true)
239
+ }.should.raise(Rack::MockRequest::FatalWarning)
240
+ end
241
+ end