Browse Source

CLDC-3693: Extract shared validations (#2744)

* Extract lettings household validation from shared validations

* Extract lettings setup validation from shared validations

* Extract only shared validations
pull/2750/head^2
Manny Dinssa 1 month ago committed by GitHub
parent
commit
61eb0057f6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      app/models/user.rb
  2. 9
      app/models/validations/household_validations.rb
  3. 8
      app/models/validations/property_validations.rb
  4. 9
      app/models/validations/sales/household_validations.rb
  5. 8
      app/models/validations/sales/property_validations.rb
  6. 8
      app/models/validations/sales/setup_validations.rb
  7. 49
      app/models/validations/setup_validations.rb
  8. 80
      app/models/validations/shared_validations.rb
  9. 35
      config/locales/en.yml
  10. 7
      config/locales/validations/lettings/household.en.yml
  11. 6
      config/locales/validations/lettings/property_information.en.yml
  12. 35
      config/locales/validations/lettings/setup.en.yml
  13. 1
      config/locales/validations/sales/property_information.en.yml
  14. 1
      config/locales/validations/sales/setup.en.yml
  15. 19
      config/locales/validations/shared.en.yml
  16. 4
      lib/tasks/generate_lettings_documentation.rake
  17. 4
      lib/tasks/generate_sales_documentation.rake
  18. 8
      spec/models/form/sales/pages/la_nominations_spec.rb
  19. 6
      spec/models/form/sales/pages/last_accommodation_la_spec.rb
  20. 6
      spec/models/form/sales/pages/last_accommodation_spec.rb
  21. 2
      spec/models/validations/date_validations_spec.rb
  22. 14
      spec/models/validations/household_validations_spec.rb
  23. 42
      spec/models/validations/setup_validations_spec.rb
  24. 34
      spec/models/validations/shared_validations_spec.rb
  25. 4
      spec/models/validations/tenancy_validations_spec.rb
  26. 2
      spec/requests/lettings_logs_controller_spec.rb

2
app/models/user.rb

@ -19,7 +19,7 @@ class User < ApplicationRecord
validates :password, presence: { if: :password_required? }
validates :password, length: { within: Devise.password_length, allow_blank: true }
validates :password, confirmation: { if: :password_required? }
validates :phone_extension, format: { with: /\A\d+\z/, allow_blank: true, message: I18n.t("validations.numeric.format", field: "") }
validates :phone_extension, format: { with: /\A\d+\z/, allow_blank: true, message: I18n.t("validations.not_number", field: "") }
after_validation :send_data_protection_confirmation_reminder, if: :is_dpo_changed?

9
app/models/validations/household_validations.rb

@ -52,7 +52,14 @@ module Validations::HouseholdValidations
end
def validate_partner_count(record)
shared_validate_partner_count(record, 8)
return if record.form.start_year_2024_or_later?
partner_numbers = (2..8).select { |n| person_is_partner?(record["relat#{n}"]) }
if partner_numbers.count > 1
partner_numbers.each do |n|
record.errors.add "relat#{n}", I18n.t("validations.lettings.household.relat.one_partner")
end
end
end
def validate_person_1_economic(record)

8
app/models/validations/property_validations.rb

@ -57,4 +57,12 @@ module Validations::PropertyValidations
record.errors.add :uprn, I18n.t("validations.property.uprn.invalid")
end
def validate_property_postcode(record)
postcode = record.postcode_full
if record.postcode_known? && (postcode.blank? || !postcode.match(POSTCODE_REGEXP))
error_message = I18n.t("validations.lettings.property_information.postcode_full.invalid")
record.errors.add :postcode_full, :wrong_format, message: error_message
end
end
end

9
app/models/validations/sales/household_validations.rb

@ -2,7 +2,14 @@ module Validations::Sales::HouseholdValidations
include Validations::SharedValidations
def validate_partner_count(record)
shared_validate_partner_count(record, 6)
return if record.form.start_year_2024_or_later?
partner_numbers = (2..6).select { |n| person_is_partner?(record["relat#{n}"]) }
if partner_numbers.count > 1
partner_numbers.each do |n|
record.errors.add "relat#{n}", I18n.t("validations.sales.household.relat.one_partner")
end
end
end
def validate_buyers_living_in_property(record)

8
app/models/validations/sales/property_validations.rb

@ -28,4 +28,12 @@ module Validations::Sales::PropertyValidations
record.errors.add :uprn, I18n.t("validations.sales.property_information.uprn.invalid")
end
def validate_property_postcode(record)
postcode = record.postcode_full
if record.postcode_known? && (postcode.blank? || !postcode.match(POSTCODE_REGEXP))
error_message = I18n.t("validations.sales.property_information.postcode_full.invalid")
record.errors.add :postcode_full, :wrong_format, message: error_message
end
end
end

8
app/models/validations/sales/setup_validations.rb

@ -58,6 +58,14 @@ module Validations::Sales::SetupValidations
end
end
def validate_owning_organisation_data_sharing_agremeent_signed(record)
return if record.skip_dpo_validation
if record.owning_organisation_id_changed? && record.owning_organisation.present? && !record.owning_organisation.data_protection_confirmed?
record.errors.add :owning_organisation_id, I18n.t("validations.sales.setup.owning_organisation.data_sharing_agreement_not_signed")
end
end
private
def active_collection_start_date

49
app/models/validations/setup_validations.rb

@ -72,17 +72,15 @@ module Validations::SetupValidations
end
end
def validate_scheme_has_confirmed_locations_validation(record)
def validate_scheme(record)
return unless record.scheme
unless record.scheme.locations.confirmed.any?
record.errors.add :scheme_id, :no_completed_locations, message: I18n.t("validations.lettings.setup.scheme.no_completed_locations")
end
if record.scheme.status == :incomplete
record.errors.add :scheme_id, :incomplete, message: I18n.t("validations.lettings.setup.scheme.incomplete")
end
def validate_scheme(record)
if record.scheme&.status == :incomplete
record.errors.add :scheme_id, :incomplete, message: I18n.t("validations.lettings.setup.scheme.incomplete")
if record.scheme.locations.nil? || (record.scheme.locations.present? && record.scheme.locations.confirmed.none?)
record.errors.add :scheme_id, :no_completed_locations, message: I18n.t("validations.lettings.setup.scheme.no_completed_locations")
end
scheme_during_startdate_validation(record)
@ -98,6 +96,35 @@ module Validations::SetupValidations
end
end
def location_during_startdate_validation(record)
location_inactive_status = inactive_status(record.startdate, record.location)
if location_inactive_status.present?
date, scope, deactivation_date = location_inactive_status.values_at(:date, :scope, :deactivation_date)
record.errors.add :startdate, :not_active, message: I18n.t("validations.lettings.setup.startdate.location.#{scope}.startdate", postcode: record.location.postcode, date:, deactivation_date:)
record.errors.add :location_id, :not_active, message: I18n.t("validations.lettings.setup.startdate.location.#{scope}.location_id", postcode: record.location.postcode, date:, deactivation_date:)
record.errors.add :scheme_id, :not_active, message: I18n.t("validations.lettings.setup.startdate.location.#{scope}.location_id", postcode: record.location.postcode, date:, deactivation_date:)
end
end
def scheme_during_startdate_validation(record)
scheme_inactive_status = inactive_status(record.startdate, record.scheme)
if scheme_inactive_status.present?
date, scope, deactivation_date = scheme_inactive_status.values_at(:date, :scope, :deactivation_date)
record.errors.add :startdate, I18n.t("validations.lettings.setup.startdate.scheme.#{scope}.startdate", name: record.scheme.service_name, date:, deactivation_date:)
record.errors.add :scheme_id, I18n.t("validations.lettings.setup.startdate.scheme.#{scope}.scheme_id", name: record.scheme.service_name, date:, deactivation_date:)
end
end
def tenancy_startdate_with_scheme_locations(record)
return if record.scheme.blank? || record.startdate.blank?
return if record.scheme.has_active_locations_on_date?(record.startdate)
record.errors.add :startdate, I18n.t("validations.lettings.setup.startdate.scheme.locations_inactive.startdate", name: record.scheme.service_name)
record.errors.add :scheme_id, I18n.t("validations.lettings.setup.startdate.scheme.locations_inactive.scheme_id", name: record.scheme.service_name)
end
def validate_managing_organisation_data_sharing_agremeent_signed(record)
return if record.skip_dpo_validation
@ -106,6 +133,14 @@ module Validations::SetupValidations
end
end
def validate_owning_organisation_data_sharing_agremeent_signed(record)
return if record.skip_dpo_validation
if record.owning_organisation_id_changed? && record.owning_organisation.present? && !record.owning_organisation.data_protection_confirmed?
record.errors.add :owning_organisation_id, I18n.t("validations.lettings.setup.owning_organisation.data_sharing_agreement_not_signed")
end
end
private
def active_collection_start_date

80
app/models/validations/shared_validations.rb

@ -7,12 +7,12 @@ module Validations::SharedValidations
main_field_label = main_label || main_field.to_s.humanize(capitalize: false)
other_field_label = other_label || other_field.to_s.humanize(capitalize: false)
if record[main_field] == value_other && record[other_field].blank?
record.errors.add main_field.to_sym, I18n.t("validations.other_field_missing", main_field_label:, other_field_label:)
record.errors.add other_field.to_sym, I18n.t("validations.other_field_missing", main_field_label:, other_field_label:)
record.errors.add main_field.to_sym, I18n.t("validations.shared.other_field_missing", main_field_label:, other_field_label:)
record.errors.add other_field.to_sym, I18n.t("validations.shared.other_field_missing", main_field_label:, other_field_label:)
end
if record[main_field] != value_other && record[other_field].present?
record.errors.add other_field.to_sym, I18n.t("validations.other_field_not_required", main_field_label:, other_field_label:)
record.errors.add other_field.to_sym, I18n.t("validations.shared.other_field_not_required", main_field_label:, other_field_label:)
end
end
@ -22,7 +22,7 @@ module Validations::SharedValidations
next if record.send("#{question.id}_before_type_cast").to_s.match?(/\A\d+(\.\d+)?\z/)
field = question.check_answer_label || question.id
record.errors.add question.id.to_sym, I18n.t("validations.numeric.format", field:)
record.errors.add question.id.to_sym, I18n.t("validations.shared.numeric.format", field:)
end
end
@ -55,46 +55,17 @@ module Validations::SharedValidations
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_hundredth", field:)
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
when 1 then record.errors.add question.id.to_sym, :not_integer, message: 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 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:)
end
end
end
end
def validate_property_postcode(record)
postcode = record.postcode_full
if record.postcode_known? && (postcode.blank? || !postcode.match(POSTCODE_REGEXP))
error_message = I18n.t("validations.postcode")
record.errors.add :postcode_full, :wrong_format, message: error_message
end
end
def location_during_startdate_validation(record)
location_inactive_status = inactive_status(record.startdate, record.location)
if location_inactive_status.present?
date, scope, deactivation_date = location_inactive_status.values_at(:date, :scope, :deactivation_date)
record.errors.add :startdate, :not_active, message: I18n.t("validations.setup.startdate.location.#{scope}.startdate", postcode: record.location.postcode, date:, deactivation_date:)
record.errors.add :location_id, :not_active, message: I18n.t("validations.setup.startdate.location.#{scope}.location_id", postcode: record.location.postcode, date:, deactivation_date:)
record.errors.add :scheme_id, :not_active, message: I18n.t("validations.setup.startdate.location.#{scope}.location_id", postcode: record.location.postcode, date:, deactivation_date:)
end
end
def scheme_during_startdate_validation(record)
scheme_inactive_status = inactive_status(record.startdate, record.scheme)
if scheme_inactive_status.present?
date, scope, deactivation_date = scheme_inactive_status.values_at(:date, :scope, :deactivation_date)
record.errors.add :startdate, I18n.t("validations.setup.startdate.scheme.#{scope}.startdate", name: record.scheme.service_name, date:, deactivation_date:)
record.errors.add :scheme_id, I18n.t("validations.setup.startdate.scheme.#{scope}.scheme_id", name: record.scheme.service_name, date:, deactivation_date:)
end
end
def inactive_status(date, resource)
return if date.blank? || resource.blank?
@ -117,46 +88,15 @@ module Validations::SharedValidations
{ scope: status, date: date&.to_formatted_s(:govuk_date), deactivation_date: closest_reactivation&.deactivation_date&.to_formatted_s(:govuk_date) }
end
def tenancy_startdate_with_scheme_locations(record)
return if record.scheme.blank? || record.startdate.blank?
return if record.scheme.has_active_locations_on_date?(record.startdate)
record.errors.add :startdate, I18n.t("validations.setup.startdate.scheme.locations_inactive.startdate", name: record.scheme.service_name)
record.errors.add :scheme_id, I18n.t("validations.setup.startdate.scheme.locations_inactive.scheme_id", name: record.scheme.service_name)
end
def shared_validate_partner_count(record, max_people)
return if record.form.start_year_2024_or_later?
partner_numbers = (2..max_people).select { |n| person_is_partner?(record["relat#{n}"]) }
if partner_numbers.count > 1
partner_numbers.each do |n|
if record.sales?
record.errors.add "relat#{n}", I18n.t("validations.sales.household.relat.one_partner")
else
record.errors.add "relat#{n}", I18n.t("validations.household.relat.one_partner")
end
end
end
end
def date_valid?(question, record)
if record[question].is_a?(ActiveSupport::TimeWithZone) && record[question].year.zero?
record.errors.add question, I18n.t("validations.date.invalid_date")
record.errors.add question, I18n.t("validations.shared.date.invalid_date")
false
else
true
end
end
def validate_owning_organisation_data_sharing_agremeent_signed(record)
return if record.skip_dpo_validation
if record.owning_organisation_id_changed? && record.owning_organisation.present? && !record.owning_organisation.data_protection_confirmed?
record.errors.add :owning_organisation_id, I18n.t("validations.setup.owning_organisation.data_sharing_agreement_not_signed")
end
end
private
def person_is_partner?(relationship)
@ -169,9 +109,9 @@ private
max = [question.prefix, number_with_delimiter(question.max, delimiter: ","), question.suffix].join("") if question.max
if min && max
record.errors.add question.id.to_sym, :outside_the_range, message: I18n.t("validations.numeric.within_range", field:, min:, max:)
record.errors.add question.id.to_sym, :outside_the_range, message: I18n.t("validations.shared.numeric.within_range", field:, min:, max:)
elsif min
record.errors.add question.id.to_sym, :under_min, message: I18n.t("validations.numeric.above_min", field:, min:)
record.errors.add question.id.to_sym, :under_min, message: I18n.t("validations.shared.numeric.above_min", field:, min:)
end
end
end

