exception_handling 2.2.1 → 2.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.
Files changed (34) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +5 -0
  4. data/Gemfile +7 -6
  5. data/Gemfile.lock +26 -23
  6. data/README.md +0 -1
  7. data/Rakefile +4 -4
  8. data/config/exception_filters.yml +2 -3
  9. data/exception_handling.gemspec +12 -10
  10. data/lib/exception_handling/exception_catalog.rb +5 -4
  11. data/lib/exception_handling/exception_description.rb +28 -28
  12. data/lib/exception_handling/exception_info.rb +80 -72
  13. data/lib/exception_handling/honeybadger_callbacks.rb +41 -24
  14. data/lib/exception_handling/log_stub_error.rb +10 -8
  15. data/lib/exception_handling/mailer.rb +27 -48
  16. data/lib/exception_handling/methods.rb +15 -11
  17. data/lib/exception_handling/sensu.rb +7 -5
  18. data/lib/exception_handling/testing.rb +21 -19
  19. data/lib/exception_handling/version.rb +1 -1
  20. data/lib/exception_handling.rb +105 -200
  21. data/test/helpers/controller_helpers.rb +3 -1
  22. data/test/helpers/exception_helpers.rb +9 -0
  23. data/test/test_helper.rb +26 -21
  24. data/test/unit/exception_handling/exception_catalog_test.rb +15 -14
  25. data/test/unit/exception_handling/exception_description_test.rb +22 -31
  26. data/test/unit/exception_handling/exception_info_test.rb +76 -37
  27. data/test/unit/exception_handling/honeybadger_callbacks_test.rb +46 -9
  28. data/test/unit/exception_handling/log_error_stub_test.rb +6 -4
  29. data/test/unit/exception_handling/mailer_test.rb +8 -14
  30. data/test/unit/exception_handling/methods_test.rb +9 -6
  31. data/test/unit/exception_handling/sensu_test.rb +6 -4
  32. data/test/unit/exception_handling_test.rb +279 -364
  33. metadata +24 -24
  34. data/views/exception_handling/mailer/exception_notification.html.erb +0 -92
