Commit 387bca94f6e617fe5e910eed032900145de4b11b

Authored by Marcin Ciunelis
1 parent 3db48ca3
Exists in master and in 1 other branch production

rename ErrsController to ProblemsController

Showing 44 changed files with 1016 additions and 1017 deletions   Show diff stats
app/controllers/comments_controller.rb
@@ -11,7 +11,7 @@ class CommentsController < ApplicationController @@ -11,7 +11,7 @@ class CommentsController < ApplicationController
11 else 11 else
12 flash[:error] = "I'm sorry, your comment was blank! Try again?" 12 flash[:error] = "I'm sorry, your comment was blank! Try again?"
13 end 13 end
14 - redirect_to app_err_path(@app, @problem) 14 + redirect_to app_problem_path(@app, @problem)
15 end 15 end
16 16
17 def destroy 17 def destroy
@@ -21,7 +21,7 @@ class CommentsController < ApplicationController @@ -21,7 +21,7 @@ class CommentsController < ApplicationController
21 else 21 else
22 flash[:error] = "Sorry, I couldn't delete your comment for some reason. I hope you don't have any sensitive information in there!" 22 flash[:error] = "Sorry, I couldn't delete your comment for some reason. I hope you don't have any sensitive information in there!"
23 end 23 end
24 - redirect_to app_err_path(@app, @problem) 24 + redirect_to app_problem_path(@app, @problem)
25 end 25 end
26 26
27 protected 27 protected
@@ -34,7 +34,7 @@ class CommentsController < ApplicationController @@ -34,7 +34,7 @@ class CommentsController < ApplicationController
34 end 34 end
35 35
36 def find_problem 36 def find_problem
37 - @problem = @app.problems.find(params[:err_id]) 37 + @problem = @app.problems.find(params[:problem_id])
38 end 38 end
39 end 39 end
40 40
app/controllers/errs_controller.rb
@@ -1,157 +0,0 @@ @@ -1,157 +0,0 @@
1 -class ErrsController < ApplicationController  
2 - include ActionView::Helpers::TextHelper  
3 -  
4 - before_filter :find_app, :except => [:index, :all, :destroy_several, :resolve_several, :unresolve_several, :merge_several, :unmerge_several]  
5 - before_filter :find_problem, :except => [:index, :all, :destroy_several, :resolve_several, :unresolve_several, :merge_several, :unmerge_several]  
6 - before_filter :find_selected_problems, :only => [:destroy_several, :resolve_several, :unresolve_several, :merge_several, :unmerge_several]  
7 - before_filter :set_sorting_params, :only => [:index, :all]  
8 - before_filter :set_tracker_params, :only => [:create_issue]  
9 -  
10 - def index  
11 - app_scope = current_user.admin? ? App.all : current_user.apps  
12 -  
13 - @problems = Problem.for_apps(app_scope).in_env(params[:environment]).unresolved.ordered_by(@sort, @order)  
14 - @selected_problems = params[:problems] || []  
15 - respond_to do |format|  
16 - format.html do  
17 - @problems = @problems.page(params[:page]).per(current_user.per_page)  
18 - end  
19 - format.atom  
20 - end  
21 - end  
22 -  
23 - def all  
24 - app_scope = current_user.admin? ? App.all : current_user.apps  
25 - @problems = Problem.for_apps(app_scope).ordered_by(@sort, @order).page(params[:page]).per(current_user.per_page)  
26 - @selected_problems = params[:problems] || []  
27 - end  
28 -  
29 - def show  
30 - @notices = @problem.notices.reverse_ordered.page(params[:notice]).per(1)  
31 - @notice = @notices.first  
32 - @comment = Comment.new  
33 - if request.headers['X-PJAX']  
34 - params["_pjax"] = nil  
35 - render :layout => false  
36 - end  
37 - end  
38 -  
39 - def create_issue  
40 - # Create an issue on GitHub using user's github token  
41 - if params[:tracker] == 'user_github'  
42 - if !@app.github_repo?  
43 - flash[:error] = "This app doesn't have a GitHub repo set up."  
44 - elsif !current_user.github_account?  
45 - flash[:error] = "You haven't linked your Github account."  
46 - else  
47 - @tracker = GithubIssuesTracker.new(  
48 - :app => @app,  
49 - :username => current_user.github_login,  
50 - :oauth_token => current_user.github_oauth_token  
51 - )  
52 - end  
53 -  
54 - # Or, create an issue using the App's issue tracker  
55 - elsif @app.issue_tracker_configured?  
56 - @tracker = @app.issue_tracker  
57 -  
58 - # Otherwise, display error about missing tracker configuration.  
59 - else  
60 - flash[:error] = "This app has no issue tracker setup."  
61 - end  
62 -  
63 - if flash[:error].blank? && @tracker  
64 - begin  
65 - @tracker.create_issue @problem, current_user  
66 - rescue Exception => ex  
67 - Rails.logger.error "Error during issue creation: " << ex.message  
68 - flash[:error] = "There was an error during issue creation: #{ex.message}"  
69 - end  
70 - end  
71 -  
72 - redirect_to app_err_path(@app, @problem)  
73 - end  
74 -  
75 - def unlink_issue  
76 - @problem.update_attribute :issue_link, nil  
77 - redirect_to app_err_path(@app, @problem)  
78 - end  
79 -  
80 - def resolve  
81 - @problem.resolve!  
82 - flash[:success] = 'Great news everyone! The err has been resolved.'  
83 - redirect_to :back  
84 - rescue ActionController::RedirectBackError  
85 - redirect_to app_path(@app)  
86 - end  
87 -  
88 - def resolve_several  
89 - @selected_problems.each(&:resolve!)  
90 - flash[:success] = "Great news everyone! #{pluralize(@selected_problems.count, 'err has', 'errs have')} been resolved."  
91 - redirect_to :back  
92 - end  
93 -  
94 - def unresolve_several  
95 - @selected_problems.each(&:unresolve!)  
96 - flash[:success] = "#{pluralize(@selected_problems.count, 'err has', 'errs have')} been unresolved."  
97 - redirect_to :back  
98 - end  
99 -  
100 - def merge_several  
101 - if @selected_problems.length < 2  
102 - flash[:notice] = "You must select at least two errors to merge"  
103 - else  
104 - @merged_problem = Problem.merge!(@selected_problems)  
105 - flash[:notice] = "#{@selected_problems.count} errors have been merged."  
106 - end  
107 - redirect_to :back  
108 - end  
109 -  
110 - def unmerge_several  
111 - all = @selected_problems.map(&:unmerge!).flatten  
112 - flash[:success] = "#{pluralize(all.length, 'err has', 'errs have')} been unmerged."  
113 - redirect_to :back  
114 - end  
115 -  
116 - def destroy_several  
117 - nb_problem_destroy = ProblemDestroy.execute(@selected_problems)  
118 - flash[:notice] = "#{pluralize(nb_problem_destroy, 'err has', 'errs have')} been deleted."  
119 - redirect_to :back  
120 - end  
121 -  
122 - protected  
123 - def find_app  
124 - @app = App.find(params[:app_id])  
125 -  
126 - # Mongoid Bug: could not chain: current_user.apps.find_by_id!  
127 - # apparently finding by 'watchers.email' and 'id' is broken  
128 - raise(Mongoid::Errors::DocumentNotFound.new(App,@app.id)) unless current_user.admin? || current_user.watching?(@app)  
129 - end  
130 -  
131 - def find_problem  
132 - @problem = @app.problems.find(params[:id])  
133 - end  
134 -  
135 - def set_tracker_params  
136 - IssueTracker.default_url_options[:host] = request.host  
137 - IssueTracker.default_url_options[:port] = request.port  
138 - IssueTracker.default_url_options[:protocol] = request.scheme  
139 - end  
140 -  
141 - def find_selected_problems  
142 - err_ids = (params[:problems] || []).compact  
143 - if err_ids.empty?  
144 - flash[:notice] = "You have not selected any errors"  
145 - redirect_to :back  
146 - else  
147 - @selected_problems = Array(Problem.find(err_ids))  
148 - end  
149 - end  
150 -  
151 - def set_sorting_params  
152 - @sort = params[:sort]  
153 - @sort = "last_notice_at" unless %w{app message last_notice_at last_deploy_at count}.member?(@sort)  
154 - @order = params[:order] || "desc"  
155 - end  
156 -end  
157 -  
app/controllers/notices_controller.rb
@@ -15,6 +15,6 @@ class NoticesController &lt; ApplicationController @@ -15,6 +15,6 @@ class NoticesController &lt; ApplicationController
15 # Redirects a notice to the problem page. Useful when using User Information at Airbrake gem. 15 # Redirects a notice to the problem page. Useful when using User Information at Airbrake gem.
16 def locate 16 def locate
17 problem = Notice.find(params[:id]).problem 17 problem = Notice.find(params[:id]).problem
18 - redirect_to app_err_path(problem.app, problem) 18 + redirect_to app_problem_path(problem.app, problem)
19 end 19 end
20 end 20 end
app/controllers/problems_controller.rb 0 → 100644
@@ -0,0 +1,157 @@ @@ -0,0 +1,157 @@
  1 +class ProblemsController < ApplicationController
  2 + include ActionView::Helpers::TextHelper
  3 +
  4 + before_filter :find_app, :except => [:index, :all, :destroy_several, :resolve_several, :unresolve_several, :merge_several, :unmerge_several]
  5 + before_filter :find_problem, :except => [:index, :all, :destroy_several, :resolve_several, :unresolve_several, :merge_several, :unmerge_several]
  6 + before_filter :find_selected_problems, :only => [:destroy_several, :resolve_several, :unresolve_several, :merge_several, :unmerge_several]
  7 + before_filter :set_sorting_params, :only => [:index, :all]
  8 + before_filter :set_tracker_params, :only => [:create_issue]
  9 +
  10 + def index
  11 + app_scope = current_user.admin? ? App.all : current_user.apps
  12 +
  13 + @problems = Problem.for_apps(app_scope).in_env(params[:environment]).unresolved.ordered_by(@sort, @order)
  14 + @selected_problems = params[:problems] || []
  15 + respond_to do |format|
  16 + format.html do
  17 + @problems = @problems.page(params[:page]).per(current_user.per_page)
  18 + end
  19 + format.atom
  20 + end
  21 + end
  22 +
  23 + def all
  24 + app_scope = current_user.admin? ? App.all : current_user.apps
  25 + @problems = Problem.for_apps(app_scope).ordered_by(@sort, @order).page(params[:page]).per(current_user.per_page)
  26 + @selected_problems = params[:problems] || []
  27 + end
  28 +
  29 + def show
  30 + @notices = @problem.notices.reverse_ordered.page(params[:notice]).per(1)
  31 + @notice = @notices.first
  32 + @comment = Comment.new
  33 + if request.headers['X-PJAX']
  34 + params["_pjax"] = nil
  35 + render :layout => false
  36 + end
  37 + end
  38 +
  39 + def create_issue
  40 + # Create an issue on GitHub using user's github token
  41 + if params[:tracker] == 'user_github'
  42 + if !@app.github_repo?
  43 + flash[:error] = "This app doesn't have a GitHub repo set up."
  44 + elsif !current_user.github_account?
  45 + flash[:error] = "You haven't linked your Github account."
  46 + else
  47 + @tracker = GithubIssuesTracker.new(
  48 + :app => @app,
  49 + :username => current_user.github_login,
  50 + :oauth_token => current_user.github_oauth_token
  51 + )
  52 + end
  53 +
  54 + # Or, create an issue using the App's issue tracker
  55 + elsif @app.issue_tracker_configured?
  56 + @tracker = @app.issue_tracker
  57 +
  58 + # Otherwise, display error about missing tracker configuration.
  59 + else
  60 + flash[:error] = "This app has no issue tracker setup."
  61 + end
  62 +
  63 + if flash[:error].blank? && @tracker
  64 + begin
  65 + @tracker.create_issue @problem, current_user
  66 + rescue Exception => ex
  67 + Rails.logger.error "Error during issue creation: " << ex.message
  68 + flash[:error] = "There was an error during issue creation: #{ex.message}"
  69 + end
  70 + end
  71 +
  72 + redirect_to app_problem_path(@app, @problem)
  73 + end
  74 +
  75 + def unlink_issue
  76 + @problem.update_attribute :issue_link, nil
  77 + redirect_to app_problem_path(@app, @problem)
  78 + end
  79 +
  80 + def resolve
  81 + @problem.resolve!
  82 + flash[:success] = 'Great news everyone! The err has been resolved.'
  83 + redirect_to :back
  84 + rescue ActionController::RedirectBackError
  85 + redirect_to app_path(@app)
  86 + end
  87 +
  88 + def resolve_several
  89 + @selected_problems.each(&:resolve!)
  90 + flash[:success] = "Great news everyone! #{pluralize(@selected_problems.count, 'err has', 'errs have')} been resolved."
  91 + redirect_to :back
  92 + end
  93 +
  94 + def unresolve_several
  95 + @selected_problems.each(&:unresolve!)
  96 + flash[:success] = "#{pluralize(@selected_problems.count, 'err has', 'errs have')} been unresolved."
  97 + redirect_to :back
  98 + end
  99 +
  100 + def merge_several
  101 + if @selected_problems.length < 2
  102 + flash[:notice] = "You must select at least two errors to merge"
  103 + else
  104 + @merged_problem = Problem.merge!(@selected_problems)
  105 + flash[:notice] = "#{@selected_problems.count} errors have been merged."
  106 + end
  107 + redirect_to :back
  108 + end
  109 +
  110 + def unmerge_several
  111 + all = @selected_problems.map(&:unmerge!).flatten
  112 + flash[:success] = "#{pluralize(all.length, 'err has', 'errs have')} been unmerged."
  113 + redirect_to :back
  114 + end
  115 +
  116 + def destroy_several
  117 + nb_problem_destroy = ProblemDestroy.execute(@selected_problems)
  118 + flash[:notice] = "#{pluralize(nb_problem_destroy, 'err has', 'errs have')} been deleted."
  119 + redirect_to :back
  120 + end
  121 +
  122 + protected
  123 + def find_app
  124 + @app = App.find(params[:app_id])
  125 +
  126 + # Mongoid Bug: could not chain: current_user.apps.find_by_id!
  127 + # apparently finding by 'watchers.email' and 'id' is broken
  128 + raise(Mongoid::Errors::DocumentNotFound.new(App,@app.id)) unless current_user.admin? || current_user.watching?(@app)
  129 + end
  130 +
  131 + def find_problem
  132 + @problem = @app.problems.find(params[:id])
  133 + end
  134 +
  135 + def set_tracker_params
  136 + IssueTracker.default_url_options[:host] = request.host
  137 + IssueTracker.default_url_options[:port] = request.port
  138 + IssueTracker.default_url_options[:protocol] = request.scheme
  139 + end
  140 +
  141 + def find_selected_problems
  142 + err_ids = (params[:problems] || []).compact
  143 + if err_ids.empty?
  144 + flash[:notice] = "You have not selected any errors"
  145 + redirect_to :back
  146 + else
  147 + @selected_problems = Array(Problem.find(err_ids))
  148 + end
  149 + end
  150 +
  151 + def set_sorting_params
  152 + @sort = params[:sort]
  153 + @sort = "last_notice_at" unless %w{app message last_notice_at last_deploy_at count}.member?(@sort)
  154 + @order = params[:order] || "desc"
  155 + end
  156 +end
  157 +
