Commit 30b00acfc34c1db93d3f8dc1460452ea866ed0c0

Authored by Nick Recobra
1 parent 12640a49
Exists in master and in 1 other branch production

Specs for lighthouse tracker integration.

@@ -14,7 +14,7 @@ end @@ -14,7 +14,7 @@ end
14 14
15 group :development, :test do 15 group :development, :test do
16 gem 'rspec-rails', '~> 2.5' 16 gem 'rspec-rails', '~> 2.5'
17 - gem 'webmock' 17 + gem 'webmock', :require => false
18 end 18 end
19 19
20 group :test do 20 group :test do
app/controllers/apps_controller.rb
@@ -22,6 +22,7 @@ class AppsController < ApplicationController @@ -22,6 +22,7 @@ class AppsController < ApplicationController
22 def new 22 def new
23 @app = App.new 23 @app = App.new
24 @app.watchers.build 24 @app.watchers.build
  25 + @app.issue_tracker = IssueTracker.new
25 end 26 end
26 27
27 def edit 28 def edit
app/controllers/errs_controller.rb
1 class ErrsController < ApplicationController 1 class ErrsController < ApplicationController
2 2
3 before_filter :find_app, :except => [:index, :all] 3 before_filter :find_app, :except => [:index, :all]
  4 + before_filter :find_err, :except => [:index, :all]
4 5
5 def index 6 def index
6 app_scope = current_user.admin? ? App.all : current_user.apps 7 app_scope = current_user.admin? ? App.all : current_user.apps
@@ -20,16 +21,25 @@ class ErrsController &lt; ApplicationController @@ -20,16 +21,25 @@ class ErrsController &lt; ApplicationController
20 end 21 end
21 22
22 def show 23 def show
23 - @err = @app.errs.find(params[:id])  
24 page = (params[:notice] || @err.notices.count) 24 page = (params[:notice] || @err.notices.count)
25 page = 1 if page.to_i.zero? 25 page = 1 if page.to_i.zero?
26 @notices = @err.notices.ordered.paginate(:page => page, :per_page => 1) 26 @notices = @err.notices.ordered.paginate(:page => page, :per_page => 1)
27 @notice = @notices.first 27 @notice = @notices.first
28 end 28 end
  29 +
  30 + def create_issue
  31 + if @app.issue_tracker
  32 + @app.issue_tracker.create_issue @err
  33 + else
  34 + flash[:error] = "This up has no issue tracker setup."
  35 + end
  36 + redirect_to app_err_path(@app, @err)
  37 + rescue ActiveResource::ConnectionError
  38 + flash[:error] = "There was an error during issue creation. Check your tracker settings or try again later."
  39 + redirect_to app_err_path(@app, @err)
  40 + end
29 41
30 def resolve 42 def resolve
31 - @err = @app.errs.find(params[:id])  
32 -  
33 # Deal with bug in mogoid where find is returning an Enumberable obj 43 # Deal with bug in mogoid where find is returning an Enumberable obj
34 @err = @err.first if @err.respond_to?(:first) 44 @err = @err.first if @err.respond_to?(:first)
35 45
@@ -51,5 +61,9 @@ class ErrsController &lt; ApplicationController @@ -51,5 +61,9 @@ class ErrsController &lt; ApplicationController
51 # apparently finding by 'watchers.email' and 'id' is broken 61 # apparently finding by 'watchers.email' and 'id' is broken
52 raise(Mongoid::Errors::DocumentNotFound.new(App,@app.id)) unless current_user.admin? || current_user.watching?(@app) 62 raise(Mongoid::Errors::DocumentNotFound.new(App,@app.id)) unless current_user.admin? || current_user.watching?(@app)
53 end 63 end
  64 +
  65 + def find_err
  66 + @err = @app.errs.find(params[:id])
  67 + end
54 68
55 end 69 end
app/models/err.rb
@@ -9,6 +9,7 @@ class Err @@ -9,6 +9,7 @@ class Err
9 field :fingerprint 9 field :fingerprint
10 field :last_notice_at, :type => DateTime 10 field :last_notice_at, :type => DateTime
11 field :resolved, :type => Boolean, :default => false 11 field :resolved, :type => Boolean, :default => false
  12 + field :issue_link, :type => String
