jakewendt-simply_testable 1.6.0
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/LICENSE +20 -0
- data/README.rdoc +42 -0
- data/generators/simply_testable/USAGE +0 -0
- data/generators/simply_testable/simply_testable_generator.rb +72 -0
- data/lib/jakewendt-simply_testable.rb +1 -0
- data/lib/simply_testable.rb +33 -0
- data/lib/simply_testable/action_controller_extension.rb +6 -0
- data/lib/simply_testable/action_controller_extension/accessible_via_format.rb +4 -0
- data/lib/simply_testable/action_controller_extension/accessible_via_protocol.rb +403 -0
- data/lib/simply_testable/action_controller_extension/accessible_via_user.rb +452 -0
- data/lib/simply_testable/action_controller_extension/routing.rb +27 -0
- data/lib/simply_testable/action_controller_extension/test_case.rb +23 -0
- data/lib/simply_testable/acts_as_list.rb +41 -0
- data/lib/simply_testable/assertions.rb +49 -0
- data/lib/simply_testable/associations.rb +222 -0
- data/lib/simply_testable/attributes.rb +240 -0
- data/lib/simply_testable/declarative.rb +57 -0
- data/lib/simply_testable/errors.rb +14 -0
- data/lib/simply_testable/pending.rb +73 -0
- data/lib/simply_testable/test_case.rb +65 -0
- metadata +102 -0
@@ -0,0 +1,452 @@
|
|
1
|
+
module SimplyTestable::ActionControllerExtension
|
2
|
+
module AccessibleViaUser
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ClassMethods
|
6
|
+
base.send(:include,InstanceMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
module InstanceMethods
|
10
|
+
|
11
|
+
# This needs to be static and not dynamic or the multiple
|
12
|
+
# calls that would create it would overwrite each other.
|
13
|
+
def nawil_redirection(options={})
|
14
|
+
if options[:redirect]
|
15
|
+
send(options[:redirect])
|
16
|
+
else
|
17
|
+
root_path
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end # module InstanceMethods
|
22
|
+
|
23
|
+
module ClassMethods
|
24
|
+
|
25
|
+
def awil_title(options={})
|
26
|
+
"with #{options[:login]} login#{options[:suffix]}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def assert_access_with_login(*actions)
|
30
|
+
user_options = actions.extract_options!
|
31
|
+
|
32
|
+
options = {}
|
33
|
+
if ( self.constants.include?('ASSERT_ACCESS_OPTIONS') )
|
34
|
+
options.merge!(self::ASSERT_ACCESS_OPTIONS)
|
35
|
+
end
|
36
|
+
options.merge!(user_options)
|
37
|
+
actions += options[:actions]||[]
|
38
|
+
|
39
|
+
m_key = options[:model].try(:underscore).try(:to_sym)
|
40
|
+
|
41
|
+
# o = {
|
42
|
+
# :actions => {
|
43
|
+
# :new => {
|
44
|
+
# :request => [ :get, :new ]
|
45
|
+
# }
|
46
|
+
# }
|
47
|
+
# }
|
48
|
+
|
49
|
+
logins = Array(options[:logins]||options[:login])
|
50
|
+
logins.each do |login|
|
51
|
+
# options[:login] is set for the title,
|
52
|
+
# but "login_as send(login)" as options[:login]
|
53
|
+
# will be the last in the array at runtime.
|
54
|
+
options[:login] = login
|
55
|
+
|
56
|
+
test "#{brand}should get new #{awil_title(options)}" do
|
57
|
+
login_as send(login)
|
58
|
+
args = options[:new] || {}
|
59
|
+
send(:get,:new,args)
|
60
|
+
assert_response :success
|
61
|
+
assert_template 'new'
|
62
|
+
assert assigns(m_key)
|
63
|
+
assert_nil flash[:error]
|
64
|
+
end if actions.include?(:new) || options.keys.include?(:new)
|
65
|
+
|
66
|
+
test "#{brand}should post create #{awil_title(options)}" do
|
67
|
+
login_as send(login)
|
68
|
+
args = if options[:create]
|
69
|
+
options[:create]
|
70
|
+
elsif options[:attributes_for_create]
|
71
|
+
{m_key => send(options[:attributes_for_create])}
|
72
|
+
else
|
73
|
+
{}
|
74
|
+
end
|
75
|
+
assert_difference("#{options[:model]}.count",1) do
|
76
|
+
send(:post,:create,args)
|
77
|
+
end
|
78
|
+
assert_response :redirect
|
79
|
+
assert_nil flash[:error]
|
80
|
+
end if actions.include?(:create) || options.keys.include?(:create)
|
81
|
+
|
82
|
+
test "#{brand}should get edit #{awil_title(options)}" do
|
83
|
+
login_as send(login)
|
84
|
+
args={}
|
85
|
+
if options[:method_for_create]
|
86
|
+
obj = send(options[:method_for_create])
|
87
|
+
args[:id] = obj.id
|
88
|
+
end
|
89
|
+
send(:get,:edit, args)
|
90
|
+
assert_response :success
|
91
|
+
assert_template 'edit'
|
92
|
+
assert assigns(m_key)
|
93
|
+
assert_nil flash[:error]
|
94
|
+
end if actions.include?(:edit) || options.keys.include?(:edit)
|
95
|
+
|
96
|
+
test "#{brand}should put update #{awil_title(options)}" do
|
97
|
+
login_as send(login)
|
98
|
+
args={}
|
99
|
+
if options[:method_for_create] && options[:attributes_for_create]
|
100
|
+
obj = send(options[:method_for_create])
|
101
|
+
args[:id] = obj.id
|
102
|
+
args[m_key] = send(options[:attributes_for_create])
|
103
|
+
end
|
104
|
+
before = obj.updated_at if obj
|
105
|
+
sleep 1 if obj # if updated too quickly, updated_at won't change
|
106
|
+
send(:put,:update, args)
|
107
|
+
after = obj.reload.updated_at if obj
|
108
|
+
assert_not_equal before.to_i,after.to_i if obj
|
109
|
+
assert_response :redirect
|
110
|
+
assert_nil flash[:error]
|
111
|
+
end if actions.include?(:update) || options.keys.include?(:update)
|
112
|
+
|
113
|
+
test "#{brand}should get show #{awil_title(options)}" do
|
114
|
+
login_as send(login)
|
115
|
+
args={}
|
116
|
+
if options[:method_for_create]
|
117
|
+
obj = send(options[:method_for_create])
|
118
|
+
args[:id] = obj.id
|
119
|
+
end
|
120
|
+
send(:get,:show, args)
|
121
|
+
assert_response :success
|
122
|
+
assert_template 'show'
|
123
|
+
assert assigns(m_key)
|
124
|
+
assert_nil flash[:error]
|
125
|
+
end if actions.include?(:show) || options.keys.include?(:show)
|
126
|
+
|
127
|
+
test "#{brand}should delete destroy #{awil_title(options)}" do
|
128
|
+
login_as send(login)
|
129
|
+
args={}
|
130
|
+
if options[:method_for_create]
|
131
|
+
obj = send(options[:method_for_create])
|
132
|
+
args[:id] = obj.id
|
133
|
+
end
|
134
|
+
assert_difference("#{options[:model]}.count",-1) do
|
135
|
+
send(:delete,:destroy,args)
|
136
|
+
end
|
137
|
+
assert_response :redirect
|
138
|
+
assert assigns(m_key)
|
139
|
+
assert_nil flash[:error]
|
140
|
+
end if actions.include?(:destroy) || options.keys.include?(:destroy)
|
141
|
+
|
142
|
+
test "#{brand}should get index #{awil_title(options)}" do
|
143
|
+
login_as send(login)
|
144
|
+
get :index
|
145
|
+
assert_response :success
|
146
|
+
assert_template 'index'
|
147
|
+
assert assigns(m_key.try(:to_s).try(:pluralize).try(:to_sym))
|
148
|
+
assert_nil flash[:error]
|
149
|
+
end if actions.include?(:index) || options.keys.include?(:index)
|
150
|
+
|
151
|
+
test "#{brand}should get index #{awil_title(options)} and items" do
|
152
|
+
send(options[:before]) if !options[:before].blank?
|
153
|
+
login_as send(login)
|
154
|
+
3.times{ send(options[:method_for_create]) } if !options[:method_for_create].blank?
|
155
|
+
get :index
|
156
|
+
assert_response :success
|
157
|
+
assert_template 'index'
|
158
|
+
assert assigns(m_key.try(:to_s).try(:pluralize).try(:to_sym))
|
159
|
+
assert_nil flash[:error]
|
160
|
+
end if actions.include?(:index) || options.keys.include?(:index)
|
161
|
+
|
162
|
+
end # logins.each
|
163
|
+
end
|
164
|
+
|
165
|
+
|
166
|
+
# I can't imagine a whole lot of use for this one.
|
167
|
+
|
168
|
+
def assert_access_without_login(*actions)
|
169
|
+
user_options = actions.extract_options!
|
170
|
+
|
171
|
+
options = {}
|
172
|
+
if ( self.constants.include?('ASSERT_ACCESS_OPTIONS') )
|
173
|
+
options.merge!(self::ASSERT_ACCESS_OPTIONS)
|
174
|
+
end
|
175
|
+
options.merge!(user_options)
|
176
|
+
actions += options[:actions]||[]
|
177
|
+
|
178
|
+
m_key = options[:model].try(:underscore).try(:to_sym)
|
179
|
+
|
180
|
+
# test "should NOT get new without login" do
|
181
|
+
# get :new
|
182
|
+
# assert_redirected_to_login
|
183
|
+
# end if actions.include?(:new) || options.keys.include?(:new)
|
184
|
+
#
|
185
|
+
# test "should NOT post create without login" do
|
186
|
+
# args = {}
|
187
|
+
# args = if options[:create]
|
188
|
+
# options[:create]
|
189
|
+
# else
|
190
|
+
# {options[:factory] => Factory.attributes_for(options[:factory])}
|
191
|
+
# end
|
192
|
+
# assert_no_difference("#{options[:model]}.count") do
|
193
|
+
# send(:post,:create,args)
|
194
|
+
# end
|
195
|
+
# assert_redirected_to_login
|
196
|
+
# end if actions.include?(:create) || options.keys.include?(:create)
|
197
|
+
#
|
198
|
+
# test "should NOT get edit without login" do
|
199
|
+
# args=[]
|
200
|
+
# if options[:factory]
|
201
|
+
# obj = Factory(options[:factory])
|
202
|
+
# args.push(:id => obj.id)
|
203
|
+
# end
|
204
|
+
# send(:get,:edit, *args)
|
205
|
+
# assert_redirected_to_login
|
206
|
+
# end if actions.include?(:edit) || options.keys.include?(:edit)
|
207
|
+
#
|
208
|
+
# test "should NOT put update without login" do
|
209
|
+
# args={}
|
210
|
+
# if options[:factory]
|
211
|
+
# obj = Factory(options[:factory])
|
212
|
+
# args[:id] = obj.id
|
213
|
+
# args[options[:factory]] = Factory.attributes_for(options[:factory])
|
214
|
+
# end
|
215
|
+
# send(:put,:update, args)
|
216
|
+
# assert_redirected_to_login
|
217
|
+
# end if actions.include?(:update) || options.keys.include?(:update)
|
218
|
+
|
219
|
+
test "#{brand}AWoL should get show without login" do
|
220
|
+
args={}
|
221
|
+
if options[:method_for_create]
|
222
|
+
obj = send(options[:method_for_create])
|
223
|
+
args[:id] = obj.id
|
224
|
+
end
|
225
|
+
send(:get,:show, args)
|
226
|
+
assert_response :success
|
227
|
+
assert_template 'show'
|
228
|
+
assert assigns(m_key)
|
229
|
+
assert_nil flash[:error]
|
230
|
+
end if actions.include?(:show) || options.keys.include?(:show)
|
231
|
+
|
232
|
+
# test "should NOT delete destroy without login" do
|
233
|
+
# args=[]
|
234
|
+
# if options[:factory]
|
235
|
+
# obj = Factory(options[:factory])
|
236
|
+
# args.push(:id => obj.id)
|
237
|
+
# end
|
238
|
+
# assert_no_difference("#{options[:model]}.count") do
|
239
|
+
# send(:delete,:destroy,*args)
|
240
|
+
# end
|
241
|
+
# assert_redirected_to_login
|
242
|
+
# end if actions.include?(:destroy) || options.keys.include?(:destroy)
|
243
|
+
#
|
244
|
+
# test "should NOT get index without login" do
|
245
|
+
# get :index
|
246
|
+
# assert_redirected_to_login
|
247
|
+
# end if actions.include?(:index) || options.keys.include?(:index)
|
248
|
+
|
249
|
+
end
|
250
|
+
|
251
|
+
def nawil_title(options={})
|
252
|
+
"with #{options[:login]} login#{options[:suffix]}"
|
253
|
+
end
|
254
|
+
|
255
|
+
def assert_no_access_with_login(*actions)
|
256
|
+
user_options = actions.extract_options!
|
257
|
+
|
258
|
+
options = {}
|
259
|
+
if ( self.constants.include?('ASSERT_ACCESS_OPTIONS') )
|
260
|
+
options.merge!(self::ASSERT_ACCESS_OPTIONS)
|
261
|
+
end
|
262
|
+
options.merge!(user_options)
|
263
|
+
actions += options[:actions]||[]
|
264
|
+
|
265
|
+
m_key = options[:model].try(:underscore).try(:to_sym)
|
266
|
+
|
267
|
+
logins = Array(options[:logins]||options[:login])
|
268
|
+
logins.each do |login|
|
269
|
+
# options[:login] is set for the title,
|
270
|
+
# but "login_as send(login)" as options[:login]
|
271
|
+
# will be the last in the array at runtime.
|
272
|
+
options[:login] = login
|
273
|
+
|
274
|
+
test "#{brand}should NOT get new #{nawil_title(options)}" do
|
275
|
+
login_as send(login)
|
276
|
+
args = options[:new]||{}
|
277
|
+
send(:get,:new,args)
|
278
|
+
assert_not_nil flash[:error]
|
279
|
+
assert_redirected_to nawil_redirection(options)
|
280
|
+
end if actions.include?(:new) || options.keys.include?(:new)
|
281
|
+
|
282
|
+
test "#{brand}should NOT post create #{nawil_title(options)}" do
|
283
|
+
login_as send(login)
|
284
|
+
args = if options[:create]
|
285
|
+
options[:create]
|
286
|
+
elsif options[:attributes_for_create]
|
287
|
+
{m_key => send(options[:attributes_for_create])}
|
288
|
+
else
|
289
|
+
{}
|
290
|
+
end
|
291
|
+
assert_no_difference("#{options[:model]}.count") do
|
292
|
+
send(:post,:create,args)
|
293
|
+
end
|
294
|
+
assert_not_nil flash[:error]
|
295
|
+
assert_redirected_to nawil_redirection(options)
|
296
|
+
end if actions.include?(:create) || options.keys.include?(:create)
|
297
|
+
|
298
|
+
test "#{brand}should NOT get edit #{nawil_title(options)}" do
|
299
|
+
login_as send(login)
|
300
|
+
args=options[:edit]||{}
|
301
|
+
if options[:method_for_create]
|
302
|
+
obj = send(options[:method_for_create])
|
303
|
+
args[:id] = obj.id
|
304
|
+
end
|
305
|
+
send(:get,:edit, args)
|
306
|
+
assert_not_nil flash[:error]
|
307
|
+
assert_redirected_to nawil_redirection(options)
|
308
|
+
end if actions.include?(:edit) || options.keys.include?(:edit)
|
309
|
+
|
310
|
+
test "#{brand}should NOT put update #{nawil_title(options)}" do
|
311
|
+
login_as send(login)
|
312
|
+
args=options[:update]||{}
|
313
|
+
if options[:method_for_create] && options[:attributes_for_create]
|
314
|
+
obj = send(options[:method_for_create])
|
315
|
+
args[:id] = obj.id
|
316
|
+
args[m_key] = send(options[:attributes_for_create])
|
317
|
+
end
|
318
|
+
before = obj.updated_at if obj
|
319
|
+
send(:put,:update, args)
|
320
|
+
after = obj.reload.updated_at if obj
|
321
|
+
assert_equal before.to_s(:db), after.to_s(:db) if obj
|
322
|
+
assert_not_nil flash[:error]
|
323
|
+
assert_redirected_to nawil_redirection(options)
|
324
|
+
end if actions.include?(:update) || options.keys.include?(:update)
|
325
|
+
|
326
|
+
test "#{brand}should NOT get show #{nawil_title(options)}" do
|
327
|
+
login_as send(login)
|
328
|
+
args=options[:show]||{}
|
329
|
+
if options[:method_for_create]
|
330
|
+
obj = send(options[:method_for_create])
|
331
|
+
args[:id] = obj.id
|
332
|
+
end
|
333
|
+
send(:get,:show, args)
|
334
|
+
assert_not_nil flash[:error]
|
335
|
+
assert_redirected_to nawil_redirection(options)
|
336
|
+
end if actions.include?(:show) || options.keys.include?(:show)
|
337
|
+
|
338
|
+
test "#{brand}should NOT delete destroy #{nawil_title(options)}" do
|
339
|
+
login_as send(login)
|
340
|
+
args=options[:destroy]||{}
|
341
|
+
if options[:method_for_create]
|
342
|
+
obj = send(options[:method_for_create])
|
343
|
+
args[:id] = obj.id
|
344
|
+
end
|
345
|
+
assert_no_difference("#{options[:model]}.count") do
|
346
|
+
send(:delete,:destroy,args)
|
347
|
+
end
|
348
|
+
assert_not_nil flash[:error]
|
349
|
+
assert_redirected_to nawil_redirection(options)
|
350
|
+
end if actions.include?(:destroy) || options.keys.include?(:destroy)
|
351
|
+
|
352
|
+
test "#{brand}should NOT get index #{nawil_title(options)}" do
|
353
|
+
login_as send(login)
|
354
|
+
get :index
|
355
|
+
assert_not_nil flash[:error]
|
356
|
+
assert_redirected_to nawil_redirection(options)
|
357
|
+
end if actions.include?(:index) || options.keys.include?(:index)
|
358
|
+
|
359
|
+
end # logins.each
|
360
|
+
end
|
361
|
+
|
362
|
+
def assert_no_access_without_login(*actions)
|
363
|
+
user_options = actions.extract_options!
|
364
|
+
|
365
|
+
options = {}
|
366
|
+
if ( self.constants.include?('ASSERT_ACCESS_OPTIONS') )
|
367
|
+
options.merge!(self::ASSERT_ACCESS_OPTIONS)
|
368
|
+
end
|
369
|
+
options.merge!(user_options)
|
370
|
+
actions += options[:actions]||[]
|
371
|
+
|
372
|
+
m_key = options[:model].try(:underscore).try(:to_sym)
|
373
|
+
|
374
|
+
test "#{brand}should NOT get new without login" do
|
375
|
+
get :new
|
376
|
+
assert_redirected_to_login
|
377
|
+
end if actions.include?(:new) || options.keys.include?(:new)
|
378
|
+
|
379
|
+
test "#{brand}should NOT post create without login" do
|
380
|
+
args = if options[:create]
|
381
|
+
options[:create]
|
382
|
+
elsif options[:attributes_for_create]
|
383
|
+
{m_key => send(options[:attributes_for_create])}
|
384
|
+
else
|
385
|
+
{}
|
386
|
+
end
|
387
|
+
assert_no_difference("#{options[:model]}.count") do
|
388
|
+
send(:post,:create,args)
|
389
|
+
end
|
390
|
+
assert_redirected_to_login
|
391
|
+
end if actions.include?(:create) || options.keys.include?(:create)
|
392
|
+
|
393
|
+
test "#{brand}should NOT get edit without login" do
|
394
|
+
args={}
|
395
|
+
if options[:method_for_create]
|
396
|
+
obj = send(options[:method_for_create])
|
397
|
+
args[:id] = obj.id
|
398
|
+
end
|
399
|
+
send(:get,:edit, args)
|
400
|
+
assert_redirected_to_login
|
401
|
+
end if actions.include?(:edit) || options.keys.include?(:edit)
|
402
|
+
|
403
|
+
test "#{brand}should NOT put update without login" do
|
404
|
+
args={}
|
405
|
+
if options[:method_for_create] && options[:attributes_for_create]
|
406
|
+
obj = send(options[:method_for_create])
|
407
|
+
args[:id] = obj.id
|
408
|
+
args[m_key] = send(options[:attributes_for_create])
|
409
|
+
end
|
410
|
+
before = obj.updated_at if obj
|
411
|
+
send(:put,:update, args)
|
412
|
+
after = obj.reload.updated_at if obj
|
413
|
+
assert_equal before.to_s(:db), after.to_s(:db) if obj
|
414
|
+
assert_redirected_to_login
|
415
|
+
end if actions.include?(:update) || options.keys.include?(:update)
|
416
|
+
|
417
|
+
test "#{brand}should NOT get show without login" do
|
418
|
+
args={}
|
419
|
+
if options[:method_for_create]
|
420
|
+
obj = send(options[:method_for_create])
|
421
|
+
args[:id] = obj.id
|
422
|
+
end
|
423
|
+
send(:get,:show, args)
|
424
|
+
assert_redirected_to_login
|
425
|
+
end if actions.include?(:show) || options.keys.include?(:show)
|
426
|
+
|
427
|
+
test "#{brand}should NOT delete destroy without login" do
|
428
|
+
args={}
|
429
|
+
if options[:method_for_create]
|
430
|
+
obj = send(options[:method_for_create])
|
431
|
+
args[:id] = obj.id
|
432
|
+
end
|
433
|
+
assert_no_difference("#{options[:model]}.count") do
|
434
|
+
send(:delete,:destroy,args)
|
435
|
+
end
|
436
|
+
assert_redirected_to_login
|
437
|
+
end if actions.include?(:destroy) || options.keys.include?(:destroy)
|
438
|
+
|
439
|
+
test "#{brand}should NOT get index without login" do
|
440
|
+
get :index
|
441
|
+
assert_redirected_to_login
|
442
|
+
end if actions.include?(:index) || options.keys.include?(:index)
|
443
|
+
|
444
|
+
end
|
445
|
+
|
446
|
+
end # module ClassMethods
|
447
|
+
end # module AccessibleViaProtocol
|
448
|
+
end # module SimplyTestable::ActionControllerExtension
|
449
|
+
require 'action_controller'
|
450
|
+
require 'action_controller/test_case'
|
451
|
+
ActionController::TestCase.send(:include,
|
452
|
+
SimplyTestable::ActionControllerExtension::AccessibleViaUser)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module SimplyTestable::ActionControllerExtension
|
2
|
+
module Routing
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
|
10
|
+
# def assert_route
|
11
|
+
# end
|
12
|
+
|
13
|
+
def assert_no_route(verb,action,args={})
|
14
|
+
test "#{brand}no route to #{verb} #{action} #{args}" do
|
15
|
+
assert_raise(ActionController::RoutingError){
|
16
|
+
send(verb,action,args)
|
17
|
+
}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end # module ClassMethods
|
22
|
+
end # module Routing
|
23
|
+
end # module SimplyTestable::ActionControllerExtension
|
24
|
+
require 'action_controller'
|
25
|
+
require 'action_controller/test_case'
|
26
|
+
ActionController::TestCase.send(:include,
|
27
|
+
SimplyTestable::ActionControllerExtension::Routing)
|