shoulda-matchers 2.6.1 → 2.6.2
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +9 -0
- data/.yardopts +8 -0
- data/Appraisals +82 -33
- data/Gemfile +18 -2
- data/Gemfile.lock +13 -1
- data/NEWS.md +27 -2
- data/README.md +83 -1329
- data/Rakefile +118 -1
- data/cucumber.yml +1 -0
- data/doc_config/gh-pages/index.html.erb +9 -0
- data/doc_config/yard/setup.rb +22 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/bootstrap.css +5967 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/full_list.css +12 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/global.css +45 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/solarized.css +69 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/style.css +283 -0
- data/doc_config/yard/templates/default/fulldoc/html/full_list.erb +32 -0
- data/doc_config/yard/templates/default/fulldoc/html/full_list_class.erb +1 -0
- data/doc_config/yard/templates/default/fulldoc/html/full_list_method.erb +8 -0
- data/doc_config/yard/templates/default/fulldoc/html/js/app.js +298 -0
- data/doc_config/yard/templates/default/fulldoc/html/js/full_list.js +1 -0
- data/doc_config/yard/templates/default/fulldoc/html/js/jquery.stickyheaders.js +289 -0
- data/doc_config/yard/templates/default/fulldoc/html/js/underscore.min.js +6 -0
- data/doc_config/yard/templates/default/fulldoc/html/setup.rb +8 -0
- data/doc_config/yard/templates/default/layout/html/breadcrumb.erb +14 -0
- data/doc_config/yard/templates/default/layout/html/fonts.erb +1 -0
- data/doc_config/yard/templates/default/layout/html/layout.erb +23 -0
- data/doc_config/yard/templates/default/layout/html/search.erb +13 -0
- data/doc_config/yard/templates/default/layout/html/setup.rb +40 -0
- data/doc_config/yard/templates/default/method_details/html/source.erb +10 -0
- data/doc_config/yard/templates/default/module/html/box_info.erb +31 -0
- data/docs.watchr +5 -0
- data/features/rails_integration.feature +32 -0
- data/features/step_definitions/rails_steps.rb +55 -9
- data/features/support/env.rb +1 -0
- data/gemfiles/3.0.gemfile +13 -1
- data/gemfiles/3.0.gemfile.lock +13 -1
- data/gemfiles/3.1.gemfile +17 -2
- data/gemfiles/3.1.gemfile.lock +31 -2
- data/gemfiles/3.1_1.9.2.gemfile +33 -0
- data/gemfiles/3.1_1.9.2.gemfile.lock +203 -0
- data/gemfiles/3.2.gemfile +18 -2
- data/gemfiles/3.2.gemfile.lock +32 -2
- data/gemfiles/3.2_1.9.2.gemfile +32 -0
- data/gemfiles/3.2_1.9.2.gemfile.lock +200 -0
- data/gemfiles/4.0.0.gemfile +20 -1
- data/gemfiles/4.0.0.gemfile.lock +46 -2
- data/gemfiles/4.0.1.gemfile +20 -1
- data/gemfiles/4.0.1.gemfile.lock +46 -2
- data/gemfiles/4.1.gemfile +21 -2
- data/gemfiles/4.1.gemfile.lock +47 -4
- data/lib/shoulda/matchers/action_controller.rb +0 -20
- data/lib/shoulda/matchers/action_controller/callback_matcher.rb +119 -28
- data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +22 -6
- data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +43 -10
- data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +40 -13
- data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +63 -11
- data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +34 -1
- data/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +84 -15
- data/lib/shoulda/matchers/action_controller/route_matcher.rb +84 -28
- data/lib/shoulda/matchers/action_controller/route_params.rb +4 -3
- data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +76 -13
- data/lib/shoulda/matchers/action_controller/set_the_flash_matcher.rb +147 -13
- data/lib/shoulda/matchers/action_controller/strong_parameters_matcher.rb +148 -2
- data/lib/shoulda/matchers/active_model.rb +0 -25
- data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +66 -9
- data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +161 -19
- data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +5 -5
- data/lib/shoulda/matchers/active_model/ensure_exclusion_of_matcher.rb +92 -13
- data/lib/shoulda/matchers/active_model/ensure_inclusion_of_matcher.rb +218 -16
- data/lib/shoulda/matchers/active_model/ensure_length_of_matcher.rb +198 -32
- data/lib/shoulda/matchers/active_model/errors.rb +5 -2
- data/lib/shoulda/matchers/active_model/exception_message_finder.rb +1 -1
- data/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +29 -8
- data/lib/shoulda/matchers/active_model/helpers.rb +20 -8
- data/lib/shoulda/matchers/active_model/numericality_matchers.rb +9 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +4 -6
- data/lib/shoulda/matchers/active_model/numericality_matchers/even_number_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +3 -2
- data/lib/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +52 -14
- data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +51 -13
- data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +53 -7
- data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +275 -19
- data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +84 -14
- data/lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb +170 -41
- data/lib/shoulda/matchers/active_model/validation_matcher.rb +20 -15
- data/lib/shoulda/matchers/active_model/validation_message_finder.rb +1 -2
- data/lib/shoulda/matchers/active_record.rb +1 -12
- data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +89 -15
- data/lib/shoulda/matchers/active_record/association_matcher.rb +726 -70
- data/lib/shoulda/matchers/active_record/association_matchers.rb +9 -0
- data/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_record/association_matchers/inverse_of_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +2 -1
- data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +4 -3
- data/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +4 -5
- data/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +79 -15
- data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +64 -15
- data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +21 -7
- data/lib/shoulda/matchers/active_record/serialize_matcher.rb +85 -10
- data/lib/shoulda/matchers/assertion_error.rb +7 -1
- data/lib/shoulda/matchers/doublespeak.rb +2 -1
- data/lib/shoulda/matchers/doublespeak/double.rb +3 -1
- data/lib/shoulda/matchers/doublespeak/double_collection.rb +2 -1
- data/lib/shoulda/matchers/doublespeak/double_implementation_registry.rb +1 -0
- data/lib/shoulda/matchers/doublespeak/object_double.rb +2 -1
- data/lib/shoulda/matchers/doublespeak/proxy_implementation.rb +2 -1
- data/lib/shoulda/matchers/doublespeak/structs.rb +2 -0
- data/lib/shoulda/matchers/doublespeak/stub_implementation.rb +2 -1
- data/lib/shoulda/matchers/doublespeak/world.rb +3 -4
- data/lib/shoulda/matchers/error.rb +1 -0
- data/lib/shoulda/matchers/independent/delegate_matcher.rb +108 -20
- data/lib/shoulda/matchers/independent/delegate_matcher/stubbed_target.rb +4 -3
- data/lib/shoulda/matchers/integrations/nunit_test_case_detection.rb +3 -0
- data/lib/shoulda/matchers/rails_shim.rb +3 -2
- data/lib/shoulda/matchers/version.rb +2 -1
- data/lib/shoulda/matchers/warn.rb +1 -0
- data/script/SUPPORTED_VERSIONS +1 -0
- data/script/install_gems_in_all_appraisals +14 -0
- data/script/run_all_tests +14 -0
- data/shoulda-matchers.gemspec +0 -10
- data/spec/report_warnings.rb +7 -0
- data/spec/shoulda/matchers/action_controller/route_matcher_spec.rb +1 -1
- data/spec/shoulda/matchers/action_controller/strong_parameters_matcher_spec.rb +9 -0
- data/spec/shoulda/matchers/active_model/validate_uniqueness_of_matcher_spec.rb +0 -36
- data/spec/shoulda/matchers/active_model/validation_message_finder_spec.rb +2 -2
- data/spec/shoulda/matchers/doublespeak/double_spec.rb +1 -1
- data/spec/shoulda/matchers/doublespeak/world_spec.rb +11 -29
- data/spec/shoulda/matchers/doublespeak_spec.rb +3 -3
- data/spec/spec_helper.rb +17 -0
- data/spec/support/class_builder.rb +4 -0
- data/spec/support/test_application.rb +1 -1
- data/spec/warnings_spy.rb +64 -0
- data/spec/warnings_spy/filesystem.rb +45 -0
- data/spec/warnings_spy/partitioner.rb +29 -0
- data/spec/warnings_spy/reader.rb +64 -0
- data/spec/warnings_spy/reporter.rb +87 -0
- metadata +49 -134
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8ff48aa28034edc27f14e97808a24f0e777cf3ab
|
|
4
|
+
data.tar.gz: 6432f92a9497036932281d941a437b40f5636e06
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7f64a534e64d8f070d5e5d524bb9b21df80fa2afe93f4be3cf7b44e6ecb7a33fff7c91b87756194548fb0670548d0302467ce2d83e1371c42bf80f7283c1673b
|
|
7
|
+
data.tar.gz: 940a2d667949ef94d42ada95554fda4a288af2d8cfa95f307900a3e345f46d867ca9cae347758e1f3bf2782e482397cc83a109aeb7359fbb3c69406f0abb0523
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
|
@@ -16,6 +16,10 @@ matrix:
|
|
|
16
16
|
- rvm: rbx-19mode
|
|
17
17
|
- rvm: jruby-19mode
|
|
18
18
|
include:
|
|
19
|
+
- rvm: 1.9.2
|
|
20
|
+
gemfile: gemfiles/3.1_1.9.2.gemfile
|
|
21
|
+
- rvm: 1.9.2
|
|
22
|
+
gemfile: gemfiles/3.2_1.9.2.gemfile
|
|
19
23
|
- rvm: 1.9.3
|
|
20
24
|
gemfile: gemfiles/4.0.0.gemfile
|
|
21
25
|
- rvm: 1.9.3
|
|
@@ -34,3 +38,8 @@ matrix:
|
|
|
34
38
|
gemfile: gemfiles/3.2.gemfile
|
|
35
39
|
- rvm: jruby-19mode
|
|
36
40
|
gemfile: gemfiles/3.2.gemfile
|
|
41
|
+
exclude:
|
|
42
|
+
- rvm: 1.9.2
|
|
43
|
+
gemfile: gemfiles/3.1.gemfile
|
|
44
|
+
- rvm: 1.9.2
|
|
45
|
+
gemfile: gemfiles/3.2.gemfile
|
data/.yardopts
ADDED
data/Appraisals
CHANGED
|
@@ -1,5 +1,42 @@
|
|
|
1
|
-
|
|
1
|
+
ruby_version = Gem::Version.new(RUBY_VERSION + '')
|
|
2
|
+
|
|
3
|
+
spring = proc do
|
|
4
|
+
gem 'spring'
|
|
5
|
+
gem 'spring-commands-rspec'
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
rails_3 = proc do
|
|
9
|
+
gem 'strong_parameters'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
rails_3_1 = proc do
|
|
13
|
+
instance_eval(&rails_3)
|
|
14
|
+
gem 'rails', '~> 3.1.8'
|
|
15
|
+
gem 'bcrypt-ruby', '~> 3.0.0'
|
|
16
|
+
gem 'jquery-rails'
|
|
17
|
+
gem 'sass-rails', '~> 3.1.5'
|
|
18
|
+
gem 'coffee-rails', '~> 3.1.1'
|
|
19
|
+
gem 'uglifier', '>= 1.0.3'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
rails_3_2 = proc do
|
|
23
|
+
instance_eval(&rails_3)
|
|
24
|
+
gem 'rails', '~> 3.2.13'
|
|
25
|
+
gem 'bcrypt-ruby', '~> 3.0.0'
|
|
26
|
+
gem 'jquery-rails'
|
|
27
|
+
gem 'sass-rails', '~> 3.2.3'
|
|
28
|
+
gem 'coffee-rails', '~> 3.2.1'
|
|
29
|
+
gem 'uglifier', '>= 1.0.3'
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
rails_4 = proc do
|
|
33
|
+
instance_eval(&spring)
|
|
34
|
+
gem 'uglifier', '>= 1.3.0'
|
|
35
|
+
gem 'coffee-rails', '~> 4.0.0'
|
|
2
36
|
gem 'jquery-rails'
|
|
37
|
+
gem 'turbolinks'
|
|
38
|
+
gem 'jbuilder', '~> 1.2'
|
|
39
|
+
gem 'sdoc'
|
|
3
40
|
gem 'activeresource', '4.0.0'
|
|
4
41
|
# Test suite makes heavy use of attr_accessible
|
|
5
42
|
gem 'protected_attributes'
|
|
@@ -7,47 +44,59 @@ end
|
|
|
7
44
|
|
|
8
45
|
#---
|
|
9
46
|
|
|
10
|
-
if
|
|
47
|
+
if Gem::Requirement.new('< 2').satisfied_by?(ruby_version)
|
|
11
48
|
appraise '3.0' do
|
|
49
|
+
instance_eval(&rails_3)
|
|
12
50
|
gem 'rails', '~> 3.0.17'
|
|
13
|
-
gem 'strong_parameters'
|
|
14
51
|
end
|
|
15
52
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
53
|
+
if Gem::Requirement.new('= 1.9.2').satisfied_by?(ruby_version)
|
|
54
|
+
appraise '3.1-1.9.2' do
|
|
55
|
+
instance_eval(&rails_3_1)
|
|
56
|
+
gem 'turn', '0.8.2'
|
|
57
|
+
end
|
|
58
|
+
else
|
|
59
|
+
appraise '3.1' do
|
|
60
|
+
instance_eval(&rails_3_1)
|
|
61
|
+
gem 'turn', '~> 0.8.3'
|
|
62
|
+
end
|
|
22
63
|
end
|
|
23
64
|
end
|
|
24
65
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
66
|
+
if Gem::Requirement.new('= 1.9.2').satisfied_by?(ruby_version)
|
|
67
|
+
appraise '3.2-1.9.2' do
|
|
68
|
+
instance_eval(&rails_3_2)
|
|
69
|
+
end
|
|
70
|
+
else
|
|
71
|
+
appraise '3.2' do
|
|
72
|
+
instance_eval(&rails_3_2)
|
|
73
|
+
instance_eval(&spring)
|
|
74
|
+
end
|
|
31
75
|
end
|
|
32
76
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
77
|
+
if Gem::Requirement.new('> 1.9.2').satisfied_by?(ruby_version)
|
|
78
|
+
appraise '4.0.0' do
|
|
79
|
+
instance_eval(&rails_4)
|
|
80
|
+
gem 'rails', '4.0.0'
|
|
81
|
+
gem 'sass-rails', '~> 4.0.0'
|
|
82
|
+
gem 'bcrypt-ruby', '~> 3.0.0'
|
|
83
|
+
end
|
|
39
84
|
|
|
40
|
-
appraise '4.0.1' do
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
end
|
|
85
|
+
appraise '4.0.1' do
|
|
86
|
+
instance_eval(&rails_4)
|
|
87
|
+
gem 'rails', '4.0.1'
|
|
88
|
+
gem 'sass-rails', '~> 4.0.0'
|
|
89
|
+
gem 'bcrypt-ruby', '~> 3.1.2'
|
|
90
|
+
end
|
|
46
91
|
|
|
47
|
-
appraise '4.1' do
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
92
|
+
appraise '4.1' do
|
|
93
|
+
instance_eval(&rails_4)
|
|
94
|
+
gem 'rails', '~> 4.1.0'
|
|
95
|
+
gem 'jbuilder', '~> 2.0'
|
|
96
|
+
gem 'sass-rails', '~> 4.0.3'
|
|
97
|
+
gem 'sdoc', '~> 0.4.0'
|
|
98
|
+
gem 'bcrypt', '~> 3.1.7'
|
|
99
|
+
gem 'protected_attributes', "~> 1.0.6"
|
|
100
|
+
gem 'spring'
|
|
101
|
+
end
|
|
53
102
|
end
|
data/Gemfile
CHANGED
|
@@ -2,12 +2,28 @@ source 'https://rubygems.org'
|
|
|
2
2
|
|
|
3
3
|
gemspec
|
|
4
4
|
|
|
5
|
+
gem 'appraisal', '~> 1.0.0.beta2'
|
|
6
|
+
gem 'aruba'
|
|
7
|
+
gem 'bourne', '~> 1.3'
|
|
8
|
+
gem 'bundler', '~> 1.1'
|
|
9
|
+
gem 'cucumber', '~> 1.1'
|
|
10
|
+
gem 'pry'
|
|
11
|
+
gem 'rails', '~> 3.0'
|
|
12
|
+
gem 'rake', '>= 0.9.2'
|
|
13
|
+
gem 'rspec-rails', '>= 2.13.1', '< 3'
|
|
14
|
+
|
|
15
|
+
# YARD
|
|
16
|
+
gem 'yard'
|
|
17
|
+
gem 'redcarpet'
|
|
18
|
+
gem 'pygments.rb'
|
|
19
|
+
gem 'watchr'
|
|
20
|
+
|
|
5
21
|
# For test Rails application
|
|
6
22
|
gem 'shoulda-context', '~> 1.2.0'
|
|
7
23
|
gem 'sqlite3', :platform => :ruby
|
|
8
24
|
|
|
9
|
-
# Can't wrap in platform :jruby do...end block because appraisal doesn't
|
|
10
|
-
# it
|
|
25
|
+
# Can't wrap in platform :jruby do...end block because appraisal doesn't
|
|
26
|
+
# support it
|
|
11
27
|
gem 'activerecord-jdbc-adapter', :platform => :jruby
|
|
12
28
|
gem 'activerecord-jdbcsqlite3-adapter', :platform => :jruby
|
|
13
29
|
gem 'jdbc-sqlite3', :platform => :jruby
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
shoulda-matchers (2.6.
|
|
4
|
+
shoulda-matchers (2.6.2)
|
|
5
5
|
activesupport (>= 3.0.0)
|
|
6
6
|
|
|
7
7
|
GEM
|
|
@@ -75,10 +75,14 @@ GEM
|
|
|
75
75
|
multi_json (1.8.4)
|
|
76
76
|
multi_test (0.0.3)
|
|
77
77
|
polyglot (0.3.3)
|
|
78
|
+
posix-spawn (0.3.8)
|
|
78
79
|
pry (0.9.12.6)
|
|
79
80
|
coderay (~> 1.0)
|
|
80
81
|
method_source (~> 0.8)
|
|
81
82
|
slop (~> 3.4)
|
|
83
|
+
pygments.rb (0.3.7)
|
|
84
|
+
posix-spawn (~> 0.3.6)
|
|
85
|
+
yajl-ruby (~> 1.1.0)
|
|
82
86
|
rack (1.4.5)
|
|
83
87
|
rack-cache (1.2)
|
|
84
88
|
rack (>= 0.4)
|
|
@@ -104,6 +108,7 @@ GEM
|
|
|
104
108
|
rake (10.1.1)
|
|
105
109
|
rdoc (3.12.2)
|
|
106
110
|
json (~> 1.4)
|
|
111
|
+
redcarpet (3.0.0)
|
|
107
112
|
rspec-core (2.14.7)
|
|
108
113
|
rspec-expectations (2.14.4)
|
|
109
114
|
diff-lcs (>= 1.1.3, < 2.0)
|
|
@@ -130,6 +135,9 @@ GEM
|
|
|
130
135
|
polyglot
|
|
131
136
|
polyglot (>= 0.3.1)
|
|
132
137
|
tzinfo (0.3.38)
|
|
138
|
+
watchr (0.7)
|
|
139
|
+
yajl-ruby (1.1.0)
|
|
140
|
+
yard (0.8.7.3)
|
|
133
141
|
|
|
134
142
|
PLATFORMS
|
|
135
143
|
ruby
|
|
@@ -145,10 +153,14 @@ DEPENDENCIES
|
|
|
145
153
|
jdbc-sqlite3
|
|
146
154
|
jruby-openssl
|
|
147
155
|
pry
|
|
156
|
+
pygments.rb
|
|
148
157
|
rails (~> 3.0)
|
|
149
158
|
rake (>= 0.9.2)
|
|
159
|
+
redcarpet
|
|
150
160
|
rspec-rails (>= 2.13.1, < 3)
|
|
151
161
|
shoulda-context (~> 1.2.0)
|
|
152
162
|
shoulda-matchers!
|
|
153
163
|
sqlite3
|
|
154
164
|
therubyrhino
|
|
165
|
+
watchr
|
|
166
|
+
yard
|
data/NEWS.md
CHANGED
|
@@ -1,12 +1,37 @@
|
|
|
1
|
+
# HEAD
|
|
2
|
+
|
|
3
|
+
# 2.6.2
|
|
4
|
+
|
|
5
|
+
### Bug fixes
|
|
6
|
+
|
|
7
|
+
* If you have a Rails >= 4.1 project and you are running tests using Spring,
|
|
8
|
+
matchers that depend on assertions within Rails' testing layer (e.g.
|
|
9
|
+
`render_template` and `route`) will no longer fail.
|
|
10
|
+
|
|
11
|
+
* Fix `permit` so that it can be used more than once in the same test.
|
|
12
|
+
|
|
13
|
+
* Revert change to `validate_uniqueness_of` made in 2.6.0 so that it no longer
|
|
14
|
+
provides default values for non-primary, non-nullable columns. This approach
|
|
15
|
+
was causing test failures because it makes the assumption that none of these
|
|
16
|
+
columns allow only specific values, which is not true. If you get an error
|
|
17
|
+
from `validate_uniqueness_of`, your best bet continues to be creating a record
|
|
18
|
+
manually and calling `validate_uniqueness_of` on that instead.
|
|
19
|
+
|
|
20
|
+
### Other changes
|
|
21
|
+
|
|
22
|
+
* The majority of warnings that the gem produced have been removed. The gem
|
|
23
|
+
still produces warnings under Ruby 1.9.3; we will address this in a future
|
|
24
|
+
release.
|
|
25
|
+
|
|
1
26
|
# 2.6.1
|
|
2
27
|
|
|
3
|
-
|
|
28
|
+
### Features
|
|
4
29
|
|
|
5
30
|
* Teach `with_message` qualifier on `allow_value` to accept a hash of i18n
|
|
6
31
|
interpolation values:
|
|
7
32
|
`allow_value('foo').for(:attr).with_message(:greater_than, values: { count: 20 })`.
|
|
8
33
|
|
|
9
|
-
|
|
34
|
+
### Bug fixes
|
|
10
35
|
|
|
11
36
|
* Revert changes to `validate_numericality_of` made in the last release, which
|
|
12
37
|
made it so that comparison qualifiers specified on the validation are tested
|
data/README.md
CHANGED
|
@@ -6,28 +6,92 @@ shoulda-matchers provides Test::Unit- and RSpec-compatible one-liners that test
|
|
|
6
6
|
common Rails functionality. These tests would otherwise be much longer, more
|
|
7
7
|
complex, and error-prone.
|
|
8
8
|
|
|
9
|
+
### ActiveModel Matchers
|
|
10
|
+
|
|
11
|
+
* **[allow_mass_assignment_of](lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb)**
|
|
12
|
+
tests usage of Rails 3's `attr_accessible` and `attr_protected` macros.
|
|
13
|
+
* **[allow_value](lib/shoulda/matchers/active_model/allow_value_matcher.rb)** tests usage of
|
|
14
|
+
the `validates_format_of` validation.
|
|
15
|
+
* **[ensure_inclusion_of](lib/shoulda/matchers/active_model/ensure_inclusion_of_matcher.rb)** tests
|
|
16
|
+
usage of `validates_inclusion_of`.
|
|
17
|
+
* **[ensure_exclusion_of](lib/shoulda/matchers/active_model/ensure_exclusion_of_matcher.rb)** tests
|
|
18
|
+
usage of `validates_exclusion_of`.
|
|
19
|
+
* **[ensure_length_of](lib/shoulda/matchers/active_model/ensure_length_of_matcher.rb)** tests usage
|
|
20
|
+
of `validates_length_of`.
|
|
21
|
+
* **[have_secure_password](lib/shoulda/matchers/active_model/have_secure_password_matcher.rb)** tests
|
|
22
|
+
usage of `has_secure_password`.
|
|
23
|
+
* **[validate_confirmation_of](lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb)**
|
|
24
|
+
tests usage of `validates_confirmation_of`.
|
|
25
|
+
* **[validate_numericality_of](lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb)**
|
|
26
|
+
tests usage of `validates_numericality_of`.
|
|
27
|
+
* **[validate_presence_of](lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb)** tests
|
|
28
|
+
usage of `validates_presence_of`.
|
|
29
|
+
* **[validate_uniqueness_of](lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb)** tests
|
|
30
|
+
usage of `validates_uniqueness_of`.
|
|
31
|
+
|
|
32
|
+
### ActiveRecord Matchers
|
|
33
|
+
|
|
34
|
+
* **[accept_nested_attributes_for](lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb)**
|
|
35
|
+
tests usage of the `accepts_nested_attributes_for` macro.
|
|
36
|
+
* **[belong_to](lib/shoulda/matchers/active_record/association_matcher.rb)** tests
|
|
37
|
+
your `belongs_to` associations.
|
|
38
|
+
* **[have_many](lib/shoulda/matchers/active_record/association_matcher.rb)** tests
|
|
39
|
+
your `has_many` associations.
|
|
40
|
+
* **[have_one](lib/shoulda/matchers/active_record/association_matcher.rb)** tests your
|
|
41
|
+
`has_one` associations.
|
|
42
|
+
* **[have_and_belong_to_many](lib/shoulda/matchers/active_record/association_matcher.rb)**
|
|
43
|
+
tests your `has_and_belongs_to_many` associations.
|
|
44
|
+
* **[have_db_column](lib/shoulda/matchers/active_record/have_db_column_matcher.rb)** tests that
|
|
45
|
+
the table that backs your model has a specific column.
|
|
46
|
+
* **[have_db_index](lib/shoulda/matchers/active_record/have_db_index_matcher.rb)** tests that the
|
|
47
|
+
table that backs your model has an index on a specific column.
|
|
48
|
+
* **[have_readonly_attribute](lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb)**
|
|
49
|
+
tests usage of the `attr_readonly` macro.
|
|
50
|
+
* **[serialize](lib/shoulda/matchers/active_record/serialize_matcher.rb)** tests usage of the
|
|
51
|
+
`serialize` macro.
|
|
52
|
+
|
|
53
|
+
### ActionController Matchers
|
|
54
|
+
|
|
55
|
+
* **[filter_param](lib/shoulda/matchers/action_controller/filter_param_matcher.rb)** tests
|
|
56
|
+
parameter filtering configuration.
|
|
57
|
+
* **[redirect_to](lib/shoulda/matchers/action_controller/redirect_to_matcher.rb)** tests that
|
|
58
|
+
an action redirects to a certain location.
|
|
59
|
+
* **[render_template](lib/shoulda/matchers/action_controller/render_template_matcher.rb)** tests
|
|
60
|
+
that an action renders a template.
|
|
61
|
+
* **[render_with_layout](lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb)** tests
|
|
62
|
+
that an action is rendereed with a certain layout.
|
|
63
|
+
* **[rescue_from](lib/shoulda/matchers/action_controller/rescue_from_matcher.rb)** tests usage
|
|
64
|
+
of the `rescue_from` macro.
|
|
65
|
+
* **[respond_with](lib/shoulda/matchers/action_controller/respond_with_matcher.rb)** tests that
|
|
66
|
+
an action responds with a certain status code.
|
|
67
|
+
* **[route](lib/shoulda/matchers/action_controller/route_matcher.rb)** tests your routes.
|
|
68
|
+
* **[set_session](lib/shoulda/matchers/action_controller/set_session_matcher.rb)** makes
|
|
69
|
+
assertions on the `session` hash.
|
|
70
|
+
* **[set_the_flash](lib/shoulda/matchers/action_controller/set_the_flash_matcher.rb)** makes
|
|
71
|
+
assertions on the `flash` hash.
|
|
72
|
+
|
|
73
|
+
### Independent Matchers
|
|
74
|
+
|
|
75
|
+
* **[delegate_matcher](lib/shoulda/matchers/independent/delegate_matcher.rb)**
|
|
76
|
+
tests that an object forwards messages to other, internal objects by way of
|
|
77
|
+
delegation.
|
|
78
|
+
|
|
9
79
|
## Installation
|
|
10
80
|
|
|
11
81
|
### RSpec
|
|
12
82
|
|
|
13
83
|
Include the gem in your Gemfile:
|
|
14
84
|
|
|
15
|
-
```ruby
|
|
85
|
+
``` ruby
|
|
16
86
|
group :test do
|
|
17
|
-
gem 'shoulda-matchers'
|
|
87
|
+
gem 'shoulda-matchers', require: false
|
|
18
88
|
end
|
|
19
89
|
```
|
|
20
90
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
```ruby
|
|
25
|
-
# Gemfile
|
|
26
|
-
group :test do
|
|
27
|
-
gem 'shoulda-matchers', require: false
|
|
28
|
-
end
|
|
91
|
+
Then require the gem following rspec-rails in your rails_helper (or spec_helper
|
|
92
|
+
if you're using RSpec 2.x):
|
|
29
93
|
|
|
30
|
-
|
|
94
|
+
``` ruby
|
|
31
95
|
require 'rspec/rails'
|
|
32
96
|
require 'shoulda/matchers'
|
|
33
97
|
```
|
|
@@ -72,1329 +136,19 @@ gem 'shoulda-matchers'
|
|
|
72
136
|
gem 'activemodel'
|
|
73
137
|
```
|
|
74
138
|
|
|
75
|
-
##
|
|
76
|
-
|
|
77
|
-
Different matchers apply to different parts of Rails:
|
|
78
|
-
|
|
79
|
-
* [ActiveModel](#activemodel-matchers)
|
|
80
|
-
* [ActiveRecord](#activerecord-matchers)
|
|
81
|
-
* [ActionController](#actioncontroller-matchers)
|
|
82
|
-
|
|
83
|
-
### ActiveModel Matchers
|
|
84
|
-
|
|
85
|
-
*Jump to: [allow_mass_assignment_of](#allow_mass_assignment_of), [allow_value](#allow_value), [ensure_inclusion_of](#ensure_inclusion_of), [ensure_exclusion_of](#ensure_exclusion_of), [ensure_length_of](#ensure_length_of), [have_secure_password](#have_secure_password), [validate_absence_of](#validate_absence_of), [validate_acceptance_of](#validate_acceptance_of), [validate_confirmation_of](#validate_confirmation_of), [validate_numericality_of](#validate_numericality_of), [validate_presence_of](#validate_presence_of), [validate_uniqueness_of](#validate_uniqueness_of)*
|
|
86
|
-
|
|
87
|
-
Note that all of the examples in this section are based on an ActiveRecord
|
|
88
|
-
model for simplicity, but these matchers will work just as well using an
|
|
89
|
-
ActiveModel model.
|
|
90
|
-
|
|
91
|
-
#### allow_mass_assignment_of
|
|
92
|
-
|
|
93
|
-
The `allow_mass_assignment_of` matcher tests usage of Rails 3's
|
|
94
|
-
`attr_accessible` and `attr_protected` macros, asserting that attributes can or
|
|
95
|
-
cannot be mass-assigned on a record.
|
|
96
|
-
|
|
97
|
-
```ruby
|
|
98
|
-
class Post < ActiveRecord::Base
|
|
99
|
-
attr_accessible :title
|
|
100
|
-
attr_accessible :published_status, as: :admin
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
class User < ActiveRecord::Base
|
|
104
|
-
attr_protected :encrypted_password
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
# RSpec
|
|
108
|
-
describe Post do
|
|
109
|
-
it { should allow_mass_assignment_of(:title) }
|
|
110
|
-
it { should allow_mass_assignment_of(:published_status).as(:admin) }
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
describe User do
|
|
114
|
-
it { should_not allow_mass_assignment_of(:encrypted_password) }
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
# Test::Unit
|
|
118
|
-
class PostTest < ActiveSupport::TestCase
|
|
119
|
-
should allow_mass_assignment_of(:title)
|
|
120
|
-
should allow_mass_assignment_of(:published_status).as(:admin)
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
class UserTest < ActiveSupport::TestCase
|
|
124
|
-
should_not allow_mass_assignment_of(:encrypted_password)
|
|
125
|
-
end
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
#### allow_value
|
|
129
|
-
|
|
130
|
-
The `allow_value` matcher tests usage of the `validates_format_of` validation.
|
|
131
|
-
It asserts that an attribute can be set to one or more values, succeeding if
|
|
132
|
-
none of the values cause the record to be invalid.
|
|
133
|
-
|
|
134
|
-
```ruby
|
|
135
|
-
class UserProfile < ActiveRecord::Base
|
|
136
|
-
validates_format_of :website_url, with: URI.regexp
|
|
137
|
-
|
|
138
|
-
validates_format_of :birthday_as_string,
|
|
139
|
-
with: /^(\d+)-(\d+)-(\d+)$/,
|
|
140
|
-
on: :create
|
|
141
|
-
|
|
142
|
-
validates_format_of :state,
|
|
143
|
-
with: /^(open|closed)$/,
|
|
144
|
-
message: 'State must be open or closed'
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
# RSpec
|
|
148
|
-
describe UserProfile do
|
|
149
|
-
it { should allow_value('http://foo.com', 'http://bar.com/baz').for(:website_url) }
|
|
150
|
-
it { should_not allow_value('asdfjkl').for(:website_url) }
|
|
151
|
-
|
|
152
|
-
it do
|
|
153
|
-
should allow_value('2013-01-01').
|
|
154
|
-
for(:birthday_as_string).
|
|
155
|
-
on(:create)
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
it do
|
|
159
|
-
should allow_value('open', 'closed').
|
|
160
|
-
for(:state).
|
|
161
|
-
with_message('State must be open or closed')
|
|
162
|
-
end
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
# Test::Unit
|
|
166
|
-
class UserProfileTest < ActiveSupport::TestCase
|
|
167
|
-
should allow_value('http://foo.com', 'http://bar.com/baz').for(:website_url)
|
|
168
|
-
should_not allow_value('asdfjkl').for(:website_url)
|
|
169
|
-
|
|
170
|
-
should allow_value('2013-01-01').
|
|
171
|
-
for(:birthday_as_string).
|
|
172
|
-
on(:create)
|
|
173
|
-
|
|
174
|
-
should allow_value('open', 'closed').
|
|
175
|
-
for(:state).
|
|
176
|
-
with_message('State must be open or closed')
|
|
177
|
-
end
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
**PLEASE NOTE:** Using `should_not` with `allow_value` completely negates the
|
|
181
|
-
assertion. This means that if multiple values are given to `allow_value`, the
|
|
182
|
-
matcher succeeds once it sees the *first* value that will cause the record to be
|
|
183
|
-
invalid:
|
|
184
|
-
|
|
185
|
-
```ruby
|
|
186
|
-
describe User do
|
|
187
|
-
# 'b' and 'c' will not be tested
|
|
188
|
-
it { should_not allow_value('a', 'b', 'c').for(:website_url) }
|
|
189
|
-
end
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
#### ensure_inclusion_of
|
|
193
|
-
|
|
194
|
-
The `ensure_inclusion_of` matcher tests usage of the `validates_inclusion_of`
|
|
195
|
-
validation, asserting that an attribute can take a set of values and cannot
|
|
196
|
-
take values outside of this set.
|
|
197
|
-
|
|
198
|
-
```ruby
|
|
199
|
-
class Issue < ActiveRecord::Base
|
|
200
|
-
validates_inclusion_of :state, in: %w(open resolved unresolved)
|
|
201
|
-
validates_inclusion_of :priority, in: 1..5
|
|
202
|
-
|
|
203
|
-
validates_inclusion_of :severity,
|
|
204
|
-
in: %w(low medium high),
|
|
205
|
-
message: 'Severity must be low, medium, or high'
|
|
206
|
-
end
|
|
207
|
-
|
|
208
|
-
# RSpec
|
|
209
|
-
describe Issue do
|
|
210
|
-
it { should ensure_inclusion_of(:state).in_array(%w(open resolved unresolved)) }
|
|
211
|
-
it { should ensure_inclusion_of(:priority).in_range(1..5) }
|
|
212
|
-
|
|
213
|
-
it do
|
|
214
|
-
should ensure_inclusion_of(:severity).
|
|
215
|
-
in_array(%w(low medium high)).
|
|
216
|
-
with_message('Severity must be low, medium, or high')
|
|
217
|
-
end
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
# Test::Unit
|
|
221
|
-
class IssueTest < ActiveSupport::TestCase
|
|
222
|
-
should ensure_inclusion_of(:state).in_array(%w(open resolved unresolved))
|
|
223
|
-
should ensure_inclusion_of(:priority).in_range(1..5)
|
|
224
|
-
|
|
225
|
-
should ensure_inclusion_of(:severity).
|
|
226
|
-
in_array(%w(low medium high)).
|
|
227
|
-
with_message('Severity must be low, medium, or high')
|
|
228
|
-
end
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
#### ensure_exclusion_of
|
|
232
|
-
|
|
233
|
-
The `ensure_exclusion_of` matcher tests usage of the `validates_exclusion_of`
|
|
234
|
-
validation, asserting that an attribute cannot take a set of values.
|
|
235
|
-
|
|
236
|
-
```ruby
|
|
237
|
-
class Game < ActiveRecord::Base
|
|
238
|
-
validates_exclusion_of :supported_os, in: ['Mac', 'Linux']
|
|
239
|
-
validates_exclusion_of :floors_with_enemies, in: 5..8
|
|
240
|
-
|
|
241
|
-
validates_exclusion_of :weapon,
|
|
242
|
-
in: ['pistol', 'paintball gun', 'stick'],
|
|
243
|
-
message: 'You chose a puny weapon'
|
|
244
|
-
end
|
|
245
|
-
|
|
246
|
-
# RSpec
|
|
247
|
-
describe Game do
|
|
248
|
-
it { should ensure_exclusion_of(:supported_os).in_array(['Mac', 'Linux']) }
|
|
249
|
-
it { should ensure_exclusion_of(:floors_with_enemies).in_range(5..8) }
|
|
250
|
-
|
|
251
|
-
it do
|
|
252
|
-
should ensure_exclusion_of(:weapon).
|
|
253
|
-
in_array(['pistol', 'paintball gun', 'stick']).
|
|
254
|
-
with_message('You chose a puny weapon')
|
|
255
|
-
end
|
|
256
|
-
end
|
|
257
|
-
|
|
258
|
-
# Test::Unit
|
|
259
|
-
class GameTest < ActiveSupport::TestCase
|
|
260
|
-
should ensure_exclusion_of(:supported_os).in_array(['Mac', 'Linux'])
|
|
261
|
-
should ensure_exclusion_of(:floors_with_enemies).in_range(5..8)
|
|
262
|
-
|
|
263
|
-
should ensure_exclusion_of(:weapon).
|
|
264
|
-
in_array(['pistol', 'paintball gun', 'stick']).
|
|
265
|
-
with_message('You chose a puny weapon')
|
|
266
|
-
end
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
#### ensure_length_of
|
|
270
|
-
|
|
271
|
-
The `ensure_length_of` matcher tests usage of the `validates_length_of` matcher.
|
|
272
|
-
|
|
273
|
-
```ruby
|
|
274
|
-
class User < ActiveRecord::Base
|
|
275
|
-
validates_length_of :bio, minimum: 15
|
|
276
|
-
validates_length_of :favorite_superhero, is: 6
|
|
277
|
-
validates_length_of :status_update, maximum: 140
|
|
278
|
-
validates_length_of :password, in: 5..30
|
|
279
|
-
|
|
280
|
-
validates_length_of :api_token,
|
|
281
|
-
in: 10..20,
|
|
282
|
-
message: 'API token must be in between 10 and 20 characters'
|
|
283
|
-
|
|
284
|
-
validates_length_of :secret_key, in: 15..100,
|
|
285
|
-
too_short: 'Secret key must be more than 15 characters',
|
|
286
|
-
too_long: 'Secret key cannot be more than 100 characters'
|
|
287
|
-
end
|
|
288
|
-
|
|
289
|
-
# RSpec
|
|
290
|
-
describe User do
|
|
291
|
-
it { should ensure_length_of(:bio).is_at_least(15) }
|
|
292
|
-
it { should ensure_length_of(:favorite_superhero).is_equal_to(6) }
|
|
293
|
-
it { should ensure_length_of(:status_update).is_at_most(140) }
|
|
294
|
-
it { should ensure_length_of(:password).is_at_least(5).is_at_most(30) }
|
|
295
|
-
|
|
296
|
-
it do
|
|
297
|
-
should ensure_length_of(:api_token).
|
|
298
|
-
is_at_least(10).
|
|
299
|
-
is_at_most(20).
|
|
300
|
-
with_message('Password must be in between 10 and 20 characters')
|
|
301
|
-
end
|
|
302
|
-
|
|
303
|
-
it do
|
|
304
|
-
should ensure_length_of(:secret_key).
|
|
305
|
-
is_at_least(15).
|
|
306
|
-
is_at_most(100).
|
|
307
|
-
with_short_message('Secret key must be more than 15 characters').
|
|
308
|
-
with_long_message('Secret key cannot be more than 100 characters')
|
|
309
|
-
end
|
|
310
|
-
end
|
|
311
|
-
|
|
312
|
-
# Test::Unit
|
|
313
|
-
class UserTest < ActiveSupport::TestCase
|
|
314
|
-
should ensure_length_of(:bio).is_at_least(15)
|
|
315
|
-
should ensure_length_of(:favorite_superhero).is_equal_to(6)
|
|
316
|
-
should ensure_length_of(:status_update).is_at_most(140)
|
|
317
|
-
should ensure_length_of(:password).is_at_least(5).is_at_most(30)
|
|
318
|
-
|
|
319
|
-
should ensure_length_of(:api_token).
|
|
320
|
-
is_at_least(15).
|
|
321
|
-
is_at_most(20).
|
|
322
|
-
with_message('Password must be in between 15 and 20 characters')
|
|
323
|
-
|
|
324
|
-
should ensure_length_of(:secret_key).
|
|
325
|
-
is_at_least(15).
|
|
326
|
-
is_at_most(100).
|
|
327
|
-
with_short_message('Secret key must be more than 15 characters').
|
|
328
|
-
with_long_message('Secret key cannot be more than 100 characters')
|
|
329
|
-
end
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
#### have_secure_password
|
|
333
|
-
|
|
334
|
-
The `have_secure_password` matcher tests usage of the `has_secure_password`
|
|
335
|
-
macro.
|
|
336
|
-
|
|
337
|
-
```ruby
|
|
338
|
-
class User < ActiveRecord::Base
|
|
339
|
-
has_secure_password
|
|
340
|
-
end
|
|
341
|
-
|
|
342
|
-
# RSpec
|
|
343
|
-
describe User do
|
|
344
|
-
it { should have_secure_password }
|
|
345
|
-
end
|
|
346
|
-
|
|
347
|
-
# Test::Unit
|
|
348
|
-
class UserTest < ActiveSupport::TestCase
|
|
349
|
-
should have_secure_password
|
|
350
|
-
end
|
|
351
|
-
```
|
|
352
|
-
|
|
353
|
-
#### validate_absence_of
|
|
354
|
-
|
|
355
|
-
The `validate_absence_of` matcher tests the usage of the
|
|
356
|
-
`validates_absence_of` validation.
|
|
357
|
-
|
|
358
|
-
```ruby
|
|
359
|
-
class Tank
|
|
360
|
-
include ActiveModel::Model
|
|
361
|
-
|
|
362
|
-
validates_absence_of :arms
|
|
363
|
-
validates_absence_of :legs,
|
|
364
|
-
message: "Tanks don't have legs."
|
|
365
|
-
end
|
|
366
|
-
|
|
367
|
-
# RSpec
|
|
368
|
-
describe Tank do
|
|
369
|
-
it { should validate_absence_of(:arms) }
|
|
370
|
-
|
|
371
|
-
it do
|
|
372
|
-
should validate_absence_of(:legs).
|
|
373
|
-
with_message("Tanks don't have legs.")
|
|
374
|
-
end
|
|
375
|
-
end
|
|
376
|
-
|
|
377
|
-
# Test::Unit
|
|
378
|
-
class TankTest < ActiveSupport::TestCase
|
|
379
|
-
should validate_absence_of(:arms)
|
|
380
|
-
|
|
381
|
-
should validate_absence_of(:legs).
|
|
382
|
-
with_message("Tanks don't have legs.")
|
|
383
|
-
end
|
|
384
|
-
```
|
|
385
|
-
|
|
386
|
-
#### validate_acceptance_of
|
|
387
|
-
|
|
388
|
-
The `validate_acceptance_of` matcher tests usage of the
|
|
389
|
-
`validates_acceptance_of` validation.
|
|
390
|
-
|
|
391
|
-
```ruby
|
|
392
|
-
class Registration < ActiveRecord::Base
|
|
393
|
-
validates_acceptance_of :eula
|
|
394
|
-
validates_acceptance_of :terms_of_service,
|
|
395
|
-
message: 'You must accept the terms of service'
|
|
396
|
-
end
|
|
397
|
-
|
|
398
|
-
# RSpec
|
|
399
|
-
describe Registration do
|
|
400
|
-
it { should validate_acceptance_of(:eula) }
|
|
401
|
-
|
|
402
|
-
it do
|
|
403
|
-
should validate_acceptance_of(:terms_of_service).
|
|
404
|
-
with_message('You must accept the terms of service')
|
|
405
|
-
end
|
|
406
|
-
end
|
|
407
|
-
|
|
408
|
-
# Test::Unit
|
|
409
|
-
class RegistrationTest < ActiveSupport::TestCase
|
|
410
|
-
should validate_acceptance_of(:eula)
|
|
411
|
-
|
|
412
|
-
should validate_acceptance_of(:terms_of_service).
|
|
413
|
-
with_message('You must accept the terms of service')
|
|
414
|
-
end
|
|
415
|
-
```
|
|
416
|
-
|
|
417
|
-
#### validate_confirmation_of
|
|
418
|
-
|
|
419
|
-
The `validate_confirmation_of` matcher tests usage of the
|
|
420
|
-
`validates_confirmation_of` validation.
|
|
421
|
-
|
|
422
|
-
```ruby
|
|
423
|
-
class User < ActiveRecord::Base
|
|
424
|
-
validates_confirmation_of :email
|
|
425
|
-
validates_confirmation_of :password, message: 'Please re-enter your password'
|
|
426
|
-
end
|
|
427
|
-
|
|
428
|
-
# RSpec
|
|
429
|
-
describe User do
|
|
430
|
-
it do
|
|
431
|
-
should validate_confirmation_of(:email)
|
|
432
|
-
end
|
|
433
|
-
|
|
434
|
-
it do
|
|
435
|
-
should validate_confirmation_of(:password).
|
|
436
|
-
with_message('Please re-enter your password')
|
|
437
|
-
end
|
|
438
|
-
end
|
|
439
|
-
|
|
440
|
-
# Test::Unit
|
|
441
|
-
class UserTest < ActiveSupport::TestCase
|
|
442
|
-
should validate_confirmation_of(:email)
|
|
443
|
-
|
|
444
|
-
should validate_confirmation_of(:password).
|
|
445
|
-
with_message('Please re-enter your password')
|
|
446
|
-
end
|
|
447
|
-
```
|
|
448
|
-
|
|
449
|
-
#### validate_numericality_of
|
|
450
|
-
|
|
451
|
-
The `validate_numericality_of` matcher tests usage of the
|
|
452
|
-
`validates_numericality_of` validation.
|
|
453
|
-
|
|
454
|
-
```ruby
|
|
455
|
-
class Person < ActiveRecord::Base
|
|
456
|
-
validates_numericality_of :gpa
|
|
457
|
-
validates_numericality_of :age, only_integer: true
|
|
458
|
-
validates_numericality_of :legal_age, greater_than: 21
|
|
459
|
-
validates_numericality_of :height, greater_than_or_equal_to: 55
|
|
460
|
-
validates_numericality_of :weight, equal_to: 150
|
|
461
|
-
validates_numericality_of :number_of_cars, less_than: 2
|
|
462
|
-
validates_numericality_of :birth_year, less_than_or_equal_to: 1987
|
|
463
|
-
validates_numericality_of :birth_day, odd: true
|
|
464
|
-
validates_numericality_of :birth_month, even: true
|
|
465
|
-
validates_numericality_of :rank, less_than_or_equal_to: 10, allow_nil: true
|
|
466
|
-
|
|
467
|
-
validates_numericality_of :number_of_dependents,
|
|
468
|
-
message: 'Number of dependents must be a number'
|
|
469
|
-
end
|
|
470
|
-
|
|
471
|
-
# RSpec
|
|
472
|
-
describe Person do
|
|
473
|
-
it { should validate_numericality_of(:gpa) }
|
|
474
|
-
it { should validate_numericality_of(:age).only_integer }
|
|
475
|
-
it { should validate_numericality_of(:legal_age).is_greater_than(21) }
|
|
476
|
-
it { should validate_numericality_of(:height).is_greater_than_or_equal_to(55) }
|
|
477
|
-
it { should validate_numericality_of(:weight).is_equal_to(150) }
|
|
478
|
-
it { should validate_numericality_of(:number_of_cars).is_less_than(2) }
|
|
479
|
-
it { should validate_numericality_of(:birth_year).is_less_than_or_equal_to(1987) }
|
|
480
|
-
it { should validate_numericality_of(:birth_day).odd }
|
|
481
|
-
it { should validate_numericality_of(:birth_month).even }
|
|
482
|
-
|
|
483
|
-
it do
|
|
484
|
-
should validate_numericality_of(:number_of_dependents).
|
|
485
|
-
with_message('Number of dependents must be a number')
|
|
486
|
-
end
|
|
487
|
-
end
|
|
488
|
-
|
|
489
|
-
# Test::Unit
|
|
490
|
-
class PersonTest < ActiveSupport::TestCase
|
|
491
|
-
should validate_numericality_of(:gpa)
|
|
492
|
-
should validate_numericality_of(:age).only_integer
|
|
493
|
-
should validate_numericality_of(:legal_age).is_greater_than(21)
|
|
494
|
-
should validate_numericality_of(:height).is_greater_than_or_equal_to(55)
|
|
495
|
-
should validate_numericality_of(:weight).is_equal_to(150)
|
|
496
|
-
should validate_numericality_of(:number_of_cars).is_less_than(2)
|
|
497
|
-
should validate_numericality_of(:birth_year).is_less_than_or_equal_to(1987)
|
|
498
|
-
should validate_numericality_of(:birth_day).odd
|
|
499
|
-
should validate_numericality_of(:birth_month).even
|
|
500
|
-
|
|
501
|
-
should validate_numericality_of(:number_of_dependents).
|
|
502
|
-
with_message('Number of dependents must be a number')
|
|
503
|
-
end
|
|
504
|
-
```
|
|
505
|
-
|
|
506
|
-
#### validate_presence_of
|
|
507
|
-
|
|
508
|
-
The `validate_presence_of` matcher tests usage of the `validates_presence_of`
|
|
509
|
-
matcher.
|
|
510
|
-
|
|
511
|
-
```ruby
|
|
512
|
-
class Robot < ActiveRecord::Base
|
|
513
|
-
validates_presence_of :arms
|
|
514
|
-
validates_presence_of :legs, message: 'Robot has no legs'
|
|
515
|
-
end
|
|
516
|
-
|
|
517
|
-
# RSpec
|
|
518
|
-
describe Robot do
|
|
519
|
-
it { should validate_presence_of(:arms) }
|
|
520
|
-
it { should validate_presence_of(:legs).with_message('Robot has no legs') }
|
|
521
|
-
end
|
|
522
|
-
|
|
523
|
-
# Test::Unit
|
|
524
|
-
class RobotTest < ActiveSupport::TestCase
|
|
525
|
-
should validate_presence_of(:arms)
|
|
526
|
-
should validate_presence_of(:legs).with_message('Robot has no legs')
|
|
527
|
-
end
|
|
528
|
-
```
|
|
529
|
-
|
|
530
|
-
#### validate_uniqueness_of
|
|
531
|
-
|
|
532
|
-
The `validate_uniqueness_of` matcher tests usage of the
|
|
533
|
-
`validates_uniqueness_of` validation.
|
|
534
|
-
|
|
535
|
-
```ruby
|
|
536
|
-
class Post < ActiveRecord::Base
|
|
537
|
-
validates_uniqueness_of :permalink
|
|
538
|
-
validates_uniqueness_of :slug, scope: :user_id
|
|
539
|
-
validates_uniqueness_of :key, case_insensitive: true
|
|
540
|
-
validates_uniqueness_of :author_id, allow_nil: true
|
|
541
|
-
|
|
542
|
-
validates_uniqueness_of :title, message: 'Please choose another title'
|
|
543
|
-
end
|
|
544
|
-
|
|
545
|
-
# RSpec
|
|
546
|
-
describe Post do
|
|
547
|
-
it { should validate_uniqueness_of(:permalink) }
|
|
548
|
-
it { should validate_uniqueness_of(:slug).scoped_to(:user_id) }
|
|
549
|
-
it { should validate_uniqueness_of(:key).case_insensitive }
|
|
550
|
-
it { should validate_uniqueness_of(:author_id).allow_nil }
|
|
551
|
-
|
|
552
|
-
it do
|
|
553
|
-
should validate_uniqueness_of(:title).
|
|
554
|
-
with_message('Please choose another title')
|
|
555
|
-
end
|
|
556
|
-
end
|
|
557
|
-
|
|
558
|
-
# Test::Unit
|
|
559
|
-
class PostTest < ActiveSupport::TestCase
|
|
560
|
-
should validate_uniqueness_of(:permalink)
|
|
561
|
-
should validate_uniqueness_of(:slug).scoped_to(:user_id)
|
|
562
|
-
should validate_uniqueness_of(:key).case_insensitive
|
|
563
|
-
should validate_uniqueness_of(:author_id).allow_nil
|
|
564
|
-
|
|
565
|
-
should validate_uniqueness_of(:title).
|
|
566
|
-
with_message('Please choose another title')
|
|
567
|
-
end
|
|
568
|
-
```
|
|
569
|
-
|
|
570
|
-
**PLEASE NOTE:** This matcher works differently from other validation matchers.
|
|
571
|
-
Since the very concept of uniqueness depends on checking against a pre-existing
|
|
572
|
-
record in the database, this matcher will first use the model you're testing to
|
|
573
|
-
query for such a record, and if it can't find an existing one, it will create
|
|
574
|
-
one itself. Sometimes this step fails, especially if you have other validations
|
|
575
|
-
on the attribute you're testing (or, if you have database-level restrictions on
|
|
576
|
-
any attributes). In this case, the solution is to create a record before you use
|
|
577
|
-
`validate_uniqueness_of`.
|
|
578
|
-
|
|
579
|
-
For example, if you have this model:
|
|
580
|
-
|
|
581
|
-
```ruby
|
|
582
|
-
class Post < ActiveRecord::Base
|
|
583
|
-
validates_presence_of :permalink
|
|
584
|
-
validates_uniqueness_of :permalink
|
|
585
|
-
end
|
|
586
|
-
```
|
|
587
|
-
|
|
588
|
-
then you will need to test it like this:
|
|
589
|
-
|
|
590
|
-
```ruby
|
|
591
|
-
describe Post do
|
|
592
|
-
it do
|
|
593
|
-
Post.create!(title: 'This is the title')
|
|
594
|
-
should validate_uniqueness_of(:permalink)
|
|
595
|
-
end
|
|
596
|
-
end
|
|
597
|
-
```
|
|
598
|
-
|
|
599
|
-
### ActiveRecord Matchers
|
|
600
|
-
|
|
601
|
-
*Jump to: [accept_nested_attributes_for](#accept_nested_attributes_for), [belong_to](#belong_to), [have_many](#have_many), [have_one](#have_one), [have_and_belong_to_many](#have_and_belong_to_many), [have_db_column](#have_db_column), [have_db_index](#have_db_index), [have_readonly_attribute](#have_readonly_attribute), [serialize](#serialize)*
|
|
602
|
-
|
|
603
|
-
#### accept_nested_attributes_for
|
|
604
|
-
|
|
605
|
-
The `accept_nested_attributes_for` matcher tests usage of the
|
|
606
|
-
`accepts_nested_attributes_for` macro.
|
|
607
|
-
|
|
608
|
-
```ruby
|
|
609
|
-
class Car < ActiveRecord::Base
|
|
610
|
-
accept_nested_attributes_for :doors
|
|
611
|
-
accept_nested_attributes_for :mirrors, allow_destroy: true
|
|
612
|
-
accept_nested_attributes_for :windows, limit: 3
|
|
613
|
-
accept_nested_attributes_for :engine, update_only: true
|
|
614
|
-
end
|
|
615
|
-
|
|
616
|
-
# RSpec
|
|
617
|
-
describe Car do
|
|
618
|
-
it { should accept_nested_attributes_for(:doors) }
|
|
619
|
-
it { should accept_nested_attributes_for(:mirrors).allow_destroy(true) }
|
|
620
|
-
it { should accept_nested_attributes_for(:windows).limit(3) }
|
|
621
|
-
it { should accept_nested_attributes_for(:engine).update_only(true) }
|
|
622
|
-
end
|
|
623
|
-
|
|
624
|
-
# Test::Unit (using Shoulda)
|
|
625
|
-
class CarTest < ActiveSupport::TestCase
|
|
626
|
-
should accept_nested_attributes_for(:doors)
|
|
627
|
-
should accept_nested_attributes_for(:mirrors).allow_destroy(true)
|
|
628
|
-
should accept_nested_attributes_for(:windows).limit(3)
|
|
629
|
-
should accept_nested_attributes_for(:engine).update_only(true)
|
|
630
|
-
end
|
|
631
|
-
```
|
|
632
|
-
|
|
633
|
-
#### belong_to
|
|
634
|
-
|
|
635
|
-
The `belong_to` matcher tests your `belongs_to` associations.
|
|
636
|
-
|
|
637
|
-
```ruby
|
|
638
|
-
class Person < ActiveRecord::Base
|
|
639
|
-
belongs_to :organization
|
|
640
|
-
belongs_to :family, -> { where(everyone_is_perfect: false) }
|
|
641
|
-
belongs_to :previous_company, -> { order('hired_on desc') }
|
|
642
|
-
belongs_to :ancient_city, class_name: 'City'
|
|
643
|
-
belongs_to :great_country, foreign_key: 'country_id'
|
|
644
|
-
belongs_to :mental_institution, touch: true
|
|
645
|
-
belongs_to :world, dependent: :destroy
|
|
646
|
-
end
|
|
647
|
-
|
|
648
|
-
# RSpec
|
|
649
|
-
describe Person do
|
|
650
|
-
it { should belong_to(:organization) }
|
|
651
|
-
it { should belong_to(:family).conditions(everyone_is_perfect: false) }
|
|
652
|
-
it { should belong_to(:previous_company).order('hired_on desc') }
|
|
653
|
-
it { should belong_to(:ancient_city).class_name('City') }
|
|
654
|
-
it { should belong_to(:great_country).with_foreign_key('country_id') }
|
|
655
|
-
it { should belong_to(:mental_institution).touch(true) }
|
|
656
|
-
it { should belong_to(:world).dependent(:destroy) }
|
|
657
|
-
end
|
|
658
|
-
|
|
659
|
-
# Test::Unit
|
|
660
|
-
class PersonTest < ActiveSupport::TestCase
|
|
661
|
-
should belong_to(:organization)
|
|
662
|
-
should belong_to(:family).conditions(everyone_is_perfect: false)
|
|
663
|
-
should belong_to(:previous_company).order('hired_on desc')
|
|
664
|
-
should belong_to(:ancient_city).class_name('City')
|
|
665
|
-
should belong_to(:great_country).with_foreign_key('country_id')
|
|
666
|
-
should belong_to(:mental_institution).touch(true)
|
|
667
|
-
should belong_to(:world).dependent(:destroy)
|
|
668
|
-
end
|
|
669
|
-
```
|
|
670
|
-
|
|
671
|
-
#### have_many
|
|
672
|
-
|
|
673
|
-
The `have_many` matcher tests your `has_many` and `has_many :through` associations.
|
|
674
|
-
|
|
675
|
-
```ruby
|
|
676
|
-
class Person < ActiveRecord::Base
|
|
677
|
-
has_many :friends
|
|
678
|
-
has_many :acquaintances, through: :friends
|
|
679
|
-
has_many :job_offers, through: :friends, source: :opportunities
|
|
680
|
-
has_many :coins, -> { where(condition: 'mint') }
|
|
681
|
-
has_many :shirts, -> { order('color') }
|
|
682
|
-
has_many :hopes, class_name: 'Dream'
|
|
683
|
-
has_many :worries, foreign_key: 'worrier_id'
|
|
684
|
-
has_many :distractions, counter_cache: true
|
|
685
|
-
has_many :ideas, validate: false
|
|
686
|
-
has_many :topics_of_interest, touch: true
|
|
687
|
-
has_many :secret_documents, dependent: :destroy
|
|
688
|
-
end
|
|
689
|
-
|
|
690
|
-
# RSpec
|
|
691
|
-
describe Person do
|
|
692
|
-
it { should have_many(:friends) }
|
|
693
|
-
it { should have_many(:acquaintances).through(:friends) }
|
|
694
|
-
it { should have_many(:job_offers).through(:friends).source(:opportunities) }
|
|
695
|
-
it { should have_many(:coins).conditions(condition: 'mint') }
|
|
696
|
-
it { should have_many(:shirts).order('color') }
|
|
697
|
-
it { should have_many(:hopes).class_name('Dream') }
|
|
698
|
-
it { should have_many(:worries).with_foreign_key('worrier_id') }
|
|
699
|
-
it { should have_many(:ideas).validate(false) }
|
|
700
|
-
it { should have_many(:distractions).counter_cache(true) }
|
|
701
|
-
it { should have_many(:topics_of_interest).touch(true) }
|
|
702
|
-
it { should have_many(:secret_documents).dependent(:destroy) }
|
|
703
|
-
end
|
|
704
|
-
|
|
705
|
-
# Test::Unit
|
|
706
|
-
class PersonTest < ActiveSupport::TestCase
|
|
707
|
-
should have_many(:friends)
|
|
708
|
-
should have_many(:acquaintances).through(:friends)
|
|
709
|
-
should have_many(:job_offers).through(:friends).source(:opportunities)
|
|
710
|
-
should have_many(:coins).conditions(condition: 'mint')
|
|
711
|
-
should have_many(:shirts).order('color')
|
|
712
|
-
should have_many(:hopes).class_name('Dream')
|
|
713
|
-
should have_many(:worries).with_foreign_key('worrier_id')
|
|
714
|
-
should have_many(:ideas).validate(false)
|
|
715
|
-
should have_many(:distractions).counter_cache(true)
|
|
716
|
-
should have_many(:topics_of_interest).touch(true)
|
|
717
|
-
should have_many(:secret_documents).dependent(:destroy)
|
|
718
|
-
end
|
|
719
|
-
```
|
|
720
|
-
|
|
721
|
-
#### have_one
|
|
722
|
-
|
|
723
|
-
The `have_one` matcher tests your `has_one` and `has_one :through` associations.
|
|
724
|
-
|
|
725
|
-
```ruby
|
|
726
|
-
class Person < ActiveRecord::Base
|
|
727
|
-
has_one :partner
|
|
728
|
-
has_one :life, through: :partner
|
|
729
|
-
has_one :car, through: :partner, source: :vehicle
|
|
730
|
-
has_one :pet, -> { where('weight < 80') }
|
|
731
|
-
has_one :focus, -> { order('priority desc') }
|
|
732
|
-
has_one :chance, class_name: 'Opportunity'
|
|
733
|
-
has_one :job, foreign_key: 'worker_id'
|
|
734
|
-
has_one :parking_card, validate: false
|
|
735
|
-
has_one :contract, dependent: :nullify
|
|
736
|
-
end
|
|
737
|
-
|
|
738
|
-
# RSpec
|
|
739
|
-
describe Person do
|
|
740
|
-
it { should have_one(:partner) }
|
|
741
|
-
it { should have_one(:life).through(:partner) }
|
|
742
|
-
it { should have_one(:car).through(:partner).source(:vehicle) }
|
|
743
|
-
it { should have_one(:pet).conditions('weight < 80') }
|
|
744
|
-
it { should have_one(:focus).order('priority desc') }
|
|
745
|
-
it { should have_one(:chance).class_name('Opportunity') }
|
|
746
|
-
it { should have_one(:job).with_foreign_key('worker_id') }
|
|
747
|
-
it { should have_one(:parking_card).validate(false) }
|
|
748
|
-
it { should have_one(:contract).dependent(:nullify) }
|
|
749
|
-
end
|
|
750
|
-
|
|
751
|
-
# Test::Unit
|
|
752
|
-
class PersonTest < ActiveSupport::TestCase
|
|
753
|
-
should have_one(:partner)
|
|
754
|
-
should have_one(:life).through(:partner)
|
|
755
|
-
should have_one(:car).through(:partner).source(:vehicle)
|
|
756
|
-
should have_one(:pet).conditions('weight < 80')
|
|
757
|
-
should have_one(:focus).order('priority desc')
|
|
758
|
-
should have_one(:chance).class_name('Opportunity')
|
|
759
|
-
should have_one(:job).with_foreign_key('worker_id')
|
|
760
|
-
should have_one(:parking_card).validate(false)
|
|
761
|
-
should have_one(:contract).dependent(:nullify)
|
|
762
|
-
end
|
|
763
|
-
```
|
|
764
|
-
|
|
765
|
-
#### have_and_belong_to_many
|
|
766
|
-
|
|
767
|
-
The `have_and_belong_to_many` matcher tests your `has_and_belongs_to_many`
|
|
768
|
-
associations.
|
|
769
|
-
|
|
770
|
-
```ruby
|
|
771
|
-
class Person < ActiveRecord::Base
|
|
772
|
-
has_and_belongs_to_many :awards
|
|
773
|
-
has_and_belongs_to_many :issues, -> { where(difficulty: 'hard') }
|
|
774
|
-
has_and_belongs_to_many :projects, -> { order('time_spent') }
|
|
775
|
-
has_and_belongs_to_many :places_visited, class_name: 'City'
|
|
776
|
-
has_and_belongs_to_many :interviews, validate: false
|
|
777
|
-
end
|
|
778
|
-
|
|
779
|
-
# RSpec
|
|
780
|
-
describe Person do
|
|
781
|
-
it { should have_and_belong_to_many(:awards) }
|
|
782
|
-
it { should have_and_belong_to_many(:issues).conditions(difficulty: 'hard') }
|
|
783
|
-
it { should have_and_belong_to_many(:projects).order('time_spent') }
|
|
784
|
-
it { should have_and_belong_to_many(:places_visited).class_name('City') }
|
|
785
|
-
it { should have_and_belong_to_many(:interviews).validate(false) }
|
|
786
|
-
end
|
|
787
|
-
|
|
788
|
-
# Test::Unit
|
|
789
|
-
class PersonTest < ActiveSupport::TestCase
|
|
790
|
-
should have_and_belong_to_many(:awards)
|
|
791
|
-
should have_and_belong_to_many(:issues).conditions(difficulty: 'hard')
|
|
792
|
-
should have_and_belong_to_many(:projects).order('time_spent')
|
|
793
|
-
should have_and_belong_to_many(:places_visited).class_name('City')
|
|
794
|
-
should have_and_belong_to_many(:interviews).validate(false)
|
|
795
|
-
end
|
|
796
|
-
```
|
|
797
|
-
|
|
798
|
-
#### have_db_column
|
|
799
|
-
|
|
800
|
-
The `have_db_column` matcher tests that the table that backs your model
|
|
801
|
-
has a specific column.
|
|
802
|
-
|
|
803
|
-
```ruby
|
|
804
|
-
class CreatePhones < ActiveRecord::Migration
|
|
805
|
-
def change
|
|
806
|
-
create_table :phones do |t|
|
|
807
|
-
t.decimal :supported_ios_version
|
|
808
|
-
t.string :model, null: false
|
|
809
|
-
t.decimal :camera_aperture, precision: 1
|
|
810
|
-
end
|
|
811
|
-
end
|
|
812
|
-
end
|
|
813
|
-
|
|
814
|
-
# RSpec
|
|
815
|
-
describe Phone do
|
|
816
|
-
it { should have_db_column(:supported_ios_version) }
|
|
817
|
-
it { should have_db_column(:model).with_options(null: false) }
|
|
818
|
-
|
|
819
|
-
it do
|
|
820
|
-
should have_db_column(:camera_aperture).
|
|
821
|
-
of_type(:decimal).
|
|
822
|
-
with_options(precision: 1)
|
|
823
|
-
end
|
|
824
|
-
end
|
|
825
|
-
|
|
826
|
-
# Test::Unit
|
|
827
|
-
class PhoneTest < ActiveSupport::TestCase
|
|
828
|
-
should have_db_column(:supported_ios_version)
|
|
829
|
-
should have_db_column(:model).with_options(null: false)
|
|
830
|
-
|
|
831
|
-
should have_db_column(:camera_aperture).
|
|
832
|
-
of_type(:decimal).
|
|
833
|
-
with_options(precision: 1)
|
|
834
|
-
end
|
|
835
|
-
```
|
|
836
|
-
|
|
837
|
-
#### have_db_index
|
|
838
|
-
|
|
839
|
-
The `have_db_index` matcher tests that the table that backs your model has a
|
|
840
|
-
index on a specific column.
|
|
841
|
-
|
|
842
|
-
```ruby
|
|
843
|
-
class CreateBlogs < ActiveRecord::Migration
|
|
844
|
-
def change
|
|
845
|
-
create_table :blogs do |t|
|
|
846
|
-
t.integer :user_id, null: false
|
|
847
|
-
t.string :name, null: false
|
|
848
|
-
end
|
|
849
|
-
|
|
850
|
-
add_index :blogs, :user_id
|
|
851
|
-
add_index :blogs, :name, unique: true
|
|
852
|
-
end
|
|
853
|
-
end
|
|
854
|
-
|
|
855
|
-
# RSpec
|
|
856
|
-
describe Blog do
|
|
857
|
-
it { should have_db_index(:user_id) }
|
|
858
|
-
it { should have_db_index(:name).unique(true) }
|
|
859
|
-
end
|
|
860
|
-
|
|
861
|
-
# Test::Unit
|
|
862
|
-
class BlogTest < ActiveSupport::TestCase
|
|
863
|
-
should have_db_index(:user_id)
|
|
864
|
-
should have_db_index(:name).unique(true)
|
|
865
|
-
end
|
|
866
|
-
```
|
|
867
|
-
|
|
868
|
-
#### have_readonly_attribute
|
|
869
|
-
|
|
870
|
-
The `have_readonly_attribute` matcher tests usage of the `attr_readonly` macro.
|
|
871
|
-
|
|
872
|
-
```ruby
|
|
873
|
-
class User < ActiveRecord::Base
|
|
874
|
-
attr_readonly :password
|
|
875
|
-
end
|
|
876
|
-
|
|
877
|
-
# RSpec
|
|
878
|
-
describe User do
|
|
879
|
-
it { should have_readonly_attribute(:password) }
|
|
880
|
-
end
|
|
881
|
-
|
|
882
|
-
# Test::Unit
|
|
883
|
-
class UserTest < ActiveSupport::TestCase
|
|
884
|
-
should have_readonly_attribute(:password)
|
|
885
|
-
end
|
|
886
|
-
```
|
|
887
|
-
|
|
888
|
-
#### serialize
|
|
889
|
-
|
|
890
|
-
The `serialize` matcher tests usage of the `serialize` macro.
|
|
891
|
-
|
|
892
|
-
```ruby
|
|
893
|
-
class ProductOptionsSerializer
|
|
894
|
-
def load(string)
|
|
895
|
-
# ...
|
|
896
|
-
end
|
|
897
|
-
|
|
898
|
-
def dump(options)
|
|
899
|
-
# ...
|
|
900
|
-
end
|
|
901
|
-
end
|
|
902
|
-
|
|
903
|
-
class Product < ActiveRecord::Base
|
|
904
|
-
serialize :customizations
|
|
905
|
-
serialize :specifications, ProductSpecsSerializer
|
|
906
|
-
serialize :options, ProductOptionsSerializer.new
|
|
907
|
-
end
|
|
908
|
-
|
|
909
|
-
# RSpec
|
|
910
|
-
describe Product do
|
|
911
|
-
it { should serialize(:customizations) }
|
|
912
|
-
it { should serialize(:specifications).as(ProductSpecsSerializer) }
|
|
913
|
-
it { should serialize(:options).as_instance_of(ProductOptionsSerializer) }
|
|
914
|
-
end
|
|
915
|
-
|
|
916
|
-
# Test::Unit
|
|
917
|
-
class ProductTest < ActiveSupport::TestCase
|
|
918
|
-
should serialize(:customizations)
|
|
919
|
-
should serialize(:specifications).as(ProductSpecsSerializer)
|
|
920
|
-
should serialize(:options).as_instance_of(ProductOptionsSerializer)
|
|
921
|
-
end
|
|
922
|
-
```
|
|
923
|
-
|
|
924
|
-
### ActionController Matchers
|
|
925
|
-
|
|
926
|
-
*Jump to: [filter_param](#filter_param), [permit](#permit), [redirect_to](#redirect_to), [render_template](#render_template), [render_with_layout](#render_with_layout), [rescue_from](#rescue_from), [respond_with](#respond_with), [route](#route), [set_session](#set_session), [set_the_flash](#set_the_flash), [use_after_filter / use_after_action](#use_after_filter--use_after_action), [use_around_filter / use_around_action](#use_around_filter--use_around_action), [use_before_filter / use_around_action](#use_before_filter--use_before_action)*
|
|
927
|
-
|
|
928
|
-
#### filter_param
|
|
929
|
-
|
|
930
|
-
The `filter_param` matcher tests parameter filtering configuration.
|
|
931
|
-
|
|
932
|
-
```ruby
|
|
933
|
-
class MyApplication < Rails::Application
|
|
934
|
-
config.filter_parameters << :secret_key
|
|
935
|
-
end
|
|
936
|
-
|
|
937
|
-
# RSpec
|
|
938
|
-
describe ApplicationController do
|
|
939
|
-
it { should filter_param(:secret_key) }
|
|
940
|
-
end
|
|
941
|
-
|
|
942
|
-
# Test::Unit
|
|
943
|
-
class ApplicationControllerTest < ActionController::TestCase
|
|
944
|
-
should filter_param(:secret_key)
|
|
945
|
-
end
|
|
946
|
-
```
|
|
947
|
-
|
|
948
|
-
#### permit
|
|
949
|
-
|
|
950
|
-
The `permit` matcher tests that only whitelisted parameters are permitted.
|
|
951
|
-
|
|
952
|
-
```ruby
|
|
953
|
-
class UserController < ActionController::Base
|
|
954
|
-
def create
|
|
955
|
-
User.create(user_params)
|
|
956
|
-
end
|
|
957
|
-
|
|
958
|
-
private
|
|
959
|
-
|
|
960
|
-
def user_params
|
|
961
|
-
params.require(:user).permit(:email)
|
|
962
|
-
end
|
|
963
|
-
end
|
|
964
|
-
|
|
965
|
-
# RSpec
|
|
966
|
-
describe UserController do
|
|
967
|
-
it { should permit(:email).for(:create) }
|
|
968
|
-
end
|
|
969
|
-
|
|
970
|
-
# Test::Unit
|
|
971
|
-
class UserControllerTest < ActionController::TestCase
|
|
972
|
-
should permit(:email).for(:create)
|
|
973
|
-
end
|
|
974
|
-
```
|
|
975
|
-
|
|
976
|
-
#### redirect_to
|
|
977
|
-
|
|
978
|
-
The `redirect_to` matcher tests that an action redirects to a certain location.
|
|
979
|
-
In a test suite using RSpec, it is very similar to rspec-rails's `redirect_to`
|
|
980
|
-
matcher. In a test suite using Test::Unit / Shoulda, it provides a more
|
|
981
|
-
expressive syntax over `assert_redirected_to`.
|
|
982
|
-
|
|
983
|
-
```ruby
|
|
984
|
-
class PostsController < ApplicationController
|
|
985
|
-
def show
|
|
986
|
-
redirect_to :index
|
|
987
|
-
end
|
|
988
|
-
end
|
|
989
|
-
|
|
990
|
-
# RSpec
|
|
991
|
-
describe PostsController do
|
|
992
|
-
describe 'GET #list' do
|
|
993
|
-
before { get :list }
|
|
994
|
-
|
|
995
|
-
it { should redirect_to(posts_path) }
|
|
996
|
-
end
|
|
997
|
-
end
|
|
998
|
-
|
|
999
|
-
# Test::Unit
|
|
1000
|
-
class PostsControllerTest < ActionController::TestCase
|
|
1001
|
-
context 'GET #list' do
|
|
1002
|
-
setup { get :list }
|
|
1003
|
-
|
|
1004
|
-
should redirect_to { posts_path }
|
|
1005
|
-
end
|
|
1006
|
-
end
|
|
1007
|
-
```
|
|
1008
|
-
|
|
1009
|
-
#### render_template
|
|
1010
|
-
|
|
1011
|
-
The `render_template` matcher tests that an action renders a template.
|
|
1012
|
-
In RSpec, it is very similar to rspec-rails's `render_template` matcher.
|
|
1013
|
-
In Test::Unit, it provides a more expressive syntax over `assert_template`.
|
|
1014
|
-
|
|
1015
|
-
```ruby
|
|
1016
|
-
class PostsController < ApplicationController
|
|
1017
|
-
def show
|
|
1018
|
-
end
|
|
1019
|
-
end
|
|
1020
|
-
|
|
1021
|
-
# RSpec
|
|
1022
|
-
describe PostsController do
|
|
1023
|
-
describe 'GET #show' do
|
|
1024
|
-
before { get :show }
|
|
1025
|
-
|
|
1026
|
-
it { should render_template('show') }
|
|
1027
|
-
end
|
|
1028
|
-
end
|
|
1029
|
-
|
|
1030
|
-
# Test::Unit
|
|
1031
|
-
class PostsControllerTest < ActionController::TestCase
|
|
1032
|
-
context 'GET #show' do
|
|
1033
|
-
setup { get :show }
|
|
1034
|
-
|
|
1035
|
-
should render_template('show')
|
|
1036
|
-
end
|
|
1037
|
-
end
|
|
1038
|
-
```
|
|
1039
|
-
|
|
1040
|
-
#### render_with_layout
|
|
1041
|
-
|
|
1042
|
-
The `render_with_layout` matcher tests that an action is rendered with a certain
|
|
1043
|
-
layout.
|
|
1044
|
-
|
|
1045
|
-
```ruby
|
|
1046
|
-
class PostsController < ApplicationController
|
|
1047
|
-
def show
|
|
1048
|
-
render layout: 'posts'
|
|
1049
|
-
end
|
|
1050
|
-
end
|
|
1051
|
-
|
|
1052
|
-
# RSpec
|
|
1053
|
-
describe PostsController do
|
|
1054
|
-
describe 'GET #show' do
|
|
1055
|
-
before { get :show }
|
|
1056
|
-
|
|
1057
|
-
it { should render_with_layout('posts') }
|
|
1058
|
-
end
|
|
1059
|
-
end
|
|
1060
|
-
|
|
1061
|
-
# Test::Unit
|
|
1062
|
-
class PostsControllerTest < ActionController::TestCase
|
|
1063
|
-
context 'GET #show' do
|
|
1064
|
-
setup { get :show }
|
|
1065
|
-
|
|
1066
|
-
should render_with_layout('posts')
|
|
1067
|
-
end
|
|
1068
|
-
end
|
|
1069
|
-
```
|
|
1070
|
-
|
|
1071
|
-
#### rescue_from
|
|
1072
|
-
|
|
1073
|
-
The `rescue_from` matcher tests usage of the `rescue_from` macro.
|
|
1074
|
-
|
|
1075
|
-
```ruby
|
|
1076
|
-
class ApplicationController < ActionController::Base
|
|
1077
|
-
rescue_from ActiveRecord::RecordNotFound, with: :handle_not_found
|
|
1078
|
-
|
|
1079
|
-
private
|
|
1080
|
-
|
|
1081
|
-
def handle_not_found
|
|
1082
|
-
# ...
|
|
1083
|
-
end
|
|
1084
|
-
end
|
|
1085
|
-
|
|
1086
|
-
# RSpec
|
|
1087
|
-
describe ApplicationController do
|
|
1088
|
-
it do
|
|
1089
|
-
should rescue_from(ActiveRecord::RecordNotFound).
|
|
1090
|
-
with(:handle_not_found)
|
|
1091
|
-
end
|
|
1092
|
-
end
|
|
1093
|
-
|
|
1094
|
-
# Test::Unit
|
|
1095
|
-
class ApplicationControllerTest < ActionController::TestCase
|
|
1096
|
-
should rescue_from(ActiveRecord::RecordNotFound).
|
|
1097
|
-
with(:handle_not_found)
|
|
1098
|
-
end
|
|
1099
|
-
```
|
|
1100
|
-
|
|
1101
|
-
#### respond_with
|
|
1102
|
-
|
|
1103
|
-
The `respond_with` matcher tests that an action responds with a certain status
|
|
1104
|
-
code.
|
|
1105
|
-
|
|
1106
|
-
```ruby
|
|
1107
|
-
class PostsController < ApplicationController
|
|
1108
|
-
def index
|
|
1109
|
-
render status: 403
|
|
1110
|
-
end
|
|
1111
|
-
|
|
1112
|
-
def show
|
|
1113
|
-
render status: :locked
|
|
1114
|
-
end
|
|
1115
|
-
|
|
1116
|
-
def destroy
|
|
1117
|
-
render status: 508
|
|
1118
|
-
end
|
|
1119
|
-
end
|
|
1120
|
-
|
|
1121
|
-
# RSpec
|
|
1122
|
-
describe PostsController do
|
|
1123
|
-
describe 'GET #index' do
|
|
1124
|
-
before { get :index }
|
|
1125
|
-
|
|
1126
|
-
it { should respond_with(403) }
|
|
1127
|
-
end
|
|
1128
|
-
|
|
1129
|
-
describe 'GET #show' do
|
|
1130
|
-
before { get :show }
|
|
1131
|
-
|
|
1132
|
-
it { should respond_with(:locked) }
|
|
1133
|
-
end
|
|
1134
|
-
|
|
1135
|
-
describe 'DELETE #destroy' do
|
|
1136
|
-
before { delete :destroy }
|
|
1137
|
-
|
|
1138
|
-
it { should respond_with(500..600) }
|
|
1139
|
-
end
|
|
1140
|
-
end
|
|
1141
|
-
|
|
1142
|
-
# Test::Unit
|
|
1143
|
-
class PostsControllerTest < ActionController::TestCase
|
|
1144
|
-
context 'GET #index' do
|
|
1145
|
-
setup { get :index }
|
|
1146
|
-
|
|
1147
|
-
should respond_with(403)
|
|
1148
|
-
end
|
|
1149
|
-
|
|
1150
|
-
context 'GET #show' do
|
|
1151
|
-
setup { get :show }
|
|
1152
|
-
|
|
1153
|
-
should respond_with(:locked)
|
|
1154
|
-
end
|
|
1155
|
-
|
|
1156
|
-
context 'DELETE #destroy' do
|
|
1157
|
-
setup { delete :destroy }
|
|
1158
|
-
|
|
1159
|
-
should respond_with(500..600)
|
|
1160
|
-
end
|
|
1161
|
-
end
|
|
1162
|
-
```
|
|
1163
|
-
|
|
1164
|
-
#### route
|
|
1165
|
-
|
|
1166
|
-
The `route` matcher tests that a route resolves to a controller, action, and
|
|
1167
|
-
params; and that the controller, action, and params generates the same route. For
|
|
1168
|
-
an RSpec suite, this is like using a combination of `route_to` and
|
|
1169
|
-
`be_routable`. For a Test::Unit suite, it provides a more expressive syntax
|
|
1170
|
-
over `assert_routing`.
|
|
1171
|
-
|
|
1172
|
-
```ruby
|
|
1173
|
-
My::Application.routes.draw do
|
|
1174
|
-
get '/posts', controller: 'posts', action: 'index'
|
|
1175
|
-
get '/posts/:id' => 'posts#show'
|
|
1176
|
-
end
|
|
1177
|
-
|
|
1178
|
-
# RSpec
|
|
1179
|
-
describe 'Routing' do
|
|
1180
|
-
it { should route(:get, '/posts').to(controller: 'posts', action: 'index') }
|
|
1181
|
-
it { should route(:get, '/posts/1').to('posts#show', id: 1) }
|
|
1182
|
-
end
|
|
1183
|
-
|
|
1184
|
-
# Test::Unit
|
|
1185
|
-
class RoutesTest < ActionController::IntegrationTest
|
|
1186
|
-
should route(:get, '/posts').to(controller: 'posts', action: 'index')
|
|
1187
|
-
should route(:get, '/posts/1').to('posts#show', id: 1)
|
|
1188
|
-
end
|
|
1189
|
-
```
|
|
1190
|
-
|
|
1191
|
-
#### set_session
|
|
1192
|
-
|
|
1193
|
-
The `set_session` matcher asserts that a key in the `session` hash has been set
|
|
1194
|
-
to a certain value.
|
|
1195
|
-
|
|
1196
|
-
```ruby
|
|
1197
|
-
class PostsController < ApplicationController
|
|
1198
|
-
def show
|
|
1199
|
-
session[:foo] = 'bar'
|
|
1200
|
-
end
|
|
1201
|
-
end
|
|
1202
|
-
|
|
1203
|
-
# RSpec
|
|
1204
|
-
describe PostsController do
|
|
1205
|
-
describe 'GET #show' do
|
|
1206
|
-
before { get :show }
|
|
1207
|
-
|
|
1208
|
-
it { should set_session(:foo).to('bar') }
|
|
1209
|
-
it { should_not set_session(:baz) }
|
|
1210
|
-
end
|
|
1211
|
-
end
|
|
1212
|
-
|
|
1213
|
-
# Test::Unit
|
|
1214
|
-
class PostsControllerTest < ActionController::TestCase
|
|
1215
|
-
context 'GET #show' do
|
|
1216
|
-
setup { get :show }
|
|
1217
|
-
|
|
1218
|
-
should set_session(:foo).to('bar')
|
|
1219
|
-
should_not set_session(:baz)
|
|
1220
|
-
end
|
|
1221
|
-
end
|
|
1222
|
-
```
|
|
1223
|
-
|
|
1224
|
-
#### set_the_flash
|
|
1225
|
-
|
|
1226
|
-
The `set_the_flash` matcher asserts that a key in the `flash` hash is set to a
|
|
1227
|
-
certain value.
|
|
1228
|
-
|
|
1229
|
-
```ruby
|
|
1230
|
-
class PostsController < ApplicationController
|
|
1231
|
-
def index
|
|
1232
|
-
flash[:foo] = 'A candy bar'
|
|
1233
|
-
end
|
|
1234
|
-
|
|
1235
|
-
def show
|
|
1236
|
-
flash.now[:foo] = 'bar'
|
|
1237
|
-
end
|
|
1238
|
-
|
|
1239
|
-
def destroy
|
|
1240
|
-
end
|
|
1241
|
-
end
|
|
1242
|
-
|
|
1243
|
-
# RSpec
|
|
1244
|
-
describe PostsController do
|
|
1245
|
-
describe 'GET #index' do
|
|
1246
|
-
before { get :index }
|
|
1247
|
-
|
|
1248
|
-
it { should set_the_flash.to('bar') }
|
|
1249
|
-
it { should set_the_flash.to(/bar/) }
|
|
1250
|
-
it { should set_the_flash[:foo].to('bar') }
|
|
1251
|
-
it { should_not set_the_flash[:baz] }
|
|
1252
|
-
end
|
|
1253
|
-
|
|
1254
|
-
describe 'GET #show' do
|
|
1255
|
-
before { get :show }
|
|
1256
|
-
|
|
1257
|
-
it { should set_the_flash.now }
|
|
1258
|
-
it { should set_the_flash[:foo].now }
|
|
1259
|
-
it { should set_the_flash[:foo].to('bar').now }
|
|
1260
|
-
end
|
|
1261
|
-
|
|
1262
|
-
describe 'DELETE #destroy' do
|
|
1263
|
-
before { delete :destroy }
|
|
1264
|
-
|
|
1265
|
-
it { should_not set_the_flash }
|
|
1266
|
-
end
|
|
1267
|
-
end
|
|
1268
|
-
|
|
1269
|
-
# Test::Unit
|
|
1270
|
-
class PostsControllerTest < ActionController::TestCase
|
|
1271
|
-
context 'GET #index' do
|
|
1272
|
-
setup { get :index }
|
|
1273
|
-
|
|
1274
|
-
should set_the_flash.to('bar')
|
|
1275
|
-
should set_the_flash.to(/bar/)
|
|
1276
|
-
should set_the_flash[:foo].to('bar')
|
|
1277
|
-
should_not set_the_flash[:baz]
|
|
1278
|
-
end
|
|
1279
|
-
|
|
1280
|
-
context 'GET #show' do
|
|
1281
|
-
setup { get :show }
|
|
1282
|
-
|
|
1283
|
-
should set_the_flash.now
|
|
1284
|
-
should set_the_flash[:foo].now
|
|
1285
|
-
should set_the_flash[:foo].to('bar').now
|
|
1286
|
-
end
|
|
1287
|
-
|
|
1288
|
-
context 'DELETE #destroy' do
|
|
1289
|
-
setup { delete :destroy }
|
|
1290
|
-
|
|
1291
|
-
should_not set_the_flash
|
|
1292
|
-
end
|
|
1293
|
-
end
|
|
1294
|
-
```
|
|
1295
|
-
|
|
1296
|
-
#### use_after_filter / use_after_action
|
|
139
|
+
## Generating documentation
|
|
1297
140
|
|
|
1298
|
-
|
|
1299
|
-
|
|
141
|
+
YARD is used to generate documentation, which can be viewed [online][rubydocs].
|
|
142
|
+
You can preview changes you make to the documentation locally by running
|
|
1300
143
|
|
|
1301
|
-
|
|
1302
|
-
class UserController < ActionController::Base
|
|
1303
|
-
after_filter :log_activity
|
|
1304
|
-
end
|
|
144
|
+
yard doc
|
|
1305
145
|
|
|
1306
|
-
|
|
1307
|
-
describe UserController do
|
|
1308
|
-
it { should use_after_filter(:log_activity) }
|
|
1309
|
-
end
|
|
1310
|
-
|
|
1311
|
-
# Test::Unit
|
|
1312
|
-
class UserControllerTest < ActionController::TestCase
|
|
1313
|
-
should use_after_filter(:log_activity)
|
|
1314
|
-
end
|
|
1315
|
-
```
|
|
146
|
+
from this directory. Then, open `doc/index.html` in your browser.
|
|
1316
147
|
|
|
1317
|
-
|
|
148
|
+
If you want to see a live preview as you work without having to run `yard` over
|
|
149
|
+
and over again, keep this command running in a separate terminal session:
|
|
1318
150
|
|
|
1319
|
-
|
|
1320
|
-
available as `use_around_action` to provide Rails 4 support.
|
|
1321
|
-
|
|
1322
|
-
```ruby
|
|
1323
|
-
class UserController < ActionController::Base
|
|
1324
|
-
around_filter :log_activity
|
|
1325
|
-
end
|
|
1326
|
-
|
|
1327
|
-
# RSpec
|
|
1328
|
-
describe UserController do
|
|
1329
|
-
it { should use_around_filter(:log_activity) }
|
|
1330
|
-
end
|
|
1331
|
-
|
|
1332
|
-
# Test::Unit
|
|
1333
|
-
class UserControllerTest < ActionController::TestCase
|
|
1334
|
-
should use_around_filter(:log_activity)
|
|
1335
|
-
end
|
|
1336
|
-
```
|
|
1337
|
-
|
|
1338
|
-
#### use_before_filter / use_before_action
|
|
1339
|
-
|
|
1340
|
-
The `use_before_filter` ensures a given `before_filter` is used. This is also
|
|
1341
|
-
available as `use_before_action` for Rails 4 support.
|
|
1342
|
-
|
|
1343
|
-
```ruby
|
|
1344
|
-
class UserController < ActionController::Base
|
|
1345
|
-
before_filter :authenticate_user!
|
|
1346
|
-
end
|
|
1347
|
-
|
|
1348
|
-
# RSpec
|
|
1349
|
-
describe UserController do
|
|
1350
|
-
it { should use_before_filter(:authenticate_user!) }
|
|
1351
|
-
end
|
|
1352
|
-
|
|
1353
|
-
# Test::Unit
|
|
1354
|
-
class UserControllerTest < ActionController::TestCase
|
|
1355
|
-
should use_before_filter(:authenticate_user!)
|
|
1356
|
-
end
|
|
1357
|
-
```
|
|
1358
|
-
|
|
1359
|
-
## Independent Matchers
|
|
1360
|
-
|
|
1361
|
-
Matchers to test non-Rails-dependent code:
|
|
1362
|
-
|
|
1363
|
-
#### delegate_method
|
|
1364
|
-
|
|
1365
|
-
```ruby
|
|
1366
|
-
class Human < ActiveRecord::Base
|
|
1367
|
-
has_one :robot
|
|
1368
|
-
delegate :work, to: :robot
|
|
1369
|
-
|
|
1370
|
-
# alternatively, if you are not using Rails
|
|
1371
|
-
def work
|
|
1372
|
-
robot.work
|
|
1373
|
-
end
|
|
1374
|
-
|
|
1375
|
-
def protect
|
|
1376
|
-
robot.protect('Sarah Connor')
|
|
1377
|
-
end
|
|
1378
|
-
|
|
1379
|
-
def speak
|
|
1380
|
-
robot.beep_boop
|
|
1381
|
-
end
|
|
1382
|
-
end
|
|
1383
|
-
|
|
1384
|
-
# RSpec
|
|
1385
|
-
describe Human do
|
|
1386
|
-
it { should delegate_method(:work).to(:robot) }
|
|
1387
|
-
it { should delegate_method(:protect).to(:robot).with_arguments('Sarah Connor') }
|
|
1388
|
-
it { should delegate_method(:beep_boop).to(:robot).as(:speak) }
|
|
1389
|
-
end
|
|
1390
|
-
|
|
1391
|
-
# Test::Unit
|
|
1392
|
-
class HumanTest < ActiveSupport::TestCase
|
|
1393
|
-
should delegate_method(:work).to(:robot)
|
|
1394
|
-
should delegate_method(:protect).to(:robot).with_arguments('Sarah Connor')
|
|
1395
|
-
should delegate_method(:beep_boop).to(:robot).as(:speak)
|
|
1396
|
-
end
|
|
1397
|
-
```
|
|
151
|
+
watchr docs.watchr
|
|
1398
152
|
|
|
1399
153
|
## Versioning
|
|
1400
154
|
|