12 13
13 index :last_notice_at 14 index :last_notice_at
14 15
app/models/issue_tracker.rb
1 class IssueTracker 1 class IssueTracker
2 include Mongoid::Document 2 include Mongoid::Document
3 include Mongoid::Timestamps 3 include Mongoid::Timestamps
  4 + include HashHelper
  5 + include Rails.application.routes.url_helpers
  6 + default_url_options[:host] = Errbit::Application.config.action_mailer.default_url_options[:host]
4 7
5 validate :check_lighthouseapp_params 8 validate :check_lighthouseapp_params
6 9
@@ -15,11 +18,72 @@ class IssueTracker @@ -15,11 +18,72 @@ class IssueTracker
15 Lighthouse.account = account 18 Lighthouse.account = account
16 Lighthouse.token = api_token 19 Lighthouse.token = api_token
17 20
  21 + # updating lighthouse account
  22 + Lighthouse::Ticket.site
  23 +
18 ticket = Lighthouse::Ticket.new(:project_id => project_id) 24 ticket = Lighthouse::Ticket.new(:project_id => project_id)
19 - ticket.title = "[#{ err.where }] #{err.message.to_s.truncate(27)}"  
20 - #ticket.body = err.backtrace.join("\n") 25 + ticket.title = "[#{ err.environment }][#{ err.where }] #{err.message.to_s.truncate(100)}"
  26 +
  27 + ticket.body = ""
  28 + ticket.body += "[See this exception on Errbit](#{ app_err_url err.app, err } \"See this exception on Errbit\")"
  29 + ticket.body += "\n"
  30 + if notice = err.notices.first
  31 + ticket.body += "# #{notice.message} #"
  32 + ticket.body += "\n"
  33 + ticket.body += "## Summary ##"
  34 + ticket.body += "\n"
  35 + if notice.request['url'].present?
  36 + ticket.body += "### URL ###"
  37 + ticket.body += "\n"
  38 + ticket.body += "[#{notice.request['url']}](#{notice.request['url']})"
  39 + ticket.body += "\n"
  40 + end
  41 + ticket.body += "### Where ###"
  42 + ticket.body += "\n"
  43 + ticket.body += notice.err.where
  44 + ticket.body += "\n"
  45 +
  46 + ticket.body += "### Occured ###"
  47 + ticket.body += "\n"
  48 + ticket.body += notice.created_at.to_s(:micro)
  49 + ticket.body += "\n"
  50 +
  51 + ticket.body += "### Similar ###"
  52 + ticket.body += "\n"
  53 + ticket.body += (notice.err.notices.count - 1).to_s
  54 + ticket.body += "\n"
  55 +
  56 + ticket.body += "## Params ##"
  57 + ticket.body += "\n"
  58 + ticket.body += "<code>#{pretty_hash(notice.params)}</code>"
  59 + ticket.body += "\n"
  60 +
  61 + ticket.body += "## Session ##"
  62 + ticket.body += "\n"
  63 + ticket.body += "<code>#{pretty_hash(notice.session)}</code>"
  64 + ticket.body += "\n"
  65 +
  66 + ticket.body += "## Backtrace ##"
  67 + ticket.body += "\n"
  68 + ticket.body += "<code>"
  69 + for line in notice.backtrace
  70 + ticket.body += "#{line['number']}: #{line['file'].sub(/^\[PROJECT_ROOT\]/, '')} -> **#{line['method']}**"
  71 + ticket.body += "\n"
  72 + end
  73 + ticket.body += "</code>"
  74 + ticket.body += "\n"
  75 +
  76 + ticket.body += "## Environment ##"
  77 + ticket.body += "\n"
  78 + for key, val in notice.env_vars
  79 + ticket.body += "#{key}: #{val}"
  80 + end
  81 + ticket.body += "\n"
  82 + end
  83 +
21 ticket.tags << "errbit" 84 ticket.tags << "errbit"
22 - ticket.save 85 + ticket.save!
  86 + err.update_attribute :issue_link, "#{Lighthouse::Ticket.site.to_s.sub(/#{Lighthouse::Ticket.site.path}$/, '')}#{Lighthouse::Ticket.element_path(ticket.id, :project_id => project_id)}".sub(/\.xml$/, '')
