Commit 5e0a95c39d6ca1107461a3e90eae85a7507bc641

Authored by Marvin Frederickson
2 parents 734913ca 8c05e867
Exists in master

merged upstream

1 source 'https://rubygems.org' 1 source 'https://rubygems.org'
2 2
3 -RAILS_VERSION = '~> 4.2.5.1' 3 +RAILS_VERSION = '~> 4.2.5.2'
4 4
5 send :ruby, ENV['GEMFILE_RUBY_VERSION'] if ENV['GEMFILE_RUBY_VERSION'] 5 send :ruby, ENV['GEMFILE_RUBY_VERSION'] if ENV['GEMFILE_RUBY_VERSION']
6 6
1 GEM 1 GEM
2 remote: https://rubygems.org/ 2 remote: https://rubygems.org/
3 specs: 3 specs:
4 - actionmailer (4.2.5.1)  
5 - actionpack (= 4.2.5.1)  
6 - actionview (= 4.2.5.1)  
7 - activejob (= 4.2.5.1) 4 + actionmailer (4.2.5.2)
  5 + actionpack (= 4.2.5.2)
  6 + actionview (= 4.2.5.2)
  7 + activejob (= 4.2.5.2)
8 mail (~> 2.5, >= 2.5.4) 8 mail (~> 2.5, >= 2.5.4)
9 rails-dom-testing (~> 1.0, >= 1.0.5) 9 rails-dom-testing (~> 1.0, >= 1.0.5)
10 actionmailer_inline_css (1.5.3) 10 actionmailer_inline_css (1.5.3)
11 actionmailer (>= 3.0.0) 11 actionmailer (>= 3.0.0)
12 nokogiri (>= 1.4.4) 12 nokogiri (>= 1.4.4)
13 premailer (>= 1.7.1) 13 premailer (>= 1.7.1)
14 - actionpack (4.2.5.1)  
15 - actionview (= 4.2.5.1)  
16 - activesupport (= 4.2.5.1) 14 + actionpack (4.2.5.2)
  15 + actionview (= 4.2.5.2)
  16 + activesupport (= 4.2.5.2)
17 rack (~> 1.6) 17 rack (~> 1.6)
18 rack-test (~> 0.6.2) 18 rack-test (~> 0.6.2)
19 rails-dom-testing (~> 1.0, >= 1.0.5) 19 rails-dom-testing (~> 1.0, >= 1.0.5)
20 rails-html-sanitizer (~> 1.0, >= 1.0.2) 20 rails-html-sanitizer (~> 1.0, >= 1.0.2)
21 - actionview (4.2.5.1)  
22 - activesupport (= 4.2.5.1) 21 + actionview (4.2.5.2)
  22 + activesupport (= 4.2.5.2)
23 builder (~> 3.1) 23 builder (~> 3.1)
24 erubis (~> 2.7.0) 24 erubis (~> 2.7.0)
25 rails-dom-testing (~> 1.0, >= 1.0.5) 25 rails-dom-testing (~> 1.0, >= 1.0.5)
26 rails-html-sanitizer (~> 1.0, >= 1.0.2) 26 rails-html-sanitizer (~> 1.0, >= 1.0.2)
27 - activejob (4.2.5.1)  
28 - activesupport (= 4.2.5.1) 27 + activejob (4.2.5.2)
  28 + activesupport (= 4.2.5.2)
29 globalid (>= 0.3.0) 29 globalid (>= 0.3.0)
30 - activemodel (4.2.5.1)  
31 - activesupport (= 4.2.5.1) 30 + activemodel (4.2.5.2)
  31 + activesupport (= 4.2.5.2)
32 builder (~> 3.1) 32 builder (~> 3.1)
33 - activerecord (4.2.5.1)  
34 - activemodel (= 4.2.5.1)  
35 - activesupport (= 4.2.5.1) 33 + activerecord (4.2.5.2)
  34 + activemodel (= 4.2.5.2)
  35 + activesupport (= 4.2.5.2)
