exception_notification 4.2.1 → 4.4.3

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 +105 -780
  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 +30 -23
  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 +71 -40
  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 +17 -14
  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} +13 -11
  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 +59 -38
  66. data/test/exception_notifier/datadog_notifier_test.rb +153 -0
  67. data/test/exception_notifier/email_notifier_test.rb +279 -145
  68. data/test/exception_notifier/google_chat_notifier_test.rb +185 -0
  69. data/test/exception_notifier/hipchat_notifier_test.rb +105 -64
  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 -17
  75. data/test/exception_notifier/slack_notifier_test.rb +84 -62
  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 +52 -48
  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 -35
  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,3 +1,3 @@
1
1
  <pre style="font-size: 12px; padding: 10px; border: 1px solid #e1e1e8; background-color:#f5f5f5">
2
- <%= @backtrace.join("\n") %>
2
+ <%= @backtrace.join("\n") %>
3
3
  </pre>
@@ -1,5 +1,5 @@
1
1
  <% filtered_env = @request.filtered_env -%>
2
2
  <% max = filtered_env.keys.map(&:to_s).max { |a, b| a.length <=> b.length } -%>
3
3
  <% filtered_env.keys.map(&:to_s).sort.each do |key| -%>
4
- * <%= raw safe_encode("%-*s: %s" % [max.length, key, inspect_object(filtered_env[key])]) %>
4
+ * <%= raw safe_encode("%-*s: %s" % [max.length, key, inspect_object(filtered_env[key])]).strip %>
5
5
  <% end -%>
@@ -5,6 +5,6 @@
5
5
  * Timestamp : <%= raw @timestamp %>
6
6
  * Server : <%= raw Socket.gethostname %>
7
7
  <% if defined?(Rails) && Rails.respond_to?(:root) %>
8
- * Rails root : <%= raw Rails.root %>
8
+ * Rails root : <%= raw Rails.root %>
9
9
  <% end %>
10
10
  * Process: <%= raw $$ %>
@@ -3,12 +3,12 @@
3
3
  <%= @exception.message %>
4
4
  <%= @backtrace.first %>
5
5
 
6
- <% sections = @sections.map do |section|
7
- summary = render(section).strip
8
- unless summary.blank?
9
- title = render("title", :title => section).strip
10
- "#{title}\n\n#{summary.gsub(/^/, " ")}\n\n"
11
- end
12
- end.join
13
- %>
14
- <%= raw sections %>
6
+ <% sections = @sections.map do |section|
7
+ summary = render(section).strip
8
+ unless summary.blank?
9
+ title = render("title", :title => section).strip
10
+ "#{title}\n\n#{summary.gsub(/^/, " ")}\n\n"
11
+ end
12
+ end.join
13
+ %>
14
+ <%= raw sections %>
@@ -11,14 +11,12 @@
11
11
  begin
12
12
  summary = render(section).strip
13
13
  unless summary.blank?
14
- title = render("title", :title => section).strip
14
+ title = render("title", title: section).strip
15
15
  [title, summary]
16
16
  end
17
-
18
17
  rescue Exception => e
19
- title = render("title", :title => section).strip
18
+ title = render("title", title: section).strip
20
19
  summary = ["ERROR: Failed to generate exception summary:", [e.class.to_s, e.message].join(": "), e.backtrace && e.backtrace.join("\n")].compact.join("\n\n")
21
-
22
20
  [title, summary]
23
21
  end
24
22
  end
@@ -8,12 +8,12 @@
8
8
  begin
9
9
  summary = render(section).strip
10
10
  unless summary.blank?
11
- title = render("title", :title => section).strip
11
+ title = render("title", title: section).strip
12
12
  "#{title}\n\n#{summary.gsub(/^/, " ")}\n\n"
13
13
  end
14
14
 
15
15
  rescue Exception => e
16
- title = render("title", :title => section).strip
16
+ title = render("title", title: section).strip
17
17
  summary = ["ERROR: Failed to generate exception summary:", [e.class.to_s, e.message].join(": "), e.backtrace && e.backtrace.join("\n")].compact.join("\n\n")
18
18
 
19
19
  [title, summary.gsub(/^/, " "), nil].join("\n\n")
@@ -1,15 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'action_dispatch'
2
4
  require 'active_support/core_ext/time'
3
5
 
4
6
  module ExceptionNotifier
5
7
  class WebhookNotifier < BaseNotifier
6
-
7
8
  def initialize(options)
8
9
  super
9
10
  @default_options = options
10
11
  end
11
12
 
