Browse Source

CLDC-1917 Add Startdate Validation (#1378)

* feat: add validation with feature flag, typo fix and update tests

* feat: flip feature toggle

* feat: update feature toggle name

* feat: fix form handler inequality

* refactor: linting

* refactor: use between in form handler

* feat: remove feature toggle

* feat: add dynamic date to lettings log factory

* feat: fix log_summary_component_spec.rb tests

* feat: update lettings_log.rb and start fixing lettings_log_spec.rb

* feat: fix more tests

* feat: fix more tests

* feat: fix lettings log import service

* refactor: linting

* feat: fix checkboxes_spec.rb

* feat: fix interruption_screen_helper_spec.rb

* feat: fix check_answers_helper_spec.rb

* feat: fix page_routing_spec.rb

* feat: fix lettings_logs_field_import_service_spec.rb

* feat: fix lettings_log_spec.rb

* feat: fix question_spec.rb

* feat: fix lettings_logs_controller_spec.rb

* feat: fix check_answers_page_lettings_logs_spec.rb

* feat: fix tenancy_validations_spec.rb

* feat: fix validations_spec.rb

* feat: fix accessible_autocomplete_spec.rb

* feat: fix form_navigation_spec.rb

* feat: fix soft_validations_spec.rb

* feat: fix lettings_log_export_service_spec.rb

* feat: fix saving_data_spec.rb

* feat: fix page_spec.rb

* feat: fix form_controller_spec.rb

* refactor: linting

* feat: fix subsection_spec.rb

* feat: fix lettings_log_spec.rb

* feat: fix financial_validations_spec.rb

* feat: fix tasklist_page_spec.rb

* feat: fix conditional_questions_spec.rb

* feat: fix form_page_error_helper_spec.rb and log_summary_component_spec.rb

* feat: fix lettings_log_csv_service_spec.rb

* feat: fix tasklist_helper_spec.rb

* refactor: linting

* refactor: linting

* feat: fix lettings_log_spec.rb

* refactor: linting

* refactor: replace financial year with collection yaer

* feat: respond to PR comments pt. 1

* feat: respond to PR comments pt. 2
revert-1378-CLDC-1917-startdate-validation
natdeanlewissoftwire 2 years ago committed by GitHub
parent
commit
f758d598c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      app/models/form_handler.rb
  2. 26
      app/models/validations/date_validations.rb
  3. 12
      app/models/validations/sales/setup_validations.rb
  4. 40
      app/models/validations/setup_validations.rb
  5. 4
      config/initializers/feature_toggle.rb
  6. 14
      config/locales/en.yml
  7. 2
      db/schema.rb
  8. 6
      spec/components/log_summary_component_spec.rb
  9. 13
      spec/factories/lettings_log.rb
  10. 13
      spec/features/form/accessible_autocomplete_spec.rb
  11. 11
      spec/features/form/check_answers_page_lettings_logs_spec.rb
  12. 9
      spec/features/form/checkboxes_spec.rb
  13. 10
      spec/features/form/conditional_questions_spec.rb
  14. 9
      spec/features/form/form_navigation_spec.rb
  15. 159
      spec/features/form/page_routing_spec.rb
  16. 9
      spec/features/form/progressive_total_field_spec.rb
  17. 9
      spec/features/form/saving_data_spec.rb
  18. 16
      spec/features/form/tasklist_page_spec.rb
  19. 11
      spec/features/form/validations_spec.rb
  20. 2
      spec/fixtures/exports/general_needs_log.csv
  21. 4
      spec/fixtures/exports/general_needs_log.xml
  22. 4
      spec/fixtures/exports/supported_housing_logs.xml
  23. 9
      spec/helpers/check_answers_helper_spec.rb
  24. 9
      spec/helpers/form_page_error_helper_spec.rb
  25. 9
      spec/helpers/interruption_screen_helper_spec.rb
  26. 86
      spec/helpers/tasklist_helper_spec.rb
  27. 6
      spec/jobs/email_csv_job_spec.rb
  28. 9
      spec/models/form/page_spec.rb
  29. 11
      spec/models/form/question_spec.rb
  30. 9
      spec/models/form/subsection_spec.rb
  31. 9
      spec/models/form_spec.rb
  32. 181
      spec/models/lettings_log_spec.rb
  33. 24
      spec/models/validations/date_validations_spec.rb
  34. 2
      spec/models/validations/financial_validations_spec.rb
  35. 20
      spec/models/validations/sales/setup_validations_spec.rb
  36. 102
      spec/models/validations/setup_validations_spec.rb
  37. 16
      spec/models/validations/soft_validations_spec.rb
  38. 20
      spec/models/validations/tenancy_validations_spec.rb
  39. 16
      spec/requests/form_controller_spec.rb
  40. 44
      spec/requests/lettings_logs_controller_spec.rb
  41. 9
      spec/requests/sales_logs_controller_spec.rb
  42. 2
      spec/services/csv/lettings_log_csv_service_spec.rb
  43. 8
      spec/services/exports/lettings_log_export_service_spec.rb
  44. 11
      spec/services/imports/lettings_logs_field_import_service_spec.rb
  45. 733
      spec/services/imports/lettings_logs_import_service_spec.rb
  46. 9
      spec/views/form/page_view_spec.rb

4
app/models/form_handler.rb

@ -79,12 +79,12 @@ class FormHandler
def lettings_in_crossover_period?(now: Time.zone.now) def lettings_in_crossover_period?(now: Time.zone.now)
forms = lettings_forms.values forms = lettings_forms.values
forms.count { |form| form.start_date < now && now < form.end_date } > 1 forms.count { |form| now.between?(form.start_date, form.end_date) } > 1
end end
def sales_in_crossover_period?(now: Time.zone.now) def sales_in_crossover_period?(now: Time.zone.now)
forms = sales_forms.values forms = sales_forms.values
forms.count { |form| form.start_date < now && now < form.end_date } > 1 forms.count { |form| now.between?(form.start_date, form.end_date) } > 1
end end
def use_fake_forms! def use_fake_forms!

26
app/models/validations/date_validations.rb

@ -33,16 +33,6 @@ module Validations::DateValidations
def validate_startdate(record) def validate_startdate(record)
return unless record.startdate && date_valid?("startdate", record) return unless record.startdate && date_valid?("startdate", record)
created_at = record.created_at || Time.zone.now
if created_at > first_collection_end_date && record.startdate < second_collection_start_date
record.errors.add :startdate, I18n.t("validations.date.outside_collection_window")
end
if (record.startdate < first_collection_start_date || record.startdate > second_collection_end_date) && FeatureToggle.startdate_collection_window_validation_enabled?
record.errors.add :startdate, I18n.t("validations.date.outside_collection_window")
end
if FeatureToggle.startdate_two_week_validation_enabled? && record.startdate > Time.zone.today + 14 if FeatureToggle.startdate_two_week_validation_enabled? && record.startdate > Time.zone.today + 14
record.errors.add :startdate, I18n.t("validations.setup.startdate.later_than_14_days_after") record.errors.add :startdate, I18n.t("validations.setup.startdate.later_than_14_days_after")
end end
@ -68,22 +58,6 @@ module Validations::DateValidations
private private
def first_collection_start_date
@first_collection_start_date ||= FormHandler.instance.lettings_forms["previous_lettings"].start_date
end
def first_collection_end_date
@first_collection_end_date ||= FormHandler.instance.lettings_forms["previous_lettings"].end_date
end
def second_collection_start_date
@second_collection_start_date ||= FormHandler.instance.lettings_forms["current_lettings"].start_date
end
def second_collection_end_date
@second_collection_end_date ||= FormHandler.instance.lettings_forms["current_lettings"].end_date
end
def is_rsnvac_first_let?(record) def is_rsnvac_first_let?(record)
[15, 16, 17].include?(record["rsnvac"]) [15, 16, 17].include?(record["rsnvac"])
end end

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

@ -3,10 +3,10 @@ module Validations::Sales::SetupValidations
include CollectionTimeHelper include CollectionTimeHelper
def validate_saledate(record) def validate_saledate(record)
return unless record.saledate && date_valid?("saledate", record) return unless record.saledate && date_valid?("saledate", record) && FeatureToggle.saledate_collection_window_validation_enabled?
unless record.saledate.between?(active_collection_start_date, current_collection_end_date) || !FeatureToggle.saledate_collection_window_validation_enabled? unless record.saledate.between?(active_collection_start_date, current_collection_end_date)
record.errors.add :saledate, validation_error_message record.errors.add :saledate, saledate_validation_error_message
end end
end end
@ -20,12 +20,12 @@ private
end end
end end
def validation_error_message def saledate_validation_error_message
current_end_year_long = current_collection_end_date.strftime("#{current_collection_end_date.day.ordinalize} %B %Y") current_end_year_long = current_collection_end_date.strftime("#{current_collection_end_date.day.ordinalize} %B %Y")
if FormHandler.instance.sales_in_crossover_period? if FormHandler.instance.sales_in_crossover_period?
I18n.t( I18n.t(
"validations.setup.saledate.previous_and_current_financial_year", "validations.setup.saledate.previous_and_current_collection_year",
previous_start_year_short: previous_collection_start_date.strftime("%y"), previous_start_year_short: previous_collection_start_date.strftime("%y"),
previous_end_year_short: previous_collection_end_date.strftime("%y"), previous_end_year_short: previous_collection_end_date.strftime("%y"),
previous_start_year_long: previous_collection_start_date.strftime("#{previous_collection_start_date.day.ordinalize} %B %Y"), previous_start_year_long: previous_collection_start_date.strftime("#{previous_collection_start_date.day.ordinalize} %B %Y"),
@ -34,7 +34,7 @@ private
) )
else else
I18n.t( I18n.t(
"validations.setup.saledate.current_financial_year", "validations.setup.saledate.current_collection_year",
current_start_year_short: current_collection_start_date.strftime("%y"), current_start_year_short: current_collection_start_date.strftime("%y"),
current_end_year_short: current_collection_end_date.strftime("%y"), current_end_year_short: current_collection_end_date.strftime("%y"),
current_start_year_long: current_collection_start_date.strftime("#{current_collection_start_date.day.ordinalize} %B %Y"), current_start_year_long: current_collection_start_date.strftime("#{current_collection_start_date.day.ordinalize} %B %Y"),

40
app/models/validations/setup_validations.rb

@ -1,5 +1,14 @@
module Validations::SetupValidations module Validations::SetupValidations
include Validations::SharedValidations include Validations::SharedValidations
include CollectionTimeHelper
def validate_startdate_setup(record)
return unless record.startdate && date_valid?("startdate", record) && FeatureToggle.startdate_collection_window_validation_enabled?
unless record.startdate.between?(active_collection_start_date, current_collection_end_date)
record.errors.add :startdate, startdate_validation_error_message
end
end
def validate_irproduct_other(record) def validate_irproduct_other(record)
if intermediate_product_rent_type?(record) && record.irproduct_other.blank? if intermediate_product_rent_type?(record) && record.irproduct_other.blank?
@ -27,6 +36,37 @@ module Validations::SetupValidations
private private
def active_collection_start_date
if FormHandler.instance.lettings_in_crossover_period?
previous_collection_start_date
else
current_collection_start_date
end
end
def startdate_validation_error_message
current_end_year_long = current_collection_end_date.strftime("#{current_collection_end_date.day.ordinalize} %B %Y")
if FormHandler.instance.lettings_in_crossover_period?
I18n.t(
"validations.setup.startdate.previous_and_current_collection_year",
previous_start_year_short: previous_collection_start_date.strftime("%y"),
previous_end_year_short: previous_collection_end_date.strftime("%y"),
previous_start_year_long: previous_collection_start_date.strftime("#{previous_collection_start_date.day.ordinalize} %B %Y"),
current_end_year_short: current_collection_end_date.strftime("%y"),
current_end_year_long:,
)
else
I18n.t(
"validations.setup.startdate.current_collection_year",
current_start_year_short: current_collection_start_date.strftime("%y"),
current_end_year_short: current_collection_end_date.strftime("%y"),
current_start_year_long: current_collection_start_date.strftime("#{current_collection_start_date.day.ordinalize} %B %Y"),
current_end_year_long:,
)
end
end
def intermediate_product_rent_type?(record) def intermediate_product_rent_type?(record)
record.rent_type == 5 record.rent_type == 5
end end

4
config/initializers/feature_toggle.rb

@ -4,11 +4,11 @@ class FeatureToggle
Rails.env.production? || Rails.env.test? || Rails.env.staging? Rails.env.production? || Rails.env.test? || Rails.env.staging?
end end
def self.startdate_two_week_validation_enabled? def self.startdate_collection_window_validation_enabled?
Rails.env.production? || Rails.env.test? || Rails.env.staging? Rails.env.production? || Rails.env.test? || Rails.env.staging?
end end
def self.startdate_collection_window_validation_enabled? def self.startdate_two_week_validation_enabled?
Rails.env.production? || Rails.env.test? || Rails.env.staging? Rails.env.production? || Rails.env.test? || Rails.env.staging?
end end

14
config/locales/en.yml

@ -141,7 +141,7 @@ en:
above_min: "%{field} must be at least %{min}" above_min: "%{field} must be at least %{min}"
date: date:
invalid_date: "Enter a date in the correct format, for example 31 1 2022" invalid_date: "Enter a date in the correct format, for example 31 1 2022"
outside_collection_window: Enter a date within the 22/23 financial year, which is between 1st April 2022 and 31st March 2023 outside_collection_window: Enter a date within the 22/23 collection year, which is between 1st April 2022 and 31st March 2023
postcode: "Enter a postcode in the correct format, for example AA1 1AA" postcode: "Enter a postcode in the correct format, for example AA1 1AA"
location_admin_district: "Select a local authority" location_admin_district: "Select a local authority"
email: email:
@ -155,14 +155,18 @@ en:
intermediate_rent_product_name: intermediate_rent_product_name:
blank: "Enter name of other intermediate rent product" blank: "Enter name of other intermediate rent product"
saledate: saledate:
current_financial_year: current_collection_year:
Enter a date within the %{current_start_year_short}/%{current_end_year_short} financial year, which is between %{current_start_year_long} and %{current_end_year_long} Enter a date within the %{current_start_year_short}/%{current_end_year_short} collection year, which is between %{current_start_year_long} and %{current_end_year_long}
previous_and_current_financial_year: previous_and_current_collection_year:
"Enter a date within the %{previous_start_year_short}/%{previous_end_year_short} or %{previous_end_year_short}/%{current_end_year_short} financial years, which is between %{previous_start_year_long} and %{current_end_year_long}" "Enter a date within the %{previous_start_year_short}/%{previous_end_year_short} or %{previous_end_year_short}/%{current_end_year_short} collection years, which is between %{previous_start_year_long} and %{current_end_year_long}"
type: type:
percentage_bought_must_be_at_least_threshold: "The minimum increase in equity while staircasing is %{threshold}% for this shared ownership type" percentage_bought_must_be_at_least_threshold: "The minimum increase in equity while staircasing is %{threshold}% for this shared ownership type"
startdate: startdate:
current_collection_year:
Enter a date within the %{current_start_year_short}/%{current_end_year_short} collection year, which is between %{current_start_year_long} and %{current_end_year_long}
previous_and_current_collection_year:
"Enter a date within the %{previous_start_year_short}/%{previous_end_year_short} or %{previous_end_year_short}/%{current_end_year_short} collection years, which is between %{previous_start_year_long} and %{current_end_year_long}"
later_than_14_days_after: "The tenancy start date must not be later than 14 days from today’s date" later_than_14_days_after: "The tenancy start date must not be later than 14 days from today’s date"
before_scheme_end_date: "The tenancy start date must be before the end date for this supported housing scheme" before_scheme_end_date: "The tenancy start date must be before the end date for this supported housing scheme"
after_void_date: "Enter a tenancy start date that is after the void date" after_void_date: "Enter a tenancy start date that is after the void date"

2
db/schema.rb

@ -557,9 +557,9 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_09_145740) do
t.integer "ethnicbuy2" t.integer "ethnicbuy2"
t.integer "proplen_asked" t.integer "proplen_asked"
t.string "old_id" t.string "old_id"
t.integer "pregblank"
t.integer "buy2living" t.integer "buy2living"
t.integer "prevtenbuy2" t.integer "prevtenbuy2"
t.integer "pregblank"
t.integer "nationalbuy2" t.integer "nationalbuy2"
t.string "uprn" t.string "uprn"
t.integer "uprn_known" t.integer "uprn_known"

6
spec/components/log_summary_component_spec.rb

@ -5,7 +5,7 @@ RSpec.describe LogSummaryComponent, type: :component do
let(:coordinator_user) { FactoryBot.create(:user) } let(:coordinator_user) { FactoryBot.create(:user) }
let(:propcode) { "P3647" } let(:propcode) { "P3647" }
let(:tenancycode) { "T62863" } let(:tenancycode) { "T62863" }
let(:lettings_log) { FactoryBot.create(:lettings_log, needstype: 1, startdate: Time.utc(2022, 1, 1), tenancycode:, propcode:) } let(:lettings_log) { FactoryBot.create(:lettings_log, needstype: 1, tenancycode:, propcode:, startdate: Time.zone.today) }
let(:sales_log) { FactoryBot.create(:sales_log) } let(:sales_log) { FactoryBot.create(:sales_log) }
context "when rendering lettings log for a support user" do context "when rendering lettings log for a support user" do
@ -16,8 +16,8 @@ RSpec.describe LogSummaryComponent, type: :component do
expect(result).to have_text(lettings_log.tenancycode) expect(result).to have_text(lettings_log.tenancycode)
expect(result).to have_text(lettings_log.propcode) expect(result).to have_text(lettings_log.propcode)
expect(result).to have_text("General needs") expect(result).to have_text("General needs")
expect(result).to have_text("Tenancy starts 1 January 2022") expect(result).to have_text("Tenancy starts #{Time.zone.today.strftime('%e %B %Y')}")
expect(result).to have_text("Created 8 February 2022") expect(result).to have_text("Created #{Time.zone.today.strftime('%e %B %Y')}")
expect(result).to have_text("by Danny Rojas") expect(result).to have_text("by Danny Rojas")
expect(result).to have_content("Owned by\n DLUHC") expect(result).to have_content("Owned by\n DLUHC")
expect(result).to have_content("Managed by\n DLUHC") expect(result).to have_content("Managed by\n DLUHC")

13
spec/factories/lettings_log.rb

@ -7,7 +7,6 @@ FactoryBot.define do
renewal { 0 } renewal { 0 }
needstype { 1 } needstype { 1 }
rent_type { 1 } rent_type { 1 }
startdate { Time.zone.local(2022, 5, 1) }
end end
trait :in_progress do trait :in_progress do
status { 1 } status { 1 }
@ -18,7 +17,7 @@ FactoryBot.define do
age2 { 19 } age2 { 19 }
renewal { 1 } renewal { 1 }
rent_type { 1 } rent_type { 1 }
startdate { Time.zone.local(2021, 5, 1) } startdate { Time.zone.today }
end end
trait :soft_validations_triggered do trait :soft_validations_triggered do
status { 1 } status { 1 }
@ -36,6 +35,7 @@ FactoryBot.define do
hhmemb { 1 } hhmemb { 1 }
end end
trait :completed do trait :completed do
startdate { Time.zone.today }
status { 2 } status { 2 }
tenancycode { Faker::Name.initials(number: 10) } tenancycode { Faker::Name.initials(number: 10) }
age1_known { 0 } age1_known { 0 }
@ -66,7 +66,7 @@ FactoryBot.define do
rsnvac { 6 } rsnvac { 6 }
unittype_gn { 7 } unittype_gn { 7 }
beds { 3 } beds { 3 }
voiddate { "03/11/2019" } voiddate { 2.days.ago }
offered { 2 } offered { 2 }
wchair { 1 } wchair { 1 }
earnings { 68 } earnings { 68 }
@ -132,9 +132,8 @@ FactoryBot.define do
hbrentshortfall { 1 } hbrentshortfall { 1 }
tshortfall { 12 } tshortfall { 12 }
property_relet { 0 } property_relet { 0 }
mrcdate { Time.zone.local(2020, 5, 5, 10, 36, 49) } mrcdate { 1.day.ago }
incref { 0 } incref { 0 }
startdate { Time.zone.today }
armedforces { 1 } armedforces { 1 }
builtype { 1 } builtype { 1 }
unitletas { 2 } unitletas { 2 }
@ -155,7 +154,7 @@ FactoryBot.define do
sheltered { 0 } sheltered { 0 }
household_charge { 0 } household_charge { 0 }
end end
created_at { Time.utc(2022, 2, 8, 16, 52, 15) } created_at { Time.zone.today }
updated_at { Time.utc(2022, 2, 8, 16, 52, 15) } updated_at { Time.zone.today }
end end
end end

13
spec/features/form/accessible_autocomplete_spec.rb

@ -2,6 +2,15 @@ require "rails_helper"
require_relative "helpers" require_relative "helpers"
RSpec.describe "Accessible Autocomplete" do RSpec.describe "Accessible Autocomplete" do
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
include Helpers include Helpers
let(:user) { FactoryBot.create(:user) } let(:user) { FactoryBot.create(:user) }
let(:lettings_log) do let(:lettings_log) do
@ -64,8 +73,8 @@ RSpec.describe "Accessible Autocomplete" do
let(:scheme) { FactoryBot.create(:scheme, owning_organisation_id: lettings_log.created_by.organisation_id, primary_client_group: "Q", secondary_client_group: "P") } let(:scheme) { FactoryBot.create(:scheme, owning_organisation_id: lettings_log.created_by.organisation_id, primary_client_group: "Q", secondary_client_group: "P") }
before do before do
FactoryBot.create(:location, scheme:, postcode: "W6 0ST") FactoryBot.create(:location, scheme:, postcode: "W6 0ST", startdate: Time.zone.local(2022, 1, 1))
FactoryBot.create(:location, scheme:, postcode: "SE6 1LB") FactoryBot.create(:location, scheme:, postcode: "SE6 1LB", startdate: Time.zone.local(2022, 1, 1))
lettings_log.update!(needstype: 2) lettings_log.update!(needstype: 2)
visit("/lettings-logs/#{lettings_log.id}/scheme") visit("/lettings-logs/#{lettings_log.id}/scheme")
end end

11
spec/features/form/check_answers_page_lettings_logs_spec.rb

@ -2,6 +2,15 @@ require "rails_helper"
require_relative "helpers" require_relative "helpers"
RSpec.describe "Lettings Log Check Answers Page" do RSpec.describe "Lettings Log Check Answers Page" do
around do |example|
Timecop.freeze(Time.zone.local(2021, 5, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
include Helpers include Helpers
let(:user) { FactoryBot.create(:user) } let(:user) { FactoryBot.create(:user) }
let(:subsection) { "household-characteristics" } let(:subsection) { "household-characteristics" }
@ -152,7 +161,7 @@ RSpec.describe "Lettings Log Check Answers Page" do
context "when viewing setup section answers" do context "when viewing setup section answers" do
before do before do
FactoryBot.create(:location, scheme:) FactoryBot.create(:location, scheme:, startdate: Time.zone.local(2021, 1, 1))
end end
it "displays inferred postcode with the location id" do it "displays inferred postcode with the location id" do

9
spec/features/form/checkboxes_spec.rb

@ -14,6 +14,15 @@ RSpec.describe "Checkboxes" do
end end
let(:id) { lettings_log.id } let(:id) { lettings_log.id }
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
before do before do
allow(lettings_log.form).to receive(:end_date).and_return(Time.zone.today + 1.day) allow(lettings_log.form).to receive(:end_date).and_return(Time.zone.today + 1.day)
RequestHelper.stub_http_requests RequestHelper.stub_http_requests

10
spec/features/form/conditional_questions_spec.rb

@ -2,6 +2,15 @@ require "rails_helper"
require_relative "helpers" require_relative "helpers"
RSpec.describe "Form Conditional Questions" do RSpec.describe "Form Conditional Questions" do
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
include Helpers include Helpers
let(:user) { FactoryBot.create(:user) } let(:user) { FactoryBot.create(:user) }
let(:lettings_log) do let(:lettings_log) do
@ -16,6 +25,7 @@ RSpec.describe "Form Conditional Questions" do
:sales_log, :sales_log,
:completed, :completed,
created_by: user, created_by: user,
saledate: Time.zone.local(2022, 1, 1),
) )
end end
let(:id) { lettings_log.id } let(:id) { lettings_log.id }

9
spec/features/form/form_navigation_spec.rb

@ -2,6 +2,15 @@ require "rails_helper"
require_relative "helpers" require_relative "helpers"
RSpec.describe "Form Navigation" do RSpec.describe "Form Navigation" do
around do |example|
Timecop.travel(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
include Helpers include Helpers
let(:user) { FactoryBot.create(:user) } let(:user) { FactoryBot.create(:user) }
let(:lettings_log) do let(:lettings_log) do

159
spec/features/form/page_routing_spec.rb

@ -20,95 +20,106 @@ RSpec.describe "Form Page Routing" do
sign_in user sign_in user
end end
it "can route the user to a different page based on their answer on the current page", js: true do context "with 21/22 logs" do
visit("/lettings-logs/#{id}/conditional-question") around do |example|
# using a question name that is already in the db to avoid Timecop.freeze(Time.zone.local(2022, 1, 1)) do
# having to add a new column to the db for this test Singleton.__init__(FormHandler)
choose("lettings-log-preg-occ-1-field", allow_label_click: true) example.run
click_button("Save and continue") end
expect(page).to have_current_path("/lettings-logs/#{id}/conditional-question-yes-page") Timecop.return
click_link(text: "Back") Singleton.__init__(FormHandler)
expect(page).to have_current_path("/lettings-logs/#{id}/conditional-question") end
choose("lettings-log-preg-occ-2-field", allow_label_click: true)
click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{id}/conditional-question-no-page")
end
it "can route based on multiple conditions", js: true do
visit("/lettings-logs/#{id}/person-1-gender")
choose("lettings-log-sex1-f-field", allow_label_click: true)
click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{id}/person-1-working-situation")
visit("/lettings-logs/#{id}/conditional-question")
choose("lettings-log-preg-occ-2-field", allow_label_click: true)
click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{id}/conditional-question-no-page")
choose("lettings-log-cbl-0-field", allow_label_click: true)
click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{id}/conditional-question/check-answers")
end
context "when the answers are inferred", js: true do it "can route the user to a different page based on their answer on the current page", js: true do
it "shows question if the answer could not be inferred" do visit("/lettings-logs/#{id}/conditional-question")
visit("/lettings-logs/#{id}/property-postcode") # using a question name that is already in the db to avoid
fill_in("lettings-log-postcode-full-field", with: "PO5 3TE") # having to add a new column to the db for this test
choose("lettings-log-preg-occ-1-field", allow_label_click: true)
click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{id}/conditional-question-yes-page")
click_link(text: "Back")
expect(page).to have_current_path("/lettings-logs/#{id}/conditional-question")
choose("lettings-log-preg-occ-2-field", allow_label_click: true)
click_button("Save and continue") click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{id}/do-you-know-the-local-authority") expect(page).to have_current_path("/lettings-logs/#{id}/conditional-question-no-page")
end end
it "shows question if the answer could not be inferred from an empty input" do it "can route based on multiple conditions", js: true do
visit("/lettings-logs/#{id}/property-postcode") visit("/lettings-logs/#{id}/person-1-gender")
choose("lettings-log-sex1-f-field", allow_label_click: true)
click_button("Save and continue") click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{id}/do-you-know-the-local-authority") expect(page).to have_current_path("/lettings-logs/#{id}/person-1-working-situation")
visit("/lettings-logs/#{id}/conditional-question")
choose("lettings-log-preg-occ-2-field", allow_label_click: true)
click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{id}/conditional-question-no-page")
choose("lettings-log-cbl-0-field", allow_label_click: true)
click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{id}/conditional-question/check-answers")
end end
it "does not show question if the answer could be inferred" do context "when the answers are inferred", js: true do
stub_request(:get, /api.postcodes.io/) it "shows question if the answer could not be inferred" do
.to_return(status: 200, body: "{\"status\":200,\"result\":{\"admin_district\":\"Manchester\", \"codes\":{\"admin_district\": \"E08000003\"}}}", headers: {}) visit("/lettings-logs/#{id}/property-postcode")
fill_in("lettings-log-postcode-full-field", with: "PO5 3TE")
click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{id}/do-you-know-the-local-authority")
end
visit("/lettings-logs/#{id}/property-postcode") it "shows question if the answer could not be inferred from an empty input" do
fill_in("lettings-log-postcode-full-field", with: "P0 5ST") visit("/lettings-logs/#{id}/property-postcode")
click_button("Save and continue") click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{id}/property-wheelchair-accessible") expect(page).to have_current_path("/lettings-logs/#{id}/do-you-know-the-local-authority")
end end
end
context "when answer is invalid" do it "does not show question if the answer could be inferred" do
it "shows error with invalid value in the field" do stub_request(:get, /api.postcodes.io/)
visit("/lettings-logs/#{id}/property-postcode") .to_return(status: 200, body: "{\"status\":200,\"result\":{\"admin_district\":\"Manchester\", \"codes\":{\"admin_district\": \"E08000003\"}}}", headers: {})
fill_in("lettings-log-postcode-full-field", with: "fake_postcode")
click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{id}/property-postcode") visit("/lettings-logs/#{id}/property-postcode")
expect(find("#lettings-log-postcode-full-field-error").value).to eq("fake_postcode") fill_in("lettings-log-postcode-full-field", with: "P0 5ST")
click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{id}/property-wheelchair-accessible")
end
end end
it "does not reset the displayed date" do context "when answer is invalid" do
lettings_log.update!(startdate: "2021/10/13") it "shows error with invalid value in the field" do
visit("/lettings-logs/#{id}/tenancy-start-date") visit("/lettings-logs/#{id}/property-postcode")
fill_in("lettings_log[startdate(1i)]", with: "202") fill_in("lettings-log-postcode-full-field", with: "fake_postcode")
fill_in("lettings_log[startdate(2i)]", with: "32") click_button("Save and continue")
fill_in("lettings_log[startdate(3i)]", with: "0")
click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{id}/tenancy-start-date") expect(page).to have_current_path("/lettings-logs/#{id}/property-postcode")
expect(find_field("lettings_log[startdate(3i)]").value).to eq("13") expect(find("#lettings-log-postcode-full-field-error").value).to eq("fake_postcode")
expect(find_field("lettings_log[startdate(2i)]").value).to eq("10") end
expect(find_field("lettings_log[startdate(1i)]").value).to eq("2021")
end
it "does not reset the displayed date if it's empty" do it "does not reset the displayed date" do
lettings_log.update!(startdate: nil) lettings_log.update!(startdate: "2021/10/13")
visit("/lettings-logs/#{id}/tenancy-start-date") visit("/lettings-logs/#{id}/tenancy-start-date")
fill_in("lettings_log[startdate(1i)]", with: "202") fill_in("lettings_log[startdate(1i)]", with: "202")
fill_in("lettings_log[startdate(2i)]", with: "32") fill_in("lettings_log[startdate(2i)]", with: "32")
fill_in("lettings_log[startdate(3i)]", with: "0") fill_in("lettings_log[startdate(3i)]", with: "0")
click_button("Save and continue") click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{id}/tenancy-start-date")
expect(find_field("lettings_log[startdate(3i)]").value).to eq("13")
expect(find_field("lettings_log[startdate(2i)]").value).to eq("10")
expect(find_field("lettings_log[startdate(1i)]").value).to eq("2021")
end
expect(page).to have_current_path("/lettings-logs/#{id}/tenancy-start-date") it "does not reset the displayed date if it's empty" do
expect(find_field("lettings_log[startdate(3i)]").value).to eq(nil) lettings_log.update!(startdate: nil)
expect(find_field("lettings_log[startdate(2i)]").value).to eq(nil) visit("/lettings-logs/#{id}/tenancy-start-date")
expect(find_field("lettings_log[startdate(1i)]").value).to eq(nil) fill_in("lettings_log[startdate(1i)]", with: "202")
fill_in("lettings_log[startdate(2i)]", with: "32")
fill_in("lettings_log[startdate(3i)]", with: "0")
click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{id}/tenancy-start-date")
expect(find_field("lettings_log[startdate(3i)]").value).to eq(nil)
expect(find_field("lettings_log[startdate(2i)]").value).to eq(nil)
expect(find_field("lettings_log[startdate(1i)]").value).to eq(nil)
end
end end
end end

9
spec/features/form/progressive_total_field_spec.rb

@ -12,6 +12,15 @@ RSpec.describe "Accessible Autocomplete" do
) )
end end
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
before do before do
allow(lettings_log.form).to receive(:end_date).and_return(Time.zone.today + 1.day) allow(lettings_log.form).to receive(:end_date).and_return(Time.zone.today + 1.day)
sign_in user sign_in user

9
spec/features/form/saving_data_spec.rb

@ -2,6 +2,15 @@ require "rails_helper"
require_relative "helpers" require_relative "helpers"
RSpec.describe "Form Saving Data" do RSpec.describe "Form Saving Data" do
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
include Helpers include Helpers
let(:user) { FactoryBot.create(:user) } let(:user) { FactoryBot.create(:user) }
let(:lettings_log) do let(:lettings_log) do

16
spec/features/form/tasklist_page_spec.rb

@ -36,18 +36,32 @@ RSpec.describe "Task List" do
:about_completed, :about_completed,
owning_organisation: user.organisation, owning_organisation: user.organisation,
managing_organisation: user.organisation, managing_organisation: user.organisation,
startdate: Time.zone.local(2021, 5, 1),
created_by: user, created_by: user,
) )
end end
let(:id) { lettings_log.id } let(:id) { lettings_log.id }
let(:status) { lettings_log.status } let(:status) { lettings_log.status }
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
before do before do
Timecop.freeze(Time.zone.local(2021, 5, 1))
setup_completed_log.update!(startdate: Time.zone.local(2021, 5, 1))
allow(lettings_log.form).to receive(:end_date).and_return(Time.zone.today + 1.day) allow(lettings_log.form).to receive(:end_date).and_return(Time.zone.today + 1.day)
sign_in user sign_in user
end end
after do
Timecop.unfreeze
end
it "shows if the section has not been started" do it "shows if the section has not been started" do
visit("/lettings-logs/#{empty_lettings_log.id}") visit("/lettings-logs/#{empty_lettings_log.id}")
expect(page).to have_content("This log has not been started.") expect(page).to have_content("This log has not been started.")