@@ -1,12 +1,14 @@
1
- require File.expand_path('../../../test_helper', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path('../../test_helper', __dir__)
2
4
 
3
5
  module ExceptionHandling
4
6
  class ExceptionCatalogTest < ActiveSupport::TestCase
5
7
 
6
8
  context "With stubbed yaml content" do
7
9
  setup do
8
- filter_list = { :exception1 => { error: "my error message" },
9
- :exception2 => { error: "some other message", session: "misc data" } }
10
+ filter_list = { exception1: { error: "my error message" },
11
+ exception2: { error: "some other message", session: "misc data" } }
10
12
  stub(YAML).load_file { filter_list }
11
13
 
12
14
  # bump modified time up to get the above filter loaded
@@ -16,7 +18,7 @@ module ExceptionHandling
16
18
  context "with loaded data" do
17
19
  setup do
18
20
  stub(File).mtime { incrementing_mtime }
19
- @exception_catalog = ExceptionCatalog.new( ExceptionHandling.filter_list_filename )
21
+ @exception_catalog = ExceptionCatalog.new(ExceptionHandling.filter_list_filename)
20
22
  @exception_catalog.send :load_file
21
23
  end
22
24
 
@@ -25,7 +27,7 @@ module ExceptionHandling
25
27
  end
26
28
 
27
29
  should "find messages in the catalog" do
28
- assert !@exception_catalog.find( error: "Scott says unlikely to ever match" )
30
+ assert !@exception_catalog.find(error: "Scott says unlikely to ever match")
29
31
  end
30
32
 
31
33
  should "find matching data" do
@@ -36,29 +38,28 @@ module ExceptionHandling
36
38
  end
37
39
 
38
40
  should "write errors loading the yaml file directly to the log file" do
39
- @exception_catalog = ExceptionCatalog.new( ExceptionHandling.filter_list_filename )
41
+ @exception_catalog = ExceptionCatalog.new(ExceptionHandling.filter_list_filename)
40
42
 
41
43
  mock(ExceptionHandling).log_error.never
42
- mock(ExceptionHandling).write_exception_to_log(anything(), "ExceptionCatalog#refresh_filters: ./config/exception_filters.yml", anything())
43
- mock(@exception_catalog).load_file { raise "noooooo"}
44
+ mock(ExceptionHandling).write_exception_to_log(anything, "ExceptionCatalog#refresh_filters: ./config/exception_filters.yml", anything)
45
+ mock(@exception_catalog).load_file { raise "noooooo" }
44
46
 
45
47
  @exception_catalog.find({})
46
48
  end
47
-
48
49
  end
49
50
 
50
51
  context "with live yaml content" do
51
52
  setup do
52
- @filename = File.expand_path('../../../../config/exception_filters.yml', __FILE__)
53
- @exception_catalog = ExceptionCatalog.new( @filename )
53
+ @filename = File.expand_path('../../../config/exception_filters.yml', __dir__)
54
+ @exception_catalog = ExceptionCatalog.new(@filename)
54
55
  assert_nothing_raised "Loading the exception filter should not raise" do
55
56
  @exception_catalog.send :load_file
56
57
  end
57
58
  end
58
59
 
59
60
  should "load the filter data" do
60
- assert !@exception_catalog.find( error: "Scott says unlikely to ever match" )
61
- assert !@exception_catalog.find( error: "Scott says unlikely to ever match" )
61
+ assert !@exception_catalog.find(error: "Scott says unlikely to ever match")
62
+ assert !@exception_catalog.find(error: "Scott says unlikely to ever match")
62
63
  end
63
64
  end
64
65
 
@@ -69,7 +70,7 @@ module ExceptionHandling
69
70
 
70
71
  should "not load filter data" do
71
72
  mock(ExceptionHandling).write_exception_to_log.with_any_args.never
72
- @exception_catalog.find( error: "Scott says unlikely to ever match" )
73
+ @exception_catalog.find(error: "Scott says unlikely to ever match")
73
74
  end
74
75
  end
75
76
 
@@ -1,23 +1,24 @@
1
- require File.expand_path('../../../test_helper', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path('../../test_helper', __dir__)
2
4
 
3
5
  module ExceptionHandling
4
6
  class ExceptionDescriptionTest < ActiveSupport::TestCase
5
7
 
6
8
  context "Filter" do
7
-
8
9
  should "allow direct matching of strings" do
9
- @f = ExceptionDescription.new(:filter1, :error => "my error message" )
10
- assert @f.match?( 'error' => "my error message")
10
+ @f = ExceptionDescription.new(:filter1, error: "my error message")
11
+ assert @f.match?('error' => "my error message")
11
12
  end
12
13
 
13
14
  should "allow direct matching of strings on with symbol keys" do
14
- @f = ExceptionDescription.new(:filter1, :error => "my error message" )
15
- assert @f.match?( :error => "my error message")
15
+ @f = ExceptionDescription.new(:filter1, error: "my error message")
16
+ assert @f.match?(error: "my error message")
16
17
  end
17
18
 
18
19
  should "allow wildcards to cross line boundries" do
19
- @f = ExceptionDescription.new(:filter1, :error => "my error message.*with multiple lines" )
20
- assert @f.match?( :error => "my error message\nwith more than one, with multiple lines")
20
+ @f = ExceptionDescription.new(:filter1, error: "my error message.*with multiple lines")
21
+ assert @f.match?(error: "my error message\nwith more than one, with multiple lines")
21
22
  end
22
23
 
23
24
  should "complain when no regexps have a value" do
@@ -28,12 +29,6 @@ module ExceptionHandling
28
29
  assert_raise(ArgumentError, "Unknown section: not_a_parameter") { ExceptionDescription.new(:filter1, error: "my error message", not_a_parameter: false) }
29
30
  end
30
31
 
31
- should "allow send email to be specified" do
32
- assert !ExceptionDescription.new(:filter1, error: "my error message", send_email: false ).send_email
33
- assert ExceptionDescription.new(:filter1, error: "my error message", send_email: true ).send_email
34
- assert !ExceptionDescription.new(:filter1, error: "my error message" ).send_email
35
- end
36
-
37
32
  should "allow send_to_honeybadger to be specified and have it disabled by default" do
38
33
  assert !ExceptionDescription.new(:filter1, error: "my error message", send_to_honeybadger: false).send_to_honeybadger
39
34
  assert ExceptionDescription.new(:filter1, error: "my error message", send_to_honeybadger: true).send_to_honeybadger
@@ -41,37 +36,35 @@ module ExceptionHandling
41
36
  end
42
37
 
43
38
  should "allow send_metric to be configured" do
44
- assert !ExceptionDescription.new(:filter1, error: "my error message", send_metric: false ).send_metric
45
- assert ExceptionDescription.new(:filter1, error: "my error message", send_email: true ).send_metric
46
- assert ExceptionDescription.new(:filter1, error: "my error message" ).send_metric
39
+ assert !ExceptionDescription.new(:filter1, error: "my error message", send_metric: false).send_metric
40
+ assert ExceptionDescription.new(:filter1, error: "my error message").send_metric
47
41
  end
48
42
 
49
43
  should "provide metric name" do
50
- assert_equal "filter1", ExceptionDescription.new(:filter1, error: "my error message" ).metric_name
51
- assert_equal "some_other_metric_name", ExceptionDescription.new(:filter1, error: "my error message", metric_name: :some_other_metric_name ).metric_name
44
+ assert_equal "filter1", ExceptionDescription.new(:filter1, error: "my error message").metric_name
45
+ assert_equal "some_other_metric_name", ExceptionDescription.new(:filter1, error: "my error message", metric_name: :some_other_metric_name).metric_name
52
46
  end
53
47
 
54
48
  should "replace spaces in metric name" do
55
- @f = ExceptionDescription.new(:"filter has spaces", :error => "my error message" )
49
+ @f = ExceptionDescription.new(:"filter has spaces", error: "my error message")
56
50
  assert_equal "filter_has_spaces", @f.metric_name
57
51
  end
58
52
 
59
53
  should "allow notes to be recorded" do
60
- assert_nil ExceptionDescription.new(:filter1, error: "my error message" ).notes
61
- assert_equal "a long string", ExceptionDescription.new(:filter1, error: "my error message", notes: "a long string" ).notes
54
+ assert_nil ExceptionDescription.new(:filter1, error: "my error message").notes
55
+ assert_equal "a long string", ExceptionDescription.new(:filter1, error: "my error message", notes: "a long string").notes
62
56
  end
63
57
 
64
58
  should "not consider config options in the filter set" do
65
- assert ExceptionDescription.new(:filter1, error: "my error message", send_email: false ).match?( :error => "my error message")
66
- assert ExceptionDescription.new(:filter1, error: "my error message", send_metric: false ).match?( :error => "my error message")
67
- assert ExceptionDescription.new(:filter1, error: "my error message", metric_name: "false" ).match?( :error => "my error message")
68
- assert ExceptionDescription.new(:filter1, error: "my error message", notes: "hey" ).match?( :error => "my error message")
59
+ assert ExceptionDescription.new(:filter1, error: "my error message", send_metric: false).match?(error: "my error message")
60
+ assert ExceptionDescription.new(:filter1, error: "my error message", metric_name: "false").match?(error: "my error message")
61
+ assert ExceptionDescription.new(:filter1, error: "my error message", notes: "hey").match?(error: "my error message")
69
62
  end
70
63
 
71
64
  should "provide exception details" do
72
- exception_description = ExceptionDescription.new(:filter1, error: "my error message", notes: "hey" )
65
+ exception_description = ExceptionDescription.new(:filter1, error: "my error message", notes: "hey")
73
66
 
74
- expected = {"send_metric" => true, "metric_name" => "filter1", "notes" => "hey"}
67
+ expected = { "send_metric" => true, "metric_name" => "filter1", "notes" => "hey" }
75
68
 
76
69
  assert_equal expected, exception_description.exception_data
77
70
  end
@@ -80,12 +73,10 @@ module ExceptionHandling
80
73
  mobi = "ExceptionHandling::Warning: LoginAttempt::IPAddressLocked: failed login for 'mcc@mobistreak.com'"
81
74
  credit = "ExceptionHandling::Warning: LoginAttempt::IPAddressLocked: failed login for 'damon@thecreditpros.com'"
82
75
 
83
- exception_description = ExceptionDescription.new(:filter1, error: "ExceptionHandling::Warning: LoginAttempt::IPAddressLocked: failed login for '(mcc\@mobistreak|damon\@thecreditpros).com'" )
76
+ exception_description = ExceptionDescription.new(:filter1, error: "ExceptionHandling::Warning: LoginAttempt::IPAddressLocked: failed login for '(mcc\@mobistreak|damon\@thecreditpros).com'")
84
77
  assert exception_description.match?(error: mobi), "does not match mobi"
85
78
  assert exception_description.match?(error: credit), "does not match credit"
86
79
  end
87
-
88
80
  end
89
-
90
81
  end
91
82
  end
@@ -1,4 +1,6 @@
1
- require File.expand_path('../../../test_helper', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path('../../test_helper', __dir__)
2
4
  require_test_helper 'controller_helpers'
3
5
  require_test_helper 'exception_helpers'
4
6
 
@@ -228,10 +230,12 @@ module ExceptionHandling
228
230
  "session" => {
229
231
  "key" => "session_key",
230
232
  "data" => { "username" => "jsmith", "id" => "session_key" },
231
- "to_s" => "data:\n id: session_key\n username: jsmith\nkey: session_key\n" },
233
+ "to_s" => "data:\n id: session_key\n username: jsmith\nkey: session_key\n"
234
+ },
232
235
  "environment" => {
233
236
  "SERVER_NAME" => "exceptional.com",
234
- "to_s" => "SERVER_NAME: exceptional.com\n" },
237
+ "to_s" => "SERVER_NAME: exceptional.com\n"
238
+ },
235
239
  "request" => {
236
240
  "params" => { "advertiser_id" => 435, "controller" => "dummy", "action" => "fail" },
237
241
  "rails_root" => "Rails.root not defined. Is this a test environment?",
@@ -249,11 +253,11 @@ module ExceptionHandling
249
253
  @controller.request.parameters[:user] = { "password" => "also super secret", "password_confirmation" => "also super secret" }
250
254
  exception_info = ExceptionInfo.new(@exception, @exception_context, @timestamp, @controller)
251
255
  expected_params = {
252
- "password" => "[FILTERED]",
256
+ "password" => "[FILTERED]",
253
257
  "advertiser_id" => 435, "controller" => "dummy",
254
- "action" => "fail",
255
- "user" => {
256
- "password" => "[FILTERED]",
258
+ "action" => "fail",
259
+ "user" => {
260
+ "password" => "[FILTERED]",
257
261
  "password_confirmation" => "[FILTERED]"
258
262
  }
259
263
  }
@@ -296,7 +300,7 @@ module ExceptionHandling
296
300
  end
297
301
 
298
302
  should "log info if the custom data hook results in a nil message exception" do
299
- ExceptionHandling.custom_data_hook = lambda do |data|
303
+ ExceptionHandling.custom_data_hook = ->(_data) do
300
304
  raise_exception_with_nil_message
301
305
  end
302
306
  log_info_messages = []
@@ -345,9 +349,40 @@ module ExceptionHandling
345
349
  end
346
350
  end
347
351
 
352
+ context "controller_name" do
353
+ setup do
354
+ @exception = StandardError.new('something went wrong')
355
+ @timestamp = Time.now
356
+ @exception_context = {
357
+ 'rack.session' => {
358
+ user_id: 23,
359
+ user_name: 'John'
360
+ },
361
+ 'SERVER_NAME' => 'exceptional.com'
362
+ }
363
+ end
364
+
365
+ should "return controller_name when controller is present" do
366
+ env = { server: 'fe98' }
367
+ parameters = { controller: 'some_controller' }
368
+ session = { username: 'smith' }
369
+ request_uri = "host/path"
370
+ controller = create_dummy_controller(env, parameters, session, request_uri)
371
+ exception_info = ExceptionInfo.new(@exception, @exception_context, @timestamp, controller)
372
+
373
+ assert_equal 'some_controller', exception_info.controller_name
374
+ end
375
+
376
+ should "return an empty string when controller is not present" do
377
+ exception_info = ExceptionInfo.new(@exception, @exception_context, @timestamp)
378
+
379
+ assert_equal '', exception_info.controller_name
380
+ end
381
+ end
382
+
348
383
  context "send_to_honeybadger?" do
349
384
  should "be enabled when Honeybadger is defined and exception is not in the filter list" do
350
- stub(ExceptionHandling).honeybadger? { true }
385
+ stub(ExceptionHandling).honeybadger_defined? { true }
351
386
  exception = StandardError.new("something went wrong")
352
387
  exception_info = ExceptionInfo.new(exception, {}, Time.now)
353
388
  assert_nil exception_info.exception_description
@@ -355,7 +390,7 @@ module ExceptionHandling
355
390
  end
356
391
 
357
392
  should "be enabled when Honeybadger is defined and exception is on the filter list with the flag turned on" do
358
- stub(ExceptionHandling).honeybadger? { true }
393
+ stub(ExceptionHandling).honeybadger_defined? { true }
359
394
  exception = StandardError.new("No route matches")
360
395
  exception_info = ExceptionInfo.new(exception, {}, Time.now)
361
396
  assert_not_nil exception_info.exception_description
@@ -364,7 +399,7 @@ module ExceptionHandling
364
399
  end
365
400
 
366
401
  should "be disabled when Honeybadger is defined and exception is on the filter list with the flag turned off" do
367
- stub(ExceptionHandling).honeybadger? { true }
402
+ stub(ExceptionHandling).honeybadger_defined? { true }
368
403
  exception = StandardError.new("No route matches")
369
404
  exception_info = ExceptionInfo.new(exception, {}, Time.now)
370
405
  assert_not_nil exception_info.exception_description
@@ -373,7 +408,7 @@ module ExceptionHandling
373
408
  end
374
409
 
375
410
  should "be disabled when Honeybadger is not defined" do
376
- stub(ExceptionHandling).honeybadger? { false }
411
+ stub(ExceptionHandling).honeybadger_defined? { false }
377
412
  exception = StandardError.new("something went wrong")
378
413
  exception_info = ExceptionInfo.new(exception, {}, Time.now)
379
414
  assert_nil exception_info.exception_description
@@ -390,10 +425,11 @@ module ExceptionHandling
390
425
  controller = create_dummy_controller(env, parameters, session, request_uri)
391
426
  stub(ExceptionHandling).server_name { "invoca_fe98" }
392
427
 
393
- exception = StandardError.new("Some BS")
428
+ exception = StandardError.new("Some Exception")
394
429
  exception.set_backtrace([
395
- "test/unit/exception_handling_test.rb:847:in `exception_1'",
396
- "test/unit/exception_handling_test.rb:455:in `block (4 levels) in <class:ExceptionHandlingTest>'"])
430
+ "test/unit/exception_handling_test.rb:847:in `exception_1'",
431
+ "test/unit/exception_handling_test.rb:455:in `block (4 levels) in <class:ExceptionHandlingTest>'"
432
+ ])
397
433
  exception_context = { "SERVER_NAME" => "exceptional.com" }
398
434
  data_callback = ->(data) do
399
435
  data[:scm_revision] = "5b24eac37aaa91f5784901e9aabcead36fd9df82"
@@ -415,46 +451,49 @@ module ExceptionHandling
415
451
  request: {
416
452
  "params" => { "advertiser_id" => 435 },
417
453
  "rails_root" => "Rails.root not defined. Is this a test environment?",
418
- "url" => "host/path" },
454
+ "url" => "host/path"
455
+ },
419
456
  session: {
420
457
  "key" => nil,
421
- "data" => { "username" => "jsmith" } },
458
+ "data" => { "username" => "jsmith" }
459
+ },
422
460
  environment: {
423
- "SERVER_NAME" => "exceptional.com" },
461
+ "SERVER_NAME" => "exceptional.com"
462
+ },
424
463
  backtrace: [
425
464
  "test/unit/exception_handling_test.rb:847:in `exception_1'",
426
- "test/unit/exception_handling_test.rb:455:in `block (4 levels) in <class:ExceptionHandlingTest>'"],
465
+ "test/unit/exception_handling_test.rb:455:in `block (4 levels) in <class:ExceptionHandlingTest>'"
466
+ ],
427
467
  event_response: "Event successfully received"
