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,13 @@
1
+ ENV["RAILS_ENV"] = "test"
2
+ require File.expand_path('../../config/environment', __FILE__)
3
+ require 'rails/test_help'
4
+
5
+ class ActiveSupport::TestCase
6
+ # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
7
+ #
8
+ # Note: You'll currently still have to declare fixtures explicitly in integration tests
9
+ # -- they do not yet inherit this setting
10
+ fixtures :all
11
+
12
+ # Add more helper methods to be used by all tests here...
13
+ end
@@ -0,0 +1,20 @@
1
+ require 'test_helper'
2
+
3
+ class RackTest < ActiveSupport::TestCase
4
+
5
+ setup do
6
+ @pass_app = Object.new
7
+ @pass_app.stubs(:call).returns([nil, { 'X-Cascade' => 'pass' }, nil])
8
+ end
9
+
10
+ test "should ignore \"X-Cascade\" header by default" do
11
+ ExceptionNotifier.expects(:notify_exception).never
12
+ ExceptionNotification::Rack.new(@pass_app).call({})
13
+ end
14
+
15
+ test "should notify on \"X-Cascade\" = \"pass\" if ignore_cascade_pass option is false" do
16
+ ExceptionNotifier.expects(:notify_exception).once
17
+ ExceptionNotification::Rack.new(@pass_app, :ignore_cascade_pass => false).call({})
18
+ end
19
+
20
+ end
@@ -0,0 +1,100 @@
1
+ require 'test_helper'
2
+ require 'tinder'
3
+
4
+ class CampfireNotifierTest < ActiveSupport::TestCase
5
+
6
+ test "should send campfire notification if properly configured" do
7
+ ExceptionNotifier::CampfireNotifier.stubs(:new).returns(Object.new)
8
+ campfire = ExceptionNotifier::CampfireNotifier.new({:subdomain => 'test', :token => 'test_token', :room_name => 'test_room'})
9
+ campfire.stubs(:call).returns(fake_notification)
10
+ notif = campfire.call(fake_exception)
11
+
12
+ assert !notif[:message].empty?
13
+ assert_equal notif[:message][:type], 'PasteMessage'
14
+ assert_includes notif[:message][:body], "A new exception occurred:"
15
+ assert_includes notif[:message][:body], "divided by 0"
16
+ assert_includes notif[:message][:body], "/exception_notification/test/campfire_test.rb:45"
17
+ end
18
+
19
+ test "should send campfire notification without backtrace info if properly configured" do
20
+ ExceptionNotifier::CampfireNotifier.stubs(:new).returns(Object.new)
21
+ campfire = ExceptionNotifier::CampfireNotifier.new({:subdomain => 'test', :token => 'test_token', :room_name => 'test_room'})
22
+ campfire.stubs(:call).returns(fake_notification_without_backtrace)
23
+ notif = campfire.call(fake_exception_without_backtrace)
24
+
25
+ assert !notif[:message].empty?
26
+ assert_equal notif[:message][:type], 'PasteMessage'
27
+ assert_includes notif[:message][:body], "A new exception occurred:"
28
+ assert_includes notif[:message][:body], "my custom error"
29
+ end
30
+
31
+ test "should not send campfire notification if badly configured" do
32
+ wrong_params = {:subdomain => 'test', :token => 'bad_token', :room_name => 'test_room'}
33
+ Tinder::Campfire.stubs(:new).with('test', {:token => 'bad_token'}).returns(nil)
34
+ campfire = ExceptionNotifier::CampfireNotifier.new(wrong_params)
35
+
36
+ assert_nil campfire.room
37
+ assert_nil campfire.call(fake_exception)
38
+ end
39
+
40
+ test "should not send campfire notification if config attr missing" do
41
+ wrong_params = {:subdomain => 'test', :room_name => 'test_room'}
42
+ Tinder::Campfire.stubs(:new).with('test', {}).returns(nil)
43
+ campfire = ExceptionNotifier::CampfireNotifier.new(wrong_params)
44
+
45
+ assert_nil campfire.room
46
+ assert_nil campfire.call(fake_exception)
47
+ end
48
+
49
+ test "should call pre/post_callback if specified" do
50
+ pre_callback_called, post_callback_called = 0,0
51
+ Tinder::Campfire.stubs(:new).returns(Object.new)
52
+
53
+ campfire = ExceptionNotifier::CampfireNotifier.new(
54
+ {
55
+ :subdomain => 'test',
56
+ :token => 'test_token',
57
+ :room_name => 'test_room',
58
+ :pre_callback => proc { |opts, notifier, backtrace, message, message_opts|
59
+ pre_callback_called += 1
60
+ },
61
+ :post_callback => proc { |opts, notifier, backtrace, message, message_opts|
62
+ post_callback_called += 1
63
+ }
64
+ }
65
+ )
66
+ campfire.room = Object.new
67
+ campfire.room.stubs(:paste).returns(fake_notification)
68
+ campfire.call(fake_exception)
69
+ assert_equal(1, pre_callback_called)
70
+ assert_equal(1, post_callback_called)
71
+ end
72
+
73
+ private
74
+
75
+ def fake_notification
76
+ {:message => {:type => 'PasteMessage',
77
+ :body => "A new exception occurred: 'divided by 0' on '/Users/sebastian/exception_notification/test/campfire_test.rb:45:in `/'"
78
+ }
79
+ }
80
+ end
81
+
82
+ def fake_exception
83
+ exception = begin
84
+ 5/0
85
+ rescue Exception => e
86
+ e
87
+ end
88
+ end
89
+
90
+ def fake_notification_without_backtrace
91
+ {:message => {:type => 'PasteMessage',
92
+ :body => "A new exception occurred: 'my custom error'"
93
+ }
94
+ }
95
+ end
96
+
97
+ def fake_exception_without_backtrace
98
+ StandardError.new('my custom error')
99
+ end
100
+ end
@@ -0,0 +1,185 @@
1
+ require 'test_helper'
2
+ require 'action_mailer'
3
+
4
+ class EmailNotifierTest < ActiveSupport::TestCase
5
+ setup do
6
+ Time.stubs(:current).returns('Sat, 20 Apr 2013 20:58:55 UTC +00:00')
7
+ @email_notifier = ExceptionNotifier.registered_exception_notifier(:email)
8
+ begin
9
+ 1/0
10
+ rescue => e
11
+ @exception = e
12
+ @mail = @email_notifier.create_email(@exception,
13
+ :data => {:job => 'DivideWorkerJob', :payload => '1/0', :message => 'My Custom Message'})
14
+ end
15
+ end
16
+
17
+ test "should call pre/post_callback if specified" do
18
+ assert_equal @email_notifier.options[:pre_callback_called], 1
19
+ assert_equal @email_notifier.options[:post_callback_called], 1
20
+ end
21
+
22
+ test "should have default sender address overridden" do
23
+ assert_equal @email_notifier.sender_address, %("Dummy Notifier" <dummynotifier@example.com>)
24
+ end
25
+
26
+ test "should have default exception recipients overridden" do
27
+ assert_equal @email_notifier.exception_recipients, %w(dummyexceptions@example.com)
28
+ end
29
+
30
+ test "should have default email prefix overridden" do
31
+ assert_equal @email_notifier.email_prefix, "[Dummy ERROR] "
32
+ end
33
+
34
+ test "should have default email headers overridden" do
35
+ assert_equal @email_notifier.email_headers, { "X-Custom-Header" => "foobar"}
36
+ end
37
+
38
+ test "should have default sections overridden" do
39
+ for section in %w(new_section request session environment backtrace)
40
+ assert_includes @email_notifier.sections, section
41
+ end
42
+ end
43
+
44
+ test "should have default background sections" do
45
+ for section in %w(new_bkg_section backtrace data)
46
+ assert_includes @email_notifier.background_sections, section
47
+ end
48
+ end
49
+
50
+ test "should have email format by default" do
51
+ assert_equal @email_notifier.email_format, :text
52
+ end
53
+
54
+ test "should have verbose subject by default" do
55
+ assert @email_notifier.verbose_subject
56
+ end
57
+
58
+ test "should have normalize_subject false by default" do
59
+ refute @email_notifier.normalize_subject
60
+ end
61
+
62
+ test "should have delivery_method nil by default" do
63
+ assert_nil @email_notifier.delivery_method
64
+ end
65
+
66
+ test "should have mailer_settings nil by default" do
67
+ assert_nil @email_notifier.mailer_settings
68
+ end
69
+
70
+ test "should have mailer_parent by default" do
71
+ assert_equal @email_notifier.mailer_parent, 'ActionMailer::Base'
72
+ end
73
+
74
+ test "should have template_path by default" do
75
+ assert_equal @email_notifier.template_path, 'exception_notifier'
76
+ end
77
+
78
+ test "should normalize multiple digits into one N" do
79
+ assert_equal 'N foo N bar N baz N',
80
+ ExceptionNotifier::EmailNotifier.normalize_digits('1 foo 12 bar 123 baz 1234')
81
+ end
82
+
83
+ test "mail should be plain text and UTF-8 enconded by default" do
84
+ assert_equal @mail.content_type, "text/plain; charset=UTF-8"
85
+ end
86
+
87
+ test "should have raised an exception" do
88
+ refute_nil @exception
89
+ end
90
+
91
+ test "should have generated a notification email" do
92
+ refute_nil @mail
93
+ end
94
+
95
+ test "mail should have a from address set" do
96
+ assert_equal @mail.from, ["dummynotifier@example.com"]
97
+ end
98
+
99
+ test "mail should have a to address set" do
100
+ assert_equal @mail.to, ["dummyexceptions@example.com"]
101
+ end
102
+
103
+ test "mail should have a descriptive subject" do
104
+ assert_match /^\[Dummy ERROR\]\s+\(ZeroDivisionError\) "divided by 0"$/, @mail.subject
105
+ end
106
+
107
+ test "mail should say exception was raised in background at show timestamp" do
108
+ assert_includes @mail.encoded, "A ZeroDivisionError occurred in background at #{Time.current}"
109
+ end
110
+
111
+ test "mail should prefix exception class with 'an' instead of 'a' when it starts with a vowel" do
112
+ begin
113
+ raise ActiveRecord::RecordNotFound
114
+ rescue => e
115
+ @vowel_exception = e
116
+ @vowel_mail = @email_notifier.create_email(@vowel_exception)
117
+ end
118
+
119
+ assert_includes @vowel_mail.encoded, "An ActiveRecord::RecordNotFound occurred in background at #{Time.current}"
120
+ end
121
+
122
+ test "mail should contain backtrace in body" do
123
+ assert @mail.encoded.include?("test/exception_notifier/email_notifier_test.rb:9"), "\n#{@mail.inspect}"
124
+ end
125
+
126
+ test "mail should contain data in body" do
127
+ assert_includes @mail.encoded, '* data:'
128
+ assert_includes @mail.encoded, ':payload=>"1/0"'
129
+ assert_includes @mail.encoded, ':job=>"DivideWorkerJob"'
130
+ assert_includes @mail.encoded, "My Custom Message"
131
+ end
132
+
133
+ test "mail should not contain any attachments" do
134
+ assert_equal @mail.attachments, []
135
+ end
136
+
137
+ test "should not send notification if one of ignored exceptions" do
138
+ begin
139
+ raise ActiveRecord::RecordNotFound
140
+ rescue => e
141
+ @ignored_exception = e
142
+ unless ExceptionNotifier.ignored_exceptions.include?(@ignored_exception.class.name)
143
+ @ignored_mail = @email_notifier.create_email(@ignored_exception)
144
+ end
145
+ end
146
+
147
+ assert_equal @ignored_exception.class.inspect, "ActiveRecord::RecordNotFound"
148
+ assert_nil @ignored_mail
149
+ end
150
+
151
+ test "should encode environment strings" do
152
+ email_notifier = ExceptionNotifier::EmailNotifier.new(
153
+ :sender_address => "<dummynotifier@example.com>",
154
+ :exception_recipients => %w{dummyexceptions@example.com},
155
+ :deliver_with => :deliver_now
156
+ )
157
+
158
+ mail = email_notifier.create_email(
159
+ @exception,
160
+ :env => {
161
+ "REQUEST_METHOD" => "GET",
162
+ "rack.input" => "",
163
+ "invalid_encoding" => "R\xC3\xA9sum\xC3\xA9".force_encoding(Encoding::ASCII),
164
+ },
165
+ :email_format => :text
166
+ )
167
+
168
+ assert_match /invalid_encoding\s+: R__sum__/, mail.encoded
169
+ end
170
+
171
+ test "should send email using ActionMailer" do
172
+ ActionMailer::Base.deliveries.clear
173
+
174
+ email_notifier = ExceptionNotifier::EmailNotifier.new(
175
+ :email_prefix => '[Dummy ERROR] ',
176
+ :sender_address => %{"Dummy Notifier" <dummynotifier@example.com>},
177
+ :exception_recipients => %w{dummyexceptions@example.com},
178
+ :delivery_method => :test
179
+ )
180
+
181
+ email_notifier.call(@exception)
182
+
183
+ assert_equal 1, ActionMailer::Base.deliveries.count
184
+ end
185
+ end
@@ -0,0 +1,177 @@
1
+ require 'test_helper'
2
+ require 'hipchat'
3
+
4
+ class HipchatNotifierTest < ActiveSupport::TestCase
5
+
6
+ test "should send hipchat notification if properly configured" do
7
+ options = {
8
+ :api_token => 'good_token',
9
+ :room_name => 'room_name',
10
+ :color => 'yellow',
11
+ }
12
+
13
+ HipChat::Room.any_instance.expects(:send).with('Exception', fake_body, { :color => 'yellow' })
14
+
15
+ hipchat = ExceptionNotifier::HipchatNotifier.new(options)
16
+ hipchat.call(fake_exception)
17
+ end
18
+
19
+ test "should call pre/post_callback if specified" do
20
+ pre_callback_called, post_callback_called = 0,0
21
+ options = {
22
+ :api_token => 'good_token',
23
+ :room_name => 'room_name',
24
+ :color => 'yellow',
25
+ :pre_callback => proc { |*| pre_callback_called += 1},
26
+ :post_callback => proc { |*| post_callback_called += 1}
27
+ }
28
+
29
+ HipChat::Room.any_instance.expects(:send).with('Exception', fake_body, { :color => 'yellow' }.merge(options.except(:api_token, :room_name)))
30
+
31
+ hipchat = ExceptionNotifier::HipchatNotifier.new(options)
32
+ hipchat.call(fake_exception)
33
+ assert_equal(1, pre_callback_called)
34
+ assert_equal(1, post_callback_called)
35
+ end
36
+
37
+ test "should send hipchat notification without backtrace info if properly configured" do
38
+ options = {
39
+ :api_token => 'good_token',
40
+ :room_name => 'room_name',
41
+ :color => 'yellow',
42
+ }
43
+
44
+ HipChat::Room.any_instance.expects(:send).with('Exception', fake_body_without_backtrace, { :color => 'yellow' })
45
+
46
+ hipchat = ExceptionNotifier::HipchatNotifier.new(options)
47
+ hipchat.call(fake_exception_without_backtrace)
48
+ end
49
+
50
+ test "should allow custom from value if set" do
51
+ options = {
52
+ :api_token => 'good_token',
53
+ :room_name => 'room_name',
54
+ :from => 'TrollFace',
55
+ }
56
+
57
+ HipChat::Room.any_instance.expects(:send).with('TrollFace', fake_body, { :color => 'red' })
58
+
59
+ hipchat = ExceptionNotifier::HipchatNotifier.new(options)
60
+ hipchat.call(fake_exception)
61
+ end
62
+
63
+ test "should not send hipchat notification if badly configured" do
64
+ wrong_params = {
65
+ :api_token => 'bad_token',
66
+ :room_name => 'test_room'
67
+ }
68
+
69
+ HipChat::Client.stubs(:new).with('bad_token', {:api_version => 'v1'}).returns(nil)
70
+
71
+ hipchat = ExceptionNotifier::HipchatNotifier.new(wrong_params)
72
+ assert_nil hipchat.room
73
+ end
74
+
75
+ test "should not send hipchat notification if api_key is missing" do
76
+ wrong_params = {:room_name => 'test_room'}
77
+
78
+ HipChat::Client.stubs(:new).with(nil, {:api_version => 'v1'}).returns(nil)
79
+
80
+ hipchat = ExceptionNotifier::HipchatNotifier.new(wrong_params)
81
+ assert_nil hipchat.room
82
+ end
83
+
84
+ test "should not send hipchat notification if room_name is missing" do
85
+ wrong_params = {:api_token => 'good_token'}
86
+
87
+ HipChat::Client.stubs(:new).with('good_token', {:api_version => 'v1'}).returns({})
88
+
89
+ hipchat = ExceptionNotifier::HipchatNotifier.new(wrong_params)
90
+ assert_nil hipchat.room
91
+ end
92
+
93
+ test "should send hipchat notification with message_template" do
94
+ options = {
95
+ :api_token => 'good_token',
96
+ :room_name => 'room_name',
97
+ :color => 'yellow',
98
+ :message_template => ->(exception) { "This is custom message: '#{exception.message}'" }
99
+ }
100
+
101
+ HipChat::Room.any_instance.expects(:send).with('Exception', "This is custom message: '#{fake_exception.message}'", { :color => 'yellow' })
102
+
103
+ hipchat = ExceptionNotifier::HipchatNotifier.new(options)
104
+ hipchat.call(fake_exception)
105
+ end
106
+
107
+ test "should send hipchat notification with HTML-escaped meessage if using default message_template" do
108
+ options = {
109
+ :api_token => 'good_token',
110
+ :room_name => 'room_name',
111
+ :color => 'yellow',
112
+ }
113
+
114
+ exception = fake_exception_with_html_characters
115
+ body = "A new exception occurred: '#{Rack::Utils.escape_html(exception.message)}' on '#{exception.backtrace.first}'"
116
+
117
+ HipChat::Room.any_instance.expects(:send).with('Exception', body, { :color => 'yellow' })
118
+
119
+ hipchat = ExceptionNotifier::HipchatNotifier.new(options)
120
+ hipchat.call(exception)
121
+ end
122
+
123
+ test "should use APIv1 if api_version is not specified" do
124
+ options = {
125
+ :api_token => 'good_token',
126
+ :room_name => 'room_name',
127
+ }
128
+
129
+ HipChat::Client.stubs(:new).with('good_token', {:api_version => 'v1'}).returns({})
130
+
131
+ hipchat = ExceptionNotifier::HipchatNotifier.new(options)
132
+ hipchat.call(fake_exception)
133
+ end
134
+
135
+ test "should use APIv2 when specified" do
136
+ options = {
137
+ :api_token => 'good_token',
138
+ :room_name => 'room_name',
139
+ :api_version => 'v2',
140
+ }
141
+
142
+ HipChat::Client.stubs(:new).with('good_token', {:api_version => 'v2'}).returns({})
143
+
144
+ hipchat = ExceptionNotifier::HipchatNotifier.new(options)
145
+ hipchat.call(fake_exception)
146
+ end
147
+
148
+ private
149
+
150
+ def fake_body
151
+ "A new exception occurred: '#{fake_exception.message}' on '#{fake_exception.backtrace.first}'"
152
+ end
153
+
154
+ def fake_exception
155
+ exception = begin
156
+ 5/0
157
+ rescue Exception => e
158
+ e
159
+ end
160
+ end
161
+
162
+ def fake_exception_with_html_characters
163
+ exception = begin
164
+ raise StandardError.new('an error with <html> characters')
165
+ rescue Exception => e
166
+ e
167
+ end
168
+ end
169
+
170
+ def fake_body_without_backtrace
171
+ "A new exception occurred: '#{fake_exception_without_backtrace.message}'"
172
+ end
173
+
174
+ def fake_exception_without_backtrace
175
+ StandardError.new('my custom error')
176
+ end
177
+ end