app/helpers/application_helper.rb
@@ -13,7 +13,7 @@ module ApplicationHelper @@ -13,7 +13,7 @@ module ApplicationHelper
13 event.dtend = notice.created_at.utc + 60.minutes 13 event.dtend = notice.created_at.utc + 60.minutes
14 event.organizer = notice.server_environment && notice.server_environment["hostname"] 14 event.organizer = notice.server_environment && notice.server_environment["hostname"]
15 event.location = notice.server_environment && notice.server_environment["project-root"] 15 event.location = notice.server_environment && notice.server_environment["project-root"]
16 - event.url = app_err_url(:app_id => notice.problem.app.id, :id => notice.problem) 16 + event.url = app_problem_url(:app_id => notice.problem.app.id, :id => notice.problem)
17 end 17 end
18 end 18 end
19 end.to_s 19 end.to_s
@@ -58,11 +58,11 @@ module ApplicationHelper @@ -58,11 +58,11 @@ module ApplicationHelper
58 percent = 100.0 / total.to_f 58 percent = 100.0 / total.to_f
59 rows = tallies.map {|value, count| [(count.to_f * percent), value]} \ 59 rows = tallies.map {|value, count| [(count.to_f * percent), value]} \
60 .sort {|a, b| a[0] <=> b[0]} 60 .sort {|a, b| a[0] <=> b[0]}
61 - render "errs/tally_table", :rows => rows 61 + render "problems/tally_table", :rows => rows
62 end 62 end
63 63
64 def head(collection) 64 def head(collection)
65 - collection.first(head_size) 65 + collection.first(head_size)
66 end 66 end
67 67
68 def tail(collection) 68 def tail(collection)
app/helpers/errs_helper.rb
@@ -1,27 +0,0 @@ @@ -1,27 +0,0 @@
1 -module ErrsHelper  
2 - def err_confirm  
3 - Errbit::Config.confirm_resolve_err === false ? nil : 'Seriously?'  
4 - end  
5 -  
6 - def truncated_err_message(problem)  
7 - unless (msg = problem.message).blank?  
8 - # Truncate & insert invisible chars so that firefox can emulate 'word-wrap: break-word' CSS rule  
9 - truncate(msg, :length => 300).scan(/.{1,5}/).map { |s| h(s) }.join("&#8203;").html_safe  
10 - end  
11 - end  
12 -  
13 - def gravatar_tag(email, options = {})  
14 - image_tag gravatar_url(email, options), :alt => email, :class => 'gravatar'  
15 - end  
16 -  
17 - def gravatar_url(email, options = {})  
18 - default_options = {  
19 - :d => Errbit::Config.gravatar_default,  
20 - }  
21 - options.reverse_merge! default_options  
22 - params = options.extract!(:s, :d).delete_if { |k, v| v.blank? }  
23 - email_hash = Digest::MD5.hexdigest(email)  
24 - "http://www.gravatar.com/avatar/#{email_hash}?#{params.to_query}"  
25 - end  
26 -end  
27 -  
app/helpers/problems_helper.rb 0 → 100644
@@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
  1 +module ProblemsHelper
  2 + def problem_confirm
  3 + Errbit::Config.confirm_resolve_err === false ? nil : 'Seriously?'
  4 + end
  5 +
  6 + def truncated_problem_message(problem)
  7 + unless (msg = problem.message).blank?
  8 + # Truncate & insert invisible chars so that firefox can emulate 'word-wrap: break-word' CSS rule
  9 + truncate(msg, :length => 300).scan(/.{1,5}/).map { |s| h(s) }.join("&#8203;").html_safe
  10 + end
  11 + end
  12 +
  13 + def gravatar_tag(email, options = {})
  14 + image_tag gravatar_url(email, options), :alt => email, :class => 'gravatar'
  15 + end
  16 +
  17 + def gravatar_url(email, options = {})
  18 + default_options = {
  19 + :d => Errbit::Config.gravatar_default,
  20 + }
  21 + options.reverse_merge! default_options
  22 + params = options.extract!(:s, :d).delete_if { |k, v| v.blank? }
  23 + email_hash = Digest::MD5.hexdigest(email)
  24 + "http://www.gravatar.com/avatar/#{email_hash}?#{params.to_query}"
  25 + end
  26 +end
  27 +
