Commit c6548a8e1514f78d2770307a92158b24b7e71b4f

Authored by Stephen Crosby
2 parents 0ff2eb5a 74429ae6
Exists in master and in 1 other branch production

Merge pull request #938 from stevecrozz/users_can_see_all_apps

Refs #561 users can see all apps
app/assets/stylesheets/errbit.css.erb
@@ -540,8 +540,8 @@ a.button.active { @@ -540,8 +540,8 @@ a.button.active {
540 display: inline-block; 540 display: inline-block;
541 } 541 }
542 542
543 -/* Watchers / Issue Tracker / Notification Forms */  
544 -div.watcher.nested .watcher_params, div.issue_tracker.nested .tracker_params, div.notification_service.nested .notification_params { 543 +/* Issue Tracker / Notification Forms */
  544 +div.issue_tracker.nested .tracker_params, div.notification_service.nested .notification_params {
545 display: none; 545 display: none;
546 } 546 }
547 547
app/controllers/application_controller.rb
@@ -5,13 +5,6 @@ class ApplicationController < ActionController::Base @@ -5,13 +5,6 @@ class ApplicationController < ActionController::Base
5 before_action :authenticate_user! 5 before_action :authenticate_user!
6 before_action :set_time_zone 6 before_action :set_time_zone
7 7
8 - # Devise override - After login, if there is only one app,  
9 - # redirect to that app's path instead of the root path (apps#index).  
10 - def stored_location_for(resource)  
11 - location = super || root_path  
12 - (location == root_path && current_user.apps.count == 1) ? app_path(current_user.apps.first) : location  
13 - end  
14 -  
15 rescue_from ActionController::RedirectBackError, :with => :redirect_to_root 8 rescue_from ActionController::RedirectBackError, :with => :redirect_to_root
16 9
17 class StrongParametersWithEagerAttributesStrategy < DecentExposure::StrongParametersStrategy 10 class StrongParametersWithEagerAttributesStrategy < DecentExposure::StrongParametersStrategy
app/controllers/apps_controller.rb
@@ -7,9 +7,7 @@ class AppsController &lt; ApplicationController @@ -7,9 +7,7 @@ class AppsController &lt; ApplicationController
7 before_action :parse_notice_at_notices_or_set_default, :only => [:create, :update] 7 before_action :parse_notice_at_notices_or_set_default, :only => [:create, :update]
8 respond_to :html 8 respond_to :html
9 9
10 - expose(:app_scope) {  
11 - (current_user.admin? ? App : current_user.apps)  
12 - } 10 + expose(:app_scope) { App }
13 11
14 expose(:apps) { 12 expose(:apps) {
15 app_scope.asc(:name).map { |app| AppDecorator.new(app) } 13 app_scope.asc(:name).map { |app| AppDecorator.new(app) }
app/controllers/comments_controller.rb
@@ -27,10 +27,6 @@ class CommentsController &lt; ApplicationController @@ -27,10 +27,6 @@ class CommentsController &lt; ApplicationController
27 protected 27 protected
28 def find_app 28 def find_app
29 @app = App.find(params[:app_id]) 29 @app = App.find(params[:app_id])
30 -  
31 - # Mongoid Bug: could not chain: current_user.apps.find_by_id!  
32 - # apparently finding by 'watchers.email' and 'id' is broken  
33 - raise(Mongoid::Errors::DocumentNotFound.new(App,@app.id)) unless current_user.admin? || current_user.watching?(@app)  
34 end 30 end
35 31
36 def find_problem 32 def find_problem
app/controllers/deploys_controller.rb
@@ -12,13 +12,9 @@ class DeploysController &lt; ApplicationController @@ -12,13 +12,9 @@ class DeploysController &lt; ApplicationController
12 end 12 end
13 13
14 def index 14 def index
15 - # See AppsController#find_app for the reasoning behind this code.  
16 - app = App.find(params[:app_id])  
17 - raise Mongoid::Errors::DocumentNotFound.new(App, app.id) unless current_user.admin? || current_user.watching?(app)  
18 -  
19 - @deploys = Kaminari.paginate_array(app.deploys.order_by(:created_at.desc)). 15 + @app = App.find(params[:app_id])
  16 + @deploys = Kaminari.paginate_array(@app.deploys.order_by(:created_at.desc)).
20 page(params[:page]).per(10) 17 page(params[:page]).per(10)
21 - @app = app  
22 end 18 end
23 19
24 private 20 private
app/controllers/problems_controller.rb
@@ -13,8 +13,7 @@ class ProblemsController &lt; ApplicationController @@ -13,8 +13,7 @@ class ProblemsController &lt; ApplicationController
13 ] 13 ]
14 14
15 expose(:app_scope) { 15 expose(:app_scope) {
16 - apps = current_user.admin? ? App.all : current_user.apps  
17 - params[:app_id] ? apps.where(:_id => params[:app_id]) : apps 16 + params[:app_id] ? App.where(:_id => params[:app_id]) : App.all
18 } 17 }
19 18
20 expose(:app) { 19 expose(:app) {
@@ -34,11 +33,11 @@ class ProblemsController &lt; ApplicationController @@ -34,11 +33,11 @@ class ProblemsController &lt; ApplicationController
34 } 33 }
35 34
36 expose(:problems) { 35 expose(:problems) {
37 - pro = Problem.for_apps(  
38 - app_scope  
39 - ).in_env(  
40 - params_environement  
41 - ).all_else_unresolved(all_errs).ordered_by(params_sort, params_order) 36 + pro = Problem
  37 + .for_apps(app_scope)
  38 + .in_env(params_environement)
  39 + .all_else_unresolved(all_errs)
  40 + .ordered_by(params_sort, params_order)
42 41
43 if request.format == :html 42 if request.format == :html
44 pro.page(params[:page]).per(current_user.per_page) 43 pro.page(params[:page]).per(current_user.per_page)
app/controllers/watchers_controller.rb
@@ -5,23 +5,16 @@ class WatchersController &lt; ApplicationController @@ -5,23 +5,16 @@ class WatchersController &lt; ApplicationController
5 App.find(params[:app_id]) 5 App.find(params[:app_id])
6 end 6 end
7 7
8 - expose(:watcher) do  
9 - app.watchers.where(:user_id => params[:id]).first  
10 - end  
11 -  
12 - before_action :require_watcher_edit_priviledges, :only => [:destroy]  
13 -  
14 def destroy 8 def destroy
  9 + watcher = app.watchers.where(:user_id => params[:id]).first
15 app.watchers.delete(watcher) 10 app.watchers.delete(watcher)
16 - flash[:success] = "That's sad. #{watcher.label} is no longer watcher."  
17 - redirect_to root_path 11 + flash[:success] = t('.success', app: app.name)
  12 + redirect_to app_path(app)
18 end 13 end
19 14
20 - private  
21 -  
22 - def require_watcher_edit_priviledges  
23 - redirect_to(root_path) unless current_user == watcher.user || current_user.admin? 15 + def update
  16 + app.watchers.create(user_id: current_user.id)
  17 + flash[:success] = t('.success', app: app.name)
  18 + redirect_to app_path(app)
24 end 19 end
25 -  
26 end 20 end
27 -  
app/interactors/user_destroy.rb
@@ -4,8 +4,11 @@ class UserDestroy @@ -4,8 +4,11 @@ class UserDestroy
4 end 4 end
5 5
6 def destroy 6 def destroy
  7 + App.watched_by(@user).each do |app|
  8 + watcher = app.watchers.where(user_id: @user.id).first
  9 + app.watchers.delete(watcher)
  10 + end
  11 +
7 @user.destroy 12 @user.destroy
8 - @user.watchers.each(&:destroy)  
9 end 13 end
10 -  
11 end 14 end
app/models/app.rb
@@ -23,7 +23,6 @@ class App @@ -23,7 +23,6 @@ class App
23 pre_processed: true, 23 pre_processed: true,
24 default: ->{ BSON::ObjectId.new.to_s } 24 default: ->{ BSON::ObjectId.new.to_s }
25 25
26 -  
27 embeds_many :watchers 26 embeds_many :watchers
28 embeds_many :deploys 27 embeds_many :deploys
29 embeds_one :issue_tracker, :class_name => 'IssueTracker' 28 embeds_one :issue_tracker, :class_name => 'IssueTracker'
@@ -48,6 +47,14 @@ class App @@ -48,6 +47,14 @@ class App
48 accepts_nested_attributes_for :notification_service, :allow_destroy => true, 47 accepts_nested_attributes_for :notification_service, :allow_destroy => true,
49 :reject_if => proc { |attrs| !NotificationService.subclasses.map(&:to_s).include?(attrs[:type].to_s) } 48 :reject_if => proc { |attrs| !NotificationService.subclasses.map(&:to_s).include?(attrs[:type].to_s) }
50 49
  50 + scope :watched_by, ->(user) do
  51 + where watchers: { "$elemMatch" => { "user_id" => user.id } }
  52 + end
  53 +
  54 + def watched_by?(user)
  55 + watchers.pluck("user_id").include? user.id
  56 + end
  57 +
51 # Acceps a hash with the following attributes: 58 # Acceps a hash with the following attributes:
52 # 59 #
53 # * <tt>:error_class</tt> - the class of error (required to create a new Problem) 60 # * <tt>:error_class</tt> - the class of error (required to create a new Problem)
app/models/user.rb
@@ -41,17 +41,11 @@ class User @@ -41,17 +41,11 @@ class User
41 validates_presence_of :name 41 validates_presence_of :name
42 validates_uniqueness_of :github_login, :allow_nil => true 42 validates_uniqueness_of :github_login, :allow_nil => true
43 43
44 - has_many :apps, :foreign_key => 'watchers.user_id'  
45 -  
46 if Errbit::Config.user_has_username 44 if Errbit::Config.user_has_username
47 field :username 45 field :username
48 validates_presence_of :username 46 validates_presence_of :username
49 end 47 end
50 48
51 - def watchers  
52 - apps.map(&:watchers).flatten.select {|w| w.user_id.to_s == id.to_s}  
53 - end  
54 -  
55 def per_page 49 def per_page
56 super || PER_PAGE 50 super || PER_PAGE
57 end 51 end
app/views/apps/_fields.html.haml
@@ -44,21 +44,6 @@ @@ -44,21 +44,6 @@
44 = f.check_box :notify_all_users 44 = f.check_box :notify_all_users
45 = f.label :notify_all_users, 'Send notifications to all users' 45 = f.label :notify_all_users, 'Send notifications to all users'
46 46
47 -  
48 -%fieldset.watchers.nested-wrapper{:style => app_decorate.notify_user_display}  
49 - %legend Watchers  
50 - = f.fields_for :watchers do |w|  
51 - %div.watcher.nested  
52 - %div.choose  
53 - = w.radio_button :watcher_type, :user  
54 - = w.label :watcher_type_user, 'User'  
55 - = w.radio_button :watcher_type, :email  
56 - = label_tag :watcher_type_email, 'Email Address', :for => label_for_attr(w, 'watcher_type_email')  
57 - %div.watcher_params.user{:class => w.object.email.blank? ? 'chosen' : nil}  
58 - = w.select :user_id, users.map{|u| [u.name,u.id.to_s]}, :include_blank => '-- Select a User --'  
59 - %div.watcher_params.email{:class => w.object.email.present? ? 'chosen' : nil}  
60 - = w.text_field :email  
61 -  
62 %div.checkbox 47 %div.checkbox
63 = f.check_box :resolve_errs_on_deploy 48 = f.check_box :resolve_errs_on_deploy
64 = f.label :resolve_errs_on_deploy, 'Resolve errs on deploy' 49 = f.label :resolve_errs_on_deploy, 'Resolve errs on deploy'
app/views/apps/show.html.haml
@@ -19,8 +19,11 @@ @@ -19,8 +19,11 @@
19 - else 19 - else
20 = link_to t('.all_errs'), app_path(app, :all_errs => true), :class => 'button' 20 = link_to t('.all_errs'), app_path(app, :all_errs => true), :class => 'button'
21 21
22 - - if current_user.watching?(app)  
23 - = link_to t('.unwatch'), app_watcher_path({app_id: app, id: current_user.id}), method: :delete, class: 'button', data: {confirm: t('.are_you_sure')} 22 + - if app.watched_by?(current_user)
  23 + = link_to t('.unwatch'), app_watcher_path(app_id: app, id: current_user.id), method: :delete, class: 'button'
  24 + - else
  25 + = link_to t('.watch'), app_watcher_path(app_id: app, id: current_user.id), method: :put, class: 'button'
  26 +
24 %h3#watchers_toggle 27 %h3#watchers_toggle
25 =t('.watchers') 28 =t('.watchers')
26 %span.click_span=t('.show_hide') 29 %span.click_span=t('.show_hide')
config/locales/en.yml
@@ -124,6 +124,7 @@ en: @@ -124,6 +124,7 @@ en:
124 unresolved_errs: unresolved errors 124 unresolved_errs: unresolved errors
125 unwatch: unwatch 125 unwatch: unwatch
126 user_or_email: User or Email 126 user_or_email: User or Email
  127 + watch: watch
127 watchers: Watchers 128 watchers: Watchers
128 when: When 129 when: When
129 who: Who 130 who: Who
@@ -139,4 +140,8 @@ en: @@ -139,4 +140,8 @@ en:
139 cancel: 'cancel' 140 cancel: 'cancel'
140 seriously: 'Seriously?' 141 seriously: 'Seriously?'
141 update: 'Update App' 142 update: 'Update App'
142 - 143 + watchers:
  144 + destroy:
  145 + success: "You are no longer watching %{app}"
  146 + update:
  147 + success: "You are now watching %{app}"
config/routes.rb
@@ -42,7 +42,7 @@ Rails.application.routes.draw do @@ -42,7 +42,7 @@ Rails.application.routes.draw do
42 end 42 end
43 end 43 end
44 resources :deploys, :only => [:index] 44 resources :deploys, :only => [:index]
45 - resources :watchers, :only => [:destroy] 45 + resources :watchers, :only => [:destroy, :update]
46 member do 46 member do
47 post :regenerate_api_key 47 post :regenerate_api_key
48 end 48 end
public/mockup.html
@@ -1,90 +0,0 @@ @@ -1,90 +0,0 @@
1 -<!DOCTYPE html>  
2 -<html>  
3 - <head>  
4 - <title>  
5 - Errbit &mdash;  
6 - Add App  
7 - </title>  
8 - <meta content='text/html; charset=utf-8' http-equiv='content-type'>  
9 - <meta name="csrf-param" content="authenticity_token"/>  
10 - <meta name="csrf-token" content="2xxr2t/FRsJU1jXFRJYSbR/x7dk4jIPwmEhE2sgrWFA="/>  
11 - <script src="/javascripts/jquery.js?1281707549" type="text/javascript"></script>  
12 - <script src="/javascripts/rails.js?1281707549" type="text/javascript"></script>  
13 - <script src="/javascripts/form.js?1281727831" type="text/javascript"></script>  
14 - <script src="/javascripts/application.js?1281707549" type="text/javascript"></script>  
15 -  
16 -  
17 - <link href="/stylesheets/reset.css?1281707549" media="screen" rel="stylesheet" type="text/css" />  
18 - <link href="/stylesheets/application.css?1281730151" media="screen" rel="stylesheet" type="text/css" />  
19 -  
20 - <style type="text/css" media="screen">  
21 - #app_watchers_attributes_0_user_id,  
22 - #app_watchers_attributes_0_email {  
23 - display:none;  
24 - }  
25 - #app_watchers_attributes_0_user_id.show,  
26 - #app_watchers_attributes_0_email.show {  
27 - display: block;  
28 - }  
29 - </style>  
30 -  
31 - </head>  
32 - <body class='new' id='apps'>  
33 - <div id='header'>  
34 - <div>  
35 - <a href="/" id="site-name">Errbit</a>  
36 - <ul id='session-links'>  
37 - <li><a href="/users/sign_out" id="sign-out">Sign out</a></li>  
38 - </ul>  
39 - </div>  
40 - </div>  
41 - <div id='nav-bar'>  
42 - <ul>  
43 - <!-- /%li= link_to 'Dashboard', admin_dashboard_path, :class => active_if_here(:dashboards) -->  
44 - <li class='active apps'><a href="/apps">Apps</a></li>  
45 - <li class='errs'><a href="/errs">Errs</a></li>  
46 - <li class='users'><a href="/users">Users</a></li>  
47 - </ul>  
48 - <div class='clear'></div>  
49 - </div>  
50 - <div id='content-wrapper'>  
51 - <div id='content-title'>  
52 - <h1>Add App</h1>  
53 - <span class='meta'></span>  
54 - <div id='action-bar'>  
55 - <a href="/apps">cancel</a>  
56 - </div>  
57 - </div>  
58 - <div id='content'>  
59 -  
60 - <form accept-charset="UTF-8" action="/apps" class="new_app" id="new_app" method="post"><div style="margin:0;padding:0;display:inline"><input name="_snowman" type="hidden" value="&#9731;" /><input name="authenticity_token" type="hidden" value="2xxr2t/FRsJU1jXFRJYSbR/x7dk4jIPwmEhE2sgrWFA=" /></div>  
61 - <div class='required'>  
62 - <label for="app_name">Name</label>  
63 - <input id="app_name" name="app[name]" size="30" type="text" />  
64 - </div>  
65 - <div class='checkbox'>  
66 - <input name="app[resolve_errs_on_deploy]" type="hidden" value="0" /><input id="app_resolve_errs_on_deploy" name="app[resolve_errs_on_deploy]" type="checkbox" value="1" />  
67 - <label for="app_resolve_errs_on_deploy">Resolve errs on deploy</label>  
68 - </div>  
69 - <fieldset class='nested-wrapper'>  
70 - <legend>Watchers</legend>  
71 - <div class='nested'>  
72 - <div>  
73 - <input type="radio" name="watcher_type" id="watcher_name"/> <label class="inline">Name</label>&nbsp;&nbsp;  
74 - <input type="radio" name="watcher_type" id="watcher_email"/> <label class="inline">Email</label><br/><br/>  
75 - </div>  
76 - <div>  
77 - <select id="app_watchers_attributes_0_user_id" name="app[watchers_attributes][0][user_id]"><option value="">-- Select a User --</option>  
78 - <option value="4c654f41eacf8d2ae8000001">Errbit Admin</option></select>  
79 - <input id="app_watchers_attributes_0_email" name="app[watchers_attributes][0][email]" size="30" type="text" />  
80 - </div>  
81 - </div>  
82 - </fieldset>  
83 - <div class='add_app'><input id="app_submit" name="commit" type="submit" value="Add" /></div>  
84 - </form>  
85 - </div>  
86 - </div>  
87 - <div id='footer'>Powered by <a href="http://github.com/errbit/errbit" target="_blank">Errbit</a>: the open source Hoptoad server.</div>  
88 -  
89 - </body>  
90 -</html>  
spec/acceptance/watch_unwatch_app_spec.rb
1 require 'acceptance/acceptance_helper' 1 require 'acceptance/acceptance_helper'
2 2
3 feature 'A user can watch and unwatch an application' do 3 feature 'A user can watch and unwatch an application' do
4 -  
5 let!(:app) { Fabricate(:app) } 4 let!(:app) { Fabricate(:app) }
6 - let!(:user) do  
7 - user = Fabricate(:user)  
8 - app.watchers.create!(  
9 - :user_id => user.id  
10 - ) 5 + let!(:user) { Fabricate(:user) }
  6 +
  7 + scenario 'log in and unwatch a project' do
  8 + app.watchers.create!(user_id: user.id)
