From 9078c463f4287f2d504695fe6b7773f1513b51bb Mon Sep 17 00:00:00 2001 From: Mark Moser Date: Thu, 22 Sep 2016 13:30:30 -0500 Subject: [PATCH] move recruiter to admin/candidate --- app/controllers/admin/candidate_controller.rb | 70 ++++++++++++++++ app/controllers/recruiter_controller.rb | 80 ------------------- app/models/user.rb | 16 ++++ app/policies/candidate_policy.rb | 33 ++++++++ app/policies/question_policy.rb | 16 ++-- app/policies/quiz_policy.rb | 6 +- app/policies/user_policy.rb | 12 +-- .../candidate}/_form.html.erb | 0 app/views/admin/candidate/edit.html.erb | 6 ++ .../candidate}/index.html.erb | 6 +- app/views/admin/candidate/new.html.erb | 6 ++ app/views/recruiter/edit.html.erb | 6 -- app/views/recruiter/login.html.erb | 21 ----- app/views/recruiter/new.html.erb | 6 -- config/routes.rb | 54 ++++++------- .../admin/candidate_controller/index_test.rb | 31 +++++++ .../new_candidate_test.rb | 73 +++++++++++++++++ .../update_candidate_test.rb | 36 +++++++++ .../recruiter_controller/index_test.rb | 56 ------------- .../new_candidate_test.rb | 71 ---------------- .../update_candidate_test.rb | 34 -------- test/controllers/review_controller_test.rb | 2 +- test/policies/candidate_policy_test.rb | 48 +++++++++++ test/policies/question_policy_test.rb | 2 +- test/test_helpers/auth_test_helper.rb | 19 ++++- 25 files changed, 383 insertions(+), 327 deletions(-) create mode 100644 app/controllers/admin/candidate_controller.rb delete mode 100644 app/controllers/recruiter_controller.rb create mode 100644 app/policies/candidate_policy.rb rename app/views/{recruiter => admin/candidate}/_form.html.erb (100%) create mode 100644 app/views/admin/candidate/edit.html.erb rename app/views/{recruiter => admin/candidate}/index.html.erb (71%) create mode 100644 app/views/admin/candidate/new.html.erb delete mode 100644 app/views/recruiter/edit.html.erb delete mode 100644 app/views/recruiter/login.html.erb delete mode 100644 app/views/recruiter/new.html.erb create mode 100644 test/controllers/admin/candidate_controller/index_test.rb create mode 100644 test/controllers/admin/candidate_controller/new_candidate_test.rb create mode 100644 test/controllers/admin/candidate_controller/update_candidate_test.rb delete mode 100644 test/controllers/recruiter_controller/index_test.rb delete mode 100644 test/controllers/recruiter_controller/new_candidate_test.rb delete mode 100644 test/controllers/recruiter_controller/update_candidate_test.rb create mode 100644 test/policies/candidate_policy_test.rb diff --git a/app/controllers/admin/candidate_controller.rb b/app/controllers/admin/candidate_controller.rb new file mode 100644 index 0000000..6eaf61f --- /dev/null +++ b/app/controllers/admin/candidate_controller.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true +module Admin + class CandidateController < AdminController + before_action :collect_quizzes, except: [:login, :auth] + + def index + @candidates = policy_scope current_recruiter.candidates + end + + def new + authorize Candidate + @candidate = Candidate.new + render :new + end + + def create + authorize Candidate + @candidate = Candidate.create(candidate_params.merge(recruiter_id: current_recruiter.id)) + + if @candidate.persisted? + send_notifications @candidate + redirect_to admin_candidate_path, + flash: { success: "Sucessfully created candidate #{@candidate.name}" } + else + flash[:error] = "Failed to save candidate." + render :new + end + end + + def edit + authorize Candidate + @candidate = Candidate.find_by(id: params[:id]) + end + + def update + authorize Candidate + @candidate = Candidate.find_by(id: params[:id]) + @candidate.update(candidate_params) + + if @candidate.save + redirect_to admin_candidate_path, flash: { success: "#{@candidate.name} updated!" } + else + flash[:error] = "Failed to save candidate." + render :edit + end + end + + def resend_welcome + authorize Candidate + candidate = Candidate.find_by(id: params[:id]) + CandidateMailer.welcome(candidate).deliver_later + render json: { message: "Email queued!" }.to_json + end + + private + + def candidate_params + params.require(:candidate).permit(:name, :email, :experience, :quiz_id) + end + + def collect_quizzes + @quizzes ||= Quiz.order(:name) + end + + def send_notifications candidate + CandidateMailer.welcome(candidate).deliver_later + RecruiterMailer.candidate_created(candidate).deliver_later + end + end +end diff --git a/app/controllers/recruiter_controller.rb b/app/controllers/recruiter_controller.rb deleted file mode 100644 index a8b32cb..0000000 --- a/app/controllers/recruiter_controller.rb +++ /dev/null @@ -1,80 +0,0 @@ -# frozen_string_literal: true -class RecruiterController < ApplicationController - before_action :authorize_recruiter, except: [:login, :auth] - before_action :collect_quizzes, except: [:login, :auth] - - def index - @candidates = current_recruiter.candidates - end - - def new - @candidate = Candidate.new - render :new - end - - def create - @candidate = Candidate.create(candidate_params.merge(recruiter_id: current_recruiter.id)) - - if @candidate.persisted? - CandidateMailer.welcome(@candidate).deliver_later - RecruiterMailer.candidate_created(@candidate).deliver_later - redirect_to recruiter_path, flash: { success: "Sucessfully created candidate #{@candidate.name}" } - else - flash[:error] = "Failed to save candidate." - render :new - end - end - - def edit - @candidate = Candidate.find_by(id: params[:id]) - end - - def update - @candidate = Candidate.find_by(id: params[:id]) - @candidate.update(candidate_params) - - if @candidate.save - redirect_to recruiter_path, flash: { success: "#{@candidate.name} updated!" } - else - flash[:error] = "Failed to save candidate." - render :edit - end - end - - def login - redirect_to recruiter_path unless current_recruiter.nil? - end - - def auth - recruiter = User.find_by(email: auth_params[:email], role: %w(admin recruiter)) - - if recruiter && recruiter.authenticate(auth_params[:password]) - session[:user] = recruiter.to_i - redirect_to recruiter_path - else - redirect_to recruiter_login_path, - flash: { error: "Sorry, incorrect email or password. Please try again." } - end - end - - def logout - reset_session - redirect_to recruiter_login_path - end - - def resend_welcome - candidate = Candidate.find_by(id: params[:id]) - CandidateMailer.welcome(candidate).deliver_later - render json: { message: "Email queued!" }.to_json - end - - private - - def candidate_params - params.require(:candidate).permit(:name, :email, :experience, :quiz_id) - end - - def collect_quizzes - @quizzes ||= Quiz.order(:name) - end -end diff --git a/app/models/user.rb b/app/models/user.rb index a44ec5b..35ed228 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -20,7 +20,15 @@ class User < ApplicationRecord 'admin' == role end + def acts_as_admin? + 'admin' == role + end + def manager? + 'manager' == role + end + + def acts_as_manager? %w(admin manager).include? role end @@ -28,10 +36,18 @@ class User < ApplicationRecord 'recruiter' == role end + def acts_as_recruiter? + %w(admin recruiter).include? role + end + def reviewer? 'reviewer' == role end + def acts_as_reviewer? + %w(admin reviewer).include? role + end + private def gen_reset_token diff --git a/app/policies/candidate_policy.rb b/app/policies/candidate_policy.rb new file mode 100644 index 0000000..4e6418f --- /dev/null +++ b/app/policies/candidate_policy.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true +class CandidatePolicy < ApplicationPolicy + # Candidate Access Policy + # + # Only Recruiters and Admins can view, create, or update, candidates + + def index? + user.acts_as_recruiter? + end + + def view? + user.acts_as_recruiter? + end + + def create? + user.acts_as_recruiter? + end + + def update? + user.acts_as_recruiter? + end + + def resend_welcome? + user.acts_as_recruiter? + end + + class Scope < Scope + def resolve + return scope if user.acts_as_recruiter? + raise Pundit::NotAuthorizedError, "No Access to Resource" + end + end +end diff --git a/app/policies/question_policy.rb b/app/policies/question_policy.rb index 2c64165..f578844 100644 --- a/app/policies/question_policy.rb +++ b/app/policies/question_policy.rb @@ -8,27 +8,27 @@ class QuestionPolicy < ApplicationPolicy def view? return false if user.recruiter? - return true if user.admin? || user.manager? + return true if user.acts_as_manager? user.quizzes.include? record.quiz end + def options? + view? + end + def create? - user.manager? || user.admin? + user.acts_as_manager? end def update? - user.manager? || user.admin? - end - - def options? - !user.recruiter? + user.acts_as_manager? end class Scope < Scope def resolve raise(Pundit::NotAuthorizedError, 'No Access to resource.') if user.recruiter? - if user.admin? || user.manager? + if user.acts_as_manager? scope else scope.where(quiz_id: user.quizzes.map(&:id)) diff --git a/app/policies/quiz_policy.rb b/app/policies/quiz_policy.rb index 4b2dc56..6f80113 100644 --- a/app/policies/quiz_policy.rb +++ b/app/policies/quiz_policy.rb @@ -11,16 +11,16 @@ class QuizPolicy < ApplicationPolicy end def view? - return true if user.admin? || user.manager? + return true if user.acts_as_manager? user.quizzes.include? record end def create? - user.manager? || user.admin? + user.acts_as_manager? end def update? - user.manager? || user.admin? + user.acts_as_manager? end class Scope < Scope diff --git a/app/policies/user_policy.rb b/app/policies/user_policy.rb index c02a137..00a81f5 100644 --- a/app/policies/user_policy.rb +++ b/app/policies/user_policy.rb @@ -6,29 +6,29 @@ class UserPolicy < ApplicationPolicy # All other users can only access themselves (profile interface) def index? - user.admin? + user.acts_as_admin? end def view? - user.admin? || user == record + user.acts_as_admin? || user == record end def create? - user.admin? + user.acts_as_admin? end def update? - user.admin? || user == record + user.acts_as_admin? || user == record end def permitted_attributes - return [:name, :email, :role, :password, quiz_ids: []] if user.admin? + return [:name, :email, :role, :password, quiz_ids: []] if user.acts_as_admin? [:name, :email, :password, :password_confirmation] end class Scope < Scope def resolve - return scope if user.admin? + return scope if user.acts_as_admin? scope.where(id: user.id) end end diff --git a/app/views/recruiter/_form.html.erb b/app/views/admin/candidate/_form.html.erb similarity index 100% rename from app/views/recruiter/_form.html.erb rename to app/views/admin/candidate/_form.html.erb diff --git a/app/views/admin/candidate/edit.html.erb b/app/views/admin/candidate/edit.html.erb new file mode 100644 index 0000000..5de8973 --- /dev/null +++ b/app/views/admin/candidate/edit.html.erb @@ -0,0 +1,6 @@ +
+

