Commit 042904910794ba34b459b6cfe9a01575e84e38ec

Authored by Cyril Mougel
2 parents f2e95433 c7507da1
Exists in master and in 1 other branch production

Merge pull request #521 from shingara/refactor/problem_controller

Refactor/problem controller
.gitignore
... ... @@ -18,3 +18,4 @@ bin
18 18 bundle
19 19 coverage
20 20 *#
  21 +.ruby-version
... ...
Gemfile
... ... @@ -11,7 +11,6 @@ gem 'htmlentities'
11 11 gem 'rack-ssl', :require => 'rack/ssl' # force SSL
12 12  
13 13 gem 'useragent'
14   -gem 'inherited_resources'
15 14 gem 'decent_exposure'
16 15 gem 'strong_parameters'
17 16 gem 'SystemTimer', :platform => :ruby_18
... ...
Gemfile.lock
... ... @@ -123,6 +123,7 @@ GEM
123 123 multipart-post (~> 1.1)
124 124 faraday_middleware (0.8.8)
125 125 faraday (>= 0.7.4, < 0.9)
  126 + ffi (1.9.0)
126 127 flowdock (0.3.1)
127 128 httparty (~> 0.7)
128 129 multi_json
... ... @@ -133,7 +134,6 @@ GEM
133 134 tilt
134 135 happymapper (0.4.0)
135 136 libxml-ruby (~> 2.0)
136   - has_scope (0.5.1)
137 137 hashie (1.2.0)
138 138 highline (1.6.19)
139 139 hike (1.2.3)
... ... @@ -151,9 +151,6 @@ GEM
151 151 multi_xml (>= 0.5.2)
152 152 httpauth (0.2.0)
153 153 i18n (0.6.1)
154   - inherited_resources (1.4.0)
155   - has_scope (~> 0.5.0)
156   - responders (~> 0.9)
157 154 journey (1.0.4)
158 155 jquery-rails (2.1.4)
159 156 railties (>= 3.0, < 5.0)
... ... @@ -288,8 +285,6 @@ GEM
288 285 rdoc (3.12.2)
289 286 json (~> 1.4)
290 287 ref (1.0.5)
291   - responders (0.9.3)
292   - railties (~> 3.1)
293 288 rest-client (1.6.7)
294 289 mime-types (>= 1.16)
295 290 ri_cal (0.8.8)
... ... @@ -412,7 +407,6 @@ DEPENDENCIES
412 407 hoptoad_notifier (~> 2.4)
413 408 htmlentities
414 409 httparty
415   - inherited_resources
416 410 jquery-rails (~> 2.1.4)
417 411 kaminari (>= 0.14.1)
418 412 launchy
... ...
app/controllers/apps_controller.rb
1   -class AppsController < InheritedResources::Base
  1 +class AppsController < ApplicationController
  2 +
  3 + include ProblemsSearcher
  4 +
2 5 before_filter :require_admin!, :except => [:index, :show]
3 6 before_filter :parse_email_at_notices_or_set_default, :only => [:create, :update]
4 7 before_filter :parse_notice_at_notices_or_set_default, :only => [:create, :update]
5 8 respond_to :html
6 9  
7   - def show
8   - respond_to do |format|
9   - format.html do
10   - @all_errs = !!params[:all_errs]
  10 + expose(:app_scope) {
  11 + (current_user.admin? ? App : current_user.apps)
  12 + }
  13 +
  14 + expose(:apps) {
  15 + app_scope.all.sort
  16 + }
  17 +
  18 + expose(:app, :ancestor => :app_scope)
  19 +
  20 + expose(:all_errs) {
  21 + !!params[:all_errs]
  22 + }
  23 + expose(:problems) {
  24 + if request.format == :atom
  25 + app.problems.unresolved.ordered
  26 + else
  27 + pr = app.problems
  28 + pr = pr.unresolved unless all_errs
  29 + pr.in_env(
  30 + params[:environment]
  31 + ).ordered_by(params_sort, params_order).page(params[:page]).per(current_user.per_page)
  32 + end
  33 + }
11 34  
12   - @sort = params[:sort]
13   - @order = params[:order]
14   - @sort = "last_notice_at" unless %w{message app last_deploy_at last_notice_at count}.member?(@sort)
15   - @order = "desc" unless %w{asc desc}.member?(@order)
  35 + expose(:deploys) {
  36 + app.deploys.order_by(:created_at.desc).limit(5)
  37 + }
16 38  
17   - @problems = resource.problems
18   - @problems = @problems.unresolved unless @all_errs
19   - @problems = @problems.in_env(params[:environment]).ordered_by(@sort, @order).page(params[:page]).per(current_user.per_page)
  39 + def index; end
  40 + def show
  41 + app
  42 + end
20 43  
21   - @selected_problems = params[:problems] || []
22   - @deploys = @app.deploys.order_by(:created_at.desc).limit(5)
23   - end
24   - format.atom do
25   - @problems = resource.problems.unresolved.ordered
26   - end
27   - end
  44 + def new
  45 + plug_params(app)
28 46 end
29 47  
30 48 def create
31   - @app = App.new(params[:app])
32 49 initialize_subclassed_issue_tracker
33 50 initialize_subclassed_notification_service
34   - create!
  51 + if app.save
  52 + redirect_to app_url(app), :flash => { :success => I18n.t('controllers.apps.flash.create.success') }
  53 + else
  54 + flash[:error] = I18n.t('controllers.apps.flash.create.error')
  55 + render :new
  56 + end
35 57 end
36 58  
37 59 def update
38   - @app = resource
39 60 initialize_subclassed_issue_tracker
40 61 initialize_subclassed_notification_service
41   - update!
  62 + if app.save
  63 + redirect_to app_url(app), :flash => { :success => I18n.t('controllers.apps.flash.update.success') }
  64 + else
  65 + flash[:error] = I18n.t('controllers.apps.flash.update.error')
  66 + render :edit
  67 + end
42 68 end
43 69  
44   - def new
45   - plug_params(build_resource)
46   - new!
  70 + def edit
  71 + plug_params(app)
47 72 end
48 73  
49   - def edit
50   - plug_params(resource)
51   - edit!
  74 + def destroy
  75 + if app.destroy
  76 + redirect_to apps_url, :flash => { :success => I18n.t('controllers.apps.flash.destroy.success') }
  77 + else
  78 + flash[:error] = I18n.t('controllers.apps.flash.destroy.error')
  79 + render :show
  80 + end
52 81 end
53 82  
54 83 protected
55   - def collection
56   - @apps ||= end_of_association_chain.all.sort
57   - end
58 84  
59 85 def initialize_subclassed_issue_tracker
60 86 # set the app's issue tracker
61 87 if params[:app][:issue_tracker_attributes] && tracker_type = params[:app][:issue_tracker_attributes][:type]
62 88 if IssueTracker.subclasses.map(&:name).concat(["IssueTracker"]).include?(tracker_type)
63   - @app.issue_tracker = tracker_type.constantize.new(params[:app][:issue_tracker_attributes])
  89 + app.issue_tracker = tracker_type.constantize.new(params[:app][:issue_tracker_attributes])
64 90 end
65 91 end
66 92 end
... ... @@ -69,21 +95,11 @@ class AppsController &lt; InheritedResources::Base
69 95 # set the app's notification service
70 96 if params[:app][:notification_service_attributes] && notification_type = params[:app][:notification_service_attributes][:type]
71 97 if NotificationService.subclasses.map(&:name).concat(["NotificationService"]).include?(notification_type)
72   - @app.notification_service = notification_type.constantize.new(params[:app][:notification_service_attributes])
  98 + app.notification_service = notification_type.constantize.new(params[:app][:notification_service_attributes])