11 user.reload 9 user.reload
12 - end  
13 10
14 - scenario 'log in watch a project and unwatch it' do  
15 log_in user 11 log_in user
  12 + click_on app.name
16 click_on I18n.t('apps.show.unwatch') 13 click_on I18n.t('apps.show.unwatch')
17 - expect(page).to have_content(I18n.t('apps.index.no_apps')) 14 + expect(page).to have_content(
  15 + I18n.t('watchers.destroy.success', app: app.name))
18 end 16 end
19 17
  18 + scenario 'log in and watch a project' do
  19 + log_in user
  20 + click_on app.name
  21 + click_on I18n.t('apps.show.watch')
  22 + expect(page).to have_content(
  23 + I18n.t('watchers.update.success', app: app.name))
  24 + end
20 end 25 end
spec/controllers/apps_controller_spec.rb
@@ -39,12 +39,11 @@ describe AppsController, type: &#39;controller&#39; do @@ -39,12 +39,11 @@ describe AppsController, type: &#39;controller&#39; do
39 end 39 end
40 40
41 context 'when logged in as a regular user' do 41 context 'when logged in as a regular user' do
42 - it 'finds apps the user is watching' do  
43 - sign_in(user)  
44 - watched_app1 && watched_app2 && unwatched_app 42 + it 'finds all apps' do
  43 + sign_in user
  44 + unwatched_app && watched_app1 && watched_app2