35
config/locales/en.yml

@ -239,23 +239,12 @@ en:
merged: "That organisation has already been merged. Select a different organisation."
scheme_duplicates_not_resolved: "You must resolve all duplicates or indicate that there are no duplicates"
not_answered: "You must answer %{question}"
not_number: "%{field} must be a number."
invalid_option: "Enter a valid value for %{question}"
invalid_number: "Enter a number for %{question}"
no_address_found: "We could not find this address. Check the address data in your CSV file is correct and complete, or select the correct address using the CORE site."
other_field_missing: "If %{main_field_label} is other then %{other_field_label} must be provided."
other_field_not_required: "%{other_field_label} must not be provided if %{main_field_label} was not other."
numeric:
within_range: "%{field} must be between %{min} and %{max}."
above_min: "%{field} must be at least %{min}."
whole_number: "%{field} must be a whole number."
nearest_ten: "%{field} must be given to the nearest ten."
nearest_hundredth: "%{field} must be given to the nearest hundredth."
normal_format: "Enter a number."
format: "%{field} must be a number."
date:
invalid_date: "Enter a date in the correct format, for example 31 1 2024."
outside_collection_window: "Enter a date within the %{year_combo} collection year, which is between 1st April %{start_year} and 31st March %{end_year}."
postcode: "Enter a postcode in the correct format, for example AA1 1AA."
location_admin_district: "Select a local authority."
@ -271,29 +260,8 @@ en:
year_not_two_or_four_digits: "Sale completion year must be 2 or 4 digits."
type:
percentage_bought_must_be_at_least_threshold: "The minimum increase in equity while staircasing is %{threshold}% for this shared ownership type."
startdate:
before_scheme_end_date: "The tenancy start date must be before the end date for this supported housing scheme."
location:
deactivated:
startdate: "The location %{postcode} is inactive on this date. Enter another date or choose another location."
location_id: "This location is not active on the tenancy start date. Choose another location or edit the tenancy start date."
activating_soon:
startdate: "The location %{postcode} is not available until %{date}. Enter a tenancy start date after %{date}."
location_id: "The location %{postcode} is not available until %{date}. Select another location or edit the tenancy start date."
reactivating_soon:
startdate: "The location %{postcode} is not available until %{date}. Enter a tenancy start date after %{date}."
location_id: "The location %{postcode} is not available until %{date}. Select another location or edit the tenancy start date."
scheme:
deactivated:
startdate: "The scheme %{name} was deactivated on %{date} and was not available on the day you entered. Select another scheme or edit the tenancy start date."
scheme_id: "The scheme %{name} was deactivated on %{date} and was not available on the day you entered. Select another scheme or edit the tenancy start date."
reactivating_soon:
startdate: "The scheme %{name} is not available until %{date}. Enter a tenancy start date after %{date}."
scheme_id: "The scheme %{name} is not available until %{date}. Select another scheme or edit the tenancy start date."
locations_inactive:
startdate: "The scheme %{name} has no locations that are active on this date. Enter another date or choose another scheme."
scheme_id: "The scheme %{name} has no locations that are active on this date. Enter another date or choose another scheme."
owning_organisation:
data_sharing_agreement_not_signed: "The organisation must accept the Data Sharing Agreement before it can be selected as the owning organisation."
property:
@ -451,7 +419,6 @@ en:
cannot_be_student: "Person cannot be a student if they are aged 16-19 but are not a child."
relat:
child_under_16_lettings: "Answer cannot be ‘partner’ as you told us person %{person_num}'s age is under 16."
one_partner: "Number of partners cannot be greater than 1."
not_student_16_19: "Answer cannot be ‘child’ as you told us the person %{person_num} is between 16 and 19 and is not a full-time student."
student_16_19:
cannot_be_child:

7
config/locales/validations/lettings/household.en.yml

@ -0,0 +1,7 @@
en:
validations:
lettings:
household:
relat:
one_partner: "Number of partners cannot be greater than 1."

6
config/locales/validations/lettings/property_information.en.yml

@ -0,0 +1,6 @@
en:
validations:
lettings:
property_information:
postcode_full:
invalid: "Enter a postcode in the correct format, for example AA1 1AA."

35
config/locales/validations/lettings/setup.en.yml

@ -21,12 +21,40 @@ en:
owning_organisation: "Enter a date when the owning organisation was active. %{owning_organisation} became active on %{available_from}."
managing_organisation: "Enter a date when the managing organisation was active. %{managing_organisation} became active on %{available_from}."
different_organisations: "Enter a date when the owning and managing organisations were active. %{owning_organisation} became active on %{owning_organisation_active_from}, and %{managing_organisation} became active on %{managing_organisation_active_from}."
location:
deactivated:
startdate: "The location %{postcode} is inactive on this date. Enter another date or choose another location."
location_id: "This location is not active on the tenancy start date. Choose another location or edit the tenancy start date."
activating_soon:
startdate: "The location %{postcode} is not available until %{date}. Enter a tenancy start date after %{date}."
location_id: "The location %{postcode} is not available until %{date}. Select another location or edit the tenancy start date."
reactivating_soon:
startdate: "The location %{postcode} is not available until %{date}. Enter a tenancy start date after %{date}."
location_id: "The location %{postcode} is not available until %{date}. Select another location or edit the tenancy start date."
scheme:
deactivated:
startdate: "The scheme %{name} was deactivated on %{date} and was not available on the day you entered. Select another scheme or edit the tenancy start date."
scheme_id: "The scheme %{name} was deactivated on %{date} and was not available on the day you entered. Select another scheme or edit the tenancy start date."
reactivating_soon:
startdate: "The scheme %{name} is not available until %{date}. Enter a tenancy start date after %{date}."
scheme_id: "The scheme %{name} is not available until %{date}. Select another scheme or edit the tenancy start date."
locations_inactive:
startdate: "The scheme %{name} has no locations that are active on this date. Enter another date or choose another scheme."
scheme_id: "The scheme %{name} has no locations that are active on this date. Enter another date or choose another scheme."
scheme:
incomplete: "This scheme is incomplete. Select another scheme or update this one."
no_completed_locations: "This scheme cannot be chosen as it has no completed locations."
location:
incomplete: "This location is incomplete. Select another location or update this one."
assigned_to:
invalid: "Please select the owning organisation or managing organisation that you belong to."
owning_organisation:
invalid: "Please select the owning organisation or managing organisation that you belong to."
data_sharing_agreement_not_signed: "The organisation must accept the Data Sharing Agreement before it can be selected as the owning organisation."
inactive:
merged_organisation:
"The owning organisation must be active on the tenancy start date. %{owning_organisation} became inactive on %{merge_date} and was replaced by %{absorbing_organisation}."
@ -44,10 +72,3 @@ en:
intermediate_rent_product_name:
blank: "Enter name of other intermediate rent product."
scheme:
incomplete: "This scheme is incomplete. Select another scheme or update this one."
no_completed_locations: "This scheme cannot be chosen as it has no completed locations."
location:
incomplete: "This location is incomplete. Select another location or update this one."

