- ©2016 All Rights Reserved - Perficient Digital
+ ©2016-<%= Time.now.year %> All Rights Reserved - Perficient Digital
|
<%= image_tag(attachments["perficientdigital-logo.jpg"].url, alt:"Perficient Digital") %>
diff --git a/app/views/recruiter_mailer/candidate_created.html.inky b/app/views/recruiter_mailer/candidate_created.html.inky
index 0a9cc9e..dcd04c7 100644
--- a/app/views/recruiter_mailer/candidate_created.html.inky
+++ b/app/views/recruiter_mailer/candidate_created.html.inky
@@ -7,8 +7,9 @@
Candidate email: <%= @candidate.email %>
Candidate ID: <%= @candidate.test_hash %>
Years of experience: <%= @candidate.experience %> Years
+ Client/Project: <%= @candidate.project %>
You will be notified when the candidate has finished taking the test.
-
\ No newline at end of file
+
diff --git a/app/views/recruiter_mailer/candidate_created.text.erb b/app/views/recruiter_mailer/candidate_created.text.erb
index 56b001b..c16e184 100644
--- a/app/views/recruiter_mailer/candidate_created.text.erb
+++ b/app/views/recruiter_mailer/candidate_created.text.erb
@@ -6,5 +6,6 @@ Candidate name: <%= @candidate.name %>
Candidate email: <%= @candidate.email %>
Candidate ID: <%= @candidate.test_hash %>
Years of experience: <%= @candidate.experience %> Years
+Client/Project: <%= @candidate.project %>
You will be notified when the candidate has finished taking the test.
diff --git a/app/views/recruiter_mailer/candidate_reviewed.html.inky b/app/views/recruiter_mailer/candidate_reviewed.html.inky
new file mode 100644
index 0000000..1eecc06
--- /dev/null
+++ b/app/views/recruiter_mailer/candidate_reviewed.html.inky
@@ -0,0 +1,9 @@
+
+
+ The team has <%= @candidate.review_status %> an interview with <%= @candidate.name %> with the following comments:
+
+ <%= @candidate.review_comments %>
+
+ Thank you
+
+
diff --git a/app/views/recruiter_mailer/candidate_reviewed.text.erb b/app/views/recruiter_mailer/candidate_reviewed.text.erb
new file mode 100644
index 0000000..0beabee
--- /dev/null
+++ b/app/views/recruiter_mailer/candidate_reviewed.text.erb
@@ -0,0 +1,7 @@
+PERFICIENT/digital - Skills Assessment Test
+
+The team has <%= @candidate.review_status %> an interview with <%= @candidate.name %> with the following comments:
+
+<%= @candidate.review_comments %>
+
+Thank you.
diff --git a/app/views/recruiter_mailer/candidate_submitted.html.inky b/app/views/recruiter_mailer/candidate_submitted.html.inky
index c4c8b4b..5e5a706 100644
--- a/app/views/recruiter_mailer/candidate_submitted.html.inky
+++ b/app/views/recruiter_mailer/candidate_submitted.html.inky
@@ -1,6 +1,6 @@
<%= @candidate.name %> has completed the Skills Assessment Test.
- Martin Ridgway will let you know if we would like to interview this candidate.
+ <%= @candidate.manager.name %> will let you know if we would like to interview this candidate.
-
\ No newline at end of file
+
diff --git a/app/views/recruiter_mailer/candidate_submitted.text.erb b/app/views/recruiter_mailer/candidate_submitted.text.erb
index c6e7142..9387254 100644
--- a/app/views/recruiter_mailer/candidate_submitted.text.erb
+++ b/app/views/recruiter_mailer/candidate_submitted.text.erb
@@ -1,4 +1,4 @@
PERFICIENT/digital - Skills Assessment Test
<%= @candidate.name %> has completed the Skills Assessment Test.
-Martin Ridgway will let you know if we would like to interview this candidate.
+<%= @candidate.manager.name %> will let you know if we would like to interview this candidate.
diff --git a/app/views/reviewer_mailer/candidate_submission.html.inky b/app/views/reviewer_mailer/candidate_submission.html.inky
index 1c5a20f..eeaed3d 100644
--- a/app/views/reviewer_mailer/candidate_submission.html.inky
+++ b/app/views/reviewer_mailer/candidate_submission.html.inky
@@ -1,6 +1,9 @@
- Candidate <%= @candidate.test_hash %> has completed the Skills Assessment Test.
+
+ Candidate <%= @candidate.test_hash %> has completed the
+ Skills Assessment Test for client/project <%= @candidate.project %>.
+
You can view the results here: <%= link_to nil, admin_result_url(@candidate.test_hash) %>.
diff --git a/app/views/reviewer_mailer/candidate_submission.text.erb b/app/views/reviewer_mailer/candidate_submission.text.erb
index e81acc2..7120c2e 100644
--- a/app/views/reviewer_mailer/candidate_submission.text.erb
+++ b/app/views/reviewer_mailer/candidate_submission.text.erb
@@ -1,5 +1,5 @@
PERFICIENT/digital SKILLS ASSESSMENT RESULTS
-Candidate <%= @candidate.test_hash %> has completed the Skills Assessment Test.
+Candidate <%= @candidate.test_hash %> has completed the Skills Assessment Test for client/project <%= @candidate.project %>.
You can view the results here: <%= admin_result_url(@candidate.test_hash) %>.
diff --git a/app/views/reviewer_mailer/new_comment.html.inky b/app/views/reviewer_mailer/new_comment.html.inky
new file mode 100644
index 0000000..b37e27b
--- /dev/null
+++ b/app/views/reviewer_mailer/new_comment.html.inky
@@ -0,0 +1,13 @@
+
+
+
+ <%= @comment.user.name %> wrote a comment for quiz <%= @comment.test_hash %>
+
+
+
+ <%= @comment.message %>
+
+
+ You can view and reply here: <%= link_to nil, admin_result_url(@comment.test_hash) %>.
+
+
diff --git a/app/views/reviewer_mailer/new_comment.text.erb b/app/views/reviewer_mailer/new_comment.text.erb
new file mode 100644
index 0000000..c109f9e
--- /dev/null
+++ b/app/views/reviewer_mailer/new_comment.text.erb
@@ -0,0 +1,9 @@
+SKILLS ASSESSMENT RESULT COMMENT
+
+<%= @comment.user.name %> wrote a comment for quiz <%= @comment.test_hash %>
+
+--- --- --- ---
+<%= @comment.message %>
+--- --- --- ---
+
+You can view and reply here: <%= admin_result_url(@comment.test_hash) %>.
diff --git a/app/views/reviewer_mailer/notify_manager.html.inky b/app/views/reviewer_mailer/notify_manager.html.inky
new file mode 100644
index 0000000..c11d797
--- /dev/null
+++ b/app/views/reviewer_mailer/notify_manager.html.inky
@@ -0,0 +1,10 @@
+
+
+ Hello <%= @manager.name %>,
+
+ Everyone has voted and you need to request or decline an interview for
+ <%= link_to nil, admin_result_url(@candidate.test_hash) %>
+
+
+
+
diff --git a/app/views/reviewer_mailer/notify_manager.text.erb b/app/views/reviewer_mailer/notify_manager.text.erb
new file mode 100644
index 0000000..dacc2bb
--- /dev/null
+++ b/app/views/reviewer_mailer/notify_manager.text.erb
@@ -0,0 +1,6 @@
+PERFICIENT/digital SKILLS ASSESSMENT RESULTS
+
+Hello <%= @manager.name %>,
+
+Everyone has voted and you need to request or decline an interview for
+<%= admin_result_url(@candidate.test_hash) %>
diff --git a/app/views/reviewer_mailer/reminder.html.inky b/app/views/reviewer_mailer/reminder.html.inky
new file mode 100644
index 0000000..af7cfc8
--- /dev/null
+++ b/app/views/reviewer_mailer/reminder.html.inky
@@ -0,0 +1,9 @@
+
+
+ Hello <%= @reminder.name %>,
+
+ Please review and vote on the results for <%= link_to nil, admin_result_url(@reminder.test_hash) %>
+
+
+
+
diff --git a/app/views/reviewer_mailer/reminder.text.erb b/app/views/reviewer_mailer/reminder.text.erb
new file mode 100644
index 0000000..ef651e0
--- /dev/null
+++ b/app/views/reviewer_mailer/reminder.text.erb
@@ -0,0 +1,5 @@
+PERFICIENT/digital SKILLS ASSESSMENT RESULTS
+
+Hello <%= @reminder.name %>,
+
+Please review and vote on the results for <%= admin_result_url(@reminder.test_hash) %>.
diff --git a/app/workers/reminder.rb b/app/workers/candidate_reminder.rb
similarity index 97%
rename from app/workers/reminder.rb
rename to app/workers/candidate_reminder.rb
index 7437f04..a804e8e 100644
--- a/app/workers/reminder.rb
+++ b/app/workers/candidate_reminder.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-class Reminder
+class CandidateReminder
def initialize
@collection = reminder_collection
end
diff --git a/app/workers/reviewer_reminder.rb b/app/workers/reviewer_reminder.rb
new file mode 100644
index 0000000..7e67da6
--- /dev/null
+++ b/app/workers/reviewer_reminder.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+class ReviewerReminder
+ def initialize
+ @collection = reminder_collection
+ end
+
+ def count
+ @collection.count
+ end
+ alias size count
+
+ def reminders
+ @reminders ||= @collection.to_hash.map { |r| OpenStruct.new(r) }
+ end
+
+ def send_all
+ reminders.each do |reminder|
+ ReviewerMailer.reminder(reminder).deliver_now
+ end
+ end
+
+ private
+
+ def reminder_collection
+ sql = "select u.name, u.email, c.test_hash, c.project
+ from reviewer_votes rev
+ inner join users u on u.id = rev.user_id
+ inner join candidates c on c.id = rev.candidate_id
+ where rev.vote = 0 and rev.veto = 0
+ and u.role != 'manager' and u.active is not false;"
+ ActiveRecord::Base.connection.exec_query(sql)
+ end
+end
diff --git a/config/application.rb b/config/application.rb
index 98b8077..ea7c038 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -30,5 +30,8 @@ module SkillAssessmentApp
g.helper false
g.routes false
end
+
+ # let's use lib/utils for dev only utility classes & helpers
+ config.autoload_paths << "#{Rails.root}/lib/utils"
end
end
diff --git a/config/brakeman.ignore b/config/brakeman.ignore
index 3348c50..e869cec 100644
--- a/config/brakeman.ignore
+++ b/config/brakeman.ignore
@@ -1,10 +1,81 @@
{
"ignored_warnings": [
{
+ "warning_type": "SQL Injection",
+ "warning_code": 0,
+ "fingerprint": "6f3216446dca0fa79e96267eb0323d50cc59e7bc1e1529fd160cd5beb185e2f2",
+ "message": "Possible SQL injection",
+ "file": "app/controllers/admin/candidate_controller.rb",
+ "line": 7,
+ "link": "http://brakemanscanner.org/docs/warning_types/sql_injection/",
+ "code": "Candidate.order(\"#{sort_column} #{sort_direction}\")",
+ "render_path": null,
+ "location": {
+ "type": "method",
+ "class": "Admin::CandidateController",
+ "method": "index"
+ },
+ "user_input": "sort_column",
+ "confidence": "Medium",
+ "note": ""
+ },
+ {
+ "warning_type": "SQL Injection",
+ "warning_code": 0,
+ "fingerprint": "9e802ac2067c1ee551f97c1f37816b585451abc42b6a2c7903c6d97aa042da61",
+ "message": "Possible SQL injection",
+ "file": "app/controllers/admin/user_controller.rb",
+ "line": 5,
+ "link": "http://brakemanscanner.org/docs/warning_types/sql_injection/",
+ "code": "User.order(\"#{sort_column} #{sort_direction}\")",
+ "render_path": null,
+ "location": {
+ "type": "method",
+ "class": "Admin::UserController",
+ "method": "index"
+ },
+ "user_input": "sort_column",
+ "confidence": "Medium",
+ "note": ""
+ },
+ {
+ "warning_type": "SQL Injection",
+ "warning_code": 0,
+ "fingerprint": "a65b53d63f1d43cb831947d0693d2d1b8819e21aec5ee18bf09b577ade02a0ee",
+ "message": "Possible SQL injection",
+ "file": "app/controllers/admin/result_controller.rb",
+ "line": 16,
+ "link": "http://brakemanscanner.org/docs/warning_types/sql_injection/",
+ "code": "Candidate.where(:completed => true).includes(:recruiter).order(\"#{(\"(case when review_status = 0 then '' else name end)\" or sort_column)} #{sort_direction}\")",
+ "render_path": null,
+ "location": {
+ "type": "method",
+ "class": "Admin::ResultController",
+ "method": "index"
+ },
+ "user_input": "sort_column",
+ "confidence": "Medium",
+ "note": ""
+ },
+ {
+ "warning_type": "Dynamic Render Path",
+ "warning_code": 15,
"fingerprint": "da17225c940987e6239cc4ecfe27bcb1e5da2db1134435dc3e1025d97927e0ba",
+ "message": "Render path contains parameter value",
+ "file": "app/views/admin/question/options.html.erb",
+ "line": 3,
+ "link": "http://brakemanscanner.org/docs/warning_types/dynamic_render_path/",
+ "code": "render(partial => \"admin/question/#{params[:input_type]}\", { :locals => ({ :question => ((Question.find(params[:question_id]) or Question.new)) }) })",
+ "render_path": [{"type":"controller","class":"Admin::QuestionController","method":"options","line":58,"file":"app/controllers/admin/question_controller.rb"}],
+ "location": {
+ "type": "template",
+ "template": "admin/question/options"
+ },
+ "user_input": "params[:input_type]",
+ "confidence": "Medium",
"note": "false positive"
}
],
- "updated": "2016-09-19 09:06:25 -0500",
- "brakeman_version": "3.4.0"
+ "updated": "2017-03-06 12:16:23 -0600",
+ "brakeman_version": "3.4.1"
}
diff --git a/config/initializers/kaminari_config.rb b/config/initializers/kaminari_config.rb
new file mode 100644
index 0000000..373150f
--- /dev/null
+++ b/config/initializers/kaminari_config.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+Kaminari.configure do |config|
+ config.default_per_page = 10
+ # config.max_per_page = nil
+ # config.window = 4
+ # config.outer_window = 0
+ # config.left = 0
+ # config.right = 0
+ # config.page_method_name = :page
+ # config.param_name = :page
+ # config.params_on_first_page = false
+end
diff --git a/config/routes.rb b/config/routes.rb
index 691f4c5..6996760 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,4 +1,6 @@
# frozen_string_literal: true
+# Neat routing visualizer, in irb:
+# File.open('routing.html', 'w+'){|f| f.write Rails.application.routes.router.visualizer }
Rails.application.routes.draw do
get "/styleguide", to: "application#styleguide", as: :styleguide
get "/admin/styleguide", to: "application#styleguide"
@@ -45,15 +47,17 @@ Rails.application.routes.draw do
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 "/admin/candidate/:id/resend", to: "admin/candidate#resend_welcome", as: :admin_resend_welcome, defaults: { format: 'json' }
get "/admin/results", to: "admin/result#index", as: :admin_results
get "/admin/result/:test_hash", to: "admin/result#view", as: :admin_result
- get "admin/vote/:test_hash/up", to: "admin/vote#up", as: :admin_up_vote
- get "admin/vote/:test_hash/down", to: "admin/vote#down", as: :admin_down_vote
- get "admin/vote/:test_hash/approve", to: "admin/vote#approve", as: :admin_approve_vote
- get "admin/vote/:test_hash/decline", to: "admin/vote#decline", as: :admin_decline_vote
+ post "/admin/comment/:test_hash/:id", to: "admin/comment#update", as: :admin_update_comment
+ post "/admin/comment/:test_hash", to: "admin/comment#create", as: :admin_create_comment
+
+ get "admin/vote/:test_hash/up", to: "admin/vote#up", as: :admin_up_vote, defaults: { format: 'json' }
+ get "admin/vote/:test_hash/down", to: "admin/vote#down", as: :admin_down_vote, defaults: { format: 'json' }
+ post "admin/vote/:test_hash", to: "admin/vote#interview_request", as: :admin_interview
get "/admin", to: "admin/dashboard#show", as: :admin
diff --git a/db/migrate/20161204213828_remove_vote_locking.rb b/db/migrate/20161204213828_remove_vote_locking.rb
new file mode 100644
index 0000000..b842e74
--- /dev/null
+++ b/db/migrate/20161204213828_remove_vote_locking.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+class RemoveVoteLocking < ActiveRecord::Migration[5.0]
+ def change
+ remove_column :reviewer_votes, :locked, :boolean, default: false, null: false
+ end
+end
diff --git a/db/migrate/20161204220527_add_completed_at.rb b/db/migrate/20161204220527_add_completed_at.rb
new file mode 100644
index 0000000..8315b00
--- /dev/null
+++ b/db/migrate/20161204220527_add_completed_at.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+class AddCompletedAt < ActiveRecord::Migration[5.0]
+ def change
+ add_column :candidates, :completed_at, :datetime, after: :completed
+
+ Candidate.reset_column_information
+ Candidate.where(completed: true).each do |candidate|
+ candidate.completed_at = candidate.updated_at
+ candidate.save
+ end
+ end
+end
diff --git a/db/migrate/20170208212526_add_project_to_client.rb b/db/migrate/20170208212526_add_project_to_client.rb
new file mode 100644
index 0000000..e3adda1
--- /dev/null
+++ b/db/migrate/20170208212526_add_project_to_client.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+class AddProjectToClient < ActiveRecord::Migration[5.0]
+ def change
+ add_column :candidates, :project, :string, after: :experience
+ end
+end
diff --git a/db/migrate/20170210165110_create_quiz_comments.rb b/db/migrate/20170210165110_create_quiz_comments.rb
new file mode 100644
index 0000000..caae162
--- /dev/null
+++ b/db/migrate/20170210165110_create_quiz_comments.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+class CreateQuizComments < ActiveRecord::Migration[5.0]
+ def change
+ create_table :quiz_comments do |t|
+ t.integer :user_id
+ t.string :test_hash
+ t.text :message
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20170227154554_add_attributes_to_candidate.rb b/db/migrate/20170227154554_add_attributes_to_candidate.rb
new file mode 100644
index 0000000..bac89ff
--- /dev/null
+++ b/db/migrate/20170227154554_add_attributes_to_candidate.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+class AddAttributesToCandidate < ActiveRecord::Migration[5.0]
+ def change
+ add_column :candidates, :skill_needs, :string, after: :project
+ add_column :candidates, :position, :string, after: :project
+ end
+end
diff --git a/db/migrate/20170228161543_add_comments_to_candidate.rb b/db/migrate/20170228161543_add_comments_to_candidate.rb
new file mode 100644
index 0000000..960f178
--- /dev/null
+++ b/db/migrate/20170228161543_add_comments_to_candidate.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+class AddCommentsToCandidate < ActiveRecord::Migration[5.0]
+ def change
+ add_column :candidates, :review_comments, :text, after: :review_status
+ end
+end
diff --git a/db/migrate/20170228161729_remove_last_reminded_from_reviewer_votes.rb b/db/migrate/20170228161729_remove_last_reminded_from_reviewer_votes.rb
new file mode 100644
index 0000000..1631176
--- /dev/null
+++ b/db/migrate/20170228161729_remove_last_reminded_from_reviewer_votes.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+class RemoveLastRemindedFromReviewerVotes < ActiveRecord::Migration[5.0]
+ def change
+ remove_column :reviewer_votes, :last_reminded, :datetime
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 2126b30..243d9ea 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20161120175737) do
+ActiveRecord::Schema.define(version: 20170228161729) do
create_table "answers", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
t.integer "candidate_id"
@@ -30,13 +30,18 @@ ActiveRecord::Schema.define(version: 20161120175737) do
t.string "name"
t.string "email"
t.string "experience"
+ t.string "project"
+ t.string "position"
+ t.string "skill_needs"
t.integer "recruiter_id"
t.boolean "completed"
+ t.datetime "completed_at"
t.boolean "reminded"
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
t.integer "quiz_id"
- t.integer "review_status", default: 0, null: false
+ t.integer "review_status", default: 0, null: false
+ t.text "review_comments", limit: 65535
t.index ["quiz_id"], name: "index_candidates_on_quiz_id", using: :btree
t.index ["recruiter_id"], name: "index_candidates_on_recruiter_id", using: :btree
t.index ["test_hash"], name: "index_candidates_on_test_hash", unique: true, using: :btree
@@ -58,6 +63,14 @@ ActiveRecord::Schema.define(version: 20161120175737) do
t.index ["sort"], name: "index_questions_on_sort", using: :btree
end
+ create_table "quiz_comments", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
+ t.integer "user_id"
+ t.string "test_hash"
+ t.text "message", limit: 65535
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
create_table "quizzes", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
t.string "unit"
t.string "dept"
@@ -77,12 +90,10 @@ ActiveRecord::Schema.define(version: 20161120175737) do
create_table "reviewer_votes", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
t.integer "candidate_id"
t.integer "user_id"
- t.integer "vote", default: 0, null: false
- t.integer "veto", default: 0, null: false
- t.datetime "last_reminded"
- t.boolean "locked", default: false, null: false
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
+ t.integer "vote", default: 0, null: false
+ t.integer "veto", default: 0, null: false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
t.index ["candidate_id", "user_id"], name: "index_reviewer_votes_on_candidate_id_and_user_id", unique: true, using: :btree
end
diff --git a/lib/tasks/reminders.rake b/lib/tasks/reminders.rake
index 2695aa6..680dfde 100644
--- a/lib/tasks/reminders.rake
+++ b/lib/tasks/reminders.rake
@@ -2,7 +2,13 @@
namespace :reminders do
desc "send reminders to stagnate quizes"
task send_all: :environment do
- reminders = Reminder.new
+ reminders = CandidateReminder.new
+ reminders.send_all
+ end
+
+ desc "send reminders to reviewers"
+ task reviewers: :environment do
+ reminders = ReviewerReminder.new
reminders.send_all
end
end
diff --git a/lib/utils/fake_quiz.rb b/lib/utils/fake_quiz.rb
new file mode 100644
index 0000000..835305f
--- /dev/null
+++ b/lib/utils/fake_quiz.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+class FakeQuiz
+ def create_completed_quizzes num = 10
+ num.times do
+ candidate = create_candidate Faker::Name.name
+ answer_questions candidate
+ candidate.update_attributes(completed: true, completed_at: Time.zone.now - rand(0..112).days)
+ candidate.build_reviews
+ end
+ end
+
+ def create_candidate name
+ Candidate.create(name: name,
+ email: "#{Faker::Internet.user_name(name)}@mailinator.com",
+ experience: rando_experience,
+ project: Faker::Company.name,
+ recruiter_id: recruiter_id,
+ quiz_id: fed_quiz_id)
+ end
+
+ def answer_questions candidate
+ candidate.quiz.questions.each do |question|
+ candidate.answers.create(question_id: question.id,
+ answer: generate_answer(question),
+ submitted: true)
+ end
+ end
+
+ private
+
+ def fed_quiz_id
+ Quiz.find_by(dept: 'fed').id
+ end
+
+ def recruiter_id
+ User.find_by(name: 'Sam Recruiter').id
+ end
+
+ def rando_experience
+ %w(0-3 4-6 7-9 10-14 15+)[rand(0..4)]
+ end
+
+ def generate_answer question # rubocop:disable Metrics/MethodLength
+ case question.input_type
+ when "checkbox"
+ question.input_options
+ when "checkbox_other"
+ {
+ other: Faker::TwinPeaks.quote,
+ options: question.input_options
+ }
+ when "radio"
+ question.input_options.sample
+ when "radio_other"
+ {
+ other: Faker::TwinPeaks.quote,
+ options: question.input_options.sample
+ }
+ when "live_code"
+ {
+ html: "#{Faker::TwinPeaks.quote} ",
+ css: "body {color: #{Faker::Color.hex_color}}",
+ text: Faker::TwinPeaks.quote
+ }
+ else
+ Faker::TwinPeaks.quote
+ end
+ end # rubocop:enable Metrics/MethodLength
+end
diff --git a/test/controllers/admin/auth_controller_test.rb b/test/controllers/admin/auth_controller_test.rb
index f99bfaa..477200c 100644
--- a/test/controllers/admin/auth_controller_test.rb
+++ b/test/controllers/admin/auth_controller_test.rb
@@ -26,6 +26,18 @@ module Admin
assert_redirected_to admin_url
end
+ test "should auth to original request" do
+ elsie = candidates(:elsie)
+
+ get admin_result_url(test_hash: elsie.test_hash)
+
+ assert_redirected_to admin_login_url
+ post admin_auth_url, params: { auth:
+ { email: 'fed.reviewer@mailinator.com', password: 'password' } }
+
+ assert_redirected_to admin_result_url(test_hash: elsie.test_hash)
+ end
+
test "should FAIL auth" do
post admin_auth_url, params: { auth:
{ email: 'alan.admin@mailinator.com', password: 'b@d9a$$werD' } }
diff --git a/test/controllers/admin/candidate_controller/new_candidate_test.rb b/test/controllers/admin/candidate_controller/new_candidate_test.rb
index c59f58c..8ebd2ba 100644
--- a/test/controllers/admin/candidate_controller/new_candidate_test.rb
+++ b/test/controllers/admin/candidate_controller/new_candidate_test.rb
@@ -23,8 +23,14 @@ module Admin
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 } }
+ post admin_create_candidate_path, params: { candidate: {
+ name: 'new name',
+ email: 'test@mailinator.com',
+ experience: '0-3',
+ position: 'full-time',
+ project: 'client project',
+ quiz_id: quizzes(:fed).id
+ } }
end
end
assert_redirected_to admin_candidates_path
diff --git a/test/controllers/admin/comment_controller_test.rb b/test/controllers/admin/comment_controller_test.rb
new file mode 100644
index 0000000..8fd3f31
--- /dev/null
+++ b/test/controllers/admin/comment_controller_test.rb
@@ -0,0 +1,103 @@
+# frozen_string_literal: true
+require 'test_helper'
+
+module Admin
+ class CommentControllerTest < ActionDispatch::IntegrationTest
+ include ActiveJob::TestHelper
+
+ test "should post update" do
+ auth_manager
+ comment = quiz_comments(:com5)
+ post admin_update_comment_url(test_hash: comment.test_hash, id: comment.id),
+ params: { quiz_comment: { message: 'updated comment' } }
+
+ assert_redirected_to admin_result_url(test_hash: comment.test_hash)
+ assert flash[:success]
+ refute_equal comment.message, QuizComment.find_by(id: comment.id).message
+ end
+
+ test "should require message to update" do
+ auth_manager
+ comment = quiz_comments(:com5)
+ post admin_update_comment_url(test_hash: comment.test_hash, id: comment.id),
+ params: { quiz_comment: { message: '' } }
+
+ assert_redirected_to admin_result_url(test_hash: comment.test_hash)
+ assert flash[:error]
+ assert_equal comment.message, QuizComment.find_by(id: comment.id).message
+ end
+
+ test "should post create" do
+ auth_reviewer
+ candidate = candidates(:stacy)
+
+ assert_difference("QuizComment.count") do
+ post admin_create_comment_url(test_hash: candidate.test_hash),
+ params: { quiz_comment: { message: 'this is a test comment' } }
+ end
+
+ assert_redirected_to admin_result_url(test_hash: candidate.test_hash)
+ assert flash[:success]
+ end
+
+ test "admin can post comment" do
+ auth_admin
+ candidate = candidates(:stacy)
+
+ assert_difference("QuizComment.count") do
+ post admin_create_comment_url(test_hash: candidate.test_hash),
+ params: { quiz_comment: { message: 'this is an admin comment' } }
+ end
+
+ assert_redirected_to admin_result_url(test_hash: candidate.test_hash)
+ assert flash[:success]
+ end
+
+ test "should queue emails on create" do
+ auth_reviewer
+ candidate = candidates(:stacy)
+
+ assert_enqueued_jobs 1 do
+ assert_difference("QuizComment.count", 1) do
+ post admin_create_comment_url(test_hash: candidate.test_hash),
+ params: { quiz_comment: { message: 'this is a test comment' } }
+ end
+ end
+ end
+
+ test "should require comment to create" do
+ auth_reviewer
+ candidate = candidates(:stacy)
+
+ assert_difference("QuizComment.count", 0) do
+ post admin_create_comment_url(test_hash: candidate.test_hash),
+ params: { quiz_comment: { message: '' } }
+ end
+
+ assert_redirected_to admin_result_url(test_hash: candidate.test_hash)
+ assert flash[:error]
+ end
+
+ test "should not edit others comments" do
+ auth_reviewer
+ comment = quiz_comments(:com5)
+ post admin_update_comment_url(test_hash: comment.test_hash, id: comment.id),
+ params: { quiz_comment: { message: 'updated comment' } }
+
+ assert_redirected_to admin_login_url
+ assert_equal comment.message, QuizComment.find_by(id: comment.id).message
+ end
+
+ test "can not comment on Gustov" do
+ auth_reviewer
+ candidate = candidates(:gustov)
+
+ assert_difference("QuizComment.count", 0) do
+ post admin_create_comment_url(test_hash: candidate.test_hash),
+ params: { quiz_comment: { message: 'this is a test comment' } }
+ end
+
+ assert_redirected_to admin_login_url
+ end
+ end
+end
diff --git a/test/controllers/admin/vote_controller_test.rb b/test/controllers/admin/vote_controller_test.rb
index f05e4e2..e7de4e4 100644
--- a/test/controllers/admin/vote_controller_test.rb
+++ b/test/controllers/admin/vote_controller_test.rb
@@ -3,10 +3,30 @@ require 'test_helper'
module Admin
class VoteControllerTest < ActionDispatch::IntegrationTest
- test "reviewer can up vote henry" do
+ include ActiveJob::TestHelper
+
+ test "reviewer can only vote after commenting" do
auth_user users(:reviewer)
henry = candidates(:henry)
+ assert_difference("Candidate.find(#{henry.id}).votes.yea.count", 0) do
+ get admin_up_vote_url(henry.test_hash)
+ end
+
+ post admin_create_comment_url(test_hash: henry.test_hash),
+ params: { quiz_comment: { message: 'this is a comment to vote' } }
+
+ assert_difference("Candidate.find(#{henry.id}).votes.yea.count", 1) do
+ get admin_up_vote_url(henry.test_hash)
+ end
+
+ assert_response :success
+ end
+
+ test "reviewer can up vote henry" do
+ auth_user users(:reviewer2)
+ henry = candidates(:henry)
+
assert_difference("Candidate.find(#{henry.id}).votes.yea.count", 1) do
get admin_up_vote_url(henry.test_hash)
end
@@ -14,7 +34,7 @@ module Admin
end
test "reviewer can down vote henry" do
- auth_user users(:reviewer)
+ auth_user users(:reviewer2)
henry = candidates(:henry)
assert_difference("Candidate.find(#{henry.id}).votes.nay.count", 1) do
@@ -24,7 +44,7 @@ module Admin
end
test "reviewer can change vote on henry" do
- auth_user users(:reviewer)
+ auth_user users(:reviewer2)
henry = candidates(:henry)
get admin_up_vote_url(henry.test_hash)
@@ -36,24 +56,30 @@ module Admin
assert_response :success
end
- test "manager can approve henry" do
+ test "manager can approve henry and notify recruiter" do
auth_user users(:manager)
henry = candidates(:henry)
- get admin_approve_vote_url(henry.test_hash)
- assert_equal 1, henry.votes.approved.count
+ assert_enqueued_jobs 1 do
+ post admin_interview_url(henry.test_hash), params: {
+ review_status: 'approved',
+ review_comments: 'ipsum'
+ }
+ end
assert_equal 'approved', Candidate.find(henry.to_i).review_status
- assert_response :success
+ assert_equal 'ipsum', Candidate.find(henry.to_i).review_comments
+ assert_redirected_to admin_result_url(henry.test_hash)
end
- test "manager can decline henry" do
+ test "approve fails without comment" do
auth_user users(:manager)
henry = candidates(:henry)
- get admin_decline_vote_url(henry.test_hash)
- assert_equal 1, henry.votes.rejected.count
- assert_equal 'declined', Candidate.find(henry.to_i).review_status
- assert_response :success
+ assert_enqueued_jobs 0 do
+ post admin_interview_url(henry.test_hash), params: { review_status: 'approved' }
+ end
+ assert_match 'comment', flash[:error]
+ assert_redirected_to admin_result_url(henry.test_hash)
end
end
end
diff --git a/test/controllers/admin_controller_test.rb b/test/controllers/admin_controller_test.rb
index 6666e23..6084334 100644
--- a/test/controllers/admin_controller_test.rb
+++ b/test/controllers/admin_controller_test.rb
@@ -9,4 +9,11 @@ class AdminControllerTest < ActionDispatch::IntegrationTest
assert_redirected_to admin_login_path
assert_match 'not authorized', flash[:error]
end
+
+ test 'sort_column present' do
+ # a stupid coverage report thing.
+ admin_controller = AdminController.new
+
+ assert_equal :completed_at, admin_controller.send(:sort_column)
+ end
end
diff --git a/test/fixtures/answers.yml b/test/fixtures/answers.yml
index de70e0c..69019e2 100644
--- a/test/fixtures/answers.yml
+++ b/test/fixtures/answers.yml
@@ -696,3 +696,197 @@ wade10:
created_at: <%= DateTime.now() - 36.hours - 40.minutes %>
updated_at: <%= DateTime.now() - 36.hours - 20.minutes %>
+jorge1:
+ candidate: jorge
+ question: Cras justo odio, dapibus ac facilisis in, egestas eget quam. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Nullam id dolor id nibh ultricies vehicula ut id elit.
+ answer: option 3
+ saved: 0
+ submitted: true
+ created_at: <%= DateTime.now() - 36.hours - 22.minutes %>
+ updated_at: <%= DateTime.now() - 36.hours - 22.minutes %>
+
+jorge2:
+ candidate: jorge
+ question: fed2
+ answer: 'indexOf()'
+ saved: 0
+ submitted: true
+ created_at: <%= DateTime.now() - 36.hours - 24.minutes %>
+ updated_at: <%= DateTime.now() - 36.hours - 4.minutes %>
+
+jorge3:
+ candidate: jorge
+ question: fed3
+ answer: {html: 'Salmon', css: 'h1 {color: salmon;}', js: '', text: 'Gotta lotta GOOD things on sale, strangah.'}
+ saved: 0
+ submitted: true
+ created_at: <%= DateTime.now() - 36.hours - 26.minutes %>
+ updated_at: <%= DateTime.now() - 36.hours - 6.minutes %>
+
+jorge4:
+ candidate: jorge
+ question: fed4
+ answer: Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
+ saved: 0
+ submitted: true
+ created_at: <%= DateTime.now() - 36.hours - 28.minutes %>
+ updated_at: <%= DateTime.now() - 36.hours - 28.minutes %>
+
+jorge5:
+ candidate: jorge
+ question: fed5
+ answer: 'Dynamic listeners'
+ saved: 0
+ submitted: true
+ created_at: <%= DateTime.now() - 36.hours - 30.minutes %>
+ updated_at: <%= DateTime.now() - 36.hours - 30.minutes %>
+
+jorge6:
+ candidate: jorge
+ question: fed6
+ answer: Integer posuere erat a ante venenatis dapibus posuere velit aliquet.
+ saved: 0
+ submitted: true
+ created_at: <%= DateTime.now() - 36.hours - 32.minutes %>
+ updated_at: <%= DateTime.now() - 36.hours - 12.minutes %>
+
+jorge7:
+ candidate: jorge
+ question: fed7
+ answer: {html: 'This means jQuery needs to be available in live-coder! ', css: "strong {font-size: 1.6em;}\n.green {color: green;}", js: '$("strong").addClass("green");'}
+ saved: 0
+ submitted: true
+ created_at: <%= DateTime.now() - 36.hours - 34.minutes %>
+ updated_at: <%= DateTime.now() - 36.hours - 14.minutes %>
+
+jorge8:
+ candidate: jorge
+ question: fed8
+ answer:
+ other: Some generic user input
+ options:
+ - other
+ saved: 0
+ submitted: true
+ created_at: <%= DateTime.now() - 36.hours - 36.minutes %>
+ updated_at: <%= DateTime.now() - 36.hours - 16.minutes %>
+
+jorge9:
+ candidate: jorge
+ question: fed9
+ answer:
+ other: Brunch
+ options:
+ - Neither
+ - other
+ saved: 0
+ submitted: true
+ created_at: <%= DateTime.now() - 36.hours - 38.minutes %>
+ updated_at: <%= DateTime.now() - 36.hours - 18.minutes %>
+
+jorge10:
+ candidate: jorge
+ question: fed10
+ answer: ["Live long and prosper", "Who you calling Scruffy?"]
+ saved: 0
+ submitted: true
+ created_at: <%= DateTime.now() - 36.hours - 40.minutes %>
+ updated_at: <%= DateTime.now() - 36.hours - 20.minutes %>
+
+elsie1:
+ candidate: elsie
+ question: Cras justo odio, dapibus ac facilisis in, egestas eget quam. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Nullam id dolor id nibh ultricies vehicula ut id elit.
+ answer: option 3
+ saved: 0
+ submitted: true
+ created_at: <%= DateTime.now() - 36.hours - 22.minutes %>
+ updated_at: <%= DateTime.now() - 36.hours - 22.minutes %>
+
+elsie2:
+ candidate: elsie
+ question: fed2
+ answer: 'indexOf()'
+ saved: 0
+ submitted: true
+ created_at: <%= DateTime.now() - 36.hours - 24.minutes %>
+ updated_at: <%= DateTime.now() - 36.hours - 4.minutes %>
+
+elsie3:
+ candidate: elsie
+ question: fed3
+ answer: {html: 'Salmon', css: 'h1 {color: salmon;}', js: '', text: 'Gotta lotta GOOD things on sale, strangah.'}
+ saved: 0
+ submitted: true
+ created_at: <%= DateTime.now() - 36.hours - 26.minutes %>
+ updated_at: <%= DateTime.now() - 36.hours - 6.minutes %>
+
+elsie4:
+ candidate: elsie
+ question: fed4
+ answer: Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
+ saved: 0
+ submitted: true
+ created_at: <%= DateTime.now() - 36.hours - 28.minutes %>
+ updated_at: <%= DateTime.now() - 36.hours - 28.minutes %>
+
+elsie5:
+ candidate: elsie
+ question: fed5
+ answer: 'Dynamic listeners'
+ saved: 0
+ submitted: true
+ created_at: <%= DateTime.now() - 36.hours - 30.minutes %>
+ updated_at: <%= DateTime.now() - 36.hours - 30.minutes %>
+
+elsie6:
+ candidate: elsie
+ question: fed6
+ answer: Integer posuere erat a ante venenatis dapibus posuere velit aliquet.
+ saved: 0
+ submitted: true
+ created_at: <%= DateTime.now() - 36.hours - 32.minutes %>
+ updated_at: <%= DateTime.now() - 36.hours - 12.minutes %>
+
+elsie7:
+ candidate: elsie
+ question: fed7
+ answer: {html: 'This means jQuery needs to be available in live-coder! ', css: "strong {font-size: 1.6em;}\n.green {color: green;}", js: '$("strong").addClass("green");'}
+ saved: 0
+ submitted: true
+ created_at: <%= DateTime.now() - 36.hours - 34.minutes %>
+ updated_at: <%= DateTime.now() - 36.hours - 14.minutes %>
+
+elsie8:
+ candidate: elsie
+ question: fed8
+ answer:
+ other: Some generic user input
+ options:
+ - other
+ saved: 0
+ submitted: true
+ created_at: <%= DateTime.now() - 36.hours - 36.minutes %>
+ updated_at: <%= DateTime.now() - 36.hours - 16.minutes %>
+
+elsie9:
+ candidate: elsie
+ question: fed9
+ answer:
+ other: Brunch
+ options:
+ - Neither
+ - other
+ saved: 0
+ submitted: true
+ created_at: <%= DateTime.now() - 36.hours - 38.minutes %>
+ updated_at: <%= DateTime.now() - 36.hours - 18.minutes %>
+
+elsie10:
+ candidate: elsie
+ question: fed10
+ answer: ["Live long and prosper", "Who you calling Scruffy?"]
+ saved: 0
+ submitted: true
+ created_at: <%= DateTime.now() - 36.hours - 40.minutes %>
+ updated_at: <%= DateTime.now() - 36.hours - 20.minutes %>
+
diff --git a/test/fixtures/candidates.yml b/test/fixtures/candidates.yml
index 4def21b..d298cc5 100644
--- a/test/fixtures/candidates.yml
+++ b/test/fixtures/candidates.yml
@@ -4,6 +4,9 @@ roy: # Roy should have started, and is ready for a reminder
name: Roy Cruz
email: <%= CryptSerializer.dump 'roy.cruz@mailinator.com' %>
experience: 0-3
+ project: Client/Project
+ position: 'full-time'
+ skill_needs: 'css/html'
recruiter: recruiter
quiz: fed
completed: false
@@ -14,6 +17,9 @@ gillian: # Gillian has not begun the test
name: Gillian Anderson
email: <%= CryptSerializer.dump 'gillian.anderson@mailinator.com' %>
experience: 4-6
+ project: Client/Project
+ position: 'full-time'
+ skill_needs: 'css/html'
recruiter: recruiter
quiz: fed
completed: false
@@ -24,6 +30,9 @@ martha: # Martha has not begun the test
name: Martha Watts
email: <%= CryptSerializer.dump 'martha.watts@mailinator.com' %>
experience: 4-6
+ project: Client/Project
+ position: 'contract'
+ skill_needs: 'angular'
recruiter: recruiter
quiz: fed
completed: false
@@ -34,6 +43,9 @@ dawn: # Dawn has completed, and been reminded, but not submitted the test
name: Dawn Hopkins
email: <%= CryptSerializer.dump 'dawn.hopkins@mailinator.com' %>
experience: 0-2
+ project: Client/Project
+ position: 'contract'
+ skill_needs: 'javascript'
recruiter: recruiter
quiz: fed
completed: false
@@ -44,6 +56,9 @@ peggy: # Peggy has completed, and been reminded, but not submitted the test
name: Peggy Blisters
email: <%= CryptSerializer.dump 'peggy.blisters@mailinator.com' %>
experience: 0-2
+ project: Client/Project
+ position: 'contract'
+ skill_needs: 'css/html'
recruiter: recruiter
quiz: fed
completed: false
@@ -54,17 +69,25 @@ richard: # Richard has completed AND submitted the test
name: Richard Burns
email: <%= CryptSerializer.dump 'richard.burns@mailinator.com' %>
experience: 15+
+ project: Client/Project
+ position: 'full-time'
+ skill_needs: 'css/html'
recruiter: recruiter
quiz: fed
completed: true
+ completed_at: <%= DateTime.current - 20.days %>
reminded: false
test_hash: 6NjnourLE6Y
review_status: 1
+ review_comments: "Some reasons why or why not, but here they are."
juan: # Juan has chosen "finish later" for live coders
name: Juan Campbell
email: <%= CryptSerializer.dump 'juan.campbell@mailinator.com' %>
experience: 15+
+ project: Client/Project
+ position: 'full-time'
+ skill_needs: 'css/html'
recruiter: recruiter
quiz: fed
completed: false
@@ -75,20 +98,29 @@ stacy: # Stacy has completed AND submitted the test
name: Stacy Scott
email: <%= CryptSerializer.dump 'stacy.scott@mailinator.com' %>
experience: 7-9
+ project: Client/Project
+ position: 'full-time'
+ skill_needs: 'css/html'
recruiter: recruiter
quiz: fed
completed: true
+ completed_at: <%= DateTime.current - 13.hours %>
reminded: false
test_hash: s6oFExZliYYFx
review_status: 2
+ review_comments: "Some reasons why or why not, but here they are."
henry: # Henry has completed AND submitted the test
name: Henry Butler
email: <%= CryptSerializer.dump 'henry.butler@mailinator.com' %>
experience: 4-6
+ project: Client/Project
+ position: 'full-time'
+ skill_needs: 'css/html'
recruiter: recruiter
quiz: fed
completed: true
+ completed_at: <%= DateTime.current - 3.days %>
reminded: false
test_hash: egPomAuVDeCEp
@@ -96,16 +128,51 @@ wade: # Wade has completed AND submitted the test
name: Wade Armstrong
email: <%= CryptSerializer.dump 'wade.armstrong@mailinator.com' %>
experience: 0-3
+ project: Client/Project
+ position: 'full-time'
+ skill_needs: 'css/html'
recruiter: recruiter
quiz: fed
completed: true
+ completed_at: <%= DateTime.current - 8.days %>
reminded: false
test_hash: BkSkpapJnkz2N
+jorge: # Jorge has completed AND submitted the test
+ name: Jorge Holmes
+ email: <%= CryptSerializer.dump 'jorge.holmes@mailinator.com' %>
+ experience: 0-3
+ project: Client/Project
+ position: 'full-time'
+ skill_needs: 'css/html'
+ recruiter: recruiter
+ quiz: fed
+ completed: true
+ completed_at: <%= DateTime.current - 12.days + 3.hours %>
+ reminded: false
+ test_hash: iC5FdWJxcyySBmpOpU
+
+elsie: # Elsie has completed AND submitted the test
+ name: Elsie Lowe
+ email: <%= CryptSerializer.dump 'elsie.lowe@mailinator.com' %>
+ experience: 0-3
+ project: Client/Project
+ position: 'full-time'
+ skill_needs: 'css/html'
+ recruiter: recruiter
+ quiz: fed
+ completed: true
+ completed_at: <%= DateTime.current - 45.days + 6.hours %>
+ reminded: false
+ test_hash: rLSoizA3ATMNSCx
+
gustov: # Gustov is NOT for FED
name: Gustov
email: <%= CryptSerializer.dump 'gustov@mailinator.com' %>
experience: 0-3
+ project: Client/Project
+ position: 'full-time'
+ skill_needs: 'C#, SQL'
recruiter: recruiter
quiz: admin
completed: false
diff --git a/test/fixtures/quiz_comments.yml b/test/fixtures/quiz_comments.yml
new file mode 100644
index 0000000..3ac5c7a
--- /dev/null
+++ b/test/fixtures/quiz_comments.yml
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+com1:
+ test_hash: BkSkpapJnkz2N #wade
+ user: reviewer
+ message: Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Etiam porta sem malesuada magna mollis euismod. Aenean lacinia bibendum nulla sed consectetur. Maecenas faucibus mollis interdum.
+
+com2:
+ test_hash: BkSkpapJnkz2N #wade
+ user: reviewer
+ message: Donec sed odio dui. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Curabitur blandit tempus porttitor. Nullam quis risus eget urna mollis ornare vel eu leo. Nullam id dolor id nibh ultricies vehicula ut id elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+
+com3:
+ test_hash: BkSkpapJnkz2N #wade
+ user: reviewer2
+ message: Cras mattis consectetur purus sit amet fermentum. Donec sed odio dui. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.
+
+com4:
+ test_hash: iC5FdWJxcyySBmpOpU #jorge
+ user: manager
+ message: Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed posuere consectetur est at lobortis.
+
+com5:
+ test_hash: egPomAuVDeCEp #henry
+ user: manager
+ message: no.
+
+com6:
+ test_hash: egPomAuVDeCEp #henry
+ user: reviewer2
+ message: fine.
+
+com7:
+ test_hash: iC5FdWJxcyySBmpOpU #jorge
+ user: reviewer
+ message: Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit.
+
+com8:
+ test_hash: egPomAuVDeCEp #henry
+ user: manager
+ message: no.
+
+com9:
+ test_hash: rLSoizA3ATMNSCx #elsie
+ user: reviewer
+ message: Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec ullamcorper nulla non metus auctor fringilla. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Etiam porta sem malesuada magna mollis euismod. Vestibulum id ligula porta felis euismod semper. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Maecenas faucibus mollis interdum.
+
+com10:
+ test_hash: rLSoizA3ATMNSCx #elsie
+ user: reviewer2
+ message: Ornare Tellus Nullam Mattis
+
+com11:
+ test_hash: rLSoizA3ATMNSCx #elsie
+ user: reviewer2
+ message: Nibh Ultricies Purus
+
+com12:
+ test_hash: rLSoizA3ATMNSCx #elsie
+ user: reviewer
+ message: Donec id elit non mi porta gravida at eget metus.
+
+com13:
+ test_hash: rLSoizA3ATMNSCx #elsie
+ user: manager
+ message: Donec id elit non mi porta gravida at eget metus.
+
+com14:
+ test_hash: rLSoizA3ATMNSCx #elsie
+ user: reviewer2
+ message: Ultricies Vulputate Bibendum Parturient
+
+com15:
+ test_hash: 6NjnourLE6Y #richard
+ user: manager
+ message: gibberish
+
+com16:
+ test_hash: egPomAuVDeCEp #henry
+ user: admin
+ message: word.
+
+com17:
+ test_hash: 6NjnourLE6Y #richard
+ user: reviewer
+ message: more gibberish
+
diff --git a/test/fixtures/reviewer_votes.yml b/test/fixtures/reviewer_votes.yml
index 2669604..a8ab4c1 100644
--- a/test/fixtures/reviewer_votes.yml
+++ b/test/fixtures/reviewer_votes.yml
@@ -66,3 +66,30 @@ reviewer2_wade:
candidate: wade
user: reviewer2
+
+manager_jorge:
+ candidate: jorge
+ user: manager
+
+reviewer_jorge:
+ candidate: jorge
+ user: reviewer
+ vote: 1
+
+reviewer2_jorge:
+ candidate: jorge
+ user: reviewer2
+
+
+manager_elsie:
+ candidate: elsie
+ user: manager
+
+reviewer_elsie:
+ candidate: elsie
+ user: reviewer
+
+reviewer2_elsie:
+ candidate: elsie
+ user: reviewer2
+
diff --git a/test/mailers/previews/recruiter_mailer_preview.rb b/test/mailers/previews/recruiter_mailer_preview.rb
index 9a14fb3..f287a52 100644
--- a/test/mailers/previews/recruiter_mailer_preview.rb
+++ b/test/mailers/previews/recruiter_mailer_preview.rb
@@ -8,4 +8,8 @@ class RecruiterMailerPreview < ActionMailer::Preview
def candidate_submitted
RecruiterMailer.candidate_submitted Candidate.find_by(test_hash: 'OvP0ZqGKwJ0') # Dawn
end
+
+ def candidate_reviewed
+ RecruiterMailer.candidate_reviewed Candidate.find_by(test_hash: 's6oFExZliYYFx') # Stacy
+ end
end
diff --git a/test/mailers/previews/reviewer_mailer_preview.rb b/test/mailers/previews/reviewer_mailer_preview.rb
index df8b1cb..9a95c1c 100644
--- a/test/mailers/previews/reviewer_mailer_preview.rb
+++ b/test/mailers/previews/reviewer_mailer_preview.rb
@@ -4,4 +4,18 @@ class ReviewerMailerPreview < ActionMailer::Preview
def candidate_submission
ReviewerMailer.candidate_submission Candidate.find_by(test_hash: 'OvP0ZqGKwJ0') # Dawn
end
+
+ def reminder
+ reminders = ReviewerReminder.new
+ reminder = reminders.reminders.first
+ ReviewerMailer.reminder reminder
+ end
+
+ def notify_manager
+ ReviewerMailer.notify_manager Candidate.find_by(test_hash: 'OvP0ZqGKwJ0').id # Dawn
+ end
+
+ def new_comment
+ ReviewerMailer.new_comment QuizComment.first
+ end
end
diff --git a/test/mailers/previews/user_mailer_preview.rb b/test/mailers/previews/user_mailer_preview.rb
index 27b0d13..6d632ad 100644
--- a/test/mailers/previews/user_mailer_preview.rb
+++ b/test/mailers/previews/user_mailer_preview.rb
@@ -3,6 +3,7 @@
class UserMailerPreview < ActionMailer::Preview
def password_reset
user = User.find_by(email: 'alan.admin@mailinator.com')
+ user.send(:gen_reset_token)
UserMailer.password_reset user
end
diff --git a/test/mailers/recruiter_mailer_test.rb b/test/mailers/recruiter_mailer_test.rb
index 5331ca9..bf1341e 100644
--- a/test/mailers/recruiter_mailer_test.rb
+++ b/test/mailers/recruiter_mailer_test.rb
@@ -12,11 +12,24 @@ class RecruiterMailerTest < ActionMailer::TestCase
end
test "candidate_submitted" do
- candidate = candidates :dawn
+ candidate = candidates :elsie
+ manager = users :manager
mail = RecruiterMailer.candidate_submitted candidate
assert_match candidate.name, mail.subject
assert_equal [candidate.recruiter.email], mail.to
assert_equal [ENV["default_mail_from"]], mail.from
assert_match candidate.name, mail.body.encoded
+ assert_match manager.name, mail.body.encoded
+ end
+
+ test "candidate_reviewed" do
+ candidate = candidates :stacy
+ mail = RecruiterMailer.candidate_reviewed candidate
+ assert_match candidate.name, mail.subject
+ assert_equal [candidate.recruiter.email], mail.to
+ assert_equal [ENV["default_mail_from"]], mail.from
+ assert_match candidate.review_status, mail.body.encoded
+ assert_match candidate.name, mail.body.encoded
+ assert_match candidate.review_comments, mail.body.encoded
end
end
diff --git a/test/mailers/reviewer_mailer_test.rb b/test/mailers/reviewer_mailer_test.rb
index 35673eb..c656806 100644
--- a/test/mailers/reviewer_mailer_test.rb
+++ b/test/mailers/reviewer_mailer_test.rb
@@ -11,4 +11,33 @@ class ReviewerMailerTest < ActionMailer::TestCase
assert_equal [ENV["default_mail_from"]], mail.from
assert_match candidate.test_hash, mail.body.encoded
end
+
+ test "reminder" do
+ reminders = ReviewerReminder.new
+ reminder = reminders.reminders.first
+ mail = ReviewerMailer.reminder reminder
+ assert_match "Review Reminder", mail.subject
+ assert_equal [reminder.email], mail.to
+ assert_equal [ENV["default_mail_from"]], mail.from
+ assert_match reminder.test_hash, mail.body.encoded
+ end
+
+ test "notify_manager" do
+ candidate = candidates(:richard)
+ mail = ReviewerMailer.notify_manager candidate.id
+ assert_match "Voting Complete", mail.subject
+ assert_equal [candidate.manager.email], mail.to
+ assert_equal [ENV["default_mail_from"]], mail.from
+ assert_match candidate.test_hash, mail.body.encoded
+ end
+
+ test "comment notification" do
+ comment = quiz_comments(:com5)
+ mail = ReviewerMailer.new_comment comment
+ assert_match "Comment", mail.subject
+ assert_match comment.test_hash, mail.subject
+ assert_equal comment.candidate.reviewers.map(&:email), mail.to
+ assert_equal [ENV["default_mail_from"]], mail.from
+ assert_match comment.test_hash, mail.body.encoded
+ end
end
diff --git a/test/models/candidate_test.rb b/test/models/candidate_test.rb
index 393c7e8..5b9ea44 100644
--- a/test/models/candidate_test.rb
+++ b/test/models/candidate_test.rb
@@ -6,6 +6,7 @@ class CandidateTest < ActiveSupport::TestCase
candidate = Candidate.create(name: 'new name',
email: 'test@mailinator.com',
experience: '0-3',
+ project: 'Client',
quiz_id: quizzes(:fed).id)
assert candidate.test_hash.present?
@@ -16,6 +17,8 @@ class CandidateTest < ActiveSupport::TestCase
candidate = Candidate.create(name: 'new name',
email: email,
experience: '0-3',
+ project: 'Client',
+ position: 'full-time',
recruiter_id: users(:recruiter).id,
quiz_id: quizzes(:fed).id)
diff --git a/test/models/quiz_comment_test.rb b/test/models/quiz_comment_test.rb
new file mode 100644
index 0000000..9f81ccd
--- /dev/null
+++ b/test/models/quiz_comment_test.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+require 'test_helper'
+
+class QuizCommentTest < ActiveSupport::TestCase
+ test "the truth" do
+ assert QuizComment
+ end
+
+ test "user to comments association" do
+ manager = users(:manager)
+
+ assert_equal 5, manager.quiz_comments.size
+ end
+
+ test "candidate to comments association" do
+ candidate = candidates(:elsie)
+
+ assert_equal 6, candidate.quiz_comments.size
+ end
+
+ test 'comment to user' do
+ comment = quiz_comments(:com1)
+
+ assert_match 'Wade', comment.candidate.name
+ assert_match 'Tina', comment.user.name
+ end
+end
diff --git a/test/models/reviewer_vote_test.rb b/test/models/reviewer_vote_test.rb
index 48db0fe..d5a9ef3 100644
--- a/test/models/reviewer_vote_test.rb
+++ b/test/models/reviewer_vote_test.rb
@@ -3,7 +3,7 @@ require 'test_helper'
class ReviewerVoteTest < ActiveSupport::TestCase
test "the truth" do
- assert ReviewerVoteTest
+ assert ReviewerVote
end
test "richard has 3 votes" do
@@ -12,10 +12,11 @@ class ReviewerVoteTest < ActiveSupport::TestCase
assert_equal 3, richard.votes.size
end
- test "manager has 4 votes" do
+ test "manager has a vote for every completed quiz" do
manager = users(:manager)
+ completed_count = Candidate.where(completed: true).count
- assert_equal 4, manager.votes.size
+ assert_equal completed_count, manager.votes.size
end
test "richard has been approved" do
@@ -31,4 +32,22 @@ class ReviewerVoteTest < ActiveSupport::TestCase
assert stacy.declined?
refute stacy.approved?
end
+
+ test "mailer is queued on last vote" do
+ reviewer = users(:reviewer2)
+ candidate = candidates(:jorge)
+
+ assert_difference("ActionMailer::Base.deliveries.size", 1) do
+ reviewer.cast_yea_on(candidate)
+ end
+ end
+
+ test "mailer is NOT queued on first vote" do
+ reviewer = users(:reviewer2)
+ candidate = candidates(:elsie)
+
+ assert_difference("ActionMailer::Base.deliveries.size", 0) do
+ reviewer.cast_yea_on(candidate)
+ end
+ end
end
diff --git a/test/policies/quiz_comment_policy_test.rb b/test/policies/quiz_comment_policy_test.rb
new file mode 100644
index 0000000..08b2543
--- /dev/null
+++ b/test/policies/quiz_comment_policy_test.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+require 'test_helper'
+
+class QuizCommentPolicyTest < PolicyAssertions::Test
+ test 'should require current_user' do
+ assert_raise Pundit::NotAuthorizedError do
+ QuizCommentPolicy.new(nil, User.first).create?
+ end
+ end
+
+ def test_create
+ candidate = candidates(:stacy)
+ comment = QuizComment.new(test_hash: candidate.test_hash)
+
+ assert_permit users(:manager), comment
+ assert_permit users(:reviewer), comment
+ assert_permit users(:admin), comment
+
+ refute_permit users(:recruiter), comment
+ end
+
+ def test_update
+ assert_permit users(:reviewer2), quiz_comments(:com6)
+
+ refute_permit users(:reviewer), quiz_comments(:com6)
+ refute_permit users(:manager), quiz_comments(:com6)
+ refute_permit users(:admin), quiz_comments(:com6)
+ refute_permit users(:recruiter), quiz_comments(:com6)
+ end
+end
diff --git a/test/policies/reviewer_vote_policy_test.rb b/test/policies/reviewer_vote_policy_test.rb
index 1824293..e529e10 100644
--- a/test/policies/reviewer_vote_policy_test.rb
+++ b/test/policies/reviewer_vote_policy_test.rb
@@ -31,8 +31,8 @@ class ReviewerVotePolicyTest < PolicyAssertions::Test
def test_up
assert_permit users(:manager), reviewer_votes(:manager_richard)
assert_permit users(:reviewer), reviewer_votes(:reviewer_richard)
- assert_permit users(:admin), reviewer_votes(:manager_henry)
+ refute_permit users(:admin), reviewer_votes(:manager_henry)
refute_permit users(:recruiter), reviewer_votes(:manager_henry)
refute_permit users(:reviewer), reviewer_votes(:gustov)
refute_permit users(:manager), reviewer_votes(:gustov)
@@ -41,22 +41,14 @@ class ReviewerVotePolicyTest < PolicyAssertions::Test
def test_down
assert_permit users(:manager), reviewer_votes(:manager_richard)
assert_permit users(:reviewer), reviewer_votes(:reviewer_richard)
- assert_permit users(:admin), reviewer_votes(:manager_henry)
+ refute_permit users(:admin), reviewer_votes(:manager_henry)
refute_permit users(:recruiter), reviewer_votes(:manager_henry)
refute_permit users(:reviewer), reviewer_votes(:gustov)
refute_permit users(:manager), reviewer_votes(:gustov)
end
- def approve
- assert_permit users(:manager), reviewer_votes(:manager_richard)
- assert_permit users(:admin), reviewer_votes(:manager_henry)
-
- refute_permit users(:recruiter), reviewer_votes(:manager_henry)
- refute_permit users(:reviewer), reviewer_votes(:reviewer_richard)
- end
-
- def decline
+ def interview_request
assert_permit users(:manager), reviewer_votes(:manager_richard)
assert_permit users(:admin), reviewer_votes(:manager_henry)
diff --git a/test/test_helper.rb b/test/test_helper.rb
index 65a1a33..275642d 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -8,6 +8,8 @@ SimpleCov.start 'rails' do
add_group 'Services & Workers', %w(app/workers app/services)
add_group "Jobs", 'app/jobs'
add_group "Policies", 'app/policies'
+
+ add_filter "/lib/utils/" # no need to test dev only utility classes
end
require File.expand_path('../../config/environment', __FILE__)
@@ -19,6 +21,7 @@ Dir[Rails.root.join("test/test_helpers/**/*.rb")].each { |f| require f }
Minitest::Reporters.use! [Minitest::Reporters::DefaultReporter.new(color: true)]
class ActiveSupport::TestCase
+ ActiveRecord::Migration.maintain_test_schema!
ActiveRecord::Migration.check_pending!
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
diff --git a/test/workers/reminder_test.rb b/test/workers/candidate_reminder_test.rb
similarity index 81%
rename from test/workers/reminder_test.rb
rename to test/workers/candidate_reminder_test.rb
index 32dabbb..fbe83a5 100644
--- a/test/workers/reminder_test.rb
+++ b/test/workers/candidate_reminder_test.rb
@@ -1,14 +1,14 @@
# frozen_string_literal: true
require 'test_helper'
-class ReminderTest < ActiveSupport::TestCase
+class CandidateReminderTest < ActiveSupport::TestCase
test "collection is created with one result" do
- reminders = Reminder.new
+ reminders = CandidateReminder.new
assert_equal 1, reminders.size
end
test "each candidate has needed attributes" do
- reminders = Reminder.new
+ reminders = CandidateReminder.new
assert_instance_of String, reminders.candidates.first.name
assert_instance_of String, reminders.candidates.first.test_hash
@@ -16,7 +16,7 @@ class ReminderTest < ActiveSupport::TestCase
end
test "send reminders sends email, and flags reminded" do
- reminders = Reminder.new
+ reminders = CandidateReminder.new
pre_reminded = Candidate.find(reminders.candidates.first.id).reminded
assert_difference("ActionMailer::Base.deliveries.size", reminders.count) do
diff --git a/test/workers/quiz_status_test.rb b/test/workers/quiz_status_test.rb
index f79b299..ea52280 100644
--- a/test/workers/quiz_status_test.rb
+++ b/test/workers/quiz_status_test.rb
@@ -97,7 +97,7 @@ class QuizStatusTest < ActiveSupport::TestCase
dawn = candidates :dawn
status = QuizStatus.new dawn
- assert_equal nil, status.current_question_id
+ assert_nil status.current_question_id
end
test "richard has no_finish_laters" do
diff --git a/test/workers/reviewer_reminder_test.rb b/test/workers/reviewer_reminder_test.rb
new file mode 100644
index 0000000..c4399dd
--- /dev/null
+++ b/test/workers/reviewer_reminder_test.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+require 'test_helper'
+
+class ReviewerReminderTest < ActiveSupport::TestCase
+ test "collection is created with results" do
+ reminders = ReviewerReminder.new
+ assert_equal 6, reminders.size
+ end
+
+ test "each reminder has needed attributes" do
+ collection = ReviewerReminder.new
+
+ assert_instance_of String, collection.reminders.first.name
+ assert_instance_of String, collection.reminders.first.email
+ assert_instance_of String, collection.reminders.first.test_hash
+ end
+
+ test "send_all sends emails for each reviewer and test" do
+ collection = ReviewerReminder.new
+
+ assert_difference("ActionMailer::Base.deliveries.size", collection.count) do
+ collection.send_all
+ end
+ end
+end
|