remarkable_rails 3.0.0 → 3.0.1
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 +14 -51
- data/README +83 -2
- data/lib/remarkable_rails/action_controller/base.rb +2 -2
- data/lib/remarkable_rails/action_controller/macro_stubs.rb +485 -510
- metadata +4 -4
data/CHANGELOG
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[TODO] Port views matchers from rspec to Remarkable to provide I18n.
|
|
2
2
|
|
|
3
|
-
# v3.0.0
|
|
3
|
+
# v3.0.0
|
|
4
4
|
|
|
5
5
|
[ENHANCEMENT] redirect_to and render_template were ported from rspec-rails to
|
|
6
6
|
remarkable to provide I18n. The second was also extended to deal with :with,
|
|
@@ -18,64 +18,27 @@ consistent API.
|
|
|
18
18
|
[ENHANCEMENT] remarkable_rails now ships with a new feature, called macro stubs.
|
|
19
19
|
This allows you to declare just once your mocks and/or expectations, and each
|
|
20
20
|
matcher will know how to deal with properly. A TasksController could have your
|
|
21
|
-
specs for a
|
|
21
|
+
specs for a create action rewritten like this:
|
|
22
22
|
|
|
23
|
-
describe
|
|
24
|
-
|
|
25
|
-
expects :destroy, :on => mock_task
|
|
23
|
+
describe TasksController do
|
|
24
|
+
mock_models :task
|
|
26
25
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
This will generate two tests, the first one will assert the assignment of
|
|
32
|
-
:task and the second will assert if the action is redirecting to tasks_url.
|
|
33
|
-
|
|
34
|
-
But before doing the assertions, each macros run the expectations declared and
|
|
35
|
-
perform the action automatically. In other words, should assign to macro is
|
|
36
|
-
doing:
|
|
37
|
-
|
|
38
|
-
it 'should assign to task' do
|
|
39
|
-
Task.should_receive(:find).with('37').and_return(mock_task)
|
|
40
|
-
mock_task.should_receive(:destroy)
|
|
41
|
-
delete :destroy, :id => '37'
|
|
42
|
-
assigns(:task).should == mock_task
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
On the other hand, should render template is doing something like this:
|
|
46
|
-
|
|
47
|
-
it 'should render template show' do
|
|
48
|
-
Task.stub!(:find).and_return(mock_task)
|
|
49
|
-
mock_task.should_receive(:destroy)
|
|
50
|
-
delete :destroy, :id => '37'
|
|
51
|
-
response.should render_template('show')
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
But how each macro knows if they should perform expectations or stubs? By default,
|
|
55
|
-
only should_assign_to macro performs expectations (check macro stubs documentation
|
|
56
|
-
to change this behavior).
|
|
26
|
+
describe :post => :create, :task => { :these => 'params' } do
|
|
27
|
+
expects :new, :on => Task, with => {'these' => 'params'}, :returns => mock_task
|
|
28
|
+
expects :save, :on => mock_task, :returns => true
|
|
57
29
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
describe ProjectsController do
|
|
63
|
-
mock_models :project
|
|
30
|
+
should_assign_to :task, :with => mock_task
|
|
31
|
+
should_redirect_to { task_url(mock_task) }
|
|
32
|
+
end
|
|
64
33
|
end
|
|
65
34
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
proc { mock_project }
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def mock_project(stubs={})
|
|
73
|
-
@project ||= mock_model(Project, stubs)
|
|
74
|
-
end
|
|
35
|
+
It automatically performs the action before running each macro. In assign_to,
|
|
36
|
+
it executes the expects as expectations (:should_receive), and in redirect_to
|
|
37
|
+
it executes the expects as stubs (:stub!), just as above.
|
|
75
38
|
|
|
76
39
|
For more options, information and configuration, check macro stubs documentation.
|
|
77
40
|
|
|
78
41
|
# v2.x
|
|
79
42
|
|
|
80
43
|
[ENHANCMENT] Added assign_to, filter_params, render_with_layout, respond_with
|
|
81
|
-
respond_with_content_type, set_session and set_the_flash matchers.
|
|
44
|
+
respond_with_content_type, route, set_session and set_the_flash matchers.
|
data/README
CHANGED
|
@@ -1,2 +1,83 @@
|
|
|
1
|
-
Remarkable Rails
|
|
2
|
-
|
|
1
|
+
= Remarkable Rails
|
|
2
|
+
|
|
3
|
+
Remarkable Rails is a collection of matchers to Rails. This package has some
|
|
4
|
+
ActionController matchers and soon some ActionView matchers.
|
|
5
|
+
|
|
6
|
+
Whenever using the Remarkable Rails gem and ActiveRecord, it will automatically
|
|
7
|
+
add your ActiveRecord matchers. So just one line is needed to install both:
|
|
8
|
+
|
|
9
|
+
sudo gem install remarkable_rails
|
|
10
|
+
|
|
11
|
+
== Matchers & Macros
|
|
12
|
+
|
|
13
|
+
The supported matchers and macros are:
|
|
14
|
+
|
|
15
|
+
assign_to, filter_params, render_with_layout, respond_with,
|
|
16
|
+
respond_with_content_type, route, set_session and set_the_flash matchers.
|
|
17
|
+
|
|
18
|
+
In Remarkable 3.0, we also ported and extended redirect to and render template
|
|
19
|
+
from rspec rails matchers to provide I18n. You can also do:
|
|
20
|
+
|
|
21
|
+
render_template 'edit', :layout => 'default'
|
|
22
|
+
respond_with 404, :content_type => Mime::XML, :body => /Not found/
|
|
23
|
+
|
|
24
|
+
== Macro stubs
|
|
25
|
+
|
|
26
|
+
Another cool feature in Remarkable 3.0 is macro stubs, which makes your mocks
|
|
27
|
+
and stubs DRY and easier to maintain. An rspec default scaffold would be:
|
|
28
|
+
|
|
29
|
+
describe TasksController do
|
|
30
|
+
def mock_task(stubs={})
|
|
31
|
+
@task ||= mock_model(Task, stubs)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe “responding to #POST create” do
|
|
35
|
+
it "exposes a newly created task as @task" do
|
|
36
|
+
Task.should_receive(:new).with({'these' => 'params'}).
|
|
37
|
+
and_return(mock_task(:save => true))
|
|
38
|
+
post :create, :task => {:these => 'params'}
|
|
39
|
+
assigns[:task].should equal(mock_task)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "redirects to the created task" do
|
|
43
|
+
Task.stub!(:new).and_return(mock_task(:save => true))
|
|
44
|
+
post :create, :task => {}
|
|
45
|
+
response.should redirect_to(task_url(mock_task))
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
An equivalent in remarkable would be:
|
|
51
|
+
|
|
52
|
+
describe TasksController do
|
|
53
|
+
mock_models :task
|
|
54
|
+
|
|
55
|
+
describe :post => :create, :task => { :these => 'params' } do
|
|
56
|
+
expects :new, :on => Task, with => {'these' => 'params'}, :returns => mock_task
|
|
57
|
+
expects :save, :on => mock_task, :returns => true
|
|
58
|
+
|
|
59
|
+
should_assign_to :task, :with => mock_task
|
|
60
|
+
should_redirect_to { task_url(mock_task) }
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
It automatically performs the action before running each macro. In assign_to,
|
|
65
|
+
it executes the expects as expectations (:should_receive), and in redirect_to
|
|
66
|
+
it executes the expects as stubs (:stub!), just as above.
|
|
67
|
+
|
|
68
|
+
There are also params and mime methods:
|
|
69
|
+
|
|
70
|
+
describe TasksController
|
|
71
|
+
params :project_id => 42
|
|
72
|
+
mime Mime::HTML
|
|
73
|
+
|
|
74
|
+
describe :get => :show, :id => 37 do
|
|
75
|
+
should_assign_to :project, :task
|
|
76
|
+
|
|
77
|
+
describe Mime::XML do
|
|
78
|
+
should_assign_to :project, :task
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
And much more. Be sure to check macro stubs documentation.
|
|
@@ -12,11 +12,11 @@ module Remarkable
|
|
|
12
12
|
# Before assertions, call run_action! to perform the action if it was
|
|
13
13
|
# not performed yet.
|
|
14
14
|
#
|
|
15
|
-
def perform_action_with_macro_stubs
|
|
15
|
+
def perform_action_with_macro_stubs #:nodoc:
|
|
16
16
|
@spec.send(:run_action!, run_with_expectations?) if @spec.send(:controller)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
def run_with_expectations?
|
|
19
|
+
def run_with_expectations? #:nodoc:
|
|
20
20
|
if @options.key?(:with_stubs)
|
|
21
21
|
!@options[:with_stubs]
|
|
22
22
|
elsif @options.key?(:with_expectations)
|
|
@@ -1,518 +1,493 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
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
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
33
|
-
#
|
|
34
|
-
#
|
|
35
|
-
#
|
|
36
|
-
#
|
|
37
|
-
#
|
|
38
|
-
#
|
|
39
|
-
#
|
|
40
|
-
#
|
|
41
|
-
# it 'should
|
|
42
|
-
# Project.
|
|
43
|
-
# get :show, :id => '37'
|
|
44
|
-
#
|
|
45
|
-
# end
|
|
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
|
-
# describe
|
|
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
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
#
|
|
260
|
-
#
|
|
261
|
-
#
|
|
262
|
-
# == Examples
|
|
263
|
-
#
|
|
264
|
-
# #{verb} :action, :id => 42
|
|
265
|
-
#
|
|
266
|
-
def #{verb}(action, params={})
|
|
267
|
-
params(params)
|
|
268
|
-
write_inheritable_attribute(:default_verb, #{verb.inspect})
|
|
269
|
-
write_inheritable_attribute(:default_action, action)
|
|
270
|
-
end
|
|
271
|
-
VERB
|
|
272
|
-
end
|
|
273
|
-
|
|
274
|
-
[:get!, :post!, :put!, :delete!].each do |verb|
|
|
275
|
-
module_eval <<-VERB, __FILE__, __LINE__
|
|
276
|
-
# Declares that we want to do a #{verb} request in the given action
|
|
277
|
-
# and with the given params, but the action is performed just once
|
|
278
|
-
# in the describe group. In other words, it's performed in a
|
|
279
|
-
# before(:all) filter.
|
|
280
|
-
#
|
|
281
|
-
# == Examples
|
|
282
|
-
#
|
|
283
|
-
# #{verb} :action, :id => 42
|
|
284
|
-
#
|
|
285
|
-
def #{verb}(action=nil, params={}, &block)
|
|
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
|
+
# On the other hand, should render template is doing something like this:
|
|
40
|
+
#
|
|
41
|
+
# it 'should render template show' do
|
|
42
|
+
# Project.stub!(:find).and_return(mock_project)
|
|
43
|
+
# get :show, :id => '37'
|
|
44
|
+
# response.should render_template('show')
|
|
45
|
+
# end
|
|
46
|
+
#
|
|
47
|
+
# Now comes the first question: how each macro knows if they should perform
|
|
48
|
+
# expectations or stubs?
|
|
49
|
+
#
|
|
50
|
+
# By default, only should_assign_to macro performs expectations. You can change
|
|
51
|
+
# this behavior sending :with_stubs or :with_expectations as options:
|
|
52
|
+
#
|
|
53
|
+
# should_assign_to :project, :with_stubs => true
|
|
54
|
+
# should_render_template 'show', :with_expectations => true
|
|
55
|
+
#
|
|
56
|
+
# This also works in the rspec way:
|
|
57
|
+
#
|
|
58
|
+
# it { should assign_to(:project).with_stubs }
|
|
59
|
+
# it { should render_tempalte('show').with_expectations }
|
|
60
|
+
#
|
|
61
|
+
# == mock_models
|
|
62
|
+
#
|
|
63
|
+
# You don't have to play with proc all the time. You can call mock_models which
|
|
64
|
+
# creates a class method that simply returns a proc and a instance method that
|
|
65
|
+
# do the actual mock. In other words, it creates:
|
|
66
|
+
#
|
|
67
|
+
# def self.mock_project
|
|
68
|
+
# proc { mock_project }
|
|
69
|
+
# end
|
|
70
|
+
#
|
|
71
|
+
# def mock_project(stubs={})
|
|
72
|
+
# @project ||= mock_model(Project, stubs)
|
|
73
|
+
# end
|
|
74
|
+
#
|
|
75
|
+
# Then you can replace those lines:
|
|
76
|
+
#
|
|
77
|
+
# expects :find, :on => Project, :with => '37', :returns => proc { mock_project }
|
|
78
|
+
# should_assign_to :project, :with => proc { mock_project }
|
|
79
|
+
#
|
|
80
|
+
# For:
|
|
81
|
+
#
|
|
82
|
+
# expects :find, :on => Project, :with => '37', :returns => mock_project
|
|
83
|
+
# should_assign_to :project, :with => mock_project
|
|
84
|
+
#
|
|
85
|
+
# = Give me more!
|
|
86
|
+
#
|
|
87
|
+
# If you need to specify the describe description, you can also do:
|
|
88
|
+
#
|
|
89
|
+
# describe 'my description' do
|
|
90
|
+
# get :show, :id => 37
|
|
91
|
+
#
|
|
92
|
+
# Which is the same as above.
|
|
93
|
+
#
|
|
94
|
+
# Things start to get even better when we start to talk about nested resources.
|
|
95
|
+
# After our ProjectsController is created, we want to create a TasksController:
|
|
96
|
+
#
|
|
97
|
+
# describe TasksController do
|
|
98
|
+
# params :project_id => '42' #=> define params for all requests
|
|
99
|
+
#
|
|
100
|
+
# # Those two expectations get inherited in all describe groups below
|
|
101
|
+
# expects :find_by_title, :on => Project, :with => '42', :returns => mock_project
|
|
102
|
+
# expects :tasks, :and_return => Task
|
|
103
|
+
#
|
|
104
|
+
# describe :get => :show, :id => '37' do
|
|
105
|
+
# expects :find, :with => '37', :and_return => mock_task
|
|
106
|
+
#
|
|
107
|
+
# should_assign_to :project, :task
|
|
108
|
+
# should_render_template 'show'
|
|
109
|
+
# end
|
|
110
|
+
# end
|
|
111
|
+
#
|
|
112
|
+
# As you noticed, you can define parameters that will be available to all requests,
|
|
113
|
+
# using the method <tt>params</tt>.
|
|
114
|
+
#
|
|
115
|
+
# Finally, if you used expects chain like above, but need to write a spec by
|
|
116
|
+
# hand you can invoke the action and expectations with run_expectations!,
|
|
117
|
+
# run_stubs! and run_action!. Examples:
|
|
118
|
+
#
|
|
119
|
+
# describe :get => :new do
|
|
120
|
+
# expects :new, :on => Project, :returns => mock_project
|
|
121
|
+
#
|
|
122
|
+
# it "should do something different" do
|
|
123
|
+
# run_action!
|
|
124
|
+
# # do you assertions here
|
|
125
|
+
# end
|
|
126
|
+
# end
|
|
127
|
+
#
|
|
128
|
+
# = Performance!
|
|
129
|
+
#
|
|
130
|
+
# Remarkable comes with a new way to speed up your tests. It perform the action
|
|
131
|
+
# inside a before(:all), so you can do:
|
|
132
|
+
#
|
|
133
|
+
# describe "responding to GET show" do
|
|
134
|
+
# get! :show, :id => 37
|
|
135
|
+
#
|
|
136
|
+
# should_assign_to :task
|
|
137
|
+
# should_render_template :show
|
|
138
|
+
# end
|
|
139
|
+
#
|
|
140
|
+
# Or in the compact way:
|
|
141
|
+
#
|
|
142
|
+
# describe :get! => :show, :id => 37
|
|
143
|
+
#
|
|
144
|
+
# The action will be performed just once before asserting the assignment and
|
|
145
|
+
# the template. If any error happens while performing the action rspec will
|
|
146
|
+
# output an error but ALL the examples inside the example group (describe) won't
|
|
147
|
+
# be run.
|
|
148
|
+
#
|
|
149
|
+
# By now, the bang methods works only when integrate_views are true and this is
|
|
150
|
+
# when you must have the bigger performance gain.
|
|
151
|
+
#
|
|
152
|
+
# This comes with some rspec and rspec rails tweakings. So if you want to do
|
|
153
|
+
# something before the action is performed (stubs something or log someone in
|
|
154
|
+
# session), you have to do it giving a block to the action method:
|
|
155
|
+
#
|
|
156
|
+
# get! :show, :id => 37 do
|
|
157
|
+
# login_as(mock_user)
|
|
158
|
+
# end
|
|
159
|
+
#
|
|
160
|
+
# You can still use the compact way and give the block:
|
|
161
|
+
#
|
|
162
|
+
# describe :get => :show, :id => 37 do
|
|
163
|
+
# get! do
|
|
164
|
+
# login_as(mock_user)
|
|
165
|
+
# end
|
|
166
|
+
# end
|
|
167
|
+
#
|
|
168
|
+
module MacroStubs
|
|
169
|
+
HTTP_VERBS_METHODS = [:get, :get!, :post, :post!, :put, :put!, :delete, :delete!]
|
|
170
|
+
|
|
171
|
+
def self.included(base) #:nodoc:
|
|
172
|
+
base.extend ClassMethods
|
|
173
|
+
base.class_inheritable_reader :expects_chain, :default_action, :default_mime,
|
|
174
|
+
:default_verb, :default_params, :before_all_block
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
module ClassMethods
|
|
178
|
+
|
|
179
|
+
# Creates a chain that will be evaluated as stub or expectation. The
|
|
180
|
+
# first parameter is the method expected.
|
|
181
|
+
#
|
|
182
|
+
# == Options
|
|
183
|
+
#
|
|
184
|
+
# * <tt>:on</tt> - Tell which object will receive the expected method.
|
|
185
|
+
# This option is always required.
|
|
186
|
+
#
|
|
187
|
+
# * <tt>:with</tt> - Tell each parameters will be sent with the expected
|
|
188
|
+
# method. This option is used only in expectations and is optional.
|
|
189
|
+
#
|
|
190
|
+
# * <tt>:returns</tt> - Tell what the expectations should return. Not
|
|
191
|
+
# required.
|
|
192
|
+
#
|
|
193
|
+
# * <tt>:times</tt> - The number of times the object will receive the
|
|
194
|
+
# method. Used only in expectations and when not given, defaults to 1.
|
|
195
|
+
#
|
|
196
|
+
# == Example
|
|
197
|
+
#
|
|
198
|
+
# expects :new, :on => Project, :returns => :mock_project, :times => 2
|
|
199
|
+
#
|
|
200
|
+
def expects(*args)
|
|
201
|
+
write_inheritable_array(:expects_chain, [args])
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# The mime type of the request. The value given will be called transformed
|
|
205
|
+
# into a string and set in the @request.env['HTTP_ACCEPT'] variable.
|
|
206
|
+
#
|
|
207
|
+
# == Examples
|
|
208
|
+
#
|
|
209
|
+
# mime Mime::XML
|
|
210
|
+
# mime 'application/xml+rss'
|
|
211
|
+
#
|
|
212
|
+
def mime(mime)
|
|
213
|
+
write_inheritable_attribute(:default_mime, mime.to_s)
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# The params used for the request. Calls are always nested:
|
|
217
|
+
#
|
|
218
|
+
# == Examples
|
|
219
|
+
#
|
|
220
|
+
# describe TasksController do
|
|
221
|
+
# params :project_id => 42
|
|
222
|
+
#
|
|
223
|
+
# describe :get => :show, :id => 37 do
|
|
224
|
+
# # will request with params {:id => 37, :project_id => 42}
|
|
225
|
+
# end
|
|
226
|
+
# end
|
|
227
|
+
#
|
|
228
|
+
def params(params)
|
|
229
|
+
write_inheritable_hash(:default_params, params)
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
[:get, :post, :put, :delete].each do |verb|
|
|
233
|
+
module_eval <<-VERB, __FILE__, __LINE__
|
|
234
|
+
# Declares that we want to do a #{verb} request in the given action
|
|
235
|
+
# and with the given params.
|
|
236
|
+
#
|
|
237
|
+
# == Examples
|
|
238
|
+
#
|
|
239
|
+
# #{verb} :action, :id => 42
|
|
240
|
+
#
|
|
241
|
+
def #{verb}(action, params={})
|
|
242
|
+
params(params)
|
|
243
|
+
write_inheritable_attribute(:default_verb, #{verb.inspect})
|
|
244
|
+
write_inheritable_attribute(:default_action, action)
|
|
245
|
+
end
|
|
246
|
+
VERB
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
[:get!, :post!, :put!, :delete!].each do |verb|
|
|
250
|
+
module_eval <<-VERB, __FILE__, __LINE__
|
|
251
|
+
# Declares that we want to do a #{verb} request in the given action
|
|
252
|
+
# and with the given params, but the action is performed just once
|
|
253
|
+
# in the describe group. In other words, it's performed in a
|
|
254
|
+
# before(:all) filter.
|
|
255
|
+
#
|
|
256
|
+
# == Examples
|
|
257
|
+
#
|
|
258
|
+
# #{verb} :action, :id => 42
|
|
259
|
+
#
|
|
260
|
+
def #{verb}(action=nil, params={}, &block)
|
|
286
261
|
#{verb.to_s.chop}(action, params) if action
|
|
287
|
-
write_inheritable_array(:before_all_block, [block]) if block
|
|
288
|
-
run_callbacks_once!
|
|
289
|
-
end
|
|
290
|
-
VERB
|
|
291
|
-
end
|
|
292
|
-
|
|
293
|
-
# Undefine the method run_callbacks so rspec won't run them in the
|
|
294
|
-
# before and after :each cycle. Then we redefine it as run_callbacks_once,
|
|
295
|
-
# which will be used as an before(:all) and after(:all) filter.
|
|
296
|
-
#
|
|
297
|
-
def run_callbacks_once!(&block) #:nodoc:
|
|
298
|
-
unless instance_methods.any?{|m| m.to_s == 'run_callbacks_once' }
|
|
299
|
-
alias_method :run_callbacks_once, :run_callbacks
|
|
300
|
-
class_eval "def run_callbacks(*args); end"
|
|
301
|
-
|
|
302
|
-
before(:all) do
|
|
303
|
-
setup_mocks_for_rspec
|
|
262
|
+
write_inheritable_array(:before_all_block, [block]) if block
|
|
263
|
+
run_callbacks_once!
|
|
264
|
+
end
|
|
265
|
+
VERB
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
# Undefine the method run_callbacks so rspec won't run them in the
|
|
269
|
+
# before and after :each cycle. Then we redefine it as run_callbacks_once,
|
|
270
|
+
# which will be used as an before(:all) and after(:all) filter.
|
|
271
|
+
#
|
|
272
|
+
def run_callbacks_once!(&block) #:nodoc:
|
|
273
|
+
unless instance_methods.any?{|m| m.to_s == 'run_callbacks_once' }
|
|
274
|
+
alias_method :run_callbacks_once, :run_callbacks
|
|
275
|
+
class_eval "def run_callbacks(*args); end"
|
|
276
|
+
|
|
277
|
+
before(:all) do
|
|
278
|
+
setup_mocks_for_rspec
|
|
304
279
|
run_callbacks_once :setup
|
|
305
280
|
|
|
306
281
|
before_all_block.each do |block|
|
|
307
282
|
instance_eval(&block)
|
|
308
283
|
end if before_all_block
|
|
309
|
-
|
|
284
|
+
|
|
310
285
|
run_action!
|
|
311
286
|
verify_mocks_for_rspec
|
|
312
|
-
teardown_mocks_for_rspec
|
|
313
|
-
end
|
|
314
|
-
|
|
315
|
-
after(:all) do
|
|
316
|
-
run_callbacks_once :teardown
|
|
317
|
-
end
|
|
318
|
-
end
|
|
319
|
-
end
|
|
320
|
-
|
|
321
|
-
# Overwrites describe to provide quick action description with I18n.
|
|
322
|
-
#
|
|
323
|
-
# You can now do:
|
|
324
|
-
#
|
|
325
|
-
# describe :get => :show, :id => 37
|
|
326
|
-
#
|
|
327
|
-
# Which is the same as:
|
|
328
|
-
#
|
|
329
|
-
# describe 'responding to #GET show' do
|
|
330
|
-
# get :show, :id => 37
|
|
331
|
-
#
|
|
332
|
-
# And do this:
|
|
333
|
-
#
|
|
334
|
-
# describe Mime::XML
|
|
335
|
-
#
|
|
336
|
-
# Which is the same as:
|
|
337
|
-
#
|
|
338
|
-
# describe 'with xml' do
|
|
339
|
-
# mime Mime::XML
|
|
340
|
-
#
|
|
341
|
-
# The string can be localized using I18n. An example yml file is:
|
|
342
|
-
#
|
|
343
|
-
# locale:
|
|
344
|
-
# remarkable:
|
|
345
|
-
# action_controller:
|
|
346
|
-
# responding: "responding to #{{verb}} {{action}}"
|
|
347
|
-
# mime_type: "with {{format}} ({{content_type}})"
|
|
348
|
-
#
|
|
349
|
-
# And load the locale file with:
|
|
350
|
-
#
|
|
351
|
-
# Remarkable.add_locale locale_path
|
|
352
|
-
#
|
|
353
|
-
def describe(*args, &block)
|
|
354
|
-
options = args.first.is_a?(Hash) ? args.first : {}
|
|
355
|
-
verb = (options.keys & HTTP_VERBS_METHODS).first
|
|
356
|
-
|
|
357
|
-
if verb
|
|
358
|
-
action = options.delete(verb)
|
|
359
|
-
verb = verb.to_s
|
|
360
|
-
|
|
361
|
-
description = Remarkable.t 'remarkable.action_controller.responding',
|
|
362
|
-
:default => "responding to ##{verb.upcase} #{action}",
|
|
363
|
-
:verb => verb.sub('!', '').upcase, :action => action
|
|
364
|
-
|
|
365
|
-
send_args = [ verb, action, options ]
|
|
366
|
-
elsif args.first.is_a?(Mime::Type)
|
|
367
|
-
mime = args.first
|
|
368
|
-
|
|
369
|
-
description = Remarkable.t 'remarkable.action_controller.mime_type',
|
|
370
|
-
:default => "with #{mime.to_sym}",
|
|
371
|
-
:format => mime.to_sym, :content_type => mime.to_s
|
|
372
|
-
|
|
373
|
-
send_args = [ :mime, mime ]
|
|
374
|
-
else # return if no special type was found
|
|
375
|
-
return super(*args, &block)
|
|
376
|
-
end
|
|
377
|
-
|
|
378
|
-
args.shift
|
|
379
|
-
args.unshift(description)
|
|
380
|
-
|
|
381
|
-
# Creates an example group, send the method and eval the given block.
|
|
382
|
-
#
|
|
383
|
-
example_group = super(*args) do
|
|
384
|
-
send(*send_args)
|
|
385
|
-
instance_eval(&block)
|
|
386
|
-
end
|
|
387
|
-
end
|
|
388
|
-
|
|
389
|
-
# Creates mock methods automatically.
|
|
390
|
-
#
|
|
391
|
-
# == Options
|
|
392
|
-
#
|
|
393
|
-
# * <tt>:class_method</tt> - When set to false, does not create the
|
|
394
|
-
# class method which returns a proc.
|
|
395
|
-
#
|
|
396
|
-
# == Examples
|
|
397
|
-
#
|
|
398
|
-
# Doing this:
|
|
399
|
-
#
|
|
400
|
-
# describe ProjectsController do
|
|
401
|
-
# mock_models :project
|
|
402
|
-
# end
|
|
403
|
-
#
|
|
404
|
-
# Will create a class and instance mock method for you:
|
|
405
|
-
#
|
|
406
|
-
# def self.mock_project
|
|
407
|
-
# proc { mock_project }
|
|
408
|
-
# end
|
|
409
|
-
#
|
|
410
|
-
# def mock_project(stubs={})
|
|
411
|
-
# @project ||= mock_model(Project, stubs)
|
|
412
|
-
# end
|
|
413
|
-
#
|
|
414
|
-
# If you want to create just the instance method, you can give
|
|
415
|
-
# :class_method => false as option.
|
|
416
|
-
#
|
|
417
|
-
def mock_models(*models)
|
|
418
|
-
options = models.extract_options!
|
|
419
|
-
options = { :class_method => true }.merge(options)
|
|
420
|
-
|
|
421
|
-
models.each do |model|
|
|
422
|
-
self.class_eval <<-METHOD
|
|
423
|
-
#{"def self.mock_#{model}; proc { mock_#{model} }; end" if options[:class_method]}
|
|
424
|
-
|
|
425
|
-
def mock_#{model}(stubs={})
|
|
426
|
-
@#{model} ||= mock_model(#{model.to_s.classify}, stubs)
|
|
427
|
-
end
|
|
428
|
-
METHOD
|
|
429
|
-
end
|
|
430
|
-
end
|
|
431
|
-
|
|
432
|
-
end
|
|
433
|
-
|
|
434
|
-
protected
|
|
435
|
-
|
|
436
|
-
# Evaluates the expectation chain as stub or expectations.
|
|
437
|
-
#
|
|
438
|
-
def evaluate_expectation_chain(use_expectations=true) #:nodoc:
|
|
439
|
-
return if self.expects_chain.nil?
|
|
440
|
-
|
|
441
|
-
self.expects_chain.each do |method, default_options|
|
|
442
|
-
options = default_options.dup
|
|
443
|
-
|
|
444
|
-
# Those are used both in expectations and stubs
|
|
445
|
-
object = evaluate_value(options.delete(:on))
|
|
446
|
-
return_value = evaluate_value(options.delete(:returns))
|
|
447
|
-
|
|
448
|
-
raise ScriptError, "You have to give me :on as an option when calling :expects." if object.nil?
|
|
449
|
-
|
|
450
|
-
if use_expectations
|
|
451
|
-
with = evaluate_value(options.delete(:with))
|
|
452
|
-
times = options.delete(:times) || 1
|
|
453
|
-
|
|
454
|
-
chain = object.should_receive(method)
|
|
455
|
-
chain = chain.with(with) if with
|
|
456
|
-
chain = chain.exactly(times).times
|
|
457
|
-
else
|
|
458
|
-
chain = object.stub!(method)
|
|
459
|
-
end
|
|
460
|
-
chain = chain.and_return(return_value)
|
|
461
|
-
end
|
|
462
|
-
end
|
|
463
|
-
|
|
464
|
-
# Instance method run_stubs! if someone wants to declare additional
|
|
465
|
-
# tests and call the stubs inside of it.
|
|
466
|
-
#
|
|
467
|
-
def run_stubs!
|
|
468
|
-
evaluate_expectation_chain(false)
|
|
469
|
-
end
|
|
470
|
-
|
|
471
|
-
# Instance method run_expectations! if someone wants to declare
|
|
472
|
-
# additional tests and call the stubs inside of it.
|
|
473
|
-
#
|
|
474
|
-
def run_expectations!
|
|
475
|
-
evaluate_expectation_chain(true)
|
|
476
|
-
end
|
|
477
|
-
|
|
478
|
-
# Run the action declared in the describe group, but before runs also
|
|
479
|
-
# the expectations. If an action was already performed, it doesn't run
|
|
480
|
-
# anything at all and returns false.
|
|
481
|
-
#
|
|
482
|
-
# The first parameter is if you want to run expectations or stubs. You
|
|
483
|
-
# can also supply the verb (get, post, put or delete), which action to
|
|
484
|
-
# call, parameters and the mime type. If any of those parameters are
|
|
485
|
-
# supplied, they override the current definition.
|
|
486
|
-
#
|
|
487
|
-
def run_action!(use_expectations=true, verb=nil, action=nil, params=nil, mime=nil)
|
|
488
|
-
return false if controller.send(:performed?)
|
|
489
|
-
|
|
490
|
-
evaluate_expectation_chain(use_expectations)
|
|
491
|
-
|
|
492
|
-
mime ||= default_mime
|
|
493
|
-
verb ||= default_verb
|
|
494
|
-
action ||= default_action
|
|
495
|
-
params ||= default_params
|
|
496
|
-
|
|
497
|
-
raise ScriptError, "No action was performed or declared." unless verb && action
|
|
498
|
-
|
|
499
|
-
request.env["HTTP_ACCEPT"] ||= mime.to_s if mime
|
|
500
|
-
send(verb, action, params)
|
|
501
|
-
end
|
|
502
|
-
|
|
503
|
-
# Evaluate a given value.
|
|
504
|
-
#
|
|
505
|
-
# This allows procs to be given to the expectation chain and they will
|
|
506
|
-
# be evaluated in the instance binding.
|
|
507
|
-
#
|
|
508
|
-
def evaluate_value(duck) #:nodoc:
|
|
509
|
-
if duck.is_a?(Proc)
|
|
510
|
-
self.instance_eval(&duck)
|
|
511
|
-
else
|
|
512
|
-
duck
|
|
513
|
-
end
|
|
514
|
-
end
|
|
515
|
-
|
|
516
|
-
end
|
|
517
|
-
end
|
|
518
|
-
end
|
|
287
|
+
teardown_mocks_for_rspec
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
after(:all) do
|
|
291
|
+
run_callbacks_once :teardown
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
# Overwrites describe to provide quick action description with I18n.
|
|
297
|
+
#
|
|
298
|
+
# You can now do:
|
|
299
|
+
#
|
|
300
|
+
# describe :get => :show, :id => 37
|
|
301
|
+
#
|
|
302
|
+
# Which is the same as:
|
|
303
|
+
#
|
|
304
|
+
# describe 'responding to #GET show' do
|
|
305
|
+
# get :show, :id => 37
|
|
306
|
+
#
|
|
307
|
+
# And do this:
|
|
308
|
+
#
|
|
309
|
+
# describe Mime::XML
|
|
310
|
+
#
|
|
311
|
+
# Which is the same as:
|
|
312
|
+
#
|
|
313
|
+
# describe 'with xml' do
|
|
314
|
+
# mime Mime::XML
|
|
315
|
+
#
|
|
316
|
+
# The string can be localized using I18n. An example yml file is:
|
|
317
|
+
#
|
|
318
|
+
# locale:
|
|
319
|
+
# remarkable:
|
|
320
|
+
# action_controller:
|
|
321
|
+
# responding: "responding to #{{verb}} {{action}}"
|
|
322
|
+
# mime_type: "with {{format}} ({{content_type}})"
|
|
323
|
+
#
|
|
324
|
+
# And load the locale file with:
|
|
325
|
+
#
|
|
326
|
+
# Remarkable.add_locale locale_path
|
|
327
|
+
#
|
|
328
|
+
def describe(*args, &block)
|
|
329
|
+
options = args.first.is_a?(Hash) ? args.first : {}
|
|
330
|
+
verb = (options.keys & HTTP_VERBS_METHODS).first
|
|
331
|
+
|
|
332
|
+
if verb
|
|
333
|
+
action = options.delete(verb)
|
|
334
|
+
verb = verb.to_s
|
|
335
|
+
|
|
336
|
+
description = Remarkable.t 'remarkable.action_controller.responding',
|
|
337
|
+
:default => "responding to ##{verb.upcase} #{action}",
|
|
338
|
+
:verb => verb.sub('!', '').upcase, :action => action
|
|
339
|
+
|
|
340
|
+
send_args = [ verb, action, options ]
|
|
341
|
+
elsif args.first.is_a?(Mime::Type)
|
|
342
|
+
mime = args.first
|
|
343
|
+
|
|
344
|
+
description = Remarkable.t 'remarkable.action_controller.mime_type',
|
|
345
|
+
:default => "with #{mime.to_sym}",
|
|
346
|
+
:format => mime.to_sym, :content_type => mime.to_s
|
|
347
|
+
|
|
348
|
+
send_args = [ :mime, mime ]
|
|
349
|
+
else # return if no special type was found
|
|
350
|
+
return super(*args, &block)
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
args.shift
|
|
354
|
+
args.unshift(description)
|
|
355
|
+
|
|
356
|
+
# Creates an example group, send the method and eval the given block.
|
|
357
|
+
#
|
|
358
|
+
example_group = super(*args) do
|
|
359
|
+
send(*send_args)
|
|
360
|
+
instance_eval(&block)
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
# Creates mock methods automatically.
|
|
365
|
+
#
|
|
366
|
+
# == Options
|
|
367
|
+
#
|
|
368
|
+
# * <tt>:class_method</tt> - When set to false, does not create the
|
|
369
|
+
# class method which returns a proc.
|
|
370
|
+
#
|
|
371
|
+
# == Examples
|
|
372
|
+
#
|
|
373
|
+
# Doing this:
|
|
374
|
+
#
|
|
375
|
+
# describe ProjectsController do
|
|
376
|
+
# mock_models :project
|
|
377
|
+
# end
|
|
378
|
+
#
|
|
379
|
+
# Will create a class and instance mock method for you:
|
|
380
|
+
#
|
|
381
|
+
# def self.mock_project
|
|
382
|
+
# proc { mock_project }
|
|
383
|
+
# end
|
|
384
|
+
#
|
|
385
|
+
# def mock_project(stubs={})
|
|
386
|
+
# @project ||= mock_model(Project, stubs)
|
|
387
|
+
# end
|
|
388
|
+
#
|
|
389
|
+
# If you want to create just the instance method, you can give
|
|
390
|
+
# :class_method => false as option.
|
|
391
|
+
#
|
|
392
|
+
def mock_models(*models)
|
|
393
|
+
options = models.extract_options!
|
|
394
|
+
options = { :class_method => true }.merge(options)
|
|
395
|
+
|
|
396
|
+
models.each do |model|
|
|
397
|
+
self.class_eval <<-METHOD
|
|
398
|
+
#{"def self.mock_#{model}; proc { mock_#{model} }; end" if options[:class_method]}
|
|
399
|
+
|
|
400
|
+
def mock_#{model}(stubs={})
|
|
401
|
+
@#{model} ||= mock_model(#{model.to_s.classify}, stubs)
|
|
402
|
+
end
|
|
403
|
+
METHOD
|
|
404
|
+
end
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
protected
|
|
410
|
+
|
|
411
|
+
# Evaluates the expectation chain as stub or expectations.
|
|
412
|
+
#
|
|
413
|
+
def evaluate_expectation_chain(use_expectations=true) #:nodoc:
|
|
414
|
+
return if self.expects_chain.nil?
|
|
415
|
+
|
|
416
|
+
self.expects_chain.each do |method, default_options|
|
|
417
|
+
options = default_options.dup
|
|
418
|
+
|
|
419
|
+
# Those are used both in expectations and stubs
|
|
420
|
+
object = evaluate_value(options.delete(:on))
|
|
421
|
+
return_value = evaluate_value(options.delete(:returns))
|
|
422
|
+
|
|
423
|
+
raise ScriptError, "You have to give me :on as an option when calling :expects." if object.nil?
|
|
424
|
+
|
|
425
|
+
if use_expectations
|
|
426
|
+
with = evaluate_value(options.delete(:with))
|
|
427
|
+
times = options.delete(:times) || 1
|
|
428
|
+
|
|
429
|
+
chain = object.should_receive(method)
|
|
430
|
+
chain = chain.with(with) if with
|
|
431
|
+
chain = chain.exactly(times).times
|
|
432
|
+
else
|
|
433
|
+
chain = object.stub!(method)
|
|
434
|
+
end
|
|
435
|
+
chain = chain.and_return(return_value)
|
|
436
|
+
end
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
# Instance method run_stubs! if someone wants to declare additional
|
|
440
|
+
# tests and call the stubs inside of it.
|
|
441
|
+
#
|
|
442
|
+
def run_stubs!
|
|
443
|
+
evaluate_expectation_chain(false)
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
# Instance method run_expectations! if someone wants to declare
|
|
447
|
+
# additional tests and call the stubs inside of it.
|
|
448
|
+
#
|
|
449
|
+
def run_expectations!
|
|
450
|
+
evaluate_expectation_chain(true)
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
# Run the action declared in the describe group, but before runs also
|
|
454
|
+
# the expectations. If an action was already performed, it doesn't run
|
|
455
|
+
# anything at all and returns false.
|
|
456
|
+
#
|
|
457
|
+
# The first parameter is if you want to run expectations or stubs. You
|
|
458
|
+
# can also supply the verb (get, post, put or delete), which action to
|
|
459
|
+
# call, parameters and the mime type. If any of those parameters are
|
|
460
|
+
# supplied, they override the current definition.
|
|
461
|
+
#
|
|
462
|
+
def run_action!(use_expectations=true, verb=nil, action=nil, params=nil, mime=nil)
|
|
463
|
+
return false if controller.send(:performed?)
|
|
464
|
+
|
|
465
|
+
evaluate_expectation_chain(use_expectations)
|
|
466
|
+
|
|
467
|
+
mime ||= default_mime
|
|
468
|
+
verb ||= default_verb
|
|
469
|
+
action ||= default_action
|
|
470
|
+
params ||= default_params
|
|
471
|
+
|
|
472
|
+
raise ScriptError, "No action was performed or declared." unless verb && action
|
|
473
|
+
|
|
474
|
+
request.env["HTTP_ACCEPT"] ||= mime.to_s if mime
|
|
475
|
+
send(verb, action, params)
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
# Evaluate a given value.
|
|
479
|
+
#
|
|
480
|
+
# This allows procs to be given to the expectation chain and they will
|
|
481
|
+
# be evaluated in the instance binding.
|
|
482
|
+
#
|
|
483
|
+
def evaluate_value(duck) #:nodoc:
|
|
484
|
+
if duck.is_a?(Proc)
|
|
485
|
+
self.instance_eval(&duck)
|
|
486
|
+
else
|
|
487
|
+
duck
|
|
488
|
+
end
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
end
|
|
492
|
+
end
|
|
493
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: remarkable_rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.0.
|
|
4
|
+
version: 3.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Carlos Brando
|
|
@@ -10,7 +10,7 @@ autorequire:
|
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
12
|
|
|
13
|
-
date: 2009-04-
|
|
13
|
+
date: 2009-04-10 00:00:00 +02:00
|
|
14
14
|
default_executable:
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
@@ -31,7 +31,7 @@ dependencies:
|
|
|
31
31
|
requirements:
|
|
32
32
|
- - ">="
|
|
33
33
|
- !ruby/object:Gem::Version
|
|
34
|
-
version: 3.0.
|
|
34
|
+
version: 3.0.1
|
|
35
35
|
version:
|
|
36
36
|
- !ruby/object:Gem::Dependency
|
|
37
37
|
name: remarkable_activerecord
|
|
@@ -41,7 +41,7 @@ dependencies:
|
|
|
41
41
|
requirements:
|
|
42
42
|
- - ">="
|
|
43
43
|
- !ruby/object:Gem::Version
|
|
44
|
-
version: 3.0.
|
|
44
|
+
version: 3.0.1
|
|
45
45
|
version:
|
|
46
46
|
description: "Remarkable Rails: collection of matchers and macros with I18n for Rails"
|
|
47
47
|
email:
|