remarkable_rails 3.1.8 → 3.1.9

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 (38) hide show
  1. data/CHANGELOG +91 -88
  2. data/LICENSE +20 -20
  3. data/README +80 -80
  4. data/lib/remarkable_rails/action_controller/base.rb +29 -29
  5. data/lib/remarkable_rails/action_controller/macro_stubs.rb +459 -457
  6. data/lib/remarkable_rails/action_controller/matchers/assign_to_matcher.rb +92 -92
  7. data/lib/remarkable_rails/action_controller/matchers/filter_params_matcher.rb +41 -41
  8. data/lib/remarkable_rails/action_controller/matchers/redirect_to_matcher.rb +119 -119
  9. data/lib/remarkable_rails/action_controller/matchers/render_template_matcher.rb +146 -146
  10. data/lib/remarkable_rails/action_controller/matchers/respond_with_matcher.rb +126 -126
  11. data/lib/remarkable_rails/action_controller/matchers/route_matcher.rb +135 -109
  12. data/lib/remarkable_rails/action_controller/matchers/set_cookies_matcher.rb +49 -49
  13. data/lib/remarkable_rails/action_controller/matchers/set_session_matcher.rb +106 -106
  14. data/lib/remarkable_rails/action_controller/matchers/set_the_flash_matcher.rb +54 -54
  15. data/lib/remarkable_rails/action_controller.rb +22 -22
  16. data/lib/remarkable_rails/action_view/base.rb +7 -7
  17. data/lib/remarkable_rails/action_view.rb +18 -18
  18. data/lib/remarkable_rails/active_orm.rb +19 -19
  19. data/lib/remarkable_rails.rb +30 -30
  20. data/locale/en.yml +110 -110
  21. data/spec/action_controller/assign_to_matcher_spec.rb +142 -142
  22. data/spec/action_controller/filter_params_matcher_spec.rb +64 -64
  23. data/spec/action_controller/macro_stubs_spec.rb +234 -208
  24. data/spec/action_controller/redirect_to_matcher_spec.rb +102 -102
  25. data/spec/action_controller/render_template_matcher_spec.rb +251 -251
  26. data/spec/action_controller/respond_with_matcher_spec.rb +223 -223
  27. data/spec/action_controller/route_matcher_spec.rb +96 -79
  28. data/spec/action_controller/set_cookies_matcher_spec.rb +149 -149
  29. data/spec/action_controller/set_session_matcher_spec.rb +141 -141
  30. data/spec/action_controller/set_the_flash_matcher_spec.rb +93 -93
  31. data/spec/application/application.rb +15 -15
  32. data/spec/application/tasks_controller.rb +34 -34
  33. data/spec/functional_builder.rb +88 -88
  34. data/spec/rcov.opts +2 -2
  35. data/spec/remarkable_rails_spec.rb +5 -5
  36. data/spec/spec.opts +4 -4
  37. data/spec/spec_helper.rb +42 -42
  38. metadata +7 -7
