exception_notification 4.2.0 → 4.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. checksums.yaml +5 -5
  2. data/Appraisals +4 -3
  3. data/CHANGELOG.rdoc +57 -1
  4. data/CONTRIBUTING.md +21 -2
  5. data/Gemfile +3 -1
  6. data/README.md +106 -789
  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 -23
  25. data/gemfiles/rails4_0.gemfile +1 -2
  26. data/gemfiles/rails4_1.gemfile +1 -2
  27. data/gemfiles/rails4_2.gemfile +1 -2
  28. data/gemfiles/rails5_0.gemfile +1 -2
  29. data/gemfiles/rails5_1.gemfile +7 -0
  30. data/gemfiles/rails5_2.gemfile +7 -0
  31. data/gemfiles/rails6_0.gemfile +7 -0
  32. data/lib/exception_notification.rb +3 -0
  33. data/lib/exception_notification/rack.rb +34 -27
  34. data/lib/exception_notification/rails.rb +3 -0
  35. data/lib/exception_notification/resque.rb +10 -10
  36. data/lib/exception_notification/sidekiq.rb +10 -12
  37. data/lib/exception_notification/version.rb +5 -0
  38. data/lib/exception_notifier.rb +79 -11
  39. data/lib/exception_notifier/base_notifier.rb +10 -5
  40. data/lib/exception_notifier/campfire_notifier.rb +14 -9
  41. data/lib/exception_notifier/datadog_notifier.rb +156 -0
  42. data/lib/exception_notifier/email_notifier.rb +78 -87
  43. data/lib/exception_notifier/google_chat_notifier.rb +44 -0
  44. data/lib/exception_notifier/hipchat_notifier.rb +16 -10
  45. data/lib/exception_notifier/irc_notifier.rb +38 -31
  46. data/lib/exception_notifier/mattermost_notifier.rb +54 -131
  47. data/lib/exception_notifier/modules/backtrace_cleaner.rb +2 -2
  48. data/lib/exception_notifier/modules/error_grouping.rb +87 -0
  49. data/lib/exception_notifier/modules/formatter.rb +121 -0
  50. data/lib/exception_notifier/notifier.rb +9 -6
  51. data/lib/exception_notifier/slack_notifier.rb +75 -32
  52. data/lib/exception_notifier/sns_notifier.rb +86 -0
  53. data/lib/exception_notifier/teams_notifier.rb +200 -0
  54. data/lib/exception_notifier/views/exception_notifier/_backtrace.html.erb +1 -1
  55. data/lib/exception_notifier/views/exception_notifier/_environment.text.erb +1 -1
  56. data/lib/exception_notifier/views/exception_notifier/_request.text.erb +1 -1
  57. data/lib/exception_notifier/views/exception_notifier/background_exception_notification.text.erb +9 -9
  58. data/lib/exception_notifier/views/exception_notifier/exception_notification.html.erb +2 -4
  59. data/lib/exception_notifier/views/exception_notifier/exception_notification.text.erb +2 -2
  60. data/lib/exception_notifier/webhook_notifier.rb +19 -16
  61. data/lib/generators/exception_notification/install_generator.rb +11 -5
  62. data/lib/generators/exception_notification/templates/{exception_notification.rb → exception_notification.rb.erb} +14 -12
  63. data/test/exception_notification/rack_test.rb +90 -4
  64. data/test/exception_notification/resque_test.rb +54 -0
  65. data/test/exception_notifier/campfire_notifier_test.rb +66 -39
  66. data/test/exception_notifier/datadog_notifier_test.rb +153 -0
  67. data/test/exception_notifier/email_notifier_test.rb +301 -145
  68. data/test/exception_notifier/google_chat_notifier_test.rb +185 -0
  69. data/test/exception_notifier/hipchat_notifier_test.rb +112 -65
  70. data/test/exception_notifier/irc_notifier_test.rb +48 -30
  71. data/test/exception_notifier/mattermost_notifier_test.rb +218 -55
  72. data/test/exception_notifier/modules/error_grouping_test.rb +167 -0
  73. data/test/exception_notifier/modules/formatter_test.rb +152 -0
  74. data/test/exception_notifier/sidekiq_test.rb +9 -6
  75. data/test/exception_notifier/slack_notifier_test.rb +109 -59
  76. data/test/exception_notifier/sns_notifier_test.rb +123 -0
  77. data/test/exception_notifier/teams_notifier_test.rb +92 -0
  78. data/test/exception_notifier/webhook_notifier_test.rb +68 -38
  79. data/test/exception_notifier_test.rb +220 -37
  80. data/test/support/exception_notifier_helper.rb +14 -0
  81. data/test/{dummy/app → support}/views/exception_notifier/_new_bkg_section.html.erb +0 -0
  82. data/test/{dummy/app → support}/views/exception_notifier/_new_bkg_section.text.erb +0 -0
  83. data/test/{dummy/app → support}/views/exception_notifier/_new_section.html.erb +0 -0
  84. data/test/{dummy/app → support}/views/exception_notifier/_new_section.text.erb +0 -0
  85. data/test/test_helper.rb +14 -13
  86. metadata +154 -162
  87. data/test/dummy/.gitignore +0 -4
  88. data/test/dummy/Rakefile +0 -7
  89. data/test/dummy/app/controllers/application_controller.rb +0 -3
  90. data/test/dummy/app/controllers/posts_controller.rb +0 -30
  91. data/test/dummy/app/helpers/application_helper.rb +0 -2
  92. data/test/dummy/app/helpers/posts_helper.rb +0 -2
  93. data/test/dummy/app/models/post.rb +0 -2
  94. data/test/dummy/app/views/layouts/application.html.erb +0 -14
  95. data/test/dummy/app/views/posts/_form.html.erb +0 -0
  96. data/test/dummy/app/views/posts/new.html.erb +0 -0
  97. data/test/dummy/app/views/posts/show.html.erb +0 -0
  98. data/test/dummy/config.ru +0 -4
  99. data/test/dummy/config/application.rb +0 -42
  100. data/test/dummy/config/boot.rb +0 -6
  101. data/test/dummy/config/database.yml +0 -22
  102. data/test/dummy/config/environment.rb +0 -17
  103. data/test/dummy/config/environments/development.rb +0 -25
  104. data/test/dummy/config/environments/production.rb +0 -50
  105. data/test/dummy/config/environments/test.rb +0 -38
  106. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  107. data/test/dummy/config/initializers/inflections.rb +0 -10
  108. data/test/dummy/config/initializers/mime_types.rb +0 -5
  109. data/test/dummy/config/initializers/secret_token.rb +0 -8
  110. data/test/dummy/config/initializers/session_store.rb +0 -8
  111. data/test/dummy/config/locales/en.yml +0 -5
  112. data/test/dummy/config/routes.rb +0 -3
  113. data/test/dummy/db/migrate/20110729022608_create_posts.rb +0 -15
  114. data/test/dummy/db/schema.rb +0 -24
  115. data/test/dummy/db/seeds.rb +0 -7
  116. data/test/dummy/lib/tasks/.gitkeep +0 -0
  117. data/test/dummy/public/404.html +0 -26
  118. data/test/dummy/public/422.html +0 -26
  119. data/test/dummy/public/500.html +0 -26
  120. data/test/dummy/public/favicon.ico +0 -0
  121. data/test/dummy/public/images/rails.png +0 -0
  122. data/test/dummy/public/index.html +0 -239
  123. data/test/dummy/public/javascripts/application.js +0 -2
  124. data/test/dummy/public/javascripts/controls.js +0 -965
  125. data/test/dummy/public/javascripts/dragdrop.js +0 -974
  126. data/test/dummy/public/javascripts/effects.js +0 -1123
  127. data/test/dummy/public/javascripts/prototype.js +0 -6001
  128. data/test/dummy/public/javascripts/rails.js +0 -191
  129. data/test/dummy/public/robots.txt +0 -5
  130. data/test/dummy/public/stylesheets/.gitkeep +0 -0
  131. data/test/dummy/public/stylesheets/scaffold.css +0 -56
  132. data/test/dummy/script/rails +0 -6
  133. data/test/dummy/test/functional/posts_controller_test.rb +0 -218
  134. data/test/dummy/test/test_helper.rb +0 -7