36 arel (~> 6.0) 36 arel (~> 6.0)
37 - activesupport (4.2.5.1) 37 + activesupport (4.2.5.2)
38 i18n (~> 0.7) 38 i18n (~> 0.7)
39 json (~> 1.7, >= 1.7.7) 39 json (~> 1.7, >= 1.7.7)
40 minitest (~> 5.1) 40 minitest (~> 5.1)
@@ -89,8 +89,8 @@ GEM @@ -89,8 +89,8 @@ GEM
89 coderay (1.1.0) 89 coderay (1.1.0)
90 colorize (0.7.7) 90 colorize (0.7.7)
91 columnize (0.9.0) 91 columnize (0.9.0)
92 - concurrent-ruby (1.0.0)  
93 - concurrent-ruby (1.0.0-java) 92 + concurrent-ruby (1.0.1)
  93 + concurrent-ruby (1.0.1-java)
94 coveralls (0.8.2) 94 coveralls (0.8.2)
95 json (~> 1.8) 95 json (~> 1.8)
96 rest-client (>= 1.6.8, < 2) 96 rest-client (>= 1.6.8, < 2)
@@ -184,7 +184,7 @@ GEM @@ -184,7 +184,7 @@ GEM
184 rack-contrib (~> 1.1) 184 rack-contrib (~> 1.1)
185 railties (>= 3.0.0, < 5.0.0) 185 railties (>= 3.0.0, < 5.0.0)
186 method_source (0.8.2) 186 method_source (0.8.2)
187 - mime-types (2.99) 187 + mime-types (2.99.1)
188 mimemagic (0.3.0) 188 mimemagic (0.3.0)
189 mini_portile2 (2.0.0) 189 mini_portile2 (2.0.0)
190 minitest (5.8.4) 190 minitest (5.8.4)
@@ -261,8 +261,8 @@ GEM @@ -261,8 +261,8 @@ GEM
261 pry (~> 0.10) 261 pry (~> 0.10)
262 pry-rails (0.3.4) 262 pry-rails (0.3.4)
263 pry (>= 0.9.10) 263 pry (>= 0.9.10)
264 - puma (2.15.3)  
265 - puma (2.15.3-java) 264 + puma (3.1.0)
  265 + puma (3.1.0-java)
266 quiet_assets (1.1.0) 266 quiet_assets (1.1.0)
267 railties (>= 3.1, < 5.0) 267 railties (>= 3.1, < 5.0)
268 rack (1.6.4) 268 rack (1.6.4)
@@ -273,16 +273,16 @@ GEM @@ -273,16 +273,16 @@ GEM
273 rack-ssl-enforcer (0.2.8) 273 rack-ssl-enforcer (0.2.8)
274 rack-test (0.6.3) 274 rack-test (0.6.3)
275 rack (>= 1.0) 275 rack (>= 1.0)
276 - rails (4.2.5.1)  
277 - actionmailer (= 4.2.5.1)  
278 - actionpack (= 4.2.5.1)  
279 - actionview (= 4.2.5.1)  
280 - activejob (= 4.2.5.1)  
281 - activemodel (= 4.2.5.1)  
282 - activerecord (= 4.2.5.1)  
283 - activesupport (= 4.2.5.1) 276 + rails (4.2.5.2)
  277 + actionmailer (= 4.2.5.2)
  278 + actionpack (= 4.2.5.2)
  279 + actionview (= 4.2.5.2)
  280 + activejob (= 4.2.5.2)
  281 + activemodel (= 4.2.5.2)
  282 + activerecord (= 4.2.5.2)
  283 + activesupport (= 4.2.5.2)
284 bundler (>= 1.3.0, < 2.0) 284 bundler (>= 1.3.0, < 2.0)
285 - railties (= 4.2.5.1) 285 + railties (= 4.2.5.2)
286 sprockets-rails 286 sprockets-rails
287 rails-deprecated_sanitizer (1.0.3) 287 rails-deprecated_sanitizer (1.0.3)
288 activesupport (>= 4.2.0.alpha) 288 activesupport (>= 4.2.0.alpha)
@@ -299,9 +299,9 @@ GEM @@ -299,9 +299,9 @@ GEM
299 rails (> 3.1) 299 rails (> 3.1)
300 rails_serve_static_assets (0.0.4) 300 rails_serve_static_assets (0.0.4)
301 rails_stdout_logging (0.0.3) 301 rails_stdout_logging (0.0.3)
302 - railties (4.2.5.1)  
303 - actionpack (= 4.2.5.1)  
304 - activesupport (= 4.2.5.1) 302 + railties (4.2.5.2)
  303 + actionpack (= 4.2.5.2)
  304 + activesupport (= 4.2.5.2)