1
config/locales/validations/sales/property_information.en.yml

@ -6,6 +6,7 @@ en:
postcode_must_match_previous:
joint_purchase: "Buyers’ last accommodation and discounted ownership postcodes must match."
not_joint_purchase: "Buyer’s last accommodation and discounted ownership postcodes must match."
invalid: "Enter a postcode in the correct format, for example AA1 1AA."
ppostcode_full:
postcode_must_match_previous:
joint_purchase: "Buyers’ last accommodation and discounted ownership postcodes must match."

1
config/locales/validations/sales/setup.en.yml

@ -17,6 +17,7 @@ en:
"Enter a date when the owning organisation was active. %{owning_organisation} became active on %{available_from}."
owning_organisation:
data_sharing_agreement_not_signed: "The organisation must accept the Data Sharing Agreement before it can be selected as the owning organisation."
inactive:
merged_organisation:
"The owning organisation must be active on the sale completion date. %{owning_organisation} became inactive on %{merge_date} and was replaced by %{absorbing_organisation}."

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

@ -0,0 +1,19 @@
en:
validations:
shared:
other_field_missing: "If %{main_field_label} is other then %{other_field_label} must be provided."
other_field_not_required: "%{other_field_label} must not be provided if %{main_field_label} was not other."
numeric:
within_range: "%{field} must be between %{min} and %{max}."
above_min: "%{field} must be at least %{min}."
whole_number: "%{field} must be a whole number."
nearest_ten: "%{field} must be given to the nearest ten."
nearest_hundredth: "%{field} must be given to the nearest hundredth."
normal_format: "Enter a number."
format: "%{field} must be a number."
postcode: "Enter a postcode in the correct format, for example AA1 1AA."
date:
invalid_date: "Enter a date in the correct format, for example 31 1 2024."

4
lib/tasks/generate_lettings_documentation.rake

@ -60,13 +60,13 @@ namespace :generate_lettings_documentation do
min = [question.prefix, question.min].join("") if question.min
max = [question.prefix, question.max].join("") if question.max
error_message = I18n.t("validations.numeric.above_min", field:, min:)
error_message = I18n.t("validations.shared.numeric.above_min", field:, min:)
validation_name = "minimum"
validation_description = "Field value is lower than the minimum value"
if min && max
validation_name = "range"
error_message = I18n.t("validations.numeric.within_range", field:, min:, max:)
error_message = I18n.t("validations.shared.numeric.within_range", field:, min:, max:)
validation_description = "Field value is lower than the minimum value or higher than the maximum value"
end