@@ -1,50 +1,50 @@
1
- module Remarkable
2
- module ActionController
3
-
4
- # Macro stubs makes stubs and expectations easier, more readable and DRY.
5
- #
6
- # == Example
7
- #
8
- # Let's jump off to an example:
9
- #
10
- # describe ProjectsController do
11
- # describe :get => :show, :id => 37 do
12
- # expects :find, :on => Project, :with => '37', :returns => proc { mock_project }
13
- #
14
- # should_assign_to :project, :with => proc { mock_project }
15
- # should_render_template 'show'
16
- #
17
- # describe Mime::XML do
18
- # should_assign_to :project
19
- # should_respond_with_content_type Mime::XML
20
- # end
21
- # end
22
- # end
23
- #
24
- # See how the spec is readable: a ProjectsController responding to get show
25
- # expects :find on Project which a mock project and then should assign to
26
- # project and render template 'show'.
27
- #
28
- # Each macro before asserting will check if an action was already performed and
29
- # if not, it runs the expectations and call the action.
30
- #
31
- # In other words, should assign to macro is basically doing:
32
- #
33
- # it 'should assign to project' do
34
- # Project.should_receive(:find).with('37').and_return(mock_project)
35
- # get :show, :id => '37'
36
- # assigns(:project).should == mock_project
37
- # end
38
- #
39
- # By default, all macros perform expectations. You can change
40
- # this behavior sending :with_stubs or :with_expectations as options:
41
- #
42
- # should_assign_to :project, :with_stubs => true
43
- # should_render_template 'show', :with_expectations => false
44
- #
45
- # This also works in the rspec way:
46
- #
47
- # it { should assign_to(:project).with_stubs }
1
+ module Remarkable
2
+ module ActionController
3
+
4
+ # Macro stubs makes stubs and expectations easier, more readable and DRY.
5
+ #
6
+ # == Example
7
+ #
8
+ # Let's jump off to an example:
9
+ #
10
+ # describe ProjectsController do
11
+ # describe :get => :show, :id => 37 do
12
+ # expects :find, :on => Project, :with => '37', :returns => proc { mock_project }
13
+ #
14
+ # should_assign_to :project, :with => proc { mock_project }
15
+ # should_render_template 'show'
16
+ #
17
+ # describe Mime::XML do
18
+ # should_assign_to :project
19
+ # should_respond_with_content_type Mime::XML
20
+ # end
21
+ # end
22
+ # end
23
+ #
24
+ # See how the spec is readable: a ProjectsController responding to get show
25
+ # expects :find on Project which a mock project and then should assign to
26
+ # project and render template 'show'.
27
+ #
28
+ # Each macro before asserting will check if an action was already performed and
29
+ # if not, it runs the expectations and call the action.
30
+ #
31
+ # In other words, should assign to macro is basically doing:
32
+ #
33
+ # it 'should assign to project' do
34
+ # Project.should_receive(:find).with('37').and_return(mock_project)
35
+ # get :show, :id => '37'
36
+ # assigns(:project).should == mock_project
37
+ # end
38
+ #
39
+ # By default, all macros perform expectations. You can change
40
+ # this behavior sending :with_stubs or :with_expectations as options:
41
+ #
42
+ # should_assign_to :project, :with_stubs => true
43
+ # should_render_template 'show', :with_expectations => false
44
+ #
45
+ # This also works in the rspec way:
46
+ #
47
+ # it { should assign_to(:project).with_stubs }
48
48
  # it { should render_template('show').with_expectations(false) }
49
49
  #
50
50
  # == Attention!
@@ -60,166 +60,166 @@ module Remarkable
60
60
  #
61
61
  # And it won't work. The right way to handle this is:
62
62
  #
63
- # expects :comment_ids=, :on => Post, :with => [[1,2,3]]
64
- #
65
- # == mock_models
66
- #
67
- # You don't have to play with proc all the time. You can call mock_models which
68
- # creates two class methods that simply returns a proc and a instance method that
63
+ # expects :comment_ids=, :on => Post, :with => [[1,2,3]]
64
+ #
65
+ # == mock_models
66
+ #
67
+ # You don't have to play with proc all the time. You can call mock_models which
68
+ # creates two class methods that simply returns a proc and a instance method that
69
69
  # do the actual mock.
70
70
  #
71
71
  # describe ProjectsController do
72
72
  # mock_models :project
73
73
  #
74
- # And it creates:
75
- #
76
- # def self.project_proc
77
- # proc { mock_project }
74
+ # And it creates:
75
+ #
76
+ # def self.project_proc
77
+ # proc { mock_project }
78
78
  # end
79
79
  #
80
80
  # # To be used on index actions
81
- # def self.projects_proc
82
- # proc { [mock_project] }
83
- # end
84
- #
85
- # def mock_project(stubs={})
86
- # @project ||= mock_model(Project, stubs)
87
- # end
88
- #
89
- # Then you can replace those lines:
90
- #
91
- # expects :find, :on => Project, :with => '37', :returns => proc { mock_project }
92
- # should_assign_to :project, :with => proc { mock_project }
93
- #
94
- # For:
95
- #
96
- # expects :find, :on => Project, :with => '37', :returns => project_proc
97
- # should_assign_to :project, :with => project_proc
98
- #
99
- # = Give me more!
100
- #
81
+ # def self.projects_proc
82
+ # proc { [mock_project] }
83
+ # end
84
+ #
85
+ # def mock_project(stubs={})
86
+ # @project ||= mock_model(Project, stubs)
87
+ # end
88
+ #
89
+ # Then you can replace those lines:
90
+ #
91
+ # expects :find, :on => Project, :with => '37', :returns => proc { mock_project }
92
+ # should_assign_to :project, :with => proc { mock_project }
93
+ #
94
+ # For:
95
+ #
96
+ # expects :find, :on => Project, :with => '37', :returns => project_proc
97
+ # should_assign_to :project, :with => project_proc
98
+ #
99
+ # = Give me more!
100
+ #
101
101
  # If you need to set the example group description, you can also call <tt>get</tt>,
