exception_notification 4.3.0 → 4.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. checksums.yaml +5 -5
  2. data/Appraisals +4 -2
  3. data/CHANGELOG.rdoc +47 -0
  4. data/CONTRIBUTING.md +18 -0
  5. data/Gemfile +3 -1
  6. data/README.md +97 -945
  7. data/Rakefile +4 -2
  8. data/docs/notifiers/campfire.md +50 -0
  9. data/docs/notifiers/custom.md +42 -0
  10. data/docs/notifiers/datadog.md +51 -0
  11. data/docs/notifiers/email.md +195 -0
  12. data/docs/notifiers/google_chat.md +31 -0
  13. data/docs/notifiers/hipchat.md +66 -0
  14. data/docs/notifiers/irc.md +97 -0
  15. data/docs/notifiers/mattermost.md +115 -0
  16. data/docs/notifiers/slack.md +161 -0
  17. data/docs/notifiers/sns.md +37 -0
  18. data/docs/notifiers/teams.md +54 -0
  19. data/docs/notifiers/webhook.md +60 -0
  20. data/examples/sample_app.rb +56 -0
  21. data/examples/sinatra/Gemfile +8 -6
  22. data/examples/sinatra/config.ru +3 -1
  23. data/examples/sinatra/sinatra_app.rb +19 -11
  24. data/exception_notification.gemspec +30 -24
  25. data/gemfiles/{rails4_0.gemfile → rails5_2.gemfile} +2 -2
  26. data/gemfiles/{rails4_1.gemfile → rails6_0.gemfile} +2 -2
  27. data/gemfiles/{rails4_2.gemfile → rails6_1.gemfile} +2 -2
  28. data/gemfiles/{rails5_0.gemfile → rails7_0.gemfile} +2 -2
  29. data/lib/exception_notification/rack.rb +28 -30
  30. data/lib/exception_notification/rails.rb +2 -0
  31. data/lib/exception_notification/resque.rb +10 -10
  32. data/lib/exception_notification/sidekiq.rb +10 -12
  33. data/lib/exception_notification/version.rb +5 -0
  34. data/lib/exception_notification.rb +3 -0
  35. data/lib/exception_notifier/base_notifier.rb +10 -5
  36. data/lib/exception_notifier/datadog_notifier.rb +156 -0
  37. data/lib/exception_notifier/email_notifier.rb +73 -88
  38. data/lib/exception_notifier/google_chat_notifier.rb +27 -119
  39. data/lib/exception_notifier/hipchat_notifier.rb +13 -12
  40. data/lib/exception_notifier/irc_notifier.rb +36 -33
  41. data/lib/exception_notifier/mattermost_notifier.rb +54 -137
  42. data/lib/exception_notifier/modules/backtrace_cleaner.rb +2 -2
  43. data/lib/exception_notifier/modules/error_grouping.rb +24 -13
  44. data/lib/exception_notifier/modules/formatter.rb +125 -0
  45. data/lib/exception_notifier/notifier.rb +9 -6
  46. data/lib/exception_notifier/slack_notifier.rb +65 -40
  47. data/lib/exception_notifier/sns_notifier.rb +23 -13
  48. data/lib/exception_notifier/teams_notifier.rb +67 -46
  49. data/lib/exception_notifier/views/exception_notifier/_backtrace.html.erb +1 -1
  50. data/lib/exception_notifier/views/exception_notifier/_environment.text.erb +1 -1
  51. data/lib/exception_notifier/views/exception_notifier/_request.text.erb +1 -1
  52. data/lib/exception_notifier/views/exception_notifier/exception_notification.html.erb +2 -2
  53. data/lib/exception_notifier/views/exception_notifier/exception_notification.text.erb +2 -2
  54. data/lib/exception_notifier/webhook_notifier.rb +17 -14
  55. data/lib/exception_notifier.rb +65 -10
  56. data/lib/generators/exception_notification/install_generator.rb +11 -5
  57. data/lib/generators/exception_notification/templates/{exception_notification.rb → exception_notification.rb.erb} +13 -11
  58. data/test/exception_notification/rack_test.rb +75 -13
  59. data/test/exception_notification/resque_test.rb +54 -0
  60. data/test/exception_notifier/datadog_notifier_test.rb +153 -0
  61. data/test/exception_notifier/email_notifier_test.rb +275 -153
  62. data/test/exception_notifier/google_chat_notifier_test.rb +158 -101
  63. data/test/exception_notifier/hipchat_notifier_test.rb +84 -81
  64. data/test/exception_notifier/irc_notifier_test.rb +36 -34
  65. data/test/exception_notifier/mattermost_notifier_test.rb +213 -67
  66. data/test/exception_notifier/modules/error_grouping_test.rb +41 -40
  67. data/test/exception_notifier/modules/formatter_test.rb +152 -0
  68. data/test/exception_notifier/sidekiq_test.rb +9 -17
  69. data/test/exception_notifier/slack_notifier_test.rb +66 -63
  70. data/test/exception_notifier/sns_notifier_test.rb +84 -32
  71. data/test/exception_notifier/teams_notifier_test.rb +25 -26
  72. data/test/exception_notifier/webhook_notifier_test.rb +52 -48
  73. data/test/exception_notifier_test.rb +150 -41
  74. data/test/support/exception_notifier_helper.rb +14 -0
  75. data/test/{dummy/app → support}/views/exception_notifier/_new_bkg_section.html.erb +0 -0
  76. data/test/{dummy/app → support}/views/exception_notifier/_new_bkg_section.text.erb +0 -0
  77. data/test/{dummy/app → support}/views/exception_notifier/_new_section.html.erb +0 -0
  78. data/test/{dummy/app → support}/views/exception_notifier/_new_section.text.erb +0 -0
  79. data/test/test_helper.rb +14 -13
  80. metadata +134 -175
  81. data/gemfiles/rails5_1.gemfile +0 -7
  82. data/lib/exception_notifier/campfire_notifier.rb +0 -40
  83. data/test/dummy/.gitignore +0 -4
  84. data/test/dummy/Rakefile +0 -7
  85. data/test/dummy/app/controllers/application_controller.rb +0 -3
  86. data/test/dummy/app/controllers/posts_controller.rb +0 -30
  87. data/test/dummy/app/helpers/application_helper.rb +0 -2
  88. data/test/dummy/app/helpers/posts_helper.rb +0 -2
  89. data/test/dummy/app/models/post.rb +0 -2
  90. data/test/dummy/app/views/layouts/application.html.erb +0 -14
  91. data/test/dummy/app/views/posts/_form.html.erb +0 -0
  92. data/test/dummy/app/views/posts/new.html.erb +0 -0
  93. data/test/dummy/app/views/posts/show.html.erb +0 -0
  94. data/test/dummy/config/application.rb +0 -42
  95. data/test/dummy/config/boot.rb +0 -6
  96. data/test/dummy/config/database.yml +0 -22
  97. data/test/dummy/config/environment.rb +0 -17
  98. data/test/dummy/config/environments/development.rb +0 -25
  99. data/test/dummy/config/environments/production.rb +0 -50
  100. data/test/dummy/config/environments/test.rb +0 -35
  101. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  102. data/test/dummy/config/initializers/inflections.rb +0 -10
  103. data/test/dummy/config/initializers/mime_types.rb +0 -5
  104. data/test/dummy/config/initializers/secret_token.rb +0 -8
  105. data/test/dummy/config/initializers/session_store.rb +0 -8
  106. data/test/dummy/config/locales/en.yml +0 -5
  107. data/test/dummy/config/routes.rb +0 -3
  108. data/test/dummy/config.ru +0 -4
  109. data/test/dummy/db/migrate/20110729022608_create_posts.rb +0 -15
  110. data/test/dummy/db/schema.rb +0 -24
  111. data/test/dummy/db/seeds.rb +0 -7
  112. data/test/dummy/lib/tasks/.gitkeep +0 -0
  113. data/test/dummy/public/404.html +0 -26
  114. data/test/dummy/public/422.html +0 -26
  115. data/test/dummy/public/500.html +0 -26
  116. data/test/dummy/public/favicon.ico +0 -0
  117. data/test/dummy/public/images/rails.png +0 -0
  118. data/test/dummy/public/index.html +0 -239
  119. data/test/dummy/public/javascripts/application.js +0 -2
  120. data/test/dummy/public/javascripts/controls.js +0 -965
  121. data/test/dummy/public/javascripts/dragdrop.js +0 -974
  122. data/test/dummy/public/javascripts/effects.js +0 -1123
  123. data/test/dummy/public/javascripts/prototype.js +0 -6001
  124. data/test/dummy/public/javascripts/rails.js +0 -191
  125. data/test/dummy/public/robots.txt +0 -5
  126. data/test/dummy/public/stylesheets/.gitkeep +0 -0
  127. data/test/dummy/public/stylesheets/scaffold.css +0 -56
  128. data/test/dummy/script/rails +0 -6
  129. data/test/dummy/test/functional/posts_controller_test.rb +0 -237
  130. data/test/dummy/test/test_helper.rb +0 -7
  131. data/test/exception_notifier/campfire_notifier_test.rb +0 -120
