exception_handling 2.16.0 → 3.0.pre.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 +5 -5
- data/.gitignore +0 -3
- data/.ruby-version +1 -1
- data/Gemfile +16 -12
- data/Gemfile.lock +114 -109
- data/README.md +21 -61
- data/Rakefile +11 -8
- data/exception_handling.gemspec +10 -12
- data/lib/exception_handling/exception_info.rb +11 -15
- data/lib/exception_handling/honeybadger_callbacks.rb +59 -0
- data/lib/exception_handling/log_stub_error.rb +1 -2
- data/lib/exception_handling/methods.rb +53 -6
- data/lib/exception_handling/testing.rb +10 -20
- data/lib/exception_handling/version.rb +1 -1
- data/lib/exception_handling.rb +34 -95
- data/semaphore_ci/setup.sh +3 -0
- data/{spec → test}/helpers/exception_helpers.rb +2 -2
- data/{spec/spec_helper.rb → test/test_helper.rb} +42 -63
- data/test/unit/exception_handling/exception_catalog_test.rb +85 -0
- data/test/unit/exception_handling/exception_description_test.rb +82 -0
- data/{spec/unit/exception_handling/exception_info_spec.rb → test/unit/exception_handling/exception_info_test.rb} +114 -170
- data/test/unit/exception_handling/honeybadger_callbacks_test.rb +122 -0
- data/{spec/unit/exception_handling/log_error_stub_spec.rb → test/unit/exception_handling/log_error_stub_test.rb} +22 -38
- data/{spec/unit/exception_handling/mailer_spec.rb → test/unit/exception_handling/mailer_test.rb} +18 -17
- data/test/unit/exception_handling/methods_test.rb +84 -0
- data/test/unit/exception_handling/sensu_test.rb +52 -0
- data/test/unit/exception_handling_test.rb +1109 -0
- metadata +60 -100
- data/.github/CODEOWNERS +0 -1
- data/.github/workflows/pipeline.yml +0 -40
- data/.rspec +0 -3
- data/.tool-versions +0 -1
- data/Appraisals +0 -19
- data/CHANGELOG.md +0 -136
- data/gemfiles/rails_5.gemfile +0 -18
- data/gemfiles/rails_6.gemfile +0 -18
- data/gemfiles/rails_7.gemfile +0 -18
- data/lib/exception_handling/escalate_callback.rb +0 -19
- data/lib/exception_handling/logging_methods.rb +0 -27
- data/spec/rake_test_warning_false.rb +0 -20
- data/spec/unit/exception_handling/escalate_callback_spec.rb +0 -81
- data/spec/unit/exception_handling/exception_catalog_spec.rb +0 -85
- data/spec/unit/exception_handling/exception_description_spec.rb +0 -82
- data/spec/unit/exception_handling/logging_methods_spec.rb +0 -38
- data/spec/unit/exception_handling/methods_spec.rb +0 -105
- data/spec/unit/exception_handling/sensu_spec.rb +0 -51
- data/spec/unit/exception_handling_spec.rb +0 -1361
- /data/{spec → test}/helpers/controller_helpers.rb +0 -0
@@ -1,15 +1,65 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'active_support/concern'
|
4
|
-
require_relative 'logging_methods'
|
5
4
|
|
6
5
|
module ExceptionHandling
|
7
6
|
module Methods # included on models and controllers
|
8
7
|
extend ActiveSupport::Concern
|
9
|
-
include ExceptionHandling::LoggingMethods
|
10
8
|
|
11
9
|
protected
|
12
10
|
|
11
|
+
def log_error(exception_or_string, exception_context = '')
|
12
|
+
controller = self if respond_to?(:request) && respond_to?(:session)
|
13
|
+
ExceptionHandling.log_error(exception_or_string, exception_context, controller)
|
14
|
+
end
|
15
|
+
|
16
|
+
def log_error_rack(exception_or_string, exception_context = '', rack_filter = '')
|
17
|
+
ExceptionHandling.log_error_rack(exception_or_string, exception_context, rack_filter)
|
18
|
+
end
|
19
|
+
|
20
|
+
def log_warning(message)
|
21
|
+
ExceptionHandling.log_warning(message)
|
22
|
+
end
|
23
|
+
|
24
|
+
def log_info(message)
|
25
|
+
ExceptionHandling.logger.info(message)
|
26
|
+
end
|
27
|
+
|
28
|
+
def log_debug(message)
|
29
|
+
ExceptionHandling.logger.debug(message)
|
30
|
+
end
|
31
|
+
|
32
|
+
def ensure_safe(exception_context = "")
|
33
|
+
yield
|
34
|
+
rescue => ex
|
35
|
+
log_error ex, exception_context
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
|
39
|
+
def escalate_error(exception_or_string, email_subject)
|
40
|
+
ExceptionHandling.escalate_error(exception_or_string, email_subject)
|
41
|
+
end
|
42
|
+
|
43
|
+
def escalate_warning(message, email_subject)
|
44
|
+
ExceptionHandling.escalate_warning(message, email_subject)
|
45
|
+
end
|
46
|
+
|
47
|
+
def ensure_escalation(*args)
|
48
|
+
ExceptionHandling.ensure_escalation(*args) do
|
49
|
+
yield
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def alert_warning(*args)
|
54
|
+
ExceptionHandling.alert_warning(*args)
|
55
|
+
end
|
56
|
+
|
57
|
+
def ensure_alert(*args)
|
58
|
+
ExceptionHandling.ensure_alert(*args) do
|
59
|
+
yield
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
13
63
|
def long_controller_action_timeout
|
14
64
|
if defined?(Rails) && Rails.respond_to?(:env) && Rails.env == 'test'
|
15
65
|
300
|
@@ -38,10 +88,7 @@ module ExceptionHandling
|
|
38
88
|
end
|
39
89
|
|
40
90
|
included do
|
41
|
-
|
42
|
-
if respond_to? :around_filter
|
43
|
-
around_filter :set_current_controller
|
44
|
-
end
|
91
|
+
around_filter :set_current_controller if respond_to? :around_filter
|
45
92
|
end
|
46
93
|
|
47
94
|
class_methods do
|
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
module ExceptionHandling
|
6
6
|
module Testing
|
7
|
-
class
|
7
|
+
class ControllerStub
|
8
8
|
|
9
9
|
class Request
|
10
10
|
attr_accessor :parameters, :protocol, :host, :request_uri, :env, :session_options
|
@@ -25,7 +25,7 @@ module ExceptionHandling
|
|
25
25
|
attr_accessor :around_filter_method
|
26
26
|
|
27
27
|
def around_filter(method)
|
28
|
-
|
28
|
+
ControllerStub.around_filter_method = method
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
@@ -44,6 +44,14 @@ module ExceptionHandling
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
+
def simulate_around_filter(&block)
|
48
|
+
set_current_controller(&block)
|
49
|
+
end
|
50
|
+
|
51
|
+
def controller_name
|
52
|
+
"ControllerStub"
|
53
|
+
end
|
54
|
+
|
47
55
|
def action_name
|
48
56
|
"test_action"
|
49
57
|
end
|
@@ -51,27 +59,9 @@ module ExceptionHandling
|
|
51
59
|
def complete_request_uri
|
52
60
|
"#{@request.protocol}#{@request.host}#{@request.request_uri}"
|
53
61
|
end
|
54
|
-
end
|
55
|
-
|
56
|
-
class LoggingMethodsControllerStub < ControllerStubBase
|
57
|
-
include ExceptionHandling::LoggingMethods
|
58
|
-
|
59
|
-
def controller_name
|
60
|
-
"LoggingMethodsControllerStub"
|
61
|
-
end
|
62
|
-
end
|
63
62
|
|
64
|
-
class MethodsControllerStub < ControllerStubBase
|
65
63
|
include ExceptionHandling::Methods
|
66
64
|
set_long_controller_action_timeout 2
|
67
|
-
|
68
|
-
def simulate_around_filter(&block)
|
69
|
-
set_current_controller(&block)
|
70
|
-
end
|
71
|
-
|
72
|
-
def controller_name
|
73
|
-
"MethodsControllerStub"
|
74
|
-
end
|
75
65
|
end
|
76
66
|
end
|
77
67
|
end
|
data/lib/exception_handling.rb
CHANGED
@@ -1,21 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'digest'
|
4
3
|
require 'timeout'
|
5
4
|
require 'active_support'
|
6
|
-
require 'active_support/core_ext'
|
5
|
+
require 'active_support/core_ext/hash'
|
7
6
|
require 'contextual_logger'
|
8
7
|
|
9
8
|
require 'invoca/utils'
|
10
9
|
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
14
|
-
require
|
15
|
-
require
|
16
|
-
require
|
17
|
-
require
|
18
|
-
require
|
10
|
+
require "exception_handling/mailer"
|
11
|
+
require "exception_handling/sensu"
|
12
|
+
require "exception_handling/methods"
|
13
|
+
require "exception_handling/log_stub_error"
|
14
|
+
require "exception_handling/exception_description"
|
15
|
+
require "exception_handling/exception_catalog"
|
16
|
+
require "exception_handling/exception_info"
|
17
|
+
require "exception_handling/honeybadger_callbacks.rb"
|
19
18
|
|
20
19
|
_ = ActiveSupport::HashWithIndifferentAccess
|
21
20
|
|
@@ -30,8 +29,6 @@ module ExceptionHandling # never included
|
|
30
29
|
AUTHENTICATION_HEADERS = ['HTTP_AUTHORIZATION', 'X-HTTP_AUTHORIZATION', 'X_HTTP_AUTHORIZATION', 'REDIRECT_X_HTTP_AUTHORIZATION'].freeze
|
31
30
|
HONEYBADGER_STATUSES = [:success, :failure, :skipped].freeze
|
32
31
|
|
33
|
-
Deprecation3_0 = ActiveSupport::Deprecation.new('3.0', 'exception_handling')
|
34
|
-
|
35
32
|
class << self
|
36
33
|
|
37
34
|
#
|
@@ -53,28 +50,15 @@ module ExceptionHandling # never included
|
|
53
50
|
@exception_recipients or raise ArgumentError, "You must assign a value to #{name}.exception_recipients"
|
54
51
|
end
|
55
52
|
|
56
|
-
def configured?
|
57
|
-
!@logger.nil?
|
58
|
-
end
|
59
|
-
|
60
53
|
def logger
|
61
54
|
@logger or raise ArgumentError, "You must assign a value to #{name}.logger"
|
62
55
|
end
|
63
56
|
|
64
57
|
def logger=(logger)
|
65
|
-
@logger =
|
66
|
-
logger
|
67
|
-
else
|
68
|
-
Deprecation3_0.deprecation_warning('implicit extend with ContextualLogger::LoggerMixin', 'extend your logger instance or include into your logger class first')
|
69
|
-
logger.extend(ContextualLogger::LoggerMixin)
|
70
|
-
end
|
71
|
-
EscalateCallback.register_if_configured!
|
58
|
+
@logger = logger.is_a?(ContextualLogger) ? logger : ContextualLogger.new(logger)
|
72
59
|
end
|
73
60
|
|
74
|
-
def default_metric_name(exception_data, exception, treat_like_warning
|
75
|
-
include_prefix and Deprecation3_0.deprecation_warning("the 'expection_handling.' prefix in ExceptionHandling::default_metric_name",
|
76
|
-
"do not rely on metric names including the 'exception_handling.' prefix.")
|
77
|
-
|
61
|
+
def default_metric_name(exception_data, exception, treat_like_warning)
|
78
62
|
metric_name = if exception_data['metric_name']
|
79
63
|
exception_data['metric_name']
|
80
64
|
elsif exception.is_a?(ExceptionHandling::Warning)
|
@@ -86,7 +70,7 @@ module ExceptionHandling # never included
|
|
86
70
|
"exception"
|
87
71
|
end
|
88
72
|
|
89
|
-
"
|
73
|
+
"exception_handling.#{metric_name}"
|
90
74
|
end
|
91
75
|
|
92
76
|
def default_honeybadger_metric_name(honeybadger_status)
|
@@ -114,7 +98,6 @@ module ExceptionHandling # never included
|
|
114
98
|
attr_reader :filter_list_filename
|
115
99
|
attr_reader :eventmachine_safe
|
116
100
|
attr_reader :eventmachine_synchrony
|
117
|
-
attr_reader :honeybadger_auto_tagger
|
118
101
|
|
119
102
|
@filter_list_filename = "./config/exception_filters.yml"
|
120
103
|
@email_environment = ""
|
@@ -155,14 +138,6 @@ module ExceptionHandling # never included
|
|
155
138
|
@exception_catalog ||= ExceptionCatalog.new(@filter_list_filename)
|
156
139
|
end
|
157
140
|
|
158
|
-
# rubocop:disable Style/TrivialAccessors
|
159
|
-
# @param value [Proc|nil] Proc that accepts 1 parameter that will be the exception object or nil to disable the auto-tagger.
|
160
|
-
# The proc is always expected to return an array of strings. The array can be empty.
|
161
|
-
def honeybadger_auto_tagger=(value)
|
162
|
-
@honeybadger_auto_tagger = value
|
163
|
-
end
|
164
|
-
# rubocop:enable Style/TrivialAccessors
|
165
|
-
|
166
141
|
#
|
167
142
|
# internal settings (don't set directly)
|
168
143
|
#
|
@@ -202,18 +177,13 @@ module ExceptionHandling # never included
|
|
202
177
|
# Called directly by our code, usually from rescue blocks.
|
203
178
|
# Writes to log file and may send to honeybadger
|
204
179
|
#
|
205
|
-
# TODO: the **log_context means we can never have context named treat_like_warning. In general, keyword args will be conflated with log_context.
|
206
|
-
# Ideally we'd separate to log_context from the other keywords so they don't interfere in any way. Or have no keyword args.
|
207
|
-
#
|
208
180
|
# Functional Test Operation:
|
209
181
|
# Calls into handle_stub_log_error and returns. no log file. no honeybadger
|
210
182
|
#
|
211
|
-
def log_error(exception_or_string, exception_context = '',
|
183
|
+
def log_error(exception_or_string, exception_context = '', treat_like_warning: false, **log_context, &data_callback)
|
212
184
|
ex = make_exception(exception_or_string)
|
213
185
|
timestamp = set_log_error_timestamp
|
214
|
-
exception_info = ExceptionInfo.new(ex, exception_context, timestamp,
|
215
|
-
controller: controller || current_controller, data_callback: data_callback,
|
216
|
-
log_context: log_context)
|
186
|
+
exception_info = ExceptionInfo.new(ex, exception_context, timestamp, current_controller, data_callback)
|
217
187
|
|
218
188
|
if stub_handler
|
219
189
|
stub_handler.handle_stub_log_error(exception_info.data)
|
@@ -240,13 +210,7 @@ module ExceptionHandling # never included
|
|
240
210
|
#
|
241
211
|
def write_exception_to_log(ex, exception_context, timestamp, log_context = {})
|
242
212
|
ActiveSupport::Deprecation.silence do
|
243
|
-
|
244
|
-
|
245
|
-
if ex.is_a?(Warning)
|
246
|
-
ExceptionHandling.logger.warn("\nExceptionHandlingWarning (Warning:#{timestamp}) #{log_message}", **log_context)
|
247
|
-
else
|
248
|
-
ExceptionHandling.logger.fatal("\nExceptionHandlingError (Error:#{timestamp}) #{log_message}", **log_context)
|
249
|
-
end
|
213
|
+
ExceptionHandling.logger.fatal("\nExceptionHandlingError (Error:#{timestamp}) #{ex.class} #{exception_context} (#{encode_utf8(ex.message.to_s)}):\n " + clean_backtrace(ex).join("\n ") + "\n\n", log_context)
|
250
214
|
end
|
251
215
|
end
|
252
216
|
|
@@ -279,16 +243,11 @@ module ExceptionHandling # never included
|
|
279
243
|
def send_exception_to_honeybadger(exception_info)
|
280
244
|
exception = exception_info.exception
|
281
245
|
exception_description = exception_info.exception_description
|
282
|
-
|
283
|
-
# Note: Both commas and spaces are treated as delimiters for the :tags string. Space-delimiters are not officially documented.
|
284
|
-
# https://github.com/honeybadger-io/honeybadger-ruby/pull/422
|
285
|
-
tags = (honeybadger_auto_tags(exception) + exception_info.honeybadger_tags).join(' ')
|
286
246
|
response = Honeybadger.notify(error_class: exception_description ? exception_description.filter_name : exception.class.name,
|
287
247
|
error_message: exception.message.to_s,
|
288
248
|
exception: exception,
|
289
249
|
context: exception_info.honeybadger_context_data,
|
290
|
-
controller: exception_info.controller_name
|
291
|
-
tags: tags)
|
250
|
+
controller: exception_info.controller_name)
|
292
251
|
response ? :success : :failure
|
293
252
|
rescue Exception => ex
|
294
253
|
warn("ExceptionHandling.send_exception_to_honeybadger rescued exception while logging #{exception_info.exception_context}:\n#{exception.class}: #{exception.message}:\n#{ex.class}: #{ex.message}\n#{ex.backtrace.join("\n")}")
|
@@ -296,18 +255,6 @@ module ExceptionHandling # never included
|
|
296
255
|
:failure
|
297
256
|
end
|
298
257
|
|
299
|
-
# @param exception [Exception]
|
300
|
-
#
|
301
|
-
# @return [Array<String>]
|
302
|
-
def honeybadger_auto_tags(exception)
|
303
|
-
@honeybadger_auto_tagger&.call(exception) || []
|
304
|
-
rescue => ex
|
305
|
-
traces = ex.backtrace.join("\n")
|
306
|
-
message = "Unable to execute honeybadger_auto_tags callback. #{ExceptionHandling.encode_utf8(ex.message.to_s)} #{traces}\n"
|
307
|
-
ExceptionHandling.log_info(message)
|
308
|
-
[]
|
309
|
-
end
|
310
|
-
|
311
258
|
#
|
312
259
|
# Check if Honeybadger defined.
|
313
260
|
#
|
@@ -318,41 +265,38 @@ module ExceptionHandling # never included
|
|
318
265
|
#
|
319
266
|
# Expects passed in hash to only include keys which be directly set on the Honeybadger config
|
320
267
|
#
|
321
|
-
def enable_honeybadger(
|
268
|
+
def enable_honeybadger(config = {})
|
322
269
|
Bundler.require(:honeybadger)
|
270
|
+
HoneybadgerCallbacks.register_callbacks
|
323
271
|
Honeybadger.configure do |config_klass|
|
324
272
|
config.each do |k, v|
|
325
|
-
|
326
|
-
config_klass.send(k, v)
|
327
|
-
else
|
328
|
-
config_klass.send(:"#{k}=", v)
|
329
|
-
end
|
273
|
+
config_klass.send(:"#{k}=", v)
|
330
274
|
end
|
331
275
|
end
|
332
276
|
end
|
333
277
|
|
334
|
-
def log_warning(message,
|
278
|
+
def log_warning(message, log_context = {})
|
335
279
|
warning = Warning.new(message)
|
336
280
|
warning.set_backtrace([])
|
337
281
|
log_error(warning, **log_context)
|
338
282
|
end
|
339
283
|
|
340
|
-
def log_info(message,
|
341
|
-
ExceptionHandling.logger.info(message,
|
284
|
+
def log_info(message, log_context = {})
|
285
|
+
ExceptionHandling.logger.info(message, log_context)
|
342
286
|
end
|
343
287
|
|
344
|
-
def log_debug(message,
|
345
|
-
ExceptionHandling.logger.debug(message,
|
288
|
+
def log_debug(message, log_context = {})
|
289
|
+
ExceptionHandling.logger.debug(message, log_context)
|
346
290
|
end
|
347
291
|
|
348
|
-
def ensure_safe(exception_context = "",
|
292
|
+
def ensure_safe(exception_context = "", log_context = {})
|
349
293
|
yield
|
350
294
|
rescue => ex
|
351
295
|
log_error(ex, exception_context, **log_context)
|
352
296
|
nil
|
353
297
|
end
|
354
298
|
|
355
|
-
def ensure_completely_safe(exception_context = "",
|
299
|
+
def ensure_completely_safe(exception_context = "", log_context = {})
|
356
300
|
yield
|
357
301
|
rescue SystemExit, SystemStackError, NoMemoryError, SecurityError, SignalException
|
358
302
|
raise
|
@@ -367,29 +311,26 @@ module ExceptionHandling # never included
|
|
367
311
|
escalate(email_subject, ex, last_exception_timestamp, production_support_recipients)
|
368
312
|
end
|
369
313
|
|
370
|
-
def escalate_error(exception_or_string, email_subject, custom_recipients = nil,
|
314
|
+
def escalate_error(exception_or_string, email_subject, custom_recipients = nil, log_context = {})
|
371
315
|
ex = make_exception(exception_or_string)
|
372
316
|
log_error(ex, **log_context)
|
373
317
|
escalate(email_subject, ex, last_exception_timestamp, custom_recipients)
|
374
318
|
end
|
375
319
|
|
376
|
-
def escalate_warning(message, email_subject, custom_recipients = nil,
|
320
|
+
def escalate_warning(message, email_subject, custom_recipients = nil, log_context = {})
|
377
321
|
ex = Warning.new(message)
|
378
322
|
log_error(ex, **log_context)
|
379
323
|
escalate(email_subject, ex, last_exception_timestamp, custom_recipients)
|
380
324
|
end
|
381
325
|
|
382
|
-
def ensure_escalation(email_subject, custom_recipients = nil,
|
326
|
+
def ensure_escalation(email_subject, custom_recipients = nil, log_context = {})
|
383
327
|
yield
|
384
328
|
rescue => ex
|
385
|
-
escalate_error(ex, email_subject, custom_recipients,
|
329
|
+
escalate_error(ex, email_subject, custom_recipients, log_context)
|
386
330
|
nil
|
387
331
|
end
|
388
332
|
|
389
|
-
|
390
|
-
deprecator: ActiveSupport::Deprecation.new('3.0', 'ExceptionHandling')
|
391
|
-
|
392
|
-
def alert_warning(exception_or_string, alert_name, exception_context, **log_context)
|
333
|
+
def alert_warning(exception_or_string, alert_name, exception_context, log_context)
|
393
334
|
ex = make_exception(exception_or_string)
|
394
335
|
log_error(ex, exception_context, **log_context)
|
395
336
|
begin
|
@@ -399,10 +340,10 @@ module ExceptionHandling # never included
|
|
399
340
|
end
|
400
341
|
end
|
401
342
|
|
402
|
-
def ensure_alert(alert_name, exception_context,
|
343
|
+
def ensure_alert(alert_name, exception_context, log_context = {})
|
403
344
|
yield
|
404
345
|
rescue => ex
|
405
|
-
alert_warning(ex, alert_name, exception_context,
|
346
|
+
alert_warning(ex, alert_name, exception_context, log_context)
|
406
347
|
nil
|
407
348
|
end
|
408
349
|
|
@@ -419,7 +360,7 @@ module ExceptionHandling # never included
|
|
419
360
|
result
|
420
361
|
end
|
421
362
|
|
422
|
-
def log_periodically(exception_key, interval, message,
|
363
|
+
def log_periodically(exception_key, interval, message, log_context = {})
|
423
364
|
self.periodic_exception_intervals ||= {}
|
424
365
|
last_logged = self.periodic_exception_intervals[exception_key]
|
425
366
|
if !last_logged || ((last_logged + interval) < Time.now)
|
@@ -522,6 +463,4 @@ module ExceptionHandling # never included
|
|
522
463
|
end
|
523
464
|
end
|
524
465
|
end
|
525
|
-
|
526
|
-
EscalateCallback.register_if_configured!
|
527
466
|
end
|
@@ -7,7 +7,7 @@ module ExceptionHelpers
|
|
7
7
|
|
8
8
|
def exception_with_nil_message
|
9
9
|
exception_with_nil_message = RuntimeError.new(nil)
|
10
|
-
|
10
|
+
stub(exception_with_nil_message).message { nil }
|
11
11
|
exception_with_nil_message
|
12
12
|
end
|
13
13
|
|
@@ -15,6 +15,6 @@ module ExceptionHelpers
|
|
15
15
|
|
16
16
|
def capture_notifications
|
17
17
|
@sent_notifications = []
|
18
|
-
|
18
|
+
stub(ExceptionHandling).send_exception_to_honeybadger(anything) { |exception_info| @sent_notifications << exception_info }
|
19
19
|
end
|
20
20
|
end
|
@@ -1,9 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
4
|
-
require '
|
5
|
-
require '
|
6
|
-
|
3
|
+
require 'active_support'
|
4
|
+
require 'active_support/time'
|
5
|
+
require 'active_support/test_case'
|
6
|
+
require 'active_model'
|
7
|
+
require 'action_mailer'
|
8
|
+
require 'action_dispatch'
|
9
|
+
require 'hobo_support'
|
10
|
+
require 'shoulda'
|
11
|
+
require 'rr'
|
12
|
+
require 'minitest/autorun'
|
7
13
|
require 'pry'
|
8
14
|
require 'honeybadger'
|
9
15
|
require 'contextual_logger'
|
@@ -11,31 +17,26 @@ require 'contextual_logger'
|
|
11
17
|
require 'exception_handling'
|
12
18
|
require 'exception_handling/testing'
|
13
19
|
|
20
|
+
ActiveSupport::TestCase.test_order = :sorted
|
21
|
+
|
14
22
|
class LoggerStub
|
15
|
-
include ContextualLogger
|
16
|
-
attr_accessor :logged
|
23
|
+
include ContextualLogger
|
24
|
+
attr_accessor :logged
|
17
25
|
|
18
26
|
def initialize
|
19
|
-
@level = Logger::Severity::DEBUG
|
20
|
-
@progname = nil
|
21
|
-
@logdev = nil
|
22
27
|
clear
|
23
28
|
end
|
24
29
|
|
25
|
-
def debug(message, log_context = {})
|
26
|
-
logged << { message: message, context: log_context, severity: 'DEBUG' }
|
27
|
-
end
|
28
|
-
|
29
30
|
def info(message, log_context = {})
|
30
|
-
logged << { message: message, context: log_context
|
31
|
+
logged << { message: message, context: log_context }
|
31
32
|
end
|
32
33
|
|
33
34
|
def warn(message, log_context = {})
|
34
|
-
logged << { message: message, context: log_context
|
35
|
+
logged << { message: message, context: log_context }
|
35
36
|
end
|
36
37
|
|
37
38
|
def fatal(message, log_context = {})
|
38
|
-
logged << { message: message, context: log_context
|
39
|
+
logged << { message: message, context: log_context }
|
39
40
|
end
|
40
41
|
|
41
42
|
def clear
|
@@ -76,17 +77,27 @@ end
|
|
76
77
|
|
77
78
|
ActionMailer::Base.delivery_method = :test
|
78
79
|
|
80
|
+
_ = ActiveSupport
|
81
|
+
_ = ActiveSupport::TestCase
|
79
82
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
83
|
+
class ActiveSupport::TestCase
|
84
|
+
@@constant_overrides = []
|
85
|
+
|
86
|
+
setup do
|
87
|
+
unless @@constant_overrides.nil? || @@constant_overrides.empty?
|
88
|
+
raise "Uh-oh! constant_overrides left over: #{@@constant_overrides.inspect}"
|
89
|
+
end
|
85
90
|
|
91
|
+
unless defined?(Rails) && defined?(Rails.env)
|
92
|
+
module ::Rails
|
93
|
+
class << self
|
94
|
+
attr_writer :env
|
86
95
|
|
87
|
-
|
88
|
-
|
89
|
-
|
96
|
+
def env
|
97
|
+
@env ||= 'test'
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
90
101
|
end
|
91
102
|
|
92
103
|
Time.now_override = nil
|
@@ -106,8 +117,8 @@ module TestHelper
|
|
106
117
|
ExceptionHandling.sensu_prefix = ""
|
107
118
|
end
|
108
119
|
|
109
|
-
|
110
|
-
|
120
|
+
teardown do
|
121
|
+
@@constant_overrides&.reverse&.each do |parent_module, k, v|
|
111
122
|
ExceptionHandling.ensure_safe "constant cleanup #{k.inspect}, #{parent_module}(#{parent_module.class})::#{v.inspect}(#{v.class})" do
|
112
123
|
silence_warnings do
|
113
124
|
if v == :never_defined
|
@@ -118,7 +129,7 @@ module TestHelper
|
|
118
129
|
end
|
119
130
|
end
|
120
131
|
end
|
121
|
-
|
132
|
+
@@constant_overrides = []
|
122
133
|
end
|
123
134
|
|
124
135
|
def set_test_const(const_name, value)
|
@@ -138,7 +149,7 @@ module TestHelper
|
|
138
149
|
end
|
139
150
|
end
|
140
151
|
|
141
|
-
|
152
|
+
@@constant_overrides << [final_parent_module, final_const_name, original_value]
|
142
153
|
|
143
154
|
silence_warnings { final_parent_module.const_set(final_const_name, value) }
|
144
155
|
end
|
@@ -150,15 +161,15 @@ module TestHelper
|
|
150
161
|
else
|
151
162
|
original_count = 0
|
152
163
|
end
|
153
|
-
|
164
|
+
assert_equal expected, ActionMailer::Base.deliveries.size - original_count, "wrong number of emails#{': ' + message.to_s if message}"
|
154
165
|
end
|
155
166
|
end
|
156
167
|
|
157
168
|
def assert_equal_with_diff(arg1, arg2, msg = '')
|
158
169
|
if arg1 == arg2
|
159
|
-
|
170
|
+
assert true # To keep the assertion count accurate
|
160
171
|
else
|
161
|
-
|
172
|
+
assert_equal arg1, arg2, "#{msg}\n#{Diff.compare(arg1, arg2)}"
|
162
173
|
end
|
163
174
|
end
|
164
175
|
|
@@ -189,35 +200,3 @@ class Time
|
|
189
200
|
end
|
190
201
|
end
|
191
202
|
end
|
192
|
-
|
193
|
-
RSpec.configure do |config|
|
194
|
-
config.add_formatter(RspecJunitFormatter, 'spec/reports/rspec.xml')
|
195
|
-
config.include TestHelper
|
196
|
-
|
197
|
-
config.before(:each) do
|
198
|
-
setup_constant_overrides
|
199
|
-
unless defined?(Rails) && defined?(Rails.env)
|
200
|
-
module Rails
|
201
|
-
class << self
|
202
|
-
attr_writer :env
|
203
|
-
|
204
|
-
def env
|
205
|
-
@env ||= 'test'
|
206
|
-
end
|
207
|
-
end
|
208
|
-
end
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
config.after(:each) do
|
213
|
-
teardown_constant_overrides
|
214
|
-
end
|
215
|
-
|
216
|
-
config.mock_with :rspec do |mocks|
|
217
|
-
mocks.verify_partial_doubles = true
|
218
|
-
end
|
219
|
-
|
220
|
-
config.expect_with(:rspec, :test_unit)
|
221
|
-
|
222
|
-
RSpec::Support::ObjectFormatter.default_instance.max_formatted_output_length = 2_000
|
223
|
-
end
|