428
468
  }
429
469
  assert_equal_with_diff expected_data, exception_info.honeybadger_context_data
430
470
  end
431
471
 
432
- [ ['Hash', { 'cookie' => 'cookie_context' } ],
433
- ['String', 'Entering Error State' ],
434
- ['Array', ['Error1', 'Error2'] ]].each do |klass, value|
435
-
436
- should "extract context from exception_context when it is a #{klass}" do
437
- exception = StandardError.new("Exception")
438
- exception_context = value
439
- exception_info = ExceptionInfo.new(exception, exception_context, Time.now)
472
+ [['Hash', { 'cookie' => 'cookie_context' }],
473
+ ['String', 'Entering Error State'],
474
+ ['Array', ['Error1', 'Error2']]].each do |klass, value|
475
+ should "extract context from exception_context when it is a #{klass}" do
476
+ exception = StandardError.new("Exception")
477
+ exception_context = value
478
+ exception_info = ExceptionInfo.new(exception, exception_context, Time.now)
440
479
 
441
- assert_equal klass, value.class.name
442
- assert_equal value, exception_info.honeybadger_context_data[:exception_context]
443
- end
480
+ assert_equal klass, value.class.name
481
+ assert_equal value, exception_info.honeybadger_context_data[:exception_context]
482
+ end
444
483
  end
