Commit 387bca94f6e617fe5e910eed032900145de4b11b
1 parent
3db48ca3
Exists in
master
and in
1 other branch
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 < ApplicationController | @@ -15,6 +15,6 @@ class NoticesController < 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 |
@@ -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("​").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 | - |
@@ -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("​").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
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 & 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
app/views/errs/index.atom.builder
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 '✘'.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
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 <%= @notice.environment_name %>: <%= raw(@notice.mes | @@ -2,7 +2,7 @@ An err has just occurred in <%= @notice.environment_name %>: <%= 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: |
@@ -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" |
@@ -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 |
@@ -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 & 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 | + |
@@ -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] |
@@ -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 |
@@ -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 '✘'.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 |
@@ -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("​", "").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 |
@@ -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("​", "").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&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&s=48\" />" | ||
31 | - helper.gravatar_tag(email, :d => 'retro', :s => 48).should eq(expected) | ||
32 | - end | ||
33 | - end | ||
34 | - end | ||
35 | -end |
@@ -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&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&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 | - |
@@ -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 | + |