73 99 end
74 100 end
75 101 end
76 102  
77   - def begin_of_association_chain
78   - # Filter the @apps collection to apps watched by the current user, unless user is an admin.
79   - # If user is an admin, then no filter is applied, and all apps are shown.
80   - current_user unless current_user.admin?
81   - end
82   -
83   - def interpolation_options
84   - {:app_name => resource.name}
85   - end
86   -
87 103 def plug_params app
88 104 app.watchers.build if app.watchers.none?
89 105 app.issue_tracker = IssueTracker.new unless app.issue_tracker_configured?
... ...
app/controllers/problems_controller.rb
  1 +##
  2 +# Manage problems
  3 +#
  4 +# List of actions available :
  5 +# MEMBER => :show, :edit, :update, :create, :destroy, :resolve, :unresolve, :create_issue, :unlink_issue
  6 +# COLLECTION => :index, :all, :destroy_several, :resolve_several, :unresolve_several, :merge_several, :unmerge_several, :search
1 7 class ProblemsController < ApplicationController
2   - before_filter :find_app, :except => [:index, :all, :destroy_several, :resolve_several, :unresolve_several, :merge_several, :unmerge_several, :search]
3   - before_filter :find_problem, :except => [:index, :all, :destroy_several, :resolve_several, :unresolve_several, :merge_several, :unmerge_several, :search]
4   - before_filter :find_selected_problems, :only => [:destroy_several, :resolve_several, :unresolve_several, :merge_several, :unmerge_several]
5   - before_filter :set_sorting_params, :only => [:index, :all, :search]
6   - before_filter :set_tracker_params, :only => [:create_issue]
7   -
8   - def index
9   - app_scope = current_user.admin? ? App.all : current_user.apps
10   - @all_errs = params[:all_errs]
11   - @problems = Problem.for_apps(app_scope).in_env(params[:environment]).all_else_unresolved(@all_errs).ordered_by(@sort, @order)
12   - @selected_problems = params[:problems] || []
13   - respond_to do |format|
14   - format.html do
15   - @problems = @problems.page(params[:page]).per(current_user.per_page)
16   - end
17   - format.atom
  8 +
  9 +
  10 + include ProblemsSearcher
  11 +
  12 + before_filter :need_selected_problem, :only => [
  13 + :resolve_several, :unresolve_several, :unmerge_several
  14 + ]
  15 +
  16 + expose(:app) {
  17 + if current_user.admin?
  18 + App.find(params[:app_id])
  19 + else
  20 + current_user.apps.find(params[:app_id])
18 21 end
19   - end
  22 + }
  23 +
  24 + expose(:problem) {
  25 + app.problems.find(params[:id])
  26 + }
  27 +
  28 +
  29 + expose(:all_errs) {
  30 + params[:all_errs]
  31 + }
  32 +
  33 + expose(:app_scope) {
  34 + apps = current_user.admin? ? App.all : current_user.apps
  35 + params[:app_id] ? apps.where(:_id => params[:app_id]) : apps
  36 + }
  37 +
  38 + expose(:params_environement) {
  39 + params[:environment]
  40 + }
  41 +
  42 + expose(:problems) {
  43 + pro = Problem.for_apps(
  44 + app_scope
  45 + ).in_env(
  46 + params_environement
  47 + ).all_else_unresolved(all_errs).ordered_by(params_sort, params_order)
  48 +
  49 + if request.format == :html
  50 + pro.page(params[:page]).per(current_user.per_page)
  51 + else
  52 + pro
  53 + end
  54 + }
  55 +
  56 + def index; end
20 57  
21 58 def show
22   - @notices = @problem.notices.reverse_ordered.page(params[:notice]).per(1)
  59 + @notices = problem.notices.reverse_ordered.page(params[:notice]).per(1)
23 60 @notice = @notices.first
24 61 @comment = Comment.new
25 62 end
26 63  
27 64 def create_issue
28   - issue_creation = IssueCreation.new(@problem, current_user, params[:tracker])
  65 + IssueTracker.update_url_options(request)
  66 + issue_creation = IssueCreation.new(problem, current_user, params[:tracker])
29 67  
30 68 unless issue_creation.execute
31   - flash[:error] = issue_creation.errors[:base].first
  69 + flash[:error] = issue_creation.errors.full_messages.join(', ')
32 70 end
33 71  
34   - redirect_to app_problem_path(@app, @problem)
  72 + redirect_to app_problem_path(app, problem)
35 73 end
36 74  
37 75 def unlink_issue
38   - @problem.update_attribute :issue_link, nil
39   - redirect_to app_problem_path(@app, @problem)
  76 + problem.update_attribute :issue_link, nil
  77 + redirect_to app_problem_path(app, problem)
40 78 end
41 79  
42 80 def resolve
43   - @problem.resolve!
  81 + problem.resolve!
44 82 flash[:success] = 'Great news everyone! The err has been resolved.'
45 83 redirect_to :back
46 84 rescue ActionController::RedirectBackError
47   - redirect_to app_path(@app)
  85 + redirect_to app_path(app)
48 86 end
49 87  
50 88 def resolve_several
51   - @selected_problems.each(&:resolve!)
52   - flash[:success] = "Great news everyone! #{I18n.t(:n_errs_have, :count => @selected_problems.count)} been resolved."
  89 + selected_problems.each(&:resolve!)
  90 + flash[:success] = "Great news everyone! #{I18n.t(:n_errs_have, :count => selected_problems.count)} been resolved."
53 91 redirect_to :back
54 92 end
55 93  
56 94 def unresolve_several
57   - @selected_problems.each(&:unresolve!)
58   - flash[:success] = "#{I18n.t(:n_errs_have, :count => @selected_problems.count)} been unresolved."
  95 + selected_problems.each(&:unresolve!)
  96 + flash[:success] = "#{I18n.t(:n_errs_have, :count => selected_problems.count)} been unresolved."
59 97 redirect_to :back
60 98 end
61 99  
  100 + ##
  101 + # Action to merge several Problem in One problem
  102 + #
  103 + # @param [ Array<String> ] :problems the list of problem ids
  104 + #
62 105 def merge_several
63   - if @selected_problems.length < 2
64   - flash[:notice] = "You must select at least two errors to merge"
  106 + if selected_problems.length < 2
  107 + flash[:notice] = I18n.t('controllers.problems.flash.need_two_errors_merge')
65 108 else
66   - @merged_problem = Problem.merge!(@selected_problems)
67   - flash[:notice] = "#{@selected_problems.count} errors have been merged."
  109 + ProblemMerge.new(selected_problems).merge
  110 + flash[:notice] = I18n.t('controllers.problems.flash.merge_several.success', :nb => selected_problems.count)
68 111 end
69 112 redirect_to :back
70 113 end
71 114  
72 115 def unmerge_several
73   - all = @selected_problems.map(&:unmerge!).flatten
  116 + all = selected_problems.map(&:unmerge!).flatten
74 117 flash[:success] = "#{I18n.t(:n_errs_have, :count => all.length)} been unmerged."
75 118 redirect_to :back
76 119 end
77 120  
78 121 def destroy_several
79   - nb_problem_destroy = ProblemDestroy.execute(@selected_problems)
  122 + nb_problem_destroy = ProblemDestroy.execute(selected_problems)
80 123 flash[:notice] = "#{I18n.t(:n_errs_have, :count => nb_problem_destroy)} been deleted."
81 124 redirect_to :back
82 125 end
83 126  
84 127 def search
85   - if params[:app_id]
86   - app_scope = App.where(:_id => params[:app_id])
87   - else
88   - app_scope = current_user.admin? ? App.all : current_user.apps
89   - end
90   - @problems = Problem.search(params[:search]).for_apps(app_scope).in_env(params[:environment]).all_else_unresolved(params[:all_errs]).ordered_by(@sort, @order)
  128 + @problems = Problem.search(params[:search]).for_apps(app_scope).in_env(params[:environment]).all_else_unresolved(params[:all_errs]).ordered_by(params_sort, params_order)
