Commit 30b00acfc34c1db93d3f8dc1460452ea866ed0c0

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

Specs for lighthouse tracker integration.

Gemfile
... ... @@ -14,7 +14,7 @@ end
14 14  
15 15 group :development, :test do
16 16 gem 'rspec-rails', '~> 2.5'
17   - gem 'webmock'
  17 + gem 'webmock', :require => false
18 18 end
19 19  
20 20 group :test do
... ...
app/controllers/apps_controller.rb
... ... @@ -22,6 +22,7 @@ class AppsController < ApplicationController
22 22 def new
23 23 @app = App.new
24 24 @app.watchers.build
  25 + @app.issue_tracker = IssueTracker.new
25 26 end
26 27  
27 28 def edit
... ...
app/controllers/errs_controller.rb
1 1 class ErrsController < ApplicationController
2 2  
3 3 before_filter :find_app, :except => [:index, :all]
  4 + before_filter :find_err, :except => [:index, :all]
4 5  
5 6 def index
6 7 app_scope = current_user.admin? ? App.all : current_user.apps
... ... @@ -20,16 +21,25 @@ class ErrsController &lt; ApplicationController
20 21 end
21 22  
22 23 def show
23   - @err = @app.errs.find(params[:id])
24 24 page = (params[:notice] || @err.notices.count)
25 25 page = 1 if page.to_i.zero?
26 26 @notices = @err.notices.ordered.paginate(:page => page, :per_page => 1)
27 27 @notice = @notices.first
28 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 42 def resolve
31   - @err = @app.errs.find(params[:id])
32   -
33 43 # Deal with bug in mogoid where find is returning an Enumberable obj
34 44 @err = @err.first if @err.respond_to?(:first)
35 45  
... ... @@ -51,5 +61,9 @@ class ErrsController &lt; ApplicationController
51 61 # apparently finding by 'watchers.email' and 'id' is broken
52 62 raise(Mongoid::Errors::DocumentNotFound.new(App,@app.id)) unless current_user.admin? || current_user.watching?(@app)
53 63 end
  64 +
  65 + def find_err
  66 + @err = @app.errs.find(params[:id])
  67 + end
54 68  
55 69 end
... ...
app/models/err.rb
... ... @@ -9,6 +9,7 @@ class Err
9 9 field :fingerprint
10 10 field :last_notice_at, :type => DateTime
11 11 field :resolved, :type => Boolean, :default => false
  12 + field :issue_link, :type => String
12 13  
13 14 index :last_notice_at
14 15  
... ...
app/models/issue_tracker.rb
1 1 class IssueTracker
2 2 include Mongoid::Document
3 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 8 validate :check_lighthouseapp_params
6 9  
... ... @@ -15,11 +18,72 @@ class IssueTracker
15 18 Lighthouse.account = account
16 19 Lighthouse.token = api_token
17 20  
  21 + # updating lighthouse account
  22 + Lighthouse::Ticket.site
  23 +
18 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 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 87 end
24 88  
25 89 protected
... ...
app/views/errs/show.html.haml
... ... @@ -10,7 +10,13 @@
10 10 %strong Last Notice:
11 11 = last_notice_at(@err).to_s(:micro)
12 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 21 %h4= @notice.try(:message)
16 22  
... ...
config/environments/development.rb
... ... @@ -16,6 +16,7 @@ Errbit::Application.configure do
16 16  
17 17 # Don't care if the mailer can't send
18 18 config.action_mailer.raise_delivery_errors = false
  19 + config.action_mailer.default_url_options = { :host => 'localhost:3000' }
19 20  
20 21 # Print deprecation notices to the Rails logger
21 22 config.active_support.deprecation = :log
... ...
config/environments/test.rb
... ... @@ -24,6 +24,7 @@ Errbit::Application.configure do
24 24 # The :test delivery method accumulates sent emails in the
25 25 # ActionMailer::Base.deliveries array.
26 26 config.action_mailer.delivery_method = :test
  27 + config.action_mailer.default_url_options = { :host => 'test.host' }
27 28  
28 29 # Use SQL instead of Active Record's schema dumper when creating the test database.
29 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 20 resources :notices
21 21 member do
22 22 put :resolve
  23 + post :create_issue
23 24 end
24 25 end
25 26  
... ...
spec/controllers/errs_controller_spec.rb
... ... @@ -123,6 +123,33 @@ describe ErrsController do
123 123 get :show, :app_id => app.id, :id => err.id
124 124 response.should be_success
125 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 153 end
127 154  
128 155 context 'when logged in as a user' do
... ... @@ -186,5 +213,83 @@ describe ErrsController do
186 213 response.should redirect_to(errs_path)
187 214 end
188 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 295 end
... ...
spec/models/issue_tracker_spec.rb
... ... @@ -2,16 +2,4 @@
2 2 require 'spec_helper'
3 3  
4 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 5 end
... ...