From a51a7515247289a1c1f1354ddc1c6913afeeaffc Mon Sep 17 00:00:00 2001 From: Mark Moser Date: Fri, 16 Sep 2016 11:36:48 -0500 Subject: [PATCH] recruiter can edit candidate completes #82 --- Guardfile | 3 +- app/controllers/recruiter_controller.rb | 27 +++++++-- app/helpers/application_helper.rb | 4 ++ app/views/recruiter/_form.html.erb | 25 +++++++++ app/views/recruiter/edit.html.erb | 6 ++ app/views/recruiter/form.html.erb | 28 ---------- app/views/recruiter/index.html.erb | 2 +- app/views/recruiter/new.html.erb | 5 ++ config/routes.rb | 6 +- .../recruiter_controller/index_test.rb | 56 +++++++++++++++++++ .../new_candidate_test.rb} | 45 --------------- .../update_candidate_test.rb | 34 +++++++++++ 12 files changed, 160 insertions(+), 81 deletions(-) create mode 100644 app/views/recruiter/_form.html.erb create mode 100644 app/views/recruiter/edit.html.erb delete mode 100644 app/views/recruiter/form.html.erb create mode 100644 app/views/recruiter/new.html.erb create mode 100644 test/controllers/recruiter_controller/index_test.rb rename test/controllers/{recruiter_controller_test.rb => recruiter_controller/new_candidate_test.rb} (64%) create mode 100644 test/controllers/recruiter_controller/update_candidate_test.rb diff --git a/Guardfile b/Guardfile index 302e522..704d52c 100644 --- a/Guardfile +++ b/Guardfile @@ -63,8 +63,9 @@ guard :minitest, spring: "bin/rails test", all_after_pass: true do watch(%r{^lib/(.+)\.rb$}) { |m| "test/lib/#{m[1]}_test.rb" } watch(%r{^test/test_helper\.rb$}) { 'test' } watch(%r{^test/.+_test\.rb$}) - # run controller/integration test when touching erb files + # run controller/integration test when touching the router or erb files watch(%r{^app/views/((?!_mailer).)*([^/]+)\.erb$}) { ["test/controllers", "test/integration"] } + watch(%r{^config/routes.rb}) { ["test/controllers", "test/integration"] } # run mailers/integration test when touching mailer erb files watch(%r{^app/views/(.*_mailer/)?([^/]+)\.erb$}) { ["test/mailers", "test/integration"] } end diff --git a/app/controllers/recruiter_controller.rb b/app/controllers/recruiter_controller.rb index 8ca72cc..a8b32cb 100644 --- a/app/controllers/recruiter_controller.rb +++ b/app/controllers/recruiter_controller.rb @@ -1,6 +1,7 @@ # 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 @@ -8,12 +9,10 @@ class RecruiterController < ApplicationController def new @candidate = Candidate.new - @quizzes = Quiz.order(:name) - render :form + render :new end def create - @quizzes = Quiz.order(:name) @candidate = Candidate.create(candidate_params.merge(recruiter_id: current_recruiter.id)) if @candidate.persisted? @@ -22,7 +21,23 @@ class RecruiterController < ApplicationController redirect_to recruiter_path, flash: { success: "Sucessfully created candidate #{@candidate.name}" } else flash[:error] = "Failed to save candidate." - render :form + 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 @@ -58,4 +73,8 @@ class RecruiterController < ApplicationController 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/helpers/application_helper.rb b/app/helpers/application_helper.rb index 99e9420..e6138c5 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -11,6 +11,10 @@ module ApplicationHelper ], disabled: "-", selected: (val.blank? ? '' : val)) end + def quiz_options quizzes, selected_val + options_from_collection_for_select(quizzes, 'id', 'name', selected_val) + end + def admin_role_options val options_for_select([ %w(Reviewer reviewer), diff --git a/app/views/recruiter/_form.html.erb b/app/views/recruiter/_form.html.erb new file mode 100644 index 0000000..a70b8dd --- /dev/null +++ b/app/views/recruiter/_form.html.erb @@ -0,0 +1,25 @@ +<%= render partial: 'shared/form_model_errors', locals: { obj: candidate } %> + +<%= form_for candidate, url: create_candidate_path do |form| %> +
+ <%= form.label :name, "Candidate name" %> + <%= form.text_field :name %> +
+ +
+ <%= form.label :email, "Candidate email" %> + <%= form.email_field :email %> +
+ +
+ <%= form.label :experience, "Years of experience" %> + <%= form.select :experience, experience_options(candidate.experience), include_blank: false %> +
+ +
+ <%= form.label :quiz_id, "Quiz" %> + <%= form.select :quiz_id, quiz_options(quizzes, candidate.quiz_id), include_blank: (quizzes.size > 1) %> +
+ + <%= submit_tag %> +<% end %> diff --git a/app/views/recruiter/edit.html.erb b/app/views/recruiter/edit.html.erb new file mode 100644 index 0000000..da33352 --- /dev/null +++ b/app/views/recruiter/edit.html.erb @@ -0,0 +1,6 @@ +
+