Edit: <%= @candidate.name %>

+

Test ID: <%= @candidate.test_hash %>

+ + <%= render partial: 'form', locals: { action: admin_update_candidate_path(@candidate.id), candidate: @candidate, quizzes: @quizzes } %> +
diff --git a/app/views/recruiter/index.html.erb b/app/views/admin/candidate/index.html.erb similarity index 71% rename from app/views/recruiter/index.html.erb rename to app/views/admin/candidate/index.html.erb index c7fc407..e6095fc 100644 --- a/app/views/recruiter/index.html.erb +++ b/app/views/admin/candidate/index.html.erb @@ -1,7 +1,7 @@

Candidates

- <%= link_to(new_candidate_path, { class: 'secondary-btn' }) do %> + <%= link_to(admin_new_candidate_path, { class: 'secondary-btn' }) do %> <% end %> @@ -18,12 +18,12 @@ <% @candidates.each do |candidate| %> - <%= link_to candidate.name, edit_candidate_path(candidate.id) %> + <%= link_to candidate.name, admin_edit_candidate_path(candidate.id) %> <%= candidate.test_hash %> <%= mail_to(candidate.email) %>
- <%= link_to "resend welcome email", resend_welcome_path(candidate.id), remote: true, class: '', data: { id: 'ajax-action' } %> + <%= link_to "resend welcome email", admin_resend_welcome_path(candidate.id), remote: true, class: '', data: { id: 'ajax-action' } %> <%= candidate.experience %> years <%= candidate.status %> diff --git a/app/views/admin/candidate/new.html.erb b/app/views/admin/candidate/new.html.erb new file mode 100644 index 0000000..c529467 --- /dev/null +++ b/app/views/admin/candidate/new.html.erb @@ -0,0 +1,6 @@ +
+