@@ -0,0 +1,152 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+ require 'timecop'
5
+
6
+ class FormatterTest < ActiveSupport::TestCase
7
+ setup do
8
+ @exception = RuntimeError.new('test')
9
+ Timecop.freeze('2018-12-09 12:07:16 UTC')
10
+ end
11
+
12
+ teardown do
13
+ Timecop.return
14
+ end
15
+
16
+ #
17
+ # #title
18
+ #
19
+ test 'title returns correct content' do
20
+ formatter = ExceptionNotifier::Formatter.new(@exception)
21
+
22
+ title = if defined?(::Rails) && ::Rails.respond_to?(:env)
23
+ '⚠️ Error occurred in test ⚠️'
24
+ else
25
+ '⚠️ Error occurred ⚠️'
26
+ end
27
+
28
+ assert_equal title, formatter.title
29
+ end
30
+
31
+ #
32
+ # #subtitle
33
+ #
34
+ test 'subtitle without accumulated error' do
35
+ formatter = ExceptionNotifier::Formatter.new(@exception)
36
+ assert_equal 'A *RuntimeError* occurred.', formatter.subtitle
37
+ end
38
+
39
+ test 'subtitle with accumulated error' do
40
+ formatter = ExceptionNotifier::Formatter.new(@exception, accumulated_errors_count: 3)
41
+ assert_equal '3 *RuntimeError* occurred.', formatter.subtitle
42
+ end
43
+
44
+ test 'subtitle with controller' do
45
+ env = Rack::MockRequest.env_for(
46
+ '/', 'action_controller.instance' => test_controller
47
+ )
48
+
49
+ formatter = ExceptionNotifier::Formatter.new(@exception, env: env)
50
+ assert_equal 'A *RuntimeError* occurred in *home#index*.', formatter.subtitle
51
+ end
52
+
53
+ #
54
+ # #app_name
55
+ #
56
+ test 'app_name defaults to Rails app name' do
57
+ formatter = ExceptionNotifier::Formatter.new(@exception)
58
+
59
+ if defined?(::Rails) && ::Rails.respond_to?(:application)
60
+ assert_equal 'dummy', formatter.app_name
61
+ else
62
+ assert_nil formatter.app_name
63
+ end
64
+ end
65
+
66
+ test 'app_name can be overwritten using options' do
67
+ formatter = ExceptionNotifier::Formatter.new(@exception, app_name: 'test')
68
+ assert_equal 'test', formatter.app_name
69
+ end
70
+
71
+ #
72
+ # #request_message
73
+ #
74
+ test 'request_message when env set' do
75
+ text = [
76
+ '```',
77
+ '* url : http://test.address/?id=foo',
78
+ '* http_method : GET',
79
+ '* ip_address : 127.0.0.1',
80
+ '* parameters : {"id"=>"foo"}',
81
+ '* timestamp : 2018-12-09 12:07:16 UTC',
82
+ '```'
83
+ ].join("\n")
84
+
85
+ env = Rack::MockRequest.env_for(
86
+ '/',
87
+ 'HTTP_HOST' => 'test.address',
88
+ 'REMOTE_ADDR' => '127.0.0.1',
89
+ params: { id: 'foo' }
90
+ )
91
+
92
+ formatter = ExceptionNotifier::Formatter.new(@exception, env: env)
93
+ assert_equal text, formatter.request_message
94
+ end
95
+
96
+ test 'request_message when env not set' do
97
+ formatter = ExceptionNotifier::Formatter.new(@exception)
98
+ assert_nil formatter.request_message
99
+ end
100
+
101
+ #
102
+ # #backtrace_message
103
+ #
104
+ test 'backtrace_message when backtrace set' do
105
+ text = [
106
+ '```',
107
+ "* app/controllers/my_controller.rb:53:in `my_controller_params'",
108
+ "* app/controllers/my_controller.rb:34:in `update'",
109
+ '```'
110
+ ].join("\n")
111
+
112
+ @exception.set_backtrace([
113
+ "app/controllers/my_controller.rb:53:in `my_controller_params'",
114
+ "app/controllers/my_controller.rb:34:in `update'"
115
+ ])
116
+
117
+ formatter = ExceptionNotifier::Formatter.new(@exception)
118
+ assert_equal text, formatter.backtrace_message
119
+ end
120
+
121
+ test 'backtrace_message when no backtrace' do
122
+ formatter = ExceptionNotifier::Formatter.new(@exception)
123
+ assert_nil formatter.backtrace_message
124
+ end
125
+
126
+ #
127
+ # #controller_and_action
128
+ #
129
+ test 'correct controller_and_action if controller is present' do
130
+ env = Rack::MockRequest.env_for(
131
+ '/', 'action_controller.instance' => test_controller
132
+ )
133
+
134
+ formatter = ExceptionNotifier::Formatter.new(@exception, env: env)
135
+ assert_equal 'home#index', formatter.controller_and_action
136
+ end
137
+
138
+ test 'controller_and_action is nil if no controller' do
139
+ env = Rack::MockRequest.env_for('/')
140
+
141
+ formatter = ExceptionNotifier::Formatter.new(@exception, env: env)
142
+ assert_nil formatter.controller_and_action
143
+ end
144
+
145
+ def test_controller
146
+ controller = mock('controller')
147
+ controller.stubs(:action_name).returns('index')
148
+ controller.stubs(:controller_name).returns('home')
149
+
150
+ controller
151
+ end
152
+ end
@@ -1,38 +1,30 @@
1
- require "test_helper"
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
2
4
 
