shoulda 2.10.1 → 2.10.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CONTRIBUTION_GUIDELINES.rdoc +4 -6
- data/README.rdoc +14 -12
- data/lib/shoulda.rb +1 -1
- data/lib/shoulda/action_controller.rb +0 -2
- data/lib/shoulda/action_controller/macros.rb +38 -75
- data/lib/shoulda/action_controller/matchers/respond_with_content_type_matcher.rb +4 -0
- data/lib/shoulda/action_controller/matchers/set_session_matcher.rb +1 -1
- data/lib/shoulda/action_view/macros.rb +6 -1
- data/lib/shoulda/active_record/assertions.rb +4 -4
- data/lib/shoulda/active_record/helpers.rb +0 -13
- data/lib/shoulda/active_record/macros.rb +50 -127
- data/lib/shoulda/active_record/matchers.rb +2 -1
- data/lib/shoulda/active_record/matchers/allow_mass_assignment_of_matcher.rb +1 -1
- data/lib/shoulda/active_record/matchers/allow_value_matcher.rb +5 -5
- data/lib/shoulda/active_record/matchers/association_matcher.rb +3 -3
- data/lib/shoulda/active_record/matchers/{have_index_matcher.rb → have_db_index_matcher.rb} +15 -8
- data/lib/shoulda/active_record/matchers/have_named_scope_matcher.rb +3 -0
- data/lib/shoulda/active_record/matchers/validate_format_of_matcher.rb +67 -0
- data/lib/shoulda/active_record/matchers/validation_matcher.rb +1 -0
- data/lib/shoulda/assertions.rb +18 -6
- data/lib/shoulda/context.rb +99 -1
- data/lib/shoulda/macros.rb +83 -23
- data/lib/shoulda/private_helpers.rb +1 -8
- data/lib/shoulda/test_unit.rb +3 -0
- data/test/fail_macros.rb +6 -1
- data/test/functional/posts_controller_test.rb +17 -21
- data/test/functional/users_controller_test.rb +1 -1
- data/test/matchers/active_record/allow_mass_assignment_of_matcher_test.rb +1 -1
- data/test/matchers/active_record/allow_value_matcher_test.rb +24 -1
- data/test/matchers/active_record/association_matcher_test.rb +8 -3
- data/test/matchers/active_record/ensure_inclusion_of_matcher_test.rb +1 -1
- data/test/matchers/active_record/ensure_length_of_matcher_test.rb +1 -1
- data/test/matchers/active_record/have_db_column_matcher_test.rb +1 -1
- data/test/matchers/active_record/{have_index_matcher_test.rb → have_db_index_matcher_test.rb} +24 -7
- data/test/matchers/active_record/have_named_scope_matcher_test.rb +1 -1
- data/test/matchers/active_record/have_readonly_attributes_matcher_test.rb +1 -1
- data/test/matchers/active_record/validate_acceptance_of_matcher_test.rb +1 -1
- data/test/matchers/active_record/validate_format_of_matcher_test.rb +39 -0
- data/test/matchers/active_record/validate_numericality_of_matcher_test.rb +1 -1
- data/test/matchers/active_record/validate_presence_of_matcher_test.rb +1 -1
- data/test/matchers/active_record/validate_uniqueness_of_matcher_test.rb +1 -1
- data/test/matchers/controller/assign_to_matcher_test.rb +1 -1
- data/test/matchers/controller/filter_param_matcher_test.rb +1 -1
- data/test/matchers/controller/render_with_layout_matcher_test.rb +1 -1
- data/test/matchers/controller/respond_with_content_type_matcher_test.rb +12 -7
- data/test/matchers/controller/respond_with_matcher_test.rb +1 -1
- data/test/matchers/controller/route_matcher_test.rb +1 -1
- data/test/matchers/controller/set_session_matcher_test.rb +9 -2
- data/test/matchers/controller/set_the_flash_matcher.rb +1 -1
- data/test/model_builder.rb +1 -1
- data/test/other/autoload_macro_test.rb +1 -1
- data/test/other/context_test.rb +45 -1
- data/test/other/convert_to_should_syntax_test.rb +3 -3
- data/test/other/helpers_test.rb +102 -3
- data/test/other/private_helpers_test.rb +6 -8
- data/test/other/should_test.rb +8 -3
- data/test/rails_root/app/controllers/{application.rb → application_controller.rb} +0 -0
- data/test/rails_root/app/controllers/posts_controller.rb +1 -0
- data/test/rails_root/app/models/pets/cat.rb +7 -0
- data/test/rails_root/app/models/profile.rb +2 -0
- data/test/rails_root/app/models/registration.rb +2 -0
- data/test/rails_root/app/models/user.rb +3 -0
- data/test/rails_root/config/boot.rb +6 -5
- data/test/rails_root/config/environment.rb +5 -1
- data/test/rails_root/db/migrate/20090506203502_create_profiles.rb +12 -0
- data/test/rails_root/db/migrate/20090506203536_create_registrations.rb +14 -0
- data/test/rails_root/db/migrate/20090513104502_create_cats.rb +12 -0
- data/test/rails_root/test/shoulda_macros/custom_macro.rb +1 -1
- data/test/rails_root/vendor/gems/gem_with_macro-0.0.1/shoulda_macros/gem_macro.rb +1 -1
- data/test/rails_root/vendor/plugins/plugin_with_macro/shoulda_macros/plugin_macro.rb +1 -1
- data/test/rspec_test.rb +1 -1
- data/test/test_helper.rb +3 -10
- data/test/unit/address_test.rb +2 -2
- data/test/unit/cat_test.rb +7 -0
- data/test/unit/dog_test.rb +2 -3
- data/test/unit/flea_test.rb +1 -1
- data/test/unit/post_test.rb +2 -2
- data/test/unit/product_test.rb +2 -6
- data/test/unit/tag_test.rb +2 -2
- data/test/unit/tagging_test.rb +1 -1
- data/test/unit/user_test.rb +18 -8
- metadata +15 -9
- data/lib/shoulda/action_controller/helpers.rb +0 -47
- data/test/rails_root/log/sqlite3.log +0 -0
- data/test/rails_root/log/test.log +0 -0
@@ -1,12 +1,10 @@
|
|
1
|
-
We're using GitHub[http://github.com/thoughtbot/shoulda/tree/master]
|
1
|
+
We're using GitHub[http://github.com/thoughtbot/shoulda/tree/master], and we've been getting any combination of github pull requests, tickets, patches, emails, etc. We need to normalize this workflow to make sure we don't miss any fixes.
|
2
2
|
|
3
3
|
* Make sure you're accessing the source from the {official repository}[http://github.com/thoughtbot/shoulda/tree/master].
|
4
|
-
* We prefer git branches over patches, but we can take either.
|
4
|
+
* We prefer git branches over patches, but we can take either.
|
5
5
|
* If you're using git, please make a branch for each separate contribution. We can cherry pick your commits, but pulling from a branch is easier.
|
6
6
|
* If you're submitting patches, please cut each fix or feature into a separate patch.
|
7
|
-
* There should be
|
8
|
-
*
|
9
|
-
* Please <b>don't send pull requests</b> Just update the lighthouse ticket with the url for your fix (or attach the patch) when it's ready. The github pull requests pretty much get dropped on the floor until someone with commit rights notices them in the mailbox.
|
7
|
+
* There should be an issue[http://github.com/thoughtbot/shoulda/issues] for any submission. If you've found a bug and want to fix it, open a new ticket at the same time.
|
8
|
+
* Please <b>don't send pull requests</b> Just update the issue with the url for your fix (or attach the patch) when it's ready. The github pull requests pretty much get dropped on the floor until someone with commit rights notices them in the mailbox.
|
10
9
|
* Contributions without tests won't be accepted. The file <tt>/test/README</tt> explains the testing system pretty thoroughly.
|
11
10
|
|
12
|
-
|
data/README.rdoc
CHANGED
@@ -75,22 +75,24 @@ Makes TDD so much easier.
|
|
75
75
|
=== Controller Tests (Shoulda::Controller::Macros)
|
76
76
|
|
77
77
|
Macros to test the most common controller patterns...
|
78
|
+
|
79
|
+
class PostsControllerTest < ActionController::TestCase
|
80
|
+
context "on GET to :show for first record" do
|
81
|
+
setup do
|
82
|
+
get :show, :id => 1
|
83
|
+
end
|
78
84
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
should_assign_to :user
|
85
|
-
should_respond_with :success
|
86
|
-
should_render_template :show
|
87
|
-
should_not_set_the_flash
|
85
|
+
should_assign_to :user
|
86
|
+
should_respond_with :success
|
87
|
+
should_render_template :show
|
88
|
+
should_not_set_the_flash
|
88
89
|
|
89
|
-
|
90
|
-
|
90
|
+
should "do something else really cool" do
|
91
|
+
assert_equal 1, assigns(:user).id
|
92
|
+
end
|
91
93
|
end
|
92
94
|
end
|
93
|
-
|
95
|
+
|
94
96
|
=== Helpful Assertions (Shoulda::Assertions)
|
95
97
|
|
96
98
|
More to come here, but have fun with what's there.
|
data/lib/shoulda.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'shoulda'
|
2
|
-
require 'shoulda/action_controller/helpers'
|
3
2
|
require 'shoulda/action_controller/matchers'
|
4
3
|
require 'shoulda/action_controller/macros'
|
5
4
|
|
@@ -7,7 +6,6 @@ module Test # :nodoc: all
|
|
7
6
|
module Unit
|
8
7
|
class TestCase
|
9
8
|
include Shoulda::ActionController::Matchers
|
10
|
-
include Shoulda::ActionController::Helpers
|
11
9
|
extend Shoulda::ActionController::Macros
|
12
10
|
end
|
13
11
|
end
|
@@ -24,31 +24,35 @@ module Shoulda # :nodoc:
|
|
24
24
|
module Macros
|
25
25
|
include Matchers
|
26
26
|
|
27
|
-
# Macro that creates a test asserting that the flash contains the given
|
28
|
-
#
|
27
|
+
# Macro that creates a test asserting that the flash contains the given
|
28
|
+
# value. Expects a +String+ or +Regexp+.
|
29
|
+
#
|
30
|
+
# If the argument is +nil+, it will assert that the flash is not set.
|
31
|
+
# This behavior is deprecated.
|
29
32
|
#
|
30
33
|
# Example:
|
31
34
|
#
|
32
35
|
# should_set_the_flash_to "Thank you for placing this order."
|
33
36
|
# should_set_the_flash_to /created/i
|
34
|
-
# should_set_the_flash_to nil
|
35
37
|
def should_set_the_flash_to(val)
|
36
|
-
matcher = set_the_flash.to(val)
|
37
38
|
if val
|
39
|
+
matcher = set_the_flash.to(val)
|
38
40
|
should matcher.description do
|
39
41
|
assert_accepts matcher, @controller
|
40
42
|
end
|
41
43
|
else
|
42
|
-
|
43
|
-
|
44
|
-
|
44
|
+
warn "[DEPRECATION] should_set_the_flash_to nil is deprecated. " <<
|
45
|
+
"Use should_not_set_the_flash instead."
|
46
|
+
should_not_set_the_flash
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
48
|
-
# Macro that creates a test asserting that the flash is empty.
|
49
|
-
# @should_set_the_flash_to nil@
|
50
|
+
# Macro that creates a test asserting that the flash is empty.
|
50
51
|
def should_not_set_the_flash
|
51
|
-
|
52
|
+
matcher = set_the_flash
|
53
|
+
should "not #{matcher.description}" do
|
54
|
+
assert_rejects matcher, @controller
|
55
|
+
end
|
52
56
|
end
|
53
57
|
|
54
58
|
# Macro that creates a test asserting that filter_parameter_logging
|
@@ -71,8 +75,9 @@ module Shoulda # :nodoc:
|
|
71
75
|
#
|
72
76
|
# Options:
|
73
77
|
# * <tt>:class</tt> - The expected class of the instance variable being checked.
|
74
|
-
#
|
75
|
-
# the
|
78
|
+
#
|
79
|
+
# If a block is passed, the assigned variable is expected to be equal to
|
80
|
+
# the return value of that block.
|
76
81
|
#
|
77
82
|
# Example:
|
78
83
|
#
|
@@ -80,25 +85,11 @@ module Shoulda # :nodoc:
|
|
80
85
|
# should_assign_to :user, :class => User
|
81
86
|
# should_assign_to(:user) { @user }
|
82
87
|
def should_assign_to(*names, &block)
|
83
|
-
|
84
|
-
if opts[:equals]
|
85
|
-
warn "[DEPRECATION] should_assign_to :var, :equals => 'val' " <<
|
86
|
-
"is deprecated. Use should_assign_to(:var) { 'val' } instead."
|
87
|
-
end
|
88
|
+
klass = get_options!(names, :class)
|
88
89
|
names.each do |name|
|
89
|
-
matcher = assign_to(name).with_kind_of(
|
90
|
-
|
91
|
-
|
92
|
-
should test_name do
|
93
|
-
if opts[:equals]
|
94
|
-
instantiate_variables_from_assigns do
|
95
|
-
expected_value = eval(opts[:equals],
|
96
|
-
self.send(:binding),
|
97
|
-
__FILE__,
|
98
|
-
__LINE__)
|
99
|
-
matcher = matcher.with(expected_value)
|
100
|
-
end
|
101
|
-
elsif block
|
90
|
+
matcher = assign_to(name).with_kind_of(klass)
|
91
|
+
should matcher.description do
|
92
|
+
if block
|
102
93
|
expected_value = instance_eval(&block)
|
103
94
|
matcher = matcher.with(expected_value)
|
104
95
|
end
|
@@ -141,49 +132,29 @@ module Shoulda # :nodoc:
|
|
141
132
|
# should_respond_with_content_type :rss
|
142
133
|
# should_respond_with_content_type /rss/
|
143
134
|
def should_respond_with_content_type(content_type)
|
144
|
-
|
145
|
-
|
135
|
+
matcher = respond_with_content_type(content_type)
|
136
|
+
should matcher.description do
|
146
137
|
assert_accepts matcher, @controller
|
147
138
|
end
|
148
139
|
end
|
149
140
|
|
150
|
-
# Macro that creates a test asserting that a value returned from the
|
151
|
-
#
|
152
|
-
#
|
141
|
+
# Macro that creates a test asserting that a value returned from the
|
142
|
+
# session is correct. Expects the session key as a parameter, and a block
|
143
|
+
# that returns the expected value.
|
144
|
+
#
|
153
145
|
# Example:
|
154
146
|
#
|
155
|
-
# should_set_session(:user_id) {
|
147
|
+
# should_set_session(:user_id) { @user.id }
|
156
148
|
# should_set_session(:message) { "Free stuff" }
|
157
|
-
def should_set_session(key,
|
149
|
+
def should_set_session(key, &block)
|
158
150
|
matcher = set_session(key)
|
159
|
-
if expected
|
160
|
-
warn "[DEPRECATION] should_set_session :key, 'val' is deprecated. " <<
|
161
|
-
"Use should_set_session(:key) { 'val' } instead."
|
162
|
-
end
|
163
151
|
should matcher.description do
|
164
|
-
|
165
|
-
|
166
|
-
expected_value = eval(expected,
|
167
|
-
self.send(:binding),
|
168
|
-
__FILE__,
|
169
|
-
__LINE__)
|
170
|
-
matcher = matcher.to(expected_value)
|
171
|
-
end
|
172
|
-
else
|
173
|
-
expected_value = instance_eval(&block)
|
174
|
-
matcher = matcher.to(expected_value)
|
175
|
-
end
|
152
|
+
expected_value = instance_eval(&block)
|
153
|
+
matcher = matcher.to(expected_value)
|
176
154
|
assert_accepts matcher, @controller
|
177
155
|
end
|
178
156
|
end
|
179
157
|
|
180
|
-
# Deprecated. See should_set_session
|
181
|
-
def should_return_from_session(key, expected)
|
182
|
-
warn "[DEPRECATION] should_require_attributes is deprecated. " <<
|
183
|
-
"Use should_set_session instead."
|
184
|
-
should_set_session(key, expected)
|
185
|
-
end
|
186
|
-
|
187
158
|
# Macro that creates a test asserting that the controller rendered the given template.
|
188
159
|
# Example:
|
189
160
|
#
|
@@ -217,26 +188,18 @@ module Shoulda # :nodoc:
|
|
217
188
|
should_render_with_layout nil
|
218
189
|
end
|
219
190
|
|
220
|
-
# Macro that creates a test asserting that the controller returned a
|
221
|
-
#
|
222
|
-
#
|
191
|
+
# Macro that creates a test asserting that the controller returned a
|
192
|
+
# redirect to the given path. The passed description will be used when
|
193
|
+
# generating a test name. Expects a block that returns the expected path
|
194
|
+
# for the redirect.
|
195
|
+
#
|
223
196
|
# Example:
|
224
197
|
#
|
225
198
|
# should_redirect_to("the user's profile") { user_url(@user) }
|
226
199
|
def should_redirect_to(description, &block)
|
227
|
-
unless block
|
228
|
-
warn "[DEPRECATION] should_redirect_to without a block is " <<
|
229
|
-
"deprecated. Use should_redirect_to('somewhere') { } instead."
|
230
|
-
end
|
231
200
|
should "redirect to #{description}" do
|
232
|
-
|
233
|
-
|
234
|
-
else
|
235
|
-
instantiate_variables_from_assigns do
|
236
|
-
url = eval(description, self.send(:binding), __FILE__, __LINE__)
|
237
|
-
end
|
238
|
-
end
|
239
|
-
assert_redirected_to url
|
201
|
+
expected_url = instance_eval(&block)
|
202
|
+
assert_redirected_to expected_url
|
240
203
|
end
|
241
204
|
end
|
242
205
|
|
@@ -11,7 +11,6 @@ module Shoulda # :nodoc:
|
|
11
11
|
# get :new
|
12
12
|
# end
|
13
13
|
#
|
14
|
-
# should_render_a_form
|
15
14
|
# should_render_page_with_metadata :title => /index/
|
16
15
|
#
|
17
16
|
# should "do something else really cool" do
|
@@ -23,12 +22,17 @@ module Shoulda # :nodoc:
|
|
23
22
|
module Macros
|
24
23
|
|
25
24
|
# Macro that creates a test asserting that the rendered view contains a <form> element.
|
25
|
+
#
|
26
|
+
# Deprecated.
|
26
27
|
def should_render_a_form
|
28
|
+
warn "[DEPRECATION] should_render_a_form is deprecated."
|
27
29
|
should "display a form" do
|
28
30
|
assert_select "form", true, "The template doesn't contain a <form> element"
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
34
|
+
# Deprecated.
|
35
|
+
#
|
32
36
|
# Macro that creates a test asserting that the rendered view contains the selected metatags.
|
33
37
|
# Values can be string or Regexps.
|
34
38
|
# Example:
|
@@ -40,6 +44,7 @@ module Shoulda # :nodoc:
|
|
40
44
|
# Example:
|
41
45
|
# should_render_page_with_metadata :title => /index/
|
42
46
|
def should_render_page_with_metadata(options)
|
47
|
+
warn "[DEPRECATION] should_render_page_with_metadata is deprecated."
|
43
48
|
options.each do |key, value|
|
44
49
|
should "have metatag #{key}" do
|
45
50
|
if key.to_sym == :title
|
@@ -30,8 +30,8 @@ module Shoulda # :nodoc:
|
|
30
30
|
#
|
31
31
|
# assert_good_value(User, :email, "user@example.com")
|
32
32
|
#
|
33
|
-
#
|
34
|
-
# assert_good_value(
|
33
|
+
# product = Product.new(:tangible => false)
|
34
|
+
# assert_good_value(product, :price, "0")
|
35
35
|
def assert_good_value(object_or_klass, attribute, value, error_message_to_avoid = nil)
|
36
36
|
object = get_instance_of(object_or_klass)
|
37
37
|
matcher = allow_value(value).
|
@@ -54,8 +54,8 @@ module Shoulda # :nodoc:
|
|
54
54
|
#
|
55
55
|
# assert_bad_value(User, :email, "invalid")
|
56
56
|
#
|
57
|
-
#
|
58
|
-
# assert_bad_value(
|
57
|
+
# product = Product.new(:tangible => true)
|
58
|
+
# assert_bad_value(product, :price, "0")
|
59
59
|
def assert_bad_value(object_or_klass, attribute, value,
|
60
60
|
error_message_to_expect = nil)
|
61
61
|
object = get_instance_of(object_or_klass)
|
@@ -8,19 +8,6 @@ module Shoulda # :nodoc:
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
def get_instance_of(object_or_klass)
|
12
|
-
if object_or_klass.is_a?(Class)
|
13
|
-
klass = object_or_klass
|
14
|
-
instance_variable_get("@#{instance_variable_name_for(klass)}") || klass.new
|
15
|
-
else
|
16
|
-
object_or_klass
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def instance_variable_name_for(klass)
|
21
|
-
klass.to_s.split('::').last.underscore
|
22
|
-
end
|
23
|
-
|
24
11
|
# Helper method that determines the default error message used by Active
|
25
12
|
# Record. Works for both existing Rails 2.1 and Rails 2.2 with the newly
|
26
13
|
# introduced I18n module used for localization.
|
@@ -25,10 +25,6 @@ module Shoulda # :nodoc:
|
|
25
25
|
|
26
26
|
# Ensures that the model cannot be saved if one of the attributes listed is not present.
|
27
27
|
#
|
28
|
-
# If an instance variable has been created in the setup named after the
|
29
|
-
# model being tested, then this method will use that. Otherwise, it will
|
30
|
-
# create a new instance to test against.
|
31
|
-
#
|
32
28
|
# Options:
|
33
29
|
# * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
34
30
|
# Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.blank')</tt>
|
@@ -38,23 +34,15 @@ module Shoulda # :nodoc:
|
|
38
34
|
#
|
39
35
|
def should_validate_presence_of(*attributes)
|
40
36
|
message = get_options!(attributes, :message)
|
41
|
-
klass = model_class
|
42
37
|
|
43
38
|
attributes.each do |attribute|
|
44
39
|
matcher = validate_presence_of(attribute).with_message(message)
|
45
40
|
should matcher.description do
|
46
|
-
assert_accepts(matcher,
|
41
|
+
assert_accepts(matcher, subject)
|
47
42
|
end
|
48
43
|
end
|
49
44
|
end
|
50
45
|
|
51
|
-
# Deprecated. See should_validate_presence_of
|
52
|
-
def should_require_attributes(*attributes)
|
53
|
-
warn "[DEPRECATION] should_require_attributes is deprecated. " <<
|
54
|
-
"Use should_validate_presence_of instead."
|
55
|
-
should_validate_presence_of(*attributes)
|
56
|
-
end
|
57
|
-
|
58
46
|
# Ensures that the model cannot be saved if one of the attributes listed is not unique.
|
59
47
|
# Requires an existing record
|
60
48
|
#
|
@@ -78,37 +66,27 @@ module Shoulda # :nodoc:
|
|
78
66
|
scope = [*scope].compact
|
79
67
|
case_sensitive = true if case_sensitive.nil?
|
80
68
|
|
81
|
-
klass = model_class
|
82
|
-
|
83
69
|
attributes.each do |attribute|
|
84
70
|
matcher = validate_uniqueness_of(attribute).
|
85
71
|
with_message(message).scoped_to(scope)
|
86
72
|
matcher = matcher.case_insensitive unless case_sensitive
|
87
73
|
should matcher.description do
|
88
|
-
assert_accepts(matcher,
|
74
|
+
assert_accepts(matcher, subject)
|
89
75
|
end
|
90
76
|
end
|
91
77
|
end
|
92
78
|
|
93
|
-
# Deprecated. See should_validate_uniqueness_of
|
94
|
-
def should_require_unique_attributes(*attributes)
|
95
|
-
warn "[DEPRECATION] should_require_unique_attributes is deprecated. " <<
|
96
|
-
"Use should_validate_uniqueness_of instead."
|
97
|
-
should_validate_uniqueness_of(*attributes)
|
98
|
-
end
|
99
|
-
|
100
79
|
# Ensures that the attribute can be set on mass update.
|
101
80
|
#
|
102
81
|
# should_allow_mass_assignment_of :first_name, :last_name
|
103
82
|
#
|
104
83
|
def should_allow_mass_assignment_of(*attributes)
|
105
84
|
get_options!(attributes)
|
106
|
-
klass = model_class
|
107
85
|
|
108
86
|
attributes.each do |attribute|
|
109
87
|
matcher = allow_mass_assignment_of(attribute)
|
110
88
|
should matcher.description do
|
111
|
-
assert_accepts matcher,
|
89
|
+
assert_accepts matcher, subject
|
112
90
|
end
|
113
91
|
end
|
114
92
|
end
|
@@ -119,90 +97,67 @@ module Shoulda # :nodoc:
|
|
119
97
|
#
|
120
98
|
def should_not_allow_mass_assignment_of(*attributes)
|
121
99
|
get_options!(attributes)
|
122
|
-
klass = model_class
|
123
100
|
|
124
101
|
attributes.each do |attribute|
|
125
102
|
matcher = allow_mass_assignment_of(attribute)
|
126
103
|
should "not #{matcher.description}" do
|
127
|
-
assert_rejects matcher,
|
104
|
+
assert_rejects matcher, subject
|
128
105
|
end
|
129
106
|
end
|
130
107
|
end
|
131
108
|
|
132
|
-
# Deprecated. See should_not_allow_mass_assignment_of
|
133
|
-
def should_protect_attributes(*attributes)
|
134
|
-
warn "[DEPRECATION] should_protect_attributes is deprecated. " <<
|
135
|
-
"Use should_not_allow_mass_assignment_of instead."
|
136
|
-
should_not_allow_mass_assignment_of(*attributes)
|
137
|
-
end
|
138
|
-
|
139
109
|
# Ensures that the attribute cannot be changed once the record has been created.
|
140
110
|
#
|
141
111
|
# should_have_readonly_attributes :password, :admin_flag
|
142
112
|
#
|
143
113
|
def should_have_readonly_attributes(*attributes)
|
144
114
|
get_options!(attributes)
|
145
|
-
klass = model_class
|
146
115
|
|
147
116
|
attributes.each do |attribute|
|
148
117
|
matcher = have_readonly_attribute(attribute)
|
149
118
|
should matcher.description do
|
150
|
-
assert_accepts matcher,
|
119
|
+
assert_accepts matcher, subject
|
151
120
|
end
|
152
121
|
end
|
153
122
|
end
|
154
123
|
|
155
124
|
# Ensures that the attribute cannot be set to the given values
|
156
125
|
#
|
157
|
-
# If an instance variable has been created in the setup named after the
|
158
|
-
# model being tested, then this method will use that. Otherwise, it will
|
159
|
-
# create a new instance to test against.
|
160
|
-
#
|
161
126
|
# Options:
|
162
127
|
# * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
163
|
-
# Regexp or string.
|
128
|
+
# Regexp or string. If omitted, the test will pass if there is ANY error in
|
129
|
+
# <tt>errors.on(:attribute)</tt>.
|
164
130
|
#
|
165
131
|
# Example:
|
166
132
|
# should_not_allow_values_for :isbn, "bad 1", "bad 2"
|
167
133
|
#
|
168
134
|
def should_not_allow_values_for(attribute, *bad_values)
|
169
135
|
message = get_options!(bad_values, :message)
|
170
|
-
klass = model_class
|
171
136
|
bad_values.each do |value|
|
172
137
|
matcher = allow_value(value).for(attribute).with_message(message)
|
173
138
|
should "not #{matcher.description}" do
|
174
|
-
assert_rejects matcher,
|
139
|
+
assert_rejects matcher, subject
|
175
140
|
end
|
176
141
|
end
|
177
142
|
end
|
178
143
|
|
179
144
|
# Ensures that the attribute can be set to the given values.
|
180
145
|
#
|
181
|
-
# If an instance variable has been created in the setup named after the
|
182
|
-
# model being tested, then this method will use that. Otherwise, it will
|
183
|
-
# create a new instance to test against.
|
184
|
-
#
|
185
146
|
# Example:
|
186
147
|
# should_allow_values_for :isbn, "isbn 1 2345 6789 0", "ISBN 1-2345-6789-0"
|
187
148
|
#
|
188
149
|
def should_allow_values_for(attribute, *good_values)
|
189
150
|
get_options!(good_values)
|
190
|
-
klass = model_class
|
191
|
-
klass = model_class
|
192
151
|
good_values.each do |value|
|
193
152
|
matcher = allow_value(value).for(attribute)
|
194
153
|
should matcher.description do
|
195
|
-
assert_accepts matcher,
|
154
|
+
assert_accepts matcher, subject
|
196
155
|
end
|
197
156
|
end
|
198
157
|
end
|
199
158
|
|
200
159
|
# Ensures that the length of the attribute is in the given range
|
201
160
|
#
|
202
|
-
# If an instance variable has been created in the setup named after the
|
203
|
-
# model being tested, then this method will use that. Otherwise, it will
|
204
|
-
# create a new instance to test against.
|
205
|
-
#
|
206
161
|
# Options:
|
207
162
|
# * <tt>:short_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
208
163
|
# Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.too_short') % range.first</tt>
|
@@ -216,8 +171,6 @@ module Shoulda # :nodoc:
|
|
216
171
|
short_message, long_message = get_options!([opts],
|
217
172
|
:short_message,
|
218
173
|
:long_message)
|
219
|
-
klass = model_class
|
220
|
-
|
221
174
|
matcher = ensure_length_of(attribute).
|
222
175
|
is_at_least(range.first).
|
223
176
|
with_short_message(short_message).
|
@@ -225,16 +178,12 @@ module Shoulda # :nodoc:
|
|
225
178
|
with_long_message(long_message)
|
226
179
|
|
227
180
|
should matcher.description do
|
228
|
-
assert_accepts matcher,
|
181
|
+
assert_accepts matcher, subject
|
229
182
|
end
|
230
183
|
end
|
231
184
|
|
232
185
|
# Ensures that the length of the attribute is at least a certain length
|
233
186
|
#
|
234
|
-
# If an instance variable has been created in the setup named after the
|
235
|
-
# model being tested, then this method will use that. Otherwise, it will
|
236
|
-
# create a new instance to test against.
|
237
|
-
#
|
238
187
|
# Options:
|
239
188
|
# * <tt>:short_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
240
189
|
# Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.too_short') % min_length</tt>
|
@@ -244,23 +193,18 @@ module Shoulda # :nodoc:
|
|
244
193
|
#
|
245
194
|
def should_ensure_length_at_least(attribute, min_length, opts = {})
|
246
195
|
short_message = get_options!([opts], :short_message)
|
247
|
-
klass = model_class
|
248
196
|
|
249
197
|
matcher = ensure_length_of(attribute).
|
250
198
|
is_at_least(min_length).
|
251
199
|
with_short_message(short_message)
|
252
200
|
|
253
201
|
should matcher.description do
|
254
|
-
assert_accepts matcher,
|
202
|
+
assert_accepts matcher, subject
|
255
203
|
end
|
256
204
|
end
|
257
205
|
|
258
206
|
# Ensures that the length of the attribute is exactly a certain length
|
259
207
|
#
|
260
|
-
# If an instance variable has been created in the setup named after the
|
261
|
-
# model being tested, then this method will use that. Otherwise, it will
|
262
|
-
# create a new instance to test against.
|
263
|
-
#
|
264
208
|
# Options:
|
265
209
|
# * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
266
210
|
# Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.wrong_length') % length</tt>
|
@@ -270,22 +214,17 @@ module Shoulda # :nodoc:
|
|
270
214
|
#
|
271
215
|
def should_ensure_length_is(attribute, length, opts = {})
|
272
216
|
message = get_options!([opts], :message)
|
273
|
-
klass = model_class
|
274
217
|
matcher = ensure_length_of(attribute).
|
275
218
|
is_equal_to(length).
|
276
219
|
with_message(message)
|
277
220
|
|
278
221
|
should matcher.description do
|
279
|
-
assert_accepts matcher,
|
222
|
+
assert_accepts matcher, subject
|
280
223
|
end
|
281
224
|
end
|
282
225
|
|
283
226
|
# Ensure that the attribute is in the range specified
|
284
227
|
#
|
285
|
-
# If an instance variable has been created in the setup named after the
|
286
|
-
# model being tested, then this method will use that. Otherwise, it will
|
287
|
-
# create a new instance to test against.
|
288
|
-
#
|
289
228
|
# Options:
|
290
229
|
# * <tt>:low_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
291
230
|
# Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.inclusion')</tt>
|
@@ -300,23 +239,18 @@ module Shoulda # :nodoc:
|
|
300
239
|
:message,
|
301
240
|
:low_message,
|
302
241
|
:high_message)
|
303
|
-
klass = model_class
|
304
242
|
matcher = ensure_inclusion_of(attribute).
|
305
243
|
in_range(range).
|
306
244
|
with_message(message).
|
307
245
|
with_low_message(low_message).
|
308
246
|
with_high_message(high_message)
|
309
247
|
should matcher.description do
|
310
|
-
assert_accepts matcher,
|
248
|
+
assert_accepts matcher, subject
|
311
249
|
end
|
312
250
|
end
|
313
251
|
|
314
252
|
# Ensure that the attribute is numeric
|
315
253
|
#
|
316
|
-
# If an instance variable has been created in the setup named after the
|
317
|
-
# model being tested, then this method will use that. Otherwise, it will
|
318
|
-
# create a new instance to test against.
|
319
|
-
#
|
320
254
|
# Options:
|
321
255
|
# * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
322
256
|
# Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.not_a_number')</tt>
|
@@ -326,23 +260,15 @@ module Shoulda # :nodoc:
|
|
326
260
|
#
|
327
261
|
def should_validate_numericality_of(*attributes)
|
328
262
|
message = get_options!(attributes, :message)
|
329
|
-
klass = model_class
|
330
263
|
attributes.each do |attribute|
|
331
264
|
matcher = validate_numericality_of(attribute).
|
332
265
|
with_message(message)
|
333
266
|
should matcher.description do
|
334
|
-
assert_accepts matcher,
|
267
|
+
assert_accepts matcher, subject
|
335
268
|
end
|
336
269
|
end
|
337
270
|
end
|
338
271
|
|
339
|
-
# Deprecated. See should_validate_numericality_of
|
340
|
-
def should_only_allow_numeric_values_for(*attributes)
|
341
|
-
warn "[DEPRECATION] should_only_allow_numeric_values_for is " <<
|
342
|
-
"deprecated. Use should_validate_numericality_of instead."
|
343
|
-
should_validate_numericality_of(*attributes)
|
344
|
-
end
|
345
|
-
|
346
272
|
# Ensures that the has_many relationship exists. Will also test that the
|
347
273
|
# associated table has the required columns. Works with polymorphic
|
348
274
|
# associations.
|
@@ -358,11 +284,10 @@ module Shoulda # :nodoc:
|
|
358
284
|
#
|
359
285
|
def should_have_many(*associations)
|
360
286
|
through, dependent = get_options!(associations, :through, :dependent)
|
361
|
-
klass = model_class
|
362
287
|
associations.each do |association|
|
363
288
|
matcher = have_many(association).through(through).dependent(dependent)
|
364
289
|
should matcher.description do
|
365
|
-
assert_accepts(matcher,
|
290
|
+
assert_accepts(matcher, subject)
|
366
291
|
end
|
367
292
|
end
|
368
293
|
end
|
@@ -378,12 +303,11 @@ module Shoulda # :nodoc:
|
|
378
303
|
# should_have_one :god # unless hindu
|
379
304
|
#
|
380
305
|
def should_have_one(*associations)
|
381
|
-
dependent = get_options!(associations, :dependent)
|
382
|
-
klass = model_class
|
306
|
+
dependent, through = get_options!(associations, :dependent, :through)
|
383
307
|
associations.each do |association|
|
384
|
-
matcher = have_one(association).dependent(dependent)
|
308
|
+
matcher = have_one(association).dependent(dependent).through(through)
|
385
309
|
should matcher.description do
|
386
|
-
assert_accepts(matcher,
|
310
|
+
assert_accepts(matcher, subject)
|
387
311
|
end
|
388
312
|
end
|
389
313
|
end
|
@@ -395,12 +319,11 @@ module Shoulda # :nodoc:
|
|
395
319
|
#
|
396
320
|
def should_have_and_belong_to_many(*associations)
|
397
321
|
get_options!(associations)
|
398
|
-
klass = model_class
|
399
322
|
|
400
323
|
associations.each do |association|
|
401
324
|
matcher = have_and_belong_to_many(association)
|
402
325
|
should matcher.description do
|
403
|
-
assert_accepts(matcher,
|
326
|
+
assert_accepts(matcher, subject)
|
404
327
|
end
|
405
328
|
end
|
406
329
|
end
|
@@ -411,11 +334,10 @@ module Shoulda # :nodoc:
|
|
411
334
|
#
|
412
335
|
def should_belong_to(*associations)
|
413
336
|
dependent = get_options!(associations, :dependent)
|
414
|
-
klass = model_class
|
415
337
|
associations.each do |association|
|
416
338
|
matcher = belong_to(association).dependent(dependent)
|
417
339
|
should matcher.description do
|
418
|
-
assert_accepts(matcher,
|
340
|
+
assert_accepts(matcher, subject)
|
419
341
|
end
|
420
342
|
end
|
421
343
|
end
|
@@ -426,7 +348,7 @@ module Shoulda # :nodoc:
|
|
426
348
|
#
|
427
349
|
def should_have_class_methods(*methods)
|
428
350
|
get_options!(methods)
|
429
|
-
klass =
|
351
|
+
klass = described_type
|
430
352
|
methods.each do |method|
|
431
353
|
should "respond to class method ##{method}" do
|
432
354
|
assert_respond_to klass, method, "#{klass.name} does not have class method #{method}"
|
@@ -440,7 +362,7 @@ module Shoulda # :nodoc:
|
|
440
362
|
#
|
441
363
|
def should_have_instance_methods(*methods)
|
442
364
|
get_options!(methods)
|
443
|
-
klass =
|
365
|
+
klass = described_type
|
444
366
|
methods.each do |method|
|
445
367
|
should "respond to instance method ##{method}" do
|
446
368
|
assert_respond_to klass.new, method, "#{klass.name} does not have instance method #{method}"
|
@@ -449,7 +371,7 @@ module Shoulda # :nodoc:
|
|
449
371
|
end
|
450
372
|
|
451
373
|
# Ensure that the given columns are defined on the models backing SQL table.
|
452
|
-
# Also aliased to
|
374
|
+
# Also aliased to should_have_db_column for readability.
|
453
375
|
# Takes the same options available in migrations:
|
454
376
|
# :type, :precision, :limit, :default, :null, and :scale
|
455
377
|
#
|
@@ -465,7 +387,6 @@ module Shoulda # :nodoc:
|
|
465
387
|
column_type, precision, limit, default, null, scale, sql_type =
|
466
388
|
get_options!(columns, :type, :precision, :limit,
|
467
389
|
:default, :null, :scale, :sql_type)
|
468
|
-
klass = model_class
|
469
390
|
columns.each do |name|
|
470
391
|
matcher = have_db_column(name).
|
471
392
|
of_type(column_type).
|
@@ -473,7 +394,7 @@ module Shoulda # :nodoc:
|
|
473
394
|
:default => default, :null => null,
|
474
395
|
:scale => scale, :sql_type => sql_type)
|
475
396
|
should matcher.description do
|
476
|
-
assert_accepts(matcher,
|
397
|
+
assert_accepts(matcher, subject)
|
477
398
|
end
|
478
399
|
end
|
479
400
|
end
|
@@ -481,7 +402,7 @@ module Shoulda # :nodoc:
|
|
481
402
|
alias_method :should_have_db_column, :should_have_db_columns
|
482
403
|
|
483
404
|
# Ensures that there are DB indices on the given columns or tuples of columns.
|
484
|
-
# Also aliased to
|
405
|
+
# Also aliased to should_have_db_index for readability
|
485
406
|
#
|
486
407
|
# Options:
|
487
408
|
# * <tt>:unique</tt> - whether or not the index has a unique
|
@@ -492,30 +413,39 @@ module Shoulda # :nodoc:
|
|
492
413
|
#
|
493
414
|
# Examples:
|
494
415
|
#
|
495
|
-
#
|
496
|
-
#
|
497
|
-
#
|
416
|
+
# should_have_db_indices :email, :name, [:commentable_type, :commentable_id]
|
417
|
+
# should_have_db_index :age
|
418
|
+
# should_have_db_index :ssn, :unique => true
|
498
419
|
#
|
499
|
-
def
|
420
|
+
def should_have_db_indices(*columns)
|
500
421
|
unique = get_options!(columns, :unique)
|
501
|
-
klass = model_class
|
502
422
|
|
503
423
|
columns.each do |column|
|
504
|
-
matcher =
|
424
|
+
matcher = have_db_index(column).unique(unique)
|
505
425
|
should matcher.description do
|
506
|
-
assert_accepts(matcher,
|
426
|
+
assert_accepts(matcher, subject)
|
507
427
|
end
|
508
428
|
end
|
509
429
|
end
|
510
430
|
|
511
|
-
alias_method :
|
431
|
+
alias_method :should_have_db_index, :should_have_db_indices
|
432
|
+
|
433
|
+
# Deprecated. See should_have_db_index
|
434
|
+
def should_have_index(*args)
|
435
|
+
warn "[DEPRECATION] should_have_index is deprecated. " <<
|
436
|
+
"Use should_have_db_index instead."
|
437
|
+
should_have_db_index(*args)
|
438
|
+
end
|
439
|
+
|
440
|
+
# Deprecated. See should_have_db_indices
|
441
|
+
def should_have_indices(*args)
|
442
|
+
warn "[DEPRECATION] should_have_indices is deprecated. " <<
|
443
|
+
"Use should_have_db_indices instead."
|
444
|
+
should_have_db_indices(*args)
|
445
|
+
end
|
512
446
|
|
513
447
|
# Ensures that the model cannot be saved if one of the attributes listed is not accepted.
|
514
448
|
#
|
515
|
-
# If an instance variable has been created in the setup named after the
|
516
|
-
# model being tested, then this method will use that. Otherwise, it will
|
517
|
-
# create a new instance to test against.
|
518
|
-
#
|
519
449
|
# Options:
|
520
450
|
# * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
521
451
|
# Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.accepted')</tt>
|
@@ -525,23 +455,17 @@ module Shoulda # :nodoc:
|
|
525
455
|
#
|
526
456
|
def should_validate_acceptance_of(*attributes)
|
527
457
|
message = get_options!(attributes, :message)
|
528
|
-
klass = model_class
|
529
458
|
|
530
459
|
attributes.each do |attribute|
|
531
460
|
matcher = validate_acceptance_of(attribute).with_message(message)
|
532
461
|
should matcher.description do
|
533
|
-
assert_accepts matcher,
|
462
|
+
assert_accepts matcher, subject
|
534
463
|
end
|
535
464
|
end
|
536
465
|
end
|
537
466
|
|
538
|
-
# Deprecated.
|
539
|
-
|
540
|
-
warn "[DEPRECATION] should_require_acceptance_of is deprecated. " <<
|
541
|
-
"Use should_validate_acceptance_of instead."
|
542
|
-
should_validate_acceptance_of(*attributes)
|
543
|
-
end
|
544
|
-
|
467
|
+
# Deprecated.
|
468
|
+
#
|
545
469
|
# Ensures that the model has a method named scope_name that returns a NamedScope object with the
|
546
470
|
# proxy options set to the options you supply. scope_name can be either a symbol, or a method
|
547
471
|
# call which will be evaled against the model. The eval'd method call has access to all the same
|
@@ -578,10 +502,9 @@ module Shoulda # :nodoc:
|
|
578
502
|
# end
|
579
503
|
#
|
580
504
|
def should_have_named_scope(scope_call, find_options = nil)
|
581
|
-
klass = model_class
|
582
505
|
matcher = have_named_scope(scope_call).finding(find_options)
|
583
506
|
should matcher.description do
|
584
|
-
assert_accepts matcher.in_context(self),
|
507
|
+
assert_accepts matcher.in_context(self), subject
|
585
508
|
end
|
586
509
|
end
|
587
510
|
end
|