exception_notification 4.3.0 → 4.5.0

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 (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