exception_notification 4.3.0 → 4.4.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 +4 -4
  2. data/Appraisals +2 -2
  3. data/CHANGELOG.rdoc +14 -0
  4. data/CONTRIBUTING.md +18 -0
  5. data/Gemfile +1 -1
  6. data/README.md +64 -935
  7. data/Rakefile +2 -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 +54 -0
  21. data/examples/sinatra/Gemfile +6 -6
  22. data/examples/sinatra/config.ru +1 -1
  23. data/examples/sinatra/sinatra_app.rb +14 -10
  24. data/exception_notification.gemspec +27 -22
  25. data/gemfiles/rails4_0.gemfile +3 -3
  26. data/gemfiles/rails4_1.gemfile +3 -3
  27. data/gemfiles/rails4_2.gemfile +3 -3
  28. data/gemfiles/rails5_0.gemfile +3 -3
  29. data/gemfiles/rails5_1.gemfile +3 -3
  30. data/gemfiles/rails5_2.gemfile +7 -0
  31. data/gemfiles/rails6_0.gemfile +7 -0
  32. data/lib/exception_notification.rb +1 -0
  33. data/lib/exception_notification/rack.rb +8 -21
  34. data/lib/exception_notification/resque.rb +8 -10
  35. data/lib/exception_notification/sidekiq.rb +8 -12
  36. data/lib/exception_notification/version.rb +3 -0
  37. data/lib/exception_notifier.rb +20 -3
  38. data/lib/exception_notifier/base_notifier.rb +2 -3
  39. data/lib/exception_notifier/campfire_notifier.rb +12 -13
  40. data/lib/exception_notifier/datadog_notifier.rb +153 -0
  41. data/lib/exception_notifier/email_notifier.rb +64 -87
  42. data/lib/exception_notifier/google_chat_notifier.rb +25 -119
  43. data/lib/exception_notifier/hipchat_notifier.rb +11 -12
  44. data/lib/exception_notifier/irc_notifier.rb +32 -30
  45. data/lib/exception_notifier/mattermost_notifier.rb +47 -140
  46. data/lib/exception_notifier/modules/backtrace_cleaner.rb +0 -2
  47. data/lib/exception_notifier/modules/error_grouping.rb +5 -5
  48. data/lib/exception_notifier/modules/formatter.rb +118 -0
  49. data/lib/exception_notifier/notifier.rb +5 -6
  50. data/lib/exception_notifier/slack_notifier.rb +63 -40
  51. data/lib/exception_notifier/sns_notifier.rb +17 -11
  52. data/lib/exception_notifier/teams_notifier.rb +58 -44
  53. data/lib/exception_notifier/views/exception_notifier/_backtrace.html.erb +1 -1
  54. data/lib/exception_notifier/views/exception_notifier/_environment.text.erb +1 -1
  55. data/lib/exception_notifier/views/exception_notifier/_request.text.erb +1 -1
  56. data/lib/exception_notifier/views/exception_notifier/exception_notification.html.erb +2 -2
  57. data/lib/exception_notifier/views/exception_notifier/exception_notification.text.erb +2 -2
  58. data/lib/exception_notifier/webhook_notifier.rb +14 -11
  59. data/lib/generators/exception_notification/install_generator.rb +5 -5
  60. data/lib/generators/exception_notification/templates/{exception_notification.rb → exception_notification.rb.erb} +13 -11
  61. data/test/exception_notification/rack_test.rb +27 -11
  62. data/test/exception_notification/resque_test.rb +52 -0
  63. data/test/exception_notifier/campfire_notifier_test.rb +42 -42
  64. data/test/exception_notifier/datadog_notifier_test.rb +151 -0
  65. data/test/exception_notifier/email_notifier_test.rb +269 -153
  66. data/test/exception_notifier/google_chat_notifier_test.rb +154 -101
  67. data/test/exception_notifier/hipchat_notifier_test.rb +78 -81
  68. data/test/exception_notifier/irc_notifier_test.rb +34 -34
  69. data/test/exception_notifier/mattermost_notifier_test.rb +164 -67
  70. data/test/exception_notifier/modules/error_grouping_test.rb +39 -40
  71. data/test/exception_notifier/modules/formatter_test.rb +150 -0
  72. data/test/exception_notifier/sidekiq_test.rb +6 -6
  73. data/test/exception_notifier/slack_notifier_test.rb +61 -60
  74. data/test/exception_notifier/sns_notifier_test.rb +27 -32
  75. data/test/exception_notifier/teams_notifier_test.rb +23 -26
  76. data/test/exception_notifier/webhook_notifier_test.rb +48 -46
  77. data/test/exception_notifier_test.rb +41 -38
  78. data/test/{dummy/app → support}/views/exception_notifier/_new_bkg_section.html.erb +0 -0
  79. data/test/{dummy/app → support}/views/exception_notifier/_new_bkg_section.text.erb +0 -0
  80. data/test/{dummy/app → support}/views/exception_notifier/_new_section.html.erb +0 -0
  81. data/test/{dummy/app → support}/views/exception_notifier/_new_section.text.erb +0 -0
  82. data/test/test_helper.rb +11 -14
  83. metadata +136 -166
  84. data/test/dummy/.gitignore +0 -4
  85. data/test/dummy/Rakefile +0 -7
  86. data/test/dummy/app/controllers/application_controller.rb +0 -3
  87. data/test/dummy/app/controllers/posts_controller.rb +0 -30
  88. data/test/dummy/app/helpers/application_helper.rb +0 -2
  89. data/test/dummy/app/helpers/posts_helper.rb +0 -2
  90. data/test/dummy/app/models/post.rb +0 -2
  91. data/test/dummy/app/views/layouts/application.html.erb +0 -14
  92. data/test/dummy/app/views/posts/_form.html.erb +0 -0
  93. data/test/dummy/app/views/posts/new.html.erb +0 -0
  94. data/test/dummy/app/views/posts/show.html.erb +0 -0
  95. data/test/dummy/config.ru +0 -4
  96. data/test/dummy/config/application.rb +0 -42
  97. data/test/dummy/config/boot.rb +0 -6
  98. data/test/dummy/config/database.yml +0 -22
  99. data/test/dummy/config/environment.rb +0 -17
  100. data/test/dummy/config/environments/development.rb +0 -25
  101. data/test/dummy/config/environments/production.rb +0 -50
  102. data/test/dummy/config/environments/test.rb +0 -35
  103. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  104. data/test/dummy/config/initializers/inflections.rb +0 -10
  105. data/test/dummy/config/initializers/mime_types.rb +0 -5
  106. data/test/dummy/config/initializers/secret_token.rb +0 -8
  107. data/test/dummy/config/initializers/session_store.rb +0 -8
  108. data/test/dummy/config/locales/en.yml +0 -5
  109. data/test/dummy/config/routes.rb +0 -3
  110. data/test/dummy/db/migrate/20110729022608_create_posts.rb +0 -15
  111. data/test/dummy/db/schema.rb +0 -24
  112. data/test/dummy/db/seeds.rb +0 -7
  113. data/test/dummy/lib/tasks/.gitkeep +0 -0
  114. data/test/dummy/public/404.html +0 -26
  115. data/test/dummy/public/422.html +0 -26
  116. data/test/dummy/public/500.html +0 -26
  117. data/test/dummy/public/favicon.ico +0 -0
  118. data/test/dummy/public/images/rails.png +0 -0
  119. data/test/dummy/public/index.html +0 -239
  120. data/test/dummy/public/javascripts/application.js +0 -2
  121. data/test/dummy/public/javascripts/controls.js +0 -965
  122. data/test/dummy/public/javascripts/dragdrop.js +0 -974
  123. data/test/dummy/public/javascripts/effects.js +0 -1123
  124. data/test/dummy/public/javascripts/prototype.js +0 -6001
  125. data/test/dummy/public/javascripts/rails.js +0 -191
  126. data/test/dummy/public/robots.txt +0 -5
  127. data/test/dummy/public/stylesheets/.gitkeep +0 -0
  128. data/test/dummy/public/stylesheets/scaffold.css +0 -56
  129. data/test/dummy/script/rails +0 -6
  130. data/test/dummy/test/functional/posts_controller_test.rb +0 -237
  131. data/test/dummy/test/test_helper.rb +0 -7