3
5
  # To allow sidekiq error handlers to be registered, sidekiq must be in
4
6
  # "server mode". This mode is triggered by loading sidekiq/cli. Note this
5
7
  # has to be loaded before exception_notification/sidekiq.
6
- require "sidekiq/cli"
8
+ require 'sidekiq/cli'
9
+ require 'sidekiq/testing'
7
10
 
8
- require "exception_notification/sidekiq"
11
+ require 'exception_notification/sidekiq'
9
12
 
10
13
  class MockSidekiqServer
11
14
  include ::Sidekiq::ExceptionHandler
12
15
  end
13
16
 
14
17
  class SidekiqTest < ActiveSupport::TestCase
15
- setup do
16
- @_original_sidekiq_logger = Sidekiq::Logging.logger
17
-
18
- # Silence sidekiq warning to stdout
19
- Sidekiq::Logging.logger = nil
20
- end
21
-
22
- test "should call notify_exception when sidekiq raises an error" do
18
+ test 'should call notify_exception when sidekiq raises an error' do
23
19
  server = MockSidekiqServer.new
24
- message = Hash.new
20
+ message = {}
25
21
  exception = RuntimeError.new
26
22
 
27
23
  ExceptionNotifier.expects(:notify_exception).with(
28
24
  exception,
29
- :data => { :sidekiq => message }
25
+ data: { sidekiq: message }
30
26
  )