Edit: <%= @candidate.name %>

+

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

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

New Candidate

- - <%= render partial: 'shared/form_model_errors', locals: { obj: @candidate } %> - <%= form_for @candidate, url: create_candidate_path do |form| %> -
- <%= form.label :name, "Candidate name" %> - <%= form.text_field :name %> -
- -
- <%= form.label :email, "Candidate email" %> - <%= form.email_field :email %> -
- -
- <%= form.label :experience, "Years of experience" %> - <%= form.select :experience, experience_options(@candidate.experience), include_blank: false %> -
- -
- <%= form.label :quiz_id, "Quiz" %> - <%= form.select :quiz_id, options_from_collection_for_select(@quizzes, 'id', 'name'), include_blank: (@quizzes.size > 1) %> -
- - <%= submit_tag "Create" %> - <% end %> -
diff --git a/app/views/recruiter/index.html.erb b/app/views/recruiter/index.html.erb index 86d8219..c7fc407 100644 --- a/app/views/recruiter/index.html.erb +++ b/app/views/recruiter/index.html.erb @@ -18,7 +18,7 @@ <% @candidates.each do |candidate| %> - <%= candidate.name %> + <%= link_to candidate.name, edit_candidate_path(candidate.id) %> <%= candidate.test_hash %> <%= mail_to(candidate.email) %> diff --git a/app/views/recruiter/new.html.erb b/app/views/recruiter/new.html.erb new file mode 100644 index 0000000..2c4059e --- /dev/null +++ b/app/views/recruiter/new.html.erb @@ -0,0 +1,5 @@ +
+

New Candidate

+ + <%= render partial: 'form', locals: { candidate: @candidate, quizzes: @quizzes } %> +
diff --git a/config/routes.rb b/config/routes.rb index ed1aba5..0a9f7e8 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -63,8 +63,10 @@ Rails.application.routes.draw do get "/resend/welcome/:id", to: "recruiter#resend_welcome", as: :resend_welcome get "/recruiter", to: "recruiter#index", as: :recruiter - get "/recruiter/new-candidate", to: "recruiter#new", as: :new_candidate - post "/recruiter/new-candidate", to: "recruiter#create", as: :create_candidate + 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 diff --git a/test/controllers/recruiter_controller/index_test.rb b/test/controllers/recruiter_controller/index_test.rb new file mode 100644 index 0000000..b6b4a7c --- /dev/null +++ b/test/controllers/recruiter_controller/index_test.rb @@ -0,0 +1,56 @@ +# 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_test.rb b/test/controllers/recruiter_controller/new_candidate_test.rb similarity index 64% rename from test/controllers/recruiter_controller_test.rb rename to test/controllers/recruiter_controller/new_candidate_test.rb index e028d3f..458237b 100644 --- a/test/controllers/recruiter_controller_test.rb +++ b/test/controllers/recruiter_controller/new_candidate_test.rb @@ -4,51 +4,6 @@ require 'test_helper' class RecruiterControllerTest < ActionDispatch::IntegrationTest include ActiveJob::TestHelper - 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 get new" do auth_recruiter get new_candidate_url diff --git a/test/controllers/recruiter_controller/update_candidate_test.rb b/test/controllers/recruiter_controller/update_candidate_test.rb new file mode 100644 index 0000000..02a1dbe --- /dev/null +++ b/test/controllers/recruiter_controller/update_candidate_test.rb @@ -0,0 +1,34 @@ +# 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