Hello community,

here is the log from the commit of package rubygem-exception_notification for 
openSUSE:Factory checked in at 2019-01-21 10:25:53
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rubygem-exception_notification (Old)
 and      /work/SRC/openSUSE:Factory/.rubygem-exception_notification.new.28833 
(New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "rubygem-exception_notification"

Mon Jan 21 10:25:53 2019 rev:18 rq:656380 version:4.3.0

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/rubygem-exception_notification/rubygem-exception_notification.changes
    2017-09-04 12:36:55.882372182 +0200
+++ 
/work/SRC/openSUSE:Factory/.rubygem-exception_notification.new.28833/rubygem-exception_notification.changes
 2019-01-21 10:25:55.561712878 +0100
@@ -1,0 +2,21 @@
+Sat Dec  8 16:20:42 UTC 2018 - Stephan Kulow <[email protected]>
+
+- updated to version 4.3.0
+ see installed CHANGELOG.rdoc
+
+  == 4.3.0
+  
+  * enhancements
+    * Add Microsoft Teams Notifier (by @phaelin)
+    * Add SNS notifier (by @FLarra)
+    * Add Google Chats notifier (by @renatolond)
+    * Align output of section-headers consistently (by @kronn)
+    * ExceptionNotifier.notify_exception receives block & pass it to each 
notifier (by @pocke)
+    * Update Travis to latest rubies (by @lostapathy)
+  
+  * bug fixes
+    * Replace all before_filter to before_action on readme (by @pastullo)
+    * Fix error when using error grouping outside of rails (by @garethcokell)
+    * Fix missing MissingController Mattermost class (by @n-rodriguez)
+
+-------------------------------------------------------------------

Old:
----
  exception_notification-4.2.2.gem

New:
----
  exception_notification-4.3.0.gem

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ rubygem-exception_notification.spec ++++++
--- /var/tmp/diff_new_pack.002CIj/_old  2019-01-21 10:25:56.913711393 +0100
+++ /var/tmp/diff_new_pack.002CIj/_new  2019-01-21 10:25:56.913711393 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package rubygem-exception_notification
 #
-# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -12,7 +12,7 @@
 # license that conforms to the Open Source Definition (Version 1.9)
 # published by the Open Source Initiative.
 
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
 #
 
 
@@ -24,7 +24,7 @@
 #
 
 Name:           rubygem-exception_notification
-Version:        4.2.2
+Version:        4.3.0
 Release:        0
 %define mod_name exception_notification
 %define mod_full_name %{mod_name}-%{version}
@@ -33,7 +33,7 @@
 BuildRequires:  %{rubygem gem2rpm}
 BuildRequires:  ruby-macros >= 5
 Url:            https://smartinez87.github.io/exception_notification/
-Source:         http://rubygems.org/gems/%{mod_full_name}.gem
+Source:         https://rubygems.org/gems/%{mod_full_name}.gem
 Source1:        gem2rpm.yml
 Summary:        Exception notification for Rails apps
 License:        MIT

++++++ exception_notification-4.2.2.gem -> exception_notification-4.3.0.gem 
++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Appraisals new/Appraisals
--- old/Appraisals      2017-08-12 22:52:29.000000000 +0200
+++ new/Appraisals      2018-11-22 23:02:26.000000000 +0100
@@ -1,8 +1,7 @@
-rails_versions = ['~> 4.0.5', '~> 4.1.1', '~> 4.2.0', '~> 5.0.0']
+rails_versions = ['~> 4.0.5', '~> 4.1.1', '~> 4.2.0', '~> 5.0.0', '~> 5.1.0']
 
 rails_versions.each do |rails_version|
   appraise "rails#{rails_version.slice(/\d+\.\d+/).gsub('.', '_')}" do
     gem 'rails', rails_version
-    gem "sqlite3"
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CHANGELOG.rdoc new/CHANGELOG.rdoc
--- old/CHANGELOG.rdoc  2017-08-12 22:52:29.000000000 +0200
+++ new/CHANGELOG.rdoc  2018-11-22 23:02:26.000000000 +0100
@@ -1,7 +1,22 @@
+== 4.3.0
+
+* enhancements
+  * Add Microsoft Teams Notifier (by @phaelin)
+  * Add SNS notifier (by @FLarra)
+  * Add Google Chats notifier (by @renatolond)
+  * Align output of section-headers consistently (by @kronn)
+  * ExceptionNotifier.notify_exception receives block & pass it to each 
notifier (by @pocke)
+  * Update Travis to latest rubies (by @lostapathy)
+
+* bug fixes
+  * Replace all before_filter to before_action on readme (by @pastullo)
+  * Fix error when using error grouping outside of rails (by @garethcokell)
+  * Fix missing MissingController Mattermost class (by @n-rodriguez)
+
 == 4.2.2
 
 * enhancements
-  * Error groupiong (by @Martin91)
+  * Error grouping (by @Martin91)
   * Additional fields for Slack support (by @schurig)
   * Enterprise HipChat support (by @seanhuber)
 
@@ -131,7 +146,7 @@
   * Add normalize_subject option to remove numbers from email so that they 
thread (by @jjb)
   * Allow the user to provide a custom message and hash of data (by @jjb)
   * Add support for configurable background sections and a data partial (by 
@jeffrafter)
-  * Include timestamp of exception in notification body        
+  * Include timestamp of exception in notification body
   * Add support for rack based session management (by @phoet)
   * Add ignore_crawlers option to ignore exceptions generated by crawlers
   * Add verbode_subject option to exclude exception message from subject (by 
@amishyn)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/README.md new/README.md
--- old/README.md       2017-08-12 22:52:29.000000000 +0200
+++ new/README.md       2018-11-22 23:02:26.000000000 +0100
@@ -9,7 +9,7 @@
 
 ---
 
-The Exception Notification gem provides a set of [notifiers](#notifiers) for 
sending notifications when errors occur in a Rack/Rails application. The 
built-in notifiers can deliver notifications by [email](#email-notifier), 
[Campfire](#campfire-notifier), [HipChat](#hipchat-notifier), 
[Slack](#slack-notifier), [Mattermost](#mattermost-notifier), 
[IRC](#irc-notifier) or via custom [WebHooks](#webhook-notifier).
+The Exception Notification gem provides a set of [notifiers](#notifiers) for 
sending notifications when errors occur in a Rack/Rails application. The 
built-in notifiers can deliver notifications by [email](#email-notifier), 
[Campfire](#campfire-notifier), [HipChat](#hipchat-notifier), 
[Slack](#slack-notifier), [Mattermost](#mattermost-notifier), 
[Teams](#teams-notifier), [IRC](#irc-notifier), [Amazon 
SNS](#amazon-sns-notifier), [Google Chat](#google-chat-notifier) or via custom 
[WebHooks](#webhook-notifier).
 
 There's a great [Railscast about Exception 
Notification](http://railscasts.com/episodes/104-exception-notifications-revised)
 you can see that may help you getting started.
 
@@ -56,7 +56,7 @@
 
 ```ruby
 class ApplicationController < ActionController::Base
-  before_filter :prepare_exception_notifier
+  before_action :prepare_exception_notifier
   private
   def prepare_exception_notifier
     request.env["exception_notifier.exception_data"] = {
@@ -90,6 +90,9 @@
 * [IRC notifier](#irc-notifier)
 * [Slack notifier](#slack-notifier)
 * [Mattermost notifier](#mattermost-notifier)
+* [Teams notifier](#teams-notifier)
+* [Amazon SNS](#amazon-sns-notifier)
+* [Google Chat notifier](#google-chat-notifier)
 * [WebHook notifier](#webhook-notifier)
 
 But, you also can easily implement your own [custom 
notifier](#custom-notifier).
@@ -220,7 +223,7 @@
 
 ```ruby
 class ApplicationController < ActionController::Base
-  before_filter :log_additional_data
+  before_action :log_additional_data
   ...
   protected
     def log_additional_data
@@ -542,7 +545,7 @@
 An example of how to send the server name to Slack in Rails (put this code in 
application_controller.rb):
 
 ```ruby
-before_filter :set_notification
+before_action :set_notification
 
 def set_notification
      request.env['exception_notifier.exception_data'] = {"server" => 
request.env['SERVER_NAME']}
@@ -608,7 +611,7 @@
 
 Contains additional fields that will be added to the attachement. See [Slack 
documentation](https://api.slack.com/docs/message-attachments).
 
-## Mattermost notifier
+### Mattermost notifier
 
 Post notification in a mattermost channel via [incoming 
webhook](http://docs.mattermost.com/developer/webhooks-incoming.html)
 
@@ -723,6 +726,128 @@
 
 Your application name used for issue creation link. Defaults to ``` 
Rails.application.class.parent_name.underscore```.
 
+### Google Chat Notifier
+
+Post notifications in a Google Chats channel via [incoming 
webhook](https://developers.google.com/hangouts/chat/how-tos/webhooks)
+
+Add the [HTTParty](https://github.com/jnunemaker/httparty) gem to your 
`Gemfile`:
+
+```ruby
+gem 'httparty'
+```
+
+To configure it, you **need** to set the `webhook_url` option.
+
+```ruby
+Rails.application.config.middleware.use ExceptionNotification::Rack,
+  :google_chat => {
+    :webhook_url => 
'https://chat.googleapis.com/v1/spaces/XXXXXXXX/messages?key=YYYYYYYYYYYYY&token=ZZZZZZZZZZZZ'
+  }
+```
+
+##### webhook_url
+
+*String, required*
+
+The Incoming WebHook URL on Google Chats.
+
+##### app_name
+
+*String, optional*
+
+Your application name, shown in the notification. Defaults to 
`Rails.application.class.parent_name.underscore`.
+
+### Amazon SNS Notifier
+
+Notify all exceptions Amazon - Simple Notification Service: 
[SNS](https://aws.amazon.com/sns/).
+
+#### Usage
+
+Add the 
[aws-sdk-sns](https://github.com/aws/aws-sdk-ruby/tree/master/gems/aws-sdk-sns) 
gem to your `Gemfile`:
+
+```ruby
+  gem 'aws-sdk-sns', '~> 1.5'
+```
+
+To configure it, you **need** to set 3 required options for aws: `region`, 
`access_key_id` and `secret_access_key`, and one more option for sns: 
`topic_arn`.
+
+```ruby
+Rails.application.config.middleware.use ExceptionNotification::Rack,
+  sns: {
+    region: 'us-east-x',
+    access_key_id: 'access_key_id',
+    secret_access_key: 'secret_access_key',
+    topic_arn: 'arn:aws:sns:us-east-x:XXXX:my-topic'
+  }
+```
+
+##### sns_prefix
+*String, optional *
+
+Prefix in the notification subject, by default: "[Error]"
+
+##### backtrace_lines
+*Integer, optional *
+
+Number of backtrace lines to be displayed in the notification message. By 
default: 10
+
+#### Note:
+* You may need to update your previous `aws-sdk-*` gems in order to setup 
`aws-sdk-sns` correctly.
+* If you need any further information about the available regions or any other 
SNS related topic consider: [SNS faqs](https://aws.amazon.com/sns/faqs/)
+
+### Teams notifier
+
+Post notification in a Microsoft Teams channel via [Incoming Webhook 
Connector](https://docs.microsoft.com/en-us/outlook/actionable-messages/actionable-messages-via-connectors)
+Just add the [HTTParty](https://github.com/jnunemaker/httparty) gem to your 
`Gemfile`:
+
+```ruby
+gem 'httparty'
+```
+
+To configure it, you **need** to set the `webhook_url` option.  
+If you are using GitLab for issue tracking, you can specify `git_url` as 
follows to add a *Create issue* button in your notification.  
+By default this will use your Rails application name to match the git 
repository. If yours differs, you can specify `app_name`.  
+By that same notion, you may also set a `jira_url` to get a button that will 
send you to the New Issue screen in Jira.
+
+```ruby
+Rails.application.config.middleware.use ExceptionNotification::Rack,
+  :email => {
+    :email_prefix => "[PREFIX] ",
+    :sender_address => %{"notifier" <[email protected]>},
+    :exception_recipients => %w{[email protected]}
+  },
+  :teams => {
+    :webhook_url => 
'https://outlook.office.com/webhook/your-guid/IncomingWebhook/team-guid',
+    :git_url => 'https://your-gitlab.com/Group/Project',
+    :jira_url => 'https://your-jira.com'
+  }
+```
+
+#### Options
+
+##### webhook_url
+
+*String, required*
+
+The Incoming WebHook URL on mattermost.
+
+##### git_url
+
+*String, optional*
+
+Url of your gitlab or github with your organisation name for issue creation 
link (Eg: `github.com/aschen`). Defaults to nil and doesn't add link to the 
notification.
+
+##### jira_url
+
+*String, optional*
+
+Url of your Jira instance, adds button for Create Issue screen. Defaults to 
nil and doesn't add a button to the card.
+
+##### app_name
+
+*String, optional*
+
+Your application name used for git issue creation link. Defaults to 
`Rails.application.class.parent_name.underscore`.
 
 ### WebHook notifier
 
Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exception_notification.gemspec 
new/exception_notification.gemspec
--- old/exception_notification.gemspec  2017-08-12 22:52:29.000000000 +0200
+++ new/exception_notification.gemspec  2018-11-22 23:02:26.000000000 +0100
@@ -1,8 +1,8 @@
 Gem::Specification.new do |s|
   s.name = 'exception_notification'
-  s.version = '4.2.2'
+  s.version = '4.3.0'
   s.authors = ["Jamis Buck", "Josh Peek"]
-  s.date = %q{2017-08-12}
+  s.date = %q{2018-11-22}
   s.summary = "Exception notification for Rails apps"
   s.homepage = "https://smartinez87.github.io/exception_notification/";
   s.email = "[email protected]"
@@ -32,4 +32,5 @@
   s.add_development_dependency "hipchat", ">= 1.0.0"
   s.add_development_dependency "carrier-pigeon", ">= 0.7.0"
   s.add_development_dependency "slack-notifier", ">= 1.0.0"
+  s.add_development_dependency "aws-sdk-sns", "~> 1"
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gemfiles/rails4_0.gemfile 
new/gemfiles/rails4_0.gemfile
--- old/gemfiles/rails4_0.gemfile       2017-08-12 22:52:29.000000000 +0200
+++ new/gemfiles/rails4_0.gemfile       2018-11-22 23:02:26.000000000 +0100
@@ -3,6 +3,5 @@
 source "https://rubygems.org";
 
 gem "rails", "~> 4.0.5"
-gem "sqlite3"
 
 gemspec :path => "../"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gemfiles/rails4_1.gemfile 
new/gemfiles/rails4_1.gemfile
--- old/gemfiles/rails4_1.gemfile       2017-08-12 22:52:29.000000000 +0200
+++ new/gemfiles/rails4_1.gemfile       2018-11-22 23:02:26.000000000 +0100
@@ -3,6 +3,5 @@
 source "https://rubygems.org";
 
 gem "rails", "~> 4.1.1"
-gem "sqlite3"
 
 gemspec :path => "../"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gemfiles/rails4_2.gemfile 
new/gemfiles/rails4_2.gemfile
--- old/gemfiles/rails4_2.gemfile       2017-08-12 22:52:29.000000000 +0200
+++ new/gemfiles/rails4_2.gemfile       2018-11-22 23:02:26.000000000 +0100
@@ -3,6 +3,5 @@
 source "https://rubygems.org";
 
 gem "rails", "~> 4.2.0"
-gem "sqlite3"
 
 gemspec :path => "../"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gemfiles/rails5_0.gemfile 
new/gemfiles/rails5_0.gemfile
--- old/gemfiles/rails5_0.gemfile       2017-08-12 22:52:29.000000000 +0200
+++ new/gemfiles/rails5_0.gemfile       2018-11-22 23:02:26.000000000 +0100
@@ -3,6 +3,5 @@
 source "https://rubygems.org";
 
 gem "rails", "~> 5.0.0"
-gem "sqlite3"
 
 gemspec :path => "../"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gemfiles/rails5_1.gemfile 
new/gemfiles/rails5_1.gemfile
--- old/gemfiles/rails5_1.gemfile       1970-01-01 01:00:00.000000000 +0100
+++ new/gemfiles/rails5_1.gemfile       2018-11-22 23:02:26.000000000 +0100
@@ -0,0 +1,7 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org";
+
+gem "rails", "~> 5.1.0"
+
+gemspec :path => "../"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/exception_notifier/email_notifier.rb 
new/lib/exception_notifier/email_notifier.rb
--- old/lib/exception_notifier/email_notifier.rb        2017-08-12 
22:52:29.000000000 +0200
+++ new/lib/exception_notifier/email_notifier.rb        2018-11-22 
23:02:26.000000000 +0100
@@ -60,8 +60,8 @@
 
           def compose_subject
             subject = "#{@options[:email_prefix]}"
-            subject << "(#{@options[:accumulated_errors_count]} times) " if 
@options[:accumulated_errors_count].to_i > 1
-            subject << 
"#{@kontroller.controller_name}##{@kontroller.action_name}" if @kontroller && 
@options[:include_controller_and_action_names_in_subject]
+            subject << "(#{@options[:accumulated_errors_count]} times)" if 
@options[:accumulated_errors_count].to_i > 1
+            subject << "#{@kontroller.controller_name} 
#{@kontroller.action_name}" if @kontroller && 
@options[:include_controller_and_action_names_in_subject]
             subject << " (#{@exception.class})"
             subject << " #{@exception.message.inspect}" if 
@options[:verbose_subject]
             subject = EmailNotifier.normalize_digits(subject) if 
@options[:normalize_subject]
@@ -75,17 +75,17 @@
           end
 
           helper_method :inspect_object
-          
+
           def truncate(string, max)
             string.length > max ? "#{string[0...max]}..." : string
           end
-          
+
           def inspect_object(object)
             case object
               when Hash, Array
                 truncate(object.inspect, 300)
               else
-                  object.to_s 
+                  object.to_s
             end
           end
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/exception_notifier/google_chat_notifier.rb 
new/lib/exception_notifier/google_chat_notifier.rb
--- old/lib/exception_notifier/google_chat_notifier.rb  1970-01-01 
01:00:00.000000000 +0100
+++ new/lib/exception_notifier/google_chat_notifier.rb  2018-11-22 
23:02:26.000000000 +0100
@@ -0,0 +1,136 @@
+require 'action_dispatch'
+require 'active_support/core_ext/time'
+
+module ExceptionNotifier
+  class GoogleChatNotifier
+    include ExceptionNotifier::BacktraceCleaner
+
+    class MissingController
+      def method_missing(*args, &block)
+      end
+    end
+
+    attr_accessor :httparty
+
+    def initialize(options = {})
+      super()
+      @default_options = options
+      @httparty = HTTParty
+    end
+
+    def call(exception, options = {})
+      @options = options.merge(@default_options)
+      @exception = exception
+      @backtrace = exception.backtrace ? clean_backtrace(exception) : nil
+
+      @env = @options.delete(:env)
+
+      @application_name = @options.delete(:app_name) || 
Rails.application.class.parent_name.underscore
+
+      @webhook_url = @options.delete(:webhook_url)
+      raise ArgumentError.new "You must provide 'webhook_url' parameter." 
unless @webhook_url
+
+      unless @env.nil?
+        @controller = @env['action_controller.instance'] || 
MissingController.new
+
+        request = ActionDispatch::Request.new(@env)
+
+        @request_items = { url: request.original_url,
+                           http_method: request.method,
+                           ip_address: request.remote_ip,
+                           parameters: request.filtered_parameters,
+                           timestamp: Time.current }
+      else
+        @controller = @request_items = nil
+      end
+
+
+      @options[:body] = payload.to_json
+      @options[:headers] ||= {}
+      @options[:headers].merge!({ 'Content-Type' => 'application/json' })
+
+      @httparty.post(@webhook_url, @options)
+    end
+
+    private
+
+    def payload
+      {
+        text: exception_text
+      }
+    end
+
+    def header
+      errors_count = @options[:accumulated_errors_count].to_i
+      text = ['']
+
+      text << "Application: *#{@application_name}*"
+      text << "#{errors_count > 1 ? errors_count : 'An'} *#{@exception.class}* 
occured" + if @controller then " in *#{controller_and_method}*." else "." end
+
+      text
+    end
+
+    def exception_text
+      text = []
+
+      text << header
+      text << ''
+
+      text << "⚠️ Error 500 in #{Rails.env} ⚠️"
+      text << "*#{@exception.message.gsub('`', %q('))}*"
+
+      if @request_items
+        text << ''
+        text += message_request
+      end
+
+      if @backtrace
+        text << ''
+        text += message_backtrace
+      end
+
+      text.join("\n")
+    end
+
+    def message_request
+      text = []
+
+      text << "*Request:*"
+      text << "```"
+      text << hash_presentation(@request_items)
+      text << "```"
+
+      text
+    end
+
+    def hash_presentation(hash)
+      text = []
+
+      hash.each do |key, value|
+        text << "* #{key} : #{value}"
+      end
+
+      text.join("\n")
+    end
+
+    def message_backtrace(size = 3)
+      text = []
+
+      size = @backtrace.size < size ? @backtrace.size : size
+      text << "*Backtrace:*"
+      text << "```"
+      size.times { |i| text << "* " + @backtrace[i] }
+      text << "```"
+
+      text
+    end
+
+    def controller_and_method
+      if @controller
+        "#{@controller.controller_name}##{@controller.action_name}"
+      else
+        ""
+      end
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/exception_notifier/mattermost_notifier.rb 
new/lib/exception_notifier/mattermost_notifier.rb
--- old/lib/exception_notifier/mattermost_notifier.rb   2017-08-12 
22:52:29.000000000 +0200
+++ new/lib/exception_notifier/mattermost_notifier.rb   2018-11-22 
23:02:26.000000000 +0100
@@ -5,6 +5,11 @@
   class MattermostNotifier
     include ExceptionNotifier::BacktraceCleaner
 
+    class MissingController
+      def method_missing(*args, &block)
+      end
+    end
+
     attr_accessor :httparty
 
     def initialize(options = {})
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/exception_notifier/modules/error_grouping.rb 
new/lib/exception_notifier/modules/error_grouping.rb
--- old/lib/exception_notifier/modules/error_grouping.rb        2017-08-12 
22:52:29.000000000 +0200
+++ new/lib/exception_notifier/modules/error_grouping.rb        2018-11-22 
23:02:26.000000000 +0100
@@ -52,7 +52,7 @@
         else
           backtrace_based_key = 
"exception:#{Zlib.crc32("#{exception.class.name}\npath:#{exception.backtrace.try(:first)}")}"
 
-          if count = Rails.cache.read(backtrace_based_key)
+          if count = error_grouping_cache.read(backtrace_based_key)
             accumulated_errors_count = count + 1
             save_error_count(backtrace_based_key, accumulated_errors_count)
           else
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/exception_notifier/sns_notifier.rb 
new/lib/exception_notifier/sns_notifier.rb
--- old/lib/exception_notifier/sns_notifier.rb  1970-01-01 01:00:00.000000000 
+0100
+++ new/lib/exception_notifier/sns_notifier.rb  2018-11-22 23:02:26.000000000 
+0100
@@ -0,0 +1,79 @@
+module ExceptionNotifier
+  class SnsNotifier < BaseNotifier
+    def initialize(options)
+      super
+
+      raise ArgumentError.new "You must provide 'region' option" unless 
options[:region]
+      raise ArgumentError.new "You must provide 'access_key_id' option" unless 
options[:access_key_id]
+      raise ArgumentError.new "You must provide 'secret_access_key' option" 
unless options[:secret_access_key]
+
+      @notifier = Aws::SNS::Client.new(
+        region: options[:region],
+        access_key_id: options[:access_key_id],
+        secret_access_key: options[:secret_access_key]
+      )
+      @options = default_options.merge(options)
+    end
+
+    def call(exception, custom_opts = {})
+      custom_options = options.merge(custom_opts)
+
+      subject = build_subject(exception, custom_options)
+      message = build_message(exception, custom_options)
+
+      notifier.publish(
+        topic_arn: custom_options[:topic_arn],
+        message: message,
+        subject: subject
+      )
+    end
+
+    private
+
+    attr_reader :notifier, :options
+
+    def build_subject(exception, options)
+      subject = "#{options[:sns_prefix]} - "
+      subject << accumulated_exception_name(exception, options)
+      subject << " occurred"
+      subject.length > 120 ? subject[0...120] + "..." : subject
+    end
+
+    def build_message(exception, options)
+      exception_name = accumulated_exception_name(exception, options)
+
+      if options[:env].nil?
+        text = "#{exception_name} occured in background\n"
+      else
+        env = options[:env]
+
+        kontroller = env['action_controller.instance']
+        request = "#{env['REQUEST_METHOD']} <#{env['REQUEST_URI']}>"
+
+        text = "#{exception_name} occurred while #{request}"
+        text += " was processed by 
#{kontroller.controller_name}##{kontroller.action_name}\n" if kontroller
+      end
+
+      text += "Exception: #{exception.message}\n"
+      text += "Hostname: #{Socket.gethostname}\n"
+
+      if exception.backtrace
+        formatted_backtrace = 
"#{exception.backtrace.first(options[:backtrace_lines]).join("\n")}"
+        text += "Backtrace:\n#{formatted_backtrace}\n"
+      end
+    end
+
+    def accumulated_exception_name(exception, options)
+      errors_count = options[:accumulated_errors_count].to_i
+      measure_word = errors_count > 1 ? errors_count : (exception.class.to_s 
=~ /^[aeiou]/i ? 'An' : 'A')
+      "#{measure_word} #{exception.class.to_s}"
+    end
+
+    def default_options
+      {
+        sns_prefix: '[ERROR]',
+        backtrace_lines: 10
+      }
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/exception_notifier/teams_notifier.rb 
new/lib/exception_notifier/teams_notifier.rb
--- old/lib/exception_notifier/teams_notifier.rb        1970-01-01 
01:00:00.000000000 +0100
+++ new/lib/exception_notifier/teams_notifier.rb        2018-11-22 
23:02:26.000000000 +0100
@@ -0,0 +1,179 @@
+require 'action_dispatch'
+require 'active_support/core_ext/time'
+
+module ExceptionNotifier
+  class TeamsNotifier < BaseNotifier
+    include ExceptionNotifier::BacktraceCleaner
+
+    class MissingController
+      def method_missing(*args, &block)
+      end
+    end
+
+    attr_accessor :httparty
+
+    def initialize(options = {})
+      super
+      @default_options = options
+      @httparty = HTTParty
+    end
+
+    def call(exception, options={})
+      @options = options.merge(@default_options)
+      @exception = exception
+      @backtrace = exception.backtrace ? clean_backtrace(exception) : nil
+
+      @env = @options.delete(:env)
+
+      @application_name = @options.delete(:app_name) || 
Rails.application.class.parent_name.underscore
+      @gitlab_url = @options.delete(:git_url)
+      @jira_url = @options.delete(:jira_url)
+
+      @webhook_url = @options.delete(:webhook_url)
+      raise ArgumentError.new "You must provide 'webhook_url' parameter." 
unless @webhook_url
+
+      unless @env.nil?
+        @controller = @env['action_controller.instance'] || 
MissingController.new
+
+        request = ActionDispatch::Request.new(@env)
+
+        @request_items = { url: request.original_url,
+                           http_method: request.method,
+                           ip_address: request.remote_ip,
+                           parameters: request.filtered_parameters,
+                           timestamp: Time.current }
+
+        if request.session["warden.user.user.key"]
+          current_user = 
User.find(request.session["warden.user.user.key"][0][0])
+          @request_items.merge!({ current_user: { id: current_user.id, email: 
current_user.email  } })
+        end
+      else
+        @controller = @request_items = nil
+      end
+
+      payload = message_text
+
+      @options[:body] = payload.to_json
+      @options[:headers] ||= {}
+      @options[:headers].merge!({ 'Content-Type' => 'application/json' })
+      @options[:debug_output] = $stdout
+
+      @httparty.post(@webhook_url, @options)
+    end
+
+    private
+
+    def message_text
+      errors_count = @options[:accumulated_errors_count].to_i
+
+      text = {
+        "@type" => "MessageCard",
+        "@context" => "http://schema.org/extensions";,
+        "summary" => "#{@application_name} Exception Alert",
+        "title" => "⚠️ Exception Occurred in #{Rails.env} ⚠️",
+        "sections" => [
+          {
+            "activityTitle" => "#{errors_count > 1 ? errors_count : 'A'} 
*#{@exception.class}* occurred" + if @controller then " in 
*#{controller_and_method}*." else "." end,
+            "activitySubtitle" => "#{@exception.message}"
+          }
+        ],
+        "potentialAction" => []
+      }
+
+      text['sections'].push details
+      text['potentialAction'].push gitlab_view_link unless @gitlab_url.nil?
+      text['potentialAction'].push gitlab_issue_link unless @gitlab_url.nil?
+      text['potentialAction'].push jira_issue_link unless @jira_url.nil?
+
+      text
+    end
+
+    def details
+      details = {
+        "title" => "Details",
+        "facts" => []
+      }
+
+      details['facts'].push message_request unless @request_items.nil?
+      details['facts'].push message_backtrace unless @backtrace.nil?
+
+      details
+    end
+
+    def message_request
+      {
+        "name" => "Request",
+        "value" => "#{hash_presentation(@request_items)}\n  "
+      }
+    end
+
+    def message_backtrace(size = 3)
+      text = []
+      size = @backtrace.size < size ? @backtrace.size : size
+      text << "```"
+      size.times { |i| text << "* " + @backtrace[i] }
+      text << "```"
+
+      {
+        "name" => "Backtrace",
+        "value" => "#{text.join("  \n")}"
+      }
+    end
+
+    def gitlab_view_link
+      {
+        "@type" => "ViewAction",
+        "name" => "🦊 View in GitLab",
+        "target" => [
+          "#{@gitlab_url}/#{@application_name}"
+        ]
+      }
+    end
+
+    def gitlab_issue_link
+      link = [@gitlab_url, @application_name, "issues", "new"].join("/")
+      params = {
+        "issue[title]" => ["[BUG] Error 500 :",
+                           controller_and_method,
+                           "(#{@exception.class})",
+                           @exception.message].compact.join(" ")
+      }.to_query
+
+      {
+        "@type" => "ViewAction",
+        "name" => "🦊 Create Issue in GitLab",
+        "target" => [
+          "#{link}/?#{params}"
+      ]
+      }
+    end
+
+    def jira_issue_link
+      {
+        "@type" => "ViewAction",
+        "name" => "🐞 Create Issue in Jira",
+        "target" => [
+          "#{@jira_url}/secure/CreateIssue!default.jspa"
+      ]
+      }
+    end
+
+    def controller_and_method
+      if @controller
+        "#{@controller.controller_name}##{@controller.action_name}"
+      else
+        ""
+      end
+    end
+
+    def hash_presentation(hash)
+      text = []
+
+      hash.each do |key, value|
+        text << "* **#{key}** : `#{value}`"
+      end
+
+      text.join("  \n")
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lib/exception_notifier/views/exception_notifier/background_exception_notification.text.erb
 
new/lib/exception_notifier/views/exception_notifier/background_exception_notification.text.erb
--- 
old/lib/exception_notifier/views/exception_notifier/background_exception_notification.text.erb
      2017-08-12 22:52:29.000000000 +0200
+++ 
new/lib/exception_notifier/views/exception_notifier/background_exception_notification.text.erb
      2018-11-22 23:02:26.000000000 +0100
@@ -3,12 +3,12 @@
   <%= @exception.message %>
   <%= @backtrace.first %>
 
-  <%  sections = @sections.map do |section|
-        summary = render(section).strip
-        unless summary.blank?
-          title = render("title", :title => section).strip
-          "#{title}\n\n#{summary.gsub(/^/, "  ")}\n\n"
-        end
-      end.join
-  %>
-  <%= raw sections %>
+<%  sections = @sections.map do |section|
+      summary = render(section).strip
+      unless summary.blank?
+        title = render("title", :title => section).strip
+        "#{title}\n\n#{summary.gsub(/^/, "  ")}\n\n"
+      end
+    end.join
+%>
+<%= raw sections %>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/exception_notifier.rb 
new/lib/exception_notifier.rb
--- old/lib/exception_notifier.rb       2017-08-12 22:52:29.000000000 +0200
+++ new/lib/exception_notifier.rb       2018-11-22 23:02:26.000000000 +0100
@@ -17,6 +17,9 @@
   autoload :IrcNotifier, 'exception_notifier/irc_notifier'
   autoload :SlackNotifier, 'exception_notifier/slack_notifier'
   autoload :MattermostNotifier, 'exception_notifier/mattermost_notifier'
+  autoload :TeamsNotifier, 'exception_notifier/teams_notifier'
+  autoload :SnsNotifier, 'exception_notifier/sns_notifier'
+  autoload :GoogleChatNotifier, 'exception_notifier/google_chat_notifier'
 
   class UndefinedNotifierError < StandardError; end
 
@@ -42,7 +45,7 @@
       self.testing_mode = true
     end
 
-    def notify_exception(exception, options={})
+    def notify_exception(exception, options={}, &block)
       return false if ignored_exception?(options[:ignore_exceptions], 
exception)
       return false if ignored?(exception, options)
       if error_grouping
@@ -52,7 +55,7 @@
 
       selected_notifiers = options.delete(:notifiers) || notifiers
       [*selected_notifiers].each do |notifier|
-        fire_notification(notifier, exception, options.dup)
+        fire_notification(notifier, exception, options.dup, &block)
       end
       true
     end
@@ -104,12 +107,14 @@
     end
 
     def ignored_exception?(ignore_array, exception)
-      (Array(ignored_exceptions) + 
Array(ignore_array)).map(&:to_s).include?(exception.class.name)
+      all_ignored_exceptions = (Array(ignored_exceptions) + 
Array(ignore_array)).map(&:to_s)
+      exception_ancestors = exception.class.ancestors.map(&:to_s)
+      !(all_ignored_exceptions & exception_ancestors).empty?
     end
 
-    def fire_notification(notifier_name, exception, options)
+    def fire_notification(notifier_name, exception, options, &block)
       notifier = registered_exception_notifier(notifier_name)
-      notifier.call(exception, options)
+      notifier.call(exception, options, &block)
     rescue Exception => e
       raise e if @@testing_mode
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/metadata new/metadata
--- old/metadata        2017-08-12 22:52:29.000000000 +0200
+++ new/metadata        2018-11-22 23:02:26.000000000 +0100
@@ -1,7 +1,7 @@
 --- !ruby/object:Gem::Specification
 name: exception_notification
 version: !ruby/object:Gem::Version
-  version: 4.2.2
+  version: 4.3.0
 platform: ruby
 authors:
 - Jamis Buck
@@ -9,7 +9,7 @@
 autorequire: 
 bindir: bin
 cert_chain: []
-date: 2017-08-12 00:00:00.000000000 Z
+date: 2018-11-22 00:00:00.000000000 Z
 dependencies:
 - !ruby/object:Gem::Dependency
   name: actionmailer
@@ -231,6 +231,20 @@
     - - ">="
       - !ruby/object:Gem::Version
         version: 1.0.0
+- !ruby/object:Gem::Dependency
+  name: aws-sdk-sns
+  requirement: !ruby/object:Gem::Requirement
+    requirements:
+    - - "~>"
+      - !ruby/object:Gem::Version
+        version: '1'
+  type: :development
+  prerelease: false
+  version_requirements: !ruby/object:Gem::Requirement
+    requirements:
+    - - "~>"
+      - !ruby/object:Gem::Version
+        version: '1'
 description: 
 email: [email protected]
 executables: []
@@ -256,6 +270,7 @@
 - gemfiles/rails4_1.gemfile
 - gemfiles/rails4_2.gemfile
 - gemfiles/rails5_0.gemfile
+- gemfiles/rails5_1.gemfile
 - lib/exception_notification.rb
 - lib/exception_notification/rack.rb
 - lib/exception_notification/rails.rb
@@ -265,6 +280,7 @@
 - lib/exception_notifier/base_notifier.rb
 - lib/exception_notifier/campfire_notifier.rb
 - lib/exception_notifier/email_notifier.rb
+- lib/exception_notifier/google_chat_notifier.rb
 - lib/exception_notifier/hipchat_notifier.rb
 - lib/exception_notifier/irc_notifier.rb
 - lib/exception_notifier/mattermost_notifier.rb
@@ -272,6 +288,8 @@
 - lib/exception_notifier/modules/error_grouping.rb
 - lib/exception_notifier/notifier.rb
 - lib/exception_notifier/slack_notifier.rb
+- lib/exception_notifier/sns_notifier.rb
+- lib/exception_notifier/teams_notifier.rb
 - lib/exception_notifier/views/exception_notifier/_backtrace.html.erb
 - lib/exception_notifier/views/exception_notifier/_backtrace.text.erb
 - lib/exception_notifier/views/exception_notifier/_data.html.erb
@@ -346,12 +364,15 @@
 - test/exception_notification/rack_test.rb
 - test/exception_notifier/campfire_notifier_test.rb
 - test/exception_notifier/email_notifier_test.rb
+- test/exception_notifier/google_chat_notifier_test.rb
 - test/exception_notifier/hipchat_notifier_test.rb
 - test/exception_notifier/irc_notifier_test.rb
 - test/exception_notifier/mattermost_notifier_test.rb
 - test/exception_notifier/modules/error_grouping_test.rb
 - test/exception_notifier/sidekiq_test.rb
 - test/exception_notifier/slack_notifier_test.rb
+- test/exception_notifier/sns_notifier_test.rb
+- test/exception_notifier/teams_notifier_test.rb
 - test/exception_notifier/webhook_notifier_test.rb
 - test/exception_notifier_test.rb
 - test/test_helper.rb
@@ -375,7 +396,7 @@
       version: 1.8.11
 requirements: []
 rubyforge_project: 
-rubygems_version: 2.5.1
+rubygems_version: 2.5.2
 signing_key: 
 specification_version: 4
 summary: Exception notification for Rails apps
@@ -435,12 +456,15 @@
 - test/exception_notification/rack_test.rb
 - test/exception_notifier/campfire_notifier_test.rb
 - test/exception_notifier/email_notifier_test.rb
+- test/exception_notifier/google_chat_notifier_test.rb
 - test/exception_notifier/hipchat_notifier_test.rb
 - test/exception_notifier/irc_notifier_test.rb
 - test/exception_notifier/mattermost_notifier_test.rb
 - test/exception_notifier/modules/error_grouping_test.rb
 - test/exception_notifier/sidekiq_test.rb
 - test/exception_notifier/slack_notifier_test.rb
+- test/exception_notifier/sns_notifier_test.rb
+- test/exception_notifier/teams_notifier_test.rb
 - test/exception_notifier/webhook_notifier_test.rb
 - test/exception_notifier_test.rb
 - test/test_helper.rb
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/exception_notifier/google_chat_notifier_test.rb 
new/test/exception_notifier/google_chat_notifier_test.rb
--- old/test/exception_notifier/google_chat_notifier_test.rb    1970-01-01 
01:00:00.000000000 +0100
+++ new/test/exception_notifier/google_chat_notifier_test.rb    2018-11-22 
23:02:26.000000000 +0100
@@ -0,0 +1,128 @@
+require 'test_helper'
+require 'httparty'
+
+class GoogleChatNotifierTest < ActiveSupport::TestCase
+
+  test "should send notification if properly configured" do
+    options = {
+      :webhook_url => 'http://localhost:8000'
+    }
+    google_chat_notifier = ExceptionNotifier::GoogleChatNotifier.new
+    google_chat_notifier.httparty = FakeHTTParty.new
+
+    options = google_chat_notifier.call ArgumentError.new("foo"), options
+
+    body = ActiveSupport::JSON.decode options[:body]
+    assert body.has_key? 'text'
+
+    text = body['text'].split("\n")
+    assert_equal 6, text.size
+    assert_equal 'Application: *dummy*', text[1]
+    assert_equal 'An *ArgumentError* occured.', text[2]
+    assert_equal '*foo*', text[5]
+  end
+
+  test "should use 'An' for exceptions count if :accumulated_errors_count 
option is nil" do
+    google_chat_notifier = ExceptionNotifier::GoogleChatNotifier.new
+    exception = ArgumentError.new("foo")
+    google_chat_notifier.instance_variable_set(:@exception, exception)
+    google_chat_notifier.instance_variable_set(:@options, {})
+
+    assert_includes google_chat_notifier.send(:header), "An *ArgumentError* 
occured."
+  end
+
+  test "shoud use direct errors count if :accumulated_errors_count option is 
5" do
+    google_chat_notifier = ExceptionNotifier::GoogleChatNotifier.new
+    exception = ArgumentError.new("foo")
+    google_chat_notifier.instance_variable_set(:@exception, exception)
+    google_chat_notifier.instance_variable_set(:@options, { 
accumulated_errors_count: 5 })
+
+    assert_includes google_chat_notifier.send(:header), "5 *ArgumentError* 
occured."
+  end
+
+  test "Message request should be formatted as hash" do
+    google_chat_notifier = ExceptionNotifier::GoogleChatNotifier.new
+    request_items = { url: 'http://test.address',
+                      http_method: :get,
+                      ip_address: '127.0.0.1',
+                      parameters: '{"id"=>"foo"}',
+                      timestamp: Time.parse('2018-08-13 12:13:24 UTC') }
+    google_chat_notifier.instance_variable_set(:@request_items, request_items)
+
+    message_request =  google_chat_notifier.send(:message_request).join("\n")
+    assert_includes message_request, '* url : http://test.address'
+    assert_includes message_request, '* http_method : get'
+    assert_includes message_request, '* ip_address : 127.0.0.1'
+    assert_includes message_request, '* parameters : {"id"=>"foo"}'
+    assert_includes message_request, '* timestamp : 2018-08-13 12:13:24 UTC'
+  end
+
+  test 'backtrace with less than 3 lines should be displayed fully' do
+    google_chat_notifier = ExceptionNotifier::GoogleChatNotifier.new
+
+    backtrace = ["app/controllers/my_controller.rb:53:in 
`my_controller_params'", "app/controllers/my_controller.rb:34:in `update'"]
+    google_chat_notifier.instance_variable_set(:@backtrace, backtrace)
+
+    message_backtrace =  
google_chat_notifier.send(:message_backtrace).join("\n")
+    assert_includes message_backtrace, "* 
app/controllers/my_controller.rb:53:in `my_controller_params'"
+    assert_includes message_backtrace, "* 
app/controllers/my_controller.rb:34:in `update'"
+  end
+
+  test 'backtrace with more than 3 lines should display only top 3 lines' do
+    google_chat_notifier = ExceptionNotifier::GoogleChatNotifier.new
+
+    backtrace = ["app/controllers/my_controller.rb:99:in `specific_function'", 
"app/controllers/my_controller.rb:70:in `specific_param'", 
"app/controllers/my_controller.rb:53:in `my_controller_params'", 
"app/controllers/my_controller.rb:34:in `update'"]
+    google_chat_notifier.instance_variable_set(:@backtrace, backtrace)
+
+    message_backtrace =  
google_chat_notifier.send(:message_backtrace).join("\n")
+    assert_includes message_backtrace, "* 
app/controllers/my_controller.rb:99:in `specific_function'"
+    assert_includes message_backtrace, "* 
app/controllers/my_controller.rb:70:in `specific_param'"
+    assert_includes message_backtrace, "* 
app/controllers/my_controller.rb:53:in `my_controller_params'"
+    assert_not_includes message_backtrace, "* 
app/controllers/my_controller.rb:34:in `update'"
+  end
+
+  test 'Get text with backtrace and request info' do
+    google_chat_notifier = ExceptionNotifier::GoogleChatNotifier.new
+
+    backtrace = ["app/controllers/my_controller.rb:53:in 
`my_controller_params'", "app/controllers/my_controller.rb:34:in `update'"]
+    google_chat_notifier.instance_variable_set(:@backtrace, backtrace)
+
+    request_items = { url: 'http://test.address',
+                      http_method: :get,
+                      ip_address: '127.0.0.1',
+                      parameters: '{"id"=>"foo"}',
+                      timestamp: Time.parse('2018-08-13 12:13:24 UTC') }
+    google_chat_notifier.instance_variable_set(:@request_items, request_items)
+
+    google_chat_notifier.instance_variable_set(:@options, 
{accumulated_errors_count: 0})
+
+    google_chat_notifier.instance_variable_set(:@application_name, 'dummy')
+
+    exception = ArgumentError.new("foo")
+    google_chat_notifier.instance_variable_set(:@exception, exception)
+
+    text = google_chat_notifier.send(:exception_text)
+    expected_text = %q(
+Application: *dummy*
+An *ArgumentError* occured.
+
+⚠️ Error 500 in test ⚠️
+*foo*
+
+*Request:*
+```
+* url : http://test.address
+* http_method : get
+* ip_address : 127.0.0.1
+* parameters : {"id"=>"foo"}
+* timestamp : 2018-08-13 12:13:24 UTC
+```
+
+*Backtrace:*
+```
+* app/controllers/my_controller.rb:53:in `my_controller_params'
+* app/controllers/my_controller.rb:34:in `update'
+```)
+    assert_equal text, expected_text
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/test/exception_notifier/modules/error_grouping_test.rb 
new/test/exception_notifier/modules/error_grouping_test.rb
--- old/test/exception_notifier/modules/error_grouping_test.rb  2017-08-12 
22:52:29.000000000 +0200
+++ new/test/exception_notifier/modules/error_grouping_test.rb  2018-11-22 
23:02:26.000000000 +0100
@@ -5,7 +5,7 @@
   setup do
     module TestModule
       include ExceptionNotifier::ErrorGrouping
-      @@error_grouping_cache = 
ActiveSupport::Cache::FileStore.new("test/dummy/tmp/cache")
+      @@error_grouping_cache = 
ActiveSupport::Cache::FileStore.new("test/dummy/tmp/non_default_location")
     end
 
     @exception = RuntimeError.new("ERROR")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/exception_notifier/sns_notifier_test.rb 
new/test/exception_notifier/sns_notifier_test.rb
--- old/test/exception_notifier/sns_notifier_test.rb    1970-01-01 
01:00:00.000000000 +0100
+++ new/test/exception_notifier/sns_notifier_test.rb    2018-11-22 
23:02:26.000000000 +0100
@@ -0,0 +1,126 @@
+require 'test_helper'
+require 'aws-sdk-sns'
+
+class SnsNotifierTest < ActiveSupport::TestCase
+  def setup
+    @exception = fake_exception
+    @exception.stubs(:class).returns('MyException')
+    @exception.stubs(:backtrace).returns(fake_backtrace)
+    @exception.stubs(:message).returns("undefined method 'method=' for Empty")
+    @options = {
+      access_key_id: 'my-access_key_id',
+      secret_access_key: 'my-secret_access_key',
+      region: 'us-east',
+      topic_arn: 'topicARN',
+      sns_prefix: '[App Exception]',
+    }
+    Socket.stubs(:gethostname).returns('example.com')
+  end
+
+  # initialize
+
+  test 'should initialize aws notifier with received params' do
+    Aws::SNS::Client.expects(:new).with(
+      region: 'us-east',
+      access_key_id: 'my-access_key_id',
+      secret_access_key: 'my-secret_access_key'
+    )
+
+    ExceptionNotifier::SnsNotifier.new(@options)
+  end
+
+  test 'should raise an exception if region is not received' do
+    @options[:region] = nil
+
+    error = assert_raises ArgumentError do
+      ExceptionNotifier::SnsNotifier.new(@options)
+    end
+    assert_equal "You must provide 'region' option", error.message
+  end
+
+  test 'should raise an exception on publish if access_key_id is not received' 
do
+    @options[:access_key_id] = nil
+    error = assert_raises ArgumentError do
+      ExceptionNotifier::SnsNotifier.new(@options)
+    end
+
+    assert_equal "You must provide 'access_key_id' option", error.message
+  end
+
+  test 'should raise an exception on publish if secret_access_key is not 
received' do
+    @options[:secret_access_key] = nil
+    error = assert_raises ArgumentError do
+      ExceptionNotifier::SnsNotifier.new(@options)
+    end
+
+    assert_equal "You must provide 'secret_access_key' option", error.message
+  end
+
+  # call
+
+  test 'should send a sns notification in background' do
+    Aws::SNS::Client.any_instance.expects(:publish).with(
+      {
+      topic_arn: "topicARN",
+      message: "3 MyException occured in background\n"\
+               "Exception: undefined method 'method=' for Empty\n"\
+               "Hostname: example.com\n"\
+               "Backtrace:\n#{fake_backtrace.join("\n")}\n",
+      subject: "[App Exception] - 3 MyException occurred"
+    })
+
+    sns_notifier = ExceptionNotifier::SnsNotifier.new(@options)
+    sns_notifier.call(@exception, { accumulated_errors_count: 3 })
+  end
+
+  test 'should send a sns notification with controller#action information' do
+    ExamplesController.any_instance.stubs(:action_name).returns('index')
+
+    Aws::SNS::Client.any_instance.expects(:publish).with(
+      {
+      topic_arn: "topicARN",
+      message: "A MyException occurred while GET </examples> "\
+               "was processed by examples#index\n"\
+               "Exception: undefined method 'method=' for Empty\n"\
+               "Hostname: example.com\n"\
+               "Backtrace:\n#{fake_backtrace.join("\n")}\n",
+      subject: "[App Exception] - A MyException occurred"
+    })
+
+    sns_notifier = ExceptionNotifier::SnsNotifier.new(@options)
+    sns_notifier.call(@exception,
+      env: {
+        'REQUEST_METHOD' => 'GET',
+        'REQUEST_URI' => '/examples',
+        'action_controller.instance' => ExamplesController.new
+      }
+    )
+  end
+
+  private
+
+  class ExamplesController < ActionController::Base; end
+
+  def fake_exception
+    begin
+      1 / 0
+    rescue Exception => e
+      e
+    end
+  end
+
+  def fake_exception_without_backtrace
+    StandardError.new('my custom error')
+  end
+
+  def fake_backtrace
+    [
+      'backtrace line 1',
+      'backtrace line 2',
+      'backtrace line 3',
+      'backtrace line 4',
+      'backtrace line 5',
+      'backtrace line 6'
+    ]
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/exception_notifier/teams_notifier_test.rb 
new/test/exception_notifier/teams_notifier_test.rb
--- old/test/exception_notifier/teams_notifier_test.rb  1970-01-01 
01:00:00.000000000 +0100
+++ new/test/exception_notifier/teams_notifier_test.rb  2018-11-22 
23:02:26.000000000 +0100
@@ -0,0 +1,93 @@
+require 'test_helper'
+require 'httparty'
+
+class TeamsNotifierTest < ActiveSupport::TestCase
+
+  test "should send notification if properly configured" do
+    options = {
+      :webhook_url => 'http://localhost:8000'
+    }
+    teams_notifier = ExceptionNotifier::TeamsNotifier.new
+    teams_notifier.httparty = FakeHTTParty.new
+
+    options = teams_notifier.call ArgumentError.new("foo"), options
+
+    body = ActiveSupport::JSON.decode options[:body]
+    assert body.has_key? 'title'
+    assert body.has_key? 'sections'
+
+    sections = body['sections']
+    header = sections[0]
+
+    assert_equal 2, sections.size
+    assert_equal 'A *ArgumentError* occurred.', header['activityTitle']
+    assert_equal 'foo', header['activitySubtitle']
+  end
+
+  test "should send notification with create gitlab issue link if specified" do
+    options = {
+      :webhook_url => 'http://localhost:8000',
+      :git_url => 'github.com/aschen'
+    }
+    teams_notifier = ExceptionNotifier::TeamsNotifier.new
+    teams_notifier.httparty = FakeHTTParty.new
+
+    options = teams_notifier.call ArgumentError.new("foo"), options
+
+    body = ActiveSupport::JSON.decode options[:body]
+
+    potential_action = body['potentialAction']
+    assert_equal 2, potential_action.size
+    assert_equal '🦊 View in GitLab', potential_action[0]['name']
+    assert_equal '🦊 Create Issue in GitLab', potential_action[1]['name']
+  end
+
+  test 'should add other HTTParty options to params' do
+    options = {
+      :webhook_url => 'http://localhost:8000',
+      :username => "Test Bot",
+      :avatar => 'http://site.com/icon.png',
+      :basic_auth => {
+        :username => 'clara',
+        :password => 'password'
+      }
+    }
+    teams_notifier = ExceptionNotifier::TeamsNotifier.new
+    teams_notifier.httparty = FakeHTTParty.new
+
+    options = teams_notifier.call ArgumentError.new("foo"), options
+
+    assert options.has_key? :basic_auth
+    assert 'clara', options[:basic_auth][:username]
+    assert 'password', options[:basic_auth][:password]
+  end
+
+  test "should use 'A' for exceptions count if :accumulated_errors_count 
option is nil" do
+    teams_notifier = ExceptionNotifier::TeamsNotifier.new
+    exception = ArgumentError.new("foo")
+    teams_notifier.instance_variable_set(:@exception, exception)
+    teams_notifier.instance_variable_set(:@options, {})
+
+    message_text = teams_notifier.send(:message_text)
+    header = message_text['sections'][0]
+    assert_equal 'A *ArgumentError* occurred.', header['activityTitle']
+  end
+
+  test "should use direct errors count if :accumulated_errors_count option is 
5" do
+    teams_notifier = ExceptionNotifier::TeamsNotifier.new
+    exception = ArgumentError.new("foo")
+    teams_notifier.instance_variable_set(:@exception, exception)
+    teams_notifier.instance_variable_set(:@options, { 
accumulated_errors_count: 5 })
+    message_text = teams_notifier.send(:message_text)
+    header = message_text['sections'][0]
+    assert_equal '5 *ArgumentError* occurred.', header['activityTitle']
+  end
+end
+
+class FakeHTTParty
+
+  def post(url, options)
+    return options
+  end
+
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/exception_notifier_test.rb 
new/test/exception_notifier_test.rb
--- old/test/exception_notifier_test.rb 2017-08-12 22:52:30.000000000 +0200
+++ new/test/exception_notifier_test.rb 2018-11-22 23:02:26.000000000 +0100
@@ -110,6 +110,35 @@
     assert_equal @notifier_calls, 1
   end
 
+  test "should not send notification if subclass of one of ignored exceptions" 
do
+    ExceptionNotifier.register_exception_notifier(:test, @test_notifier)
+
+    class StandardErrorSubclass < StandardError
+    end
+
+    exception = StandardErrorSubclass.new
+
+    ExceptionNotifier.notify_exception(exception, {:notifiers => :test})
+    assert_equal @notifier_calls, 1
+
+    ExceptionNotifier.notify_exception(exception, {:notifiers => :test, 
:ignore_exceptions => 'StandardError' })
+    assert_equal @notifier_calls, 1
+  end
+
+  test "should call received block" do
+    @block_called = false
+    notifier = lambda { |exception, options, &block| block.call }
+    ExceptionNotifier.register_exception_notifier(:test, notifier)
+
+    exception = ExceptionOne.new
+
+    ExceptionNotifier.notify_exception(exception) do
+      @block_called = true
+    end
+
+    assert @block_called
+  end
+
   test "should not call group_error! or send_notification? if error_grouping 
false" do
     exception = StandardError.new
     ExceptionNotifier.expects(:group_error!).never


Reply via email to