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.
- data/CHANGELOG +91 -88
- data/LICENSE +20 -20
- data/README +80 -80
- data/lib/remarkable_rails/action_controller/base.rb +29 -29
- data/lib/remarkable_rails/action_controller/macro_stubs.rb +459 -457
- data/lib/remarkable_rails/action_controller/matchers/assign_to_matcher.rb +92 -92
- data/lib/remarkable_rails/action_controller/matchers/filter_params_matcher.rb +41 -41
- data/lib/remarkable_rails/action_controller/matchers/redirect_to_matcher.rb +119 -119
- data/lib/remarkable_rails/action_controller/matchers/render_template_matcher.rb +146 -146
- data/lib/remarkable_rails/action_controller/matchers/respond_with_matcher.rb +126 -126
- data/lib/remarkable_rails/action_controller/matchers/route_matcher.rb +135 -109
- data/lib/remarkable_rails/action_controller/matchers/set_cookies_matcher.rb +49 -49
- data/lib/remarkable_rails/action_controller/matchers/set_session_matcher.rb +106 -106
- data/lib/remarkable_rails/action_controller/matchers/set_the_flash_matcher.rb +54 -54
- data/lib/remarkable_rails/action_controller.rb +22 -22
- data/lib/remarkable_rails/action_view/base.rb +7 -7
- data/lib/remarkable_rails/action_view.rb +18 -18
- data/lib/remarkable_rails/active_orm.rb +19 -19
- data/lib/remarkable_rails.rb +30 -30
- data/locale/en.yml +110 -110
- data/spec/action_controller/assign_to_matcher_spec.rb +142 -142
- data/spec/action_controller/filter_params_matcher_spec.rb +64 -64
- data/spec/action_controller/macro_stubs_spec.rb +234 -208
- data/spec/action_controller/redirect_to_matcher_spec.rb +102 -102
- data/spec/action_controller/render_template_matcher_spec.rb +251 -251
- data/spec/action_controller/respond_with_matcher_spec.rb +223 -223
- data/spec/action_controller/route_matcher_spec.rb +96 -79
- data/spec/action_controller/set_cookies_matcher_spec.rb +149 -149
- data/spec/action_controller/set_session_matcher_spec.rb +141 -141
- data/spec/action_controller/set_the_flash_matcher_spec.rb +93 -93
- data/spec/application/application.rb +15 -15
- data/spec/application/tasks_controller.rb +34 -34
- data/spec/functional_builder.rb +88 -88
- data/spec/rcov.opts +2 -2
- data/spec/remarkable_rails_spec.rb +5 -5
- data/spec/spec.opts +4 -4
- data/spec/spec_helper.rb +42 -42
- 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
|
-
#
|
441
|
-
#
|
442
|
-
#
|
443
|
-
|
444
|
-
|
445
|
-
|
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
|
-
|
564
|
-
duck
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
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
|