diff --git a/app/models/validations/shared_validations.rb b/app/models/validations/shared_validations.rb index 99be14509..6a42b02f5 100644 --- a/app/models/validations/shared_validations.rb +++ b/app/models/validations/shared_validations.rb @@ -39,26 +39,18 @@ module Validations::SharedValidations next unless question.step next unless record[question.id] && question.page.routed_to?(record, nil) - begin - input = record.public_send("#{question.id}_before_type_cast") - answer = Float(input) - rescue ArgumentError - add_step_error(record, question) - end - - if (answer * 100) % (question.step * 100) != 0 - add_step_error(record, question) - end - end - end - - def validate_numeric_normal_format(record) - record.form.numeric_questions.each do |question| - next unless record[question.id] && question.page.routed_to?(record, nil) - - user_input = record.public_send("#{question.id}_before_type_cast") - if user_input.is_a?(String) && user_input.include?("e") - record.errors.add question.id.to_sym, I18n.t("validations.numeric.normal_format") + value = record.public_send("#{question.id}_before_type_cast") + field = question.check_answer_label || question.id + incorrect_accuracy = (value.to_d * 100) % (question.step * 100) != 0 + + if question.step < 1 && incorrect_accuracy + record.errors.add question.id.to_sym, I18n.t("validations.numeric.nearest_penny", field:) + elsif incorrect_accuracy || value.to_d != value.to_i # if the user enters a value in exponent notation (eg '4e1') the to_i method does not convert this to the correct value + field = question.check_answer_label || question.id + case question.step + when 1 then record.errors.add question.id.to_sym, I18n.t("validations.numeric.whole_number", field:) + when 10 then record.errors.add question.id.to_sym, I18n.t("validations.numeric.nearest_ten", field:) + end end end end @@ -154,13 +146,4 @@ private record.errors.add question.id.to_sym, :under_min, message: I18n.t("validations.numeric.above_min", field:, min:) end end - - def add_step_error(record, question) - field = question.check_answer_label || question.id - case question.step - when 1 then record.errors.add question.id.to_sym, I18n.t("validations.numeric.whole_number", field:) - when 10 then record.errors.add question.id.to_sym, I18n.t("validations.numeric.nearest_ten", field:) - when 0.01 then record.errors.add question.id.to_sym, I18n.t("validations.numeric.nearest_penny", field:) - end - end end diff --git a/spec/models/validations/shared_validations_spec.rb b/spec/models/validations/shared_validations_spec.rb index 2c985ad83..3de553df9 100644 --- a/spec/models/validations/shared_validations_spec.rb +++ b/spec/models/validations/shared_validations_spec.rb @@ -122,6 +122,12 @@ RSpec.describe Validations::SharedValidations do expect(sales_log.errors[:income1]).to include I18n.t("validations.numeric.whole_number", field: "Buyer 1’s gross annual income") end + it "adds an error if the user attempts to input a number in exponent format" do + sales_log.income1 = "3e5" + shared_validator.validate_numeric_step(sales_log) + expect(sales_log.errors[:income1]).to include I18n.t("validations.numeric.whole_number", field: "Buyer 1’s gross annual income") + end + it "does not add an error if input is an integer" do sales_log.income1 = 30_000 shared_validator.validate_numeric_step(sales_log) @@ -136,6 +142,12 @@ RSpec.describe Validations::SharedValidations do expect(sales_log.errors[:savings]).to include I18n.t("validations.numeric.nearest_ten", field: "Buyer’s total savings (to nearest £10) before any deposit paid") end + it "adds an error if the user attempts to input a number in exponent format" do + sales_log.savings = "3e5" + shared_validator.validate_numeric_step(sales_log) + expect(sales_log.errors[:savings]).to include I18n.t("validations.numeric.nearest_ten", field: "Buyer’s total savings (to nearest £10) before any deposit paid") + end + it "does not add an error if input is a multiple of ten" do sales_log.savings = 30_000 shared_validator.validate_numeric_step(sales_log) @@ -150,6 +162,12 @@ RSpec.describe Validations::SharedValidations do expect(sales_log.errors[:mscharge]).to include I18n.t("validations.numeric.nearest_penny", field: "Monthly leasehold charges") end + it "does not add an error if the user attempts to input a number in exponent format" do + sales_log.mscharge = "3e1" + shared_validator.validate_numeric_step(sales_log) + expect(sales_log.errors).to be_empty + end + it "does not add an error if input has 2 or fewer decimal places" do sales_log.mscharge = 30.74 shared_validator.validate_numeric_step(sales_log) @@ -158,20 +176,6 @@ RSpec.describe Validations::SharedValidations do end end - describe "validating the format of inputs in numeric questions" do - it "adds an error if number is input in exponent notation" do - sales_log.age2 = "1e1" - shared_validator.validate_numeric_normal_format(sales_log) - expect(sales_log.errors[:age2]).to include I18n.t("validations.numeric.normal_format") - end - - it "does not add an error if number is input in standard notation" do - sales_log.age2 = "11" - shared_validator.validate_numeric_normal_format(sales_log) - expect(sales_log.errors).to be_empty - end - end - describe "radio options validations" do it "allows only possible values" do lettings_log.needstype = 1