45 get :index 45 get :index
46 - expect(controller.apps).to include(watched_app1, watched_app2)  
47 - expect(controller.apps).to_not include(unwatched_app) 46 + expect(controller.apps.entries).to eq App.all.sort.entries
48 end 47 end
49 end 48 end
50 end 49 end
@@ -163,19 +162,12 @@ describe AppsController, type: &#39;controller&#39; do @@ -163,19 +162,12 @@ describe AppsController, type: &#39;controller&#39; do
163 end 162 end
164 163
165 context 'logged in as a user' do 164 context 'logged in as a user' do
166 - it 'finds the app if the user is watching it' do  
167 - watcher  
168 - sign_in user  
169 - get :show, :id => app.id  
170 - expect(controller.app).to eq app  
171 - end  
172 -  
173 - it 'does not find the app if the user is not watching it' do 165 + it 'finds the app even when not watching it' do
174 sign_in Fabricate(:user) 166 sign_in Fabricate(:user)
175 app = Fabricate(:app) 167 app = Fabricate(:app)
176 - expect{  
177 - get :show, :id => app.id  
178 - }.to raise_error(Mongoid::Errors::DocumentNotFound) 168 +
  169 + get :show, :id => app.id
  170 + expect(controller.app).to eq app
179 end 171 end
180 end 172 end
181 end 173 end
spec/controllers/devise_sessions_controller_spec.rb
@@ -14,12 +14,6 @@ describe Devise::SessionsController, type: &#39;controller&#39; do @@ -14,12 +14,6 @@ describe Devise::SessionsController, type: &#39;controller&#39; do
14 expect(response).to redirect_to(root_path) 14 expect(response).to redirect_to(root_path)
15 end 15 end
16 16
17 - it 'redirects to app page if there is app for the user' do  
18 - Fabricate(:user_watcher, :app => app, :user => user)  
19 - post :create, { :user => { 'email' => user.email, 'password' => user.password } }  
20 - expect(response).to redirect_to(app_path(app))  
21 - end  
22 -  
23 it 'displays a friendly error when credentials are invalid' do 17 it 'displays a friendly error when credentials are invalid' do
24 post :create, { :user => { 'email' => 'whatever', 'password' => 'somethinginvalid' } } 18 post :create, { :user => { 'email' => 'whatever', 'password' => 'somethinginvalid' } }
25 expect(request.flash["alert"]).to eq(I18n.t 'devise.failure.user.email_invalid') 19 expect(request.flash["alert"]).to eq(I18n.t 'devise.failure.user.email_invalid')
spec/controllers/problems_controller_spec.rb
@@ -6,122 +6,94 @@ describe ProblemsController, type: &#39;controller&#39; do @@ -6,122 +6,94 @@ describe ProblemsController, type: &#39;controller&#39; do
6 6
7 let(:app) { Fabricate(:app) } 7 let(:app) { Fabricate(:app) }
8 let(:err) { Fabricate(:err, :problem => problem) } 8 let(:err) { Fabricate(:err, :problem => problem) }
9 - let(:admin) { Fabricate(:admin) } 9 + let(:user) { Fabricate(:user) }
10 let(:problem) { Fabricate(:problem, :app => app, :environment => "production") } 10 let(:problem) { Fabricate(:problem, :app => app, :environment => "production") }
11 11
12 describe "GET /problems" do 12 describe "GET /problems" do
13 - context 'when logged in as an admin' do 13 + before(:each) do
  14 + sign_in user
  15 + @problem = Fabricate(:notice, :err => Fabricate(:err, :problem => Fabricate(:problem, :app => app, :environment => "production"))).problem
  16 + end
  17 +
  18 + context "pagination" do
