Updated README.rdoc again
[feedcatcher.git] / vendor / rails / actionpack / lib / action_controller / vendor / rack-1.0 / rack / mock.rb
1 require 'uri'
2 require 'stringio'
3 require 'rack/lint'
4 require 'rack/utils'
5 require 'rack/response'
6
7 module Rack
8 # Rack::MockRequest helps testing your Rack application without
9 # actually using HTTP.
10 #
11 # After performing a request on a URL with get/post/put/delete, it
12 # returns a MockResponse with useful helper methods for effective
13 # testing.
14 #
15 # You can pass a hash with additional configuration to the
16 # get/post/put/delete.
17 # <tt>:input</tt>:: A String or IO-like to be used as rack.input.
18 # <tt>:fatal</tt>:: Raise a FatalWarning if the app writes to rack.errors.
19 # <tt>:lint</tt>:: If true, wrap the application in a Rack::Lint.
20
21 class MockRequest
22 class FatalWarning < RuntimeError
23 end
24
25 class FatalWarner
26 def puts(warning)
27 raise FatalWarning, warning
28 end
29
30 def write(warning)
31 raise FatalWarning, warning
32 end
33
34 def flush
35 end
36
37 def string
38 ""
39 end
40 end
41
42 DEFAULT_ENV = {
43 "rack.version" => [0,1],
44 "rack.input" => StringIO.new,
45 "rack.errors" => StringIO.new,
46 "rack.multithread" => true,
47 "rack.multiprocess" => true,
48 "rack.run_once" => false,
49 }
50
51 def initialize(app)
52 @app = app
53 end
54
55 def get(uri, opts={}) request("GET", uri, opts) end
56 def post(uri, opts={}) request("POST", uri, opts) end
57 def put(uri, opts={}) request("PUT", uri, opts) end
58 def delete(uri, opts={}) request("DELETE", uri, opts) end
59
60 def request(method="GET", uri="", opts={})
61 env = self.class.env_for(uri, opts.merge(:method => method))
62
63 if opts[:lint]
64 app = Rack::Lint.new(@app)
65 else
66 app = @app
67 end
68
69 errors = env["rack.errors"]
70 MockResponse.new(*(app.call(env) + [errors]))
71 end
72
73 # Return the Rack environment used for a request to +uri+.
74 def self.env_for(uri="", opts={})
75 uri = URI(uri)
76 env = DEFAULT_ENV.dup
77
78 env["REQUEST_METHOD"] = opts[:method] || "GET"
79 env["SERVER_NAME"] = uri.host || "example.org"
80 env["SERVER_PORT"] = uri.port ? uri.port.to_s : "80"
81 env["QUERY_STRING"] = uri.query.to_s
82 env["PATH_INFO"] = (!uri.path || uri.path.empty?) ? "/" : uri.path
83 env["rack.url_scheme"] = uri.scheme || "http"
84
85 env["SCRIPT_NAME"] = opts[:script_name] || ""
86
87 if opts[:fatal]
88 env["rack.errors"] = FatalWarner.new
89 else
90 env["rack.errors"] = StringIO.new
91 end
92
93 opts[:input] ||= ""
94 if String === opts[:input]
95 env["rack.input"] = StringIO.new(opts[:input])
96 else
97 env["rack.input"] = opts[:input]
98 end
99
100 env["CONTENT_LENGTH"] ||= env["rack.input"].length.to_s
101
102 opts.each { |field, value|
103 env[field] = value if String === field
104 }
105
106 env
107 end
108 end
109
110 # Rack::MockResponse provides useful helpers for testing your apps.
111 # Usually, you don't create the MockResponse on your own, but use
112 # MockRequest.
113
114 class MockResponse
115 def initialize(status, headers, body, errors=StringIO.new(""))
116 @status = status.to_i
117
118 @original_headers = headers
119 @headers = Rack::Utils::HeaderHash.new
120 headers.each { |field, values|
121 @headers[field] = values
122 @headers[field] = "" if values.empty?
123 }
124
125 @body = ""
126 body.each { |part| @body << part }
127
128 @errors = errors.string
129 end
130
131 # Status
132 attr_reader :status
133
134 # Headers
135 attr_reader :headers, :original_headers
136
137 def [](field)
138 headers[field]
139 end
140
141
142 # Body
143 attr_reader :body
144
145 def =~(other)
146 @body =~ other
147 end
148
149 def match(other)
150 @body.match other
151 end
152
153
154 # Errors
155 attr_accessor :errors
156
157
158 include Response::Helpers
159 end
160 end