31
27
 
32
28
  server.handle_exception(exception, message)
33
29
  end
34
-
35
- teardown do
36
- Sidekiq::Logging.logger = @_original_sidekiq_logger
37
- end
38
30
  end
@@ -1,18 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
  require 'slack-notifier'
3
5
 
4
6
  class SlackNotifierTest < ActiveSupport::TestCase
5
-
6
7
  def setup
7
8
  @exception = fake_exception
8
9
  @exception.stubs(:backtrace).returns(fake_backtrace)
9
10
  @exception.stubs(:message).returns('exception message')
11
+ ExceptionNotifier::SlackNotifier.any_instance.stubs(:clean_backtrace).returns(fake_cleaned_backtrace)
10
12
  Socket.stubs(:gethostname).returns('example.com')
11
13
  end
12
14
 
13
- test "should send a slack notification if properly configured" do
15
+ test 'should send a slack notification if properly configured' do
14
16
  options = {
15
- webhook_url: "http://slack.webhook.url"
17
+ webhook_url: 'http://slack.webhook.url'
16
18
  }
17
19
 
18
20
  Slack::Notifier.any_instance.expects(:ping).with('', fake_notification)
@@ -21,9 +23,9 @@ class SlackNotifierTest < ActiveSupport::TestCase
21
23
  slack_notifier.call(@exception)