New Candidate

+ + <%= render partial: 'form', locals: + { action: admin_create_candidate_path, candidate: @candidate, quizzes: @quizzes } %> +
diff --git a/app/views/recruiter/edit.html.erb b/app/views/recruiter/edit.html.erb deleted file mode 100644 index dc6aff7..0000000 --- a/app/views/recruiter/edit.html.erb +++ /dev/null @@ -1,6 +0,0 @@ -
-

Edit: <%= @candidate.name %>

-

Test ID: <%= @candidate.test_hash %>

- - <%= render partial: 'form', locals: { action: update_candidate_path(@candidate.id), candidate: @candidate, quizzes: @quizzes } %> -
diff --git a/app/views/recruiter/login.html.erb b/app/views/recruiter/login.html.erb deleted file mode 100644 index 9d4098d..0000000 --- a/app/views/recruiter/login.html.erb +++ /dev/null @@ -1,21 +0,0 @@ -
-

Recruiter Login

- - <% if flash[:error].present? %> -
<%= flash[:error] %>
- <% end %> - - <%= form_for :auth, url: recruiter_login_path do |form| %> -
- <%= form.label :email %> - <%= form.email_field :email %> -
- -
- <%= form.label :password %> - <%= form.password_field :password %> -
- - <%= submit_tag "Log in" %> - <% end %> -
diff --git a/app/views/recruiter/new.html.erb b/app/views/recruiter/new.html.erb deleted file mode 100644 index 7892256..0000000 --- a/app/views/recruiter/new.html.erb +++ /dev/null @@ -1,6 +0,0 @@ -
-