@@ -2,10 +2,9 @@ require 'test_helper'
2
2
  require 'carrier-pigeon'
3
3
 
4
4
  class IrcNotifierTest < ActiveSupport::TestCase
5
-
6
- test "should send irc notification if properly configured" do
5
+ test 'should send irc notification if properly configured' do
7
6
  options = {
8
- :domain => 'irc.example.com'
7
+ domain: 'irc.example.com'
9
8
  }
10
9
 
11
10
  CarrierPigeon.expects(:send).with(has_key(:uri)) do |v|
@@ -16,29 +15,30 @@ class IrcNotifierTest < ActiveSupport::TestCase
16
15
  irc.call(fake_exception)
17
16
  end
18
17
 
19
- test "should exclude errors count in message if :accumulated_errors_count nil" do
18
+ test 'should exclude errors count in message if :accumulated_errors_count nil' do
20
19
  irc = ExceptionNotifier::IrcNotifier.new({})
21
20
  irc.stubs(:active?).returns(true)
22
21
 
23
- irc.expects(:send_message).with{ |message| message.include?("divided by 0") }.once
22
+ irc.expects(:send_message).with { |message| message.include?('divided by 0') }.once
24
23
  irc.call(fake_exception)
25
24
  end
26
25
 
27
- test "should include errors count in message if :accumulated_errors_count is 3" do
26
+ test 'should include errors count in message if :accumulated_errors_count is 3' do
28
27
  irc = ExceptionNotifier::IrcNotifier.new({})
