spec_mock.rb 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. require 'yaml'
  2. require 'rack/mock'
  3. require 'stringio'
  4. app = lambda { |env|
  5. req = Rack::Request.new(env)
  6. env["mock.postdata"] = env["rack.input"].read
  7. if req.GET["error"]
  8. env["rack.errors"].puts req.GET["error"]
  9. env["rack.errors"].flush
  10. end
  11. Rack::Response.new(env.to_yaml,
  12. req.GET["status"] || 200,
  13. "Content-Type" => "text/yaml").finish
  14. }
  15. describe Rack::MockRequest do
  16. should "return a MockResponse" do
  17. res = Rack::MockRequest.new(app).get("")
  18. res.should.be.kind_of Rack::MockResponse
  19. end
  20. should "be able to only return the environment" do
  21. env = Rack::MockRequest.env_for("")
  22. env.should.be.kind_of Hash
  23. env.should.include "rack.version"
  24. end
  25. should "provide sensible defaults" do
  26. res = Rack::MockRequest.new(app).request
  27. env = YAML.load(res.body)
  28. env["REQUEST_METHOD"].should.equal "GET"
  29. env["SERVER_NAME"].should.equal "example.org"
  30. env["SERVER_PORT"].should.equal "80"
  31. env["QUERY_STRING"].should.equal ""
  32. env["PATH_INFO"].should.equal "/"
  33. env["SCRIPT_NAME"].should.equal ""
  34. env["rack.url_scheme"].should.equal "http"
  35. env["mock.postdata"].should.be.empty
  36. end
  37. should "allow GET/POST/PUT/DELETE/HEAD" do
  38. res = Rack::MockRequest.new(app).get("", :input => "foo")
  39. env = YAML.load(res.body)
  40. env["REQUEST_METHOD"].should.equal "GET"
  41. res = Rack::MockRequest.new(app).post("", :input => "foo")
  42. env = YAML.load(res.body)
  43. env["REQUEST_METHOD"].should.equal "POST"
  44. res = Rack::MockRequest.new(app).put("", :input => "foo")
  45. env = YAML.load(res.body)
  46. env["REQUEST_METHOD"].should.equal "PUT"
  47. res = Rack::MockRequest.new(app).delete("", :input => "foo")
  48. env = YAML.load(res.body)
  49. env["REQUEST_METHOD"].should.equal "DELETE"
  50. res = Rack::MockRequest.new(app).head("", :input => "foo")
  51. env = YAML.load(res.body)
  52. env["REQUEST_METHOD"].should.equal "HEAD"
  53. Rack::MockRequest.env_for("/", :method => "OPTIONS")["REQUEST_METHOD"].
  54. should.equal "OPTIONS"
  55. end
  56. should "set content length" do
  57. env = Rack::MockRequest.env_for("/", :input => "foo")
  58. env["CONTENT_LENGTH"].should.equal "3"
  59. end
  60. should "allow posting" do
  61. res = Rack::MockRequest.new(app).get("", :input => "foo")
  62. env = YAML.load(res.body)
  63. env["mock.postdata"].should.equal "foo"
  64. res = Rack::MockRequest.new(app).post("", :input => StringIO.new("foo"))
  65. env = YAML.load(res.body)
  66. env["mock.postdata"].should.equal "foo"
  67. end
  68. should "use all parts of an URL" do
  69. res = Rack::MockRequest.new(app).
  70. get("https://bla.example.org:9292/meh/foo?bar")
  71. res.should.be.kind_of Rack::MockResponse
  72. env = YAML.load(res.body)
  73. env["REQUEST_METHOD"].should.equal "GET"
  74. env["SERVER_NAME"].should.equal "bla.example.org"
  75. env["SERVER_PORT"].should.equal "9292"
  76. env["QUERY_STRING"].should.equal "bar"
  77. env["PATH_INFO"].should.equal "/meh/foo"
  78. env["rack.url_scheme"].should.equal "https"
  79. end
  80. should "set SSL port and HTTP flag on when using https" do
  81. res = Rack::MockRequest.new(app).
  82. get("https://example.org/foo")
  83. res.should.be.kind_of Rack::MockResponse
  84. env = YAML.load(res.body)
  85. env["REQUEST_METHOD"].should.equal "GET"
  86. env["SERVER_NAME"].should.equal "example.org"
  87. env["SERVER_PORT"].should.equal "443"
  88. env["QUERY_STRING"].should.equal ""
  89. env["PATH_INFO"].should.equal "/foo"
  90. env["rack.url_scheme"].should.equal "https"
  91. env["HTTPS"].should.equal "on"
  92. end
  93. should "prepend slash to uri path" do
  94. res = Rack::MockRequest.new(app).
  95. get("foo")
  96. res.should.be.kind_of Rack::MockResponse
  97. env = YAML.load(res.body)
  98. env["REQUEST_METHOD"].should.equal "GET"
  99. env["SERVER_NAME"].should.equal "example.org"
  100. env["SERVER_PORT"].should.equal "80"
  101. env["QUERY_STRING"].should.equal ""
  102. env["PATH_INFO"].should.equal "/foo"
  103. env["rack.url_scheme"].should.equal "http"
  104. end
  105. should "properly convert method name to an uppercase string" do
  106. res = Rack::MockRequest.new(app).request(:get)
  107. env = YAML.load(res.body)
  108. env["REQUEST_METHOD"].should.equal "GET"
  109. end
  110. should "accept params and build query string for GET requests" do
  111. res = Rack::MockRequest.new(app).get("/foo?baz=2", :params => {:foo => {:bar => "1"}})
  112. env = YAML.load(res.body)
  113. env["REQUEST_METHOD"].should.equal "GET"
  114. env["QUERY_STRING"].should.include "baz=2"
  115. env["QUERY_STRING"].should.include "foo[bar]=1"
  116. env["PATH_INFO"].should.equal "/foo"
  117. env["mock.postdata"].should.equal ""
  118. end
  119. should "accept raw input in params for GET requests" do
  120. res = Rack::MockRequest.new(app).get("/foo?baz=2", :params => "foo[bar]=1")
  121. env = YAML.load(res.body)
  122. env["REQUEST_METHOD"].should.equal "GET"
  123. env["QUERY_STRING"].should.include "baz=2"
  124. env["QUERY_STRING"].should.include "foo[bar]=1"
  125. env["PATH_INFO"].should.equal "/foo"
  126. env["mock.postdata"].should.equal ""
  127. end
  128. should "accept params and build url encoded params for POST requests" do
  129. res = Rack::MockRequest.new(app).post("/foo", :params => {:foo => {:bar => "1"}})
  130. env = YAML.load(res.body)
  131. env["REQUEST_METHOD"].should.equal "POST"
  132. env["QUERY_STRING"].should.equal ""
  133. env["PATH_INFO"].should.equal "/foo"
  134. env["CONTENT_TYPE"].should.equal "application/x-www-form-urlencoded"
  135. env["mock.postdata"].should.equal "foo[bar]=1"
  136. end
  137. should "accept raw input in params for POST requests" do
  138. res = Rack::MockRequest.new(app).post("/foo", :params => "foo[bar]=1")
  139. env = YAML.load(res.body)
  140. env["REQUEST_METHOD"].should.equal "POST"
  141. env["QUERY_STRING"].should.equal ""
  142. env["PATH_INFO"].should.equal "/foo"
  143. env["CONTENT_TYPE"].should.equal "application/x-www-form-urlencoded"
  144. env["mock.postdata"].should.equal "foo[bar]=1"
  145. end
  146. should "accept params and build multipart encoded params for POST requests" do
  147. files = Rack::Multipart::UploadedFile.new(File.join(File.dirname(__FILE__), "multipart", "file1.txt"))
  148. res = Rack::MockRequest.new(app).post("/foo", :params => { "submit-name" => "Larry", "files" => files })
  149. env = YAML.load(res.body)
  150. env["REQUEST_METHOD"].should.equal "POST"
  151. env["QUERY_STRING"].should.equal ""
  152. env["PATH_INFO"].should.equal "/foo"
  153. env["CONTENT_TYPE"].should.equal "multipart/form-data; boundary=AaB03x"
  154. # The gsub accounts for differences in YAMLs affect on the data.
  155. env["mock.postdata"].gsub("\r", "").length.should.equal 206
  156. end
  157. should "behave valid according to the Rack spec" do
  158. lambda {
  159. Rack::MockRequest.new(app).
  160. get("https://bla.example.org:9292/meh/foo?bar", :lint => true)
  161. }.should.not.raise(Rack::Lint::LintError)
  162. end
  163. should "call close on the original body object" do
  164. called = false
  165. body = Rack::BodyProxy.new(['hi']) { called = true }
  166. capp = proc { |e| [200, {'Content-Type' => 'text/plain'}, body] }
  167. called.should.equal false
  168. Rack::MockRequest.new(capp).get('/', :lint => true)
  169. called.should.equal true
  170. end
  171. end
  172. describe Rack::MockResponse do
  173. should "provide access to the HTTP status" do
  174. res = Rack::MockRequest.new(app).get("")
  175. res.should.be.successful
  176. res.should.be.ok
  177. res = Rack::MockRequest.new(app).get("/?status=404")
  178. res.should.not.be.successful
  179. res.should.be.client_error
  180. res.should.be.not_found
  181. res = Rack::MockRequest.new(app).get("/?status=501")
  182. res.should.not.be.successful
  183. res.should.be.server_error
  184. res = Rack::MockRequest.new(app).get("/?status=307")
  185. res.should.be.redirect
  186. res = Rack::MockRequest.new(app).get("/?status=201", :lint => true)
  187. res.should.be.empty
  188. end
  189. should "provide access to the HTTP headers" do
  190. res = Rack::MockRequest.new(app).get("")
  191. res.should.include "Content-Type"
  192. res.headers["Content-Type"].should.equal "text/yaml"
  193. res.original_headers["Content-Type"].should.equal "text/yaml"
  194. res["Content-Type"].should.equal "text/yaml"
  195. res.content_type.should.equal "text/yaml"
  196. res.content_length.should.not.equal 0
  197. res.location.should.be.nil
  198. end
  199. should "provide access to the HTTP body" do
  200. res = Rack::MockRequest.new(app).get("")
  201. res.body.should =~ /rack/
  202. res.should =~ /rack/
  203. res.should.match(/rack/)
  204. res.should.satisfy { |r| r.match(/rack/) }
  205. end
  206. should "provide access to the Rack errors" do
  207. res = Rack::MockRequest.new(app).get("/?error=foo", :lint => true)
  208. res.should.be.ok
  209. res.errors.should.not.be.empty
  210. res.errors.should.include "foo"
  211. end
  212. should "allow calling body.close afterwards" do
  213. # this is exactly what rack-test does
  214. body = StringIO.new("hi")
  215. res = Rack::MockResponse.new(200, {}, body)
  216. body.close if body.respond_to?(:close)
  217. res.body.should == 'hi'
  218. end
  219. should "optionally make Rack errors fatal" do
  220. lambda {
  221. Rack::MockRequest.new(app).get("/?error=foo", :fatal => true)
  222. }.should.raise(Rack::MockRequest::FatalWarning)
  223. end
  224. end