New Candidate

- - <%= render partial: 'form', locals: - { action: create_candidate_path, candidate: @candidate, quizzes: @quizzes } %> -
diff --git a/config/routes.rb b/config/routes.rb index 41c8002..1fd272b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,8 @@ # frozen_string_literal: true Rails.application.routes.draw do + get "/styleguide", to: "application#styleguide", as: :styleguide + get "/admin/styleguide", to: "application#styleguide" + post "/admin/login", to: "admin/auth#auth", as: :admin_auth get "/admin/login", to: "admin/auth#login", as: :admin_login get "/admin/logout", to: "admin/auth#logout", as: :admin_logout @@ -33,26 +36,16 @@ Rails.application.routes.draw do post "/admin/question/:question_id/edit", to: "admin/question#update", as: :admin_update_question patch "/admin/question/:question_id/edit", to: "admin/question#update" - get "/admin/profile", to: "admin/profile#view", as: :admin_profile - post "/admin/profile", to: "admin/profile#update", as: :admin_update_profile - get "/admin/profile/edit", to: "admin/profile#edit", as: :admin_edit_profile + get "/admin/profile", to: "admin/profile#view", as: :admin_profile + post "/admin/profile", to: "admin/profile#update", as: :admin_update_profile + get "/admin/profile/edit", to: "admin/profile#edit", as: :admin_edit_profile - get "/admin", to: "admin/dashboard#show", as: :admin - - ######################################################################################### - - post "/validate", to: "candidate#validate", as: :validate_candidate - get "/login(/:test_id)", to: "candidate#login", as: :login - get "/welcome", to: "candidate#welcome", as: :welcome - get "/saved", to: "candidate#saved", as: :saved - get "/thankyou", to: "candidate#thankyou", as: :thankyou - - get "/oops", to: "candidate#oops", as: :oops - - post "/question(/:answer_id)", to: "quiz#update_answer", as: :post_answer - get "/question(/:question_id)", to: "quiz#question", as: :question - post "/summary", to: "quiz#submit_summary", as: :post_summary - get "/summary", to: "quiz#summary", as: :summary + get "/admin/candidate", to: "admin/candidate#index", as: :admin_candidate + get "/admin/candidate/new", to: "admin/candidate#new", as: :admin_new_candidate + post "/admin/candidate/new", to: "admin/candidate#create", as: :admin_create_candidate + get "/admin/candidate/:id", to: "admin/candidate#edit", as: :admin_edit_candidate + post "/admin/candidate/:id", to: "admin/candidate#update", as: :admin_update_candidate + get "/admin/candidate/:id/resend", to: "admin/candidate#resend_welcome", as: :admin_resend_welcome get "/review/logout", to: "review#logout", as: :review_logout post "/review/login", to: "review#auth", as: :review_auth @@ -60,18 +53,21 @@ Rails.application.routes.draw do get "/review", to: "review#index", as: :review get "/review/:test_hash", to: "review#view", as: :review_test - get "/resend/welcome/:id", to: "recruiter#resend_welcome", as: :resend_welcome + get "/admin", to: "admin/dashboard#show", as: :admin - get "/recruiter", to: "recruiter#index", as: :recruiter - get "/recruiter/candidate", to: "recruiter#new", as: :new_candidate - post "/recruiter/candidate", to: "recruiter#create", as: :create_candidate - get "/recruiter/candidate/:id", to: "recruiter#edit", as: :edit_candidate - post "/recruiter/candidate/:id", to: "recruiter#update", as: :update_candidate - get "/recruiter/logout", to: "recruiter#logout", as: :recruiter_logout - get "/recruiter/login", to: "recruiter#login", as: :recruiter_login - post "/recruiter/login", to: "recruiter#auth", as: :recruiter_auth + ######################################################################################### - get "/styleguide", to: "application#styleguide", as: :styleguide + post "/validate", to: "candidate#validate", as: :validate_candidate + get "/login(/:test_id)", to: "candidate#login", as: :login + get "/welcome", to: "candidate#welcome", as: :welcome + get "/saved", to: "candidate#saved", as: :saved + get "/thankyou", to: "candidate#thankyou", as: :thankyou + get "/oops", to: "candidate#oops", as: :oops + + post "/question(/:answer_id)", to: "quiz#update_answer", as: :post_answer + get "/question(/:question_id)", to: "quiz#question", as: :question + post "/summary", to: "quiz#submit_summary", as: :post_summary + get "/summary", to: "quiz#summary", as: :summary root to: "candidate#login" diff --git a/test/controllers/admin/candidate_controller/index_test.rb b/test/controllers/admin/candidate_controller/index_test.rb new file mode 100644 index 0000000..d9c2b11 --- /dev/null +++ b/test/controllers/admin/candidate_controller/index_test.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true +require 'test_helper' + +module Admin + class CandidateControllerTest < ActionDispatch::IntegrationTest + test "should require auth or redirect" do + get admin_candidate_url + assert_redirected_to admin_login_url + + get admin_new_candidate_url + assert_redirected_to admin_login_url + + post admin_create_candidate_url, params: { candidate: { name: 'foo', email: 'bar', experience: 'baz' } } + assert_redirected_to admin_login_url + end + + test "should get candidate list" do + auth_recruiter + get admin_candidate_url + assert_response :success + assert assigns(:candidates), "@candidates not present" + end + + test 'should have edit links' do + auth_recruiter + get admin_candidate_url + assert_response :success + assert_select "a[href='#{admin_edit_candidate_path(candidates(:martha))}']" + end + end +end diff --git a/test/controllers/admin/candidate_controller/new_candidate_test.rb b/test/controllers/admin/candidate_controller/new_candidate_test.rb new file mode 100644 index 0000000..50fb582 --- /dev/null +++ b/test/controllers/admin/candidate_controller/new_candidate_test.rb @@ -0,0 +1,73 @@ +# frozen_string_literal: true +require 'test_helper' + +module Admin + class CandidateControllerTest < ActionDispatch::IntegrationTest + include ActiveJob::TestHelper + + test "should get new" do + auth_recruiter + get admin_new_candidate_url + assert_response :success + assert assigns(:candidate), "@candidate not present" + end + + test "should get create" do + auth_recruiter + get admin_create_candidate_url + assert_response :success + end + + test "should create new candidate" do + auth_recruiter + + assert_enqueued_jobs 2 do + assert_difference("Candidate.count") do + post admin_create_candidate_path, params: { candidate: + { name: 'new name', email: 'test@mailinator.com', experience: '0-3', quiz_id: quizzes(:fed).id } } + end + end + assert_redirected_to admin_candidate_path + assert flash[:success] + end + + test "should fail creation with improper email format" do + auth_recruiter + + assert_enqueued_jobs 0 do + assert_difference("Candidate.count", 0) do + post admin_create_candidate_path, params: { candidate: + { name: 'new name', email: 'test@mailinatorcom', experience: '0-3', quiz_id: quizzes(:fed).id } } + end + end + assert :success + assert assigns(:candidate), "@candidate not present" + assert_match(/failed.*save/i, flash[:error]) + end + + test "should fail creation gracefully with empty email" do + auth_recruiter + + assert_enqueued_jobs 0 do + assert_difference("Candidate.count", 0) do + post admin_create_candidate_path, params: { candidate: + { name: 'new name', email: "", experience: '0-3', quiz_id: quizzes(:fed).id } } + end + end + assert :success + assert assigns(:candidate), "@candidate not present" + assert_match(/failed.*save/i, flash[:error]) + end + + test 'should queue up a welcome email [resend]' do + auth_recruiter + + assert_enqueued_jobs 1 do + get admin_resend_welcome_path(id: candidates(:peggy)), xhr: true + end + assert_response :success + data = JSON.parse(response.body) + assert_match 'queued', data["message"] + end + end +end diff --git a/test/controllers/admin/candidate_controller/update_candidate_test.rb b/test/controllers/admin/candidate_controller/update_candidate_test.rb new file mode 100644 index 0000000..25a6efc --- /dev/null +++ b/test/controllers/admin/candidate_controller/update_candidate_test.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true +require 'test_helper' + +module Admin + class CandidateControllerTest < ActionDispatch::IntegrationTest + test 'should edit candidate' do + auth_recruiter + candidate = candidates(:martha) + + get admin_edit_candidate_path(candidate.id) + assert_response :success + assert_select 'form' + end + + test 'should update candidate, but NOT test_hash' do + auth_recruiter + candidate = candidates(:martha) + post admin_update_candidate_url(id: candidate.id), params: + { candidate: { name: 'new name', email: "mail@martha.me", test_hash: 'SOMENEWSTRING' } } + + refute_equal candidate.name, Candidate.find_by(id: candidate.id).name + assert_equal candidate.test_hash, Candidate.find_by(id: candidate.id).test_hash + assert_redirected_to admin_candidate_url + end + + test 'should redirect to form on fail' do + auth_recruiter + candidate = candidates(:martha) + post admin_update_candidate_url(id: candidate.id), params: + { candidate: { name: 'new name', email: "mail@martha" } } + + assert :success + assert_match(/failed.*save/i, flash[:error]) + end + end +end diff --git a/test/controllers/recruiter_controller/index_test.rb b/test/controllers/recruiter_controller/index_test.rb deleted file mode 100644 index b6b4a7c..0000000 --- a/test/controllers/recruiter_controller/index_test.rb +++ /dev/null @@ -1,56 +0,0 @@ -# frozen_string_literal: true -require 'test_helper' - -class RecruiterControllerTest < ActionDispatch::IntegrationTest - test "should get login" do - get recruiter_login_url - assert_response :success - end - - test 'should logout and reset session' do - auth_recruiter - get recruiter_logout_path - - assert :success - assert session[:user].nil? - end - - test "should require auth or redirect" do - get recruiter_url - assert_redirected_to recruiter_login_path - - get new_candidate_url - assert_redirected_to recruiter_login_path - - post create_candidate_url, params: { candidate: { name: 'foo', email: 'bar', experience: 'baz' } } - assert_redirected_to recruiter_login_path - end - - test "should auth to index" do - auth_recruiter - assert_redirected_to recruiter_path - assert session[:user].present? - end - - test "should fail auth with flash" do - post recruiter_auth_url, params: { auth: - { email: 'pdr.recruiter@mailinator.com', password: 'bad-password' } } - - assert_redirected_to recruiter_login_path - assert flash[:error] - end - - test "should get candidate list" do - auth_recruiter - get recruiter_url - assert_response :success - assert assigns(:candidates), "@candidates not present" - end - - test 'should have edit links' do - auth_recruiter - get recruiter_url - assert_response :success - assert_select "a[href='#{edit_candidate_path(candidates(:martha))}']" - end -end diff --git a/test/controllers/recruiter_controller/new_candidate_test.rb b/test/controllers/recruiter_controller/new_candidate_test.rb deleted file mode 100644 index 458237b..0000000 --- a/test/controllers/recruiter_controller/new_candidate_test.rb +++ /dev/null @@ -1,71 +0,0 @@ -# frozen_string_literal: true -require 'test_helper' - -class RecruiterControllerTest < ActionDispatch::IntegrationTest - include ActiveJob::TestHelper - - test "should get new" do - auth_recruiter - get new_candidate_url - assert_response :success - assert assigns(:candidate), "@candidate not present" - end - - test "should get create" do - auth_recruiter - get create_candidate_url - assert_response :success - end - - test "should create new candidate" do - auth_recruiter - - assert_enqueued_jobs 2 do - assert_difference("Candidate.count") do - post create_candidate_path, params: { candidate: - { name: 'new name', email: 'test@mailinator.com', experience: '0-3', quiz_id: quizzes(:fed).id } } - end - end - assert_redirected_to recruiter_path - assert flash[:success] - end - - test "should fail creation with improper email format" do - auth_recruiter - - assert_enqueued_jobs 0 do - assert_difference("Candidate.count", 0) do - post create_candidate_path, params: { candidate: - { name: 'new name', email: 'test@mailinatorcom', experience: '0-3', quiz_id: quizzes(:fed).id } } - end - end - assert :success - assert assigns(:candidate), "@candidate not present" - assert_match(/failed.*save/i, flash[:error]) - end - - test "should fail creation gracefully with empty email" do - auth_recruiter - - assert_enqueued_jobs 0 do - assert_difference("Candidate.count", 0) do - post create_candidate_path, params: { candidate: - { name: 'new name', email: "", experience: '0-3', quiz_id: quizzes(:fed).id } } - end - end - assert :success - assert assigns(:candidate), "@candidate not present" - assert_match(/failed.*save/i, flash[:error]) - end - - test 'should queue up a welcome email [resend]' do - auth_recruiter - - assert_enqueued_jobs 1 do - get resend_welcome_path(id: candidates(:peggy)), xhr: true - end - assert_response :success - data = JSON.parse(response.body) - assert_match 'queued', data["message"] - end -end diff --git a/test/controllers/recruiter_controller/update_candidate_test.rb b/test/controllers/recruiter_controller/update_candidate_test.rb deleted file mode 100644 index 02a1dbe..0000000 --- a/test/controllers/recruiter_controller/update_candidate_test.rb +++ /dev/null @@ -1,34 +0,0 @@ -# frozen_string_literal: true -require 'test_helper' - -class RecruiterControllerTest < ActionDispatch::IntegrationTest - test 'should edit candidate' do - auth_recruiter - candidate = candidates(:martha) - - get edit_candidate_path(candidate.id) - assert_response :success - assert_select 'form' - end - - test 'should update candidate, but NOT test_hash' do - auth_recruiter - candidate = candidates(:martha) - post update_candidate_url(id: candidate.id), params: - { candidate: { name: 'new name', email: "mail@martha.me", test_hash: 'SOMENEWSTRING' } } - - refute_equal candidate.name, Candidate.find_by(id: candidate.id).name - assert_equal candidate.test_hash, Candidate.find_by(id: candidate.id).test_hash - assert_redirected_to recruiter_url - end - - test 'should redirect to form on fail' do - auth_recruiter - candidate = candidates(:martha) - post update_candidate_url(id: candidate.id), params: - { candidate: { name: 'new name', email: "mail@martha" } } - - assert :success - assert_match(/failed.*save/i, flash[:error]) - end -end diff --git a/test/controllers/review_controller_test.rb b/test/controllers/review_controller_test.rb index 5851678..453a629 100644 --- a/test/controllers/review_controller_test.rb +++ b/test/controllers/review_controller_test.rb @@ -17,7 +17,7 @@ class ReviewControllerTest < ActionDispatch::IntegrationTest test "should auth to index" do auth_reviewer - assert_redirected_to review_path + assert_redirected_to admin_path assert session[:user].present? end diff --git a/test/policies/candidate_policy_test.rb b/test/policies/candidate_policy_test.rb new file mode 100644 index 0000000..5124ec8 --- /dev/null +++ b/test/policies/candidate_policy_test.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true +require 'test_helper' + +class CandidatePolicyTest < PolicyAssertions::Test + test 'should require current_user' do + assert_raise Pundit::NotAuthorizedError do + CandidatePolicy.new(nil, Candidate.first).view? + end + end + + test 'should allow admin to scope' do + scope = CandidatePolicy::Scope.new(users(:admin), Candidate).resolve + assert_equal Candidate.count, scope.count + end + + test 'should allow recruiter to scope' do + scope = CandidatePolicy::Scope.new(users(:recruiter), Candidate).resolve + assert_equal Candidate.count, scope.count + end + + test 'reviewer CAN NOT scope candidates' do + assert_raise Pundit::NotAuthorizedError do + CandidatePolicy::Scope.new(users(:reviewer), Candidate).resolve + end + end + + test 'manager CAN NOT scope candidates' do + assert_raise Pundit::NotAuthorizedError do + CandidatePolicy::Scope.new(users(:manager), Candidate).resolve + end + end + + def test_view_and_update + assert_permit users(:admin), candidates(:roy) + assert_permit users(:recruiter), candidates(:roy) + + refute_permit users(:manager), candidates(:roy) + refute_permit users(:reviewer), candidates(:roy) + end + + def test_create + assert_permit users(:admin), Candidate + assert_permit users(:recruiter), Candidate + + refute_permit users(:manager), Candidate + refute_permit users(:reviewer), Candidate + end +end diff --git a/test/policies/question_policy_test.rb b/test/policies/question_policy_test.rb index 28d63c8..f8173db 100644 --- a/test/policies/question_policy_test.rb +++ b/test/policies/question_policy_test.rb @@ -31,7 +31,7 @@ class QuestionPolicyTest < PolicyAssertions::Test end end - def test_view + def test_view_and_options assert_permit users(:admin), questions(:fed1) assert_permit users(:manager), questions(:fed1) assert_permit users(:reviewer), questions(:fed1) diff --git a/test/test_helpers/auth_test_helper.rb b/test/test_helpers/auth_test_helper.rb index 7bddabe..152a7b6 100644 --- a/test/test_helpers/auth_test_helper.rb +++ b/test/test_helpers/auth_test_helper.rb @@ -4,13 +4,28 @@ module AuthTestHelper post validate_candidate_url, params: { test_id: candidate.test_hash } end + def auth_user user + post admin_auth_url, params: { auth: + { email: user.email, password: 'password' } } + end + + def auth_admin + post admin_auth_url, params: { auth: + { email: 'alan.admin@mailinator.com', password: 'password' } } + end + + def auth_manager + post admin_auth_url, params: { auth: + { email: 'mary.manager@mailinator.com', password: 'password' } } + end + def auth_recruiter - post recruiter_auth_url, params: { auth: + post admin_auth_url, params: { auth: { email: 'pdr.recruiter@mailinator.com', password: 'password' } } end def auth_reviewer - post review_auth_url, params: { auth: + post admin_auth_url, params: { auth: { email: 'fed.reviewer@mailinator.com', password: 'password' } } end end