diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb
index fbd5447..0d36cf3 100644
--- a/app/controllers/comments_controller.rb
+++ b/app/controllers/comments_controller.rb
@@ -11,7 +11,7 @@ class CommentsController < ApplicationController
else
flash[:error] = "I'm sorry, your comment was blank! Try again?"
end
- redirect_to app_err_path(@app, @problem)
+ redirect_to app_problem_path(@app, @problem)
end
def destroy
@@ -21,7 +21,7 @@ class CommentsController < ApplicationController
else
flash[:error] = "Sorry, I couldn't delete your comment for some reason. I hope you don't have any sensitive information in there!"
end
- redirect_to app_err_path(@app, @problem)
+ redirect_to app_problem_path(@app, @problem)
end
protected
@@ -34,7 +34,7 @@ class CommentsController < ApplicationController
end
def find_problem
- @problem = @app.problems.find(params[:err_id])
+ @problem = @app.problems.find(params[:problem_id])
end
end
diff --git a/app/controllers/errs_controller.rb b/app/controllers/errs_controller.rb
deleted file mode 100644
index 84c6d22..0000000
--- a/app/controllers/errs_controller.rb
+++ /dev/null
@@ -1,157 +0,0 @@
-class ErrsController < ApplicationController
- include ActionView::Helpers::TextHelper
-
- before_filter :find_app, :except => [:index, :all, :destroy_several, :resolve_several, :unresolve_several, :merge_several, :unmerge_several]
- before_filter :find_problem, :except => [:index, :all, :destroy_several, :resolve_several, :unresolve_several, :merge_several, :unmerge_several]
- before_filter :find_selected_problems, :only => [:destroy_several, :resolve_several, :unresolve_several, :merge_several, :unmerge_several]
- before_filter :set_sorting_params, :only => [:index, :all]
- before_filter :set_tracker_params, :only => [:create_issue]
-
- def index
- app_scope = current_user.admin? ? App.all : current_user.apps
-
- @problems = Problem.for_apps(app_scope).in_env(params[:environment]).unresolved.ordered_by(@sort, @order)
- @selected_problems = params[:problems] || []
- respond_to do |format|
- format.html do
- @problems = @problems.page(params[:page]).per(current_user.per_page)
- end
- format.atom
- end
- end
-
- def all
- app_scope = current_user.admin? ? App.all : current_user.apps
- @problems = Problem.for_apps(app_scope).ordered_by(@sort, @order).page(params[:page]).per(current_user.per_page)
- @selected_problems = params[:problems] || []
- end
-
- def show
- @notices = @problem.notices.reverse_ordered.page(params[:notice]).per(1)
- @notice = @notices.first
- @comment = Comment.new
- if request.headers['X-PJAX']
- params["_pjax"] = nil
- render :layout => false
- end
- end
-
- def create_issue
- # Create an issue on GitHub using user's github token
- if params[:tracker] == 'user_github'
- if !@app.github_repo?
- flash[:error] = "This app doesn't have a GitHub repo set up."
- elsif !current_user.github_account?
- flash[:error] = "You haven't linked your Github account."
- else
- @tracker = GithubIssuesTracker.new(
- :app => @app,
- :username => current_user.github_login,
- :oauth_token => current_user.github_oauth_token
- )
- end
-
- # Or, create an issue using the App's issue tracker
- elsif @app.issue_tracker_configured?
- @tracker = @app.issue_tracker
-
- # Otherwise, display error about missing tracker configuration.
- else
- flash[:error] = "This app has no issue tracker setup."
- end
-
- if flash[:error].blank? && @tracker
- begin
- @tracker.create_issue @problem, current_user
- rescue Exception => ex
- Rails.logger.error "Error during issue creation: " << ex.message
- flash[:error] = "There was an error during issue creation: #{ex.message}"
- end
- end
-
- redirect_to app_err_path(@app, @problem)
- end
-
- def unlink_issue
- @problem.update_attribute :issue_link, nil
- redirect_to app_err_path(@app, @problem)
- end
-
- def resolve
- @problem.resolve!
- flash[:success] = 'Great news everyone! The err has been resolved.'
- redirect_to :back
- rescue ActionController::RedirectBackError
- redirect_to app_path(@app)
- end
-
- def resolve_several
- @selected_problems.each(&:resolve!)
- flash[:success] = "Great news everyone! #{pluralize(@selected_problems.count, 'err has', 'errs have')} been resolved."
- redirect_to :back
- end
-
- def unresolve_several
- @selected_problems.each(&:unresolve!)
- flash[:success] = "#{pluralize(@selected_problems.count, 'err has', 'errs have')} been unresolved."
- redirect_to :back
- end
-
- def merge_several
- if @selected_problems.length < 2
- flash[:notice] = "You must select at least two errors to merge"
- else
- @merged_problem = Problem.merge!(@selected_problems)
- flash[:notice] = "#{@selected_problems.count} errors have been merged."
- end
- redirect_to :back
- end
-
- def unmerge_several
- all = @selected_problems.map(&:unmerge!).flatten
- flash[:success] = "#{pluralize(all.length, 'err has', 'errs have')} been unmerged."
- redirect_to :back
- end
-
- def destroy_several
- nb_problem_destroy = ProblemDestroy.execute(@selected_problems)
- flash[:notice] = "#{pluralize(nb_problem_destroy, 'err has', 'errs have')} been deleted."
- redirect_to :back
- end
-
- protected
- def find_app
- @app = App.find(params[:app_id])
-
- # Mongoid Bug: could not chain: current_user.apps.find_by_id!
- # apparently finding by 'watchers.email' and 'id' is broken
- raise(Mongoid::Errors::DocumentNotFound.new(App,@app.id)) unless current_user.admin? || current_user.watching?(@app)
- end
-
- def find_problem
- @problem = @app.problems.find(params[:id])
- end
-
- def set_tracker_params
- IssueTracker.default_url_options[:host] = request.host
- IssueTracker.default_url_options[:port] = request.port
- IssueTracker.default_url_options[:protocol] = request.scheme
- end
-
- def find_selected_problems
- err_ids = (params[:problems] || []).compact
- if err_ids.empty?
- flash[:notice] = "You have not selected any errors"
- redirect_to :back
- else
- @selected_problems = Array(Problem.find(err_ids))
- end
- end
-
- def set_sorting_params
- @sort = params[:sort]
- @sort = "last_notice_at" unless %w{app message last_notice_at last_deploy_at count}.member?(@sort)
- @order = params[:order] || "desc"
- end
-end
-
diff --git a/app/controllers/notices_controller.rb b/app/controllers/notices_controller.rb
index 40bef96..8b900ad 100644
--- a/app/controllers/notices_controller.rb
+++ b/app/controllers/notices_controller.rb
@@ -15,6 +15,6 @@ class NoticesController < ApplicationController
# Redirects a notice to the problem page. Useful when using User Information at Airbrake gem.
def locate
problem = Notice.find(params[:id]).problem
- redirect_to app_err_path(problem.app, problem)
+ redirect_to app_problem_path(problem.app, problem)
end
end
diff --git a/app/controllers/problems_controller.rb b/app/controllers/problems_controller.rb
new file mode 100644
index 0000000..b88d2f8
--- /dev/null
+++ b/app/controllers/problems_controller.rb
@@ -0,0 +1,157 @@
+class ProblemsController < ApplicationController
+ include ActionView::Helpers::TextHelper
+
+ before_filter :find_app, :except => [:index, :all, :destroy_several, :resolve_several, :unresolve_several, :merge_several, :unmerge_several]
+ before_filter :find_problem, :except => [:index, :all, :destroy_several, :resolve_several, :unresolve_several, :merge_several, :unmerge_several]
+ before_filter :find_selected_problems, :only => [:destroy_several, :resolve_several, :unresolve_several, :merge_several, :unmerge_several]
+ before_filter :set_sorting_params, :only => [:index, :all]
+ before_filter :set_tracker_params, :only => [:create_issue]
+
+ def index
+ app_scope = current_user.admin? ? App.all : current_user.apps
+
+ @problems = Problem.for_apps(app_scope).in_env(params[:environment]).unresolved.ordered_by(@sort, @order)
+ @selected_problems = params[:problems] || []
+ respond_to do |format|
+ format.html do
+ @problems = @problems.page(params[:page]).per(current_user.per_page)
+ end
+ format.atom
+ end
+ end
+
+ def all
+ app_scope = current_user.admin? ? App.all : current_user.apps
+ @problems = Problem.for_apps(app_scope).ordered_by(@sort, @order).page(params[:page]).per(current_user.per_page)
+ @selected_problems = params[:problems] || []
+ end
+
+ def show
+ @notices = @problem.notices.reverse_ordered.page(params[:notice]).per(1)
+ @notice = @notices.first
+ @comment = Comment.new
+ if request.headers['X-PJAX']
+ params["_pjax"] = nil
+ render :layout => false
+ end
+ end
+
+ def create_issue
+ # Create an issue on GitHub using user's github token
+ if params[:tracker] == 'user_github'
+ if !@app.github_repo?
+ flash[:error] = "This app doesn't have a GitHub repo set up."
+ elsif !current_user.github_account?
+ flash[:error] = "You haven't linked your Github account."
+ else
+ @tracker = GithubIssuesTracker.new(
+ :app => @app,
+ :username => current_user.github_login,
+ :oauth_token => current_user.github_oauth_token
+ )
+ end
+
+ # Or, create an issue using the App's issue tracker
+ elsif @app.issue_tracker_configured?
+ @tracker = @app.issue_tracker
+
+ # Otherwise, display error about missing tracker configuration.
+ else
+ flash[:error] = "This app has no issue tracker setup."
+ end
+
+ if flash[:error].blank? && @tracker
+ begin
+ @tracker.create_issue @problem, current_user
+ rescue Exception => ex
+ Rails.logger.error "Error during issue creation: " << ex.message
+ flash[:error] = "There was an error during issue creation: #{ex.message}"
+ end
+ end
+
+ redirect_to app_problem_path(@app, @problem)
+ end
+
+ def unlink_issue
+ @problem.update_attribute :issue_link, nil
+ redirect_to app_problem_path(@app, @problem)
+ end
+
+ def resolve
+ @problem.resolve!
+ flash[:success] = 'Great news everyone! The err has been resolved.'
+ redirect_to :back
+ rescue ActionController::RedirectBackError
+ redirect_to app_path(@app)
+ end
+
+ def resolve_several
+ @selected_problems.each(&:resolve!)
+ flash[:success] = "Great news everyone! #{pluralize(@selected_problems.count, 'err has', 'errs have')} been resolved."
+ redirect_to :back
+ end
+
+ def unresolve_several
+ @selected_problems.each(&:unresolve!)
+ flash[:success] = "#{pluralize(@selected_problems.count, 'err has', 'errs have')} been unresolved."
+ redirect_to :back
+ end
+
+ def merge_several
+ if @selected_problems.length < 2
+ flash[:notice] = "You must select at least two errors to merge"
+ else
+ @merged_problem = Problem.merge!(@selected_problems)
+ flash[:notice] = "#{@selected_problems.count} errors have been merged."
+ end
+ redirect_to :back
+ end
+
+ def unmerge_several
+ all = @selected_problems.map(&:unmerge!).flatten
+ flash[:success] = "#{pluralize(all.length, 'err has', 'errs have')} been unmerged."
+ redirect_to :back
+ end
+
+ def destroy_several
+ nb_problem_destroy = ProblemDestroy.execute(@selected_problems)
+ flash[:notice] = "#{pluralize(nb_problem_destroy, 'err has', 'errs have')} been deleted."
+ redirect_to :back
+ end
+
+ protected
+ def find_app
+ @app = App.find(params[:app_id])
+
+ # Mongoid Bug: could not chain: current_user.apps.find_by_id!
+ # apparently finding by 'watchers.email' and 'id' is broken
+ raise(Mongoid::Errors::DocumentNotFound.new(App,@app.id)) unless current_user.admin? || current_user.watching?(@app)
+ end
+
+ def find_problem
+ @problem = @app.problems.find(params[:id])
+ end
+
+ def set_tracker_params
+ IssueTracker.default_url_options[:host] = request.host
+ IssueTracker.default_url_options[:port] = request.port
+ IssueTracker.default_url_options[:protocol] = request.scheme
+ end
+
+ def find_selected_problems
+ err_ids = (params[:problems] || []).compact
+ if err_ids.empty?
+ flash[:notice] = "You have not selected any errors"
+ redirect_to :back
+ else
+ @selected_problems = Array(Problem.find(err_ids))
+ end
+ end
+
+ def set_sorting_params
+ @sort = params[:sort]
+ @sort = "last_notice_at" unless %w{app message last_notice_at last_deploy_at count}.member?(@sort)
+ @order = params[:order] || "desc"
+ end
+end
+
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 19b9a5d..966585c 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -13,7 +13,7 @@ module ApplicationHelper
event.dtend = notice.created_at.utc + 60.minutes
event.organizer = notice.server_environment && notice.server_environment["hostname"]
event.location = notice.server_environment && notice.server_environment["project-root"]
- event.url = app_err_url(:app_id => notice.problem.app.id, :id => notice.problem)
+ event.url = app_problem_url(:app_id => notice.problem.app.id, :id => notice.problem)
end
end
end.to_s
@@ -58,11 +58,11 @@ module ApplicationHelper
percent = 100.0 / total.to_f
rows = tallies.map {|value, count| [(count.to_f * percent), value]} \
.sort {|a, b| a[0] <=> b[0]}
- render "errs/tally_table", :rows => rows
+ render "problems/tally_table", :rows => rows
end
def head(collection)
- collection.first(head_size)
+ collection.first(head_size)
end
def tail(collection)
diff --git a/app/helpers/errs_helper.rb b/app/helpers/errs_helper.rb
deleted file mode 100644
index ffdd958..0000000
--- a/app/helpers/errs_helper.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-module ErrsHelper
- def err_confirm
- Errbit::Config.confirm_resolve_err === false ? nil : 'Seriously?'
- end
-
- def truncated_err_message(problem)
- unless (msg = problem.message).blank?
- # Truncate & insert invisible chars so that firefox can emulate 'word-wrap: break-word' CSS rule
- truncate(msg, :length => 300).scan(/.{1,5}/).map { |s| h(s) }.join("").html_safe
- end
- end
-
- def gravatar_tag(email, options = {})
- image_tag gravatar_url(email, options), :alt => email, :class => 'gravatar'
- end
-
- def gravatar_url(email, options = {})
- default_options = {
- :d => Errbit::Config.gravatar_default,
- }
- options.reverse_merge! default_options
- params = options.extract!(:s, :d).delete_if { |k, v| v.blank? }
- email_hash = Digest::MD5.hexdigest(email)
- "http://www.gravatar.com/avatar/#{email_hash}?#{params.to_query}"
- end
-end
-
diff --git a/app/helpers/problems_helper.rb b/app/helpers/problems_helper.rb
new file mode 100644
index 0000000..0e0c807
--- /dev/null
+++ b/app/helpers/problems_helper.rb
@@ -0,0 +1,27 @@
+module ProblemsHelper
+ def problem_confirm
+ Errbit::Config.confirm_resolve_err === false ? nil : 'Seriously?'
+ end
+
+ def truncated_problem_message(problem)
+ unless (msg = problem.message).blank?
+ # Truncate & insert invisible chars so that firefox can emulate 'word-wrap: break-word' CSS rule
+ truncate(msg, :length => 300).scan(/.{1,5}/).map { |s| h(s) }.join("").html_safe
+ end
+ end
+
+ def gravatar_tag(email, options = {})
+ image_tag gravatar_url(email, options), :alt => email, :class => 'gravatar'
+ end
+
+ def gravatar_url(email, options = {})
+ default_options = {
+ :d => Errbit::Config.gravatar_default,
+ }
+ options.reverse_merge! default_options
+ params = options.extract!(:s, :d).delete_if { |k, v| v.blank? }
+ email_hash = Digest::MD5.hexdigest(email)
+ "http://www.gravatar.com/avatar/#{email_hash}?#{params.to_query}"
+ end
+end
+
diff --git a/app/views/apps/show.atom.builder b/app/views/apps/show.atom.builder
index fc416c1..84d3120 100644
--- a/app/views/apps/show.atom.builder
+++ b/app/views/apps/show.atom.builder
@@ -1,4 +1,4 @@
atom_feed do |feed|
feed.title("Errbit notices for #{h @app.name} at #{root_url}")
- render "errs/list", :feed => feed
+ render "problems/list", :feed => feed
end
diff --git a/app/views/apps/show.html.haml b/app/views/apps/show.html.haml
index b7bf7ba..de352a2 100644
--- a/app/views/apps/show.html.haml
+++ b/app/views/apps/show.html.haml
@@ -83,7 +83,7 @@
- if @app.problems.any?
%h3.clear Errors
- = render 'errs/table', :errs => @problems
+ = render 'problems/table', :problems => @problems
- else
%h3.clear No errs have been caught yet, make sure you setup your app
= render 'configuration_instructions', :app => @app
diff --git a/app/views/errs/_issue_tracker_links.html.haml b/app/views/errs/_issue_tracker_links.html.haml
deleted file mode 100644
index 2e36277..0000000
--- a/app/views/errs/_issue_tracker_links.html.haml
+++ /dev/null
@@ -1,15 +0,0 @@
-- if @app.issue_tracker_configured? || current_user.github_account?
- - if @problem.issue_link.present?
- %span= link_to 'go to issue', @problem.issue_link, :class => "#{@problem.issue_type}_goto goto-issue"
- = link_to 'unlink issue', unlink_issue_app_err_path(@app, @problem), :method => :delete, :data => { :confirm => "Unlink err issues?" }, :class => "unlink-issue"
- - elsif @problem.issue_link == "pending"
- %span.disabled= link_to 'creating...', '#', :class => "#{@problem.issue_type}_inactive create-issue"
- = link_to 'retry', create_issue_app_err_path(@app, @problem), :method => :post
- - else
- - if @app.github_repo?
- - if current_user.can_create_github_issues?
- %span= link_to 'create issue', create_issue_app_err_path(@app, @problem, :tracker => 'user_github'), :method => :post, :class => "github_create create-issue"
- - elsif @app.issue_tracker_configured? && @app.issue_tracker.is_a?(GithubIssuesTracker)
- %span= link_to 'create issue', create_issue_app_err_path(@app, @problem), :method => :post, :class => "github_create create-issue"
- - if @app.issue_tracker_configured? && !@app.issue_tracker.is_a?(GithubIssuesTracker)
- %span= link_to 'create issue', create_issue_app_err_path(@app, @problem), :method => :post, :class => "#{@app.issue_tracker.label}_create create-issue"
diff --git a/app/views/errs/_list.atom.builder b/app/views/errs/_list.atom.builder
deleted file mode 100644
index 36197b7..0000000
--- a/app/views/errs/_list.atom.builder
+++ /dev/null
@@ -1,15 +0,0 @@
-feed.updated(@problems.first.try(:created_at) || Time.now)
-
-for problem in @problems
- notice = problem.notices.first
-
- feed.entry(problem, :url => app_err_url(problem.app, problem)) do |entry|
- entry.title "[#{ problem.where }] #{problem.message.to_s.truncate(27)}"
- entry.author do |author|
- author.name "#{ problem.app.name } [#{ problem.environment }]"
- end
- if notice
- entry.summary(notice_atom_summary(notice), :type => "html")
- end
- end
-end
diff --git a/app/views/errs/_table.html.haml b/app/views/errs/_table.html.haml
deleted file mode 100644
index d2d2c96..0000000
--- a/app/views/errs/_table.html.haml
+++ /dev/null
@@ -1,56 +0,0 @@
-- any_issue_links = errs.any?{|e| e.issue_link.present? && e.issue_link != 'pending' }
-=form_tag do
- %table.errs.selectable
- %thead
- %tr
- %th= check_box_tag "toggle_problems_checkboxes"
- %th= link_for_sort "App"
- %th= link_for_sort "What & Where".html_safe, "message"
- %th= link_for_sort "Latest", "last_notice_at"
- %th= link_for_sort "Deploy", "last_deploy_at"
- %th= link_for_sort "Count"
- - if any_issue_links
- %th Issue
- %th Resolve
- %tbody
- - errs.each do |problem|
- %tr{:class => problem.resolved? ? 'resolved' : 'unresolved'}
- %td.select
- = check_box_tag "problems[]", problem.id, @selected_problems.member?(problem.id.to_s)
- %td.app
- = link_to problem.app.name, app_path(problem.app)
- - if current_page?(:controller => 'errs')
- %span.environment= link_to problem.environment, errs_path(:environment => problem.environment)
- - else
- %span.environment= link_to problem.environment, app_path(problem.app, :environment => problem.environment)
- %td.message
- = link_to truncated_err_message(problem), app_err_path(problem.app, problem)
- %em= problem.where
- - if problem.comments_count > 0
- - comment = problem.comments.last
- %br
- .inline_comment
- - if comment.user
- %em.commenter= (Errbit::Config.user_has_username ? comment.user.username : comment.user.email).to_s << ":"
- %em= truncate(comment.body, :length => 100, :separator => ' ')
- %td.latest #{time_ago_in_words(problem.last_notice_at)} ago
- %td.deploy= problem.last_deploy_at ? problem.last_deploy_at.to_s(:micro) : 'n/a'
- %td.count= link_to problem.notices_count, app_err_path(problem.app, problem)
- - if any_issue_links
- %td.issue_link
- - if problem.app.issue_tracker_configured? && problem.issue_link.present? && problem.issue_link != 'pending'
- = link_to image_tag("#{problem.issue_type}_goto.png"), problem.issue_link, :target => "_blank"
- %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?
- - if errs.none?
- %tr
- %td{:colspan => (any_issue_links ? 8 : 7)}
- %em No errs here
- = paginate errs
- .tab-bar
- %ul
- %li= submit_tag 'Merge', :id => 'merge_errs', :class => 'button', 'data-action' => merge_several_errs_path
- %li= submit_tag 'Unmerge', :id => 'unmerge_errs', :class => 'button', 'data-action' => unmerge_several_errs_path
- %li= submit_tag 'Resolve', :id => 'resolve_errs', :class => 'button', 'data-action' => resolve_several_errs_path
- %li= submit_tag 'Unresolve', :id => 'unresolve_errs', :class => 'button', 'data-action' => unresolve_several_errs_path
- %li= submit_tag 'Delete', :id => 'delete_errs', :class => 'button', 'data-action' => destroy_several_errs_path
-
diff --git a/app/views/errs/_tally_table.html.haml b/app/views/errs/_tally_table.html.haml
deleted file mode 100644
index bd03ede..0000000
--- a/app/views/errs/_tally_table.html.haml
+++ /dev/null
@@ -1,18 +0,0 @@
-.head_and_tail
- %table.tally.head
- %tbody
- - head(rows).each do |row|
- %tr
- %td.percent= number_to_percentage(row[0], :precision => 1)
- %th.value= row[1]
- - if rows.size > head_size
- %tfoot
- %tr
- %td{:colspan => 2}
- = link_to 'Show more...', '#', :class => :show_tail
- %table.tally.tail{:style => "display: none"}
- %tbody
- - tail(rows).each do |row|
- %tr
- %td.percent= number_to_percentage(row[0], :precision => 1)
- %th.value= row[1]
diff --git a/app/views/errs/all.html.haml b/app/views/errs/all.html.haml
deleted file mode 100644
index de9a42f..0000000
--- a/app/views/errs/all.html.haml
+++ /dev/null
@@ -1,4 +0,0 @@
-- content_for :title, 'All Errors'
-- content_for :action_bar do
- = link_to 'hide resolved', errs_path, :class => 'button'
-= render 'table', :errs => @problems
diff --git a/app/views/errs/index.atom.builder b/app/views/errs/index.atom.builder
deleted file mode 100644
index 55df01c..0000000
--- a/app/views/errs/index.atom.builder
+++ /dev/null
@@ -1,4 +0,0 @@
-atom_feed do |feed|
- feed.title("Errbit notices at #{root_url}")
- render "errs/list", :feed => feed
-end
diff --git a/app/views/errs/index.html.haml b/app/views/errs/index.html.haml
deleted file mode 100644
index d265f14..0000000
--- a/app/views/errs/index.html.haml
+++ /dev/null
@@ -1,6 +0,0 @@
-- content_for :title, 'Unresolved Errors'
-- content_for :head do
- = auto_discovery_link_tag :atom, errs_path(User.token_authentication_key => current_user.authentication_token, :format => "atom"), :title => "Errbit notices at #{request.host}"
-- content_for :action_bar do
- = link_to 'show resolved', all_errs_path, :class => 'button'
-= render 'table', :errs => @problems
diff --git a/app/views/errs/show.html.haml b/app/views/errs/show.html.haml
deleted file mode 100644
index 511d4e0..0000000
--- a/app/views/errs/show.html.haml
+++ /dev/null
@@ -1,83 +0,0 @@
-- content_for :page_title, @problem.message
-- content_for :title_css_class, 'err_show'
-- content_for :title, @problem.error_class || truncate(@problem.message, :length => 32)
-- content_for :meta do
- %strong App:
- = link_to @app.name, app_path(@app)
- %strong Where:
- = @problem.where
- %br
- %strong Environment:
- = @problem.environment
- %strong Last Notice:
- = @problem.last_notice_at.to_s(:precise)
-- content_for :action_bar do
- - if @problem.unresolved?
- %span= link_to 'resolve', resolve_app_err_path(@app, @problem), :method => :put, :data => { :confirm => err_confirm }, :class => 'resolve'
- - if current_user.authentication_token
- %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"
- %span>= link_to 'up', (request.env['HTTP_REFERER'] ? :back : app_errs_path(@app)), :class => 'up'
- %br
- = render "issue_tracker_links"
-
-- if Errbit::Config.allow_comments_with_issue_tracker || !@app.issue_tracker_configured? || @problem.comments.any?
- - content_for :comments do
- %h3 Comments
- - @problem.comments.each do |comment|
- .window
- %table.comment
- %tr
- %th
- - if Errbit::Config.use_gravatar
- = gravatar_tag comment.user.email, :s => 24
- %span.comment-info
- = time_ago_in_words(comment.created_at, true) << " ago by "
- = link_to comment.user.email, user_path(comment.user)
- %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"
- %tr
- %td= comment.body.gsub("\n", "
").html_safe
- - if Errbit::Config.allow_comments_with_issue_tracker || !@app.issue_tracker_configured?
- = form_for @comment, :url => app_err_comments_path(@app, @problem) do |comment_form|
- %p Add a comment
- = comment_form.text_area :body, :style => "width: 420px; height: 80px;"
- = comment_form.submit "Save Comment"
-
-%h4= @notice.try(:message)
-
-= paginate @notices, :param_name => :notice, :theme => :notices
-
-.tab-bar
- %ul
- %li= link_to 'Summary', '#summary', :rel => 'summary', :class => 'button'
- %li= link_to 'Backtrace', '#backtrace', :rel => 'backtrace', :class => 'button'
- - if @notice && @notice.user_attributes.present?
- %li= link_to 'User Details', '#user_attributes', :rel => 'user_attributes', :class => 'button'
- %li= link_to 'Environment', '#environment', :rel => 'environment', :class => 'button'
- %li= link_to 'Parameters', '#params', :rel => 'params', :class => 'button'
- %li= link_to 'Session', '#session', :rel => 'session', :class => 'button'
-
-- if @notice
- #summary
- %h3 Summary
- = render 'notices/summary', :notice => @notice, :problem => @problem
-
- #backtrace
- %h3 Backtrace
- = render 'notices/backtrace', :lines => @notice.backtrace
-
- - if @notice.user_attributes.present?
- #user_attributes
- %h3 User Details
- = render 'notices/user_attributes', :user => @notice.user_attributes
-
- #environment
- %h3 Environment
- = render 'notices/environment', :notice => @notice
-
- #params
- %h3 Parameters
- = render 'notices/params', :notice => @notice
-
- #session
- %h3 Session
- = render 'notices/session', :notice => @notice
diff --git a/app/views/errs/show.ics.haml b/app/views/errs/show.ics.haml
deleted file mode 100644
index 913dbf4..0000000
--- a/app/views/errs/show.ics.haml
+++ /dev/null
@@ -1 +0,0 @@
-= generate_problem_ical(@problem.notices.order_by(:created_at.asc))
diff --git a/app/views/issue_trackers/fogbugz_body.txt.erb b/app/views/issue_trackers/fogbugz_body.txt.erb
index 85a5364..56195b9 100644
--- a/app/views/issue_trackers/fogbugz_body.txt.erb
+++ b/app/views/issue_trackers/fogbugz_body.txt.erb
@@ -1,4 +1,4 @@
-"See this exception on Errbit": <%= app_err_url(problem.app, problem) %>
+"See this exception on Errbit": <%= app_problem_url(problem.app, problem) %>
<% if notice = problem.notices.first %>
<%= notice.message %>
diff --git a/app/views/issue_trackers/github_issues_body.txt.erb b/app/views/issue_trackers/github_issues_body.txt.erb
index 7ac9514..b0edcd5 100644
--- a/app/views/issue_trackers/github_issues_body.txt.erb
+++ b/app/views/issue_trackers/github_issues_body.txt.erb
@@ -1,4 +1,4 @@
-[See this exception on Errbit](<%= app_err_url problem.app, problem %> "See this exception on Errbit")
+[See this exception on Errbit](<%= app_problem_url problem.app, problem %> "See this exception on Errbit")
<% if notice = problem.notices.first %>
# <%= notice.message %> #
## Summary ##
diff --git a/app/views/issue_trackers/lighthouseapp_body.txt.erb b/app/views/issue_trackers/lighthouseapp_body.txt.erb
index 713711e..612047c 100644
--- a/app/views/issue_trackers/lighthouseapp_body.txt.erb
+++ b/app/views/issue_trackers/lighthouseapp_body.txt.erb
@@ -1,4 +1,4 @@
-[See this exception on Errbit](<%= app_err_url problem.app, problem %> "See this exception on Errbit")
+[See this exception on Errbit](<%= app_problem_url problem.app, problem %> "See this exception on Errbit")
<% if notice = problem.notices.first %>
# <%= notice.message %> #
## Summary ##
diff --git a/app/views/issue_trackers/pivotal_body.txt.erb b/app/views/issue_trackers/pivotal_body.txt.erb
index 5c9e6bd..b2fadc5 100644
--- a/app/views/issue_trackers/pivotal_body.txt.erb
+++ b/app/views/issue_trackers/pivotal_body.txt.erb
@@ -1,4 +1,4 @@
-See this exception on Errbit: <%= app_err_url problem.app, problem %>
+See this exception on Errbit: <%= app_problem_url problem.app, problem %>
<% if notice = problem.notices.first %>
<% if notice.request['url'].present? %>URL: <%= notice.request['url'] %><% end %>
Where: <%= notice.where %>
diff --git a/app/views/issue_trackers/textile_body.txt.erb b/app/views/issue_trackers/textile_body.txt.erb
index 82bd6fa..c65d886 100644
--- a/app/views/issue_trackers/textile_body.txt.erb
+++ b/app/views/issue_trackers/textile_body.txt.erb
@@ -1,7 +1,7 @@
<% if notice = problem.notices.first %>
h1. <%= notice.message %>
-h3. "See this exception on Errbit":<%= app_err_url problem.app, problem %>
+h3. "See this exception on Errbit":<%= app_problem_url problem.app, problem %>
h2. Summary
<% if notice.request['url'].present? %>
diff --git a/app/views/mailer/err_notification.html.haml b/app/views/mailer/err_notification.html.haml
index ea0103b..9884876 100644
--- a/app/views/mailer/err_notification.html.haml
+++ b/app/views/mailer/err_notification.html.haml
@@ -14,7 +14,7 @@
%br
This err has occurred #{pluralize @notice.problem.notices_count, 'time'}.
%p
- = link_to("Click here to view the error on Errbit", app_err_url(@app, @notice.problem), :class => "bold") << "."
+ = link_to("Click here to view the error on Errbit", app_problem_url(@app, @notice.problem), :class => "bold") << "."
%tr
%td.section
%table(cellpadding="0" cellspacing="0" border="0" align="left")
diff --git a/app/views/mailer/err_notification.text.erb b/app/views/mailer/err_notification.text.erb
index 33add18..22acf3e 100644
--- a/app/views/mailer/err_notification.text.erb
+++ b/app/views/mailer/err_notification.text.erb
@@ -2,7 +2,7 @@ An err has just occurred in <%= @notice.environment_name %>: <%= raw(@notice.mes
This err has occurred <%= pluralize @notice.problem.notices_count, 'time' %>. You should really look into it here:
- <%= app_err_url(@app, @notice.problem) %>
+ <%= app_problem_url(@app, @notice.problem) %>
ERROR MESSAGE:
diff --git a/app/views/problems/_issue_tracker_links.html.haml b/app/views/problems/_issue_tracker_links.html.haml
new file mode 100644
index 0000000..1f85327
--- /dev/null
+++ b/app/views/problems/_issue_tracker_links.html.haml
@@ -0,0 +1,15 @@
+- if @app.issue_tracker_configured? || current_user.github_account?
+ - if @problem.issue_link.present?
+ %span= link_to 'go to issue', @problem.issue_link, :class => "#{@problem.issue_type}_goto goto-issue"
+ = link_to 'unlink issue', unlink_issue_app_problem_path(@app, @problem), :method => :delete, :data => { :confirm => "Unlink err issues?" }, :class => "unlink-issue"
+ - elsif @problem.issue_link == "pending"
+ %span.disabled= link_to 'creating...', '#', :class => "#{@problem.issue_type}_inactive create-issue"
+ = link_to 'retry', create_issue_app_problem_path(@app, @problem), :method => :post
+ - else
+ - if @app.github_repo?
+ - if current_user.can_create_github_issues?
+ %span= link_to 'create issue', create_issue_app_problem_path(@app, @problem, :tracker => 'user_github'), :method => :post, :class => "github_create create-issue"
+ - elsif @app.issue_tracker_configured? && @app.issue_tracker.is_a?(GithubIssuesTracker)
+ %span= link_to 'create issue', create_issue_app_problem_path(@app, @problem), :method => :post, :class => "github_create create-issue"
+ - if @app.issue_tracker_configured? && !@app.issue_tracker.is_a?(GithubIssuesTracker)
+ %span= link_to 'create issue', create_issue_app_problem_path(@app, @problem), :method => :post, :class => "#{@app.issue_tracker.label}_create create-issue"
diff --git a/app/views/problems/_list.atom.builder b/app/views/problems/_list.atom.builder
new file mode 100644
index 0000000..4201144
--- /dev/null
+++ b/app/views/problems/_list.atom.builder
@@ -0,0 +1,15 @@
+feed.updated(@problems.first.try(:created_at) || Time.now)
+
+for problem in @problems
+ notice = problem.notices.first
+
+ feed.entry(problem, :url => app_problem_url(problem.app, problem)) do |entry|
+ entry.title "[#{ problem.where }] #{problem.message.to_s.truncate(27)}"
+ entry.author do |author|
+ author.name "#{ problem.app.name } [#{ problem.environment }]"
+ end
+ if notice
+ entry.summary(notice_atom_summary(notice), :type => "html")
+ end
+ end
+end
diff --git a/app/views/problems/_table.html.haml b/app/views/problems/_table.html.haml
new file mode 100644
index 0000000..2de89bf
--- /dev/null
+++ b/app/views/problems/_table.html.haml
@@ -0,0 +1,56 @@
+- any_issue_links = problems.any?{|e| e.issue_link.present? && e.issue_link != 'pending' }
+=form_tag do
+ %table.errs.selectable
+ %thead
+ %tr
+ %th= check_box_tag "toggle_problems_checkboxes"
+ %th= link_for_sort "App"
+ %th= link_for_sort "What & Where".html_safe, "message"
+ %th= link_for_sort "Latest", "last_notice_at"
+ %th= link_for_sort "Deploy", "last_deploy_at"
+ %th= link_for_sort "Count"
+ - if any_issue_links
+ %th Issue
+ %th Resolve
+ %tbody
+ - problems.each do |problem|
+ %tr{:class => problem.resolved? ? 'resolved' : 'unresolved'}
+ %td.select
+ = check_box_tag "problems[]", problem.id, @selected_problems.member?(problem.id.to_s)
+ %td.app
+ = link_to problem.app.name, app_path(problem.app)
+ - if current_page?(:controller => 'problems')
+ %span.environment= link_to problem.environment, problems_path(:environment => problem.environment)
+ - else
+ %span.environment= link_to problem.environment, app_path(problem.app, :environment => problem.environment)
+ %td.message
+ = link_to truncated_problem_message(problem), app_problem_path(problem.app, problem)
+ %em= problem.where
+ - if problem.comments_count > 0
+ - comment = problem.comments.last
+ %br
+ .inline_comment
+ - if comment.user
+ %em.commenter= (Errbit::Config.user_has_username ? comment.user.username : comment.user.email).to_s << ":"
+ %em= truncate(comment.body, :length => 100, :separator => ' ')
+ %td.latest #{time_ago_in_words(problem.last_notice_at)} ago
+ %td.deploy= problem.last_deploy_at ? problem.last_deploy_at.to_s(:micro) : 'n/a'
+ %td.count= link_to problem.notices_count, app_problem_path(problem.app, problem)
+ - if any_issue_links
+ %td.issue_link
+ - if problem.app.issue_tracker_configured? && problem.issue_link.present? && problem.issue_link != 'pending'
+ = link_to image_tag("#{problem.issue_type}_goto.png"), problem.issue_link, :target => "_blank"
+ %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?
+ - if problems.none?
+ %tr
+ %td{:colspan => (any_issue_links ? 8 : 7)}
+ %em No errs here
+ = paginate problems
+ .tab-bar
+ %ul
+ %li= submit_tag 'Merge', :id => 'merge_problems', :class => 'button', 'data-action' => merge_several_problems_path
+ %li= submit_tag 'Unmerge', :id => 'unmerge_problems', :class => 'button', 'data-action' => unmerge_several_problems_path
+ %li= submit_tag 'Resolve', :id => 'resolve_problems', :class => 'button', 'data-action' => resolve_several_problems_path
+ %li= submit_tag 'Unresolve', :id => 'unresolve_problems', :class => 'button', 'data-action' => unresolve_several_problems_path
+ %li= submit_tag 'Delete', :id => 'delete_problems', :class => 'button', 'data-action' => destroy_several_problems_path
+
diff --git a/app/views/problems/_tally_table.html.haml b/app/views/problems/_tally_table.html.haml
new file mode 100644
index 0000000..bd03ede
--- /dev/null
+++ b/app/views/problems/_tally_table.html.haml
@@ -0,0 +1,18 @@
+.head_and_tail
+ %table.tally.head
+ %tbody
+ - head(rows).each do |row|
+ %tr
+ %td.percent= number_to_percentage(row[0], :precision => 1)
+ %th.value= row[1]
+ - if rows.size > head_size
+ %tfoot
+ %tr
+ %td{:colspan => 2}
+ = link_to 'Show more...', '#', :class => :show_tail
+ %table.tally.tail{:style => "display: none"}
+ %tbody
+ - tail(rows).each do |row|
+ %tr
+ %td.percent= number_to_percentage(row[0], :precision => 1)
+ %th.value= row[1]
diff --git a/app/views/problems/all.html.haml b/app/views/problems/all.html.haml
new file mode 100644
index 0000000..3f6159e
--- /dev/null
+++ b/app/views/problems/all.html.haml
@@ -0,0 +1,4 @@
+- content_for :title, 'All Errors'
+- content_for :action_bar do
+ = link_to 'hide resolved', problems_path, :class => 'button'
+= render 'table', :problems => @problems
diff --git a/app/views/problems/index.atom.builder b/app/views/problems/index.atom.builder
new file mode 100644
index 0000000..aa0710b
--- /dev/null
+++ b/app/views/problems/index.atom.builder
@@ -0,0 +1,4 @@
+atom_feed do |feed|
+ feed.title("Errbit notices at #{root_url}")
+ render "problems/list", :feed => feed
+end
diff --git a/app/views/problems/index.html.haml b/app/views/problems/index.html.haml
new file mode 100644
index 0000000..74267b8
--- /dev/null
+++ b/app/views/problems/index.html.haml
@@ -0,0 +1,6 @@
+- content_for :title, 'Unresolved Errors'
+- content_for :head do
+ = auto_discovery_link_tag :atom, problems_path(User.token_authentication_key => current_user.authentication_token, :format => "atom"), :title => "Errbit notices at #{request.host}"
+- content_for :action_bar do
+ = link_to 'show resolved', all_problems_path, :class => 'button'
+= render 'table', :problems => @problems
diff --git a/app/views/problems/show.html.haml b/app/views/problems/show.html.haml
new file mode 100644
index 0000000..596964d
--- /dev/null
+++ b/app/views/problems/show.html.haml
@@ -0,0 +1,83 @@
+- content_for :page_title, @problem.message
+- content_for :title_css_class, 'err_show'
+- content_for :title, @problem.error_class || truncate(@problem.message, :length => 32)
+- content_for :meta do
+ %strong App:
+ = link_to @app.name, app_path(@app)
+ %strong Where:
+ = @problem.where
+ %br
+ %strong Environment:
+ = @problem.environment
+ %strong Last Notice:
+ = @problem.last_notice_at.to_s(:precise)
+- content_for :action_bar do
+ - if @problem.unresolved?
+ %span= link_to 'resolve', resolve_app_problem_path(@app, @problem), :method => :put, :data => { :confirm => problem_confirm }, :class => 'resolve'
+ - if current_user.authentication_token
+ %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"
+ %span>= link_to 'up', (request.env['HTTP_REFERER'] ? :back : app_problems_path(@app)), :class => 'up'
+ %br
+ = render "issue_tracker_links"
+
+- if Errbit::Config.allow_comments_with_issue_tracker || !@app.issue_tracker_configured? || @problem.comments.any?
+ - content_for :comments do
+ %h3 Comments
+ - @problem.comments.each do |comment|
+ .window
+ %table.comment
+ %tr
+ %th
+ - if Errbit::Config.use_gravatar
+ = gravatar_tag comment.user.email, :s => 24
+ %span.comment-info
+ = time_ago_in_words(comment.created_at, true) << " ago by "
+ = link_to comment.user.email, user_path(comment.user)
+ %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"
+ %tr
+ %td= comment.body.gsub("\n", "
").html_safe
+ - if Errbit::Config.allow_comments_with_issue_tracker || !@app.issue_tracker_configured?
+ = form_for @comment, :url => app_problem_comments_path(@app, @problem) do |comment_form|
+ %p Add a comment
+ = comment_form.text_area :body, :style => "width: 420px; height: 80px;"
+ = comment_form.submit "Save Comment"
+
+%h4= @notice.try(:message)
+
+= paginate @notices, :param_name => :notice, :theme => :notices
+
+.tab-bar
+ %ul
+ %li= link_to 'Summary', '#summary', :rel => 'summary', :class => 'button'
+ %li= link_to 'Backtrace', '#backtrace', :rel => 'backtrace', :class => 'button'
+ - if @notice && @notice.user_attributes.present?
+ %li= link_to 'User Details', '#user_attributes', :rel => 'user_attributes', :class => 'button'
+ %li= link_to 'Environment', '#environment', :rel => 'environment', :class => 'button'
+ %li= link_to 'Parameters', '#params', :rel => 'params', :class => 'button'
+ %li= link_to 'Session', '#session', :rel => 'session', :class => 'button'
+
+- if @notice
+ #summary
+ %h3 Summary
+ = render 'notices/summary', :notice => @notice, :problem => @problem
+
+ #backtrace
+ %h3 Backtrace
+ = render 'notices/backtrace', :lines => @notice.backtrace
+
+ - if @notice.user_attributes.present?
+ #user_attributes
+ %h3 User Details
+ = render 'notices/user_attributes', :user => @notice.user_attributes
+
+ #environment
+ %h3 Environment
+ = render 'notices/environment', :notice => @notice
+
+ #params
+ %h3 Parameters
+ = render 'notices/params', :notice => @notice
+
+ #session
+ %h3 Session
+ = render 'notices/session', :notice => @notice
diff --git a/app/views/problems/show.ics.haml b/app/views/problems/show.ics.haml
new file mode 100644
index 0000000..913dbf4
--- /dev/null
+++ b/app/views/problems/show.ics.haml
@@ -0,0 +1 @@
+= generate_problem_ical(@problem.notices.order_by(:created_at.asc))
diff --git a/app/views/shared/_navigation.html.haml b/app/views/shared/_navigation.html.haml
index 518f412..9e036a5 100644
--- a/app/views/shared/_navigation.html.haml
+++ b/app/views/shared/_navigation.html.haml
@@ -2,7 +2,7 @@
%ul
//%li= link_to 'Dashboard', admin_dashboard_path, :class => active_if_here(:dashboards)
%li.apps{:class => active_if_here(:apps)}= link_to 'Apps', apps_path
- %li.errs{:class => active_if_here(:errs)}= link_to 'Errors', errs_path
+ %li.errs{:class => active_if_here(:problems)}= link_to 'Errors', problems_path
- if user_signed_in? && current_user.admin?
%li.users{:class => active_if_here(:users)}= link_to 'Users', users_path
- %div.clear
\ No newline at end of file
+ %div.clear
diff --git a/config/routes.rb b/config/routes.rb
index fbdc652..5ff11a4 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -14,7 +14,7 @@ Errbit::Application.routes.draw do
delete :unlink_github
end
end
- resources :errs, :only => [:index] do
+ resources :problems, :only => [:index] do
collection do
post :destroy_several
post :resolve_several
@@ -26,7 +26,7 @@ Errbit::Application.routes.draw do
end
resources :apps do
- resources :errs do
+ resources :problems do
resources :notices
resources :comments, :only => [:create, :destroy]
@@ -37,7 +37,7 @@ Errbit::Application.routes.draw do
delete :unlink_issue
end
end
-
+
resources :deploys, :only => [:index]
end
@@ -46,7 +46,7 @@ Errbit::Application.routes.draw do
resources :problems, :only => [:index], :defaults => { :format => 'json' }
resources :notices, :only => [:index], :defaults => { :format => 'json' }
end
- end
+ end
root :to => 'apps#index'
diff --git a/spec/controllers/comments_controller_spec.rb b/spec/controllers/comments_controller_spec.rb
index 12a6cee..b1c74d7 100644
--- a/spec/controllers/comments_controller_spec.rb
+++ b/spec/controllers/comments_controller_spec.rb
@@ -16,7 +16,7 @@ describe CommentsController do
let(:user) { Fabricate(:user) }
before(:each) do
- post :create, :app_id => problem.app.id, :err_id => problem.id,
+ post :create, :app_id => problem.app.id, :problem_id => problem.id,
:comment => { :body => "One test comment", :user_id => user.id }
problem.reload
end
@@ -26,7 +26,7 @@ describe CommentsController do
end
it "should redirect to problem page" do
- response.should redirect_to( app_err_path(problem.app, problem) )
+ response.should redirect_to( app_problem_path(problem.app, problem) )
end
end
end
@@ -43,7 +43,7 @@ describe CommentsController do
let(:comment) { problem.reload.comments.first }
before(:each) do
- delete :destroy, :app_id => problem.app.id, :err_id => problem.id, :id => comment.id.to_s
+ delete :destroy, :app_id => problem.app.id, :problem_id => problem.id, :id => comment.id.to_s
problem.reload
end
@@ -52,7 +52,7 @@ describe CommentsController do
end
it "should redirect to problem page" do
- response.should redirect_to( app_err_path(problem.app, problem) )
+ response.should redirect_to( app_problem_path(problem.app, problem) )
end
end
end
diff --git a/spec/controllers/errs_controller_spec.rb b/spec/controllers/errs_controller_spec.rb
deleted file mode 100644
index 33a8136..0000000
--- a/spec/controllers/errs_controller_spec.rb
+++ /dev/null
@@ -1,441 +0,0 @@
-require 'spec_helper'
-
-describe ErrsController do
-
- it_requires_authentication :for => {
- :index => :get, :all => :get, :show => :get, :resolve => :put
- },
- :params => {:app_id => 'dummyid', :id => 'dummyid'}
-
- let(:app) { Fabricate(:app) }
- let(:err) { Fabricate(:err, :problem => Fabricate(:problem, :app => app, :environment => "production")) }
-
-
- describe "GET /errs" do
- render_views
- context 'when logged in as an admin' do
- before(:each) do
- @user = Fabricate(:admin)
- sign_in @user
- @problem = Fabricate(:notice, :err => Fabricate(:err, :problem => Fabricate(:problem, :app => app, :environment => "production"))).problem
- end
-
- it "should successfully list errs" do
- get :index
- response.should be_success
- response.body.gsub("", "").should match(@problem.message)
- end
-
- it "should list atom feed successfully" do
- get :index, :format => "atom"
- response.should be_success
- response.body.should match(@problem.message)
- end
-
- context "pagination" do
- before(:each) do
- 35.times { Fabricate :err }
- end
-
- it "should have default per_page value for user" do
- get :index
- assigns(:problems).to_a.size.should == User::PER_PAGE
- end
-
- it "should be able to override default per_page value" do
- @user.update_attribute :per_page, 10
- get :index
- assigns(:problems).to_a.size.should == 10
- end
- end
-
- context 'with environment filters' do
- before(:each) do
- environments = ['production', 'test', 'development', 'staging']
- 20.times do |i|
- Fabricate(:problem, :environment => environments[i % environments.length])
- end
- end
-
- context 'no params' do
- it 'shows errs for all environments' do
- get :index
- assigns(:problems).size.should == 21
- end
- end
-
- context 'environment production' do
- it 'shows errs for just production' do
- get :index, :environment => 'production'
- assigns(:problems).size.should == 6
- end
- end
-
- context 'environment staging' do
- it 'shows errs for just staging' do
- get :index, :environment => 'staging'
- assigns(:problems).size.should == 5
- end
- end
-
- context 'environment development' do
- it 'shows errs for just development' do
- get :index, :environment => 'development'
- assigns(:problems).size.should == 5
- end
- end
-
- context 'environment test' do
- it 'shows errs for just test' do
- get :index, :environment => 'test'
- assigns(:problems).size.should == 5
- end
- end
- end
- end
-
- context 'when logged in as a user' do
- it 'gets a paginated list of unresolved errs for the users apps' do
- sign_in(user = Fabricate(:user))
- unwatched_err = Fabricate(:err)
- watched_unresolved_err = Fabricate(:err, :problem => Fabricate(:problem, :app => Fabricate(:user_watcher, :user => user).app, :resolved => false))
- watched_resolved_err = Fabricate(:err, :problem => Fabricate(:problem, :app => Fabricate(:user_watcher, :user => user).app, :resolved => true))
- get :index
- assigns(:problems).should include(watched_unresolved_err.problem)
- assigns(:problems).should_not include(unwatched_err.problem, watched_resolved_err.problem)
- end
- end
- end
-
- describe "GET /errs/all" do
- context 'when logged in as an admin' do
- it "gets a paginated list of all errs" do
- sign_in Fabricate(:admin)
- errs = Kaminari.paginate_array((1..30).to_a)
- 3.times { errs << Fabricate(:err).problem }
- 3.times { errs << Fabricate(:err, :problem => Fabricate(:problem, :resolved => true)).problem }
- Problem.should_receive(:ordered_by).and_return(
- mock('proxy', :page => mock('other_proxy', :per => errs))
- )
- get :all
- assigns(:problems).should == errs
- end
- end
-
- context 'when logged in as a user' do
- it 'gets a paginated list of all errs for the users apps' do
- sign_in(user = Fabricate(:user))
- unwatched_err = Fabricate(:problem)
- watched_unresolved_err = Fabricate(:problem, :app => Fabricate(:user_watcher, :user => user).app, :resolved => false)
- watched_resolved_err = Fabricate(:problem, :app => Fabricate(:user_watcher, :user => user).app, :resolved => true)
- get :all
- assigns(:problems).should include(watched_resolved_err, watched_unresolved_err)
- assigns(:problems).should_not include(unwatched_err)
- end
- end
- end
-
- describe "GET /apps/:app_id/errs/:id" do
- render_views
-
- context 'when logged in as an admin' do
- before do
- sign_in Fabricate(:admin)
- end
-
- it "finds the app" do
- get :show, :app_id => app.id, :id => err.problem.id
- assigns(:app).should == app
- end
-
- it "finds the err" do
- get :show, :app_id => app.id, :id => err.problem.id
- assigns(:problem).should == err.problem
- end
-
- it "successfully render page" do
- get :show, :app_id => app.id, :id => err.problem.id
- response.should be_success
- end
-
- context 'pagination' do
- let!(:notices) do
- 3.times.reduce([]) do |coll, i|
- coll << Fabricate(:notice, :err => err, :created_at => (Time.now + i))
- end
- end
-
- it "paginates the notices 1 at a time, starting with the most recent" do
- get :show, :app_id => app.id, :id => err.problem.id
- assigns(:notices).entries.count.should == 1
- assigns(:notices).should include(notices.last)
- end
-
- it "paginates the notices 1 at a time, based on then notice param" do
- get :show, :app_id => app.id, :id => err.problem.id, :notice => 3
- assigns(:notices).entries.count.should == 1
- assigns(:notices).should include(notices.first)
- end
- end
-
- context "create issue button" do
- let(:button_matcher) { match(/create issue/) }
-
- it "should not exist for err's app without issue tracker" do
- err = Fabricate :err
- get :show, :app_id => err.app.id, :id => err.problem.id
-
- response.body.should_not button_matcher
- end
-
- it "should exist for err's app with issue tracker" do
- tracker = Fabricate(:lighthouse_tracker)
- err = Fabricate(:err, :problem => Fabricate(:problem, :app => tracker.app))
- get :show, :app_id => err.app.id, :id => err.problem.id
-
- response.body.should button_matcher
- end
-
- it "should not exist for err with issue_link" do
- tracker = Fabricate(:lighthouse_tracker)
- err = Fabricate(:err, :problem => Fabricate(:problem, :app => tracker.app, :issue_link => "http://some.host"))
- get :show, :app_id => err.app.id, :id => err.problem.id
-
- response.body.should_not button_matcher
- end
- end
- end
-
- context 'when logged in as a user' do
- before do
- sign_in(@user = Fabricate(:user))
- @unwatched_err = Fabricate(:err)
- @watched_app = Fabricate(:app)
- @watcher = Fabricate(:user_watcher, :user => @user, :app => @watched_app)
- @watched_err = Fabricate(:err, :problem => Fabricate(:problem, :app => @watched_app))
- end
-
- it 'finds the err if the user is watching the app' do
- get :show, :app_id => @watched_app.to_param, :id => @watched_err.problem.id
- assigns(:problem).should == @watched_err.problem
- end
-
- it 'raises a DocumentNotFound error if the user is not watching the app' do
- lambda {
- get :show, :app_id => @unwatched_err.problem.app_id, :id => @unwatched_err.problem.id
- }.should raise_error(Mongoid::Errors::DocumentNotFound)
- end
- end
- end
-
- describe "PUT /apps/:app_id/errs/:id/resolve" do
- before do
- sign_in Fabricate(:admin)
-
- @problem = Fabricate(:err)
- App.stub(:find).with(@problem.app.id).and_return(@problem.app)
- @problem.app.problems.stub(:find).and_return(@problem.problem)
- @problem.problem.stub(:resolve!)
- end
-
- it 'finds the app and the err' do
- App.should_receive(:find).with(@problem.app.id).and_return(@problem.app)
- @problem.app.problems.should_receive(:find).and_return(@problem.problem)
- put :resolve, :app_id => @problem.app.id, :id => @problem.problem.id
- assigns(:app).should == @problem.app
- assigns(:problem).should == @problem.problem
- end
-
- it "should resolve the issue" do
- @problem.problem.should_receive(:resolve!).and_return(true)
- put :resolve, :app_id => @problem.app.id, :id => @problem.problem.id
- end
-
- it "should display a message" do
- put :resolve, :app_id => @problem.app.id, :id => @problem.problem.id
- request.flash[:success].should match(/Great news/)
- end
-
- it "should redirect to the app page" do
- put :resolve, :app_id => @problem.app.id, :id => @problem.problem.id
- response.should redirect_to(app_path(@problem.app))
- end
-
- it "should redirect back to errs page" do
- request.env["Referer"] = errs_path
- put :resolve, :app_id => @problem.app.id, :id => @problem.problem.id
- response.should redirect_to(errs_path)
- end
- end
-
- describe "POST /apps/:app_id/errs/:id/create_issue" do
- render_views
-
- before(:each) do
- sign_in Fabricate(:admin)
- end
-
- context "successful issue creation" do
- context "lighthouseapp tracker" do
- let(:notice) { Fabricate :notice }
- let(:tracker) { Fabricate :lighthouse_tracker, :app => notice.app }
- let(:problem) { notice.problem }
-
- before(:each) do
- number = 5
- @issue_link = "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets/#{number}.xml"
- body = "#{number}"
- stub_request(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml").
- to_return(:status => 201, :headers => {'Location' => @issue_link}, :body => body )
-
- post :create_issue, :app_id => problem.app.id, :id => problem.id
- problem.reload
- end
-
- it "should redirect to problem page" do
- response.should redirect_to( app_err_path(problem.app, problem) )
- end
- end
- end
-
- context "absent issue tracker" do
- let(:problem) { Fabricate :problem }
-
- before(:each) do
- post :create_issue, :app_id => problem.app.id, :id => problem.id
- end
-
- it "should redirect to problem page" do
- response.should redirect_to( app_err_path(problem.app, problem) )
- end
-
- it "should set flash error message telling issue tracker of the app doesn't exist" do
- flash[:error].should == "This app has no issue tracker setup."
- end
- end
-
- context "error during request to a tracker" do
- context "lighthouseapp tracker" do
- let(:tracker) { Fabricate :lighthouse_tracker }
- let(:err) { Fabricate(:err, :problem => Fabricate(:problem, :app => tracker.app)) }
-
- before(:each) do
- stub_request(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml").to_return(:status => 500)
-
- post :create_issue, :app_id => err.app.id, :id => err.problem.id
- end
-
- it "should redirect to err page" do
- response.should redirect_to( app_err_path(err.app, err.problem) )
- end
-
- it "should notify of connection error" do
- flash[:error].should include("There was an error during issue creation:")
- end
- end
- end
- end
-
- describe "DELETE /apps/:app_id/errs/:id/unlink_issue" do
- before(:each) do
- sign_in Fabricate(:admin)
- end
-
- context "err with issue" do
- let(:err) { Fabricate(:err, :problem => Fabricate(:problem, :issue_link => "http://some.host")) }
-
- before(:each) do
- delete :unlink_issue, :app_id => err.app.id, :id => err.problem.id
- err.problem.reload
- end
-
- it "should redirect to err page" do
- response.should redirect_to( app_err_path(err.app, err.problem) )
- end
-
- it "should clear issue link" do
- err.problem.issue_link.should be_nil
- end
- end
-
- context "err without issue" do
- let(:err) { Fabricate :err }
-
- before(:each) do
- delete :unlink_issue, :app_id => err.app.id, :id => err.problem.id
- err.problem.reload
- end
-
- it "should redirect to err page" do
- response.should redirect_to( app_err_path(err.app, err.problem) )
- end
- end
- end
-
- describe "Bulk Actions" do
- before(:each) do
- sign_in Fabricate(:admin)
- @problem1 = Fabricate(:err, :problem => Fabricate(:problem, :resolved => true)).problem
- @problem2 = Fabricate(:err, :problem => Fabricate(:problem, :resolved => false)).problem
- end
-
- it "should apply to multiple problems" do
- post :resolve_several, :problems => [@problem1.id.to_s, @problem2.id.to_s]
- assigns(:selected_problems).should == [@problem1, @problem2]
- end
-
- it "should require at least one problem" do
- post :resolve_several, :problems => []
- request.flash[:notice].should match(/You have not selected any/)
- end
-
- context "POST /errs/merge_several" do
- it "should require at least two problems" do
- post :merge_several, :problems => [@problem1.id.to_s]
- request.flash[:notice].should match(/You must select at least two/)
- end
-
- it "should merge the problems" do
- lambda {
- post :merge_several, :problems => [@problem1.id.to_s, @problem2.id.to_s]
- assigns(:merged_problem).reload.errs.length.should == 2
- }.should change(Problem, :count).by(-1)
- end
- end
-
- context "POST /errs/unmerge_several" do
- it "should unmerge a merged problem" do
- merged_problem = Problem.merge!(@problem1, @problem2)
- merged_problem.errs.length.should == 2
- lambda {
- post :unmerge_several, :problems => [merged_problem.id.to_s]
- merged_problem.reload.errs.length.should == 1
- }.should change(Problem, :count).by(1)
- end
- end
-
- context "POST /errs/resolve_several" do
- it "should resolve the issue" do
- post :resolve_several, :problems => [@problem2.id.to_s]
- @problem2.reload.resolved?.should == true
- end
- end
-
- context "POST /errs/unresolve_several" do
- it "should unresolve the issue" do
- post :unresolve_several, :problems => [@problem1.id.to_s]
- @problem1.reload.resolved?.should == false
- end
- end
-
- context "POST /errs/destroy_several" do
- it "should delete the errs" do
- lambda {
- post :destroy_several, :problems => [@problem1.id.to_s]
- }.should change(Problem, :count).by(-1)
- end
- end
- end
-
-end
-
diff --git a/spec/controllers/notices_controller_spec.rb b/spec/controllers/notices_controller_spec.rb
index be32eb1..31820dd 100644
--- a/spec/controllers/notices_controller_spec.rb
+++ b/spec/controllers/notices_controller_spec.rb
@@ -68,7 +68,7 @@ describe NoticesController do
problem = Fabricate(:problem, :app => app, :environment => "production")
notice = Fabricate(:notice, :err => Fabricate(:err, :problem => problem))
get :locate, :id => notice.id
- response.should redirect_to(app_err_path(problem.app, problem))
+ response.should redirect_to(app_problem_path(problem.app, problem))
end
end
end
diff --git a/spec/controllers/problems_controller_spec.rb b/spec/controllers/problems_controller_spec.rb
new file mode 100644
index 0000000..f024d29
--- /dev/null
+++ b/spec/controllers/problems_controller_spec.rb
@@ -0,0 +1,441 @@
+require 'spec_helper'
+
+describe ProblemsController do
+
+ it_requires_authentication :for => {
+ :index => :get, :all => :get, :show => :get, :resolve => :put
+ },
+ :params => {:app_id => 'dummyid', :id => 'dummyid'}
+
+ let(:app) { Fabricate(:app) }
+ let(:err) { Fabricate(:err, :problem => Fabricate(:problem, :app => app, :environment => "production")) }
+
+
+ describe "GET /problems" do
+ render_views
+ context 'when logged in as an admin' do
+ before(:each) do
+ @user = Fabricate(:admin)
+ sign_in @user
+ @problem = Fabricate(:notice, :err => Fabricate(:err, :problem => Fabricate(:problem, :app => app, :environment => "production"))).problem
+ end
+
+ it "should successfully list problems" do
+ get :index
+ response.should be_success
+ response.body.gsub("", "").should match(@problem.message)
+ end
+
+ it "should list atom feed successfully" do
+ get :index, :format => "atom"
+ response.should be_success
+ response.body.should match(@problem.message)
+ end
+
+ context "pagination" do
+ before(:each) do
+ 35.times { Fabricate :err }
+ end
+
+ it "should have default per_page value for user" do
+ get :index
+ assigns(:problems).to_a.size.should == User::PER_PAGE
+ end
+
+ it "should be able to override default per_page value" do
+ @user.update_attribute :per_page, 10
+ get :index
+ assigns(:problems).to_a.size.should == 10
+ end
+ end
+
+ context 'with environment filters' do
+ before(:each) do
+ environments = ['production', 'test', 'development', 'staging']
+ 20.times do |i|
+ Fabricate(:problem, :environment => environments[i % environments.length])
+ end
+ end
+
+ context 'no params' do
+ it 'shows problems for all environments' do
+ get :index
+ assigns(:problems).size.should == 21
+ end
+ end
+
+ context 'environment production' do
+ it 'shows problems for just production' do
+ get :index, :environment => 'production'
+ assigns(:problems).size.should == 6
+ end
+ end
+
+ context 'environment staging' do
+ it 'shows problems for just staging' do
+ get :index, :environment => 'staging'
+ assigns(:problems).size.should == 5
+ end
+ end
+
+ context 'environment development' do
+ it 'shows problems for just development' do
+ get :index, :environment => 'development'
+ assigns(:problems).size.should == 5
+ end
+ end
+
+ context 'environment test' do
+ it 'shows problems for just test' do
+ get :index, :environment => 'test'
+ assigns(:problems).size.should == 5
+ end
+ end
+ end
+ end
+
+ context 'when logged in as a user' do
+ it 'gets a paginated list of unresolved problems for the users apps' do
+ sign_in(user = Fabricate(:user))
+ unwatched_err = Fabricate(:err)
+ watched_unresolved_err = Fabricate(:err, :problem => Fabricate(:problem, :app => Fabricate(:user_watcher, :user => user).app, :resolved => false))
+ watched_resolved_err = Fabricate(:err, :problem => Fabricate(:problem, :app => Fabricate(:user_watcher, :user => user).app, :resolved => true))
+ get :index
+ assigns(:problems).should include(watched_unresolved_err.problem)
+ assigns(:problems).should_not include(unwatched_err.problem, watched_resolved_err.problem)
+ end
+ end
+ end
+
+ describe "GET /problems/all" do
+ context 'when logged in as an admin' do
+ it "gets a paginated list of all problems" do
+ sign_in Fabricate(:admin)
+ problems = Kaminari.paginate_array((1..30).to_a)
+ 3.times { problems << Fabricate(:err).problem }
+ 3.times { problems << Fabricate(:err, :problem => Fabricate(:problem, :resolved => true)).problem }
+ Problem.should_receive(:ordered_by).and_return(
+ mock('proxy', :page => mock('other_proxy', :per => problems))
+ )
+ get :all
+ assigns(:problems).should == problems
+ end
+ end
+
+ context 'when logged in as a user' do
+ it 'gets a paginated list of all problems for the users apps' do
+ sign_in(user = Fabricate(:user))
+ unwatched_problem = Fabricate(:problem)
+ watched_unresolved_problem = Fabricate(:problem, :app => Fabricate(:user_watcher, :user => user).app, :resolved => false)
+ watched_resolved_problem = Fabricate(:problem, :app => Fabricate(:user_watcher, :user => user).app, :resolved => true)
+ get :all
+ assigns(:problems).should include(watched_resolved_problem, watched_unresolved_problem)
+ assigns(:problems).should_not include(unwatched_problem)
+ end
+ end
+ end
+
+ describe "GET /apps/:app_id/problems/:id" do
+ render_views
+
+ context 'when logged in as an admin' do
+ before do
+ sign_in Fabricate(:admin)
+ end
+
+ it "finds the app" do
+ get :show, :app_id => app.id, :id => err.problem.id
+ assigns(:app).should == app
+ end
+
+ it "finds the problem" do
+ get :show, :app_id => app.id, :id => err.problem.id
+ assigns(:problem).should == err.problem
+ end
+
+ it "successfully render page" do
+ get :show, :app_id => app.id, :id => err.problem.id
+ response.should be_success
+ end
+
+ context 'pagination' do
+ let!(:notices) do
+ 3.times.reduce([]) do |coll, i|
+ coll << Fabricate(:notice, :err => err, :created_at => (Time.now + i))
+ end
+ end
+
+ it "paginates the notices 1 at a time, starting with the most recent" do
+ get :show, :app_id => app.id, :id => err.problem.id
+ assigns(:notices).entries.count.should == 1
+ assigns(:notices).should include(notices.last)
+ end
+
+ it "paginates the notices 1 at a time, based on then notice param" do
+ get :show, :app_id => app.id, :id => err.problem.id, :notice => 3
+ assigns(:notices).entries.count.should == 1
+ assigns(:notices).should include(notices.first)
+ end
+ end
+
+ context "create issue button" do
+ let(:button_matcher) { match(/create issue/) }
+
+ it "should not exist for problem's app without issue tracker" do
+ err = Fabricate :err
+ get :show, :app_id => err.app.id, :id => err.problem.id
+
+ response.body.should_not button_matcher
+ end
+
+ it "should exist for problem's app with issue tracker" do
+ tracker = Fabricate(:lighthouse_tracker)
+ err = Fabricate(:err, :problem => Fabricate(:problem, :app => tracker.app))
+ get :show, :app_id => err.app.id, :id => err.problem.id
+
+ response.body.should button_matcher
+ end
+
+ it "should not exist for problem with issue_link" do
+ tracker = Fabricate(:lighthouse_tracker)
+ err = Fabricate(:err, :problem => Fabricate(:problem, :app => tracker.app, :issue_link => "http://some.host"))
+ get :show, :app_id => err.app.id, :id => err.problem.id
+
+ response.body.should_not button_matcher
+ end
+ end
+ end
+
+ context 'when logged in as a user' do
+ before do
+ sign_in(@user = Fabricate(:user))
+ @unwatched_err = Fabricate(:err)
+ @watched_app = Fabricate(:app)
+ @watcher = Fabricate(:user_watcher, :user => @user, :app => @watched_app)
+ @watched_err = Fabricate(:err, :problem => Fabricate(:problem, :app => @watched_app))
+ end
+
+ it 'finds the problem if the user is watching the app' do
+ get :show, :app_id => @watched_app.to_param, :id => @watched_err.problem.id
+ assigns(:problem).should == @watched_err.problem
+ end
+
+ it 'raises a DocumentNotFound error if the user is not watching the app' do
+ lambda {
+ get :show, :app_id => @unwatched_err.problem.app_id, :id => @unwatched_err.problem.id
+ }.should raise_error(Mongoid::Errors::DocumentNotFound)
+ end
+ end
+ end
+
+ describe "PUT /apps/:app_id/problems/:id/resolve" do
+ before do
+ sign_in Fabricate(:admin)
+
+ @problem = Fabricate(:err)
+ App.stub(:find).with(@problem.app.id).and_return(@problem.app)
+ @problem.app.problems.stub(:find).and_return(@problem.problem)
+ @problem.problem.stub(:resolve!)
+ end
+
+ it 'finds the app and the problem' do
+ App.should_receive(:find).with(@problem.app.id).and_return(@problem.app)
+ @problem.app.problems.should_receive(:find).and_return(@problem.problem)
+ put :resolve, :app_id => @problem.app.id, :id => @problem.problem.id
+ assigns(:app).should == @problem.app
+ assigns(:problem).should == @problem.problem
+ end
+
+ it "should resolve the issue" do
+ @problem.problem.should_receive(:resolve!).and_return(true)
+ put :resolve, :app_id => @problem.app.id, :id => @problem.problem.id
+ end
+
+ it "should display a message" do
+ put :resolve, :app_id => @problem.app.id, :id => @problem.problem.id
+ request.flash[:success].should match(/Great news/)
+ end
+
+ it "should redirect to the app page" do
+ put :resolve, :app_id => @problem.app.id, :id => @problem.problem.id
+ response.should redirect_to(app_path(@problem.app))
+ end
+
+ it "should redirect back to problems page" do
+ request.env["Referer"] = problems_path
+ put :resolve, :app_id => @problem.app.id, :id => @problem.problem.id
+ response.should redirect_to(problems_path)
+ end
+ end
+
+ describe "POST /apps/:app_id/problems/:id/create_issue" do
+ render_views
+
+ before(:each) do
+ sign_in Fabricate(:admin)
+ end
+
+ context "successful issue creation" do
+ context "lighthouseapp tracker" do
+ let(:notice) { Fabricate :notice }
+ let(:tracker) { Fabricate :lighthouse_tracker, :app => notice.app }
+ let(:problem) { notice.problem }
+
+ before(:each) do
+ number = 5
+ @issue_link = "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets/#{number}.xml"
+ body = "#{number}"
+ stub_request(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml").
+ to_return(:status => 201, :headers => {'Location' => @issue_link}, :body => body )
+
+ post :create_issue, :app_id => problem.app.id, :id => problem.id
+ problem.reload
+ end
+
+ it "should redirect to problem page" do
+ response.should redirect_to( app_problem_path(problem.app, problem) )
+ end
+ end
+ end
+
+ context "absent issue tracker" do
+ let(:problem) { Fabricate :problem }
+
+ before(:each) do
+ post :create_issue, :app_id => problem.app.id, :id => problem.id
+ end
+
+ it "should redirect to problem page" do
+ response.should redirect_to( app_problem_path(problem.app, problem) )
+ end
+
+ it "should set flash error message telling issue tracker of the app doesn't exist" do
+ flash[:error].should == "This app has no issue tracker setup."
+ end
+ end
+
+ context "error during request to a tracker" do
+ context "lighthouseapp tracker" do
+ let(:tracker) { Fabricate :lighthouse_tracker }
+ let(:err) { Fabricate(:err, :problem => Fabricate(:problem, :app => tracker.app)) }
+
+ before(:each) do
+ stub_request(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml").to_return(:status => 500)
+
+ post :create_issue, :app_id => err.app.id, :id => err.problem.id
+ end
+
+ it "should redirect to problem page" do
+ response.should redirect_to( app_problem_path(err.app, err.problem) )
+ end
+
+ it "should notify of connection error" do
+ flash[:error].should include("There was an error during issue creation:")
+ end
+ end
+ end
+ end
+
+ describe "DELETE /apps/:app_id/problems/:id/unlink_issue" do
+ before(:each) do
+ sign_in Fabricate(:admin)
+ end
+
+ context "problem with issue" do
+ let(:err) { Fabricate(:err, :problem => Fabricate(:problem, :issue_link => "http://some.host")) }
+
+ before(:each) do
+ delete :unlink_issue, :app_id => err.app.id, :id => err.problem.id
+ err.problem.reload
+ end
+
+ it "should redirect to problem page" do
+ response.should redirect_to( app_problem_path(err.app, err.problem) )
+ end
+
+ it "should clear issue link" do
+ err.problem.issue_link.should be_nil
+ end
+ end
+
+ context "err without issue" do
+ let(:err) { Fabricate :err }
+
+ before(:each) do
+ delete :unlink_issue, :app_id => err.app.id, :id => err.problem.id
+ err.problem.reload
+ end
+
+ it "should redirect to problem page" do
+ response.should redirect_to( app_problem_path(err.app, err.problem) )
+ end
+ end
+ end
+
+ describe "Bulk Actions" do
+ before(:each) do
+ sign_in Fabricate(:admin)
+ @problem1 = Fabricate(:err, :problem => Fabricate(:problem, :resolved => true)).problem
+ @problem2 = Fabricate(:err, :problem => Fabricate(:problem, :resolved => false)).problem
+ end
+
+ it "should apply to multiple problems" do
+ post :resolve_several, :problems => [@problem1.id.to_s, @problem2.id.to_s]
+ assigns(:selected_problems).should == [@problem1, @problem2]
+ end
+
+ it "should require at least one problem" do
+ post :resolve_several, :problems => []
+ request.flash[:notice].should match(/You have not selected any/)
+ end
+
+ context "POST /problems/merge_several" do
+ it "should require at least two problems" do
+ post :merge_several, :problems => [@problem1.id.to_s]
+ request.flash[:notice].should match(/You must select at least two/)
+ end
+
+ it "should merge the problems" do
+ lambda {
+ post :merge_several, :problems => [@problem1.id.to_s, @problem2.id.to_s]
+ assigns(:merged_problem).reload.errs.length.should == 2
+ }.should change(Problem, :count).by(-1)
+ end
+ end
+
+ context "POST /problems/unmerge_several" do
+ it "should unmerge a merged problem" do
+ merged_problem = Problem.merge!(@problem1, @problem2)
+ merged_problem.errs.length.should == 2
+ lambda {
+ post :unmerge_several, :problems => [merged_problem.id.to_s]
+ merged_problem.reload.errs.length.should == 1
+ }.should change(Problem, :count).by(1)
+ end
+ end
+
+ context "POST /problems/resolve_several" do
+ it "should resolve the issue" do
+ post :resolve_several, :problems => [@problem2.id.to_s]
+ @problem2.reload.resolved?.should == true
+ end
+ end
+
+ context "POST /problems/unresolve_several" do
+ it "should unresolve the issue" do
+ post :unresolve_several, :problems => [@problem1.id.to_s]
+ @problem1.reload.resolved?.should == false
+ end
+ end
+
+ context "POST /problems/destroy_several" do
+ it "should delete the problems" do
+ lambda {
+ post :destroy_several, :problems => [@problem1.id.to_s]
+ }.should change(Problem, :count).by(-1)
+ end
+ end
+ end
+
+end
+
diff --git a/spec/helpers/errs_helper_spec.rb b/spec/helpers/errs_helper_spec.rb
deleted file mode 100644
index c4b8731..0000000
--- a/spec/helpers/errs_helper_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-require 'spec_helper'
-
-describe ErrsHelper do
- describe '#truncated_err_message' do
- it 'is html safe' do
- problem = double('problem', :message => '#')
- truncated = helper.truncated_err_message(problem)
- truncated.should be_html_safe
- truncated.should_not include('<', '>')
- end
- end
-
- describe "#gravatar_tag" do
- let(:email) { "gravatar@example.com" }
- let(:email_hash) { Digest::MD5.hexdigest email }
- let(:base_url) { "http://www.gravatar.com/avatar/#{email_hash}" }
-
- context "default config" do
- before do
- Errbit::Config.stub(:use_gravatar).and_return(true)
- Errbit::Config.stub(:gravatar_default).and_return('identicon')
- end
-
- it "should render image_tag with correct alt and src" do
- expected = "
"
- helper.gravatar_tag(email, :s => 48).should eq(expected)
- end
-
- it "should override :d" do
- expected = "
"
- helper.gravatar_tag(email, :d => 'retro', :s => 48).should eq(expected)
- end
- end
- end
-end
diff --git a/spec/helpers/problems_helper_spec.rb b/spec/helpers/problems_helper_spec.rb
new file mode 100644
index 0000000..5c20c6d
--- /dev/null
+++ b/spec/helpers/problems_helper_spec.rb
@@ -0,0 +1,35 @@
+require 'spec_helper'
+
+describe ProblemsHelper do
+ describe '#truncated_problem_message' do
+ it 'is html safe' do
+ problem = double('problem', :message => '#')
+ truncated = helper.truncated_problem_message(problem)
+ truncated.should be_html_safe
+ truncated.should_not include('<', '>')
+ end
+ end
+
+ describe "#gravatar_tag" do
+ let(:email) { "gravatar@example.com" }
+ let(:email_hash) { Digest::MD5.hexdigest email }
+ let(:base_url) { "http://www.gravatar.com/avatar/#{email_hash}" }
+
+ context "default config" do
+ before do
+ Errbit::Config.stub(:use_gravatar).and_return(true)
+ Errbit::Config.stub(:gravatar_default).and_return('identicon')
+ end
+
+ it "should render image_tag with correct alt and src" do
+ expected = "
"
+ helper.gravatar_tag(email, :s => 48).should eq(expected)
+ end
+
+ it "should override :d" do
+ expected = "
"
+ helper.gravatar_tag(email, :d => 'retro', :s => 48).should eq(expected)
+ end
+ end
+ end
+end
diff --git a/spec/views/errs/show.html.haml_spec.rb b/spec/views/errs/show.html.haml_spec.rb
deleted file mode 100644
index 4f00bcc..0000000
--- a/spec/views/errs/show.html.haml_spec.rb
+++ /dev/null
@@ -1,128 +0,0 @@
-require 'spec_helper'
-
-describe "errs/show.html.haml" do
- before do
- err = Fabricate(:err)
- problem = err.problem
- comment = Fabricate(:comment)
- assign :problem, problem
- assign :comment, comment
- assign :app, problem.app
- assign :notices, err.notices.page(1).per(1)
- assign :notice, err.notices.first
- controller.stub(:current_user) { Fabricate(:user) }
- end
-
- def with_issue_tracker(tracker, problem)
- problem.app.issue_tracker = tracker.new :api_token => "token token token", :project_id => "1234"
- assign :problem, problem
- assign :app, problem.app
- end
-
- describe "content_for :action_bar" do
- def action_bar
- view.content_for(:action_bar)
- end
-
- it "should confirm the 'resolve' link by default" do
- render
-
- action_bar.should have_selector('a.resolve[data-confirm="Seriously?"]')
- end
-
- it "should confirm the 'resolve' link if configuration is unset" do
- Errbit::Config.stub(:confirm_resolve_err).and_return(nil)
- render
-
- action_bar.should have_selector('a.resolve[data-confirm="Seriously?"]')
- end
-
- it "should not confirm the 'resolve' link if configured not to" do
- Errbit::Config.stub(:confirm_resolve_err).and_return(false)
- render
-
- action_bar.should have_selector('a.resolve[data-confirm="null"]')
- end
-
- it "should link 'up' to HTTP_REFERER if is set" do
- url = 'http://localhost:3000/errs'
- controller.request.env['HTTP_REFERER'] = url
- render
-
- action_bar.should have_selector("span a.up[href='#{url}']", :text => 'up')
- end
-
- it "should link 'up' to app_errs_path if HTTP_REFERER isn't set'" do
- controller.request.env['HTTP_REFERER'] = nil
- problem = Fabricate(:problem_with_comments)
- assign :problem, problem
- assign :app, problem.app
- render
-
- action_bar.should have_selector("span a.up[href='#{app_errs_path(problem.app)}']", :text => 'up')
- end
-
- context 'create issue links' do
- it 'should allow creating issue for github if current user has linked their github account' do
- user = Fabricate(:user, :github_login => 'test_user', :github_oauth_token => 'abcdef')
- controller.stub(:current_user) { user }
-
- problem = Fabricate(:problem_with_comments, :app => Fabricate(:app, :github_repo => "test_user/test_repo"))
- assign :problem, problem
- assign :app, problem.app
- render
-
- action_bar.should have_selector("span a.github_create.create-issue", :text => 'create issue')
- end
-
- it 'should allow creating issue for github if application has a github tracker' do
- problem = Fabricate(:problem_with_comments, :app => Fabricate(:app, :github_repo => "test_user/test_repo"))
- with_issue_tracker(GithubIssuesTracker, problem)
- assign :problem, problem
- assign :app, problem.app
- render
-
- action_bar.should have_selector("span a.github_create.create-issue", :text => 'create issue')
- end
- end
- end
-
- describe "content_for :comments with comments disabled for configured issue tracker" do
- before do
- Errbit::Config.stub(:allow_comments_with_issue_tracker).and_return(false)
- Errbit::Config.stub(:use_gravatar).and_return(true)
- end
-
- it 'should display comments and new comment form when no issue tracker' do
- problem = Fabricate(:problem_with_comments)
- assign :problem, problem
- assign :app, problem.app
- render
-
- view.content_for(:comments).should include('Test comment')
- view.content_for(:comments).should have_selector('img[src^="http://www.gravatar.com/avatar"]')
- view.content_for(:comments).should include('Add a comment')
- end
-
- context "with issue tracker" do
- it 'should not display the comments section' do
- problem = Fabricate(:problem)
- with_issue_tracker(PivotalLabsTracker, problem)
- render
- view.view_flow.get(:comments).should be_blank
- end
-
- it 'should display existing comments' do
- problem = Fabricate(:problem_with_comments)
- problem.reload
- with_issue_tracker(PivotalLabsTracker, problem)
- render
-
- view.content_for(:comments).should include('Test comment')
- view.content_for(:comments).should have_selector('img[src^="http://www.gravatar.com/avatar"]')
- view.content_for(:comments).should_not include('Add a comment')
- end
- end
- end
-end
-
diff --git a/spec/views/problems/show.html.haml_spec.rb b/spec/views/problems/show.html.haml_spec.rb
new file mode 100644
index 0000000..6a1e305
--- /dev/null
+++ b/spec/views/problems/show.html.haml_spec.rb
@@ -0,0 +1,127 @@
+require 'spec_helper'
+
+describe "problems/show.html.haml" do
+ before do
+ problem = Fabricate(:problem)
+ comment = Fabricate(:comment)
+ assign :problem, problem
+ assign :comment, comment
+ assign :app, problem.app
+ assign :notices, problem.notices.page(1).per(1)
+ assign :notice, problem.notices.first
+ controller.stub(:current_user) { Fabricate(:user) }
+ end
+
+ def with_issue_tracker(tracker, problem)
+ problem.app.issue_tracker = tracker.new :api_token => "token token token", :project_id => "1234"
+ assign :problem, problem
+ assign :app, problem.app
+ end
+
+ describe "content_for :action_bar" do
+ def action_bar
+ view.content_for(:action_bar)
+ end
+
+ it "should confirm the 'resolve' link by default" do
+ render
+
+ action_bar.should have_selector('a.resolve[data-confirm="Seriously?"]')
+ end
+
+ it "should confirm the 'resolve' link if configuration is unset" do
+ Errbit::Config.stub(:confirm_resolve_err).and_return(nil)
+ render
+
+ action_bar.should have_selector('a.resolve[data-confirm="Seriously?"]')
+ end
+
+ it "should not confirm the 'resolve' link if configured not to" do
+ Errbit::Config.stub(:confirm_resolve_err).and_return(false)
+ render
+
+ action_bar.should have_selector('a.resolve[data-confirm="null"]')
+ end
+
+ it "should link 'up' to HTTP_REFERER if is set" do
+ url = 'http://localhost:3000/problems'
+ controller.request.env['HTTP_REFERER'] = url
+ render
+
+ action_bar.should have_selector("span a.up[href='#{url}']", :text => 'up')
+ end
+
+ it "should link 'up' to app_problems_path if HTTP_REFERER isn't set'" do
+ controller.request.env['HTTP_REFERER'] = nil
+ problem = Fabricate(:problem_with_comments)
+ assign :problem, problem
+ assign :app, problem.app
+ render
+
+ action_bar.should have_selector("span a.up[href='#{app_problems_path(problem.app)}']", :text => 'up')
+ end
+
+ context 'create issue links' do
+ it 'should allow creating issue for github if current user has linked their github account' do
+ user = Fabricate(:user, :github_login => 'test_user', :github_oauth_token => 'abcdef')
+ controller.stub(:current_user) { user }
+
+ problem = Fabricate(:problem_with_comments, :app => Fabricate(:app, :github_repo => "test_user/test_repo"))
+ assign :problem, problem
+ assign :app, problem.app
+ render
+
+ action_bar.should have_selector("span a.github_create.create-issue", :text => 'create issue')
+ end
+
+ it 'should allow creating issue for github if application has a github tracker' do
+ problem = Fabricate(:problem_with_comments, :app => Fabricate(:app, :github_repo => "test_user/test_repo"))
+ with_issue_tracker(GithubIssuesTracker, problem)
+ assign :problem, problem
+ assign :app, problem.app
+ render
+
+ action_bar.should have_selector("span a.github_create.create-issue", :text => 'create issue')
+ end
+ end
+ end
+
+ describe "content_for :comments with comments disabled for configured issue tracker" do
+ before do
+ Errbit::Config.stub(:allow_comments_with_issue_tracker).and_return(false)
+ Errbit::Config.stub(:use_gravatar).and_return(true)
+ end
+
+ it 'should display comments and new comment form when no issue tracker' do
+ problem = Fabricate(:problem_with_comments)
+ assign :problem, problem
+ assign :app, problem.app
+ render
+
+ view.content_for(:comments).should include('Test comment')
+ view.content_for(:comments).should have_selector('img[src^="http://www.gravatar.com/avatar"]')
+ view.content_for(:comments).should include('Add a comment')
+ end
+
+ context "with issue tracker" do
+ it 'should not display the comments section' do
+ problem = Fabricate(:problem)
+ with_issue_tracker(PivotalLabsTracker, problem)
+ render
+ view.view_flow.get(:comments).should be_blank
+ end
+
+ it 'should display existing comments' do
+ problem = Fabricate(:problem_with_comments)
+ problem.reload
+ with_issue_tracker(PivotalLabsTracker, problem)
+ render
+
+ view.content_for(:comments).should include('Test comment')
+ view.content_for(:comments).should have_selector('img[src^="http://www.gravatar.com/avatar"]')
+ view.content_for(:comments).should_not include('Add a comment')
+ end
+ end
+ end
+end
+
--
libgit2 0.21.2