29
28
  irc.stubs(:active?).returns(true)
30
29
 
31
- irc.expects(:send_message).with{ |message| message.include?("(3 times)'divided by 0'") }.once
30
+ irc.expects(:send_message).with { |message| message.include?("(3 times)'divided by 0'") }.once
32
31
  irc.call(fake_exception, accumulated_errors_count: 3)
33
32
  end
34
33
 
35
- test "should call pre/post_callback if specified" do
36
- pre_callback_called, post_callback_called = 0,0
34
+ test 'should call pre/post_callback if specified' do
35
+ pre_callback_called = 0
36
+ post_callback_called = 0
37
37
 
38
38
  options = {
39
- :domain => 'irc.example.com',
40
- :pre_callback => proc { |*| pre_callback_called += 1},
41
- :post_callback => proc { |*| post_callback_called += 1}
39
+ domain: 'irc.example.com',
40
+ pre_callback: proc { |*| pre_callback_called += 1 },
41
+ post_callback: proc { |*| post_callback_called += 1 }
42
42
  }
43
43
 
44
44
  CarrierPigeon.expects(:send).with(has_key(:uri)) do |v|
@@ -51,9 +51,9 @@ class IrcNotifierTest < ActiveSupport::TestCase
51
51
  assert_equal(1, post_callback_called)
52
52
  end
53
53
 
54
- test "should send irc notification without backtrace info if properly configured" do
54
+ test 'should send irc notification without backtrace info if properly configured' do
55
55
  options = {
56
- :domain => 'irc.example.com'
56
+ domain: 'irc.example.com'
57
57
  }
58
58
 
59
59
  CarrierPigeon.expects(:send).with(has_key(:uri)) do |v|
@@ -64,25 +64,25 @@ class IrcNotifierTest < ActiveSupport::TestCase
64
64
  irc.call(fake_exception_without_backtrace)
65
65
  end
66
66
 
67
- test "should properly construct URI from constituent parts" do
67
+ test 'should properly construct URI from constituent parts' do
68
68
  options = {
69
- :nick => 'BadNewsBot',
70
- :password => 'secret',
71
- :domain => 'irc.example.com',
72
- :port => 9999,
73
- :channel => '#exceptions'
69
+ nick: 'BadNewsBot',
70
+ password: 'secret',
71
+ domain: 'irc.example.com',
72
+ port: 9999,
73
+ channel: '#exceptions'
74
74
  }
75
75
 
76
- CarrierPigeon.expects(:send).with(has_entry(uri: "irc://BadNewsBot:secret@irc.example.com:9999/#exceptions"))
76
+ CarrierPigeon.expects(:send).with(has_entry(uri: 'irc://BadNewsBot:secret@irc.example.com:9999/#exceptions'))
77
77
 
78
78
  irc = ExceptionNotifier::IrcNotifier.new(options)
79
79
  irc.call(fake_exception)
80
80
  end
81
81
 
82
- test "should properly add recipients if specified" do
82
+ test 'should properly add recipients if specified' do
83
83
  options = {
84
84
  domain: 'irc.example.com',
85
- recipients: ['peter', 'michael', 'samir']
85
+ recipients: %w[peter michael samir]
86
86
  }
87
87
 
88
88
  CarrierPigeon.expects(:send).with(has_key(:uri)) do |v|
@@ -93,7 +93,7 @@ class IrcNotifierTest < ActiveSupport::TestCase
93
93
  irc.call(fake_exception)
94
94
  end
95
95
 
