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,540 @@
|
|
|
1
|
+
require 'shoulda/matchers/doublespeak'
|
|
2
|
+
require 'shoulda/matchers/matcher_context'
|
|
3
|
+
|
|
4
|
+
module Shoulda
|
|
5
|
+
module Matchers
|
|
6
|
+
module Independent
|
|
7
|
+
# The `delegate_method` matcher tests that an object forwards messages
|
|
8
|
+
# to other, internal objects by way of delegation.
|
|
9
|
+
#
|
|
10
|
+
# In this example, we test that Courier forwards a call to #deliver onto
|
|
11
|
+
# its PostOffice instance:
|
|
12
|
+
#
|
|
13
|
+
# require 'forwardable'
|
|
14
|
+
#
|
|
15
|
+
# class Courier
|
|
16
|
+
# extend Forwardable
|
|
17
|
+
#
|
|
18
|
+
# attr_reader :post_office
|
|
19
|
+
#
|
|
20
|
+
# def_delegators :post_office, :deliver
|
|
21
|
+
#
|
|
22
|
+
# def initialize
|
|
23
|
+
# @post_office = PostOffice.new
|
|
24
|
+
# end
|
|
25
|
+
# end
|
|
26
|
+
#
|
|
27
|
+
# # RSpec
|
|
28
|
+
# describe Courier do
|
|
29
|
+
# it { should delegate_method(:deliver).to(:post_office) }
|
|
30
|
+
# end
|
|
31
|
+
#
|
|
32
|
+
# # Minitest
|
|
33
|
+
# class CourierTest < Minitest::Test
|
|
34
|
+
# should delegate_method(:deliver).to(:post_office)
|
|
35
|
+
# end
|
|
36
|
+
#
|
|
37
|
+
# You can also use `delegate_method` with Rails's `delegate` macro:
|
|
38
|
+
#
|
|
39
|
+
# class Courier
|
|
40
|
+
# attr_reader :post_office
|
|
41
|
+
# delegate :deliver, to: :post_office
|
|
42
|
+
#
|
|
43
|
+
# def initialize
|
|
44
|
+
# @post_office = PostOffice.new
|
|
45
|
+
# end
|
|
46
|
+
# end
|
|
47
|
+
#
|
|
48
|
+
# describe Courier do
|
|
49
|
+
# it { should delegate_method(:deliver).to(:post_office) }
|
|
50
|
+
# end
|
|
51
|
+
#
|
|
52
|
+
# To employ some terminology, we would say that Courier's #deliver method
|
|
53
|
+
# is the *delegating method*, PostOffice is the *delegate object*, and
|
|
54
|
+
# PostOffice#deliver is the *delegate method*.
|
|
55
|
+
#
|
|
56
|
+
# #### Qualifiers
|
|
57
|
+
#
|
|
58
|
+
# ##### as
|
|
59
|
+
#
|
|
60
|
+
# Use `as` if the name of the delegate method is different from the name
|
|
61
|
+
# of the delegating method.
|
|
62
|
+
#
|
|
63
|
+
# Here, Courier has a #deliver method, but instead of calling #deliver on
|
|
64
|
+
# the PostOffice, it calls #ship:
|
|
65
|
+
#
|
|
66
|
+
# class Courier
|
|
67
|
+
# attr_reader :post_office
|
|
68
|
+
#
|
|
69
|
+
# def initialize
|
|
70
|
+
# @post_office = PostOffice.new
|
|
71
|
+
# end
|
|
72
|
+
#
|
|
73
|
+
# def deliver(package)
|
|
74
|
+
# post_office.ship(package)
|
|
75
|
+
# end
|
|
76
|
+
# end
|
|
77
|
+
#
|
|
78
|
+
# # RSpec
|
|
79
|
+
# describe Courier do
|
|
80
|
+
# it { should delegate_method(:deliver).to(:post_office).as(:ship) }
|
|
81
|
+
# end
|
|
82
|
+
#
|
|
83
|
+
# # Minitest
|
|
84
|
+
# class CourierTest < Minitest::Test
|
|
85
|
+
# should delegate_method(:deliver).to(:post_office).as(:ship)
|
|
86
|
+
# end
|
|
87
|
+
#
|
|
88
|
+
# ##### with_prefix
|
|
89
|
+
#
|
|
90
|
+
# Use `with_prefix` when using Rails's `delegate` helper along with the
|
|
91
|
+
# `:prefix` option.
|
|
92
|
+
#
|
|
93
|
+
# class Page < ActiveRecord::Base
|
|
94
|
+
# belongs_to :site
|
|
95
|
+
# delegate :name, to: :site, prefix: true
|
|
96
|
+
# delegate :title, to: :site, prefix: :root
|
|
97
|
+
# end
|
|
98
|
+
#
|
|
99
|
+
# # RSpec
|
|
100
|
+
# describe Page do
|
|
101
|
+
# it { should delegate_method(:name).to(:site).with_prefix }
|
|
102
|
+
# it { should delegate_method(:name).to(:site).with_prefix(true) }
|
|
103
|
+
# it { should delegate_method(:title).to(:site).with_prefix(:root) }
|
|
104
|
+
# end
|
|
105
|
+
#
|
|
106
|
+
# # Minitest
|
|
107
|
+
# class PageTest < Minitest::Test
|
|
108
|
+
# should delegate_method(:name).to(:site).with_prefix
|
|
109
|
+
# should delegate_method(:name).to(:site).with_prefix(true)
|
|
110
|
+
# should delegate_method(:title).to(:site).with_prefix(:root)
|
|
111
|
+
# end
|
|
112
|
+
#
|
|
113
|
+
# ##### with_arguments
|
|
114
|
+
#
|
|
115
|
+
# Use `with_arguments` to assert that the delegate method is called with
|
|
116
|
+
# certain arguments. Note that this qualifier can only be used when the
|
|
117
|
+
# delegating method takes no arguments; it does not support delegating
|
|
118
|
+
# or delegate methods that take arbitrary arguments.
|
|
119
|
+
#
|
|
120
|
+
# Here, when Courier#deliver_package calls PostOffice#deliver_package, it
|
|
121
|
+
# adds an options hash:
|
|
122
|
+
#
|
|
123
|
+
# class Courier
|
|
124
|
+
# attr_reader :post_office
|
|
125
|
+
#
|
|
126
|
+
# def initialize
|
|
127
|
+
# @post_office = PostOffice.new
|
|
128
|
+
# end
|
|
129
|
+
#
|
|
130
|
+
# def deliver_package
|
|
131
|
+
# post_office.deliver_package(expedited: true)
|
|
132
|
+
# end
|
|
133
|
+
# end
|
|
134
|
+
#
|
|
135
|
+
# # RSpec
|
|
136
|
+
# describe Courier do
|
|
137
|
+
# it do
|
|
138
|
+
# should delegate_method(:deliver_package).
|
|
139
|
+
# to(:post_office).
|
|
140
|
+
# with_arguments(expedited: true)
|
|
141
|
+
# end
|
|
142
|
+
# end
|
|
143
|
+
#
|
|
144
|
+
# # Minitest
|
|
145
|
+
# class CourierTest < Minitest::Test
|
|
146
|
+
# should delegate_method(:deliver_package).
|
|
147
|
+
# to(:post_office).
|
|
148
|
+
# with_arguments(expedited: true)
|
|
149
|
+
# end
|
|
150
|
+
#
|
|
151
|
+
# ##### allow_nil
|
|
152
|
+
#
|
|
153
|
+
# Use `allow_nil` if the delegation accounts for the fact that your
|
|
154
|
+
# delegate object could be nil. (This is mostly intended as an analogue to
|
|
155
|
+
# the `allow_nil` option that Rails' `delegate` helper takes.)
|
|
156
|
+
#
|
|
157
|
+
# class Account
|
|
158
|
+
# delegate :plan, to: :subscription, allow_nil: true
|
|
159
|
+
# end
|
|
160
|
+
#
|
|
161
|
+
# # RSpec
|
|
162
|
+
# describe Account do
|
|
163
|
+
# it { should delegate_method(:plan).to(:subscription).allow_nil }
|
|
164
|
+
# end
|
|
165
|
+
#
|
|
166
|
+
# # Minitest
|
|
167
|
+
# class PageTest < Minitest::Test
|
|
168
|
+
# should delegate_method(:plan).to(:subscription).allow_nil
|
|
169
|
+
# end
|
|
170
|
+
#
|
|
171
|
+
# ##### with_private
|
|
172
|
+
#
|
|
173
|
+
# Use `with_private` if the delegation accounts for the fact that your
|
|
174
|
+
# delegation is private. (This is mostly intended as an analogue to
|
|
175
|
+
# the `private` option that Rails' `delegate` helper takes.)
|
|
176
|
+
#
|
|
177
|
+
# class Account
|
|
178
|
+
# delegate :plan, to: :subscription, private: true
|
|
179
|
+
# end
|
|
180
|
+
#
|
|
181
|
+
# # RSpec
|
|
182
|
+
# describe Account do
|
|
183
|
+
# it { should delegate_method(:plan).to(:subscription).with_private }
|
|
184
|
+
# end
|
|
185
|
+
#
|
|
186
|
+
# # Minitest
|
|
187
|
+
# class PageTest < Minitest::Test
|
|
188
|
+
# should delegate_method(:plan).to(:subscription).with_private
|
|
189
|
+
# end
|
|
190
|
+
#
|
|
191
|
+
# @return [DelegateMethodMatcher]
|
|
192
|
+
def delegate_method(delegating_method)
|
|
193
|
+
DelegateMethodMatcher.new(delegating_method).in_context(self)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# @private
|
|
197
|
+
class DelegateMethodMatcher
|
|
198
|
+
def initialize(delegating_method)
|
|
199
|
+
@delegating_method = delegating_method
|
|
200
|
+
|
|
201
|
+
@delegate_method = @delegating_method
|
|
202
|
+
@delegate_object = Doublespeak::ObjectDouble.new
|
|
203
|
+
|
|
204
|
+
@context = nil
|
|
205
|
+
@subject = nil
|
|
206
|
+
@delegate_object_reader_method = nil
|
|
207
|
+
@delegated_arguments = []
|
|
208
|
+
@expects_to_allow_nil_delegate_object = false
|
|
209
|
+
@expects_private_delegation = false
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def in_context(context)
|
|
213
|
+
@context = MatcherContext.new(context)
|
|
214
|
+
self
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def matches?(subject)
|
|
218
|
+
@subject = subject
|
|
219
|
+
|
|
220
|
+
ensure_delegate_object_has_been_specified!
|
|
221
|
+
|
|
222
|
+
subject_has_delegating_method? &&
|
|
223
|
+
subject_has_delegate_object_reader_method? &&
|
|
224
|
+
subject_delegates_to_delegate_object_correctly? &&
|
|
225
|
+
subject_handles_nil_delegate_object? &&
|
|
226
|
+
subject_handles_private_delegation?
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def description
|
|
230
|
+
string =
|
|
231
|
+
"delegate #{formatted_delegating_method_name} to the " +
|
|
232
|
+
"#{formatted_delegate_object_reader_method_name} object"
|
|
233
|
+
|
|
234
|
+
if expects_private_delegation?
|
|
235
|
+
string << ' privately'
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
if delegated_arguments.any?
|
|
239
|
+
string << " passing arguments #{delegated_arguments.inspect}"
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
if delegate_method != delegating_method
|
|
243
|
+
string << " as #{formatted_delegate_method}"
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
if expects_to_allow_nil_delegate_object?
|
|
247
|
+
string << ', allowing '
|
|
248
|
+
string << formatted_delegate_object_reader_method_name
|
|
249
|
+
string << ' to return nil'
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
string
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def to(delegate_object_reader_method)
|
|
256
|
+
@delegate_object_reader_method = delegate_object_reader_method
|
|
257
|
+
self
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def as(delegate_method)
|
|
261
|
+
@delegate_method = delegate_method
|
|
262
|
+
self
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def with_arguments(*arguments)
|
|
266
|
+
@delegated_arguments = arguments
|
|
267
|
+
self
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
def with_prefix(prefix = nil)
|
|
271
|
+
@delegating_method =
|
|
272
|
+
:"#{build_delegating_method_prefix(prefix)}_#{delegate_method}"
|
|
273
|
+
delegate_method
|
|
274
|
+
self
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
def allow_nil
|
|
278
|
+
@expects_to_allow_nil_delegate_object = true
|
|
279
|
+
self
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
def with_private
|
|
283
|
+
@expects_private_delegation = true
|
|
284
|
+
self
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def build_delegating_method_prefix(prefix)
|
|
288
|
+
case prefix
|
|
289
|
+
when true, nil then delegate_object_reader_method
|
|
290
|
+
else prefix
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
def failure_message
|
|
295
|
+
message = "Expected #{class_under_test} to #{description}.\n\n"
|
|
296
|
+
|
|
297
|
+
if failed_to_allow_nil_delegate_object? || failed_to_handle_private_delegation?
|
|
298
|
+
message << formatted_delegating_method_name(include_module: true)
|
|
299
|
+
message << ' did delegate to '
|
|
300
|
+
message << formatted_delegate_object_reader_method_name
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
if failed_to_allow_nil_delegate_object?
|
|
304
|
+
message << ' when it was non-nil, but it failed to account '
|
|
305
|
+
message << 'for when '
|
|
306
|
+
message << formatted_delegate_object_reader_method_name
|
|
307
|
+
message << ' *was* nil.'
|
|
308
|
+
elsif failed_to_handle_private_delegation?
|
|
309
|
+
message << ", but 'private: true' is missing."
|
|
310
|
+
else
|
|
311
|
+
message << 'Method calls sent to '
|
|
312
|
+
message << formatted_delegate_object_reader_method_name(
|
|
313
|
+
include_module: true,
|
|
314
|
+
)
|
|
315
|
+
message << ": #{formatted_calls_on_delegate_object}"
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
Shoulda::Matchers.word_wrap(message)
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
def failure_message_when_negated
|
|
322
|
+
"Expected #{class_under_test} not to #{description}, but it did."
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
protected
|
|
326
|
+
|
|
327
|
+
attr_reader \
|
|
328
|
+
:context,
|
|
329
|
+
:delegated_arguments,
|
|
330
|
+
:delegating_method,
|
|
331
|
+
:method,
|
|
332
|
+
:delegate_method,
|
|
333
|
+
:delegate_object,
|
|
334
|
+
:delegate_object_reader_method
|
|
335
|
+
|
|
336
|
+
def subject
|
|
337
|
+
@subject
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
def subject_is_a_class?
|
|
341
|
+
if @subject
|
|
342
|
+
@subject.is_a?(Class)
|
|
343
|
+
else
|
|
344
|
+
context.subject_is_a_class?
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
def class_under_test
|
|
349
|
+
if subject_is_a_class?
|
|
350
|
+
subject
|
|
351
|
+
else
|
|
352
|
+
subject.class
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
def expects_to_allow_nil_delegate_object?
|
|
357
|
+
@expects_to_allow_nil_delegate_object
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
def expects_private_delegation?
|
|
361
|
+
@expects_private_delegation
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
def formatted_delegate_method(options = {})
|
|
365
|
+
formatted_method_name_for(delegate_method, options)
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
def formatted_delegating_method_name(options = {})
|
|
369
|
+
formatted_method_name_for(delegating_method, options)
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
def formatted_delegate_object_reader_method_name(options = {})
|
|
373
|
+
formatted_method_name_for(delegate_object_reader_method, options)
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
def formatted_method_name_for(method_name, options)
|
|
377
|
+
possible_class_under_test(options) +
|
|
378
|
+
class_or_instance_method_indicator +
|
|
379
|
+
method_name.to_s
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
def possible_class_under_test(options)
|
|
383
|
+
if options[:include_module]
|
|
384
|
+
class_under_test.to_s
|
|
385
|
+
else
|
|
386
|
+
''
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
def class_or_instance_method_indicator
|
|
391
|
+
if subject_is_a_class?
|
|
392
|
+
'.'
|
|
393
|
+
else
|
|
394
|
+
'#'
|
|
395
|
+
end
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
def delegate_object_received_call?
|
|
399
|
+
calls_to_delegate_method.any?
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
def delegate_object_received_call_with_delegated_arguments?
|
|
403
|
+
calls_to_delegate_method.any? do |call|
|
|
404
|
+
call.args == delegated_arguments
|
|
405
|
+
end
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
def subject_has_delegating_method?
|
|
409
|
+
if expects_private_delegation?
|
|
410
|
+
!subject.respond_to?(delegating_method) && subject.respond_to?(delegating_method, true)
|
|
411
|
+
else
|
|
412
|
+
subject.respond_to?(delegating_method)
|
|
413
|
+
end
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
def subject_has_delegate_object_reader_method?
|
|
417
|
+
subject.respond_to?(delegate_object_reader_method, true)
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
def ensure_delegate_object_has_been_specified!
|
|
421
|
+
if delegate_object_reader_method.to_s.empty?
|
|
422
|
+
raise DelegateObjectNotSpecified
|
|
423
|
+
end
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
def subject_delegates_to_delegate_object_correctly?
|
|
427
|
+
if expects_private_delegation?
|
|
428
|
+
privately_call_delegating_method_with_delegate_method_returning(delegate_object)
|
|
429
|
+
else
|
|
430
|
+
call_delegating_method_with_delegate_method_returning(delegate_object)
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
if delegated_arguments.any?
|
|
434
|
+
delegate_object_received_call_with_delegated_arguments?
|
|
435
|
+
else
|
|
436
|
+
delegate_object_received_call?
|
|
437
|
+
end
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
def subject_handles_nil_delegate_object?
|
|
441
|
+
@subject_handled_nil_delegate_object =
|
|
442
|
+
if expects_to_allow_nil_delegate_object?
|
|
443
|
+
begin
|
|
444
|
+
call_delegating_method_with_delegate_method_returning(nil)
|
|
445
|
+
true
|
|
446
|
+
rescue Module::DelegationError
|
|
447
|
+
false
|
|
448
|
+
rescue NoMethodError => e
|
|
449
|
+
if e.message =~ /undefined method [`']#{delegate_method}[`'] for nil/
|
|
450
|
+
false
|
|
451
|
+
else
|
|
452
|
+
raise e
|
|
453
|
+
end
|
|
454
|
+
end
|
|
455
|
+
else
|
|
456
|
+
true
|
|
457
|
+
end
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
def subject_handles_private_delegation?
|
|
461
|
+
@subject_handled_private_delegation =
|
|
462
|
+
if expects_private_delegation?
|
|
463
|
+
begin
|
|
464
|
+
call_delegating_method_with_delegate_method_returning(delegate_object)
|
|
465
|
+
true
|
|
466
|
+
rescue Module::DelegationError
|
|
467
|
+
false
|
|
468
|
+
rescue NoMethodError => e
|
|
469
|
+
if e.message =~ /private method [`']#{delegating_method}[`'] called for/
|
|
470
|
+
true
|
|
471
|
+
else
|
|
472
|
+
raise e
|
|
473
|
+
end
|
|
474
|
+
end
|
|
475
|
+
else
|
|
476
|
+
true
|
|
477
|
+
end
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
def failed_to_allow_nil_delegate_object?
|
|
481
|
+
expects_to_allow_nil_delegate_object? &&
|
|
482
|
+
!@subject_handled_nil_delegate_object
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
def failed_to_handle_private_delegation?
|
|
486
|
+
expects_private_delegation? &&
|
|
487
|
+
!@subject_handled_private_delegation
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
def call_delegating_method_with_delegate_method_returning(value)
|
|
491
|
+
register_subject_double_collection_to(value)
|
|
492
|
+
|
|
493
|
+
Doublespeak.with_doubles_activated do
|
|
494
|
+
subject.public_send(delegating_method, *delegated_arguments)
|
|
495
|
+
end
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
def privately_call_delegating_method_with_delegate_method_returning(value)
|
|
499
|
+
register_subject_double_collection_to(value)
|
|
500
|
+
|
|
501
|
+
Doublespeak.with_doubles_activated do
|
|
502
|
+
subject.__send__(delegating_method, *delegated_arguments)
|
|
503
|
+
end
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
def register_subject_double_collection_to(returned_value)
|
|
507
|
+
double_collection =
|
|
508
|
+
Doublespeak.double_collection_for(subject.singleton_class)
|
|
509
|
+
double_collection.register_stub(delegate_object_reader_method).
|
|
510
|
+
to_return(returned_value)
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
def calls_to_delegate_method
|
|
514
|
+
delegate_object.calls_to(delegate_method)
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
def calls_on_delegate_object
|
|
518
|
+
delegate_object.calls
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
def formatted_calls_on_delegate_object
|
|
522
|
+
String.new.tap do |string|
|
|
523
|
+
if calls_on_delegate_object.any?
|
|
524
|
+
string << "\n\n"
|
|
525
|
+
calls_on_delegate_object.each_with_index do |call, i|
|
|
526
|
+
name = call.method_name
|
|
527
|
+
args = call.args.map(&:inspect).join(', ')
|
|
528
|
+
string << "#{i + 1}) #{name}(#{args})\n"
|
|
529
|
+
end
|
|
530
|
+
else
|
|
531
|
+
string << ' (none)'
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
string.rstrip!
|
|
535
|
+
end
|
|
536
|
+
end
|
|
537
|
+
end
|
|
538
|
+
end
|
|
539
|
+
end
|
|
540
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
require 'shoulda/matchers/independent/delegate_method_matcher'
|
|
2
|
+
require 'shoulda/matchers/independent/delegate_method_matcher/target_not_defined_error'
|
|
3
|
+
|
|
4
|
+
module Shoulda
|
|
5
|
+
module Matchers
|
|
6
|
+
# This module provides matchers that are used to test behavior outside of
|
|
7
|
+
# Rails-specific classes.
|
|
8
|
+
module Independent
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
module Shoulda
|
|
2
|
+
module Matchers
|
|
3
|
+
module Integrations
|
|
4
|
+
# @private
|
|
5
|
+
class Configuration
|
|
6
|
+
def self.apply(&block)
|
|
7
|
+
new(&block).apply
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
attr_reader :test_frameworks
|
|
11
|
+
|
|
12
|
+
def initialize(&block)
|
|
13
|
+
@test_frameworks = Set.new
|
|
14
|
+
@libraries = Set.new
|
|
15
|
+
|
|
16
|
+
test_framework :missing_test_framework
|
|
17
|
+
library :missing_library
|
|
18
|
+
|
|
19
|
+
block.call(self)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def test_framework(name)
|
|
23
|
+
clear_default_test_framework
|
|
24
|
+
@test_frameworks << Integrations.find_test_framework!(name)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def library(name)
|
|
28
|
+
@libraries << Integrations.find_library!(name)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def apply
|
|
32
|
+
if no_test_frameworks_added? && no_libraries_added?
|
|
33
|
+
raise ConfigurationError, <<EOT
|
|
34
|
+
shoulda-matchers is not configured correctly. You need to specify at least one
|
|
35
|
+
test framework and/or library. For example:
|
|
36
|
+
|
|
37
|
+
Shoulda::Matchers.configure do |config|
|
|
38
|
+
config.integrate do |with|
|
|
39
|
+
with.test_framework :rspec
|
|
40
|
+
with.library :rails
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
EOT
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
@test_frameworks.each do |test_framework|
|
|
47
|
+
test_framework.include(Shoulda::Matchers::Independent)
|
|
48
|
+
@libraries.each { |library| library.integrate_with(test_framework) }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
self
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
def clear_default_test_framework
|
|
57
|
+
@test_frameworks.select!(&:present?)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def no_test_frameworks_added?
|
|
61
|
+
@test_frameworks.empty? || @test_frameworks.none?(&:present?)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def no_libraries_added?
|
|
65
|
+
@libraries.empty?
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Shoulda
|
|
2
|
+
module Matchers
|
|
3
|
+
module Integrations
|
|
4
|
+
# @private
|
|
5
|
+
module Inclusion
|
|
6
|
+
def include_into(mod, *other_mods, &block)
|
|
7
|
+
mods_to_include = other_mods.dup
|
|
8
|
+
mods_to_extend = other_mods.dup
|
|
9
|
+
|
|
10
|
+
if block
|
|
11
|
+
mods_to_include << Module.new(&block)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
mod.__send__(:include, *mods_to_include)
|
|
15
|
+
mod.extend(*mods_to_extend)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module Shoulda
|
|
2
|
+
module Matchers
|
|
3
|
+
module Integrations
|
|
4
|
+
module Libraries
|
|
5
|
+
# @private
|
|
6
|
+
class ActionController
|
|
7
|
+
Integrations.register_library(self, :action_controller)
|
|
8
|
+
|
|
9
|
+
include Integrations::Inclusion
|
|
10
|
+
include Integrations::Rails
|
|
11
|
+
|
|
12
|
+
def integrate_with(test_framework)
|
|
13
|
+
test_framework.include(matchers_module, type: :controller)
|
|
14
|
+
|
|
15
|
+
tap do |instance|
|
|
16
|
+
ActiveSupport.on_load(:action_controller_test_case, run_once: true) do
|
|
17
|
+
instance.include_into(::ActionController::TestCase, instance.matchers_module) do
|
|
18
|
+
def subject # rubocop:disable Lint/NestedMethodDefinition
|
|
19
|
+
@controller
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def matchers_module
|
|
27
|
+
Shoulda::Matchers::ActionController
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Shoulda
|
|
2
|
+
module Matchers
|
|
3
|
+
module Integrations
|
|
4
|
+
module Libraries
|
|
5
|
+
# @private
|
|
6
|
+
class ActiveModel
|
|
7
|
+
Integrations.register_library(self, :active_model)
|
|
8
|
+
|
|
9
|
+
include Integrations::Inclusion
|
|
10
|
+
include Integrations::Rails
|
|
11
|
+
|
|
12
|
+
def integrate_with(test_framework)
|
|
13
|
+
test_framework.include(matchers_module, type: :model)
|
|
14
|
+
include_into(ActiveSupport::TestCase, matchers_module)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def matchers_module
|
|
20
|
+
Shoulda::Matchers::ActiveModel
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|