102
- # <tt>post</tt>, <tt>put</tt> and <tt>delete</tt> methods:
103
- #
104
- # describe 'my description' do
105
- # get :show, :id => 37
106
- #
107
- # Things start to get even better when we start to talk about nested resources.
108
- # After our ProjectsController is created, we want to create a TasksController:
109
- #
110
- # describe TasksController do
111
- # params :project_id => '42' #=> define params for all requests
112
- #
113
- # # Those two expectations get inherited in all describe groups below
114
- # expects :find_by_title, :on => Project, :with => '42', :returns => project_proc
115
- # expects :tasks, :and_return => Task
116
- #
117
- # describe :get => :show, :id => '37' do
118
- # expects :find, :with => '37', :and_return => task_proc
119
- #
120
- # should_assign_to :project, :task
121
- # should_render_template 'show'
122
- # end
123
- # end
124
- #
125
- # As you noticed, you can define parameters that will be available to all requests,
126
- # using the method <tt>params</tt>.
127
- #
102
+ # <tt>post</tt>, <tt>put</tt> and <tt>delete</tt> methods:
103
+ #
104
+ # describe 'my description' do
105
+ # get :show, :id => 37
106
+ #
107
+ # Things start to get even better when we start to talk about nested resources.
108
+ # After our ProjectsController is created, we want to create a TasksController:
109
+ #
110
+ # describe TasksController do
111
+ # params :project_id => '42' #=> define params for all requests
112
+ #
113
+ # # Those two expectations get inherited in all describe groups below
114
+ # expects :find_by_title, :on => Project, :with => '42', :returns => project_proc
115
+ # expects :tasks, :and_return => Task
116
+ #
117
+ # describe :get => :show, :id => '37' do
118
+ # expects :find, :with => '37', :and_return => task_proc
119
+ #
120
+ # should_assign_to :project, :task
121
+ # should_render_template 'show'
122
+ # end
123
+ # end
124
+ #
125
+ # As you noticed, you can define parameters that will be available to all requests,
126
+ # using the method <tt>params</tt>.
127
+ #
128
128
  # Finally if you need to write a spec by hand, you can invoke the action and
129
- # expectations with run_action!, run_expectations! and run_stubs!. Examples:
130
- #
131
- # describe :get => :new do
132
- # expects :new, :on => Project, :returns => project_proc
133
- #
134
- # it "should do something different" do
135
- # run_action!
136
- # # do you assertions here
137
- # end
138
- # end
139
- #
140
- # = Performance!
141
- #
129
+ # expectations with run_action!, run_expectations! and run_stubs!. Examples:
130
+ #
131
+ # describe :get => :new do
132
+ # expects :new, :on => Project, :returns => project_proc
133
+ #
134
+ # it "should do something different" do
135
+ # run_action!
136
+ # # do you assertions here
137
+ # end
138
+ # end
139
+ #
140
+ # = Performance!
141
+ #
142
142
  # Remarkable comes with a new way to speed up your tests. It performs the
143
- # action inside a before(:all), so you can do:
144
- #
145
- # describe "responding to GET show" do
146
- # get! :show, :id => 37
147
- #
148
- # should_assign_to :task
149
- # should_render_template :show
150
- # end
151
- #
152
- # Or in the compact way:
153
- #
154
- # describe :get! => :show, :id => 37
155
- #
143
+ # action inside a before(:all), so you can do:
144
+ #
145
+ # describe "responding to GET show" do
146
+ # get! :show, :id => 37
147
+ #
148
+ # should_assign_to :task
149
+ # should_render_template :show
150
+ # end
151
+ #
152
+ # Or in the compact way:
153
+ #
154
+ # describe :get! => :show, :id => 37
155
+ #
156
156
  # The action will be performed just once before running the macros. If any
157
157
  # error happens while performing the action, rspec will output an error
158
- # but ALL the examples inside the example group (describe) won't be run.
159
- #
158
+ # but ALL the examples inside the example group (describe) won't be run.
159
+ #
160
160
  # By now, the bang methods works only when integrate_views is true and this
161
- # is when you must see a bigger performance gain.
162
- #
161
+ # is when you must see a bigger performance gain.
162
+ #
163
163
  # This feature comes with some rspec and rspec rails tweakings. So if you want
164
164
  # to do something before the action is performed (stubs something or log
