public
Rubygem
Description: Merb Core: All you need. None you don't.
Homepage: http://www.merbivore.com
Clone URL: git://github.com/wycats/merb-core.git
Search Repo:
Merge branch 'rspec' of git://github.com/benburkert/merb-core
wycats (author)
Fri Feb 29 13:05:58 -0800 2008
commit  af2ef094e2582bc37e1606040f9b7108088f1058
tree    8589877ca08428721e3436c2e0178e9513a42f24
parent  f66745664c774ed84b9a3a7740290dbf6ef338d5 parent  c233e7fc252ba5a7850702bf7f014487885cd40c
...
60
61
62
63
 
 
 
64
65
66
...
60
61
62
 
63
64
65
66
67
68
0
@@ -60,7 +60,9 @@
0
   s.add_dependency "rake"
0
   s.add_dependency "json_pure"
0
   s.add_dependency "rspec"
0
- s.add_dependency "rack"
0
+ s.add_dependency "rack"
0
+ s.add_dependency "hpricot"
0
+ s.add_dependency "mime-types"
0
   # Requirements
0
   s.requirements << "install the json gem to get faster json parsing"
0
   s.required_ruby_version = ">= 1.8.4"
...
16
17
18
 
19
20
21
...
16
17
18
19
20
21
22
0
@@ -16,6 +16,7 @@
0
   autoload :ResponderMixin, "merb-core/controller/mixins/responder"
0
   autoload :Router, "merb-core/dispatch/router"
0
   autoload :SessionMixin, "merb-core/dispatch/session"
0
+ autoload :Test, "merb-core/test"
0
 end
0
 
0
 # Require this rather than autoloading it so we can be sure the default template
...
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
0
@@ -1 +1,11 @@
0
+require "hpricot"
0
+
0
+require 'merb-core/test/test_ext/hpricot'
0
+require 'merb-core/test/test_ext/object'
0
+
0
+module Merb; module Test; end; end
0
+
0
+require 'merb-core/test/helpers'
0
+
0
+require 'merb-core/test/matchers'
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0
@@ -1,45 +1 @@
0
-module Merb
0
-
0
- module Test
0
- # FakeRequest sets up a default enviroment which can be overridden either
0
- # by passing and env into initialize or using request['HTTP_VAR'] = 'foo'
0
- class FakeRequest < Request
0
-
0
- # ==== Parameters
0
- # env<Hash>:: Environment options that override the defaults.
0
- # req<StringIO>:: The request to set as input for Rack.
0
- def initialize(env = {}, req = StringIO.new)
0
- env.environmentize_keys!
0
- env['rack.input'] = req
0
- super(DEFAULT_ENV.merge(env))
0
- end
0
-
0
- private
0
- DEFAULT_ENV = Mash.new({
0
- 'SERVER_NAME' => 'localhost',
0
- 'PATH_INFO' => '/',
0
- 'HTTP_ACCEPT_ENCODING' => 'gzip,deflate',
0
- 'HTTP_USER_AGENT' => 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.0.1) Gecko/20060214 Camino/1.0',
0
- 'SCRIPT_NAME' => '/',
0
- 'SERVER_PROTOCOL' => 'HTTP/1.1',
0
- 'HTTP_CACHE_CONTROL' => 'max-age=0',
0
- 'HTTP_ACCEPT_LANGUAGE' => 'en,ja;q=0.9,fr;q=0.9,de;q=0.8,es;q=0.7,it;q=0.7,nl;q=0.6,sv;q=0.5,nb;q=0.5,da;q=0.4,fi;q=0.3,pt;q=0.3,zh-Hans;q=0.2,zh-Hant;q=0.1,ko;q=0.1',
0
- 'HTTP_HOST' => 'localhost',
0
- 'REMOTE_ADDR' => '127.0.0.1',
0
- 'SERVER_SOFTWARE' => 'Mongrel 1.1',
0
- 'HTTP_KEEP_ALIVE' => '300',
0
- 'HTTP_REFERER' => 'http://localhost/',
0
- 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
0
- 'HTTP_VERSION' => 'HTTP/1.1',
0
- 'REQUEST_URI' => '/',
0
- 'SERVER_PORT' => '80',
0
- 'GATEWAY_INTERFACE' => 'CGI/1.2',
0
- 'HTTP_ACCEPT' => 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5',
0
- 'HTTP_CONNECTION' => 'keep-alive',
0
- 'REQUEST_METHOD' => 'GET'
0
- }) unless defined?(DEFAULT_ENV)
0
- end
0
-
0
- end
0
-end
...
1
2
3
4
5
6
7
8
 
 
 
 
 
 
 