91 129 @selected_problems = params[:problems] || []
92 130 @problems = @problems.page(params[:page]).per(current_user.per_page)
93 131 render :content_type => 'text/javascript'
94 132 end
95 133  
96 134 protected
97   - def find_app
98   - @app = App.find(params[:app_id])
99   -
100   - # Mongoid Bug: could not chain: current_user.apps.find_by_id!
101   - # apparently finding by 'watchers.email' and 'id' is broken
102   - raise(Mongoid::Errors::DocumentNotFound.new(App,@app.id)) unless current_user.admin? || current_user.watching?(@app)
103   - end
104 135  
105   - def find_problem
106   - @problem = @app.problems.find(params[:id])
107   - end
108   -
109   - def set_tracker_params
110   - IssueTracker.default_url_options[:host] = request.host
111   - IssueTracker.default_url_options[:port] = request.port
112   - IssueTracker.default_url_options[:protocol] = request.scheme
113   - end
114   -
115   - def find_selected_problems
116   - err_ids = (params[:problems] || []).compact
117   - if err_ids.empty?
118   - flash[:notice] = "You have not selected any errors"
119   - redirect_to :back
120   - else
121   - @selected_problems = Array(Problem.find(err_ids))
122   - end
123   - end
124   -
125   - def set_sorting_params
126   - @sort = params[:sort]
127   - @sort = "last_notice_at" unless %w{app message last_notice_at last_deploy_at count}.member?(@sort)
128   - @order = params[:order] || "desc"
  136 + ##
  137 + # Redirect :back if no errors selected
  138 + #
  139 + def need_selected_problem
  140 + if err_ids.empty?
  141 + flash[:notice] = I18n.t('controllers.problems.flash.no_select_problem')
  142 + redirect_to :back
129 143 end
  144 + end
130 145 end
131 146  
... ...
app/controllers/problems_searcher.rb 0 → 100644
... ... @@ -0,0 +1,34 @@
  1 +# Include to do a Search
  2 +# TODO: Need to be in a Dedicated Object ProblemsSearch with params like input
  3 +#
  4 +module ProblemsSearcher
  5 + extend ActiveSupport::Concern
  6 +
  7 + included do
  8 +
  9 + expose(:params_sort) {
  10 + unless %w{app message last_notice_at last_deploy_at count}.member?(params[:sort])
  11 + "last_notice_at"
  12 + else
  13 + params[:sort]
  14 + end
  15 + }
  16 +
  17 + expose(:params_order){
  18 + unless %w{asc desc}.member?(params[:order])
  19 + 'desc'
  20 + else
  21 + params[:order]
  22 + end
  23 + }
  24 +
  25 + expose(:selected_problems) {
  26 + Array(Problem.find(err_ids))
  27 + }
  28 +
  29 + expose(:err_ids) {
  30 + (params[:problems] || []).compact
  31 + }
  32 +
  33 + end
  34 +end
... ...
app/helpers/apps_helper.rb
... ... @@ -41,7 +41,7 @@ module AppsHelper
41 41 def detect_any_apps_with_attributes
42 42 @any_github_repos = @any_issue_trackers = @any_deploys = @any_bitbucket_repos = @any_notification_services = false
43 43  
44   - @apps.each do |app|
  44 + apps.each do |app|
45 45 @any_github_repos ||= app.github_repo?
46 46 @any_bitbucket_repos ||= app.bitbucket_repo?
47 47 @any_issue_trackers ||= app.issue_tracker_configured?
... ...
app/helpers/sort_helper.rb
1 1 # encoding: utf-8
2 2 module SortHelper
3   -
  3 +
4 4 def link_for_sort(name, field=nil)
5 5 field ||= name.underscore
6   - current = (@sort == field)
7   - order = (current && (@order == "asc")) ? "desc" : "asc"
  6 + current = (params_sort == field)
  7 + order = (current && (params_order == "asc")) ? "desc" : "asc"
8 8 url = request.path + "?sort=#{field}&order=#{order}"
9 9 options = {}
10 10 options.merge!(:class => "current #{order}") if current
11 11 link_to(name, url, options)
12 12 end
13   -
  13 +
14 14 end
... ...
app/interactors/issue_creation.rb
... ... @@ -41,15 +41,11 @@ class IssueCreation
41 41 end
42 42  
43 43 def execute
44   - if tracker
45   - begin
46   - tracker.create_issue problem, user
47   - rescue => ex
48   - Rails.logger.error "Error during issue creation: " << ex.message
49   - errors.add :base, "There was an error during issue creation: #{ex.message}"
50   - end
51   - end
52   -
  44 + tracker.create_issue problem, user if tracker
53 45 errors.empty?
  46 + rescue => ex
  47 + Rails.logger.error "Error during issue creation: " << ex.message
  48 + errors.add :base, "There was an error during issue creation: #{ex.message}"
  49 + false
54 50 end
55 51 end
... ...
app/models/issue_tracker.rb
... ... @@ -40,4 +40,15 @@ class IssueTracker
40 40 def configured?
41 41 project_id.present?
42 42 end
  43 +
  44 + ##
  45 + # Update default_url_option with valid data from the request information
  46 + #
  47 + # @param [ Request ] a request with host, port and protocol
  48 + #
  49 + def self.update_url_options(request)
  50 + IssueTracker.default_url_options[:host] = request.host
  51 + IssueTracker.default_url_options[:port] = request.port
  52 + IssueTracker.default_url_options[:protocol] = request.scheme
  53 + end
43 54 end
... ...
app/views/apps/_fields.html.haml
1   -= errors_for @app
  1 += errors_for app
2 2  
3 3 %div.required
4 4 = f.label :name
... ...
app/views/apps/edit.html.haml
1 1 - content_for :title, 'Edit App'
2 2 - content_for :action_bar do
3 3 = link_to_copy_attributes_from_other_app
4   - = link_to 'destroy application', app_path(@app), :method => :delete, :data => { :confirm => 'Seriously?' }, :class => 'button'
5   - = link_to('cancel', app_path(@app), :class => 'button')
  4 + = link_to 'destroy application', app_path(app), :method => :delete, :data => { :confirm => 'Seriously?' }, :class => 'button'
  5 + = link_to('cancel', app_path(app), :class => 'button')
6 6  
7   -= form_for @app do |f|
  7 += form_for app do |f|
8 8  
9 9 = render 'fields', :f => f
10 10  
... ...
app/views/apps/index.html.haml
... ... @@ -16,7 +16,7 @@
16 16 %th Last Deploy
17 17 %th Errors
18 18 %tbody
19   - - @apps.each do |app|
  19 + - apps.each do |app|
20 20 %tr
21 21 %td.name= link_to app.name, app_path(app)
22 22 - if any_github_repos? or any_bitbucket_repos?
... ... @@ -50,7 +50,7 @@
50 50 - if app.problem_count > 0
51 51 - unresolved = app.unresolved_count
52 52 = link_to unresolved, app_path(app), :class => (unresolved == 0 ? "resolved" : nil)
53   - - if @apps.none?
  53 + - if apps.none?
54 54 %tr
55 55 %td{:colspan => 3}
56 56 %em
... ...
app/views/apps/new.html.haml
... ... @@ -3,7 +3,7 @@
3 3 = link_to_copy_attributes_from_other_app
4 4 = link_to('cancel', apps_path, :class => 'button')
5 5  
6   -= form_for @app do |f|
  6 += form_for app do |f|
7 7  
8 8 = render 'fields', :f => f
9 9  
... ...
app/views/apps/show.atom.builder
1 1 atom_feed do |feed|
2   - feed.title("Errbit notices for #{h @app.name} at #{root_url}")
  2 + feed.title("Errbit notices for #{h app.name} at #{root_url}")
