activesupport 7.0.4 → 7.1.5.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 +4 -4
- data/CHANGELOG.md +1076 -230
- data/MIT-LICENSE +1 -1
- data/README.rdoc +6 -6
- data/lib/active_support/actionable_error.rb +3 -1
- data/lib/active_support/array_inquirer.rb +2 -0
- data/lib/active_support/backtrace_cleaner.rb +30 -5
- data/lib/active_support/benchmarkable.rb +1 -0
- data/lib/active_support/broadcast_logger.rb +251 -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 +37 -10
- data/lib/active_support/cache/mem_cache_store.rb +100 -76
- data/lib/active_support/cache/memory_store.rb +78 -24
- data/lib/active_support/cache/null_store.rb +6 -0
- data/lib/active_support/cache/redis_cache_store.rb +153 -141
- data/lib/active_support/cache/serializer_with_fallback.rb +175 -0
- data/lib/active_support/cache/strategy/local_cache.rb +29 -14
- data/lib/active_support/cache.rb +333 -253
- data/lib/active_support/callbacks.rb +44 -21
- data/lib/active_support/code_generator.rb +15 -10
- data/lib/active_support/concern.rb +4 -2
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +42 -3
- data/lib/active_support/concurrency/null_lock.rb +13 -0
- data/lib/active_support/configurable.rb +10 -0
- data/lib/active_support/core_ext/array/conversions.rb +2 -1
- data/lib/active_support/core_ext/array.rb +0 -1
- data/lib/active_support/core_ext/class/subclasses.rb +13 -10
- data/lib/active_support/core_ext/date/calculations.rb +15 -0
- data/lib/active_support/core_ext/date/conversions.rb +2 -1
- data/lib/active_support/core_ext/date.rb +0 -1
- data/lib/active_support/core_ext/date_and_time/calculations.rb +10 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +4 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +6 -2
- data/lib/active_support/core_ext/date_time.rb +0 -1
- data/lib/active_support/core_ext/digest/uuid.rb +1 -10
- data/lib/active_support/core_ext/enumerable.rb +8 -75
- data/lib/active_support/core_ext/erb/util.rb +196 -0
- data/lib/active_support/core_ext/hash/conversions.rb +1 -1
- data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +3 -3
- data/lib/active_support/core_ext/hash/keys.rb +3 -3
- data/lib/active_support/core_ext/integer/inflections.rb +12 -12
- data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -0
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +34 -16
- data/lib/active_support/core_ext/module/concerning.rb +6 -6
- data/lib/active_support/core_ext/module/delegation.rb +81 -37
- data/lib/active_support/core_ext/module/deprecation.rb +15 -12
- data/lib/active_support/core_ext/module/introspection.rb +0 -1
- data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +2 -0
- data/lib/active_support/core_ext/numeric.rb +0 -1
- data/lib/active_support/core_ext/object/deep_dup.rb +16 -0
- data/lib/active_support/core_ext/object/duplicable.rb +25 -16
- 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 +16 -6
- data/lib/active_support/core_ext/object/to_query.rb +0 -2
- data/lib/active_support/core_ext/object/with.rb +44 -0
- data/lib/active_support/core_ext/object/with_options.rb +9 -9
- 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 +2 -0
- data/lib/active_support/core_ext/pathname.rb +1 -0
- data/lib/active_support/core_ext/range/conversions.rb +28 -7
- 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/securerandom.rb +24 -12
- data/lib/active_support/core_ext/string/filters.rb +20 -14
- data/lib/active_support/core_ext/string/indent.rb +1 -1
- data/lib/active_support/core_ext/string/inflections.rb +16 -9
- data/lib/active_support/core_ext/string/output_safety.rb +42 -174
- data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
- data/lib/active_support/core_ext/time/calculations.rb +22 -2
- data/lib/active_support/core_ext/time/conversions.rb +2 -2
- data/lib/active_support/core_ext/time/zones.rb +7 -8
- data/lib/active_support/core_ext/time.rb +0 -1
- data/lib/active_support/current_attributes.rb +15 -6
- data/lib/active_support/deep_mergeable.rb +53 -0
- data/lib/active_support/dependencies/autoload.rb +17 -12
- data/lib/active_support/deprecation/behaviors.rb +65 -42
- 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 +6 -8
- data/lib/active_support/deprecation/instance_delegator.rb +31 -4
- data/lib/active_support/deprecation/method_wrappers.rb +6 -23
- data/lib/active_support/deprecation/proxy_wrappers.rb +37 -22
- data/lib/active_support/deprecation/reporting.rb +43 -26
- data/lib/active_support/deprecation.rb +32 -5
- data/lib/active_support/deprecator.rb +7 -0
- data/lib/active_support/descendants_tracker.rb +104 -132
- data/lib/active_support/duration/iso8601_serializer.rb +0 -2
- data/lib/active_support/duration.rb +2 -1
- data/lib/active_support/encrypted_configuration.rb +63 -11
- data/lib/active_support/encrypted_file.rb +16 -12
- data/lib/active_support/environment_inquirer.rb +22 -2
- data/lib/active_support/error_reporter/test_helper.rb +15 -0
- data/lib/active_support/error_reporter.rb +121 -35
- data/lib/active_support/evented_file_update_checker.rb +17 -2
- data/lib/active_support/execution_wrapper.rb +4 -4
- data/lib/active_support/file_update_checker.rb +4 -2
- data/lib/active_support/fork_tracker.rb +10 -2
- data/lib/active_support/gem_version.rb +4 -4
- data/lib/active_support/gzip.rb +2 -0
- data/lib/active_support/hash_with_indifferent_access.rb +35 -17
- data/lib/active_support/html_safe_translation.rb +16 -6
- data/lib/active_support/i18n.rb +1 -1
- data/lib/active_support/i18n_railtie.rb +20 -13
- data/lib/active_support/inflector/inflections.rb +2 -0
- data/lib/active_support/inflector/methods.rb +28 -18
- data/lib/active_support/inflector/transliterate.rb +3 -1
- data/lib/active_support/isolated_execution_state.rb +26 -22
- data/lib/active_support/json/decoding.rb +2 -1
- data/lib/active_support/json/encoding.rb +25 -43
- data/lib/active_support/key_generator.rb +9 -1
- data/lib/active_support/lazy_load_hooks.rb +7 -5
- data/lib/active_support/locale/en.yml +2 -0
- data/lib/active_support/log_subscriber.rb +85 -33
- data/lib/active_support/logger.rb +9 -60
- data/lib/active_support/logger_thread_safe_level.rb +10 -24
- data/lib/active_support/message_encryptor.rb +197 -53
- 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 +212 -93
- 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 +111 -45
- data/lib/active_support/messages/rotation_coordinator.rb +93 -0
- data/lib/active_support/messages/rotator.rb +34 -32
- data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
- data/lib/active_support/multibyte/chars.rb +2 -0
- data/lib/active_support/multibyte/unicode.rb +9 -37
- data/lib/active_support/notifications/fanout.rb +245 -81
- data/lib/active_support/notifications/instrumenter.rb +87 -22
- data/lib/active_support/notifications.rb +3 -3
- data/lib/active_support/number_helper/number_converter.rb +14 -5
- data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -6
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +3 -3
- data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -0
- data/lib/active_support/number_helper.rb +379 -317
- data/lib/active_support/ordered_hash.rb +3 -3
- data/lib/active_support/ordered_options.rb +14 -0
- data/lib/active_support/parameter_filter.rb +103 -84
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/railtie.rb +33 -21
- data/lib/active_support/reloader.rb +12 -4
- data/lib/active_support/rescuable.rb +2 -0
- data/lib/active_support/secure_compare_rotator.rb +16 -9
- data/lib/active_support/string_inquirer.rb +3 -1
- data/lib/active_support/subscriber.rb +9 -27
- data/lib/active_support/syntax_error_proxy.rb +60 -0
- data/lib/active_support/tagged_logging.rb +64 -24
- data/lib/active_support/test_case.rb +153 -6
- data/lib/active_support/testing/assertions.rb +26 -10
- 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 +25 -25
- data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
- data/lib/active_support/testing/isolation.rb +29 -28
- data/lib/active_support/testing/method_call_assertions.rb +21 -8
- data/lib/active_support/testing/parallelize_executor.rb +8 -3
- data/lib/active_support/testing/setup_and_teardown.rb +2 -0
- data/lib/active_support/testing/stream.rb +1 -1
- data/lib/active_support/testing/strict_warnings.rb +39 -0
- data/lib/active_support/testing/time_helpers.rb +37 -15
- data/lib/active_support/time_with_zone.rb +8 -37
- data/lib/active_support/values/time_zone.rb +18 -7
- data/lib/active_support/version.rb +1 -1
- data/lib/active_support/xml_mini/jdom.rb +3 -10
- data/lib/active_support/xml_mini/nokogiri.rb +1 -1
- data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
- data/lib/active_support/xml_mini/rexml.rb +1 -1
- data/lib/active_support/xml_mini.rb +2 -2
- data/lib/active_support.rb +14 -3
- metadata +148 -19
- data/lib/active_support/core_ext/array/deprecated_conversions.rb +0 -25
- data/lib/active_support/core_ext/date/deprecated_conversions.rb +0 -26
- data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +0 -22
- data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +0 -60
- data/lib/active_support/core_ext/range/deprecated_conversions.rb +0 -26
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -7
- data/lib/active_support/core_ext/range/overlaps.rb +0 -10
- data/lib/active_support/core_ext/time/deprecated_conversions.rb +0 -22
- data/lib/active_support/core_ext/uri.rb +0 -5
- data/lib/active_support/per_thread_registry.rb +0 -65
@@ -6,14 +6,16 @@ require "logger"
|
|
6
6
|
require "active_support/logger"
|
7
7
|
|
8
8
|
module ActiveSupport
|
9
|
+
# = Active Support Tagged Logging
|
10
|
+
#
|
9
11
|
# Wraps any standard Logger object to provide tagging capabilities.
|
10
12
|
#
|
11
13
|
# May be called with a block:
|
12
14
|
#
|
13
15
|
# logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
|
14
|
-
# logger.tagged('BCX') { logger.info 'Stuff' }
|
15
|
-
# logger.tagged('BCX', "Jason") {
|
16
|
-
# logger.tagged('BCX') { logger.tagged('Jason') { logger.info 'Stuff' } }
|
16
|
+
# logger.tagged('BCX') { logger.info 'Stuff' } # Logs "[BCX] Stuff"
|
17
|
+
# logger.tagged('BCX', "Jason") { |tagged_logger| tagged_logger.info 'Stuff' } # Logs "[BCX] [Jason] Stuff"
|
18
|
+
# logger.tagged('BCX') { logger.tagged('Jason') { logger.info 'Stuff' } } # Logs "[BCX] [Jason] Stuff"
|
17
19
|
#
|
18
20
|
# If called without a block, a new logger will be returned with applied tags:
|
19
21
|
#
|
@@ -29,52 +31,86 @@ module ActiveSupport
|
|
29
31
|
module Formatter # :nodoc:
|
30
32
|
# This method is invoked when a log event occurs.
|
31
33
|
def call(severity, timestamp, progname, msg)
|
32
|
-
super(severity, timestamp, progname,
|
34
|
+
super(severity, timestamp, progname, tag_stack.format_message(msg))
|
33
35
|
end
|
34
36
|
|
35
37
|
def tagged(*tags)
|
36
|
-
|
38
|
+
pushed_count = tag_stack.push_tags(tags).size
|
37
39
|
yield self
|
38
40
|
ensure
|
39
|
-
pop_tags(
|
41
|
+
pop_tags(pushed_count)
|
40
42
|
end
|
41
43
|
|
42
44
|
def push_tags(*tags)
|
43
|
-
tags
|
44
|
-
tags.reject!(&:blank?)
|
45
|
-
current_tags.concat tags
|
46
|
-
tags
|
45
|
+
tag_stack.push_tags(tags)
|
47
46
|
end
|
48
47
|
|
49
|
-
def pop_tags(
|
50
|
-
|
48
|
+
def pop_tags(count = 1)
|
49
|
+
tag_stack.pop_tags(count)
|
51
50
|
end
|
52
51
|
|
53
52
|
def clear_tags!
|
54
|
-
|
53
|
+
tag_stack.clear
|
55
54
|
end
|
56
55
|
|
57
|
-
def
|
56
|
+
def tag_stack
|
58
57
|
# We use our object ID here to avoid conflicting with other instances
|
59
|
-
|
60
|
-
IsolatedExecutionState[thread_key] ||=
|
58
|
+
@thread_key ||= "activesupport_tagged_logging_tags:#{object_id}"
|
59
|
+
IsolatedExecutionState[@thread_key] ||= TagStack.new
|
60
|
+
end
|
61
|
+
|
62
|
+
def current_tags
|
63
|
+
tag_stack.tags
|
61
64
|
end
|
62
65
|
|
63
66
|
def tags_text
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
67
|
+
tag_stack.format_message("")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class TagStack # :nodoc:
|
72
|
+
attr_reader :tags
|
73
|
+
|
74
|
+
def initialize
|
75
|
+
@tags = []
|
76
|
+
@tags_string = nil
|
77
|
+
end
|
78
|
+
|
79
|
+
def push_tags(tags)
|
80
|
+
@tags_string = nil
|
81
|
+
tags.flatten!
|
82
|
+
tags.reject!(&:blank?)
|
83
|
+
@tags.concat(tags)
|
84
|
+
tags
|
85
|
+
end
|
86
|
+
|
87
|
+
def pop_tags(count)
|
88
|
+
@tags_string = nil
|
89
|
+
@tags.pop(count)
|
90
|
+
end
|
91
|
+
|
92
|
+
def clear
|
93
|
+
@tags_string = nil
|
94
|
+
@tags.clear
|
95
|
+
end
|
96
|
+
|
97
|
+
def format_message(message)
|
98
|
+
if @tags.empty?
|
99
|
+
message
|
100
|
+
elsif @tags.size == 1
|
101
|
+
"[#{@tags[0]}] #{message}"
|
102
|
+
else
|
103
|
+
@tags_string ||= "[#{@tags.join("] [")}] "
|
104
|
+
"#{@tags_string}#{message}"
|
69
105
|
end
|
70
106
|
end
|
71
107
|
end
|
72
108
|
|
73
109
|
module LocalTagStorage # :nodoc:
|
74
|
-
attr_accessor :
|
110
|
+
attr_accessor :tag_stack
|
75
111
|
|
76
112
|
def self.extended(base)
|
77
|
-
base.
|
113
|
+
base.tag_stack = TagStack.new
|
78
114
|
end
|
79
115
|
end
|
80
116
|
|
@@ -82,7 +118,11 @@ module ActiveSupport
|
|
82
118
|
logger = logger.clone
|
83
119
|
|
84
120
|
if logger.formatter
|
85
|
-
logger.formatter = logger.formatter.
|
121
|
+
logger.formatter = logger.formatter.clone
|
122
|
+
|
123
|
+
# Workaround for https://bugs.ruby-lang.org/issues/20250
|
124
|
+
# Can be removed when Ruby 3.4 is the least supported version.
|
125
|
+
logger.formatter.object_id if logger.formatter.is_a?(Proc)
|
86
126
|
else
|
87
127
|
# Ensure we set a default formatter so we aren't extending nil!
|
88
128
|
logger.formatter = ActiveSupport::Logger::SimpleFormatter.new
|
@@ -1,15 +1,16 @@
|
|
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"
|
15
16
|
require "active_support/testing/parallelize_executor"
|
@@ -66,7 +67,7 @@ module ActiveSupport
|
|
66
67
|
# The default parallelization method is to fork processes. If you'd like to
|
67
68
|
# use threads instead you can pass <tt>with: :threads</tt> to the +parallelize+
|
68
69
|
# method. Note the threaded parallelization does not create multiple
|
69
|
-
#
|
70
|
+
# databases and will not work with system tests.
|
70
71
|
#
|
71
72
|
# parallelize(workers: :number_of_processors, with: :threads)
|
72
73
|
#
|
@@ -80,8 +81,6 @@ module ActiveSupport
|
|
80
81
|
workers = Concurrent.physical_processor_count if workers == :number_of_processors
|
81
82
|
workers = ENV["PARALLEL_WORKERS"].to_i if ENV["PARALLEL_WORKERS"]
|
82
83
|
|
83
|
-
return if workers <= 1
|
84
|
-
|
85
84
|
Minitest.parallel_executor = ActiveSupport::Testing::ParallelizeExecutor.new(size: workers, with: with, threshold: threshold)
|
86
85
|
end
|
87
86
|
|
@@ -118,6 +117,25 @@ module ActiveSupport
|
|
118
117
|
def parallelize_teardown(&block)
|
119
118
|
ActiveSupport::Testing::Parallelization.run_cleanup_hook(&block)
|
120
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>.
|
121
139
|
end
|
122
140
|
|
123
141
|
alias_method :method_name, :name
|
@@ -125,25 +143,154 @@ module ActiveSupport
|
|
125
143
|
include ActiveSupport::Testing::TaggedLogging
|
126
144
|
prepend ActiveSupport::Testing::SetupAndTeardown
|
127
145
|
include ActiveSupport::Testing::Assertions
|
146
|
+
include ActiveSupport::Testing::ErrorReporterAssertions
|
128
147
|
include ActiveSupport::Testing::Deprecation
|
148
|
+
include ActiveSupport::Testing::ConstantStubbing
|
129
149
|
include ActiveSupport::Testing::TimeHelpers
|
130
150
|
include ActiveSupport::Testing::FileFixtures
|
131
151
|
extend ActiveSupport::Testing::Declarative
|
132
152
|
|
133
|
-
|
134
|
-
|
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
|
+
#
|
135
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
|
+
#
|
136
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
|
+
#
|
137
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
|
+
#
|
138
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
|
+
#
|
139
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
|
+
#
|
140
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
|
+
#
|
141
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
|
+
#
|
142
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
|
+
#
|
143
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
|
+
#
|
144
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
|
+
#
|
145
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
|
+
#
|
146
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
|
+
#
|
147
294
|
alias :assert_not_same :refute_same
|
148
295
|
|
149
296
|
ActiveSupport.run_load_hooks(:active_support_test_case, self)
|
@@ -7,9 +7,9 @@ module ActiveSupport
|
|
7
7
|
module Assertions
|
8
8
|
UNTRACKED = Object.new # :nodoc:
|
9
9
|
|
10
|
-
# Asserts that an expression is not truthy. Passes if
|
11
|
-
# +
|
12
|
-
#
|
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>.
|
13
13
|
#
|
14
14
|
# assert_not nil # => true
|
15
15
|
# assert_not false # => true
|
@@ -23,6 +23,21 @@ module ActiveSupport
|
|
23
23
|
assert !object, message
|
24
24
|
end
|
25
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
|
+
|
26
41
|
# Assertion that the block should not raise an exception.
|
27
42
|
#
|
28
43
|
# Passes if evaluated code in the yielded block raises no exception.
|
@@ -31,7 +46,7 @@ module ActiveSupport
|
|
31
46
|
# perform_service(param: 'no_exception')
|
32
47
|
# end
|
33
48
|
def assert_nothing_raised
|
34
|
-
yield
|
49
|
+
yield.tap { assert(true) }
|
35
50
|
rescue => error
|
36
51
|
raise Minitest::UnexpectedError.new(error)
|
37
52
|
end
|
@@ -50,7 +65,7 @@ module ActiveSupport
|
|
50
65
|
# end
|
51
66
|
#
|
52
67
|
# An arbitrary positive or negative difference can be specified.
|
53
|
-
# The default is
|
68
|
+
# The default is +1+.
|
54
69
|
#
|
55
70
|
# assert_difference 'Article.count', -1 do
|
56
71
|
# post :delete, params: { id: ... }
|
@@ -102,9 +117,10 @@ module ActiveSupport
|
|
102
117
|
retval = _assert_nothing_raised_or_warn("assert_difference", &block)
|
103
118
|
|
104
119
|
expressions.zip(exps, before) do |(code, diff), exp, before_value|
|
105
|
-
|
120
|
+
actual = exp.call
|
121
|
+
error = "#{code.inspect} didn't change by #{diff}, but by #{actual - before_value}"
|
106
122
|
error = "#{message}.\n#{error}" if message
|
107
|
-
assert_equal(before_value + diff,
|
123
|
+
assert_equal(before_value + diff, actual, error)
|
108
124
|
end
|
109
125
|
|
110
126
|
retval
|
@@ -179,7 +195,7 @@ module ActiveSupport
|
|
179
195
|
retval = _assert_nothing_raised_or_warn("assert_changes", &block)
|
180
196
|
|
181
197
|
unless from == UNTRACKED
|
182
|
-
error = "Expected change from #{from.inspect}"
|
198
|
+
error = "Expected change from #{from.inspect}, got #{before}"
|
183
199
|
error = "#{message}.\n#{error}" if message
|
184
200
|
assert from === before, error
|
185
201
|
end
|
@@ -192,7 +208,7 @@ module ActiveSupport
|
|
192
208
|
refute_equal before, after, error
|
193
209
|
|
194
210
|
unless to == UNTRACKED
|
195
|
-
error = "Expected change to #{to}\n"
|
211
|
+
error = "Expected change to #{to}, got #{after}\n"
|
196
212
|
error = "#{message}.\n#{error}" if message
|
197
213
|
assert to === after, error
|
198
214
|
end
|
@@ -207,7 +223,7 @@ module ActiveSupport
|
|
207
223
|
# post :create, params: { status: { ok: true } }
|
208
224
|
# end
|
209
225
|
#
|
210
|
-
# Provide the optional keyword argument
|
226
|
+
# Provide the optional keyword argument +:from+ to specify the expected
|
211
227
|
# initial value.
|
212
228
|
#
|
213
229
|
# assert_no_changes -> { Status.all_good? }, from: true do
|
@@ -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
|
@@ -5,6 +5,11 @@ require "active_support/deprecation"
|
|
5
5
|
module ActiveSupport
|
6
6
|
module Testing
|
7
7
|
module Deprecation
|
8
|
+
##
|
9
|
+
# :call-seq:
|
10
|
+
# assert_deprecated(deprecator, &block)
|
11
|
+
# assert_deprecated(match, deprecator, &block)
|
12
|
+
#
|
8
13
|
# Asserts that a matching deprecation warning was emitted by the given deprecator during the execution of the yielded block.
|
9
14
|
#
|
10
15
|
# assert_deprecated(/foo/, CustomDeprecator) do
|
@@ -19,16 +24,15 @@ module ActiveSupport
|
|
19
24
|
#
|
20
25
|
# If the +match+ is omitted (or explicitly +nil+), any deprecation warning will match.
|
21
26
|
#
|
22
|
-
# assert_deprecated(
|
27
|
+
# assert_deprecated(CustomDeprecator) do
|
23
28
|
# CustomDeprecator.warn "foo should no longer be used"
|
24
29
|
# end
|
25
|
-
#
|
26
|
-
# If no +deprecator+ is given, defaults to ActiveSupport::Deprecation.
|
27
|
-
#
|
28
|
-
# assert_deprecated do
|
29
|
-
# ActiveSupport::Deprecation.warn "foo should no longer be used"
|
30
|
-
# end
|
31
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
|
32
36
|
result, warnings = collect_deprecations(deprecator, &block)
|
33
37
|
assert !warnings.empty?, "Expected a deprecation warning within the block but received none"
|
34
38
|
if match
|
@@ -44,36 +48,32 @@ module ActiveSupport
|
|
44
48
|
# CustomDeprecator.warn "message" # fails assertion
|
45
49
|
# end
|
46
50
|
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
# assert_not_deprecated do
|
50
|
-
# ActiveSupport::Deprecation.warn "message" # fails assertion
|
51
|
-
# end
|
52
|
-
#
|
53
|
-
# assert_not_deprecated do
|
54
|
-
# CustomDeprecator.warn "message" # passes assertion
|
51
|
+
# assert_not_deprecated(ActiveSupport::Deprecation.new) do
|
52
|
+
# CustomDeprecator.warn "message" # passes assertion, different deprecator
|
55
53
|
# end
|
56
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
|
57
59
|
result, deprecations = collect_deprecations(deprecator, &block)
|
58
60
|
assert deprecations.empty?, "Expected no deprecation warning within the block but received #{deprecations.size}: \n #{deprecations * "\n "}"
|
59
61
|
result
|
60
62
|
end
|
61
63
|
|
62
|
-
# Returns an array of all the deprecation warnings emitted by the given
|
64
|
+
# Returns the return value of the block and an array of all the deprecation warnings emitted by the given
|
63
65
|
# +deprecator+ during the execution of the yielded block.
|
64
66
|
#
|
65
67
|
# collect_deprecations(CustomDeprecator) do
|
66
68
|
# CustomDeprecator.warn "message"
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
# collect_deprecations do
|
72
|
-
# CustomDeprecator.warn "custom message"
|
73
|
-
# ActiveSupport::Deprecation.warn "message"
|
74
|
-
# end # => ["message"]
|
69
|
+
# ActiveSupport::Deprecation.new.warn "other message"
|
70
|
+
# :result
|
71
|
+
# end # => [:result, ["message"]]
|
75
72
|
def collect_deprecations(deprecator = nil)
|
76
|
-
deprecator
|
73
|
+
unless deprecator
|
74
|
+
ActiveSupport.deprecator.warn("collect_deprecations without a deprecator is deprecated")
|
75
|
+
deprecator = ActiveSupport::Deprecation._instance
|
76
|
+
end
|
77
77
|
old_behavior = deprecator.behavior
|
78
78
|
deprecations = []
|
79
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
|