165
- # someone in session), you have to do it giving a block to the action method:
166
- #
167
- # get! :show, :id => 37 do
168
- # login_as(mock_user)
169
- # end
170
- #
171
- # You can still use the compact way and give the block:
172
- #
173
- # describe :get => :show, :id => 37 do
174
- # get! do
175
- # login_as(mock_user)
176
- # end
177
- # end
178
- #
179
- module MacroStubs
180
- HTTP_VERBS_METHODS = [:get, :get!, :post, :post!, :put, :put!, :delete, :delete!]
181
-
182
- def self.included(base) #:nodoc:
183
- base.extend ClassMethods
184
- base.class_inheritable_reader :expects_chain, :default_action, :default_mime,
165
+ # someone in session), you have to do it giving a block to the action method:
166
+ #
167
+ # get! :show, :id => 37 do
168
+ # login_as(mock_user)
169
+ # end
170
+ #
171
+ # You can still use the compact way and give the block:
172
+ #
173
+ # describe :get => :show, :id => 37 do
174
+ # get! do
175
+ # login_as(mock_user)
176
+ # end
177
+ # end
178
+ #
179
+ module MacroStubs
180
+ HTTP_VERBS_METHODS = [:get, :get!, :post, :post!, :put, :put!, :delete, :delete!]
181
+
182
+ def self.included(base) #:nodoc:
183
+ base.extend ClassMethods
184
+ base.class_inheritable_reader :expects_chain, :default_action, :default_mime,
185
185
  :default_verb, :default_params, :default_xhr,
186
- :before_all_block
187
- end
188
-
189
- module ClassMethods
190
-
191
- # Creates a chain that will be evaluated as stub or expectation. The
186
+ :before_all_block
187
+ end
188
+
189
+ module ClassMethods
190
+
191
+ # Creates a chain that will be evaluated as stub or expectation. The
192
192
  # first parameter is the method expected. You can also specify multiple
193
193
  # methods to stub and give a block to calculate the returned value. See
194
194
  # examples below.
195
- #
196
- # == Options
197
- #
198
- # * <tt>:on</tt> - Tell which object will receive the expected method.
199
- # This option is always required.
200
- #
201
- # * <tt>:with</tt> - Tell each parameters will be sent with the expected
202
- # method. This option is used only in expectations and is optional.
203
- #
204
- # * <tt>:returns</tt> - Tell what the expectations should return. Not
205
- # required.
206
- #
207
- # * <tt>:times</tt> - The number of times the object will receive the
195
+ #
196
+ # == Options
197
+ #
198
+ # * <tt>:on</tt> - Tell which object will receive the expected method.
199
+ # This option is always required.
200
+ #
201
+ # * <tt>:with</tt> - Tell each parameters will be sent with the expected
202
+ # method. This option is used only in expectations and is optional.
203
+ #
204
+ # * <tt>:returns</tt> - Tell what the expectations should return. Not
205
+ # required.
206
+ #
207
+ # * <tt>:times</tt> - The number of times the object will receive the
208
208
  # method. Used only in expectations and when not given, defaults to 1.
209
209
  #
210
210
  # * <tt>:ordered</tt> - When true specifies that expectations should
211
- # be received in order.
212
- #
213
- # == Example
214
- #
211
+ # be received in order.
212
+ #
213
+ # == Example
214
+ #
215
215
  # expects :new, :on => Project, :returns => :project_proc, :times => 2
216
216
  #
217
217
  # expects :new, :find, :on => Project, :returns => :project_proc
218
218
  #
219
219
  # expects :human_attribute_name, :on => Project, :with => :title do |attr|
220
220
  # attr.to_s.humanize
221
- # end
222
- #
221
+ # end
222
+ #
223
223
  def expects(*args, &block)
224
224
  options = args.extract_options!
225
225
  options.assert_valid_keys(:on, :with, :returns, :times, :ordered)
@@ -227,34 +227,34 @@ module Remarkable
227
227
  args.each do |arg|
228
228
  write_inheritable_array(:expects_chain, [ [ arg, options, block] ])
229
229
  end
230
- end
231
-
232
- # The mime type of the request. The value given will be called transformed
233
- # into a string and set in the @request.env['HTTP_ACCEPT'] variable.
234
- #
235
- # == Examples
236
- #
237
- # mime Mime::XML
238
- # mime 'application/xml+rss'
239
- #
240
- def mime(mime)
241
- write_inheritable_attribute(:default_mime, mime.to_s)
242
- end
243
-
244
- # The params used for the request. Calls are always nested:
245
- #
246
- # == Examples
247
- #
248
- # describe TasksController do
249
- # params :project_id => 42
250
- #
251
- # describe :get => :show, :id => 37 do
252
- # # will request with params {:id => 37, :project_id => 42}
253
- # end
254
- # end
255
- #
256
- def params(params)
257
- write_inheritable_hash(:default_params, params)
230
+ end
231
+
232
+ # The mime type of the request. The value given will be called transformed
233
+ # into a string and set in the @request.env['HTTP_ACCEPT'] variable.
234
+ #
235
+ # == Examples
236
+ #
237
+ # mime Mime::XML
238
+ # mime 'application/xml+rss'
239
+ #
240
+ def mime(mime)
241
+ write_inheritable_attribute(:default_mime, mime.to_s)
242
+ end
243
+
244
+ # The params used for the request. Calls are always nested:
245
+ #
246
+ # == Examples
247
+ #
248
+ # describe TasksController do
249
+ # params :project_id => 42
250
+ #
251
+ # describe :get => :show, :id => 37 do
252
+ # # will request with params {:id => 37, :project_id => 42}
253
+ # end
254
+ # end
255
+ #
256
+ def params(params)
257
+ write_inheritable_hash(:default_params, params)
258
258
  end