3 3 render "problems/list", :feed => feed
4 4 end
... ...
app/views/apps/show.html.haml
1   -- content_for :title, @app.name
  1 +- content_for :title, app.name
2 2 - content_for :head do
3   - = auto_discovery_link_tag :atom, app_path(@app, User.token_authentication_key => current_user.authentication_token, :format => "atom"), :title => "Errbit notices for #{@app.name} at #{request.host}"
  3 + = auto_discovery_link_tag :atom, app_path(app, User.token_authentication_key => current_user.authentication_token, :format => "atom"), :title => "Errbit notices for #{app.name} at #{request.host}"
4 4 - content_for :meta do
5 5 %strong Errors Caught:
6   - = @app.problems.count
  6 + = app.problems.count
7 7 %strong Deploy Count:
8   - = @app.deploys.count
  8 + = app.deploys.count
9 9 %strong API Key:
10   - = @app.api_key
  10 + = app.api_key
11 11 - content_for :action_bar do
12 12 - if current_user.admin?
13   - = link_to 'edit', edit_app_path(@app), :class => 'button'
14   - - if @all_errs
15   - = link_to 'unresolved errs', app_path(@app), :class => 'button'
  13 + = link_to 'edit', edit_app_path(app), :class => 'button'
  14 + - if all_errs
  15 + = link_to 'unresolved errs', app_path(app), :class => 'button'
16 16 - else
17   - = link_to 'all errs', app_path(@app, :all_errs => true), :class => 'button'
  17 + = link_to 'all errs', app_path(app, :all_errs => true), :class => 'button'
18 18  
19 19 %h3#watchers_toggle
20 20 Watchers
21 21 %span.click_span (show/hide)
22 22 #watchers_div
23   - - if @app.notify_all_users
  23 + - if app.notify_all_users
24 24 %table.watchers
25 25 %thead
26 26 %tr
... ... @@ -31,15 +31,15 @@
31 31 %tr
32 32 %th User or Email
33 33 %tbody
34   - - @app.watchers.each do |watcher|
  34 + - app.watchers.each do |watcher|
35 35 %tr
36 36 %td= watcher.label
37   - - if @app.watchers.none?
  37 + - if app.watchers.none?
38 38 %tr
39 39 %td
40 40 %em Sadly, no one is watching this app
41 41  
42   -- if @app.github_repo?
  42 +- if app.github_repo?
43 43 %h3#repository_toggle
44 44 Repository
45 45 %span.click_span (show/hide)
... ... @@ -50,13 +50,13 @@
50 50 %th GitHub Repo
51 51 %tbody
52 52 %tr
53   - %td= link_to(@app.github_repo, @app.github_url, :target => '_blank')
  53 + %td= link_to(app.github_repo, app.github_url, :target => '_blank')
54 54  
55 55 %h3#deploys_toggle
56 56 Latest Deploys
57 57 %span.click_span (show/hide)
58 58 #deploys_div
59   - - if @deploys.any?
  59 + - if deploys.any?
60 60 %table.deploys
61 61 %thead
62 62 %tr
... ... @@ -68,7 +68,7 @@
68 68 %th Revision
69 69  
70 70 %tbody
71   - - @deploys.each do |deploy|
  71 + - deploys.each do |deploy|
72 72 %tr
73 73 %td.when #{deploy.created_at.to_s(:micro)}
74 74 %td.environment #{deploy.environment}
... ... @@ -76,20 +76,20 @@
76 76 %td.message #{deploy.message}
77 77 %td.repository #{deploy.repository}
78 78 %td.revision #{deploy.short_revision}
79   - = link_to "All Deploys (#{@app.deploys.count})", app_deploys_path(@app), :class => 'button'
  79 + = link_to "All Deploys (#{app.deploys.count})", app_deploys_path(app), :class => 'button'
80 80 - else
81 81 %h3 No deploys
82 82  
83   -- if @app.problems.any?
  83 +- if app.problems.any?
84 84 %h3.clear Errors
85 85 %section
86   - = form_tag search_problems_path(:all_errs => @all_errs, :app_id => @app.id), :method => :get, :remote => true do
  86 + = form_tag search_problems_path(:all_errs => all_errs, :app_id => app.id), :method => :get, :remote => true do
87 87 = text_field_tag :search, params[:search], :placeholder => 'Search for issues'
88 88 %br
89 89 %section
90 90 .problem_table{:id => 'problem_table'}
91   - = render 'problems/table', :problems => @problems
  91 + = render 'problems/table', :problems => problems
92 92 - else
93 93 %h3.clear No errs have been caught yet, make sure you setup your app
94   - = render 'configuration_instructions', :app => @app
  94 + = render 'configuration_instructions', :app => app
95 95  
... ...
app/views/problems/_issue_tracker_links.html.haml
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
  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 8 - else
9   - - if @app.github_repo?
  9 + - if app.github_repo?
10 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.label.eql?('github')
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.label.eql?('github')
15   - %span= link_to 'create issue', create_issue_app_problem_path(@app, @problem), :method => :post, :class => "#{@app.issue_tracker.label}_create create-issue"
  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.label.eql?('github')
  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.label.eql?('github')
  15 + %span= link_to 'create issue', create_issue_app_problem_path(app, problem), :method => :post, :class => "#{app.issue_tracker.label}_create create-issue"
... ...
app/views/problems/_list.atom.builder
1   -feed.updated(@problems.first.try(:created_at) || Time.now)
  1 +feed.updated(problems.first.try(:created_at) || Time.now)
2 2  
3   -for problem in @problems
  3 +for problem in problems
4 4 notice = problem.notices.first
5 5  
6   - feed.entry(problem, :url => app_problem_url(problem.app, problem)) do |entry|
  6 + feed.entry(problem, :url => app_problem_url(problem.app.to_param, problem.to_param)) do |entry|
7 7 entry.title "[#{ problem.where }] #{problem.message.to_s.truncate(27)}"
8 8 entry.author do |author|
9 9 author.name "#{ problem.app.name } [#{ problem.environment }]"
... ...
app/views/problems/_table.html.haml
... ... @@ -16,7 +16,7 @@
16 16 - problems.each do |problem|
17 17 %tr{:class => problem.resolved? ? 'resolved' : 'unresolved'}
18 18 %td.select
19   - = check_box_tag "problems[]", problem.id, @selected_problems.member?(problem.id.to_s)
  19 + = check_box_tag "problems[]", problem.id, selected_problems.member?(problem.id.to_s)
20 20 %td.app
21 21 = link_to problem.app.name, app_path(problem.app)
22 22 - if current_page?(:controller => 'problems')
... ...
app/views/problems/index.html.haml
1 1 - content_for :title, @all_errs ? 'All Errors' : 'Unresolved Errors'
2 2 - content_for :head do
3 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 +
4 5 - content_for :action_bar do
5 6 - if @all_errs
6 7 = link_to 'hide resolved', problems_path, :class => 'button'
7 8 - else
8 9 = link_to 'show resolved', problems_path(:all_errs => true), :class => 'button'
  10 +
9 11 %section
10 12 = form_tag search_problems_path(:all_errs => @all_errs), :method => :get, :remote => true do
11 13 = text_field_tag :search, params[:search], :placeholder => 'Search for issues'
12 14 %br
13 15 %section
14   - .problem_table{:id => 'problem_table'}
15   - = render 'problems/table', :problems => @problems
  16 + #problem_table.problem_table
  17 + = render 'problems/table'
... ...
app/views/problems/show.html.haml
1   -- content_for :page_title, @problem.message
  1 +- content_for :page_title, problem.message
2 2 - content_for :title_css_class, 'err_show'
3   -- content_for :title, @problem.error_class || truncate(@problem.message, :length => 32)
  3 +- content_for :title, problem.error_class || truncate(problem.message, :length => 32)