22
24
  end
23
25
 
24
- test "should send a slack notification without backtrace info if properly configured" do
26
+ test 'should send a slack notification without backtrace info if properly configured' do
25
27
  options = {
26
- webhook_url: "http://slack.webhook.url"
28
+ webhook_url: 'http://slack.webhook.url'
27
29
  }
28
30
 
29
31
  Slack::Notifier.any_instance.expects(:ping).with('', fake_notification(fake_exception_without_backtrace))
@@ -32,10 +34,10 @@ class SlackNotifierTest < ActiveSupport::TestCase
32
34
  slack_notifier.call(fake_exception_without_backtrace)
33
35
  end
34
36
 
35
- test "should send the notification to the specified channel" do
37
+ test 'should send the notification to the specified channel' do
36
38
  options = {
37
- webhook_url: "http://slack.webhook.url",
38
- channel: "channel"
39
+ webhook_url: 'http://slack.webhook.url',
40
+ channel: 'channel'
39
41
  }
40
42
 
41
43
  Slack::Notifier.any_instance.expects(:ping).with('', fake_notification)
@@ -47,10 +49,10 @@ class SlackNotifierTest < ActiveSupport::TestCase
47
49
  assert_equal channel, options[:channel]
48
50
  end
49
51
 
50
- test "should send the notification to the specified username" do
52
+ test 'should send the notification to the specified username' do
51
53
  options = {
52
- webhook_url: "http://slack.webhook.url",
53
- username: "username"
54
+ webhook_url: 'http://slack.webhook.url',
55
+ username: 'username'
54
56
  }
55
57
 
56
58
  Slack::Notifier.any_instance.expects(:ping).with('', fake_notification)
@@ -62,9 +64,9 @@ class SlackNotifierTest < ActiveSupport::TestCase
62
64
  assert_equal username, options[:username]
63
65
  end
64
66
 
65
- test "should send the notification with specific backtrace lines" do
67
+ test 'should send the notification with specific backtrace lines' do
66
68
  options = {
67
- webhook_url: "http://slack.webhook.url",
69
+ webhook_url: 'http://slack.webhook.url',
68
70
  backtrace_lines: 1
69
71
  }
70
72
 
@@ -74,10 +76,10 @@ class SlackNotifierTest < ActiveSupport::TestCase
74
76
  slack_notifier.call(@exception)
75
77
  end
76
78
 
77
- test "should send the notification with additional fields" do
78
- field = {title: "Branch", value: "master", short: true}
79
+ test 'should send the notification with additional fields' do
80
+ field = { title: 'Branch', value: 'master', short: true }
79
81
  options = {
80
- webhook_url: "http://slack.webhook.url",
82
+ webhook_url: 'http://slack.webhook.url',
81
83
  additional_fields: [field]
82
84
  }
83
85
 
@@ -90,17 +92,17 @@ class SlackNotifierTest < ActiveSupport::TestCase
90
92
  assert_equal additional_fields, options[:additional_fields]
91
93
  end
92
94
 
93
- test "should pass the additional parameters to Slack::Notifier.ping" do
95
+ test 'should pass the additional parameters to Slack::Notifier.ping' do
94
96
  options = {
95
- webhook_url: "http://slack.webhook.url",
96
- username: "test",
97
- custom_hook: "hook",
97
+ webhook_url: 'http://slack.webhook.url',
98
+ username: 'test',
99
+ custom_hook: 'hook',
98
100
  additional_parameters: {
99
- icon_url: "icon",
101
+ icon_url: 'icon'
100
102
  }
101
103
  }
102
104
 
103
- Slack::Notifier.any_instance.expects(:ping).with('', options[:additional_parameters].merge(fake_notification) )
105
+ Slack::Notifier.any_instance.expects(:ping).with('', options[:additional_parameters].merge(fake_notification))
104
106
 
105
107
  slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
106
108
  slack_notifier.call(@exception)
@@ -115,55 +117,57 @@ class SlackNotifierTest < ActiveSupport::TestCase
115
117
  assert_nil slack_notifier.call(@exception)
116
118
  end
117
119
 