14 before(:each) do 19 before(:each) do
15 - sign_in admin  
16 - @problem = Fabricate(:notice, :err => Fabricate(:err, :problem => Fabricate(:problem, :app => app, :environment => "production"))).problem 20 + 35.times { Fabricate :err }
17 end 21 end
18 22
19 - context "pagination" do  
20 - before(:each) do  
21 - 35.times { Fabricate :err }  
22 - end  
23 -  
24 - it "should have default per_page value for user" do  
25 - get :index  
26 - expect(controller.problems.to_a.size).to eq User::PER_PAGE  
27 - end  
28 -  
29 - it "should be able to override default per_page value" do  
30 - admin.update_attribute :per_page, 10  
31 - get :index  
32 - expect(controller.problems.to_a.size).to eq 10  
33 - end 23 + it "should have default per_page value for user" do
  24 + get :index
  25 + expect(controller.problems.to_a.size).to eq User::PER_PAGE
34 end 26 end
35 27
36 - context 'with environment filters' do  
37 - before(:each) do  
38 - environments = ['production', 'test', 'development', 'staging']  
39 - 20.times do |i|  
40 - Fabricate(:problem, :environment => environments[i % environments.length])  
41 - end  
42 - end 28 + it "should be able to override default per_page value" do
  29 + user.update_attribute :per_page, 10
  30 + get :index
  31 + expect(controller.problems.to_a.size).to eq 10
  32 + end
  33 + end