11
spec/features/form/validations_spec.rb

@ -2,6 +2,15 @@ require "rails_helper"
require_relative "helpers" require_relative "helpers"
RSpec.describe "validations" do RSpec.describe "validations" do
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
let(:fake_2021_2022_form) { Form.new("spec/fixtures/forms/2021_2022.json") } let(:fake_2021_2022_form) { Form.new("spec/fixtures/forms/2021_2022.json") }
let(:user) { FactoryBot.create(:user) } let(:user) { FactoryBot.create(:user) }
let(:lettings_log) do let(:lettings_log) do
@ -26,6 +35,8 @@ RSpec.describe "validations" do
status: 1, status: 1,
declaration: nil, declaration: nil,
startdate: Time.zone.local(2021, 5, 1), startdate: Time.zone.local(2021, 5, 1),
voiddate: Time.zone.local(2021, 5, 1),
mrcdate: Time.zone.local(2021, 5, 1),
) )
end end
let(:id) { lettings_log.id } let(:id) { lettings_log.id }

2
spec/fixtures/exports/general_needs_log.csv vendored

@ -1,2 +1,2 @@
status,tenancycode,age1,sex1,ethnic,national,prevten,ecstat1,hhmemb,age2,sex2,ecstat2,age3,sex3,ecstat3,age4,sex4,ecstat4,age5,sex5,ecstat5,age6,sex6,ecstat6,age7,sex7,ecstat7,age8,sex8,ecstat8,homeless,underoccupation_benefitcap,leftreg,reservist,illness,preg_occ,startertenancy,tenancylength,tenancy,ppostcode_full,rsnvac,unittype_gn,beds,offered,wchair,earnings,incfreq,benefits,period,layear,waityear,postcode_full,reasonpref,cbl,chr,cap,reasonother,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,illness_type_1,illness_type_2,illness_type_3,illness_type_4,illness_type_8,illness_type_5,illness_type_6,illness_type_7,illness_type_9,illness_type_10,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,tenancyother,irproduct_other,reason,propcode,la,prevloc,hb,hbrentshortfall,mrcdate,incref,startdate,armedforces,unitletas,builtype,voiddate,renttype,needstype,lettype,totchild,totelder,totadult,nocharge,referral,brent,scharge,pscharge,supcharg,tcharge,tshortfall,chcharge,ppcodenk,has_benefits,renewal,wrent,wscharge,wpschrge,wsupchrg,wtcharge,wtshortfall,refused,housingneeds,wchchrg,newprop,relat2,relat3,relat4,relat5,relat6,relat7,relat8,lar,irproduct,joint,sheltered,hhtype,new_old,vacdays,formid,owningorgid,owningorgname,hcnum,maningorgid,maningorgname,manhcnum,createddate,uploaddate status,tenancycode,age1,sex1,ethnic,national,prevten,ecstat1,hhmemb,age2,sex2,ecstat2,age3,sex3,ecstat3,age4,sex4,ecstat4,age5,sex5,ecstat5,age6,sex6,ecstat6,age7,sex7,ecstat7,age8,sex8,ecstat8,homeless,underoccupation_benefitcap,leftreg,reservist,illness,preg_occ,startertenancy,tenancylength,tenancy,ppostcode_full,rsnvac,unittype_gn,beds,offered,wchair,earnings,incfreq,benefits,period,layear,waityear,postcode_full,reasonpref,cbl,chr,cap,reasonother,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,illness_type_1,illness_type_2,illness_type_3,illness_type_4,illness_type_8,illness_type_5,illness_type_6,illness_type_7,illness_type_9,illness_type_10,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,tenancyother,irproduct_other,reason,propcode,la,prevloc,hb,hbrentshortfall,mrcdate,incref,startdate,armedforces,unitletas,builtype,voiddate,renttype,needstype,lettype,totchild,totelder,totadult,nocharge,referral,brent,scharge,pscharge,supcharg,tcharge,tshortfall,chcharge,ppcodenk,has_benefits,renewal,wrent,wscharge,wpschrge,wsupchrg,wtcharge,wtshortfall,refused,housingneeds,wchchrg,newprop,relat2,relat3,relat4,relat5,relat6,relat7,relat8,lar,irproduct,joint,sheltered,hhtype,new_old,vacdays,formid,owningorgid,owningorgname,hcnum,maningorgid,maningorgname,manhcnum,createddate,uploaddate
2,BZ737,35,F,2,4,6,0,2,32,M,6,,,,,,,,,,,,,,,,,,,1,4,1,1,1,2,1,5,1,SE2 6RT,6,7,3,2,1,68,1,1,2,2,1,NW1 5TY,1,2,1,2,,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,,,4,123,E09000003,E07000105,6,1,2020-05-05T10:36:49+01:00,0,2022-02-02T10:36:49+00:00,1,2,1,2019-11-03T00:00:00+00:00,2,1,7,0,0,2,0,2,200.0,50.0,40.0,35.0,325.0,12.0,,1,1,0,100.0,25.0,20.0,17.5,162.5,6.0,0,1,,2,P,,,,,,,,,,,4,2,638,{id},{owning_org_id},DLUHC,1234,{managing_org_id},DLUHC,1234,2022-02-08T16:52:15+00:00,2022-02-08T16:52:15+00:00 2,BZ737,35,F,2,4,6,0,2,32,M,6,,,,,,,,,,,,,,,,,,,1,4,1,1,1,2,1,5,1,SE2 6RT,6,7,3,2,1,68,1,1,2,2,1,NW1 5TY,1,2,1,2,,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,,,4,123,E09000003,E07000105,6,1,2020-05-05T10:36:49+01:00,0,2022-02-02T10:36:49+00:00,1,2,1,2019-11-03T00:00:00+00:00,2,1,7,0,0,2,0,2,200.0,50.0,40.0,35.0,325.0,12.0,,1,1,0,100.0,25.0,20.0,17.5,162.5,6.0,0,1,,2,P,,,,,,,,,,,4,2,638,{id},{owning_org_id},DLUHC,1234,{managing_org_id},DLUHC,1234,2022-05-01T00:00:00+01:00,2022-05-01T00:00:00+01:00