118
- test "should pass along environment data" do
120
+ test 'should pass along environment data' do
119
121
  options = {
120
- webhook_url: "http://slack.webhook.url",
121
- ignore_data_if: lambda {|k,v|
122
- "#{k}" == 'key_to_be_ignored' || v.is_a?(Hash)
122
+ webhook_url: 'http://slack.webhook.url',
123
+ ignore_data_if: lambda { |k, v|
124
+ k.to_s == 'key_to_be_ignored' || v.is_a?(Hash)
123
125
  }
124
126
  }
125
127
 
126
128
  notification_options = {
127
129
  env: {
128
- 'exception_notifier.exception_data' => {foo: 'bar', john: 'doe'}
130
+ 'exception_notifier.exception_data' => { foo: 'bar', john: 'doe' }
129
131
  },
130
132
  data: {
131
- 'user_id' => 5,
133
+ 'user_id' => 5,
132
134
  'key_to_be_ignored' => 'whatever',
133
- 'ignore_as_well' => {what: 'ever'}
135
+ 'ignore_as_well' => { what: 'ever' }
134
136
  }
135
137
  }
136
138
 
137
139
  expected_data_string = "foo: bar\njohn: doe\nuser_id: 5"
138
140
 
139
- Slack::Notifier.any_instance.expects(:ping).with('', fake_notification(@exception, notification_options, expected_data_string))
141
+ Slack::Notifier.any_instance
142
+ .expects(:ping)
143
+ .with('', fake_notification(@exception, notification_options, expected_data_string))
140
144
  slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
141
145
  slack_notifier.call(@exception, notification_options)
142
146
  end
143
147
 
144
- test "should call pre/post_callback proc if specified" do
148
+ test 'should call pre/post_callback proc if specified' do
145
149
  post_callback_called = 0
146
150
  options = {
147
- webhook_url: "http://slack.webhook.url",
148
- username: "test",
149
- custom_hook: "hook",
150
- :pre_callback => proc { |opts, notifier, backtrace, message, message_opts|
151
- (message_opts[:attachments] = []) << { text: "#{backtrace.join("\n")}", color: 'danger' }
151
+ webhook_url: 'http://slack.webhook.url',
152
+ username: 'test',
153
+ custom_hook: 'hook',
154
+ pre_callback: proc { |_opts, _notifier, backtrace, _message, message_opts|
155
+ (message_opts[:attachments] = []) << { text: backtrace.join("\n").to_s, color: 'danger' }
152
156
  },
153
- :post_callback => proc { |opts, notifier, backtrace, message, message_opts|
157
+ post_callback: proc { |_opts, _notifier, _backtrace, _message, _message_opts|
154
158
  post_callback_called = 1
155
159
  },
156
160
  additional_parameters: {
157
- icon_url: "icon",
161
+ icon_url: 'icon'
158
162
  }
159
163
  }
160
164
 
161
165
  Slack::Notifier.any_instance.expects(:ping).with('',
162
- {:icon_url => 'icon',
163
- :attachments => [
164
- {:text => fake_backtrace.join("\n"),
165
- :color => 'danger'}
166
- ]})
166
+ icon_url: 'icon',
167
+ attachments: [{
168
+ text: fake_backtrace.join("\n"),
169
+ color: 'danger'
170
+ }])
167
171
 
168
172
  slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
169
173
  slack_notifier.call(@exception)
@@ -173,11 +177,9 @@ class SlackNotifierTest < ActiveSupport::TestCase
173
177
  private
174
178
 
175
179
  def fake_exception
176
- begin
177
- 5/0
178
- rescue Exception => e
179
- e
180
- end
180
+ 5 / 0
181
+ rescue StandardError => e
182
+ e
181
183
  end
182
184
 
183
185
  def fake_exception_without_backtrace
@@ -186,17 +188,19 @@ class SlackNotifierTest < ActiveSupport::TestCase
186
188
 
187
189
  def fake_backtrace
188
190
  [
189
- "backtrace line 1",
190
- "backtrace line 2",
191
- "backtrace line 3",
192
- "backtrace line 4",
193
- "backtrace line 5",
194
- "backtrace line 6",
191
+ 'backtrace line 1', 'backtrace line 2', 'backtrace line 3',
192
+ 'backtrace line 4', 'backtrace line 5', 'backtrace line 6'
195
193
  ]
196
194
  end
197
195
 
198
- def fake_notification(exception = @exception, notification_options = {}, data_string = nil, expected_backtrace_lines = 10, additional_fields = [])
199
- exception_name = "*#{exception.class.to_s =~ /^[aeiou]/i ? 'An' : 'A'}* `#{exception.class.to_s}`"
196
+ def fake_cleaned_backtrace
197
+ fake_backtrace[2..-1]
198
+ end
199
+
200
+ def fake_notification(exception = @exception, notification_options = {},
201
+ data_string = nil, expected_backtrace_lines = 10, additional_fields = [])
202
+
203
+ exception_name = "*#{exception.class.to_s =~ /^[aeiou]/i ? 'An' : 'A'}* `#{exception.class}`"
200
204
  if notification_options[:env].nil?
201
205
  text = "#{exception_name} *occured in background*"
202
206
  else
@@ -211,16 +215,15 @@ class SlackNotifierTest < ActiveSupport::TestCase
211
215
 
212
216
  text += "\n"
213
217
 
214
- fields = [ { title: 'Exception', value: exception.message} ]
215
- fields.push({ title: 'Hostname', value: 'example.com' })
218
+ fields = [{ title: 'Exception', value: exception.message }]
219
+ fields.push(title: 'Hostname', value: 'example.com')
216
220
  if exception.backtrace
217
- formatted_backtrace = "```#{exception.backtrace.first(expected_backtrace_lines).join("\n")}```"
218
- fields.push({ title: 'Backtrace', value: formatted_backtrace })
221
+ formatted_backtrace = "```#{fake_cleaned_backtrace.first(expected_backtrace_lines).join("\n")}```"
222
+ fields.push(title: 'Backtrace', value: formatted_backtrace)
219
223
  end
220
- fields.push({ title: 'Data', value: "```#{data_string}```" }) if data_string
224
+ fields.push(title: 'Data', value: "```#{data_string}```") if data_string
221
225
  additional_fields.each { |f| fields.push(f) }
222
226
 
223
- { attachments: [ color: 'danger', text: text, fields: fields, mrkdwn_in: %w(text fields) ] }
227
+ { attachments: [color: 'danger', text: text, fields: fields, mrkdwn_in: %w[text fields]] }
224
228
  end
225
-
226
229
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
  require 'aws-sdk-sns'
3
5
 
@@ -12,7 +14,7 @@ class SnsNotifierTest < ActiveSupport::TestCase
12
14
  secret_access_key: 'my-secret_access_key',
13
15
  region: 'us-east',
14
16
  topic_arn: 'topicARN',
15
- sns_prefix: '[App Exception]',
17
+ sns_prefix: '[App Exception]'
16
18
  }
17
19
  Socket.stubs(:gethostname).returns('example.com')
18
20
  end
@@ -60,53 +62,103 @@ class SnsNotifierTest < ActiveSupport::TestCase
60
62
 
61
63
  test 'should send a sns notification in background' do
62
64
  Aws::SNS::Client.any_instance.expects(:publish).with(
63
- {
64
- topic_arn: "topicARN",
65
- message: "3 MyException occured in background\n"\
66
- "Exception: undefined method 'method=' for Empty\n"\
67
- "Hostname: example.com\n"\
68
- "Backtrace:\n#{fake_backtrace.join("\n")}\n",
69
- subject: "[App Exception] - 3 MyException occurred"
70
- })
65
+ topic_arn: 'topicARN',
66
+ message: "3 MyException occured in background\n" \
67
+ "Exception: undefined method 'method=' for Empty\n" \
68
+ "Hostname: example.com\n" \
69
+ "Data: {}\n" \
70
+ "Backtrace:\n#{fake_backtrace.join("\n")}\n",
71
+ subject: '[App Exception] - 3 MyException occurred'
72
+ )
71
73
 