43 34
44 - context 'no params' do  
45 - it 'shows problems for all environments' do  
46 - get :index  
47 - expect(controller.problems.size).to eq 21  
48 - end 35 + context 'with environment filters' do
  36 + before(:each) do
  37 + environments = ['production', 'test', 'development', 'staging']
  38 + 20.times do |i|
  39 + Fabricate(:problem, :environment => environments[i % environments.length])
49 end 40 end
  41 + end
50 42
51 - context 'environment production' do  
52 - it 'shows problems for just production' do  
53 - get :index, :environment => 'production'  
54 - expect(controller.problems.size).to eq 6  
55 - end 43 + context 'no params' do
  44 + it 'shows problems for all environments' do
  45 + get :index
  46 + expect(controller.problems.size).to eq 21
56 end 47 end
  48 + end
57 49
58 - context 'environment staging' do  
59 - it 'shows problems for just staging' do  
60 - get :index, :environment => 'staging'  
61 - expect(controller.problems.size).to eq 5  
62 - end 50 + context 'environment production' do
  51 + it 'shows problems for just production' do
  52 + get :index, :environment => 'production'
  53 + expect(controller.problems.size).to eq 6
63 end 54 end
  55 + end
64 56
65 - context 'environment development' do  
66 - it 'shows problems for just development' do  
67 - get :index, :environment => 'development'  
68 - expect(controller.problems.size).to eq 5  
69 - end 57 + context 'environment staging' do
  58 + it 'shows problems for just staging' do
  59 + get :index, :environment => 'staging'
  60 + expect(controller.problems.size).to eq 5
70 end 61 end
  62 + end
