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. 11
      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. 12
      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. 82
      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. 7
      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. 121
      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

11
spec/features/form/page_routing_spec.rb

@ -20,6 +20,16 @@ RSpec.describe "Form Page Routing" do
sign_in user sign_in user
end end
context "with 21/22 logs" 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
it "can route the user to a different page based on their answer on the current page", js: true do it "can route the user to a different page based on their answer on the current page", js: true do
visit("/lettings-logs/#{id}/conditional-question") visit("/lettings-logs/#{id}/conditional-question")
# using a question name that is already in the db to avoid # using a question name that is already in the db to avoid
@ -111,6 +121,7 @@ RSpec.describe "Form Page Routing" do
expect(find_field("lettings_log[startdate(1i)]").value).to eq(nil) expect(find_field("lettings_log[startdate(1i)]").value).to eq(nil)
end end
end end
end
context "when completing the setup section" do context "when completing the setup section" do
context "with a supported housing log" do context "with a supported housing log" do

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

12
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)

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

82
spec/models/validations/setup_validations_spec.rb

@ -6,6 +6,88 @@ 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

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

7
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
example.run
end 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: {})

121
spec/services/imports/lettings_logs_import_service_spec.rb

@ -1,8 +1,18 @@
require "rails_helper" require "rails_helper"
RSpec.describe Imports::LettingsLogsImportService do RSpec.describe Imports::LettingsLogsImportService do
context "with 21/22 logs" do
subject(:lettings_log_service) { described_class.new(storage_service, logger) } subject(:lettings_log_service) { described_class.new(storage_service, logger) }
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(:storage_service) { instance_double(Storage::S3Service) } let(:storage_service) { instance_double(Storage::S3Service) }
let(:logger) { instance_double(ActiveSupport::Logger) } let(:logger) { instance_double(ActiveSupport::Logger) }
@ -37,22 +47,22 @@ RSpec.describe Imports::LettingsLogsImportService do
FactoryBot.create(:location, old_visible_id: "10", postcode: "LS166FT", scheme_id: scheme2.id, mobility_type: "W", 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 # 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("previous_lettings").and_return(real_2021_2022_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("next_lettings").and_return(real_2022_2023_form)
end end
context "when importing lettings logs" do context "when importing lettings logs" do
let(:remote_folder) { "lettings_logs" } let(:remote_folder) { "lettings_logs" }
let(:lettings_log_id) { "0ead17cb-1668-442d-898c-0d52879ff592" } let(:lettings_log_id) { "0ead17cb-1668-442d-898c-0d52879ff592" }
let(:lettings_log_id2) { "166fc004-392e-47a8-acb8-1c018734882b" } let(:lettings_log_id2) { "166fc004-392e-47a8-acb8-1c018734882b" }
let(:lettings_log_id3) { "00d2343e-d5fa-4c89-8400-ec3854b0f2b4" } let(:lettings_log_id3) { "0b4a68df-30cc-474a-93c0-a56ce8fdad3b" }
let(:lettings_log_id4) { "0b4a68df-30cc-474a-93c0-a56ce8fdad3b" }
let(:sales_log) { "shared_ownership_sales_log" } let(:sales_log) { "shared_ownership_sales_log" }
before do before do
# Stub the S3 file listing and download # Stub the S3 file listing and download
allow(storage_service).to receive(:list_files) 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}/#{lettings_log_id4}.xml #{remote_folder}/#{sales_log}.xml]) .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_id}.xml") .with("#{remote_folder}/#{lettings_log_id}.xml")
.and_return(open_file(fixture_directory, lettings_log_id), open_file(fixture_directory, lettings_log_id)) .and_return(open_file(fixture_directory, lettings_log_id), open_file(fixture_directory, lettings_log_id))
@ -62,9 +72,6 @@ RSpec.describe Imports::LettingsLogsImportService do
allow(storage_service).to receive(:get_file_io) allow(storage_service).to receive(:get_file_io)
.with("#{remote_folder}/#{lettings_log_id3}.xml") .with("#{remote_folder}/#{lettings_log_id3}.xml")
.and_return(open_file(fixture_directory, lettings_log_id3), open_file(fixture_directory, lettings_log_id3)) .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) allow(storage_service).to receive(:get_file_io)
.with("#{remote_folder}/#{sales_log}.xml") .with("#{remote_folder}/#{sales_log}.xml")
.and_return(open_file(fixture_directory, sales_log), open_file(fixture_directory, sales_log)) .and_return(open_file(fixture_directory, sales_log), open_file(fixture_directory, sales_log))
@ -75,15 +82,15 @@ RSpec.describe Imports::LettingsLogsImportService do
expect(logger).not_to receive(:warn) expect(logger).not_to receive(:warn)
expect(logger).not_to receive(:info) expect(logger).not_to receive(:info)
expect { lettings_log_service.create_logs(remote_folder) } expect { lettings_log_service.create_logs(remote_folder) }
.to change(LettingsLog, :count).by(4) .to change(LettingsLog, :count).by(3)
end end
it "only updates existing lettings logs" do it "only updates existing lettings logs" do
expect(logger).not_to receive(:error) expect(logger).not_to receive(:error)
expect(logger).not_to receive(:warn) expect(logger).not_to receive(:warn)
expect(logger).to receive(:info).with(/Updating lettings log/).exactly(4).times expect(logger).to receive(:info).with(/Updating lettings log/).exactly(3).times
expect { 2.times { lettings_log_service.create_logs(remote_folder) } } expect { 2.times { lettings_log_service.create_logs(remote_folder) } }
.to change(LettingsLog, :count).by(4) .to change(LettingsLog, :count).by(3)
end end
it "creates organisation relationship once" do it "creates organisation relationship once" do
@ -440,3 +447,97 @@ RSpec.describe Imports::LettingsLogsImportService do
end end
end end
end end
context "with 22/23 logs" do
subject(:lettings_log_service) { described_class.new(storage_service, logger) }
around do |example|
Timecop.freeze(Time.zone.local(2023, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
let(:storage_service) { instance_double(Storage::S3Service) }
let(:logger) { instance_double(ActiveSupport::Logger) }
let(:real_2021_2022_form) { Form.new("config/forms/2021_2022.json") }
let(:real_2022_2023_form) { Form.new("config/forms/2022_2023.json") }
let(:fixture_directory) { "spec/fixtures/imports/logs" }
let(:organisation) { FactoryBot.create(:organisation, old_visible_id: "1", provider_type: "PRP") }
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("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
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" }
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(:info)
expect { lettings_log_service.create_logs(remote_folder) }
.to change(LettingsLog, :count).by(1)
end
it "only updates existing lettings logs" do
expect(logger).not_to receive(:error)
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

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