72
74
  sns_notifier = ExceptionNotifier::SnsNotifier.new(@options)
73
- sns_notifier.call(@exception, { accumulated_errors_count: 3 })
75
+ sns_notifier.call(@exception, accumulated_errors_count: 3)
74
76
  end
75
77
 
76
78
  test 'should send a sns notification with controller#action information' do
77
- ExamplesController.any_instance.stubs(:action_name).returns('index')
79
+ controller = mock('controller')
80
+ controller.stubs(:action_name).returns('index')
81
+ controller.stubs(:controller_name).returns('examples')
78
82
 
79
83
  Aws::SNS::Client.any_instance.expects(:publish).with(
80
- {
81
- topic_arn: "topicARN",
82
- message: "A MyException occurred while GET </examples> "\
83
- "was processed by examples#index\n"\
84
- "Exception: undefined method 'method=' for Empty\n"\
85
- "Hostname: example.com\n"\
86
- "Backtrace:\n#{fake_backtrace.join("\n")}\n",
87
- subject: "[App Exception] - A MyException occurred"
88
- })
84
+ topic_arn: 'topicARN',
85
+ message: 'A MyException occurred while GET </examples> ' \
86
+ "was processed by examples#index\n" \
87
+ "Exception: undefined method 'method=' for Empty\n" \
88
+ "Hostname: example.com\n" \
89
+ "Data: {}\n" \
90
+ "Backtrace:\n#{fake_backtrace.join("\n")}\n",
91
+ subject: '[App Exception] - A MyException occurred'
92
+ )
89
93
 