71 63
72 - context 'environment test' do  
73 - it 'shows problems for just test' do  
74 - get :index, :environment => 'test'  
75 - expect(controller.problems.size).to eq 5  
76 - end 64 + context 'environment development' do
  65 + it 'shows problems for just development' do
  66 + get :index, :environment => 'development'
  67 + expect(controller.problems.size).to eq 5
77 end 68 end
78 end 69 end
79 - end  
80 70
81 - context 'when logged in as a user' do  
82 - it 'gets a paginated list of unresolved problems for the users apps' do  
83 - sign_in(user = Fabricate(:user))  
84 - unwatched_err = Fabricate(:err)  
85 - watched_unresolved_err = Fabricate(:err, :problem => Fabricate(:problem, :app => Fabricate(:user_watcher, :user => user).app, :resolved => false))  
86 - watched_resolved_err = Fabricate(:err, :problem => Fabricate(:problem, :app => Fabricate(:user_watcher, :user => user).app, :resolved => true))  
87 - get :index  
88 - expect(controller.problems).to include(watched_unresolved_err.problem)  
89 - expect(controller.problems).to_not include(unwatched_err.problem, watched_resolved_err.problem) 71 + context 'environment test' do
  72 + it 'shows problems for just test' do
  73 + get :index, :environment => 'test'
  74 + expect(controller.problems.size).to eq 5
  75 + end
90 end 76 end
91 end 77 end
92 end 78 end
93 79
94 describe "GET /problems - previously all" do 80 describe "GET /problems - previously all" do
95 - context 'when logged in as an admin' do  
96 - it "gets a paginated list of all problems" do  
97 - sign_in admin  
98 - problems = Kaminari.paginate_array((1..30).to_a)  
99 - 3.times { problems << Fabricate(:err).problem }  
100 - 3.times { problems << Fabricate(:err, :problem => Fabricate(:problem, :resolved => true)).problem }  
101 - expect(Problem).to receive(:ordered_by).and_return(  
102 - double('proxy', :page => double('other_proxy', :per => problems))  
103 - )  
104 - get :index, :all_errs => true  
105 - expect(controller.problems).to eq problems  
106 - end  
107 - end  
108 -  
109 - context 'when logged in as a user' do  
110 - it 'gets a paginated list of all problems for the users apps' do  
111 - sign_in(user = Fabricate(:user))  
112 - unwatched_problem = Fabricate(:problem)  
113 - watched_unresolved_problem = Fabricate(:problem, :app => Fabricate(:user_watcher, :user => user).app, :resolved => false)  
114 - watched_resolved_problem = Fabricate(:problem, :app => Fabricate(:user_watcher, :user => user).app, :resolved => true)  
115 - get :index, :all_errs => true  
116 - expect(controller.problems).to include(watched_resolved_problem, watched_unresolved_problem)  
117 - expect(controller.problems).to_not include(unwatched_problem)  
118 - end 81 + it "gets a paginated list of all problems" do
  82 + sign_in Fabricate(:user)
  83 + problems = Kaminari.paginate_array((1..30).to_a)
  84 + 3.times { problems << Fabricate(:err).problem }
  85 + 3.times { problems << Fabricate(:err, :problem => Fabricate(:problem, :resolved => true)).problem }
  86 + expect(Problem).to receive(:ordered_by).and_return(
  87 + double('proxy', :page => double('other_proxy', :per => problems))
  88 + )
  89 + get :index, :all_errs => true
  90 + expect(controller.problems).to eq problems
119 end 91 end
120 end 92 end
121 93
122 describe "GET /problems/search" do 94 describe "GET /problems/search" do
123 before do 95 before do
124 - sign_in Fabricate(:admin) 96 + sign_in user
125 @app = Fabricate(:app) 97 @app = Fabricate(:app)
126 @problem1 = Fabricate(:problem, :app=>@app, message: "Most important") 98 @problem1 = Fabricate(:problem, :app=>@app, message: "Most important")
127 @problem2 = Fabricate(:problem, :app=>@app, message: "Very very important") 99 @problem2 = Fabricate(:problem, :app=>@app, message: "Very very important")
@@ -145,73 +117,49 @@ describe ProblemsController, type: &#39;controller&#39; do @@ -145,73 +117,49 @@ describe ProblemsController, type: &#39;controller&#39; do
145 end 117 end
146 118
147 describe "GET /apps/:app_id/problems/:id" do 119 describe "GET /apps/:app_id/problems/:id" do
148 - context 'when logged in as an admin' do  
149 - before do  
150 - sign_in admin  
151 - end  
152 -  
153 - it "finds the app" do  
154 - get :show, :app_id => app.id, :id => err.problem.id  
155 - expect(controller.app).to eq app  
156 - end  
157 -  
158 - it "finds the problem" do  
159 - get :show, :app_id => app.id, :id => err.problem.id  
160 - expect(controller.problem).to eq err.problem  
161 - end  
162 -  
163 - it "successfully render page" do  
164 - get :show, :app_id => app.id, :id => err.problem.id  
165 - expect(response).to be_success  
166 - end  
167 -  
168 - context 'pagination' do  
169 - let!(:notices) do  
170 - 3.times.reduce([]) do |coll, i|  
171 - coll << Fabricate(:notice, :err => err, :created_at => (Time.now + i))  
172 - end  
173 - end 120 + before do
  121 + sign_in user
  122 + end
174 123
175 - it "paginates the notices 1 at a time, starting with the most recent" do  
176 - get :show, :app_id => app.id, :id => err.problem.id  
177 - expect(assigns(:notices).entries.count).to eq 1  
178 - expect(assigns(:notices)).to include(notices.last)  
179 - end 124 + it "finds the app" do
  125 + get :show, :app_id => app.id, :id => err.problem.id
  126 + expect(controller.app).to eq app
  127 + end
