Browse Source

CLDC-3837: Fix bug with step validation for numeric fields with step 0.1 (#2893)

* CLDC-3837: Fix bug with step validation for numeric fields with step 0.1

* Refactor tests

* Fix test
pull/2897/head^2
Rachael Booth 1 week ago committed by GitHub
parent
commit
80f126c49b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 11
      app/models/validations/shared_validations.rb
  2. 2
      config/locales/validations/shared.en.yml
  3. 74
      spec/models/validations/shared_validations_spec.rb

11
app/models/validations/shared_validations.rb

@ -54,14 +54,15 @@ module Validations::SharedValidations
field = question.check_answer_label || question.id field = question.check_answer_label || question.id
incorrect_accuracy = (value.to_d * 100) % (question.step * 100) != 0 incorrect_accuracy = (value.to_d * 100) % (question.step * 100) != 0
if question.step < 1 && incorrect_accuracy next unless incorrect_accuracy
record.errors.add question.id.to_sym, I18n.t("validations.shared.numeric.nearest_hundredth", 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 case question.step
when 0.01 then record.errors.add question.id.to_sym, I18n.t("validations.shared.numeric.nearest_hundredth", field:)
when 0.1 then record.errors.add question.id.to_sym, I18n.t("validations.shared.numeric.nearest_tenth", field:)
when 1 then record.errors.add question.id.to_sym, :not_integer, message: I18n.t("validations.shared.numeric.whole_number", field:) when 1 then record.errors.add question.id.to_sym, :not_integer, message: I18n.t("validations.shared.numeric.whole_number", field:)
when 10 then record.errors.add question.id.to_sym, I18n.t("validations.shared.numeric.nearest_ten", field:) when 10 then record.errors.add question.id.to_sym, I18n.t("validations.shared.numeric.nearest_ten", field:)
end else
record.errors.add question.id.to_sym, I18n.t("validations.shared.numeric.nearest_step", field:, step: question.step)
end end
end end
end end

2
config/locales/validations/shared.en.yml

@ -9,7 +9,9 @@ en:
above_min: "%{field} must be at least %{min}." above_min: "%{field} must be at least %{min}."
whole_number: "%{field} must be a whole number." whole_number: "%{field} must be a whole number."
nearest_ten: "%{field} must be given to the nearest ten." nearest_ten: "%{field} must be given to the nearest ten."
nearest_tenth: "%{field} must be given to the nearest tenth."
nearest_hundredth: "%{field} must be given to the nearest hundredth." nearest_hundredth: "%{field} must be given to the nearest hundredth."
nearest_step: "${field} must be given to the nearest %{step}."
normal_format: "Enter a number." normal_format: "Enter a number."
format: "%{field} must be a number." format: "%{field} must be a number."

74
spec/models/validations/shared_validations_spec.rb

@ -116,19 +116,23 @@ RSpec.describe Validations::SharedValidations do
end end
describe "validating level of accuracy or rounding for numeric questions" do describe "validating level of accuracy or rounding for numeric questions" do
let(:sales_log) { build(:sales_log, :completed) }
before do
income_question = instance_double(Form::Question, step:, type: "numeric", id: "income1", check_answer_label: "Buyer 1’s gross annual income", page: instance_double(Form::Page, routed_to?: true))
form = instance_double(Form, numeric_questions: [income_question])
allow(FormHandler.instance).to receive(:get_form).and_return(form)
end
context "when validating a question with a step of 1" do context "when validating a question with a step of 1" do
let(:step) { 1 }
it "adds an error if input is a decimal" do it "adds an error if input is a decimal" do
sales_log.income1 = 30_000.5 sales_log.income1 = 30_000.5
shared_validator.validate_numeric_step(sales_log) shared_validator.validate_numeric_step(sales_log)
expect(sales_log.errors[:income1]).to include I18n.t("validations.shared.numeric.whole_number", field: "Buyer 1’s gross annual income") expect(sales_log.errors[:income1]).to include I18n.t("validations.shared.numeric.whole_number", field: "Buyer 1’s gross annual income")
end 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.shared.numeric.whole_number", field: "Buyer 1’s gross annual income")
end
it "does not add an error if input is an integer" do it "does not add an error if input is an integer" do
sales_log.income1 = 30_000 sales_log.income1 = 30_000
shared_validator.validate_numeric_step(sales_log) shared_validator.validate_numeric_step(sales_log)
@ -137,47 +141,64 @@ RSpec.describe Validations::SharedValidations do
end end
context "when validating a question with a step of 10" do context "when validating a question with a step of 10" do
it "adds an error if input is not a multiple of ten" do let(:step) { 10 }
sales_log.savings = 30_005
sales_log.jointpur = 1
shared_validator.validate_numeric_step(sales_log)
expect(sales_log.errors[:savings]).to include I18n.t("validations.shared.numeric.nearest_ten", field: "Buyers’ total savings before any deposit paid")
end
it "adds an error if the user attempts to input a number in exponent format" do it "adds an error if input is not a multiple of ten" do
sales_log.savings = "3e5" sales_log.income1 = 30_005
sales_log.jointpur = 1
shared_validator.validate_numeric_step(sales_log) shared_validator.validate_numeric_step(sales_log)
expect(sales_log.errors[:savings]).to include I18n.t("validations.shared.numeric.nearest_ten", field: "Buyers’ total savings before any deposit paid") expect(sales_log.errors[:income1]).to include I18n.t("validations.shared.numeric.nearest_ten", field: "Buyer 1’s gross annual income")
end end
it "does not add an error if input is a multiple of ten" do it "does not add an error if input is a multiple of ten" do
sales_log.savings = 30_000 sales_log.income1 = 30_000
shared_validator.validate_numeric_step(sales_log) shared_validator.validate_numeric_step(sales_log)
expect(sales_log.errors).to be_empty expect(sales_log.errors).to be_empty
end end
end end
context "when validating a question with a step of 0.01" do context "when validating a question with a step of 0.01" do
let(:step) { 0.01 }
it "adds an error if input has more than 2 decimal places" do it "adds an error if input has more than 2 decimal places" do
sales_log.mscharge = 30.7418 sales_log.income1 = 30_123.7418
shared_validator.validate_numeric_step(sales_log) shared_validator.validate_numeric_step(sales_log)
expect(sales_log.errors[:mscharge]).to include I18n.t("validations.shared.numeric.nearest_hundredth", field: "Monthly leasehold charges") expect(sales_log.errors[:income1]).to include I18n.t("validations.shared.numeric.nearest_hundredth", field: "Buyer 1’s gross annual income")
end end
it "does not add an error if the user attempts to input a number in exponent format" do it "does not add an error if input has 2 or fewer decimal places" do
sales_log.mscharge = "3e1" sales_log.income1 = 30_123.74
shared_validator.validate_numeric_step(sales_log) shared_validator.validate_numeric_step(sales_log)
expect(sales_log.errors).to be_empty expect(sales_log.errors).to be_empty
end end
end
it "does not add an error if input has 2 or fewer decimal places" do context "when validating a question with a step of 0.1" do
sales_log.mscharge = 30.74 let(:step) { 0.1 }
it "adds an error if input has more than 1 decimal place" do
sales_log.income1 = 30_123.74
shared_validator.validate_numeric_step(sales_log)
expect(sales_log.errors[:income1]).to include I18n.t("validations.shared.numeric.nearest_tenth", field: "Buyer 1’s gross annual income")
end
it "does not add an error if input has 1 or fewer decimal places" do
sales_log.income1 = 30_123.8
shared_validator.validate_numeric_step(sales_log) shared_validator.validate_numeric_step(sales_log)
expect(sales_log.errors).to be_empty expect(sales_log.errors).to be_empty
end end
end end
context "when validating a question with an unusual step" do
let(:step) { 0.001 }
it "adds an appropriate error if input does not match" do
sales_log.income1 = 30_123.7419
shared_validator.validate_numeric_step(sales_log)
expect(sales_log.errors[:income1]).to include I18n.t("validations.shared.numeric.nearest_step", field: "Buyer 1’s gross annual income", step: 0.001)
end
end
end
%i[sales_log lettings_log].each do |log_type| %i[sales_log lettings_log].each do |log_type|
describe "validate_owning_organisation_data_sharing_agremeent_signed" do describe "validate_owning_organisation_data_sharing_agremeent_signed" do
it "is valid if the Data Protection Confirmation is signed" do it "is valid if the Data Protection Confirmation is signed" do
@ -214,7 +235,6 @@ RSpec.describe Validations::SharedValidations do
end end
end end
end end
end
describe "validate numeric question input" do describe "validate numeric question input" do
it "does not allow letters" do it "does not allow letters" do
@ -229,6 +249,12 @@ RSpec.describe Validations::SharedValidations do
expect(sales_log.errors[:income1]).to include I18n.t("validations.shared.numeric.format", field: "Buyer 1’s gross annual income") expect(sales_log.errors[:income1]).to include I18n.t("validations.shared.numeric.format", field: "Buyer 1’s gross annual income")
end end
it "does not allow exponent format" do
sales_log.income1 = "1e4"
shared_validator.validate_numeric_input(sales_log)
expect(sales_log.errors[:income1]).to include I18n.t("validations.shared.numeric.format", field: "Buyer 1’s gross annual income")
end
it "allows a digit" do it "allows a digit" do
sales_log.income1 = "300" sales_log.income1 = "300"
shared_validator.validate_numeric_input(sales_log) shared_validator.validate_numeric_input(sales_log)

Loading…
Cancel
Save