...
1
2
 
 
 
 
 
 
3
4
5
6
7
8
9
0
@@ -1,9 +1,10 @@
0
 # This is a place holder to allow plugins etc a place to include
0
 # testing helpers
0
-module Merb
0
- module Test
0
- module Helpers
0
- end
0
- end
0
-end
0
+module Merb::Test::Helpers; end
0
+
0
+require "merb-core/test/helpers/request_helper"
0
+require "merb-core/test/helpers/multipart_request_helper"
0
+require "merb-core/test/helpers/controller_helper"
0
+require "merb-core/test/helpers/route_helper"
0
+require "merb-core/test/helpers/view_helper"
...
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
0
@@ -1 +1,9 @@
0
+module Merb
0
+ module Test
0
+ module ControllerHelper
0
+ include RequestHelper
0
+ include MultipartRequestHelper
0
+ end
0
+ end
0
+end
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
0
@@ -1 +1,176 @@
0
+module Merb::Test::MultipartRequestHelper
0
+ require 'rubygems'
0
+ require 'mime/types'
0
+
0
+ class Param
0
+ attr_accessor :key, :value
0
+
0
+ # ==== Parameters
0
+ # key<~to_s>:: The parameter key.
0
+ # value<~to_s>:: The parameter value.
0
+ def initialize(key, value)
0
+ @key = key
0
+ @value = value
0
+ end
0
+
0
+ # ==== Returns
0
+ # String:: The parameter in a form suitable for a multipart request.
0
+ def to_multipart
0
+ return %(Content-Disposition: form-data; name="#{key}"\r\n\r\n#{value}\r\n)
0
+ end
0
+ end
0
+
0
+ class FileParam
0
+ attr_accessor :key, :filename, :content
0
+
0
+ # ==== Parameters
0
+ # key<~to_s>:: The parameter key.
0
+ # filename<~to_s>:: Name of the file for this parameter.
0
+ # content<~to_s>:: Content of the file for this parameter.
0
+ def initialize(key, filename, content)
0
+ @key = key
0
+ @filename = filename
0
+ @content = content
0
+ end
0
+
0
+ # ==== Returns
0
+ # String::
0
+ # The file parameter in a form suitable for a multipart request.
0
+ def to_multipart
0
+ return %(Content-Disposition: form-data; name="#{key}"; filename="#{filename}"\r\n) + "Content-Type: #{MIME::Types.type_for(@filename)}\r\n\r\n" + content + "\r\n"
0
+ end
0
+ end
0
+
0
+ class Post
0
+ BOUNDARY = '----------0xKhTmLbOuNdArY'
0
+ CONTENT_TYPE = "multipart/form-data, boundary=" + BOUNDARY
0
+
0
+ # ==== Parameters
0
+ # params<Hash>:: Optional params for the controller.
0
+ def initialize(params = {})
0
+ @multipart_params = []
0
+ push_params(params)
0
+ end
0
+
0
+ # Saves the params in an array of multipart params as Param and
0
+ # FileParam objects.
0
+ #
0
+ # ==== Parameters
0
+ # params<Hash>:: The params to add to the multipart params.
0
+ # prefix<~to_s>:: An optional prefix for the request string keys.
0
+ def push_params(params, prefix = nil)
0
+ params.sort_by {|k| k.to_s}.each do |key, value|
0
+ param_key = prefix.nil? ? key : "#{prefix}[#{key}]"
0
+ if value.respond_to?(:read)
0
+ @multipart_params << FileParam.new(param_key, value.path, value.read)
0
+ else
0
+ if value.is_a?(Hash) || value.is_a?(Mash)
0
+ value.keys.each do |k|
0
+ push_params(value, param_key)
0
+ end
0
+ else
0
+ @multipart_params << Param.new(param_key, value)
0
+ end
0
+ end
0
+ end
0
+ end
0
+
0
+ # ==== Returns
0
+ # Array[String, String]:: The query and the content type.
0
+ def to_multipart
0
+ query = @multipart_params.collect { |param| "--" + BOUNDARY + "\r\n" + param.to_multipart }.join("") + "--" + BOUNDARY + "--"
0
+ return query, CONTENT_TYPE
0
+ end
0
+ end
0
+
0
+ # Similar to dispatch_to but allows for sending files inside params.
0
+ #
0
+ # ==== Paramters
0
+ # controller_klass<Controller>::
0
+ # The controller class object that the action should be dispatched to.
0
+ # action<Symbol>:: The action name, as a symbol.
0
+ # params<Hash>::
0
+ # An optional hash that will end up as params in the controller instance.
0
+ # env<Hash>::
0
+ # An optional hash that is passed to the fake request. Any request options
0
+ # should go here (see +fake_request+).
0
+ # &blk:: The block is executed in the context of the controller.
0
+ #
0
+ # ==== Example
0
+ # dispatch_multipart_to(MyController, :create, :my_file => @a_file ) do
0
+ # self.stub!(:current_user).and_return(@user)
0
+ # end
0
+ #
0
+ # ==== Note
0
+ # Set your option to contain a file object to simulate file uploads.
0
+ #
0
+ # Does not use routes.
0
+ #---
0
+ # @public
0
+ def dispatch_multipart_to(controller_klass, action, params = {}, env = {}, &blk)
0
+ request = multipart_fake_request(env, params)
0
+ dispatch_request(request, controller_klass, action, &blk)
0
+ end
0
+
0
+ # An HTTP POST request that operates through the router and uses multipart
0
+ # parameters.
0
+ #
0
+ # ==== Parameters
0
+ # path<String>:: The path that should go to the router as the request uri.
0
+ # params<Hash>::
0
+ # An optional hash that will end up as params in the controller instance.
0
+ # env<Hash>::
0
+ # An optional hash that is passed to the fake request. Any request options
0
+ # should go here (see +fake_request+).
0
+ # block<Proc>:: The block is executed in the context of the controller.
0
+ #
0
+ # ==== Note
0
+ # To include an uploaded file, put a file object as a value in params.
0
+ def multipart_post(path, params = {}, env = {}, &block)
0
+ env[:request_method] = "POST"
0
+ env[:test_with_multipart] = true
0
+ request(path, params, env, &block)
0
+ end
0
+
0
+ # An HTTP PUT request that operates through the router and uses multipart
0
+ # parameters.
0
+ #
0
+ # ==== Parameters
0
+ # path<String>:: The path that should go to the router as the request uri.
0
+ # params<Hash>::
0
+ # An optional hash that will end up as params in the controller instance.
0
+ # env<Hash>::
0
+ # An optional hash that is passed to the fake request. Any request options
0
+ # should go here (see +fake_request+).
0
+ # block<Proc>:: The block is executed in the context of the controller.
0
+ #
0
+ # ==== Note
0
+ # To include an uplaoded file, put a file object as a value in params.
0
+ def multipart_put(path, params = {}, env = {}, &block)
0
+ env[:request_method] = "PUT"
0
+ env[:test_with_multipart] = true
0
+ request(path, params, env, &block)
0
+ end
0
+
0
+ # ==== Parameters
0
+ # env<Hash>::
0
+ # An optional hash that is passed to the fake request. Any request options
0
+ # should go here (see +fake_request+).
0
+ # params<Hash>::
0
+ # An optional hash that will end up as params in the controller instance.
0
+ #
0
+ # ==== Returns
0
+ # FakeRequest::
0
+ # A multipart Request object that is built based on the parameters.
0
+ def multipart_fake_request(env = {}, params = {})
0
+ if params.empty?
0
+ fake_request(env)
0
+ else
0
+ m = Post.new(params)
0
+ body, head = m.to_multipart
0
+ fake_request(env.merge( :content_type => head,
0
+ :content_length => body.length), :post_body => body)
0
+ end
0
+ end
0
+end
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
0
@@ -1 +1,255 @@
0
+require 'tempfile'
0
+
0
+module Merb
0
+ module Test
0
+ module RequestHelper
0
+ # FakeRequest sets up a default enviroment which can be overridden either
0
+ # by passing and env into initialize or using request['HTTP_VAR'] = 'foo'
0
+ class FakeRequest < Request
0
+
0
+ # ==== Parameters
0
+ # env<Hash>:: Environment options that override the defaults.
0
+ # req<StringIO>:: The request to set as input for Rack.
0
+ def initialize(env = {}, req = StringIO.new)
0
+ env.environmentize_keys!
0
+ env['rack.input'] = req
0
+ super(DEFAULT_ENV.merge(env))
0
+ end
0
+
0
+ private
0
+ DEFAULT_ENV = Mash.new({
0
+ 'SERVER_NAME' => 'localhost',
0
+ 'PATH_INFO' => '/',
0
+ 'HTTP_ACCEPT_ENCODING' => 'gzip,deflate',
0
+ 'HTTP_USER_AGENT' => 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.0.1) Gecko/20060214 Camino/1.0',
0
+ 'SCRIPT_NAME' => '/',
0
+ 'SERVER_PROTOCOL' => 'HTTP/1.1',
0
+ 'HTTP_CACHE_CONTROL' => 'max-age=0',
0
+ 'HTTP_ACCEPT_LANGUAGE' => 'en,ja;q=0.9,fr;q=0.9,de;q=0.8,es;q=0.7,it;q=0.7,nl;q=0.6,sv;q=0.5,nb;q=0.5,da;q=0.4,fi;q=0.3,pt;q=0.3,zh-Hans;q=0.2,zh-Hant;q=0.1,ko;q=0.1',
0
+ 'HTTP_HOST' => 'localhost',
0
+ 'REMOTE_ADDR' => '127.0.0.1',
0
+ 'SERVER_SOFTWARE' => 'Mongrel 1.1',
0
+ 'HTTP_KEEP_ALIVE' => '300',
0
+ 'HTTP_REFERER' => 'http://localhost/',
0
+ 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
0
+ 'HTTP_VERSION' => 'HTTP/1.1',
0
+ 'REQUEST_URI' => '/',
0
+ 'SERVER_PORT' => '80',
0
+ 'GATEWAY_INTERFACE' => 'CGI/1.2',
0
+ 'HTTP_ACCEPT' => 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5',
0
+ 'HTTP_CONNECTION' => 'keep-alive',
0
+ 'REQUEST_METHOD' => 'GET'
0
+ }) unless defined?(DEFAULT_ENV)
0
+ end
0
+
0
+ # ==== Parameters
0
+ # env<Hash>:: A hash of environment keys to be merged into the default list.
0
+ # opt<Hash>:: A hash of options (see below).
0
+ #
0
+ # ==== Options (opt)
0
+ # :post_body<String>:: The post body for the request.
0
+ # :req<String>::
0
+ # The request string. This will only be used if :post_body is left out.
0
+ #
0
+ # ==== Returns
0
+ # FakeRequest:: A Request object that is built based on the parameters.
0
+ #
0
+ # ==== Note
0
+ # If you pass a post body, the content-type will be set to URL-encoded.
0
+ #
0
+ #---
0
+ # @public
0
+ def fake_request(env = {}, opt = {})
0
+ if opt[:post_body]
0
+ req = opt[:post_body]
0
+ env[:content_type] ||= "application/x-www-form-urlencoded"
0
+ else
0
+ req = opt[:req]
0
+ end
0
+ FakeRequest.new(env, req ? StringIO.new(req) : nil)
0
+ end
0
+
0
+ # Dispatches an action to the given class. This bypasses the router and is
0
+ # suitable for unit testing of controllers.
0
+ #
0
+ # ==== Parameters
0
+ # controller_klass<Controller>::
0
+ # The controller class object that the action should be dispatched to.
0
+ # action<Symbol>:: The action name, as a symbol.
0
+ # params<Hash>::
0
+ # An optional hash that will end up as params in the controller instance.
0
+ # env<Hash>::
0
+ # An optional hash that is passed to the fake request. Any request options
0
+ # should go here (see +fake_request+).
0
+ # &blk::
0
+ # The controller is yielded to the block provided for actions *prior* to
0
+ # the action being dispatched.
0
+ #
0
+ # ==== Example
0
+ # dispatch_to(MyController, :create, :name => 'Homer' ) do
0
+ # self.stub!(:current_user).and_return(@user)
0
+ # end
0
+ #
0
+ # ==== Note
0
+ # Does not use routes.
0
+ #
0
+ #---
0
+ # @public
0
+ def dispatch_to(controller_klass, action, params = {}, env = {}, &blk)
0
+ request = fake_request(env.merge(
0
+ :query_string => Merb::Request.params_to_query_string(params)))
0
+
0
+ dispatch_request(request, controller_klass, action, &blk)
0
+ end
0
+
0
+ # An HTTP GET request that operates through the router.
0
+ #
0
+ # ==== Parameters
0
+ # path<String>:: The path that should go to the router as the request uri.
0
+ # params<Hash>::
0
+ # An optional hash that will end up as params in the controller instance.
0
+ # env<Hash>::
0
+ # An optional hash that is passed to the fake request. Any request options
0
+ # should go here (see +fake_request+).
0
+ # &block:: The block is executed in the context of the controller.
0
+ def get(path, params = {}, env = {}, &block)
0
+ env[:request_method] = "GET"
0
+ request(path, params, env, &block)
0
+ end
0
+
0
+ # An HTTP POST request that operates through the router.
0
+ #
0
+ # ==== Parameters
0
+ # path<String>:: The path that should go to the router as the request uri.
0
+ # params<Hash>::
0
+ # An optional hash that will end up as params in the controller instance.
0
+ # env<Hash>::
0
+ # An optional hash that is passed to the fake request. Any request options
0
+ # should go here (see fake_request).
0
+ # &block:: The block is executed in the context of the controller.
0
+ def post(path, params = {}, env = {}, &block)
0
+ env[:request_method] = "POST"
0
+ request(path, params, env, &block)
0
+ end
0
+
0
+ # An HTTP PUT request that operates through the router.
0
+ #
0
+ # ==== Parameters
0
+ # path<String>:: The path that should go to the router as the request uri.
0
+ # params<Hash>::
0
+ # An optional hash that will end up as params in the controller instance.
0
+ # env<Hash>::
0
+ # An optional hash that is passed to the fake request. Any request options
0
+ # should go here (see fake_request).
0
+ # &block:: The block is executed in the context of the controller.
0
+ def put(path, params = {}, env = {}, &block)
0
+ env[:request_method] = "PUT"
0
+ request(path, params, env, &block)
0
+ end
0
+
0
+ # An HTTP DELETE request that operates through the router
0
+ #
0
+ # ==== Parameters
0
+ # path<String>:: The path that should go to the router as the request uri.
0
+ # params<Hash>::
0
+ # An optional hash that will end up as params in the controller instance.
0
+ # env<Hash>::
0
+ # An optional hash that is passed to the fake request. Any request options
0
+ # should go here (see fake_request).
0
+ # &block:: The block is executed in the context of the controller.
0
+ def delete(path, params = {}, env = {}, &block)
0
+ env[:request_method] = "DELETE"
0
+ request(path, params, env, &block)
0
+ end
0
+
0
+ # A generic request that checks the router for the controller and action.
0
+ # This request goes through the Merb::Router and finishes at the controller.
0
+ #
0
+ # ==== Parameters
0
+ # path<String>:: The path that should go to the router as the request uri.
0
+ # params<Hash>::
0
+ # An optional hash that will end up as params in the controller instance.
0
+ # env<Hash>::
0
+ # An optional hash that is passed to the fake request. Any request options
0
+ # should go here (see +fake_request+).
0
+ # blk<Proc>:: The block is executed in the context of the controller.
0
+ #
0
+ # ==== Example
0
+ # request(path, :create, :name => 'Homer' ) do
0
+ # self.stub!(:current_user).and_return(@user)
0
+ # end
0
+ #
0
+ # ==== Note
0
+ # Uses Routes.
0
+ #
0
+ #---
0
+ # @semi-public
0
+ def request(path, params = {}, env= {}, &block)
0
+ env[:request_method] ||= "GET"
0
+ env[:request_uri] = path
0
+ multipart = env.delete(:test_with_multipart)
0
+
0
+ request = fake_request(env)
0
+
0
+ opts = check_request_for_route(request) # Check that the request will be routed correctly
0
+ klass = Object.full_const_get(opts.delete(:controller).to_const_string)
0
+ action = opts.delete(:action).to_s
0
+ params.merge!(opts)
0
+
0
+ multipart.nil? ? dispatch_to(klass, action, params, env, &block) : dispatch_multipart_to(klass, action, params, env, &block)
0
+ end
0
+
0
+
0
+ # The workhorse for the dispatch*to helpers.
0
+ #
0
+ # ==== Parameters
0
+ # request<Merb::Test::FakeRequest, Merb::Request>::
0
+ # A request object that has been setup for testing.
0
+ # controller_klass<Merb::Controller>::
0
+ # The class object off the controller to dispatch the action to.
0
+ # action<Symbol>:: The action to dispatch the request to.
0
+ # blk<Proc>:: The block will execute in the context of the controller itself.
0
+ #
0
+ # ==== Returns
0
+ # An instance of +controller_klass+ based on the parameters.
0
+ #
0
+ # ==== Note
0
+ # Does not use routes.
0
+ #
0
+ #---
0
+ # @private
0
+ def dispatch_request(request, controller_klass, action, &blk)
0
+ controller = controller_klass.new(request)
0
+ yield controller if block_given?
0
+ controller._dispatch(action)
0
+
0
+ Merb.logger.info controller._benchmarks.inspect
0
+ Merb.logger.flush
0
+
0
+ controller
0
+ end
0
+
0
+ # Checks to see that a request is routable.
0
+ #
0
+ # ==== Parameters
0
+ # request<Merb::Test::FakeRequest, Merb::Request>::
0
+ # The request object to inspect.
0
+ #
0
+ # ==== Raises
0
+ # Merb::ControllerExceptions::BadRequest::
0
+ # No matching route was found.
0
+ #
0
+ # ==== Returns
0
+ # Hash:: The parameters built based on the matching route.
0
+ def check_request_for_route(request)
0
+ match = ::Merb::Router.match(request)
0
+ if match[0].nil?
0
+ raise ::Merb::ControllerExceptions::BadRequest, "No routes match the request"
0
+ else
0
+ match[1]
0
+ end
0
+ end
0
+ end
0
+ end
0
+end
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
0
@@ -1 +1,34 @@
0
+module Merb
0
+ module Test
0
+ module RouteHelper
0
+ include RequestHelper
0
+
0
+ # Mimics the url method available to controllers.
0
+ #
0
+ # ==== Parameters
0
+ # name<~to_sym>:: The name of the URL to generate.
0
+ # params<Hash>:: Parameters for the route generation.
0
+ #
0
+ # ==== Returns
0
+ # String:: The generated URL.
0
+ def url(name, params={})
0
+ Merb::Router.generate(name, params)
0
+ end
0
+
0
+ # ==== Parameters
0
+ # path<~to_string>:: The URL of the request.
0
+ # method<~to_sym>:: HTTP request method.
0
+ # env<Hash>:: Additional parameters for the request.
0
+ #
0
+ # ==== Returns
0
+ # Hash:: A hash containing the controller and action along with any parameters
0
+ def request_to(path, method = :get, env = {})
0
+ env[:request_method] ||= method.to_s.upcase
0
+ env[:request_uri] = path
0
+
0
+ check_request_for_route(fake_request(env))
0
+ end
0
+ end
0
+ end
0
+end
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
0
@@ -1 +1,77 @@
0
+module Merb
0
+ module Test
0
+ module ViewHelper
0
+
0
+ # small utility class for working with
0
+ # the Hpricot parser class
0
+ class DocumentOutput
0
+ def initialize(response_body)
0
+ @parser = Hpricot.parse(response_body)
0
+ end
0
+
0
+ def content_for(css_query)
0
+ match = @parser.search(css_query).first
0
+ match.inner_text unless match.nil?
0
+ end
0
+
0
+ def content_for_all(css_query)
0
+ matches = @parser.search(css_query).collect{|ele| ele.inner_text}
0
+ end
0
+
0
+ def [](css_query)
0
+ @parser.search(css_query)
0
+ end
0
+ end
0
+
0
+ # returns the inner content of
0
+ # the first tag found by the css query
0
+ def tag(css_query, output = process_output)
0
+ output.content_for(css_query)
0
+ end
0
+
0
+ # returns an array of tag contents
0
+ # for all of the tags found by the
0
+ # css query
0
+ def tags(css_query, output = process_output)
0
+ output.content_for_all(css_query)
0
+ end
0
+
0
+ # returns a raw Hpricot::Elem object
0
+ # for the first result found by the query
0
+ def element(css_query, output = process_output)
0
+ output[css_query].first
0
+ end
0
+
0
+ # returns an array of Hpricot::Elem objects
0
+ # for the results found by the query
0
+ def elements(css_query, output = process_output)
0
+ Hpricot::Elements[*css_query.to_s.split(",").map{|s| s.strip}.map do |query|
0
+ output[query]
0
+ end.flatten]
0
+ end
0
+
0
+ def get_elements(css_query, text, output = nil)
0
+ els = elements(*[css_query, output].compact)
0
+ case text
0
+ when String then els.reject {|t| !t.contains?(text) }
0
+ when Regexp then els.reject {|t| !t.matches?(text) }
0
+ else []
0
+ end
0
+ end
0
+
0
+ protected
0
+ # creates a new DocumentOutput object from the response
0
+ # body if hasn't already been created. This is
0
+ # called automatically by the element and tag methods
0
+ def process_output
0
+ return @output unless @output.nil?
0
+ return @output = DocumentOutput.new(@response_output) unless @response_output.nil?
0
+
0
+ raise "The response output was not in it's usual places, please provide the output" if @controller.nil? || @controller.body.empty?
0
+ @response_output = @controller.body
0
+ @output = DocumentOutput.new(@controller.body)
0
+ end
0
+ end
0
+ end
0
+end
...
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
0
@@ -1 +1,10 @@
0
+module Merb::Test::Rspec; end
0
+
0
+require "merb-core/test/matchers/controller_matchers"
0
+require "merb-core/test/matchers/route_matchers"
0
+require "merb-core/test/matchers/view_matchers"
0
+