thoughtbot-shoulda 2.10.2 → 2.11.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/CONTRIBUTION_GUIDELINES.rdoc +5 -5
- data/README.rdoc +72 -89
- data/Rakefile +31 -33
- data/lib/shoulda.rb +6 -6
- data/lib/shoulda/action_controller.rb +8 -0
- data/lib/shoulda/action_controller/macros.rb +54 -73
- data/lib/shoulda/action_controller/matchers.rb +7 -5
- data/lib/shoulda/action_controller/matchers/assign_to_matcher.rb +10 -7
- data/lib/shoulda/action_controller/matchers/filter_param_matcher.rb +18 -1
- data/lib/shoulda/action_controller/matchers/redirect_to_matcher.rb +62 -0
- data/lib/shoulda/action_controller/matchers/render_template_matcher.rb +54 -0
- data/lib/shoulda/action_controller/matchers/render_with_layout_matcher.rb +33 -15
- data/lib/shoulda/action_controller/matchers/respond_with_content_type_matcher.rb +10 -10
- data/lib/shoulda/action_controller/matchers/respond_with_matcher.rb +17 -13
- data/lib/shoulda/action_controller/matchers/route_matcher.rb +3 -3
- data/lib/shoulda/action_controller/matchers/set_session_matcher.rb +13 -2
- data/lib/shoulda/action_controller/matchers/set_the_flash_matcher.rb +1 -1
- data/lib/shoulda/action_mailer.rb +3 -0
- data/lib/shoulda/action_mailer/assertions.rb +4 -0
- data/lib/shoulda/action_mailer/matchers.rb +22 -0
- data/lib/shoulda/action_mailer/matchers/have_sent_email.rb +110 -0
- data/lib/shoulda/active_record/helpers.rb +8 -3
- data/lib/shoulda/active_record/macros.rb +88 -143
- data/lib/shoulda/active_record/matchers.rb +0 -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 +10 -2
- data/lib/shoulda/active_record/matchers/association_matcher.rb +8 -8
- data/lib/shoulda/active_record/matchers/ensure_inclusion_of_matcher.rb +1 -1
- data/lib/shoulda/active_record/matchers/ensure_length_of_matcher.rb +2 -2
- data/lib/shoulda/active_record/matchers/have_db_column_matcher.rb +11 -11
- data/lib/shoulda/active_record/matchers/have_db_index_matcher.rb +8 -8
- data/lib/shoulda/active_record/matchers/validate_format_of_matcher.rb +2 -4
- data/lib/shoulda/active_record/matchers/validate_uniqueness_of_matcher.rb +3 -3
- data/lib/shoulda/active_record/matchers/validation_matcher.rb +0 -1
- data/lib/shoulda/assertions.rb +10 -2
- data/lib/shoulda/autoload_macros.rb +20 -20
- data/lib/shoulda/context.rb +70 -39
- data/lib/shoulda/{rspec.rb → integrations/rspec.rb} +2 -0
- data/lib/shoulda/integrations/rspec2.rb +22 -0
- data/lib/shoulda/{test_unit.rb → integrations/test_unit.rb} +0 -0
- data/lib/shoulda/macros.rb +46 -18
- data/lib/shoulda/rails.rb +0 -5
- data/lib/shoulda/tasks/yaml_to_shoulda.rake +11 -11
- data/lib/shoulda/version.rb +4 -0
- data/rails/init.rb +3 -2
- data/test/fail_macros.rb +20 -4
- data/test/functional/posts_controller_test.rb +7 -7
- data/test/functional/users_controller_test.rb +1 -1
- data/test/matchers/action_mailer/have_sent_email_test.rb +70 -0
- data/test/matchers/active_record/allow_mass_assignment_of_matcher_test.rb +7 -1
- data/test/matchers/active_record/allow_value_matcher_test.rb +1 -1
- data/test/matchers/active_record/association_matcher_test.rb +16 -16
- data/test/matchers/active_record/ensure_inclusion_of_matcher_test.rb +3 -2
- 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_db_index_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 +1 -1
- 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 +11 -1
- data/test/matchers/controller/filter_param_matcher_test.rb +10 -2
- data/test/matchers/controller/redirect_to_matcher_test.rb +37 -0
- data/test/matchers/controller/render_template_matcher_test.rb +37 -0
- data/test/matchers/controller/render_with_layout_matcher_test.rb +15 -1
- data/test/matchers/controller/respond_with_content_type_matcher_test.rb +1 -1
- data/test/matchers/controller/respond_with_matcher_test.rb +1 -11
- data/test/matchers/controller/route_matcher_test.rb +18 -1
- data/test/matchers/controller/set_session_matcher_test.rb +11 -1
- data/test/matchers/controller/set_the_flash_matcher.rb +1 -1
- data/test/other/autoload_macro_test.rb +1 -1
- data/test/other/context_test.rb +210 -27
- data/test/other/convert_to_should_syntax_test.rb +1 -1
- data/test/other/helpers_test.rb +13 -36
- data/test/other/private_helpers_test.rb +2 -2
- data/test/other/should_test.rb +13 -13
- data/test/{model_builder.rb → rails2_model_builder.rb} +32 -8
- data/test/{rails_root → rails2_root}/app/controllers/application_controller.rb +0 -3
- data/test/{rails_root → rails2_root}/app/controllers/posts_controller.rb +0 -0
- data/test/{rails_root → rails2_root}/app/controllers/users_controller.rb +0 -0
- data/test/{rails_root → rails2_root}/app/helpers/application_helper.rb +0 -0
- data/test/{rails_root → rails2_root}/app/helpers/posts_helper.rb +0 -0
- data/test/{rails_root → rails2_root}/app/helpers/users_helper.rb +0 -0
- data/test/{rails_root → rails2_root}/app/models/address.rb +0 -0
- data/test/rails2_root/app/models/flea.rb +11 -0
- data/test/{rails_root → rails2_root}/app/models/friendship.rb +0 -0
- data/test/rails2_root/app/models/notifier.rb +8 -0
- data/test/{rails_root → rails2_root}/app/models/pets/cat.rb +0 -0
- data/test/{rails_root → rails2_root}/app/models/pets/dog.rb +0 -0
- data/test/{rails_root → rails2_root}/app/models/post.rb +1 -1
- data/test/{rails_root → rails2_root}/app/models/product.rb +0 -0
- data/test/{rails_root → rails2_root}/app/models/profile.rb +0 -0
- data/test/{rails_root → rails2_root}/app/models/registration.rb +0 -0
- data/test/{rails_root → rails2_root}/app/models/tag.rb +0 -0
- data/test/{rails_root → rails2_root}/app/models/tagging.rb +0 -0
- data/test/{rails_root → rails2_root}/app/models/treat.rb +0 -0
- data/test/{rails_root → rails2_root}/app/models/user.rb +0 -0
- data/test/{rails_root → rails2_root}/app/views/layouts/posts.rhtml +0 -0
- data/test/{rails_root → rails2_root}/app/views/layouts/users.rhtml +0 -0
- data/test/{rails_root → rails2_root}/app/views/layouts/wide.html.erb +0 -0
- data/test/rails2_root/app/views/notifier/the_email.html.erb +1 -0
- data/test/{rails_root → rails2_root}/app/views/posts/edit.rhtml +0 -0
- data/test/{rails_root → rails2_root}/app/views/posts/index.rhtml +0 -0
- data/test/{rails_root → rails2_root}/app/views/posts/new.rhtml +0 -0
- data/test/{rails_root → rails2_root}/app/views/posts/show.rhtml +0 -0
- data/test/{rails_root → rails2_root}/app/views/users/edit.rhtml +0 -0
- data/test/{rails_root → rails2_root}/app/views/users/index.rhtml +0 -0
- data/test/{rails_root → rails2_root}/app/views/users/new.rhtml +0 -0
- data/test/{rails_root → rails2_root}/app/views/users/show.rhtml +0 -0
- data/test/{rails_root → rails2_root}/config/boot.rb +0 -0
- data/test/{rails_root → rails2_root}/config/database.yml +1 -1
- data/test/{rails_root → rails2_root}/config/environment.rb +0 -1
- data/test/rails2_root/config/environments/test.rb +23 -0
- data/test/{rails_root → rails2_root}/config/initializers/new_rails_defaults.rb +0 -0
- data/test/{rails_root → rails2_root}/config/initializers/shoulda.rb +0 -0
- data/test/{rails_root → rails2_root}/config/routes.rb +0 -0
- data/test/{rails_root → rails2_root}/db/migrate/001_create_users.rb +0 -0
- data/test/{rails_root → rails2_root}/db/migrate/002_create_posts.rb +0 -0
- data/test/{rails_root → rails2_root}/db/migrate/003_create_taggings.rb +0 -0
- data/test/{rails_root → rails2_root}/db/migrate/004_create_tags.rb +0 -0
- data/test/{rails_root → rails2_root}/db/migrate/005_create_dogs.rb +0 -0
- data/test/{rails_root → rails2_root}/db/migrate/006_create_addresses.rb +0 -0
- data/test/{rails_root → rails2_root}/db/migrate/007_create_fleas.rb +0 -0
- data/test/{rails_root → rails2_root}/db/migrate/008_create_dogs_fleas.rb +0 -0
- data/test/{rails_root → rails2_root}/db/migrate/009_create_products.rb +0 -0
- data/test/{rails_root → rails2_root}/db/migrate/010_create_friendships.rb +0 -0
- data/test/{rails_root → rails2_root}/db/migrate/011_create_treats.rb +0 -0
- data/test/{rails_root → rails2_root}/db/migrate/20090506203502_create_profiles.rb +0 -0
- data/test/{rails_root → rails2_root}/db/migrate/20090506203536_create_registrations.rb +0 -0
- data/test/{rails_root → rails2_root}/db/migrate/20090513104502_create_cats.rb +0 -0
- data/test/{rails_root → rails2_root}/db/schema.rb +0 -0
- data/test/{rails_root → rails2_root}/public/404.html +0 -0
- data/test/{rails_root → rails2_root}/public/422.html +0 -0
- data/test/{rails_root → rails2_root}/public/500.html +0 -0
- data/test/{rails_root → rails2_root}/script/console +0 -0
- data/test/{rails_root → rails2_root}/script/generate +0 -0
- data/test/{rails_root → rails2_root}/test/shoulda_macros/custom_macro.rb +0 -0
- data/test/{rails_root → rails2_root}/vendor/gems/gem_with_macro-0.0.1/shoulda_macros/gem_macro.rb +0 -0
- data/test/{rails_root → rails2_root}/vendor/plugins/plugin_with_macro/shoulda_macros/plugin_macro.rb +0 -0
- data/test/rails2_test_helper.rb +6 -0
- data/test/rails3_model_builder.rb +118 -0
- data/test/rails3_root/Gemfile +28 -0
- data/test/rails3_root/README +244 -0
- data/test/rails3_root/Rakefile +10 -0
- data/test/rails3_root/app/controllers/application_controller.rb +22 -0
- data/test/rails3_root/app/controllers/posts_controller.rb +87 -0
- data/test/rails3_root/app/controllers/users_controller.rb +82 -0
- data/test/rails3_root/app/helpers/application_helper.rb +2 -0
- data/test/rails3_root/app/models/address.rb +7 -0
- data/test/rails3_root/app/models/flea.rb +11 -0
- data/test/rails3_root/app/models/friendship.rb +4 -0
- data/test/rails3_root/app/models/notifier.rb +8 -0
- data/test/rails3_root/app/models/pets/cat.rb +7 -0
- data/test/rails3_root/app/models/pets/dog.rb +10 -0
- data/test/rails3_root/app/models/post.rb +12 -0
- data/test/rails3_root/app/models/product.rb +12 -0
- data/test/rails3_root/app/models/profile.rb +2 -0
- data/test/rails3_root/app/models/registration.rb +2 -0
- data/test/rails3_root/app/models/tag.rb +8 -0
- data/test/rails3_root/app/models/tagging.rb +4 -0
- data/test/rails3_root/app/models/treat.rb +3 -0
- data/test/rails3_root/app/models/user.rb +32 -0
- data/test/rails3_root/app/views/layouts/application.html.erb +14 -0
- data/test/rails3_root/app/views/layouts/posts.rhtml +19 -0
- data/test/rails3_root/app/views/layouts/users.rhtml +17 -0
- data/test/rails3_root/app/views/layouts/wide.html.erb +1 -0
- data/test/rails3_root/app/views/notifier/the_email.html.erb +1 -0
- data/test/rails3_root/app/views/posts/edit.rhtml +27 -0
- data/test/rails3_root/app/views/posts/index.rhtml +25 -0
- data/test/rails3_root/app/views/posts/new.rhtml +24 -0
- data/test/rails3_root/app/views/posts/show.rhtml +18 -0
- data/test/rails3_root/app/views/users/edit.rhtml +22 -0
- data/test/rails3_root/app/views/users/index.rhtml +22 -0
- data/test/rails3_root/app/views/users/new.rhtml +21 -0
- data/test/rails3_root/app/views/users/show.rhtml +13 -0
- data/test/rails3_root/config.ru +4 -0
- data/test/rails3_root/config/application.rb +46 -0
- data/test/rails3_root/config/boot.rb +6 -0
- data/test/rails3_root/config/database.yml +22 -0
- data/test/rails3_root/config/environment.rb +5 -0
- data/test/rails3_root/config/environments/development.rb +19 -0
- data/test/rails3_root/config/environments/production.rb +42 -0
- data/test/rails3_root/config/environments/test.rb +32 -0
- data/test/rails3_root/config/initializers/backtrace_silencers.rb +7 -0
- data/test/rails3_root/config/initializers/inflections.rb +10 -0
- data/test/rails3_root/config/initializers/mime_types.rb +5 -0
- data/test/rails3_root/config/initializers/secret_token.rb +7 -0
- data/test/rails3_root/config/initializers/session_store.rb +8 -0
- data/test/rails3_root/config/locales/en.yml +5 -0
- data/test/rails3_root/config/routes.rb +4 -0
- data/test/rails3_root/db/migrate/001_create_users.rb +19 -0
- data/test/rails3_root/db/migrate/002_create_posts.rb +13 -0
- data/test/rails3_root/db/migrate/003_create_taggings.rb +12 -0
- data/test/rails3_root/db/migrate/004_create_tags.rb +11 -0
- data/test/rails3_root/db/migrate/005_create_dogs.rb +12 -0
- data/test/rails3_root/db/migrate/006_create_addresses.rb +14 -0
- data/test/rails3_root/db/migrate/007_create_fleas.rb +11 -0
- data/test/rails3_root/db/migrate/008_create_dogs_fleas.rb +12 -0
- data/test/rails3_root/db/migrate/009_create_products.rb +17 -0
- data/test/rails3_root/db/migrate/010_create_friendships.rb +14 -0
- data/test/rails3_root/db/migrate/011_create_treats.rb +12 -0
- data/test/rails3_root/db/migrate/20090506203502_create_profiles.rb +12 -0
- data/test/rails3_root/db/migrate/20090506203536_create_registrations.rb +14 -0
- data/test/rails3_root/db/migrate/20090513104502_create_cats.rb +12 -0
- data/test/rails3_root/db/seeds.rb +7 -0
- data/test/rails3_root/public/404.html +26 -0
- data/test/rails3_root/public/422.html +26 -0
- data/test/rails3_root/public/500.html +26 -0
- data/test/{rails_root/config/environments/test.rb → rails3_root/public/favicon.ico} +0 -0
- data/test/rails3_root/public/images/rails.png +0 -0
- data/test/rails3_root/public/index.html +279 -0
- data/test/rails3_root/public/javascripts/application.js +2 -0
- data/test/rails3_root/public/javascripts/controls.js +965 -0
- data/test/rails3_root/public/javascripts/dragdrop.js +974 -0
- data/test/rails3_root/public/javascripts/effects.js +1123 -0
- data/test/rails3_root/public/javascripts/prototype.js +4874 -0
- data/test/rails3_root/public/javascripts/rails.js +118 -0
- data/test/rails3_root/public/robots.txt +5 -0
- data/test/rails3_root/script/rails +9 -0
- data/test/rails3_root/test/performance/browsing_test.rb +9 -0
- data/test/rails3_root/test/test_helper.rb +13 -0
- data/test/rails3_test_helper.rb +6 -0
- data/test/test_helper.rb +16 -8
- data/test/unit/address_test.rb +1 -1
- data/test/unit/cat_test.rb +1 -1
- data/test/unit/dog_test.rb +1 -1
- data/test/unit/flea_test.rb +9 -1
- data/test/unit/friendship_test.rb +1 -1
- data/test/unit/post_test.rb +1 -5
- data/test/unit/product_test.rb +1 -1
- data/test/unit/tag_test.rb +1 -5
- data/test/unit/tagging_test.rb +1 -1
- data/test/unit/user_test.rb +3 -37
- metadata +184 -118
- data/lib/shoulda/action_view.rb +0 -10
- data/lib/shoulda/action_view/macros.rb +0 -61
- data/lib/shoulda/active_record/matchers/have_named_scope_matcher.rb +0 -128
- data/test/matchers/active_record/have_named_scope_matcher_test.rb +0 -65
- data/test/rails_root/app/models/flea.rb +0 -3
@@ -13,7 +13,6 @@ require 'shoulda/active_record/matchers/have_db_column_matcher'
|
|
13
13
|
require 'shoulda/active_record/matchers/have_db_index_matcher'
|
14
14
|
require 'shoulda/active_record/matchers/have_readonly_attribute_matcher'
|
15
15
|
require 'shoulda/active_record/matchers/allow_mass_assignment_of_matcher'
|
16
|
-
require 'shoulda/active_record/matchers/have_named_scope_matcher'
|
17
16
|
|
18
17
|
|
19
18
|
module Shoulda # :nodoc:
|
@@ -24,7 +24,7 @@ module Shoulda # :nodoc:
|
|
24
24
|
@failure_message = "#{@attribute} was made accessible"
|
25
25
|
else
|
26
26
|
if protected_attributes.empty?
|
27
|
-
@
|
27
|
+
@negative_failure_message = "no attributes were protected"
|
28
28
|
else
|
29
29
|
@failure_message = "#{class_name} is protecting " <<
|
30
30
|
"#{protected_attributes.to_a.to_sentence}, " <<
|
@@ -59,9 +59,17 @@ module Shoulda # :nodoc:
|
|
59
59
|
|
60
60
|
def errors_match?
|
61
61
|
@instance.valid?
|
62
|
-
@errors = @instance
|
62
|
+
@errors = errors_for_attribute(@instance, @attribute)
|
63
63
|
@errors = [@errors] unless @errors.is_a?(Array)
|
64
|
-
@expected_message ? (errors_match_regexp? || errors_match_string?) : (@errors
|
64
|
+
@expected_message ? (errors_match_regexp? || errors_match_string?) : (@errors.compact.any?)
|
65
|
+
end
|
66
|
+
|
67
|
+
def errors_for_attribute(instance, attribute)
|
68
|
+
if instance.errors.respond_to?(:[])
|
69
|
+
instance.errors[attribute]
|
70
|
+
else
|
71
|
+
instance.errors.on(attribute)
|
72
|
+
end
|
65
73
|
end
|
66
74
|
|
67
75
|
def errors_match_regexp?
|
@@ -20,9 +20,9 @@ module Shoulda # :nodoc:
|
|
20
20
|
# dependent option.
|
21
21
|
#
|
22
22
|
# Example:
|
23
|
-
# it {
|
24
|
-
# it {
|
25
|
-
# it {
|
23
|
+
# it { should have_many(:friends) }
|
24
|
+
# it { should have_many(:enemies).through(:friends) }
|
25
|
+
# it { should have_many(:enemies).dependent(:destroy) }
|
26
26
|
#
|
27
27
|
def have_many(name)
|
28
28
|
AssociationMatcher.new(:has_many, name)
|
@@ -70,10 +70,10 @@ module Shoulda # :nodoc:
|
|
70
70
|
|
71
71
|
def matches?(subject)
|
72
72
|
@subject = subject
|
73
|
-
association_exists? &&
|
74
|
-
macro_correct? &&
|
75
|
-
foreign_key_exists? &&
|
76
|
-
through_association_valid? &&
|
73
|
+
association_exists? &&
|
74
|
+
macro_correct? &&
|
75
|
+
foreign_key_exists? &&
|
76
|
+
through_association_valid? &&
|
77
77
|
dependent_correct? &&
|
78
78
|
join_table_exists?
|
79
79
|
end
|
@@ -160,7 +160,7 @@ module Shoulda # :nodoc:
|
|
160
160
|
end
|
161
161
|
|
162
162
|
def join_table_exists?
|
163
|
-
if @macro != :has_and_belongs_to_many ||
|
163
|
+
if @macro != :has_and_belongs_to_many ||
|
164
164
|
::ActiveRecord::Base.connection.tables.include?(join_table.to_s)
|
165
165
|
true
|
166
166
|
else
|
@@ -84,7 +84,7 @@ module Shoulda # :nodoc:
|
|
84
84
|
def matches?(subject)
|
85
85
|
super(subject)
|
86
86
|
translate_messages!
|
87
|
-
disallows_lower_length &&
|
87
|
+
disallows_lower_length &&
|
88
88
|
allows_minimum_length &&
|
89
89
|
((@minimum == @maximum) ||
|
90
90
|
(disallows_higher_length &&
|
@@ -106,7 +106,7 @@ module Shoulda # :nodoc:
|
|
106
106
|
end
|
107
107
|
|
108
108
|
def disallows_lower_length
|
109
|
-
@minimum == 0 ||
|
109
|
+
@minimum == 0 ||
|
110
110
|
@minimum.nil? ||
|
111
111
|
disallows_length_of(@minimum - 1, @short_message)
|
112
112
|
end
|
@@ -24,12 +24,12 @@ module Shoulda # :nodoc:
|
|
24
24
|
@macro = macro
|
25
25
|
@column = column
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
def of_type(column_type)
|
29
29
|
@column_type = column_type
|
30
30
|
self
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
def with_options(opts = {})
|
34
34
|
@precision = opts[:precision]
|
35
35
|
@limit = opts[:limit]
|
@@ -41,8 +41,8 @@ module Shoulda # :nodoc:
|
|
41
41
|
|
42
42
|
def matches?(subject)
|
43
43
|
@subject = subject
|
44
|
-
column_exists? &&
|
45
|
-
correct_column_type? &&
|
44
|
+
column_exists? &&
|
45
|
+
correct_column_type? &&
|
46
46
|
correct_precision? &&
|
47
47
|
correct_limit? &&
|
48
48
|
correct_default? &&
|
@@ -80,7 +80,7 @@ module Shoulda # :nodoc:
|
|
80
80
|
false
|
81
81
|
end
|
82
82
|
end
|
83
|
-
|
83
|
+
|
84
84
|
def correct_column_type?
|
85
85
|
return true if @column_type.nil?
|
86
86
|
if matched_column.type.to_s == @column_type.to_s
|
@@ -91,7 +91,7 @@ module Shoulda # :nodoc:
|
|
91
91
|
false
|
92
92
|
end
|
93
93
|
end
|
94
|
-
|
94
|
+
|
95
95
|
def correct_precision?
|
96
96
|
return true if @precision.nil?
|
97
97
|
if matched_column.precision.to_s == @precision.to_s
|
@@ -103,7 +103,7 @@ module Shoulda # :nodoc:
|
|
103
103
|
false
|
104
104
|
end
|
105
105
|
end
|
106
|
-
|
106
|
+
|
107
107
|
def correct_limit?
|
108
108
|
return true if @limit.nil?
|
109
109
|
if matched_column.limit.to_s == @limit.to_s
|
@@ -115,7 +115,7 @@ module Shoulda # :nodoc:
|
|
115
115
|
false
|
116
116
|
end
|
117
117
|
end
|
118
|
-
|
118
|
+
|
119
119
|
def correct_default?
|
120
120
|
return true if @default.nil?
|
121
121
|
if matched_column.default.to_s == @default.to_s
|
@@ -127,7 +127,7 @@ module Shoulda # :nodoc:
|
|
127
127
|
false
|
128
128
|
end
|
129
129
|
end
|
130
|
-
|
130
|
+
|
131
131
|
def correct_null?
|
132
132
|
return true if @null.nil?
|
133
133
|
if matched_column.null.to_s == @null.to_s
|
@@ -139,7 +139,7 @@ module Shoulda # :nodoc:
|
|
139
139
|
false
|
140
140
|
end
|
141
141
|
end
|
142
|
-
|
142
|
+
|
143
143
|
def correct_scale?
|
144
144
|
return true if @scale.nil?
|
145
145
|
if matched_column.scale.to_s == @scale.to_s
|
@@ -150,7 +150,7 @@ module Shoulda # :nodoc:
|
|
150
150
|
false
|
151
151
|
end
|
152
152
|
end
|
153
|
-
|
153
|
+
|
154
154
|
def matched_column
|
155
155
|
model_class.columns.detect { |each| each.name == @column.to_s }
|
156
156
|
end
|
@@ -27,7 +27,7 @@ module Shoulda # :nodoc:
|
|
27
27
|
@macro = macro
|
28
28
|
@columns = normalize_columns_to_array(columns)
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
def unique(unique)
|
32
32
|
@unique = unique
|
33
33
|
self
|
@@ -51,11 +51,11 @@ module Shoulda # :nodoc:
|
|
51
51
|
end
|
52
52
|
|
53
53
|
protected
|
54
|
-
|
54
|
+
|
55
55
|
def index_exists?
|
56
56
|
! matched_index.nil?
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
59
|
def correct_unique?
|
60
60
|
return true if @unique.nil?
|
61
61
|
if matched_index.unique == @unique
|
@@ -66,7 +66,7 @@ module Shoulda # :nodoc:
|
|
66
66
|
false
|
67
67
|
end
|
68
68
|
end
|
69
|
-
|
69
|
+
|
70
70
|
def matched_index
|
71
71
|
indexes.detect { |each| each.columns == @columns }
|
72
72
|
end
|
@@ -74,11 +74,11 @@ module Shoulda # :nodoc:
|
|
74
74
|
def model_class
|
75
75
|
@subject.class
|
76
76
|
end
|
77
|
-
|
77
|
+
|
78
78
|
def table_name
|
79
79
|
model_class.table_name
|
80
80
|
end
|
81
|
-
|
81
|
+
|
82
82
|
def indexes
|
83
83
|
::ActiveRecord::Base.connection.indexes(table_name)
|
84
84
|
end
|
@@ -86,7 +86,7 @@ module Shoulda # :nodoc:
|
|
86
86
|
def expectation
|
87
87
|
expected = "#{model_class.name} to #{description}"
|
88
88
|
end
|
89
|
-
|
89
|
+
|
90
90
|
def index_type
|
91
91
|
case @unique
|
92
92
|
when nil
|
@@ -97,7 +97,7 @@ module Shoulda # :nodoc:
|
|
97
97
|
'unique'
|
98
98
|
end
|
99
99
|
end
|
100
|
-
|
100
|
+
|
101
101
|
def normalize_columns_to_array(columns)
|
102
102
|
if columns.class == Array
|
103
103
|
columns.collect { |each| each.to_s }
|
@@ -25,7 +25,7 @@ module Shoulda # :nodoc:
|
|
25
25
|
end
|
26
26
|
|
27
27
|
class ValidateFormatOfMatcher < ValidationMatcher # :nodoc:
|
28
|
-
|
28
|
+
|
29
29
|
def initialize(attribute)
|
30
30
|
super
|
31
31
|
end
|
@@ -34,13 +34,12 @@ module Shoulda # :nodoc:
|
|
34
34
|
@expected_message = message if message
|
35
35
|
self
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
def with(value)
|
39
39
|
raise "You may not call both with and not_with" if @value_to_fail
|
40
40
|
@value_to_pass = value
|
41
41
|
self
|
42
42
|
end
|
43
|
-
|
44
43
|
|
45
44
|
def not_with(value)
|
46
45
|
raise "You may not call both with and not_with" if @value_to_pass
|
@@ -48,7 +47,6 @@ module Shoulda # :nodoc:
|
|
48
47
|
self
|
49
48
|
end
|
50
49
|
|
51
|
-
|
52
50
|
def matches?(subject)
|
53
51
|
super(subject)
|
54
52
|
@expected_message ||= :blank
|
@@ -67,8 +67,8 @@ module Shoulda # :nodoc:
|
|
67
67
|
def matches?(subject)
|
68
68
|
@subject = subject.class.new
|
69
69
|
@expected_message ||= :taken
|
70
|
-
find_existing &&
|
71
|
-
set_scoped_attributes &&
|
70
|
+
find_existing &&
|
71
|
+
set_scoped_attributes &&
|
72
72
|
validate_attribute &&
|
73
73
|
validate_after_scope_change
|
74
74
|
end
|
@@ -121,7 +121,7 @@ module Shoulda # :nodoc:
|
|
121
121
|
@subject.send("#{scope}=", next_value)
|
122
122
|
|
123
123
|
if allows_value_of(existing_value, @expected_message)
|
124
|
-
@negative_failure_message <<
|
124
|
+
@negative_failure_message <<
|
125
125
|
" (with different value of #{scope})"
|
126
126
|
true
|
127
127
|
else
|
data/lib/shoulda/assertions.rb
CHANGED
@@ -26,7 +26,7 @@ module Shoulda # :nodoc:
|
|
26
26
|
case x
|
27
27
|
when Regexp
|
28
28
|
assert(collection.detect { |e| e =~ x }, msg)
|
29
|
-
else
|
29
|
+
else
|
30
30
|
assert(collection.include?(x), msg)
|
31
31
|
end
|
32
32
|
end
|
@@ -39,13 +39,17 @@ module Shoulda # :nodoc:
|
|
39
39
|
case x
|
40
40
|
when Regexp
|
41
41
|
assert(!collection.detect { |e| e =~ x }, msg)
|
42
|
-
else
|
42
|
+
else
|
43
43
|
assert(!collection.include?(x), msg)
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
47
|
# Asserts that the given matcher returns true when +target+ is passed to #matches?
|
48
48
|
def assert_accepts(matcher, target, options = {})
|
49
|
+
if matcher.respond_to?(:in_context)
|
50
|
+
matcher.in_context(self)
|
51
|
+
end
|
52
|
+
|
49
53
|
if matcher.matches?(target)
|
50
54
|
assert_block { true }
|
51
55
|
if options[:message]
|
@@ -58,6 +62,10 @@ module Shoulda # :nodoc:
|
|
58
62
|
|
59
63
|
# Asserts that the given matcher returns false when +target+ is passed to #matches?
|
60
64
|
def assert_rejects(matcher, target, options = {})
|
65
|
+
if matcher.respond_to?(:in_context)
|
66
|
+
matcher.in_context(self)
|
67
|
+
end
|
68
|
+
|
61
69
|
unless matcher.matches?(target)
|
62
70
|
assert_block { true }
|
63
71
|
if options[:message]
|
@@ -1,40 +1,40 @@
|
|
1
1
|
module Shoulda # :nodoc:
|
2
|
-
# Call autoload_macros when you want to load test macros automatically in a non-Rails
|
2
|
+
# Call autoload_macros when you want to load test macros automatically in a non-Rails
|
3
3
|
# project (it's done automatically for Rails projects).
|
4
4
|
# You don't need to specify ROOT/test/shoulda_macros explicitly. Your custom macros
|
5
5
|
# are loaded automatically when you call autoload_macros.
|
6
6
|
#
|
7
7
|
# The first argument is the path to you application's root directory.
|
8
|
-
# All following arguments are directories relative to your root, which contain
|
9
|
-
# shoulda_macros subdirectories. These directories support the same kinds of globs as the
|
8
|
+
# All following arguments are directories relative to your root, which contain
|
9
|
+
# shoulda_macros subdirectories. These directories support the same kinds of globs as the
|
10
10
|
# Dir class.
|
11
|
-
#
|
11
|
+
#
|
12
12
|
# Basic usage (from a test_helper):
|
13
13
|
# Shoulda.autoload_macros(File.dirname(__FILE__) + '/..')
|
14
|
-
#
|
15
|
-
#
|
14
|
+
# will load everything in
|
15
|
+
# - your_app/test/shoulda_macros
|
16
16
|
#
|
17
|
-
#
|
17
|
+
# To load vendored macros as well:
|
18
18
|
# Shoulda.autoload_macros(APP_ROOT, 'vendor/*')
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
19
|
+
# will load everything in
|
20
|
+
# - APP_ROOT/vendor/*/shoulda_macros
|
21
|
+
# - APP_ROOT/test/shoulda_macros
|
22
22
|
#
|
23
|
-
#
|
23
|
+
# To load macros in an app with a vendor directory laid out like Rails':
|
24
24
|
# Shoulda.autoload_macros(APP_ROOT, 'vendor/{plugins,gems}/*')
|
25
25
|
# or
|
26
26
|
# Shoulda.autoload_macros(APP_ROOT, 'vendor/plugins/*', 'vendor/gems/*')
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
27
|
+
# will load everything in
|
28
|
+
# - APP_ROOT/vendor/plugins/*/shoulda_macros
|
29
|
+
# - APP_ROOT/vendor/gems/*/shoulda_macros
|
30
|
+
# - APP_ROOT/test/shoulda_macros
|
31
31
|
#
|
32
|
-
#
|
32
|
+
# If you prefer to stick testing dependencies away from your production dependencies:
|
33
33
|
# Shoulda.autoload_macros(APP_ROOT, 'vendor/*', 'test/vendor/*')
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
34
|
+
# will load everything in
|
35
|
+
# - APP_ROOT/vendor/*/shoulda_macros
|
36
|
+
# - APP_ROOT/test/vendor/*/shoulda_macros
|
37
|
+
# - APP_ROOT/test/shoulda_macros
|
38
38
|
def self.autoload_macros(root, *dirs)
|
39
39
|
dirs << File.join('test')
|
40
40
|
complete_dirs = dirs.map{|d| File.join(root, d, 'shoulda_macros')}
|
data/lib/shoulda/context.rb
CHANGED
@@ -21,9 +21,10 @@ module Shoulda
|
|
21
21
|
module ClassMethods
|
22
22
|
# == Should statements
|
23
23
|
#
|
24
|
-
# Should statements are just syntactic sugar over normal Test::Unit test
|
25
|
-
# contains all the normal code and assertions
|
26
|
-
#
|
24
|
+
# Should statements are just syntactic sugar over normal Test::Unit test
|
25
|
+
# methods. A should block contains all the normal code and assertions
|
26
|
+
# you're used to seeing, with the added benefit that they can be wrapped
|
27
|
+
# inside context blocks (see below).
|
27
28
|
#
|
28
29
|
# === Example:
|
29
30
|
#
|
@@ -56,14 +57,43 @@ module Shoulda
|
|
56
57
|
# assert true
|
57
58
|
# end
|
58
59
|
# end
|
60
|
+
#
|
61
|
+
# Should statements can also wrap matchers, making virtually any matcher
|
62
|
+
# usable in a macro style. The matcher's description is used to generate a
|
63
|
+
# test name and failure message, and the test will pass if the matcher
|
64
|
+
# matches the subject.
|
65
|
+
#
|
66
|
+
# === Example:
|
67
|
+
#
|
68
|
+
# should validate_presence_of(:first_name).with_message(/gotta be there/)
|
69
|
+
#
|
70
|
+
|
71
|
+
def should(name_or_matcher, options = {}, &blk)
|
72
|
+
if Shoulda.current_context
|
73
|
+
Shoulda.current_context.should(name_or_matcher, options, &blk)
|
74
|
+
else
|
75
|
+
context_name = self.name.gsub(/Test/, "")
|
76
|
+
context = Shoulda::Context.new(context_name, self) do
|
77
|
+
should(name_or_matcher, options, &blk)
|
78
|
+
end
|
79
|
+
context.build
|
80
|
+
end
|
81
|
+
end
|
59
82
|
|
60
|
-
|
83
|
+
# Allows negative tests using matchers. The matcher's description is used
|
84
|
+
# to generate a test name and negative failure message, and the test will
|
85
|
+
# pass unless the matcher matches the subject.
|
86
|
+
#
|
87
|
+
# === Example:
|
88
|
+
#
|
89
|
+
# should_not set_the_flash
|
90
|
+
def should_not(matcher)
|
61
91
|
if Shoulda.current_context
|
62
|
-
|
92
|
+
Shoulda.current_context.should_not(matcher)
|
63
93
|
else
|
64
94
|
context_name = self.name.gsub(/Test/, "")
|
65
95
|
context = Shoulda::Context.new(context_name, self) do
|
66
|
-
|
96
|
+
should_not(matcher)
|
67
97
|
end
|
68
98
|
context.build
|
69
99
|
end
|
@@ -86,7 +116,7 @@ module Shoulda
|
|
86
116
|
# context "on GET" do
|
87
117
|
# setup { get :index }
|
88
118
|
#
|
89
|
-
#
|
119
|
+
# should respond_with(:success)
|
90
120
|
#
|
91
121
|
# # runs before "get :index"
|
92
122
|
# before_should "find all users" do
|
@@ -185,7 +215,7 @@ module Shoulda
|
|
185
215
|
# subject { User.first }
|
186
216
|
#
|
187
217
|
# # uses the existing user
|
188
|
-
#
|
218
|
+
# should validate_uniqueness_of(:email)
|
189
219
|
# end
|
190
220
|
def subject(&block)
|
191
221
|
@subject_block = block
|
@@ -214,27 +244,10 @@ module Shoulda
|
|
214
244
|
# end
|
215
245
|
# end
|
216
246
|
#
|
217
|
-
# If an instance variable exists named after the described class, that
|
218
|
-
# instance variable will be used as the subject. This behavior is
|
219
|
-
# deprecated, and will be removed in a future version of Shoulda. The
|
220
|
-
# recommended approach for using a different subject is to use the subject
|
221
|
-
# class method.
|
222
|
-
#
|
223
|
-
# class UserTest
|
224
|
-
# should "be the existing user" do
|
225
|
-
# @user = User.new
|
226
|
-
# assert_equal @user, subject # passes
|
227
|
-
# end
|
228
|
-
# end
|
229
|
-
#
|
230
247
|
# The subject is used by all macros that require an instance of the class
|
231
248
|
# being tested.
|
232
249
|
def subject
|
233
|
-
|
234
|
-
instance_eval(&subject_block)
|
235
|
-
else
|
236
|
-
get_instance_of(self.class.described_type)
|
237
|
-
end
|
250
|
+
@shoulda_subject ||= construct_subject
|
238
251
|
end
|
239
252
|
|
240
253
|
def subject_block # :nodoc:
|
@@ -243,17 +256,7 @@ module Shoulda
|
|
243
256
|
|
244
257
|
def get_instance_of(object_or_klass) # :nodoc:
|
245
258
|
if object_or_klass.is_a?(Class)
|
246
|
-
|
247
|
-
ivar = "@#{instance_variable_name_for(klass)}"
|
248
|
-
if instance = instance_variable_get(ivar)
|
249
|
-
warn "[WARNING] Using #{ivar} as the subject. Future versions " <<
|
250
|
-
"of Shoulda will require an explicit subject using the " <<
|
251
|
-
"subject class method. Add this after your setup to avoid " <<
|
252
|
-
"this warning: subject { #{ivar} }"
|
253
|
-
instance
|
254
|
-
else
|
255
|
-
klass.new
|
256
|
-
end
|
259
|
+
object_or_klass.new
|
257
260
|
else
|
258
261
|
object_or_klass
|
259
262
|
end
|
@@ -262,6 +265,16 @@ module Shoulda
|
|
262
265
|
def instance_variable_name_for(klass) # :nodoc:
|
263
266
|
klass.to_s.split('::').last.underscore
|
264
267
|
end
|
268
|
+
|
269
|
+
private
|
270
|
+
|
271
|
+
def construct_subject
|
272
|
+
if subject_block
|
273
|
+
instance_eval(&subject_block)
|
274
|
+
else
|
275
|
+
get_instance_of(self.class.described_type)
|
276
|
+
end
|
277
|
+
end
|
265
278
|
end
|
266
279
|
|
267
280
|
class Context # :nodoc:
|
@@ -305,14 +318,27 @@ module Shoulda
|
|
305
318
|
self.teardown_blocks << blk
|
306
319
|
end
|
307
320
|
|
308
|
-
def should(
|
309
|
-
if
|
321
|
+
def should(name_or_matcher, options = {}, &blk)
|
322
|
+
if name_or_matcher.respond_to?(:description) && name_or_matcher.respond_to?(:matches?)
|
323
|
+
name = name_or_matcher.description
|
324
|
+
blk = lambda { assert_accepts name_or_matcher, subject }
|
325
|
+
else
|
326
|
+
name = name_or_matcher
|
327
|
+
end
|
328
|
+
|
329
|
+
if blk
|
310
330
|
self.shoulds << { :name => name, :before => options[:before], :block => blk }
|
311
331
|
else
|
312
332
|
self.should_eventuallys << { :name => name }
|
313
333
|
end
|
314
334
|
end
|
315
335
|
|
336
|
+
def should_not(matcher)
|
337
|
+
name = matcher.description
|
338
|
+
blk = lambda { assert_rejects matcher, subject }
|
339
|
+
self.shoulds << { :name => "not #{name}", :block => blk }
|
340
|
+
end
|
341
|
+
|
316
342
|
def should_eventually(name, &blk)
|
317
343
|
self.should_eventuallys << { :name => name, :block => blk }
|
318
344
|
end
|
@@ -321,6 +347,11 @@ module Shoulda
|
|
321
347
|
self.subject_block = block
|
322
348
|
end
|
323
349
|
|
350
|
+
def subject_block
|
351
|
+
return @subject_block if @subject_block
|
352
|
+
parent.subject_block
|
353
|
+
end
|
354
|
+
|
324
355
|
def full_name
|
325
356
|
parent_name = parent.full_name if am_subcontext?
|
326
357
|
return [parent_name, name].join(" ").strip
|