4
lib/tasks/generate_sales_documentation.rake

@ -59,13 +59,13 @@ namespace :generate_sales_documentation do
min = [question.prefix, question.min].join("") if question.min
max = [question.prefix, question.max].join("") if question.max
error_message = I18n.t("validations.numeric.above_min", field:, min:)
error_message = I18n.t("validations.shared.numeric.above_min", field:, min:)
validation_name = "minimum"
validation_description = "Field value is lower than the minimum value"
if min && max
validation_name = "range"
error_message = I18n.t("validations.numeric.within_range", field:, min:, max:)
error_message = I18n.t("validations.shared.numeric.within_range", field:, min:, max:)
validation_description = "Field value is lower than the minimum value or higher than the maximum value"
end

8
spec/models/form/sales/pages/la_nominations_spec.rb

@ -7,8 +7,8 @@ RSpec.describe Form::Sales::Pages::LaNominations, type: :model do
let(:page_id) { nil }
let(:page_definition) { nil }
let(:start_year_after_2024) { false }
let(:form) { instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_2024_or_later?: start_year_after_2024) }
let(:start_year_2024_or_later) { false }
let(:form) { instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_2024_or_later?: start_year_2024_or_later) }
let(:subsection) { instance_double(Form::Subsection, form:) }
before do
@ -32,7 +32,7 @@ RSpec.describe Form::Sales::Pages::LaNominations, type: :model do
end
context "with 23/24 log" do
let(:start_year_after_2024) { false }
let(:start_year_2024_or_later) { false }
it "has correct routed to" do
log.staircase = 1
@ -41,7 +41,7 @@ RSpec.describe Form::Sales::Pages::LaNominations, type: :model do
end
context "with 24/25 log" do
let(:start_year_after_2024) { true }
let(:start_year_2024_or_later) { true }
it "has correct routed to when staircase is yes" do
log.staircase = 1

6
spec/models/form/sales/pages/last_accommodation_la_spec.rb

@ -5,8 +5,8 @@ RSpec.describe Form::Sales::Pages::LastAccommodationLa, type: :model do
let(:page_id) { nil }
let(:page_definition) { nil }
let(:start_year_after_2024) { false }
let(:form) { instance_double(Form, depends_on_met: true, start_date: Time.zone.local(2023, 4, 1), start_year_2024_or_later?: start_year_after_2024) }
let(:start_year_2024_or_later) { false }
let(:form) { instance_double(Form, depends_on_met: true, start_date: Time.zone.local(2023, 4, 1), start_year_2024_or_later?: start_year_2024_or_later) }
let(:subsection) { instance_double(Form::Subsection, form:, depends_on: nil, enabled?: true) }
let(:log) { build(:sales_log, :completed) }
@ -38,7 +38,7 @@ RSpec.describe Form::Sales::Pages::LastAccommodationLa, type: :model do
end
context "with 2024 form" do
let(:start_year_after_2024) { true }
let(:start_year_2024_or_later) { true }
it "is routed to for 2024 non discounted sale logs" do
log.update!(ownershipsch: 1)

6
spec/models/form/sales/pages/last_accommodation_spec.rb

@ -7,8 +7,8 @@ RSpec.describe Form::Sales::Pages::LastAccommodation, type: :model do
let(:page_id) { nil }
let(:page_definition) { nil }
let(:start_year_after_2024) { false }
let(:form) { instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_2024_or_later?: start_year_after_2024) }
let(:start_year_2024_or_later) { false }
let(:form) { instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_2024_or_later?: start_year_2024_or_later) }
let(:subsection) { instance_double(Form::Subsection, form:, depends_on: nil) }
it "has correct subsection" do
@ -37,7 +37,7 @@ RSpec.describe Form::Sales::Pages::LastAccommodation, type: :model do
end
context "with 2024 form" do
let(:start_year_after_2024) { true }
let(:start_year_2024_or_later) { true }
it "is routed to for 2024 non discounted sale logs" do
log.update!(ownershipsch: 1)

2
spec/models/validations/date_validations_spec.rb

@ -12,7 +12,7 @@ RSpec.describe Validations::DateValidations do
it "must be a valid date" do
record.startdate = Time.zone.local(0, 7, 1)
date_validator.validate_startdate(record)
expect(record.errors["startdate"]).to include(match I18n.t("validations.date.invalid_date"))
expect(record.errors["startdate"]).to include(match I18n.t("validations.shared.date.invalid_date"))
end
it "does not raise an error when valid" do

14
spec/models/validations/household_validations_spec.rb

@ -27,13 +27,13 @@ RSpec.describe Validations::HouseholdValidations do
end
describe "reason for leaving last settled home validations" do
let(:field) { "validations.other_field_not_required" }
let(:field) { "validations.shared.other_field_not_required" }
let(:main_field_label) { "reason" }
let(:other_field_label) { "reasonother" }
let(:expected_error) { I18n.t(field, main_field_label:, other_field_label:) }
context "when reason is other" do
let(:field) { "validations.other_field_missing" }
let(:field) { "validations.shared.other_field_missing" }
it "validates that a reason is provided" do
record.reason = 20
@ -251,14 +251,14 @@ RSpec.describe Validations::HouseholdValidations do
record.hhmemb = 0
household_validator.validate_numeric_min_max(record)
expect(record.errors["hhmemb"])
.to include(match I18n.t("validations.numeric.within_range", field: "Number of household members", min: 1, max: 8))
.to include(match I18n.t("validations.shared.numeric.within_range", field: "Number of household members", min: 1, max: 8))
end
it "validates that the number of household members cannot be more than 8" do
record.hhmemb = 9
household_validator.validate_numeric_min_max(record)
expect(record.errors["hhmemb"])
.to include(match I18n.t("validations.numeric.within_range", field: "Number of household members", min: 1, max: 8))
.to include(match I18n.t("validations.shared.numeric.within_range", field: "Number of household members", min: 1, max: 8))
end
it "expects that the number of other household members is between the min and max" do
@ -276,11 +276,11 @@ RSpec.describe Validations::HouseholdValidations do
record.relat3 = "P"
household_validator.validate_partner_count(record)
expect(record.errors["relat2"])
.to include(match I18n.t("validations.household.relat.one_partner"))
.to include(match I18n.t("validations.lettings.household.relat.one_partner"))
expect(record.errors["relat3"])
.to include(match I18n.t("validations.household.relat.one_partner"))
.to include(match I18n.t("validations.lettings.household.relat.one_partner"))
expect(record.errors["relat4"])
.not_to include(match I18n.t("validations.household.relat.one_partner"))
.not_to include(match I18n.t("validations.lettings.household.relat.one_partner"))
end
it "expects that a tenant can have a partner" do