96
- test "should properly set miscellaneous options" do
96
+ test 'should properly set miscellaneous options' do
97
97
  options = {
98
98
  domain: 'irc.example.com',
99
99
  ssl: true,
@@ -102,11 +102,13 @@ class IrcNotifierTest < ActiveSupport::TestCase
102
102
  prefix: '[test notification]'
103
103
  }
104
104
 
105
- CarrierPigeon.expects(:send).with(has_entries(
105
+ entries = {
106
106
  ssl: true,
107
107
  join: true,
108
- notice: true,
109
- )) do |v|
108
+ notice: true
109
+ }
110
+
111
+ CarrierPigeon.expects(:send).with(has_entries(entries)) do |v|
110
112
  /\[test notification\]/.match(v[:message])
111
113
  end
112
114
 
@@ -114,8 +116,8 @@ class IrcNotifierTest < ActiveSupport::TestCase
114
116
  irc.call(fake_exception)
115
117
  end
116
118
 
117
- test "should not send irc notification if badly configured" do
118
- wrong_params = { domain: '##scriptkiddie.com###'}
119
+ test 'should not send irc notification if badly configured' do
120
+ wrong_params = { domain: '##scriptkiddie.com###' }
119
121
  irc = ExceptionNotifier::IrcNotifier.new(wrong_params)
120
122
 
121
123
  assert_nil irc.call(fake_exception)
@@ -124,11 +126,9 @@ class IrcNotifierTest < ActiveSupport::TestCase
124
126
  private
125
127
 
126
128
  def fake_exception
127
- begin
128
- 5/0
129
- rescue Exception => e
130
- e
131
- end
129
+ 5 / 0
130
+ rescue StandardError => e
131
+ e
132
132
  end
133
133
 
134
134
  def fake_exception_without_backtrace
@@ -1,105 +1,202 @@
1
1
  require 'test_helper'
2
2
  require 'httparty'
3
+ require 'timecop'
4
+ require 'json'
3
5
 
4
6
  class MattermostNotifierTest < ActiveSupport::TestCase
7
+ URL = 'http://localhost:8000'.freeze
5
8
 