4 4 - content_for :meta do
5 5 %strong App:
6   - = link_to @app.name, @app
  6 + = link_to app.name, app
7 7 %strong Where:
8   - = @problem.where
  8 + = problem.where
9 9 %br
10 10 %strong Environment:
11   - = @problem.environment
  11 + = problem.environment
12 12 %strong Last Notice:
13   - = @problem.last_notice_at.to_s(:precise)
  13 + = problem.last_notice_at.to_s(:precise)
14 14 - content_for :action_bar do
15   - - if @problem.unresolved?
16   - %span= link_to 'resolve', [:resolve, @app, @problem], :method => :put, :data => { :confirm => problem_confirm }, :class => 'resolve'
  15 + - if problem.unresolved?
  16 + %span= link_to 'resolve', [:resolve, app, problem], :method => :put, :data => { :confirm => problem_confirm }, :class => 'resolve'
17 17 - if current_user.authentication_token
18   - %span= link_to 'iCal', polymorphic_path([@app, @problem], :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'
  18 + %span= link_to 'iCal', polymorphic_path([app, problem], :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 20 %br
21 21 = render "issue_tracker_links"
22 22  
23   -- if @problem.comments_allowed? || @problem.comments.any?
  23 +- if problem.comments_allowed? || problem.comments.any?
24 24 - content_for :comments do
25 25 %h3 Comments
26   - - @problem.comments.each do |comment|
  26 + - problem.comments.each do |comment|
27 27 .window
28 28 %table.comment
29 29 %tr
... ... @@ -37,11 +37,11 @@
37 37 - else
38 38 %span.comment-info
39 39 = time_ago_in_words(comment.created_at, true) << " ago by [Unknown User]"
40   - %span.delete= link_to '&#10008;'.html_safe, [@app, @problem, comment], :method => :delete, :data => { :confirm => "Are you sure you don't need this comment?" }, :class => "destroy-comment"
  40 + %span.delete= link_to '&#10008;'.html_safe, [app, problem, comment], :method => :delete, :data => { :confirm => "Are you sure you don't need this comment?" }, :class => "destroy-comment"
41 41 %tr
42 42 %td= simple_format comment.body
43   - - if @problem.comments_allowed?
44   - = form_for [@app, @problem, @comment] do |comment_form|
  43 + - if problem.comments_allowed?
  44 + = form_for [app, problem, @comment] do |comment_form|
45 45 %p Add a comment
46 46 = comment_form.text_area :body
47 47 = comment_form.submit "Save Comment"
... ... @@ -63,7 +63,7 @@
63 63 - if @notice
64 64 #summary
65 65 %h3 Summary
66   - = render 'notices/summary', :notice => @notice, :problem => @problem
  66 + = render 'notices/summary', :notice => @notice
67 67  
68 68 #backtrace
69 69 %h3 Backtrace
... ...
app/views/problems/show.ics.haml
1   -= generate_problem_ical(@problem.notices.order_by(:created_at.asc))
  1 += generate_problem_ical(problem.notices.order_by(:created_at.asc))
... ...
config/initializers/inherited_resources.rb
... ... @@ -1,2 +0,0 @@
1   -InheritedResources.flash_keys = [:success, :error]
2   -
config/locales/en.yml
... ... @@ -2,7 +2,6 @@
2 2 # See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
3 3  
4 4 en:
5   - hello: "Hello world"
6 5 flash:
7 6 apps:
8 7 create:
... ... @@ -11,6 +10,7 @@ en:
11 10 success: "Good news everyone! '%{app_name}' was successfully updated."
12 11 destroy:
13 12 success: "'%{app_name}' was successfully destroyed."
  13 +
14 14 n_errs_have:
15 15 one: "%{count} err has"
16 16 other: "%{count} errs have"
... ... @@ -31,6 +31,18 @@ en:
31 31 edit_profile: 'Edit profile'
32 32  
33 33 controllers:
  34 + apps:
  35 + flash:
  36 + create:
  37 + success: "Your app was successfully created."
  38 + error: "You app was successfully destroyed."
  39 + update:
  40 + success: "You app was successfully updated."
  41 + error: "You app was not updated"
  42 + destroy:
  43 + success: "You app was successfully destroyed."
  44 + error: "You app could not be destroyed."
  45 +
34 46 users:
35 47 flash:
36 48 destroy:
... ... @@ -38,6 +50,13 @@ en:
38 50 error: "You can't delete yourself"
39 51 update:
40 52 success: "%{name}'s information was successfully updated."
  53 + problems:
  54 + flash:
  55 + no_select_problem: "You have not selected any errors"
  56 + need_two_errors_merge: "You must select at least two errors to merge"
  57 + merge_several:
  58 + success: "%{nb} errors have been merged."
  59 +
41 60  
42 61 devise:
43 62 registrations:
... ...
spec/controllers/apps_controller_spec.rb
... ... @@ -6,15 +6,13 @@ describe AppsController do
6 6 it_requires_authentication
7 7 it_requires_admin_privileges :for => {:new => :get, :edit => :get, :create => :post, :update => :put, :destroy => :delete}
8 8  
9   -
10 9 describe "GET /apps" do
11 10 context 'when logged in as an admin' do
12 11 it 'finds all apps' do
13 12 sign_in Fabricate(:admin)
14 13 3.times { Fabricate(:app) }
15   - apps = App.all
16 14 get :index
17   - assigns(:apps).should == apps
  15 + controller.apps.should == App.all.sort.entries
18 16 end
19 17 end
20 18  
... ... @@ -27,8 +25,8 @@ describe AppsController do
27 25 Fabricate(:user_watcher, :user => user, :app => watched_app1)
28 26 Fabricate(:user_watcher, :user => user, :app => watched_app2)
29 27 get :index
30   - assigns(:apps).should include(watched_app1, watched_app2)
31   - assigns(:apps).should_not include(unwatched_app)
  28 + controller.apps.should include(watched_app1, watched_app2)
  29 + controller.apps.should_not include(unwatched_app)
32 30 end
33 31 end
34 32 end
... ... @@ -44,7 +42,7 @@ describe AppsController do
44 42  
45 43 it 'finds the app' do
46 44 get :show, :id => @app.id
47   - assigns(:app).should == @app
  45 + controller.app.should == @app
48 46 end
49 47  
50 48 it "should not raise errors for app with err without notices" do
... ... @@ -65,13 +63,13 @@ describe AppsController do
65 63  
66 64 it "should have default per_page value for user" do
67 65 get :show, :id => @app.id
68   - assigns(:problems).to_a.size.should == User::PER_PAGE
  66 + controller.problems.to_a.size.should == User::PER_PAGE
69 67 end
70 68  
71 69 it "should be able to override default per_page value" do
72 70 @user.update_attribute :per_page, 10
73 71 get :show, :id => @app.id
74   - assigns(:problems).to_a.size.should == 10
  72 + controller.problems.to_a.size.should == 10
75 73 end
76 74 end
77 75  
... ... @@ -85,14 +83,14 @@ describe AppsController do
85 83 context 'and no params' do
86 84 it 'shows only unresolved problems' do
87 85 get :show, :id => @app.id
88   - assigns(:problems).size.should == 1
  86 + controller.problems.size.should == 1
89 87 end
90 88 end
91 89  
92 90 context 'and all_problems=true params' do
93 91 it 'shows all errors' do
94 92 get :show, :id => @app.id, :all_errs => true
95   - assigns(:problems).size.should == 2
  93 + controller.problems.size.should == 2
96 94 end
97 95 end
98 96 end
... ... @@ -108,35 +106,35 @@ describe AppsController do
108 106 context 'no params' do
109 107 it 'shows errs for all environments' do
110 108 get :show, :id => @app.id
111   - assigns(:problems).size.should == 21
  109 + controller.problems.size.should == 21
112 110 end
113 111 end
114 112  
115 113 context 'environment production' do
116 114 it 'shows errs for just production' do
117 115 get :show, :id => @app.id, :environment => 'production'
118   - assigns(:problems).size.should == 6
  116 + controller.problems.size.should == 6
119 117 end
120 118 end
121 119  
122 120 context 'environment staging' do
123 121 it 'shows errs for just staging' do
124 122 get :show, :id => @app.id, :environment => 'staging'
125   - assigns(:problems).size.should == 5
  123 + controller.problems.size.should == 5
126 124 end
127 125 end
128 126  
129 127 context 'environment development' do
130 128 it 'shows errs for just development' do
131 129 get :show, :id => @app.id, :environment => 'development'
132   - assigns(:problems).size.should == 5
  130 + controller.problems.size.should == 5
133 131 end
134 132 end
135 133  
136 134 context 'environment test' do
137 135 it 'shows errs for just test' do
138 136 get :show, :id => @app.id, :environment => 'test'
139   - assigns(:problems).size.should == 5
  137 + controller.problems.size.should == 5
140 138 end
141 139 end
142 140 end
... ... @@ -149,7 +147,7 @@ describe AppsController do
149 147 watcher = Fabricate(:user_watcher, :app => app, :user => user)
150 148 sign_in user
151 149 get :show, :id => app.id
152   - assigns(:app).should == app
  150 + controller.app.should == app
153 151 end
154 152  
155 153 it 'does not find the app if the user is not watching it' do
... ... @@ -170,19 +168,19 @@ describe AppsController do
170 168 describe "GET /apps/new" do
171 169 it 'instantiates a new app with a prebuilt watcher' do
172 170 get :new
173   - assigns(:app).should be_a(App)
174   - assigns(:app).should be_new_record
175   - assigns(:app).watchers.should_not be_empty
  171 + controller.app.should be_a(App)
  172 + controller.app.should be_new_record
  173 + controller.app.watchers.should_not be_empty
176 174 end
177 175  
178 176 it "should copy attributes from an existing app" do
179 177 @app = Fabricate(:app, :name => "do not copy",
180 178 :github_repo => "test/example")
181 179 get :new, :copy_attributes_from => @app.id
182   - assigns(:app).should be_a(App)
183   - assigns(:app).should be_new_record
184   - assigns(:app).name.should be_blank
185   - assigns(:app).github_repo.should == "test/example"
  180 + controller.app.should be_a(App)
  181 + controller.app.should be_new_record
  182 + controller.app.name.should be_blank
  183 + controller.app.github_repo.should == "test/example"
186 184 end
187 185 end
188 186  
... ... @@ -190,7 +188,7 @@ describe AppsController do
190 188 it 'finds the correct app' do
191 189 app = Fabricate(:app)
192 190 get :edit, :id => app.id
193   - assigns(:app).should == app
  191 + controller.app.should == app
194 192 end
195 193 end
196 194  
... ... @@ -326,12 +324,11 @@ describe AppsController do
326 324 describe "DELETE /apps/:id" do
327 325 before do
328 326 @app = Fabricate(:app)
329   - App.stub(:find).with(@app.id).and_return(@app)
330 327 end
331 328  
332 329 it "should find the app" do
333 330 delete :destroy, :id => @app.id
334   - assigns(:app).should == @app
  331 + controller.app.should == @app
335 332 end
336 333  
337 334 it "should destroy the app" do
... ...
spec/controllers/problems_controller_spec.rb
... ... @@ -12,7 +12,7 @@ describe ProblemsController do
12 12  
13 13  
14 14 describe "GET /problems" do
15   - render_views
  15 + #render_views
16 16 context 'when logged in as an admin' do
17 17 before(:each) do
18 18 @user = Fabricate(:admin)
... ... @@ -20,18 +20,6 @@ describe ProblemsController do
20 20 @problem = Fabricate(:notice, :err => Fabricate(:err, :problem => Fabricate(:problem, :app => app, :environment => "production"))).problem
21 21 end
22 22  
23   - it "should successfully list problems" do
24   - get :index
25   - response.should be_success
26   - response.body.gsub("&#8203;", "").should match(@problem.message)
27   - end
28   -
29   - it "should list atom feed successfully" do
30   - get :index, :format => "atom"
31   - response.should be_success
32   - response.body.should match(@problem.message)
33   - end
34   -
35 23 context "pagination" do
36 24 before(:each) do
37 25 35.times { Fabricate :err }
... ... @@ -39,13 +27,13 @@ describe ProblemsController do
39 27  
40 28 it "should have default per_page value for user" do
41 29 get :index
42   - assigns(:problems).to_a.size.should == User::PER_PAGE
  30 + controller.problems.to_a.size.should == User::PER_PAGE
43 31 end
44 32  
45 33 it "should be able to override default per_page value" do
46 34 @user.update_attribute :per_page, 10
47 35 get :index
48   - assigns(:problems).to_a.size.should == 10
  36 + controller.problems.to_a.size.should == 10
49 37 end
50 38 end
51 39  
... ... @@ -60,35 +48,35 @@ describe ProblemsController do
60 48 context 'no params' do
61 49 it 'shows problems for all environments' do
62 50 get :index
63   - assigns(:problems).size.should == 21
  51 + controller.problems.size.should == 21
64 52 end
65 53 end
66 54  
67 55 context 'environment production' do
68 56 it 'shows problems for just production' do
69 57 get :index, :environment => 'production'
70   - assigns(:problems).size.should == 6
  58 + controller.problems.size.should == 6
71 59 end
72 60 end
73 61  
74 62 context 'environment staging' do
75 63 it 'shows problems for just staging' do
76 64 get :index, :environment => 'staging'
77   - assigns(:problems).size.should == 5
  65 + controller.problems.size.should == 5
78 66 end
79 67 end
80 68  
81 69 context 'environment development' do
82 70 it 'shows problems for just development' do
83 71 get :index, :environment => 'development'
84   - assigns(:problems).size.should == 5
  72 + controller.problems.size.should == 5
85 73 end
86 74 end
87 75  
88 76 context 'environment test' do
89 77 it 'shows problems for just test' do
90 78 get :index, :environment => 'test'
91   - assigns(:problems).size.should == 5
  79 + controller.problems.size.should == 5
92 80 end
93 81 end
94 82 end
... ... @@ -101,8 +89,8 @@ describe ProblemsController do
101 89 watched_unresolved_err = Fabricate(:err, :problem => Fabricate(:problem, :app => Fabricate(:user_watcher, :user => user).app, :resolved => false))
102 90 watched_resolved_err = Fabricate(:err, :problem => Fabricate(:problem, :app => Fabricate(:user_watcher, :user => user).app, :resolved => true))
103 91 get :index
104   - assigns(:problems).should include(watched_unresolved_err.problem)
105   - assigns(:problems).should_not include(unwatched_err.problem, watched_resolved_err.problem)
  92 + controller.problems.should include(watched_unresolved_err.problem)
  93 + controller.problems.should_not include(unwatched_err.problem, watched_resolved_err.problem)
106 94 end
107 95 end
108 96 end
... ... @@ -118,7 +106,7 @@ describe ProblemsController do
118 106 mock('proxy', :page => mock('other_proxy', :per => problems))
119 107 )
120 108 get :index, :all_errs => true
121   - assigns(:problems).should == problems
  109 + controller.problems.should == problems
122 110 end
123 111 end
124 112  
... ... @@ -129,14 +117,14 @@ describe ProblemsController do
129 117 watched_unresolved_problem = Fabricate(:problem, :app => Fabricate(:user_watcher, :user => user).app, :resolved => false)
130 118 watched_resolved_problem = Fabricate(:problem, :app => Fabricate(:user_watcher, :user => user).app, :resolved => true)
131 119 get :index, :all_errs => true
132   - assigns(:problems).should include(watched_resolved_problem, watched_unresolved_problem)
133   - assigns(:problems).should_not include(unwatched_problem)
  120 + controller.problems.should include(watched_resolved_problem, watched_unresolved_problem)
  121 + controller.problems.should_not include(unwatched_problem)
134 122 end
135 123 end
136 124 end
137 125  
138 126 describe "GET /apps/:app_id/problems/:id" do
139   - render_views
  127 + #render_views
140 128  
141 129 context 'when logged in as an admin' do
142 130 before do
... ... @@ -145,12 +133,12 @@ describe ProblemsController do
145 133  
146 134 it "finds the app" do
147 135 get :show, :app_id => app.id, :id => err.problem.id
148   - assigns(:app).should == app
  136 + controller.app.should == app
149 137 end
150 138  
151 139 it "finds the problem" do
152 140 get :show, :app_id => app.id, :id => err.problem.id
153   - assigns(:problem).should == err.problem
  141 + controller.problem.should == err.problem
154 142 end
155 143  
156 144 it "successfully render page" do
... ... @@ -178,32 +166,6 @@ describe ProblemsController do
178 166 end
179 167 end
180 168  
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 169 end
208 170  
209 171 context 'when logged in as a user' do
... ... @@ -217,7 +179,7 @@ describe ProblemsController do
217 179  
218 180 it 'finds the problem if the user is watching the app' do
219 181 get :show, :app_id => @watched_app.to_param, :id => @watched_err.problem.id
220   - assigns(:problem).should == @watched_err.problem
  182 + controller.problem.should == @watched_err.problem
221 183 end
222 184  
223 185 it 'raises a DocumentNotFound error if the user is not watching the app' do
... ... @@ -242,8 +204,8 @@ describe ProblemsController do
242 204 App.should_receive(:find).with(@problem.app.id).and_return(@problem.app)
243 205 @problem.app.problems.should_receive(:find).and_return(@problem.problem)
244 206 put :resolve, :app_id => @problem.app.id, :id => @problem.problem.id
245   - assigns(:app).should == @problem.app
246   - assigns(:problem).should == @problem.problem
  207 + controller.app.should == @problem.app
  208 + controller.problem.should == @problem.problem
247 209 end
248 210  
249 211 it "should resolve the issue" do
... ... @@ -269,7 +231,7 @@ describe ProblemsController do
269 231 end
270 232  
271 233 describe "POST /apps/:app_id/problems/:id/create_issue" do
272   - render_views
  234 + #render_views
273 235  
274 236 before(:each) do
275 237 sign_in Fabricate(:admin)
... ... @@ -379,31 +341,25 @@ describe ProblemsController do
379 341 @problem2 = Fabricate(:err, :problem => Fabricate(:problem, :resolved => false)).problem
380 342 end
381 343  
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 344 context "POST /problems/merge_several" do
393 345 it "should require at least two problems" do
394 346 post :merge_several, :problems => [@problem1.id.to_s]
395   - request.flash[:notice].should match(/You must select at least two/)
  347 + request.flash[:notice].should eql I18n.t('controllers.problems.flash.need_two_errors_merge')
396 348 end
397 349  
398 350 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)
  351 + ProblemMerge.should_receive(:new).and_return(double(:merge => true))
  352 + post :merge_several, :problems => [@problem1.id.to_s, @problem2.id.to_s]
