activesupport 6.0.6.1 → 7.1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +865 -438
- data/MIT-LICENSE +1 -1
- data/README.rdoc +6 -6
- data/lib/active_support/actionable_error.rb +4 -2
- data/lib/active_support/array_inquirer.rb +4 -2
- data/lib/active_support/backtrace_cleaner.rb +30 -10
- data/lib/active_support/benchmarkable.rb +4 -3
- data/lib/active_support/broadcast_logger.rb +250 -0
- data/lib/active_support/builder.rb +1 -1
- data/lib/active_support/cache/coder.rb +153 -0
- data/lib/active_support/cache/entry.rb +134 -0
- data/lib/active_support/cache/file_store.rb +53 -20
- data/lib/active_support/cache/mem_cache_store.rb +208 -63
- data/lib/active_support/cache/memory_store.rb +120 -38
- data/lib/active_support/cache/null_store.rb +16 -2
- data/lib/active_support/cache/redis_cache_store.rb +201 -208
- data/lib/active_support/cache/serializer_with_fallback.rb +175 -0
- data/lib/active_support/cache/strategy/local_cache.rb +73 -66
- data/lib/active_support/cache.rb +539 -261
- data/lib/active_support/callbacks.rb +273 -142
- data/lib/active_support/code_generator.rb +65 -0
- data/lib/active_support/concern.rb +53 -7
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +44 -7
- data/lib/active_support/concurrency/null_lock.rb +13 -0
- data/lib/active_support/concurrency/share_lock.rb +2 -2
- data/lib/active_support/configurable.rb +19 -6
- data/lib/active_support/configuration_file.rb +51 -0
- data/lib/active_support/core_ext/array/access.rb +1 -5
- data/lib/active_support/core_ext/array/conversions.rb +15 -13
- data/lib/active_support/core_ext/array/grouping.rb +6 -6
- data/lib/active_support/core_ext/array/inquiry.rb +2 -2
- data/lib/active_support/core_ext/benchmark.rb +2 -2
- data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
- data/lib/active_support/core_ext/class/attribute.rb +34 -44
- data/lib/active_support/core_ext/class/subclasses.rb +19 -29
- data/lib/active_support/core_ext/date/blank.rb +1 -1
- data/lib/active_support/core_ext/date/calculations.rb +24 -9
- data/lib/active_support/core_ext/date/conversions.rb +18 -16
- data/lib/active_support/core_ext/date_and_time/calculations.rb +27 -4
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
- data/lib/active_support/core_ext/date_time/blank.rb +1 -1
- data/lib/active_support/core_ext/date_time/calculations.rb +4 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +19 -15
- data/lib/active_support/core_ext/digest/uuid.rb +30 -13
- data/lib/active_support/core_ext/enumerable.rb +146 -72
- data/lib/active_support/core_ext/erb/util.rb +196 -0
- data/lib/active_support/core_ext/file/atomic.rb +3 -1
- data/lib/active_support/core_ext/hash/conversions.rb +3 -4
- data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +4 -4
- data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
- data/lib/active_support/core_ext/hash/keys.rb +5 -5
- data/lib/active_support/core_ext/hash/slice.rb +3 -2
- data/lib/active_support/core_ext/integer/inflections.rb +12 -12
- data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
- data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
- data/lib/active_support/core_ext/load_error.rb +1 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
- data/lib/active_support/core_ext/module/attribute_accessors.rb +31 -29
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +51 -20
- data/lib/active_support/core_ext/module/concerning.rb +14 -8
- data/lib/active_support/core_ext/module/delegation.rb +75 -42
- data/lib/active_support/core_ext/module/deprecation.rb +15 -12
- data/lib/active_support/core_ext/module/introspection.rb +1 -26
- data/lib/active_support/core_ext/name_error.rb +23 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +82 -73
- data/lib/active_support/core_ext/object/acts_like.rb +29 -5
- data/lib/active_support/core_ext/object/blank.rb +2 -2
- data/lib/active_support/core_ext/object/deep_dup.rb +17 -1
- data/lib/active_support/core_ext/object/duplicable.rb +15 -4
- data/lib/active_support/core_ext/object/inclusion.rb +13 -5
- data/lib/active_support/core_ext/object/instance_variables.rb +22 -12
- data/lib/active_support/core_ext/object/json.rb +52 -28
- data/lib/active_support/core_ext/object/to_query.rb +2 -4
- data/lib/active_support/core_ext/object/try.rb +20 -20
- data/lib/active_support/core_ext/object/with.rb +44 -0
- data/lib/active_support/core_ext/object/with_options.rb +25 -6
- data/lib/active_support/core_ext/object.rb +1 -0
- data/lib/active_support/core_ext/pathname/blank.rb +16 -0
- data/lib/active_support/core_ext/pathname/existence.rb +23 -0
- data/lib/active_support/core_ext/pathname.rb +4 -0
- data/lib/active_support/core_ext/range/compare_range.rb +6 -25
- data/lib/active_support/core_ext/range/conversions.rb +34 -13
- data/lib/active_support/core_ext/range/each.rb +1 -1
- data/lib/active_support/core_ext/range/overlap.rb +40 -0
- data/lib/active_support/core_ext/range.rb +1 -2
- data/lib/active_support/core_ext/regexp.rb +8 -1
- data/lib/active_support/core_ext/securerandom.rb +25 -13
- data/lib/active_support/core_ext/string/access.rb +5 -24
- data/lib/active_support/core_ext/string/conversions.rb +3 -2
- data/lib/active_support/core_ext/string/filters.rb +21 -15
- data/lib/active_support/core_ext/string/indent.rb +1 -1
- data/lib/active_support/core_ext/string/inflections.rb +51 -10
- data/lib/active_support/core_ext/string/inquiry.rb +2 -1
- data/lib/active_support/core_ext/string/multibyte.rb +2 -2
- data/lib/active_support/core_ext/string/output_safety.rb +85 -194
- data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
- data/lib/active_support/core_ext/time/calculations.rb +46 -8
- data/lib/active_support/core_ext/time/conversions.rb +16 -13
- data/lib/active_support/core_ext/time/zones.rb +12 -28
- data/lib/active_support/core_ext.rb +2 -1
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +54 -22
- data/lib/active_support/deep_mergeable.rb +53 -0
- data/lib/active_support/dependencies/autoload.rb +17 -12
- data/lib/active_support/dependencies/interlock.rb +10 -18
- data/lib/active_support/dependencies/require_dependency.rb +28 -0
- data/lib/active_support/dependencies.rb +58 -769
- data/lib/active_support/deprecation/behaviors.rb +77 -38
- data/lib/active_support/deprecation/constant_accessor.rb +5 -4
- data/lib/active_support/deprecation/deprecators.rb +104 -0
- data/lib/active_support/deprecation/disallowed.rb +54 -0
- data/lib/active_support/deprecation/instance_delegator.rb +31 -5
- data/lib/active_support/deprecation/method_wrappers.rb +12 -28
- data/lib/active_support/deprecation/proxy_wrappers.rb +40 -25
- data/lib/active_support/deprecation/reporting.rb +76 -16
- data/lib/active_support/deprecation.rb +36 -4
- data/lib/active_support/deprecator.rb +7 -0
- data/lib/active_support/descendants_tracker.rb +150 -68
- data/lib/active_support/digest.rb +5 -3
- data/lib/active_support/duration/iso8601_parser.rb +3 -3
- data/lib/active_support/duration/iso8601_serializer.rb +24 -12
- data/lib/active_support/duration.rb +136 -56
- data/lib/active_support/encrypted_configuration.rb +72 -9
- data/lib/active_support/encrypted_file.rb +46 -13
- data/lib/active_support/environment_inquirer.rb +40 -0
- data/lib/active_support/error_reporter/test_helper.rb +15 -0
- data/lib/active_support/error_reporter.rb +203 -0
- data/lib/active_support/evented_file_update_checker.rb +86 -137
- data/lib/active_support/execution_context/test_helper.rb +13 -0
- data/lib/active_support/execution_context.rb +53 -0
- data/lib/active_support/execution_wrapper.rb +31 -12
- data/lib/active_support/executor/test_helper.rb +7 -0
- data/lib/active_support/file_update_checker.rb +4 -2
- data/lib/active_support/fork_tracker.rb +79 -0
- data/lib/active_support/gem_version.rb +5 -5
- data/lib/active_support/gzip.rb +2 -0
- data/lib/active_support/hash_with_indifferent_access.rb +86 -42
- data/lib/active_support/html_safe_translation.rb +53 -0
- data/lib/active_support/i18n.rb +2 -1
- data/lib/active_support/i18n_railtie.rb +29 -27
- data/lib/active_support/inflector/inflections.rb +26 -9
- data/lib/active_support/inflector/methods.rb +54 -64
- data/lib/active_support/inflector/transliterate.rb +7 -5
- data/lib/active_support/isolated_execution_state.rb +76 -0
- data/lib/active_support/json/decoding.rb +6 -5
- data/lib/active_support/json/encoding.rb +31 -45
- data/lib/active_support/key_generator.rb +32 -7
- data/lib/active_support/lazy_load_hooks.rb +33 -7
- data/lib/active_support/locale/en.yml +10 -4
- data/lib/active_support/log_subscriber/test_helper.rb +2 -2
- data/lib/active_support/log_subscriber.rb +101 -32
- data/lib/active_support/logger.rb +9 -60
- data/lib/active_support/logger_silence.rb +2 -26
- data/lib/active_support/logger_thread_safe_level.rb +24 -25
- data/lib/active_support/message_encryptor.rb +205 -58
- data/lib/active_support/message_encryptors.rb +141 -0
- data/lib/active_support/message_pack/cache_serializer.rb +23 -0
- data/lib/active_support/message_pack/extensions.rb +292 -0
- data/lib/active_support/message_pack/serializer.rb +63 -0
- data/lib/active_support/message_pack.rb +50 -0
- data/lib/active_support/message_verifier.rb +237 -86
- data/lib/active_support/message_verifiers.rb +135 -0
- data/lib/active_support/messages/codec.rb +65 -0
- data/lib/active_support/messages/metadata.rb +112 -46
- data/lib/active_support/messages/rotation_configuration.rb +2 -1
- data/lib/active_support/messages/rotation_coordinator.rb +93 -0
- data/lib/active_support/messages/rotator.rb +35 -32
- data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
- data/lib/active_support/multibyte/chars.rb +15 -52
- data/lib/active_support/multibyte/unicode.rb +8 -122
- data/lib/active_support/multibyte.rb +1 -1
- data/lib/active_support/notifications/fanout.rb +310 -105
- data/lib/active_support/notifications/instrumenter.rb +113 -48
- data/lib/active_support/notifications.rb +56 -29
- data/lib/active_support/number_helper/number_converter.rb +15 -8
- data/lib/active_support/number_helper/number_to_currency_converter.rb +11 -6
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_human_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +5 -5
- data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -1
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +9 -5
- data/lib/active_support/number_helper/rounding_helper.rb +12 -32
- data/lib/active_support/number_helper.rb +379 -304
- data/lib/active_support/option_merger.rb +11 -18
- data/lib/active_support/ordered_hash.rb +4 -4
- data/lib/active_support/ordered_options.rb +23 -3
- data/lib/active_support/parameter_filter.rb +104 -75
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +1 -4
- data/lib/active_support/railtie.rb +90 -6
- data/lib/active_support/reloader.rb +12 -4
- data/lib/active_support/rescuable.rb +18 -16
- data/lib/active_support/ruby_features.rb +7 -0
- data/lib/active_support/secure_compare_rotator.rb +58 -0
- data/lib/active_support/security_utils.rb +19 -12
- data/lib/active_support/string_inquirer.rb +5 -3
- data/lib/active_support/subscriber.rb +23 -47
- data/lib/active_support/syntax_error_proxy.rb +70 -0
- data/lib/active_support/tagged_logging.rb +84 -23
- data/lib/active_support/test_case.rb +166 -27
- data/lib/active_support/testing/assertions.rb +73 -20
- data/lib/active_support/testing/autorun.rb +0 -2
- data/lib/active_support/testing/constant_stubbing.rb +32 -0
- data/lib/active_support/testing/deprecation.rb +53 -2
- data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
- data/lib/active_support/testing/isolation.rb +30 -29
- data/lib/active_support/testing/method_call_assertions.rb +24 -11
- data/lib/active_support/testing/parallelization/server.rb +82 -0
- data/lib/active_support/testing/parallelization/worker.rb +103 -0
- data/lib/active_support/testing/parallelization.rb +16 -95
- data/lib/active_support/testing/parallelize_executor.rb +81 -0
- data/lib/active_support/testing/stream.rb +4 -6
- data/lib/active_support/testing/strict_warnings.rb +39 -0
- data/lib/active_support/testing/tagged_logging.rb +1 -1
- data/lib/active_support/testing/time_helpers.rb +89 -19
- data/lib/active_support/time_with_zone.rb +105 -70
- data/lib/active_support/values/time_zone.rb +59 -26
- data/lib/active_support/version.rb +1 -1
- data/lib/active_support/xml_mini/jdom.rb +4 -11
- data/lib/active_support/xml_mini/libxml.rb +5 -5
- data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
- data/lib/active_support/xml_mini/nokogiri.rb +5 -5
- data/lib/active_support/xml_mini/nokogirisax.rb +2 -2
- data/lib/active_support/xml_mini/rexml.rb +9 -2
- data/lib/active_support/xml_mini.rb +7 -6
- data/lib/active_support.rb +40 -1
- metadata +127 -40
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -5
- data/lib/active_support/core_ext/hash/compact.rb +0 -5
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -5
- data/lib/active_support/core_ext/marshal.rb +0 -24
- data/lib/active_support/core_ext/module/reachable.rb +0 -6
- data/lib/active_support/core_ext/numeric/inquiry.rb +0 -5
- data/lib/active_support/core_ext/range/include_range.rb +0 -9
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -23
- data/lib/active_support/core_ext/range/overlaps.rb +0 -10
- data/lib/active_support/core_ext/uri.rb +0 -25
- data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -117
- data/lib/active_support/per_thread_registry.rb +0 -60
@@ -1,17 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
gem "minitest" # make sure we get the gem, not stdlib
|
4
3
|
require "minitest"
|
5
4
|
require "active_support/testing/tagged_logging"
|
6
5
|
require "active_support/testing/setup_and_teardown"
|
7
6
|
require "active_support/testing/assertions"
|
7
|
+
require "active_support/testing/error_reporter_assertions"
|
8
8
|
require "active_support/testing/deprecation"
|
9
9
|
require "active_support/testing/declarative"
|
10
10
|
require "active_support/testing/isolation"
|
11
11
|
require "active_support/testing/constant_lookup"
|
12
12
|
require "active_support/testing/time_helpers"
|
13
|
+
require "active_support/testing/constant_stubbing"
|
13
14
|
require "active_support/testing/file_fixtures"
|
14
15
|
require "active_support/testing/parallelization"
|
16
|
+
require "active_support/testing/parallelize_executor"
|
15
17
|
require "concurrent/utility/processor_counter"
|
16
18
|
|
17
19
|
module ActiveSupport
|
@@ -65,32 +67,21 @@ module ActiveSupport
|
|
65
67
|
# The default parallelization method is to fork processes. If you'd like to
|
66
68
|
# use threads instead you can pass <tt>with: :threads</tt> to the +parallelize+
|
67
69
|
# method. Note the threaded parallelization does not create multiple
|
68
|
-
#
|
70
|
+
# databases and will not work with system tests.
|
69
71
|
#
|
70
72
|
# parallelize(workers: :number_of_processors, with: :threads)
|
71
73
|
#
|
72
74
|
# The threaded parallelization uses minitest's parallel executor directly.
|
73
75
|
# The processes parallelization uses a Ruby DRb server.
|
74
|
-
|
76
|
+
#
|
77
|
+
# Because parallelization presents an overhead, it is only enabled when the
|
78
|
+
# number of tests to run is above the +threshold+ param. The default value is
|
79
|
+
# 50, and it's configurable via +config.active_support.test_parallelization_threshold+.
|
80
|
+
def parallelize(workers: :number_of_processors, with: :processes, threshold: ActiveSupport.test_parallelization_threshold)
|
75
81
|
workers = Concurrent.physical_processor_count if workers == :number_of_processors
|
76
82
|
workers = ENV["PARALLEL_WORKERS"].to_i if ENV["PARALLEL_WORKERS"]
|
77
83
|
|
78
|
-
|
79
|
-
|
80
|
-
executor = case with
|
81
|
-
when :processes
|
82
|
-
Testing::Parallelization.new(workers)
|
83
|
-
when :threads
|
84
|
-
Minitest::Parallel::Executor.new(workers)
|
85
|
-
else
|
86
|
-
raise ArgumentError, "#{with} is not a supported parallelization executor."
|
87
|
-
end
|
88
|
-
|
89
|
-
self.lock_threads = false if defined?(self.lock_threads) && with == :threads
|
90
|
-
|
91
|
-
Minitest.parallel_executor = executor
|
92
|
-
|
93
|
-
parallelize_me!
|
84
|
+
Minitest.parallel_executor = ActiveSupport::Testing::ParallelizeExecutor.new(size: workers, with: with, threshold: threshold)
|
94
85
|
end
|
95
86
|
|
96
87
|
# Set up hook for parallel testing. This can be used if you have multiple
|
@@ -107,9 +98,7 @@ module ActiveSupport
|
|
107
98
|
# end
|
108
99
|
# end
|
109
100
|
def parallelize_setup(&block)
|
110
|
-
ActiveSupport::Testing::Parallelization.after_fork_hook
|
111
|
-
yield worker
|
112
|
-
end
|
101
|
+
ActiveSupport::Testing::Parallelization.after_fork_hook(&block)
|
113
102
|
end
|
114
103
|
|
115
104
|
# Clean up hook for parallel testing. This can be used to drop databases
|
@@ -126,10 +115,27 @@ module ActiveSupport
|
|
126
115
|
# end
|
127
116
|
# end
|
128
117
|
def parallelize_teardown(&block)
|
129
|
-
ActiveSupport::Testing::Parallelization.run_cleanup_hook
|
130
|
-
yield worker
|
131
|
-
end
|
118
|
+
ActiveSupport::Testing::Parallelization.run_cleanup_hook(&block)
|
132
119
|
end
|
120
|
+
|
121
|
+
# :singleton-method: fixture_paths
|
122
|
+
#
|
123
|
+
# Returns the ActiveRecord::FixtureSet collection.
|
124
|
+
#
|
125
|
+
# In your +test_helper.rb+ you must have <tt>require "rails/test_help"</tt>.
|
126
|
+
|
127
|
+
# :singleton-method: fixture_paths=
|
128
|
+
#
|
129
|
+
# :call-seq:
|
130
|
+
# fixture_paths=(fixture_paths)
|
131
|
+
#
|
132
|
+
# Sets the given path to the fixture set.
|
133
|
+
#
|
134
|
+
# Can also append multiple paths.
|
135
|
+
#
|
136
|
+
# ActiveSupport::TestCase.fixture_paths << "component1/test/fixtures"
|
137
|
+
#
|
138
|
+
# In your +test_helper.rb+ you must have <tt>require "rails/test_help"</tt>.
|
133
139
|
end
|
134
140
|
|
135
141
|
alias_method :method_name, :name
|
@@ -137,27 +143,160 @@ module ActiveSupport
|
|
137
143
|
include ActiveSupport::Testing::TaggedLogging
|
138
144
|
prepend ActiveSupport::Testing::SetupAndTeardown
|
139
145
|
include ActiveSupport::Testing::Assertions
|
146
|
+
include ActiveSupport::Testing::ErrorReporterAssertions
|
140
147
|
include ActiveSupport::Testing::Deprecation
|
148
|
+
include ActiveSupport::Testing::ConstantStubbing
|
141
149
|
include ActiveSupport::Testing::TimeHelpers
|
142
150
|
include ActiveSupport::Testing::FileFixtures
|
143
151
|
extend ActiveSupport::Testing::Declarative
|
144
152
|
|
145
|
-
|
146
|
-
|
153
|
+
##
|
154
|
+
# :method: assert_not_empty
|
155
|
+
#
|
156
|
+
# :call-seq:
|
157
|
+
# assert_not_empty(obj, msg = nil)
|
158
|
+
#
|
159
|
+
# Alias for: refute_empty[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_empty]
|
160
|
+
|
161
|
+
#
|
147
162
|
alias :assert_not_empty :refute_empty
|
163
|
+
|
164
|
+
##
|
165
|
+
# :method: assert_not_equal
|
166
|
+
#
|
167
|
+
# :call-seq:
|
168
|
+
# assert_not_equal(exp, act, msg = nil)
|
169
|
+
#
|
170
|
+
# Alias for: refute_equal[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_equal]
|
171
|
+
|
172
|
+
#
|
148
173
|
alias :assert_not_equal :refute_equal
|
174
|
+
|
175
|
+
##
|
176
|
+
# :method: assert_not_in_delta
|
177
|
+
#
|
178
|
+
# :call-seq:
|
179
|
+
# assert_not_in_delta(exp, act, delta = 0.001, msg = nil)
|
180
|
+
#
|
181
|
+
# Alias for: refute_in_delta[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_in_delta]
|
182
|
+
|
183
|
+
#
|
149
184
|
alias :assert_not_in_delta :refute_in_delta
|
185
|
+
|
186
|
+
##
|
187
|
+
# :method: assert_not_in_epsilon
|
188
|
+
#
|
189
|
+
# :call-seq:
|
190
|
+
# assert_not_in_epsilon(a, b, epsilon = 0.001, msg = nil)
|
191
|
+
#
|
192
|
+
# Alias for: refute_in_epsilon[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_in_epsilon]
|
193
|
+
|
194
|
+
#
|
150
195
|
alias :assert_not_in_epsilon :refute_in_epsilon
|
196
|
+
|
197
|
+
##
|
198
|
+
# :method: assert_not_includes
|
199
|
+
#
|
200
|
+
# :call-seq:
|
201
|
+
# assert_not_includes(collection, obj, msg = nil)
|
202
|
+
#
|
203
|
+
# Alias for: refute_includes[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_includes]
|
204
|
+
|
205
|
+
#
|
151
206
|
alias :assert_not_includes :refute_includes
|
207
|
+
|
208
|
+
##
|
209
|
+
# :method: assert_not_instance_of
|
210
|
+
#
|
211
|
+
# :call-seq:
|
212
|
+
# assert_not_instance_of(cls, obj, msg = nil)
|
213
|
+
#
|
214
|
+
# Alias for: refute_instance_of[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_instance_of]
|
215
|
+
|
216
|
+
#
|
152
217
|
alias :assert_not_instance_of :refute_instance_of
|
218
|
+
|
219
|
+
##
|
220
|
+
# :method: assert_not_kind_of
|
221
|
+
#
|
222
|
+
# :call-seq:
|
223
|
+
# assert_not_kind_of(cls, obj, msg = nil)
|
224
|
+
#
|
225
|
+
# Alias for: refute_kind_of[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_kind_of]
|
226
|
+
|
227
|
+
#
|
153
228
|
alias :assert_not_kind_of :refute_kind_of
|
229
|
+
|
230
|
+
##
|
231
|
+
# :method: assert_no_match
|
232
|
+
#
|
233
|
+
# :call-seq:
|
234
|
+
# assert_no_match(matcher, obj, msg = nil)
|
235
|
+
#
|
236
|
+
# Alias for: refute_match[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_match]
|
237
|
+
|
238
|
+
#
|
154
239
|
alias :assert_no_match :refute_match
|
240
|
+
|
241
|
+
##
|
242
|
+
# :method: assert_not_nil
|
243
|
+
#
|
244
|
+
# :call-seq:
|
245
|
+
# assert_not_nil(obj, msg = nil)
|
246
|
+
#
|
247
|
+
# Alias for: refute_nil[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_nil]
|
248
|
+
|
249
|
+
#
|
155
250
|
alias :assert_not_nil :refute_nil
|
251
|
+
|
252
|
+
##
|
253
|
+
# :method: assert_not_operator
|
254
|
+
#
|
255
|
+
# :call-seq:
|
256
|
+
# assert_not_operator(o1, op, o2 = UNDEFINED, msg = nil)
|
257
|
+
#
|
258
|
+
# Alias for: refute_operator[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_operator]
|
259
|
+
|
260
|
+
#
|
156
261
|
alias :assert_not_operator :refute_operator
|
262
|
+
|
263
|
+
##
|
264
|
+
# :method: assert_not_predicate
|
265
|
+
#
|
266
|
+
# :call-seq:
|
267
|
+
# assert_not_predicate(o1, op, msg = nil)
|
268
|
+
#
|
269
|
+
# Alias for: refute_predicate[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_predicate]
|
270
|
+
|
271
|
+
#
|
157
272
|
alias :assert_not_predicate :refute_predicate
|
273
|
+
|
274
|
+
##
|
275
|
+
# :method: assert_not_respond_to
|
276
|
+
#
|
277
|
+
# :call-seq:
|
278
|
+
# assert_not_respond_to(obj, meth, msg = nil)
|
279
|
+
#
|
280
|
+
# Alias for: refute_respond_to[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_respond_to]
|
281
|
+
|
282
|
+
#
|
158
283
|
alias :assert_not_respond_to :refute_respond_to
|
284
|
+
|
285
|
+
##
|
286
|
+
# :method: assert_not_same
|
287
|
+
#
|
288
|
+
# :call-seq:
|
289
|
+
# assert_not_same(exp, act, msg = nil)
|
290
|
+
#
|
291
|
+
# Alias for: refute_same[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_same]
|
292
|
+
|
293
|
+
#
|
159
294
|
alias :assert_not_same :refute_same
|
160
295
|
|
161
296
|
ActiveSupport.run_load_hooks(:active_support_test_case, self)
|
297
|
+
|
298
|
+
def inspect # :nodoc:
|
299
|
+
Object.instance_method(:to_s).bind_call(self)
|
300
|
+
end
|
162
301
|
end
|
163
302
|
end
|
@@ -1,13 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/core_ext/enumerable"
|
4
|
+
|
3
5
|
module ActiveSupport
|
4
6
|
module Testing
|
5
7
|
module Assertions
|
6
8
|
UNTRACKED = Object.new # :nodoc:
|
7
9
|
|
8
|
-
# Asserts that an expression is not truthy. Passes if
|
9
|
-
# +
|
10
|
-
#
|
10
|
+
# Asserts that an expression is not truthy. Passes if +object+ is +nil+ or
|
11
|
+
# +false+. "Truthy" means "considered true in a conditional" like <tt>if
|
12
|
+
# foo</tt>.
|
11
13
|
#
|
12
14
|
# assert_not nil # => true
|
13
15
|
# assert_not false # => true
|
@@ -21,6 +23,21 @@ module ActiveSupport
|
|
21
23
|
assert !object, message
|
22
24
|
end
|
23
25
|
|
26
|
+
# Asserts that a block raises one of +exp+. This is an enhancement of the
|
27
|
+
# standard Minitest assertion method with the ability to test error
|
28
|
+
# messages.
|
29
|
+
#
|
30
|
+
# assert_raises(ArgumentError, match: /incorrect param/i) do
|
31
|
+
# perform_service(param: 'exception')
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
def assert_raises(*exp, match: nil, &block)
|
35
|
+
error = super(*exp, &block)
|
36
|
+
assert_match(match, error.message) if match
|
37
|
+
error
|
38
|
+
end
|
39
|
+
alias :assert_raise :assert_raises
|
40
|
+
|
24
41
|
# Assertion that the block should not raise an exception.
|
25
42
|
#
|
26
43
|
# Passes if evaluated code in the yielded block raises no exception.
|
@@ -29,7 +46,9 @@ module ActiveSupport
|
|
29
46
|
# perform_service(param: 'no_exception')
|
30
47
|
# end
|
31
48
|
def assert_nothing_raised
|
32
|
-
yield
|
49
|
+
yield.tap { assert(true) }
|
50
|
+
rescue => error
|
51
|
+
raise Minitest::UnexpectedError.new(error)
|
33
52
|
end
|
34
53
|
|
35
54
|
# Test numeric difference between the return value of an expression as a
|
@@ -46,7 +65,7 @@ module ActiveSupport
|
|
46
65
|
# end
|
47
66
|
#
|
48
67
|
# An arbitrary positive or negative difference can be specified.
|
49
|
-
# The default is
|
68
|
+
# The default is +1+.
|
50
69
|
#
|
51
70
|
# assert_difference 'Article.count', -1 do
|
52
71
|
# post :delete, params: { id: ... }
|
@@ -87,7 +106,7 @@ module ActiveSupport
|
|
87
106
|
else
|
88
107
|
difference = args[0] || 1
|
89
108
|
message = args[1]
|
90
|
-
|
109
|
+
Array(expression).index_with(difference)
|
91
110
|
end
|
92
111
|
|
93
112
|
exps = expressions.keys.map { |e|
|
@@ -95,12 +114,13 @@ module ActiveSupport
|
|
95
114
|
}
|
96
115
|
before = exps.map(&:call)
|
97
116
|
|
98
|
-
retval =
|
117
|
+
retval = _assert_nothing_raised_or_warn("assert_difference", &block)
|
99
118
|
|
100
119
|
expressions.zip(exps, before) do |(code, diff), exp, before_value|
|
101
|
-
|
120
|
+
actual = exp.call
|
121
|
+
error = "#{code.inspect} didn't change by #{diff}, but by #{actual - before_value}"
|
102
122
|
error = "#{message}.\n#{error}" if message
|
103
|
-
assert_equal(before_value + diff,
|
123
|
+
assert_equal(before_value + diff, actual, error)
|
104
124
|
end
|
105
125
|
|
106
126
|
retval
|
@@ -155,7 +175,7 @@ module ActiveSupport
|
|
155
175
|
# @object = 42
|
156
176
|
# end
|
157
177
|
#
|
158
|
-
# The keyword arguments
|
178
|
+
# The keyword arguments +:from+ and +:to+ can be given to specify the
|
159
179
|
# expected initial value and the expected value after the block was
|
160
180
|
# executed.
|
161
181
|
#
|
@@ -172,10 +192,10 @@ module ActiveSupport
|
|
172
192
|
exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) }
|
173
193
|
|
174
194
|
before = exp.call
|
175
|
-
retval =
|
195
|
+
retval = _assert_nothing_raised_or_warn("assert_changes", &block)
|
176
196
|
|
177
197
|
unless from == UNTRACKED
|
178
|
-
error = "#{
|
198
|
+
error = "Expected change from #{from.inspect}, got #{before}"
|
179
199
|
error = "#{message}.\n#{error}" if message
|
180
200
|
assert from === before, error
|
181
201
|
end
|
@@ -185,12 +205,10 @@ module ActiveSupport
|
|
185
205
|
error = "#{expression.inspect} didn't change"
|
186
206
|
error = "#{error}. It was already #{to}" if before == to
|
187
207
|
error = "#{message}.\n#{error}" if message
|
188
|
-
|
208
|
+
refute_equal before, after, error
|
189
209
|
|
190
210
|
unless to == UNTRACKED
|
191
|
-
error = "
|
192
|
-
error = "#{error}Expected: #{to.inspect}\n"
|
193
|
-
error = "#{error} Actual: #{after.inspect}"
|
211
|
+
error = "Expected change to #{to}, got #{after}\n"
|
194
212
|
error = "#{message}.\n#{error}" if message
|
195
213
|
assert to === after, error
|
196
214
|
end
|
@@ -205,24 +223,59 @@ module ActiveSupport
|
|
205
223
|
# post :create, params: { status: { ok: true } }
|
206
224
|
# end
|
207
225
|
#
|
226
|
+
# Provide the optional keyword argument +:from+ to specify the expected
|
227
|
+
# initial value.
|
228
|
+
#
|
229
|
+
# assert_no_changes -> { Status.all_good? }, from: true do
|
230
|
+
# post :create, params: { status: { ok: true } }
|
231
|
+
# end
|
232
|
+
#
|
208
233
|
# An error message can be specified.
|
209
234
|
#
|
210
235
|
# assert_no_changes -> { Status.all_good? }, 'Expected the status to be good' do
|
211
236
|
# post :create, params: { status: { ok: false } }
|
212
237
|
# end
|
213
|
-
def assert_no_changes(expression, message = nil, &block)
|
238
|
+
def assert_no_changes(expression, message = nil, from: UNTRACKED, &block)
|
214
239
|
exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) }
|
215
240
|
|
216
241
|
before = exp.call
|
217
|
-
retval =
|
242
|
+
retval = _assert_nothing_raised_or_warn("assert_no_changes", &block)
|
243
|
+
|
244
|
+
unless from == UNTRACKED
|
245
|
+
error = "Expected initial value of #{from.inspect}"
|
246
|
+
error = "#{message}.\n#{error}" if message
|
247
|
+
assert from === before, error
|
248
|
+
end
|
249
|
+
|
218
250
|
after = exp.call
|
219
251
|
|
220
|
-
error = "#{expression.inspect}
|
252
|
+
error = "#{expression.inspect} changed"
|
221
253
|
error = "#{message}.\n#{error}" if message
|
222
|
-
|
254
|
+
|
255
|
+
if before.nil?
|
256
|
+
assert_nil after, error
|
257
|
+
else
|
258
|
+
assert_equal before, after, error
|
259
|
+
end
|
223
260
|
|
224
261
|
retval
|
225
262
|
end
|
263
|
+
|
264
|
+
private
|
265
|
+
def _assert_nothing_raised_or_warn(assertion, &block)
|
266
|
+
assert_nothing_raised(&block)
|
267
|
+
rescue Minitest::UnexpectedError => e
|
268
|
+
if tagged_logger && tagged_logger.warn?
|
269
|
+
warning = <<~MSG
|
270
|
+
#{self.class} - #{name}: #{e.error.class} raised.
|
271
|
+
If you expected this exception, use `assert_raises` as near to the code that raises as possible.
|
272
|
+
Other block based assertions (e.g. `#{assertion}`) can be used, as long as `assert_raises` is inside their block.
|
273
|
+
MSG
|
274
|
+
tagged_logger.warn warning
|
275
|
+
end
|
276
|
+
|
277
|
+
raise
|
278
|
+
end
|
226
279
|
end
|
227
280
|
end
|
228
281
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
module Testing
|
5
|
+
module ConstantStubbing
|
6
|
+
# Changes the value of a constant for the duration of a block. Example:
|
7
|
+
#
|
8
|
+
# # World::List::Import::LARGE_IMPORT_THRESHOLD = 5000
|
9
|
+
# stub_const(World::List::Import, :LARGE_IMPORT_THRESHOLD, 1) do
|
10
|
+
# assert_equal 1, World::List::Import::LARGE_IMPORT_THRESHOLD
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# assert_equal 5000, World::List::Import::LARGE_IMPORT_THRESHOLD
|
14
|
+
#
|
15
|
+
# Using this method rather than forcing <tt>World::List::Import::LARGE_IMPORT_THRESHOLD = 5000</tt> prevents
|
16
|
+
# warnings from being thrown, and ensures that the old value is returned after the test has completed.
|
17
|
+
#
|
18
|
+
# Note: Stubbing a const will stub it across all threads. So if you have concurrent threads
|
19
|
+
# (like separate test suites running in parallel) that all depend on the same constant, it's possible
|
20
|
+
# divergent stubbing will trample on each other.
|
21
|
+
def stub_const(mod, constant, new_value)
|
22
|
+
old_value = mod.const_get(constant, false)
|
23
|
+
mod.send(:remove_const, constant)
|
24
|
+
mod.const_set(constant, new_value)
|
25
|
+
yield
|
26
|
+
ensure
|
27
|
+
mod.send(:remove_const, constant)
|
28
|
+
mod.const_set(constant, old_value)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -4,8 +4,35 @@ require "active_support/deprecation"
|
|
4
4
|
|
5
5
|
module ActiveSupport
|
6
6
|
module Testing
|
7
|
-
module Deprecation
|
7
|
+
module Deprecation
|
8
|
+
##
|
9
|
+
# :call-seq:
|
10
|
+
# assert_deprecated(deprecator, &block)
|
11
|
+
# assert_deprecated(match, deprecator, &block)
|
12
|
+
#
|
13
|
+
# Asserts that a matching deprecation warning was emitted by the given deprecator during the execution of the yielded block.
|
14
|
+
#
|
15
|
+
# assert_deprecated(/foo/, CustomDeprecator) do
|
16
|
+
# CustomDeprecator.warn "foo should no longer be used"
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# The +match+ object may be a +Regexp+, or +String+ appearing in the message.
|
20
|
+
#
|
21
|
+
# assert_deprecated('foo', CustomDeprecator) do
|
22
|
+
# CustomDeprecator.warn "foo should no longer be used"
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# If the +match+ is omitted (or explicitly +nil+), any deprecation warning will match.
|
26
|
+
#
|
27
|
+
# assert_deprecated(CustomDeprecator) do
|
28
|
+
# CustomDeprecator.warn "foo should no longer be used"
|
29
|
+
# end
|
8
30
|
def assert_deprecated(match = nil, deprecator = nil, &block)
|
31
|
+
match, deprecator = nil, match if match.is_a?(ActiveSupport::Deprecation)
|
32
|
+
unless deprecator
|
33
|
+
ActiveSupport.deprecator.warn("assert_deprecated without a deprecator is deprecated")
|
34
|
+
deprecator = ActiveSupport::Deprecation._instance
|
35
|
+
end
|
9
36
|
result, warnings = collect_deprecations(deprecator, &block)
|
10
37
|
assert !warnings.empty?, "Expected a deprecation warning within the block but received none"
|
11
38
|
if match
|
@@ -15,14 +42,38 @@ module ActiveSupport
|
|
15
42
|
result
|
16
43
|
end
|
17
44
|
|
45
|
+
# Asserts that no deprecation warnings are emitted by the given deprecator during the execution of the yielded block.
|
46
|
+
#
|
47
|
+
# assert_not_deprecated(CustomDeprecator) do
|
48
|
+
# CustomDeprecator.warn "message" # fails assertion
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# assert_not_deprecated(ActiveSupport::Deprecation.new) do
|
52
|
+
# CustomDeprecator.warn "message" # passes assertion, different deprecator
|
53
|
+
# end
|
18
54
|
def assert_not_deprecated(deprecator = nil, &block)
|
55
|
+
unless deprecator
|
56
|
+
ActiveSupport.deprecator.warn("assert_not_deprecated without a deprecator is deprecated")
|
57
|
+
deprecator = ActiveSupport::Deprecation._instance
|
58
|
+
end
|
19
59
|
result, deprecations = collect_deprecations(deprecator, &block)
|
20
60
|
assert deprecations.empty?, "Expected no deprecation warning within the block but received #{deprecations.size}: \n #{deprecations * "\n "}"
|
21
61
|
result
|
22
62
|
end
|
23
63
|
|
64
|
+
# Returns the return value of the block and an array of all the deprecation warnings emitted by the given
|
65
|
+
# +deprecator+ during the execution of the yielded block.
|
66
|
+
#
|
67
|
+
# collect_deprecations(CustomDeprecator) do
|
68
|
+
# CustomDeprecator.warn "message"
|
69
|
+
# ActiveSupport::Deprecation.new.warn "other message"
|
70
|
+
# :result
|
71
|
+
# end # => [:result, ["message"]]
|
24
72
|
def collect_deprecations(deprecator = nil)
|
25
|
-
deprecator
|
73
|
+
unless deprecator
|
74
|
+
ActiveSupport.deprecator.warn("collect_deprecations without a deprecator is deprecated")
|
75
|
+
deprecator = ActiveSupport::Deprecation._instance
|
76
|
+
end
|
26
77
|
old_behavior = deprecator.behavior
|
27
78
|
deprecations = []
|
28
79
|
deprecator.behavior = Proc.new do |message, callstack|
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
module Testing
|
5
|
+
module ErrorReporterAssertions
|
6
|
+
module ErrorCollector # :nodoc:
|
7
|
+
@subscribed = false
|
8
|
+
@mutex = Mutex.new
|
9
|
+
|
10
|
+
Report = Struct.new(:error, :handled, :severity, :context, :source, keyword_init: true)
|
11
|
+
class Report
|
12
|
+
alias_method :handled?, :handled
|
13
|
+
end
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def record
|
17
|
+
subscribe
|
18
|
+
recorders = ActiveSupport::IsolatedExecutionState[:active_support_error_reporter_assertions] ||= []
|
19
|
+
reports = []
|
20
|
+
recorders << reports
|
21
|
+
begin
|
22
|
+
yield
|
23
|
+
reports
|
24
|
+
ensure
|
25
|
+
recorders.delete_if { |r| reports.equal?(r) }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def report(error, **kwargs)
|
30
|
+
report = Report.new(error: error, **kwargs)
|
31
|
+
ActiveSupport::IsolatedExecutionState[:active_support_error_reporter_assertions]&.each do |reports|
|
32
|
+
reports << report
|
33
|
+
end
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
def subscribe
|
39
|
+
return if @subscribed
|
40
|
+
@mutex.synchronize do
|
41
|
+
return if @subscribed
|
42
|
+
|
43
|
+
if ActiveSupport.error_reporter
|
44
|
+
ActiveSupport.error_reporter.subscribe(self)
|
45
|
+
@subscribed = true
|
46
|
+
else
|
47
|
+
raise Minitest::Assertion, "No error reporter is configured"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Assertion that the block should not cause an exception to be reported
|
55
|
+
# to +Rails.error+.
|
56
|
+
#
|
57
|
+
# Passes if evaluated code in the yielded block reports no exception.
|
58
|
+
#
|
59
|
+
# assert_no_error_reported do
|
60
|
+
# perform_service(param: 'no_exception')
|
61
|
+
# end
|
62
|
+
def assert_no_error_reported(&block)
|
63
|
+
reports = ErrorCollector.record do
|
64
|
+
_assert_nothing_raised_or_warn("assert_no_error_reported", &block)
|
65
|
+
end
|
66
|
+
assert_predicate(reports, :empty?)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Assertion that the block should cause at least one exception to be reported
|
70
|
+
# to +Rails.error+.
|
71
|
+
#
|
72
|
+
# Passes if the evaluated code in the yielded block reports a matching exception.
|
73
|
+
#
|
74
|
+
# assert_error_reported(IOError) do
|
75
|
+
# Rails.error.report(IOError.new("Oops"))
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
# To test further details about the reported exception, you can use the return
|
79
|
+
# value.
|
80
|
+
#
|
81
|
+
# report = assert_error_reported(IOError) do
|
82
|
+
# # ...
|
83
|
+
# end
|
84
|
+
# assert_equal "Oops", report.error.message
|
85
|
+
# assert_equal "admin", report.context[:section]
|
86
|
+
# assert_equal :warning, report.severity
|
87
|
+
# assert_predicate report, :handled?
|
88
|
+
def assert_error_reported(error_class = StandardError, &block)
|
89
|
+
reports = ErrorCollector.record do
|
90
|
+
_assert_nothing_raised_or_warn("assert_error_reported", &block)
|
91
|
+
end
|
92
|
+
|
93
|
+
if reports.empty?
|
94
|
+
assert(false, "Expected a #{error_class.name} to be reported, but there were no errors reported.")
|
95
|
+
elsif (report = reports.find { |r| error_class === r.error })
|
96
|
+
self.assertions += 1
|
97
|
+
report
|
98
|
+
else
|
99
|
+
message = "Expected a #{error_class.name} to be reported, but none of the " \
|
100
|
+
"#{reports.size} reported errors matched: \n" \
|
101
|
+
"#{reports.map { |r| r.error.class.name }.join("\n ")}"
|
102
|
+
assert(false, message)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|