exception_notification_more_info 1.0.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 (118) hide show
  1. checksums.yaml +7 -0
  2. data/Appraisals +7 -0
  3. data/CHANGELOG.rdoc +141 -0
  4. data/CODE_OF_CONDUCT.md +22 -0
  5. data/CONTRIBUTING.md +42 -0
  6. data/Gemfile +3 -0
  7. data/MIT-LICENSE +20 -0
  8. data/README.md +839 -0
  9. data/Rakefile +23 -0
  10. data/examples/sinatra/Gemfile +8 -0
  11. data/examples/sinatra/Gemfile.lock +95 -0
  12. data/examples/sinatra/Procfile +2 -0
  13. data/examples/sinatra/README.md +11 -0
  14. data/examples/sinatra/config.ru +3 -0
  15. data/examples/sinatra/sinatra_app.rb +32 -0
  16. data/exception_notification_more_info.gemspec +34 -0
  17. data/gemfiles/rails4_0.gemfile +7 -0
  18. data/gemfiles/rails4_1.gemfile +7 -0
  19. data/gemfiles/rails4_2.gemfile +7 -0
  20. data/lib/exception_notification.rb +11 -0
  21. data/lib/exception_notification/rack.rb +59 -0
  22. data/lib/exception_notification/rails.rb +8 -0
  23. data/lib/exception_notification/resque.rb +24 -0
  24. data/lib/exception_notification/sidekiq.rb +31 -0
  25. data/lib/exception_notifier.rb +121 -0
  26. data/lib/exception_notifier/base_notifier.rb +25 -0
  27. data/lib/exception_notifier/campfire_notifier.rb +36 -0
  28. data/lib/exception_notifier/email_notifier.rb +204 -0
  29. data/lib/exception_notifier/hipchat_notifier.rb +45 -0
  30. data/lib/exception_notifier/irc_notifier.rb +51 -0
  31. data/lib/exception_notifier/modules/backtrace_cleaner.rb +13 -0
  32. data/lib/exception_notifier/notifier.rb +16 -0
  33. data/lib/exception_notifier/slack_notifier.rb +73 -0
  34. data/lib/exception_notifier/views/exception_notifier/_backtrace.html.erb +3 -0
  35. data/lib/exception_notifier/views/exception_notifier/_backtrace.text.erb +1 -0
  36. data/lib/exception_notifier/views/exception_notifier/_data.html.erb +6 -0
  37. data/lib/exception_notifier/views/exception_notifier/_data.text.erb +1 -0
  38. data/lib/exception_notifier/views/exception_notifier/_environment.html.erb +10 -0
  39. data/lib/exception_notifier/views/exception_notifier/_environment.text.erb +5 -0
  40. data/lib/exception_notifier/views/exception_notifier/_request.html.erb +36 -0
  41. data/lib/exception_notifier/views/exception_notifier/_request.text.erb +10 -0
  42. data/lib/exception_notifier/views/exception_notifier/_session.html.erb +10 -0
  43. data/lib/exception_notifier/views/exception_notifier/_session.text.erb +2 -0
  44. data/lib/exception_notifier/views/exception_notifier/_title.html.erb +3 -0
  45. data/lib/exception_notifier/views/exception_notifier/_title.text.erb +3 -0
  46. data/lib/exception_notifier/views/exception_notifier/background_exception_notification.html.erb +53 -0
  47. data/lib/exception_notifier/views/exception_notifier/background_exception_notification.text.erb +14 -0
  48. data/lib/exception_notifier/views/exception_notifier/exception_notification.html.erb +54 -0
  49. data/lib/exception_notifier/views/exception_notifier/exception_notification.text.erb +24 -0
  50. data/lib/exception_notifier/webhook_notifier.rb +47 -0
  51. data/lib/generators/exception_notification/install_generator.rb +15 -0
  52. data/lib/generators/exception_notification/templates/exception_notification.rb +53 -0
  53. data/test/dummy/.gitignore +4 -0
  54. data/test/dummy/Gemfile +34 -0
  55. data/test/dummy/Gemfile.lock +137 -0
  56. data/test/dummy/Rakefile +7 -0
  57. data/test/dummy/app/controllers/application_controller.rb +3 -0
  58. data/test/dummy/app/controllers/posts_controller.rb +30 -0
  59. data/test/dummy/app/helpers/application_helper.rb +2 -0
  60. data/test/dummy/app/helpers/posts_helper.rb +2 -0
  61. data/test/dummy/app/models/post.rb +2 -0
  62. data/test/dummy/app/views/exception_notifier/_new_bkg_section.html.erb +1 -0
  63. data/test/dummy/app/views/exception_notifier/_new_bkg_section.text.erb +1 -0
  64. data/test/dummy/app/views/exception_notifier/_new_section.html.erb +1 -0
  65. data/test/dummy/app/views/exception_notifier/_new_section.text.erb +1 -0
  66. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  67. data/test/dummy/app/views/posts/_form.html.erb +0 -0
  68. data/test/dummy/app/views/posts/new.html.erb +0 -0
  69. data/test/dummy/app/views/posts/show.html.erb +0 -0
  70. data/test/dummy/config.ru +4 -0
  71. data/test/dummy/config/application.rb +42 -0
  72. data/test/dummy/config/boot.rb +6 -0
  73. data/test/dummy/config/database.yml +22 -0
  74. data/test/dummy/config/environment.rb +17 -0
  75. data/test/dummy/config/environments/development.rb +25 -0
  76. data/test/dummy/config/environments/production.rb +50 -0
  77. data/test/dummy/config/environments/test.rb +38 -0
  78. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  79. data/test/dummy/config/initializers/inflections.rb +10 -0
  80. data/test/dummy/config/initializers/mime_types.rb +5 -0
  81. data/test/dummy/config/initializers/secret_token.rb +8 -0
  82. data/test/dummy/config/initializers/session_store.rb +8 -0
  83. data/test/dummy/config/locales/en.yml +5 -0
  84. data/test/dummy/config/routes.rb +3 -0
  85. data/test/dummy/db/migrate/20110729022608_create_posts.rb +15 -0
  86. data/test/dummy/db/schema.rb +24 -0
  87. data/test/dummy/db/seeds.rb +7 -0
  88. data/test/dummy/lib/tasks/.gitkeep +0 -0
  89. data/test/dummy/public/404.html +26 -0
  90. data/test/dummy/public/422.html +26 -0
  91. data/test/dummy/public/500.html +26 -0
  92. data/test/dummy/public/favicon.ico +0 -0
  93. data/test/dummy/public/images/rails.png +0 -0
  94. data/test/dummy/public/index.html +239 -0
  95. data/test/dummy/public/javascripts/application.js +2 -0
  96. data/test/dummy/public/javascripts/controls.js +965 -0
  97. data/test/dummy/public/javascripts/dragdrop.js +974 -0
  98. data/test/dummy/public/javascripts/effects.js +1123 -0
  99. data/test/dummy/public/javascripts/prototype.js +6001 -0
  100. data/test/dummy/public/javascripts/rails.js +191 -0
  101. data/test/dummy/public/robots.txt +5 -0
  102. data/test/dummy/public/stylesheets/.gitkeep +0 -0
  103. data/test/dummy/public/stylesheets/scaffold.css +56 -0
  104. data/test/dummy/script/rails +6 -0
  105. data/test/dummy/test/fixtures/posts.yml +11 -0
  106. data/test/dummy/test/functional/posts_controller_test.rb +224 -0
  107. data/test/dummy/test/test_helper.rb +13 -0
  108. data/test/exception_notification/rack_test.rb +20 -0
  109. data/test/exception_notifier/campfire_notifier_test.rb +100 -0
  110. data/test/exception_notifier/email_notifier_test.rb +185 -0
  111. data/test/exception_notifier/hipchat_notifier_test.rb +177 -0
  112. data/test/exception_notifier/irc_notifier_test.rb +121 -0
  113. data/test/exception_notifier/sidekiq_test.rb +27 -0
  114. data/test/exception_notifier/slack_notifier_test.rb +179 -0
  115. data/test/exception_notifier/webhook_notifier_test.rb +68 -0
  116. data/test/exception_notifier_test.rb +103 -0
  117. data/test/test_helper.rb +18 -0
  118. metadata +428 -0