app/views/apps/show.atom.builder
1 atom_feed do |feed| 1 atom_feed do |feed|
2 feed.title("Errbit notices for #{h @app.name} at #{root_url}") 2 feed.title("Errbit notices for #{h @app.name} at #{root_url}")
3 - render "errs/list", :feed => feed 3 + render "problems/list", :feed => feed
4 end 4 end
app/views/apps/show.html.haml
@@ -83,7 +83,7 @@ @@ -83,7 +83,7 @@
83 83
84 - if @app.problems.any? 84 - if @app.problems.any?
85 %h3.clear Errors 85 %h3.clear Errors
86 - = render 'errs/table', :errs => @problems 86 + = render 'problems/table', :problems => @problems
87 - else 87 - else
88 %h3.clear No errs have been caught yet, make sure you setup your app 88 %h3.clear No errs have been caught yet, make sure you setup your app
89 = render 'configuration_instructions', :app => @app 89 = render 'configuration_instructions', :app => @app
app/views/errs/_issue_tracker_links.html.haml
@@ -1,15 +0,0 @@ @@ -1,15 +0,0 @@
1 -- if @app.issue_tracker_configured? || current_user.github_account?  
2 - - if @problem.issue_link.present?  
3 - %span= link_to 'go to issue', @problem.issue_link, :class => "#{@problem.issue_type}_goto goto-issue"  
4 - = link_to 'unlink issue', unlink_issue_app_err_path(@app, @problem), :method => :delete, :data => { :confirm => "Unlink err issues?" }, :class => "unlink-issue"  
5 - - elsif @problem.issue_link == "pending"  
6 - %span.disabled= link_to 'creating...', '#', :class => "#{@problem.issue_type}_inactive create-issue"  
7 - = link_to 'retry', create_issue_app_err_path(@app, @problem), :method => :post  
8 - - else  
9 - - if @app.github_repo?  
10 - - if current_user.can_create_github_issues?  
11 - %span= link_to 'create issue', create_issue_app_err_path(@app, @problem, :tracker => 'user_github'), :method => :post, :class => "github_create create-issue"  
12 - - elsif @app.issue_tracker_configured? && @app.issue_tracker.is_a?(GithubIssuesTracker)  
13 - %span= link_to 'create issue', create_issue_app_err_path(@app, @problem), :method => :post, :class => "github_create create-issue"  
14 - - if @app.issue_tracker_configured? && !@app.issue_tracker.is_a?(GithubIssuesTracker)  
15 - %span= link_to 'create issue', create_issue_app_err_path(@app, @problem), :method => :post, :class => "#{@app.issue_tracker.label}_create create-issue"  
app/views/errs/_list.atom.builder
@@ -1,15 +0,0 @@ @@ -1,15 +0,0 @@
1 -feed.updated(@problems.first.try(:created_at) || Time.now)  
2 -  
3 -for problem in @problems  
4 - notice = problem.notices.first  
5 -  
6 - feed.entry(problem, :url => app_err_url(problem.app, problem)) do |entry|  
7 - entry.title "[#{ problem.where }] #{problem.message.to_s.truncate(27)}"  
8 - entry.author do |author|  
9 - author.name "#{ problem.app.name } [#{ problem.environment }]"  
10 - end  
11 - if notice  
12 - entry.summary(notice_atom_summary(notice), :type => "html")  
13 - end  
14 - end  
15 -end  
app/views/errs/_table.html.haml
@@ -1,56 +0,0 @@ @@ -1,56 +0,0 @@
1 -- any_issue_links = errs.any?{|e| e.issue_link.present? && e.issue_link != 'pending' }  
2 -=form_tag do  
3 - %table.errs.selectable  
4 - %thead  
5 - %tr  
6 - %th= check_box_tag "toggle_problems_checkboxes"  
7 - %th= link_for_sort "App"  
8 - %th= link_for_sort "What &amp; Where".html_safe, "message"  
9 - %th= link_for_sort "Latest", "last_notice_at"  
10 - %th= link_for_sort "Deploy", "last_deploy_at"  
11 - %th= link_for_sort "Count"  
12 - - if any_issue_links  
13 - %th Issue  
14 - %th Resolve  
15 - %tbody  
16 - - errs.each do |problem|  
17 - %tr{:class => problem.resolved? ? 'resolved' : 'unresolved'}  
18 - %td.select  
19 - = check_box_tag "problems[]", problem.id, @selected_problems.member?(problem.id.to_s)  
20 - %td.app  
21 - = link_to problem.app.name, app_path(problem.app)  
22 - - if current_page?(:controller => 'errs')  
23 - %span.environment= link_to problem.environment, errs_path(:environment => problem.environment)  
24 - - else  
25 - %span.environment= link_to problem.environment, app_path(problem.app, :environment => problem.environment)  
26 - %td.message  
27 - = link_to truncated_err_message(problem), app_err_path(problem.app, problem)  
28 - %em= problem.where  
29 - - if problem.comments_count > 0  
30 - - comment = problem.comments.last  
31 - %br  
32 - .inline_comment  
33 - - if comment.user  
34 - %em.commenter= (Errbit::Config.user_has_username ? comment.user.username : comment.user.email).to_s << ":"  
35 - %em= truncate(comment.body, :length => 100, :separator => ' ')  
36 - %td.latest #{time_ago_in_words(problem.last_notice_at)} ago  
37 - %td.deploy= problem.last_deploy_at ? problem.last_deploy_at.to_s(:micro) : 'n/a'  
38 - %td.count= link_to problem.notices_count, app_err_path(problem.app, problem)  
39 - - if any_issue_links  
40 - %td.issue_link  
41 - - if problem.app.issue_tracker_configured? && problem.issue_link.present? && problem.issue_link != 'pending'  
42 - = link_to image_tag("#{problem.issue_type}_goto.png"), problem.issue_link, :target => "_blank"  
43 - %td.resolve= link_to image_tag("thumbs-up.png"), resolve_app_err_path(problem.app, problem), :title => "Resolve", :method => :put, :data => { :confirm => err_confirm }, :class => 'resolve' if problem.unresolved?  
44 - - if errs.none?  
45 - %tr  
46 - %td{:colspan => (any_issue_links ? 8 : 7)}  
47 - %em No errs here  
48 - = paginate errs  
49 - .tab-bar  
50 - %ul  
51 - %li= submit_tag 'Merge', :id => 'merge_errs', :class => 'button', 'data-action' => merge_several_errs_path  
52 - %li= submit_tag 'Unmerge', :id => 'unmerge_errs', :class => 'button', 'data-action' => unmerge_several_errs_path  
53 - %li= submit_tag 'Resolve', :id => 'resolve_errs', :class => 'button', 'data-action' => resolve_several_errs_path  
54 - %li= submit_tag 'Unresolve', :id => 'unresolve_errs', :class => 'button', 'data-action' => unresolve_several_errs_path  
55 - %li= submit_tag 'Delete', :id => 'delete_errs', :class => 'button', 'data-action' => destroy_several_errs_path  
56 -  
app/views/errs/_tally_table.html.haml
@@ -1,18 +0,0 @@ @@ -1,18 +0,0 @@
1 -.head_and_tail  
2 - %table.tally.head  
3 - %tbody  
4 - - head(rows).each do |row|  
5 - %tr  
6 - %td.percent= number_to_percentage(row[0], :precision => 1)  
7 - %th.value= row[1]  
8 - - if rows.size > head_size  
9 - %tfoot  
10 - %tr  
11 - %td{:colspan => 2}  
12 - = link_to 'Show more...', '#', :class => :show_tail  
13 - %table.tally.tail{:style => "display: none"}  
14 - %tbody  
15 - - tail(rows).each do |row|  
16 - %tr  
17 - %td.percent= number_to_percentage(row[0], :precision => 1)  
18 - %th.value= row[1]  
app/views/errs/all.html.haml
@@ -1,4 +0,0 @@ @@ -1,4 +0,0 @@
1 -- content_for :title, 'All Errors'  
2 -- content_for :action_bar do  
3 - = link_to 'hide resolved', errs_path, :class => 'button'  
4 -= render 'table', :errs => @problems  
app/views/errs/index.atom.builder
@@ -1,4 +0,0 @@ @@ -1,4 +0,0 @@
1 -atom_feed do |feed|  
2 - feed.title("Errbit notices at #{root_url}")  
3 - render "errs/list", :feed => feed  
4 -end  
app/views/errs/index.html.haml
@@ -1,6 +0,0 @@ @@ -1,6 +0,0 @@
1 -- content_for :title, 'Unresolved Errors'  
2 -- content_for :head do  
3 - = auto_discovery_link_tag :atom, errs_path(User.token_authentication_key => current_user.authentication_token, :format => "atom"), :title => "Errbit notices at #{request.host}"  
4 -- content_for :action_bar do  
5 - = link_to 'show resolved', all_errs_path, :class => 'button'  
6 -= render 'table', :errs => @problems  
app/views/errs/show.html.haml
@@ -1,83 +0,0 @@ @@ -1,83 +0,0 @@
1 -- content_for :page_title, @problem.message  
2 -- content_for :title_css_class, 'err_show'  
3 -- content_for :title, @problem.error_class || truncate(@problem.message, :length => 32)  
4 -- content_for :meta do  
5 - %strong App:  
6 - = link_to @app.name, app_path(@app)  
7 - %strong Where:  
8 - = @problem.where  
9 - %br  
10 - %strong Environment:  
11 - = @problem.environment  
12 - %strong Last Notice:  
13 - = @problem.last_notice_at.to_s(:precise)  
14 -- content_for :action_bar do  
15 - - if @problem.unresolved?  
16 - %span= link_to 'resolve', resolve_app_err_path(@app, @problem), :method => :put, :data => { :confirm => err_confirm }, :class => 'resolve'  
17 - - if current_user.authentication_token  
18 - %span= link_to 'iCal', app_err_path(:app_id => @app.id, :id => @problem.id, :format => "ics", :auth_token => current_user.authentication_token), :class => "calendar_link"  
19 - %span>= link_to 'up', (request.env['HTTP_REFERER'] ? :back : app_errs_path(@app)), :class => 'up'  
20 - %br  
21 - = render "issue_tracker_links"  
22 -  
23 -- if Errbit::Config.allow_comments_with_issue_tracker || !@app.issue_tracker_configured? || @problem.comments.any?  
24 - - content_for :comments do  
25 - %h3 Comments  
26 - - @problem.comments.each do |comment|  
27 - .window  
28 - %table.comment  
29 - %tr  
30 - %th  
31 - - if Errbit::Config.use_gravatar  
32 - = gravatar_tag comment.user.email, :s => 24  
33 - %span.comment-info  
34 - = time_ago_in_words(comment.created_at, true) << " ago by "  
35 - = link_to comment.user.email, user_path(comment.user)  
36 - %span.delete= link_to '&#10008;'.html_safe, app_err_comment_path(@app, @problem, comment), :method => :delete, :data => { :confirm => "Are sure you don't need this comment?" }, :class => "destroy-comment"  
37 - %tr  
38 - %td= comment.body.gsub("\n", "<br>").html_safe  
39 - - if Errbit::Config.allow_comments_with_issue_tracker || !@app.issue_tracker_configured?  
40 - = form_for @comment, :url => app_err_comments_path(@app, @problem) do |comment_form|  
41 - %p Add a comment  
42 - = comment_form.text_area :body, :style => "width: 420px; height: 80px;"  
43 - = comment_form.submit "Save Comment"  
44 -  
45 -%h4= @notice.try(:message)  
46 -  
47 -= paginate @notices, :param_name => :notice, :theme => :notices  
48 -  
49 -.tab-bar  
50 - %ul  
51 - %li= link_to 'Summary', '#summary', :rel => 'summary', :class => 'button'  
52 - %li= link_to 'Backtrace', '#backtrace', :rel => 'backtrace', :class => 'button'  
53 - - if @notice && @notice.user_attributes.present?  
54 - %li= link_to 'User Details', '#user_attributes', :rel => 'user_attributes', :class => 'button'  
55 - %li= link_to 'Environment', '#environment', :rel => 'environment', :class => 'button'  
56 - %li= link_to 'Parameters', '#params', :rel => 'params', :class => 'button'  
57 - %li= link_to 'Session', '#session', :rel => 'session', :class => 'button'  
58 -  
59 -- if @notice  
60 - #summary  
61 - %h3 Summary  
62 - = render 'notices/summary', :notice => @notice, :problem => @problem  
63 -  
64 - #backtrace  
65 - %h3 Backtrace  
66 - = render 'notices/backtrace', :lines => @notice.backtrace  
67 -  
68 - - if @notice.user_attributes.present?  
69 - #user_attributes  
70 - %h3 User Details  
71 - = render 'notices/user_attributes', :user => @notice.user_attributes  
72 -  
73 - #environment  
74 - %h3 Environment  
75 - = render 'notices/environment', :notice => @notice  
76 -  
77 - #params  
78 - %h3 Parameters  
79 - = render 'notices/params', :notice => @notice  
80 -  
81 - #session  
82 - %h3 Session  
83 - = render 'notices/session', :notice => @notice  
app/views/errs/show.ics.haml
@@ -1 +0,0 @@ @@ -1 +0,0 @@
1 -= generate_problem_ical(@problem.notices.order_by(:created_at.asc))  
app/views/issue_trackers/fogbugz_body.txt.erb
1 -"See this exception on Errbit": <%= app_err_url(problem.app, problem) %> 1 +"See this exception on Errbit": <%= app_problem_url(problem.app, problem) %>
2 <% if notice = problem.notices.first %> 2 <% if notice = problem.notices.first %>
3 <%= notice.message %> 3 <%= notice.message %>
4 4
app/views/issue_trackers/github_issues_body.txt.erb
1 -[See this exception on Errbit](<%= app_err_url problem.app, problem %> "See this exception on Errbit") 1 +[See this exception on Errbit](<%= app_problem_url problem.app, problem %> "See this exception on Errbit")
2 <% if notice = problem.notices.first %> 2 <% if notice = problem.notices.first %>
3 # <%= notice.message %> # 3 # <%= notice.message %> #
4 ## Summary ## 4 ## Summary ##
app/views/issue_trackers/lighthouseapp_body.txt.erb
1 -[See this exception on Errbit](<%= app_err_url problem.app, problem %> "See this exception on Errbit") 1 +[See this exception on Errbit](<%= app_problem_url problem.app, problem %> "See this exception on Errbit")
2 <% if notice = problem.notices.first %> 2 <% if notice = problem.notices.first %>
3 # <%= notice.message %> # 3 # <%= notice.message %> #
4 ## Summary ## 4 ## Summary ##
app/views/issue_trackers/pivotal_body.txt.erb
1 -See this exception on Errbit: <%= app_err_url problem.app, problem %> 1 +See this exception on Errbit: <%= app_problem_url problem.app, problem %>
2 <% if notice = problem.notices.first %> 2 <% if notice = problem.notices.first %>
3 <% if notice.request['url'].present? %>URL: <%= notice.request['url'] %><% end %> 3 <% if notice.request['url'].present? %>URL: <%= notice.request['url'] %><% end %>
4 Where: <%= notice.where %> 4 Where: <%= notice.where %>
app/views/issue_trackers/textile_body.txt.erb
1 <% if notice = problem.notices.first %> 1 <% if notice = problem.notices.first %>
2 h1. <%= notice.message %> 2 h1. <%= notice.message %>
3 3
4 -h3. "See this exception on Errbit":<%= app_err_url problem.app, problem %> 4 +h3. "See this exception on Errbit":<%= app_problem_url problem.app, problem %>
5 5
6 h2. Summary 6 h2. Summary
7 <% if notice.request['url'].present? %> 7 <% if notice.request['url'].present? %>
app/views/mailer/err_notification.html.haml
@@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
14 %br 14 %br
15 This err has occurred #{pluralize @notice.problem.notices_count, 'time'}. 15 This err has occurred #{pluralize @notice.problem.notices_count, 'time'}.
16 %p 16 %p
17 - = link_to("Click here to view the error on Errbit", app_err_url(@app, @notice.problem), :class => "bold") << "." 17 + = link_to("Click here to view the error on Errbit", app_problem_url(@app, @notice.problem), :class => "bold") << "."
18 %tr 18 %tr
19 %td.section 19 %td.section
20 %table(cellpadding="0" cellspacing="0" border="0" align="left") 20 %table(cellpadding="0" cellspacing="0" border="0" align="left")
app/views/mailer/err_notification.text.erb
@@ -2,7 +2,7 @@ An err has just occurred in &lt;%= @notice.environment_name %&gt;: &lt;%= raw(@notice.mes @@ -2,7 +2,7 @@ An err has just occurred in &lt;%= @notice.environment_name %&gt;: &lt;%= raw(@notice.mes
2 2
3 This err has occurred <%= pluralize @notice.problem.notices_count, 'time' %>. You should really look into it here: 3 This err has occurred <%= pluralize @notice.problem.notices_count, 'time' %>. You should really look into it here:
4 4
5 - <%= app_err_url(@app, @notice.problem) %> 5 + <%= app_problem_url(@app, @notice.problem) %>
6 6
7 7
8 ERROR MESSAGE: 8 ERROR MESSAGE:
app/views/problems/_issue_tracker_links.html.haml 0 → 100644
@@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
  1 +- if @app.issue_tracker_configured? || current_user.github_account?
  2 + - if @problem.issue_link.present?
  3 + %span= link_to 'go to issue', @problem.issue_link, :class => "#{@problem.issue_type}_goto goto-issue"
  4 + = link_to 'unlink issue', unlink_issue_app_problem_path(@app, @problem), :method => :delete, :data => { :confirm => "Unlink err issues?" }, :class => "unlink-issue"
  5 + - elsif @problem.issue_link == "pending"
  6 + %span.disabled= link_to 'creating...', '#', :class => "#{@problem.issue_type}_inactive create-issue"
  7 + = link_to 'retry', create_issue_app_problem_path(@app, @problem), :method => :post
  8 + - else
  9 + - if @app.github_repo?
  10 + - if current_user.can_create_github_issues?
  11 + %span= link_to 'create issue', create_issue_app_problem_path(@app, @problem, :tracker => 'user_github'), :method => :post, :class => "github_create create-issue"
  12 + - elsif @app.issue_tracker_configured? && @app.issue_tracker.is_a?(GithubIssuesTracker)
  13 + %span= link_to 'create issue', create_issue_app_problem_path(@app, @problem), :method => :post, :class => "github_create create-issue"
  14 + - if @app.issue_tracker_configured? && !@app.issue_tracker.is_a?(GithubIssuesTracker)
  15 + %span= link_to 'create issue', create_issue_app_problem_path(@app, @problem), :method => :post, :class => "#{@app.issue_tracker.label}_create create-issue"
app/views/problems/_list.atom.builder 0 → 100644
@@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
  1 +feed.updated(@problems.first.try(:created_at) || Time.now)
  2 +
  3 +for problem in @problems
  4 + notice = problem.notices.first
  5 +
  6 + feed.entry(problem, :url => app_problem_url(problem.app, problem)) do |entry|
  7 + entry.title "[#{ problem.where }] #{problem.message.to_s.truncate(27)}"
  8 + entry.author do |author|
  9 + author.name "#{ problem.app.name } [#{ problem.environment }]"
  10 + end
  11 + if notice
  12 + entry.summary(notice_atom_summary(notice), :type => "html")
  13 + end
  14 + end
  15 +end
app/views/problems/_table.html.haml 0 → 100644
@@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
  1 +- any_issue_links = problems.any?{|e| e.issue_link.present? && e.issue_link != 'pending' }
  2 +=form_tag do
  3 + %table.errs.selectable
  4 + %thead
  5 + %tr
  6 + %th= check_box_tag "toggle_problems_checkboxes"
  7 + %th= link_for_sort "App"
  8 + %th= link_for_sort "What &amp; Where".html_safe, "message"
  9 + %th= link_for_sort "Latest", "last_notice_at"
  10 + %th= link_for_sort "Deploy", "last_deploy_at"
  11 + %th= link_for_sort "Count"
  12 + - if any_issue_links
  13 + %th Issue
  14 + %th Resolve
  15 + %tbody
  16 + - problems.each do |problem|
  17 + %tr{:class => problem.resolved? ? 'resolved' : 'unresolved'}
  18 + %td.select
  19 + = check_box_tag "problems[]", problem.id, @selected_problems.member?(problem.id.to_s)
  20 + %td.app
  21 + = link_to problem.app.name, app_path(problem.app)
  22 + - if current_page?(:controller => 'problems')
  23 + %span.environment= link_to problem.environment, problems_path(:environment => problem.environment)
  24 + - else
  25 + %span.environment= link_to problem.environment, app_path(problem.app, :environment => problem.environment)
  26 + %td.message
  27 + = link_to truncated_problem_message(problem), app_problem_path(problem.app, problem)
  28 + %em= problem.where
  29 + - if problem.comments_count > 0
  30 + - comment = problem.comments.last
  31 + %br
  32 + .inline_comment
  33 + - if comment.user
  34 + %em.commenter= (Errbit::Config.user_has_username ? comment.user.username : comment.user.email).to_s << ":"
  35 + %em= truncate(comment.body, :length => 100, :separator => ' ')
  36 + %td.latest #{time_ago_in_words(problem.last_notice_at)} ago
  37 + %td.deploy= problem.last_deploy_at ? problem.last_deploy_at.to_s(:micro) : 'n/a'
  38 + %td.count= link_to problem.notices_count, app_problem_path(problem.app, problem)
  39 + - if any_issue_links
  40 + %td.issue_link
  41 + - if problem.app.issue_tracker_configured? && problem.issue_link.present? && problem.issue_link != 'pending'
  42 + = link_to image_tag("#{problem.issue_type}_goto.png"), problem.issue_link, :target => "_blank"
  43 + %td.resolve= link_to image_tag("thumbs-up.png"), resolve_app_problem_path(problem.app, problem), :title => "Resolve", :method => :put, :data => { :confirm => problem_confirm }, :class => 'resolve' if problem.unresolved?
  44 + - if problems.none?
  45 + %tr
  46 + %td{:colspan => (any_issue_links ? 8 : 7)}
  47 + %em No errs here
  48 + = paginate problems
  49 + .tab-bar
  50 + %ul
  51 + %li= submit_tag 'Merge', :id => 'merge_problems', :class => 'button', 'data-action' => merge_several_problems_path
  52 + %li= submit_tag 'Unmerge', :id => 'unmerge_problems', :class => 'button', 'data-action' => unmerge_several_problems_path
  53 + %li= submit_tag 'Resolve', :id => 'resolve_problems', :class => 'button', 'data-action' => resolve_several_problems_path
  54 + %li= submit_tag 'Unresolve', :id => 'unresolve_problems', :class => 'button', 'data-action' => unresolve_several_problems_path
  55 + %li= submit_tag 'Delete', :id => 'delete_problems', :class => 'button', 'data-action' => destroy_several_problems_path
  56 +
app/views/problems/_tally_table.html.haml 0 → 100644
@@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
  1 +.head_and_tail
  2 + %table.tally.head
  3 + %tbody
  4 + - head(rows).each do |row|
  5 + %tr
  6 + %td.percent= number_to_percentage(row[0], :precision => 1)
  7 + %th.value= row[1]
  8 + - if rows.size > head_size
  9 + %tfoot
  10 + %tr
  11 + %td{:colspan => 2}
  12 + = link_to 'Show more...', '#', :class => :show_tail
  13 + %table.tally.tail{:style => "display: none"}
  14 + %tbody
  15 + - tail(rows).each do |row|
  16 + %tr
  17 + %td.percent= number_to_percentage(row[0], :precision => 1)
  18 + %th.value= row[1]
app/views/problems/all.html.haml 0 → 100644
@@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
  1 +- content_for :title, 'All Errors'
  2 +- content_for :action_bar do
  3 + = link_to 'hide resolved', problems_path, :class => 'button'
  4 += render 'table', :problems => @problems
app/views/problems/index.atom.builder 0 → 100644
@@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
  1 +atom_feed do |feed|
  2 + feed.title("Errbit notices at #{root_url}")
  3 + render "problems/list", :feed => feed
  4 +end
app/views/problems/index.html.haml 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +- content_for :title, 'Unresolved Errors'
  2 +- content_for :head do
  3 + = auto_discovery_link_tag :atom, problems_path(User.token_authentication_key => current_user.authentication_token, :format => "atom"), :title => "Errbit notices at #{request.host}"
  4 +- content_for :action_bar do
  5 + = link_to 'show resolved', all_problems_path, :class => 'button'
  6 += render 'table', :problems => @problems
app/views/problems/show.html.haml 0 → 100644
@@ -0,0 +1,83 @@ @@ -0,0 +1,83 @@
  1 +- content_for :page_title, @problem.message
  2 +- content_for :title_css_class, 'err_show'
  3 +- content_for :title, @problem.error_class || truncate(@problem.message, :length => 32)
  4 +- content_for :meta do
  5 + %strong App:
  6 + = link_to @app.name, app_path(@app)
  7 + %strong Where:
  8 + = @problem.where
  9 + %br
  10 + %strong Environment:
  11 + = @problem.environment
  12 + %strong Last Notice:
  13 + = @problem.last_notice_at.to_s(:precise)
  14 +- content_for :action_bar do
  15 + - if @problem.unresolved?
  16 + %span= link_to 'resolve', resolve_app_problem_path(@app, @problem), :method => :put, :data => { :confirm => problem_confirm }, :class => 'resolve'
  17 + - if current_user.authentication_token
  18 + %span= link_to 'iCal', app_problem_path(:app_id => @app.id, :id => @problem.id, :format => "ics", :auth_token => current_user.authentication_token), :class => "calendar_link"
  19 + %span>= link_to 'up', (request.env['HTTP_REFERER'] ? :back : app_problems_path(@app)), :class => 'up'
  20 + %br
  21 + = render "issue_tracker_links"
  22 +
  23 +- if Errbit::Config.allow_comments_with_issue_tracker || !@app.issue_tracker_configured? || @problem.comments.any?
  24 + - content_for :comments do
  25 + %h3 Comments
  26 + - @problem.comments.each do |comment|
  27 + .window
  28 + %table.comment
  29 + %tr
  30 + %th
  31 + - if Errbit::Config.use_gravatar
  32 + = gravatar_tag comment.user.email, :s => 24
  33 + %span.comment-info
  34 + = time_ago_in_words(comment.created_at, true) << " ago by "
  35 + = link_to comment.user.email, user_path(comment.user)
  36 + %span.delete= link_to '&#10008;'.html_safe, app_problem_comment_path(@app, @problem, comment), :method => :delete, :data => { :confirm => "Are sure you don't need this comment?" }, :class => "destroy-comment"
  37 + %tr
  38 + %td= comment.body.gsub("\n", "<br>").html_safe
  39 + - if Errbit::Config.allow_comments_with_issue_tracker || !@app.issue_tracker_configured?
  40 + = form_for @comment, :url => app_problem_comments_path(@app, @problem) do |comment_form|
  41 + %p Add a comment
  42 + = comment_form.text_area :body, :style => "width: 420px; height: 80px;"
  43 + = comment_form.submit "Save Comment"
  44 +
  45 +%h4= @notice.try(:message)
  46 +
  47 += paginate @notices, :param_name => :notice, :theme => :notices
  48 +
  49 +.tab-bar
  50 + %ul
  51 + %li= link_to 'Summary', '#summary', :rel => 'summary', :class => 'button'
  52 + %li= link_to 'Backtrace', '#backtrace', :rel => 'backtrace', :class => 'button'
  53 + - if @notice && @notice.user_attributes.present?
  54 + %li= link_to 'User Details', '#user_attributes', :rel => 'user_attributes', :class => 'button'
  55 + %li= link_to 'Environment', '#environment', :rel => 'environment', :class => 'button'
  56 + %li= link_to 'Parameters', '#params', :rel => 'params', :class => 'button'
  57 + %li= link_to 'Session', '#session', :rel => 'session', :class => 'button'
  58 +
  59 +- if @notice
  60 + #summary
  61 + %h3 Summary
  62 + = render 'notices/summary', :notice => @notice, :problem => @problem
  63 +
  64 + #backtrace
  65 + %h3 Backtrace
  66 + = render 'notices/backtrace', :lines => @notice.backtrace
  67 +
  68 + - if @notice.user_attributes.present?
  69 + #user_attributes
  70 + %h3 User Details
  71 + = render 'notices/user_attributes', :user => @notice.user_attributes
  72 +
  73 + #environment
  74 + %h3 Environment
  75 + = render 'notices/environment', :notice => @notice
  76 +
  77 + #params
  78 + %h3 Parameters
  79 + = render 'notices/params', :notice => @notice
  80 +
  81 + #session
  82 + %h3 Session
  83 + = render 'notices/session', :notice => @notice
app/views/problems/show.ics.haml 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 += generate_problem_ical(@problem.notices.order_by(:created_at.asc))
app/views/shared/_navigation.html.haml
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 %ul 2 %ul
3 //%li= link_to 'Dashboard', admin_dashboard_path, :class => active_if_here(:dashboards) 3 //%li= link_to 'Dashboard', admin_dashboard_path, :class => active_if_here(:dashboards)
4 %li.apps{:class => active_if_here(:apps)}= link_to 'Apps', apps_path 4 %li.apps{:class => active_if_here(:apps)}= link_to 'Apps', apps_path
5 - %li.errs{:class => active_if_here(:errs)}= link_to 'Errors', errs_path 5 + %li.errs{:class => active_if_here(:problems)}= link_to 'Errors', problems_path
6 - if user_signed_in? && current_user.admin? 6 - if user_signed_in? && current_user.admin?
7 %li.users{:class => active_if_here(:users)}= link_to 'Users', users_path 7 %li.users{:class => active_if_here(:users)}= link_to 'Users', users_path
8 - %div.clear  
9 \ No newline at end of file 8 \ No newline at end of file
  9 + %div.clear
config/routes.rb
@@ -14,7 +14,7 @@ Errbit::Application.routes.draw do @@ -14,7 +14,7 @@ Errbit::Application.routes.draw do
14 delete :unlink_github 14 delete :unlink_github
15 end 15 end
16 end 16 end
17 - resources :errs, :only => [:index] do 17 + resources :problems, :only => [:index] do
18 collection do 18 collection do
19 post :destroy_several 19 post :destroy_several
20 post :resolve_several 20 post :resolve_several
@@ -26,7 +26,7 @@ Errbit::Application.routes.draw do @@ -26,7 +26,7 @@ Errbit::Application.routes.draw do
26 end 26 end
27 27
28 resources :apps do 28 resources :apps do
29 - resources :errs do 29 + resources :problems do
30 resources :notices 30 resources :notices
31 resources :comments, :only => [:create, :destroy] 31 resources :comments, :only => [:create, :destroy]
32 32
@@ -37,7 +37,7 @@ Errbit::Application.routes.draw do @@ -37,7 +37,7 @@ Errbit::Application.routes.draw do
37 delete :unlink_issue 37 delete :unlink_issue
38 end 38 end
39 end 39 end
40 - 40 +
41 resources :deploys, :only => [:index] 41 resources :deploys, :only => [:index]
42 end 42 end
43 43
@@ -46,7 +46,7 @@ Errbit::Application.routes.draw do @@ -46,7 +46,7 @@ Errbit::Application.routes.draw do
46 resources :problems, :only => [:index], :defaults => { :format => 'json' } 46 resources :problems, :only => [:index], :defaults => { :format => 'json' }
47 resources :notices, :only => [:index], :defaults => { :format => 'json' } 47 resources :notices, :only => [:index], :defaults => { :format => 'json' }
48 end 48 end
49 - end 49 + end
50 50
51 root :to => 'apps#index' 51 root :to => 'apps#index'
52 52
spec/controllers/comments_controller_spec.rb
@@ -16,7 +16,7 @@ describe CommentsController do @@ -16,7 +16,7 @@ describe CommentsController do
16 let(:user) { Fabricate(:user) } 16 let(:user) { Fabricate(:user) }
17 17
18 before(:each) do 18 before(:each) do
19 - post :create, :app_id => problem.app.id, :err_id => problem.id, 19 + post :create, :app_id => problem.app.id, :problem_id => problem.id,
20 :comment => { :body => "One test comment", :user_id => user.id } 20 :comment => { :body => "One test comment", :user_id => user.id }
21 problem.reload 21 problem.reload
22 end 22 end
@@ -26,7 +26,7 @@ describe CommentsController do @@ -26,7 +26,7 @@ describe CommentsController do
26 end 26 end
27 27
28 it "should redirect to problem page" do 28 it "should redirect to problem page" do
29 - response.should redirect_to( app_err_path(problem.app, problem) ) 29 + response.should redirect_to( app_problem_path(problem.app, problem) )
30 end 30 end
31 end 31 end
32 end 32 end
@@ -43,7 +43,7 @@ describe CommentsController do @@ -43,7 +43,7 @@ describe CommentsController do
43 let(:comment) { problem.reload.comments.first } 43 let(:comment) { problem.reload.comments.first }
44 44
45 before(:each) do 45 before(:each) do
46 - delete :destroy, :app_id => problem.app.id, :err_id => problem.id, :id => comment.id.to_s 46 + delete :destroy, :app_id => problem.app.id, :problem_id => problem.id, :id => comment.id.to_s
47 problem.reload 47 problem.reload
48 end 48 end
49 49
@@ -52,7 +52,7 @@ describe CommentsController do @@ -52,7 +52,7 @@ describe CommentsController do
52 end 52 end
53 53
54 it "should redirect to problem page" do 54 it "should redirect to problem page" do
55 - response.should redirect_to( app_err_path(problem.app, problem) ) 55 + response.should redirect_to( app_problem_path(problem.app, problem) )
56 end 56 end
57 end 57 end
58 end 58 end
spec/controllers/errs_controller_spec.rb
@@ -1,441 +0,0 @@ @@ -1,441 +0,0 @@
1 -require 'spec_helper'  
2 -  
3 -describe ErrsController do  
4 -  
5 - it_requires_authentication :for => {  
6 - :index => :get, :all => :get, :show => :get, :resolve => :put  
7 - },  
8 - :params => {:app_id => 'dummyid', :id => 'dummyid'}  
9 -  
10 - let(:app) { Fabricate(:app) }  
11 - let(:err) { Fabricate(:err, :problem => Fabricate(:problem, :app => app, :environment => "production")) }  
12 -  
13 -  
14 - describe "GET /errs" do  
15 - render_views  
16 - context 'when logged in as an admin' do  
17 - before(:each) do  
18 - @user = Fabricate(:admin)  
19 - sign_in @user  
20 - @problem = Fabricate(:notice, :err => Fabricate(:err, :problem => Fabricate(:problem, :app => app, :environment => "production"))).problem  
21 - end  
22 -  
23 - it "should successfully list errs" do  
24 - get :index  
25 - response.should be_success  
26 - response.body.gsub("&#8203;", "").should match(@problem.message)  
27 - end  
28 -  
29 - it "should list atom feed successfully" do  
30 - get :index, :format => "atom"  
31 - response.should be_success  
32 - response.body.should match(@problem.message)  
33 - end  
34 -  
35 - context "pagination" do  
36 - before(:each) do  
37 - 35.times { Fabricate :err }  
38 - end  
39 -  
40 - it "should have default per_page value for user" do  
41 - get :index  
42 - assigns(:problems).to_a.size.should == User::PER_PAGE  
43 - end  
44 -  
45 - it "should be able to override default per_page value" do  
46 - @user.update_attribute :per_page, 10  
47 - get :index  
48 - assigns(:problems).to_a.size.should == 10  
49 - end  
50 - end  
51 -  
52 - context 'with environment filters' do  
53 - before(:each) do  
54 - environments = ['production', 'test', 'development', 'staging']  
55 - 20.times do |i|  
56 - Fabricate(:problem, :environment => environments[i % environments.length])  
57 - end  
58 - end  
59 -  
60 - context 'no params' do  
61 - it 'shows errs for all environments' do  
62 - get :index  
63 - assigns(:problems).size.should == 21  
64 - end  
65 - end  
66 -  
67 - context 'environment production' do  
68 - it 'shows errs for just production' do  
69 - get :index, :environment => 'production'  
70 - assigns(:problems).size.should == 6  
71 - end  
72 - end  
73 -  
74 - context 'environment staging' do  
75 - it 'shows errs for just staging' do  
76 - get :index, :environment => 'staging'  
77 - assigns(:problems).size.should == 5  
78 - end  
79 - end  
80 -  
81 - context 'environment development' do  
82 - it 'shows errs for just development' do  
83 - get :index, :environment => 'development'  
84 - assigns(:problems).size.should == 5  
85 - end  
86 - end  
87 -  
88 - context 'environment test' do  
89 - it 'shows errs for just test' do  
90 - get :index, :environment => 'test'  
91 - assigns(:problems).size.should == 5  
92 - end  
93 - end  
94 - end  
95 - end  
96 -  
97 - context 'when logged in as a user' do  
98 - it 'gets a paginated list of unresolved errs for the users apps' do  
99 - sign_in(user = Fabricate(:user))  
100 - unwatched_err = Fabricate(:err)  
101 - watched_unresolved_err = Fabricate(:err, :problem => Fabricate(:problem, :app => Fabricate(:user_watcher, :user => user).app, :resolved => false))  
102 - watched_resolved_err = Fabricate(:err, :problem => Fabricate(:problem, :app => Fabricate(:user_watcher, :user => user).app, :resolved => true))  
103 - get :index  
104 - assigns(:problems).should include(watched_unresolved_err.problem)  
105 - assigns(:problems).should_not include(unwatched_err.problem, watched_resolved_err.problem)  
106 - end  
107 - end  
108 - end  
109 -  
110 - describe "GET /errs/all" do  
111 - context 'when logged in as an admin' do  
112 - it "gets a paginated list of all errs" do  
113 - sign_in Fabricate(:admin)  
114 - errs = Kaminari.paginate_array((1..30).to_a)  
115 - 3.times { errs << Fabricate(:err).problem }  
116 - 3.times { errs << Fabricate(:err, :problem => Fabricate(:problem, :resolved => true)).problem }  
117 - Problem.should_receive(:ordered_by).and_return(  
118 - mock('proxy', :page => mock('other_proxy', :per => errs))  
119 - )  
120 - get :all  
121 - assigns(:problems).should == errs  
122 - end  
123 - end  
124 -  
125 - context 'when logged in as a user' do  
126 - it 'gets a paginated list of all errs for the users apps' do  
127 - sign_in(user = Fabricate(:user))  
128 - unwatched_err = Fabricate(:problem)  
129 - watched_unresolved_err = Fabricate(:problem, :app => Fabricate(:user_watcher, :user => user).app, :resolved => false)  
130 - watched_resolved_err = Fabricate(:problem, :app => Fabricate(:user_watcher, :user => user).app, :resolved => true)  
131 - get :all  
132 - assigns(:problems).should include(watched_resolved_err, watched_unresolved_err)  
133 - assigns(:problems).should_not include(unwatched_err)  
134 - end  
135 - end  
136 - end  
137 -  
138 - describe "GET /apps/:app_id/errs/:id" do  
139 - render_views  
140 -  
141 - context 'when logged in as an admin' do  
142 - before do  
143 - sign_in Fabricate(:admin)  
144 - end  
145 -  
146 - it "finds the app" do  
147 - get :show, :app_id => app.id, :id => err.problem.id  
148 - assigns(:app).should == app  
149 - end  
150 -  
151 - it "finds the err" do  
152 - get :show, :app_id => app.id, :id => err.problem.id  
153 - assigns(:problem).should == err.problem  
154 - end  
155 -  
156 - it "successfully render page" do  
157 - get :show, :app_id => app.id, :id => err.problem.id  
158 - response.should be_success  
159 - end  
160 -  
161 - context 'pagination' do  
162 - let!(:notices) do  
163 - 3.times.reduce([]) do |coll, i|  
164 - coll << Fabricate(:notice, :err => err, :created_at => (Time.now + i))  
165 - end  
166 - end  
167 -  
168 - it "paginates the notices 1 at a time, starting with the most recent" do  
169 - get :show, :app_id => app.id, :id => err.problem.id  
170 - assigns(:notices).entries.count.should == 1  
171 - assigns(:notices).should include(notices.last)  
172 - end  
173 -  
174 - it "paginates the notices 1 at a time, based on then notice param" do  
175 - get :show, :app_id => app.id, :id => err.problem.id, :notice => 3  
176 - assigns(:notices).entries.count.should == 1  
177 - assigns(:notices).should include(notices.first)  
178 - end  
179 - end  
180 -  
181 - context "create issue button" do  
182 - let(:button_matcher) { match(/create issue/) }  
183 -  
184 - it "should not exist for err's app without issue tracker" do  
185 - err = Fabricate :err  
186 - get :show, :app_id => err.app.id, :id => err.problem.id  
187 -  
188 - response.body.should_not button_matcher  
189 - end  
190 -  
191 - it "should exist for err's app with issue tracker" do  
192 - tracker = Fabricate(:lighthouse_tracker)  
193 - err = Fabricate(:err, :problem => Fabricate(:problem, :app => tracker.app))  
194 - get :show, :app_id => err.app.id, :id => err.problem.id  
195 -  
196 - response.body.should button_matcher  
197 - end  
198 -  
199 - it "should not exist for err with issue_link" do  
200 - tracker = Fabricate(:lighthouse_tracker)  
201 - err = Fabricate(:err, :problem => Fabricate(:problem, :app => tracker.app, :issue_link => "http://some.host"))  
202 - get :show, :app_id => err.app.id, :id => err.problem.id  
203 -  
204 - response.body.should_not button_matcher  
205 - end  
206 - end  
207 - end  
208 -  
209 - context 'when logged in as a user' do  
210 - before do  
211 - sign_in(@user = Fabricate(:user))  
212 - @unwatched_err = Fabricate(:err)  
213 - @watched_app = Fabricate(:app)  
214 - @watcher = Fabricate(:user_watcher, :user => @user, :app => @watched_app)  
215 - @watched_err = Fabricate(:err, :problem => Fabricate(:problem, :app => @watched_app))  
216 - end  
217 -  
218 - it 'finds the err if the user is watching the app' do  
219 - get :show, :app_id => @watched_app.to_param, :id => @watched_err.problem.id  
220 - assigns(:problem).should == @watched_err.problem  
221 - end  
222 -  
223 - it 'raises a DocumentNotFound error if the user is not watching the app' do  
224 - lambda {  
225 - get :show, :app_id => @unwatched_err.problem.app_id, :id => @unwatched_err.problem.id  
226 - }.should raise_error(Mongoid::Errors::DocumentNotFound)  
227 - end  
228 - end  
229 - end  
230 -  
231 - describe "PUT /apps/:app_id/errs/:id/resolve" do  
232 - before do  
233 - sign_in Fabricate(:admin)  
234 -  
235 - @problem = Fabricate(:err)  
236 - App.stub(:find).with(@problem.app.id).and_return(@problem.app)  
237 - @problem.app.problems.stub(:find).and_return(@problem.problem)  
238 - @problem.problem.stub(:resolve!)  
239 - end  
240 -  
241 - it 'finds the app and the err' do  
242 - App.should_receive(:find).with(@problem.app.id).and_return(@problem.app)  
243 - @problem.app.problems.should_receive(:find).and_return(@problem.problem)  
244 - put :resolve, :app_id => @problem.app.id, :id => @problem.problem.id  
245 - assigns(:app).should == @problem.app  
246 - assigns(:problem).should == @problem.problem  
247 - end  
248 -  
249 - it "should resolve the issue" do  
250 - @problem.problem.should_receive(:resolve!).and_return(true)  
251 - put :resolve, :app_id => @problem.app.id, :id => @problem.problem.id  
252 - end  
253 -  
254 - it "should display a message" do  
255 - put :resolve, :app_id => @problem.app.id, :id => @problem.problem.id  
256 - request.flash[:success].should match(/Great news/)  
257 - end  
258 -  
259 - it "should redirect to the app page" do  
260 - put :resolve, :app_id => @problem.app.id, :id => @problem.problem.id  
261 - response.should redirect_to(app_path(@problem.app))  
262 - end  
263 -  
264 - it "should redirect back to errs page" do  
265 - request.env["Referer"] = errs_path  
266 - put :resolve, :app_id => @problem.app.id, :id => @problem.problem.id  
267 - response.should redirect_to(errs_path)  
268 - end  
269 - end  
270 -  
271 - describe "POST /apps/:app_id/errs/:id/create_issue" do  
272 - render_views  
273 -  
274 - before(:each) do  
275 - sign_in Fabricate(:admin)  
276 - end  
277 -  
278 - context "successful issue creation" do  
279 - context "lighthouseapp tracker" do  
280 - let(:notice) { Fabricate :notice }  
281 - let(:tracker) { Fabricate :lighthouse_tracker, :app => notice.app }  
282 - let(:problem) { notice.problem }  
283 -  
284 - before(:each) do  
285 - number = 5  
286 - @issue_link = "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets/#{number}.xml"  
287 - body = "<ticket><number type=\"integer\">#{number}</number></ticket>"  
288 - stub_request(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml").  
289 - to_return(:status => 201, :headers => {'Location' => @issue_link}, :body => body )  
290 -  
291 - post :create_issue, :app_id => problem.app.id, :id => problem.id  
292 - problem.reload  
293 - end  
294 -  
295 - it "should redirect to problem page" do  
296 - response.should redirect_to( app_err_path(problem.app, problem) )  
297 - end  
298 - end  
299 - end  
300 -  
301 - context "absent issue tracker" do  
302 - let(:problem) { Fabricate :problem }  
303 -  
304 - before(:each) do  
305 - post :create_issue, :app_id => problem.app.id, :id => problem.id  
306 - end  
307 -  
308 - it "should redirect to problem page" do  
309 - response.should redirect_to( app_err_path(problem.app, problem) )  
310 - end  
311 -  
312 - it "should set flash error message telling issue tracker of the app doesn't exist" do  
313 - flash[:error].should == "This app has no issue tracker setup."  
314 - end  
315 - end  
316 -  
317 - context "error during request to a tracker" do  
318 - context "lighthouseapp tracker" do  
319 - let(:tracker) { Fabricate :lighthouse_tracker }  
320 - let(:err) { Fabricate(:err, :problem => Fabricate(:problem, :app => tracker.app)) }  
321 -  
322 - before(:each) do  
323 - stub_request(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml").to_return(:status => 500)  
324 -  
325 - post :create_issue, :app_id => err.app.id, :id => err.problem.id  
326 - end  
327 -  
328 - it "should redirect to err page" do  
329 - response.should redirect_to( app_err_path(err.app, err.problem) )  
330 - end  
331 -  
332 - it "should notify of connection error" do  
333 - flash[:error].should include("There was an error during issue creation:")  
334 - end  
335 - end  
336 - end  
337 - end  
338 -  
339 - describe "DELETE /apps/:app_id/errs/:id/unlink_issue" do  
340 - before(:each) do  
341 - sign_in Fabricate(:admin)  
342 - end  
343 -  
344 - context "err with issue" do  
345 - let(:err) { Fabricate(:err, :problem => Fabricate(:problem, :issue_link => "http://some.host")) }  
346 -  
347 - before(:each) do  
348 - delete :unlink_issue, :app_id => err.app.id, :id => err.problem.id  
349 - err.problem.reload  
350 - end  
351 -  
352 - it "should redirect to err page" do  
353 - response.should redirect_to( app_err_path(err.app, err.problem) )  
354 - end  
355 -  
356 - it "should clear issue link" do  
357 - err.problem.issue_link.should be_nil  
358 - end  
359 - end  
360 -  
361 - context "err without issue" do  
362 - let(:err) { Fabricate :err }  
363 -  
364 - before(:each) do  
365 - delete :unlink_issue, :app_id => err.app.id, :id => err.problem.id  
366 - err.problem.reload  
367 - end  
368 -  
369 - it "should redirect to err page" do  
370 - response.should redirect_to( app_err_path(err.app, err.problem) )  
371 - end  
372 - end  
373 - end  
374 -  
375 - describe "Bulk Actions" do  
376 - before(:each) do  
377 - sign_in Fabricate(:admin)  
378 - @problem1 = Fabricate(:err, :problem => Fabricate(:problem, :resolved => true)).problem  
379 - @problem2 = Fabricate(:err, :problem => Fabricate(:problem, :resolved => false)).problem  
380 - end  
381 -  
382 - it "should apply to multiple problems" do  
383 - post :resolve_several, :problems => [@problem1.id.to_s, @problem2.id.to_s]  
384 - assigns(:selected_problems).should == [@problem1, @problem2]  
385 - end  
386 -  
387 - it "should require at least one problem" do  
388 - post :resolve_several, :problems => []  
389 - request.flash[:notice].should match(/You have not selected any/)  
390 - end  
391 -  
392 - context "POST /errs/merge_several" do  
393 - it "should require at least two problems" do  
394 - post :merge_several, :problems => [@problem1.id.to_s]  
395 - request.flash[:notice].should match(/You must select at least two/)  
396 - end  
397 -  
398 - it "should merge the problems" do  
399 - lambda {  
400 - post :merge_several, :problems => [@problem1.id.to_s, @problem2.id.to_s]  
401 - assigns(:merged_problem).reload.errs.length.should == 2  
402 - }.should change(Problem, :count).by(-1)  
403 - end  
404 - end  
405 -  
406 - context "POST /errs/unmerge_several" do  
407 - it "should unmerge a merged problem" do  
408 - merged_problem = Problem.merge!(@problem1, @problem2)  
409 - merged_problem.errs.length.should == 2  
410 - lambda {  
411 - post :unmerge_several, :problems => [merged_problem.id.to_s]  
412 - merged_problem.reload.errs.length.should == 1  
413 - }.should change(Problem, :count).by(1)  
414 - end  
415 - end  
416 -  
417 - context "POST /errs/resolve_several" do  
418 - it "should resolve the issue" do  
419 - post :resolve_several, :problems => [@problem2.id.to_s]  
420 - @problem2.reload.resolved?.should == true  
421 - end  
422 - end  
423 -  
424 - context "POST /errs/unresolve_several" do  
425 - it "should unresolve the issue" do  
426 - post :unresolve_several, :problems => [@problem1.id.to_s]  
427 - @problem1.reload.resolved?.should == false  
428 - end  
429 - end  
430 -  
431 - context "POST /errs/destroy_several" do  
432 - it "should delete the errs" do  
433 - lambda {  
434 - post :destroy_several, :problems => [@problem1.id.to_s]  
435 - }.should change(Problem, :count).by(-1)  
436 - end  
437 - end  
438 - end  
439 -  
440 -end  
441 -  
spec/controllers/notices_controller_spec.rb
@@ -68,7 +68,7 @@ describe NoticesController do @@ -68,7 +68,7 @@ describe NoticesController do
68 problem = Fabricate(:problem, :app => app, :environment => "production") 68 problem = Fabricate(:problem, :app => app, :environment => "production")
69 notice = Fabricate(:notice, :err => Fabricate(:err, :problem => problem)) 69 notice = Fabricate(:notice, :err => Fabricate(:err, :problem => problem))
70 get :locate, :id => notice.id 70 get :locate, :id => notice.id
71 - response.should redirect_to(app_err_path(problem.app, problem)) 71 + response.should redirect_to(app_problem_path(problem.app, problem))
72 end 72 end
73 end 73 end
74 end 74 end
spec/controllers/problems_controller_spec.rb 0 → 100644
@@ -0,0 +1,441 @@ @@ -0,0 +1,441 @@
  1 +require 'spec_helper'
  2 +
  3 +describe ProblemsController do
  4 +
  5 + it_requires_authentication :for => {
  6 + :index => :get, :all => :get, :show => :get, :resolve => :put
  7 + },
  8 + :params => {:app_id => 'dummyid', :id => 'dummyid'}
  9 +
  10 + let(:app) { Fabricate(:app) }
  11 + let(:err) { Fabricate(:err, :problem => Fabricate(:problem, :app => app, :environment => "production")) }
  12 +
  13 +
  14 + describe "GET /problems" do
  15 + render_views
  16 + context 'when logged in as an admin' do
  17 + before(:each) do
  18 + @user = Fabricate(:admin)
  19 + sign_in @user
  20 + @problem = Fabricate(:notice, :err => Fabricate(:err, :problem => Fabricate(:problem, :app => app, :environment => "production"))).problem
  21 + end
  22 +
  23 + it "should successfully list problems" do
  24 + get :index
  25 + response.should be_success
  26 + response.body.gsub("&#8203;", "").should match(@problem.message)
  27 + end
  28 +
  29 + it "should list atom feed successfully" do
  30 + get :index, :format => "atom"
  31 + response.should be_success
  32 + response.body.should match(@problem.message)
  33 + end
  34 +
  35 + context "pagination" do
  36 + before(:each) do
  37 + 35.times { Fabricate :err }
  38 + end
  39 +
  40 + it "should have default per_page value for user" do
  41 + get :index
  42 + assigns(:problems).to_a.size.should == User::PER_PAGE
  43 + end
  44 +
  45 + it "should be able to override default per_page value" do
  46 + @user.update_attribute :per_page, 10
  47 + get :index
  48 + assigns(:problems).to_a.size.should == 10
  49 + end
  50 + end
  51 +
  52 + context 'with environment filters' do
  53 + before(:each) do
  54 + environments = ['production', 'test', 'development', 'staging']
  55 + 20.times do |i|
  56 + Fabricate(:problem, :environment => environments[i % environments.length])
  57 + end
  58 + end
  59 +
  60 + context 'no params' do
  61 + it 'shows problems for all environments' do
  62 + get :index
  63 + assigns(:problems).size.should == 21
  64 + end
  65 + end
  66 +
  67 + context 'environment production' do
  68 + it 'shows problems for just production' do
  69 + get :index, :environment => 'production'
  70 + assigns(:problems).size.should == 6
  71 + end
  72 + end
  73 +
  74 + context 'environment staging' do
  75 + it 'shows problems for just staging' do
  76 + get :index, :environment => 'staging'
  77 + assigns(:problems).size.should == 5
  78 + end
  79 + end
  80 +
  81 + context 'environment development' do
  82 + it 'shows problems for just development' do
  83 + get :index, :environment => 'development'
  84 + assigns(:problems).size.should == 5
  85 + end
  86 + end
  87 +
  88 + context 'environment test' do
  89 + it 'shows problems for just test' do
  90 + get :index, :environment => 'test'
  91 + assigns(:problems).size.should == 5
  92 + end
  93 + end
  94 + end
  95 + end
  96 +
  97 + context 'when logged in as a user' do
  98 + it 'gets a paginated list of unresolved problems for the users apps' do
  99 + sign_in(user = Fabricate(:user))
  100 + unwatched_err = Fabricate(:err)
  101 + watched_unresolved_err = Fabricate(:err, :problem => Fabricate(:problem, :app => Fabricate(:user_watcher, :user => user).app, :resolved => false))
  102 + watched_resolved_err = Fabricate(:err, :problem => Fabricate(:problem, :app => Fabricate(:user_watcher, :user => user).app, :resolved => true))
  103 + get :index
  104 + assigns(:problems).should include(watched_unresolved_err.problem)
  105 + assigns(:problems).should_not include(unwatched_err.problem, watched_resolved_err.problem)
  106 + end
  107 + end
  108 + end
  109 +
  110 + describe "GET /problems/all" do
  111 + context 'when logged in as an admin' do
  112 + it "gets a paginated list of all problems" do
  113 + sign_in Fabricate(:admin)
  114 + problems = Kaminari.paginate_array((1..30).to_a)
  115 + 3.times { problems << Fabricate(:err).problem }
  116 + 3.times { problems << Fabricate(:err, :problem => Fabricate(:problem, :resolved => true)).problem }
  117 + Problem.should_receive(:ordered_by).and_return(
  118 + mock('proxy', :page => mock('other_proxy', :per => problems))
  119 + )
  120 + get :all
  121 + assigns(:problems).should == problems
  122 + end
  123 + end
  124 +
  125 + context 'when logged in as a user' do
  126 + it 'gets a paginated list of all problems for the users apps' do
  127 + sign_in(user = Fabricate(:user))
  128 + unwatched_problem = Fabricate(:problem)
  129 + watched_unresolved_problem = Fabricate(:problem, :app => Fabricate(:user_watcher, :user => user).app, :resolved => false)
  130 + watched_resolved_problem = Fabricate(:problem, :app => Fabricate(:user_watcher, :user => user).app, :resolved => true)
  131 + get :all
  132 + assigns(:problems).should include(watched_resolved_problem, watched_unresolved_problem)
  133 + assigns(:problems).should_not include(unwatched_problem)
  134 + end
  135 + end
  136 + end
  137 +
  138 + describe "GET /apps/:app_id/problems/:id" do
  139 + render_views
  140 +
  141 + context 'when logged in as an admin' do
  142 + before do
  143 + sign_in Fabricate(:admin)
  144 + end
  145 +
  146 + it "finds the app" do
  147 + get :show, :app_id => app.id, :id => err.problem.id
  148 + assigns(:app).should == app
  149 + end
  150 +
  151 + it "finds the problem" do
  152 + get :show, :app_id => app.id, :id => err.problem.id
  153 + assigns(:problem).should == err.problem
  154 + end
  155 +
  156 + it "successfully render page" do
  157 + get :show, :app_id => app.id, :id => err.problem.id
  158 + response.should be_success
  159 + end
  160 +
  161 + context 'pagination' do
  162 + let!(:notices) do
  163 + 3.times.reduce([]) do |coll, i|
  164 + coll << Fabricate(:notice, :err => err, :created_at => (Time.now + i))
  165 + end
  166 + end
  167 +
  168 + it "paginates the notices 1 at a time, starting with the most recent" do
  169 + get :show, :app_id => app.id, :id => err.problem.id
  170 + assigns(:notices).entries.count.should == 1
  171 + assigns(:notices).should include(notices.last)
  172 + end
  173 +
  174 + it "paginates the notices 1 at a time, based on then notice param" do
  175 + get :show, :app_id => app.id, :id => err.problem.id, :notice => 3
  176 + assigns(:notices).entries.count.should == 1
  177 + assigns(:notices).should include(notices.first)
  178 + end
  179 + end
  180 +
  181 + context "create issue button" do
  182 + let(:button_matcher) { match(/create issue/) }
  183 +
  184 + it "should not exist for problem's app without issue tracker" do
  185 + err = Fabricate :err
  186 + get :show, :app_id => err.app.id, :id => err.problem.id
  187 +
  188 + response.body.should_not button_matcher
  189 + end
  190 +
  191 + it "should exist for problem's app with issue tracker" do
  192 + tracker = Fabricate(:lighthouse_tracker)
  193 + err = Fabricate(:err, :problem => Fabricate(:problem, :app => tracker.app))
  194 + get :show, :app_id => err.app.id, :id => err.problem.id
  195 +
  196 + response.body.should button_matcher
  197 + end
  198 +
  199 + it "should not exist for problem with issue_link" do
  200 + tracker = Fabricate(:lighthouse_tracker)
  201 + err = Fabricate(:err, :problem => Fabricate(:problem, :app => tracker.app, :issue_link => "http://some.host"))
  202 + get :show, :app_id => err.app.id, :id => err.problem.id
  203 +
  204 + response.body.should_not button_matcher
  205 + end
  206 + end
  207 + end
  208 +
  209 + context 'when logged in as a user' do
  210 + before do
  211 + sign_in(@user = Fabricate(:user))
  212 + @unwatched_err = Fabricate(:err)
  213 + @watched_app = Fabricate(:app)
  214 + @watcher = Fabricate(:user_watcher, :user => @user, :app => @watched_app)
  215 + @watched_err = Fabricate(:err, :problem => Fabricate(:problem, :app => @watched_app))
  216 + end
  217 +
  218 + it 'finds the problem if the user is watching the app' do
  219 + get :show, :app_id => @watched_app.to_param, :id => @watched_err.problem.id
  220 + assigns(:problem).should == @watched_err.problem
  221 + end
  222 +
  223 + it 'raises a DocumentNotFound error if the user is not watching the app' do
  224 + lambda {
  225 + get :show, :app_id => @unwatched_err.problem.app_id, :id => @unwatched_err.problem.id
  226 + }.should raise_error(Mongoid::Errors::DocumentNotFound)
  227 + end
  228 + end
  229 + end
  230 +
  231 + describe "PUT /apps/:app_id/problems/:id/resolve" do
  232 + before do
  233 + sign_in Fabricate(:admin)
  234 +
  235 + @problem = Fabricate(:err)
  236 + App.stub(:find).with(@problem.app.id).and_return(@problem.app)
  237 + @problem.app.problems.stub(:find).and_return(@problem.problem)
  238 + @problem.problem.stub(:resolve!)
  239 + end
  240 +
  241 + it 'finds the app and the problem' do
  242 + App.should_receive(:find).with(@problem.app.id).and_return(@problem.app)
  243 + @problem.app.problems.should_receive(:find).and_return(@problem.problem)
  244 + put :resolve, :app_id => @problem.app.id, :id => @problem.problem.id
  245 + assigns(:app).should == @problem.app
  246 + assigns(:problem).should == @problem.problem
  247 + end
  248 +
  249 + it "should resolve the issue" do
  250 + @problem.problem.should_receive(:resolve!).and_return(true)
  251 + put :resolve, :app_id => @problem.app.id, :id => @problem.problem.id
  252 + end
  253 +
  254 + it "should display a message" do
  255 + put :resolve, :app_id => @problem.app.id, :id => @problem.problem.id
  256 + request.flash[:success].should match(/Great news/)
  257 + end
  258 +
  259 + it "should redirect to the app page" do
  260 + put :resolve, :app_id => @problem.app.id, :id => @problem.problem.id
  261 + response.should redirect_to(app_path(@problem.app))
  262 + end
  263 +
  264 + it "should redirect back to problems page" do
  265 + request.env["Referer"] = problems_path
  266 + put :resolve, :app_id => @problem.app.id, :id => @problem.problem.id
  267 + response.should redirect_to(problems_path)
  268 + end
  269 + end
  270 +
  271 + describe "POST /apps/:app_id/problems/:id/create_issue" do
  272 + render_views
  273 +
  274 + before(:each) do
  275 + sign_in Fabricate(:admin)
  276 + end
  277 +
  278 + context "successful issue creation" do
  279 + context "lighthouseapp tracker" do
  280 + let(:notice) { Fabricate :notice }
  281 + let(:tracker) { Fabricate :lighthouse_tracker, :app => notice.app }
  282 + let(:problem) { notice.problem }
  283 +
  284 + before(:each) do
  285 + number = 5
  286 + @issue_link = "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets/#{number}.xml"
  287 + body = "<ticket><number type=\"integer\">#{number}</number></ticket>"
  288 + stub_request(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml").
  289 + to_return(:status => 201, :headers => {'Location' => @issue_link}, :body => body )
  290 +
  291 + post :create_issue, :app_id => problem.app.id, :id => problem.id
  292 + problem.reload
  293 + end
  294 +
  295 + it "should redirect to problem page" do
  296 + response.should redirect_to( app_problem_path(problem.app, problem) )
  297 + end
  298 + end
  299 + end
  300 +
  301 + context "absent issue tracker" do
  302 + let(:problem) { Fabricate :problem }
  303 +
  304 + before(:each) do
  305 + post :create_issue, :app_id => problem.app.id, :id => problem.id
  306 + end
  307 +
  308 + it "should redirect to problem page" do
  309 + response.should redirect_to( app_problem_path(problem.app, problem) )
  310 + end
  311 +
  312 + it "should set flash error message telling issue tracker of the app doesn't exist" do
  313 + flash[:error].should == "This app has no issue tracker setup."
  314 + end
  315 + end
  316 +
  317 + context "error during request to a tracker" do
  318 + context "lighthouseapp tracker" do
  319 + let(:tracker) { Fabricate :lighthouse_tracker }
  320 + let(:err) { Fabricate(:err, :problem => Fabricate(:problem, :app => tracker.app)) }
  321 +
  322 + before(:each) do
  323 + stub_request(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml").to_return(:status => 500)
  324 +
  325 + post :create_issue, :app_id => err.app.id, :id => err.problem.id
  326 + end
  327 +
  328 + it "should redirect to problem page" do
  329 + response.should redirect_to( app_problem_path(err.app, err.problem) )
  330 + end
  331 +
  332 + it "should notify of connection error" do
  333 + flash[:error].should include("There was an error during issue creation:")
  334 + end
  335 + end
  336 + end
  337 + end
  338 +
  339 + describe "DELETE /apps/:app_id/problems/:id/unlink_issue" do
  340 + before(:each) do
  341 + sign_in Fabricate(:admin)
  342 + end
  343 +
  344 + context "problem with issue" do
  345 + let(:err) { Fabricate(:err, :problem => Fabricate(:problem, :issue_link => "http://some.host")) }
  346 +
  347 + before(:each) do
  348 + delete :unlink_issue, :app_id => err.app.id, :id => err.problem.id
  349 + err.problem.reload
  350 + end
  351 +
  352 + it "should redirect to problem page" do
  353 + response.should redirect_to( app_problem_path(err.app, err.problem) )
  354 + end
  355 +
  356 + it "should clear issue link" do
  357 + err.problem.issue_link.should be_nil
  358 + end
  359 + end
  360 +
  361 + context "err without issue" do
  362 + let(:err) { Fabricate :err }
  363 +
  364 + before(:each) do
  365 + delete :unlink_issue, :app_id => err.app.id, :id => err.problem.id
  366 + err.problem.reload
  367 + end
  368 +
  369 + it "should redirect to problem page" do
  370 + response.should redirect_to( app_problem_path(err.app, err.problem) )
  371 + end
  372 + end
  373 + end
  374 +
  375 + describe "Bulk Actions" do
  376 + before(:each) do
  377 + sign_in Fabricate(:admin)
  378 + @problem1 = Fabricate(:err, :problem => Fabricate(:problem, :resolved => true)).problem
  379 + @problem2 = Fabricate(:err, :problem => Fabricate(:problem, :resolved => false)).problem
  380 + end
  381 +
  382 + it "should apply to multiple problems" do
  383 + post :resolve_several, :problems => [@problem1.id.to_s, @problem2.id.to_s]
  384 + assigns(:selected_problems).should == [@problem1, @problem2]
  385 + end
  386 +
  387 + it "should require at least one problem" do
  388 + post :resolve_several, :problems => []
  389 + request.flash[:notice].should match(/You have not selected any/)
  390 + end
  391 +
  392 + context "POST /problems/merge_several" do
  393 + it "should require at least two problems" do
  394 + post :merge_several, :problems => [@problem1.id.to_s]
  395 + request.flash[:notice].should match(/You must select at least two/)
  396 + end
  397 +
  398 + it "should merge the problems" do
  399 + lambda {
  400 + post :merge_several, :problems => [@problem1.id.to_s, @problem2.id.to_s]
  401 + assigns(:merged_problem).reload.errs.length.should == 2
  402 + }.should change(Problem, :count).by(-1)
  403 + end
  404 + end
  405 +
  406 + context "POST /problems/unmerge_several" do
  407 + it "should unmerge a merged problem" do
  408 + merged_problem = Problem.merge!(@problem1, @problem2)
  409 + merged_problem.errs.length.should == 2
  410 + lambda {
  411 + post :unmerge_several, :problems => [merged_problem.id.to_s]
  412 + merged_problem.reload.errs.length.should == 1
  413 + }.should change(Problem, :count).by(1)
  414 + end
  415 + end
  416 +
  417 + context "POST /problems/resolve_several" do
  418 + it "should resolve the issue" do
  419 + post :resolve_several, :problems => [@problem2.id.to_s]
  420 + @problem2.reload.resolved?.should == true
  421 + end
  422 + end
  423 +
  424 + context "POST /problems/unresolve_several" do
  425 + it "should unresolve the issue" do
  426 + post :unresolve_several, :problems => [@problem1.id.to_s]
  427 + @problem1.reload.resolved?.should == false
  428 + end
  429 + end
  430 +
  431 + context "POST /problems/destroy_several" do
  432 + it "should delete the problems" do
  433 + lambda {
  434 + post :destroy_several, :problems => [@problem1.id.to_s]
  435 + }.should change(Problem, :count).by(-1)
  436 + end
  437 + end
  438 + end
  439 +
  440 +end
  441 +
spec/helpers/errs_helper_spec.rb
@@ -1,35 +0,0 @@ @@ -1,35 +0,0 @@
1 -require 'spec_helper'  
2 -  
3 -describe ErrsHelper do  
4 - describe '#truncated_err_message' do  
5 - it 'is html safe' do  
6 - problem = double('problem', :message => '#<NoMethodError: ...>')  
7 - truncated = helper.truncated_err_message(problem)  
8 - truncated.should be_html_safe  
9 - truncated.should_not include('<', '>')  
10 - end  
11 - end  
12 -  
13 - describe "#gravatar_tag" do  
14 - let(:email) { "gravatar@example.com" }  
15 - let(:email_hash) { Digest::MD5.hexdigest email }  
16 - let(:base_url) { "http://www.gravatar.com/avatar/#{email_hash}" }  
17 -  
18 - context "default config" do  
19 - before do  
20 - Errbit::Config.stub(:use_gravatar).and_return(true)  
21 - Errbit::Config.stub(:gravatar_default).and_return('identicon')  
22 - end  
23 -  
24 - it "should render image_tag with correct alt and src" do  
25 - expected = "<img alt=\"#{email}\" class=\"gravatar\" src=\"#{base_url}?d=identicon&amp;s=48\" />"  
26 - helper.gravatar_tag(email, :s => 48).should eq(expected)  
27 - end  
28 -  
29 - it "should override :d" do  
30 - expected = "<img alt=\"#{email}\" class=\"gravatar\" src=\"#{base_url}?d=retro&amp;s=48\" />"  
31 - helper.gravatar_tag(email, :d => 'retro', :s => 48).should eq(expected)  
32 - end  
33 - end  
34 - end  
35 -end  
spec/helpers/problems_helper_spec.rb 0 → 100644
@@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
  1 +require 'spec_helper'
  2 +
  3 +describe ProblemsHelper do
  4 + describe '#truncated_problem_message' do
  5 + it 'is html safe' do
  6 + problem = double('problem', :message => '#<NoMethodError: ...>')
  7 + truncated = helper.truncated_problem_message(problem)
  8 + truncated.should be_html_safe
  9 + truncated.should_not include('<', '>')
  10 + end
  11 + end
  12 +
  13 + describe "#gravatar_tag" do
  14 + let(:email) { "gravatar@example.com" }
  15 + let(:email_hash) { Digest::MD5.hexdigest email }
  16 + let(:base_url) { "http://www.gravatar.com/avatar/#{email_hash}" }
  17 +
  18 + context "default config" do
  19 + before do
  20 + Errbit::Config.stub(:use_gravatar).and_return(true)
  21 + Errbit::Config.stub(:gravatar_default).and_return('identicon')
  22 + end
  23 +
  24 + it "should render image_tag with correct alt and src" do
  25 + expected = "<img alt=\"#{email}\" class=\"gravatar\" src=\"#{base_url}?d=identicon&amp;s=48\" />"
  26 + helper.gravatar_tag(email, :s => 48).should eq(expected)
  27 + end
  28 +
  29 + it "should override :d" do
  30 + expected = "<img alt=\"#{email}\" class=\"gravatar\" src=\"#{base_url}?d=retro&amp;s=48\" />"
  31 + helper.gravatar_tag(email, :d => 'retro', :s => 48).should eq(expected)
  32 + end
  33 + end
  34 + end
  35 +end
spec/views/errs/show.html.haml_spec.rb
@@ -1,128 +0,0 @@ @@ -1,128 +0,0 @@
1 -require 'spec_helper'  
2 -  
3 -describe "errs/show.html.haml" do  
4 - before do  
5 - err = Fabricate(:err)  
6 - problem = err.problem  
7 - comment = Fabricate(:comment)  
8 - assign :problem, problem  
9 - assign :comment, comment  
10 - assign :app, problem.app  
11 - assign :notices, err.notices.page(1).per(1)  
12 - assign :notice, err.notices.first  
13 - controller.stub(:current_user) { Fabricate(:user) }  
14 - end  
15 -  
16 - def with_issue_tracker(tracker, problem)  
17 - problem.app.issue_tracker = tracker.new :api_token => "token token token", :project_id => "1234"  
18 - assign :problem, problem  
19 - assign :app, problem.app  
20 - end  
21 -  
22 - describe "content_for :action_bar" do  
23 - def action_bar  
24 - view.content_for(:action_bar)  
25 - end  
26 -  
27 - it "should confirm the 'resolve' link by default" do  
28 - render  
29 -  
30 - action_bar.should have_selector('a.resolve[data-confirm="Seriously?"]')  
31 - end  
32 -  
33 - it "should confirm the 'resolve' link if configuration is unset" do  
34 - Errbit::Config.stub(:confirm_resolve_err).and_return(nil)  
35 - render  
36 -  
37 - action_bar.should have_selector('a.resolve[data-confirm="Seriously?"]')  
38 - end  
39 -  
40 - it "should not confirm the 'resolve' link if configured not to" do  
41 - Errbit::Config.stub(:confirm_resolve_err).and_return(false)  
42 - render  
43 -  
44 - action_bar.should have_selector('a.resolve[data-confirm="null"]')  
45 - end  
46 -  
47 - it "should link 'up' to HTTP_REFERER if is set" do  
48 - url = 'http://localhost:3000/errs'  
49 - controller.request.env['HTTP_REFERER'] = url  
50 - render  
51 -  
52 - action_bar.should have_selector("span a.up[href='#{url}']", :text => 'up')  
53 - end  
54 -  
55 - it "should link 'up' to app_errs_path if HTTP_REFERER isn't set'" do  
56 - controller.request.env['HTTP_REFERER'] = nil  
57 - problem = Fabricate(:problem_with_comments)  
58 - assign :problem, problem  
59 - assign :app, problem.app  
60 - render  
61 -  
62 - action_bar.should have_selector("span a.up[href='#{app_errs_path(problem.app)}']", :text => 'up')  
63 - end  
64 -  
65 - context 'create issue links' do  
66 - it 'should allow creating issue for github if current user has linked their github account' do  
67 - user = Fabricate(:user, :github_login => 'test_user', :github_oauth_token => 'abcdef')  
68 - controller.stub(:current_user) { user }  
69 -  
70 - problem = Fabricate(:problem_with_comments, :app => Fabricate(:app, :github_repo => "test_user/test_repo"))  
71 - assign :problem, problem  
72 - assign :app, problem.app  
73 - render  
74 -  
75 - action_bar.should have_selector("span a.github_create.create-issue", :text => 'create issue')  
76 - end  
77 -  
78 - it 'should allow creating issue for github if application has a github tracker' do  
79 - problem = Fabricate(:problem_with_comments, :app => Fabricate(:app, :github_repo => "test_user/test_repo"))  
80 - with_issue_tracker(GithubIssuesTracker, problem)  
81 - assign :problem, problem  
82 - assign :app, problem.app  
83 - render  
84 -  
85 - action_bar.should have_selector("span a.github_create.create-issue", :text => 'create issue')  
86 - end  
87 - end  
88 - end  
89 -  
90 - describe "content_for :comments with comments disabled for configured issue tracker" do  
91 - before do  
92 - Errbit::Config.stub(:allow_comments_with_issue_tracker).and_return(false)  
93 - Errbit::Config.stub(:use_gravatar).and_return(true)  
94 - end  
95 -  
96 - it 'should display comments and new comment form when no issue tracker' do  
97 - problem = Fabricate(:problem_with_comments)  
98 - assign :problem, problem  
99 - assign :app, problem.app  
100 - render  
101 -  
102 - view.content_for(:comments).should include('Test comment')  
103 - view.content_for(:comments).should have_selector('img[src^="http://www.gravatar.com/avatar"]')  
104 - view.content_for(:comments).should include('Add a comment')  
105 - end  
106 -  
107 - context "with issue tracker" do  
108 - it 'should not display the comments section' do  
109 - problem = Fabricate(:problem)  
110 - with_issue_tracker(PivotalLabsTracker, problem)  
111 - render  
112 - view.view_flow.get(:comments).should be_blank  
113 - end  
114 -  
115 - it 'should display existing comments' do  
116 - problem = Fabricate(:problem_with_comments)  
117 - problem.reload  
118 - with_issue_tracker(PivotalLabsTracker, problem)  
119 - render  
120 -  
121 - view.content_for(:comments).should include('Test comment')  
122 - view.content_for(:comments).should have_selector('img[src^="http://www.gravatar.com/avatar"]')  
123 - view.content_for(:comments).should_not include('Add a comment')  
124 - end  
125 - end  
126 - end  
127 -end  
128 -  
spec/views/problems/show.html.haml_spec.rb 0 → 100644
@@ -0,0 +1,127 @@ @@ -0,0 +1,127 @@
  1 +require 'spec_helper'
  2 +
  3 +describe "problems/show.html.haml" do
  4 + before do
  5 + problem = Fabricate(:problem)
  6 + comment = Fabricate(:comment)
  7 + assign :problem, problem
  8 + assign :comment, comment
  9 + assign :app, problem.app
  10 + assign :notices, problem.notices.page(1).per(1)
  11 + assign :notice, problem.notices.first
  12 + controller.stub(:current_user) { Fabricate(:user) }
  13 + end
  14 +
  15 + def with_issue_tracker(tracker, problem)
  16 + problem.app.issue_tracker = tracker.new :api_token => "token token token", :project_id => "1234"
  17 + assign :problem, problem
  18 + assign :app, problem.app
  19 + end
  20 +
  21 + describe "content_for :action_bar" do
  22 + def action_bar
  23 + view.content_for(:action_bar)
  24 + end
  25 +
  26 + it "should confirm the 'resolve' link by default" do
  27 + render
  28 +
  29 + action_bar.should have_selector('a.resolve[data-confirm="Seriously?"]')
  30 + end
  31 +
  32 + it "should confirm the 'resolve' link if configuration is unset" do
  33 + Errbit::Config.stub(:confirm_resolve_err).and_return(nil)
  34 + render
  35 +
  36 + action_bar.should have_selector('a.resolve[data-confirm="Seriously?"]')
  37 + end
  38 +
  39 + it "should not confirm the 'resolve' link if configured not to" do
  40 + Errbit::Config.stub(:confirm_resolve_err).and_return(false)
  41 + render
  42 +
  43 + action_bar.should have_selector('a.resolve[data-confirm="null"]')
  44 + end
  45 +
  46 + it "should link 'up' to HTTP_REFERER if is set" do
  47 + url = 'http://localhost:3000/problems'
  48 + controller.request.env['HTTP_REFERER'] = url
  49 + render
  50 +
  51 + action_bar.should have_selector("span a.up[href='#{url}']", :text => 'up')
  52 + end
  53 +
  54 + it "should link 'up' to app_problems_path if HTTP_REFERER isn't set'" do
  55 + controller.request.env['HTTP_REFERER'] = nil
  56 + problem = Fabricate(:problem_with_comments)
  57 + assign :problem, problem
  58 + assign :app, problem.app
  59 + render
  60 +
  61 + action_bar.should have_selector("span a.up[href='#{app_problems_path(problem.app)}']", :text => 'up')
  62 + end
  63 +
  64 + context 'create issue links' do
  65 + it 'should allow creating issue for github if current user has linked their github account' do
  66 + user = Fabricate(:user, :github_login => 'test_user', :github_oauth_token => 'abcdef')
  67 + controller.stub(:current_user) { user }
  68 +
  69 + problem = Fabricate(:problem_with_comments, :app => Fabricate(:app, :github_repo => "test_user/test_repo"))
  70 + assign :problem, problem
  71 + assign :app, problem.app
  72 + render
  73 +
  74 + action_bar.should have_selector("span a.github_create.create-issue", :text => 'create issue')
  75 + end
  76 +
  77 + it 'should allow creating issue for github if application has a github tracker' do
  78 + problem = Fabricate(:problem_with_comments, :app => Fabricate(:app, :github_repo => "test_user/test_repo"))
  79 + with_issue_tracker(GithubIssuesTracker, problem)
  80 + assign :problem, problem
  81 + assign :app, problem.app
  82 + render
  83 +
  84 + action_bar.should have_selector("span a.github_create.create-issue", :text => 'create issue')
  85 + end
  86 + end
  87 + end
  88 +
  89 + describe "content_for :comments with comments disabled for configured issue tracker" do
  90 + before do
  91 + Errbit::Config.stub(:allow_comments_with_issue_tracker).and_return(false)
  92 + Errbit::Config.stub(:use_gravatar).and_return(true)
  93 + end
  94 +
  95 + it 'should display comments and new comment form when no issue tracker' do
  96 + problem = Fabricate(:problem_with_comments)
  97 + assign :problem, problem
  98 + assign :app, problem.app
  99 + render
  100 +
  101 + view.content_for(:comments).should include('Test comment')
  102 + view.content_for(:comments).should have_selector('img[src^="http://www.gravatar.com/avatar"]')
  103 + view.content_for(:comments).should include('Add a comment')
  104 + end
  105 +
  106 + context "with issue tracker" do
  107 + it 'should not display the comments section' do
  108 + problem = Fabricate(:problem)
  109 + with_issue_tracker(PivotalLabsTracker, problem)
  110 + render
  111 + view.view_flow.get(:comments).should be_blank
  112 + end
  113 +
  114 + it 'should display existing comments' do
  115 + problem = Fabricate(:problem_with_comments)
  116 + problem.reload
  117 + with_issue_tracker(PivotalLabsTracker, problem)
  118 + render
  119 +
  120 + view.content_for(:comments).should include('Test comment')
  121 + view.content_for(:comments).should have_selector('img[src^="http://www.gravatar.com/avatar"]')
  122 + view.content_for(:comments).should_not include('Add a comment')
  123 + end
  124 + end
  125 + end
  126 +end
  127 +