180 128
181 - it "paginates the notices 1 at a time, based on then notice param" do  
182 - get :show, :app_id => app.id, :id => err.problem.id, :notice => 3  
183 - expect(assigns(:notices).entries.count).to eq 1  
184 - expect(assigns(:notices)).to include(notices.first)  
185 - end  
186 - end 129 + it "finds the problem" do
  130 + get :show, :app_id => app.id, :id => err.problem.id
  131 + expect(controller.problem).to eq err.problem
  132 + end
187 133
  134 + it "successfully render page" do
  135 + get :show, :app_id => app.id, :id => err.problem.id
  136 + expect(response).to be_success
188 end 137 end
189 138
190 - context 'when logged in as a user' do  
191 - before do  
192 - sign_in(@user = Fabricate(:user))  
193 - @unwatched_err = Fabricate(:err)  
194 - @watched_app = Fabricate(:app)  
195 - @watcher = Fabricate(:user_watcher, :user => @user, :app => @watched_app)  
196 - @watched_err = Fabricate(:err, :problem => Fabricate(:problem, :app => @watched_app)) 139 + context 'pagination' do
  140 + let!(:notices) do
  141 + 3.times.reduce([]) do |coll, i|
  142 + coll << Fabricate(:notice, :err => err, :created_at => (Time.now + i))
  143 + end
197 end 144 end
198 145
199 - it 'finds the problem if the user is watching the app' do  
200 - get :show, :app_id => @watched_app.to_param, :id => @watched_err.problem.id  
201 - expect(controller.problem).to eq @watched_err.problem 146 + it "paginates the notices 1 at a time, starting with the most recent" do
  147 + get :show, :app_id => app.id, :id => err.problem.id
  148 + expect(assigns(:notices).entries.count).to eq 1
  149 + expect(assigns(:notices)).to include(notices.last)
202 end 150 end
203 151
204 - it 'raises a DocumentNotFound error if the user is not watching the app' do  
205 - expect {  
206 - get :show, :app_id => @unwatched_err.problem.app_id, :id => @unwatched_err.problem.id  
207 - }.to raise_error(Mongoid::Errors::DocumentNotFound) 152 + it "paginates the notices 1 at a time, based on then notice param" do
  153 + get :show, :app_id => app.id, :id => err.problem.id, :notice => 3
  154 + expect(assigns(:notices).entries.count).to eq 1
  155 + expect(assigns(:notices)).to include(notices.first)
208 end 156 end
209 end 157 end
210 end 158 end
211 159
212 describe "PUT /apps/:app_id/problems/:id/resolve" do 160 describe "PUT /apps/:app_id/problems/:id/resolve" do
213 before do 161 before do
214 - sign_in admin 162 + sign_in user
215 163
216 @err = Fabricate(:err) 164 @err = Fabricate(:err)
217 end 165 end
@@ -245,7 +193,7 @@ describe ProblemsController, type: &#39;controller&#39; do @@ -245,7 +193,7 @@ describe ProblemsController, type: &#39;controller&#39; do
245 end 193 end
246 194
247 describe "POST /apps/:app_id/problems/:id/create_issue" do 195 describe "POST /apps/:app_id/problems/:id/create_issue" do
248 - before { sign_in admin } 196 + before { sign_in user }
249 197
250 context "when app has a issue tracker" do 198 context "when app has a issue tracker" do
251 let(:notice) { NoticeDecorator.new(Fabricate :notice) } 199 let(:notice) { NoticeDecorator.new(Fabricate :notice) }
@@ -259,7 +207,7 @@ describe ProblemsController, type: &#39;controller&#39; do @@ -259,7 +207,7 @@ describe ProblemsController, type: &#39;controller&#39; do
259 before do 207 before do
260 problem.app.issue_tracker = issue_tracker 208 problem.app.issue_tracker = issue_tracker
261 allow(controller).to receive(:problem).and_return(problem) 209 allow(controller).to receive(:problem).and_return(problem)
262 - allow(controller).to receive(:current_user).and_return(admin) 210 + allow(controller).to receive(:current_user).and_return(user)
263 end 211 end
264 212
265 it "should redirect to problem page" do 213 it "should redirect to problem page" do
@@ -316,7 +264,7 @@ describe ProblemsController, type: &#39;controller&#39; do @@ -316,7 +264,7 @@ describe ProblemsController, type: &#39;controller&#39; do
316 264
317 describe "DELETE /apps/:app_id/problems/:id/unlink_issue" do 265 describe "DELETE /apps/:app_id/problems/:id/unlink_issue" do
318 before(:each) do 266 before(:each) do
319 - sign_in admin 267 + sign_in user
320 end 268 end
321 269
322 context "problem with issue" do 270 context "problem with issue" do
@@ -352,7 +300,7 @@ describe ProblemsController, type: &#39;controller&#39; do @@ -352,7 +300,7 @@ describe ProblemsController, type: &#39;controller&#39; do
352 300
353 describe "Bulk Actions" do 301 describe "Bulk Actions" do
354 before(:each) do 302 before(:each) do
355 - sign_in admin 303 + sign_in user
356 @problem1 = Fabricate(:err, :problem => Fabricate(:problem, :resolved => true)).problem 304 @problem1 = Fabricate(:err, :problem => Fabricate(:problem, :resolved => true)).problem
357 @problem2 = Fabricate(:err, :problem => Fabricate(:problem, :resolved => false)).problem 305 @problem2 = Fabricate(:err, :problem => Fabricate(:problem, :resolved => false)).problem
358 end 306 end
@@ -434,7 +382,7 @@ describe ProblemsController, type: &#39;controller&#39; do @@ -434,7 +382,7 @@ describe ProblemsController, type: &#39;controller&#39; do
434 382
435 describe "POST /apps/:app_id/problems/destroy_all" do 383 describe "POST /apps/:app_id/problems/destroy_all" do
436 before do 384 before do
437 - sign_in Fabricate(:admin) 385 + sign_in user
438 @app = Fabricate(:app) 386 @app = Fabricate(:app)
439 @problem1 = Fabricate(:problem, :app=>@app) 387 @problem1 = Fabricate(:problem, :app=>@app)
440 @problem2 = Fabricate(:problem, :app=>@app) 388 @problem2 = Fabricate(:problem, :app=>@app)
spec/controllers/watchers_controller_spec.rb
1 describe WatchersController, type: 'controller' do 1 describe WatchersController, type: 'controller' do
2 - let(:app) do  
3 - a = Fabricate(:app)  
4 - Fabricate(:user_watcher, :app => a)  
5 - a  
6 - end 2 + let(:user) { Fabricate(:user) }
  3 + let(:problem) { Fabricate(:problem) }
  4 +
  5 + before(:each) { sign_in user }
  6 +
  7 + describe "#destroy" do
  8 + let(:app) do
  9 + a = Fabricate(:app)
  10 + Fabricate(:user_watcher, app: a, user: user)
  11 + a
  12 + end
  13 +
  14 + context "successful watcher deletion" do
  15 + let(:watcher) { app.watchers.first }