445
484
 
446
485
  should "filter out sensitive data from exception context such as [password, password_confirmation, oauth_token]" do
447
486
  sensitive_data = {
448
- "password" => "super_secret",
487
+ "password" => "super_secret",
449
488
  "password_confirmation" => "super_secret_confirmation",
450
- "oauth_token" => "super_secret_oauth_token"
489
+ "oauth_token" => "super_secret_oauth_token"
451
490
  }
452
491
 
453
492
  exception = StandardError.new("boom")
454
493
  exception_context = {
455
494
  "SERVER_NAME" => "exceptional.com",
456
- "one_layer" => sensitive_data,
457
- "two_layers" => {
495
+ "one_layer" => sensitive_data,
496
+ "two_layers" => {
458
497
  "sensitive_data" => sensitive_data
459
498
  },
460
499
  "rack.request.form_vars" => "username=investor%40invoca.com&password=my_special_password&commit=Log+In",
@@ -468,8 +507,8 @@ module ExceptionHandling
468
507
  expected_sensitive_data = ["password", "password_confirmation", "oauth_token"].build_hash { |key| [key, "[FILTERED]"] }
469
508
  expected_exception_context = {
470
509
  "SERVER_NAME" => "exceptional.com",
471
- "one_layer" => expected_sensitive_data,
472
- "two_layers" => {
510
+ "one_layer" => expected_sensitive_data,
511
+ "two_layers" => {
473
512
  "sensitive_data" => expected_sensitive_data
474
513
  },
475
514
  "rack.request.form_vars" => "username=investor%40invoca.com&password=[FILTERED]&commit=Log+In",
@@ -491,7 +530,7 @@ module ExceptionHandling
491
530
  end
492
531
 
493
532
  def prepare_data(data)
494
- data.each do |key, section|
533
+ data.each do |_key, section|
495
534
  if section.is_a?(Hash)
496
535
  section.delete(:to_s)
497
536
  end
@@ -1,4 +1,6 @@
1
- require File.expand_path('../../../test_helper', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path('../../test_helper', __dir__)
2
4
 
3
5
  module ExceptionHandling
4
6
  class HoneybadgerCallbacksTest < ActiveSupport::TestCase
@@ -34,6 +36,24 @@ module ExceptionHandling
34
36
  end
35
37
  end
36
38
 
39
+ class TestRaiseOnInspect < TestPoroWithAttribute
40
+ def inspect
41
+ raise "some error"
42
+ end
43
+ end
44
+
45
+ class TestRaiseOnInspectWithId < TestRaiseOnInspect
46
+ def id
47
+ 123
48
+ end
49
+ end
50
+
51
+ class TestRaiseOnInspectWithToPk < TestRaiseOnInspect
52
+ def to_pk
53
+ "SomeRecord-123"
54
+ end
55
+ end
56
+
37
57
  context "register_callbacks" do
38
58
  should "store the callbacks in the honeybadger object" do
39
59
  HoneybadgerCallbacks.register_callbacks
@@ -46,37 +66,54 @@ module ExceptionHandling
46
66
  should "not inspect String, Hash, Array, Set, Numeric, TrueClass, FalseClass, NilClass" do
47
67
  [
48
68
  ['test', String],
49
- [{a: 1}, Hash],
50
- [[1,2], Array],
51
- [Set.new([1,2]), Set],
69
+ [{ a: 1 }, Hash],
70
+ [[1, 2], Array],
71
+ [Set.new([1, 2]), Set],
52
72
  [4.5, Numeric],
53
73
  [true, TrueClass],
54
74
  [false, FalseClass],
55
75
  [nil, NilClass]
56
76
  ].each do |object, expected_class|
57
- result = HoneybadgerCallbacks.local_variable_filter(:variable_name, object, [])
77
+ result = HoneybadgerCallbacks.send(:local_variable_filter, :variable_name, object, [])
58
78
  assert result.is_a?(expected_class), "Expected #{expected_class.name} but got #{result.class.name}"
59
79
  end
60
80
  end
61
81
 
62
82
  should "inspect other classes" do
63
- result = HoneybadgerCallbacks.local_variable_filter(:variable_name, TestPoroWithAttribute.new, ['password'])
83
+ result = HoneybadgerCallbacks.send(:local_variable_filter, :variable_name, TestPoroWithAttribute.new, ['password'])
64
84
  assert_match(/#<ExceptionHandling::HoneybadgerCallbacksTest::TestPoroWithAttribute:.* @test_attribute="test">/, result)
65
85
  end
66
86
 
87
+ context "when inspect raises exceptions" do
88
+ should "handle exceptions for objects" do
89
+ result = HoneybadgerCallbacks.send(:local_variable_filter, :variable_name, TestRaiseOnInspect.new, ['password'])
90
+ assert_equal "#<ExceptionHandling::HoneybadgerCallbacksTest::TestRaiseOnInspect [error 'RuntimeError: some error' while calling #inspect]>", result
91
+ end
92
+
93
+ should "handle exceptions for objects responding to id" do
94
+ result = HoneybadgerCallbacks.send(:local_variable_filter, :variable_name, TestRaiseOnInspectWithId.new, ['password'])
95
+ assert_equal "#<ExceptionHandling::HoneybadgerCallbacksTest::TestRaiseOnInspectWithId @id=123 [error 'RuntimeError: some error' while calling #inspect]>", result
96
+ end
97
+
98
+ should "handle exceptions for objects responding to to_pik" do
99
+ result = HoneybadgerCallbacks.send(:local_variable_filter, :variable_name, TestRaiseOnInspectWithToPk.new, ['password'])
100
+ assert_equal "#<ExceptionHandling::HoneybadgerCallbacksTest::TestRaiseOnInspectWithToPk @pk=SomeRecord-123 [error 'RuntimeError: some error' while calling #inspect]>", result
101
+ end
102
+ end
103
+
67
104
  context "not inspect objects that contain filter keys" do
68
105
  should "use to_pk if available, even if id is available" do
69
- result = HoneybadgerCallbacks.local_variable_filter(:variable_name, TestPoroWithFilteredAttributePkAndId.new, ['password'])
106
+ result = HoneybadgerCallbacks.send(:local_variable_filter, :variable_name, TestPoroWithFilteredAttributePkAndId.new, ['password'])
70
107
  assert_match(/#<ExceptionHandling::HoneybadgerCallbacksTest::TestPoroWithFilteredAttributePkAndId @pk=TestPoroWithFilteredAttributePkAndId_1, \[FILTERED\]>/, result)
71
108
  end
72
109
 
73
110
  should "use id if to_pk is not available" do
74
- result = HoneybadgerCallbacks.local_variable_filter(:variable_name, TestPoroWithFilteredAttributeAndId.new, ['password'])
111
+ result = HoneybadgerCallbacks.send(:local_variable_filter, :variable_name, TestPoroWithFilteredAttributeAndId.new, ['password'])
75
112
  assert_match(/#<ExceptionHandling::HoneybadgerCallbacksTest::TestPoroWithFilteredAttributeAndId @id=1, \[FILTERED\]>/, result)
76
113
  end
77
114
 
78
115
  should "print the object name if no id or to_pk" do
79
- result = HoneybadgerCallbacks.local_variable_filter(:variable_name, TestPoroWithFilteredAttribute.new, ['password'])
116
+ result = HoneybadgerCallbacks.send(:local_variable_filter, :variable_name, TestPoroWithFilteredAttribute.new, ['password'])
80
117
  assert_match(/#<ExceptionHandling::HoneybadgerCallbacksTest::TestPoroWithFilteredAttribute \[FILTERED\]>/, result)
81
118
  end
82
119
  end
@@ -1,4 +1,6 @@
1
- require File.expand_path('../../../test_helper', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path('../../test_helper', __dir__)
2
4
 
3
5
  module ExceptionHandling
4
6
  class LogErrorStubTest < ActiveSupport::TestCase
@@ -18,7 +20,7 @@ module ExceptionHandling
18
20
  begin
19
21
  ExceptionHandling.log_error("Something happened")
20
22
  flunk
21
- rescue Exception => ex #LogErrorStub::UnexpectedExceptionLogged => ex
23
+ rescue Exception => ex # LogErrorStub::UnexpectedExceptionLogged => ex
22
24
  assert ex.to_s.starts_with?("StandardError: Something happened"), ex.to_s
23
25
  end
24
26
 
@@ -28,8 +30,8 @@ module ExceptionHandling
28
30
  rescue => ex
29
31
  begin
30
32
  ExceptionHandling.log_error(ex)
31
- rescue LogErrorStub::UnexpectedExceptionLogged => ex_inner
32
- assert ex_inner.to_s.starts_with?("RaisedError: This should raise"), ex_inner.to_s
33
+ rescue LogErrorStub::UnexpectedExceptionLogged => ex
34
+ assert ex.to_s.starts_with?("RaisedError: This should raise"), ex.to_s
33
35
  end
34
36
  end
35
37
  end
@@ -1,4 +1,6 @@
1
- require File.expand_path('../../../test_helper', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path('../../test_helper', __dir__)
2
4
 
3
5
  module ExceptionHandling
4
6
  class MailerTest < ActionMailer::TestCase
@@ -18,14 +20,6 @@ module ExceptionHandling
18
20
  ExceptionHandling.escalation_recipients = ['test_escalation@invoca.com']
19
21
  end
20
22
 
21
- should "deliver" do
22
- #ActionMailer::Base.delivery_method = :smtp
23
- result = ExceptionHandling::Mailer.exception_notification({ :error => "Test Error."}).deliver_now
24
- assert_match(/Test Error./, result.body.to_s)
25
- assert_equal_with_diff ['test_exception@invoca.com'], result.to
26
- assert_emails 1
27
- end
28
-
29
23
  context "log_parser_exception_notification" do
30
24
  should "send with string" do
31
25
  result = ExceptionHandling::Mailer.log_parser_exception_notification("This is my fake error", "My Fake Subj").deliver_now
@@ -46,7 +40,7 @@ module ExceptionHandling
46
40
  ExceptionHandling.email_environment = 'Staging Full'
47
41
  ExceptionHandling.server_name = 'test-fe3'
48
42
 
49
- ExceptionHandling::Mailer.escalation_notification("Your Favorite <b>Feature<b> Failed", :error_string => "It failed because of an error\n <i>More Info<i>", :timestamp => 1234567 ).deliver_now
43
+ ExceptionHandling::Mailer.escalation_notification("Your Favorite <b>Feature<b> Failed", error_string: "It failed because of an error\n <i>More Info<i>", timestamp: 1234567).deliver_now
50
44
 
51
45
  assert_emails 1
52
46
  result = ActionMailer::Base.deliveries.last
@@ -56,18 +50,18 @@ module ExceptionHandling
56
50
  assert_equal "Staging Full Escalation: Your Favorite <b>Feature<b> Failed", result.subject
57
51
  assert_select "title", "Exception Escalation"
58
52
  assert_select "html" do
59
- assert_select "body br", { :count => 4 }, result.body.to_s # plus 1 for the multiline summary
53
+ assert_select "body br", { count: 4 }, result.body.to_s # plus 1 for the multiline summary
60
54
  assert_select "body h3", "Your Favorite <b>Feature<b> Failed", result.body.to_s
61
55
  assert_select "body", /1234567/
62
56
  assert_select "body", /It failed because of an error/
63
57
  assert_select "body", /\n <i>More Info<i>/
64
58
  assert_select "body", /test-fe3/
65
- #assert_select "body", /#{Web::Application::GIT_REVISION}/
59
+ # assert_select "body", /#{Web::Application::GIT_REVISION}/
66
60
  end
67
61
  end
68
62
 
69
63
  should "use defaults for missing fields" do
70
- result = ExceptionHandling::Mailer.escalation_notification("Your Favorite Feature Failed", :error_string => "It failed because of an error\n More Info")
64
+ result = ExceptionHandling::Mailer.escalation_notification("Your Favorite Feature Failed", error_string: "It failed because of an error\n More Info")
71
65
  @body_html = Nokogiri::HTML(result.body.to_s)
72
66
 
73
67
  assert_equal_with_diff ['test_escalation@invoca.com'], result.to
@@ -93,7 +87,7 @@ module ExceptionHandling
93
87
  ExceptionHandling.production_support_recipients = recipients
94
88
  ExceptionHandling.last_exception_timestamp = Time.now.to_i
95
89
 
96
- mock(ExceptionHandling).escalate_custom(subject, exception, Time.now.to_i, recipients)
90
+ mock(ExceptionHandling).escalate(subject, exception, Time.now.to_i, recipients)
97
91
  ExceptionHandling.escalate_to_production_support(exception, subject)
98
92
  end
99
93
  end
@@ -1,9 +1,12 @@
1
- require File.expand_path('../../../test_helper', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path('../../test_helper', __dir__)
2
4
 
3
5
  require "exception_handling/testing"
4
6
 
5
7
  module ExceptionHandling
6
8
  class MethodsTest < ActiveSupport::TestCase
9
+ include ExceptionHelpers
7
10
 
8
11
  def dont_stub_log_error
9
12
  true
@@ -25,13 +28,13 @@ module ExceptionHandling
25
28
  end
26
29
 
27
30
  should "use the current_controller when available" do
28
- mock(Honeybadger).notify(anything)
31
+ capture_notifications
32
+
29
33
  mock(ExceptionHandling.logger).fatal(/blah/, anything)
30
34
  @controller.simulate_around_filter do
31
- ExceptionHandling.log_error( ArgumentError.new("blah") )
32
- mail = ActionMailer::Base.deliveries.last
33
- assert_match( @controller.request.request_uri, mail.body.to_s )
34
- # assert_match( Username.first.username.to_s, mail.body.to_s ) if defined?(Username)
35
+ ExceptionHandling.log_error(ArgumentError.new("blah"))
36
+ assert_equal 1, sent_notifications.size, sent_notifications.inspect
37
+ assert_match(@controller.request.request_uri, sent_notifications.last.enhanced_data['request'].to_s)
35
38
  end
36
39
  end
37
40