1 status tenancycode age1 sex1 ethnic national prevten ecstat1 hhmemb age2 sex2 ecstat2 age3 sex3 ecstat3 age4 sex4 ecstat4 age5 sex5 ecstat5 age6 sex6 ecstat6 age7 sex7 ecstat7 age8 sex8 ecstat8 homeless underoccupation_benefitcap leftreg reservist illness preg_occ startertenancy tenancylength tenancy ppostcode_full rsnvac unittype_gn beds offered wchair earnings incfreq benefits period layear waityear postcode_full reasonpref cbl chr cap reasonother housingneeds_a housingneeds_b housingneeds_c housingneeds_f housingneeds_g housingneeds_h illness_type_1 illness_type_2 illness_type_3 illness_type_4 illness_type_8 illness_type_5 illness_type_6 illness_type_7 illness_type_9 illness_type_10 rp_homeless rp_insan_unsat rp_medwel rp_hardship rp_dontknow tenancyother irproduct_other reason propcode la prevloc hb hbrentshortfall mrcdate incref startdate armedforces unitletas builtype voiddate renttype needstype lettype totchild totelder totadult nocharge referral brent scharge pscharge supcharg tcharge tshortfall chcharge ppcodenk has_benefits renewal wrent wscharge wpschrge wsupchrg wtcharge wtshortfall refused housingneeds wchchrg newprop relat2 relat3 relat4 relat5 relat6 relat7 relat8 lar irproduct joint sheltered hhtype new_old vacdays formid owningorgid owningorgname hcnum maningorgid maningorgname manhcnum createddate uploaddate
2 2 BZ737 35 F 2 4 6 0 2 32 M 6 1 4 1 1 1 2 1 5 1 SE2 6RT 6 7 3 2 1 68 1 1 2 2 1 NW1 5TY 1 2 1 2 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 4 123 E09000003 E07000105 6 1 2020-05-05T10:36:49+01:00 0 2022-02-02T10:36:49+00:00 1 2 1 2019-11-03T00:00:00+00:00 2 1 7 0 0 2 0 2 200.0 50.0 40.0 35.0 325.0 12.0 1 1 0 100.0 25.0 20.0 17.5 162.5 6.0 0 1 2 P 4 2 638 {id} {owning_org_id} DLUHC 1234 {managing_org_id} DLUHC 1234 2022-02-08T16:52:15+00:00 2022-05-01T00:00:00+01:00 2022-02-08T16:52:15+00:00 2022-05-01T00:00:00+01:00

4
spec/fixtures/exports/general_needs_log.xml vendored

@ -142,8 +142,8 @@
<maningorgid>{managing_org_id}</maningorgid> <maningorgid>{managing_org_id}</maningorgid>
<maningorgname>DLUHC</maningorgname> <maningorgname>DLUHC</maningorgname>
<manhcnum>1234</manhcnum> <manhcnum>1234</manhcnum>
<createddate>2022-02-08T16:52:15+00:00</createddate> <createddate>2022-05-01T00:00:00+01:00</createddate>
<uploaddate>2022-02-08T16:52:15+00:00</uploaddate> <uploaddate>2022-05-01T00:00:00+01:00</uploaddate>
<providertype>1</providertype> <providertype>1</providertype>
</form> </form>
</forms> </forms>

4
spec/fixtures/exports/supported_housing_logs.xml vendored

@ -141,8 +141,8 @@
<maningorgid>{managing_org_id}</maningorgid> <maningorgid>{managing_org_id}</maningorgid>
<maningorgname>DLUHC</maningorgname> <maningorgname>DLUHC</maningorgname>
<manhcnum>1234</manhcnum> <manhcnum>1234</manhcnum>
<createddate>2022-02-08T16:52:15+00:00</createddate> <createddate>2022-05-01T00:00:00+01:00</createddate>
<uploaddate>2022-02-08T16:52:15+00:00</uploaddate> <uploaddate>2022-05-01T00:00:00+01:00</uploaddate>
<unittype_sh>7</unittype_sh> <unittype_sh>7</unittype_sh>
<confidential>1</confidential> <confidential>1</confidential>
<cligrp1>G</cligrp1> <cligrp1>G</cligrp1>

9
spec/helpers/check_answers_helper_spec.rb

@ -6,6 +6,15 @@ RSpec.describe CheckAnswersHelper do
let(:lettings_log) { FactoryBot.build(:lettings_log, :in_progress) } let(:lettings_log) { FactoryBot.build(:lettings_log, :in_progress) }
let(:current_user) { FactoryBot.build(:user) } let(:current_user) { FactoryBot.build(:user) }
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
describe "display_answered_questions_summary" do describe "display_answered_questions_summary" do
context "when a section hasn't been completed yet" do context "when a section hasn't been completed yet" do
it "returns that you have unanswered questions" do it "returns that you have unanswered questions" do

9
spec/helpers/form_page_error_helper_spec.rb

@ -3,6 +3,15 @@ require "rails_helper"
RSpec.describe FormPageErrorHelper do RSpec.describe FormPageErrorHelper do
describe "#remove_other_page_errors" do describe "#remove_other_page_errors" do
context "when non base other questions are removed" do context "when non base other questions are removed" do
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
let!(:lettings_log) { FactoryBot.create(:lettings_log, :in_progress) } let!(:lettings_log) { FactoryBot.create(:lettings_log, :in_progress) }
let!(:form) { lettings_log.form } let!(:form) { lettings_log.form }

9
spec/helpers/interruption_screen_helper_spec.rb

@ -17,6 +17,15 @@ RSpec.describe InterruptionScreenHelper do
) )
end end
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
describe "display_informative_text" do describe "display_informative_text" do
context "when 2 out of 2 arguments are given" do context "when 2 out of 2 arguments are given" do
it "returns correct informative text" do it "returns correct informative text" do

86
spec/helpers/tasklist_helper_spec.rb

@ -1,7 +1,7 @@
require "rails_helper" require "rails_helper"
RSpec.describe TasklistHelper do RSpec.describe TasklistHelper do
let(:now) { Time.utc(2022, 6, 1) } let(:now) { Time.utc(2022, 1, 1) }
around do |example| around do |example|
Timecop.freeze(now) do Timecop.freeze(now) do
@ -13,7 +13,7 @@ RSpec.describe TasklistHelper do
describe "with lettings" do describe "with lettings" do
let(:empty_lettings_log) { create(:lettings_log) } let(:empty_lettings_log) { create(:lettings_log) }
let(:lettings_log) { build(:lettings_log, :in_progress, needstype: 1) } let(:lettings_log) { build(:lettings_log, :in_progress, needstype: 1, startdate: now) }
describe "get next incomplete section" do describe "get next incomplete section" do
it "returns the first subsection name if it is not completed" do it "returns the first subsection name if it is not completed" do
@ -27,8 +27,14 @@ RSpec.describe TasklistHelper do
end end
describe "get sections count" do describe "get sections count" do
let(:fake_2021_2022_form) { Form.new("spec/fixtures/forms/2021_2022.json") }
before do
allow(FormHandler.instance).to receive(:get_form).and_return(fake_2021_2022_form)
end
it "returns the total of sections if no status is given" do it "returns the total of sections if no status is given" do
expect(get_subsections_count(empty_lettings_log)).to eq(1) expect(get_subsections_count(empty_lettings_log)).to eq(8)
end end
it "returns 0 sections for completed sections if no sections are completed" do it "returns 0 sections for completed sections if no sections are completed" do
@ -36,7 +42,7 @@ RSpec.describe TasklistHelper do
end end
it "returns the number of not started sections" do it "returns the number of not started sections" do
expect(get_subsections_count(empty_lettings_log, :not_started)).to eq(1) expect(get_subsections_count(empty_lettings_log, :not_started)).to eq(8)
end end
it "returns the number of sections in progress" do it "returns the number of sections in progress" do
@ -48,41 +54,6 @@ RSpec.describe TasklistHelper do
end end
end end
describe "review_log_text" do
context "when collection_period_open? == true" do
context "with 2023 deadline" do
let(:now) { Time.utc(2022, 6, 1) }
let(:lettings_log) { create(:lettings_log, :completed) }
it "returns relevant text" do
expect(review_log_text(lettings_log)).to eq(
"You can #{govuk_link_to 'review and make changes to this log', review_lettings_log_path(lettings_log)} until 1 July 2023.".html_safe,
)
end
end
context "with 2024 deadline" do
let(:now) { Time.utc(2023, 6, 20) }
let(:lettings_log) { create(:lettings_log, :completed, national: 18, waityear: 2) }
it "returns relevant text" do
expect(review_log_text(lettings_log)).to eq(
"You can #{govuk_link_to 'review and make changes to this log', review_lettings_log_path(lettings_log)} until 9 July 2024.".html_safe,
)
end
end
end
context "when collection_period_open? == false" do
let(:now) { Time.utc(2023, 7, 8) }
let(:lettings_log) { create(:lettings_log, :completed, startdate: Time.utc(2023, 2, 8)) }
it "returns relevant text" do
expect(review_log_text(lettings_log)).to eq("This log is from the 2022/2023 collection window, which is now closed.")
end
end
end
describe "subsection link" do describe "subsection link" do
let(:lettings_log) { create(:lettings_log, :completed) } let(:lettings_log) { create(:lettings_log, :completed) }
let(:subsection) { lettings_log.form.get_subsection("household_characteristics") } let(:subsection) { lettings_log.form.get_subsection("household_characteristics") }
@ -130,5 +101,42 @@ RSpec.describe TasklistHelper do
end end
end end
end end
context "with lettings log" do
context "when collection_period_open? == true" do
context "with 2023 deadline" do
let(:now) { Time.utc(2022, 6, 1) }
let(:lettings_log) { create(:lettings_log, :completed) }
it "returns relevant text" do
expect(review_log_text(lettings_log)).to eq(
"You can #{govuk_link_to 'review and make changes to this log', review_lettings_log_path(lettings_log)} until 1 July 2023.".html_safe,
)
end
end
context "with 2024 deadline" do
let(:now) { Time.utc(2023, 6, 20) }
let(:lettings_log) { create(:lettings_log, :completed, national: 18, waityear: 2) }
it "returns relevant text" do
expect(review_log_text(lettings_log)).to eq(
"You can #{govuk_link_to 'review and make changes to this log', review_lettings_log_path(lettings_log)} until 9 July 2024.".html_safe,
)
end
end
end
context "when collection_period_open? == false" do
let(:now) { Time.utc(2022, 6, 1) }
let!(:sales_log) { create(:lettings_log, :completed) }
it "returns relevant text" do
Timecop.freeze(now + 1.year) do
expect(review_log_text(sales_log)).to eq("This log is from the 2021/2022 collection window, which is now closed.")
end
end
end
end
end end
end end

6
spec/jobs/email_csv_job_spec.rb

@ -31,7 +31,9 @@ describe EmailCsvJob do
FactoryBot.create(:lettings_log, FactoryBot.create(:lettings_log,
:completed, :completed,
created_by: user, created_by: user,
startdate: Time.zone.local(2021, 5, 1)) startdate: Time.zone.local(2022, 5, 1),
voiddate: Time.zone.local(2022, 5, 1),
mrcdate: Time.zone.local(2022, 5, 1))
allow(Storage::S3Service).to receive(:new).and_return(storage_service) allow(Storage::S3Service).to receive(:new).and_return(storage_service)
allow(storage_service).to receive(:write_file) allow(storage_service).to receive(:write_file)
@ -104,7 +106,7 @@ describe EmailCsvJob do
it "writes answer labels rather than values" do it "writes answer labels rather than values" do
expect_csv do |csv| expect_csv do |csv|
expect(csv.second[16]).to eq("Full-time – 30 hours or more") expect(csv.second[19]).to eq("Full-time – 30 hours or more")
end end
job.perform(user) job.perform(user)

9
spec/models/form/page_spec.rb

@ -3,6 +3,15 @@ require "rails_helper"
RSpec.describe Form::Page, type: :model do RSpec.describe Form::Page, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) } subject(:page) { described_class.new(page_id, page_definition, subsection) }
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
let(:user) { FactoryBot.create(:user) } let(:user) { FactoryBot.create(:user) }
let(:lettings_log) { FactoryBot.build(:lettings_log) } let(:lettings_log) { FactoryBot.build(:lettings_log) }
let(:form) { lettings_log.form } let(:form) { lettings_log.form }

11
spec/models/form/question_spec.rb

@ -3,6 +3,15 @@ require "rails_helper"
RSpec.describe Form::Question, type: :model do RSpec.describe Form::Question, type: :model do
subject(:question) { described_class.new(question_id, question_definition, page) } subject(:question) { described_class.new(question_id, question_definition, page) }
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
let(:lettings_log) { FactoryBot.build(:lettings_log) } let(:lettings_log) { FactoryBot.build(:lettings_log) }
let(:form) { lettings_log.form } let(:form) { lettings_log.form }
let(:section_id) { "rent_and_charges" } let(:section_id) { "rent_and_charges" }
@ -367,7 +376,7 @@ RSpec.describe Form::Question, type: :model do
end end
context "when Sales form" do context "when Sales form" do
let(:sales_log) { FactoryBot.create(:sales_log, :completed, ethnic_group: 17) } let(:sales_log) { FactoryBot.create(:sales_log, :completed, ethnic_group: 17, saledate: Time.zone.local(2022, 1, 1)) }
let(:question) { sales_log.form.get_question("ethnic_group", sales_log) } let(:question) { sales_log.form.get_question("ethnic_group", sales_log) }
it "returns the inferred label value" do it "returns the inferred label value" do

9
spec/models/form/subsection_spec.rb

@ -4,6 +4,15 @@ require_relative "../../request_helper"
RSpec.describe Form::Subsection, type: :model do RSpec.describe Form::Subsection, type: :model do
subject(:subsection) { described_class.new(subsection_id, subsection_definition, section) } subject(:subsection) { described_class.new(subsection_id, subsection_definition, section) }
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
let(:lettings_log) { FactoryBot.build(:lettings_log) } let(:lettings_log) { FactoryBot.build(:lettings_log) }
let(:form) { lettings_log.form } let(:form) { lettings_log.form }
let(:section_id) { "household" } let(:section_id) { "household" }

9
spec/models/form_spec.rb

@ -1,6 +1,15 @@
require "rails_helper" require "rails_helper"
RSpec.describe Form, type: :model do RSpec.describe Form, type: :model do
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
let(:user) { FactoryBot.build(:user) } let(:user) { FactoryBot.build(:user) }
let(:lettings_log) { FactoryBot.build(:lettings_log, :in_progress) } let(:lettings_log) { FactoryBot.build(:lettings_log, :in_progress) }
let(:form) { lettings_log.form } let(:form) { lettings_log.form }

181
spec/models/lettings_log_spec.rb