259
259
 
260
260
  # Sets the request to perform a XmlHttpRequest.
@@ -267,183 +267,183 @@ module Remarkable
267
267
  #
268
268
  def xhr!(bool=true)
269
269
  write_inheritable_attribute(:default_xhr, bool)
270
- end
271
-
272
- [:get, :post, :put, :delete].each do |verb|
273
- module_eval <<-VERB, __FILE__, __LINE__
274
- # Declares that we want to do a #{verb} request in the given action
275
- # and with the given params.
276
- #
277
- # == Examples
278
- #
279
- # #{verb} :action, :id => 42
280
- #
281
- def #{verb}(action, params={})
282
- params(params)
283
- write_inheritable_attribute(:default_verb, #{verb.inspect})
284
- write_inheritable_attribute(:default_action, action)
285
- end
286
- VERB
287
- end
288
-
289
- [:get!, :post!, :put!, :delete!].each do |verb|
290
- module_eval <<-VERB, __FILE__, __LINE__
291
- # Declares that we want to do a #{verb} request in the given action
292
- # and with the given params, but the action is performed just once
293
- # in the describe group. In other words, it's performed in a
294
- # before(:all) filter.
295
- #
296
- # == Examples
297
- #
298
- # #{verb} :action, :id => 42
299
- #
300
- def #{verb}(action=nil, params={}, &block)
301
- #{verb.to_s.chop}(action, params) if action
302
- write_inheritable_array(:before_all_block, [block]) if block
303
- run_callbacks_once!
304
- end
305
- VERB
306
- end
307
-
308
- # Undefine the method run_callbacks so rspec won't run them in the
309
- # before and after :each cycle. Then we redefine it as run_callbacks_once,
310
- # which will be used as an before(:all) and after(:all) filter.
311
- #
312
- def run_callbacks_once!(&block) #:nodoc:
313
- unless instance_methods.any?{|m| m.to_s == 'run_callbacks_once' }
314
- alias_method :run_callbacks_once, :run_callbacks
315
- class_eval "def run_callbacks(*args); end"
316
-
317
- before(:all) do
318
- setup_mocks_for_rspec
319
- run_callbacks_once :setup
320
-
321
- before_all_block.each do |block|
322
- instance_eval(&block)
323
- end if before_all_block
324
-
325
- run_action!
326
- verify_mocks_for_rspec
327
- teardown_mocks_for_rspec
328
- end
329
-
330
- after(:all) do
331
- run_callbacks_once :teardown
332
- end
333
- end
334
- end
335
-
336
- # Overwrites describe to provide quick action description with I18n.
337
- #
338
- # You can now do:
339
- #
340
- # describe :get => :show, :id => 37
341
- #
342
- # Which is the same as:
343
- #
344
- # describe 'responding to #GET show' do
345
- # get :show, :id => 37
346
- #
347
- # And do this:
348
- #
349
- # describe Mime::XML
350
- #
351
- # Which is the same as:
352
- #
353
- # describe 'with xml' do
354
- # mime Mime::XML
355
- #
356
- # The string can be localized using I18n. An example yml file is:
357
- #
358
- # locale:
359
- # remarkable:
360
- # action_controller:
361
- # responding: "responding to #{{verb}} {{action}}"
362
- # mime_type: "with {{format}} ({{content_type}})"
363
- #
364
- # And load the locale file with:
365
- #
366
- # Remarkable.add_locale locale_path
367
- #
368
- def describe(*args, &block)
369
- options = args.first.is_a?(Hash) ? args.first : {}
370
- verb = (options.keys & HTTP_VERBS_METHODS).first
371
-
372
- if verb
373
- action = options.delete(verb)
374
- verb = verb.to_s
375
-
376
- description = Remarkable.t 'remarkable.action_controller.responding',
377
- :default => "responding to \#{{verb}} {{action}}",
378
- :verb => verb.sub('!', '').upcase, :action => action
379
-
380
- send_args = [ verb, action, options ]
381
- elsif args.first.is_a?(Mime::Type)
382
- mime = args.first
383
-
384
- description = Remarkable.t 'remarkable.action_controller.mime_type',
385
- :default => "with #{mime.to_sym}",
386
- :format => mime.to_sym, :content_type => mime.to_s
387
-
388
- send_args = [ :mime, mime ]
389
- else # return if no special type was found
390
- return super(*args, &block)
391
- end
392
-
393
- args.shift
394
- args.unshift(description)
395
-
396
- # Creates an example group, send the method and eval the given block.
397
- #
398
- example_group = super(*args) do
399
- send(*send_args)
400
- instance_eval(&block)
401
- end
402
- end
403
-
404
- # Creates mock methods automatically.
405
- #
270
+ end
271
+
272
+ [:get, :post, :put, :delete].each do |verb|
273
+ module_eval <<-VERB, __FILE__, __LINE__
274
+ # Declares that we want to do a #{verb} request in the given action
275
+ # and with the given params.
276
+ #
277
+ # == Examples
278
+ #
279
+ # #{verb} :action, :id => 42
280
+ #
281
+ def #{verb}(action, params={})
282
+ params(params)
283
+ write_inheritable_attribute(:default_verb, #{verb.inspect})
284
+ write_inheritable_attribute(:default_action, action)
285
+ end
286
+ VERB
287
+ end
288
+
289
+ [:get!, :post!, :put!, :delete!].each do |verb|
290
+ module_eval <<-VERB, __FILE__, __LINE__
291
+ # Declares that we want to do a #{verb} request in the given action
292
+ # and with the given params, but the action is performed just once
293
+ # in the describe group. In other words, it's performed in a
294
+ # before(:all) filter.
295
+ #
296
+ # == Examples
297
+ #
298
+ # #{verb} :action, :id => 42
299
+ #
300
+ def #{verb}(action=nil, params={}, &block)
301
+ #{verb.to_s.chop}(action, params) if action
302
+ write_inheritable_array(:before_all_block, [block]) if block
303
+ run_callbacks_once!
304
+ end
305
+ VERB
306
+ end
307
+
308
+ # Undefine the method run_callbacks so rspec won't run them in the
309
+ # before and after :each cycle. Then we redefine it as run_callbacks_once,
310
+ # which will be used as an before(:all) and after(:all) filter.
311
+ #
312
+ def run_callbacks_once!(&block) #:nodoc:
313
+ unless instance_methods.any?{|m| m.to_s == 'run_callbacks_once' }
314
+ alias_method :run_callbacks_once, :run_callbacks
315
+ class_eval "def run_callbacks(*args); end"
316
+
317
+ before(:all) do
318
+ setup_mocks_for_rspec
319
+ run_callbacks_once :setup
320
+
321
+ before_all_block.each do |block|
322
+ instance_eval(&block)
323
+ end if before_all_block
324
+
325
+ run_action!
326
+ verify_mocks_for_rspec
327
+ teardown_mocks_for_rspec
328
+ end
329
+
330
+ after(:all) do
331
+ run_callbacks_once :teardown
332
+ end
333
+ end
334
+ end
335
+
336
+ # Overwrites describe to provide quick action description with I18n.
337
+ #
338
+ # You can now do:
339
+ #
340
+ # describe :get => :show, :id => 37
341
+ #
342
+ # Which is the same as:
343
+ #
344
+ # describe 'responding to #GET show' do
345
+ # get :show, :id => 37
346
+ #
347
+ # And do this:
348
+ #
349
+ # describe Mime::XML
350
+ #
351
+ # Which is the same as:
352
+ #
353
+ # describe 'with xml' do
354
+ # mime Mime::XML
355
+ #
356
+ # The string can be localized using I18n. An example yml file is:
357
+ #
358
+ # locale:
359
+ # remarkable:
360
+ # action_controller:
361
+ # responding: "responding to #{{verb}} {{action}}"
362
+ # mime_type: "with {{format}} ({{content_type}})"
363
+ #
364
+ # And load the locale file with:
365
+ #
366
+ # Remarkable.add_locale locale_path
367
+ #
368
+ def describe(*args, &block)
369
+ options = args.first.is_a?(Hash) ? args.first : {}
370
+ verb = (options.keys & HTTP_VERBS_METHODS).first
371
+
372
+ if verb
373
+ action = options.delete(verb)
374
+ verb = verb.to_s
375
+
376
+ description = Remarkable.t 'remarkable.action_controller.responding',
377
+ :default => "responding to \#{{verb}} {{action}}",
378
+ :verb => verb.sub('!', '').upcase, :action => action
379
+
380
+ send_args = [ verb, action, options ]
381
+ elsif args.first.is_a?(Mime::Type)
382
+ mime = args.first
383
+
384
+ description = Remarkable.t 'remarkable.action_controller.mime_type',
385
+ :default => "with #{mime.to_sym}",
386
+ :format => mime.to_sym, :content_type => mime.to_s
387
+
388
+ send_args = [ :mime, mime ]
389
+ else # return if no special type was found
390
+ return super(*args, &block)
391
+ end
392
+
393
+ args.shift
394
+ args.unshift(description)
395
+
396
+ # Creates an example group, send the method and eval the given block.
397
+ #
398
+ example_group = super(*args) do
399
+ send(*send_args)
400
+ instance_eval(&block)
401
+ end
402
+ end
403
+
404
+ # Creates mock methods automatically.
405
+ #
406
406
  # == Options
407
407
  #
408
408
  # * <tt>:as</tt> - Used to set the model . For example, if you have
409
409
  # Admin::Task model, you have to tell the name of the class to be
410
410
  # mocked:
411
411
  #
412
- # mock_models :admin_task, :as => "Admin::Task"
413
- #
414
- # * <tt>:class_method</tt> - When set to false, does not create the
415
- # class method which returns a proc.
416
- #
417
- # == Examples
418
- #
419
- # Doing this:
420
- #
421
- # describe ProjectsController do
422
- # mock_models :project
423
- # end
424
- #
425
- # Will create one instance and two class mock methods for you:
426
- #
427
- # def self.project_proc
428
- # proc { mock_project }
412
+ # mock_models :admin_task, :as => "Admin::Task"
413
+ #
414
+ # * <tt>:class_method</tt> - When set to false, does not create the
415
+ # class method which returns a proc.
416
+ #
417
+ # == Examples
418
+ #
419
+ # Doing this:
420
+ #
421
+ # describe ProjectsController do
422
+ # mock_models :project
423
+ # end
424
+ #
425
+ # Will create one instance and two class mock methods for you:
426
+ #
427
+ # def self.project_proc
428
+ # proc { mock_project }
429
429
  # end
430
430
  #
431
431
  # # To be used on index actions
432
- # def self.projects_procs
433
- # proc { [ mock_project ] }
434
- # end
435
- #
436
- # def mock_project(stubs={})
437
- # @project ||= mock_model(Project, stubs)
432
+ # def self.projects_procs
433
+ # proc { [ mock_project ] }
438
434
  # end
439
- #
440
- # If you want to create just the instance method, you can give
441
- # :class_method => false as option.
442
- #
443
- def mock_models(*models)
444
- options = models.extract_options!
445
- options = { :class_method => true }.merge(options)
446
-
435
+ #
436
+ # def mock_project(stubs={})
437
+ # @project ||= mock_model(Project, stubs)
438
+ # end
439
+ #
440
+ # If you want to create just the instance method, you can give
441
+ # :class_method => false as option.
442
+ #
443
+ def mock_models(*models)
444
+ options = models.extract_options!
445
+ options = { :class_method => true }.merge(options)
446
+
447
447
  models.each do |model|
448
448
  model = model.to_s
449
449
  klass = options[:as] || model.classify
@@ -457,36 +457,36 @@ module Remarkable
457
457
  alias :mock_#{model.pluralize} :#{model.pluralize}_proc
458
458
  METHOD
459
459
  end
460
-
461
- self.class_eval <<-METHOD
462
- def mock_#{model}(stubs={})
463
- @#{model} ||= mock_model(#{klass}, stubs)
464
- end
465
- METHOD
466
- end
460
+
461
+ self.class_eval <<-METHOD
462
+ def mock_#{model}(stubs={})
463
+ @#{model} ||= mock_model(#{klass}, stubs)
464
+ end
465
+ METHOD
466
+ end
467
467
  end
468
- alias :mock_model :mock_models
469
-
470
- end
471
-
472
- protected
473
-
474
- # Evaluates the expectation chain as stub or expectations.
475
- #
476
- def evaluate_expectation_chain(use_expectations=true) #:nodoc:
477
- return if self.expects_chain.nil?
478
-
468
+ alias :mock_model :mock_models
469
+
470
+ end
471
+
472
+ protected
473
+
474
+ # Evaluates the expectation chain as stub or expectations.
475
+ #
476
+ def evaluate_expectation_chain(use_expectations=true) #:nodoc:
477
+ return if self.expects_chain.nil?
478
+
479
479
  self.expects_chain.each do |method, options, block|
480
- object = evaluate_value(options[:on])
481
- raise ScriptError, "You have to give me :on as an option when calling :expects." if object.nil?
482
-
483
- if use_expectations
480
+ object = evaluate_value(options[:on])
481
+ raise ScriptError, "You have to give me :on as an option when calling :expects." if object.nil?
482
+
483
+ if use_expectations
484
484
  chain = object.should_receive(method)
485
485
 
486
486
  if options.key?(:with)
487
487
  with = evaluate_value(options[:with])
488
488
 
489
- chain = if with.is_a?(Array)
489
+ chain = if with.is_a?(Array)
490
490
  chain.with(*with)
491
491
  else
492
492
  chain.with(with)
@@ -497,74 +497,76 @@ module Remarkable
497
497
  chain = chain.exactly(times).times
498
498
 
499
499
  chain = chain.ordered if options[:ordered]
500
- else
501
- chain = object.stub!(method)
500
+ else
501
+ chain = object.stub!(method)
502
502
  end
503
503
 
504
- chain = if block
504
+ chain = if block
505
505
  chain.and_return(&block)
506
506
  else
507
507
  return_value = evaluate_value(options[:returns])
508
508
  chain.and_return(return_value)
509
- end
510
- end
511
- end
512
-
513
- # Instance method run_stubs! if someone wants to declare additional
514
- # tests and call the stubs inside of it.
515
- #
516
- def run_stubs!
517
- evaluate_expectation_chain(false)
518
- end
519
-
520
- # Instance method run_expectations! if someone wants to declare
521
- # additional tests and call the stubs inside of it.
522
- #
523
- def run_expectations!
524
- evaluate_expectation_chain(true)
525
- end
526
-
527
- # Run the action declared in the describe group, but before runs also
528
- # the expectations. If an action was already performed, it doesn't run
529
- # anything at all and returns false.
530
- #
531
- # The first parameter is if you want to run expectations or stubs. You
532
- # can also supply the verb (get, post, put or delete), which action to
509
+ end
510
+ end
511
+ end
512
+
513
+ # Instance method run_stubs! if someone wants to declare additional
514
+ # tests and call the stubs inside of it.
515
+ #
516
+ def run_stubs!
517
+ evaluate_expectation_chain(false)
518
+ end
519
+
520
+ # Instance method run_expectations! if someone wants to declare
521
+ # additional tests and call the stubs inside of it.
522
+ #
523
+ def run_expectations!
524
+ evaluate_expectation_chain(true)
525
+ end
526
+
527
+ # Run the action declared in the describe group, but before runs also
528
+ # the expectations. If an action was already performed, it doesn't run
529
+ # anything at all and returns false.
530
+ #
531
+ # The first parameter is if you want to run expectations or stubs. You
532
+ # can also supply the verb (get, post, put or delete), which action to
533
533
  # call, parameters, the mime type and if a xhr should be performed. If
534
534
  # any of those parameters are supplied, they override the current
535
- # definition.
536
- #
537
- def run_action!(use_expectations=true, verb=nil, action=nil, params=nil, mime=nil, xhr=nil)
538
- return false if controller.send(:performed?)
539
-
540
- evaluate_expectation_chain(use_expectations)
541
-
542
- mime ||= default_mime
543
- verb ||= default_verb
544
- action ||= default_action
535
+ # definition.
536
+ #
537
+ def run_action!(use_expectations=true, verb=nil, action=nil, params=nil, mime=nil, xhr=nil)
538
+ return false if controller.send(:performed?)
539
+
540
+ evaluate_expectation_chain(use_expectations)
541
+
542
+ mime ||= default_mime
543
+ verb ||= default_verb
544
+ action ||= default_action
545
545
  params ||= default_params
546
- xhr ||= default_xhr
547
-
548
- raise ScriptError, "No action was performed or declared." unless verb && action
549
-
546
+ xhr ||= default_xhr
547
+
548
+ raise ScriptError, "No action was performed or declared." unless verb && action
549
+
550
550
  request.env["HTTP_ACCEPT"] ||= mime.to_s if mime
551
- request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' if xhr
552
- send(verb, action, params)
553
- end
554
-
555
- # Evaluate a given value.
556
- #
557
- # This allows procs to be given to the expectation chain and they will
558
- # be evaluated in the instance binding.
559
- #
560
- def evaluate_value(duck) #:nodoc:
561
- if duck.is_a?(Proc)
562
- self.instance_eval(&duck)
563
- else
564
- duck
565
- end
566
- end
567
-
568
- end
569
- end
570
- end
551
+ request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' if xhr
552
+ send(verb, action, params)
553
+ end
554
+
555
+ # Evaluate a given value.
556
+ #
557
+ # This allows procs to be given to the expectation chain and they will
558
+ # be evaluated in the instance binding.
559
+ #
560
+ def evaluate_value(duck) #:nodoc:
561
+ if duck.is_a?(Proc)
562
+ self.instance_eval(&duck)
563
+ elsif duck.is_a?(Array)
564
+ duck.map{|child_duck| evaluate_value(child_duck) }
565
+ else
566
+ duck
567
+ end
568
+ end
569
+
570
+ end
571
+ end
572
+ end