12
- def call(exception, options={})
13
+ def call(exception, options = {})
13
14
  env = options[:env]
14
15
 
15
16
  options = options.reverse_merge(@default_options)
@@ -18,23 +19,25 @@ module ExceptionNotifier
18
19
 
19
20
  options[:body] ||= {}
20
21
  options[:body][:server] = Socket.gethostname
21
- options[:body][:process] = $$
22
- if defined?(Rails) && Rails.respond_to?(:root)
23
- options[:body][:rails_root] = Rails.root
24
- end
25
- options[:body][:exception] = {:error_class => exception.class.to_s,
26
- :message => exception.message.inspect,
27
- :backtrace => exception.backtrace}
22
+ options[:body][:process] = $PROCESS_ID
23
+ options[:body][:rails_root] = Rails.root if defined?(Rails) && Rails.respond_to?(:root)
24
+ options[:body][:exception] = {
25
+ error_class: exception.class.to_s,
26
+ message: exception.message.inspect,
27
+ backtrace: exception.backtrace
28
+ }
28
29
  options[:body][:data] = (env && env['exception_notifier.exception_data'] || {}).merge(options[:data] || {})
29
30
 
30
31
  unless env.nil?
31
32
  request = ActionDispatch::Request.new(env)
32
33
 
33
- request_items = {:url => request.original_url,
34
- :http_method => request.method,
35
- :ip_address => request.remote_ip,
36
- :parameters => request.filtered_parameters,
37
- :timestamp => Time.current }
34
+ request_items = {
35
+ url: request.original_url,
36
+ http_method: request.method,
37
+ ip_address: request.remote_ip,
38
+ parameters: request.filtered_parameters,
39
+ timestamp: Time.current
40
+ }
38
41
 
39
42
  options[:body][:request] = request_items
40
43
  options[:body][:session] = request.session
@@ -1,14 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ExceptionNotification
2
4
  module Generators
3
5
  class InstallGenerator < Rails::Generators::Base
4
- desc "Creates a ExceptionNotification initializer."
6
+ desc 'Creates a ExceptionNotification initializer.'
5
7
 
6
- source_root File.expand_path('../templates', __FILE__)
7
- class_option :resque, :type => :boolean, :desc => 'Add support for sending notifications when errors occur in Resque jobs.'
8
- class_option :sidekiq, :type => :boolean, :desc => 'Add support for sending notifications when errors occur in Sidekiq jobs.'
8
+ source_root File.expand_path('templates', __dir__)
9
+ class_option :resque,
10
+ type: :boolean,
11
+ desc: 'Add support for sending notifications when errors occur in Resque jobs.'
12
+ class_option :sidekiq,
13
+ type: :boolean,
14
+ desc: 'Add support for sending notifications when errors occur in Sidekiq jobs.'
9
15
 
10
16
  def copy_initializer
11
- template 'exception_notification.rb', 'config/initializers/exception_notification.rb'
17
+ template 'exception_notification.rb.erb', 'config/initializers/exception_notification.rb'
12
18
  end
13
19
  end
14
20
  end
@@ -22,32 +22,34 @@ ExceptionNotification.configure do |config|
22
22
  # not Rails.env.production?
23
23
  # end
24
24
 
25
+ # Ignore exceptions generated by crawlers
26
+ # config.ignore_crawlers %w{Googlebot bingbot}
27
+
25
28
  # Notifiers =================================================================
26
29
 
27
30
  # Email notifier sends notifications by email.
28
31
  config.add_notifier :email, {
29
- :email_prefix => "[ERROR] ",
30
- :sender_address => %{"Notifier" <notifier@example.com>},
31
- :exception_recipients => %w{exceptions@example.com}
32
+ email_prefix: '[ERROR] ',
33
+ sender_address: %{"Notifier" <notifier@example.com>},
34
+ exception_recipients: %w{exceptions@example.com}
32
35
  }
33
36
 
34
37
  # Campfire notifier sends notifications to your Campfire room. Requires 'tinder' gem.
35
38
  # config.add_notifier :campfire, {
36
- # :subdomain => 'my_subdomain',
37
- # :token => 'my_token',
38
- # :room_name => 'my_room'
39
+ # subdomain: 'my_subdomain',
40
+ # token: 'my_token',
41
+ # room_name: 'my_room'
39
42
  # }
40
43
 
41
44
  # HipChat notifier sends notifications to your HipChat room. Requires 'hipchat' gem.
42
45
  # config.add_notifier :hipchat, {
43
- # :api_token => 'my_token',
44
- # :room_name => 'my_room'
46
+ # api_token: 'my_token',
47
+ # room_name: 'my_room'
45
48
  # }