23 end 87 end
24 88
25 protected 89 protected
app/views/errs/show.html.haml
@@ -10,7 +10,13 @@ @@ -10,7 +10,13 @@
10 %strong Last Notice: 10 %strong Last Notice:
11 = last_notice_at(@err).to_s(:micro) 11 = last_notice_at(@err).to_s(:micro)
12 - content_for :action_bar do 12 - content_for :action_bar do
13 - %span= link_to 'resolve', resolve_app_err_path(@app, @err), :method => :put, :confirm => err_confirm, :class => 'resolve' if @err.unresolved? 13 + - if @err.unresolved?
  14 + - if @err.app.issue_tracker
  15 + - if @err.issue_link.blank?
  16 + %span= link_to 'create issue', create_issue_app_err_path(@app, @err), :method => :post, :class => 'create-issue'
  17 + - else
  18 + %span= link_to 'go to issue', @err.issue_link, :class => 'goto-issue'
  19 + %span= link_to 'resolve', resolve_app_err_path(@app, @err), :method => :put, :confirm => err_confirm, :class => 'resolve'
14 20
15 %h4= @notice.try(:message) 21 %h4= @notice.try(:message)
16 22
config/environments/development.rb
@@ -16,6 +16,7 @@ Errbit::Application.configure do @@ -16,6 +16,7 @@ Errbit::Application.configure do
16 16
17 # Don't care if the mailer can't send 17 # Don't care if the mailer can't send
18 config.action_mailer.raise_delivery_errors = false 18 config.action_mailer.raise_delivery_errors = false
  19 + config.action_mailer.default_url_options = { :host => 'localhost:3000' }
19 20
20 # Print deprecation notices to the Rails logger 21 # Print deprecation notices to the Rails logger
21 config.active_support.deprecation = :log 22 config.active_support.deprecation = :log
config/environments/test.rb
@@ -24,6 +24,7 @@ Errbit::Application.configure do @@ -24,6 +24,7 @@ Errbit::Application.configure do
24 # The :test delivery method accumulates sent emails in the 24 # The :test delivery method accumulates sent emails in the
25 # ActionMailer::Base.deliveries array. 25 # ActionMailer::Base.deliveries array.
26 config.action_mailer.delivery_method = :test 26 config.action_mailer.delivery_method = :test
  27 + config.action_mailer.default_url_options = { :host => 'test.host' }
27 28
28 # Use SQL instead of Active Record's schema dumper when creating the test database. 29 # Use SQL instead of Active Record's schema dumper when creating the test database.
29 # This is necessary if your schema can't be completely dumped by the schema dumper, 30 # This is necessary if your schema can't be completely dumped by the schema dumper,
config/routes.rb
@@ -20,6 +20,7 @@ Errbit::Application.routes.draw do @@ -20,6 +20,7 @@ Errbit::Application.routes.draw do
20 resources :notices 20 resources :notices
21 member do 21 member do
22 put :resolve 22 put :resolve
  23 + post :create_issue
23 end 24 end
24 end 25 end
25 26
spec/controllers/errs_controller_spec.rb
@@ -123,6 +123,33 @@ describe ErrsController do @@ -123,6 +123,33 @@ describe ErrsController do
123 get :show, :app_id => app.id, :id => err.id 123 get :show, :app_id => app.id, :id => err.id
124 response.should be_success 124 response.should be_success
125 end 125 end
  126 +
  127 + context "create issue button" do
  128 + let(:button_matcher) { match(/create issue/) }
  129 +
  130 + it "should not exist for err's app without issue tracker" do
  131 + err = Factory :err
  132 + get :show, :app_id => err.app.id, :id => err.id
  133 +
  134 + response.body.should_not button_matcher
  135 + end
  136 +
  137 + it "should exist for err's app with issue tracker" do
  138 + tracker = Factory(:lighthouseapp_tracker)
  139 + err = Factory(:err, :app => tracker.app)
  140 + get :show, :app_id => err.app.id, :id => err.id
  141 +
  142 + response.body.should button_matcher
  143 + end
  144 +
  145 + it "should not exist for err with issue_link" do
  146 + tracker = Factory(:lighthouseapp_tracker)
  147 + err = Factory(:err, :app => tracker.app, :issue_link => "http://some.host")
  148 + get :show, :app_id => err.app.id, :id => err.id
  149 +
  150 + response.body.should_not button_matcher
  151 + end
  152 + end
