ultra-fast-box 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/shoulda-matchers-8.0.1/LICENSE +22 -0
- data/shoulda-matchers-8.0.1/README.md +567 -0
- data/shoulda-matchers-8.0.1/docs/errors/NonCaseSwappableValueError.md +111 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/callback_matcher.rb +121 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +70 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/flash_store.rb +86 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/permit_matcher.rb +445 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +96 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/render_template_matcher.rb +84 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +145 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +115 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +148 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/route_matcher.rb +207 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/route_params.rb +62 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/session_store.rb +34 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/set_flash_matcher.rb +228 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/set_session_matcher.rb +163 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/set_session_or_flash_matcher.rb +107 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller.rb +24 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_changed_value_error.rb +45 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_does_not_exist_error.rb +23 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter.rb +232 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter_and_validator.rb +62 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters.rb +40 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators.rb +48 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/successful_check.rb +14 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/successful_setting.rb +14 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher.rb +695 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/comparison_matcher.rb +157 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +78 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/errors.rb +52 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +125 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/helpers.rb +37 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/even_number_matcher.rb +45 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +67 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher.rb +45 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher.rb +44 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/range_matcher.rb +71 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/submatchers.rb +53 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers.rb +9 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/allow_blank.rb +26 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/allow_nil.rb +26 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/ignore_interference_by_writer.rb +101 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/ignoring_interference_by_writer.rb +21 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers.rb +14 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +180 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +128 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_comparison_of_matcher.rb +567 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +185 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +272 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +664 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +575 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +711 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +428 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validation_matcher/build_description.rb +62 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validation_matcher.rb +195 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validation_message_finder.rb +63 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validator.rb +127 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model.rb +96 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +217 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matcher.rb +2134 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +74 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +62 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/inverse_of_matcher.rb +41 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +105 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +101 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +89 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +142 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/optional_matcher.rb +71 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +41 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +76 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb +42 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +65 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers.rb +9 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +784 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/encrypt_matcher.rb +174 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_attached_matcher.rb +343 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +366 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +287 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_implicit_order_column.rb +104 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +95 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_rich_text_matcher.rb +83 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_secure_token_matcher.rb +132 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/normalize_matcher.rb +151 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/serialize_matcher.rb +203 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/model.rb +58 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/namespace.rb +39 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/test_model_creator.rb +49 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/test_models.rb +55 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness.rb +14 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +1197 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record.rb +37 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/configuration.rb +31 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/double.rb +103 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/double_collection.rb +60 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/double_implementation_registry.rb +31 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/method_call.rb +44 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/object_double.rb +43 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/proxy_implementation.rb +32 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/stub_implementation.rb +31 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/world.rb +63 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak.rb +38 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/error.rb +29 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/independent/delegate_method_matcher/target_not_defined_error.rb +15 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/independent/delegate_method_matcher.rb +540 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/independent.rb +11 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/configuration.rb +70 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/configuration_error.rb +9 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/inclusion.rb +20 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/action_controller.rb +33 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/active_model.rb +26 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/active_record.rb +26 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/missing_library.rb +19 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/rails.rb +31 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/routing.rb +29 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries.rb +16 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/rails.rb +12 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/registry.rb +28 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/active_support_test_case.rb +37 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/minitest_4.rb +36 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/minitest_5.rb +37 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/missing_test_framework.rb +40 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/rspec.rb +29 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/test_unit.rb +36 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks.rb +16 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations.rb +43 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/matcher_collection.rb +99 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/matcher_context.rb +36 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/rails_shim.rb +190 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/routing.rb +10 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/util/word_wrap.rb +211 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/util.rb +110 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/version.rb +6 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/warn.rb +28 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers.rb +25 -0
- data/shoulda-matchers-8.0.1/lib/shoulda-matchers.rb +1 -0
- data/shoulda-matchers-8.0.1/shoulda-matchers.gemspec +43 -0
- data/ultra-fast-box.gemspec +12 -0
- metadata +179 -0
data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
module Shoulda
|
|
2
|
+
module Matchers
|
|
3
|
+
module ActionController
|
|
4
|
+
# The `render_with_layout` matcher asserts that an action is rendered with
|
|
5
|
+
# a particular layout.
|
|
6
|
+
#
|
|
7
|
+
# class PostsController < ApplicationController
|
|
8
|
+
# def show
|
|
9
|
+
# render layout: 'posts'
|
|
10
|
+
# end
|
|
11
|
+
# end
|
|
12
|
+
#
|
|
13
|
+
# # RSpec
|
|
14
|
+
# RSpec.describe PostsController, type: :controller do
|
|
15
|
+
# describe 'GET #show' do
|
|
16
|
+
# before { get :show }
|
|
17
|
+
#
|
|
18
|
+
# it { should render_with_layout('posts') }
|
|
19
|
+
# end
|
|
20
|
+
# end
|
|
21
|
+
#
|
|
22
|
+
# # Minitest (Shoulda)
|
|
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
|
+
# It can also be used to assert that the action is not rendered with a
|
|
32
|
+
# layout at all:
|
|
33
|
+
#
|
|
34
|
+
# class PostsController < ApplicationController
|
|
35
|
+
# def sidebar
|
|
36
|
+
# render layout: false
|
|
37
|
+
# end
|
|
38
|
+
# end
|
|
39
|
+
#
|
|
40
|
+
# # RSpec
|
|
41
|
+
# RSpec.describe PostsController, type: :controller do
|
|
42
|
+
# describe 'GET #sidebar' do
|
|
43
|
+
# before { get :sidebar }
|
|
44
|
+
#
|
|
45
|
+
# it { should_not render_with_layout }
|
|
46
|
+
# end
|
|
47
|
+
# end
|
|
48
|
+
#
|
|
49
|
+
# # Minitest (Shoulda)
|
|
50
|
+
# class PostsControllerTest < ActionController::TestCase
|
|
51
|
+
# context 'GET #sidebar' do
|
|
52
|
+
# setup { get :sidebar }
|
|
53
|
+
#
|
|
54
|
+
# should_not render_with_layout
|
|
55
|
+
# end
|
|
56
|
+
# end
|
|
57
|
+
#
|
|
58
|
+
# @return [RenderWithLayoutMatcher]
|
|
59
|
+
#
|
|
60
|
+
def render_with_layout(expected_layout = nil)
|
|
61
|
+
RenderWithLayoutMatcher.new(expected_layout).in_context(self)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @private
|
|
65
|
+
class RenderWithLayoutMatcher
|
|
66
|
+
def initialize(expected_layout)
|
|
67
|
+
@expected_layout =
|
|
68
|
+
if expected_layout
|
|
69
|
+
expected_layout.to_s
|
|
70
|
+
else
|
|
71
|
+
nil
|
|
72
|
+
end
|
|
73
|
+
@controller = nil
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Used to provide access to layouts recorded by
|
|
77
|
+
# ActionController::TemplateAssertions in Rails 3
|
|
78
|
+
def in_context(context)
|
|
79
|
+
@context = context
|
|
80
|
+
self
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def matches?(controller)
|
|
84
|
+
@controller = controller
|
|
85
|
+
rendered_with_layout? && rendered_with_expected_layout?
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def failure_message
|
|
89
|
+
"Expected #{expectation}, but #{result}"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def failure_message_when_negated
|
|
93
|
+
"Did not expect #{expectation}, but #{result}"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def description
|
|
97
|
+
String.new('render with ').tap do |string|
|
|
98
|
+
string <<
|
|
99
|
+
if @expected_layout.nil?
|
|
100
|
+
'a layout'
|
|
101
|
+
else
|
|
102
|
+
"the #{@expected_layout.inspect} layout"
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
private
|
|
108
|
+
|
|
109
|
+
def rendered_with_layout?
|
|
110
|
+
!rendered_layouts.empty?
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def rendered_with_expected_layout?
|
|
114
|
+
@expected_layout.nil? || rendered_layouts.include?(@expected_layout)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def rendered_layouts
|
|
118
|
+
recorded_layouts.keys.compact.map { |layout|
|
|
119
|
+
layout.sub(%r{^layouts/}, '')
|
|
120
|
+
}
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def recorded_layouts
|
|
124
|
+
if @context
|
|
125
|
+
@context.instance_variable_get('@_layouts')
|
|
126
|
+
else
|
|
127
|
+
{}
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def expectation
|
|
132
|
+
"to #{description}"
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def result
|
|
136
|
+
if rendered_with_layout?
|
|
137
|
+
"rendered with #{rendered_layouts.map(&:inspect).join(', ')}"
|
|
138
|
+
else
|
|
139
|
+
'rendered without a layout'
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
@@ -0,0 +1,115 @@
|
|
|
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
|
+
# RSpec.describe ApplicationController, type: :controller do
|
|
20
|
+
# it do
|
|
21
|
+
# should rescue_from(ActiveRecord::RecordNotFound).
|
|
22
|
+
# with(:handle_not_found)
|
|
23
|
+
# end
|
|
24
|
+
# end
|
|
25
|
+
#
|
|
26
|
+
# # Minitest (Shoulda)
|
|
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
|
+
@expected_method = nil
|
|
43
|
+
@controller = nil
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def with(method)
|
|
47
|
+
@expected_method = method
|
|
48
|
+
self
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def matches?(controller)
|
|
52
|
+
@controller = controller
|
|
53
|
+
rescues_from_exception? && method_name_matches? && handler_exists?
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def description
|
|
57
|
+
description = "rescue from #{exception}"
|
|
58
|
+
description << " with ##{expected_method}" if expected_method
|
|
59
|
+
description
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def failure_message
|
|
63
|
+
"Expected #{expectation}"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def failure_message_when_negated
|
|
67
|
+
"Did not expect #{expectation}"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
protected
|
|
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"\
|
|
83
|
+
" #{expected_method}"
|
|
84
|
+
end
|
|
85
|
+
expectation
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def rescues_from_exception?
|
|
89
|
+
@handlers = controller.rescue_handlers.select do |handler|
|
|
90
|
+
handler.first == exception.to_s
|
|
91
|
+
end
|
|
92
|
+
handlers.any?
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def method_name_matches?
|
|
96
|
+
if expected_method.present?
|
|
97
|
+
handlers.any? do |handler|
|
|
98
|
+
handler.last == expected_method
|
|
99
|
+
end
|
|
100
|
+
else
|
|
101
|
+
true
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def handler_exists?
|
|
106
|
+
if expected_method.present?
|
|
107
|
+
controller.respond_to? expected_method, true
|
|
108
|
+
else
|
|
109
|
+
true
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,148 @@
|
|
|
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
|
+
# RSpec.describe PostsController, type: :controller do
|
|
17
|
+
# describe 'GET #index' do
|
|
18
|
+
# before { get :index }
|
|
19
|
+
#
|
|
20
|
+
# it { should respond_with(403) }
|
|
21
|
+
# end
|
|
22
|
+
# end
|
|
23
|
+
#
|
|
24
|
+
# # Minitest (Shoulda)
|
|
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
|
+
# RSpec.describe PostsController, type: :controller do
|
|
43
|
+
# describe 'DELETE #destroy' do
|
|
44
|
+
# before { delete :destroy }
|
|
45
|
+
#
|
|
46
|
+
# it { should respond_with(500..600) }
|
|
47
|
+
# end
|
|
48
|
+
# end
|
|
49
|
+
#
|
|
50
|
+
# # Minitest (Shoulda)
|
|
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
|
+
# RSpec.describe PostsController, type: :controller do
|
|
69
|
+
# describe 'GET #show' do
|
|
70
|
+
# before { get :show }
|
|
71
|
+
#
|
|
72
|
+
# it { should respond_with(:locked) }
|
|
73
|
+
# end
|
|
74
|
+
# end
|
|
75
|
+
#
|
|
76
|
+
# # Minitest (Shoulda)
|
|
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
|
+
|
|
106
|
+
def failure_message_when_negated
|
|
107
|
+
"Did not expect #{expectation}"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def description
|
|
111
|
+
"respond with #{@status}"
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
protected
|
|
115
|
+
|
|
116
|
+
def correct_status_code?
|
|
117
|
+
response_code == @status
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def correct_status_code_range?
|
|
121
|
+
@status.is_a?(Range) &&
|
|
122
|
+
@status.include?(response_code)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def response_code
|
|
126
|
+
@controller.response.response_code
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def symbol_to_status_code(potential_symbol)
|
|
130
|
+
case potential_symbol
|
|
131
|
+
when :success then 200
|
|
132
|
+
when :redirect then 300..399
|
|
133
|
+
when :missing then 404
|
|
134
|
+
when :error then 500..599
|
|
135
|
+
when Symbol
|
|
136
|
+
::Rack::Utils.status_code(potential_symbol)
|
|
137
|
+
else
|
|
138
|
+
potential_symbol
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def expectation
|
|
143
|
+
"response to be a #{@status}, but was #{response_code}"
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
@@ -0,0 +1,207 @@
|
|
|
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`. In a test suite using
|
|
8
|
+
# Minitest + Shoulda, it provides a more expressive syntax over
|
|
9
|
+
# `assert_routing`.
|
|
10
|
+
#
|
|
11
|
+
# You can use this matcher either in a controller test case or in a
|
|
12
|
+
# routing test case. For instance, given these routes:
|
|
13
|
+
#
|
|
14
|
+
# My::Application.routes.draw do
|
|
15
|
+
# get '/posts', to: 'posts#index'
|
|
16
|
+
# get '/posts/:id', to: 'posts#show'
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# You could choose to write tests for these routes alongside other tests
|
|
20
|
+
# for PostsController:
|
|
21
|
+
#
|
|
22
|
+
# class PostsController < ApplicationController
|
|
23
|
+
# # ...
|
|
24
|
+
# end
|
|
25
|
+
#
|
|
26
|
+
# # RSpec
|
|
27
|
+
# RSpec.describe PostsController, type: :controller do
|
|
28
|
+
# it { should route(:get, '/posts').to(action: :index) }
|
|
29
|
+
# it { should route(:get, '/posts/1').to(action: :show, id: 1) }
|
|
30
|
+
# end
|
|
31
|
+
#
|
|
32
|
+
# # Minitest (Shoulda)
|
|
33
|
+
# class PostsControllerTest < ActionController::TestCase
|
|
34
|
+
# should route(:get, '/posts').to(action: 'index')
|
|
35
|
+
# should route(:get, '/posts/1').to(action: :show, id: 1)
|
|
36
|
+
# end
|
|
37
|
+
#
|
|
38
|
+
# Or you could place the tests along with other route tests:
|
|
39
|
+
#
|
|
40
|
+
# # RSpec
|
|
41
|
+
# describe 'Routing', type: :routing do
|
|
42
|
+
# it do
|
|
43
|
+
# should route(:get, '/posts').
|
|
44
|
+
# to(controller: :posts, action: :index)
|
|
45
|
+
# end
|
|
46
|
+
#
|
|
47
|
+
# it do
|
|
48
|
+
# should route(:get, '/posts/1').
|
|
49
|
+
# to('posts#show', id: 1)
|
|
50
|
+
# end
|
|
51
|
+
# end
|
|
52
|
+
#
|
|
53
|
+
# # Minitest (Shoulda)
|
|
54
|
+
# class RoutesTest < ActionController::IntegrationTest
|
|
55
|
+
# should route(:get, '/posts').
|
|
56
|
+
# to(controller: :posts, action: :index)
|
|
57
|
+
#
|
|
58
|
+
# should route(:get, '/posts/1').
|
|
59
|
+
# to('posts#show', id: 1)
|
|
60
|
+
# end
|
|
61
|
+
#
|
|
62
|
+
# Notice that in the former case, as we are inside of a test case for
|
|
63
|
+
# PostsController, we do not have to specify that the routes resolve to
|
|
64
|
+
# this controller. In the latter case we specify this using the
|
|
65
|
+
# `controller` key passed to the `to` qualifier.
|
|
66
|
+
#
|
|
67
|
+
# #### Specifying a port
|
|
68
|
+
#
|
|
69
|
+
# If the route you're testing has a constraint on it that limits the route
|
|
70
|
+
# to a particular port, you can specify it by passing a `port` option to
|
|
71
|
+
# the matcher:
|
|
72
|
+
#
|
|
73
|
+
# class PortConstraint
|
|
74
|
+
# def initialize(port)
|
|
75
|
+
# @port = port
|
|
76
|
+
# end
|
|
77
|
+
#
|
|
78
|
+
# def matches?(request)
|
|
79
|
+
# request.port == @port
|
|
80
|
+
# end
|
|
81
|
+
# end
|
|
82
|
+
#
|
|
83
|
+
# My::Application.routes.draw do
|
|
84
|
+
# get '/posts',
|
|
85
|
+
# to: 'posts#index',
|
|
86
|
+
# constraints: PortConstraint.new(12345)
|
|
87
|
+
# end
|
|
88
|
+
#
|
|
89
|
+
# # RSpec
|
|
90
|
+
# describe 'Routing', type: :routing do
|
|
91
|
+
# it do
|
|
92
|
+
# should route(:get, '/posts', port: 12345).
|
|
93
|
+
# to('posts#index')
|
|
94
|
+
# end
|
|
95
|
+
# end
|
|
96
|
+
#
|
|
97
|
+
# # Minitest (Shoulda)
|
|
98
|
+
# class RoutesTest < ActionController::IntegrationTest
|
|
99
|
+
# should route(:get, '/posts', port: 12345).
|
|
100
|
+
# to('posts#index')
|
|
101
|
+
# end
|
|
102
|
+
#
|
|
103
|
+
# #### Qualifiers
|
|
104
|
+
#
|
|
105
|
+
# ##### to
|
|
106
|
+
#
|
|
107
|
+
# Use `to` to specify the action (along with the controller, if needed)
|
|
108
|
+
# that the route resolves to.
|
|
109
|
+
#
|
|
110
|
+
# `to` takes either keyword arguments (`controller` and `action`) or a
|
|
111
|
+
# string that represents the controller/action pair:
|
|
112
|
+
#
|
|
113
|
+
# route(:get, '/posts').to(action: index)
|
|
114
|
+
# route(:get, '/posts').to(controller: :posts, action: index)
|
|
115
|
+
# route(:get, '/posts').to('posts#index')
|
|
116
|
+
#
|
|
117
|
+
# If there are parameters in your route, then specify those too:
|
|
118
|
+
#
|
|
119
|
+
# route(:get, '/posts/1').to('posts#show', id: 1)
|
|
120
|
+
#
|
|
121
|
+
# You may also specify special parameters such as `:format`:
|
|
122
|
+
#
|
|
123
|
+
# route(:get, '/posts').to('posts#index', format: :json)
|
|
124
|
+
#
|
|
125
|
+
# @return [RouteMatcher]
|
|
126
|
+
#
|
|
127
|
+
def route(method, path, port: nil)
|
|
128
|
+
RouteMatcher.new(self, method, path, port:)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# @private
|
|
132
|
+
class RouteMatcher
|
|
133
|
+
def initialize(context, method, path, port: nil)
|
|
134
|
+
@context = context
|
|
135
|
+
@method = method
|
|
136
|
+
@path = add_port_to_path(normalize_path(path), port)
|
|
137
|
+
@params = {}
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
attr_reader :failure_message
|
|
141
|
+
|
|
142
|
+
def to(*args)
|
|
143
|
+
@params = RouteParams.new(args).normalize
|
|
144
|
+
self
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def in_context(context)
|
|
148
|
+
@context = context
|
|
149
|
+
self
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def matches?(controller)
|
|
153
|
+
guess_controller_if_necessary(controller)
|
|
154
|
+
|
|
155
|
+
route_recognized?
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def description
|
|
159
|
+
"route #{method.to_s.upcase} #{path} to/from #{params.inspect}"
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def failure_message_when_negated
|
|
163
|
+
"Didn't expect to #{description}"
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
private
|
|
167
|
+
|
|
168
|
+
attr_reader :context, :method, :path, :params
|
|
169
|
+
|
|
170
|
+
def normalize_path(path)
|
|
171
|
+
if path.start_with?('/')
|
|
172
|
+
path
|
|
173
|
+
else
|
|
174
|
+
"/#{path}"
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def add_port_to_path(path, port)
|
|
179
|
+
if port
|
|
180
|
+
"https://example.com:#{port}" + path
|
|
181
|
+
else
|
|
182
|
+
path
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def guess_controller_if_necessary(controller)
|
|
187
|
+
params[:controller] ||= controller.controller_path
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def route_recognized?
|
|
191
|
+
context.send(
|
|
192
|
+
:assert_routing,
|
|
193
|
+
{ method:, path: },
|
|
194
|
+
params,
|
|
195
|
+
)
|
|
196
|
+
true
|
|
197
|
+
rescue ::ActionController::RoutingError => e
|
|
198
|
+
@failure_message = e.message
|
|
199
|
+
false
|
|
200
|
+
rescue Shoulda::Matchers.assertion_exception_class => e
|
|
201
|
+
@failure_message = e.message
|
|
202
|
+
false
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
module Shoulda
|
|
2
|
+
module Matchers
|
|
3
|
+
module ActionController
|
|
4
|
+
# @private
|
|
5
|
+
class RouteParams
|
|
6
|
+
PARAMS_TO_SYMBOLIZE = %i{format}.freeze
|
|
7
|
+
|
|
8
|
+
def initialize(args)
|
|
9
|
+
@args = args
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def normalize
|
|
13
|
+
if controller_and_action_given_as_string?
|
|
14
|
+
extract_params_from_string
|
|
15
|
+
else
|
|
16
|
+
stringify_params
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
protected
|
|
21
|
+
|
|
22
|
+
attr_reader :args
|
|
23
|
+
|
|
24
|
+
def controller_and_action_given_as_string?
|
|
25
|
+
args[0].is_a?(String)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def extract_params_from_string
|
|
29
|
+
controller, action = args[0].split('#')
|
|
30
|
+
params = (args[1] || {}).merge!(controller:, action:)
|
|
31
|
+
normalize_values(params)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def stringify_params
|
|
35
|
+
normalize_values(args[0])
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def normalize_values(hash)
|
|
39
|
+
hash.each_with_object({}) do |(key, value), hash_copy|
|
|
40
|
+
hash_copy[key] = symbolize_or_stringify(key, value)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def symbolize_or_stringify(key, value)
|
|
45
|
+
if PARAMS_TO_SYMBOLIZE.include?(key)
|
|
46
|
+
value.to_sym
|
|
47
|
+
else
|
|
48
|
+
stringify(value)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def stringify(value)
|
|
53
|
+
if value.is_a?(Array)
|
|
54
|
+
value.map(&:to_param)
|
|
55
|
+
else
|
|
56
|
+
value.to_param
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module Shoulda
|
|
2
|
+
module Matchers
|
|
3
|
+
module ActionController
|
|
4
|
+
# @private
|
|
5
|
+
class SessionStore
|
|
6
|
+
attr_accessor :controller
|
|
7
|
+
|
|
8
|
+
def name
|
|
9
|
+
'session'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def has_key?(key)
|
|
13
|
+
session.key?(key)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def has_value?(expected_value)
|
|
17
|
+
session.values.any? do |actual_value|
|
|
18
|
+
expected_value === actual_value
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def empty?
|
|
23
|
+
session.empty?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def session
|
|
29
|
+
controller.session
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|