403 353 end
404 354 end
405 355  
406 356 context "POST /problems/unmerge_several" do
  357 +
  358 + it "should require at least one problem" do
  359 + post :unmerge_several, :problems => []
  360 + request.flash[:notice].should eql I18n.t('controllers.problems.flash.no_select_problem')
  361 + end
  362 +
407 363 it "should unmerge a merged problem" do
408 364 merged_problem = Problem.merge!(@problem1, @problem2)
409 365 merged_problem.errs.length.should == 2
... ... @@ -412,9 +368,16 @@ describe ProblemsController do
412 368 merged_problem.reload.errs.length.should == 1
413 369 }.should change(Problem, :count).by(1)
414 370 end
  371 +
415 372 end
416 373  
417 374 context "POST /problems/resolve_several" do
  375 +
  376 + it "should require at least one problem" do
  377 + post :resolve_several, :problems => []
  378 + request.flash[:notice].should eql I18n.t('controllers.problems.flash.no_select_problem')
  379 + end
  380 +
418 381 it "should resolve the issue" do
419 382 post :resolve_several, :problems => [@problem2.id.to_s]
420 383 @problem2.reload.resolved?.should == true
... ... @@ -428,10 +391,17 @@ describe ProblemsController do
428 391 it "should display a message about 2 errs" do
429 392 post :resolve_several, :problems => [@problem1.id.to_s, @problem2.id.to_s]
430 393 flash[:success].should match(/2 errs have been resolved/)
  394 + controller.selected_problems.should == [@problem1, @problem2]