@ -6,6 +6,16 @@ RSpec.describe LettingsLog do
let(:created_by_user) { create(:user) } let(:created_by_user) { create(:user) }
let(:owning_organisation) { created_by_user.organisation } let(:owning_organisation) { created_by_user.organisation }
let(:fake_2021_2022_form) { Form.new("spec/fixtures/forms/2021_2022.json") } let(:fake_2021_2022_form) { Form.new("spec/fixtures/forms/2021_2022.json") }
let(:fake_2022_2023_form) { Form.new("spec/fixtures/forms/2022_2023.json") }
around do |example|
Timecop.freeze(Time.utc(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
before do before do
allow(FormHandler.instance).to receive(:current_lettings_form).and_return(fake_2021_2022_form) allow(FormHandler.instance).to receive(:current_lettings_form).and_return(fake_2021_2022_form)
@ -33,7 +43,15 @@ RSpec.describe LettingsLog do
let(:lettings_log_2) { build(:lettings_log, startdate: Time.zone.local(2022, 1, 1), created_by: created_by_user) } let(:lettings_log_2) { build(:lettings_log, startdate: Time.zone.local(2022, 1, 1), created_by: created_by_user) }
let(:lettings_log_year_2) { build(:lettings_log, startdate: Time.zone.local(2023, 5, 1), created_by: created_by_user) } let(:lettings_log_year_2) { build(:lettings_log, startdate: Time.zone.local(2023, 5, 1), created_by: created_by_user) }
it "has returns the correct form based on the start date" do before do
Timecop.freeze(2023, 1, 1)
end
after do
Timecop.unfreeze
end
it "returns the correct form based on the start date" do
expect(lettings_log.form_name).to be_nil expect(lettings_log.form_name).to be_nil
expect(lettings_log.form).to be_a(Form) expect(lettings_log.form).to be_a(Form)
expect(lettings_log_2.form_name).to eq("previous_lettings") expect(lettings_log_2.form_name).to eq("previous_lettings")
@ -1477,10 +1495,15 @@ RSpec.describe LettingsLog do
context "when deriving renttype and unitletas" do context "when deriving renttype and unitletas" do
before do before do
Timecop.freeze(Time.zone.local(2022, 1, 1))
allow(FeatureToggle).to receive(:startdate_two_week_validation_enabled?).and_return(false) allow(FeatureToggle).to receive(:startdate_two_week_validation_enabled?).and_return(false)
lettings_log.update!(rent_type:, irproduct_other: "other") lettings_log.update!(rent_type:, irproduct_other: "other")
end end
after do
Timecop.unfreeze
end
context "when the rent_type is Social Rent (0)" do context "when the rent_type is Social Rent (0)" do
let(:rent_type) { 0 } let(:rent_type) { 0 }
@ -1497,6 +1520,23 @@ RSpec.describe LettingsLog do
end end
context "and it is a 23/24 form" do context "and it is a 23/24 form" do
before do
Timecop.freeze(Time.zone.local(2023, 5, 1))
end
after do
Timecop.unfreeze
end
around do |example|
Timecop.freeze(Time.zone.local(2023, 5, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
it "derives and saves unitletas as Social rent(1)" do it "derives and saves unitletas as Social rent(1)" do
lettings_log.update!(startdate: Time.zone.local(2023, 5, 1)) lettings_log.update!(startdate: Time.zone.local(2023, 5, 1))
record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0] record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0]
@ -1522,6 +1562,23 @@ RSpec.describe LettingsLog do
end end
context "and it is a 23/24 form" do context "and it is a 23/24 form" do
before do
Timecop.freeze(Time.zone.local(2023, 5, 1))
end
after do
Timecop.unfreeze
end
around do |example|
Timecop.freeze(Time.zone.local(2023, 5, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
it "derives and saves unitletas as Affordable Rent basis(2)" do it "derives and saves unitletas as Affordable Rent basis(2)" do
lettings_log.update!(startdate: Time.zone.local(2023, 5, 1)) lettings_log.update!(startdate: Time.zone.local(2023, 5, 1))
record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0] record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0]
@ -1547,6 +1604,23 @@ RSpec.describe LettingsLog do
end end
context "and it is a 23/24 form" do context "and it is a 23/24 form" do
before do
Timecop.freeze(Time.zone.local(2023, 5, 1))
end
after do
Timecop.unfreeze
end
around do |example|
Timecop.freeze(Time.zone.local(2023, 5, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
it "derives and saves unitletas as London Affordable Rent basis(5)" do it "derives and saves unitletas as London Affordable Rent basis(5)" do
lettings_log.update!(startdate: Time.zone.local(2023, 5, 1)) lettings_log.update!(startdate: Time.zone.local(2023, 5, 1))
record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0] record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0]
@ -1572,6 +1646,23 @@ RSpec.describe LettingsLog do
end end
context "and it is a 23/24 form" do context "and it is a 23/24 form" do
before do
Timecop.freeze(Time.zone.local(2023, 5, 1))
end
after do
Timecop.unfreeze
end
around do |example|
Timecop.freeze(Time.zone.local(2023, 5, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
it "derives and saves unitletas as Rent to Buy basis(6)" do it "derives and saves unitletas as Rent to Buy basis(6)" do
lettings_log.update!(startdate: Time.zone.local(2023, 5, 1)) lettings_log.update!(startdate: Time.zone.local(2023, 5, 1))
record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0] record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0]
@ -1597,6 +1688,23 @@ RSpec.describe LettingsLog do
end end
context "and it is a 23/24 form" do context "and it is a 23/24 form" do
before do
Timecop.freeze(Time.zone.local(2023, 5, 1))
end
after do
Timecop.unfreeze
end
around do |example|
Timecop.freeze(Time.zone.local(2023, 5, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
it "derives and saves unitletas as London Living Rent basis(7)" do it "derives and saves unitletas as London Living Rent basis(7)" do
lettings_log.update!(startdate: Time.zone.local(2023, 5, 1)) lettings_log.update!(startdate: Time.zone.local(2023, 5, 1))
record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0] record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0]
@ -1622,6 +1730,23 @@ RSpec.describe LettingsLog do
end end
context "and it is a 23/24 form" do context "and it is a 23/24 form" do
before do
Timecop.freeze(Time.zone.local(2023, 5, 1))
end
after do
Timecop.unfreeze
end
around do |example|
Timecop.freeze(Time.zone.local(2023, 5, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
it "derives and saves unitletas as Other intermediate rent basis(8)" do it "derives and saves unitletas as Other intermediate rent basis(8)" do
lettings_log.update!(startdate: Time.zone.local(2023, 5, 1)) lettings_log.update!(startdate: Time.zone.local(2023, 5, 1))
record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0] record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0]
@ -1863,7 +1988,11 @@ RSpec.describe LettingsLog do
let(:scheme) { create(:scheme) } let(:scheme) { create(:scheme) }
let!(:location) { create(:location, scheme:) } let!(:location) { create(:location, scheme:) }
before { lettings_log.update!(startdate: Time.zone.local(2022, 4, 2), scheme:) } before do
Timecop.freeze(Time.zone.local(2022, 4, 2))
lettings_log.update!(startdate: Time.zone.local(2022, 4, 2), scheme:)
Timecop.unfreeze
end
it "derives the scheme location" do it "derives the scheme location" do
record_from_db = ActiveRecord::Base.connection.execute("select location_id from lettings_logs where id=#{lettings_log.id}").to_a[0] record_from_db = ActiveRecord::Base.connection.execute("select location_id from lettings_logs where id=#{lettings_log.id}").to_a[0]
@ -1950,9 +2079,16 @@ RSpec.describe LettingsLog do
end end
context "and renewal" do context "and renewal" do
before do
Timecop.freeze(Time.zone.local(2022, 4, 2))
end
after do
Timecop.unfreeze
end
let(:scheme) { create(:scheme) } let(:scheme) { create(:scheme) }
let(:location) { create(:location, scheme:) } let(:location) { create(:location, scheme:) }
let!(:supported_housing_lettings_log) do let!(:supported_housing_lettings_log) do
described_class.create!({ described_class.create!({
managing_organisation: owning_organisation, managing_organisation: owning_organisation,
@ -1962,12 +2098,12 @@ RSpec.describe LettingsLog do
scheme_id: scheme.id, scheme_id: scheme.id,
location_id: location.id, location_id: location.id,
renewal: 1, renewal: 1,
startdate: Time.zone.now, startdate: Time.zone.local(2022, 4, 2),
created_at: Time.utc(2022, 2, 8, 16, 52, 15), created_at: Time.utc(2022, 2, 8, 16, 52, 15),
}) })
end end
it "correcly infers and saves the renewal date" do it "correctly infers and saves the renewal date" do
record_from_db = ActiveRecord::Base.connection.execute("SELECT voiddate from lettings_logs where id=#{supported_housing_lettings_log.id}").to_a[0] record_from_db = ActiveRecord::Base.connection.execute("SELECT voiddate from lettings_logs where id=#{supported_housing_lettings_log.id}").to_a[0]
expect(record_from_db["voiddate"].to_i).to eq(supported_housing_lettings_log.startdate.to_i) expect(record_from_db["voiddate"].to_i).to eq(supported_housing_lettings_log.startdate.to_i)
end end
@ -2333,6 +2469,15 @@ RSpec.describe LettingsLog do
end end
context "and the new location triggers the rent range validation" do context "and the new location triggers the rent range validation" do
around do |example|
Timecop.freeze(Time.zone.local(2022, 4, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
it "clears rent values" do it "clears rent values" do
lettings_log.update!(location:, scheme:) lettings_log.update!(location:, scheme:)
lettings_log.reload lettings_log.reload
@ -2467,8 +2612,8 @@ RSpec.describe LettingsLog do
end end
describe "scopes" do describe "scopes" do
let!(:lettings_log_1) { create(:lettings_log, :in_progress, startdate: Time.utc(2021, 5, 3), created_by: created_by_user) } let!(:lettings_log_1) { create(:lettings_log, :in_progress, startdate: Time.utc(2021, 5, 3), mrcdate: Time.utc(2021, 5, 3), voiddate: Time.utc(2021, 5, 3), created_by: created_by_user) }
let!(:lettings_log_2) { create(:lettings_log, :completed, startdate: Time.utc(2021, 5, 3), created_by: created_by_user) } let!(:lettings_log_2) { create(:lettings_log, :completed, startdate: Time.utc(2021, 5, 3), mrcdate: Time.utc(2021, 5, 3), voiddate: Time.utc(2021, 5, 3), created_by: created_by_user) }
before do before do
Timecop.freeze(Time.utc(2022, 6, 3)) Timecop.freeze(Time.utc(2022, 6, 3))
@ -2755,7 +2900,7 @@ RSpec.describe LettingsLog do
context "with values represented as human readable labels" do context "with values represented as human readable labels" do
before do before do
Timecop.freeze(Time.utc(2022, 6, 5)) Timecop.freeze(Time.utc(2022, 6, 5))
lettings_log = FactoryBot.create(:lettings_log, needstype: 2, scheme:, location:, owning_organisation: scheme.owning_organisation, created_by: user, rent_type: 2, startdate: Time.zone.local(2021, 10, 2)) lettings_log = FactoryBot.create(:lettings_log, needstype: 2, scheme:, location:, owning_organisation: scheme.owning_organisation, created_by: user, rent_type: 2, startdate: Time.zone.local(2021, 10, 2), created_at: Time.zone.local(2022, 2, 8, 16, 52, 15), updated_at: Time.zone.local(2022, 2, 8, 16, 52, 15))
expected_content.sub!(/\{id\}/, lettings_log["id"].to_s) expected_content.sub!(/\{id\}/, lettings_log["id"].to_s)
expected_content.sub!(/\{scheme_code\}/, "S#{scheme['id']}") expected_content.sub!(/\{scheme_code\}/, "S#{scheme['id']}")
expected_content.sub!(/\{scheme_service_name\}/, scheme["service_name"].to_s) expected_content.sub!(/\{scheme_service_name\}/, scheme["service_name"].to_s)
@ -2770,6 +2915,15 @@ RSpec.describe LettingsLog do
expected_content.sub!(/\{location_id\}/, location["id"].to_s) expected_content.sub!(/\{location_id\}/, location["id"].to_s)
end end
around do |example|
Timecop.freeze(Time.zone.local(2022, 6, 5)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
context "with a support user" do context "with a support user" do
let(:csv_export_file) { File.open("spec/fixtures/files/lettings_logs_download.csv", "r:UTF-8") } let(:csv_export_file) { File.open("spec/fixtures/files/lettings_logs_download.csv", "r:UTF-8") }
@ -2790,7 +2944,7 @@ RSpec.describe LettingsLog do
context "with values represented as codes" do context "with values represented as codes" do
before do before do
Timecop.freeze(Time.utc(2022, 6, 5)) Timecop.freeze(Time.utc(2022, 6, 5))
lettings_log = FactoryBot.create(:lettings_log, needstype: 2, scheme:, location:, owning_organisation: scheme.owning_organisation, created_by: user, rent_type: 2, startdate: Time.zone.local(2021, 10, 2)) lettings_log = FactoryBot.create(:lettings_log, needstype: 2, scheme:, location:, owning_organisation: scheme.owning_organisation, created_by: user, rent_type: 2, startdate: Time.zone.local(2021, 10, 2), created_at: Time.zone.local(2022, 2, 8, 16, 52, 15), updated_at: Time.zone.local(2022, 2, 8, 16, 52, 15))
expected_content.sub!(/\{id\}/, lettings_log["id"].to_s) expected_content.sub!(/\{id\}/, lettings_log["id"].to_s)
expected_content.sub!(/\{scheme_code\}/, "S#{scheme.id}") expected_content.sub!(/\{scheme_code\}/, "S#{scheme.id}")
expected_content.sub!(/\{scheme_service_name\}/, scheme.service_name.to_s) expected_content.sub!(/\{scheme_service_name\}/, scheme.service_name.to_s)
@ -2807,6 +2961,15 @@ RSpec.describe LettingsLog do
let(:csv_export_file) { File.open("spec/fixtures/files/lettings_logs_download_codes_only.csv", "r:UTF-8") } let(:csv_export_file) { File.open("spec/fixtures/files/lettings_logs_download_codes_only.csv", "r:UTF-8") }
around do |example|
Timecop.freeze(Time.zone.local(2022, 6, 5)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
it "generates a correct csv from a lettings log" do it "generates a correct csv from a lettings log" do
expect(described_class.to_csv(codes_only_export: true)).to eq(expected_content) expect(described_class.to_csv(codes_only_export: true)).to eq(expected_content)
end end

24
spec/models/validations/date_validations_spec.rb

@ -9,18 +9,6 @@ RSpec.describe Validations::DateValidations do
let(:scheme_no_end_date) { FactoryBot.create(:scheme, end_date: nil) } let(:scheme_no_end_date) { FactoryBot.create(:scheme, end_date: nil) }
describe "tenancy start date" do describe "tenancy start date" do
it "cannot be before the first collection window start date" do
record.startdate = Time.zone.local(2020, 1, 1)
date_validator.validate_startdate(record)
expect(record.errors["startdate"]).to include(match I18n.t("validations.date.outside_collection_window"))
end
it "cannot be after the second collection window end date" do
record.startdate = Time.zone.local(2023, 7, 1, 6)
date_validator.validate_startdate(record)
expect(record.errors["startdate"]).to include(match I18n.t("validations.date.outside_collection_window"))
end
it "must be a valid date" do it "must be a valid date" do
record.startdate = Time.zone.local(0, 7, 1) record.startdate = Time.zone.local(0, 7, 1)
date_validator.validate_startdate(record) date_validator.validate_startdate(record)
@ -98,7 +86,7 @@ RSpec.describe Validations::DateValidations do
record.location = location record.location = location
date_validator.validate_startdate(record) date_validator.validate_startdate(record)
expect(record.errors["startdate"]) expect(record.errors["startdate"])
.to include(match I18n.t("validations.setup.startdate.location.deactivated", postcode: location.postcode, date: "4 June 2022")) .to include(match I18n.t("validations.setup.startdate.location.deactivated", postcode: location.postcode, date: "4 June 2022"))
end end
it "produces no error when tenancy start date is during an active location period" do it "produces no error when tenancy start date is during an active location period" do
@ -123,7 +111,7 @@ RSpec.describe Validations::DateValidations do
record.location = location record.location = location
date_validator.validate_startdate(record) date_validator.validate_startdate(record)
expect(record.errors["startdate"]) expect(record.errors["startdate"])
.to include(match I18n.t("validations.setup.startdate.location.reactivating_soon", postcode: location.postcode, date: "4 August 2022")) .to include(match I18n.t("validations.setup.startdate.location.reactivating_soon", postcode: location.postcode, date: "4 August 2022"))
end end
it "produces no error when tenancy start date is during an active location period" do it "produces no error when tenancy start date is during an active location period" do
@ -150,7 +138,7 @@ RSpec.describe Validations::DateValidations do
record.location = location record.location = location
date_validator.validate_startdate(record) date_validator.validate_startdate(record)
expect(record.errors["startdate"]) expect(record.errors["startdate"])
.to include(match I18n.t("validations.setup.startdate.location.reactivating_soon", postcode: location.postcode, date: "4 September 2022")) .to include(match I18n.t("validations.setup.startdate.location.reactivating_soon", postcode: location.postcode, date: "4 September 2022"))
end end
it "produces no error when tenancy start date is during an active location period" do it "produces no error when tenancy start date is during an active location period" do
@ -177,7 +165,7 @@ RSpec.describe Validations::DateValidations do
record.location = location record.location = location
date_validator.validate_startdate(record) date_validator.validate_startdate(record)
expect(record.errors["startdate"]) expect(record.errors["startdate"])
.to include(match I18n.t("validations.setup.startdate.location.activating_soon", postcode: location.postcode, date: "15 September 2022")) .to include(match I18n.t("validations.setup.startdate.location.activating_soon", postcode: location.postcode, date: "15 September 2022"))
end end
end end
@ -194,7 +182,7 @@ RSpec.describe Validations::DateValidations do
record.scheme = scheme record.scheme = scheme
date_validator.validate_startdate(record) date_validator.validate_startdate(record)
expect(record.errors["startdate"]) expect(record.errors["startdate"])
.to include(match I18n.t("validations.setup.startdate.scheme.reactivating_soon", name: scheme.service_name, date: "4 August 2022")) .to include(match I18n.t("validations.setup.startdate.scheme.reactivating_soon", name: scheme.service_name, date: "4 August 2022"))
end end
it "produces no error when tenancy start date is during an active scheme period" do it "produces no error when tenancy start date is during an active scheme period" do
@ -220,7 +208,7 @@ RSpec.describe Validations::DateValidations do
record.scheme = scheme record.scheme = scheme
date_validator.validate_startdate(record) date_validator.validate_startdate(record)
expect(record.errors["startdate"]) expect(record.errors["startdate"])
.to include(match I18n.t("validations.setup.startdate.scheme.reactivating_soon", name: scheme.service_name, date: "4 September 2022")) .to include(match I18n.t("validations.setup.startdate.scheme.reactivating_soon", name: scheme.service_name, date: "4 September 2022"))
end end
it "produces no error when tenancy start date is during an active scheme period" do it "produces no error when tenancy start date is during an active scheme period" do

2
spec/models/validations/financial_validations_spec.rb

@ -86,7 +86,7 @@ RSpec.describe Validations::FinancialValidations do
end end
context "when outstanding rent or charges is yes" do context "when outstanding rent or charges is yes" do
let(:record) { FactoryBot.create(:lettings_log, :about_completed) } let(:record) { FactoryBot.create(:lettings_log, :about_completed, startdate: Time.zone.now) }
it "expects that a shortfall is provided" do it "expects that a shortfall is provided" do
record.hbrentshortfall = 1 record.hbrentshortfall = 1

20
spec/models/validations/sales/setup_validations_spec.rb

@ -17,7 +17,7 @@ RSpec.describe Validations::Sales::SetupValidations do
end end
end end
context "when saledate is in the 22/23 financial year" do context "when saledate is in the 22/23 collection year" do
let(:record) { build(:sales_log, saledate: Time.zone.local(2023, 1, 1)) } let(:record) { build(:sales_log, saledate: Time.zone.local(2023, 1, 1)) }
it "does not add an error" do it "does not add an error" do
@ -27,23 +27,23 @@ RSpec.describe Validations::Sales::SetupValidations do
end end
end end
context "when saledate is before the 22/23 financial year" do context "when saledate is before the 22/23 collection year" do
let(:record) { build(:sales_log, saledate: Time.zone.local(2020, 1, 1)) } let(:record) { build(:sales_log, saledate: Time.zone.local(2020, 1, 1)) }
it "adds error" do it "adds error" do
setup_validator.validate_saledate(record) setup_validator.validate_saledate(record)
expect(record.errors[:saledate]).to include("Enter a date within the 22/23 financial year, which is between 1st April 2022 and 31st March 2023") expect(record.errors[:saledate]).to include("Enter a date within the 22/23 collection year, which is between 1st April 2022 and 31st March 2023")
end end
end end
context "when saledate is after the 22/23 financial year" do context "when saledate is after the 22/23 collection year" do
let(:record) { build(:sales_log, saledate: Time.zone.local(2025, 4, 1)) } let(:record) { build(:sales_log, saledate: Time.zone.local(2025, 4, 1)) }
it "adds error" do it "adds error" do
setup_validator.validate_saledate(record) setup_validator.validate_saledate(record)
expect(record.errors[:saledate]).to include("Enter a date within the 22/23 financial year, which is between 1st April 2022 and 31st March 2023") expect(record.errors[:saledate]).to include("Enter a date within the 22/23 collection year, which is between 1st April 2022 and 31st March 2023")
end end
end end
end end
@ -67,7 +67,7 @@ RSpec.describe Validations::Sales::SetupValidations do
end end
end end
context "when saledate is in the 22/23 financial year" do context "when saledate is in the 22/23 collection year" do
let(:record) { build(:sales_log, saledate: Time.zone.local(2024, 1, 1)) } let(:record) { build(:sales_log, saledate: Time.zone.local(2024, 1, 1)) }
it "does not add an error" do it "does not add an error" do
@ -77,23 +77,23 @@ RSpec.describe Validations::Sales::SetupValidations do
end end
end end
context "when saledate is before the 22/23 financial year" do context "when saledate is before the 22/23 collection year" do
let(:record) { build(:sales_log, saledate: Time.zone.local(2020, 5, 1)) } let(:record) { build(:sales_log, saledate: Time.zone.local(2020, 5, 1)) }
it "adds error" do it "adds error" do
setup_validator.validate_saledate(record) setup_validator.validate_saledate(record)
expect(record.errors[:saledate]).to include("Enter a date within the 23/24 or 24/25 financial years, which is between 1st April 2023 and 31st March 2025") expect(record.errors[:saledate]).to include("Enter a date within the 23/24 or 24/25 collection years, which is between 1st April 2023 and 31st March 2025")
end end
end end
context "when saledate is after the 22/23 financial year" do context "when saledate is after the 22/23 collection year" do
let(:record) { build(:sales_log, saledate: Time.zone.local(2025, 4, 1)) } let(:record) { build(:sales_log, saledate: Time.zone.local(2025, 4, 1)) }
it "adds error" do it "adds error" do
setup_validator.validate_saledate(record) setup_validator.validate_saledate(record)
expect(record.errors[:saledate]).to include("Enter a date within the 23/24 or 24/25 financial years, which is between 1st April 2023 and 31st March 2025") expect(record.errors[:saledate]).to include("Enter a date within the 23/24 or 24/25 collection years, which is between 1st April 2023 and 31st March 2025")
end end
end end
end end

102
spec/models/validations/setup_validations_spec.rb

@ -6,13 +6,95 @@ RSpec.describe Validations::SetupValidations do
let(:setup_validator_class) { Class.new { include Validations::SetupValidations } } let(:setup_validator_class) { Class.new { include Validations::SetupValidations } }
let(:record) { FactoryBot.create(:lettings_log) } let(:record) { FactoryBot.create(:lettings_log) }
describe "tenancy start date" do
context "when in 22/23 collection" do
context "when in the crossover period" do
before do
allow(Time).to receive(:now).and_return(Time.zone.local(2022, 4, 1))
record.created_at = Time.zone.local(2022, 4, 1)
end
it "cannot be before the first collection window start date" do
record.startdate = Time.zone.local(2021, 1, 1)
setup_validator.validate_startdate_setup(record)
expect(record.errors["startdate"]).to include(match "Enter a date within the 21/22 or 22/23 collection years, which is between 1st April 2021 and 31st March 2023")
end
it "cannot be after the second collection window end date" do
record.startdate = Time.zone.local(2023, 7, 1, 6)
setup_validator.validate_startdate_setup(record)
expect(record.errors["startdate"]).to include(match "Enter a date within the 21/22 or 22/23 collection years, which is between 1st April 2021 and 31st March 2023")
end
end
context "when after the crossover period" do
before do
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 1, 1))
record.created_at = Time.zone.local(2023, 1, 1)
end
it "cannot be before the first collection window start date" do
record.startdate = Time.zone.local(2022, 1, 1)
setup_validator.validate_startdate_setup(record)
expect(record.errors["startdate"]).to include(match "Enter a date within the 22/23 collection year, which is between 1st April 2022 and 31st March 2023")
end
it "cannot be after the second collection window end date" do
record.startdate = Time.zone.local(2023, 7, 1, 6)
setup_validator.validate_startdate_setup(record)
expect(record.errors["startdate"]).to include(match "Enter a date within the 22/23 collection year, which is between 1st April 2022 and 31st March 2023")
end
end
end
context "when in 23/24 collection" do
context "when in the crossover period" do
before do
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 4, 1))
record.created_at = Time.zone.local(2023, 4, 1)
end
it "cannot be before the first collection window start date" do
record.startdate = Time.zone.local(2022, 1, 1)
setup_validator.validate_startdate_setup(record)
expect(record.errors["startdate"]).to include(match "Enter a date within the 22/23 or 23/24 collection years, which is between 1st April 2022 and 31st March 2024")
end
it "cannot be after the second collection window end date" do
record.startdate = Time.zone.local(2024, 7, 1, 6)
setup_validator.validate_startdate_setup(record)
expect(record.errors["startdate"]).to include(match "Enter a date within the 22/23 or 23/24 collection years, which is between 1st April 2022 and 31st March 2024")
end
end
context "when after the crossover period" do
before do
allow(Time).to receive(:now).and_return(Time.zone.local(2024, 1, 1))
record.created_at = Time.zone.local(2024, 1, 1)
end
it "cannot be before the first collection window start date" do
record.startdate = Time.zone.local(2023, 1, 1)
setup_validator.validate_startdate_setup(record)
expect(record.errors["startdate"]).to include(match "Enter a date within the 23/24 collection year, which is between 1st April 2023 and 31st March 2024")
end
it "cannot be after the second collection window end date" do
record.startdate = Time.zone.local(2024, 7, 1, 6)
setup_validator.validate_startdate_setup(record)
expect(record.errors["startdate"]).to include(match "Enter a date within the 23/24 collection year, which is between 1st April 2023 and 31st March 2024")
end
end
end
end
describe "#validate_irproduct" do describe "#validate_irproduct" do
it "adds an error when the intermediate rent product name is not provided but the rent type was given as other intermediate rent product" do it "adds an error when the intermediate rent product name is not provided but the rent type was given as other intermediate rent product" do
record.rent_type = 5 record.rent_type = 5
record.irproduct_other = nil record.irproduct_other = nil
setup_validator.validate_irproduct_other(record) setup_validator.validate_irproduct_other(record)
expect(record.errors["irproduct_other"]) expect(record.errors["irproduct_other"])
.to include(match I18n.t("validations.setup.intermediate_rent_product_name.blank")) .to include(match I18n.t("validations.setup.intermediate_rent_product_name.blank"))
end end
it "adds an error when the intermediate rent product name is blank but the rent type was given as other intermediate rent product" do it "adds an error when the intermediate rent product name is blank but the rent type was given as other intermediate rent product" do
@ -20,7 +102,7 @@ RSpec.describe Validations::SetupValidations do
record.irproduct_other = "" record.irproduct_other = ""
setup_validator.validate_irproduct_other(record) setup_validator.validate_irproduct_other(record)
expect(record.errors["irproduct_other"]) expect(record.errors["irproduct_other"])
.to include(match I18n.t("validations.setup.intermediate_rent_product_name.blank")) .to include(match I18n.t("validations.setup.intermediate_rent_product_name.blank"))
end end
it "Does not add an error when the intermediate rent product name is provided and the rent type was given as other intermediate rent product" do it "Does not add an error when the intermediate rent product name is provided and the rent type was given as other intermediate rent product" do
@ -46,7 +128,7 @@ RSpec.describe Validations::SetupValidations do
record.location = location record.location = location
setup_validator.validate_scheme(record) setup_validator.validate_scheme(record)
expect(record.errors["scheme_id"]) expect(record.errors["scheme_id"])
.to include(match I18n.t("validations.setup.startdate.location.deactivated", postcode: location.postcode, date: "4 June 2022")) .to include(match I18n.t("validations.setup.startdate.location.deactivated", postcode: location.postcode, date: "4 June 2022"))
end end
it "produces no error when tenancy start date is during an active location period" do it "produces no error when tenancy start date is during an active location period" do
@ -71,7 +153,7 @@ RSpec.describe Validations::SetupValidations do
record.location = location record.location = location
setup_validator.validate_scheme(record) setup_validator.validate_scheme(record)
expect(record.errors["scheme_id"]) expect(record.errors["scheme_id"])
.to include(match I18n.t("validations.setup.startdate.location.reactivating_soon", postcode: location.postcode, date: "4 August 2022")) .to include(match I18n.t("validations.setup.startdate.location.reactivating_soon", postcode: location.postcode, date: "4 August 2022"))
end end
it "produces no error when tenancy start date is during an active location period" do it "produces no error when tenancy start date is during an active location period" do
@ -98,7 +180,7 @@ RSpec.describe Validations::SetupValidations do
record.location = location record.location = location
setup_validator.validate_scheme(record) setup_validator.validate_scheme(record)
expect(record.errors["scheme_id"]) expect(record.errors["scheme_id"])
.to include(match I18n.t("validations.setup.startdate.location.activating_soon", postcode: location.postcode, date: "15 September 2022")) .to include(match I18n.t("validations.setup.startdate.location.activating_soon", postcode: location.postcode, date: "15 September 2022"))
end end
end end
@ -115,7 +197,7 @@ RSpec.describe Validations::SetupValidations do
record.scheme = scheme record.scheme = scheme
setup_validator.validate_scheme(record) setup_validator.validate_scheme(record)
expect(record.errors["scheme_id"]) expect(record.errors["scheme_id"])
.to include(match I18n.t("validations.setup.startdate.scheme.reactivating_soon", name: scheme.service_name, date: "4 August 2022")) .to include(match I18n.t("validations.setup.startdate.scheme.reactivating_soon", name: scheme.service_name, date: "4 August 2022"))
end end
it "produces no error when tenancy start date is during an active scheme period" do it "produces no error when tenancy start date is during an active scheme period" do
@ -141,7 +223,7 @@ RSpec.describe Validations::SetupValidations do
record.scheme = scheme record.scheme = scheme
setup_validator.validate_scheme(record) setup_validator.validate_scheme(record)
expect(record.errors["scheme_id"]) expect(record.errors["scheme_id"])
.to include(match I18n.t("validations.setup.startdate.scheme.reactivating_soon", name: scheme.service_name, date: "4 September 2022")) .to include(match I18n.t("validations.setup.startdate.scheme.reactivating_soon", name: scheme.service_name, date: "4 September 2022"))
end end
it "produces no error when tenancy start date is during an active scheme period" do it "produces no error when tenancy start date is during an active scheme period" do
@ -168,7 +250,7 @@ RSpec.describe Validations::SetupValidations do
record.location = location record.location = location
setup_validator.validate_location(record) setup_validator.validate_location(record)
expect(record.errors["location_id"]) expect(record.errors["location_id"])
.to include(match I18n.t("validations.setup.startdate.location.deactivated", postcode: location.postcode, date: "4 June 2022")) .to include(match I18n.t("validations.setup.startdate.location.deactivated", postcode: location.postcode, date: "4 June 2022"))
end end
it "produces no error when tenancy start date is during an active location period" do it "produces no error when tenancy start date is during an active location period" do
@ -193,7 +275,7 @@ RSpec.describe Validations::SetupValidations do
record.location = location record.location = location
setup_validator.validate_location(record) setup_validator.validate_location(record)
expect(record.errors["location_id"]) expect(record.errors["location_id"])
.to include(match I18n.t("validations.setup.startdate.location.reactivating_soon", postcode: location.postcode, date: "4 August 2022")) .to include(match I18n.t("validations.setup.startdate.location.reactivating_soon", postcode: location.postcode, date: "4 August 2022"))
end end
it "produces no error when tenancy start date is during an active location period" do it "produces no error when tenancy start date is during an active location period" do
@ -220,7 +302,7 @@ RSpec.describe Validations::SetupValidations do
record.location = location record.location = location
setup_validator.validate_location(record) setup_validator.validate_location(record)
expect(record.errors["location_id"]) expect(record.errors["location_id"])
.to include(match I18n.t("validations.setup.startdate.location.activating_soon", postcode: location.postcode, date: "15 September 2022")) .to include(match I18n.t("validations.setup.startdate.location.activating_soon", postcode: location.postcode, date: "15 September 2022"))
end end
end end
end end

16
spec/models/validations/soft_validations_spec.rb

@ -207,6 +207,14 @@ RSpec.describe Validations::SoftValidations do
end end
describe "major repairs date soft validations" do describe "major repairs date soft validations" do
before do
Timecop.freeze(Time.zone.local(2022, 2, 1))
end
after do
Timecop.unfreeze
end
context "when the major repairs date is within 10 years of the tenancy start date" do context "when the major repairs date is within 10 years of the tenancy start date" do
it "shows the interruption screen" do it "shows the interruption screen" do
record.update!(startdate: Time.zone.local(2022, 2, 1), mrcdate: Time.zone.local(2013, 2, 1)) record.update!(startdate: Time.zone.local(2022, 2, 1), mrcdate: Time.zone.local(2013, 2, 1))
@ -223,6 +231,14 @@ RSpec.describe Validations::SoftValidations do
end end
describe "void date soft validations" do describe "void date soft validations" do
before do
Timecop.freeze(Time.zone.local(2022, 2, 1))
end
after do
Timecop.unfreeze
end
context "when the void date is within 10 years of the tenancy start date" do context "when the void date is within 10 years of the tenancy start date" do
it "shows the interruption screen" do it "shows the interruption screen" do
record.update!(startdate: Time.zone.local(2022, 2, 1), voiddate: Time.zone.local(2013, 2, 1)) record.update!(startdate: Time.zone.local(2022, 2, 1), voiddate: Time.zone.local(2013, 2, 1))

20
spec/models/validations/tenancy_validations_spec.rb

@ -3,6 +3,10 @@ require "rails_helper"
RSpec.describe Validations::TenancyValidations do RSpec.describe Validations::TenancyValidations do
subject(:tenancy_validator) { validator_class.new } subject(:tenancy_validator) { validator_class.new }
before do
Timecop.freeze(Time.zone.local(2021, 5, 1))
end
let(:validator_class) { Class.new { include Validations::TenancyValidations } } let(:validator_class) { Class.new { include Validations::TenancyValidations } }
let(:record) { FactoryBot.create(:lettings_log, startdate: Time.zone.local(2021, 5, 1), needstype: 1, rent_type: 1) } let(:record) { FactoryBot.create(:lettings_log, startdate: Time.zone.local(2021, 5, 1), needstype: 1, rent_type: 1) }
@ -117,6 +121,14 @@ RSpec.describe Validations::TenancyValidations do
end end
context "when the collection start year is 2022 or later" do context "when the collection start year is 2022 or later" do
before do
Timecop.freeze(2022, 5, 1)
end
after do
Timecop.unfreeze
end
let(:record) { FactoryBot.create(:lettings_log, startdate: Time.zone.local(2022, 5, 1), needstype: 1, rent_type: 1) } let(:record) { FactoryBot.create(:lettings_log, startdate: Time.zone.local(2022, 5, 1), needstype: 1, rent_type: 1) }
context "when type of tenancy is Secure - fixed term" do context "when type of tenancy is Secure - fixed term" do
@ -260,6 +272,14 @@ RSpec.describe Validations::TenancyValidations do
describe "joint tenancy validation" do describe "joint tenancy validation" do
context "when the data inputter has said that there is only one member in the household" do context "when the data inputter has said that there is only one member in the household" do
before do
Timecop.freeze(2022, 5, 1)
end
after do
Timecop.unfreeze
end
let(:record) { FactoryBot.create(:lettings_log, startdate: Time.zone.local(2022, 5, 1)) } let(:record) { FactoryBot.create(:lettings_log, startdate: Time.zone.local(2022, 5, 1)) }
let(:expected_error) { I18n.t("validations.tenancy.not_joint") } let(:expected_error) { I18n.t("validations.tenancy.not_joint") }
let(:hhmemb_expected_error) { I18n.t("validations.tenancy.joint_more_than_one_member") } let(:hhmemb_expected_error) { I18n.t("validations.tenancy.joint_more_than_one_member") }

16
spec/requests/form_controller_spec.rb

@ -17,7 +17,6 @@ RSpec.describe FormController, type: :request do
:lettings_log, :lettings_log,
:about_completed, :about_completed,
status: 1, status: 1,
startdate: Time.zone.local(2021, 10, 10),
created_by: user, created_by: user,
) )
end end
@ -26,7 +25,6 @@ RSpec.describe FormController, type: :request do
:lettings_log, :lettings_log,
:completed, :completed,
created_by: user, created_by: user,
startdate: Time.zone.local(2021, 5, 1),
) )
end end
let(:headers) { { "Accept" => "text/html" } } let(:headers) { { "Accept" => "text/html" } }
@ -204,10 +202,13 @@ RSpec.describe FormController, type: :request do
describe "GET" do describe "GET" do
context "with form pages" do context "with form pages" do
context "when forms exist for multiple years" do context "when forms exist for multiple years" do
let(:lettings_log_year_1) { create(:lettings_log, startdate: Time.zone.local(2021, 5, 1), owning_organisation: organisation, created_by: user) } let(:lettings_log_year_1) { create(:lettings_log, owning_organisation: organisation, created_by: user) }
let(:lettings_log_year_2) { create(:lettings_log, :about_completed, startdate: Time.zone.local(2022, 5, 1), owning_organisation: organisation, created_by: user) } let(:lettings_log_year_2) { create(:lettings_log, :about_completed, startdate: Time.zone.local(2022, 5, 1), owning_organisation: organisation, created_by: user) }
before do before do
Timecop.freeze(Time.zone.local(2021, 5, 1))
lettings_log_year_1.update!(startdate: Time.zone.local(2021, 5, 1))
Timecop.unfreeze
allow(lettings_log_year_1.form).to receive(:end_date).and_return(Time.zone.today + 1.day) allow(lettings_log_year_1.form).to receive(:end_date).and_return(Time.zone.today + 1.day)
end end
@ -663,6 +664,15 @@ RSpec.describe FormController, type: :request do
end end
let(:referrer) { "/lettings-logs/#{completed_lettings_log.id}/net-income-value-check?referrer=check_answers" } let(:referrer) { "/lettings-logs/#{completed_lettings_log.id}/net-income-value-check?referrer=check_answers" }
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
before do before do
completed_lettings_log.update!(ecstat1: 1, earnings: 130, hhmemb: 1) # we're not routing to that page, so it gets cleared? completed_lettings_log.update!(ecstat1: 1, earnings: 130, hhmemb: 1) # we're not routing to that page, so it gets cleared?
allow(completed_lettings_log).to receive(:net_income_soft_validation_triggered?).and_return(true) allow(completed_lettings_log).to receive(:net_income_soft_validation_triggered?).and_return(true)