46
49
 
47
50
  # Webhook notifier sends notifications over HTTP protocol. Requires 'httparty' gem.
48
51
  # config.add_notifier :webhook, {
49
- # :url => 'http://example.com:5555/hubot/path',
50
- # :http_method => :post
52
+ # url: 'http://example.com:5555/hubot/path',
53
+ # http_method: :post
51
54
  # }
52
-
53
55
  end
@@ -1,20 +1,106 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  class RackTest < ActiveSupport::TestCase
4
-
5
6
  setup do
6
7
  @pass_app = Object.new
7
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])
8
12
  end
9
13
 
10
- test "should ignore \"X-Cascade\" header by default" do
14
+ teardown do
15
+ ExceptionNotifier.reset_notifiers!
16
+ end
17
+
18
+ test 'should ignore "X-Cascade" header by default' do
11
19
  ExceptionNotifier.expects(:notify_exception).never
12
20
  ExceptionNotification::Rack.new(@pass_app).call({})
13
21
  end
14
22
 
15
- test "should notify on \"X-Cascade\" = \"pass\" if ignore_cascade_pass option is false" do
23
+ test 'should notify on "X-Cascade" = "pass" if ignore_cascade_pass option is false' do
16
24
  ExceptionNotifier.expects(:notify_exception).once
17
- ExceptionNotification::Rack.new(@pass_app, :ignore_cascade_pass => false).call({})
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
18
60
  end
19
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
20
106
  end
@@ -0,0 +1,54 @@
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,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  # silence_warnings trick around require can be removed once
@@ -8,43 +10,42 @@ silence_warnings do
8
10
  end
9
11
 
10
12
  class CampfireNotifierTest < ActiveSupport::TestCase
11
-
12
- test "should send campfire notification if properly configured" do
13
+ test 'should send campfire notification if properly configured' do
13
14
  ExceptionNotifier::CampfireNotifier.stubs(:new).returns(Object.new)
14
- campfire = ExceptionNotifier::CampfireNotifier.new({:subdomain => 'test', :token => 'test_token', :room_name => 'test_room'})
15
+ campfire = ExceptionNotifier::CampfireNotifier.new(subdomain: 'test', token: 'test_token', room_name: 'test_room')
15
16
  campfire.stubs(:call).returns(fake_notification)
16
17
  notif = campfire.call(fake_exception)
17
18
 
18
19
  assert !notif[:message].empty?
19
20
  assert_equal notif[:message][:type], 'PasteMessage'
20
- assert_includes notif[:message][:body], "A new exception occurred:"
21
- assert_includes notif[:message][:body], "divided by 0"
22
- assert_includes notif[:message][:body], "/exception_notification/test/campfire_test.rb:45"
21
+ assert_includes notif[:message][:body], 'A new exception occurred:'
22
+ assert_includes notif[:message][:body], 'divided by 0'
23
+ assert_includes notif[:message][:body], '/exception_notification/test/campfire_test.rb:45'
23
24
  end
24
25
 
25
- test "should send campfire notification without backtrace info if properly configured" do
26
+ test 'should send campfire notification without backtrace info if properly configured' do
26
27
  ExceptionNotifier::CampfireNotifier.stubs(:new).returns(Object.new)
27
- campfire = ExceptionNotifier::CampfireNotifier.new({:subdomain => 'test', :token => 'test_token', :room_name => 'test_room'})
28
+ campfire = ExceptionNotifier::CampfireNotifier.new(subdomain: 'test', token: 'test_token', room_name: 'test_room')
28
29
  campfire.stubs(:call).returns(fake_notification_without_backtrace)
29
30
  notif = campfire.call(fake_exception_without_backtrace)
30
31
 
31
32
  assert !notif[:message].empty?
32
33
  assert_equal notif[:message][:type], 'PasteMessage'
33
- assert_includes notif[:message][:body], "A new exception occurred:"
34
- assert_includes notif[:message][:body], "my custom error"
34
+ assert_includes notif[:message][:body], 'A new exception occurred:'
35
+ assert_includes notif[:message][:body], 'my custom error'
35
36
  end
36
37
 
37
- test "should not send campfire notification if badly configured" do
38
- wrong_params = {:subdomain => 'test', :token => 'bad_token', :room_name => 'test_room'}
39
- Tinder::Campfire.stubs(:new).with('test', {:token => 'bad_token'}).returns(nil)
38
+ test 'should not send campfire notification if badly configured' do
39
+ wrong_params = { subdomain: 'test', token: 'bad_token', room_name: 'test_room' }
40
+ Tinder::Campfire.stubs(:new).with('test', token: 'bad_token').returns(nil)
40
41
  campfire = ExceptionNotifier::CampfireNotifier.new(wrong_params)