@@ -0,0 +1,191 @@
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
+ })();
@@ -0,0 +1,5 @@
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
@@ -0,0 +1,56 @@
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
+ }
@@ -0,0 +1,6 @@
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'
@@ -0,0 +1,11 @@
1
+ # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2
+
3
+ one:
4
+ title: MyString
5
+ body: MyText
6
+ secret: MySecret
7
+
8
+ two:
9
+ title: MyString
10
+ body: MyText
11
+ secret: MySecret
@@ -0,0 +1,224 @@
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 = posts(:one)
9
+ post :create, :post => @post.attributes
10
+ rescue => e
11
+ @exception = e
12
+ @mail = @email_notifier.create_email(@exception, {:env => request.env, :data => {:message => 'My Custom Message'}})
13
+ end
14
+ end
15
+
16
+ test "should have raised an exception" do
17
+ refute_nil @exception
18
+ end
19
+
20
+ test "should have generated a notification email" do
21
+ refute_nil @mail
22
+ end
23
+
24
+ test "mail should be plain text and UTF-8 enconded by default" do
25
+ assert_equal @mail.content_type, "text/plain; charset=UTF-8"
26
+ end
27
+
28
+ test "mail should have a from address set" do
29
+ assert_equal @mail.from, ["dummynotifier@example.com"]
30
+ end
31
+
32
+ test "mail should have a to address set" do
33
+ assert_equal @mail.to, ["dummyexceptions@example.com"]
34
+ end
35
+
36
+ test "mail subject should have the proper prefix" do
37
+ assert_includes @mail.subject, "[Dummy ERROR]"
38
+ end
39
+
40
+ test "mail subject should include descriptive error message" do
41
+ assert_includes @mail.subject, "(NoMethodError) \"undefined method `nw'"
42
+ end
43
+
44
+ test "mail should contain backtrace in body" do
45
+ assert_includes @mail.encoded, "`method_missing'\r\n app/controllers/posts_controller.rb:18:in `create'\r\n"
46
+ end
47
+
48
+ test "mail should contain timestamp of exception in body" do
49
+ assert_includes @mail.encoded, "Timestamp : #{Time.current}"
50
+ end
51
+
52
+ test "mail should contain the newly defined section" do
53
+ assert_includes @mail.encoded, "* New text section for testing"
54
+ end
55
+
56
+ test "mail should contain the custom message" do
57
+ assert_includes @mail.encoded, "My Custom Message"
58
+ end
59
+
60
+ test "should filter sensible data" do
61
+ assert_includes @mail.encoded, "secret\"=>\"[FILTERED]"
62
+ end
63
+
64
+ test "mail should contain the custom header" do
65
+ assert_includes @mail.encoded, 'X-Custom-Header: foobar'
66
+ end
67
+
68
+ test "mail should not contain any attachments" do
69
+ assert_equal @mail.attachments, []
70
+ end
71
+
72
+ test "should not send notification if one of ignored exceptions" do
73
+ begin
74
+ get :show, :id => @post.to_param + "10"
75
+ rescue => e
76
+ @ignored_exception = e
77
+ unless ExceptionNotifier.ignored_exceptions.include?(@ignored_exception.class.name)
78
+ @ignored_mail = @email_notifier.create_email(@ignored_exception, {:env => request.env})
79
+ end
80
+ end
81
+
82
+ assert_equal @ignored_exception.class.inspect, "ActiveRecord::RecordNotFound"
83
+ assert_nil @ignored_mail
84
+ end
85
+
86
+ test "should filter session_id on secure requests" do
87
+ request.env['HTTPS'] = 'on'
88
+ begin
89
+ @post = posts(:one)
90
+ post :create, :post => @post.attributes
91
+ rescue => e
92
+ @secured_mail = @email_notifier.create_email(e, {:env => request.env})
93
+ end
94
+
95
+ assert request.ssl?
96
+ assert_includes @secured_mail.encoded, "* session id: [FILTERED]\r\n *"
97
+ end
98
+
99
+ test "should ignore exception if from unwanted crawler" do
100
+ request.env['HTTP_USER_AGENT'] = "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
101
+ begin
102
+ @post = posts(:one)
103
+ post :create, :post => @post.attributes
104
+ rescue => e
105
+ @exception = e
106
+ custom_env = request.env
107
+ custom_env['exception_notifier.options'] ||= {}
108
+ custom_env['exception_notifier.options'].merge!(:ignore_crawlers => %w(Googlebot))
109
+ ignore_array = custom_env['exception_notifier.options'][:ignore_crawlers]
110
+ unless ExceptionNotification::Rack.new(Dummy::Application, custom_env['exception_notifier.options']).send(:from_crawler, custom_env, ignore_array)
111
+ @ignored_mail = @email_notifier.create_email(@exception, {:env => custom_env})
112
+ end
113
+ end
114
+
115
+ assert_nil @ignored_mail
116
+ end
117
+
118
+ test "should send html email when selected html format" do
119
+ begin
120
+ @post = posts(:one)
121
+ post :create, :post => @post.attributes
122
+ rescue => e
123
+ @exception = e
124
+ custom_env = request.env
125
+ custom_env['exception_notifier.options'] ||= {}
126
+ custom_env['exception_notifier.options'].merge!({:email_format => :html})
127
+ @mail = @email_notifier.create_email(@exception, {:env => custom_env})
128
+ end
129
+
130
+ assert_includes @mail.content_type, "multipart/alternative"
131
+ end
132
+ end
133
+
134
+ class PostsControllerTestWithoutVerboseSubject < ActionController::TestCase
135
+ tests PostsController
136
+ setup do
137
+ @email_notifier = ExceptionNotifier::EmailNotifier.new(:verbose_subject => false)
138
+ begin
139
+ @post = posts(:one)
140
+ post :create, :post => @post.attributes
141
+ rescue => e
142
+ @exception = e
143
+ @mail = @email_notifier.create_email(@exception, {:env => request.env})
144
+ end
145
+ end
146
+
147
+ test "should not include exception message in subject" do
148
+ assert_equal "[ERROR] # (NoMethodError)", @mail.subject
149
+ end
150
+ end
151
+
152
+ class PostsControllerTestWithSmtpSettings < ActionController::TestCase
153
+ tests PostsController
154
+ setup do
155
+ @email_notifier = ExceptionNotifier::EmailNotifier.new(:smtp_settings => {
156
+ :user_name => "Dummy user_name",
157
+ :password => "Dummy password"
158
+ })
159
+
160
+ begin
161
+ @post = posts(:one)
162
+ post :create, :post => @post.attributes
163
+ rescue => e
164
+ @exception = e
165
+ @mail = @email_notifier.create_email(@exception, {:env => request.env})
166
+ end
167
+ end
168
+
169
+ test "should have overridden smtp settings" do
170
+ assert_equal "Dummy user_name", @mail.delivery_method.settings[:user_name]
171
+ assert_equal "Dummy password", @mail.delivery_method.settings[:password]
172
+ end
173
+
174
+ test "should have overridden smtp settings with background notification" do
175
+ @mail = @email_notifier.create_email(@exception)
176
+ assert_equal "Dummy user_name", @mail.delivery_method.settings[:user_name]
177
+ assert_equal "Dummy password", @mail.delivery_method.settings[:password]
178
+ end
179
+ end
180
+
181
+ class PostsControllerTestBadRequestData < ActionController::TestCase
182
+ tests PostsController
183
+ setup do
184
+ @email_notifier = ExceptionNotifier.registered_exception_notifier(:email)
185
+ begin
186
+ # This might seem synthetic, but the point is that the data used by
187
+ # ExceptionNotification could be rendered "invalid" by e.g. a badly
188
+ # behaving middleware, and we want to test that ExceptionNotification
189
+ # still manages to send off an email in those cases.
190
+ #
191
+ # The trick here is to trigger an exception in the template used by
192
+ # ExceptionNotification. (The original test stuffed request.env with
193
+ # badly encoded strings, but that only works in Ruby 1.9+.)
194
+ request.send :instance_variable_set, :@env, {}
195
+
196
+ @post = posts(:one)
197
+ post :create, :post => @post.attributes
198
+ rescue => e
199
+ @exception = e
200
+ @mail = @email_notifier.create_email(@exception, {:env => request.env})
201
+ end
202
+ end
203
+
204
+ test "should include error message in body" do
205
+ assert_match /ERROR: Failed to generate exception summary/, @mail.encoded.to_s
206
+ end
207
+ end
208
+
209
+ class PostsControllerTestBackgroundNotification < ActionController::TestCase
210
+ tests PostsController
211
+ setup do
212
+ @email_notifier = ExceptionNotifier.registered_exception_notifier(:email)
213
+ begin
214
+ @post = posts(:one)
215
+ post :create, :post => @post.attributes
216
+ rescue => exception
217
+ @mail = @email_notifier.create_email(exception)
218
+ end
219
+ end
220
+
221
+ test "mail should contain the specified section" do
222
+ assert_includes @mail.encoded, "* New background section for testing"
223
+ end
224
+ end