diff --git a/app/validators/answer_format_validator.rb b/app/validators/answer_format_validator.rb index 32f0a3f..9e71bb0 100644 --- a/app/validators/answer_format_validator.rb +++ b/app/validators/answer_format_validator.rb @@ -6,31 +6,32 @@ class AnswerFormatValidator < ActiveModel::EachValidator private def text record, attribute, value - return unless value.length.between? 1, 1000 + clean_val = value.to_s.strip + return if clean_val.length.between?(1, 1000) - if value.blank? + if clean_val.blank? record.errors[attribute] << (options[:message] || "Please enter an answer.") end - if value.length > 1000 + if clean_val.length > 1000 record.errors[attribute] << (options[:message] || "The character limit for a textarea answer is 1000") end end def radio record, attribute, value - return unless value.nil? + return unless value.to_s.strip.blank? record.errors[attribute] << (options[:message] || "Please select an answer.") end def checkbox record, attribute, value - return unless value.nil? || value.join.blank? + return unless value.nil? || Array(value).join.blank? record.errors[attribute] << (options[:message] || "Please select an answer.") end def live_code record, attribute, value - return unless value.nil? + return unless value.nil? || value.values.join.blank? msg = "You must write code in one of the above textareas to progress." record.errors[attribute] << (options[:message] || msg) diff --git a/app/views/candidate/_live_code.html.erb b/app/views/candidate/_live_code.html.erb index 8abd4ec..95fdf44 100644 --- a/app/views/candidate/_live_code.html.erb +++ b/app/views/candidate/_live_code.html.erb @@ -29,3 +29,5 @@ # to check for JS capability/enabled %> + +<%= render partial: "candidate/answer_errors", locals: {question: question, answer: @answer} %> diff --git a/app/views/candidate/live_coder.html.erb b/app/views/candidate/live_coder.html.erb index df661bb..97d0afd 100644 --- a/app/views/candidate/live_coder.html.erb +++ b/app/views/candidate/live_coder.html.erb @@ -13,6 +13,4 @@ <%= text_area_tag 'answer[live_code][js]', (@answer['js'] unless @answer.nil?), { 'data-id' => 'code-js', class: 'code-answer code-js' } %> -<%= render partial: "candidate/answer_errors", locals: {question: @question, answer: @answer} %> -
diff --git a/test/validators/answer_format_validator_test.rb b/test/validators/answer_format_validator_test.rb new file mode 100644 index 0000000..56b4881 --- /dev/null +++ b/test/validators/answer_format_validator_test.rb @@ -0,0 +1,157 @@ +require 'test_helper' + +class AnswerValidatable + include ActiveModel::Validations + + attr_accessor :answer + attr_accessor :question + + validates :answer, answer_format: true + + MockQuestion = Struct.new(:input_type) + + def initialize input_type + @input_type = input_type + end + + def question + MockQuestion.new(@input_type) + end +end + +class AnswerFormatValidatorTest < ActiveSupport::TestCase + # input_type RADIO + + test "radio should pass with string" do + obj = AnswerValidatable.new('radio') + obj.answer = 'option-1' + + assert obj.valid? + assert obj.errors.messages.empty? + end + + test "radio should FAIL with nil" do + obj = AnswerValidatable.new('radio') + obj.answer = nil + + refute obj.valid? + assert_match(/select.*answer/, obj.errors.messages[:answer][0]) + end + + test "radio should FAIL with empty string" do + obj = AnswerValidatable.new('radio') + obj.answer = '' + + refute obj.valid? + assert_match(/select.*answer/, obj.errors.messages[:answer][0]) + end + + # input_type TEXT + + test "text should PASS with string" do + obj = AnswerValidatable.new('text') + obj.answer = "this is a valid answer" + + assert obj.valid? + assert obj.errors.messages.empty? + end + + test "text should FAIL with nil" do + obj = AnswerValidatable.new('text') + obj.answer = nil + + refute obj.valid? + assert_match(/enter.*answer/, obj.errors.messages[:answer][0]) + end + + test "text should FAIL with empry string" do + obj = AnswerValidatable.new('text') + obj.answer = " " + + refute obj.valid? + assert_match(/enter.*answer/, obj.errors.messages[:answer][0]) + end + + test "text should FAIL with more than 1000 charactures" do + obj = AnswerValidatable.new('text') + obj.answer = SecureRandom.urlsafe_base64(1001) + + refute obj.valid? + assert_match(/char.*limit.*1000$/, obj.errors.messages[:answer][0]) + end + + # input_type CHECK BOX + + test "checkbox should PASS with populated array" do + obj = AnswerValidatable.new('checkbox') + obj.answer = ["", "", "valid answer"] + + assert obj.valid? + assert obj.errors.messages.empty? + end + + test "checkbox should FAIL with nil" do + obj = AnswerValidatable.new('checkbox') + obj.answer = nil + + refute obj.valid? + assert_match(/select.*answer/, obj.errors.messages[:answer][0]) + end + + test "checkbox should FAIL with empty string" do + obj = AnswerValidatable.new('checkbox') + obj.answer = " " + + refute obj.valid? + assert_match(/select.*answer/, obj.errors.messages[:answer][0]) + end + + test "checkbox should FAIL with array of empty strings" do + obj = AnswerValidatable.new('checkbox') + obj.answer = ["", "", " "] + + refute obj.valid? + assert_match(/select.*answer/, obj.errors.messages[:answer][0]) + end + + # input_type LIVE CODER + test "live_code should PASS with populated hash" do + obj = AnswerValidatable.new('live_code') + obj.answer = { html: 'this is html', css: '', js: '' } + + assert obj.valid? + assert obj.errors.messages.empty? + end + + test "live_code should PASS with finish later" do + obj = AnswerValidatable.new('live_code') + obj.answer = { later: "true" } + + assert obj.valid? + assert obj.errors.messages.empty? + end + + test "live_code should FAIL with nil" do + obj = AnswerValidatable.new('live_code') + obj.answer = nil + + refute obj.valid? + assert_match(/write.*code/, obj.errors.messages[:answer][0]) + end + + test "live_code should FAIL without checking finish later" do + obj = AnswerValidatable.new('live_code') + obj.answer = { "later" => "" } + + refute obj.valid? + assert_match(/write.*code/, obj.errors.messages[:answer][0]) + end + + test "live_code should FAIL without values" do + obj = AnswerValidatable.new('live_code') + obj.answer = { "later" => "", "html" => "", "css" => "", "js" => "" } + + refute obj.valid? + assert_match(/write.*code/, obj.errors.messages[:answer][0]) + end +end