431 395 end
432 396 end
433 397  
434 398 context "POST /problems/unresolve_several" do
  399 +
  400 + it "should require at least one problem" do
  401 + post :unresolve_several, :problems => []
  402 + request.flash[:notice].should eql I18n.t('controllers.problems.flash.no_select_problem')
  403 + end
  404 +
435 405 it "should unresolve the issue" do
436 406 post :unresolve_several, :problems => [@problem1.id.to_s]
437 407 @problem1.reload.resolved?.should == false
... ...
spec/fabricators_spec.rb
... ... @@ -1,18 +0,0 @@
1   -require 'spec_helper'
2   -
3   -Fabrication::Config.fabricator_dir.each do |folder|
4   - Dir.glob(File.join(Rails.root, folder, '**', '*.rb')).each do |file|
5   - require file
6   - end
7   -end
8   -
9   -describe "Fabrication" do
10   - #TODO : when 1.8.7 drop support se directly Symbol#sort
11   - Fabrication::Fabricator.schematics.keys.sort_by(&:to_s).each do |fabricator_name|
12   - context "Fabricate(:#{fabricator_name})" do
13   - subject { Fabricate.build(fabricator_name) }
14   -
15   - it { should be_valid }
16   - end
17   - end
18   -end
spec/models/fabricators_spec.rb 0 → 100644
... ... @@ -0,0 +1,18 @@
  1 +require 'spec_helper'
  2 +
  3 +Fabrication::Config.fabricator_dir.each do |folder|
  4 + Dir.glob(File.join(Rails.root, folder, '**', '*.rb')).each do |file|
  5 + require file
  6 + end
  7 +end
  8 +
  9 +describe "Fabrication" do
  10 + #TODO : when 1.8.7 drop support se directly Symbol#sort
  11 + Fabrication::Fabricator.schematics.keys.sort_by(&:to_s).each do |fabricator_name|
  12 + context "Fabricate(:#{fabricator_name})" do
  13 + subject { Fabricate.build(fabricator_name) }
  14 +
  15 + it { should be_valid }
  16 + end
  17 + end
  18 +end
... ...
spec/models/problem_spec.rb
... ... @@ -152,7 +152,6 @@ describe Problem do
152 152 end
153 153 end
154 154  
155   -
156 155 context "Scopes" do
157 156 context "resolved" do
158 157 it 'only finds resolved Problems' do
... ...
spec/views/apps/edit.html.haml_spec.rb
... ... @@ -3,7 +3,7 @@ require &#39;spec_helper&#39;
3 3 describe "apps/edit.html.haml" do
4 4 before do
5 5 app = stub_model(App)
6   - assign :app, app
  6 + view.stub(:app).and_return(app)
7 7 controller.stub(:current_user) { stub_model(User) }
8 8 end
9 9  
... ...
spec/views/apps/index.html.haml_spec.rb
... ... @@ -3,7 +3,7 @@ require &#39;spec_helper&#39;
3 3 describe "apps/index.html.haml" do
4 4 before do
5 5 app = stub_model(App, :deploys => [stub_model(Deploy, :created_at => Time.now, :revision => "123456789abcdef")])
6   - assign :apps, [app]
  6 + view.stub(:apps).and_return([app])
