giga-safe-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/giga-safe-box.gemspec +11 -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
- metadata +178 -0
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
require 'delegate'
|
|
2
|
+
|
|
3
|
+
begin
|
|
4
|
+
require 'strong_parameters'
|
|
5
|
+
rescue LoadError
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
require 'active_support/hash_with_indifferent_access'
|
|
9
|
+
|
|
10
|
+
module Shoulda
|
|
11
|
+
module Matchers
|
|
12
|
+
module ActionController
|
|
13
|
+
# The `permit` matcher tests that an action in your controller receives a
|
|
14
|
+
# allowlist of parameters using Rails' Strong Parameters feature
|
|
15
|
+
# (specifically that `permit` was called with the correct arguments).
|
|
16
|
+
#
|
|
17
|
+
# Here's an example:
|
|
18
|
+
#
|
|
19
|
+
# class UsersController < ApplicationController
|
|
20
|
+
# def create
|
|
21
|
+
# user = User.create(user_params)
|
|
22
|
+
# # ...
|
|
23
|
+
# end
|
|
24
|
+
#
|
|
25
|
+
# private
|
|
26
|
+
#
|
|
27
|
+
# def user_params
|
|
28
|
+
# params.require(:user).permit(
|
|
29
|
+
# :first_name,
|
|
30
|
+
# :last_name,
|
|
31
|
+
# :email,
|
|
32
|
+
# :password
|
|
33
|
+
# )
|
|
34
|
+
# end
|
|
35
|
+
# end
|
|
36
|
+
#
|
|
37
|
+
# # RSpec
|
|
38
|
+
# RSpec.describe UsersController, type: :controller do
|
|
39
|
+
# it do
|
|
40
|
+
# params = {
|
|
41
|
+
# user: {
|
|
42
|
+
# first_name: 'John',
|
|
43
|
+
# last_name: 'Doe',
|
|
44
|
+
# email: 'johndoe@example.com',
|
|
45
|
+
# password: 'password'
|
|
46
|
+
# }
|
|
47
|
+
# }
|
|
48
|
+
# should permit(:first_name, :last_name, :email, :password).
|
|
49
|
+
# for(:create, params: params).
|
|
50
|
+
# on(:user)
|
|
51
|
+
# end
|
|
52
|
+
# end
|
|
53
|
+
#
|
|
54
|
+
# # Minitest (Shoulda)
|
|
55
|
+
# class UsersControllerTest < ActionController::TestCase
|
|
56
|
+
# should "(for POST #create) restrict parameters on :user to first_name, last_name, email, and password" do
|
|
57
|
+
# params = {
|
|
58
|
+
# user: {
|
|
59
|
+
# first_name: 'John',
|
|
60
|
+
# last_name: 'Doe',
|
|
61
|
+
# email: 'johndoe@example.com',
|
|
62
|
+
# password: 'password'
|
|
63
|
+
# }
|
|
64
|
+
# }
|
|
65
|
+
# matcher = permit(:first_name, :last_name, :email, :password).
|
|
66
|
+
# for(:create, params: params).
|
|
67
|
+
# on(:user)
|
|
68
|
+
# assert_accepts matcher, subject
|
|
69
|
+
# end
|
|
70
|
+
# end
|
|
71
|
+
#
|
|
72
|
+
# If your action requires query parameters in order to work, then you'll
|
|
73
|
+
# need to supply them:
|
|
74
|
+
#
|
|
75
|
+
# class UsersController < ApplicationController
|
|
76
|
+
# def update
|
|
77
|
+
# user = User.find(params[:id])
|
|
78
|
+
#
|
|
79
|
+
# if user.update_attributes(user_params)
|
|
80
|
+
# # ...
|
|
81
|
+
# else
|
|
82
|
+
# # ...
|
|
83
|
+
# end
|
|
84
|
+
# end
|
|
85
|
+
#
|
|
86
|
+
# private
|
|
87
|
+
#
|
|
88
|
+
# def user_params
|
|
89
|
+
# params.require(:user).permit(
|
|
90
|
+
# :first_name,
|
|
91
|
+
# :last_name,
|
|
92
|
+
# :email,
|
|
93
|
+
# :password
|
|
94
|
+
# )
|
|
95
|
+
# end
|
|
96
|
+
# end
|
|
97
|
+
#
|
|
98
|
+
# # RSpec
|
|
99
|
+
# RSpec.describe UsersController, type: :controller do
|
|
100
|
+
# before do
|
|
101
|
+
# create(:user, id: 1)
|
|
102
|
+
# end
|
|
103
|
+
#
|
|
104
|
+
# it do
|
|
105
|
+
# params = {
|
|
106
|
+
# id: 1,
|
|
107
|
+
# user: {
|
|
108
|
+
# first_name: 'Jon',
|
|
109
|
+
# last_name: 'Doe',
|
|
110
|
+
# email: 'jondoe@example.com',
|
|
111
|
+
# password: 'password'
|
|
112
|
+
# }
|
|
113
|
+
# }
|
|
114
|
+
# should permit(:first_name, :last_name, :email, :password).
|
|
115
|
+
# for(:update, params: params).
|
|
116
|
+
# on(:user)
|
|
117
|
+
# end
|
|
118
|
+
# end
|
|
119
|
+
#
|
|
120
|
+
# # Minitest (Shoulda)
|
|
121
|
+
# class UsersControllerTest < ActionController::TestCase
|
|
122
|
+
# setup do
|
|
123
|
+
# create(:user, id: 1)
|
|
124
|
+
# end
|
|
125
|
+
#
|
|
126
|
+
# should "(for PATCH #update) restrict parameters on :user to :first_name, :last_name, :email, and :password" do
|
|
127
|
+
# params = {
|
|
128
|
+
# id: 1,
|
|
129
|
+
# user: {
|
|
130
|
+
# first_name: 'Jon',
|
|
131
|
+
# last_name: 'Doe',
|
|
132
|
+
# email: 'jondoe@example.com',
|
|
133
|
+
# password: 'password'
|
|
134
|
+
# }
|
|
135
|
+
# }
|
|
136
|
+
# matcher = permit(:first_name, :last_name, :email, :password).
|
|
137
|
+
# for(:update, params: params).
|
|
138
|
+
# on(:user)
|
|
139
|
+
# assert_accepts matcher, subject
|
|
140
|
+
# end
|
|
141
|
+
# end
|
|
142
|
+
#
|
|
143
|
+
# Finally, if you have an action that isn't one of the seven resourceful
|
|
144
|
+
# actions, then you'll need to provide the HTTP verb that it responds to:
|
|
145
|
+
#
|
|
146
|
+
# Rails.application.routes.draw do
|
|
147
|
+
# resources :users do
|
|
148
|
+
# member do
|
|
149
|
+
# put :toggle
|
|
150
|
+
# end
|
|
151
|
+
# end
|
|
152
|
+
# end
|
|
153
|
+
#
|
|
154
|
+
# class UsersController < ApplicationController
|
|
155
|
+
# def toggle
|
|
156
|
+
# user = User.find(params[:id])
|
|
157
|
+
#
|
|
158
|
+
# if user.update_attributes(user_params)
|
|
159
|
+
# # ...
|
|
160
|
+
# else
|
|
161
|
+
# # ...
|
|
162
|
+
# end
|
|
163
|
+
# end
|
|
164
|
+
#
|
|
165
|
+
# private
|
|
166
|
+
#
|
|
167
|
+
# def user_params
|
|
168
|
+
# params.require(:user).permit(:activated)
|
|
169
|
+
# end
|
|
170
|
+
# end
|
|
171
|
+
#
|
|
172
|
+
# # RSpec
|
|
173
|
+
# RSpec.describe UsersController, type: :controller do
|
|
174
|
+
# before do
|
|
175
|
+
# create(:user, id: 1)
|
|
176
|
+
# end
|
|
177
|
+
#
|
|
178
|
+
# it do
|
|
179
|
+
# params = { id: 1, user: { activated: true } }
|
|
180
|
+
# should permit(:activated).
|
|
181
|
+
# for(:toggle, params: params, verb: :put).
|
|
182
|
+
# on(:user)
|
|
183
|
+
# end
|
|
184
|
+
# end
|
|
185
|
+
#
|
|
186
|
+
# # Minitest (Shoulda)
|
|
187
|
+
# class UsersControllerTest < ActionController::TestCase
|
|
188
|
+
# setup do
|
|
189
|
+
# create(:user, id: 1)
|
|
190
|
+
# end
|
|
191
|
+
#
|
|
192
|
+
# should "(for PUT #toggle) restrict parameters on :user to :activated" do
|
|
193
|
+
# params = { id: 1, user: { activated: true } }
|
|
194
|
+
# matcher = permit(:activated).
|
|
195
|
+
# for(:toggle, params: params, verb: :put).
|
|
196
|
+
# on(:user)
|
|
197
|
+
# assert_accepts matcher, subject
|
|
198
|
+
# end
|
|
199
|
+
# end
|
|
200
|
+
#
|
|
201
|
+
# @return [PermitMatcher]
|
|
202
|
+
#
|
|
203
|
+
def permit(*params)
|
|
204
|
+
PermitMatcher.new(params).in_context(self)
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# @private
|
|
208
|
+
class PermitMatcher
|
|
209
|
+
attr_writer :stubbed_params
|
|
210
|
+
|
|
211
|
+
def initialize(expected_permitted_parameter_names)
|
|
212
|
+
@expected_permitted_parameter_names =
|
|
213
|
+
expected_permitted_parameter_names
|
|
214
|
+
@action = nil
|
|
215
|
+
@verb = nil
|
|
216
|
+
@request_params = {}
|
|
217
|
+
@subparameter_name = nil
|
|
218
|
+
@parameters_double_registry = CompositeParametersDoubleRegistry.new
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def for(action, options = {})
|
|
222
|
+
@action = action
|
|
223
|
+
@verb = options.fetch(:verb, default_verb)
|
|
224
|
+
@request_params = options.fetch(:params, {})
|
|
225
|
+
self
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def add_params(params)
|
|
229
|
+
request_params.merge!(params)
|
|
230
|
+
self
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def on(subparameter_name)
|
|
234
|
+
@subparameter_name = subparameter_name
|
|
235
|
+
self
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def in_context(context)
|
|
239
|
+
@context = context
|
|
240
|
+
self
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def description
|
|
244
|
+
"(for #{verb.upcase} ##{action}) " + expectation
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def matches?(controller)
|
|
248
|
+
@controller = controller
|
|
249
|
+
ensure_action_and_verb_present!
|
|
250
|
+
|
|
251
|
+
parameters_double_registry.register
|
|
252
|
+
|
|
253
|
+
Doublespeak.with_doubles_activated do
|
|
254
|
+
params = { params: request_params }
|
|
255
|
+
|
|
256
|
+
context.__send__(verb, action, **params)
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
unpermitted_parameter_names.empty?
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def failure_message
|
|
263
|
+
"Expected #{verb.upcase} ##{action} to #{expectation},"\
|
|
264
|
+
"\nbut #{reality}."
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def failure_message_when_negated
|
|
268
|
+
"Expected #{verb.upcase} ##{action} not to #{expectation},"\
|
|
269
|
+
"\nbut it did."
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
protected
|
|
273
|
+
|
|
274
|
+
attr_reader :controller, :double_collections_by_parameter_name, :action,
|
|
275
|
+
:verb, :request_params, :expected_permitted_parameter_names,
|
|
276
|
+
:context, :subparameter_name, :parameters_double_registry
|
|
277
|
+
|
|
278
|
+
def expectation
|
|
279
|
+
String.new('restrict parameters ').tap do |message|
|
|
280
|
+
if subparameter_name
|
|
281
|
+
message << "on #{subparameter_name.inspect} "
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
message << 'to '\
|
|
285
|
+
"#{format_parameter_names(expected_permitted_parameter_names)}"
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
def reality
|
|
290
|
+
if actual_permitted_parameter_names.empty?
|
|
291
|
+
'it did not restrict any parameters'
|
|
292
|
+
else
|
|
293
|
+
'the restricted parameters were '\
|
|
294
|
+
"#{format_parameter_names(actual_permitted_parameter_names)}"\
|
|
295
|
+
' instead'
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
def format_parameter_names(parameter_names)
|
|
300
|
+
parameter_names.map(&:inspect).to_sentence
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
def actual_permitted_parameter_names
|
|
304
|
+
@_actual_permitted_parameter_names ||= begin
|
|
305
|
+
options =
|
|
306
|
+
if subparameter_name
|
|
307
|
+
{ for: subparameter_name }
|
|
308
|
+
else
|
|
309
|
+
{}
|
|
310
|
+
end
|
|
311
|
+
parameters_double_registry.permitted_parameter_names(options)
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
def unpermitted_parameter_names
|
|
316
|
+
expected_permitted_parameter_names - actual_permitted_parameter_names
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
def ensure_action_and_verb_present!
|
|
320
|
+
if action.blank?
|
|
321
|
+
raise ActionNotDefinedError
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
if verb.blank?
|
|
325
|
+
raise VerbNotDefinedError
|
|
326
|
+
end
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
def default_verb
|
|
330
|
+
case action
|
|
331
|
+
when :create then :post
|
|
332
|
+
when :update then RailsShim.verb_for_update
|
|
333
|
+
end
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
def parameter_names_as_sentence
|
|
337
|
+
expected_permitted_parameter_names.map(&:inspect).to_sentence
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
# @private
|
|
341
|
+
class CompositeParametersDoubleRegistry
|
|
342
|
+
def initialize
|
|
343
|
+
@parameters_double_registries = []
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
def register
|
|
347
|
+
double_collection = Doublespeak.double_collection_for(
|
|
348
|
+
::ActionController::Parameters.singleton_class,
|
|
349
|
+
)
|
|
350
|
+
double_collection.register_proxy(:new).to_return do |call|
|
|
351
|
+
params = call.return_value
|
|
352
|
+
parameters_double_registry = ParametersDoubleRegistry.new(params)
|
|
353
|
+
parameters_double_registry.register
|
|
354
|
+
parameters_double_registries << parameters_double_registry
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
def permitted_parameter_names(options = {})
|
|
359
|
+
parameters_double_registries.flat_map do |double_registry|
|
|
360
|
+
double_registry.permitted_parameter_names(options)
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
protected
|
|
365
|
+
|
|
366
|
+
attr_reader :parameters_double_registries
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
# @private
|
|
370
|
+
class ParametersDoubleRegistry
|
|
371
|
+
TOP_LEVEL = Object.new
|
|
372
|
+
|
|
373
|
+
def self.permitted_parameter_names_within(double_collection)
|
|
374
|
+
double_collection.calls_to(:permit).map(&:args).flatten
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
def initialize(params)
|
|
378
|
+
@params = params
|
|
379
|
+
@double_collections_by_parameter_name = {}
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
def register
|
|
383
|
+
register_double_for_permit_against(params, TOP_LEVEL)
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
def permitted_parameter_names(args = {})
|
|
387
|
+
subparameter_name = args.fetch(:for, TOP_LEVEL)
|
|
388
|
+
|
|
389
|
+
if double_collections_by_parameter_name.key?(subparameter_name)
|
|
390
|
+
self.class.permitted_parameter_names_within(
|
|
391
|
+
double_collections_by_parameter_name[subparameter_name],
|
|
392
|
+
)
|
|
393
|
+
else
|
|
394
|
+
[]
|
|
395
|
+
end
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
protected
|
|
399
|
+
|
|
400
|
+
attr_reader :params, :double_collections_by_parameter_name
|
|
401
|
+
|
|
402
|
+
private
|
|
403
|
+
|
|
404
|
+
def register_double_for_permit_against(params, subparameter_name)
|
|
405
|
+
klass = params.singleton_class
|
|
406
|
+
|
|
407
|
+
double_collection = Doublespeak.double_collection_for(klass)
|
|
408
|
+
register_double_for_permit_on(double_collection)
|
|
409
|
+
register_double_for_require_on(double_collection)
|
|
410
|
+
|
|
411
|
+
double_collections_by_parameter_name[subparameter_name] =
|
|
412
|
+
double_collection
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
def register_double_for_permit_on(double_collection)
|
|
416
|
+
double_collection.register_proxy(:permit)
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
def register_double_for_require_on(double_collection)
|
|
420
|
+
double_collection.register_proxy(:require).to_return do |call|
|
|
421
|
+
params = call.return_value
|
|
422
|
+
subparameter_name = call.args.first
|
|
423
|
+
register_double_for_permit_against(params, subparameter_name)
|
|
424
|
+
end
|
|
425
|
+
end
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
# @private
|
|
429
|
+
class ActionNotDefinedError < StandardError
|
|
430
|
+
def message
|
|
431
|
+
'You must specify the controller action using the #for method.'
|
|
432
|
+
end
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
# @private
|
|
436
|
+
class VerbNotDefinedError < StandardError
|
|
437
|
+
def message
|
|
438
|
+
'You must specify an HTTP verb when using a non-RESTful action.'\
|
|
439
|
+
' For example: for(:authorize, verb: :post)'
|
|
440
|
+
end
|
|
441
|
+
end
|
|
442
|
+
end
|
|
443
|
+
end
|
|
444
|
+
end
|
|
445
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
module Shoulda
|
|
2
|
+
module Matchers
|
|
3
|
+
module ActionController
|
|
4
|
+
# The `redirect_to` matcher tests that an action redirects to a certain
|
|
5
|
+
# location. In a test suite using RSpec, it is very similar to
|
|
6
|
+
# rspec-rails's `redirect_to` matcher. In a test suite using Minitest +
|
|
7
|
+
# Shoulda, it provides a more expressive syntax over
|
|
8
|
+
# `assert_redirected_to`.
|
|
9
|
+
#
|
|
10
|
+
# class PostsController < ApplicationController
|
|
11
|
+
# def show
|
|
12
|
+
# redirect_to :index
|
|
13
|
+
# end
|
|
14
|
+
# end
|
|
15
|
+
#
|
|
16
|
+
# # RSpec
|
|
17
|
+
# RSpec.describe PostsController, type: :controller do
|
|
18
|
+
# describe 'GET #show' do
|
|
19
|
+
# before { get :show }
|
|
20
|
+
#
|
|
21
|
+
# it { should redirect_to(posts_path) }
|
|
22
|
+
# it { should redirect_to(action: :index) }
|
|
23
|
+
# end
|
|
24
|
+
# end
|
|
25
|
+
#
|
|
26
|
+
# # Minitest (Shoulda)
|
|
27
|
+
# class PostsControllerTest < ActionController::TestCase
|
|
28
|
+
# context 'GET #show' do
|
|
29
|
+
# setup { get :show }
|
|
30
|
+
#
|
|
31
|
+
# should redirect_to('/posts') { posts_path }
|
|
32
|
+
# should redirect_to(action: :index)
|
|
33
|
+
# end
|
|
34
|
+
# end
|
|
35
|
+
#
|
|
36
|
+
# @return [RedirectToMatcher]
|
|
37
|
+
#
|
|
38
|
+
def redirect_to(url_or_description, &block)
|
|
39
|
+
RedirectToMatcher.new(url_or_description, self, &block)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @private
|
|
43
|
+
class RedirectToMatcher
|
|
44
|
+
attr_reader :failure_message, :failure_message_when_negated
|
|
45
|
+
|
|
46
|
+
def initialize(url_or_description, context, &block)
|
|
47
|
+
@url_block = nil
|
|
48
|
+
@url = nil
|
|
49
|
+
@context = context
|
|
50
|
+
@failure_message = nil
|
|
51
|
+
@failure_message_when_negated = nil
|
|
52
|
+
|
|
53
|
+
if block
|
|
54
|
+
@url_block = block
|
|
55
|
+
@location = url_or_description
|
|
56
|
+
else
|
|
57
|
+
@location = @url = url_or_description
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def in_context(context)
|
|
62
|
+
@context = context
|
|
63
|
+
self
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def matches?(controller)
|
|
67
|
+
@controller = controller
|
|
68
|
+
redirects_to_url?
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def description
|
|
72
|
+
"redirect to #{@location.inspect}"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
private
|
|
76
|
+
|
|
77
|
+
def redirects_to_url?
|
|
78
|
+
@context.__send__(:assert_redirected_to, url)
|
|
79
|
+
@failure_message_when_negated = "Didn't expect to redirect to #{url}"
|
|
80
|
+
true
|
|
81
|
+
rescue Shoulda::Matchers.assertion_exception_class => e
|
|
82
|
+
@failure_message = e.message
|
|
83
|
+
false
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def url
|
|
87
|
+
if @url_block
|
|
88
|
+
@context.instance_eval(&@url_block)
|
|
89
|
+
else
|
|
90
|
+
@url
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
module Shoulda
|
|
2
|
+
module Matchers
|
|
3
|
+
module ActionController
|
|
4
|
+
# The `render_template` matcher tests that an action renders a template
|
|
5
|
+
# or partial. In RSpec, it is very similar to rspec-rails's
|
|
6
|
+
# `render_template` matcher. In a test suite using Minitest + Shoulda, it
|
|
7
|
+
# provides a more expressive syntax over `assert_template`.
|
|
8
|
+
#
|
|
9
|
+
# class PostsController < ApplicationController
|
|
10
|
+
# def show
|
|
11
|
+
# end
|
|
12
|
+
# end
|
|
13
|
+
#
|
|
14
|
+
# # app/views/posts/show.html.erb
|
|
15
|
+
# <%= render 'sidebar' %>
|
|
16
|
+
#
|
|
17
|
+
# # RSpec
|
|
18
|
+
# RSpec.describe PostsController, type: :controller do
|
|
19
|
+
# describe 'GET #show' do
|
|
20
|
+
# before { get :show }
|
|
21
|
+
#
|
|
22
|
+
# it { should render_template('show') }
|
|
23
|
+
# it { should render_template(partial: '_sidebar') }
|
|
24
|
+
# end
|
|
25
|
+
# end
|
|
26
|
+
#
|
|
27
|
+
# # Minitest (Shoulda)
|
|
28
|
+
# class PostsControllerTest < ActionController::TestCase
|
|
29
|
+
# context 'GET #show' do
|
|
30
|
+
# setup { get :show }
|
|
31
|
+
#
|
|
32
|
+
# should render_template('show')
|
|
33
|
+
# should render_template(partial: '_sidebar')
|
|
34
|
+
# end
|
|
35
|
+
# end
|
|
36
|
+
#
|
|
37
|
+
# @return [RenderTemplateMatcher]
|
|
38
|
+
#
|
|
39
|
+
def render_template(options = {}, message = nil)
|
|
40
|
+
RenderTemplateMatcher.new(options, message, self)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# @private
|
|
44
|
+
class RenderTemplateMatcher
|
|
45
|
+
attr_reader :failure_message, :failure_message_when_negated
|
|
46
|
+
|
|
47
|
+
def initialize(options, message, context)
|
|
48
|
+
@options = options
|
|
49
|
+
@message = message
|
|
50
|
+
@template = options.is_a?(Hash) ? options[:partial] : options
|
|
51
|
+
@context = context
|
|
52
|
+
@controller = nil
|
|
53
|
+
@failure_message = nil
|
|
54
|
+
@failure_message_when_negated = nil
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def matches?(controller)
|
|
58
|
+
@controller = controller
|
|
59
|
+
renders_template?
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def description
|
|
63
|
+
"render template #{@template}"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def in_context(context)
|
|
67
|
+
@context = context
|
|
68
|
+
self
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
def renders_template?
|
|
74
|
+
@context.__send__(:assert_template, @options, @message)
|
|
75
|
+
@failure_message_when_negated = "Didn't expect to render #{@template}"
|
|
76
|
+
true
|
|
77
|
+
rescue Shoulda::Matchers.assertion_exception_class => e
|
|
78
|
+
@failure_message = e.message
|
|
79
|
+
false
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|