90
94
  sns_notifier = ExceptionNotifier::SnsNotifier.new(@options)
91
95
  sns_notifier.call(@exception,
92
- env: {
93
- 'REQUEST_METHOD' => 'GET',
94
- 'REQUEST_URI' => '/examples',
95
- 'action_controller.instance' => ExamplesController.new
96
- }
96
+ env: {
97
+ 'REQUEST_METHOD' => 'GET',
98
+ 'REQUEST_URI' => '/examples',
99
+ 'action_controller.instance' => controller
100
+ })
101
+ end
102
+
103
+ test 'should put data from env["exception_notifier.exception_data"] into text' do
104
+ controller = mock('controller')
105
+ controller.stubs(:action_name).returns('index')
106
+ controller.stubs(:controller_name).returns('examples')
107
+
108
+ Aws::SNS::Client.any_instance.expects(:publish).with(
109
+ topic_arn: 'topicARN',
110
+ message: 'A MyException occurred while GET </examples> ' \
111
+ "was processed by examples#index\n" \
112
+ "Exception: undefined method 'method=' for Empty\n" \
113
+ "Hostname: example.com\n" \
114
+ "Data: {:current_user=>12}\n" \
115
+ "Backtrace:\n#{fake_backtrace.join("\n")}\n",
116
+ subject: '[App Exception] - A MyException occurred'
97
117
  )
118
+
119
+ sns_notifier = ExceptionNotifier::SnsNotifier.new(@options)
120
+ sns_notifier.call(@exception,
121
+ env: {
122
+ 'REQUEST_METHOD' => 'GET',
123
+ 'REQUEST_URI' => '/examples',
124
+ 'action_controller.instance' => controller,
125
+ 'exception_notifier.exception_data' => { current_user: 12 }
126
+ })
98
127
  end
128
+ test 'should put optional data into text' do
129
+ controller = mock('controller')
130
+ controller.stubs(:action_name).returns('index')
131
+ controller.stubs(:controller_name).returns('examples')
99
132
 
100
- private
133
+ Aws::SNS::Client.any_instance.expects(:publish).with(
134
+ topic_arn: 'topicARN',
135
+ message: 'A MyException occurred while GET </examples> ' \
136
+ "was processed by examples#index\n" \
137
+ "Exception: undefined method 'method=' for Empty\n" \
138
+ "Hostname: example.com\n" \
139
+ "Data: {:current_user=>12}\n" \
140
+ "Backtrace:\n#{fake_backtrace.join("\n")}\n",
141
+ subject: '[App Exception] - A MyException occurred'
142
+ )
101
143
 
102
- class ExamplesController < ActionController::Base; end
144
+ sns_notifier = ExceptionNotifier::SnsNotifier.new(@options)
145
+ sns_notifier.call(@exception,
146
+ env: {
147
+ 'REQUEST_METHOD' => 'GET',
148
+ 'REQUEST_URI' => '/examples',
149
+ 'action_controller.instance' => controller
150
+ },
151
+ data: {
152
+ current_user: 12
153
+ })
154
+ end
155
+
156
+ private
103
157
 
104
158
  def fake_exception
105
- begin
106
- 1 / 0
107
- rescue Exception => e
108
- e
109
- end
159
+ 1 / 0
160
+ rescue StandardError => e
161
+ e
110
162
  end
111
163
 
112
164
  def fake_exception_without_backtrace