7 7 controller.stub(:current_user) { stub_model(User) }
8 8 end
9 9  
... ...
spec/views/problems/index.atom.builder_spec.rb 0 → 100644
... ... @@ -0,0 +1,14 @@
  1 +require 'spec_helper'
  2 +
  3 +describe "problems/index.atom.builder" do
  4 +
  5 + it 'display problem message' do
  6 + app = App.new(:new_record => false)
  7 + view.stub(:problems).and_return([Problem.new(
  8 + :message => 'foo',
  9 + :new_record => false, :app => app), Problem.new(:new_record => false, :app => app)])
  10 + render
  11 + rendered.should match('foo')
  12 + end
  13 +
  14 +end
... ...
spec/views/problems/index.html.haml_spec.rb 0 → 100644
... ... @@ -0,0 +1,25 @@
  1 +require 'spec_helper'
  2 +
  3 +describe "problems/index.html.haml" do
  4 + let(:problem_1) { Fabricate(:problem) }
  5 + let(:problem_2) { Fabricate(:problem, :app => problem_1.app) }
  6 +
  7 + before do
  8 + # view.stub(:app).and_return(problem.app)
  9 + view.stub(:selected_problems).and_return([])
  10 + view.stub(:problems).and_return(Kaminari.paginate_array([problem_1, problem_2]).page(1).per(10))
  11 + view.stub(:params_sort).and_return('asc')
  12 + controller.stub(:current_user) { Fabricate(:user) }
  13 + end
  14 +
  15 + describe "with problem" do
  16 + before { problem_1 && problem_2 }
  17 +
  18 + it 'should works' do
  19 + render
  20 + rendered.should have_selector('div#problem_table.problem_table')
  21 + end
  22 + end
  23 +
  24 +end
  25 +
... ...
spec/views/problems/show.html.haml_spec.rb
1 1 require 'spec_helper'
2 2  
3 3 describe "problems/show.html.haml" do
  4 + let(:problem) { Fabricate(:problem) }
  5 + let(:comment) { Fabricate(:comment) }
  6 +
4 7 before do
5   - problem = Fabricate(:problem)
6   - comment = Fabricate(:comment)
7   - assign :problem, problem
  8 + view.stub(:app).and_return(problem.app)
  9 + view.stub(:problem).and_return(problem)
  10 +
8 11 assign :comment, comment
9   - assign :app, problem.app
10 12 assign :notices, problem.notices.page(1).per(1)
11 13 assign :notice, problem.notices.first
  14 +
12 15 controller.stub(:current_user) { Fabricate(:user) }
13 16 end
14 17  
15 18 def with_issue_tracker(tracker, problem)
16 19 problem.app.issue_tracker = tracker.new :api_token => "token token token", :project_id => "1234"
17   - assign :problem, problem
18   - assign :app, problem.app
  20 + view.stub(:problem).and_return(problem)
  21 + view.stub(:app).and_return(problem.app)
19 22 end
20 23  
21 24 describe "content_for :action_bar" do
... ... @@ -54,8 +57,8 @@ describe &quot;problems/show.html.haml&quot; do
54 57 it "should link 'up' to app_problems_path if HTTP_REFERER isn't set'" do
55 58 controller.request.env['HTTP_REFERER'] = nil
56 59 problem = Fabricate(:problem_with_comments)
57   - assign :problem, problem
58   - assign :app, problem.app
  60 + view.stub(:problem).and_return(problem)
  61 + view.stub(:app).and_return(problem.app)
59 62 render
60 63  
61 64 action_bar.should have_selector("span a.up[href='#{app_problems_path(problem.app)}']", :text => 'up')
... ... @@ -67,8 +70,8 @@ describe &quot;problems/show.html.haml&quot; do
67 70 controller.stub(:current_user) { user }
68 71  
69 72 problem = Fabricate(:problem_with_comments, :app => Fabricate(:app, :github_repo => "test_user/test_repo"))
70   - assign :problem, problem
71   - assign :app, problem.app
  73 + view.stub(:problem).and_return(problem)
  74 + view.stub(:app).and_return(problem.app)
72 75 render
73 76  
74 77 action_bar.should have_selector("span a.github_create.create-issue", :text => 'create issue')
... ... @@ -77,12 +80,54 @@ describe &quot;problems/show.html.haml&quot; do
77 80 it 'should allow creating issue for github if application has a github tracker' do
78 81 problem = Fabricate(:problem_with_comments, :app => Fabricate(:app, :github_repo => "test_user/test_repo"))
79 82 with_issue_tracker(GithubIssuesTracker, problem)
80   - assign :problem, problem
81   - assign :app, problem.app
  83 + view.stub(:problem).and_return(problem)
  84 + view.stub(:app).and_return(problem.app)
82 85 render
83 86  
84 87 action_bar.should have_selector("span a.github_create.create-issue", :text => 'create issue')
85 88 end
  89 +
  90 + context "without issue tracker associate on app" do
  91 + let(:problem){ Problem.new(:new_record => false, :app => app) }
  92 + let(:app) { App.new(:new_record => false) }
  93 +
  94 + it 'not see link to create issue' do
  95 + view.stub(:problem).and_return(problem)
  96 + view.stub(:app).and_return(problem.app)
  97 + render
  98 + expect(view.content_for(:action_bar)).to_not match(/create issue/)
  99 + end
  100 +
  101 + end
  102 +
  103 + context "with lighthouse tracker on app" do
  104 + let(:app) { App.new(:new_record => false, :issue_tracker => tracker ) }
  105 + let(:tracker) {
  106 + IssueTrackers::LighthouseTracker.new(:project_id => 'x')
  107 + }
  108 + context "with problem without issue link" do
  109 + let(:problem){ Problem.new(:new_record => false, :app => app) }
  110 + it 'not see link if no issue tracker' do
  111 + view.stub(:problem).and_return(problem)
  112 + view.stub(:app).and_return(problem.app)
  113 + render
  114 + expect(view.content_for(:action_bar)).to match(/create issue/)
  115 + end
  116 +
  117 + end
  118 +
  119 + context "with problem with issue link" do
  120 + let(:problem){ Problem.new(:new_record => false, :app => app, :issue_link => 'http://foo') }
  121 +
  122 + it 'not see link if no issue tracker' do
  123 + view.stub(:problem).and_return(problem)
  124 + view.stub(:app).and_return(problem.app)
  125 + render
  126 + expect(view.content_for(:action_bar)).to_not match(/create issue/)
  127 + end
  128 + end
  129 +
  130 + end
86 131 end
87 132 end
88 133  
... ... @@ -94,8 +139,8 @@ describe &quot;problems/show.html.haml&quot; do
94 139  
95 140 it 'should display comments and new comment form when no issue tracker' do
96 141 problem = Fabricate(:problem_with_comments)
97   - assign :problem, problem
98   - assign :app, problem.app
  142 + view.stub(:problem).and_return(problem)
  143 + view.stub(:app).and_return(problem.app)
99 144 render
100 145  
101 146 view.content_for(:comments).should include('Test comment')
... ...
spec/views/problems/show.ics.haml_spec.rb 0 → 100644
... ... @@ -0,0 +1,14 @@
  1 +require 'spec_helper'
  2 +
  3 +describe "problems/show.html.ics" do
  4 + let(:problem) { Fabricate(:problem) }
  5 + before do
  6 + view.stub(:problem).and_return(problem)
  7 + end
  8 +
  9 + it 'should work' do
  10 + render :template => 'problems/show.ics.haml'
  11 + end
  12 +
  13 +
  14 +end
... ...