7 16
8 - describe "DELETE /apps/:app_id/watchers/:id/destroy" do  
9 - context "with admin user" do  
10 before(:each) do 17 before(:each) do
11 - sign_in Fabricate(:admin) 18 + delete :destroy, :app_id => app.id, :id => watcher.user.id.to_s
  19 + problem.reload
  20 + end
  21 +
  22 + it "should delete the watcher" do
  23 + expect(app.watchers.detect{|w| w.id.to_s == watcher.id }).to be nil
12 end 24 end
13 25
14 - context "successful watcher deletion" do  
15 - let(:problem) { Fabricate(:problem_with_comments) }  
16 - let(:watcher) { app.watchers.first } 26 + it "should redirect to app page" do
  27 + expect(response).to redirect_to(app_path(app))
  28 + end
  29 + end
  30 + end
17 31
18 - before(:each) do  
19 - delete :destroy, :app_id => app.id, :id => watcher.user.id.to_s  
20 - problem.reload  
21 - end 32 + describe "#update" do
  33 + let(:app) { Fabricate(:app) }
22 34
23 - it "should delete the watcher" do  
24 - expect(app.watchers.detect{|w| w.id.to_s == watcher.id }).to be nil  
25 - end 35 + context "successful watcher update" do
  36 + before(:each) do
  37 + put :update, :app_id => app.id, :id => user.id.to_s
  38 + problem.reload
  39 + end
  40 +
  41 + it "should be watching" do
  42 + app.reload
  43 + expect(app.watchers.first.user_id).to eq user.id
  44 + end
26 45
27 - it "should redirect to index page" do  
28 - expect(response).to redirect_to(root_path)  
29 - end 46 + it "should redirect to app page" do
  47 + expect(response).to redirect_to(app_path(app))
30 end 48 end
31 end 49 end
32 end 50 end
spec/models/user_spec.rb
@@ -37,24 +37,6 @@ describe User do @@ -37,24 +37,6 @@ describe User do
37 end 37 end
38 end 38 end
39 39
40 - context 'Watchers' do  
41 - it 'has many watchers' do  
42 - user = Fabricate(:user)  
43 - watcher = Fabricate(:user_watcher, :user => user)  
44 - expect(user.watchers).to_not be_empty  
45 - expect(user.watchers).to include(watcher)  
46 - end  
47 -  
48 - it "has many apps through watchers" do  
49 - user = Fabricate(:user)  
50 - watched_app = Fabricate(:app)  
51 - unwatched_app = Fabricate(:app)  
52 - Fabricate(:user_watcher, :app => watched_app, :user => user)  
53 - expect(user.apps.all).to include(watched_app)  
54 - expect(user.apps.all).to_not include(unwatched_app)  
55 - end  
56 - end  
57 -  
58 context "First user" do 40 context "First user" do
59 it "should be created this admin access via db:seed" do 41 it "should be created this admin access via db:seed" do
60 expect { 42 expect {
spec/views/apps/show.html.haml_spec.rb
@@ -30,7 +30,7 @@ describe &quot;apps/show.html.haml&quot;, type: &#39;view&#39; do @@ -30,7 +30,7 @@ describe &quot;apps/show.html.haml&quot;, type: &#39;view&#39; do
30 30
31 context "with user watch application" do 31 context "with user watch application" do
32 before do 32 before do
33 - allow(user).to receive(:watching?).with(app).and_return(true) 33 + allow(app).to receive(:watched_by?).with(user).and_return(true)
34 end 34 end
35 it 'see the unwatch button' do 35 it 'see the unwatch button' do
36 render 36 render
@@ -40,7 +40,7 @@ describe &quot;apps/show.html.haml&quot;, type: &#39;view&#39; do @@ -40,7 +40,7 @@ describe &quot;apps/show.html.haml&quot;, type: &#39;view&#39; do
40 40
41 context "with user not watch application" do 41 context "with user not watch application" do
42 before do 42 before do
43 - allow(user).to receive(:watching?).with(app).and_return(false) 43 + allow(app).to receive(:watched_by?).with(user).and_return(false)
44 end 44 end
45 it 'not see the unwatch button' do 45 it 'not see the unwatch button' do
46 render 46 render