41
42
 
42
43
  assert_nil campfire.room
43
44
  assert_nil campfire.call(fake_exception)
44
45
  end
45
46
 
46
- test "should not send campfire notification if config attr missing" do
47
- wrong_params = {:subdomain => 'test', :room_name => 'test_room'}
47
+ test 'should not send campfire notification if config attr missing' do
48
+ wrong_params = { subdomain: 'test', room_name: 'test_room' }
48
49
  Tinder::Campfire.stubs(:new).with('test', {}).returns(nil)
49
50
  campfire = ExceptionNotifier::CampfireNotifier.new(wrong_params)
50
51
 
@@ -52,21 +53,34 @@ class CampfireNotifierTest < ActiveSupport::TestCase
52
53
  assert_nil campfire.call(fake_exception)
53
54
  end
54
55
 
55
- test "should call pre/post_callback if specified" do
56
- pre_callback_called, post_callback_called = 0,0
56
+ test 'should send the new exception message if no :accumulated_errors_count option' do
57
+ campfire = ExceptionNotifier::CampfireNotifier.new({})
58
+ campfire.stubs(:active?).returns(true)
59
+ campfire.expects(:send_notice).with { |_, _, message| message.start_with?('A new exception occurred') }.once
60
+ campfire.call(fake_exception)
61
+ end
62
+
63
+ test 'shoud send the exception message if :accumulated_errors_count option greater than 1' do
64
+ campfire = ExceptionNotifier::CampfireNotifier.new({})
65
+ campfire.stubs(:active?).returns(true)
66
+ campfire.expects(:send_notice).with { |_, _, message| message.start_with?('The exception occurred 3 times:') }.once
67
+ campfire.call(fake_exception, accumulated_errors_count: 3)
68
+ end
69
+
70
+ test 'should call pre/post_callback if specified' do
71
+ pre_callback_called = 0
72
+ post_callback_called = 0
57
73
  Tinder::Campfire.stubs(:new).returns(Object.new)
58
74
 
59
75
  campfire = ExceptionNotifier::CampfireNotifier.new(
60
- {
61
- :subdomain => 'test',
62
- :token => 'test_token',
63
- :room_name => 'test_room',
64
- :pre_callback => proc { |opts, notifier, backtrace, message, message_opts|
65
- pre_callback_called += 1
66
- },
67
- :post_callback => proc { |opts, notifier, backtrace, message, message_opts|
68
- post_callback_called += 1
69
- }
76
+ subdomain: 'test',
77
+ token: 'test_token',
78
+ room_name: 'test_room',
79
+ pre_callback: proc { |_opts, _notifier, _backtrace, _message, _message_opts|
80
+ pre_callback_called += 1
81
+ },
82
+ post_callback: proc { |_opts, _notifier, _backtrace, _message, _message_opts|
83
+ post_callback_called += 1
70
84
  }
71
85
  )
72
86
  campfire.room = Object.new
@@ -79,24 +93,31 @@ class CampfireNotifierTest < ActiveSupport::TestCase
79
93
  private
80
94
 
81
95
  def fake_notification
82
- {:message => {:type => 'PasteMessage',
83
- :body => "A new exception occurred: 'divided by 0' on '/Users/sebastian/exception_notification/test/campfire_test.rb:45:in `/'"
84
- }
96
+ {
97
+ message: {
98
+ type: 'PasteMessage',
99
+ body: fake_notification_body
100
+ }
85
101
  }
86
102
  end
87
103
 
104
+ def fake_notification_body
105
+ "A new exception occurred: 'divided by 0' on " \
106
+ "/Users/sebastian/exception_notification/test/campfire_test.rb:45:in `/'"
107
+ end
108
+
88
109
  def fake_exception
89
- begin
90
- 5/0
91
- rescue Exception => e
92
- e
93
- end
110
+ 5 / 0
111
+ rescue StandardError => e
112
+ e
94
113
  end
95
114
 
96
115
  def fake_notification_without_backtrace
97
- {:message => {:type => 'PasteMessage',
98
- :body => "A new exception occurred: 'my custom error'"
99
- }
116
+ {
117
+ message: {
118
+ type: 'PasteMessage',
119
+ body: "A new exception occurred: 'my custom error'"
120
+ }
100
121
  }
101
122
  end
102
123