mcmire-shoulda-matchers 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.travis.yml +32 -0
- data/.yardopts +7 -0
- data/Appraisals +45 -0
- data/CONTRIBUTING.md +41 -0
- data/Gemfile +31 -0
- data/Gemfile.lock +166 -0
- data/MIT-LICENSE +22 -0
- data/NEWS.md +299 -0
- data/README.md +163 -0
- data/Rakefile +116 -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 +300 -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 +8 -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/features/rails_integration.feature +113 -0
- data/features/step_definitions/rails_steps.rb +162 -0
- data/features/support/env.rb +5 -0
- data/gemfiles/3.0.gemfile +24 -0
- data/gemfiles/3.0.gemfile.lock +150 -0
- data/gemfiles/3.1.gemfile +27 -0
- data/gemfiles/3.1.gemfile.lock +173 -0
- data/gemfiles/3.2.gemfile +27 -0
- data/gemfiles/3.2.gemfile.lock +171 -0
- data/gemfiles/4.0.0.gemfile +28 -0
- data/gemfiles/4.0.0.gemfile.lock +172 -0
- data/gemfiles/4.0.1.gemfile +28 -0
- data/gemfiles/4.0.1.gemfile.lock +172 -0
- data/lib/shoulda-matchers.rb +1 -0
- data/lib/shoulda/matchers.rb +11 -0
- data/lib/shoulda/matchers/action_controller.rb +17 -0
- data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +64 -0
- data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +97 -0
- data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +81 -0
- data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +117 -0
- data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +114 -0
- data/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +154 -0
- data/lib/shoulda/matchers/action_controller/route_matcher.rb +116 -0
- data/lib/shoulda/matchers/action_controller/route_params.rb +48 -0
- data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +164 -0
- data/lib/shoulda/matchers/action_controller/set_the_flash_matcher.rb +296 -0
- data/lib/shoulda/matchers/active_model.rb +30 -0
- data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +167 -0
- data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +314 -0
- data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +46 -0
- data/lib/shoulda/matchers/active_model/ensure_exclusion_of_matcher.rb +160 -0
- data/lib/shoulda/matchers/active_model/ensure_inclusion_of_matcher.rb +417 -0
- data/lib/shoulda/matchers/active_model/ensure_length_of_matcher.rb +337 -0
- data/lib/shoulda/matchers/active_model/errors.rb +10 -0
- data/lib/shoulda/matchers/active_model/exception_message_finder.rb +58 -0
- data/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +92 -0
- data/lib/shoulda/matchers/active_model/helpers.rb +46 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers.rb +9 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +75 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/even_number_matcher.rb +27 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +41 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher.rb +27 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher.rb +26 -0
- data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +112 -0
- data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +77 -0
- data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +121 -0
- data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +380 -0
- data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +89 -0
- data/lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb +372 -0
- data/lib/shoulda/matchers/active_model/validation_matcher.rb +97 -0
- data/lib/shoulda/matchers/active_model/validation_message_finder.rb +69 -0
- data/lib/shoulda/matchers/active_record.rb +22 -0
- data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +204 -0
- data/lib/shoulda/matchers/active_record/association_matcher.rb +901 -0
- data/lib/shoulda/matchers/active_record/association_matchers.rb +9 -0
- data/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +41 -0
- data/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +41 -0
- data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +81 -0
- data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +65 -0
- data/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +94 -0
- data/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +41 -0
- data/lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb +41 -0
- data/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +63 -0
- data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +261 -0
- data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +149 -0
- data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +72 -0
- data/lib/shoulda/matchers/active_record/serialize_matcher.rb +181 -0
- data/lib/shoulda/matchers/assertion_error.rb +19 -0
- data/lib/shoulda/matchers/error.rb +6 -0
- data/lib/shoulda/matchers/integrations/rspec.rb +20 -0
- data/lib/shoulda/matchers/integrations/test_unit.rb +30 -0
- data/lib/shoulda/matchers/rails_shim.rb +50 -0
- data/lib/shoulda/matchers/version.rb +6 -0
- data/lib/shoulda/matchers/warn.rb +8 -0
- data/shoulda-matchers.gemspec +23 -0
- data/spec/shoulda/matchers/action_controller/filter_param_matcher_spec.rb +22 -0
- data/spec/shoulda/matchers/action_controller/redirect_to_matcher_spec.rb +42 -0
- data/spec/shoulda/matchers/action_controller/render_template_matcher_spec.rb +78 -0
- data/spec/shoulda/matchers/action_controller/render_with_layout_matcher_spec.rb +63 -0
- data/spec/shoulda/matchers/action_controller/rescue_from_matcher_spec.rb +63 -0
- data/spec/shoulda/matchers/action_controller/respond_with_matcher_spec.rb +31 -0
- data/spec/shoulda/matchers/action_controller/route_matcher_spec.rb +70 -0
- data/spec/shoulda/matchers/action_controller/route_params_spec.rb +30 -0
- data/spec/shoulda/matchers/action_controller/set_session_matcher_spec.rb +51 -0
- data/spec/shoulda/matchers/action_controller/set_the_flash_matcher_spec.rb +153 -0
- data/spec/shoulda/matchers/active_model/allow_mass_assignment_of_matcher_spec.rb +111 -0
- data/spec/shoulda/matchers/active_model/allow_value_matcher_spec.rb +170 -0
- data/spec/shoulda/matchers/active_model/disallow_value_matcher_spec.rb +81 -0
- data/spec/shoulda/matchers/active_model/ensure_exclusion_of_matcher_spec.rb +95 -0
- data/spec/shoulda/matchers/active_model/ensure_inclusion_of_matcher_spec.rb +320 -0
- data/spec/shoulda/matchers/active_model/ensure_length_of_matcher_spec.rb +166 -0
- data/spec/shoulda/matchers/active_model/exception_message_finder_spec.rb +111 -0
- data/spec/shoulda/matchers/active_model/have_secure_password_matcher_spec.rb +20 -0
- data/spec/shoulda/matchers/active_model/helpers_spec.rb +158 -0
- data/spec/shoulda/matchers/active_model/numericality_matchers/comparison_matcher_spec.rb +169 -0
- data/spec/shoulda/matchers/active_model/numericality_matchers/even_number_matcher_spec.rb +59 -0
- data/spec/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher_spec.rb +59 -0
- data/spec/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher_spec.rb +57 -0
- data/spec/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb +139 -0
- data/spec/shoulda/matchers/active_model/validate_acceptance_of_matcher_spec.rb +41 -0
- data/spec/shoulda/matchers/active_model/validate_confirmation_of_matcher_spec.rb +47 -0
- data/spec/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +331 -0
- data/spec/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +180 -0
- data/spec/shoulda/matchers/active_model/validate_uniqueness_of_matcher_spec.rb +398 -0
- data/spec/shoulda/matchers/active_model/validation_message_finder_spec.rb +127 -0
- data/spec/shoulda/matchers/active_record/accept_nested_attributes_for_matcher_spec.rb +107 -0
- data/spec/shoulda/matchers/active_record/association_matcher_spec.rb +860 -0
- data/spec/shoulda/matchers/active_record/association_matchers/model_reflection_spec.rb +247 -0
- data/spec/shoulda/matchers/active_record/have_db_column_matcher_spec.rb +111 -0
- data/spec/shoulda/matchers/active_record/have_db_index_matcher_spec.rb +78 -0
- data/spec/shoulda/matchers/active_record/have_readonly_attributes_matcher_spec.rb +41 -0
- data/spec/shoulda/matchers/active_record/serialize_matcher_spec.rb +86 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/active_model_versions.rb +13 -0
- data/spec/support/active_resource_builder.rb +29 -0
- data/spec/support/activemodel_helpers.rb +19 -0
- data/spec/support/capture_helpers.rb +19 -0
- data/spec/support/class_builder.rb +42 -0
- data/spec/support/controller_builder.rb +74 -0
- data/spec/support/fail_with_message_including_matcher.rb +33 -0
- data/spec/support/fail_with_message_matcher.rb +32 -0
- data/spec/support/i18n_faker.rb +10 -0
- data/spec/support/mailer_builder.rb +10 -0
- data/spec/support/model_builder.rb +81 -0
- data/spec/support/rails_versions.rb +18 -0
- data/spec/support/shared_examples/numerical_submatcher.rb +19 -0
- data/spec/support/shared_examples/numerical_type_submatcher.rb +17 -0
- data/spec/support/test_application.rb +120 -0
- data/yard.watchr +5 -0
- metadata +281 -0
@@ -0,0 +1,117 @@
|
|
1
|
+
module Shoulda
|
2
|
+
module Matchers
|
3
|
+
module ActionController
|
4
|
+
# The `render_with_layout` matcher tests that an action is rendered with
|
5
|
+
# a certain layout.
|
6
|
+
#
|
7
|
+
# class PostsController < ApplicationController
|
8
|
+
# def show
|
9
|
+
# render layout: 'posts'
|
10
|
+
# end
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# # RSpec
|
14
|
+
# describe PostsController do
|
15
|
+
# describe 'GET #show' do
|
16
|
+
# before { get :show }
|
17
|
+
#
|
18
|
+
# it { should render_with_layout('posts') }
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# # Test::Unit
|
23
|
+
# class PostsControllerTest < ActionController::TestCase
|
24
|
+
# context 'GET #show' do
|
25
|
+
# setup { get :show }
|
26
|
+
#
|
27
|
+
# should render_with_layout('posts')
|
28
|
+
# end
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# @return [RenderWithLayoutMatcher]
|
32
|
+
#
|
33
|
+
def render_with_layout(expected_layout = nil)
|
34
|
+
RenderWithLayoutMatcher.new(expected_layout).in_context(self)
|
35
|
+
end
|
36
|
+
|
37
|
+
# @private
|
38
|
+
class RenderWithLayoutMatcher
|
39
|
+
def initialize(expected_layout)
|
40
|
+
unless expected_layout.nil?
|
41
|
+
@expected_layout = expected_layout.to_s
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Used to provide access to layouts recorded by
|
46
|
+
# ActionController::TemplateAssertions in Rails 3
|
47
|
+
def in_context(context)
|
48
|
+
@context = context
|
49
|
+
self
|
50
|
+
end
|
51
|
+
|
52
|
+
def matches?(controller)
|
53
|
+
@controller = controller
|
54
|
+
rendered_with_layout? && rendered_with_expected_layout?
|
55
|
+
end
|
56
|
+
|
57
|
+
def failure_message
|
58
|
+
"Expected #{expectation}, but #{result}"
|
59
|
+
end
|
60
|
+
alias failure_message_for_should failure_message
|
61
|
+
|
62
|
+
def failure_message_when_negated
|
63
|
+
"Did not expect #{expectation}, but #{result}"
|
64
|
+
end
|
65
|
+
alias failure_message_for_should_not failure_message_when_negated
|
66
|
+
|
67
|
+
def description
|
68
|
+
description = 'render with '
|
69
|
+
if @expected_layout.nil?
|
70
|
+
description << 'a layout'
|
71
|
+
else
|
72
|
+
description << "the #{@expected_layout.inspect} layout"
|
73
|
+
end
|
74
|
+
description
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def rendered_with_layout?
|
80
|
+
!rendered_layouts.empty?
|
81
|
+
end
|
82
|
+
|
83
|
+
def rendered_with_expected_layout?
|
84
|
+
if @expected_layout.nil?
|
85
|
+
true
|
86
|
+
else
|
87
|
+
rendered_layouts.include?(@expected_layout)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def rendered_layouts
|
92
|
+
recorded_layouts.keys.compact.map { |layout| layout.sub(%r{^layouts/}, '') }
|
93
|
+
end
|
94
|
+
|
95
|
+
def recorded_layouts
|
96
|
+
if @context
|
97
|
+
@context.instance_variable_get(Shoulda::Matchers::RailsShim.layouts_ivar)
|
98
|
+
else
|
99
|
+
{}
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def expectation
|
104
|
+
"to #{description}"
|
105
|
+
end
|
106
|
+
|
107
|
+
def result
|
108
|
+
if rendered_with_layout?
|
109
|
+
'rendered with ' + rendered_layouts.map(&:inspect).join(', ')
|
110
|
+
else
|
111
|
+
'rendered without a layout'
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module Shoulda
|
2
|
+
module Matchers
|
3
|
+
module ActionController
|
4
|
+
# The `rescue_from` matcher tests usage of the `rescue_from` macro. It
|
5
|
+
# asserts that an exception and method are present in the list of
|
6
|
+
# exception handlers, and that the handler method exists.
|
7
|
+
#
|
8
|
+
# class ApplicationController < ActionController::Base
|
9
|
+
# rescue_from ActiveRecord::RecordNotFound, with: :handle_not_found
|
10
|
+
#
|
11
|
+
# private
|
12
|
+
#
|
13
|
+
# def handle_not_found
|
14
|
+
# # ...
|
15
|
+
# end
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# # RSpec
|
19
|
+
# describe ApplicationController do
|
20
|
+
# it do
|
21
|
+
# should rescue_from(ActiveRecord::RecordNotFound).
|
22
|
+
# with(:handle_not_found)
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# # Test::Unit
|
27
|
+
# class ApplicationControllerTest < ActionController::TestCase
|
28
|
+
# should rescue_from(ActiveRecord::RecordNotFound).
|
29
|
+
# with(:handle_not_found)
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# @return [RescueFromMatcher]
|
33
|
+
#
|
34
|
+
def rescue_from(exception)
|
35
|
+
RescueFromMatcher.new exception
|
36
|
+
end
|
37
|
+
|
38
|
+
# @private
|
39
|
+
class RescueFromMatcher
|
40
|
+
def initialize(exception)
|
41
|
+
@exception = exception
|
42
|
+
end
|
43
|
+
|
44
|
+
def with(method)
|
45
|
+
@expected_method = method
|
46
|
+
self
|
47
|
+
end
|
48
|
+
|
49
|
+
def matches?(controller)
|
50
|
+
@controller = controller
|
51
|
+
rescues_from_exception? && method_name_matches? && handler_exists?
|
52
|
+
end
|
53
|
+
|
54
|
+
def description
|
55
|
+
description = "rescues from #{exception}"
|
56
|
+
description << " with ##{expected_method}" if expected_method
|
57
|
+
description
|
58
|
+
end
|
59
|
+
|
60
|
+
def failure_message
|
61
|
+
"Expected #{expectation}"
|
62
|
+
end
|
63
|
+
alias failure_message_for_should failure_message
|
64
|
+
|
65
|
+
def failure_message_when_negated
|
66
|
+
"Did not expect #{expectation}"
|
67
|
+
end
|
68
|
+
alias failure_message_for_should_not failure_message_when_negated
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
attr_reader :controller, :exception, :expected_method, :handlers
|
73
|
+
|
74
|
+
def expectation
|
75
|
+
expectation = "#{controller} to rescue from #{exception}"
|
76
|
+
|
77
|
+
if expected_method && !method_name_matches?
|
78
|
+
expectation << " with ##{expected_method}"
|
79
|
+
end
|
80
|
+
|
81
|
+
unless handler_exists?
|
82
|
+
expectation << " but #{controller} does not respond to #{expected_method}"
|
83
|
+
end
|
84
|
+
expectation
|
85
|
+
end
|
86
|
+
|
87
|
+
def rescues_from_exception?
|
88
|
+
@handlers = controller.rescue_handlers.select do |handler|
|
89
|
+
handler.first == exception.to_s
|
90
|
+
end
|
91
|
+
handlers.any?
|
92
|
+
end
|
93
|
+
|
94
|
+
def method_name_matches?
|
95
|
+
if expected_method.present?
|
96
|
+
handlers.any? do |handler|
|
97
|
+
handler.last == expected_method
|
98
|
+
end
|
99
|
+
else
|
100
|
+
true
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def handler_exists?
|
105
|
+
if expected_method.present?
|
106
|
+
controller.respond_to? expected_method
|
107
|
+
else
|
108
|
+
true
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
module Shoulda
|
2
|
+
module Matchers
|
3
|
+
module ActionController
|
4
|
+
# The `respond_with` matcher tests that an action responds with a certain
|
5
|
+
# status code.
|
6
|
+
#
|
7
|
+
# You can specify that the status should be a number:
|
8
|
+
#
|
9
|
+
# class PostsController < ApplicationController
|
10
|
+
# def index
|
11
|
+
# render status: 403
|
12
|
+
# end
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# # RSpec
|
16
|
+
# describe PostsController do
|
17
|
+
# describe 'GET #index' do
|
18
|
+
# before { get :index }
|
19
|
+
#
|
20
|
+
# it { should respond_with(403) }
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# # Test::Unit
|
25
|
+
# class PostsControllerTest < ActionController::TestCase
|
26
|
+
# context 'GET #index' do
|
27
|
+
# setup { get :index }
|
28
|
+
#
|
29
|
+
# should respond_with(403)
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# You can specify that the status should be within a range of numbers:
|
34
|
+
#
|
35
|
+
# class PostsController < ApplicationController
|
36
|
+
# def destroy
|
37
|
+
# render status: 508
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# # RSpec
|
42
|
+
# describe PostsController do
|
43
|
+
# describe 'DELETE #destroy' do
|
44
|
+
# before { delete :destroy }
|
45
|
+
#
|
46
|
+
# it { should respond_with(500..600) }
|
47
|
+
# end
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# # Test::Unit
|
51
|
+
# class PostsControllerTest < ActionController::TestCase
|
52
|
+
# context 'DELETE #destroy' do
|
53
|
+
# setup { delete :destroy }
|
54
|
+
#
|
55
|
+
# should respond_with(500..600)
|
56
|
+
# end
|
57
|
+
# end
|
58
|
+
#
|
59
|
+
# Finally, you can specify that the status should be a symbol:
|
60
|
+
#
|
61
|
+
# class PostsController < ApplicationController
|
62
|
+
# def show
|
63
|
+
# render status: :locked
|
64
|
+
# end
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# # RSpec
|
68
|
+
# describe PostsController do
|
69
|
+
# describe 'GET #show' do
|
70
|
+
# before { get :show }
|
71
|
+
#
|
72
|
+
# it { should respond_with(:locked) }
|
73
|
+
# end
|
74
|
+
# end
|
75
|
+
#
|
76
|
+
# # Test::Unit
|
77
|
+
# class PostsControllerTest < ActionController::TestCase
|
78
|
+
# context 'GET #show' do
|
79
|
+
# setup { get :show }
|
80
|
+
#
|
81
|
+
# should respond_with(:locked)
|
82
|
+
# end
|
83
|
+
# end
|
84
|
+
#
|
85
|
+
# @return [RespondWithMatcher]
|
86
|
+
#
|
87
|
+
def respond_with(status)
|
88
|
+
RespondWithMatcher.new(status)
|
89
|
+
end
|
90
|
+
|
91
|
+
# @private
|
92
|
+
class RespondWithMatcher
|
93
|
+
def initialize(status)
|
94
|
+
@status = symbol_to_status_code(status)
|
95
|
+
end
|
96
|
+
|
97
|
+
def matches?(controller)
|
98
|
+
@controller = controller
|
99
|
+
correct_status_code? || correct_status_code_range?
|
100
|
+
end
|
101
|
+
|
102
|
+
def failure_message
|
103
|
+
"Expected #{expectation}"
|
104
|
+
end
|
105
|
+
alias failure_message_for_should failure_message
|
106
|
+
|
107
|
+
def failure_message_when_negated
|
108
|
+
"Did not expect #{expectation}"
|
109
|
+
end
|
110
|
+
alias failure_message_for_should_not failure_message_when_negated
|
111
|
+
|
112
|
+
def description
|
113
|
+
"respond with #{@status}"
|
114
|
+
end
|
115
|
+
|
116
|
+
protected
|
117
|
+
|
118
|
+
def correct_status_code?
|
119
|
+
response_code == @status
|
120
|
+
end
|
121
|
+
|
122
|
+
def correct_status_code_range?
|
123
|
+
@status.is_a?(Range) &&
|
124
|
+
@status.include?(response_code)
|
125
|
+
end
|
126
|
+
|
127
|
+
def response_code
|
128
|
+
@controller.response.response_code
|
129
|
+
end
|
130
|
+
|
131
|
+
def symbol_to_status_code(potential_symbol)
|
132
|
+
case potential_symbol
|
133
|
+
when :success then 200
|
134
|
+
when :redirect then 300..399
|
135
|
+
when :missing then 404
|
136
|
+
when :error then 500..599
|
137
|
+
when Symbol
|
138
|
+
if defined?(::Rack::Utils::SYMBOL_TO_STATUS_CODE)
|
139
|
+
::Rack::Utils::SYMBOL_TO_STATUS_CODE[potential_symbol]
|
140
|
+
else
|
141
|
+
::ActionController::Base::SYMBOL_TO_STATUS_CODE[potential_symbol]
|
142
|
+
end
|
143
|
+
else
|
144
|
+
potential_symbol
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def expectation
|
149
|
+
"response to be a #{@status}, but was #{response_code}"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module Shoulda
|
2
|
+
module Matchers
|
3
|
+
module ActionController
|
4
|
+
# The `route` matcher tests that a route resolves to a controller,
|
5
|
+
# action, and params; and that the controller, action, and params
|
6
|
+
# generates the same route. For an RSpec suite, this is like using a
|
7
|
+
# combination of `route_to` and `be_routable`. For a Test::Unit suite, it
|
8
|
+
# provides a more expressive syntax over `assert_routing`.
|
9
|
+
#
|
10
|
+
# Given these routes:
|
11
|
+
#
|
12
|
+
# My::Application.routes.draw do
|
13
|
+
# get '/posts', controller: 'posts', action: 'index'
|
14
|
+
# get '/posts/:id' => 'posts#show'
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# You can choose to keep your routing tests under the test file for one
|
18
|
+
# controller:
|
19
|
+
#
|
20
|
+
# class PostsController < ApplicationController
|
21
|
+
# # ...
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# # RSpec
|
25
|
+
# describe PostsController do
|
26
|
+
# it { should route(:get, '/posts').to(action: :index) }
|
27
|
+
# it { should route(:get, '/posts/1').to(action: :show, id: 1) }
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# # Test::Unit
|
31
|
+
# class PostsControllerTest < ActionController::TestCase
|
32
|
+
# should route(:get, '/posts').to(action: 'index')
|
33
|
+
# should route(:get, '/posts/1').to(action: :show, id: 1)
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# Or if you like, you can keep all of your routing tests in one file.
|
37
|
+
# Just be sure to always specify a controller as `route` won't be able to
|
38
|
+
# figure it out otherwise:
|
39
|
+
#
|
40
|
+
# # RSpec
|
41
|
+
# describe 'Routing' do
|
42
|
+
# it { should route(:get, '/posts').to(controller: :posts, action: :index) }
|
43
|
+
# it { should route(:get, '/posts/1').to('posts#show', id: 1) }
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# # Test::Unit
|
47
|
+
# class RoutesTest < ActionController::IntegrationTest
|
48
|
+
# should route(:get, '/posts').to(controller: :posts, action: :index)
|
49
|
+
# should route(:get, '/posts/1').to('posts#show', id: 1)
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# @return [RouteMatcher]
|
53
|
+
#
|
54
|
+
def route(method, path)
|
55
|
+
RouteMatcher.new(method, path, self)
|
56
|
+
end
|
57
|
+
|
58
|
+
# @private
|
59
|
+
class RouteMatcher
|
60
|
+
def initialize(method, path, context)
|
61
|
+
@method = method
|
62
|
+
@path = path
|
63
|
+
@context = context
|
64
|
+
end
|
65
|
+
|
66
|
+
attr_reader :failure_message, :failure_message_when_negated
|
67
|
+
|
68
|
+
alias failure_message_for_should failure_message
|
69
|
+
alias failure_message_for_should_not failure_message_when_negated
|
70
|
+
|
71
|
+
def to(*args)
|
72
|
+
@params = RouteParams.new(args).normalize
|
73
|
+
self
|
74
|
+
end
|
75
|
+
|
76
|
+
def in_context(context)
|
77
|
+
@context = context
|
78
|
+
self
|
79
|
+
end
|
80
|
+
|
81
|
+
def matches?(controller)
|
82
|
+
guess_controller!(controller)
|
83
|
+
route_recognized?
|
84
|
+
end
|
85
|
+
|
86
|
+
def description
|
87
|
+
"route #{@method.to_s.upcase} #{@path} to/from #{@params.inspect}"
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def guess_controller!(controller)
|
93
|
+
@params[:controller] ||= controller.controller_path
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
def route_recognized?
|
98
|
+
begin
|
99
|
+
@context.__send__(:assert_routing,
|
100
|
+
{ method: @method, path: @path },
|
101
|
+
@params)
|
102
|
+
|
103
|
+
@failure_message_when_negated = "Didn't expect to #{description}"
|
104
|
+
true
|
105
|
+
rescue ::ActionController::RoutingError => error
|
106
|
+
@failure_message = error.message
|
107
|
+
false
|
108
|
+
rescue Shoulda::Matchers::AssertionError => error
|
109
|
+
@failure_message = error.message
|
110
|
+
false
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|