305 rake (>= 0.8.7) 305 rake (>= 0.8.7)
306 thor (>= 0.18.1, < 2.0) 306 thor (>= 0.18.1, < 2.0)
307 rainbow (2.0.0) 307 rainbow (2.0.0)
@@ -374,7 +374,7 @@ GEM @@ -374,7 +374,7 @@ GEM
374 sprockets (3.5.2) 374 sprockets (3.5.2)
375 concurrent-ruby (~> 1.0) 375 concurrent-ruby (~> 1.0)
376 rack (> 1, < 3) 376 rack (> 1, < 3)
377 - sprockets-rails (3.0.0) 377 + sprockets-rails (3.0.3)
378 actionpack (>= 4.0) 378 actionpack (>= 4.0)
379 activesupport (>= 4.0) 379 activesupport (>= 4.0)
380 sprockets (>= 3.0.0) 380 sprockets (>= 3.0.0)
@@ -421,9 +421,9 @@ PLATFORMS @@ -421,9 +421,9 @@ PLATFORMS
421 ruby 421 ruby
422 422
423 DEPENDENCIES 423 DEPENDENCIES
424 - actionmailer (~> 4.2.5.1) 424 + actionmailer (~> 4.2.5.2)
425 actionmailer_inline_css 425 actionmailer_inline_css
426 - actionpack (~> 4.2.5.1) 426 + actionpack (~> 4.2.5.2)
427 airbrake (~> 4.3.5) 427 airbrake (~> 4.3.5)
428 better_errors 428 better_errors
429 binding_of_caller 429 binding_of_caller
@@ -470,7 +470,7 @@ DEPENDENCIES @@ -470,7 +470,7 @@ DEPENDENCIES
470 rack-ssl-enforcer 470 rack-ssl-enforcer
471 rails_12factor 471 rails_12factor
472 rails_autolink 472 rails_autolink
473 - railties (~> 4.2.5.1) 473 + railties (~> 4.2.5.2)
474 ri_cal 474 ri_cal
475 rspec (~> 3.3) 475 rspec (~> 3.3)
476 rspec-activemodel-mocks 476 rspec-activemodel-mocks
@@ -122,7 +122,7 @@ If you host Errbit at errbit.example.com, you would fill in: @@ -122,7 +122,7 @@ If you host Errbit at errbit.example.com, you would fill in:
122 * After you have registered your app, set GITHUB_CLIENT_ID and GITHUB_SECRET 122 * After you have registered your app, set GITHUB_CLIENT_ID and GITHUB_SECRET
123 with your app's Client ID and Secret key. 123 with your app's Client ID and Secret key.
124 124
125 -When you start your applicatoin, you should see the option to **Sign in with 125 +When you start your application, you should see the option to **Sign in with
126 GitHub** on the Login page. You will also be able to link your GitHub profile 126 GitHub** on the Login page. You will also be able to link your GitHub profile
127 to your user account on your **Edit profile** page. 127 to your user account on your **Edit profile** page.
128 128
app/assets/stylesheets/errbit.css.erb
@@ -232,6 +232,14 @@ a.action { float: right; font-size: 0.9em;} @@ -232,6 +232,14 @@ a.action { float: right; font-size: 0.9em;}
232 232
233 #action-bar span.github a:before { font-family: FontAwesome; content: "\f09b"; margin-right: 8px; position: relative; top: 4px; font-size: 26px; } 233 #action-bar span.github a:before { font-family: FontAwesome; content: "\f09b"; margin-right: 8px; position: relative; top: 4px; font-size: 26px; }
234 234
  235 +#action-bar span a.issue-tracker-button {
  236 + padding-left: 5px;
  237 +}
  238 +
  239 +#action-bar span a.issue-tracker-button img {
  240 + padding-left: 10px;
  241 +}
  242 +
