exception_notification 4.6.0 → 5.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.rdoc +30 -0
- data/CONTRIBUTING.md +23 -51
- data/README.md +65 -31
- data/Rakefile +14 -7
- data/exception_notification.gemspec +36 -32
- data/lib/exception_notification/rack.rb +4 -4
- data/lib/exception_notification/rails.rb +2 -2
- data/lib/exception_notification/rake.rb +3 -7
- data/lib/exception_notification/resque.rb +2 -2
- data/lib/exception_notification/sidekiq.rb +8 -23
- data/lib/exception_notification/version.rb +1 -1
- data/lib/exception_notification.rb +3 -3
- data/lib/exception_notifier/datadog_notifier.rb +26 -26
- data/lib/exception_notifier/email_notifier.rb +34 -30
- data/lib/exception_notifier/google_chat_notifier.rb +9 -9
- data/lib/exception_notifier/hipchat_notifier.rb +12 -12
- data/lib/exception_notifier/irc_notifier.rb +6 -6
- data/lib/exception_notifier/mattermost_notifier.rb +13 -13
- data/lib/exception_notifier/modules/error_grouping.rb +5 -5
- data/lib/exception_notifier/modules/formatter.rb +12 -12
- data/lib/exception_notifier/notifier.rb +3 -3
- data/lib/exception_notifier/slack_notifier.rb +16 -16
- data/lib/exception_notifier/sns_notifier.rb +9 -9
- data/lib/exception_notifier/teams_notifier.rb +61 -57
- data/lib/exception_notifier/webhook_notifier.rb +3 -3
- data/lib/exception_notifier.rb +27 -26
- data/lib/generators/exception_notification/install_generator.rb +7 -7
- data/lib/generators/exception_notification/templates/exception_notification.rb.erb +26 -27
- metadata +41 -110
- data/Appraisals +0 -9
- data/Gemfile +0 -5
- data/Gemfile.lock +0 -352
- data/gemfiles/rails5_2.gemfile +0 -7
- data/gemfiles/rails6_0.gemfile +0 -7
- data/gemfiles/rails6_1.gemfile +0 -7
- data/gemfiles/rails7_0.gemfile +0 -7
- data/test/exception_notification/rack_test.rb +0 -106
- data/test/exception_notification/rake_test.rb +0 -38
- data/test/exception_notification/resque_test.rb +0 -54
- data/test/exception_notifier/datadog_notifier_test.rb +0 -153
- data/test/exception_notifier/email_notifier_test.rb +0 -351
- data/test/exception_notifier/google_chat_notifier_test.rb +0 -185
- data/test/exception_notifier/hipchat_notifier_test.rb +0 -218
- data/test/exception_notifier/irc_notifier_test.rb +0 -139
- data/test/exception_notifier/mattermost_notifier_test.rb +0 -251
- data/test/exception_notifier/modules/error_grouping_test.rb +0 -167
- data/test/exception_notifier/modules/formatter_test.rb +0 -152
- data/test/exception_notifier/sidekiq_test.rb +0 -34
- data/test/exception_notifier/slack_notifier_test.rb +0 -229
- data/test/exception_notifier/sns_notifier_test.rb +0 -178
- data/test/exception_notifier/teams_notifier_test.rb +0 -92
- data/test/exception_notifier/webhook_notifier_test.rb +0 -98
- data/test/exception_notifier_test.rb +0 -288
- data/test/support/exception_notifier_helper.rb +0 -14
- data/test/support/views/exception_notifier/_new_bkg_section.html.erb +0 -1
- data/test/support/views/exception_notifier/_new_bkg_section.text.erb +0 -1
- data/test/support/views/exception_notifier/_new_section.html.erb +0 -1
- data/test/support/views/exception_notifier/_new_section.text.erb +0 -1
- data/test/test_helper.rb +0 -19
@@ -1,106 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'test_helper'
|
4
|
-
|
5
|
-
class RackTest < ActiveSupport::TestCase
|
6
|
-
setup do
|
7
|
-
@pass_app = Object.new
|
8
|
-
@pass_app.stubs(:call).returns([nil, { 'X-Cascade' => 'pass' }, nil])
|
9
|
-
|
10
|
-
@normal_app = Object.new
|
11
|
-
@normal_app.stubs(:call).returns([nil, {}, nil])
|
12
|
-
end
|
13
|
-
|
14
|
-
teardown do
|
15
|
-
ExceptionNotifier.reset_notifiers!
|
16
|
-
end
|
17
|
-
|
18
|
-
test 'should ignore "X-Cascade" header by default' do
|
19
|
-
ExceptionNotifier.expects(:notify_exception).never
|
20
|
-
ExceptionNotification::Rack.new(@pass_app).call({})
|
21
|
-
end
|
22
|
-
|
23
|
-
test 'should notify on "X-Cascade" = "pass" if ignore_cascade_pass option is false' do
|
24
|
-
ExceptionNotifier.expects(:notify_exception).once
|
25
|
-
ExceptionNotification::Rack.new(@pass_app, ignore_cascade_pass: false).call({})
|
26
|
-
end
|
27
|
-
|
28
|
-
test 'should assign error_grouping if error_grouping is specified' do
|
29
|
-
refute ExceptionNotifier.error_grouping
|
30
|
-
ExceptionNotification::Rack.new(@normal_app, error_grouping: true).call({})
|
31
|
-
assert ExceptionNotifier.error_grouping
|
32
|
-
end
|
33
|
-
|
34
|
-
test 'should assign notification_trigger if notification_trigger is specified' do
|
35
|
-
assert_nil ExceptionNotifier.notification_trigger
|
36
|
-
ExceptionNotification::Rack.new(@normal_app, notification_trigger: ->(_i) { true }).call({})
|
37
|
-
assert_respond_to ExceptionNotifier.notification_trigger, :call
|
38
|
-
end
|
39
|
-
|
40
|
-
if defined?(Rails) && Rails.respond_to?(:cache)
|
41
|
-
test 'should set default cache to Rails cache' do
|
42
|
-
ExceptionNotification::Rack.new(@normal_app, error_grouping: true).call({})
|
43
|
-
assert_equal Rails.cache, ExceptionNotifier.error_grouping_cache
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
test 'should ignore exceptions with Usar Agent in ignore_crawlers' do
|
48
|
-
exception_app = Object.new
|
49
|
-
exception_app.stubs(:call).raises(RuntimeError)
|
50
|
-
|
51
|
-
env = { 'HTTP_USER_AGENT' => 'Mozilla/5.0 (compatible; Crawlerbot/2.1;)' }
|
52
|
-
|
53
|
-
begin
|
54
|
-
ExceptionNotification::Rack.new(exception_app, ignore_crawlers: %w[Crawlerbot]).call(env)
|
55
|
-
|
56
|
-
flunk
|
57
|
-
rescue StandardError
|
58
|
-
refute env['exception_notifier.delivered']
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
test 'should ignore exceptions if ignore_if condition is met' do
|
63
|
-
exception_app = Object.new
|
64
|
-
exception_app.stubs(:call).raises(RuntimeError)
|
65
|
-
|
66
|
-
env = {}
|
67
|
-
|
68
|
-
begin
|
69
|
-
ExceptionNotification::Rack.new(
|
70
|
-
exception_app,
|
71
|
-
ignore_if: ->(_env, exception) { exception.is_a? RuntimeError }
|
72
|
-
).call(env)
|
73
|
-
|
74
|
-
flunk
|
75
|
-
rescue StandardError
|
76
|
-
refute env['exception_notifier.delivered']
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
test 'should ignore exceptions with notifiers that satisfies ignore_notifier_if condition' do
|
81
|
-
exception_app = Object.new
|
82
|
-
exception_app.stubs(:call).raises(RuntimeError)
|
83
|
-
|
84
|
-
notifier1_called = notifier2_called = false
|
85
|
-
notifier1 = ->(_exception, _options) { notifier1_called = true }
|
86
|
-
notifier2 = ->(_exception, _options) { notifier2_called = true }
|
87
|
-
|
88
|
-
env = {}
|
89
|
-
|
90
|
-
begin
|
91
|
-
ExceptionNotification::Rack.new(
|
92
|
-
exception_app,
|
93
|
-
ignore_notifier_if: {
|
94
|
-
notifier1: ->(_env, exception) { exception.is_a? RuntimeError }
|
95
|
-
},
|
96
|
-
notifier1: notifier1,
|
97
|
-
notifier2: notifier2
|
98
|
-
).call(env)
|
99
|
-
|
100
|
-
flunk
|
101
|
-
rescue StandardError
|
102
|
-
refute notifier1_called
|
103
|
-
assert notifier2_called
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'test_helper'
|
4
|
-
|
5
|
-
require 'rake'
|
6
|
-
require 'exception_notification/rake'
|
7
|
-
|
8
|
-
class RakeTest < ActiveSupport::TestCase
|
9
|
-
setup do
|
10
|
-
Rake::Task.define_task :dependency_1 do
|
11
|
-
puts :dependency_1
|
12
|
-
end
|
13
|
-
Rake::Task.define_task raise_exception: :dependency_1 do
|
14
|
-
raise 'test exception'
|
15
|
-
end
|
16
|
-
@task = Rake::Task[:raise_exception]
|
17
|
-
end
|
18
|
-
|
19
|
-
test 'notifies of exception' do
|
20
|
-
ExceptionNotifier.expects(:notify_exception).with do |ex, opts|
|
21
|
-
data = opts[:data]
|
22
|
-
ex.is_a?(RuntimeError) &&
|
23
|
-
ex.message == 'test exception' &&
|
24
|
-
data[:error_class] == 'RuntimeError' &&
|
25
|
-
data[:error_message] == 'test exception' &&
|
26
|
-
data[:rake][:rake_command_line] == 'rake ' &&
|
27
|
-
data[:rake][:name] == 'raise_exception' &&
|
28
|
-
data[:rake][:timestamp] &&
|
29
|
-
data[:rake][:sources] == ['dependency_1'] &&
|
30
|
-
data[:rake][:prerequisite_tasks][0][:name] == 'dependency_1'
|
31
|
-
end
|
32
|
-
|
33
|
-
# The original error is re-raised
|
34
|
-
assert_raises(RuntimeError) do
|
35
|
-
@task.invoke
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
@@ -1,54 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'test_helper'
|
4
|
-
|
5
|
-
require 'exception_notification/resque'
|
6
|
-
require 'resque'
|
7
|
-
require 'mock_redis'
|
8
|
-
require 'resque/failure/multiple'
|
9
|
-
require 'resque/failure/redis'
|
10
|
-
|
11
|
-
class ResqueTest < ActiveSupport::TestCase
|
12
|
-
setup do
|
13
|
-
# Resque.redis=() only supports a String or Redis instance in Resque 1.8
|
14
|
-
Resque.instance_variable_set(:@redis, MockRedis.new)
|
15
|
-
|
16
|
-
Resque::Failure::Multiple.classes = [Resque::Failure::Redis, ExceptionNotification::Resque]
|
17
|
-
Resque::Failure.backend = Resque::Failure::Multiple
|
18
|
-
|
19
|
-
@worker = Resque::Worker.new(:jobs)
|
20
|
-
# Forking causes issues with Mocha's `.expects`
|
21
|
-
@worker.cant_fork = true
|
22
|
-
end
|
23
|
-
|
24
|
-
test 'count returns the number of failures' do
|
25
|
-
Resque::Job.create(:jobs, BadJob)
|
26
|
-
@worker.work(0)
|
27
|
-
assert_equal 1, ExceptionNotification::Resque.count
|
28
|
-
end
|
29
|
-
|
30
|
-
test 'notifies exception when job fails' do
|
31
|
-
ExceptionNotifier.expects(:notify_exception).with do |ex, opts|
|
32
|
-
ex.is_a?(RuntimeError) &&
|
33
|
-
ex.message == 'Bad job!' &&
|
34
|
-
opts[:data][:resque][:error_class] == 'RuntimeError' &&
|
35
|
-
opts[:data][:resque][:error_message] == 'Bad job!' &&
|
36
|
-
opts[:data][:resque][:failed_at].present? &&
|
37
|
-
opts[:data][:resque][:payload] == {
|
38
|
-
'class' => 'ResqueTest::BadJob',
|
39
|
-
'args' => []
|
40
|
-
} &&
|
41
|
-
opts[:data][:resque][:queue] == :jobs &&
|
42
|
-
opts[:data][:resque][:worker].present?
|
43
|
-
end
|
44
|
-
|
45
|
-
Resque::Job.create(:jobs, BadJob)
|
46
|
-
@worker.work(0)
|
47
|
-
end
|
48
|
-
|
49
|
-
class BadJob
|
50
|
-
def self.perform
|
51
|
-
raise 'Bad job!'
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
@@ -1,153 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'test_helper'
|
4
|
-
require 'dogapi/common'
|
5
|
-
require 'dogapi/event'
|
6
|
-
|
7
|
-
class DatadogNotifierTest < ActiveSupport::TestCase
|
8
|
-
def setup
|
9
|
-
@client = FakeDatadogClient.new
|
10
|
-
@options = {
|
11
|
-
client: @client
|
12
|
-
}
|
13
|
-
@notifier = ExceptionNotifier::DatadogNotifier.new(@options)
|
14
|
-
@exception = FakeException.new
|
15
|
-
@controller = FakeController.new
|
16
|
-
@request = FakeRequest.new
|
17
|
-
end
|
18
|
-
|
19
|
-
test 'should send an event to datadog' do
|
20
|
-
fake_event = Dogapi::Event.any_instance
|
21
|
-
@client.expects(:emit_event).with(fake_event)
|
22
|
-
|
23
|
-
@notifier.stubs(:datadog_event).returns(fake_event)
|
24
|
-
@notifier.call(@exception)
|
25
|
-
end
|
26
|
-
|
27
|
-
test 'should include exception class in event title' do
|
28
|
-
event = @notifier.datadog_event(@exception)
|
29
|
-
assert_includes event.msg_title, 'FakeException'
|
30
|
-
end
|
31
|
-
|
32
|
-
test 'should include prefix in event title and not append previous events' do
|
33
|
-
options = {
|
34
|
-
client: @client,
|
35
|
-
title_prefix: 'prefix'
|
36
|
-
}
|
37
|
-
|
38
|
-
notifier = ExceptionNotifier::DatadogNotifier.new(options)
|
39
|
-
event = notifier.datadog_event(@exception)
|
40
|
-
assert_equal event.msg_title, 'prefix (DatadogNotifierTest::FakeException) "Fake exception message"'
|
41
|
-
|
42
|
-
event2 = notifier.datadog_event(@exception)
|
43
|
-
assert_equal event2.msg_title, 'prefix (DatadogNotifierTest::FakeException) "Fake exception message"'
|
44
|
-
end
|
45
|
-
|
46
|
-
test 'should include exception message in event title' do
|
47
|
-
event = @notifier.datadog_event(@exception)
|
48
|
-
assert_includes event.msg_title, 'Fake exception message'
|
49
|
-
end
|
50
|
-
|
51
|
-
test 'should include controller info in event title if controller information is available' do
|
52
|
-
event = @notifier.datadog_event(@exception,
|
53
|
-
env: {
|
54
|
-
'action_controller.instance' => @controller,
|
55
|
-
'REQUEST_METHOD' => 'GET',
|
56
|
-
'rack.input' => ''
|
57
|
-
})
|
58
|
-
assert_includes event.msg_title, 'Fake controller'
|
59
|
-
assert_includes event.msg_title, 'Fake action'
|
60
|
-
end
|
61
|
-
|
62
|
-
test 'should include backtrace info in event body' do
|
63
|
-
event = @notifier.datadog_event(@exception)
|
64
|
-
assert_includes event.msg_text, "backtrace line 1\nbacktrace line 2\nbacktrace line 3"
|
65
|
-
end
|
66
|
-
|
67
|
-
test 'should include request info in event body' do
|
68
|
-
ActionDispatch::Request.stubs(:new).returns(@request)
|
69
|
-
|
70
|
-
event = @notifier.datadog_event(@exception,
|
71
|
-
env: {
|
72
|
-
'action_controller.instance' => @controller,
|
73
|
-
'REQUEST_METHOD' => 'GET',
|
74
|
-
'rack.input' => ''
|
75
|
-
})
|
76
|
-
assert_includes event.msg_text, 'http://localhost:8080'
|
77
|
-
assert_includes event.msg_text, 'GET'
|
78
|
-
assert_includes event.msg_text, '127.0.0.1'
|
79
|
-
assert_includes event.msg_text, '{"param 1"=>"value 1", "param 2"=>"value 2"}'
|
80
|
-
end
|
81
|
-
|
82
|
-
test 'should include tags in event' do
|
83
|
-
options = {
|
84
|
-
client: @client,
|
85
|
-
tags: %w[error production]
|
86
|
-
}
|
87
|
-
notifier = ExceptionNotifier::DatadogNotifier.new(options)
|
88
|
-
event = notifier.datadog_event(@exception)
|
89
|
-
assert_equal event.tags, %w[error production]
|
90
|
-
end
|
91
|
-
|
92
|
-
test 'should include event title in event aggregation key' do
|
93
|
-
event = @notifier.datadog_event(@exception)
|
94
|
-
assert_equal event.aggregation_key, [event.msg_title]
|
95
|
-
end
|
96
|
-
|
97
|
-
class FakeDatadogClient
|
98
|
-
def emit_event(event); end
|
99
|
-
end
|
100
|
-
|
101
|
-
class FakeController
|
102
|
-
def controller_name
|
103
|
-
'Fake controller'
|
104
|
-
end
|
105
|
-
|
106
|
-
def action_name
|
107
|
-
'Fake action'
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
class FakeException
|
112
|
-
def backtrace
|
113
|
-
[
|
114
|
-
'backtrace line 1',
|
115
|
-
'backtrace line 2',
|
116
|
-
'backtrace line 3',
|
117
|
-
'backtrace line 4',
|
118
|
-
'backtrace line 5'
|
119
|
-
]
|
120
|
-
end
|
121
|
-
|
122
|
-
def message
|
123
|
-
'Fake exception message'
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
class FakeRequest
|
128
|
-
def url
|
129
|
-
'http://localhost:8080'
|
130
|
-
end
|
131
|
-
|
132
|
-
def request_method
|
133
|
-
'GET'
|
134
|
-
end
|
135
|
-
|
136
|
-
def remote_ip
|
137
|
-
'127.0.0.1'
|
138
|
-
end
|
139
|
-
|
140
|
-
def filtered_parameters
|
141
|
-
{
|
142
|
-
'param 1' => 'value 1',
|
143
|
-
'param 2' => 'value 2'
|
144
|
-
}
|
145
|
-
end
|
146
|
-
|
147
|
-
def session
|
148
|
-
{
|
149
|
-
'session_id' => '1234'
|
150
|
-
}
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
@@ -1,351 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'test_helper'
|
4
|
-
require 'action_mailer'
|
5
|
-
require 'action_controller'
|
6
|
-
|
7
|
-
class EmailNotifierTest < ActiveSupport::TestCase
|
8
|
-
setup do
|
9
|
-
Time.stubs(:current).returns('Sat, 20 Apr 2013 20:58:55 UTC +00:00')
|
10
|
-
|
11
|
-
@exception = ZeroDivisionError.new('divided by 0')
|
12
|
-
@exception.set_backtrace(['test/exception_notifier/email_notifier_test.rb:20'])
|
13
|
-
|
14
|
-
@email_notifier = ExceptionNotifier::EmailNotifier.new(
|
15
|
-
email_prefix: '[Dummy ERROR] ',
|
16
|
-
sender_address: %("Dummy Notifier" <dummynotifier@example.com>),
|
17
|
-
exception_recipients: %w[dummyexceptions@example.com],
|
18
|
-
email_headers: { 'X-Custom-Header' => 'foobar' },
|
19
|
-
sections: %w[new_section request session environment backtrace],
|
20
|
-
background_sections: %w[new_bkg_section backtrace data],
|
21
|
-
pre_callback: proc { |_opts, _notifier, _backtrace, _message, _message_opts| @pre_callback_called = true },
|
22
|
-
post_callback: proc { |_opts, _notifier, _backtrace, _message, _message_opts| @post_callback_called = true },
|
23
|
-
smtp_settings: {
|
24
|
-
user_name: 'Dummy user_name',
|
25
|
-
password: 'Dummy password'
|
26
|
-
}
|
27
|
-
)
|
28
|
-
|
29
|
-
@mail = @email_notifier.call(
|
30
|
-
@exception,
|
31
|
-
data: { job: 'DivideWorkerJob', payload: '1/0', message: 'My Custom Message' }
|
32
|
-
)
|
33
|
-
end
|
34
|
-
|
35
|
-
test 'should call pre/post_callback if specified' do
|
36
|
-
assert @pre_callback_called
|
37
|
-
assert @post_callback_called
|
38
|
-
end
|
39
|
-
|
40
|
-
test 'sends mail with correct content' do
|
41
|
-
assert_equal %("Dummy Notifier" <dummynotifier@example.com>), @mail[:from].value
|
42
|
-
assert_equal %w[dummyexceptions@example.com], @mail.to
|
43
|
-
assert_equal '[Dummy ERROR] (ZeroDivisionError) "divided by 0"', @mail.subject
|
44
|
-
assert_equal 'foobar', @mail['X-Custom-Header'].value
|
45
|
-
assert_equal 'text/plain; charset=UTF-8', @mail.content_type
|
46
|
-
assert_equal [], @mail.attachments
|
47
|
-
assert_equal 'Dummy user_name', @mail.delivery_method.settings[:user_name]
|
48
|
-
assert_equal 'Dummy password', @mail.delivery_method.settings[:password]
|
49
|
-
|
50
|
-
body = <<-BODY.gsub(/^ /, '')
|
51
|
-
A ZeroDivisionError occurred in background at Sat, 20 Apr 2013 20:58:55 UTC +00:00 :
|
52
|
-
|
53
|
-
divided by 0
|
54
|
-
test/exception_notifier/email_notifier_test.rb:20
|
55
|
-
|
56
|
-
-------------------------------
|
57
|
-
New bkg section:
|
58
|
-
-------------------------------
|
59
|
-
|
60
|
-
* New background section for testing
|
61
|
-
|
62
|
-
-------------------------------
|
63
|
-
Backtrace:
|
64
|
-
-------------------------------
|
65
|
-
|
66
|
-
test/exception_notifier/email_notifier_test.rb:20
|
67
|
-
|
68
|
-
-------------------------------
|
69
|
-
Data:
|
70
|
-
-------------------------------
|
71
|
-
|
72
|
-
* data: {:job=>"DivideWorkerJob", :payload=>"1/0", :message=>"My Custom Message"}
|
73
|
-
|
74
|
-
|
75
|
-
BODY
|
76
|
-
|
77
|
-
assert_equal body, @mail.decode_body
|
78
|
-
end
|
79
|
-
|
80
|
-
test 'should normalize multiple digits into one N' do
|
81
|
-
assert_equal 'N foo N bar N baz N',
|
82
|
-
ExceptionNotifier::EmailNotifier.normalize_digits('1 foo 12 bar 123 baz 1234')
|
83
|
-
end
|
84
|
-
|
85
|
-
test "mail should prefix exception class with 'an' instead of 'a' when it starts with a vowel" do
|
86
|
-
begin
|
87
|
-
raise ArgumentError
|
88
|
-
rescue StandardError => e
|
89
|
-
@vowel_exception = e
|
90
|
-
@vowel_mail = @email_notifier.call(@vowel_exception)
|
91
|
-
end
|
92
|
-
|
93
|
-
assert_includes @vowel_mail.encoded, "An ArgumentError occurred in background at #{Time.current}"
|
94
|
-
end
|
95
|
-
|
96
|
-
test 'should not send notification if one of ignored exceptions' do
|
97
|
-
begin
|
98
|
-
raise AbstractController::ActionNotFound
|
99
|
-
rescue StandardError => e
|
100
|
-
@ignored_exception = e
|
101
|
-
unless ExceptionNotifier.ignored_exceptions.include?(@ignored_exception.class.name)
|
102
|
-
ignored_mail = @email_notifier.call(@ignored_exception)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
assert_equal @ignored_exception.class.inspect, 'AbstractController::ActionNotFound'
|
107
|
-
assert_nil ignored_mail
|
108
|
-
end
|
109
|
-
|
110
|
-
test 'should encode environment strings' do
|
111
|
-
email_notifier = ExceptionNotifier::EmailNotifier.new(
|
112
|
-
sender_address: '<dummynotifier@example.com>',
|
113
|
-
exception_recipients: %w[dummyexceptions@example.com]
|
114
|
-
)
|
115
|
-
|
116
|
-
mail = email_notifier.call(
|
117
|
-
@exception,
|
118
|
-
env: {
|
119
|
-
'REQUEST_METHOD' => 'GET',
|
120
|
-
'rack.input' => '',
|
121
|
-
'invalid_encoding' => "R\xC3\xA9sum\xC3\xA9".dup.force_encoding(Encoding::ASCII)
|
122
|
-
}
|
123
|
-
)
|
124
|
-
|
125
|
-
assert_match(/invalid_encoding\s+: R__sum__/, mail.encoded)
|
126
|
-
end
|
127
|
-
|
128
|
-
test 'should send email using ActionMailer' do
|
129
|
-
ActionMailer::Base.deliveries.clear
|
130
|
-
@email_notifier.call(@exception)
|
131
|
-
assert_equal 1, ActionMailer::Base.deliveries.count
|
132
|
-
end
|
133
|
-
|
134
|
-
test 'should be able to specify ActionMailer::MessageDelivery method' do
|
135
|
-
ActionMailer::Base.deliveries.clear
|
136
|
-
|
137
|
-
deliver_with = if ActionMailer.version < Gem::Version.new('4.2')
|
138
|
-
:deliver
|
139
|
-
else
|
140
|
-
:deliver_now
|
141
|
-
end
|
142
|
-
|
143
|
-
email_notifier = ExceptionNotifier::EmailNotifier.new(
|
144
|
-
email_prefix: '[Dummy ERROR] ',
|
145
|
-
sender_address: %("Dummy Notifier" <dummynotifier@example.com>),
|
146
|
-
exception_recipients: %w[dummyexceptions@example.com],
|
147
|
-
deliver_with: deliver_with
|
148
|
-
)
|
149
|
-
|
150
|
-
email_notifier.call(@exception)
|
151
|
-
|
152
|
-
assert_equal 1, ActionMailer::Base.deliveries.count
|
153
|
-
end
|
154
|
-
|
155
|
-
test 'should lazily evaluate exception_recipients' do
|
156
|
-
exception_recipients = %w[first@example.com second@example.com]
|
157
|
-
email_notifier = ExceptionNotifier::EmailNotifier.new(
|
158
|
-
email_prefix: '[Dummy ERROR] ',
|
159
|
-
sender_address: %("Dummy Notifier" <dummynotifier@example.com>),
|
160
|
-
exception_recipients: -> { [exception_recipients.shift] },
|
161
|
-
delivery_method: :test
|
162
|
-
)
|
163
|
-
|
164
|
-
mail = email_notifier.call(@exception)
|
165
|
-
assert_equal %w[first@example.com], mail.to
|
166
|
-
mail = email_notifier.call(@exception)
|
167
|
-
assert_equal %w[second@example.com], mail.to
|
168
|
-
end
|
169
|
-
|
170
|
-
test 'should prepend accumulated_errors_count in email subject if accumulated_errors_count larger than 1' do
|
171
|
-
email_notifier = ExceptionNotifier::EmailNotifier.new(
|
172
|
-
email_prefix: '[Dummy ERROR] ',
|
173
|
-
sender_address: %("Dummy Notifier" <dummynotifier@example.com>),
|
174
|
-
exception_recipients: %w[dummyexceptions@example.com],
|
175
|
-
delivery_method: :test
|
176
|
-
)
|
177
|
-
|
178
|
-
mail = email_notifier.call(@exception, accumulated_errors_count: 3)
|
179
|
-
assert mail.subject.start_with?('[Dummy ERROR] (3 times) (ZeroDivisionError)')
|
180
|
-
end
|
181
|
-
|
182
|
-
test 'should not include exception message in subject when verbose_subject: false' do
|
183
|
-
email_notifier = ExceptionNotifier::EmailNotifier.new(
|
184
|
-
sender_address: %("Dummy Notifier" <dummynotifier@example.com>),
|
185
|
-
exception_recipients: %w[dummyexceptions@example.com],
|
186
|
-
verbose_subject: false
|
187
|
-
)
|
188
|
-
|
189
|
-
mail = email_notifier.call(@exception)
|
190
|
-
|
191
|
-
assert_equal '[ERROR] (ZeroDivisionError)', mail.subject
|
192
|
-
end
|
193
|
-
|
194
|
-
test 'should send html email when selected html format' do
|
195
|
-
email_notifier = ExceptionNotifier::EmailNotifier.new(
|
196
|
-
sender_address: %("Dummy Notifier" <dummynotifier@example.com>),
|
197
|
-
exception_recipients: %w[dummyexceptions@example.com],
|
198
|
-
email_format: :html
|
199
|
-
)
|
200
|
-
|
201
|
-
mail = email_notifier.call(@exception)
|
202
|
-
|
203
|
-
assert mail.multipart?
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
207
|
-
class EmailNotifierWithEnvTest < ActiveSupport::TestCase
|
208
|
-
class HomeController < ActionController::Metal
|
209
|
-
def index; end
|
210
|
-
end
|
211
|
-
|
212
|
-
setup do
|
213
|
-
Time.stubs(:current).returns('Sat, 20 Apr 2013 20:58:55 UTC +00:00')
|
214
|
-
|
215
|
-
@exception = ZeroDivisionError.new('divided by 0')
|
216
|
-
@exception.set_backtrace(['test/exception_notifier/email_notifier_test.rb:20'])
|
217
|
-
|
218
|
-
@email_notifier = ExceptionNotifier::EmailNotifier.new(
|
219
|
-
email_prefix: '[Dummy ERROR] ',
|
220
|
-
sender_address: %("Dummy Notifier" <dummynotifier@example.com>),
|
221
|
-
exception_recipients: %w[dummyexceptions@example.com],
|
222
|
-
email_headers: { 'X-Custom-Header' => 'foobar' },
|
223
|
-
sections: %w[new_section request session environment backtrace],
|
224
|
-
background_sections: %w[new_bkg_section backtrace data],
|
225
|
-
pre_callback:
|
226
|
-
proc { |_opts, _notifier, _backtrace, _message, message_opts| message_opts[:pre_callback_called] = 1 },
|
227
|
-
post_callback:
|
228
|
-
proc { |_opts, _notifier, _backtrace, _message, message_opts| message_opts[:post_callback_called] = 1 }
|
229
|
-
)
|
230
|
-
|
231
|
-
@controller = HomeController.new
|
232
|
-
@controller.process(:index)
|
233
|
-
|
234
|
-
@test_env = Rack::MockRequest.env_for(
|
235
|
-
'/',
|
236
|
-
'HTTP_HOST' => 'test.address',
|
237
|
-
'REMOTE_ADDR' => '127.0.0.1',
|
238
|
-
'HTTP_USER_AGENT' => 'Rails Testing',
|
239
|
-
'action_dispatch.parameter_filter' => ['secret'],
|
240
|
-
'HTTPS' => 'on',
|
241
|
-
'action_controller.instance' => @controller,
|
242
|
-
'rack.session.options' => {},
|
243
|
-
params: { id: 'foo', secret: 'secret' }
|
244
|
-
)
|
245
|
-
|
246
|
-
@mail = @email_notifier.call(@exception, env: @test_env, data: { message: 'My Custom Message' })
|
247
|
-
end
|
248
|
-
|
249
|
-
test 'sends mail with correct content' do
|
250
|
-
assert_equal %("Dummy Notifier" <dummynotifier@example.com>), @mail[:from].value
|
251
|
-
assert_equal %w[dummyexceptions@example.com], @mail.to
|
252
|
-
assert_equal '[Dummy ERROR] home#index (ZeroDivisionError) "divided by 0"', @mail.subject
|
253
|
-
assert_equal 'foobar', @mail['X-Custom-Header'].value
|
254
|
-
assert_equal 'text/plain; charset=UTF-8', @mail.content_type
|
255
|
-
assert_equal [], @mail.attachments
|
256
|
-
|
257
|
-
body = <<-BODY.gsub(/^ /, '')
|
258
|
-
A ZeroDivisionError occurred in home#index:
|
259
|
-
|
260
|
-
divided by 0
|
261
|
-
test/exception_notifier/email_notifier_test.rb:20
|
262
|
-
|
263
|
-
|
264
|
-
-------------------------------
|
265
|
-
New section:
|
266
|
-
-------------------------------
|
267
|
-
|
268
|
-
* New text section for testing
|
269
|
-
|
270
|
-
-------------------------------
|
271
|
-
Request:
|
272
|
-
-------------------------------
|
273
|
-
|
274
|
-
* URL : https://test.address/?id=foo&secret=secret
|
275
|
-
* HTTP Method: GET
|
276
|
-
* IP address : 127.0.0.1
|
277
|
-
* Parameters : {\"id\"=>\"foo\", \"secret\"=>\"[FILTERED]\"}
|
278
|
-
* Timestamp : Sat, 20 Apr 2013 20:58:55 UTC +00:00
|
279
|
-
* Server : #{Socket.gethostname}
|
280
|
-
BODY
|
281
|
-
|
282
|
-
body << " * Rails root : #{Rails.root}\n" if defined?(Rails) && Rails.respond_to?(:root)
|
283
|
-
|
284
|
-
body << <<-BODY.gsub(/^ /, '')
|
285
|
-
* Process: #{Process.pid}
|
286
|
-
|
287
|
-
-------------------------------
|
288
|
-
Session:
|
289
|
-
-------------------------------
|
290
|
-
|
291
|
-
* session id: [FILTERED]
|
292
|
-
* data: {}
|
293
|
-
|
294
|
-
-------------------------------
|
295
|
-
Environment:
|
296
|
-
-------------------------------
|
297
|
-
|
298
|
-
* HTTPS : on
|
299
|
-
* HTTP_HOST : test.address
|
300
|
-
* HTTP_USER_AGENT : Rails Testing
|
301
|
-
* PATH_INFO : /
|
302
|
-
* QUERY_STRING : id=foo&secret=secret
|
303
|
-
* REMOTE_ADDR : 127.0.0.1
|
304
|
-
* REQUEST_METHOD : GET
|
305
|
-
* SCRIPT_NAME :
|
306
|
-
* SERVER_NAME : example.org
|
307
|
-
* SERVER_PORT : 80
|
308
|
-
* SERVER_PROTOCOL : HTTP/1.1
|
309
|
-
* action_controller.instance : #{@controller}
|
310
|
-
* action_dispatch.parameter_filter : [\"secret\"]
|
311
|
-
* action_dispatch.request.parameters : {"id"=>"foo", "secret"=>"[FILTERED]"}
|
312
|
-
* action_dispatch.request.path_parameters : {}
|
313
|
-
* action_dispatch.request.query_parameters : {"id"=>"foo", "secret"=>"[FILTERED]"}
|
314
|
-
* action_dispatch.request.request_parameters: {}
|
315
|
-
* rack.errors : #{@test_env['rack.errors']}
|
316
|
-
* rack.request.form_hash : {}
|
317
|
-
* rack.request.form_input :
|
318
|
-
* rack.session : #{@test_env['rack.session']}
|
319
|
-
* rack.session.options : #{@test_env['rack.session.options']}
|
320
|
-
* rack.url_scheme : http
|
321
|
-
|
322
|
-
-------------------------------
|
323
|
-
Backtrace:
|
324
|
-
-------------------------------
|
325
|
-
|
326
|
-
test/exception_notifier/email_notifier_test.rb:20
|
327
|
-
|
328
|
-
-------------------------------
|
329
|
-
Data:
|
330
|
-
-------------------------------
|
331
|
-
|
332
|
-
* data: {:message=>\"My Custom Message\"}
|
333
|
-
|
334
|
-
|
335
|
-
BODY
|
336
|
-
|
337
|
-
assert_equal body, @mail.decode_body
|
338
|
-
end
|
339
|
-
|
340
|
-
test 'should not include controller and action names in subject' do
|
341
|
-
email_notifier = ExceptionNotifier::EmailNotifier.new(
|
342
|
-
sender_address: %("Dummy Notifier" <dummynotifier@example.com>),
|
343
|
-
exception_recipients: %w[dummyexceptions@example.com],
|
344
|
-
include_controller_and_action_names_in_subject: false
|
345
|
-
)
|
346
|
-
|
347
|
-
mail = email_notifier.call(@exception, env: @test_env)
|
348
|
-
|
349
|
-
assert_equal '[ERROR] (ZeroDivisionError) "divided by 0"', mail.subject
|
350
|
-
end
|
351
|
-
end
|