Browse Source

CLDC-896: Integer Validation (#214)

* Failing spec

* Check pre-type cast value

* Update spec error message

* Ensure age doesn't silently drop strings either
pull/219/head
baarkerlounger 3 years ago committed by GitHub
parent
commit
10ffc620bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 18
      app/models/validations/household_validations.rb
  2. 14
      app/models/validations/property_validations.rb
  3. 3
      config/locales/en.yml
  4. 30
      spec/models/case_log_spec.rb
  5. 61
      spec/models/validations/property_validations_spec.rb
  6. 2
      spec/requests/case_log_controller_spec.rb

18
app/models/validations/household_validations.rb

@ -63,11 +63,7 @@ module Validations::HouseholdValidations
end end
def validate_person_1_age(record) def validate_person_1_age(record)
return unless record.age1 validate_person_age(record, 1, 16)
if !record.age1.is_a?(Integer) || record.age1 < 16 || record.age1 > 120
record.errors.add :age1, I18n.t("validations.household.age.over_16")
end
end end
def validate_person_1_economic(record) def validate_person_1_economic(record)
@ -110,12 +106,18 @@ private
end end
end end
def validate_person_age(record, person_num) def validate_person_age(record, person_num, lower_bound = 1)
age = record.public_send("age#{person_num}") age = record.public_send("age#{person_num}")
return unless age return unless age
if !age.is_a?(Integer) || age < 1 || age > 120 begin
record.errors.add "age#{person_num}".to_sym, I18n.t("validations.household.age.must_be_valid") Integer(record.public_send("age#{person_num}_before_type_cast"))
rescue ArgumentError
record.errors.add "age#{person_num}".to_sym, I18n.t("validations.household.age.must_be_valid", lower_bound: lower_bound)
end
if age < lower_bound || age > 120
record.errors.add "age#{person_num}".to_sym, I18n.t("validations.household.age.must_be_valid", lower_bound: lower_bound)
end end
end end

14
app/models/validations/property_validations.rb

@ -6,7 +6,19 @@ module Validations::PropertyValidations
POSTCODE_REGEXP = /^(([A-Z]{1,2}[0-9][A-Z0-9]?|ASCN|STHL|TDCU|BBND|[BFS]IQQ|PCRN|TKCA) ?[0-9][A-Z]{2}|BFPO ?[0-9]{1,4}|(KY[0-9]|MSR|VG|AI)[ -]?[0-9]{4}|[A-Z]{2} ?[0-9]{2}|GE ?CX|GIR ?0A{2}|SAN ?TA1)$/i POSTCODE_REGEXP = /^(([A-Z]{1,2}[0-9][A-Z0-9]?|ASCN|STHL|TDCU|BBND|[BFS]IQQ|PCRN|TKCA) ?[0-9][A-Z]{2}|BFPO ?[0-9]{1,4}|(KY[0-9]|MSR|VG|AI)[ -]?[0-9]{4}|[A-Z]{2} ?[0-9]{2}|GE ?CX|GIR ?0A{2}|SAN ?TA1)$/i
def validate_property_number_of_times_relet(record) def validate_property_number_of_times_relet(record)
if record.offered && !/^[1-9]$|^0[1-9]$|^1[0-9]$|^20$/.match?(record.offered.to_s) return unless record.offered
# Since offered is an integer type ActiveRecord will automatically cast that for us
# but it's type casting is a little lax so "random" becomes 0. To make sure that doesn't pass
# validation and then get silently dropped we attempt strict type casting on the original value
# as part of our validation.
begin
Integer(record.offered_before_type_cast)
rescue ArgumentError
record.errors.add :offered, I18n.t("validations.property.offered.relet_number")
end
if record.offered.negative? || record.offered > 20
record.errors.add :offered, I18n.t("validations.property.offered.relet_number") record.errors.add :offered, I18n.t("validations.property.offered.relet_number")
end end
end end

3
config/locales/en.yml

@ -86,8 +86,7 @@ en:
preg_occ: preg_occ:
no_female: "You must answer no as there are no female tenants aged 16-50 in the property" no_female: "You must answer no as there are no female tenants aged 16-50 in the property"
age: age:
over_16: "Tenant age must be an integer between 16 and 120" must_be_valid: "Tenant age must be an integer between %{lower_bound} and 120"
must_be_valid: "Tenant age must be an integer between 0 and 120"
retired_male: "Male tenant who is retired must be 65 or over" retired_male: "Male tenant who is retired must be 65 or over"
retired_female: "Female tenant who is retired must be 60 or over" retired_female: "Female tenant who is retired must be 60 or over"
ecstat: ecstat:

30
spec/models/case_log_spec.rb

@ -72,36 +72,6 @@ RSpec.describe Form, type: :model do
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "validates number of relets is a number" do
expect {
CaseLog.create!(
offered: "random",
owning_organisation: owning_organisation,
managing_organisation: managing_organisation,
)
}.to raise_error(ActiveRecord::RecordInvalid)
end
it "validates number of relets is under 20" do
expect {
CaseLog.create!(
offered: 21,
owning_organisation: owning_organisation,
managing_organisation: managing_organisation,
)
}.to raise_error(ActiveRecord::RecordInvalid)
end
it "validates number of relets is over 0" do
expect {
CaseLog.create!(
offered: 0,
owning_organisation: owning_organisation,
managing_organisation: managing_organisation,
)
}.to raise_error(ActiveRecord::RecordInvalid)
end
context "reasonable preference is yes" do context "reasonable preference is yes" do
it "validates a reason must be selected" do it "validates a reason must be selected" do
expect { expect {

61
spec/models/validations/property_validations_spec.rb

@ -0,0 +1,61 @@
require "rails_helper"
require_relative "../../request_helper"
RSpec.describe CaseLog do
let(:owning_organisation) { FactoryBot.create(:organisation) }
let(:managing_organisation) { owning_organisation }
before do
RequestHelper.stub_http_requests
end
describe "#new" do
it "raises an error when offered is present and invalid" do
expect {
CaseLog.create!(
offered: "random",
owning_organisation: owning_organisation,
managing_organisation: managing_organisation,
)
}.to raise_error(ActiveRecord::RecordInvalid)
end
end
end
RSpec.describe Validations::PropertyValidations do
let(:subject) { subject_class.new }
let(:subject_class) { Class.new { include Validations::PropertyValidations } }
let(:record) { FactoryBot.create(:case_log) }
let(:expected_error) { "Number of times property has been offered for relet must be a number between 0 and 20" }
describe "#validate_property_number_of_times_relet" do
it "does not add an error if the record offered is missing" do
record.offered = nil
subject.validate_property_number_of_times_relet(record)
expect(record.errors).to be_empty
end
it "does not add an error if offered is valid (number between 0 and 20)" do
record.offered = 0
subject.validate_property_number_of_times_relet(record)
expect(record.errors).to be_empty
record.offered = 10
subject.validate_property_number_of_times_relet(record)
expect(record.errors).to be_empty
record.offered = 20
subject.validate_property_number_of_times_relet(record)
expect(record.errors).to be_empty
end
it "does add an error when offered is invalid" do
record.offered = "invalid"
subject.validate_property_number_of_times_relet(record)
expect(record.errors).to_not be_empty
expect(record.errors["offered"]).to include(match(expected_error))
record.offered = 21
subject.validate_property_number_of_times_relet(record)
expect(record.errors).to_not be_empty
expect(record.errors["offered"]).to include(match(expected_error))
end
end
end

2
spec/requests/case_log_controller_spec.rb

@ -72,7 +72,7 @@ RSpec.describe CaseLogsController, type: :request do
it "validates case log parameters" do it "validates case log parameters" do
json_response = JSON.parse(response.body) json_response = JSON.parse(response.body)
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_entity)
expect(json_response["errors"]).to match_array([["offered", ["Property number of times relet must be between 0 and 20"]], ["age1", ["Tenant age must be an integer between 16 and 120"]]]) expect(json_response["errors"]).to match_array([["offered", ["Number of times property has been offered for relet must be a number between 0 and 20"]], ["age1", ["Tenant age must be an integer between 16 and 120"]]])
end end
end end

Loading…
Cancel
Save