44
spec/requests/lettings_logs_controller_spec.rb

@ -333,6 +333,13 @@ RSpec.describe LettingsLogsController, type: :request do
end end
context "with year filter" do context "with year filter" do
around do |example|
Timecop.freeze(2022, 3, 1) do
example.run
end
Timecop.unfreeze
end
let!(:lettings_log_2021) do let!(:lettings_log_2021) do
FactoryBot.create(:lettings_log, :in_progress, FactoryBot.create(:lettings_log, :in_progress,
created_by: user, created_by: user,
@ -364,6 +371,8 @@ RSpec.describe LettingsLogsController, type: :request do
context "with year and status filter" do context "with year and status filter" do
before do before do
Timecop.freeze(Time.zone.local(2022, 3, 1))
lettings_log_2021.update!(startdate: Time.zone.local(2022, 3, 1))
Timecop.freeze(Time.zone.local(2022, 12, 1)) Timecop.freeze(Time.zone.local(2022, 12, 1))
end end
@ -374,7 +383,6 @@ RSpec.describe LettingsLogsController, type: :request do
let!(:lettings_log_2021) do let!(:lettings_log_2021) do
FactoryBot.create(:lettings_log, :in_progress, FactoryBot.create(:lettings_log, :in_progress,
owning_organisation: organisation, owning_organisation: organisation,
startdate: Time.zone.local(2022, 3, 1),
managing_organisation: organisation, managing_organisation: organisation,
created_by: user) created_by: user)
end end
@ -383,6 +391,7 @@ RSpec.describe LettingsLogsController, type: :request do
owning_organisation: organisation, owning_organisation: organisation,
mrcdate: Time.zone.local(2022, 2, 1), mrcdate: Time.zone.local(2022, 2, 1),
startdate: Time.zone.local(2022, 12, 1), startdate: Time.zone.local(2022, 12, 1),
voiddate: Time.zone.local(2022, 2, 1),
tenancy: 6, tenancy: 6,
managing_organisation: organisation, managing_organisation: organisation,
created_by: user) created_by: user)
@ -846,6 +855,10 @@ RSpec.describe LettingsLogsController, type: :request do
before do before do
sign_in user sign_in user
get "/lettings-logs/#{lettings_log.id}", headers:, params: {} get "/lettings-logs/#{lettings_log.id}", headers:, params: {}
Timecop.freeze(2021, 4, 1)
completed_lettings_log.update!(startdate: Time.zone.local(2021, 4, 1), voiddate: Time.zone.local(2021, 4, 1), mrcdate: Time.zone.local(2021, 4, 1))
completed_lettings_log.reload
Timecop.unfreeze
end end
it "shows the tasklist for lettings logs you have access to" do it "shows the tasklist for lettings logs you have access to" do
@ -871,9 +884,6 @@ RSpec.describe LettingsLogsController, type: :request do
end end
it "displays a closed collection window message for previous collection year logs" do it "displays a closed collection window message for previous collection year logs" do
completed_lettings_log.update!(startdate: Time.zone.local(2021, 4, 1))
completed_lettings_log.reload
get "/lettings-logs/#{completed_lettings_log.id}", headers:, params: {} get "/lettings-logs/#{completed_lettings_log.id}", headers:, params: {}
expect(completed_lettings_log.form.end_date).to eq(Time.zone.local(2022, 7, 1)) expect(completed_lettings_log.form.end_date).to eq(Time.zone.local(2022, 7, 1))
expect(completed_lettings_log.status).to eq("completed") expect(completed_lettings_log.status).to eq("completed")
@ -940,19 +950,22 @@ RSpec.describe LettingsLogsController, type: :request do
end end
context "when accessing the check answers page" do context "when accessing the check answers page" do
before do
Timecop.freeze(2021, 4, 1)
completed_lettings_log.update!(startdate: Time.zone.local(2021, 4, 1), voiddate: Time.zone.local(2021, 4, 1), mrcdate: Time.zone.local(2021, 4, 1))
Timecop.unfreeze
stub_request(:get, /api.postcodes.io/)
.to_return(status: 200, body: "{\"status\":200,\"result\":{\"admin_district\":\"Manchester\", \"codes\":{\"admin_district\": \"E08000003\"}}}", headers: {})
sign_in user
end
let(:postcode_lettings_log) do let(:postcode_lettings_log) do
FactoryBot.create(:lettings_log, FactoryBot.create(:lettings_log,
created_by: user, created_by: user,
postcode_known: "No") postcode_known: "No")
end end
let(:id) { postcode_lettings_log.id } let(:id) { postcode_lettings_log.id }
let(:completed_lettings_log) { FactoryBot.create(:lettings_log, :completed, owning_organisation: user.organisation, managing_organisation: user.organisation, created_by: user, startdate: Time.zone.local(2021, 4, 1)) } let(:completed_lettings_log) { FactoryBot.create(:lettings_log, :completed, owning_organisation: user.organisation, managing_organisation: user.organisation, created_by: user) }
before do
stub_request(:get, /api.postcodes.io/)
.to_return(status: 200, body: "{\"status\":200,\"result\":{\"admin_district\":\"Manchester\", \"codes\":{\"admin_district\": \"E08000003\"}}}", headers: {})
sign_in user
end
it "shows the inferred la" do it "shows the inferred la" do
lettings_log = FactoryBot.create(:lettings_log, lettings_log = FactoryBot.create(:lettings_log,
@ -1154,6 +1167,15 @@ RSpec.describe LettingsLogsController, type: :request do
end end
context "with an invalid lettings log params" do context "with an invalid lettings log params" do
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
let(:params) { { age1: 200 } } let(:params) { { age1: 200 } }
it "returns 422" do it "returns 422" do

9
spec/requests/sales_logs_controller_spec.rb

@ -231,11 +231,10 @@ RSpec.describe SalesLogsController, type: :request do
end end
context "with year and status filter" do context "with year and status filter" do
before do around do |example|
Timecop.freeze(Time.zone.local(2022, 12, 1)) Timecop.freeze(2022, 12, 1) do
end example.run
end
after do
Timecop.unfreeze Timecop.unfreeze
end end

2
spec/services/csv/lettings_log_csv_service_spec.rb

@ -6,7 +6,7 @@ RSpec.describe Csv::LettingsLogCsvService do
let(:real_2021_2022_form) { Form.new("config/forms/2021_2022.json") } let(:real_2021_2022_form) { Form.new("config/forms/2021_2022.json") }
before do before do
LettingsLog.create!(startdate: "2021-10-10", created_at: Time.utc(2022, 2, 8, 16, 52, 15)) LettingsLog.create!(startdate: Time.zone.today, created_at: Time.utc(2022, 2, 8, 16, 52, 15))
allow(FormHandler.instance).to receive(:get_form).and_return(real_2021_2022_form) allow(FormHandler.instance).to receive(:get_form).and_return(real_2021_2022_form)
end end

8
spec/services/exports/lettings_log_export_service_spec.rb

@ -59,7 +59,7 @@ RSpec.describe Exports::LettingsLogExportService do
end end
context "and one lettings log is available for export" do context "and one lettings log is available for export" do
let!(:lettings_log) { FactoryBot.create(:lettings_log, :completed, propcode: "123", ppostcode_full: "SE2 6RT", postcode_full: "NW1 5TY", tenancycode: "BZ737", startdate: Time.utc(2022, 2, 2, 10, 36, 49), tenancylength: 5, underoccupation_benefitcap: 4) } let!(:lettings_log) { FactoryBot.create(:lettings_log, :completed, propcode: "123", ppostcode_full: "SE2 6RT", postcode_full: "NW1 5TY", tenancycode: "BZ737", startdate: Time.zone.local(2022, 2, 2, 10, 36, 49), voiddate: Time.zone.local(2019, 11, 3), mrcdate: Time.zone.local(2020, 5, 5, 10, 36, 49), tenancylength: 5, underoccupation_benefitcap: 4) }
it "generates a ZIP export file with the expected filename" do it "generates a ZIP export file with the expected filename" do
expect(storage_service).to receive(:write_file).with(expected_zip_filename, any_args) expect(storage_service).to receive(:write_file).with(expected_zip_filename, any_args)
@ -161,7 +161,7 @@ RSpec.describe Exports::LettingsLogExportService do
context "when this is a second export (partial)" do context "when this is a second export (partial)" do
before do before do
start_time = Time.zone.local(2022, 4, 1) start_time = Time.zone.local(2022, 6, 1)
LogsExport.new(started_at: start_time).save! LogsExport.new(started_at: start_time).save!
end end
@ -237,7 +237,7 @@ RSpec.describe Exports::LettingsLogExportService do
let(:csv_export_file) { File.open("spec/fixtures/exports/general_needs_log.csv", "r:UTF-8") } let(:csv_export_file) { File.open("spec/fixtures/exports/general_needs_log.csv", "r:UTF-8") }
let(:expected_csv_filename) { "export_2022_05_01.csv" } let(:expected_csv_filename) { "export_2022_05_01.csv" }
let(:lettings_log) { FactoryBot.create(:lettings_log, :completed, propcode: "123", ppostcode_full: "SE2 6RT", postcode_full: "NW1 5TY", tenancycode: "BZ737", startdate: Time.utc(2022, 2, 2, 10, 36, 49), tenancylength: 5, underoccupation_benefitcap: 4) } let(:lettings_log) { FactoryBot.create(:lettings_log, :completed, propcode: "123", ppostcode_full: "SE2 6RT", postcode_full: "NW1 5TY", tenancycode: "BZ737", startdate: Time.zone.local(2022, 2, 2, 10, 36, 49), voiddate: Time.zone.local(2019, 11, 3), mrcdate: Time.zone.local(2020, 5, 5, 10, 36, 49), tenancylength: 5, underoccupation_benefitcap: 4) }
it "generates an CSV export file with the expected content" do it "generates an CSV export file with the expected content" do
expected_content = replace_entity_ids(lettings_log, csv_export_file.read) expected_content = replace_entity_ids(lettings_log, csv_export_file.read)
@ -256,7 +256,7 @@ RSpec.describe Exports::LettingsLogExportService do
let(:scheme) { FactoryBot.create(:scheme, :export, owning_organisation: organisation) } let(:scheme) { FactoryBot.create(:scheme, :export, owning_organisation: organisation) }
let(:location) { FactoryBot.create(:location, :export, scheme:, startdate: Time.zone.local(2021, 4, 1)) } let(:location) { FactoryBot.create(:location, :export, scheme:, startdate: Time.zone.local(2021, 4, 1)) }
let(:lettings_log) { FactoryBot.create(:lettings_log, :completed, :export, :sh, scheme:, location:, created_by: user, owning_organisation: organisation, startdate: Time.utc(2022, 2, 2, 10, 36, 49), underoccupation_benefitcap: 4, sheltered: 1) } let(:lettings_log) { FactoryBot.create(:lettings_log, :completed, :export, :sh, scheme:, location:, created_by: user, owning_organisation: organisation, startdate: Time.zone.local(2022, 2, 2, 10, 36, 49), voiddate: Time.zone.local(2019, 11, 3), mrcdate: Time.zone.local(2020, 5, 5, 10, 36, 49), underoccupation_benefitcap: 4, sheltered: 1) }
before do before do
FactoryBot.create(:location, scheme:, startdate: Time.zone.local(2021, 4, 1), units: nil) FactoryBot.create(:location, scheme:, startdate: Time.zone.local(2021, 4, 1), units: nil)

11
spec/services/imports/lettings_logs_field_import_service_spec.rb

@ -16,6 +16,15 @@ RSpec.describe Imports::LettingsLogsFieldImportService do
let(:old_user_id) { "c3061a2e6ea0b702e6f6210d5c52d2a92612d2aa" } let(:old_user_id) { "c3061a2e6ea0b702e6f6210d5c52d2a92612d2aa" }
let(:organisation) { FactoryBot.create(:organisation, old_visible_id: "1", provider_type: "PRP") } let(:organisation) { FactoryBot.create(:organisation, old_visible_id: "1", provider_type: "PRP") }
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
def open_file(directory, filename) def open_file(directory, filename)
File.open("#{directory}/#{filename}.xml") File.open("#{directory}/#{filename}.xml")
end end
@ -27,7 +36,7 @@ RSpec.describe Imports::LettingsLogsFieldImportService do
FactoryBot.create(:user, old_user_id:, organisation:) FactoryBot.create(:user, old_user_id:, organisation:)
# Stub the form handler to use the real form # Stub the form handler to use the real form
allow(FormHandler.instance).to receive(:get_form).with("previous_lettings").and_return(real_2021_2022_form) allow(FormHandler.instance).to receive(:get_form).with("current_lettings").and_return(real_2021_2022_form)
WebMock.stub_request(:get, /api.postcodes.io\/postcodes\/LS166FT/) WebMock.stub_request(:get, /api.postcodes.io\/postcodes\/LS166FT/)
.to_return(status: 200, body: '{"status":200,"result":{"codes":{"admin_district":"E08000035"}}}', headers: {}) .to_return(status: 200, body: '{"status":200,"result":{"codes":{"admin_district":"E08000035"}}}', headers: {})

733
spec/services/imports/lettings_logs_import_service_spec.rb

@ -1,348 +1,333 @@
require "rails_helper" require "rails_helper"
RSpec.describe Imports::LettingsLogsImportService do RSpec.describe Imports::LettingsLogsImportService do
subject(:lettings_log_service) { described_class.new(storage_service, logger) } context "with 21/22 logs" do
subject(:lettings_log_service) { described_class.new(storage_service, logger) }
let(:storage_service) { instance_double(Storage::S3Service) } around do |example|
let(:logger) { instance_double(ActiveSupport::Logger) } Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
let(:real_2021_2022_form) { Form.new("config/forms/2021_2022.json") } example.run
let(:real_2022_2023_form) { Form.new("config/forms/2022_2023.json") } end
let(:fixture_directory) { "spec/fixtures/imports/logs" } Timecop.return
Singleton.__init__(FormHandler)
let(:organisation) { FactoryBot.create(:organisation, old_visible_id: "1", provider_type: "PRP") } end
let(:managing_organisation) { FactoryBot.create(:organisation, old_visible_id: "2", provider_type: "PRP") }
let(:scheme1) { FactoryBot.create(:scheme, old_visible_id: "0123", owning_organisation: organisation) }
let(:scheme2) { FactoryBot.create(:scheme, old_visible_id: "456", owning_organisation: organisation) }
def open_file(directory, filename)
File.open("#{directory}/#{filename}.xml")
end
before do
WebMock.stub_request(:get, /api.postcodes.io\/postcodes\/LS166FT/)
.to_return(status: 200, body: '{"status":200,"result":{"admin_district":"Westminster","codes":{"admin_district":"E08000035"}}}', headers: {})
allow(Organisation).to receive(:find_by).and_return(nil)
allow(Organisation).to receive(:find_by).with(old_visible_id: organisation.old_visible_id).and_return(organisation)
allow(Organisation).to receive(:find_by).with(old_visible_id: managing_organisation.old_visible_id).and_return(managing_organisation)
# Created by users
FactoryBot.create(:user, old_user_id: "c3061a2e6ea0b702e6f6210d5c52d2a92612d2aa", organisation:)
FactoryBot.create(:user, old_user_id: "e29c492473446dca4d50224f2bb7cf965a261d6f", organisation:)
# Location setup
FactoryBot.create(:location, old_visible_id: "10", postcode: "LS166FT", scheme_id: scheme1.id, mobility_type: "W", startdate: Time.zone.local(2021, 4, 1))
FactoryBot.create(:location, scheme_id: scheme1.id, startdate: Time.zone.local(2021, 4, 1))
FactoryBot.create(:location, old_visible_id: "10", postcode: "LS166FT", scheme_id: scheme2.id, mobility_type: "W", startdate: Time.zone.local(2021, 4, 1))
# Stub the form handler to use the real form
allow(FormHandler.instance).to receive(:get_form).with("previous_lettings").and_return(real_2021_2022_form)
allow(FormHandler.instance).to receive(:get_form).with("current_lettings").and_return(real_2022_2023_form)
end
context "when importing lettings logs" do let(:storage_service) { instance_double(Storage::S3Service) }
let(:remote_folder) { "lettings_logs" } let(:logger) { instance_double(ActiveSupport::Logger) }
let(:lettings_log_id) { "0ead17cb-1668-442d-898c-0d52879ff592" }
let(:lettings_log_id2) { "166fc004-392e-47a8-acb8-1c018734882b" }
let(:lettings_log_id3) { "00d2343e-d5fa-4c89-8400-ec3854b0f2b4" }
let(:lettings_log_id4) { "0b4a68df-30cc-474a-93c0-a56ce8fdad3b" }
let(:sales_log) { "shared_ownership_sales_log" }
before do let(:real_2021_2022_form) { Form.new("config/forms/2021_2022.json") }
# Stub the S3 file listing and download let(:real_2022_2023_form) { Form.new("config/forms/2022_2023.json") }
allow(storage_service).to receive(:list_files) let(:fixture_directory) { "spec/fixtures/imports/logs" }
.and_return(%W[#{remote_folder}/#{lettings_log_id}.xml #{remote_folder}/#{lettings_log_id2}.xml #{remote_folder}/#{lettings_log_id3}.xml #{remote_folder}/#{lettings_log_id4}.xml #{remote_folder}/#{sales_log}.xml])
allow(storage_service).to receive(:get_file_io)
.with("#{remote_folder}/#{lettings_log_id}.xml")
.and_return(open_file(fixture_directory, lettings_log_id), open_file(fixture_directory, lettings_log_id))
allow(storage_service).to receive(:get_file_io)
.with("#{remote_folder}/#{lettings_log_id2}.xml")
.and_return(open_file(fixture_directory, lettings_log_id2), open_file(fixture_directory, lettings_log_id2))
allow(storage_service).to receive(:get_file_io)
.with("#{remote_folder}/#{lettings_log_id3}.xml")
.and_return(open_file(fixture_directory, lettings_log_id3), open_file(fixture_directory, lettings_log_id3))
allow(storage_service).to receive(:get_file_io)
.with("#{remote_folder}/#{lettings_log_id4}.xml")
.and_return(open_file(fixture_directory, lettings_log_id4), open_file(fixture_directory, lettings_log_id4))
allow(storage_service).to receive(:get_file_io)
.with("#{remote_folder}/#{sales_log}.xml")
.and_return(open_file(fixture_directory, sales_log), open_file(fixture_directory, sales_log))
end
it "successfully create all lettings logs" do let(:organisation) { FactoryBot.create(:organisation, old_visible_id: "1", provider_type: "PRP") }
expect(logger).not_to receive(:error) let(:managing_organisation) { FactoryBot.create(:organisation, old_visible_id: "2", provider_type: "PRP") }
expect(logger).not_to receive(:warn) let(:scheme1) { FactoryBot.create(:scheme, old_visible_id: "0123", owning_organisation: organisation) }
expect(logger).not_to receive(:info) let(:scheme2) { FactoryBot.create(:scheme, old_visible_id: "456", owning_organisation: organisation) }
expect { lettings_log_service.create_logs(remote_folder) }
.to change(LettingsLog, :count).by(4)
end
it "only updates existing lettings logs" do def open_file(directory, filename)
expect(logger).not_to receive(:error) File.open("#{directory}/#{filename}.xml")
expect(logger).not_to receive(:warn)
expect(logger).to receive(:info).with(/Updating lettings log/).exactly(4).times
expect { 2.times { lettings_log_service.create_logs(remote_folder) } }
.to change(LettingsLog, :count).by(4)
end end
it "creates organisation relationship once" do before do
expect(logger).not_to receive(:error) WebMock.stub_request(:get, /api.postcodes.io\/postcodes\/LS166FT/)
expect(logger).not_to receive(:warn) .to_return(status: 200, body: '{"status":200,"result":{"admin_district":"Westminster","codes":{"admin_district":"E08000035"}}}', headers: {})
expect { lettings_log_service.create_logs(remote_folder) }
.to change(OrganisationRelationship, :count).by(1) allow(Organisation).to receive(:find_by).and_return(nil)
allow(Organisation).to receive(:find_by).with(old_visible_id: organisation.old_visible_id).and_return(organisation)
allow(Organisation).to receive(:find_by).with(old_visible_id: managing_organisation.old_visible_id).and_return(managing_organisation)
# Created by users
FactoryBot.create(:user, old_user_id: "c3061a2e6ea0b702e6f6210d5c52d2a92612d2aa", organisation:)
FactoryBot.create(:user, old_user_id: "e29c492473446dca4d50224f2bb7cf965a261d6f", organisation:)
# Location setup
FactoryBot.create(:location, old_visible_id: "10", postcode: "LS166FT", scheme_id: scheme1.id, mobility_type: "W", startdate: Time.zone.local(2021, 4, 1))
FactoryBot.create(:location, scheme_id: scheme1.id, startdate: Time.zone.local(2021, 4, 1))
FactoryBot.create(:location, old_visible_id: "10", postcode: "LS166FT", scheme_id: scheme2.id, mobility_type: "W", startdate: Time.zone.local(2021, 4, 1))
# Stub the form handler to use the real form
allow(FormHandler.instance).to receive(:get_form).with("current_lettings").and_return(real_2021_2022_form)
allow(FormHandler.instance).to receive(:get_form).with("previous_lettings").and_return(real_2021_2022_form)
allow(FormHandler.instance).to receive(:get_form).with("next_lettings").and_return(real_2022_2023_form)
end end
context "when there are status discrepancies" do context "when importing lettings logs" do
let(:lettings_log_id5) { "893ufj2s-lq77-42m4-rty6-ej09gh585uy1" } let(:remote_folder) { "lettings_logs" }
let(:lettings_log_id6) { "5ybz29dj-l33t-k1l0-hj86-n4k4ma77xkcd" } let(:lettings_log_id) { "0ead17cb-1668-442d-898c-0d52879ff592" }
let(:lettings_log_file) { open_file(fixture_directory, lettings_log_id5) } let(:lettings_log_id2) { "166fc004-392e-47a8-acb8-1c018734882b" }
let(:lettings_log_xml) { Nokogiri::XML(lettings_log_file) } let(:lettings_log_id3) { "0b4a68df-30cc-474a-93c0-a56ce8fdad3b" }
let(:sales_log) { "shared_ownership_sales_log" }
before do before do
# Stub the S3 file listing and download
allow(storage_service).to receive(:list_files)
.and_return(%W[#{remote_folder}/#{lettings_log_id}.xml #{remote_folder}/#{lettings_log_id2}.xml #{remote_folder}/#{lettings_log_id3}.xml #{remote_folder}/#{sales_log}.xml])
allow(storage_service).to receive(:get_file_io) allow(storage_service).to receive(:get_file_io)
.with("#{remote_folder}/#{lettings_log_id5}.xml") .with("#{remote_folder}/#{lettings_log_id}.xml")
.and_return(open_file(fixture_directory, lettings_log_id5), open_file(fixture_directory, lettings_log_id5)) .and_return(open_file(fixture_directory, lettings_log_id), open_file(fixture_directory, lettings_log_id))
allow(storage_service).to receive(:get_file_io) allow(storage_service).to receive(:get_file_io)
.with("#{remote_folder}/#{lettings_log_id6}.xml") .with("#{remote_folder}/#{lettings_log_id2}.xml")
.and_return(open_file(fixture_directory, lettings_log_id6), open_file(fixture_directory, lettings_log_id6)) .and_return(open_file(fixture_directory, lettings_log_id2), open_file(fixture_directory, lettings_log_id2))
allow(storage_service).to receive(:get_file_io)
.with("#{remote_folder}/#{lettings_log_id3}.xml")
.and_return(open_file(fixture_directory, lettings_log_id3), open_file(fixture_directory, lettings_log_id3))
allow(storage_service).to receive(:get_file_io)
.with("#{remote_folder}/#{sales_log}.xml")
.and_return(open_file(fixture_directory, sales_log), open_file(fixture_directory, sales_log))
end end
it "the logger logs a warning with the lettings log's old id/filename" do it "successfully create all lettings logs" do
expect(logger).to receive(:warn).with(/is not completed/).once expect(logger).not_to receive(:error)
expect(logger).to receive(:warn).with(/lettings log with old id:#{lettings_log_id5} is incomplete but status should be complete/).once expect(logger).not_to receive(:warn)
expect(logger).not_to receive(:info)
lettings_log_service.send(:create_log, lettings_log_xml) expect { lettings_log_service.create_logs(remote_folder) }
.to change(LettingsLog, :count).by(3)
end end
it "on completion the ids of all logs with status discrepancies are logged in a warning" do it "only updates existing lettings logs" do
allow(storage_service).to receive(:list_files) expect(logger).not_to receive(:error)
.and_return(%W[#{remote_folder}/#{lettings_log_id5}.xml #{remote_folder}/#{lettings_log_id6}.xml]) expect(logger).not_to receive(:warn)
expect(logger).to receive(:warn).with(/is not completed/).twice expect(logger).to receive(:info).with(/Updating lettings log/).exactly(3).times
expect(logger).to receive(:warn).with(/is incomplete but status should be complete/).twice expect { 2.times { lettings_log_service.create_logs(remote_folder) } }
expect(logger).to receive(:warn).with(/The following lettings logs had status discrepancies: \[893ufj2s-lq77-42m4-rty6-ej09gh585uy1, 5ybz29dj-l33t-k1l0-hj86-n4k4ma77xkcd\]/) .to change(LettingsLog, :count).by(3)
lettings_log_service.create_logs(remote_folder)
end end
end
end
context "when importing a specific log" do it "creates organisation relationship once" do
let(:lettings_log_id) { "0ead17cb-1668-442d-898c-0d52879ff592" } expect(logger).not_to receive(:error)
let(:lettings_log_file) { open_file(fixture_directory, lettings_log_id) } expect(logger).not_to receive(:warn)
let(:lettings_log_xml) { Nokogiri::XML(lettings_log_file) } expect { lettings_log_service.create_logs(remote_folder) }
.to change(OrganisationRelationship, :count).by(1)
end
context "and the void date is after the start date" do context "when there are status discrepancies" do
before { lettings_log_xml.at_xpath("//xmlns:VYEAR").content = 2023 } let(:lettings_log_id5) { "893ufj2s-lq77-42m4-rty6-ej09gh585uy1" }
let(:lettings_log_id6) { "5ybz29dj-l33t-k1l0-hj86-n4k4ma77xkcd" }
let(:lettings_log_file) { open_file(fixture_directory, lettings_log_id5) }
let(:lettings_log_xml) { Nokogiri::XML(lettings_log_file) }
it "does not import the voiddate" do before do
expect(logger).to receive(:warn).with(/is not completed/) allow(storage_service).to receive(:get_file_io)
expect(logger).to receive(:warn).with(/lettings log with old id:#{lettings_log_id} is incomplete but status should be complete/) .with("#{remote_folder}/#{lettings_log_id5}.xml")
.and_return(open_file(fixture_directory, lettings_log_id5), open_file(fixture_directory, lettings_log_id5))
allow(storage_service).to receive(:get_file_io)
.with("#{remote_folder}/#{lettings_log_id6}.xml")
.and_return(open_file(fixture_directory, lettings_log_id6), open_file(fixture_directory, lettings_log_id6))
end
lettings_log_service.send(:create_log, lettings_log_xml) it "the logger logs a warning with the lettings log's old id/filename" do
expect(logger).to receive(:warn).with(/is not completed/).once
expect(logger).to receive(:warn).with(/lettings log with old id:#{lettings_log_id5} is incomplete but status should be complete/).once
lettings_log = LettingsLog.where(old_id: lettings_log_id).first lettings_log_service.send(:create_log, lettings_log_xml)
expect(lettings_log&.voiddate).to be_nil end
end
end
context "and the organisation legacy ID does not exist" do it "on completion the ids of all logs with status discrepancies are logged in a warning" do
before { lettings_log_xml.at_xpath("//xmlns:OWNINGORGID").content = 99_999 } allow(storage_service).to receive(:list_files)
.and_return(%W[#{remote_folder}/#{lettings_log_id5}.xml #{remote_folder}/#{lettings_log_id6}.xml])
expect(logger).to receive(:warn).with(/is not completed/).twice
expect(logger).to receive(:warn).with(/is incomplete but status should be complete/).twice
expect(logger).to receive(:warn).with(/The following lettings logs had status discrepancies: \[893ufj2s-lq77-42m4-rty6-ej09gh585uy1, 5ybz29dj-l33t-k1l0-hj86-n4k4ma77xkcd\]/)
it "raises an exception" do lettings_log_service.create_logs(remote_folder)
expect { lettings_log_service.send(:create_log, lettings_log_xml) } end
.to raise_error(RuntimeError, "Organisation not found with legacy ID 99999")
end end
end end
context "and a person is under 16" do context "when importing a specific log" do
before { lettings_log_xml.at_xpath("//xmlns:P2Age").content = 14 } let(:lettings_log_id) { "0ead17cb-1668-442d-898c-0d52879ff592" }
let(:lettings_log_file) { open_file(fixture_directory, lettings_log_id) }
let(:lettings_log_xml) { Nokogiri::XML(lettings_log_file) }
context "and the void date is after the start date" do
before { lettings_log_xml.at_xpath("//xmlns:VYEAR").content = 2023 }
context "when the economic status is set to refuse" do it "does not import the voiddate" do
before { lettings_log_xml.at_xpath("//xmlns:P2Eco").content = "10) Refused" } expect(logger).to receive(:warn).with(/is not completed/)
expect(logger).to receive(:warn).with(/lettings log with old id:#{lettings_log_id} is incomplete but status should be complete/)
it "sets the economic status to child under 16" do
# The update is done when calculating derived variables
expect(logger).to receive(:warn).with(/Differences found when saving log/)
lettings_log_service.send(:create_log, lettings_log_xml) lettings_log_service.send(:create_log, lettings_log_xml)
lettings_log = LettingsLog.where(old_id: lettings_log_id).first lettings_log = LettingsLog.where(old_id: lettings_log_id).first
expect(lettings_log&.ecstat2).to be(9) expect(lettings_log&.voiddate).to be_nil
end end
end end
context "when the relationship to lead tenant is set to refuse" do context "and the organisation legacy ID does not exist" do
before { lettings_log_xml.at_xpath("//xmlns:P2Rel").content = "Refused" } before { lettings_log_xml.at_xpath("//xmlns:OWNINGORGID").content = 99_999 }
it "sets the relationship to lead tenant to child" do
lettings_log_service.send(:create_log, lettings_log_xml)
lettings_log = LettingsLog.where(old_id: lettings_log_id).first it "raises an exception" do
expect(lettings_log&.relat2).to eq("C") expect { lettings_log_service.send(:create_log, lettings_log_xml) }
.to raise_error(RuntimeError, "Organisation not found with legacy ID 99999")
end end
end end
end
context "and this is an internal transfer that is in-progress with invalid answers" do context "and a person is under 16" do
before do before { lettings_log_xml.at_xpath("//xmlns:P2Age").content = 14 }
lettings_log_xml.at_xpath("//meta:status").content = "submitted-invalid"
lettings_log_xml.at_xpath("//xmlns:P2Age").content = 999
end
it "intercepts the relevant validation error" do context "when the economic status is set to refuse" do
expect(logger).to receive(:warn).with(/Removing field age2 from log triggering validation: Answer cannot be over 16/) before { lettings_log_xml.at_xpath("//xmlns:P2Eco").content = "10) Refused" }
expect(logger).to receive(:warn).with(/Removing field age2 from log triggering validation: Person 2’s age must be between/)
expect(logger).to receive(:warn).with(/Removing field ecstat2 from log triggering validation: Answer cannot be ‘child under 16’/)
expect { lettings_log_service.send(:create_log, lettings_log_xml) }
.not_to raise_error
end
it "clears out the invalid answers" do it "sets the economic status to child under 16" do
allow(logger).to receive(:warn) # The update is done when calculating derived variables
expect(logger).to receive(:warn).with(/Differences found when saving log/)
lettings_log_service.send(:create_log, lettings_log_xml)
lettings_log_service.send(:create_log, lettings_log_xml) lettings_log = LettingsLog.where(old_id: lettings_log_id).first
lettings_log = LettingsLog.find_by(old_id: lettings_log_id) expect(lettings_log&.ecstat2).to be(9)
end
end
expect(lettings_log).not_to be_nil context "when the relationship to lead tenant is set to refuse" do
expect(lettings_log.age2).to be_nil before { lettings_log_xml.at_xpath("//xmlns:P2Rel").content = "Refused" }
expect(lettings_log.ecstat2).to be_nil
end
end
context "and it has zero earnings" do it "sets the relationship to lead tenant to child" do
before do lettings_log_service.send(:create_log, lettings_log_xml)
lettings_log_xml.at_xpath("//meta:status").content = "submitted"
lettings_log_xml.at_xpath("//xmlns:Q8Money").content = 0
end
it "intercepts the relevant validation error" do lettings_log = LettingsLog.where(old_id: lettings_log_id).first
expect(logger).to receive(:warn).with(/Where the income is 0, set earnings and income to blank and set incref to refused/) expect(lettings_log&.relat2).to eq("C")
expect { lettings_log_service.send(:create_log, lettings_log_xml) } end
.not_to raise_error end
end end
it "clears out the invalid answers" do context "and this is an internal transfer that is in-progress with invalid answers" do
allow(logger).to receive(:warn) before do
lettings_log_xml.at_xpath("//meta:status").content = "submitted-invalid"
lettings_log_xml.at_xpath("//xmlns:P2Age").content = 999
end
lettings_log_service.send(:create_log, lettings_log_xml) it "intercepts the relevant validation error" do
lettings_log = LettingsLog.find_by(old_id: lettings_log_id) expect(logger).to receive(:warn).with(/Removing field age2 from log triggering validation: Answer cannot be over 16/)
expect(logger).to receive(:warn).with(/Removing field age2 from log triggering validation: Person 2’s age must be between/)
expect(logger).to receive(:warn).with(/Removing field ecstat2 from log triggering validation: Answer cannot be ‘child under 16’/)
expect { lettings_log_service.send(:create_log, lettings_log_xml) }
.not_to raise_error
end
expect(lettings_log).not_to be_nil it "clears out the invalid answers" do
expect(lettings_log.earnings).to be_nil allow(logger).to receive(:warn)
expect(lettings_log.incref).to eq(1)
expect(lettings_log.net_income_known).to eq(2)
end
end
context "and an invalid tenancy length for tenancy type" do lettings_log_service.send(:create_log, lettings_log_xml)
before do lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
lettings_log_xml.at_xpath("//meta:status").content = "submitted"
lettings_log_xml.at_xpath("//xmlns:_2cYears").content = "1"
lettings_log_xml.at_xpath("//xmlns:Q2b").content = "4"
end
it "intercepts the relevant validation error" do expect(lettings_log).not_to be_nil
expect(logger).to receive(:warn).with(/Removing tenancylength as invalid/) expect(lettings_log.age2).to be_nil
expect { lettings_log_service.send(:create_log, lettings_log_xml) } expect(lettings_log.ecstat2).to be_nil
.not_to raise_error end
end end
it "clears out the invalid answers" do context "and it has zero earnings" do
allow(logger).to receive(:warn) before do
lettings_log_xml.at_xpath("//meta:status").content = "submitted"
lettings_log_xml.at_xpath("//xmlns:Q8Money").content = 0
end
lettings_log_service.send(:create_log, lettings_log_xml) it "intercepts the relevant validation error" do
lettings_log = LettingsLog.find_by(old_id: lettings_log_id) expect(logger).to receive(:warn).with(/Where the income is 0, set earnings and income to blank and set incref to refused/)
expect { lettings_log_service.send(:create_log, lettings_log_xml) }
.not_to raise_error
end
expect(lettings_log).not_to be_nil it "clears out the invalid answers" do
expect(lettings_log.tenancylength).to be_nil allow(logger).to receive(:warn)
expect(lettings_log.tenancy).to be_nil
end
end
context "and an lead tenant must be under 20 if childrens home or foster care" do lettings_log_service.send(:create_log, lettings_log_xml)
before do lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
lettings_log_xml.at_xpath("//meta:status").content = "submitted"
lettings_log_xml.at_xpath("//xmlns:Q11").content = "13"
lettings_log_xml.at_xpath("//xmlns:P1Age").content = "22"
end
it "intercepts the relevant validation error" do expect(lettings_log).not_to be_nil
expect(logger).to receive(:warn).with(/Removing age1 and prevten as incompatible/) expect(lettings_log.earnings).to be_nil
expect { lettings_log_service.send(:create_log, lettings_log_xml) } expect(lettings_log.incref).to eq(1)
.not_to raise_error expect(lettings_log.net_income_known).to eq(2)
end
end end
it "clears out the invalid answers" do context "and an invalid tenancy length for tenancy type" do
allow(logger).to receive(:warn) before do
lettings_log_xml.at_xpath("//meta:status").content = "submitted"
lettings_log_xml.at_xpath("//xmlns:_2cYears").content = "1"
lettings_log_xml.at_xpath("//xmlns:Q2b").content = "4"
end
lettings_log_service.send(:create_log, lettings_log_xml) it "intercepts the relevant validation error" do
lettings_log = LettingsLog.find_by(old_id: lettings_log_id) expect(logger).to receive(:warn).with(/Removing tenancylength as invalid/)
expect { lettings_log_service.send(:create_log, lettings_log_xml) }
.not_to raise_error
end
expect(lettings_log).not_to be_nil it "clears out the invalid answers" do
expect(lettings_log.age1).to be_nil allow(logger).to receive(:warn)
expect(lettings_log.prevten).to be_nil
end
end
context "and is a carehome but missing carehome charge" do lettings_log_service.send(:create_log, lettings_log_xml)
let(:lettings_log_id) { "0b4a68df-30cc-474a-93c0-a56ce8fdad3b" } lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
before do expect(lettings_log).not_to be_nil
lettings_log_xml.at_xpath("//meta:status").content = "submitted" expect(lettings_log.tenancylength).to be_nil
lettings_log_xml.at_xpath("//xmlns:_1cmangroupcode").content = scheme2.old_visible_id expect(lettings_log.tenancy).to be_nil
scheme2.update!(registered_under_care_act: 2) end
lettings_log_xml.at_xpath("//xmlns:Q18b").content = ""
end end
it "intercepts the relevant validation error" do context "and an lead tenant must be under 20 if childrens home or foster care" do
allow(logger).to receive(:warn) before do
lettings_log_xml.at_xpath("//meta:status").content = "submitted"
lettings_log_xml.at_xpath("//xmlns:Q11").content = "13"
lettings_log_xml.at_xpath("//xmlns:P1Age").content = "22"
end
expect { lettings_log_service.send(:create_log, lettings_log_xml) } it "intercepts the relevant validation error" do
.not_to raise_error expect(logger).to receive(:warn).with(/Removing age1 and prevten as incompatible/)
end expect { lettings_log_service.send(:create_log, lettings_log_xml) }
.not_to raise_error
end
it "clears out the invalid answers" do it "clears out the invalid answers" do
allow(logger).to receive(:warn) allow(logger).to receive(:warn)
lettings_log_service.send(:create_log, lettings_log_xml) lettings_log_service.send(:create_log, lettings_log_xml)
lettings_log = LettingsLog.find_by(old_id: lettings_log_id) lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
expect(lettings_log).not_to be_nil expect(lettings_log).not_to be_nil
expect(lettings_log.is_carehome).to be_truthy expect(lettings_log.age1).to be_nil
expect(lettings_log.chcharge).to be_nil expect(lettings_log.prevten).to be_nil
end
end end
end
context "and this is an internal transfer from a non social housing" do context "and is a carehome but missing carehome charge" do
before do let(:lettings_log_id) { "0b4a68df-30cc-474a-93c0-a56ce8fdad3b" }
lettings_log_xml.at_xpath("//xmlns:Q11").content = "9 Residential care home"
lettings_log_xml.at_xpath("//xmlns:Q16").content = "1 Internal Transfer"
end
it "intercepts the relevant validation error" do before do
expect(logger).to receive(:warn).with(/Removing internal transfer referral since previous tenancy is a non social housing/) lettings_log_xml.at_xpath("//meta:status").content = "submitted"
expect { lettings_log_service.send(:create_log, lettings_log_xml) } lettings_log_xml.at_xpath("//xmlns:_1cmangroupcode").content = scheme2.old_visible_id
.not_to raise_error scheme2.update!(registered_under_care_act: 2)
end lettings_log_xml.at_xpath("//xmlns:Q18b").content = ""
end
it "clears out the referral answer" do it "intercepts the relevant validation error" do
allow(logger).to receive(:warn) allow(logger).to receive(:warn)
lettings_log_service.send(:create_log, lettings_log_xml) expect { lettings_log_service.send(:create_log, lettings_log_xml) }
lettings_log = LettingsLog.find_by(old_id: lettings_log_id) .not_to raise_error
end
it "clears out the invalid answers" do
allow(logger).to receive(:warn)
lettings_log_service.send(:create_log, lettings_log_xml)
lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
expect(lettings_log).not_to be_nil expect(lettings_log).not_to be_nil
expect(lettings_log.referral).to be_nil expect(lettings_log.is_carehome).to be_truthy
expect(lettings_log.chcharge).to be_nil
end
end end
context "and this is an internal transfer from a previous fixed term tenancy" do context "and this is an internal transfer from a non social housing" do
before do before do
lettings_log_xml.at_xpath("//xmlns:Q11").content = "30 Fixed term Local Authority General Needs tenancy" lettings_log_xml.at_xpath("//xmlns:Q11").content = "9 Residential care home"
lettings_log_xml.at_xpath("//xmlns:Q16").content = "1 Internal Transfer" lettings_log_xml.at_xpath("//xmlns:Q16").content = "1 Internal Transfer"
end end
it "intercepts the relevant validation error" do it "intercepts the relevant validation error" do
expect(logger).to receive(:warn).with(/Removing internal transfer referral since previous tenancy is fixed terms or lifetime/) expect(logger).to receive(:warn).with(/Removing internal transfer referral since previous tenancy is a non social housing/)
expect { lettings_log_service.send(:create_log, lettings_log_xml) } expect { lettings_log_service.send(:create_log, lettings_log_xml) }
.not_to raise_error .not_to raise_error
end end
@ -356,86 +341,202 @@ RSpec.describe Imports::LettingsLogsImportService do
expect(lettings_log).not_to be_nil expect(lettings_log).not_to be_nil
expect(lettings_log.referral).to be_nil expect(lettings_log.referral).to be_nil
end end
context "and this is an internal transfer from a previous fixed term tenancy" do
before do
lettings_log_xml.at_xpath("//xmlns:Q11").content = "30 Fixed term Local Authority General Needs tenancy"
lettings_log_xml.at_xpath("//xmlns:Q16").content = "1 Internal Transfer"
end
it "intercepts the relevant validation error" do
expect(logger).to receive(:warn).with(/Removing internal transfer referral since previous tenancy is fixed terms or lifetime/)
expect { lettings_log_service.send(:create_log, lettings_log_xml) }
.not_to raise_error
end
it "clears out the referral answer" do
allow(logger).to receive(:warn)
lettings_log_service.send(:create_log, lettings_log_xml)
lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
expect(lettings_log).not_to be_nil
expect(lettings_log.referral).to be_nil
end
end
end end
end
context "and the net income soft validation is triggered (net_income_value_check)" do context "and the net income soft validation is triggered (net_income_value_check)" do
before do before do
lettings_log_xml.at_xpath("//xmlns:Q8a").content = "1 Weekly" lettings_log_xml.at_xpath("//xmlns:Q8a").content = "1 Weekly"
lettings_log_xml.at_xpath("//xmlns:Q8Money").content = 890.00 lettings_log_xml.at_xpath("//xmlns:Q8Money").content = 890.00
end
it "completes the log" do
lettings_log_service.send(:create_log, lettings_log_xml)
lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
expect(lettings_log.status).to eq("completed")
end
end end
it "completes the log" do context "and the rent soft validation is triggered (rent_value_check)" do
lettings_log_service.send(:create_log, lettings_log_xml) before do
lettings_log = LettingsLog.find_by(old_id: lettings_log_id) lettings_log_xml.at_xpath("//xmlns:Q18ai").content = 200.00
expect(lettings_log.status).to eq("completed") lettings_log_xml.at_xpath("//xmlns:Q18av").content = 232.02
lettings_log_xml.at_xpath("//xmlns:Q17").content = "1 Weekly for 52 weeks"
LaRentRange.create!(
start_year: 2021,
la: "E08000035",
beds: 2,
lettype: 1,
soft_max: 900,
hard_max: 1500,
soft_min: 500,
hard_min: 100,
)
end
it "completes the log" do
lettings_log_service.send(:create_log, lettings_log_xml)
lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
expect(lettings_log.status).to eq("completed")
end
end end
end
context "and the rent soft validation is triggered (rent_value_check)" do context "and the retirement soft validation is triggered (retirement_value_check)" do
before do before do
lettings_log_xml.at_xpath("//xmlns:Q18ai").content = 200.00 lettings_log_xml.at_xpath("//xmlns:P1Age").content = 68
lettings_log_xml.at_xpath("//xmlns:Q18av").content = 232.02 lettings_log_xml.at_xpath("//xmlns:P1Eco").content = "6) Not Seeking Work"
lettings_log_xml.at_xpath("//xmlns:Q17").content = "1 Weekly for 52 weeks" end
LaRentRange.create!(
start_year: 2021, it "completes the log" do
la: "E08000035", lettings_log_service.send(:create_log, lettings_log_xml)
beds: 2, lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
lettype: 1, expect(lettings_log.status).to eq("completed")
soft_max: 900, end
hard_max: 1500,
soft_min: 500,
hard_min: 100,
)
end end
it "completes the log" do context "and this is a supported housing log with multiple locations under a scheme" do
lettings_log_service.send(:create_log, lettings_log_xml) let(:lettings_log_id) { "0b4a68df-30cc-474a-93c0-a56ce8fdad3b" }
lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
expect(lettings_log.status).to eq("completed") it "sets the scheme and location values" do
expect(logger).not_to receive(:warn)
lettings_log_service.send(:create_log, lettings_log_xml)
lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
expect(lettings_log.scheme_id).not_to be_nil
expect(lettings_log.location_id).not_to be_nil
expect(lettings_log.status).to eq("completed")
end
end end
end
context "and the retirement soft validation is triggered (retirement_value_check)" do context "and this is a supported housing log with a single location under a scheme" do
before do let(:lettings_log_id) { "0b4a68df-30cc-474a-93c0-a56ce8fdad3b" }
lettings_log_xml.at_xpath("//xmlns:P1Age").content = 68
lettings_log_xml.at_xpath("//xmlns:P1Eco").content = "6) Not Seeking Work" before { lettings_log_xml.at_xpath("//xmlns:_1cmangroupcode").content = scheme2.old_visible_id }
it "sets the scheme and location values" do
expect(logger).not_to receive(:warn)
lettings_log_service.send(:create_log, lettings_log_xml)
lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
expect(lettings_log.scheme_id).not_to be_nil
expect(lettings_log.location_id).not_to be_nil
expect(lettings_log.status).to eq("completed")
end
end end
end
end
it "completes the log" do context "with 22/23 logs" do
lettings_log_service.send(:create_log, lettings_log_xml) subject(:lettings_log_service) { described_class.new(storage_service, logger) }
lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
expect(lettings_log.status).to eq("completed") around do |example|
Timecop.freeze(Time.zone.local(2023, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end end
Timecop.return
Singleton.__init__(FormHandler)
end end
context "and this is a supported housing log with multiple locations under a scheme" do let(:storage_service) { instance_double(Storage::S3Service) }
let(:lettings_log_id) { "0b4a68df-30cc-474a-93c0-a56ce8fdad3b" } let(:logger) { instance_double(ActiveSupport::Logger) }
it "sets the scheme and location values" do let(:real_2021_2022_form) { Form.new("config/forms/2021_2022.json") }
expect(logger).not_to receive(:warn) let(:real_2022_2023_form) { Form.new("config/forms/2022_2023.json") }
lettings_log_service.send(:create_log, lettings_log_xml) let(:fixture_directory) { "spec/fixtures/imports/logs" }
lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
expect(lettings_log.scheme_id).not_to be_nil let(:organisation) { FactoryBot.create(:organisation, old_visible_id: "1", provider_type: "PRP") }
expect(lettings_log.location_id).not_to be_nil let(:managing_organisation) { FactoryBot.create(:organisation, old_visible_id: "2", provider_type: "PRP") }
expect(lettings_log.status).to eq("completed") let(:scheme1) { FactoryBot.create(:scheme, old_visible_id: "0123", owning_organisation: organisation) }
end let(:scheme2) { FactoryBot.create(:scheme, old_visible_id: "456", owning_organisation: organisation) }
def open_file(directory, filename)
File.open("#{directory}/#{filename}.xml")
end end
context "and this is a supported housing log with a single location under a scheme" do before do
let(:lettings_log_id) { "0b4a68df-30cc-474a-93c0-a56ce8fdad3b" } WebMock.stub_request(:get, /api.postcodes.io\/postcodes\/LS166FT/)
.to_return(status: 200, body: '{"status":200,"result":{"admin_district":"Westminster","codes":{"admin_district":"E08000035"}}}', headers: {})
allow(Organisation).to receive(:find_by).and_return(nil)
allow(Organisation).to receive(:find_by).with(old_visible_id: organisation.old_visible_id).and_return(organisation)
allow(Organisation).to receive(:find_by).with(old_visible_id: managing_organisation.old_visible_id).and_return(managing_organisation)
# Created by users
FactoryBot.create(:user, old_user_id: "c3061a2e6ea0b702e6f6210d5c52d2a92612d2aa", organisation:)
FactoryBot.create(:user, old_user_id: "e29c492473446dca4d50224f2bb7cf965a261d6f", organisation:)
# Location setup
FactoryBot.create(:location, old_visible_id: "10", postcode: "LS166FT", scheme_id: scheme1.id, mobility_type: "W", startdate: Time.zone.local(2021, 4, 1))
FactoryBot.create(:location, scheme_id: scheme1.id, startdate: Time.zone.local(2021, 4, 1))
FactoryBot.create(:location, old_visible_id: "10", postcode: "LS166FT", scheme_id: scheme2.id, mobility_type: "W", startdate: Time.zone.local(2021, 4, 1))
# Stub the form handler to use the real form
allow(FormHandler.instance).to receive(:get_form).with("current_lettings").and_return(real_2022_2023_form)
allow(FormHandler.instance).to receive(:get_form).with("previous_lettings").and_return(real_2021_2022_form)
allow(FormHandler.instance).to receive(:get_form).with("next_lettings").and_return(real_2022_2023_form)
end
before { lettings_log_xml.at_xpath("//xmlns:_1cmangroupcode").content = scheme2.old_visible_id } context "when importing lettings logs" do
let(:remote_folder) { "lettings_logs" }
let(:lettings_log_id) { "00d2343e-d5fa-4c89-8400-ec3854b0f2b4" }
let(:sales_log) { "shared_ownership_sales_log" }
it "sets the scheme and location values" do before do
# Stub the S3 file listing and download
allow(storage_service).to receive(:list_files)
.and_return(%W[#{remote_folder}/#{lettings_log_id}.xml #{remote_folder}/#{sales_log}.xml])
allow(storage_service).to receive(:get_file_io)
.with("#{remote_folder}/#{lettings_log_id}.xml")
.and_return(open_file(fixture_directory, lettings_log_id), open_file(fixture_directory, lettings_log_id))
allow(storage_service).to receive(:get_file_io)
.with("#{remote_folder}/#{sales_log}.xml")
.and_return(open_file(fixture_directory, sales_log), open_file(fixture_directory, sales_log))
end
it "successfully create all lettings logs" do
expect(logger).not_to receive(:error)
expect(logger).not_to receive(:warn) expect(logger).not_to receive(:warn)
lettings_log_service.send(:create_log, lettings_log_xml) expect(logger).not_to receive(:info)
lettings_log = LettingsLog.find_by(old_id: lettings_log_id) expect { lettings_log_service.create_logs(remote_folder) }
.to change(LettingsLog, :count).by(1)
end
expect(lettings_log.scheme_id).not_to be_nil it "only updates existing lettings logs" do
expect(lettings_log.location_id).not_to be_nil expect(logger).not_to receive(:error)
expect(lettings_log.status).to eq("completed") expect(logger).not_to receive(:warn)
expect(logger).to receive(:info).with(/Updating lettings log/).once
expect { 2.times { lettings_log_service.create_logs(remote_folder) } }
.to change(LettingsLog, :count).by(1)
end
it "creates organisation relationship once" do
expect(logger).not_to receive(:error)
expect(logger).not_to receive(:warn)
expect { lettings_log_service.create_logs(remote_folder) }
.to change(OrganisationRelationship, :count).by(1)
end end
end end
end end

9
spec/views/form/page_view_spec.rb

@ -17,6 +17,15 @@ RSpec.describe "form/page" do
end end
end end
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
before do before do
assign(:log, lettings_log) assign(:log, lettings_log)
assign(:page, page) assign(:page, page)

Loading…
Cancel
Save