Commit 9c79849276ec0a292cc6fb5591837abe3d76aa83

Authored by Stephen Crosby
2 parents ccadc6a2 759a2c9a
Exists in master and in 1 other branch production

Merge branch 'master' into features/extract_issue_tracker

Conflicts:
	Gemfile.lock
@@ -4,13 +4,14 @@ env: @@ -4,13 +4,14 @@ env:
4 rvm: 4 rvm:
5 - 2.0.0 5 - 2.0.0
6 - 1.9.3 6 - 1.9.3
7 - - rbx-19mode 7 + - 2.1.2
  8 + - rbx-2
8 - ruby-head 9 - ruby-head
9 services: mongodb 10 services: mongodb
10 #script: ./script/rspec-queue-mongoid.rb --format progress spec 11 #script: ./script/rspec-queue-mongoid.rb --format progress spec
11 matrix: 12 matrix:
12 allow_failures: 13 allow_failures:
13 - - rvm: rbx-19mode 14 + - rvm: rbx-2
14 - rvm: ruby-head 15 - rvm: ruby-head
15 16
16 17
CONTRIBUTORS.md
@@ -42,11 +42,14 @@ @@ -42,11 +42,14 @@
42 - [@nashby][] 42 - [@nashby][]
43 - [@shingara][] 43 - [@shingara][]
44 - [@tscolari][] 44 - [@tscolari][]
  45 +- [@callumd][]
  46 +
45 47
46 [@anicet]: https://github.com/anicet 48 [@anicet]: https://github.com/anicet
47 [@nashby]: https://github.com/nashby 49 [@nashby]: https://github.com/nashby
48 [@shingara]: https://github.com/shingara 50 [@shingara]: https://github.com/shingara
49 [@tscolari]: https://github.com/tscolari 51 [@tscolari]: https://github.com/tscolari
  52 +[@callumd]: https://github.com/callumd
50 53
51 ## 0.2.0 - 2013-09-11 54 ## 0.2.0 - 2013-09-11
52 55
1 source 'https://rubygems.org' 1 source 'https://rubygems.org'
2 2
3 -RAILS_VERSION = '~> 3.2.18' 3 +RAILS_VERSION = '~> 3.2.19'
4 4
5 gem 'actionmailer', RAILS_VERSION 5 gem 'actionmailer', RAILS_VERSION
6 gem 'actionpack', RAILS_VERSION 6 gem 'actionpack', RAILS_VERSION
1 GEM 1 GEM
2 remote: https://rubygems.org/ 2 remote: https://rubygems.org/
3 specs: 3 specs:
4 - actionmailer (3.2.18)  
5 - actionpack (= 3.2.18) 4 + actionmailer (3.2.19)
  5 + actionpack (= 3.2.19)
6 mail (~> 2.5.4) 6 mail (~> 2.5.4)
7 actionmailer_inline_css (1.5.3) 7 actionmailer_inline_css (1.5.3)
8 actionmailer (>= 3.0.0) 8 actionmailer (>= 3.0.0)
9 nokogiri (>= 1.4.4) 9 nokogiri (>= 1.4.4)
10 premailer (>= 1.7.1) 10 premailer (>= 1.7.1)
11 - actionpack (3.2.18)  
12 - activemodel (= 3.2.18)  
13 - activesupport (= 3.2.18) 11 + actionpack (3.2.19)
  12 + activemodel (= 3.2.19)
  13 + activesupport (= 3.2.19)
14 builder (~> 3.0.0) 14 builder (~> 3.0.0)
15 erubis (~> 2.7.0) 15 erubis (~> 2.7.0)
16 journey (~> 1.0.4) 16 journey (~> 1.0.4)
@@ -18,18 +18,18 @@ GEM @@ -18,18 +18,18 @@ GEM
18 rack-cache (~> 1.2) 18 rack-cache (~> 1.2)
19 rack-test (~> 0.6.1) 19 rack-test (~> 0.6.1)
20 sprockets (~> 2.2.1) 20 sprockets (~> 2.2.1)
21 - activemodel (3.2.18)  
22 - activesupport (= 3.2.18) 21 + activemodel (3.2.19)
  22 + activesupport (= 3.2.19)
23 builder (~> 3.0.0) 23 builder (~> 3.0.0)
24 - activerecord (3.2.18)  
25 - activemodel (= 3.2.18)  
26 - activesupport (= 3.2.18) 24 + activerecord (3.2.19)
  25 + activemodel (= 3.2.19)
  26 + activesupport (= 3.2.19)
27 arel (~> 3.0.2) 27 arel (~> 3.0.2)
28 tzinfo (~> 0.3.29) 28 tzinfo (~> 0.3.29)
29 - activeresource (3.2.18)  
30 - activemodel (= 3.2.18)  
31 - activesupport (= 3.2.18)  
32 - activesupport (3.2.18) 29 + activeresource (3.2.19)
  30 + activemodel (= 3.2.19)
  31 + activesupport (= 3.2.19)
  32 + activesupport (3.2.19)
33 i18n (~> 0.6, >= 0.6.4) 33 i18n (~> 0.6, >= 0.6.4)
34 multi_json (~> 1.0) 34 multi_json (~> 1.0)
35 addressable (2.3.6) 35 addressable (2.3.6)
@@ -177,7 +177,7 @@ GEM @@ -177,7 +177,7 @@ GEM
177 kgio (2.8.1) 177 kgio (2.8.1)
178 launchy (2.3.0) 178 launchy (2.3.0)
179 addressable (~> 2.3) 179 addressable (~> 2.3)
180 - libv8 (3.16.14.3) 180 + libv8 (3.16.14.7)
181 libxml-ruby (2.7.0) 181 libxml-ruby (2.7.0)
182 lighthouse-api (2.0) 182 lighthouse-api (2.0)
183 activeresource (>= 3.0.0) 183 activeresource (>= 3.0.0)
@@ -260,7 +260,7 @@ GEM @@ -260,7 +260,7 @@ GEM
260 cliver (~> 0.3.1) 260 cliver (~> 0.3.1)
261 multi_json (~> 1.0) 261 multi_json (~> 1.0)
262 websocket-driver (>= 0.2.0) 262 websocket-driver (>= 0.2.0)
263 - polyglot (0.3.4) 263 + polyglot (0.3.5)
264 premailer (1.7.3) 264 premailer (1.7.3)
265 css_parser (>= 1.1.9) 265 css_parser (>= 1.1.9)
266 htmlentities (>= 4.0.0) 266 htmlentities (>= 4.0.0)
@@ -284,25 +284,25 @@ GEM @@ -284,25 +284,25 @@ GEM
284 rack-ssl-enforcer (0.2.6) 284 rack-ssl-enforcer (0.2.6)
285 rack-test (0.6.2) 285 rack-test (0.6.2)
286 rack (>= 1.0) 286 rack (>= 1.0)
287 - rails (3.2.18)  
288 - actionmailer (= 3.2.18)  
289 - actionpack (= 3.2.18)  
290 - activerecord (= 3.2.18)  
291 - activeresource (= 3.2.18)  
292 - activesupport (= 3.2.18) 287 + rails (3.2.19)
  288 + actionmailer (= 3.2.19)
  289 + actionpack (= 3.2.19)
  290 + activerecord (= 3.2.19)
  291 + activeresource (= 3.2.19)
  292 + activesupport (= 3.2.19)
