technicalpickles-shoulda 2.0.0 → 2.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/Rakefile +1 -1
- data/lib/shoulda/active_record/assertions.rb +2 -1
- data/lib/shoulda/active_record/macros.rb +44 -25
- data/lib/shoulda/context.rb +1 -1
- data/lib/shoulda/controller/macros.rb +95 -0
- data/lib/shoulda/controller.rb +0 -1
- data/test/functional/posts_controller_test.rb +25 -0
- data/test/rails_root/app/controllers/posts_controller.rb +8 -1
- data/test/rails_root/app/models/user.rb +1 -1
- data/test/rails_root/config/environment.rb +2 -2
- data/test/test_helper.rb +6 -4
- data/test/unit/tag_test.rb +4 -0
- data/test/unit/user_test.rb +5 -0
- metadata +1 -1
- data/lib/shoulda/controller/routing/macros.rb +0 -47
- data/lib/shoulda/controller/routing.rb +0 -10
data/Rakefile
CHANGED
@@ -3,7 +3,7 @@ require 'rake/testtask'
|
|
3
3
|
require 'rake/rdoctask'
|
4
4
|
require 'rake/gempackagetask'
|
5
5
|
require 'lib/shoulda/context'
|
6
|
-
|
6
|
+
load 'tasks/shoulda.rake'
|
7
7
|
|
8
8
|
# Test::Unit::UI::VERBOSE
|
9
9
|
test_files_pattern = 'test/{unit,functional,other}/**/*_test.rb'
|
@@ -56,7 +56,8 @@ module ThoughtBot # :nodoc:
|
|
56
56
|
#
|
57
57
|
# @product = Product.new(:tangible => true)
|
58
58
|
# assert_bad_value(Product, :price, "0")
|
59
|
-
def assert_bad_value(object_or_klass, attribute, value,
|
59
|
+
def assert_bad_value(object_or_klass, attribute, value,
|
60
|
+
error_message_to_expect = DEFAULT_ERROR_MESSAGES[:invalid])
|
60
61
|
object = get_instance_of(object_or_klass)
|
61
62
|
object.send("#{attribute}=", value)
|
62
63
|
assert !object.valid?, "#{object.class} allowed #{value.inspect} as a value for #{attribute}"
|
@@ -1,6 +1,13 @@
|
|
1
1
|
module ThoughtBot # :nodoc:
|
2
2
|
module Shoulda # :nodoc:
|
3
3
|
module ActiveRecord # :nodoc:
|
4
|
+
DEFAULT_ERROR_MESSAGES =
|
5
|
+
if Object.const_defined?(:I18n)
|
6
|
+
I18n.translate('active_record.error_messages')
|
7
|
+
else
|
8
|
+
::ActiveRecord::Errors.default_error_messages
|
9
|
+
end
|
10
|
+
|
4
11
|
# = Macro test helpers for your active record models
|
5
12
|
#
|
6
13
|
# These helpers will test most of the validations and associations for your ActiveRecord models.
|
@@ -36,14 +43,14 @@ module ThoughtBot # :nodoc:
|
|
36
43
|
#
|
37
44
|
# Options:
|
38
45
|
# * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
39
|
-
# Regexp or string. Default = <tt
|
46
|
+
# Regexp or string. Default = <tt>I18n.translate('active_record.error_messages')[:blank]</tt>
|
40
47
|
#
|
41
48
|
# Example:
|
42
49
|
# should_require_attributes :name, :phone_number
|
43
50
|
#
|
44
51
|
def should_require_attributes(*attributes)
|
45
52
|
message = get_options!(attributes, :message)
|
46
|
-
message ||=
|
53
|
+
message ||= DEFAULT_ERROR_MESSAGES[:blank]
|
47
54
|
klass = model_class
|
48
55
|
|
49
56
|
attributes.each do |attribute|
|
@@ -58,7 +65,7 @@ module ThoughtBot # :nodoc:
|
|
58
65
|
#
|
59
66
|
# Options:
|
60
67
|
# * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
61
|
-
# Regexp or string. Default = <tt
|
68
|
+
# Regexp or string. Default = <tt>I18n.translate('active_record.error_messages')[:taken]</tt>
|
62
69
|
# * <tt>:scoped_to</tt> - field(s) to scope the uniqueness to.
|
63
70
|
#
|
64
71
|
# Examples:
|
@@ -70,7 +77,7 @@ module ThoughtBot # :nodoc:
|
|
70
77
|
def should_require_unique_attributes(*attributes)
|
71
78
|
message, scope = get_options!(attributes, :message, :scoped_to)
|
72
79
|
scope = [*scope].compact
|
73
|
-
message ||=
|
80
|
+
message ||= DEFAULT_ERROR_MESSAGES[:taken]
|
74
81
|
|
75
82
|
klass = model_class
|
76
83
|
attributes.each do |attribute|
|
@@ -118,7 +125,8 @@ module ThoughtBot # :nodoc:
|
|
118
125
|
protected = klass.protected_attributes || []
|
119
126
|
accessible = klass.accessible_attributes || []
|
120
127
|
|
121
|
-
assert protected.include?(attribute.to_s) ||
|
128
|
+
assert protected.include?(attribute.to_s) ||
|
129
|
+
(!accessible.empty? && !accessible.include?(attribute.to_s)),
|
122
130
|
(accessible.empty? ?
|
123
131
|
"#{klass} is protecting #{protected.to_a.to_sentence}, but not #{attribute}." :
|
124
132
|
"#{klass} has made #{attribute} accessible")
|
@@ -155,14 +163,14 @@ module ThoughtBot # :nodoc:
|
|
155
163
|
#
|
156
164
|
# Options:
|
157
165
|
# * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
158
|
-
# Regexp or string. Default = <tt
|
166
|
+
# Regexp or string. Default = <tt>I18n.translate('active_record.error_messages')[:invalid]</tt>
|
159
167
|
#
|
160
168
|
# Example:
|
161
169
|
# should_not_allow_values_for :isbn, "bad 1", "bad 2"
|
162
170
|
#
|
163
171
|
def should_not_allow_values_for(attribute, *bad_values)
|
164
172
|
message = get_options!(bad_values, :message)
|
165
|
-
message ||=
|
173
|
+
message ||= DEFAULT_ERROR_MESSAGES[:invalid]
|
166
174
|
klass = model_class
|
167
175
|
bad_values.each do |v|
|
168
176
|
should "not allow #{attribute} to be set to #{v.inspect}" do
|
@@ -198,17 +206,17 @@ module ThoughtBot # :nodoc:
|
|
198
206
|
#
|
199
207
|
# Options:
|
200
208
|
# * <tt>:short_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
201
|
-
# Regexp or string. Default = <tt
|
209
|
+
# Regexp or string. Default = <tt>I18n.translate('active_record.error_messages')[:too_short] % range.first</tt>
|
202
210
|
# * <tt>:long_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
203
|
-
# Regexp or string. Default = <tt
|
211
|
+
# Regexp or string. Default = <tt>I18n.translate('active_record.error_messages')[:too_long] % range.last</tt>
|
204
212
|
#
|
205
213
|
# Example:
|
206
214
|
# should_ensure_length_in_range :password, (6..20)
|
207
215
|
#
|
208
216
|
def should_ensure_length_in_range(attribute, range, opts = {})
|
209
217
|
short_message, long_message = get_options!([opts], :short_message, :long_message)
|
210
|
-
short_message ||=
|
211
|
-
long_message ||=
|
218
|
+
short_message ||= DEFAULT_ERROR_MESSAGES[:too_short] % range.first
|
219
|
+
long_message ||= DEFAULT_ERROR_MESSAGES[:too_long] % range.last
|
212
220
|
|
213
221
|
klass = model_class
|
214
222
|
min_length = range.first
|
@@ -250,14 +258,14 @@ module ThoughtBot # :nodoc:
|
|
250
258
|
#
|
251
259
|
# Options:
|
252
260
|
# * <tt>:short_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
253
|
-
# Regexp or string. Default = <tt
|
261
|
+
# Regexp or string. Default = <tt>I18n.translate('active_record.error_messages')[:too_short] % min_length</tt>
|
254
262
|
#
|
255
263
|
# Example:
|
256
264
|
# should_ensure_length_at_least :name, 3
|
257
265
|
#
|
258
266
|
def should_ensure_length_at_least(attribute, min_length, opts = {})
|
259
267
|
short_message = get_options!([opts], :short_message)
|
260
|
-
short_message ||=
|
268
|
+
short_message ||= DEFAULT_ERROR_MESSAGES[:too_short] % min_length
|
261
269
|
|
262
270
|
klass = model_class
|
263
271
|
|
@@ -281,14 +289,14 @@ module ThoughtBot # :nodoc:
|
|
281
289
|
#
|
282
290
|
# Options:
|
283
291
|
# * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
284
|
-
# Regexp or string. Default = <tt
|
292
|
+
# Regexp or string. Default = <tt>I18n.translate('active_record.error_messages')[:wrong_length] % length</tt>
|
285
293
|
#
|
286
294
|
# Example:
|
287
295
|
# should_ensure_length_is :ssn, 9
|
288
296
|
#
|
289
297
|
def should_ensure_length_is(attribute, length, opts = {})
|
290
298
|
message = get_options!([opts], :message)
|
291
|
-
message ||=
|
299
|
+
message ||= DEFAULT_ERROR_MESSAGES[:wrong_length] % length
|
292
300
|
|
293
301
|
klass = model_class
|
294
302
|
|
@@ -316,17 +324,17 @@ module ThoughtBot # :nodoc:
|
|
316
324
|
#
|
317
325
|
# Options:
|
318
326
|
# * <tt>:low_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
319
|
-
# Regexp or string. Default = <tt
|
327
|
+
# Regexp or string. Default = <tt>I18n.translate('active_record.error_messages')[:inclusion]</tt>
|
320
328
|
# * <tt>:high_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
321
|
-
# Regexp or string. Default = <tt
|
329
|
+
# Regexp or string. Default = <tt>I18n.translate('active_record.error_messages')[:inclusion]</tt>
|
322
330
|
#
|
323
331
|
# Example:
|
324
332
|
# should_ensure_value_in_range :age, (0..100)
|
325
333
|
#
|
326
334
|
def should_ensure_value_in_range(attribute, range, opts = {})
|
327
335
|
low_message, high_message = get_options!([opts], :low_message, :high_message)
|
328
|
-
low_message ||=
|
329
|
-
high_message ||=
|
336
|
+
low_message ||= DEFAULT_ERROR_MESSAGES[:inclusion]
|
337
|
+
high_message ||= DEFAULT_ERROR_MESSAGES[:inclusion]
|
330
338
|
|
331
339
|
klass = model_class
|
332
340
|
min = range.first
|
@@ -361,14 +369,14 @@ module ThoughtBot # :nodoc:
|
|
361
369
|
#
|
362
370
|
# Options:
|
363
371
|
# * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
364
|
-
# Regexp or string. Default = <tt
|
372
|
+
# Regexp or string. Default = <tt>I18n.translate('active_record.error_messages')[:not_a_number]</tt>
|
365
373
|
#
|
366
374
|
# Example:
|
367
375
|
# should_only_allow_numeric_values_for :age
|
368
376
|
#
|
369
377
|
def should_only_allow_numeric_values_for(*attributes)
|
370
378
|
message = get_options!(attributes, :message)
|
371
|
-
message ||=
|
379
|
+
message ||= DEFAULT_ERROR_MESSAGES[:not_a_number]
|
372
380
|
klass = model_class
|
373
381
|
attributes.each do |attribute|
|
374
382
|
attribute = attribute.to_sym
|
@@ -439,14 +447,19 @@ module ThoughtBot # :nodoc:
|
|
439
447
|
# associated table has the required columns. Works with polymorphic
|
440
448
|
# associations.
|
441
449
|
#
|
450
|
+
# Options:
|
451
|
+
# * <tt>:dependent</tt> - tests that the association makes use of the dependent option.
|
452
|
+
#
|
442
453
|
# Example:
|
443
454
|
# should_have_one :god # unless hindu
|
444
455
|
#
|
445
456
|
def should_have_one(*associations)
|
446
|
-
get_options!(associations)
|
457
|
+
dependent = get_options!(associations, :dependent)
|
447
458
|
klass = model_class
|
448
459
|
associations.each do |association|
|
449
|
-
|
460
|
+
name = "have one #{association}"
|
461
|
+
name += " dependent => #{dependent}" if dependent
|
462
|
+
should name do
|
450
463
|
reflection = klass.reflect_on_association(association)
|
451
464
|
assert reflection, "#{klass.name} does not have any relationship to #{association}"
|
452
465
|
assert_equal :has_one, reflection.macro
|
@@ -465,6 +478,12 @@ module ThoughtBot # :nodoc:
|
|
465
478
|
end
|
466
479
|
assert associated_klass.column_names.include?(fk.to_s),
|
467
480
|
"#{associated_klass.name} does not have a #{fk} foreign key."
|
481
|
+
|
482
|
+
if dependent
|
483
|
+
assert_equal dependent.to_s,
|
484
|
+
reflection.options[:dependent].to_s,
|
485
|
+
"#{association} should have #{dependent} dependency"
|
486
|
+
end
|
468
487
|
end
|
469
488
|
end
|
470
489
|
end
|
@@ -604,14 +623,14 @@ module ThoughtBot # :nodoc:
|
|
604
623
|
#
|
605
624
|
# Options:
|
606
625
|
# * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
607
|
-
# Regexp or string. Default = <tt
|
626
|
+
# Regexp or string. Default = <tt>I18n.translate('active_record.error_messages')[:accepted]</tt>
|
608
627
|
#
|
609
628
|
# Example:
|
610
629
|
# should_require_acceptance_of :eula
|
611
630
|
#
|
612
631
|
def should_require_acceptance_of(*attributes)
|
613
632
|
message = get_options!(attributes, :message)
|
614
|
-
message ||=
|
633
|
+
message ||= DEFAULT_ERROR_MESSAGES[:accepted]
|
615
634
|
klass = model_class
|
616
635
|
|
617
636
|
attributes.each do |attribute|
|
data/lib/shoulda/context.rb
CHANGED
@@ -134,6 +134,37 @@ module ThoughtBot # :nodoc:
|
|
134
134
|
end
|
135
135
|
end
|
136
136
|
|
137
|
+
# Macro that creates a test asserting that the response content type was 'content_type'.
|
138
|
+
# Example:
|
139
|
+
#
|
140
|
+
# should_respond_with_content_type 'application/rss+xml'
|
141
|
+
def should_respond_with_content_type(content_type)
|
142
|
+
should "respond with content type of #{content_type}" do
|
143
|
+
content_type = Mime::EXTENSION_LOOKUP[content_type.to_s].to_s if content_type.is_a? Symbol
|
144
|
+
if content_type.is_a? Regexp
|
145
|
+
assert_match content_type, @response.content_type, "Expected to match #{content_type} but was actually #{@response.content_type}"
|
146
|
+
else
|
147
|
+
assert_equal content_type, @response.content_type, "Expected #{content_type} but was actually #{@response.content_type}"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
# Macro that creates a test asserting that a value returned from the session is correct.
|
153
|
+
# The given string is evaled to produce the resulting redirect path. All of the instance variables
|
154
|
+
# set by the controller are available to the evaled string.
|
155
|
+
# Example:
|
156
|
+
#
|
157
|
+
# should_return_from_session :user_id, '@user.id'
|
158
|
+
# should_return_from_session :message, '"Free stuff"'
|
159
|
+
def should_return_from_session(key, expected)
|
160
|
+
should "return the correct value from the session for key #{key}" do
|
161
|
+
instantiate_variables_from_assigns do
|
162
|
+
expected_value = eval(expected, self.send(:binding), __FILE__, __LINE__)
|
163
|
+
assert_equal expected_value, session[key], "Expected #{expected_value.inspect} but was #{session[key]}"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
137
168
|
# Macro that creates a test asserting that the controller rendered the given template.
|
138
169
|
# Example:
|
139
170
|
#
|
@@ -144,6 +175,32 @@ module ThoughtBot # :nodoc:
|
|
144
175
|
end
|
145
176
|
end
|
146
177
|
|
178
|
+
# Macro that creates a test asserting that the controller rendered with the given layout.
|
179
|
+
# Example:
|
180
|
+
#
|
181
|
+
# should_render_with_layout 'special'
|
182
|
+
def should_render_with_layout(expected_layout = 'application')
|
183
|
+
if expected_layout
|
184
|
+
should "render with #{expected_layout} layout" do
|
185
|
+
response_layout = @response.layout.blank? ? "" : @response.layout.split('/').last
|
186
|
+
assert_equal expected_layout,
|
187
|
+
response_layout,
|
188
|
+
"Expected to render with layout #{expected_layout} but was rendered with #{response_layout}"
|
189
|
+
end
|
190
|
+
else
|
191
|
+
should "render without layout" do
|
192
|
+
assert_nil @response.layout,
|
193
|
+
"Expected no layout, but was rendered using #{@response.layout}"
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
# Macro that creates a test asserting that the controller rendered without a layout.
|
199
|
+
# Same as @should_render_with_layout false@
|
200
|
+
def should_render_without_layout
|
201
|
+
should_render_with_layout nil
|
202
|
+
end
|
203
|
+
|
147
204
|
# Macro that creates a test asserting that the controller returned a redirect to the given path.
|
148
205
|
# The given string is evaled to produce the resulting redirect path. All of the instance variables
|
149
206
|
# set by the controller are available to the evaled string.
|
@@ -165,6 +222,44 @@ module ThoughtBot # :nodoc:
|
|
165
222
|
assert_select "form", true, "The template doesn't contain a <form> element"
|
166
223
|
end
|
167
224
|
end
|
225
|
+
|
226
|
+
# Macro that creates a routing test. It tries to use the given HTTP
|
227
|
+
# +method+ on the given +path+, and asserts that it routes to the
|
228
|
+
# given +options+.
|
229
|
+
#
|
230
|
+
# If you don't specify a :controller, it will try to guess the controller
|
231
|
+
# based on the current test.
|
232
|
+
#
|
233
|
+
# +to_param+ is called on the +options+ given.
|
234
|
+
#
|
235
|
+
# Examples:
|
236
|
+
#
|
237
|
+
# should_route :get, '/posts', :action => :index
|
238
|
+
# should_route :post, '/posts', :controller => :posts, :action => :create
|
239
|
+
# should_route :get, '/posts/1', :action => :show, :id => 1
|
240
|
+
# should_route :put, '/posts/1', :action => :update, :id => "1"
|
241
|
+
# should_route :delete, '/posts/1', :action => :destroy, :id => 1
|
242
|
+
# should_route :get, '/posts/new', :action => :new
|
243
|
+
#
|
244
|
+
def should_route(method, path, options)
|
245
|
+
unless options[:controller]
|
246
|
+
options[:controller] = self.name.gsub(/ControllerTest$/, '').tableize
|
247
|
+
end
|
248
|
+
options[:controller] = options[:controller].to_s
|
249
|
+
options[:action] = options[:action].to_s
|
250
|
+
|
251
|
+
populated_path = path.dup
|
252
|
+
options.each do |key, value|
|
253
|
+
options[key] = value.to_param if value.respond_to? :to_param
|
254
|
+
populated_path.gsub!(key.inspect, value.to_s)
|
255
|
+
end
|
256
|
+
|
257
|
+
should_name = "route #{method.to_s.upcase} #{populated_path} to/from #{options.inspect}"
|
258
|
+
|
259
|
+
should should_name do
|
260
|
+
assert_routing({:method => method, :path => populated_path}, options)
|
261
|
+
end
|
262
|
+
end
|
168
263
|
end
|
169
264
|
end
|
170
265
|
end
|
data/lib/shoulda/controller.rb
CHANGED
@@ -67,6 +67,31 @@ class PostsControllerTest < Test::Unit::TestCase
|
|
67
67
|
should_assign_to :user, :posts
|
68
68
|
should_not_assign_to :foo, :bar
|
69
69
|
end
|
70
|
+
|
71
|
+
context "viewing posts for a user with rss format" do
|
72
|
+
setup do
|
73
|
+
get :index, :user_id => users(:first), :format => 'rss'
|
74
|
+
@user = users(:first)
|
75
|
+
end
|
76
|
+
should_respond_with :success
|
77
|
+
should_respond_with_content_type 'application/rss+xml'
|
78
|
+
should_respond_with_content_type :rss
|
79
|
+
should_respond_with_content_type /rss/
|
80
|
+
should_return_from_session :special, "'$2 off your next purchase'"
|
81
|
+
should_return_from_session :special_user_id, '@user.id'
|
82
|
+
should_assign_to :user, :posts
|
83
|
+
should_not_assign_to :foo, :bar
|
84
|
+
end
|
85
|
+
|
86
|
+
context "viewing a post on GET to #show" do
|
87
|
+
setup { get :show, :user_id => users(:first), :id => posts(:first) }
|
88
|
+
should_render_with_layout 'wide'
|
89
|
+
end
|
90
|
+
|
91
|
+
context "on GET to #new" do
|
92
|
+
setup { get :new, :user_id => users(:first) }
|
93
|
+
should_render_without_layout
|
94
|
+
end
|
70
95
|
end
|
71
96
|
|
72
97
|
end
|
@@ -8,6 +8,12 @@ class PostsController < ApplicationController
|
|
8
8
|
respond_to do |format|
|
9
9
|
format.html # index.rhtml
|
10
10
|
format.xml { render :xml => @posts.to_xml }
|
11
|
+
format.rss do
|
12
|
+
headers['Content-Type'] = 'application/rss+xml'
|
13
|
+
session[:special] = '$2 off your next purchase'
|
14
|
+
session[:special_user_id] = @user.id
|
15
|
+
head :ok
|
16
|
+
end
|
11
17
|
end
|
12
18
|
end
|
13
19
|
|
@@ -15,13 +21,14 @@ class PostsController < ApplicationController
|
|
15
21
|
@post = @user.posts.find(params[:id])
|
16
22
|
|
17
23
|
respond_to do |format|
|
18
|
-
format.html
|
24
|
+
format.html { render :layout => 'wide' }
|
19
25
|
format.xml { render :xml => @post.to_xml }
|
20
26
|
end
|
21
27
|
end
|
22
28
|
|
23
29
|
def new
|
24
30
|
@post = @user.posts.build
|
31
|
+
render :layout => false
|
25
32
|
end
|
26
33
|
|
27
34
|
def edit
|
@@ -5,7 +5,7 @@ class User < ActiveRecord::Base
|
|
5
5
|
has_many :friendships
|
6
6
|
has_many :friends, :through => :friendships
|
7
7
|
|
8
|
-
has_one :address, :as => :addressable
|
8
|
+
has_one :address, :as => :addressable, :dependent => :destroy
|
9
9
|
|
10
10
|
named_scope :old, :conditions => "age > 50"
|
11
11
|
named_scope :eighteen, :conditions => { :age => 18 }
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Specifies gem version of Rails to use when vendor/rails is not present
|
2
2
|
old_verbose, $VERBOSE = $VERBOSE, nil
|
3
|
-
RAILS_GEM_VERSION = '2.1.0' unless defined? RAILS_GEM_VERSION
|
3
|
+
RAILS_GEM_VERSION = '>= 2.1.0' unless defined? RAILS_GEM_VERSION
|
4
4
|
$VERBOSE = old_verbose
|
5
5
|
|
6
6
|
require File.join(File.dirname(__FILE__), 'boot')
|
@@ -10,5 +10,5 @@ Rails::Initializer.run do |config|
|
|
10
10
|
config.cache_classes = false
|
11
11
|
config.whiny_nils = true
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
# Dependencies.log_activity = true
|
data/test/test_helper.rb
CHANGED
@@ -5,15 +5,15 @@ ENV['RAILS_ENV'] = 'sqlite3'
|
|
5
5
|
rails_root = File.dirname(__FILE__) + '/rails_root'
|
6
6
|
|
7
7
|
require "#{rails_root}/config/environment.rb"
|
8
|
-
|
8
|
+
|
9
9
|
# Load the testing framework
|
10
10
|
require 'test_help'
|
11
11
|
silence_warnings { RAILS_ENV = ENV['RAILS_ENV'] }
|
12
|
-
|
12
|
+
|
13
13
|
# Run the migrations
|
14
14
|
ActiveRecord::Migration.verbose = false
|
15
15
|
ActiveRecord::Migrator.migrate("#{RAILS_ROOT}/db/migrate")
|
16
|
-
|
16
|
+
|
17
17
|
# Setup the fixtures path
|
18
18
|
Test::Unit::TestCase.fixture_path = File.join(File.dirname(__FILE__), "fixtures")
|
19
19
|
|
@@ -25,7 +25,9 @@ class Test::Unit::TestCase #:nodoc:
|
|
25
25
|
Fixtures.create_fixtures(Test::Unit::TestCase.fixture_path, table_names)
|
26
26
|
end
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
self.use_transactional_fixtures = false
|
30
30
|
self.use_instantiated_fixtures = false
|
31
31
|
end
|
32
|
+
|
33
|
+
require 'test/fail_macros'
|
data/test/unit/tag_test.rb
CHANGED
data/test/unit/user_test.rb
CHANGED
@@ -10,6 +10,7 @@ class UserTest < Test::Unit::TestCase
|
|
10
10
|
should_have_many :friends
|
11
11
|
|
12
12
|
should_have_one :address
|
13
|
+
should_have_one :address, :dependent => :destroy
|
13
14
|
|
14
15
|
should_have_indices :email, :name, [:email, :name]
|
15
16
|
should_have_index :age
|
@@ -44,4 +45,8 @@ class UserTest < Test::Unit::TestCase
|
|
44
45
|
should_only_allow_numeric_values_for :ssn
|
45
46
|
|
46
47
|
should_have_readonly_attributes :name
|
48
|
+
|
49
|
+
should_fail do
|
50
|
+
should_protect_attributes :name, :age
|
51
|
+
end
|
47
52
|
end
|
metadata
CHANGED
@@ -1,47 +0,0 @@
|
|
1
|
-
module ThoughtBot
|
2
|
-
module Shoulda
|
3
|
-
module Controller
|
4
|
-
module Routing
|
5
|
-
module Macros
|
6
|
-
# Macro that creates a routing test. It tries to use the given HTTP
|
7
|
-
# +method+ on the given +path+, and asserts that it routes to the
|
8
|
-
# given +options+.
|
9
|
-
#
|
10
|
-
# If you don't specify a :controller, it will try to guess the controller
|
11
|
-
# based on the current test.
|
12
|
-
#
|
13
|
-
# +to_param+ is called on the +options+ given.
|
14
|
-
#
|
15
|
-
# Examples:
|
16
|
-
#
|
17
|
-
# should_route :get, '/posts', :action => :index
|
18
|
-
# should_route :post, '/posts', :controller => :posts, :action => :create
|
19
|
-
# should_route :get, '/posts/1', :action => :show, :id => 1
|
20
|
-
# should_route :put, '/posts/1', :action => :update, :id => "1"
|
21
|
-
# should_route :delete, '/posts/1', :action => :destroy, :id => 1
|
22
|
-
# should_route :get, '/posts/new', :action => :new
|
23
|
-
#
|
24
|
-
def should_route(method, path, options)
|
25
|
-
unless options[:controller]
|
26
|
-
options[:controller] = self.name.gsub(/ControllerTest$/, '').tableize
|
27
|
-
end
|
28
|
-
options[:controller] = options[:controller].to_s
|
29
|
-
options[:action] = options[:action].to_s
|
30
|
-
|
31
|
-
populated_path = path.dup
|
32
|
-
options.each do |key, value|
|
33
|
-
options[key] = value.to_param if value.respond_to? :to_param
|
34
|
-
populated_path.gsub!(key.inspect, value.to_s)
|
35
|
-
end
|
36
|
-
|
37
|
-
should_name = "route #{method.to_s.upcase} #{populated_path} to/from #{options.inspect}"
|
38
|
-
|
39
|
-
should should_name do
|
40
|
-
assert_routing({:method => method, :path => populated_path}, options)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|