6
- test "should send notification if properly configured" do
7
- options = {
8
- :webhook_url => 'http://localhost:8000'
9
+ def setup
10
+ Timecop.freeze('2018-12-09 12:07:16 UTC')
11
+ end
12
+
13
+ def teardown
14
+ Timecop.return
15
+ end
16
+
17
+ test 'should send notification if properly configured' do
18
+ opts = {
19
+ body: default_body.to_json,
20
+ headers: default_headers
9
21
  }
10
- mattermost_notifier = ExceptionNotifier::MattermostNotifier.new
11
- mattermost_notifier.httparty = FakeHTTParty.new
12
22
 
13
- options = mattermost_notifier.call ArgumentError.new("foo"), options
23
+ HTTParty.expects(:post).with(URL, opts)
24
+ notifier.call ArgumentError.new('foo')
25
+ end
14
26
 
15
- body = ActiveSupport::JSON.decode options[:body]
16
- assert body.has_key? 'text'
17
- assert body.has_key? 'username'
27
+ test 'should send notification with create issue link if specified' do
28
+ body = default_body.merge(
29
+ text: [
30
+ '@channel',
31
+ error_occurred_in,
32
+ 'An *ArgumentError* occurred.',
33
+ '*foo*',
34
+ github_link
35
+ ].join("\n")
36
+ )
37
+
38
+ opts = {
39
+ body: body.to_json,
40
+ headers: default_headers
41
+ }
18
42
 
19
- text = body['text'].split("\n")
20
- assert_equal 4, text.size
21
- assert_equal '@channel', text[0]
22
- assert_equal 'An *ArgumentError* occured.', text[2]
23
- assert_equal '*foo*', text[3]
43
+ HTTParty.expects(:post).with(URL, opts)
44
+ notifier.call ArgumentError.new('foo'), git_url: 'github.com/aschen'
24
45
  end
25
46
 
26
- test "should send notification with create issue link if specified" do
27
- options = {
28
- :webhook_url => 'http://localhost:8000',
29
- :git_url => 'github.com/aschen'
47
+ test 'should add username and icon_url params to the notification if specified' do
48
+ body = default_body.merge(
49
+ username: 'Test Bot',
50
+ icon_url: 'http://site.com/icon.png'
51
+ )
52
+
53
+ opts = {
54
+ body: body.to_json,
55
+ headers: default_headers
30
56
  }
31
- mattermost_notifier = ExceptionNotifier::MattermostNotifier.new
32
- mattermost_notifier.httparty = FakeHTTParty.new
33
57
 
34
- options = mattermost_notifier.call ArgumentError.new("foo"), options
58
+ HTTParty.expects(:post).with(URL, opts)
59
+ notifier.call(
60
+ ArgumentError.new('foo'),
61
+ username: 'Test Bot',
62
+ avatar: 'http://site.com/icon.png'
63
+ )
64
+ end
35
65
 
36
- body = ActiveSupport::JSON.decode options[:body]
66
+ test 'should add other HTTParty options to params' do
67
+ opts = {
68
+ basic_auth: {
69
+ username: 'clara',
70
+ password: 'password'
71
+ },
72
+ body: default_body.to_json,
73
+ headers: default_headers
74
+ }
37
75
 
38
- text = body['text'].split("\n")
39
- assert_equal 5, text.size
40
- assert_equal '[Create an issue](github.com/aschen/dummy/issues/new/?issue%5Btitle%5D=%5BBUG%5D+Error+500+%3A++%28ArgumentError%29+foo)', text[4]
76
+ HTTParty.expects(:post).with(URL, opts)
77
+ notifier.call(
78
+ ArgumentError.new('foo'),
79
+ basic_auth: {
80
+ username: 'clara',
81
+ password: 'password'
82
+ }
83
+ )
41
84
  end
42
85
 
43
- test 'should add username and icon_url params to the notification if specified' do
44
- options = {
45
- :webhook_url => 'http://localhost:8000',
46
- :username => "Test Bot",
47
- :avatar => 'http://site.com/icon.png'
86
+ test "should use 'An' for exceptions count if :accumulated_errors_count option is nil" do
87
+ opts = {
88
+ body: default_body.to_json,
89
+ headers: default_headers
48
90
  }
49
- mattermost_notifier = ExceptionNotifier::MattermostNotifier.new
50
- mattermost_notifier.httparty = FakeHTTParty.new
51
91
 
52
- options = mattermost_notifier.call ArgumentError.new("foo"), options
92
+ HTTParty.expects(:post).with(URL, opts)
93
+ notifier.call(ArgumentError.new('foo'))
94
+ end
53
95
 
54
- body = ActiveSupport::JSON.decode options[:body]
96
+ test 'shoud use direct errors count if :accumulated_errors_count option is 5' do
97
+ body = default_body.merge(
98
+ text: [
99
+ '@channel',
100
+ error_occurred_in,
101
+ '5 *ArgumentError* occurred.',
102
+ '*foo*'
103
+ ].join("\n")
104
+ )
105
+
106
+ opts = {
107
+ body: body.to_json,
108
+ headers: default_headers
109
+ }
55
110
 
56
- assert_equal 'Test Bot', body['username']
57
- assert_equal 'http://site.com/icon.png', body['icon_url']
111
+ HTTParty.expects(:post).with(URL, opts)
112
+ notifier.call(ArgumentError.new('foo'), accumulated_errors_count: 5)
58
113
  end
59
114
 
60
- test 'should add other HTTParty options to params' do
61
- options = {
62
- :webhook_url => 'http://localhost:8000',
63
- :username => "Test Bot",
64
- :avatar => 'http://site.com/icon.png',
65
- :basic_auth => {
66
- :username => 'clara',
67
- :password => 'password'
68
- }
115
+ test 'should include backtrace and request info' do
116
+ body = default_body.merge(
117
+ text: [
118
+ '@channel',
119
+ error_occurred_in,
120
+ 'An *ArgumentError* occurred.',
121
+ '*foo*',
122
+ '### Request',
123
+ '```',
124
+ '* url : http://test.address/?id=foo',
125
+ '* http_method : GET',
126
+ '* ip_address : 127.0.0.1',
127
+ '* parameters : {"id"=>"foo"}',
128
+ '* timestamp : 2018-12-09 12:07:16 UTC',
129
+ '```',
130
+ '### Backtrace',
131
+ '```',
132
+ "* app/controllers/my_controller.rb:53:in `my_controller_params'",
133
+ "* app/controllers/my_controller.rb:34:in `update'",
134
+ '```'
135
+ ].join("\n")
136
+ )
137
+
138
+ opts = {
139
+ body: body.to_json,
140
+ headers: default_headers
69
141
  }
70
- mattermost_notifier = ExceptionNotifier::MattermostNotifier.new
71
- mattermost_notifier.httparty = FakeHTTParty.new
72
142
 
73
- options = mattermost_notifier.call ArgumentError.new("foo"), options
143
+ HTTParty.expects(:post).with(URL, opts)
144
+
145
+ exception = ArgumentError.new('foo')
146
+ exception.set_backtrace([
147
+ "app/controllers/my_controller.rb:53:in `my_controller_params'",
148
+ "app/controllers/my_controller.rb:34:in `update'"
149
+ ])
74
150
 
75
- assert options.has_key? :basic_auth
76
- assert 'clara', options[:basic_auth][:username]
77
- assert 'password', options[:basic_auth][:password]
151
+ notifier.call(exception, env: test_env)
78
152
  end
79
153
 
80
- test "should use 'An' for exceptions count if :accumulated_errors_count option is nil" do
81
- mattermost_notifier = ExceptionNotifier::MattermostNotifier.new
82
- exception = ArgumentError.new("foo")
83
- mattermost_notifier.instance_variable_set(:@exception, exception)
84
- mattermost_notifier.instance_variable_set(:@options, {})
154
+ private
85
155
 
86
- assert_includes mattermost_notifier.send(:message_header), "An *ArgumentError* occured."
156
+ def notifier
157
+ ExceptionNotifier::MattermostNotifier.new(webhook_url: URL)
87
158
  end
88
159
 
89
- test "shoud use direct errors count if :accumulated_errors_count option is 5" do
90
- mattermost_notifier = ExceptionNotifier::MattermostNotifier.new
91
- exception = ArgumentError.new("foo")
92
- mattermost_notifier.instance_variable_set(:@exception, exception)
93
- mattermost_notifier.instance_variable_set(:@options, { accumulated_errors_count: 5 })
160
+ def default_body
161
+ {
162
+ text: [
163
+ '@channel',
164
+ error_occurred_in,
165
+ 'An *ArgumentError* occurred.',
166
+ '*foo*'
167
+ ].join("\n"),
168
+ username: 'Exception Notifier'
169
+ }
170
+ end
94
171
 
95
- assert_includes mattermost_notifier.send(:message_header), "5 *ArgumentError* occured."
172
+ def default_headers
173
+ { 'Content-Type' => 'application/json' }
96
174
  end
97
- end
98
175
 
99
- class FakeHTTParty
176
+ def test_env
177
+ Rack::MockRequest.env_for(
178
+ '/',
179
+ 'HTTP_HOST' => 'test.address',
180
+ 'REMOTE_ADDR' => '127.0.0.1',
181
+ 'HTTP_USER_AGENT' => 'Rails Testing',
182
+ params: { id: 'foo' }
183
+ )
184
+ end
100
185
 
101
- def post(url, options)
102
- return options
186
+ def error_occurred_in
187
+ if defined?(::Rails) && ::Rails.respond_to?(:env)
188
+ '### ⚠️ Error occurred in test ⚠️'
189
+ else
190
+ '### ⚠️ Error occurred ⚠️'
191
+ end
103
192
  end
104
193
 
194
+ def github_link
195
+ if defined?(::Rails) && ::Rails.respond_to?(:application)
196
+ '[Create an issue](github.com/aschen/dummy/issues/new/?issue%5Btitle%5D=%5BBUG%5D+Error+500+%3A++%28ArgumentError%29+foo)'
197
+ else
198
+ # TODO: fix missing app name
199
+ '[Create an issue](github.com/aschen//issues/new/?issue%5Btitle%5D=%5BBUG%5D+Error+500+%3A++%28ArgumentError%29+foo)'
200
+ end
201
+ end
105
202
  end
@@ -1,18 +1,17 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class ErrorGroupTest < ActiveSupport::TestCase
4
-
5
4
  setup do
6
5
  module TestModule
7
6
  include ExceptionNotifier::ErrorGrouping
8
- @@error_grouping_cache = ActiveSupport::Cache::FileStore.new("test/dummy/tmp/non_default_location")
7
+ @@error_grouping_cache = ActiveSupport::Cache::FileStore.new('test/dummy/tmp/non_default_location')
9
8
  end
10
9
 
11
- @exception = RuntimeError.new("ERROR")
12
- @exception.stubs(:backtrace).returns(["/path/where/error/raised:1"])
10
+ @exception = RuntimeError.new('ERROR')
11
+ @exception.stubs(:backtrace).returns(['/path/where/error/raised:1'])
13
12
 
14
- @exception2 = RuntimeError.new("ERROR2")
15
- @exception2.stubs(:backtrace).returns(["/path/where/error/found:2"])
13
+ @exception2 = RuntimeError.new('ERROR2')
14
+ @exception2.stubs(:backtrace).returns(['/path/where/error/found:2'])
16
15
  end
17
16
 
18
17
  teardown do
@@ -20,88 +19,88 @@ class ErrorGroupTest < ActiveSupport::TestCase
20
19
  TestModule.fallback_cache_store.clear
21
20
  end
22
21
 
23
- test "should add additional option: error_grouping" do
22
+ test 'should add additional option: error_grouping' do
24
23
  assert_respond_to TestModule, :error_grouping
25
24
  assert_respond_to TestModule, :error_grouping=
26
25
  end
27
26
 
28
- test "should set error_grouping to false default" do
27
+ test 'should set error_grouping to false default' do
29
28
  assert_equal false, TestModule.error_grouping
30
29
  end
31
30
 
32
- test "should add additional option: error_grouping_cache" do
31
+ test 'should add additional option: error_grouping_cache' do
33
32
  assert_respond_to TestModule, :error_grouping_cache
34
33
  assert_respond_to TestModule, :error_grouping_cache=
35
34
  end
36
35
 
37
- test "should add additional option: error_grouping_period" do
36
+ test 'should add additional option: error_grouping_period' do
38
37
  assert_respond_to TestModule, :error_grouping_period
39
38
  assert_respond_to TestModule, :error_grouping_period=
40
39
  end
41
40
 
42
- test "shoud set error_grouping_period to 5.minutes default" do
41
+ test 'shoud set error_grouping_period to 5.minutes default' do
43
42
  assert_equal 300, TestModule.error_grouping_period
44
43
  end
45
44
 
46
- test "should add additional option: notification_trigger" do
45
+ test 'should add additional option: notification_trigger' do
47
46
  assert_respond_to TestModule, :notification_trigger
48
47
  assert_respond_to TestModule, :notification_trigger=
49
48
  end
50
49
 
51
- test "should return errors count nil when not same error for .error_count" do
52
- assert_nil TestModule.error_count("something")
50
+ test 'should return errors count nil when not same error for .error_count' do
51
+ assert_nil TestModule.error_count('something')
53
52
  end
54
53
 
55
- test "should return errors count when same error for .error_count" do
56
- TestModule.error_grouping_cache.write("error_key", 13)
57
- assert_equal 13, TestModule.error_count("error_key")
54
+ test 'should return errors count when same error for .error_count' do
55
+ TestModule.error_grouping_cache.write('error_key', 13)
56
+ assert_equal 13, TestModule.error_count('error_key')
58
57
  end
59
58
 
60
- test "should fallback to memory store cache if specified cache store failed to read" do
61
- TestModule.error_grouping_cache.stubs(:read).raises(RuntimeError.new "Failed to read")
59
+ test 'should fallback to memory store cache if specified cache store failed to read' do
60
+ TestModule.error_grouping_cache.stubs(:read).raises(RuntimeError.new('Failed to read'))
62
61
  original_fallback = TestModule.fallback_cache_store
63
62
  TestModule.expects(:fallback_cache_store).returns(original_fallback).at_least_once
64
63
 
65
- assert_nil TestModule.error_count("something_to_read")
64
+ assert_nil TestModule.error_count('something_to_read')
66
65
  end
67
66
 
68
- test "should save error with count for .save_error_count" do
67
+ test 'should save error with count for .save_error_count' do
69
68
  count = rand(1..10)
70
69
 
71
- TestModule.save_error_count("error_key", count)
72
- assert_equal count, TestModule.error_grouping_cache.read("error_key")
70
+ TestModule.save_error_count('error_key', count)
71
+ assert_equal count, TestModule.error_grouping_cache.read('error_key')
73
72
  end
74
73
 
75
- test "should fallback to memory store cache if specified cache store failed to write" do
76
- TestModule.error_grouping_cache.stubs(:write).raises(RuntimeError.new "Failed to write")
74
+ test 'should fallback to memory store cache if specified cache store failed to write' do
75
+ TestModule.error_grouping_cache.stubs(:write).raises(RuntimeError.new('Failed to write'))
77
76
  original_fallback = TestModule.fallback_cache_store
78
77
  TestModule.expects(:fallback_cache_store).returns(original_fallback).at_least_once
79
78
 
80
- assert TestModule.save_error_count("something_to_cache", rand(1..10))
79
+ assert TestModule.save_error_count('something_to_cache', rand(1..10))
81
80
  end
82
81
 
83
- test "should save accumulated_errors_count into options" do
82
+ test 'should save accumulated_errors_count into options' do
84
83
  options = {}
85
84
  TestModule.group_error!(@exception, options)
86
85
 
87
86
  assert_equal 1, options[:accumulated_errors_count]
88
87
  end
89
88
 
90
- test "should not group error if different exception in .group_error!" do
89
+ test 'should not group error if different exception in .group_error!' do
91
90
  options1 = {}
92
- TestModule.expects(:save_error_count).with{|key, count| key.is_a?(String) && count == 1}.times(4).returns(true)
91
+ TestModule.expects(:save_error_count).with { |key, count| key.is_a?(String) && count == 1 }.times(4).returns(true)
93
92
  TestModule.group_error!(@exception, options1)
94
93
 
95
94
  options2 = {}
96
- TestModule.group_error!(NoMethodError.new("method not found"), options2)
95
+ TestModule.group_error!(NoMethodError.new('method not found'), options2)
97
96
 
98
97
  assert_equal 1, options1[:accumulated_errors_count]
99
98
  assert_equal 1, options2[:accumulated_errors_count]
100
99
  end
101
100
 
102
- test "should not group error is same exception but different message or backtrace" do
101
+ test 'should not group error is same exception but different message or backtrace' do
103
102
  options1 = {}
104
- TestModule.expects(:save_error_count).with{|key, count| key.is_a?(String) && count == 1}.times(4).returns(true)
103
+ TestModule.expects(:save_error_count).with { |key, count| key.is_a?(String) && count == 1 }.times(4).returns(true)
105
104
  TestModule.group_error!(@exception, options1)
106
105
 
107
106
  options2 = {}
@@ -111,7 +110,7 @@ class ErrorGroupTest < ActiveSupport::TestCase
111
110
  assert_equal 1, options2[:accumulated_errors_count]
112
111
  end
113
112
 
114
- test "should group error if same exception and message" do
113
+ test 'should group error if same exception and message' do
115
114
  options = {}
116
115
 
117
116
  10.times do |i|
@@ -122,7 +121,7 @@ class ErrorGroupTest < ActiveSupport::TestCase
122
121
  assert_equal 10, options[:accumulated_errors_count]
123
122
  end
124
123
 
125
- test "should group error if same exception and backtrace" do
124
+ test 'should group error if same exception and backtrace' do
126
125
  options = {}
127
126
 
128
127
  10.times do |i|
@@ -133,9 +132,9 @@ class ErrorGroupTest < ActiveSupport::TestCase
133
132
  assert_equal 10, options[:accumulated_errors_count]
134
133
  end
135
134
 
136
- test "should group error by that message have high priority" do
135
+ test 'should group error by that message have high priority' do
137
136
  message_based_key = "exception:#{Zlib.crc32("RuntimeError\nmessage:ERROR")}"
138
- backtrace_based_key = "exception:#{Zlib.crc32("RuntimeError\n/path/where/error/raised:1")}"
137
+ backtrace_based_key = "exception:#{Zlib.crc32("RuntimeError\npath:/path/where/error/raised:1")}"
139
138
 
140
139
  TestModule.save_error_count(message_based_key, 1)
141
140
  TestModule.save_error_count(backtrace_based_key, 1)
@@ -146,7 +145,7 @@ class ErrorGroupTest < ActiveSupport::TestCase
146
145
  TestModule.group_error!(@exception, {})
147
146
  end
148
147
 
149
- test "use default formula if not specify notification_trigger in .send_notification?" do
148
+ test 'use default formula if not specify notification_trigger in .send_notification?' do
150
149
  TestModule.stubs(:notification_trigger).returns(nil)
151
150
 
152
151
  count = 16
@@ -155,12 +154,12 @@ class ErrorGroupTest < ActiveSupport::TestCase
155
154
  assert TestModule.send_notification?(@exception, count)
156
155
  end
157
156
 
158
- test "use specified trigger in .send_notification?" do
159
- trigger = Proc.new { |exception, count| count % 4 == 0 }
157
+ test 'use specified trigger in .send_notification?' do
158
+ trigger = proc { |_exception, count| (count % 4).zero? }
160
159
  TestModule.stubs(:notification_trigger).returns(trigger)
161
160
 
162
161
  count = 16
163
162
  trigger.expects(:call).with(@exception, count).returns(true)
164
163
  assert TestModule.send_notification?(@exception, count)
165
164
  end
166
- end
165
+ end