293 bundler (~> 1.0) 293 bundler (~> 1.0)
294 - railties (= 3.2.18) 294 + railties (= 3.2.19)
295 rails_autolink (1.1.4) 295 rails_autolink (1.1.4)
296 rails (> 3.1) 296 rails (> 3.1)
297 - railties (3.2.18)  
298 - actionpack (= 3.2.18)  
299 - activesupport (= 3.2.18) 297 + railties (3.2.19)
  298 + actionpack (= 3.2.19)
  299 + activesupport (= 3.2.19)
300 rack-ssl (~> 1.3.2) 300 rack-ssl (~> 1.3.2)
301 rake (>= 0.8.7) 301 rake (>= 0.8.7)
302 rdoc (~> 3.4) 302 rdoc (~> 3.4)
303 thor (>= 0.14.6, < 2.0) 303 thor (>= 0.14.6, < 2.0)
304 raindrops (0.12.0) 304 raindrops (0.12.0)
305 - rake (10.3.1) 305 + rake (10.3.2)
306 rdoc (3.12.2) 306 rdoc (3.12.2)
307 json (~> 1.4) 307 json (~> 1.4)
308 ref (1.0.5) 308 ref (1.0.5)
@@ -352,7 +352,7 @@ GEM @@ -352,7 +352,7 @@ GEM
352 railties (~> 3.0) 352 railties (~> 3.0)
353 term-ansicolor (1.2.2) 353 term-ansicolor (1.2.2)
354 tins (~> 0.8) 354 tins (~> 0.8)
355 - therubyracer (0.12.0) 355 + therubyracer (0.12.1)
356 libv8 (~> 3.16.14.0) 356 libv8 (~> 3.16.14.0)
357 ref 357 ref
358 thor (0.19.1) 358 thor (0.19.1)
@@ -367,7 +367,7 @@ GEM @@ -367,7 +367,7 @@ GEM
367 turbo-sprockets-rails3 (0.3.10) 367 turbo-sprockets-rails3 (0.3.10)
368 railties (> 3.2.8, < 4.0.0) 368 railties (> 3.2.8, < 4.0.0)
369 sprockets (>= 2.0.0) 369 sprockets (>= 2.0.0)
370 - tzinfo (0.3.39) 370 + tzinfo (0.3.41)
371 uglifier (2.2.1) 371 uglifier (2.2.1)
372 execjs (>= 0.3.0) 372 execjs (>= 0.3.0)
373 json (>= 1.8.0) 373 json (>= 1.8.0)
@@ -392,9 +392,9 @@ PLATFORMS @@ -392,9 +392,9 @@ PLATFORMS
392 ruby 392 ruby
393 393
394 DEPENDENCIES 394 DEPENDENCIES
395 - actionmailer (~> 3.2.18) 395 + actionmailer (~> 3.2.19)
396 actionmailer_inline_css 396 actionmailer_inline_css
397 - actionpack (~> 3.2.18) 397 + actionpack (~> 3.2.19)
398 airbrake 398 airbrake
399 better_errors 399 better_errors
400 binding_of_caller 400 binding_of_caller
@@ -443,7 +443,7 @@ DEPENDENCIES @@ -443,7 +443,7 @@ DEPENDENCIES
443 rack-ssl 443 rack-ssl
444 rack-ssl-enforcer 444 rack-ssl-enforcer
445 rails_autolink 445 rails_autolink
446 - railties (~> 3.2.18) 446 + railties (~> 3.2.19)
447 ri_cal 447 ri_cal
448 rspec-rails 448 rspec-rails
449 rushover 449 rushover
@@ -78,25 +78,20 @@ There is a demo available at [http://errbit-demo.herokuapp.com/](http://errbit-d @@ -78,25 +78,20 @@ There is a demo available at [http://errbit-demo.herokuapp.com/](http://errbit-d
78 Email: demo@errbit-demo.herokuapp.com<br/> 78 Email: demo@errbit-demo.herokuapp.com<br/>
79 Password: password 79 Password: password
80 80
81 -# Requirement 81 +# Requirements
82 82
83 -The list of requirement to install Errbit is : 83 +The list of requirements to install Errbit are :
84 84
85 * Ruby 1.9.3 or higher 85 * Ruby 1.9.3 or higher
86 * MongoDB 2.2.0 or higher 86 * MongoDB 2.2.0 or higher
87 87
88 -By default it's the Ruby 2.0.0 to use. But you can define your own ruby  
89 -version with RUBY_VERSION variable between :  
90 -  
91 - * 1.9.3  
92 - * 2.0.0  
93 - * 2.1.0 88 +Errbit uses Ruby 2.0.0 as a default. However, it is compatible with Ruby 1.9.3 and above.
94 89
95 Installation 90 Installation
96 ------------ 91 ------------
97 92
98 *Note*: This app is intended for people with experience deploying and maintaining 93 *Note*: This app is intended for people with experience deploying and maintaining
99 -Rails applications. If you're uncomfortable with any step below then Errbit is not 94 +Rails applications. If you're uncomfortable with any steps below then Errbit is not
100 for you. 95 for you.
101 96
102 **Set up your local box or server(Ubuntu):** 97 **Set up your local box or server(Ubuntu):**
@@ -108,10 +103,10 @@ apt-get update @@ -108,10 +103,10 @@ apt-get update
108 apt-get install mongodb-10gen 103 apt-get install mongodb-10gen
109 ``` 104 ```
110 105
111 - * Install libxml and libcurl 106 + * Install libxml, libzip, libssl and libcurl
112 107
113 ```bash 108 ```bash
114 -apt-get install libxml2 libxml2-dev libxslt-dev libcurl4-openssl-dev 109 +apt-get install libxml2 libxml2-dev libxslt-dev libcurl4-openssl-dev libzip-dev libssl-dev
115 ``` 110 ```
116 111
117 * Install Bundler 112 * Install Bundler
@@ -179,9 +174,6 @@ heroku config:add HEROKU=true @@ -179,9 +174,6 @@ heroku config:add HEROKU=true
179 heroku config:add SECRET_TOKEN="$(bundle exec rake secret)" 174 heroku config:add SECRET_TOKEN="$(bundle exec rake secret)"
180 heroku config:add ERRBIT_HOST=some-hostname.example.com 175 heroku config:add ERRBIT_HOST=some-hostname.example.com
181 heroku config:add ERRBIT_EMAIL_FROM=example@example.com 176 heroku config:add ERRBIT_EMAIL_FROM=example@example.com
182 -# This next line is required to access env variables during asset compilation.  
183 -# For more info, go to this link: https://devcenter.heroku.com/articles/labs-user-env-compile  
184 -heroku labs:enable user-env-compile  
185 git push heroku master 177 git push heroku master
186 ``` 178 ```
187 179
@@ -360,17 +352,16 @@ rake db:migrate @@ -360,17 +352,16 @@ rake db:migrate
360 rake assets:precompile 352 rake assets:precompile
361 ``` 353 ```
362 354
363 -If we change the way that data is stored, this will run any migrations to bring your database up to date. 355 +This will ensure that your application stays up to date with any schema changes.
364 356
365 357
366 -### Upgrade from errbit 0.2 to 0.3 358 +### Upgrading errbit from version 0.2 to 0.3
367 359
368 -The file of MongoDB connection config/mongoid.yml change between 0.2 to  
369 -0.3. So Check the new config/mongoid.yml.example file and update it in  
370 -good way. 360 +The MongoDB connection file `config/mongoid.yml` has changed between version 0.2 and
  361 +0.3. We have provided a new example configuration file to use at `config/mongoid.example.yml`.
371 362
372 -This change is not need to be done if you use only ENV variable to  
373 -define you access to MongoDB database. 363 +This change is not needed if you use ENV variables to
  364 +define access to your MongoDB database.
374 365
375 366
376 ## User information in error reports 367 ## User information in error reports
@@ -379,11 +370,12 @@ Errbit can now display information about the user who experienced an error. @@ -379,11 +370,12 @@ Errbit can now display information about the user who experienced an error.
379 This gives you the ability to ask the user for more information, 370 This gives you the ability to ask the user for more information,
380 and let them know when you've fixed the bug. 371 and let them know when you've fixed the bug.
381 372
382 -If you would like to include information about the current user in your error reports,  
383 -you can replace the `airbrake` gem in your Gemfile with `airbrake_user_attributes`,  
384 -which wraps the `airbrake` gem and injects user information.  
385 -It will inject information about the current user into the error report  
386 -if your Rails app's controller responds to a `#current_user` method. 373 +If you are running a Rails application and would like to include information
  374 +about the current user in your error reports, you can replace the `airbrake`
  375 +gem in your Gemfile with `airbrake_user_attributes`.
  376 +This gem is a wrapper around the `airbrake` gem and will automatically
  377 +inject information about the user into any error reports,
  378 +so long as your controllers respond to a `#current_user` method.
387 The user's attributes are filtered to remove authentication fields. 379 The user's attributes are filtered to remove authentication fields.
388 380
389 If user information is received with an error report, 381 If user information is received with an error report,
@@ -394,26 +386,33 @@ it will be displayed under the *User Details* tab: @@ -394,26 +386,33 @@ it will be displayed under the *User Details* tab:
394 386
395 (This tab will be hidden if no user information is available.) 387 (This tab will be hidden if no user information is available.)
396 388
397 -Adding javascript errors notifications 389 +Javascript error notifications
398 -------------------------------------- 390 --------------------------------------
399 391
400 -Errbit easily supports javascript errors notifications. You just need to add `config.js_notifier = true` to the errbit initializer in the rails app. 392 +You can log javascript errors that occur in your application by following the directions below.
  393 +
  394 +# Rails Applications
  395 +
  396 +Add the following line to the `<head>` section of your application template.
  397 +
  398 +```
  399 +<%= airbrake_javascript_notifier %>
  400 +```
  401 +
  402 +# Other Platforms
  403 +
  404 +include the following before any javascript is loaded in your application.
401 405
402 ``` 406 ```
403 -Errbit.configure do |config|  
404 - config.host = 'YOUR-ERRBIT-HOST'  
405 - config.api_key = 'YOUR-PROJECT-API-KEY'  
406 - config.js_notifier = true  
407 -end 407 +<script src='http://YOUR-ERRBIT-HOST/javascripts/notifier.js' type='text/javascript'></script>
408 ``` 408 ```
409 409
410 -Then get the `notifier.js` from `errbit/public/javascript/notifier.js` and add to `application.js` on your rails app or include `http://YOUR-ERRBIT-HOST/javascripts/notifier.js` on your `application.html.erb.`  
411 410
412 Using custom fingerprinting methods 411 Using custom fingerprinting methods
413 ----------------------------------- 412 -----------------------------------
414 413
415 -Errbit now allows you to easily use your own Fingerprint Strategy if that's what you'd like to do. If you are upgrading from a very old version of errbit, you can use the `LegacyFingerprint` to provide yourself  
416 -with compatibility. The fingerprint strategy can be changed by adding an initializer to errbit: 414 +Errbit allows you to use your own Fingerprinting Strategy.
  415 +If you are upgrading from a very old version of errbit, you can use the `LegacyFingerprint` for compatibility. The fingerprint strategy can be changed by adding an initializer to errbit:
417 416
418 ```ruby 417 ```ruby
419 # config/fingerprint.rb 418 # config/fingerprint.rb
@@ -533,23 +532,18 @@ Solutions known to work are listed below: @@ -533,23 +532,18 @@ Solutions known to work are listed below:
533 <table> 532 <table>
534 <tr> 533 <tr>
535 <th>PHP (&gt;= 5.3)</th> 534 <th>PHP (&gt;= 5.3)</th>
536 - <td>https://github.com/flippa/errbit-php</td> 535 + <td>[flippa/errbit-php](https://github.com/flippa/errbit-php)</td>
537 </tr> 536 </tr>
538 <tr> 537 <tr>
539 <th>OOP PHP (&gt;= 5.3)</th> 538 <th>OOP PHP (&gt;= 5.3)</th>
540 - <td>https://github.com/emgiezet/errbitPHP</td> 539 + <td>[emgiezet/errbitPHP](https://github.com/emgiezet/errbitPHP)</td>
541 </tr> 540 </tr>
542 <tr> 541 <tr>
543 <th>Python</th> 542 <th>Python</th>
544 - <td>https://github.com/mkorenkov/errbit.py , https://github.com/pulseenergy/airbrakepy</td> 543 + <td>[mkorenkov/errbit.py](https://github.com/mkorenkov/errbit.py) , [pulseenergy/airbrakepy](https://github.com/pulseenergy/airbrakepy)</td>
545 </tr> 544 </tr>
546 </table> 545 </table>
547 546
548 -Develop on Errbit  
549 ------------------  
550 -  
551 -A guide can help on this way on [**Errbit Advanced Developer Guide**](docs/DEVELOPER-ADVANCED.md)  
552 -  
553 ## Other documentation 547 ## Other documentation
554 548
555 * [All ENV variables availables to configure Errbit](docs/ENV-VARIABLES.md) 549 * [All ENV variables availables to configure Errbit](docs/ENV-VARIABLES.md)
@@ -582,7 +576,7 @@ Special Thanks @@ -582,7 +576,7 @@ Special Thanks
582 See the [contributors graph](https://github.com/errbit/errbit/graphs/contributors) for further details. You can see another list of Contributors by release version on [CONTRIBUTORS.md] 576 See the [contributors graph](https://github.com/errbit/errbit/graphs/contributors) for further details. You can see another list of Contributors by release version on [CONTRIBUTORS.md]
583 577
584 578
585 -Contributing 579 +Contributing to Errbit
586 ------------ 580 ------------
587 581
588 We welcome any contributions. If you need to tweak Errbit for your organization's needs, 582 We welcome any contributions. If you need to tweak Errbit for your organization's needs,
@@ -604,9 +598,13 @@ and make **optional** features configurable via `config/config.yml`. @@ -604,9 +598,13 @@ and make **optional** features configurable via `config/config.yml`.
604 * Send us a pull request. Bonus points for topic branches. 598 * Send us a pull request. Bonus points for topic branches.
605 * Add you on the CONTRIBUTORS.md file on the current release 599 * Add you on the CONTRIBUTORS.md file on the current release
606 600
  601 +# Running tests
  602 +
  603 +More information can be found in the [**Errbit Advanced Developer Guide**](docs/DEVELOPER-ADVANCED.md)
  604 +
607 605
608 Copyright 606 Copyright
609 --------- 607 ---------
610 608
611 -Copyright (c) 2010-2013 Errbit Team. See LICENSE for details. 609 +Copyright (c) 2010-2014 Errbit Team. See LICENSE for details.
612 610
app/controllers/api/v1/problems_controller.rb
1 class Api::V1::ProblemsController < ApplicationController 1 class Api::V1::ProblemsController < ApplicationController
2 respond_to :json, :xml 2 respond_to :json, :xml
  3 + FIELDS = %w{app_id app_name environment message where first_notice_at last_notice_at resolved resolved_at notices_count}
  4 +
  5 + def show
  6 + result = benchmark("[api/v1/problems_controller/show] query time") do
  7 + begin
  8 + Problem.only(FIELDS).find(params[:id])
  9 + rescue Mongoid::Errors::DocumentNotFound
  10 + head :not_found
  11 + return false
  12 + end
  13 + end
  14 +
  15 + respond_to do |format|
  16 + format.any(:html, :json) { render :json => result } # render JSON if no extension specified on path
  17 + format.xml { render :xml => result }
  18 + end
  19 + end
3 20
4 def index 21 def index
5 query = {} 22 query = {}
6 - fields = %w{app_id app_name environment message where first_notice_at last_notice_at resolved resolved_at notices_count}  
7 23
8 if params.key?(:start_date) && params.key?(:end_date) 24 if params.key?(:start_date) && params.key?(:end_date)
9 start_date = Time.parse(params[:start_date]).utc 25 start_date = Time.parse(params[:start_date]).utc
@@ -11,8 +27,8 @@ class Api::V1::ProblemsController &lt; ApplicationController @@ -11,8 +27,8 @@ class Api::V1::ProblemsController &lt; ApplicationController
11 query = {:first_notice_at=>{"$lte"=>end_date}, "$or"=>[{:resolved_at=>nil}, {:resolved_at=>{"$gte"=>start_date}}]} 27 query = {:first_notice_at=>{"$lte"=>end_date}, "$or"=>[{:resolved_at=>nil}, {:resolved_at=>{"$gte"=>start_date}}]}
12 end 28 end
13 29
14 - results = benchmark("[api/v1/problems_controller] query time") do  
15 - Problem.where(query).with(:consistency => :strong).only(fields).to_a 30 + results = benchmark("[api/v1/problems_controller/index] query time") do
  31 + Problem.where(query).with(:consistency => :strong).only(FIELDS).to_a
16 end 32 end
17 33
18 respond_to do |format| 34 respond_to do |format|
app/mailers/mailer.rb
@@ -6,7 +6,12 @@ class Mailer &lt; ActionMailer::Base @@ -6,7 +6,12 @@ class Mailer &lt; ActionMailer::Base
6 helper ApplicationHelper 6 helper ApplicationHelper
7 helper BacktraceLineHelper 7 helper BacktraceLineHelper
8 8
9 - default :from => Errbit::Config.email_from 9 + default :from => Errbit::Config.email_from,
  10 + 'X-Errbit-Host' => Errbit::Config.host,
  11 + 'X-Mailer' => 'Errbit',
  12 + 'X-Auto-Response-Suppress' => 'OOF, AutoReply',
  13 + 'Precedence' => 'bulk',
  14 + 'Auto-Submitted' => 'auto-generated'
10 15
11 def err_notification(notice) 16 def err_notification(notice)
12 @notice = notice 17 @notice = notice
@@ -15,6 +20,10 @@ class Mailer &lt; ActionMailer::Base @@ -15,6 +20,10 @@ class Mailer &lt; ActionMailer::Base
15 count = @notice.similar_count 20 count = @notice.similar_count
16 count = count > 1 ? "(#{count}) " : "" 21 count = count > 1 ? "(#{count}) " : ""
17 22
  23 + errbit_headers 'App' => @app.name,
  24 + 'Environment' => @notice.environment_name,
  25 + 'Error-Id' => @notice.err_id
  26 +
18 mail :to => @app.notification_recipients, 27 mail :to => @app.notification_recipients,
19 :subject => "#{count}[#{@app.name}][#{@notice.environment_name}] #{@notice.message.truncate(50)}" 28 :subject => "#{count}[#{@app.name}][#{@notice.environment_name}] #{@notice.message.truncate(50)}"
20 end 29 end
@@ -23,6 +32,11 @@ class Mailer &lt; ActionMailer::Base @@ -23,6 +32,11 @@ class Mailer &lt; ActionMailer::Base
23 @deploy = deploy 32 @deploy = deploy
24 @app = deploy.app 33 @app = deploy.app
25 34
  35 + errbit_headers 'App' => @app.name,
  36 + 'Environment' => @deploy.environment,
  37 + 'Deploy-Revision' => @deploy.revision,
  38 + 'Deploy-User' => @deploy.username
  39 +
26 mail :to => @app.notification_recipients, 40 mail :to => @app.notification_recipients,
27 :subject => "[#{@app.name}] Deployed to #{@deploy.environment} by #{@deploy.username}" 41 :subject => "[#{@app.name}] Deployed to #{@deploy.environment} by #{@deploy.username}"
28 end 42 end
@@ -36,7 +50,18 @@ class Mailer &lt; ActionMailer::Base @@ -36,7 +50,18 @@ class Mailer &lt; ActionMailer::Base
36 50
37 recipients = @comment.notification_recipients 51 recipients = @comment.notification_recipients
38 52
  53 + errbit_headers 'App' => @app.name,
  54 + 'Environment' => @notice.environment_name,
  55 + 'Problem-Id' => @problem.id,
  56 + 'Comment-Author' => @user.name
  57 +
39 mail :to => recipients, 58 mail :to => recipients,
40 :subject => "#{@user.name} commented on [#{@app.name}][#{@notice.environment_name}] #{@notice.message.truncate(50)}" 59 :subject => "#{@user.name} commented on [#{@app.name}][#{@notice.environment_name}] #{@notice.message.truncate(50)}"
41 end 60 end
  61 +
  62 + private
  63 +
  64 + def errbit_headers(header)
  65 + header.each { |key,value| headers["X-Errbit-#{key}"] = value.to_s }
  66 + end
42 end 67 end
app/models/error_report.rb
@@ -15,15 +15,18 @@ require &#39;hoptoad_notifier&#39; @@ -15,15 +15,18 @@ require &#39;hoptoad_notifier&#39;
15 # * <tt>:notifier</tt> - information to identify the source of the error report 15 # * <tt>:notifier</tt> - information to identify the source of the error report
16 # 16 #
17 class ErrorReport 17 class ErrorReport
18 - attr_reader :error_class, :message, :request, :server_environment, :api_key, :notifier, :user_attributes, :framework 18 + attr_reader :error_class, :message, :request, :server_environment, :api_key,
  19 + :notifier, :user_attributes, :framework, :notice
19 20
20 cattr_accessor :fingerprint_strategy do 21 cattr_accessor :fingerprint_strategy do
21 Fingerprint 22 Fingerprint
22 end 23 end
23 24
24 def initialize(xml_or_attributes) 25 def initialize(xml_or_attributes)
25 - @attributes = (xml_or_attributes.is_a?(String) ? Hoptoad.parse_xml!(xml_or_attributes) : xml_or_attributes).with_indifferent_access  
26 - @attributes.each{|k, v| instance_variable_set(:"@#{k}", v) } 26 + @attributes = xml_or_attributes
  27 + @attributes = Hoptoad.parse_xml!(@attributes) if @attributes.is_a? String
  28 + @attributes = @attributes.with_indifferent_access
  29 + @attributes.each { |k, v| instance_variable_set(:"@#{k}", v) }
27 end 30 end
28 31
29 def rails_env 32 def rails_env
@@ -33,30 +36,29 @@ class ErrorReport @@ -33,30 +36,29 @@ class ErrorReport
33 end 36 end
34 37
35 def app 38 def app
36 - @app ||= App.where(:api_key => api_key).first 39 + @app ||= App.where(api_key: api_key).first
37 end 40 end
38 41
39 def backtrace 42 def backtrace
40 - @normalized_backtrace ||= Backtrace.find_or_create(:raw => @backtrace) 43 + @normalized_backtrace ||= Backtrace.find_or_create(raw: @backtrace)
41 end 44 end
42 45
43 def generate_notice! 46 def generate_notice!
44 return unless valid? 47 return unless valid?
45 return @notice if @notice 48 return @notice if @notice
46 @notice = Notice.new( 49 @notice = Notice.new(
47 - :message => message,  
48 - :error_class => error_class,  
49 - :backtrace_id => backtrace.id,  
50 - :request => request,  
51 - :server_environment => server_environment,  
52 - :notifier => notifier,  
53 - :user_attributes => user_attributes,  
54 - :framework => framework 50 + message: message,
  51 + error_class: error_class,
  52 + backtrace_id: backtrace.id,
  53 + request: request,
  54 + server_environment: server_environment,
  55 + notifier: notifier,
  56 + user_attributes: user_attributes,
  57 + framework: framework
55 ) 58 )
56 error.notices << @notice 59 error.notices << @notice
57 @notice 60 @notice
58 end 61 end
59 - attr_reader :notice  
60 62
61 ## 63 ##
62 # Error associate to this error_report 64 # Error associate to this error_report
@@ -66,23 +68,22 @@ class ErrorReport @@ -66,23 +68,22 @@ class ErrorReport
66 # @return [ Error ] 68 # @return [ Error ]
67 def error 69 def error
68 @error ||= app.find_or_create_err!( 70 @error ||= app.find_or_create_err!(
69 - :error_class => error_class,  
70 - :environment => rails_env,  
71 - :fingerprint => fingerprint 71 + error_class: error_class,
  72 + environment: rails_env,
  73 + fingerprint: fingerprint
72 ) 74 )
73 end 75 end
74 76
75 def valid? 77 def valid?
76 - !!app 78 + app.present?
77 end 79 end
78 80
79 def should_keep? 81 def should_keep?
80 app_version = server_environment['app-version'] || '' 82 app_version = server_environment['app-version'] || ''
81 - if self.app.current_app_version.present? && ( app_version.length <= 0 || Gem::Version.new(app_version) < Gem::Version.new(self.app.current_app_version) )  
82 - false  
83 - else  
84 - true  
85 - end 83 + current_version = app.current_app_version
  84 + return true unless current_version.present?
  85 + return false if app_version.length <= 0
  86 + Gem::Version.new(app_version) >= Gem::Version.new(current_version)
86 end 87 end
87 88
88 private 89 private
@@ -90,5 +91,4 @@ class ErrorReport @@ -90,5 +91,4 @@ class ErrorReport
90 def fingerprint 91 def fingerprint
91 @fingerprint ||= fingerprint_strategy.generate(notice, api_key) 92 @fingerprint ||= fingerprint_strategy.generate(notice, api_key)
92 end 93 end
93 -  
94 end 94 end
app/models/notification_service.rb
@@ -54,6 +54,6 @@ class NotificationService @@ -54,6 +54,6 @@ class NotificationService
54 end 54 end
55 55
56 def problem_url(problem) 56 def problem_url(problem)
57 - "http://#{Errbit::Config.host}/apps/#{problem.app.id}/problems/#{problem.id}" 57 + "#{Errbit::Config.protocol}://#{Errbit::Config.host}/apps/#{problem.app.id}/problems/#{problem.id}"
58 end 58 end
59 end 59 end
app/models/notification_services/campfire_service.rb
@@ -30,7 +30,7 @@ if defined? Campy @@ -30,7 +30,7 @@ if defined? Campy
30 # build the campfire client 30 # build the campfire client
31 campy = Campy::Room.new(:account => subdomain, :token => api_token, :room_id => room_id) 31 campy = Campy::Room.new(:account => subdomain, :token => api_token, :room_id => room_id)
32 # post the issue to the campfire room 32 # post the issue to the campfire room
33 - campy.speak "[errbit] #{problem.app.name} #{notification_description problem} - http://#{Errbit::Config.host}/apps/#{problem.app.id.to_s}/problems/#{problem.id.to_s}" 33 + campy.speak "[errbit] #{problem.app.name} #{notification_description problem} - #{Errbit::Config.protocol}://#{Errbit::Config.host}/apps/#{problem.app.id.to_s}/problems/#{problem.id.to_s}"
34 end 34 end
35 end 35 end
36 end 36 end
app/models/notification_services/gtalk_service.rb
@@ -47,7 +47,7 @@ class NotificationServices::GtalkService &lt; NotificationService @@ -47,7 +47,7 @@ class NotificationServices::GtalkService &lt; NotificationService
47 47
48 #has to look like this to be formatted properly in the client 48 #has to look like this to be formatted properly in the client
49 message = """#{problem.app.name.to_s} 49 message = """#{problem.app.name.to_s}
50 -http://#{Errbit::Config.host}/apps/#{problem.app.id.to_s} 50 +#{Errbit::Config.protocol}://#{Errbit::Config.host}/apps/#{problem.app.id.to_s}
51 #{notification_description problem}""" 51 #{notification_description problem}"""
52 52
53 # post the issue to the xmpp room(s) 53 # post the issue to the xmpp room(s)
app/models/notification_services/hoiio_service.rb
@@ -35,7 +35,7 @@ class NotificationServices::HoiioService &lt; NotificationService @@ -35,7 +35,7 @@ class NotificationServices::HoiioService &lt; NotificationService
35 35
36 # send sms 36 # send sms
37 room_id.split(',').each do |number| 37 room_id.split(',').each do |number|
38 - sms.send :dest => number, :msg => "http://#{Errbit::Config.host}/apps/#{problem.app.id.to_s} #{notification_description problem}" 38 + sms.send :dest => number, :msg => "#{Errbit::Config.protocol}://#{Errbit::Config.host}/apps/#{problem.app.id.to_s} #{notification_description problem}"
39 end 39 end
40 40
41 end 41 end
app/models/notification_services/pushover_service.rb
@@ -26,7 +26,7 @@ class NotificationServices::PushoverService &lt; NotificationService @@ -26,7 +26,7 @@ class NotificationServices::PushoverService &lt; NotificationService
26 notification = Rushover::Client.new(subdomain) 26 notification = Rushover::Client.new(subdomain)
27 27
28 # send push notification to pushover 28 # send push notification to pushover
29 - notification.notify(api_token, "#{notification_description problem}", :priority => 1, :title => "Errbit Notification", :url => "http://#{Errbit::Config.host}/apps/#{problem.app.id.to_s}", :url_title => "Link to error") 29 + notification.notify(api_token, "#{notification_description problem}", :priority => 1, :title => "Errbit Notification", :url => "#{Errbit::Config.protocol}://#{Errbit::Config.host}/apps/#{problem.app.id.to_s}", :url_title => "Link to error")
30 30
31 end 31 end
32 end 32 end
app/models/problem.rb
@@ -50,7 +50,6 @@ class Problem @@ -50,7 +50,6 @@ class Problem
50 50
51 validates_presence_of :last_notice_at, :first_notice_at 51 validates_presence_of :last_notice_at, :first_notice_at
52 52
53 -  
54 def self.all_else_unresolved(fetch_all) 53 def self.all_else_unresolved(fetch_all)
55 if fetch_all 54 if fetch_all
56 all 55 all
app/views/apps/show.html.haml
@@ -88,8 +88,7 @@ @@ -88,8 +88,7 @@
88 - if app.problems.any? 88 - if app.problems.any?
89 %h3.clear=t('.errors') 89 %h3.clear=t('.errors')
90 %section 90 %section
91 - = form_tag search_problems_path(:all_errs => all_errs, :app_id => app.id), :method => :get, :remote => true do  
92 - = text_field_tag :search, params[:search], :placeholder => t('.search_placeholder') 91 + = render 'problems/search', :all_errs => @all_errs, :app_id => app.id
93 %br 92 %br
94 %section 93 %section
95 .problem_table{:id => 'problem_table'} 94 .problem_table{:id => 'problem_table'}
app/views/problems/_search.html.haml 0 → 100644
@@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
  1 += form_tag search_problems_path(:all_errs => all_errs, :app_id => app_id), :method => :get, :remote => true do
  2 + = text_field_tag :search, params[:search], :placeholder => t('.search_placeholder')
app/views/problems/index.html.haml
@@ -9,8 +9,7 @@ @@ -9,8 +9,7 @@
9 = link_to 'show resolved', problems_path(:all_errs => true), :class => 'button' 9 = link_to 'show resolved', problems_path(:all_errs => true), :class => 'button'
10 10
11 %section 11 %section
12 - = form_tag search_problems_path(:all_errs => @all_errs), :method => :get, :remote => true do  
13 - = text_field_tag :search, params[:search], :placeholder => 'Search for issues' 12 + = render 'problems/search', :all_errs => @all_errs, :app_id => nil
14 %br 13 %br
15 %section 14 %section
16 #problem_table.problem_table 15 #problem_table.problem_table
config/cloud/cloud66/files/_load_config.rb
@@ -17,6 +17,7 @@ unless defined?(Errbit::Config) @@ -17,6 +17,7 @@ unless defined?(Errbit::Config)
17 Errbit::Config.use_gravatar = ENV['ERRBIT_USE_GRAVATAR'] 17 Errbit::Config.use_gravatar = ENV['ERRBIT_USE_GRAVATAR']
18 Errbit::Config.gravatar_default = ENV['ERRBIT_GRAVATAR_DEFAULT'] 18 Errbit::Config.gravatar_default = ENV['ERRBIT_GRAVATAR_DEFAULT']
19 19
  20 + Errbit::Config.github_url = ENV['GITHUB_URL']
20 Errbit::Config.github_authentication = ENV['GITHUB_AUTHENTICATION'] 21 Errbit::Config.github_authentication = ENV['GITHUB_AUTHENTICATION']
21 Errbit::Config.github_client_id = ENV['GITHUB_CLIENT_ID'] 22 Errbit::Config.github_client_id = ENV['GITHUB_CLIENT_ID']
22 Errbit::Config.github_secret = ENV['GITHUB_SECRET'] 23 Errbit::Config.github_secret = ENV['GITHUB_SECRET']
config/initializers/_load_config.rb
@@ -6,9 +6,12 @@ unless defined?(Errbit::Config) @@ -6,9 +6,12 @@ unless defined?(Errbit::Config)
6 Errbit::Config = OpenStruct.new 6 Errbit::Config = OpenStruct.new
7 use_env = ENV['HEROKU'] || ENV['USE_ENV'] 7 use_env = ENV['HEROKU'] || ENV['USE_ENV']
8 8
  9 + Errbit::Config.protocol = 'http'
  10 +
9 # If Errbit is running on Heroku, config can be set from environment variables. 11 # If Errbit is running on Heroku, config can be set from environment variables.
10 if use_env 12 if use_env
11 Errbit::Config.host = ENV['ERRBIT_HOST'] 13 Errbit::Config.host = ENV['ERRBIT_HOST']
  14 + Errbit::Config.protocol = ENV['ERRBIT_PROTOCOL'] || 'http'
12 Errbit::Config.port = ENV['ERRBIT_PORT'] 15 Errbit::Config.port = ENV['ERRBIT_PORT']
13 Errbit::Config.email_from = ENV['ERRBIT_EMAIL_FROM'] 16 Errbit::Config.email_from = ENV['ERRBIT_EMAIL_FROM']
14 # Not really easy to use like an env because need an array and ENV return a string :( 17 # Not really easy to use like an env because need an array and ENV return a string :(
@@ -34,7 +37,8 @@ unless defined?(Errbit::Config) @@ -34,7 +37,8 @@ unless defined?(Errbit::Config)
34 :authentication => :plain, 37 :authentication => :plain,
35 :user_name => ENV['SMTP_USERNAME'] || ENV['SENDGRID_USERNAME'], 38 :user_name => ENV['SMTP_USERNAME'] || ENV['SENDGRID_USERNAME'],
36 :password => ENV['SMTP_PASSWORD'] || ENV['SENDGRID_PASSWORD'], 39 :password => ENV['SMTP_PASSWORD'] || ENV['SENDGRID_PASSWORD'],
37 - :domain => ENV['SMTP_DOMAIN'] || ENV['SENDGRID_DOMAIN'] || ENV['ERRBIT_EMAIL_FROM'].split('@').last 40 + :domain => ENV['SMTP_DOMAIN'] || ENV['SENDGRID_DOMAIN'] ||
  41 + (ENV['ERRBIT_EMAIL_FROM'] ? ENV['ERRBIT_EMAIL_FROM'].split('@').last : nil)
38 } 42 }
39 end 43 end
40 44
config/initializers/mongo.rb
@@ -6,7 +6,7 @@ if config_file.file? &amp;&amp; @@ -6,7 +6,7 @@ if config_file.file? &amp;&amp;
6 elsif ENV['HEROKU'] || ENV['USE_ENV'] 6 elsif ENV['HEROKU'] || ENV['USE_ENV']
7 # No mongoid.yml file. Use ENV variable to define your MongoDB 7 # No mongoid.yml file. Use ENV variable to define your MongoDB
8 # configuration 8 # configuration
9 - if mongo = ENV['MONGOLAB_URI'] || ENV['MONGOHQ_URL'] || ENV['MONGODB_URL'] 9 + if mongo = ENV['MONGOLAB_URI'] || ENV['MONGOHQ_URL'] || ENV['MONGODB_URL'] || ENV['MONGO_URL']
10 settings = URI.parse(mongo) 10 settings = URI.parse(mongo)
11 database_name = settings.path.gsub(/^\//, '') 11 database_name = settings.path.gsub(/^\//, '')
12 else 12 else
config/locales/en.yml
@@ -77,6 +77,8 @@ en: @@ -77,6 +77,8 @@ en:
77 merge: "Merge select issues? They can be unmerged later." 77 merge: "Merge select issues? They can be unmerged later."
78 unmerge: "Unmerge selected issues? They can be re-merged later." 78 unmerge: "Unmerge selected issues? They can be re-merged later."
79 unresolve: "Unresolve selected issues? They can be resolved again later." 79 unresolve: "Unresolve selected issues? They can be resolved again later."
  80 + search:
  81 + search_placeholder: 'Search for issues'
80 82
81 comments: 83 comments:
82 confirm_delete: "Permanently delete this comment?" 84 confirm_delete: "Permanently delete this comment?"
@@ -118,7 +120,6 @@ en: @@ -118,7 +120,6 @@ en:
118 no_watcher: "Sadly, no one is watching this app" 120 no_watcher: "Sadly, no one is watching this app"
119 repository: Repository 121 repository: Repository
120 revision: Revision 122 revision: Revision
121 - search_placeholder: 'Search for issues'  
122 show_hide: "(show/hide)" 123 show_hide: "(show/hide)"
123 unresolved_errs: unresolved errs 124 unresolved_errs: unresolved errs
124 unwatch: unwatch 125 unwatch: unwatch
config/routes.rb
@@ -50,7 +50,7 @@ Errbit::Application.routes.draw do @@ -50,7 +50,7 @@ Errbit::Application.routes.draw do
50 50
51 namespace :api do 51 namespace :api do
52 namespace :v1 do 52 namespace :v1 do
53 - resources :problems, :only => [:index], :defaults => { :format => 'json' } 53 + resources :problems, :only => [:index, :show], :defaults => { :format => 'json' }
54 resources :notices, :only => [:index], :defaults => { :format => 'json' } 54 resources :notices, :only => [:index], :defaults => { :format => 'json' }
55 resources :stats, :only => [], :defaults => { :format => 'json' } do 55 resources :stats, :only => [], :defaults => { :format => 'json' } do
56 collection do 56 collection do
public/robots.txt
1 # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file 1 # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
2 -#  
3 -# To ban all spiders from the entire site uncomment the next two lines:  
4 -# User-Agent: *  
5 -# Disallow: / 2 +User-Agent: *
  3 +Disallow: /
spec/controllers/api/v1/problems_controller_spec.rb
@@ -7,6 +7,70 @@ describe Api::V1::ProblemsController do @@ -7,6 +7,70 @@ describe Api::V1::ProblemsController do
7 @user = Fabricate(:user) 7 @user = Fabricate(:user)
8 end 8 end
9 9
  10 + describe "GET /api/v1/problems/:id" do
  11 + before do
  12 + notice = Fabricate(:notice)
  13 + err = Fabricate(:err, :notices => [notice])
  14 + @problem = Fabricate(:problem, :errs => [err])
  15 + end
  16 +
  17 + it "should return JSON if JSON is requested" do
  18 + get :show, :auth_token => @user.authentication_token, :format => "json", :id => Problem.first.id
  19 + expect { JSON.load(response.body) }.not_to raise_error() #JSON::ParserError
  20 + end
  21 +
  22 + it "should return XML if XML is requested" do
  23 + get :index, :auth_token => @user.authentication_token, :format => "xml", :id => @problem.id
  24 + expect(Nokogiri::XML(response.body).errors).to be_empty
  25 + end
  26 +
  27 + it "should return JSON by default" do
  28 + get :show, :auth_token => @user.authentication_token, :id => @problem.id
  29 + expect { JSON.load(response.body) }.not_to raise_error()#JSON::ParserError)
  30 + end
  31 +
  32 + it "should return the correct problem" do
  33 + get :show, :auth_token => @user.authentication_token, :format => "json", :id => @problem.id
  34 +
  35 + returned_problem = JSON.parse(response.body)
  36 + expect( returned_problem["_id"] ).to eq(@problem.id.to_s)
  37 + end
  38 +
  39 + it "should return only the correct fields" do
  40 + get :show, :auth_token => @user.authentication_token, :format => "json", :id => @problem.id
  41 + returned_problem = JSON.parse(response.body)
  42 +
  43 + expect( returned_problem.keys ).to match_array([
  44 + "app_name",
  45 + "first_notice_at",
  46 + "error_class",
  47 + "messages",
  48 + "hosts",
  49 + "created_at",
  50 + "app_id",
  51 + "last_notice_at",
  52 + "_id",
  53 + "issue_link",
  54 + "resolved",
  55 + "updated_at",
  56 + "resolved_at",
  57 + "last_deploy_at",
  58 + "where",
  59 + "issue_type",
  60 + "notices_count",
  61 + "user_agents",
  62 + "comments_count",
  63 + "message",
  64 + "environment"
  65 + ])
  66 + end
  67 +
  68 + it "returns a 404 if the problem cannot be found" do
  69 + get :show, :auth_token => @user.authentication_token, :format => "json", :id => 'IdontExist'
  70 + expect( response.status ).to eq(404)
  71 + end
  72 + end
  73 +
10 describe "GET /api/v1/problems" do 74 describe "GET /api/v1/problems" do
11 before do 75 before do
12 Fabricate(:problem, :first_notice_at => Date.new(2012, 8, 01), :resolved_at => Date.new(2012, 8, 02)) 76 Fabricate(:problem, :first_notice_at => Date.new(2012, 8, 01), :resolved_at => Date.new(2012, 8, 02))
spec/controllers/problems_controller_spec.rb
@@ -124,6 +124,31 @@ describe ProblemsController do @@ -124,6 +124,31 @@ describe ProblemsController do
124 end 124 end
125 end 125 end
126 126
  127 + describe "GET /problems/search" do
  128 + before do
  129 + sign_in Fabricate(:admin)
  130 + @app = Fabricate(:app)
  131 + @problem1 = Fabricate(:problem, :app=>@app, message: "Most important")
  132 + @problem2 = Fabricate(:problem, :app=>@app, message: "Very very important")
  133 + end
  134 +
  135 + it "renders successfully" do
  136 + get :search
  137 + expect(response).to be_success
  138 + end
  139 +
  140 + it "renders index template" do
  141 + get :search
  142 + expect(response).to render_template('problems/index')
  143 + end
  144 +
  145 + it "searches problems for given string" do
  146 + get :search, :search => "Most important"
  147 + expect(controller.problems).to include(@problem1)
  148 + expect(controller.problems).to_not include(@problem2)
  149 + end
  150 + end
  151 +
127 describe "GET /apps/:app_id/problems/:id" do 152 describe "GET /apps/:app_id/problems/:id" do
128 #render_views 153 #render_views
129 154
spec/mailers/mailer_spec.rb
1 require 'spec_helper' 1 require 'spec_helper'
2 2
  3 +shared_examples "a notification email" do
  4 + it "should have X-Mailer header" do
  5 + expect(@email).to have_header('X-Mailer', 'Errbit')
  6 + end
  7 +
  8 + it "should have X-Errbit-Host header" do
  9 + expect(@email).to have_header('X-Errbit-Host', Errbit::Config.host)
  10 + end
  11 +
  12 + it "should have Precedence header" do
  13 + expect(@email).to have_header('Precedence', 'bulk')
  14 + end
  15 +
  16 + it "should have Auto-Submitted header" do
  17 + expect(@email).to have_header('Auto-Submitted', 'auto-generated')
  18 + end
  19 +
  20 + it "should have X-Auto-Response-Suppress header" do
  21 + # http://msdn.microsoft.com/en-us/library/ee219609(v=EXCHG.80).aspx
  22 + expect(@email).to have_header('X-Auto-Response-Suppress', 'OOF, AutoReply')
  23 + end
  24 +
  25 + it "should send the email" do
  26 + expect(ActionMailer::Base.deliveries.size).to eq 1
  27 + end
  28 +end
  29 +
3 describe Mailer do 30 describe Mailer do
4 context "Err Notification" do 31 context "Err Notification" do
5 include EmailSpec::Helpers 32 include EmailSpec::Helpers
@@ -19,9 +46,8 @@ describe Mailer do @@ -19,9 +46,8 @@ describe Mailer do
19 @email = Mailer.err_notification(notice).deliver 46 @email = Mailer.err_notification(notice).deliver
20 end 47 end
21 48
22 - it "should send the email" do  
23 - expect(ActionMailer::Base.deliveries.size).to eq 1  
24 - end 49 + it_should_behave_like "a notification email"
  50 +
25 51
26 it "should html-escape the notice's message for the html part" do 52 it "should html-escape the notice's message for the html part" do
27 expect(@email).to have_body_text("class &lt; ActionController::Base") 53 expect(@email).to have_body_text("class &lt; ActionController::Base")
@@ -62,10 +88,6 @@ describe Mailer do @@ -62,10 +88,6 @@ describe Mailer do
62 @email = Mailer.comment_notification(comment).deliver 88 @email = Mailer.comment_notification(comment).deliver
63 end 89 end
64 90
65 - it "should send the email" do  
66 - expect(ActionMailer::Base.deliveries.size).to eq 1  
67 - end  
68 -  
69 it "should be sent to comment notification recipients" do 91 it "should be sent to comment notification recipients" do
70 expect(@email.to).to eq recipients 92 expect(@email.to).to eq recipients
71 end 93 end
spec/models/notification_service/gtalk_service_spec.rb
@@ -17,7 +17,7 @@ describe NotificationService::GtalkService do @@ -17,7 +17,7 @@ describe NotificationService::GtalkService do
17 expect(gtalk).to receive(:connect).with(notification_service.service) 17 expect(gtalk).to receive(:connect).with(notification_service.service)
18 expect(gtalk).to receive(:auth).with(notification_service.api_token) 18 expect(gtalk).to receive(:auth).with(notification_service.api_token)
19 message_value = """#{problem.app.name.to_s} 19 message_value = """#{problem.app.name.to_s}
20 -http://#{Errbit::Config.host}/apps/#{problem.app.id.to_s} 20 +#{Errbit::Config.protocol}://#{Errbit::Config.host}/apps/#{problem.app.id.to_s}
21 #{notification_service.notification_description problem}""" 21 #{notification_service.notification_description problem}"""
22 22
23 expect(Jabber::Message).to receive(:new).with(notification_service.user_id, message_value).and_return(message) 23 expect(Jabber::Message).to receive(:new).with(notification_service.user_id, message_value).and_return(message)
@@ -39,7 +39,7 @@ http://#{Errbit::Config.host}/apps/#{problem.app.id.to_s} @@ -39,7 +39,7 @@ http://#{Errbit::Config.host}/apps/#{problem.app.id.to_s}
39 @notification_service = Fabricate :gtalk_notification_service, :app => @notice.app 39 @notification_service = Fabricate :gtalk_notification_service, :app => @notice.app
40 @problem = @notice.problem 40 @problem = @notice.problem
41 @error_msg = """#{@problem.app.name.to_s} 41 @error_msg = """#{@problem.app.name.to_s}
42 -http://#{Errbit::Config.host}/apps/#{@problem.app.id.to_s} 42 +#{Errbit::Config.protocol}://#{Errbit::Config.host}/apps/#{@problem.app.id.to_s}
43 #{@notification_service.notification_description @problem}""" 43 #{@notification_service.notification_description @problem}"""
44 44
45 # gtalk stubbing 45 # gtalk stubbing
@@ -105,7 +105,7 @@ http://#{Errbit::Config.host}/apps/#{@problem.app.id.to_s} @@ -105,7 +105,7 @@ http://#{Errbit::Config.host}/apps/#{@problem.app.id.to_s}
105 expect(gtalk).to receive(:connect) 105 expect(gtalk).to receive(:connect)
106 expect(gtalk).to receive(:auth).with(notification_service.api_token) 106 expect(gtalk).to receive(:auth).with(notification_service.api_token)
107 message_value = """#{problem.app.name.to_s} 107 message_value = """#{problem.app.name.to_s}
108 -http://#{Errbit::Config.host}/apps/#{problem.app.id.to_s} 108 +#{Errbit::Config.protocol}://#{Errbit::Config.host}/apps/#{problem.app.id.to_s}
109 #{notification_service.notification_description problem}""" 109 #{notification_service.notification_description problem}"""
110 110
111 expect(Jabber::Message).to receive(:new).with(notification_service.room_id, message_value).and_return(message) 111 expect(Jabber::Message).to receive(:new).with(notification_service.room_id, message_value).and_return(message)
spec/models/notification_service/notification_service_spec.rb 0 → 100644
@@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
  1 +require 'spec_helper'
  2 +
  3 +describe NotificationService do
  4 +
  5 + let(:notice) { Fabricate :notice }
  6 + let(:notification_service) { Fabricate :notification_service, :app => notice.app }
  7 + let(:problem) { notice.problem }
  8 +
  9 + it "it should use http by default in #problem_url" do
  10 + notification_service.problem_url(problem).should start_with 'http://'
  11 + end
  12 +
  13 + it "it should use the protocol value specified in the config in #problem_url" do
  14 + Errbit::Config.protocol = 'https'
  15 + notification_service.problem_url(problem).should start_with 'https://'
  16 + end
  17 +
  18 +end