126 end 153 end
127 154
128 context 'when logged in as a user' do 155 context 'when logged in as a user' do
@@ -186,5 +213,83 @@ describe ErrsController do @@ -186,5 +213,83 @@ describe ErrsController do
186 response.should redirect_to(errs_path) 213 response.should redirect_to(errs_path)
187 end 214 end
188 end 215 end
189 - 216 +
  217 + describe "POST /apps/:app_id/errs/:id/create_issue" do
  218 + render_views
  219 +
  220 + before(:each) do
  221 + sign_in Factory(:admin)
  222 + end
  223 +
  224 + context "successful issue creation" do
  225 + context "lighthouseapp tracker" do
  226 + let(:notice) { Factory :notice }
  227 + let(:tracker) { Factory :lighthouseapp_tracker, :app => notice.err.app }
  228 + let(:err) { notice.err }
  229 +
  230 + before(:each) do
  231 + number = 5
  232 + @issue_link = "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets/#{number}.xml"
  233 + body = "<ticket><number type=\"integer\">#{number}</number></ticket>"
  234 + stub_request(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml").to_return(:status => 201, :headers => {'Location' => @issue_link}, :body => body )
  235 +
  236 + post :create_issue, :app_id => err.app.id, :id => err.id
  237 + err.reload
  238 + end
  239 +
  240 + it "should make request to Lighthouseapp with err params" do
  241 + requested = have_requested(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml")
  242 + WebMock.should requested.with(:headers => {'X-Lighthousetoken' => tracker.api_token})
  243 + WebMock.should requested.with(:body => /<tag>errbit<\/tag>/)
  244 + WebMock.should requested.with(:body => /<title>\[#{ err.environment }\]\[#{err.where}\] #{err.message.to_s.truncate(100)}<\/title>/)
  245 + WebMock.should requested.with(:body => /<body>.+<\/body>/m)
  246 + end
  247 +
  248 + it "should redirect to err page" do
  249 + response.should redirect_to( app_err_path(err.app, err) )
  250 + end
  251 +
  252 + it "should create issue link for err" do
  253 + err.issue_link.should == @issue_link.sub(/\.xml$/, '')
  254 + end
  255 + end
  256 + end
  257 +
  258 + context "absent issue tracker" do
  259 + let(:err) { Factory :err }
  260 +
  261 + before(:each) do
  262 + post :create_issue, :app_id => err.app.id, :id => err.id
  263 + end
  264 +
  265 + it "should redirect to err page" do
  266 + response.should redirect_to( app_err_path(err.app, err) )
  267 + end
  268 +
  269 + it "should set flash error message telling issue tracker of the app doesn't exist" do
  270 + flash[:error].should == "This up has no issue tracker setup."
  271 + end
  272 + end
  273 +
  274 + context "error during request to a tracker" do
  275 + context "lighthouseapp tracker" do
  276 + let(:tracker) { Factory :lighthouseapp_tracker }
  277 + let(:err) { Factory :err, :app => tracker.app }
  278 +
  279 + before(:each) do
  280 + stub_request(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml").to_return(:status => 500)
  281 +
  282 + post :create_issue, :app_id => err.app.id, :id => err.id
  283 + end
  284 +
  285 + it "should redirect to err page" do
  286 + response.should redirect_to( app_err_path(err.app, err) )
  287 + end
  288 +
  289 + it "should notify of connection error" do
  290 + flash[:error].should == "There was an error during issue creation. Check your tracker settings or try again later."
  291 + end
  292 + end
  293 + end
  294 + end
190 end 295 end
spec/models/issue_tracker_spec.rb
@@ -2,16 +2,4 @@ @@ -2,16 +2,4 @@
2 require 'spec_helper' 2 require 'spec_helper'
3 3
4 describe IssueTracker do 4 describe IssueTracker do
5 - describe "#create_issue" do  
6 - context "lighthouseapp tracker" do  
7 - let(:tracker) { Factory :lighthouseapp_tracker }  
8 - let(:err) { Factory :err }  
9 -  
10 - it "should make request to Lighthouseapp with err params" do  
11 - stub_request(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml")  
12 - tracker.create_issue err  
13 - WebMock.should have_requested(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml")  
14 - end  
15 - end  
16 - end  
17 end 5 end