@@ -1,191 +0,0 @@
1
- (function() {
2
- // Technique from Juriy Zaytsev
3
- // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
4
- function isEventSupported(eventName) {
5
- var el = document.createElement('div');
6
- eventName = 'on' + eventName;
7
- var isSupported = (eventName in el);
8
- if (!isSupported) {
9
- el.setAttribute(eventName, 'return;');
10
- isSupported = typeof el[eventName] == 'function';
11
- }
12
- el = null;
13
- return isSupported;
14
- }
15
-
16
- function isForm(element) {
17
- return Object.isElement(element) && element.nodeName.toUpperCase() == 'FORM'
18
- }
19
-
20
- function isInput(element) {
21
- if (Object.isElement(element)) {
22
- var name = element.nodeName.toUpperCase()
23
- return name == 'INPUT' || name == 'SELECT' || name == 'TEXTAREA'
24
- }
25
- else return false
26
- }
27
-
28
- var submitBubbles = isEventSupported('submit'),
29
- changeBubbles = isEventSupported('change')
30
-
31
- if (!submitBubbles || !changeBubbles) {
32
- // augment the Event.Handler class to observe custom events when needed
33
- Event.Handler.prototype.initialize = Event.Handler.prototype.initialize.wrap(
34
- function(init, element, eventName, selector, callback) {
35
- init(element, eventName, selector, callback)
36
- // is the handler being attached to an element that doesn't support this event?
37
- if ( (!submitBubbles && this.eventName == 'submit' && !isForm(this.element)) ||
38
- (!changeBubbles && this.eventName == 'change' && !isInput(this.element)) ) {
39
- // "submit" => "emulated:submit"
40
- this.eventName = 'emulated:' + this.eventName
41
- }
42
- }
43
- )
44
- }
45
-
46
- if (!submitBubbles) {
47
- // discover forms on the page by observing focus events which always bubble
48
- document.on('focusin', 'form', function(focusEvent, form) {
49
- // special handler for the real "submit" event (one-time operation)
50
- if (!form.retrieve('emulated:submit')) {
51
- form.on('submit', function(submitEvent) {
52
- var emulated = form.fire('emulated:submit', submitEvent, true)
53
- // if custom event received preventDefault, cancel the real one too
54
- if (emulated.returnValue === false) submitEvent.preventDefault()
55
- })
56
- form.store('emulated:submit', true)
57
- }
58
- })
59
- }
60
-
61
- if (!changeBubbles) {
62
- // discover form inputs on the page
63
- document.on('focusin', 'input, select, texarea', function(focusEvent, input) {
64
- // special handler for real "change" events
65
- if (!input.retrieve('emulated:change')) {
66
- input.on('change', function(changeEvent) {
67
- input.fire('emulated:change', changeEvent, true)
68
- })
69
- input.store('emulated:change', true)
70
- }
71
- })
72
- }
73
-
74
- function handleRemote(element) {
75
- var method, url, params;
76
-
77
- var event = element.fire("ajax:before");
78
- if (event.stopped) return false;
79
-
80
- if (element.tagName.toLowerCase() === 'form') {
81
- method = element.readAttribute('method') || 'post';
82
- url = element.readAttribute('action');
83
- params = element.serialize();
84
- } else {
85
- method = element.readAttribute('data-method') || 'get';
86
- url = element.readAttribute('href');
87
- params = {};
88
- }
89
-
90
- new Ajax.Request(url, {
91
- method: method,
92
- parameters: params,
93
- evalScripts: true,
94
-
95
- onComplete: function(request) { element.fire("ajax:complete", request); },
96
- onSuccess: function(request) { element.fire("ajax:success", request); },
97
- onFailure: function(request) { element.fire("ajax:failure", request); }
98
- });
99
-
100
- element.fire("ajax:after");
101
- }
102
-
103
- function handleMethod(element) {
104
- var method = element.readAttribute('data-method'),
105
- url = element.readAttribute('href'),
106
- csrf_param = $$('meta[name=csrf-param]')[0],
107
- csrf_token = $$('meta[name=csrf-token]')[0];
108
-
109
- var form = new Element('form', { method: "POST", action: url, style: "display: none;" });
110
- element.parentNode.insert(form);
111
-
112
- if (method !== 'post') {
113
- var field = new Element('input', { type: 'hidden', name: '_method', value: method });
114
- form.insert(field);
115
- }
116
-
117
- if (csrf_param) {
118
- var param = csrf_param.readAttribute('content'),
119
- token = csrf_token.readAttribute('content'),
120
- field = new Element('input', { type: 'hidden', name: param, value: token });
121
- form.insert(field);
122
- }
123
-
124
- form.submit();
125
- }
126
-
127
-
128
- document.on("click", "*[data-confirm]", function(event, element) {
129
- var message = element.readAttribute('data-confirm');
130
- if (!confirm(message)) event.stop();
131
- });
132
-
133
- document.on("click", "a[data-remote]", function(event, element) {
134
- if (event.stopped) return;
135
- handleRemote(element);
136
- event.stop();
137
- });
138
-
139
- document.on("click", "a[data-method]", function(event, element) {
140
- if (event.stopped) return;
141
- handleMethod(element);
142
- event.stop();
143
- });
144
-
145
- document.on("submit", function(event) {
146
- var element = event.findElement(),
147
- message = element.readAttribute('data-confirm');
148
- if (message && !confirm(message)) {
149
- event.stop();
150
- return false;
151
- }
152
-
153
- var inputs = element.select("input[type=submit][data-disable-with]");
154
- inputs.each(function(input) {
155
- input.disabled = true;
156
- input.writeAttribute('data-original-value', input.value);
157
- input.value = input.readAttribute('data-disable-with');
158
- });
159
-
160
- var element = event.findElement("form[data-remote]");
161
- if (element) {
162
- handleRemote(element);
163
- event.stop();
164
- }
165
- });
166
-
167
- document.on("ajax:after", "form", function(event, element) {
168
- var inputs = element.select("input[type=submit][disabled=true][data-disable-with]");
169
- inputs.each(function(input) {
170
- input.value = input.readAttribute('data-original-value');
171
- input.removeAttribute('data-original-value');
172
- input.disabled = false;
173
- });
174
- });
175
-
176
- Ajax.Responders.register({
177
- onCreate: function(request) {
178
- var csrf_meta_tag = $$('meta[name=csrf-token]')[0];
179
-
180
- if (csrf_meta_tag) {
181
- var header = 'X-CSRF-Token',
182
- token = csrf_meta_tag.readAttribute('content');
183
-
184
- if (!request.options.requestHeaders) {
185
- request.options.requestHeaders = {};
186
- }
187
- request.options.requestHeaders[header] = token;
188
- }
189
- }
190
- });
191
- })();
@@ -1,5 +0,0 @@
1
- # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
2
- #
3
- # To ban all spiders from the entire site uncomment the next two lines:
4
- # User-Agent: *
5
- # Disallow: /
File without changes
@@ -1,56 +0,0 @@
1
- body { background-color: #fff; color: #333; }
2
-
3
- body, p, ol, ul, td {
4
- font-family: verdana, arial, helvetica, sans-serif;
5
- font-size: 13px;
6
- line-height: 18px;
7
- }
8
-
9
- pre {
10
- background-color: #eee;
11
- padding: 10px;
12
- font-size: 11px;
13
- }
14
-
15
- a { color: #000; }
16
- a:visited { color: #666; }
17
- a:hover { color: #fff; background-color:#000; }
18
-
19
- div.field, div.actions {
20
- margin-bottom: 10px;
21
- }
22
-
23
- #notice {
24
- color: green;
25
- }
26
-
27
- .field_with_errors {
28
- padding: 2px;
29
- background-color: red;
30
- display: table;
31
- }
32
-
33
- #error_explanation {
34
- width: 450px;
35
- border: 2px solid red;
36
- padding: 7px;
37
- padding-bottom: 0;
38
- margin-bottom: 20px;
39
- background-color: #f0f0f0;
40
- }
41
-
42
- #error_explanation h2 {
43
- text-align: left;
44
- font-weight: bold;
45
- padding: 5px 5px 5px 15px;
46
- font-size: 12px;
47
- margin: -7px;
48
- margin-bottom: 0px;
49
- background-color: #c00;
50
- color: #fff;
51
- }
52
-
53
- #error_explanation ul li {
54
- font-size: 12px;
55
- list-style: square;
56
- }
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
-
4
- APP_PATH = File.expand_path('../../config/application', __FILE__)
5
- require File.expand_path('../../config/boot', __FILE__)
6
- require 'rails/commands'
@@ -1,218 +0,0 @@
1
- require 'test_helper'
2
-
3
- class PostsControllerTest < ActionController::TestCase
4
- setup do
5
- Time.stubs(:current).returns('Sat, 20 Apr 2013 20:58:55 UTC +00:00')
6
- @email_notifier = ExceptionNotifier.registered_exception_notifier(:email)
7
- begin
8
- post :create, method: :post, params: { secret: "secret" }
9
- rescue => e
10
- @exception = e
11
- @mail = @email_notifier.create_email(@exception, {:env => request.env, :data => {:message => 'My Custom Message'}})
12
- end
13
- end
14
-
15
- test "should have raised an exception" do
16
- refute_nil @exception
17
- end
18
-
19
- test "should have generated a notification email" do
20
- refute_nil @mail
21
- end
22
-
23
- test "mail should be plain text and UTF-8 enconded by default" do
24
- assert_equal @mail.content_type, "text/plain; charset=UTF-8"
25
- end
26
-
27
- test "mail should have a from address set" do
28
- assert_equal @mail.from, ["dummynotifier@example.com"]
29
- end
30
-
31
- test "mail should have a to address set" do
32
- assert_equal @mail.to, ["dummyexceptions@example.com"]
33
- end
34
-
35
- test "mail subject should have the proper prefix" do
36
- assert_includes @mail.subject, "[Dummy ERROR]"
37
- end
38
-
39
- test "mail subject should include descriptive error message" do
40
- assert_includes @mail.subject, "(NoMethodError) \"undefined method `nw'"
41
- end
42
-
43
- test "mail should contain backtrace in body" do
44
- assert_includes @mail.encoded, "`method_missing'\r\n app/controllers/posts_controller.rb:18:in `create'\r\n"
45
- end
46
-
47
- test "mail should contain timestamp of exception in body" do
48
- assert_includes @mail.encoded, "Timestamp : #{Time.current}"
49
- end
50
-
51
- test "mail should contain the newly defined section" do
52
- assert_includes @mail.encoded, "* New text section for testing"
53
- end
54
-
55
- test "mail should contain the custom message" do
56
- assert_includes @mail.encoded, "My Custom Message"
57
- end
58
-
59
- test "should filter sensible data" do
60
- assert_includes @mail.encoded, "secret\"=>\"[FILTERED]"
61
- end
62
-
63
- test "mail should contain the custom header" do
64
- assert_includes @mail.encoded, 'X-Custom-Header: foobar'
65
- end
66
-
67
- test "mail should not contain any attachments" do
68
- assert_equal @mail.attachments, []
69
- end
70
-
71
- test "should not send notification if one of ignored exceptions" do
72
- begin
73
- get :invalid
74
- rescue => e
75
- @ignored_exception = e
76
- unless ExceptionNotifier.ignored_exceptions.include?(@ignored_exception.class.name)
77
- ignored_mail = @email_notifier.create_email(@ignored_exception, {:env => request.env})
78
- end
79
- end
80
-
81
- assert_equal @ignored_exception.class.inspect, "ActionController::UrlGenerationError"
82
- assert_nil ignored_mail
83
- end
84
-
85
- test "should filter session_id on secure requests" do
86
- request.env['HTTPS'] = 'on'
87
- begin
88
- post :create, method: :post
89
- rescue => e
90
- @secured_mail = @email_notifier.create_email(e, {:env => request.env})
91
- end
92
-
93
- assert request.ssl?
94
- assert_includes @secured_mail.encoded, "* session id: [FILTERED]\r\n *"
95
- end
96
-
97
- test "should ignore exception if from unwanted crawler" do
98
- request.env['HTTP_USER_AGENT'] = "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
99
- begin
100
- post :create, method: :post
101
- rescue => e
102
- @exception = e
103
- custom_env = request.env
104
- custom_env['exception_notifier.options'] ||= {}
105
- custom_env['exception_notifier.options'].merge!(:ignore_crawlers => %w(Googlebot))
106
- ignore_array = custom_env['exception_notifier.options'][:ignore_crawlers]
107
- unless ExceptionNotification::Rack.new(Dummy::Application, custom_env['exception_notifier.options']).send(:from_crawler, custom_env, ignore_array)
108
- ignored_mail = @email_notifier.create_email(@exception, {:env => custom_env})
109
- end
110
- end
111
-
112
- assert_nil ignored_mail
113
- end
114
-
115
- test "should send html email when selected html format" do
116
- begin
117
- post :create, method: :post
118
- rescue => e
119
- @exception = e
120
- custom_env = request.env
121
- custom_env['exception_notifier.options'] ||= {}
122
- custom_env['exception_notifier.options'].merge!({:email_format => :html})
123
- @mail = @email_notifier.create_email(@exception, {:env => custom_env})
124
- end
125
-
126
- assert_includes @mail.content_type, "multipart/alternative"
127
- end
128
- end
129
-
130
- class PostsControllerTestWithoutVerboseSubject < ActionController::TestCase
131
- tests PostsController
132
- setup do
133
- @email_notifier = ExceptionNotifier::EmailNotifier.new(:verbose_subject => false)
134
- begin
135
- post :create, method: :post
136
- rescue => e
137
- @exception = e
138
- @mail = @email_notifier.create_email(@exception, {:env => request.env})
139
- end
140
- end
141
-
142
- test "should not include exception message in subject" do
143
- assert_includes @mail.subject, '[ERROR]'
144
- assert_includes @mail.subject, '(NoMethodError)'
145
- refute_includes @mail.subject, 'undefined method'
146
- end
147
- end
148
-
149
- class PostsControllerTestWithSmtpSettings < ActionController::TestCase
150
- tests PostsController
151
- setup do
152
- @email_notifier = ExceptionNotifier::EmailNotifier.new(:smtp_settings => {
153
- :user_name => "Dummy user_name",
154
- :password => "Dummy password"
155
- })
156
-
157
- begin
158
- post :create, method: :post
159
- rescue => e
160
- @exception = e
161
- @mail = @email_notifier.create_email(@exception, {:env => request.env})
162
- end
163
- end
164
-
165
- test "should have overridden smtp settings" do
166
- assert_equal "Dummy user_name", @mail.delivery_method.settings[:user_name]
167
- assert_equal "Dummy password", @mail.delivery_method.settings[:password]
168
- end
169
-
170
- test "should have overridden smtp settings with background notification" do
171
- @mail = @email_notifier.create_email(@exception)
172
- assert_equal "Dummy user_name", @mail.delivery_method.settings[:user_name]
173
- assert_equal "Dummy password", @mail.delivery_method.settings[:password]
174
- end
175
- end
176
-
177
- class PostsControllerTestBackgroundNotification < ActionController::TestCase
178
- tests PostsController
179
- setup do
180
- @email_notifier = ExceptionNotifier.registered_exception_notifier(:email)
181
- begin
182
- post :create, method: :post
183
- rescue => exception
184
- @mail = @email_notifier.create_email(exception)
185
- end
186
- end
187
-
188
- test "mail should contain the specified section" do
189
- assert_includes @mail.encoded, "* New background section for testing"
190
- end
191
- end
192
-
193
- class PostsControllerTestWithExceptionRecipientsAsProc < ActionController::TestCase
194
- tests PostsController
195
- setup do
196
- exception_recipients = %w{first@example.com second@example.com}
197
-
198
- @email_notifier = ExceptionNotifier::EmailNotifier.new(
199
- exception_recipients: -> { [ exception_recipients.shift ] }
200
- )
201
-
202
- @action = proc do
203
- begin
204
- post :create, method: :post
205
- rescue => e
206
- @exception = e
207
- @mail = @email_notifier.create_email(@exception, {:env => request.env})
208
- end
209
- end
210
- end
211
-
212
- test "should lazily evaluate exception_recipients" do
213
- @action.call
214
- assert_equal [ "first@example.com" ], @mail.to
215
- @action.call
216
- assert_equal [ "second@example.com" ], @mail.to
217
- end
218
- end