42
spec/models/validations/setup_validations_spec.rb

@ -436,9 +436,9 @@ RSpec.describe Validations::SetupValidations do
record.scheme = scheme
setup_validator.validate_scheme(record)
expect(record.errors["startdate"])
.to include(match I18n.t("validations.setup.startdate.scheme.deactivated.startdate", name: scheme.service_name, date: "4 June 2022"))
.to include(match I18n.t("validations.lettings.setup.startdate.scheme.deactivated.startdate", name: scheme.service_name, date: "4 June 2022"))
expect(record.errors["scheme_id"])
.to include(match I18n.t("validations.setup.startdate.scheme.deactivated.scheme_id", name: scheme.service_name, date: "4 June 2022"))
.to include(match I18n.t("validations.lettings.setup.startdate.scheme.deactivated.scheme_id", name: scheme.service_name, date: "4 June 2022"))
end
it "produces no error when tenancy start date is during an active scheme period" do
@ -465,9 +465,9 @@ RSpec.describe Validations::SetupValidations do
record.scheme = scheme
setup_validator.validate_scheme(record)
expect(record.errors["startdate"])
.to include(match I18n.t("validations.setup.startdate.scheme.reactivating_soon.startdate", name: scheme.service_name, date: "4 August 2022"))
.to include(match I18n.t("validations.lettings.setup.startdate.scheme.reactivating_soon.startdate", name: scheme.service_name, date: "4 August 2022"))
expect(record.errors["scheme_id"])
.to include(match I18n.t("validations.setup.startdate.scheme.reactivating_soon.scheme_id", name: scheme.service_name, date: "4 August 2022"))
.to include(match I18n.t("validations.lettings.setup.startdate.scheme.reactivating_soon.scheme_id", name: scheme.service_name, date: "4 August 2022"))
end
it "produces no error when tenancy start date is during an active scheme period" do
@ -498,9 +498,9 @@ RSpec.describe Validations::SetupValidations do
record.scheme = scheme
setup_validator.validate_scheme(record)
expect(record.errors["startdate"])
.to include(match I18n.t("validations.setup.startdate.scheme.reactivating_soon.startdate", name: scheme.service_name, date: "4 September 2022"))
.to include(match I18n.t("validations.lettings.setup.startdate.scheme.reactivating_soon.startdate", name: scheme.service_name, date: "4 September 2022"))
expect(record.errors["scheme_id"])
.to include(match I18n.t("validations.setup.startdate.scheme.reactivating_soon.scheme_id", name: scheme.service_name, date: "4 September 2022"))
.to include(match I18n.t("validations.lettings.setup.startdate.scheme.reactivating_soon.scheme_id", name: scheme.service_name, date: "4 September 2022"))
end
it "produces no error when tenancy start date is during an active scheme period" do
@ -526,8 +526,8 @@ RSpec.describe Validations::SetupValidations do
record.startdate = Time.zone.local(2022, 7, 5)
record.scheme = scheme
setup_validator.validate_scheme(record)
expect(record.errors["startdate"]).to include(match I18n.t("validations.setup.startdate.scheme.locations_inactive.startdate", name: scheme.service_name))
expect(record.errors["scheme_id"]).to include(match I18n.t("validations.setup.startdate.scheme.locations_inactive.startdate", name: scheme.service_name))
expect(record.errors["startdate"]).to include(match I18n.t("validations.lettings.setup.startdate.scheme.locations_inactive.startdate", name: scheme.service_name))
expect(record.errors["scheme_id"]).to include(match I18n.t("validations.lettings.setup.startdate.scheme.locations_inactive.startdate", name: scheme.service_name))
end
it "produces no error when scheme has active locations on the tenancy start date" do
@ -553,8 +553,8 @@ RSpec.describe Validations::SetupValidations do
record.scheme = scheme
record.location = location
setup_validator.validate_scheme(record)
expect(record.errors["startdate"]).to include(match I18n.t("validations.setup.startdate.scheme.locations_inactive.startdate", name: scheme.service_name))
expect(record.errors["startdate"]).not_to include(match I18n.t("validations.setup.startdate.location.deactivated.startdate", postcode: location.postcode))
expect(record.errors["startdate"]).to include(match I18n.t("validations.lettings.setup.startdate.scheme.locations_inactive.startdate", name: scheme.service_name))
expect(record.errors["startdate"]).not_to include(match I18n.t("validations.lettings.setup.startdate.location.deactivated.startdate", postcode: location.postcode))
end
it "produces no error when scheme has active locations on the tenancy start date" do
@ -593,9 +593,9 @@ RSpec.describe Validations::SetupValidations do
record.location = location
setup_validator.validate_location(record)
expect(record.errors["startdate"])
.to include(match I18n.t("validations.setup.startdate.location.deactivated.startdate", postcode: location.postcode, date: "4 June 2022"))
.to include(match I18n.t("validations.lettings.setup.startdate.location.deactivated.startdate", postcode: location.postcode, date: "4 June 2022"))
expect(record.errors["location_id"])
.to include(match I18n.t("validations.setup.startdate.location.deactivated.location_id", postcode: location.postcode, date: "4 June 2022"))
.to include(match I18n.t("validations.lettings.setup.startdate.location.deactivated.location_id", postcode: location.postcode, date: "4 June 2022"))
end
it "produces no error when tenancy start date is during an active location period" do
@ -622,9 +622,9 @@ RSpec.describe Validations::SetupValidations do
record.location = location
setup_validator.validate_location(record)
expect(record.errors["startdate"])
.to include(match I18n.t("validations.setup.startdate.location.reactivating_soon.startdate", postcode: location.postcode, date: "4 August 2022"))
.to include(match I18n.t("validations.lettings.setup.startdate.location.reactivating_soon.startdate", postcode: location.postcode, date: "4 August 2022"))
expect(record.errors["location_id"])
.to include(match I18n.t("validations.setup.startdate.location.reactivating_soon.location_id", postcode: location.postcode, date: "4 August 2022"))
.to include(match I18n.t("validations.lettings.setup.startdate.location.reactivating_soon.location_id", postcode: location.postcode, date: "4 August 2022"))
end
it "produces no error when tenancy start date is during an active location period" do
@ -655,9 +655,9 @@ RSpec.describe Validations::SetupValidations do
record.location = location
setup_validator.validate_location(record)
expect(record.errors["startdate"])
.to include(match I18n.t("validations.setup.startdate.location.reactivating_soon.startdate", postcode: location.postcode, date: "4 September 2022"))
.to include(match I18n.t("validations.lettings.setup.startdate.location.reactivating_soon.startdate", postcode: location.postcode, date: "4 September 2022"))
expect(record.errors["location_id"])
.to include(match I18n.t("validations.setup.startdate.location.reactivating_soon.location_id", postcode: location.postcode, date: "4 September 2022"))
.to include(match I18n.t("validations.lettings.setup.startdate.location.reactivating_soon.location_id", postcode: location.postcode, date: "4 September 2022"))
end
it "produces no error when tenancy start date is during an active location period" do
@ -686,9 +686,9 @@ RSpec.describe Validations::SetupValidations do
record.location = location
setup_validator.validate_location(record)
expect(record.errors["startdate"])
.to include(match I18n.t("validations.setup.startdate.location.activating_soon.startdate", postcode: location.postcode, date: "15 September 2022"))
.to include(match I18n.t("validations.lettings.setup.startdate.location.activating_soon.startdate", postcode: location.postcode, date: "15 September 2022"))
expect(record.errors["location_id"])
.to include(match I18n.t("validations.setup.startdate.location.activating_soon.location_id", postcode: location.postcode, date: "15 September 2022"))
.to include(match I18n.t("validations.lettings.setup.startdate.location.activating_soon.location_id", postcode: location.postcode, date: "15 September 2022"))
end
end
@ -726,7 +726,7 @@ RSpec.describe Validations::SetupValidations do
record.startdate = Time.zone.local(2022, 7, 5)
record.location = location
setup_validator.validate_location(record)
expect(record.errors["startdate"]).to include(match I18n.t("validations.setup.startdate.location.deactivated.startdate", postcode: location.postcode))
expect(record.errors["startdate"]).to include(match I18n.t("validations.lettings.setup.startdate.location.deactivated.startdate", postcode: location.postcode))
end
it "produces no error when the chosen location is active on the tenancy start date" do
@ -900,7 +900,7 @@ RSpec.describe Validations::SetupValidations do
it "produces an error" do
record.scheme = scheme
setup_validator.validate_scheme_has_confirmed_locations_validation(record)
setup_validator.validate_scheme(record)
expect(record.errors["scheme_id"])
.to include(match I18n.t("validations.lettings.setup.scheme.no_completed_locations"))
end
@ -914,7 +914,7 @@ RSpec.describe Validations::SetupValidations do
it "does not produce an error" do
record.scheme = scheme
setup_validator.validate_scheme_has_confirmed_locations_validation(record)
setup_validator.validate_scheme(record)
expect(record.errors["scheme_id"])
.to be_empty
end