235 /* Content */ 243 /* Content */
236 #content { 244 #content {
237 padding: 20px; border-top: 1px solid #C6C6C6; 245 padding: 20px; border-top: 1px solid #C6C6C6;
app/controllers/apps_controller.rb
@@ -53,7 +53,7 @@ class AppsController &lt; ApplicationController @@ -53,7 +53,7 @@ class AppsController &lt; ApplicationController
53 if app.save 53 if app.save
54 redirect_to app_url(app), flash: { success: I18n.t('controllers.apps.flash.create.success') } 54 redirect_to app_url(app), flash: { success: I18n.t('controllers.apps.flash.create.success') }
55 else 55 else
56 - flash[:error] = I18n.t('controllers.apps.flash.create.error') 56 + flash.now[:error] = I18n.t('controllers.apps.flash.create.error')
57 render :new 57 render :new
58 end 58 end
59 end 59 end
@@ -63,7 +63,7 @@ class AppsController &lt; ApplicationController @@ -63,7 +63,7 @@ class AppsController &lt; ApplicationController
63 if app.save 63 if app.save
64 redirect_to app_url(app), flash: { success: I18n.t('controllers.apps.flash.update.success') } 64 redirect_to app_url(app), flash: { success: I18n.t('controllers.apps.flash.update.success') }
65 else 65 else
66 - flash[:error] = I18n.t('controllers.apps.flash.update.error') 66 + flash.now[:error] = I18n.t('controllers.apps.flash.update.error')
67 render :edit 67 render :edit
68 end 68 end
69 end 69 end
@@ -76,7 +76,7 @@ class AppsController &lt; ApplicationController @@ -76,7 +76,7 @@ class AppsController &lt; ApplicationController
76 if app.destroy 76 if app.destroy
77 redirect_to apps_url, flash: { success: I18n.t('controllers.apps.flash.destroy.success') } 77 redirect_to apps_url, flash: { success: I18n.t('controllers.apps.flash.destroy.success') }
78 else 78 else
79 - flash[:error] = I18n.t('controllers.apps.flash.destroy.error') 79 + flash.now[:error] = I18n.t('controllers.apps.flash.destroy.error')
80 render :show 80 render :show
81 end 81 end
82 end 82 end
@@ -97,7 +97,7 @@ protected @@ -97,7 +97,7 @@ protected
97 # set the app's notification service 97 # set the app's notification service
98 available_notification_classes = [NotificationService] + NotificationService.subclasses 98 available_notification_classes = [NotificationService] + NotificationService.subclasses
99 notification_class = available_notification_classes.detect { |c| c.name == notification_type } 99 notification_class = available_notification_classes.detect { |c| c.name == notification_type }
100 - if !notification_class.nil? 100 + unless notification_class.nil?
101 app.notification_service = notification_class.new(params[:app][:notification_service_attributes]) 101 app.notification_service = notification_class.new(params[:app][:notification_service_attributes])
102 end 102 end
103 end 103 end
app/controllers/users_controller.rb
@@ -6,7 +6,7 @@ class UsersController &lt; ApplicationController @@ -6,7 +6,7 @@ class UsersController &lt; ApplicationController
6 6
7 expose(:user, attributes: :user_params) 7 expose(:user, attributes: :user_params)
8 expose(:users) do 8 expose(:users) do
9 - User.all.page(params[:page]).per(current_user.per_page) 9 + User.order_by(name: :asc).page(params[:page]).per(current_user.per_page)
10 end 10 end
11 11
12 def index; end 12 def index; end
app/models/notification_services/slack_service.rb
@@ -19,41 +19,35 @@ class NotificationServices::SlackService &lt; NotificationService @@ -19,41 +19,35 @@ class NotificationServices::SlackService &lt; NotificationService
19 19
20 def post_payload(problem) 20 def post_payload(problem)
21 { 21 {
  22 + username: "Errbit",
  23 + icon_emoji: ":collision:",
22 attachments: [ 24 attachments: [
23 { 25 {
24 - fallback: message_for_slack(problem),  
25 - pretext: "<#{problem.url}|Errbit - #{problem.app.name}: #{problem.error_class}>",  
26 - color: "#D00000",  
27 - fields: [ 26 + fallback: message_for_slack(problem),
  27 + title: problem.message.to_s.truncate(100),
  28 + title_link: problem.url,
  29 + text: problem.where,
  30 + color: "#D00000",
  31 + fields: [
28 { 32 {
29 - title: "Environment",  
30 - value: problem.environment,  
31 - short: false 33 + title: "Application",
  34 + value: problem.app.name,
  35 + short: true
32 }, 36 },
33 { 37 {
34 - title: "Location",  
35 - value: problem.where,  
36 - short: false 38 + title: "Environment",
  39 + value: problem.environment,
  40 + short: true
37 }, 41 },
38 { 42 {
39 - title: "Message",  
40 - value: problem.message.to_s,  
41 - short: false 43 + title: "Times Occurred",
  44 + value: problem.notices_count,
  45 + short: true
42 }, 46 },
43 { 47 {
44 title: "First Noticed", 48 title: "First Noticed",
45 - value: problem.first_notice_at,  
46 - short: false  
47 - },  
48 - {  
49 - title: "Last Noticed",  
50 - value: problem.last_notice_at,  
51 - short: false  
52 - },  
53 - {  
54 - title: "Times Occurred",  
55 - value: problem.notices_count,  
56 - short: false 49 + value: problem.first_notice_at.try(:to_s, :db),
  50 + short: true
57 } 51 }
58 ] 52 ]
59 } 53 }
app/models/problem.rb
@@ -161,8 +161,8 @@ class Problem @@ -161,8 +161,8 @@ class Problem
161 app, 161 app,
162 self, 162 self,
163 protocol: Errbit::Config.protocol, 163 protocol: Errbit::Config.protocol,
164 - host: Errbit::Config.host,  
165 - port: Errbit::Config.port 164 + host: Errbit::Config.host,
  165 + port: Errbit::Config.port
166 ) 166 )
167 end 167 end
168 168
app/views/problems/_issue_tracker_links.html.haml
@@ -3,9 +3,13 @@ @@ -3,9 +3,13 @@
3 - tracker_type = tracker.type 3 - tracker_type = tracker.type
4 - if problem.issue_link.present? 4 - if problem.issue_link.present?
5 %span 5 %span
6 - %img.button-icon{"src" => tracker_type.icons[:create]}  
7 - = link_to 'go to issue', problem.issue_link, :class => "goto-issue"  
8 - = link_to 'unlink issue', unlink_issue_app_problem_path(app, problem), :method => :delete, :data => { :confirm => "Unlink err issues?" }, :class => "unlink-issue" 6 + = link_to problem.issue_link, :class => "goto-issue issue-tracker-button" do
  7 + %img.button-icon{"src" => tracker_type.icons[:goto]}
  8 + go to issue
  9 + %span
  10 + = link_to unlink_issue_app_problem_path(app, problem), :method => :delete, :data => { :confirm => "Unlink err issues?" }, :class => "unlink-issue issue-tracker-button" do
  11 + %img.button-icon{"src" => tracker_type.icons[:create]}
  12 + unlink issue
9 - if tracker.tracker.respond_to? :close_issue 13 - if tracker.tracker.respond_to? :close_issue
10 %span 14 %span
11 = link_to close_issue_app_problem_path(app, problem), method: :post, :class => "close-issue" do 15 = link_to close_issue_app_problem_path(app, problem), method: :post, :class => "close-issue" do
@@ -13,10 +17,12 @@ @@ -13,10 +17,12 @@
13 close issue 17 close issue
14 - elsif problem.issue_link == "pending" 18 - elsif problem.issue_link == "pending"
15 %span.disabled 19 %span.disabled
16 - %img.button-icon{"src" => tracker_type.icons[:inactive]}  
17 - = link_to 'creating...', '#', :class => "create-issue" 20 + = link_to '#', :class => "create-issue issue-tracker-button" do
  21 + %img.button-icon{"src" => tracker_type.icons[:inactive]}
  22 + creating...
18 = link_to 'retry', create_issue_app_problem_path(app, problem), :method => :post 23 = link_to 'retry', create_issue_app_problem_path(app, problem), :method => :post
19 - else 24 - else
20 %span 25 %span
21 - %img.button-icon{"src" => tracker_type.icons[:goto]}  
22 - = link_to 'create issue', create_issue_app_problem_path(app, problem), method: :post, :class => "create-issue" 26 + = link_to create_issue_app_problem_path(app, problem), method: :post, :class => "create-issue issue-tracker-button" do
  27 + %img.button-icon{"src" => tracker_type.icons[:create]}
  28 + create issue
config/puma.default.rb
@@ -6,8 +6,8 @@ threads threads_count, threads_count @@ -6,8 +6,8 @@ threads threads_count, threads_count
6 6
7 preload_app! 7 preload_app!
8 8
9 -rackup DefaultRackup  
10 -port ENV['PORT'] || 8080 9 +rackup DefaultRackup
  10 +port ENV['PORT'] || 8080
11 environment ENV['RACK_ENV'] || 'development' 11 environment ENV['RACK_ENV'] || 'development'
12 12
13 on_worker_boot do 13 on_worker_boot do
docs/deployment/capistrano.md
@@ -75,7 +75,7 @@ rbenv=1 bundle exec cap production deploy @@ -75,7 +75,7 @@ rbenv=1 bundle exec cap production deploy
75 75
76 ## Schedule recurring tasks 76 ## Schedule recurring tasks
77 You may want to periodically clear resolved errors to free up space. 77 You may want to periodically clear resolved errors to free up space.
78 -Schedule ```rake errbit:db:clear_resolved``` to run every day or so. 78 +Schedule ```rake errbit:clear_resolved``` to run every day or so.
79 79
80 80
81 ## Monit 81 ## Monit
docs/deployment/heroku.md
@@ -58,7 +58,7 @@ Option 1. With the heroku-scheduler add-on (replacement for cron): @@ -58,7 +58,7 @@ Option 1. With the heroku-scheduler add-on (replacement for cron):
58 heroku addons:create scheduler:standard 58 heroku addons:create scheduler:standard
59 59
60 # Go open the dashboard to schedule the job. You should use 60 # Go open the dashboard to schedule the job. You should use
61 -# 'rake errbit:db:clear_resolved' as the task command, and schedule it 61 +# 'rake errbit:clear_resolved' as the task command, and schedule it
62 # at whatever frequency you like (once/day should work great). 62 # at whatever frequency you like (once/day should work great).
63 heroku addons:create scheduler 63 heroku addons:create scheduler
64 ``` 64 ```
@@ -73,5 +73,5 @@ heroku addons:create cron:daily @@ -73,5 +73,5 @@ heroku addons:create cron:daily
73 Option 3. Clear resolved errors manually: 73 Option 3. Clear resolved errors manually:
74 74
75 ```bash 75 ```bash
76 -heroku run rake errbit:db:clear_resolved 76 +heroku run rake errbit:clear_resolved
77 ``` 77 ```
lib/airbrake_api/v3/notice_parser.rb
@@ -72,9 +72,9 @@ module AirbrakeApi @@ -72,9 +72,9 @@ module AirbrakeApi
72 return context['user'] if context['user'] 72 return context['user'] if context['user']
73 73
74 { 74 {
75 - 'id' => context['userId'],  
76 - 'name' => context['userName'],  
77 - 'email' => context['userEmail'], 75 + 'id' => context['userId'],
  76 + 'name' => context['userName'],
  77 + 'email' => context['userEmail'],
78 'username' => context['userUsername'] 78 'username' => context['userUsername']
79 }.compact 79 }.compact
80 end 80 end
lib/tasks/heroku/cron.rake
1 desc "This task is called by the Heroku cron add-on" 1 desc "This task is called by the Heroku cron add-on"
2 task cron: :environment do 2 task cron: :environment do
3 - Rake::Task["errbit:db:clear_resolved"].invoke 3 + Rake::Task["errbit:clear_resolved"].invoke
4 end 4 end
spec/fabricators/notice_fabricator.rb
@@ -2,7 +2,7 @@ Fabricator :notice do @@ -2,7 +2,7 @@ Fabricator :notice do
2 app 2 app
3 err 3 err
4 error_class 'FooError' 4 error_class 'FooError'
5 - message 'Too Much Bar' 5 + message 'FooError: Too Much Bar'
6 backtrace 6 backtrace
7 server_environment { { 'environment-name' => 'production' } } 7 server_environment { { 'environment-name' => 'production' } }
8 request { { 'component' => 'foo', 'action' => 'bar' } } 8 request { { 'component' => 'foo', 'action' => 'bar' } }
spec/models/notification_service/slack_service_spec.rb
1 describe NotificationServices::SlackService, type: 'model' do 1 describe NotificationServices::SlackService, type: 'model' do
  2 + let(:notice) { Fabricate :notice }
  3 + let(:service_url) do
  4 + "https://hooks.slack.com/services/XXXXXXXXX/XXXXXXXXX/XXXXXXXXX"
  5 + end
  6 +
  7 + let(:service) do
  8 + Fabricate :slack_notification_service, app: notice.app,
  9 + service_url: service_url
  10 + end
  11 +
2 it "it should send a notification to Slack with hook url" do 12 it "it should send a notification to Slack with hook url" do
3 # setup 13 # setup
4 - notice = Fabricate :notice  
5 - notification_service = Fabricate :slack_notification_service, app: notice.app, service_url: "https://hooks.slack.com/services/XXXXXXXXX/XXXXXXXXX/XXXXXXXXX"  
6 problem = notice.problem 14 problem = notice.problem
7 15
8 # faraday stubbing 16 # faraday stubbing
9 payload = { 17 payload = {
  18 + username: "Errbit",
  19 + icon_emoji: ":collision:",
10 attachments: [ 20 attachments: [
11 { 21 {
12 - fallback: notification_service.message_for_slack(problem),  
13 - pretext: "<#{problem.url}|Errbit - #{problem.app.name}: #{problem.error_class}>",  
14 - color: "#D00000",  
15 - fields: [ 22 + fallback: service.message_for_slack(problem),
  23 + title: problem.message.to_s.truncate(100),
  24 + title_link: problem.url,
  25 + text: problem.where,
  26 + color: "#D00000",
  27 + fields: [
16 { 28 {
17 - title: "Environment",  
18 - value: problem.environment,  
19 - short: false 29 + title: "Application",
  30 + value: problem.app.name,
  31 + short: true
20 }, 32 },
21 { 33 {
22 - title: "Location",  
23 - value: problem.where,  
24 - short: false 34 + title: "Environment",
  35 + value: problem.environment,
  36 + short: true
25 }, 37 },
26 { 38 {
27 - title: "Message",  
28 - value: problem.message.to_s,  
29 - short: false 39 + title: "Times Occurred",
  40 + value: problem.notices_count,
  41 + short: true
30 }, 42 },
31 { 43 {
32 title: "First Noticed", 44 title: "First Noticed",
33 - value: problem.first_notice_at,  
34 - short: false  
35 - },  
36 - {  
37 - title: "Last Noticed",  
38 - value: problem.last_notice_at,  
39 - short: false  
40 - },  
41 - {  
42 - title: "Times Occurred",  
43 - value: problem.notices_count,  
44 - short: false 45 + value: problem.first_notice_at.try(:to_s, :db),
  46 + short: true
45 } 47 }
46 ] 48 ]
47 } 49 }
48 ] 50 ]
49 }.to_json 51 }.to_json
50 - expect(HTTParty).to receive(:post).with(notification_service.service_url, body: payload, headers: { "Content-Type" => "application/json" }).and_return(true) 52 + expect(HTTParty).to receive(:post).with(service.service_url, body: payload, headers: { "Content-Type" => "application/json" }).and_return(true)
51 53
52 - notification_service.create_notification(problem) 54 + service.create_notification(problem)
53 end 55 end
54 end 56 end
spec/spec_helper.rb
@@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
2 # from the project root directory. 2 # from the project root directory.
3 ENV["RAILS_ENV"] = 'test' 3 ENV["RAILS_ENV"] = 'test'
4 ENV["ERRBIT_LOG_LEVEL"] = 'fatal' 4 ENV["ERRBIT_LOG_LEVEL"] = 'fatal'
  5 +ENV["ERRBIT_USER_HAS_USERNAME"] = 'false'
5 6
6 if ENV['COVERAGE'] 7 if ENV['COVERAGE']
7 require 'coveralls' 8 require 'coveralls'