34
spec/models/validations/shared_validations_spec.rb

@ -18,42 +18,42 @@ RSpec.describe Validations::SharedValidations do
lettings_log.age1 = "random"
shared_validator.validate_numeric_min_max(lettings_log)
expect(lettings_log.errors["age1"])
.to include(match I18n.t("validations.numeric.within_range", field: "Lead tenant’s age", min: 16, max: 120))
.to include(match I18n.t("validations.shared.numeric.within_range", field: "Lead tenant’s age", min: 16, max: 120))
end
it "validates that other household member ages are a number" do
lettings_log.age2 = "random"
shared_validator.validate_numeric_min_max(lettings_log)
expect(lettings_log.errors["age2"])
.to include(match I18n.t("validations.numeric.within_range", field: "Person 2’s age", min: 1, max: 120))
.to include(match I18n.t("validations.shared.numeric.within_range", field: "Person 2’s age", min: 1, max: 120))
end
it "validates that person 1's age is greater than 16" do
lettings_log.age1 = 15
shared_validator.validate_numeric_min_max(lettings_log)
expect(lettings_log.errors["age1"])
.to include(match I18n.t("validations.numeric.within_range", field: "Lead tenant’s age", min: 16, max: 120))
.to include(match I18n.t("validations.shared.numeric.within_range", field: "Lead tenant’s age", min: 16, max: 120))
end
it "validates that other household member ages are greater than 1" do
lettings_log.age2 = 0
shared_validator.validate_numeric_min_max(lettings_log)
expect(lettings_log.errors["age2"])
.to include(match I18n.t("validations.numeric.within_range", field: "Person 2’s age", min: 1, max: 120))
.to include(match I18n.t("validations.shared.numeric.within_range", field: "Person 2’s age", min: 1, max: 120))
end
it "validates that person 1's age is less than 121" do
lettings_log.age1 = 121
shared_validator.validate_numeric_min_max(lettings_log)
expect(lettings_log.errors["age1"])
.to include(match I18n.t("validations.numeric.within_range", field: "Lead tenant’s age", min: 16, max: 120))
.to include(match I18n.t("validations.shared.numeric.within_range", field: "Lead tenant’s age", min: 16, max: 120))
end
it "validates that other household member ages are greater than 121" do
lettings_log.age2 = 123
shared_validator.validate_numeric_min_max(lettings_log)
expect(lettings_log.errors["age2"])
.to include(match I18n.t("validations.numeric.within_range", field: "Person 2’s age", min: 1, max: 120))
.to include(match I18n.t("validations.shared.numeric.within_range", field: "Person 2’s age", min: 1, max: 120))
end
it "validates that person 1's age is between 16 and 120" do
@ -91,7 +91,7 @@ RSpec.describe Validations::SharedValidations do
sales_log.savings = -10
sales_log.jointpur = 1
shared_validator.validate_numeric_min_max(sales_log)
expect(sales_log.errors["savings"]).to include(match I18n.t("validations.numeric.above_min", field: "Buyers’ total savings before any deposit paid", min: "£0"))
expect(sales_log.errors["savings"]).to include(match I18n.t("validations.shared.numeric.above_min", field: "Buyers’ total savings before any deposit paid", min: "£0"))
end
context "when validating percent" do
@ -101,7 +101,7 @@ RSpec.describe Validations::SharedValidations do
sales_log.stairbought = 150
shared_validator.validate_numeric_min_max(sales_log)
expect(sales_log.errors["stairbought"])
.to include(match I18n.t("validations.numeric.within_range", field: "Percentage bought in this staircasing transaction", min: "0%", max: "100%"))
.to include(match I18n.t("validations.shared.numeric.within_range", field: "Percentage bought in this staircasing transaction", min: "0%", max: "100%"))
end
end
@ -110,7 +110,7 @@ RSpec.describe Validations::SharedValidations do
sales_log.income1 = -5
shared_validator.validate_numeric_min_max(sales_log)
expect(sales_log.errors["income1"])
.to include(match I18n.t("validations.numeric.within_range", field: "Buyer 1’s gross annual income", min: "£0", max: "£999,999"))
.to include(match I18n.t("validations.shared.numeric.within_range", field: "Buyer 1’s gross annual income", min: "£0", max: "£999,999"))
end
end
end
@ -120,13 +120,13 @@ RSpec.describe Validations::SharedValidations do
it "adds an error if input is a decimal" do
sales_log.income1 = 30_000.5
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")
expect(sales_log.errors[:income1]).to include I18n.t("validations.shared.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")
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
@ -141,14 +141,14 @@ RSpec.describe Validations::SharedValidations do
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.numeric.nearest_ten", field: "Buyers’ total savings before any deposit paid")
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
sales_log.savings = "3e5"
sales_log.jointpur = 1
shared_validator.validate_numeric_step(sales_log)
expect(sales_log.errors[:savings]).to include I18n.t("validations.numeric.nearest_ten", field: "Buyers’ total savings before any deposit paid")
expect(sales_log.errors[:savings]).to include I18n.t("validations.shared.numeric.nearest_ten", field: "Buyers’ total savings before any deposit paid")
end
it "does not add an error if input is a multiple of ten" do
@ -162,7 +162,7 @@ RSpec.describe Validations::SharedValidations do
it "adds an error if input has more than 2 decimal places" do
sales_log.mscharge = 30.7418
shared_validator.validate_numeric_step(sales_log)
expect(sales_log.errors[:mscharge]).to include I18n.t("validations.numeric.nearest_hundredth", field: "Monthly leasehold charges")
expect(sales_log.errors[:mscharge]).to include I18n.t("validations.shared.numeric.nearest_hundredth", field: "Monthly leasehold charges")
end
it "does not add an error if the user attempts to input a number in exponent format" do
@ -220,13 +220,13 @@ RSpec.describe Validations::SharedValidations do
it "does not allow letters" do
sales_log.income1 = "abc"
shared_validator.validate_numeric_input(sales_log)
expect(sales_log.errors[:income1]).to include I18n.t("validations.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
it "does not allow special characters" do
sales_log.income1 = "3%5"
shared_validator.validate_numeric_input(sales_log)
expect(sales_log.errors[:income1]).to include I18n.t("validations.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
it "allows a digit" do
@ -244,7 +244,7 @@ RSpec.describe Validations::SharedValidations do
it "does not allow decimal point in a wrong format" do
sales_log.income1 = "300.09.78"
shared_validator.validate_numeric_input(sales_log)
expect(sales_log.errors[:income1]).to include I18n.t("validations.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
end

4
spec/models/validations/tenancy_validations_spec.rb

@ -276,7 +276,7 @@ RSpec.describe Validations::TenancyValidations do
describe "tenancy type validations" do
let(:record) { FactoryBot.build(:lettings_log, :setup_completed) }
let(:field) { "validations.other_field_missing" }
let(:field) { "validations.shared.other_field_missing" }
let(:main_field_label) { "tenancy type" }
let(:other_field) { "tenancyother" }
let(:other_field_label) { "other tenancy type" }
@ -299,7 +299,7 @@ RSpec.describe Validations::TenancyValidations do
end
context "when tenancy type is not other" do
let(:field) { "validations.other_field_not_required" }
let(:field) { "validations.shared.other_field_not_required" }
it "validates that other tenancy type is not provided" do
record.tenancy = 2

2
spec/requests/lettings_logs_controller_spec.rb

@ -82,7 +82,7 @@ RSpec.describe LettingsLogsController, type: :request do
it "validates lettings log parameters" do
json_response = JSON.parse(response.body)
expect(response).to have_http_status(:unprocessable_entity)
expect(json_response["errors"]).to match_array([["offered", [I18n.t("validations.numeric.within_range", field: "Times previously offered since becoming available", min: 0, max: 20)]], ["age1", [I18n.t("validations.numeric.within_range", field: "Lead tenant’s age", min: 16, max: 120)]]])
expect(json_response["errors"]).to match_array([["offered", [I18n.t("validations.shared.numeric.within_range", field: "Times previously offered since becoming available", min: 0, max: 20)]], ["age1", [I18n.t("validations.shared.numeric.within_range", field: "Lead tenant’s age", min: 16, max: 120)]]])
end
end

Loading…
Cancel
Save