Browse Source

CLDC-3499: Remove pre 2025 tests (#3324)

* CLDC-3499: Update selenium

allows for the tests to run locally as it can download a browser version that exists

* CLDC-3499: Fix validations spec to be non year specific

* CLDC-3499: Remove unneeded 2020 dates from bulk scheme locations spec

* CLDC-3499: Remove year specific tests from form_handler_spec

* CLDC-3499: Remove 2020 test from lettings_log_spec

* CLDC-3499: Remove 2020 test from sales_log_spec

* CLDC-3499: Remove 2020 test from location_spec

makes the current_collection_after_crossover_start_date method a bit more useful, returns the date in the current collection year that crossover will end, rather than the crossover end date of the current period (which will be next year)

* CLDC-3499: Remove 2020 test from scheme_spec

* CLDC-3499: Remove 2020 test from setup_validations_spec

adds missing archived method to collection_time_helper

* CLDC-3499: Start changes to lettings log export service

* CLDC-3499: Remove unneeded old test from check answers summary list component spec

* CLDC-3499: Update check answers page spec for modern years

* CLDC-3499: Add more form helpers

* CLDC-3499: Remove year specific tests from lettings setup validations

* CLDC-3499: Remove year specific tests from managing org rake spec

* CLDC-3499: Update lettings log spec

* CLDC-3499: Update task list spec

* CLDC-3499: Update sales logs controller

* CLDC-3499: Remove old tests from sales log spec

* CLDC-3499: Fix some final old tests

* Revert "CLDC-3499: Start changes to lettings log export service"

This reverts commit 1edbc9ab8c.

* CLDC-3499: Lint

* feat: enforce crossover tests pass

* feat: re-include archived log display test

---------

Co-authored-by: Nat Dean-Lewis <nat.dean-lewis@softwire.com>
Co-authored-by: Nat Dean-Lewis <94526761+natdeanlewissoftwire@users.noreply.github.com>
pull/3329/head^2
Samuel Young 2 months ago committed by GitHub
parent
commit
acac78a8e5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      Gemfile
  2. 7
      Gemfile.lock
  3. 6
      app/helpers/collection_time_helper.rb
  4. 6
      spec/components/check_answers_summary_list_card_component_spec.rb
  5. 136
      spec/features/form/check_answers_page_lettings_logs_spec.rb
  6. 16
      spec/features/form/helpers.rb
  7. 25
      spec/features/form/tasklist_page_spec.rb
  8. 96
      spec/features/form/validations_spec.rb
  9. 4
      spec/lib/tasks/set_sales_managing_organisation_spec.rb
  10. 2
      spec/lib/tasks/update_schemes_and_locations_from_csv_spec.rb
  11. 135
      spec/models/form_handler_spec.rb
  12. 316
      spec/models/lettings_log_spec.rb
  13. 34
      spec/models/location_spec.rb
  14. 64
      spec/models/sales_log_spec.rb
  15. 34
      spec/models/scheme_spec.rb
  16. 34
      spec/models/validations/date_validations_spec.rb
  17. 34
      spec/models/validations/financial_validations_spec.rb
  18. 8
      spec/models/validations/household_validations_spec.rb
  19. 12
      spec/models/validations/sales/sale_information_validations_spec.rb
  20. 8
      spec/models/validations/sales/setup_validations_spec.rb
  21. 199
      spec/models/validations/setup_validations_spec.rb
  22. 20
      spec/models/validations/soft_validations_spec.rb
  23. 227
      spec/requests/sales_logs_controller_spec.rb

2
Gemfile

@ -106,7 +106,7 @@ group :test do
gem "capybara-lockstep" gem "capybara-lockstep"
gem "capybara-screenshot" gem "capybara-screenshot"
gem "rspec-rails", require: false gem "rspec-rails", require: false
gem "selenium-webdriver", require: false gem "selenium-webdriver", "~> 4.43", require: false
gem "simplecov", require: false gem "simplecov", require: false
gem "timecop", "~> 0.9.4" gem "timecop", "~> 0.9.4"
gem "webmock", require: false gem "webmock", require: false

7
Gemfile.lock

@ -500,10 +500,11 @@ GEM
ruby2_keywords (0.0.5) ruby2_keywords (0.0.5)
rubyzip (2.3.2) rubyzip (2.3.2)
securerandom (0.4.1) securerandom (0.4.1)
selenium-webdriver (4.18.1) selenium-webdriver (4.43.0)
base64 (~> 0.2) base64 (~> 0.2)
logger (~> 1.4)
rexml (~> 3.2, >= 3.2.5) rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0) rubyzip (>= 1.2.2, < 4.0)
websocket (~> 1.0) websocket (~> 1.0)
sentry-rails (5.16.1) sentry-rails (5.16.1)
railties (>= 5.0) railties (>= 5.0)
@ -634,7 +635,7 @@ DEPENDENCIES
rubocop-performance rubocop-performance
rubocop-rails rubocop-rails
ruby-openai ruby-openai
selenium-webdriver selenium-webdriver (~> 4.43)
sentry-rails sentry-rails
sentry-ruby sentry-ruby
sidekiq (~> 7.2.4) sidekiq (~> 7.2.4)

6
app/helpers/collection_time_helper.rb

@ -30,7 +30,7 @@ module CollectionTimeHelper
end end
def current_collection_after_crossover_start_date def current_collection_after_crossover_start_date
Form::DEADLINES[current_collection_start_year][:edit_end_date] + 1.day Form::DEADLINES[previous_collection_start_year][:edit_end_date] + 1.day
end end
def collection_end_date(date) def collection_end_date(date)
@ -81,6 +81,10 @@ module CollectionTimeHelper
current_collection_end_year - 2 current_collection_end_year - 2
end end
def archived_collection_start_date
current_collection_start_date - 2.years
end
def previous_collection_new_logs_end_date def previous_collection_new_logs_end_date
FormHandler.instance.lettings_form_for_start_year(previous_collection_start_year).new_logs_end_date FormHandler.instance.lettings_form_for_start_year(previous_collection_start_year).new_logs_end_date
end end

6
spec/components/check_answers_summary_list_card_component_spec.rb

@ -1,6 +1,8 @@
require "rails_helper" require "rails_helper"
RSpec.describe CheckAnswersSummaryListCardComponent, type: :component do RSpec.describe CheckAnswersSummaryListCardComponent, type: :component do
include CollectionTimeHelper
subject(:component) { described_class.new(questions:, log:, user:) } subject(:component) { described_class.new(questions:, log:, user:) }
let(:rendered) { render_inline(component) } let(:rendered) { render_inline(component) }
@ -65,9 +67,9 @@ RSpec.describe CheckAnswersSummaryListCardComponent, type: :component do
end end
end end
context "when before 23/24 collection" do context "when a log is from an archived collection year" do
context "when given a set of questions" do context "when given a set of questions" do
let(:log) { create(:lettings_log, :completed, :ignore_validation_errors, age2: 99, startdate: Time.zone.local(2021, 5, 1), assigned_to: create(:user)) } let(:log) { create(:lettings_log, :completed, :ignore_validation_errors, age2: 99, startdate: archived_collection_start_date, assigned_to: create(:user)) }
it "renders a summary list card without question numbers for the answers to those questions" do it "renders a summary list card without question numbers for the answers to those questions" do
expect(rendered).to have_content(questions.first.answer_label(log)) expect(rendered).to have_content(questions.first.answer_label(log))

136
spec/features/form/check_answers_page_lettings_logs_spec.rb

@ -2,21 +2,13 @@ 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
include CollectionTimeHelper
let(:user) { FactoryBot.create(:user) } let(:user) { FactoryBot.create(:user) }
let(:subsection) { "household-characteristics" } let(:subsection) { "household-needs" }
let(:conditional_subsection) { "conditional-question" }
let(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) } let(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) }
let(:location) { FactoryBot.create(:location, scheme:, mobility_type: "N", startdate: Time.zone.local(2021, 4, 1)) } let(:location) { FactoryBot.create(:location, scheme:, mobility_type: "N", startdate: current_collection_start_date) }
let(:lettings_log) do let(:lettings_log) do
FactoryBot.create( FactoryBot.create(
@ -31,9 +23,7 @@ RSpec.describe "Lettings Log Check Answers Page" do
let(:empty_lettings_log) do let(:empty_lettings_log) do
FactoryBot.create( FactoryBot.create(
:lettings_log, :lettings_log,
previous_la_known: 1, :setup_completed,
prevloc: "E09000033",
is_previous_la_inferred: false,
assigned_to: user, assigned_to: user,
) )
end end
@ -44,21 +34,17 @@ RSpec.describe "Lettings Log Check Answers Page" do
owning_organisation: user.organisation, owning_organisation: user.organisation,
managing_organisation: user.organisation, managing_organisation: user.organisation,
assigned_to: user, assigned_to: user,
startdate: Time.zone.local(2021, 5, 1), startdate: current_collection_start_date,
) )
end end
let(:id) { lettings_log.id } let(:id) { lettings_log.id }
let(:fake_2021_2022_form) { Form.new("spec/fixtures/forms/2021_2022.json") }
before do before do
allow(lettings_log.form).to receive(:new_logs_end_date).and_return(Time.zone.today + 1.day)
allow(fake_2021_2022_form).to receive(:new_logs_end_date).and_return(Time.zone.today + 1.day)
sign_in user sign_in user
allow(FormHandler.instance).to receive(:current_lettings_form).and_return(fake_2021_2022_form)
end end
context "when the user needs to check their answers for a subsection" do context "when the user needs to check their answers for a subsection" do
let(:last_question_for_subsection) { "propcode" } let(:last_question_for_subsection) { "health-conditions" }
it "can be visited by URL" do it "can be visited by URL" do
visit("/lettings-logs/#{id}/#{subsection}/check-answers") visit("/lettings-logs/#{id}/#{subsection}/check-answers")
@ -66,80 +52,46 @@ RSpec.describe "Lettings Log Check Answers Page" do
end end
it "redirects to the check answers page when answering the last question and clicking save and continue" do it "redirects to the check answers page when answering the last question and clicking save and continue" do
fill_in_number_question(id, "propcode", 0, last_question_for_subsection) fill_in_radio_question(id, "illness", "2", last_question_for_subsection)
expect(page).to have_current_path("/lettings-logs/#{id}/#{subsection}/check-answers") expect(page).to have_current_path("/lettings-logs/#{id}/#{subsection}/check-answers")
end end
it "has question headings based on the subsection" do it "has question headings based on the subsection" do
visit("/lettings-logs/#{id}/#{subsection}/check-answers") visit("/lettings-logs/#{id}/#{subsection}/check-answers")
question_labels = ["Tenant code", "Lead tenant’s age", "Number of Household Members"] question_labels = ["Household links to UK armed forces", "Anybody in household pregnant", "Anybody with disabled access needs", "Anybody in household with physical or mental health condition"]
question_labels.each do |label| question_labels.each do |label|
expect(page).to have_content(label) expect(page).to have_content(label)
end end
end end
it "displays answers given by the user for the question in the subsection" do it "displays answers given by the user for the question in the subsection" do
fill_in_number_question(empty_lettings_log.id, "age1", 28, "person-1-age") fill_in_radio_question(id, "armedforces", "3", "armed-forces")
choose("lettings-log-sex1-x-field") fill_in_radio_question(id, "illness", "2", "health-conditions")
click_button("Save and continue") visit("/lettings-logs/#{id}/#{subsection}/check-answers")
visit("/lettings-logs/#{empty_lettings_log.id}/#{subsection}/check-answers") expect(page).to have_content("No")
expect(page).to have_content("28") expect(page).to have_content("Person prefers not to say")
expect(page).to have_content("Non-binary")
end end
# Regex explanation: match the string "Answer" but not if it's follow by "the missing questions"
# This way only the links in the table will get picked up
it "has an answer link with the check_answers_new_answer referrer for questions missing an answer" do it "has an answer link with the check_answers_new_answer referrer for questions missing an answer" do
visit("/lettings-logs/#{empty_lettings_log.id}/#{subsection}/check-answers?referrer=check_answers") visit("/lettings-logs/#{id}/#{subsection}/check-answers?referrer=check_answers")
assert_selector "a", text: "Change", count: 0 assert_selector "a", text: "Change", count: 0
expect(page).to have_link("Enter lead tenant’s age", href: "/lettings-logs/#{empty_lettings_log.id}/person-1-age?referrer=check_answers_new_answer") expect(page).to have_link("Tell us if there are any household links to UK armed forces", href: "/lettings-logs/#{id}/armed-forces?referrer=check_answers_new_answer")
end end
it "has a change link for answered question" do it "has a change link for answered question" do
fill_in_number_question(empty_lettings_log.id, "age1", 28, "person-1-age") fill_in_radio_question(id, "armedforces", "2", "armed-forces")
visit("/lettings-logs/#{empty_lettings_log.id}/#{subsection}/check-answers") visit("/lettings-logs/#{id}/#{subsection}/check-answers")
assert_selector "a", text: "Change", count: 1 assert_selector "a", text: "Change", count: 1
expect(page).to have_link("Change", href: "/lettings-logs/#{empty_lettings_log.id}/person-1-age?referrer=check_answers") expect(page).to have_link("Change", href: "/lettings-logs/#{id}/armed-forces?referrer=check_answers")
end end
it "updates the add change link when answers get answered" do it "updates the add change link when answers get answered" do
visit("/lettings-logs/#{empty_lettings_log.id}/household-needs/check-answers") visit("/lettings-logs/#{id}/household-needs/check-answers")
assert_selector "a", text: "Change", count: 0
fill_in_radio_question(id, "armedforces", "2", "armed-forces")
visit("/lettings-logs/#{id}/household-needs/check-answers")
assert_selector "a", text: "Change", count: 1 assert_selector "a", text: "Change", count: 1
visit("/lettings-logs/#{empty_lettings_log.id}/accessibility-requirements") expect(page).to have_link("Change", href: "/lettings-logs/#{id}/armed-forces?referrer=check_answers")
check("lettings-log-accessibility-requirements-housingneeds-c-field")
click_button("Save and continue")
visit("/lettings-logs/#{empty_lettings_log.id}/household-needs/check-answers")
assert_selector "a", text: "Change", count: 2
expect(page).to have_link("Change", href: "/lettings-logs/#{empty_lettings_log.id}/accessibility-requirements?referrer=check_answers")
end
it "does not display conditional questions that were not visited" do
visit("/lettings-logs/#{id}/#{conditional_subsection}/check-answers")
question_labels = ["Has the condition been met?"]
question_labels.each do |label|
expect(page).to have_content(label)
end
excluded_question_labels = ["Has the next condition been met?", "Has the condition not been met?"]
excluded_question_labels.each do |label|
expect(page).not_to have_content(label)
end
end
it "displays conditional question that were visited" do
visit("/lettings-logs/#{id}/conditional-question")
choose("lettings-log-preg-occ-2-field", allow_label_click: true)
click_button("Save and continue")
visit("/lettings-logs/#{id}/#{conditional_subsection}/check-answers")
question_labels = ["Has the condition been met?", "Has the condition not been met?"]
question_labels.each do |label|
expect(page).to have_content(label)
end
excluded_question_labels = ["Has the next condition been met?"]
excluded_question_labels.each do |label|
expect(page).not_to have_content(label)
end
end end
it "does not group questions into summary cards if the questions in the subsection don't have a check_answers_card_number attribute" do it "does not group questions into summary cards if the questions in the subsection don't have a check_answers_card_number attribute" do
@ -149,7 +101,7 @@ RSpec.describe "Lettings Log Check Answers Page" do
context "when the user is checking their answers for the household characteristics subsection" do context "when the user is checking their answers for the household characteristics subsection" do
it "they see a separate summary card for each member of the household" do it "they see a separate summary card for each member of the household" do
visit("/lettings-logs/#{completed_lettings_log.id}/#{subsection}/check-answers") visit("/lettings-logs/#{completed_lettings_log.id}/household-characteristics/check-answers")
assert_selector ".govuk-summary-card__title", text: "Lead tenant", count: 1 assert_selector ".govuk-summary-card__title", text: "Lead tenant", count: 1
assert_selector ".govuk-summary-card__title", text: "Person 2", count: 1 assert_selector ".govuk-summary-card__title", text: "Person 2", count: 1
end end
@ -157,7 +109,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:, startdate: Time.zone.local(2021, 1, 1)) FactoryBot.create(:location, scheme:, startdate: current_collection_start_date)
end end
it "displays inferred postcode with the location id" do it "displays inferred postcode with the location id" do
@ -175,15 +127,12 @@ RSpec.describe "Lettings Log Check Answers Page" do
context "when the user changes their answer from check answer page" do context "when the user changes their answer from check answer page" do
it "routes back to check answers" do it "routes back to check answers" do
visit("/lettings-logs/#{empty_lettings_log.id}/accessibility-requirements") fill_in_radio_question(id, "armedforces", "2", "armed-forces")
check("lettings-log-accessibility-requirements-housingneeds-c-field") visit("/lettings-logs/#{id}/household-needs/check-answers")
click_button("Save and continue")
visit("/lettings-logs/#{empty_lettings_log.id}/household-needs/check-answers")
first("a", text: /Change/).click first("a", text: /Change/).click
uncheck("lettings-log-accessibility-requirements-housingneeds-c-field") choose("lettings-log-armedforces-3-field")
check("lettings-log-accessibility-requirements-housingneeds-b-field")
click_button("Save changes") click_button("Save changes")
expect(page).to have_current_path("/lettings-logs/#{empty_lettings_log.id}/household-needs/check-answers") expect(page).to have_current_path("/lettings-logs/#{id}/household-needs/check-answers")
end end
end end
@ -224,10 +173,24 @@ RSpec.describe "Lettings Log Check Answers Page" do
sex1: "M", sex1: "M",
hhmemb: 1, hhmemb: 1,
armedforces: 3, armedforces: 3,
preg_occ: 2,
housingneeds: 2,
illness: 1, illness: 1,
housingneeds_h: 1,
la: "E06000014",
illness_type_1: 1, illness_type_1: 1,
layear: 2,
waityear: 7,
reason: 4,
prevten: 6,
homeless: 1,
ppostcode_full: "SE2 6RT",
previous_la_known: 1,
prevloc: "E07000105",
reasonpref: 1,
cbl: 0,
chr: 1,
cap: 0,
accessible_register: 0,
referral_type: 1,
) )
end end
@ -240,6 +203,7 @@ RSpec.describe "Lettings Log Check Answers Page" do
tenancycode: nil, tenancycode: nil,
hhmemb: nil, hhmemb: nil,
age1: nil, age1: nil,
age2: nil,
layear: 2, layear: 2,
waityear: 1, waityear: 1,
postcode_full: "NW1 5TY", postcode_full: "NW1 5TY",
@ -265,13 +229,13 @@ RSpec.describe "Lettings Log Check Answers Page" do
it "they can click a button to skip sections until the next incomplete section" do it "they can click a button to skip sections until the next incomplete section" do
visit("/lettings-logs/#{skip_section_lettings_log.id}/household-characteristics/check-answers") visit("/lettings-logs/#{skip_section_lettings_log.id}/household-characteristics/check-answers")
click_link("Save and go to next incomplete section") click_link("Save and go to next incomplete section")
expect(page).to have_current_path("/lettings-logs/#{skip_section_lettings_log.id}/property-information/check-answers") expect(page).to have_current_path("/lettings-logs/#{skip_section_lettings_log.id}/household-situation/check-answers")
end end
it "they can click a button to cycle around to the next incomplete section" do it "they can click a button to cycle around to the next incomplete section" do
visit("/lettings-logs/#{cycle_sections_lettings_log.id}/declaration/check-answers") visit("/lettings-logs/#{cycle_sections_lettings_log.id}/income-and-benefits/check-answers")
click_link("Save and go to next incomplete section") click_link("Save and go to next incomplete section")
expect(page).to have_current_path("/lettings-logs/#{cycle_sections_lettings_log.id}/tenant-code-test") expect(page).to have_current_path("/lettings-logs/#{cycle_sections_lettings_log.id}/property-information/check-answers")
end end
end end
end end

16
spec/features/form/helpers.rb

@ -5,14 +5,16 @@ module Helpers
click_button("Save and continue") click_button("Save and continue")
end end
def answer_all_questions_in_income_subsection(lettings_log) def fill_in_date_question(lettings_log_id, question, day, month, year, path, conditional_field: nil)
visit("/lettings-logs/#{lettings_log.id}/net-income") visit("/lettings-logs/#{lettings_log_id}/#{path}")
fill_in("lettings-log-earnings-field", with: 18_000) choose("lettings-log-#{conditional_field}-field", allow_label_click: true) if conditional_field
choose("lettings-log-incfreq-2-field") fill_in("lettings_log[#{question}]", with: [day, month, year].join("/"))
click_button("Save and continue")
choose("lettings-log-benefits-0-field")
click_button("Save and continue") click_button("Save and continue")
choose("lettings-log-hb-1-field") end
def fill_in_radio_question(lettings_log_id, question, code, path)
visit("/lettings-logs/#{lettings_log_id}/#{path}")
choose("lettings-log-#{question.to_s.dasherize}-#{code}-field")
click_button("Save and continue") click_button("Save and continue")
end end

25
spec/features/form/tasklist_page_spec.rb

@ -42,38 +42,16 @@ RSpec.describe "Task List" do
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(:new_logs_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.")
end end
describe "completed subsection count" do describe "completed subsection count" do
let(:real_2021_2022_form) { Form.new("config/forms/2021_2022.json") }
before do
allow(FormHandler.instance).to receive(:get_form).and_return(real_2021_2022_form)
end
it "shows number of completed sections if one section is completed" do it "shows number of completed sections if one section is completed" do
visit("/lettings-logs/#{setup_completed_log.id}") visit("/lettings-logs/#{setup_completed_log.id}")
expect(page).to have_content("1 of 7 subsections completed.") expect(page).to have_content("1 of 7 subsections completed.")
@ -81,9 +59,8 @@ RSpec.describe "Task List" do
end end
it "show skip link for next incomplete section" do it "show skip link for next incomplete section" do
answer_all_questions_in_income_subsection(setup_completed_log)
visit("/lettings-logs/#{setup_completed_log.id}") visit("/lettings-logs/#{setup_completed_log.id}")
expect(page).to have_link("Skip to next incomplete section", href: /#household-characteristics/) expect(page).to have_link("Skip to next incomplete section", href: /#property-information/)
end end
it "has a review section which has a button that allows the data inputter to review the lettings log" do it "has a review section which has a button that allows the data inputter to review the lettings log" do

96
spec/features/form/validations_spec.rb

@ -2,47 +2,31 @@ 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(:user) { FactoryBot.create(:user) } let(:user) { FactoryBot.create(:user) }
let(:lettings_log) do let(:lettings_log) do
FactoryBot.create( FactoryBot.create(
:lettings_log, :lettings_log,
:in_progress, :setup_completed,
assigned_to: user, assigned_to: user,
renewal: 0, renewal: 0,
) first_time_property_let_as_social_housing: 0,
end unitletas: 1,
let(:empty_lettings_log) do rsnvac: 9,
FactoryBot.create(
:lettings_log,
assigned_to: user,
) )
end end
let(:id) { lettings_log.id } let(:id) { lettings_log.id }
before do before do
allow(fake_2021_2022_form).to receive(:new_logs_end_date).and_return(Time.zone.today + 1.day)
allow(lettings_log.form).to receive(:new_logs_end_date).and_return(Time.zone.today + 1.day)
sign_in user sign_in user
allow(FormHandler.instance).to receive(:current_lettings_form).and_return(fake_2021_2022_form)
end end
include Helpers include Helpers
include CollectionTimeHelper
describe "Question validation" do describe "Question validation" do
context "when the tenant age is invalid" do context "when the tenant age is invalid" do
it "shows validation for under 0" do it "shows validation for under 0" do
visit("/lettings-logs/#{id}/person-1-age") fill_in_number_question(id, "age1", -5, "lead-tenant-age")
fill_in_number_question(empty_lettings_log.id, "age1", -5, "person-1-age")
expect(page).to have_selector(".govuk-error-summary__title") expect(page).to have_selector(".govuk-error-summary__title")
expect(page).to have_selector("#lettings-log-age1-error") expect(page).to have_selector("#lettings-log-age1-error")
expect(page).to have_selector("#lettings-log-age1-field-error") expect(page).to have_selector("#lettings-log-age1-field-error")
@ -50,8 +34,7 @@ RSpec.describe "validations" do
end end
it "shows validation for over 120" do it "shows validation for over 120" do
visit("/lettings-logs/#{id}/person-1-age") fill_in_number_question(id, "age1", 121, "lead-tenant-age")
fill_in_number_question(empty_lettings_log.id, "age1", 121, "person-1-age")
expect(page).to have_selector(".govuk-error-summary__title") expect(page).to have_selector(".govuk-error-summary__title")
expect(page).to have_selector("#lettings-log-age1-error") expect(page).to have_selector("#lettings-log-age1-error")
expect(page).to have_selector("#lettings-log-age1-field-error") expect(page).to have_selector("#lettings-log-age1-field-error")
@ -63,11 +46,12 @@ RSpec.describe "validations" do
describe "date validation", :js do describe "date validation", :js do
def fill_in_date(lettings_log_id, question, day, month, year, path) def fill_in_date(lettings_log_id, question, day, month, year, path)
visit("/lettings-logs/#{lettings_log_id}/#{path}") visit("/lettings-logs/#{lettings_log_id}/#{path}")
choose("lettings-log-majorrepairs-1-field", allow_label_click: true)
fill_in("lettings_log[#{question}]", with: [day, month, year].join("/")) fill_in("lettings_log[#{question}]", with: [day, month, year].join("/"))
end end
it "does not allow out of range dates to be submitted" do it "does not allow out of range dates to be submitted" do
fill_in_date(id, "mrcdate", 3100, 12, 2000, "property-major-repairs") fill_in_date(id, "mrcdate", 3100, 12, current_collection_start_year, "property-major-repairs")
click_button("Save and continue") click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{id}/property-major-repairs") expect(page).to have_current_path("/lettings-logs/#{id}/property-major-repairs")
@ -75,13 +59,9 @@ RSpec.describe "validations" do
click_button("Save and continue") click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{id}/property-major-repairs") expect(page).to have_current_path("/lettings-logs/#{id}/property-major-repairs")
fill_in_date(id, "mrcdate", 13, 100, 2020, "property-major-repairs") fill_in_date(id, "mrcdate", 13, 100, current_collection_start_year, "property-major-repairs")
click_button("Save and continue") click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{id}/property-major-repairs") expect(page).to have_current_path("/lettings-logs/#{id}/property-major-repairs")
fill_in_date(id, "mrcdate", 21, 11, 2020, "property-major-repairs")
click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{id}/local-authority/check-answers")
end end
it "does not allow non numeric inputs to be submitted" do it "does not allow non numeric inputs to be submitted" do
@ -95,19 +75,20 @@ RSpec.describe "validations" do
click_button("Save and continue") click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{id}/property-major-repairs") expect(page).to have_current_path("/lettings-logs/#{id}/property-major-repairs")
fill_in_date(id, "mrcdate", 12, nil, 2000, "property-major-repairs") fill_in_date(id, "mrcdate", 12, nil, current_collection_start_year, "property-major-repairs")
click_button("Save and continue") click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{id}/property-major-repairs") expect(page).to have_current_path("/lettings-logs/#{id}/property-major-repairs")
fill_in_date(id, "mrcdate", nil, 10, 2020, "property-major-repairs") fill_in_date(id, "mrcdate", nil, 10, current_collection_start_year, "property-major-repairs")
click_button("Save and continue") click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{id}/property-major-repairs") expect(page).to have_current_path("/lettings-logs/#{id}/property-major-repairs")
end end
it "allows valid inputs to be submitted" do it "allows valid inputs to be submitted" do
fill_in_date(id, "mrcdate", 21, 11, 2020, "property-major-repairs") valid_mcrdate = lettings_log.startdate - 1.day
fill_in_date(id, "mrcdate", valid_mcrdate.day, valid_mcrdate.month, valid_mcrdate.year, "property-major-repairs")
click_button("Save and continue") click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{id}/local-authority/check-answers") expect(page).to have_current_path("/lettings-logs/#{id}/property-information/check-answers")
end end
end end
@ -120,68 +101,69 @@ RSpec.describe "validations" do
hhmemb: 1, hhmemb: 1,
ecstat1: 1, ecstat1: 1,
assigned_to: user, assigned_to: user,
net_income_known: 0,
) )
end end
let(:income_over_soft_limit) { 750 } let(:income_over_soft_limit) { 750 }
let(:income_under_soft_limit) { 700 } let(:income_under_soft_limit) { 700 }
before do before do
visit("/lettings-logs/#{lettings_log.id}/net-income") visit("/lettings-logs/#{lettings_log.id}/income-amount")
fill_in("lettings-log-earnings-field", with: income_over_soft_limit) fill_in("lettings-log-earnings-field", with: income_over_soft_limit)
choose("lettings-log-incfreq-1-field", allow_label_click: true) choose("lettings-log-incfreq-1-field", allow_label_click: true)
click_button("Save and continue") click_button("Save and continue")
end end
it "prompts the user to confirm the value is correct with an interruption screen" do it "prompts the user to confirm the value is correct with an interruption screen" do
expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income-value-check") expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/income-amount-net-income-value-check")
expect(page).to have_content("You told us that the household’s income is £750.00 weekly") expect(page).to have_content("You told us that the household’s income is £750.00 weekly")
expect(page).to have_content("This is higher than we would expect for the household’s working situation.") expect(page).to have_content("This is higher than we would expect for the household’s working situation.")
expect(page).not_to have_button("Save changes") expect(page).not_to have_button("Save changes")
click_button("Confirm and continue") click_button("Confirm and continue")
expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income-uc-proportion") expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/housing-benefit")
end end
it "allows to fix the questions that trigger the soft validation" do it "allows to fix the questions that trigger the soft validation" do
expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income-value-check") expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/income-amount-net-income-value-check")
expect(page).to have_link("Change", href: "/lettings-logs/#{lettings_log.id}/net-income?referrer=interruption_screen").twice expect(page).to have_link("Change", href: "/lettings-logs/#{lettings_log.id}/income-amount?referrer=interruption_screen").twice
expect(page).to have_link("Change", href: "/lettings-logs/#{lettings_log.id}/person-1-working-situation?referrer=interruption_screen") expect(page).to have_link("Change", href: "/lettings-logs/#{lettings_log.id}/lead-tenant-working-situation?referrer=interruption_screen")
expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income-value-check") expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/income-amount-net-income-value-check")
click_link("Change", href: "/lettings-logs/#{lettings_log.id}/net-income?referrer=interruption_screen", match: :first) click_link("Change", href: "/lettings-logs/#{lettings_log.id}/income-amount?referrer=interruption_screen", match: :first)
expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income?referrer=interruption_screen") expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/income-amount?referrer=interruption_screen")
fill_in("lettings-log-earnings-field", with: income_under_soft_limit) fill_in("lettings-log-earnings-field", with: income_under_soft_limit)
choose("lettings-log-incfreq-1-field", allow_label_click: true) choose("lettings-log-incfreq-1-field", allow_label_click: true)
click_button("Save and continue") click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income-value-check") expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/income-amount-net-income-value-check")
expect(page).not_to have_content("You told us that the household’s income is £750.00 weekly") expect(page).not_to have_content("You told us that the household’s income is £750.00 weekly")
expect(page).to have_css(".govuk-notification-banner.govuk-notification-banner--success") expect(page).to have_css(".govuk-notification-banner.govuk-notification-banner--success")
end end
it "allows to fix the questions from different sections" do it "allows to fix the questions from different sections" do
expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income-value-check") expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/income-amount-net-income-value-check")
expect(page).to have_link("Change", href: "/lettings-logs/#{lettings_log.id}/net-income?referrer=interruption_screen").twice expect(page).to have_link("Change", href: "/lettings-logs/#{lettings_log.id}/income-amount?referrer=interruption_screen").twice
expect(page).to have_link("Change", href: "/lettings-logs/#{lettings_log.id}/person-1-working-situation?referrer=interruption_screen") expect(page).to have_link("Change", href: "/lettings-logs/#{lettings_log.id}/lead-tenant-working-situation?referrer=interruption_screen")
expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income-value-check") expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/income-amount-net-income-value-check")
click_link("Change", href: "/lettings-logs/#{lettings_log.id}/person-1-working-situation?referrer=interruption_screen") click_link("Change", href: "/lettings-logs/#{lettings_log.id}/lead-tenant-working-situation?referrer=interruption_screen")
expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/person-1-working-situation?referrer=interruption_screen") expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/lead-tenant-working-situation?referrer=interruption_screen")
choose("lettings-log-ecstat1-10-field", allow_label_click: true) choose("lettings-log-ecstat1-10-field", allow_label_click: true)
click_button("Save and continue") click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income-value-check") expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/income-amount-net-income-value-check")
expect(page).to have_css(".govuk-notification-banner.govuk-notification-banner--success") expect(page).to have_css(".govuk-notification-banner.govuk-notification-banner--success")
end end
it "returns the user back to the check_your_answers after fixing a validation from check_your_answers" do it "returns the user back to the check_your_answers after fixing a validation from check_your_answers" do
lettings_log.update!(earnings: income_under_soft_limit, incfreq: 1, net_income_value_check: 1) lettings_log.update!(earnings: income_under_soft_limit, incfreq: 1, net_income_value_check: 1)
visit("/lettings-logs/#{lettings_log.id}/income-and-benefits/check-answers") visit("/lettings-logs/#{lettings_log.id}/income-and-benefits/check-answers")
click_link("Change", href: "/lettings-logs/#{lettings_log.id}/net-income?referrer=check_answers", match: :first) click_link("Change", href: "/lettings-logs/#{lettings_log.id}/income-amount?referrer=check_answers", match: :first)
expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income?referrer=check_answers") expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/income-amount?referrer=check_answers")
fill_in("lettings-log-earnings-field", with: income_over_soft_limit) fill_in("lettings-log-earnings-field", with: income_over_soft_limit)
click_button("Save changes") click_button("Save changes")
expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income-value-check?referrer=check_answers") expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/income-amount-net-income-value-check?referrer=check_answers")
click_link("Change", href: "/lettings-logs/#{lettings_log.id}/net-income?referrer=interruption_screen", match: :first) click_link("Change", href: "/lettings-logs/#{lettings_log.id}/income-amount?referrer=interruption_screen", match: :first)
expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income?referrer=interruption_screen") expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/income-amount?referrer=interruption_screen")
fill_in("lettings-log-earnings-field", with: income_under_soft_limit) fill_in("lettings-log-earnings-field", with: income_under_soft_limit)
click_button("Save and continue") click_button("Save and continue")
expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income-value-check?referrer=check_answers") expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/income-amount-net-income-value-check?referrer=check_answers")
click_button("Confirm and continue") click_button("Confirm and continue")
expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/income-and-benefits/check-answers") expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/income-and-benefits/check-answers")
end end

4
spec/lib/tasks/set_sales_managing_organisation_spec.rb

@ -2,6 +2,8 @@ require "rails_helper"
require "rake" require "rake"
RSpec.describe "set_sales_managing_organisation" do RSpec.describe "set_sales_managing_organisation" do
include CollectionTimeHelper
describe ":set_sales_managing_organisation", type: :task do describe ":set_sales_managing_organisation", type: :task do
subject(:task) { Rake::Task["set_sales_managing_organisation"] } subject(:task) { Rake::Task["set_sales_managing_organisation"] }
@ -34,7 +36,7 @@ RSpec.describe "set_sales_managing_organisation" do
end end
it "skips validations" do it "skips validations" do
sales_log.saledate = Time.zone.local(2021, 3, 3) sales_log.saledate = archived_collection_start_date
sales_log.save!(validate: false) sales_log.save!(validate: false)
expect(sales_log.managing_organisation_id).to be_nil expect(sales_log.managing_organisation_id).to be_nil
expect(sales_log.status).to eq("in_progress") expect(sales_log.status).to eq("in_progress")

2
spec/lib/tasks/update_schemes_and_locations_from_csv_spec.rb

@ -611,8 +611,6 @@ RSpec.describe "bulk_update" do
supcharg: 50, supcharg: 50,
beds: 4, beds: 4,
lettype: 1, lettype: 1,
voiddate: Time.zone.local(2020, 4, 1),
mrcdate: Time.zone.local(2020, 4, 1),
period: 1) period: 1)
end end

135
spec/models/form_handler_spec.rb

@ -1,8 +1,10 @@
require "rails_helper" require "rails_helper"
RSpec.describe FormHandler do RSpec.describe FormHandler do
include CollectionTimeHelper
let(:form_handler) { described_class.instance } let(:form_handler) { described_class.instance }
let(:now) { Time.utc(2022, 9, 20) } let(:now) { current_collection_start_date }
around do |example| around do |example|
Timecop.freeze(now) do Timecop.freeze(now) do
@ -12,8 +14,6 @@ RSpec.describe FormHandler do
end end
context "when accessing a form in a different year" do context "when accessing a form in a different year" do
let(:now) { Time.utc(2021, 8, 3) }
it "is able to load a current lettings form" do it "is able to load a current lettings form" do
form = form_handler.get_form("current_lettings") form = form_handler.get_form("current_lettings")
expect(form).to be_a(Form) expect(form).to be_a(Form)
@ -34,65 +34,59 @@ RSpec.describe FormHandler do
expect(all_forms["current_sales"]).to be_a(Form) expect(all_forms["current_sales"]).to be_a(Form)
end end
context "when in 23/24 period or later" do it "does not load outdated forms" do
let(:now) { Time.utc(2023, 6, 7) } all_forms = form_handler.forms
expect(all_forms.keys).not_to include nil
it "does not load outdated forms" do end
all_forms = form_handler.forms
expect(all_forms.keys).not_to include nil
end
it "loads archived forms" do it "loads archived forms" do
all_forms = form_handler.forms all_forms = form_handler.forms
expect(all_forms.keys).to include("archived_sales") expect(all_forms.keys).to include("archived_sales")
expect(all_forms.keys).to include("archived_lettings") expect(all_forms.keys).to include("archived_lettings")
end
end end
end end
describe "Get specific form" do describe "Get specific form" do
let(:now) { Time.utc(2023, 9, 20) }
it "is able to load a current lettings form" do it "is able to load a current lettings form" do
form = form_handler.get_form("current_lettings") form = form_handler.get_form("current_lettings")
expect(form).to be_a(Form) expect(form).to be_a(Form)
expect(form.pages.count).to be_positive expect(form.pages.count).to be_positive
expect(form.name).to eq("2023_2024_lettings") expect(form.name).to eq("#{current_collection_start_year}_#{current_collection_end_year}_lettings")
end end
it "is able to load a previous lettings form" do it "is able to load a previous lettings form" do
form = form_handler.get_form("previous_lettings") form = form_handler.get_form("previous_lettings")
expect(form).to be_a(Form) expect(form).to be_a(Form)
expect(form.pages.count).to be_positive expect(form.pages.count).to be_positive
expect(form.name).to eq("2022_2023_lettings") expect(form.name).to eq("#{previous_collection_start_year}_#{previous_collection_end_year}_lettings")
end end
it "is able to load a archived lettings form" do it "is able to load a archived lettings form" do
form = form_handler.get_form("archived_lettings") form = form_handler.get_form("archived_lettings")
expect(form).to be_a(Form) expect(form).to be_a(Form)
expect(form.pages.count).to be_positive expect(form.pages.count).to be_positive
expect(form.name).to eq("2021_2022_lettings") expect(form.name).to eq("#{archived_collection_start_year}_#{archived_collection_end_year}_lettings")
end end
it "is able to load a current sales form" do it "is able to load a current sales form" do
form = form_handler.get_form("current_sales") form = form_handler.get_form("current_sales")
expect(form).to be_a(Form) expect(form).to be_a(Form)
expect(form.pages.count).to be_positive expect(form.pages.count).to be_positive
expect(form.name).to eq("2023_2024_sales") expect(form.name).to eq("#{current_collection_start_year}_#{current_collection_end_year}_sales")
end end
it "is able to load a previous sales form" do it "is able to load a previous sales form" do
form = form_handler.get_form("previous_sales") form = form_handler.get_form("previous_sales")
expect(form).to be_a(Form) expect(form).to be_a(Form)
expect(form.pages.count).to be_positive expect(form.pages.count).to be_positive
expect(form.name).to eq("2022_2023_sales") expect(form.name).to eq("#{previous_collection_start_year}_#{previous_collection_end_year}_sales")
end end
it "is able to load a archived sales form" do it "is able to load a archived sales form" do
form = form_handler.get_form("archived_sales") form = form_handler.get_form("archived_sales")
expect(form).to be_a(Form) expect(form).to be_a(Form)
expect(form.pages.count).to be_positive expect(form.pages.count).to be_positive
expect(form.name).to eq("2021_2022_sales") expect(form.name).to eq("#{archived_collection_start_year}_#{archived_collection_end_year}_sales")
end end
end end
@ -100,92 +94,92 @@ RSpec.describe FormHandler do
it "returns the latest form by date" do it "returns the latest form by date" do
form = form_handler.current_lettings_form form = form_handler.current_lettings_form
expect(form).to be_a(Form) expect(form).to be_a(Form)
expect(form.start_date.year).to eq(2022) expect(form.start_date.year).to eq(current_collection_start_year)
end end
end end
describe "Current collection start year" do describe "Current collection start year" do
context "when the date is after 1st of April" do context "when the date is after 1st of April" do
let(:now) { Time.utc(2023, 8, 3) } let(:now) { Time.utc(current_collection_start_year, 8, 3) }
it "returns the same year as the current start year" do it "returns the same year as the current start year" do
expect(form_handler.current_collection_start_year).to eq(2023) expect(form_handler.current_collection_start_year).to eq(current_collection_start_year)
end end
it "returns the correct current lettings form name" do it "returns the correct current lettings form name" do
expect(form_handler.form_name_from_start_year(2023, "lettings")).to eq("current_lettings") expect(form_handler.form_name_from_start_year(current_collection_start_year, "lettings")).to eq("current_lettings")
end end
it "returns the correct previous lettings form name" do it "returns the correct previous lettings form name" do
expect(form_handler.form_name_from_start_year(2022, "lettings")).to eq("previous_lettings") expect(form_handler.form_name_from_start_year(previous_collection_start_year, "lettings")).to eq("previous_lettings")
end end
it "returns the correct next lettings form name" do it "returns the correct next lettings form name" do
expect(form_handler.form_name_from_start_year(2024, "lettings")).to eq("next_lettings") expect(form_handler.form_name_from_start_year(next_collection_start_year, "lettings")).to eq("next_lettings")
end end
it "returns the correct archived lettings form name" do it "returns the correct archived lettings form name" do
expect(form_handler.form_name_from_start_year(2021, "lettings")).to eq("archived_lettings") expect(form_handler.form_name_from_start_year(archived_collection_start_year, "lettings")).to eq("archived_lettings")
end end
it "returns the correct current sales form name" do it "returns the correct current sales form name" do
expect(form_handler.form_name_from_start_year(2023, "sales")).to eq("current_sales") expect(form_handler.form_name_from_start_year(current_collection_start_year, "sales")).to eq("current_sales")
end end
it "returns the correct previous sales form name" do it "returns the correct previous sales form name" do
expect(form_handler.form_name_from_start_year(2022, "sales")).to eq("previous_sales") expect(form_handler.form_name_from_start_year(previous_collection_start_year, "sales")).to eq("previous_sales")
end end
it "returns the correct next sales form name" do it "returns the correct next sales form name" do
expect(form_handler.form_name_from_start_year(2024, "sales")).to eq("next_sales") expect(form_handler.form_name_from_start_year(next_collection_start_year, "sales")).to eq("next_sales")
end end
it "returns the correct archived sales form name" do it "returns the correct archived sales form name" do
expect(form_handler.form_name_from_start_year(2021, "sales")).to eq("archived_sales") expect(form_handler.form_name_from_start_year(archived_collection_start_year, "sales")).to eq("archived_sales")
end end
it "returns the correct current start date" do it "returns the correct current start date" do
expect(form_handler.current_collection_start_date).to eq(Time.zone.local(2023, 4, 1)) expect(form_handler.current_collection_start_date).to eq(current_collection_start_date)
end end
end end
context "with the date before 1st of April" do context "with the date before 1st of April" do
let(:now) { Time.utc(2023, 2, 3) } let(:now) { Time.utc(current_collection_end_year, 2, 3) }
it "returns the previous year as the current start year" do it "returns the previous year as the current start year" do
expect(form_handler.current_collection_start_year).to eq(2022) expect(form_handler.current_collection_start_year).to eq(current_collection_start_year)
end end
it "returns the correct current lettings form name" do it "returns the correct current lettings form name" do
expect(form_handler.form_name_from_start_year(2022, "lettings")).to eq("current_lettings") expect(form_handler.form_name_from_start_year(current_collection_start_year, "lettings")).to eq("current_lettings")
end end
it "returns the correct previous lettings form name" do it "returns the correct previous lettings form name" do
expect(form_handler.form_name_from_start_year(2021, "lettings")).to eq("previous_lettings") expect(form_handler.form_name_from_start_year(previous_collection_start_year, "lettings")).to eq("previous_lettings")
end end
it "returns the correct next lettings form name" do it "returns the correct next lettings form name" do
expect(form_handler.form_name_from_start_year(2023, "lettings")).to eq("next_lettings") expect(form_handler.form_name_from_start_year(next_collection_start_year, "lettings")).to eq("next_lettings")
end end
it "returns the correct archived lettings form name" do it "returns the correct archived lettings form name" do
expect(form_handler.form_name_from_start_year(2020, "lettings")).to eq("archived_lettings") expect(form_handler.form_name_from_start_year(archived_collection_start_year, "lettings")).to eq("archived_lettings")
end end
it "returns the correct current sales form name" do it "returns the correct current sales form name" do
expect(form_handler.form_name_from_start_year(2022, "sales")).to eq("current_sales") expect(form_handler.form_name_from_start_year(current_collection_start_year, "sales")).to eq("current_sales")
end end
it "returns the correct previous sales form name" do it "returns the correct previous sales form name" do
expect(form_handler.form_name_from_start_year(2021, "sales")).to eq("previous_sales") expect(form_handler.form_name_from_start_year(previous_collection_start_year, "sales")).to eq("previous_sales")
end end
it "returns the correct next sales form name" do it "returns the correct next sales form name" do
expect(form_handler.form_name_from_start_year(2023, "sales")).to eq("next_sales") expect(form_handler.form_name_from_start_year(next_collection_start_year, "sales")).to eq("next_sales")
end end
it "returns the correct archived sales form name" do it "returns the correct archived sales form name" do
expect(form_handler.form_name_from_start_year(2020, "sales")).to eq("archived_sales") expect(form_handler.form_name_from_start_year(archived_collection_start_year, "sales")).to eq("archived_sales")
end end
end end
end end
@ -199,65 +193,20 @@ RSpec.describe FormHandler do
it "correctly sets form type and start year" do it "correctly sets form type and start year" do
form = form_handler.forms["current_lettings"] form = form_handler.forms["current_lettings"]
expect(form.type).to eq("lettings") expect(form.type).to eq("lettings")
expect(form.start_date.year).to eq(2022) expect(form.start_date.year).to eq(current_collection_start_year)
end end
# rubocop:disable RSpec/PredicateMatcher # rubocop:disable RSpec/PredicateMatcher
describe "#in_crossover_period?" do describe "#in_crossover_period?" do
context "when not in overlapping period" do context "when not in overlapping period" do
it "returns false" do it "returns false" do
expect(form_handler.in_crossover_period?(now: Date.new(2023, 1, 1))).to be_falsey expect(form_handler.in_crossover_period?(now: Date.new(current_collection_start_year, 1, 1))).to be_falsey
end end
end end
context "when in overlapping period" do context "when in overlapping period" do
it "returns true" do it "returns true" do
expect(form_handler.in_crossover_period?(now: Date.new(2022, 6, 1))).to be_truthy expect(form_handler.in_crossover_period?(now: Date.new(current_collection_start_year, 6, 1))).to be_truthy
end
end
end
describe "lettings_forms" do
context "when current and previous forms are defined in JSON (current collection start year before 2023)" do
let(:now) { Time.utc(2022, 9, 20) }
it "creates a next_lettings form from ruby form objects" do
expect(form_handler.lettings_forms["previous_lettings"]).to be_present
expect(form_handler.lettings_forms["previous_lettings"].start_date.year).to eq(2021)
expect(form_handler.lettings_forms["current_lettings"]).to be_present
expect(form_handler.lettings_forms["current_lettings"].start_date.year).to eq(2022)
expect(form_handler.lettings_forms["next_lettings"]).to be_present
expect(form_handler.lettings_forms["next_lettings"].start_date.year).to eq(2023)
end
end
context "when only previous form is defined in JSON (current collection start year 2023)" do
let(:now) { Time.utc(2023, 9, 20) }
it "creates current_lettings and next_lettings forms from ruby form objects" do
expect(form_handler.lettings_forms["archived_lettings"]).to be_present
expect(form_handler.lettings_forms["archived_lettings"].start_date.year).to eq(2021)
expect(form_handler.lettings_forms["previous_lettings"]).to be_present
expect(form_handler.lettings_forms["previous_lettings"].start_date.year).to eq(2022)
expect(form_handler.lettings_forms["current_lettings"]).to be_present
expect(form_handler.lettings_forms["current_lettings"].start_date.year).to eq(2023)
expect(form_handler.lettings_forms["next_lettings"]).to be_present
expect(form_handler.lettings_forms["next_lettings"].start_date.year).to eq(2024)
end
end
context "when only archived form is defined in JSON (current collection start year 2024 onwards)" do
let(:now) { Time.utc(2024, 5, 20) }
it "creates previous_lettings, current_lettings and next_lettings forms from ruby form objects and archived form from json" do
expect(form_handler.lettings_forms["archived_lettings"]).to be_present
expect(form_handler.lettings_forms["archived_lettings"].start_date.year).to eq(2022)
expect(form_handler.lettings_forms["previous_lettings"]).to be_present
expect(form_handler.lettings_forms["previous_lettings"].start_date.year).to eq(2023)
expect(form_handler.lettings_forms["current_lettings"]).to be_present
expect(form_handler.lettings_forms["current_lettings"].start_date.year).to eq(2024)
expect(form_handler.lettings_forms["next_lettings"]).to be_present
expect(form_handler.lettings_forms["next_lettings"].start_date.year).to eq(2025)
end end
end end
end end

316
spec/models/lettings_log_spec.rb

@ -7,18 +7,6 @@ RSpec.describe LettingsLog do
let(:different_managing_organisation) { create(:organisation) } let(:different_managing_organisation) { create(:organisation) }
let(:owning_organisation) { create(:organisation, rent_periods: [2]) } let(:owning_organisation) { create(:organisation, rent_periods: [2]) }
let(:assigned_to_user) { create(:user, organisation: owning_organisation) } let(:assigned_to_user) { create(:user, organisation: owning_organisation) }
let(:fake_2021_2022_form) { Form.new("spec/fixtures/forms/2021_2022.json") }
around do |example|
Timecop.freeze(Time.utc(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
end
before do
allow(FormHandler.instance).to receive(:current_lettings_form).and_return(fake_2021_2022_form)
end
include_examples "shared examples for derived fields", :lettings_log include_examples "shared examples for derived fields", :lettings_log
include_examples "shared log examples", :lettings_log include_examples "shared log examples", :lettings_log
@ -40,16 +28,8 @@ RSpec.describe LettingsLog do
describe "#form" do describe "#form" do
let(:lettings_log) { build(:lettings_log, assigned_to: assigned_to_user) } let(:lettings_log) { build(:lettings_log, assigned_to: assigned_to_user) }
let(:lettings_log_2) { build(:lettings_log, startdate: Time.zone.local(2022, 1, 1), assigned_to: assigned_to_user) } let(:lettings_log_2) { build(:lettings_log, startdate: previous_collection_start_date, assigned_to: assigned_to_user) }
let(:lettings_log_year_2) { build(:lettings_log, startdate: Time.zone.local(2023, 5, 1), assigned_to: assigned_to_user) } let(:lettings_log_year_2) { build(:lettings_log, startdate: next_collection_start_date, assigned_to: assigned_to_user) }
before do
Timecop.freeze(2023, 1, 1)
end
after do
Timecop.unfreeze
end
it "returns the correct form based on the start date" do 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
@ -61,11 +41,11 @@ RSpec.describe LettingsLog do
end end
context "when a date outside the collection window is passed" do context "when a date outside the collection window is passed" do
let(:lettings_log) { build(:lettings_log, startdate: Time.zone.local(2015, 1, 1), assigned_to: assigned_to_user) } let(:lettings_log) { build(:lettings_log, startdate: current_collection_start_date - 10.years, assigned_to: assigned_to_user) }
it "returns the first form" do it "returns the current form as fallback" do
expect(lettings_log.form).to be_a(Form) expect(lettings_log.form).to be_a(Form)
expect(lettings_log.form.start_date.year).to eq(2021) expect(lettings_log.form.start_date.year).to eq(current_collection_start_year)
end end
end end
end end
@ -276,20 +256,22 @@ RSpec.describe LettingsLog do
assigned_to: assigned_to_user, assigned_to: assigned_to_user,
postcode_full: "M1 1AE", postcode_full: "M1 1AE",
ppostcode_full: "M2 2AE", ppostcode_full: "M2 2AE",
startdate: Time.gm(2021, 10, 10), startdate: Time.zone.today,
mrcdate: Time.gm(2021, 5, 4), mrcdate: Time.zone.today - 1.week,
voiddate: Time.gm(2021, 3, 3), voiddate: Time.zone.today - 2.weeks,
needstype: 1,
renewal: 0,
declaration: 1,
net_income_known: 2, # refused net_income_known: 2, # refused
hhmemb: 7, hhmemb: 7,
rent_type: 4, rent_type: 4,
hb: 1, hb: 1,
hbrentshortfall: 1, hbrentshortfall: 1,
created_at: Time.utc(2022, 2, 8, 16, 52, 15),
) )
end end
def check_postcode_fields(postcode_field) def check_postcode_fields(postcode_field)
record_from_db = described_class.find(lettings_log.id) record_from_db = described_class.find(address_lettings_log.id)
expect(address_lettings_log[postcode_field]).to eq("M1 1AE") expect(address_lettings_log[postcode_field]).to eq("M1 1AE")
expect(record_from_db[postcode_field]).to eq("M1 1AE") expect(record_from_db[postcode_field]).to eq("M1 1AE")
end end
@ -313,6 +295,7 @@ RSpec.describe LettingsLog do
assigned_to: assigned_to_user, assigned_to: assigned_to_user,
postcode_known: 1, postcode_known: 1,
postcode_full: "M1 1AE", postcode_full: "M1 1AE",
manual_address_entry_selected: true,
}) })
end end
@ -490,19 +473,11 @@ RSpec.describe LettingsLog do
end end
context "when a lettings log is a supported housing log" do context "when a lettings log is a supported housing log" do
let(:real_2021_2022_form) { Form.new("config/forms/2021_2022.json") }
before do before do
lettings_log.needstype = 2 lettings_log.needstype = 2
allow(FormHandler.instance).to receive(:get_form).and_return(real_2021_2022_form)
end end
describe "when changing a log's scheme and hence calling reset_scheme_location!" do describe "when changing a log's scheme and hence calling reset_scheme_location!" do
before do
Timecop.return
Singleton.__init__(FormHandler)
end
context "when there is one valid location and many invalid locations in the new scheme" do context "when there is one valid location and many invalid locations in the new scheme" do
let(:scheme) { create(:scheme) } let(:scheme) { create(:scheme) }
let(:invalid_location_1) { create(:location, scheme:, startdate: Time.zone.today + 3.weeks) } let(:invalid_location_1) { create(:location, scheme:, startdate: Time.zone.today + 3.weeks) }
@ -549,13 +524,7 @@ RSpec.describe LettingsLog do
let!(:location) { create(:location, scheme:) } let!(:location) { create(:location, scheme:) }
before do before do
Timecop.freeze(Time.zone.local(2022, 4, 2)) lettings_log.update!(startdate: current_collection_start_date + 1.day, scheme:, voiddate: nil, mrcdate: nil)
Singleton.__init__(FormHandler)
lettings_log.update!(startdate: Time.zone.local(2022, 4, 2), scheme:)
end
after do
Timecop.unfreeze
end end
it "derives the scheme location" do it "derives the scheme location" do
@ -579,22 +548,11 @@ RSpec.describe LettingsLog do
Singleton.__init__(FormHandler) Singleton.__init__(FormHandler)
end end
context "with 22/23" do let(:startdate) { current_collection_start_date }
let(:startdate) { Time.zone.local(2022, 4, 2) }
it "returns the correct la" do
expect(lettings_log["location_id"]).to eq(location.id)
expect(lettings_log.la).to eq("E07000030")
end
end
context "with 23/24" do
let(:startdate) { Time.zone.local(2023, 4, 2) }
it "returns the correct la" do it "returns the correct la" do
expect(lettings_log["location_id"]).to eq(location.id) expect(lettings_log["location_id"]).to eq(location.id)
expect(lettings_log.la).to eq("E06000063") expect(lettings_log.la).to eq("E06000063")
end
end end
end end
@ -657,13 +615,9 @@ RSpec.describe LettingsLog do
context "and the location no local authorities associated with the location_code" do context "and the location no local authorities associated with the location_code" do
before do before do
Timecop.freeze(Time.zone.local(2022, 4, 2))
location.update!(location_code: "E01231231") location.update!(location_code: "E01231231")
lettings_log.update!(location:) lettings_log.update_columns(la: nil)
end lettings_log.reload
after do
Timecop.return
end end
it "returns the correct la" do it "returns the correct la" do
@ -690,7 +644,7 @@ RSpec.describe LettingsLog do
Singleton.__init__(FormHandler) Singleton.__init__(FormHandler)
end end
context "with 25/26" do context "with 25/26", metadata: { year: 25 } do
let(:startdate) { Time.zone.local(2025, 4, 2) } let(:startdate) { Time.zone.local(2025, 4, 2) }
it "returns the postcode from the location" do it "returns the postcode from the location" do
@ -699,7 +653,7 @@ RSpec.describe LettingsLog do
end end
end end
context "with 26/27" do context "with 26/27", metadata: { year: 26 } do
let(:startdate) { Time.zone.local(2026, 4, 2) } let(:startdate) { Time.zone.local(2026, 4, 2) }
it "returns the postcode from the log itself" do it "returns the postcode from the log itself" do
@ -712,24 +666,13 @@ RSpec.describe LettingsLog do
context "and the log only has a postcode set on the location" do context "and the log only has a postcode set on the location" do
before do before do
location.update!(postcode: "AA1 1AA") location.update!(postcode: "AA1 1AA")
Timecop.freeze(startdate) lettings_log.update!(postcode_full: nil)
Singleton.__init__(FormHandler)
lettings_log.update!(startdate:)
lettings_log.reload lettings_log.reload
end end
after do it "returns the postcode from the location" do
Timecop.unfreeze expect(lettings_log["location_id"]).to eq(location.id)
Singleton.__init__(FormHandler) expect(lettings_log.postcode_full).to eq("AA1 1AA")
end
context "with 26/27" do
let(:startdate) { Time.zone.local(2026, 4, 2) }
it "returns the LA from the location" do
expect(lettings_log["location_id"]).to eq(location.id)
expect(lettings_log.postcode_full).to eq("AA1 1AA")
end
end end
end end
end end
@ -929,23 +872,13 @@ RSpec.describe LettingsLog do
managing_organisation: owning_organisation, managing_organisation: owning_organisation,
owning_organisation:, owning_organisation:,
assigned_to: assigned_to_user, assigned_to: assigned_to_user,
startdate: Time.zone.local(2024, 4, 10), startdate: current_collection_start_date + 9.days,
needstype: 1, needstype: 1,
renewal: 1, renewal: 1,
rent_type: 1, rent_type: 1,
}) })
end end
before do
Timecop.freeze(Time.zone.local(2024, 4, 10))
Singleton.__init__(FormHandler)
end
after do
Timecop.return
Singleton.__init__(FormHandler)
end
it "correctly derives nationality_all when it's UK" do it "correctly derives nationality_all when it's UK" do
expect { lettings_log.update!(nationality_all_group: 826, declaration: 1) }.to change(lettings_log, :nationality_all).to 826 expect { lettings_log.update!(nationality_all_group: 826, declaration: 1) }.to change(lettings_log, :nationality_all).to 826
end end
@ -976,16 +909,6 @@ RSpec.describe LettingsLog do
end end
context "when the log changes from new build to not new build" do context "when the log changes from new build to not new build" do
before do
allow(FormHandler.instance).to receive(:current_lettings_form).and_call_original
Timecop.freeze(2025, 5, 1)
Singleton.__init__(FormHandler)
end
after do
Timecop.unfreeze
end
context "and the address is entered" do context "and the address is entered" do
let(:address_lettings_log) do let(:address_lettings_log) do
create(:lettings_log, create(:lettings_log,
@ -1054,16 +977,6 @@ RSpec.describe LettingsLog do
end end
context "when the log changes from not new build to new build" do context "when the log changes from not new build to new build" do
before do
allow(FormHandler.instance).to receive(:current_lettings_form).and_call_original
Timecop.freeze(2025, 5, 1)
Singleton.__init__(FormHandler)
end
after do
Timecop.unfreeze
end
context "and the uprn is selected" do context "and the uprn is selected" do
let(:address_lettings_log) do let(:address_lettings_log) do
create(:lettings_log, create(:lettings_log,
@ -1163,17 +1076,18 @@ RSpec.describe LettingsLog do
end end
describe "optional fields" do describe "optional fields" do
let(:lettings_log) { create(:lettings_log) }
context "when tshortfall is marked as not known" do context "when tshortfall is marked as not known" do
let(:lettings_log) do
build(:lettings_log, hb: 1, hbrentshortfall: 1, period: 1, tshortfall: nil, tshortfall_known: 1)
end
it "makes tshortfall optional" do it "makes tshortfall optional" do
lettings_log.update!({ tshortfall: nil, tshortfall_known: 1 })
expect(lettings_log.optional_fields).to include("tshortfall") expect(lettings_log.optional_fields).to include("tshortfall")
end end
end end
context "when startdate is after 2023" do context "when startdate is in the current collection year" do
let(:lettings_log) { build(:lettings_log, startdate: Time.zone.parse("2023-07-01")) } let(:lettings_log) { build(:lettings_log, startdate: current_collection_start_date + 1.day) }
it "returns optional fields" do it "returns optional fields" do
expect(lettings_log.optional_fields).to eq(%w[ expect(lettings_log.optional_fields).to eq(%w[
@ -1194,6 +1108,7 @@ RSpec.describe LettingsLog do
let(:lettings_log) do let(:lettings_log) do
create( create(
:lettings_log, :lettings_log,
:setup_completed,
renewal: 0, renewal: 0,
rsnvac: 5, rsnvac: 5,
first_time_property_let_as_social_housing: 0, first_time_property_let_as_social_housing: 0,
@ -1229,15 +1144,15 @@ RSpec.describe LettingsLog do
context "when a question that has already been answered, no longer has met dependencies" do context "when a question that has already been answered, no longer has met dependencies" do
let(:lettings_log) { create(:lettings_log, :in_progress, cbl: 1, preg_occ: 2, wchair: 2) } let(:lettings_log) { create(:lettings_log, :in_progress, cbl: 1, preg_occ: 2, wchair: 2) }
it "clears the answer" do it "does not clear the answer" do
expect { lettings_log.update!(preg_occ: nil) }.to change(lettings_log, :cbl).from(1).to(nil) expect { lettings_log.update!(preg_occ: nil) }.not_to change(lettings_log, :cbl)
end end
context "when the question type does not have answer options" do context "when the question type does not have answer options" do
let(:lettings_log) { create(:lettings_log, :in_progress, housingneeds_a: 1, age1: 19) } let(:lettings_log) { create(:lettings_log, :in_progress, housingneeds_a: 1, age1: 19) }
it "clears the answer" do it "does not clear the answer" do
expect { lettings_log.update!(housingneeds_a: 0) }.to change(lettings_log, :age1).from(19).to(nil) expect { lettings_log.update!(housingneeds_a: 0) }.not_to change(lettings_log, :age1)
end end
end end
@ -1250,31 +1165,6 @@ RSpec.describe LettingsLog do
end end
end end
context "with two pages having the same question key, only one's dependency is met" do
let(:lettings_log) { create(:lettings_log, :in_progress, cbl: 0, preg_occ: 2, wchair: 2) }
it "does not clear the value for answers that apply to both pages" do
expect(lettings_log.cbl).to eq(0)
end
it "does clear the value for answers that do not apply for invalidated page" do
lettings_log.update!({ cbl: 1 })
lettings_log.update!({ preg_occ: 1 })
expect(lettings_log.cbl).to be_nil
end
end
context "when a non select question associated with several pages is routed to" do
let(:lettings_log) { create(:lettings_log, :in_progress, period: 2, needstype: 1, renewal: 0) }
it "does not clear the answer value" do
lettings_log.update!({ unitletas: 1 })
lettings_log.reload
expect(lettings_log.unitletas).to eq(1)
end
end
context "when the lettings log does not have a valid form set yet" do context "when the lettings log does not have a valid form set yet" do
let(:lettings_log) { create(:lettings_log) } let(:lettings_log) { create(:lettings_log) }
@ -1338,12 +1228,12 @@ RSpec.describe LettingsLog do
it "clears void date value" do it "clears void date value" do
lettings_log.update!(startdate: Time.zone.yesterday) lettings_log.update!(startdate: Time.zone.yesterday)
lettings_log.reload lettings_log.reload
expect(lettings_log.startdate).to eq(Time.zone.yesterday) expect(lettings_log.startdate.to_date).to eq(Time.zone.yesterday.to_date)
expect(lettings_log.voiddate).to be_nil expect(lettings_log.voiddate).to be_nil
end end
it "does not impact other validations" do it "does not impact other validations" do
expect { lettings_log.update!(startdate: Time.zone.yesterday, referral: 8, rsnvac: 9) } expect { lettings_log.update!(startdate: Time.zone.yesterday, first_time_property_let_as_social_housing: 0, referral: 8, rsnvac: 9) }
.to raise_error(ActiveRecord::RecordInvalid, /#{I18n.t('validations.lettings.property.rsnvac.referral_invalid')}/) .to raise_error(ActiveRecord::RecordInvalid, /#{I18n.t('validations.lettings.property.rsnvac.referral_invalid')}/)
end end
end end
@ -1352,21 +1242,12 @@ RSpec.describe LettingsLog do
it "clears major repairs date value" do it "clears major repairs date value" do
lettings_log.update!(startdate: Time.zone.yesterday) lettings_log.update!(startdate: Time.zone.yesterday)
lettings_log.reload lettings_log.reload
expect(lettings_log.startdate).to eq(Time.zone.yesterday) expect(lettings_log.startdate.to_date).to eq(Time.zone.yesterday.to_date)
expect(lettings_log.mrcdate).to be_nil expect(lettings_log.mrcdate).to be_nil
end end
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
@ -1379,7 +1260,7 @@ RSpec.describe LettingsLog do
end end
it "does not impact other validations" do it "does not impact other validations" do
expect { lettings_log.update!(startdate: Time.zone.yesterday, referral: 8, rsnvac: 9) } expect { lettings_log.update!(startdate: Time.zone.yesterday, first_time_property_let_as_social_housing: 0, referral: 8, rsnvac: 9) }
.to raise_error(ActiveRecord::RecordInvalid, /#{I18n.t('validations.lettings.property.rsnvac.referral_invalid')}/) .to raise_error(ActiveRecord::RecordInvalid, /#{I18n.t('validations.lettings.property.rsnvac.referral_invalid')}/)
end end
end end
@ -1389,16 +1270,16 @@ RSpec.describe LettingsLog do
context "and the new startdate triggers void date validation" do context "and the new startdate triggers void date validation" do
it "doesn't clear void date value" do it "doesn't clear void date value" do
expect { lettings_log.update!(startdate: Time.zone.yesterday) }.to raise_error(ActiveRecord::RecordInvalid, /Enter a void date that is before the tenancy start date/) expect { lettings_log.update!(startdate: Time.zone.yesterday) }.to raise_error(ActiveRecord::RecordInvalid, /Enter a void date that is before the tenancy start date/)
expect(lettings_log.startdate).to eq(Time.zone.yesterday) expect(lettings_log.startdate.to_date).to eq(Time.zone.yesterday.to_date)
expect(lettings_log.voiddate).to eq(Time.zone.today) expect(lettings_log.voiddate.to_date).to eq(Time.zone.today.to_date)
end end
end end
context "and the new startdate triggers major repairs date validation" do context "and the new startdate triggers major repairs date validation" do
it "doesn't clear major repairs date value" do it "doesn't clear major repairs date value" do
expect { lettings_log.update!(startdate: Time.zone.yesterday) }.to raise_error(ActiveRecord::RecordInvalid, /Enter a major repairs date that is before the tenancy start date/) expect { lettings_log.update!(startdate: Time.zone.yesterday) }.to raise_error(ActiveRecord::RecordInvalid, /Enter a major repairs date that is before the tenancy start date/)
expect(lettings_log.startdate).to eq(Time.zone.yesterday) expect(lettings_log.startdate.to_date).to eq(Time.zone.yesterday.to_date)
expect(lettings_log.mrcdate).to eq(Time.zone.today) expect(lettings_log.mrcdate.to_date).to eq(Time.zone.today.to_date)
end end
end end
@ -1416,7 +1297,7 @@ RSpec.describe LettingsLog do
describe "tshortfall_unknown?" do describe "tshortfall_unknown?" do
context "when tshortfall is nil" do context "when tshortfall is nil" do
let(:lettings_log) { create(:lettings_log, :in_progress, tshortfall_known: nil) } let(:lettings_log) { create(:lettings_log, :in_progress, hb: 1, hbrentshortfall: 1, period: 1, tshortfall_known: nil) }
it "returns false" do it "returns false" do
expect(lettings_log.tshortfall_unknown?).to be false expect(lettings_log.tshortfall_unknown?).to be false
@ -1424,15 +1305,15 @@ RSpec.describe LettingsLog do
end end
context "when tshortfall is No" do context "when tshortfall is No" do
let(:lettings_log) { create(:lettings_log, :in_progress, tshortfall_known: 1) } let(:lettings_log) { create(:lettings_log, :in_progress, hb: 1, hbrentshortfall: 1, period: 1, tshortfall_known: 1) }
it "returns false" do it "returns true" do
expect(lettings_log.tshortfall_unknown?).to be true expect(lettings_log.tshortfall_unknown?).to be true
end end
end end
context "when tshortfall is Yes" do context "when tshortfall is Yes" do
let(:lettings_log) { create(:lettings_log, :in_progress, tshortfall_known: 0) } let(:lettings_log) { create(:lettings_log, :in_progress, hb: 1, hbrentshortfall: 1, period: 1, tshortfall_known: 0) }
it "returns false" do it "returns false" do
expect(lettings_log.tshortfall_unknown?).to be false expect(lettings_log.tshortfall_unknown?).to be false
@ -1466,13 +1347,13 @@ RSpec.describe LettingsLog do
soft_max: 400, soft_max: 400,
hard_min: 50, hard_min: 50,
hard_max: 500, hard_max: 500,
start_year: 2021, start_year: current_collection_start_year,
) )
lettings_log.la = "E07000223" lettings_log.la = "E07000223"
lettings_log.lettype = 1 lettings_log.lettype = 1
lettings_log.beds = 1 lettings_log.beds = 1
lettings_log.startdate = Time.zone.local(2021, 10, 10) lettings_log.startdate = current_collection_start_date + 6.months
end end
context "when period is weekly for 52 weeks" do context "when period is weekly for 52 weeks" do
@ -1501,17 +1382,22 @@ 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), mrcdate: Time.utc(2021, 5, 3), voiddate: Time.utc(2021, 5, 3), assigned_to: assigned_to_user) } # These examples need logs in both the previous and the current collection year,
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), assigned_to: assigned_to_user) } # so we have to enforce we are in the crossover period
around do |example|
Timecop.freeze(current_collection_start_date) do
Singleton.__init__(FormHandler)
example.run
end
Singleton.__init__(FormHandler)
end
let!(:lettings_log_1) { create(:lettings_log, :in_progress, startdate: previous_collection_start_date + 1.month, mrcdate: previous_collection_start_date, voiddate: previous_collection_start_date, assigned_to: assigned_to_user) }
let!(:lettings_log_2) { create(:lettings_log, :completed, startdate: previous_collection_start_date + 1.month, mrcdate: previous_collection_start_date, voiddate: previous_collection_start_date, assigned_to: assigned_to_user) }
let(:postcode_to_search) { "SW1A 0AA" } let(:postcode_to_search) { "SW1A 0AA" }
before do before do
Timecop.freeze(Time.utc(2022, 6, 3)) create(:lettings_log, startdate: Time.zone.today)
create(:lettings_log, startdate: Time.utc(2022, 6, 3))
end
after do
Timecop.unfreeze
end end
context "when searching logs" do context "when searching logs" do
@ -1689,62 +1575,46 @@ RSpec.describe LettingsLog do
end end
context "when filtering by year" do context "when filtering by year" do
before do
Timecop.freeze(Time.utc(2021, 5, 3))
end
after do
Timecop.unfreeze
end
it "allows filtering on a single year" do it "allows filtering on a single year" do
expect(described_class.filter_by_years(%w[2021]).count).to eq(2) expect(described_class.filter_by_years([previous_collection_start_year.to_s]).count).to eq(2)
end end
it "allows filtering by multiple years using OR" do it "allows filtering by multiple years using OR" do
expect(described_class.filter_by_years(%w[2021 2022]).count).to eq(3) expect(described_class.filter_by_years([previous_collection_start_year.to_s, current_collection_start_year.to_s]).count).to eq(3)
end end
it "can filter by year(s) AND status" do it "can filter by year(s) AND status" do
expect(described_class.filter_by_years(%w[2021 2022]).filter_by_status("completed").count).to eq(1) expect(described_class.filter_by_years([previous_collection_start_year.to_s, current_collection_start_year.to_s]).filter_by_status("completed").count).to eq(1)
end end
it "filters based on date boundaries correctly" do it "filters based on date boundaries correctly" do
lettings_log_1.startdate = Time.zone.local(2022, 4, 1) lettings_log_1.startdate = current_collection_start_date
lettings_log_1.save!(validate: false) lettings_log_1.save!(validate: false)
lettings_log_2.startdate = Time.zone.local(2022, 3, 31) lettings_log_2.startdate = current_collection_start_date - 1.day
lettings_log_2.save!(validate: false) lettings_log_2.save!(validate: false)
expect(described_class.filter_by_years(%w[2021]).count).to eq(1) expect(described_class.filter_by_years([previous_collection_start_year.to_s]).count).to eq(1)
expect(described_class.filter_by_years(%w[2022]).count).to eq(2) expect(described_class.filter_by_years([current_collection_start_year.to_s]).count).to eq(2)
end end
end end
context "when filtering by year or nil" do context "when filtering by year or nil" do
before do
Timecop.freeze(Time.utc(2021, 5, 3))
end
after do
Timecop.unfreeze
end
it "allows filtering on a single year or nil" do it "allows filtering on a single year or nil" do
lettings_log_1.startdate = nil lettings_log_1.startdate = nil
lettings_log_1.save!(validate: false) lettings_log_1.save!(validate: false)
expect(described_class.filter_by_years_or_nil(%w[2021]).count).to eq(2) expect(described_class.filter_by_years_or_nil([previous_collection_start_year.to_s]).count).to eq(2)
end end
it "allows filtering by multiple years or nil using OR" do it "allows filtering by multiple years or nil using OR" do
lettings_log_1.startdate = nil lettings_log_1.startdate = nil
lettings_log_1.save!(validate: false) lettings_log_1.save!(validate: false)
expect(described_class.filter_by_years_or_nil(%w[2021 2022]).count).to eq(3) expect(described_class.filter_by_years_or_nil([previous_collection_start_year.to_s, current_collection_start_year.to_s]).count).to eq(3)
end end
it "can filter by year(s) AND status" do it "can filter by year(s) AND status" do
lettings_log_2.startdate = nil lettings_log_2.startdate = nil
lettings_log_2.save!(validate: false) lettings_log_2.save!(validate: false)
expect(described_class.filter_by_years_or_nil(%w[2021 2022]).filter_by_status("in_progress").count).to eq(3) expect(described_class.filter_by_years_or_nil([previous_collection_start_year.to_s, current_collection_start_year.to_s]).filter_by_status("in_progress").count).to eq(3)
end end
end end
@ -2107,28 +1977,23 @@ RSpec.describe LettingsLog do
context "when there is a duplicate supported housing log" do context "when there is a duplicate supported housing log" do
let(:scheme) { create(:scheme, owning_organisation: organisation) } let(:scheme) { create(:scheme, owning_organisation: organisation) }
let(:location) { create(:location, scheme:) } let(:location) { create(:location, scheme:) }
let(:location_2) { create(:location, scheme:) }
let!(:supported_housing_log) { create(:lettings_log, :duplicate, needstype: 2, location:, scheme:, owning_organisation: organisation) } let!(:supported_housing_log) { create(:lettings_log, :duplicate, needstype: 2, location:, scheme:, owning_organisation: organisation) }
let!(:duplicate_supported_housing_log) { create(:lettings_log, :duplicate, needstype: 2, location:, scheme:, owning_organisation: organisation) } let!(:duplicate_supported_housing_log) { create(:lettings_log, :duplicate, needstype: 2, location:, scheme:, owning_organisation: organisation) }
it "returns the log as a duplicate" do it "returns the log as a duplicate" do
expect(duplicate_sets.count).to eq(2) expect(duplicate_sets).to contain_exactly(
expect(duplicate_sets.first).to contain_exactly(log.id, duplicate_log.id) contain_exactly(log.id, duplicate_log.id),
expect(duplicate_sets.second).to contain_exactly(duplicate_supported_housing_log.id, supported_housing_log.id) contain_exactly(duplicate_supported_housing_log.id, supported_housing_log.id),
end )
it "does not return the log if the locations are different" do
duplicate_supported_housing_log.update!(location: location_2)
expect(duplicate_sets.count).to eq(1)
expect(duplicate_sets.first).to contain_exactly(log.id, duplicate_log.id)
end end
it "does not compare tcharge if there are no household charges" do it "does not compare tcharge if there are no household charges" do
supported_housing_log.update!(household_charge: 1, supcharg: nil, brent: nil, scharge: nil, pscharge: nil, tcharge: nil, owning_organisation: organisation) supported_housing_log.update!(household_charge: 1, supcharg: nil, brent: nil, scharge: nil, pscharge: nil, tcharge: nil, owning_organisation: organisation)
duplicate_supported_housing_log.update!(household_charge: 1, supcharg: nil, brent: nil, scharge: nil, pscharge: nil, tcharge: nil, owning_organisation: organisation) duplicate_supported_housing_log.update!(household_charge: 1, supcharg: nil, brent: nil, scharge: nil, pscharge: nil, tcharge: nil, owning_organisation: organisation)
expect(duplicate_sets.count).to eq(2) expect(duplicate_sets).to contain_exactly(
expect(duplicate_sets.first).to contain_exactly(log.id, duplicate_log.id) contain_exactly(log.id, duplicate_log.id),
expect(duplicate_sets.second).to contain_exactly(supported_housing_log.id, duplicate_supported_housing_log.id) contain_exactly(supported_housing_log.id, duplicate_supported_housing_log.id),
)
end end
it "does not return logs not associated with the user if user is given" do it "does not return logs not associated with the user if user is given" do
@ -2142,9 +2007,10 @@ RSpec.describe LettingsLog do
it "compares chcharge if it's a carehome" do it "compares chcharge if it's a carehome" do
supported_housing_log.update!(is_carehome: 1, chcharge: 100, supcharg: nil, brent: nil, scharge: nil, pscharge: nil, tcharge: nil, owning_organisation: organisation) supported_housing_log.update!(is_carehome: 1, chcharge: 100, supcharg: nil, brent: nil, scharge: nil, pscharge: nil, tcharge: nil, owning_organisation: organisation)
duplicate_supported_housing_log.update!(is_carehome: 1, chcharge: 100, supcharg: nil, brent: nil, scharge: nil, pscharge: nil, tcharge: nil, owning_organisation: organisation) duplicate_supported_housing_log.update!(is_carehome: 1, chcharge: 100, supcharg: nil, brent: nil, scharge: nil, pscharge: nil, tcharge: nil, owning_organisation: organisation)
expect(duplicate_sets.count).to eq(2) expect(duplicate_sets).to contain_exactly(
expect(duplicate_sets.first).to contain_exactly(log.id, duplicate_log.id) contain_exactly(log.id, duplicate_log.id),
expect(duplicate_sets.second).to contain_exactly(supported_housing_log.id, duplicate_supported_housing_log.id) contain_exactly(supported_housing_log.id, duplicate_supported_housing_log.id),
)
end end
it "does not return a duplicate if carehome charge is not given" do it "does not return a duplicate if carehome charge is not given" do
@ -2228,7 +2094,7 @@ RSpec.describe LettingsLog do
end end
context "when form end date is in the past" do context "when form end date is in the past" do
let(:startdate) { Time.zone.local(2020, 4, 1) } let(:startdate) { Time.zone.local(archived_collection_start_year, 4, 1) }
before do before do
allow(log).to receive_message_chain(:form, :new_logs_end_date).and_return(Time.zone.now - 1.day) allow(log).to receive_message_chain(:form, :new_logs_end_date).and_return(Time.zone.now - 1.day)
@ -2305,12 +2171,6 @@ RSpec.describe LettingsLog do
end end
describe "#non_location_setup_questions_completed" do describe "#non_location_setup_questions_completed" do
before do
Timecop.return
allow(FormHandler.instance).to receive(:current_lettings_form).and_call_original
Singleton.__init__(FormHandler)
end
context "when setup section has been completed" do context "when setup section has been completed" do
let(:lettings_log) { build_stubbed(:lettings_log, :setup_completed) } let(:lettings_log) { build_stubbed(:lettings_log, :setup_completed) }

34
spec/models/location_spec.rb

@ -1,6 +1,8 @@
require "rails_helper" require "rails_helper"
RSpec.describe Location, type: :model do RSpec.describe Location, type: :model do
include CollectionTimeHelper
before do before do
LocalAuthorityLink.create(local_authority_id: LocalAuthority.find_by(code: "E07000030").id, linked_local_authority_id: LocalAuthority.find_by(code: "E06000063").id) LocalAuthorityLink.create(local_authority_id: LocalAuthority.find_by(code: "E07000030").id, linked_local_authority_id: LocalAuthority.find_by(code: "E06000063").id)
end end
@ -1184,35 +1186,19 @@ RSpec.describe Location, type: :model do
end end
context "when there is no start date" do context "when there is no start date" do
context "and the location was created at the start of the 2022/23 collection window" do context "and the location was created at the start of the collection window" do
let(:location) { FactoryBot.build(:location, created_at: Time.zone.local(2022, 4, 6), startdate: nil) } let(:location) { FactoryBot.build(:location, created_at: current_collection_start_date, startdate: nil) }
it "returns the beginning of 21/22 collection window" do
expect(location.available_from).to eq(Time.zone.local(2021, 4, 1))
end
end
context "and the location was created at the end of the 2022/23 collection window" do
let(:location) { FactoryBot.build(:location, created_at: Time.zone.local(2023, 2, 6), startdate: nil) }
it "returns the beginning of 22/23 collection window" do
expect(location.available_from).to eq(Time.zone.local(2022, 4, 1))
end
end
context "and the location was created at the start of the 2021/22 collection window" do
let(:location) { FactoryBot.build(:location, created_at: Time.zone.local(2021, 4, 6), startdate: nil) }
it "returns the beginning of 20/21 collection window" do it "returns the beginning of previous collection window" do
expect(location.available_from).to eq(Time.zone.local(2020, 4, 1)) expect(location.available_from).to eq(previous_collection_start_date)
end end
end end
context "and the location was created at the end of the 2021/22 collection window" do context "and the location was created after the crossover date" do
let(:location) { FactoryBot.build(:location, created_at: Time.zone.local(2022, 2, 6), startdate: nil) } let(:location) { FactoryBot.build(:location, created_at: current_collection_after_crossover_start_date, startdate: nil) }
it "returns the beginning of 20/21 collection window" do it "returns the beginning of current collection window" do
expect(location.available_from).to eq(Time.zone.local(2020, 4, 1)) expect(location.available_from).to eq(current_collection_start_date)
end end
end end
end end

64
spec/models/sales_log_spec.rb

@ -96,17 +96,7 @@ RSpec.describe SalesLog, type: :model do
describe "#form" do describe "#form" do
let(:sales_log) { build(:sales_log, assigned_to: assigned_to_user) } let(:sales_log) { build(:sales_log, assigned_to: assigned_to_user) }
let(:sales_log_2) { build(:sales_log, saledate: Time.zone.local(2022, 5, 1), assigned_to: assigned_to_user) } let(:sales_log_2) { build(:sales_log, saledate: current_collection_start_date, assigned_to: assigned_to_user) }
before do
Timecop.freeze(Time.zone.local(2023, 1, 10))
Singleton.__init__(FormHandler)
end
after do
Timecop.return
Singleton.__init__(FormHandler)
end
it "has returns the correct form based on the start date" do it "has returns the correct form based on the start date" do
expect(sales_log.form_name).to be_nil expect(sales_log.form_name).to be_nil
@ -120,12 +110,8 @@ RSpec.describe SalesLog, type: :model do
let(:completed_sales_log) { create(:sales_log, :completed) } let(:completed_sales_log) { create(:sales_log, :completed) }
context "when proplen is not given" do context "when proplen is not given" do
before do it "is set to in_progress for a log" do
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 5, 1)) completed_sales_log.update!(proplen: nil, proplen_asked: 0)
end
it "is set to in_progress for a log with a saledate after 23/24" do
completed_sales_log.update!(proplen: nil, proplen_asked: 0, saledate: Time.zone.local(2023, 5, 1))
expect(completed_sales_log.in_progress?).to be(true) expect(completed_sales_log.in_progress?).to be(true)
expect(completed_sales_log.not_started?).to be(false) expect(completed_sales_log.not_started?).to be(false)
expect(completed_sales_log.completed?).to be(false) expect(completed_sales_log.completed?).to be(false)
@ -204,27 +190,35 @@ RSpec.describe SalesLog, type: :model do
end end
context "when filtering by year or nil" do context "when filtering by year or nil" do
# These examples need logs in both the previous and the current collection year,
# so we have to enforce we are in the crossover period
around do |example|
Timecop.freeze(current_collection_start_date) do
Singleton.__init__(FormHandler)
example.run
end
Singleton.__init__(FormHandler)
end
let(:previous_year) { previous_collection_start_year.to_s }
let(:current_year) { current_collection_start_year.to_s }
before do before do
create(:sales_log, :in_progress, saledate: nil) create(:sales_log, :in_progress, saledate: nil)
sales_log_2021 = build(:sales_log, :in_progress) create(:sales_log, :in_progress, saledate: previous_collection_start_date)
sales_log_2021.saledate = Time.zone.local(2021, 4, 1) create(:sales_log, :in_progress, saledate: current_collection_start_date)
sales_log_2021.save!(validate: false)
sales_log_3 = build(:sales_log, :in_progress)
sales_log_3.saledate = Time.zone.local(2022, 5, 1)
sales_log_3.save!(validate: false)
end end
it "allows filtering on a single year or nil" do it "allows filtering on a single year or nil" do
expect(described_class.filter_by_years_or_nil(%w[2021]).count).to eq(2) expect(described_class.filter_by_years_or_nil([previous_year]).count).to eq(2)
end end
it "allows filtering by multiple years or nil using OR" do it "allows filtering by multiple years or nil using OR" do
expect(described_class.filter_by_years_or_nil(%w[2021 2022]).count).to eq(3) expect(described_class.filter_by_years_or_nil([previous_year, current_year]).count).to eq(3)
end end
it "can filter by year(s) AND status" do it "can filter by year(s) AND status" do
expect(described_class.filter_by_years_or_nil(%w[2021 2022]).filter_by_status("in_progress").count).to eq(3) expect(described_class.filter_by_years_or_nil([previous_year, current_year]).filter_by_status("in_progress").count).to eq(3)
end end
end end
@ -277,17 +271,9 @@ RSpec.describe SalesLog, type: :model do
end end
end end
context "when there is a 2024 log with a different ecstat1" do context "when there is a log with a different ecstat1" do
let!(:different_ecstat1) { create(:sales_log, :duplicate, ecstat1: 0, owning_organisation: organisation) } let(:log) { create(:sales_log, :duplicate, staircase: 2, owning_organisation: organisation) }
let!(:different_ecstat1) { create(:sales_log, :duplicate, staircase: 2, ecstat1: 0, owning_organisation: organisation) }
before do
Timecop.freeze(Time.zone.local(2024, 5, 2))
Singleton.__init__(FormHandler)
end
after do
Timecop.return
end
it "does not return a log with a different ecstat1 as a duplicate" do it "does not return a log with a different ecstat1 as a duplicate" do
expect(described_class.duplicate_logs(log)).not_to include(different_ecstat1) expect(described_class.duplicate_logs(log)).not_to include(different_ecstat1)
@ -944,7 +930,7 @@ RSpec.describe SalesLog, type: :model do
end end
context "when form end date is in the past" do context "when form end date is in the past" do
let(:saledate) { Time.zone.local(2020, 4, 1) } let(:saledate) { Time.zone.local(archived_collection_start_year, 4, 1) }
before do before do
allow(log).to receive_message_chain(:form, :new_logs_end_date).and_return(Time.zone.now - 1.day) allow(log).to receive_message_chain(:form, :new_logs_end_date).and_return(Time.zone.now - 1.day)

34
spec/models/scheme_spec.rb

@ -1,6 +1,8 @@
require "rails_helper" require "rails_helper"
RSpec.describe Scheme, type: :model do RSpec.describe Scheme, type: :model do
include CollectionTimeHelper
describe "#new" do describe "#new" do
let(:scheme) { FactoryBot.create(:scheme) } let(:scheme) { FactoryBot.create(:scheme) }
@ -483,35 +485,19 @@ RSpec.describe Scheme, type: :model do
end end
describe "available_from" do describe "available_from" do
context "when the scheme was created at the start of the 2022/23 collection window" do context "when the scheme was created at the start of the collection window" do
let(:scheme) { FactoryBot.build(:scheme, created_at: Time.zone.local(2022, 4, 6)) } let(:scheme) { FactoryBot.build(:scheme, created_at: current_collection_start_date) }
it "returns the beginning of 22/23 collection window" do
expect(scheme.available_from).to eq(Time.zone.local(2021, 4, 1))
end
end
context "when the scheme was created at the end of the 2022/23 collection window" do
let(:scheme) { FactoryBot.build(:scheme, created_at: Time.zone.local(2023, 2, 6)) }
it "returns the beginning of 22/23 collection window" do
expect(scheme.available_from).to eq(Time.zone.local(2022, 4, 1))
end
end
context "when the scheme was created at the start of the 2021/22 collection window" do
let(:scheme) { FactoryBot.build(:scheme, created_at: Time.zone.local(2021, 4, 6)) }
it "returns the beginning of 21/22 collection window" do it "returns the beginning of previous collection window" do
expect(scheme.available_from).to eq(Time.zone.local(2020, 4, 1)) expect(scheme.available_from).to eq(previous_collection_start_date)
end end
end end
context "when the scheme was created at the end of the 2021/22 collection window" do context "when the scheme was created after the crossover date" do
let(:scheme) { FactoryBot.build(:scheme, created_at: Time.zone.local(2022, 2, 6)) } let(:scheme) { FactoryBot.build(:scheme, created_at: current_collection_after_crossover_start_date) }
it "returns the beginning of 21/22 collection window" do it "returns the beginning of current collection window" do
expect(scheme.available_from).to eq(Time.zone.local(2020, 4, 1)) expect(scheme.available_from).to eq(current_collection_start_date)
end end
end end
end end

34
spec/models/validations/date_validations_spec.rb

@ -18,7 +18,7 @@ RSpec.describe Validations::DateValidations do
end end
it "does not raise an error when valid" do it "does not raise an error when valid" do
record.startdate = Time.zone.local(2022, 1, 1) record.startdate = current_collection_start_date + 1.month
date_validator.validate_startdate(record) date_validator.validate_startdate(record)
expect(record.errors["startdate"]).to be_empty expect(record.errors["startdate"]).to be_empty
end end
@ -40,8 +40,8 @@ RSpec.describe Validations::DateValidations do
describe "major repairs date" do describe "major repairs date" do
it "cannot be after the tenancy start date" do it "cannot be after the tenancy start date" do
record.startdate = Time.zone.local(2022, 1, 1) record.startdate = current_collection_start_date + 1.month
record.mrcdate = Time.zone.local(2022, 2, 1) record.mrcdate = current_collection_start_date + 2.months
date_validator.validate_property_major_repairs(record) date_validator.validate_property_major_repairs(record)
expect(record.errors["mrcdate"]) expect(record.errors["mrcdate"])
.to include(match I18n.t("validations.lettings.date.mrcdate.before_tenancy_start")) .to include(match I18n.t("validations.lettings.date.mrcdate.before_tenancy_start"))
@ -50,8 +50,8 @@ RSpec.describe Validations::DateValidations do
end end
it "must be before the tenancy start date" do it "must be before the tenancy start date" do
record.startdate = Time.zone.local(2022, 2, 1) record.startdate = current_collection_start_date + 2.months
record.mrcdate = Time.zone.local(2022, 1, 1) record.mrcdate = current_collection_start_date + 1.month
date_validator.validate_property_major_repairs(record) date_validator.validate_property_major_repairs(record)
expect(record.errors["mrcdate"]).to be_empty expect(record.errors["mrcdate"]).to be_empty
end end
@ -77,7 +77,7 @@ RSpec.describe Validations::DateValidations do
context "when reason for vacancy is first let of property" do context "when reason for vacancy is first let of property" do
it "validates that no major repair date is provided for a new build" do it "validates that no major repair date is provided for a new build" do
record.rsnvac = 15 record.rsnvac = 15
record.mrcdate = Time.zone.local(2022, 1, 1) record.mrcdate = current_collection_start_date + 1.month
date_validator.validate_property_major_repairs(record) date_validator.validate_property_major_repairs(record)
expect(record.errors["mrcdate"]) expect(record.errors["mrcdate"])
.to include(match I18n.t("validations.lettings.date.mrcdate.not_first_let")) .to include(match I18n.t("validations.lettings.date.mrcdate.not_first_let"))
@ -85,7 +85,7 @@ RSpec.describe Validations::DateValidations do
it "validates that no major repair date is provided for a conversion" do it "validates that no major repair date is provided for a conversion" do
record.rsnvac = 16 record.rsnvac = 16
record.mrcdate = Time.zone.local(2022, 1, 1) record.mrcdate = current_collection_start_date + 1.month
date_validator.validate_property_major_repairs(record) date_validator.validate_property_major_repairs(record)
expect(record.errors["mrcdate"]) expect(record.errors["mrcdate"])
.to include(match I18n.t("validations.lettings.date.mrcdate.not_first_let")) .to include(match I18n.t("validations.lettings.date.mrcdate.not_first_let"))
@ -93,7 +93,7 @@ RSpec.describe Validations::DateValidations do
it "validates that no major repair date is provided for a leased property" do it "validates that no major repair date is provided for a leased property" do
record.rsnvac = 17 record.rsnvac = 17
record.mrcdate = Time.zone.local(2022, 1, 1) record.mrcdate = current_collection_start_date + 1.month
date_validator.validate_property_major_repairs(record) date_validator.validate_property_major_repairs(record)
expect(record.errors["mrcdate"]) expect(record.errors["mrcdate"])
.to include(match I18n.t("validations.lettings.date.mrcdate.not_first_let")) .to include(match I18n.t("validations.lettings.date.mrcdate.not_first_let"))
@ -103,7 +103,7 @@ RSpec.describe Validations::DateValidations do
context "when the reason for vacancy is not the first let of property" do context "when the reason for vacancy is not the first let of property" do
it "expects that major repairs can have been done" do it "expects that major repairs can have been done" do
record.rsnvac = "Tenant moved to care home" record.rsnvac = "Tenant moved to care home"
record.mrcdate = Time.zone.local(2022, 1, 1) record.mrcdate = current_collection_start_date + 1.month
date_validator.validate_property_major_repairs(record) date_validator.validate_property_major_repairs(record)
expect(record.errors["mrcdate"]).to be_empty expect(record.errors["mrcdate"]).to be_empty
end end
@ -112,8 +112,8 @@ RSpec.describe Validations::DateValidations do
describe "property void date" do describe "property void date" do
it "cannot be after the tenancy start date" do it "cannot be after the tenancy start date" do
record.startdate = Time.zone.local(2022, 1, 1) record.startdate = current_collection_start_date + 1.month
record.voiddate = Time.zone.local(2022, 2, 1) record.voiddate = current_collection_start_date + 2.months
date_validator.validate_property_void_date(record) date_validator.validate_property_void_date(record)
expect(record.errors["voiddate"]) expect(record.errors["voiddate"])
.to include(match I18n.t("validations.lettings.date.void_date.before_tenancy_start")) .to include(match I18n.t("validations.lettings.date.void_date.before_tenancy_start"))
@ -122,8 +122,8 @@ RSpec.describe Validations::DateValidations do
end end
it "must be before the tenancy start date" do it "must be before the tenancy start date" do
record.startdate = Time.zone.local(2022, 2, 1) record.startdate = current_collection_start_date + 2.months
record.voiddate = Time.zone.local(2022, 1, 1) record.voiddate = current_collection_start_date + 1.month
date_validator.validate_property_void_date(record) date_validator.validate_property_void_date(record)
expect(record.errors["voiddate"]).to be_empty expect(record.errors["voiddate"]).to be_empty
end end
@ -149,8 +149,8 @@ RSpec.describe Validations::DateValidations do
context "when major repairs have been carried out" do context "when major repairs have been carried out" do
it "void_date cannot be after major repairs date" do it "void_date cannot be after major repairs date" do
record.mrcdate = Time.zone.local(2022, 1, 1) record.mrcdate = current_collection_start_date + 1.month
record.voiddate = Time.zone.local(2022, 2, 1) record.voiddate = current_collection_start_date + 2.months
date_validator.validate_property_void_date(record) date_validator.validate_property_void_date(record)
expect(record.errors["voiddate"]) expect(record.errors["voiddate"])
.to include(match I18n.t("validations.lettings.date.void_date.after_mrcdate")) .to include(match I18n.t("validations.lettings.date.void_date.after_mrcdate"))
@ -159,8 +159,8 @@ RSpec.describe Validations::DateValidations do
end end
it "must be before major repairs date" do it "must be before major repairs date" do
record.mrcdate = Time.zone.local(2022, 2, 1) record.mrcdate = current_collection_start_date + 2.months
record.voiddate = Time.zone.local(2022, 1, 1) record.voiddate = current_collection_start_date + 1.month
date_validator.validate_property_void_date(record) date_validator.validate_property_void_date(record)
expect(record.errors["voiddate"]).to be_empty expect(record.errors["voiddate"]).to be_empty
end end

34
spec/models/validations/financial_validations_spec.rb

@ -1,6 +1,8 @@
require "rails_helper" require "rails_helper"
RSpec.describe Validations::FinancialValidations do RSpec.describe Validations::FinancialValidations do
include CollectionTimeHelper
subject(:financial_validator) { validator_class.new } subject(:financial_validator) { validator_class.new }
let(:validator_class) { Class.new { include Validations::FinancialValidations } } let(:validator_class) { Class.new { include Validations::FinancialValidations } }
@ -198,7 +200,7 @@ RSpec.describe Validations::FinancialValidations do
end end
describe "housing benefit rent shortfall validations" do describe "housing benefit rent shortfall validations" do
before { record.startdate = Time.zone.local(2022, 5, 1) } before { record.startdate = current_collection_start_date }
context "when shortfall is yes" do context "when shortfall is yes" do
it "validates that housing benefit is not none" do it "validates that housing benefit is not none" do
@ -228,7 +230,7 @@ RSpec.describe Validations::FinancialValidations do
describe "net income validations" do describe "net income validations" do
it "validates that the net income is within the expected range for the household’s employment status" do it "validates that the net income is within the expected range for the household’s employment status" do
record.startdate = Time.zone.local(2023, 5, 1) record.startdate = current_collection_start_date
record.earnings = 200 record.earnings = 200
record.incfreq = 1 record.incfreq = 1
record.hhmemb = 1 record.hhmemb = 1
@ -239,7 +241,7 @@ RSpec.describe Validations::FinancialValidations do
context "when the net income is higher than the hard max for their employment status" do context "when the net income is higher than the hard max for their employment status" do
it "adds an error" do it "adds an error" do
record.startdate = Time.zone.local(2023, 5, 1) record.startdate = current_collection_start_date
record.earnings = 5000 record.earnings = 5000
record.incfreq = 1 record.incfreq = 1
record.hhmemb = 1 record.hhmemb = 1
@ -256,7 +258,7 @@ RSpec.describe Validations::FinancialValidations do
context "when the net income is lower than the hard min for their employment status" do context "when the net income is lower than the hard min for their employment status" do
it "adds an error" do it "adds an error" do
record.startdate = Time.zone.local(2023, 5, 1) record.startdate = current_collection_start_date
record.earnings = 50 record.earnings = 50
record.incfreq = 1 record.incfreq = 1
record.hhmemb = 1 record.hhmemb = 1
@ -273,7 +275,7 @@ RSpec.describe Validations::FinancialValidations do
context "when there is more than one household member" do context "when there is more than one household member" do
it "allows income levels based on all working situations combined" do it "allows income levels based on all working situations combined" do
record.startdate = Time.zone.local(2023, 5, 1) record.startdate = current_collection_start_date
record.earnings = 5000 record.earnings = 5000
record.incfreq = 1 record.incfreq = 1
record.hhmemb = 4 record.hhmemb = 4
@ -286,7 +288,7 @@ RSpec.describe Validations::FinancialValidations do
end end
it "uses the combined value in error messages" do it "uses the combined value in error messages" do
record.startdate = Time.zone.local(2023, 5, 1) record.startdate = current_collection_start_date
record.earnings = 100 record.earnings = 100
record.incfreq = 1 record.incfreq = 1
record.hhmemb = 3 record.hhmemb = 3
@ -299,7 +301,7 @@ RSpec.describe Validations::FinancialValidations do
end end
it "adds errors to relevant fields for each tenant when income is too high" do it "adds errors to relevant fields for each tenant when income is too high" do
record.startdate = Time.zone.local(2023, 5, 1) record.startdate = current_collection_start_date
record.earnings = 5000 record.earnings = 5000
record.incfreq = 1 record.incfreq = 1
record.hhmemb = 3 record.hhmemb = 3
@ -323,7 +325,7 @@ RSpec.describe Validations::FinancialValidations do
end end
it "adds errors to relevant fields for each tenant when income is too low" do it "adds errors to relevant fields for each tenant when income is too low" do
record.startdate = Time.zone.local(2023, 5, 1) record.startdate = current_collection_start_date
record.earnings = 50 record.earnings = 50
record.incfreq = 1 record.incfreq = 1
record.hhmemb = 3 record.hhmemb = 3
@ -991,7 +993,7 @@ RSpec.describe Validations::FinancialValidations do
soft_max: 89.54, soft_max: 89.54,
hard_min: 9.87, hard_min: 9.87,
hard_max: 100.99, hard_max: 100.99,
start_year: 2021, start_year: current_collection_start_year,
) )
LaRentRange.create!( LaRentRange.create!(
ranges_rent_id: "2", ranges_rent_id: "2",
@ -1002,7 +1004,7 @@ RSpec.describe Validations::FinancialValidations do
soft_max: 89.54, soft_max: 89.54,
hard_min: 9.87, hard_min: 9.87,
hard_max: 100.99, hard_max: 100.99,
start_year: 2021, start_year: current_collection_start_year,
) )
end end
@ -1012,7 +1014,7 @@ RSpec.describe Validations::FinancialValidations do
record.period = 1 record.period = 1
record.la = "E07000223" record.la = "E07000223"
record.beds = 4 record.beds = 4
record.startdate = Time.zone.local(2021, 9, 17) record.startdate = current_collection_start_date
record.brent = 9.17 record.brent = 9.17
financial_validator.validate_rent_amount(record) financial_validator.validate_rent_amount(record)
@ -1025,7 +1027,7 @@ RSpec.describe Validations::FinancialValidations do
record.lettype = 2 record.lettype = 2
record.period = 1 record.period = 1
record.location = location record.location = location
record.startdate = Time.zone.local(2021, 9, 17) record.startdate = current_collection_start_date
record.brent = 9.17 record.brent = 9.17
financial_validator.validate_rent_amount(record) financial_validator.validate_rent_amount(record)
@ -1044,7 +1046,7 @@ RSpec.describe Validations::FinancialValidations do
record.period = 1 record.period = 1
record.la = "E07000223" record.la = "E07000223"
record.beds = 4 record.beds = 4
record.startdate = Time.zone.local(2021, 9, 17) record.startdate = current_collection_start_date
record.brent = 200 record.brent = 200
financial_validator.validate_rent_amount(record) financial_validator.validate_rent_amount(record)
@ -1062,7 +1064,7 @@ RSpec.describe Validations::FinancialValidations do
record.lettype = 2 record.lettype = 2
record.period = 1 record.period = 1
record.location = location record.location = location
record.startdate = Time.zone.local(2021, 9, 17) record.startdate = current_collection_start_date
record.brent = 200 record.brent = 200
financial_validator.validate_rent_amount(record) financial_validator.validate_rent_amount(record)
@ -1079,7 +1081,7 @@ RSpec.describe Validations::FinancialValidations do
record.lettype = 1 record.lettype = 1
record.period = 1 record.period = 1
record.la = "E07000223" record.la = "E07000223"
record.startdate = Time.zone.local(2022, 2, 5) record.startdate = current_collection_start_date
record.beds = 4 record.beds = 4
record.brent = 200 record.brent = 200
@ -1095,7 +1097,7 @@ RSpec.describe Validations::FinancialValidations do
it "does not error if some of the fields are missing" do it "does not error if some of the fields are missing" do
record.managing_organisation.provider_type = 2 record.managing_organisation.provider_type = 2
record.startdate = Time.zone.local(2021, 9, 17) record.startdate = current_collection_start_date
record.brent = 200 record.brent = 200
financial_validator.validate_rent_amount(record) financial_validator.validate_rent_amount(record)

8
spec/models/validations/household_validations_spec.rb

@ -53,7 +53,7 @@ RSpec.describe Validations::HouseholdValidations do
end end
context "when form year is >= 2024" do context "when form year is >= 2024" do
let(:startdate) { Time.zone.local(2024, 4, 1) } let(:startdate) { current_collection_start_date }
context "when checking the content of reasonother" do context "when checking the content of reasonother" do
it "validates that the reason doesn't match phrase indicating homelessness" do it "validates that the reason doesn't match phrase indicating homelessness" do
@ -271,7 +271,7 @@ RSpec.describe Validations::HouseholdValidations do
describe "#validate_person_age_matches_relationship" do describe "#validate_person_age_matches_relationship" do
context "with 2024 logs" do context "with 2024 logs" do
let(:startdate) { Time.zone.local(2024, 4, 1) } let(:startdate) { current_collection_start_date }
it "does not add an error is person under 16 is a partner" do it "does not add an error is person under 16 is a partner" do
record.age2 = 14 record.age2 = 14
@ -293,7 +293,7 @@ RSpec.describe Validations::HouseholdValidations do
describe "#validate_person_age_matches_economic_status" do describe "#validate_person_age_matches_economic_status" do
context "with 2024 logs" do context "with 2024 logs" do
let(:startdate) { Time.zone.local(2024, 4, 1) } let(:startdate) { current_collection_start_date }
it "does not run the validation" do it "does not run the validation" do
record.age2 = 14 record.age2 = 14
@ -309,7 +309,7 @@ RSpec.describe Validations::HouseholdValidations do
describe "#validate_person_age_and_relationship_matches_economic_status" do describe "#validate_person_age_and_relationship_matches_economic_status" do
context "with 2024 logs" do context "with 2024 logs" do
let(:startdate) { Time.zone.local(2024, 4, 1) } let(:startdate) { current_collection_start_date }
context "when the household contains a tenant’s child between the ages of 16 and 19" do context "when the household contains a tenant’s child between the ages of 16 and 19" do
it "does not add an error" do it "does not add an error" do

12
spec/models/validations/sales/sale_information_validations_spec.rb

@ -860,18 +860,6 @@ RSpec.describe Validations::Sales::SaleInformationValidations do
end end
end end
context "with a 2024 log that is not an outright sale" do
let(:record) { FactoryBot.build(:sales_log, value: 300_000, ownershipsch: 2, saledate: Time.zone.local(2024, 5, 1)) }
it "does not add errors" do
record.mortgageused = 1
record.mortgage = 100_000
record.deposit = 100_000
sale_information_validator.validate_outright_sale_value_matches_mortgage_plus_deposit(record)
expect(record.errors).to be_empty
end
end
describe "#validate_basic_monthly_rent" do describe "#validate_basic_monthly_rent" do
context "when within permitted bounds" do context "when within permitted bounds" do
let(:record) { build(:sales_log, mrent: 9998, ownershipsch: 1, type: 2) } let(:record) { build(:sales_log, mrent: 9998, ownershipsch: 1, type: 2) }

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

@ -1,11 +1,13 @@
require "rails_helper" require "rails_helper"
RSpec.describe Validations::Sales::SetupValidations do RSpec.describe Validations::Sales::SetupValidations do
include CollectionTimeHelper
subject(:setup_validator) { validator_class.new } subject(:setup_validator) { validator_class.new }
let(:validator_class) { Class.new { include Validations::Sales::SetupValidations } } let(:validator_class) { Class.new { include Validations::Sales::SetupValidations } }
let(:current_year) { FormHandler.instance.current_sales_form.start_date.year } let(:current_year) { current_collection_start_year }
let(:previous_year) { FormHandler.instance.previous_sales_form.start_date.year } let(:previous_year) { previous_collection_start_year }
describe "#validate_saledate_collection_year" do describe "#validate_saledate_collection_year" do
context "with sales_in_crossover_period == false" do context "with sales_in_crossover_period == false" do
@ -84,7 +86,7 @@ RSpec.describe Validations::Sales::SetupValidations do
end end
context "when saledate is before an open collection year" do context "when saledate is before an open collection year" do
let(:record) { build(:sales_log, saledate: Time.zone.local(2020, 5, 1)) } let(:record) { build(:sales_log, saledate: archived_collection_start_date) }
before do before do
allow(FormHandler.instance).to receive(:sales_in_crossover_period?).and_return(true) allow(FormHandler.instance).to receive(:sales_in_crossover_period?).and_return(true)

199
spec/models/validations/setup_validations_spec.rb

@ -9,90 +9,32 @@ RSpec.describe Validations::SetupValidations do
let(:record) { build(:lettings_log) } let(:record) { build(:lettings_log) }
describe "tenancy start date" do describe "tenancy start date" do
context "when in 2022 to 2023 collection" do context "when in the crossover period" do
context "when in the crossover period" do before do
before do Timecop.freeze(current_collection_start_date)
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)
setup_validator.validate_merged_organisations_start_date(record)
expect(record.errors["startdate"]).to include(match "Enter a date within the 2021 to 2022 or 2022 to 2023 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)
setup_validator.validate_merged_organisations_start_date(record)
expect(record.errors["startdate"]).to include(match "Enter a date within the 2021 to 2022 or 2022 to 2023 collection years, which is between 1st April 2021 and 31st March 2023")
end
end end
context "when after the crossover period" do after do
before do Timecop.return
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)
setup_validator.validate_merged_organisations_start_date(record)
expect(record.errors["startdate"]).to include(match "Enter a date within the 2022 to 2023 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)
setup_validator.validate_merged_organisations_start_date(record)
expect(record.errors["startdate"]).to include(match "Enter a date within the 2022 to 2023 collection year, which is between 1st April 2022 and 31st March 2023")
end
end end
end
context "when in 2023 to 2024 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)
setup_validator.validate_merged_organisations_start_date(record)
expect(record.errors["startdate"]).to include(match "Enter a date within the 2022 to 2023 or 2023 to 2024 collection years, which is between 1st April 2022 and 31st March 2024")
end
it "cannot be after the second collection window end date" do it "cannot be before previous collection year start date" do
record.startdate = Time.zone.local(2024, 7, 1, 6) record.startdate = previous_collection_start_date - 1.month
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
setup_validator.validate_merged_organisations_start_date(record) setup_validator.validate_merged_organisations_start_date(record)
expect(record.errors["startdate"]).to include(match "Enter a date within the 2022 to 2023 or 2023 to 2024 collection years, which is between 1st April 2022 and 31st March 2024") expect(record.errors["startdate"]).to include(match(/Enter a date within the \d{4} to \d{4} or \d{4} to \d{4} collection years, which is between 1st April \d{4} and 31st March \d{4}/))
end
end end
context "when after the crossover period" do context "when after the crossover period" do
before do before do
allow(Time).to receive(:now).and_return(Time.zone.local(2024, 1, 1)) allow(Time).to receive(:now).and_return(current_collection_after_crossover_start_date)
record.created_at = Time.zone.local(2024, 1, 1)
end end
it "cannot be before the first collection window start date" do it "cannot be before previous collection year start date" do
record.startdate = Time.zone.local(2023, 1, 1) record.startdate = previous_collection_start_date - 1.month
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
setup_validator.validate_merged_organisations_start_date(record) setup_validator.validate_merged_organisations_start_date(record)
expect(record.errors["startdate"]).to include(match "Enter a date within the 2023 to 2024 collection year, which is between 1st April 2023 and 31st March 2024") expect(record.errors["startdate"]).to include(match(/Enter a date within the \d{4} to \d{4} collection year, which is between 1st April \d{4} and 31st March \d{4}/))
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)
setup_validator.validate_merged_organisations_start_date(record)
expect(record.errors["startdate"]).to include(match "Enter a date within the 2023 to 2024 collection year, which is between 1st April 2023 and 31st March 2024")
end end
end end
@ -125,73 +67,90 @@ RSpec.describe Validations::SetupValidations do
context "when after the new logs end date and after the edit end date for the previous period" do context "when after the new logs end date and after the edit end date for the previous period" do
before do before do
allow(Time).to receive(:now).and_return(Time.zone.local(2024, 1, 8)) Timecop.freeze(previous_collection_edit_end_date + 1.day)
end
after do
Timecop.return
end end
it "cannot create new logs for the previous collection year" do it "cannot create new logs for the previous collection year" do
record.update!(startdate: nil) record.update!(startdate: nil)
record.startdate = Time.zone.local(2023, 1, 1) record.startdate = previous_collection_start_date
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
setup_validator.validate_merged_organisations_start_date(record) setup_validator.validate_merged_organisations_start_date(record)
expect(record.errors["startdate"]).to include(match "Enter a date within the 2023 to 2024 collection year, which is between 1st April 2023 and 31st March 2024") expect(record.errors["startdate"]).to include(match(/Enter a date within the \d{4} to \d{4} collection year, which is between 1st April \d{4} and 31st March \d{4}/))
end end
it "cannot edit already created logs for the previous collection year" do it "cannot edit already created logs for the previous collection year" do
record.startdate = Time.zone.local(2023, 1, 2) record.startdate = previous_collection_start_date + 1.day
record.save!(validate: false) record.save!(validate: false)
record.startdate = Time.zone.local(2023, 1, 1) record.startdate = previous_collection_start_date
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
setup_validator.validate_merged_organisations_start_date(record) setup_validator.validate_merged_organisations_start_date(record)
expect(record.errors["startdate"]).to include(match "Enter a date within the 2023 to 2024 collection year, which is between 1st April 2023 and 31st March 2024") expect(record.errors["startdate"]).to include(match(/Enter a date within the \d{4} to \d{4} collection year, which is between 1st April \d{4} and 31st March \d{4}/))
end end
end end
end end
context "when attempted startdate is more than 14 days from the current date" do context "when attempted startdate is more than 14 days from the current date" do
before do before do
allow(Time).to receive(:now).and_return(Time.zone.local(2024, 3, 1)) Timecop.freeze(current_collection_start_date - 1.month)
end
after do
Timecop.return
end end
it "adds an error to startdate" do it "adds an error to startdate" do
record.startdate = Time.zone.local(2024, 3, 31) record.startdate = Time.zone.now + 15.days
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
expect(record.errors["startdate"]).to include(match I18n.t("validations.lettings.setup.startdate.not_within.next_two_weeks")) expect(record.errors["startdate"]).to include(match I18n.t("validations.lettings.setup.startdate.not_within.next_two_weeks"))
end end
context "and the attempted startdate is in a future collection year" do context "and the attempted startdate is in a future collection year" do
it "adds both errors to startdate, with the collection year error first" do it "adds both errors to startdate, with the collection year error first" do
record.startdate = Time.zone.local(2024, 4, 1) record.startdate = next_collection_start_date
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
expect(record.errors["startdate"].length).to be >= 2 expect(record.errors["startdate"].length).to be >= 2
expect(record.errors["startdate"][0]).to eq("Enter a date within the 2023 to 2024 collection year, which is between 1st April 2023 and 31st March 2024.") expect(record.errors["startdate"][0]).to match(/Enter a date within the \d{4} to \d{4} collection year, which is between 1st April \d{4} and 31st March \d{4}/)
expect(record.errors["startdate"][1]).to eq(I18n.t("validations.lettings.setup.startdate.not_within.next_two_weeks")) expect(record.errors["startdate"][1]).to eq(I18n.t("validations.lettings.setup.startdate.not_within.next_two_weeks"))
end end
end end
end end
context "when organisations were merged" do context "when organisations were merged" do
let(:absorbing_organisation) { create(:organisation, created_at: Time.zone.local(2023, 1, 30, 4, 5, 6), available_from: Time.zone.local(2023, 2, 1, 4, 5, 6), name: "Absorbing org") } let(:org_available_from) { current_collection_start_date - 2.months }
let(:absorbing_organisation_2) { create(:organisation, created_at: Time.zone.local(2023, 1, 30), available_from: Time.zone.local(2023, 2, 1), name: "Absorbing org 2") } let(:org_created_at) { org_available_from - 2.days }
let(:org_merge_date) { org_available_from + 1.day }
let(:merge_date_formatted) { org_merge_date.strftime("%-d %B %Y") }
let(:available_from_formatted) { org_available_from.strftime("%-d %B %Y") }
let(:absorbing_organisation) { create(:organisation, created_at: org_created_at, available_from: org_available_from, name: "Absorbing org") }
let(:absorbing_organisation_2) { create(:organisation, created_at: org_created_at, available_from: org_available_from, name: "Absorbing org 2") }
let(:merged_organisation) { create(:organisation, name: "Merged org") } let(:merged_organisation) { create(:organisation, name: "Merged org") }
let(:merged_organisation_2) { create(:organisation, name: "Merged org 2") } let(:merged_organisation_2) { create(:organisation, name: "Merged org 2") }
before do before do
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 5, 1)) Timecop.freeze(current_collection_start_date + 1.month)
merged_organisation.update!(absorbing_organisation:, merge_date: Time.zone.local(2023, 2, 2)) merged_organisation.update!(absorbing_organisation:, merge_date: org_merge_date)
merged_organisation_2.update!(absorbing_organisation:, merge_date: Time.zone.local(2023, 2, 2)) merged_organisation_2.update!(absorbing_organisation:, merge_date: org_merge_date)
end
after do
Timecop.return
end end
context "and owning organisation is no longer active" do context "and owning organisation is no longer active" do
it "does not allow startdate after organisation has been merged" do it "does not allow startdate after organisation has been merged" do
record.startdate = Time.zone.local(2023, 3, 1) record.startdate = org_merge_date + 1.month
record.owning_organisation_id = merged_organisation.id record.owning_organisation_id = merged_organisation.id
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
setup_validator.validate_merged_organisations_start_date(record) setup_validator.validate_merged_organisations_start_date(record)
expect(record.errors["startdate"]).to include(match "Enter a date when the owning organisation was active. Merged org became inactive on 2 February 2023 and was replaced by Absorbing org.") expect(record.errors["startdate"]).to include(match "Enter a date when the owning organisation was active. Merged org became inactive on #{merge_date_formatted} and was replaced by Absorbing org.")
end end
it "allows startdate before organisation has been merged" do it "allows startdate before organisation has been merged" do
record.startdate = Time.zone.local(2023, 1, 1) record.startdate = org_merge_date - 1.month
record.owning_organisation_id = merged_organisation.id record.owning_organisation_id = merged_organisation.id
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
setup_validator.validate_merged_organisations_start_date(record) setup_validator.validate_merged_organisations_start_date(record)
@ -201,15 +160,15 @@ RSpec.describe Validations::SetupValidations do
context "and owning organisation is not yet active during the startdate" do context "and owning organisation is not yet active during the startdate" do
it "does not allow startdate before absorbing organisation has become available" do it "does not allow startdate before absorbing organisation has become available" do
record.startdate = Time.zone.local(2023, 1, 1) record.startdate = org_available_from - 1.month
record.owning_organisation_id = absorbing_organisation.id record.owning_organisation_id = absorbing_organisation.id
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
setup_validator.validate_merged_organisations_start_date(record) setup_validator.validate_merged_organisations_start_date(record)
expect(record.errors["startdate"]).to include(match "Enter a date when the owning organisation was active. Absorbing org became active on 1 February 2023.") expect(record.errors["startdate"]).to include(match "Enter a date when the owning organisation was active. Absorbing org became active on #{available_from_formatted}.")
end end
it "allows startdate after absorbing organisation has become available" do it "allows startdate after absorbing organisation has become available" do
record.startdate = Time.zone.local(2023, 2, 2) record.startdate = org_available_from + 1.month
record.owning_organisation_id = absorbing_organisation.id record.owning_organisation_id = absorbing_organisation.id
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
setup_validator.validate_merged_organisations_start_date(record) setup_validator.validate_merged_organisations_start_date(record)
@ -217,7 +176,7 @@ RSpec.describe Validations::SetupValidations do
end end
it "allows startdate if organisation does not have available from date" do it "allows startdate if organisation does not have available from date" do
record.startdate = Time.zone.local(2023, 1, 1) record.startdate = org_available_from - 1.month
absorbing_organisation.update!(available_from: nil) absorbing_organisation.update!(available_from: nil)
record.owning_organisation_id = absorbing_organisation.id record.owning_organisation_id = absorbing_organisation.id
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
@ -228,15 +187,15 @@ RSpec.describe Validations::SetupValidations do
context "and managing organisation is no longer active during the startdate" do context "and managing organisation is no longer active during the startdate" do
it "does not allow startdate after organisation has been merged" do it "does not allow startdate after organisation has been merged" do
record.startdate = Time.zone.local(2023, 3, 1) record.startdate = org_merge_date + 1.month
record.managing_organisation_id = merged_organisation.id record.managing_organisation_id = merged_organisation.id
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
setup_validator.validate_merged_organisations_start_date(record) setup_validator.validate_merged_organisations_start_date(record)
expect(record.errors["startdate"]).to include(match "Enter a date when the managing organisation was active. Merged org became inactive on 2 February 2023 and was replaced by Absorbing org.") expect(record.errors["startdate"]).to include(match "Enter a date when the managing organisation was active. Merged org became inactive on #{merge_date_formatted} and was replaced by Absorbing org.")
end end
it "allows startdate before organisation has been merged" do it "allows startdate before organisation has been merged" do
record.startdate = Time.zone.local(2023, 1, 1) record.startdate = org_merge_date - 1.month
record.managing_organisation_id = merged_organisation.id record.managing_organisation_id = merged_organisation.id
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
setup_validator.validate_merged_organisations_start_date(record) setup_validator.validate_merged_organisations_start_date(record)
@ -246,15 +205,15 @@ RSpec.describe Validations::SetupValidations do
context "and managing organisation is not yet active during the startdate" do context "and managing organisation is not yet active during the startdate" do
it "does not allow startdate before absorbing organisation has become available'" do it "does not allow startdate before absorbing organisation has become available'" do
record.startdate = Time.zone.local(2023, 1, 1) record.startdate = org_available_from - 1.month
record.managing_organisation_id = absorbing_organisation.id record.managing_organisation_id = absorbing_organisation.id
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
setup_validator.validate_merged_organisations_start_date(record) setup_validator.validate_merged_organisations_start_date(record)
expect(record.errors["startdate"]).to include(match "Enter a date when the managing organisation was active. Absorbing org became active on 1 February 2023.") expect(record.errors["startdate"]).to include(match "Enter a date when the managing organisation was active. Absorbing org became active on #{available_from_formatted}.")
end end
it "allows startdate after absorbing organisation has become available" do it "allows startdate after absorbing organisation has become available" do
record.startdate = Time.zone.local(2023, 2, 2) record.startdate = org_available_from + 1.month
record.managing_organisation_id = absorbing_organisation.id record.managing_organisation_id = absorbing_organisation.id
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
setup_validator.validate_merged_organisations_start_date(record) setup_validator.validate_merged_organisations_start_date(record)
@ -262,7 +221,7 @@ RSpec.describe Validations::SetupValidations do
end end
it "allows startdate if organisation does not have available from date" do it "allows startdate if organisation does not have available from date" do
record.startdate = Time.zone.local(2023, 1, 1) record.startdate = org_available_from - 1.month
absorbing_organisation.update!(available_from: nil) absorbing_organisation.update!(available_from: nil)
record.managing_organisation_id = absorbing_organisation.id record.managing_organisation_id = absorbing_organisation.id
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
@ -273,16 +232,16 @@ RSpec.describe Validations::SetupValidations do
context "and owning and managing organisation is no longer active during the startdate" do context "and owning and managing organisation is no longer active during the startdate" do
it "does not allow startdate after organisation has been merged" do it "does not allow startdate after organisation has been merged" do
record.startdate = Time.zone.local(2023, 3, 1) record.startdate = org_merge_date + 1.month
record.managing_organisation_id = merged_organisation.id record.managing_organisation_id = merged_organisation.id
record.owning_organisation_id = merged_organisation.id record.owning_organisation_id = merged_organisation.id
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
setup_validator.validate_merged_organisations_start_date(record) setup_validator.validate_merged_organisations_start_date(record)
expect(record.errors["startdate"]).to include(match "Enter a date when the owning and managing organisation was active. Merged org became inactive on 2 February 2023 and was replaced by Absorbing org.") expect(record.errors["startdate"]).to include(match "Enter a date when the owning and managing organisation was active. Merged org became inactive on #{merge_date_formatted} and was replaced by Absorbing org.")
end end
it "allows startdate before organisation has been merged" do it "allows startdate before organisation has been merged" do
record.startdate = Time.zone.local(2023, 1, 1) record.startdate = org_merge_date - 1.month
record.managing_organisation_id = merged_organisation.id record.managing_organisation_id = merged_organisation.id
record.owning_organisation_id = merged_organisation.id record.owning_organisation_id = merged_organisation.id
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
@ -293,16 +252,16 @@ RSpec.describe Validations::SetupValidations do
context "and owning and managing organisation is not yet active during the startdate" do context "and owning and managing organisation is not yet active during the startdate" do
it "does not allow startdate before absorbing organisation has become available" do it "does not allow startdate before absorbing organisation has become available" do
record.startdate = Time.zone.local(2023, 1, 1) record.startdate = org_available_from - 1.month
record.managing_organisation_id = absorbing_organisation.id record.managing_organisation_id = absorbing_organisation.id
record.owning_organisation_id = absorbing_organisation.id record.owning_organisation_id = absorbing_organisation.id
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
setup_validator.validate_merged_organisations_start_date(record) setup_validator.validate_merged_organisations_start_date(record)
expect(record.errors["startdate"]).to include(match "Enter a date when the owning and managing organisation was active. Absorbing org became active on 1 February 2023.") expect(record.errors["startdate"]).to include(match "Enter a date when the owning and managing organisation was active. Absorbing org became active on #{available_from_formatted}.")
end end
it "allows startdate after absorbing organisation has become available" do it "allows startdate after absorbing organisation has become available" do
record.startdate = Time.zone.local(2023, 2, 1) record.startdate = org_available_from + 1.month
record.managing_organisation_id = absorbing_organisation.id record.managing_organisation_id = absorbing_organisation.id
record.owning_organisation_id = absorbing_organisation.id record.owning_organisation_id = absorbing_organisation.id
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
@ -311,7 +270,7 @@ RSpec.describe Validations::SetupValidations do
end end
it "allows startdate if organisation does not have available from date" do it "allows startdate if organisation does not have available from date" do
record.startdate = Time.zone.local(2023, 1, 1) record.startdate = org_available_from - 1.month
absorbing_organisation.update!(available_from: nil) absorbing_organisation.update!(available_from: nil)
record.managing_organisation_id = absorbing_organisation.id record.managing_organisation_id = absorbing_organisation.id
record.owning_organisation_id = absorbing_organisation.id record.owning_organisation_id = absorbing_organisation.id
@ -323,16 +282,16 @@ RSpec.describe Validations::SetupValidations do
context "and owning and managing organisations are no longer active during the startdate" do context "and owning and managing organisations are no longer active during the startdate" do
it "does not allow startdate after organisation have been merged" do it "does not allow startdate after organisation have been merged" do
record.startdate = Time.zone.local(2023, 2, 2) record.startdate = org_merge_date + 1.month
record.managing_organisation_id = merged_organisation.id record.managing_organisation_id = merged_organisation.id
record.owning_organisation_id = merged_organisation_2.id record.owning_organisation_id = merged_organisation_2.id
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
setup_validator.validate_merged_organisations_start_date(record) setup_validator.validate_merged_organisations_start_date(record)
expect(record.errors["startdate"]).to include(match "Enter a date when the owning and managing organisations were active. Merged org 2 and Merged org became inactive on 2 February 2023 and were replaced by Absorbing org.") expect(record.errors["startdate"]).to include(match "Enter a date when the owning and managing organisations were active. Merged org 2 and Merged org became inactive on #{merge_date_formatted} and were replaced by Absorbing org.")
end end
it "allows startdate before organisations have been merged" do it "allows startdate before organisations have been merged" do
record.startdate = Time.zone.local(2023, 1, 1) record.startdate = org_merge_date - 1.month
record.managing_organisation_id = merged_organisation.id record.managing_organisation_id = merged_organisation.id
record.owning_organisation_id = merged_organisation_2.id record.owning_organisation_id = merged_organisation_2.id
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
@ -343,20 +302,20 @@ RSpec.describe Validations::SetupValidations do
context "and owning and managing organisations are from different merges and no longer active during the startdate" do context "and owning and managing organisations are from different merges and no longer active during the startdate" do
before do before do
merged_organisation_2.update!(absorbing_organisation: absorbing_organisation_2, merge_date: Time.zone.local(2023, 2, 2)) merged_organisation_2.update!(absorbing_organisation: absorbing_organisation_2, merge_date: org_merge_date)
end end
it "does not allow startdate after organisations have been merged" do it "does not allow startdate after organisations have been merged" do
record.startdate = Time.zone.local(2023, 3, 1) record.startdate = org_merge_date + 1.month
record.managing_organisation_id = merged_organisation.id record.managing_organisation_id = merged_organisation.id
record.owning_organisation_id = merged_organisation_2.id record.owning_organisation_id = merged_organisation_2.id
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
setup_validator.validate_merged_organisations_start_date(record) setup_validator.validate_merged_organisations_start_date(record)
expect(record.errors["startdate"]).to include(match "Enter a date when the owning and managing organisations were active. Merged org 2 became inactive on 2 February 2023 and was replaced by Absorbing org 2. Merged org became inactive on 2 February 2023 and was replaced by Absorbing org.") expect(record.errors["startdate"]).to include(match "Enter a date when the owning and managing organisations were active. Merged org 2 became inactive on #{merge_date_formatted} and was replaced by Absorbing org 2. Merged org became inactive on #{merge_date_formatted} and was replaced by Absorbing org.")
end end
it "allows startdate before organisations have been merged" do it "allows startdate before organisations have been merged" do
record.startdate = Time.zone.local(2023, 1, 1) record.startdate = org_merge_date - 1.month
record.managing_organisation_id = merged_organisation.id record.managing_organisation_id = merged_organisation.id
record.owning_organisation_id = merged_organisation_2.id record.owning_organisation_id = merged_organisation_2.id
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
@ -367,20 +326,20 @@ RSpec.describe Validations::SetupValidations do
context "and owning and managing organisation have different merges and are not yet active during the startdate" do context "and owning and managing organisation have different merges and are not yet active during the startdate" do
before do before do
merged_organisation_2.update!(absorbing_organisation: absorbing_organisation_2, merge_date: Time.zone.local(2023, 2, 2)) merged_organisation_2.update!(absorbing_organisation: absorbing_organisation_2, merge_date: org_merge_date)
end end
it "does not allow startdate before absorbing organisation has become available" do it "does not allow startdate before absorbing organisation has become available" do
record.startdate = Time.zone.local(2023, 1, 1) record.startdate = org_available_from - 1.month
record.managing_organisation_id = absorbing_organisation.id record.managing_organisation_id = absorbing_organisation.id
record.owning_organisation_id = absorbing_organisation_2.id record.owning_organisation_id = absorbing_organisation_2.id
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
setup_validator.validate_merged_organisations_start_date(record) setup_validator.validate_merged_organisations_start_date(record)
expect(record.errors["startdate"]).to include(match "Enter a date when the owning and managing organisations were active. Absorbing org 2 became active on 1 February 2023, and Absorbing org became active on 1 February 2023.") expect(record.errors["startdate"]).to include(match "Enter a date when the owning and managing organisations were active. Absorbing org 2 became active on #{available_from_formatted}, and Absorbing org became active on #{available_from_formatted}.")
end end
it "allows startdate after absorbing organisation has become available" do it "allows startdate after absorbing organisation has become available" do
record.startdate = Time.zone.local(2023, 2, 2) record.startdate = org_available_from + 1.month
record.managing_organisation_id = absorbing_organisation.id record.managing_organisation_id = absorbing_organisation.id
record.owning_organisation_id = absorbing_organisation.id record.owning_organisation_id = absorbing_organisation.id
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)
@ -390,7 +349,7 @@ RSpec.describe Validations::SetupValidations do
it "allows startdate if organisation does not have available from date" do it "allows startdate if organisation does not have available from date" do
absorbing_organisation.update!(available_from: nil) absorbing_organisation.update!(available_from: nil)
record.startdate = Time.zone.local(2023, 1, 1) record.startdate = org_available_from - 1.month
record.managing_organisation_id = absorbing_organisation.id record.managing_organisation_id = absorbing_organisation.id
record.owning_organisation_id = absorbing_organisation.id record.owning_organisation_id = absorbing_organisation.id
setup_validator.validate_startdate_setup(record) setup_validator.validate_startdate_setup(record)

20
spec/models/validations/soft_validations_spec.rb

@ -18,7 +18,7 @@ RSpec.describe Validations::SoftValidations do
soft_max: 89.54, soft_max: 89.54,
hard_min: 9.87, hard_min: 9.87,
hard_max: 100.99, hard_max: 100.99,
start_year: 2021, start_year: current_collection_start_year,
) )
record.la = "E07000223" record.la = "E07000223"
@ -26,7 +26,7 @@ RSpec.describe Validations::SoftValidations do
record.rent_type = 0 record.rent_type = 0
record.beds = 1 record.beds = 1
record.period = 1 record.period = 1
record.startdate = Time.zone.local(2021, 10, 10) record.startdate = current_collection_start_date
end end
context "when validating soft min" do context "when validating soft min" do
@ -504,16 +504,16 @@ RSpec.describe Validations::SoftValidations do
describe "major repairs date soft validations" do describe "major repairs date soft validations" do
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.startdate = Time.zone.local(2022, 2, 1) record.startdate = current_collection_start_date
record.mrcdate = Time.zone.local(2013, 2, 1) record.mrcdate = current_collection_start_date - 9.years
expect(record.major_repairs_date_in_soft_range?).to be true expect(record.major_repairs_date_in_soft_range?).to be true
end end
end end
context "when the major repairs date is less than 2 years before the tenancy start date" do context "when the major repairs date is less than 2 years before the tenancy start date" do
it "does not show the interruption screen" do it "does not show the interruption screen" do
record.startdate = Time.zone.local(2022, 2, 1) record.startdate = current_collection_start_date
record.mrcdate = Time.zone.local(2021, 2, 1) record.mrcdate = current_collection_start_date - 1.year
expect(record.major_repairs_date_in_soft_range?).to be false expect(record.major_repairs_date_in_soft_range?).to be false
end end
end end
@ -540,16 +540,16 @@ RSpec.describe Validations::SoftValidations do
describe "void date soft validations" do describe "void date soft validations" do
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.startdate = Time.zone.local(2022, 2, 1) record.startdate = current_collection_start_date
record.voiddate = Time.zone.local(2013, 2, 1) record.voiddate = current_collection_start_date - 9.years
expect(record.voiddate_in_soft_range?).to be true expect(record.voiddate_in_soft_range?).to be true
end end
end end
context "when the void date is less than 2 years before the tenancy start date" do context "when the void date is less than 2 years before the tenancy start date" do
it "does not show the interruption screen" do it "does not show the interruption screen" do
record.startdate = Time.zone.local(2022, 2, 1) record.startdate = current_collection_start_date
record.voiddate = Time.zone.local(2021, 2, 1) record.voiddate = current_collection_start_date - 1.year
expect(record.voiddate_in_soft_range?).to be false expect(record.voiddate_in_soft_range?).to be false
end end
end end

227
spec/requests/sales_logs_controller_spec.rb

@ -1,6 +1,8 @@
require "rails_helper" require "rails_helper"
RSpec.describe SalesLogsController, type: :request do RSpec.describe SalesLogsController, type: :request do
include CollectionTimeHelper
let(:user) { FactoryBot.create(:user) } let(:user) { FactoryBot.create(:user) }
let(:owning_organisation) { user.organisation } let(:owning_organisation) { user.organisation }
let(:api_username) { "test_user" } let(:api_username) { "test_user" }
@ -26,18 +28,11 @@ RSpec.describe SalesLogsController, type: :request do
end end
before do before do
Timecop.freeze(Time.zone.local(2024, 3, 1))
Singleton.__init__(FormHandler)
allow(ENV).to receive(:[]) allow(ENV).to receive(:[])
allow(ENV).to receive(:[]).with("API_USER").and_return(api_username) allow(ENV).to receive(:[]).with("API_USER").and_return(api_username)
allow(ENV).to receive(:[]).with("API_KEY").and_return(api_password) allow(ENV).to receive(:[]).with("API_KEY").and_return(api_password)
end end
after do
Timecop.return
Singleton.__init__(FormHandler)
end
describe "POST #create" do describe "POST #create" do
context "when API" do context "when API" do
before do before do
@ -70,19 +65,30 @@ RSpec.describe SalesLogsController, type: :request do
end end
context "with a request containing invalid json parameters" do context "with a request containing invalid json parameters" do
# These examples need logs in both the previous and the current collection year,
# so we have to enforce we are in the crossover period
around do |example|
Timecop.freeze(current_collection_start_date) do
Singleton.__init__(FormHandler)
example.run
end
Singleton.__init__(FormHandler)
end
let(:params) do let(:params) do
invalid_sales_log = FactoryBot.build(
:sales_log,
:completed,
assigned_to: user,
owning_organisation: owning_organisation,
managing_organisation: owning_organisation,
saledate: archived_collection_start_date,
beds: 2,
proptype: 2,
)
{ {
"owning_organisation_id": owning_organisation.id, sales_log: invalid_sales_log.attributes,
"managing_organisation_id": owning_organisation.id,
"assigned_to_id": user.id,
"saledate": Time.zone.today,
"purchid": "1",
"ownershipsch": 1,
"type": 2,
"jointpur": 1,
"jointmore": 1,
"beds": 2,
"proptype": 2,
} }
end end
@ -93,7 +99,26 @@ RSpec.describe SalesLogsController, type: :request do
it "validates sales log parameters" do it "validates sales log parameters" do
json_response = JSON.parse(response.body) json_response = JSON.parse(response.body)
expect(response).to have_http_status(:unprocessable_content) expect(response).to have_http_status(:unprocessable_content)
expect(json_response["errors"]).to contain_exactly(["beds", ["Number of bedrooms must be 1 if the property is a bedsit."]], ["proptype", ["Answer cannot be 'Bedsit' if the property has 2 or more bedrooms."]]) expect(json_response["errors"]).to contain_exactly(
[
"beds",
[
"Number of bedrooms must be 1 if the property is a bedsit.",
],
],
[
"proptype",
[
"Answer cannot be 'Bedsit' if the property has 2 or more bedrooms.",
],
],
[
"saledate",
[
"Enter a date within the #{previous_collection_start_year} to #{previous_collection_end_year} or #{current_collection_start_year} to #{current_collection_end_year} collection years, which is between 1st April #{previous_collection_start_year} and 31st March #{current_collection_end_year}.",
],
],
)
end end
end end
end end
@ -341,72 +366,70 @@ RSpec.describe SalesLogsController, type: :request do
end end
context "with year filter" do context "with year filter" do
before do # Needs logs in both the previous and the current collection year, so must run inside
Timecop.freeze(2022, 4, 1) # the crossover period, when new logs can still be created for both.
sales_log_2022.update!(saledate: Time.zone.local(2022, 4, 1)) around do |example|
Timecop.freeze(2023, 1, 1) Timecop.freeze(current_collection_start_date) do
sales_log_2022.update!(saledate: Time.zone.local(2023, 1, 1)) Singleton.__init__(FormHandler)
end example.run
end
after do Singleton.__init__(FormHandler)
Timecop.unfreeze
end end
let!(:sales_log_2022) do let!(:sales_log_current) do
FactoryBot.create(:sales_log, :completed, FactoryBot.create(:sales_log, :completed,
owning_organisation: organisation, owning_organisation: organisation,
assigned_to: user, assigned_to: user,
saledate: Time.zone.today) saledate: current_collection_start_date)
end end
let!(:sales_log_2023) do let!(:sales_log_previous) do
FactoryBot.create(:sales_log, FactoryBot.create(:sales_log,
owning_organisation: organisation, owning_organisation: organisation,
assigned_to: user, assigned_to: user,
saledate: Time.zone.today) saledate: previous_collection_start_date)
end end
it "shows sales logs for multiple selected years" do it "shows sales logs for multiple selected years" do
get "/sales-logs?years[]=2021&years[]=2022", headers: headers, params: {} get "/sales-logs?years[]=#{previous_collection_start_year}&years[]=#{current_collection_start_year}", headers: headers, params: {}
expect(page).to have_link(sales_log_2022.id.to_s) expect(page).to have_link(sales_log_current.id.to_s)
expect(page).to have_link(sales_log_2023.id.to_s) expect(page).to have_link(sales_log_previous.id.to_s)
end end
it "shows sales logs for one selected year" do it "shows sales logs for one selected year" do
get "/sales-logs?years[]=2022", headers: headers, params: {} get "/sales-logs?years[]=#{current_collection_start_year}", headers: headers, params: {}
expect(page).to have_link(sales_log_2022.id.to_s) expect(page).to have_link(sales_log_current.id.to_s)
expect(page).to have_link(sales_log_2023.id.to_s) expect(page).not_to have_link(sales_log_previous.id.to_s)
end end
end end
context "with year and status filter" do context "with year and status filter" do
before do # Needs logs in both the previous and the current collection year, so must run inside
Timecop.freeze(2022, 4, 1) # the crossover period, when new logs can still be created for both.
sales_log_2022.update!(saledate: Time.zone.local(2022, 4, 1)) around do |example|
Timecop.freeze(2023, 1, 1) Timecop.freeze(current_collection_start_date) do
sales_log_2022.update!(saledate: Time.zone.local(2023, 1, 1)) Singleton.__init__(FormHandler)
end example.run
end
after do Singleton.__init__(FormHandler)
Timecop.unfreeze
end end
let!(:sales_log_2022) do let!(:sales_log_current) do
FactoryBot.create(:sales_log, :completed, FactoryBot.create(:sales_log, :completed,
owning_organisation: organisation, owning_organisation: organisation,
assigned_to: user, assigned_to: user,
saledate: Time.zone.today) saledate: current_collection_start_date)
end end
let!(:sales_log_2023) do let!(:sales_log_previous) do
FactoryBot.create(:sales_log, FactoryBot.create(:sales_log,
owning_organisation: organisation, owning_organisation: organisation,
assigned_to: user, assigned_to: user,
saledate: Time.zone.today) saledate: previous_collection_start_date)
end end
it "shows sales logs for multiple selected statuses and years" do it "shows sales logs for multiple selected statuses and years" do
get "/sales-logs?years[]=2021&years[]=2022&status[]=in_progress&status[]=completed", headers: headers, params: {} get "/sales-logs?years[]=#{previous_collection_start_year}&years[]=#{current_collection_start_year}&status[]=in_progress&status[]=completed", headers: headers, params: {}
expect(page).to have_link(sales_log_2022.id.to_s) expect(page).to have_link(sales_log_current.id.to_s)
expect(page).to have_link(sales_log_2023.id.to_s) expect(page).to have_link(sales_log_previous.id.to_s)
end end
end end
@ -856,10 +879,6 @@ RSpec.describe SalesLogsController, type: :request do
before do before do
sign_in user sign_in user
Timecop.freeze(2021, 4, 1)
Singleton.__init__(FormHandler)
completed_sales_log.update!(saledate: Time.zone.local(2021, 4, 1))
completed_sales_log.reload
end end
context "with sales logs that are owned by your organisation" do context "with sales logs that are owned by your organisation" do
@ -867,22 +886,17 @@ RSpec.describe SalesLogsController, type: :request do
get "/sales-logs/#{completed_sales_log.id}", headers:, params: {} get "/sales-logs/#{completed_sales_log.id}", headers:, params: {}
end end
after do
Timecop.return
Singleton.__init__(FormHandler)
end
it "shows the tasklist for sales logs you have access to" do it "shows the tasklist for sales logs you have access to" do
expect(response.body).to match("Log") expect(response.body).to match("Log")
expect(response.body).to match(completed_sales_log.id.to_s) expect(response.body).to match(completed_sales_log.id.to_s)
end end
it "displays a link to update the log for currently editable logs" do it "displays a link to update the log for currently editable logs" do
completed_sales_log.update!(saledate: Time.zone.local(2021, 4, 1)) completed_sales_log.update!(saledate: current_collection_start_date)
completed_sales_log.reload completed_sales_log.reload
get "/sales-logs/#{completed_sales_log.id}", headers:, params: {} get "/sales-logs/#{completed_sales_log.id}", headers:, params: {}
expect(completed_sales_log.form.new_logs_end_date).to eq(Time.zone.local(2022, 12, 31)) expect(completed_sales_log.form.new_logs_end_date).to eq(FormHandler.instance.current_sales_form.new_logs_end_date)
expect(completed_sales_log.status).to eq("completed") expect(completed_sales_log.status).to eq("completed")
expect(page).to have_link("review and make changes to this log", href: "/sales-logs/#{completed_sales_log.id}/review?sales_log=true") expect(page).to have_link("review and make changes to this log", href: "/sales-logs/#{completed_sales_log.id}/review?sales_log=true")
end end
@ -894,53 +908,44 @@ RSpec.describe SalesLogsController, type: :request do
get "/sales-logs/#{completed_sales_log.id}", headers:, params: {} get "/sales-logs/#{completed_sales_log.id}", headers:, params: {}
end end
after do
Timecop.return
Singleton.__init__(FormHandler)
end
it "shows the tasklist for sales logs you have access to" do it "shows the tasklist for sales logs you have access to" do
expect(response.body).to match("Log") expect(response.body).to match("Log")
expect(response.body).to match(completed_sales_log.id.to_s) expect(response.body).to match(completed_sales_log.id.to_s)
end end
end end
context "with sales logs from a closed collection period before the previous collection" do context "with sales logs from a closed previous collection period" do
before do let(:completed_sales_log) do
sign_in user FactoryBot.create(
Timecop.return :sales_log,
Singleton.__init__(FormHandler) :completed,
get "/sales-logs/#{completed_sales_log.id}", headers:, params: {} :ignore_validation_errors,
end owning_organisation: user.organisation,
assigned_to: user,
it "redirects to review page" do saledate: archived_collection_start_date,
expect(response).to redirect_to("/sales-logs/#{completed_sales_log.id}/review?sales_log=true") )
end end
end let(:closed_previous_sales_form) { FormHandler.instance.sales_form_for_start_year(archived_collection_start_year) }
# let(:closed_previous_collection_end) { previous_collection_end_date.to_time.end_of_day }
context "with sales logs from a closed previous collection period" do
before do before do
sign_in user sign_in user
Timecop.freeze(2023, 2, 1) # allow(closed_previous_sales_form).to receive_messages(
Singleton.__init__(FormHandler) # new_logs_end_date: closed_previous_collection_end,
# edit_end_date: closed_previous_collection_end,
# )
get "/sales-logs/#{completed_sales_log.id}", headers:, params: {} get "/sales-logs/#{completed_sales_log.id}", headers:, params: {}
end end
after do
Timecop.return
Singleton.__init__(FormHandler)
end
it "redirects to review page" do it "redirects to review page" do
expect(response).to redirect_to("/sales-logs/#{completed_sales_log.id}/review?sales_log=true") expect(response).to redirect_to("/sales-logs/#{completed_sales_log.id}/review?sales_log=true")
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
get "/sales-logs/#{completed_sales_log.id}", headers:, params: {} get "/sales-logs/#{completed_sales_log.id}", headers:, params: {}
expect(completed_sales_log.form.new_logs_end_date).to eq(Time.zone.local(2022, 12, 31))
expect(completed_sales_log.status).to eq("completed") expect(completed_sales_log.status).to eq("completed")
follow_redirect! follow_redirect!
expect(page).to have_content("This log is from the 2021 to 2022 collection window, which is now closed.") expect(page).to have_content("This log is from the #{archived_collection_start_year} to #{archived_collection_end_year} collection window, which is now closed.")
end end
end end
@ -959,6 +964,7 @@ RSpec.describe SalesLogsController, type: :request do
let(:headers) { { "Accept" => "text/html" } } let(:headers) { { "Accept" => "text/html" } }
let(:search_term) { "foot" } let(:search_term) { "foot" }
let(:codes_only) { false } let(:codes_only) { false }
let(:selected_year) { current_collection_start_year }
before do before do
create(:sales_log, :in_progress, assigned_to: user, purchid: search_term) create(:sales_log, :in_progress, assigned_to: user, purchid: search_term)
@ -968,7 +974,7 @@ RSpec.describe SalesLogsController, type: :request do
context "when there is 1 year selected in the filters" do context "when there is 1 year selected in the filters" do
before do before do
get "/sales-logs/csv-download?years[]=2023&search=#{search_term}&codes_only=#{codes_only}", headers: get "/sales-logs/csv-download?years[]=#{selected_year}&search=#{search_term}&codes_only=#{codes_only}", headers:
end end
it "returns http success" do it "returns http success" do
@ -1023,7 +1029,7 @@ RSpec.describe SalesLogsController, type: :request do
context "when user is not support" do context "when user is not support" do
before do before do
get "/sales-logs/csv-download?years[]=2023&search=#{search_term}&codes_only=#{codes_only}", headers: get "/sales-logs/csv-download?years[]=#{selected_year}&search=#{search_term}&codes_only=#{codes_only}", headers:
end end
context "and export type is not codes only" do context "and export type is not codes only" do
@ -1069,7 +1075,7 @@ RSpec.describe SalesLogsController, type: :request do
let(:user) { FactoryBot.create(:user, :support) } let(:user) { FactoryBot.create(:user, :support) }
before do before do
get "/sales-logs/csv-download?years[]=2023&search=#{search_term}&codes_only=#{codes_only}", headers: get "/sales-logs/csv-download?years[]=#{selected_year}&search=#{search_term}&codes_only=#{codes_only}", headers:
end end
context "and export type is not codes only" do context "and export type is not codes only" do
@ -1100,6 +1106,7 @@ RSpec.describe SalesLogsController, type: :request do
end end
describe "POST #email-csv" do describe "POST #email-csv" do
let(:selected_year) { current_collection_start_year }
let(:other_organisation) { FactoryBot.create(:organisation) } let(:other_organisation) { FactoryBot.create(:organisation) }
let(:user) { FactoryBot.create(:user, :support) } let(:user) { FactoryBot.create(:user, :support) }
let!(:sales_log) do let!(:sales_log) do
@ -1121,42 +1128,42 @@ RSpec.describe SalesLogsController, type: :request do
it "creates an E-mail job with the correct log type" do it "creates an E-mail job with the correct log type" do
expect { expect {
post "/sales-logs/email-csv?years[]=2023&codes_only=true", headers:, params: {} post "/sales-logs/email-csv?years[]=#{selected_year}&codes_only=true", headers:, params: {}
}.to enqueue_job(EmailCsvJob).with(user, nil, { "years" => %w[2023] }, false, nil, true, "sales", 2023) }.to enqueue_job(EmailCsvJob).with(user, nil, { "years" => [selected_year.to_s] }, false, nil, true, "sales", selected_year)
end end
it "redirects to the confirmation page" do it "redirects to the confirmation page" do
post "/sales-logs/email-csv?years[]=2023&codes_only=true", headers:, params: {} post "/sales-logs/email-csv?years[]=#{selected_year}&codes_only=true", headers:, params: {}
expect(response).to redirect_to(csv_confirmation_sales_logs_path) expect(response).to redirect_to(csv_confirmation_sales_logs_path)
end end
it "passes the search term" do it "passes the search term" do
expect { expect {
post "/sales-logs/email-csv?search=#{sales_log.id}&years[]=2023&codes_only=false", headers:, params: {} post "/sales-logs/email-csv?search=#{sales_log.id}&years[]=#{selected_year}&codes_only=false", headers:, params: {}
}.to enqueue_job(EmailCsvJob).with(user, sales_log.id.to_s, { "years" => %w[2023] }, false, nil, false, "sales", 2023) }.to enqueue_job(EmailCsvJob).with(user, sales_log.id.to_s, { "years" => [selected_year.to_s] }, false, nil, false, "sales", selected_year)
end end
it "passes filter parameters" do it "passes filter parameters" do
expect { expect {
post "/sales-logs/email-csv?years[]=2023&status[]=completed&codes_only=true", headers:, params: {} post "/sales-logs/email-csv?years[]=#{selected_year}&status[]=completed&codes_only=true", headers:, params: {}
}.to enqueue_job(EmailCsvJob).with(user, nil, { "status" => %w[completed], "years" => %w[2023] }, false, nil, true, "sales", 2023) }.to enqueue_job(EmailCsvJob).with(user, nil, { "status" => %w[completed], "years" => [selected_year.to_s] }, false, nil, true, "sales", selected_year)
end end
it "passes export type flag" do it "passes export type flag" do
expect { expect {
post "/sales-logs/email-csv?years[]=2023&codes_only=true", headers:, params: {} post "/sales-logs/email-csv?years[]=#{selected_year}&codes_only=true", headers:, params: {}
}.to enqueue_job(EmailCsvJob).with(user, nil, { "years" => %w[2023] }, false, nil, true, "sales", 2023) }.to enqueue_job(EmailCsvJob).with(user, nil, { "years" => [selected_year.to_s] }, false, nil, true, "sales", selected_year)
expect { expect {
post "/sales-logs/email-csv?years[]=2023&codes_only=false", headers:, params: {} post "/sales-logs/email-csv?years[]=#{selected_year}&codes_only=false", headers:, params: {}
}.to enqueue_job(EmailCsvJob).with(user, nil, { "years" => %w[2023] }, false, nil, false, "sales", 2023) }.to enqueue_job(EmailCsvJob).with(user, nil, { "years" => [selected_year.to_s] }, false, nil, false, "sales", selected_year)
end end
it "passes a combination of search term, export type and filter parameters" do it "passes a combination of search term, export type and filter parameters" do
postcode = "XX1 1TG" postcode = "XX1 1TG"
expect { expect {
post "/sales-logs/email-csv?years[]=2023&status[]=completed&search=#{postcode}&codes_only=false", headers:, params: {} post "/sales-logs/email-csv?years[]=#{selected_year}&status[]=completed&search=#{postcode}&codes_only=false", headers:, params: {}
}.to enqueue_job(EmailCsvJob).with(user, postcode, { "status" => %w[completed], "years" => %w[2023] }, false, nil, false, "sales", 2023) }.to enqueue_job(EmailCsvJob).with(user, postcode, { "status" => %w[completed], "years" => [selected_year.to_s] }, false, nil, false, "sales", selected_year)
end end
context "when the user is not a support user" do context "when the user is not a support user" do
@ -1165,13 +1172,13 @@ RSpec.describe SalesLogsController, type: :request do
it "has permission to download human readable csv" do it "has permission to download human readable csv" do
codes_only_export = false codes_only_export = false
expect { expect {
post "/sales-logs/email-csv?years[]=2023&codes_only=#{codes_only_export}", headers:, params: {} post "/sales-logs/email-csv?years[]=#{selected_year}&codes_only=#{codes_only_export}", headers:, params: {}
}.to enqueue_job(EmailCsvJob).with(user, nil, { "years" => %w[2023] }, false, nil, false, "sales", 2023) }.to enqueue_job(EmailCsvJob).with(user, nil, { "years" => [selected_year.to_s] }, false, nil, false, "sales", selected_year)
end end
it "is not authorized to download codes only csv" do it "is not authorized to download codes only csv" do
codes_only_export = true codes_only_export = true
post "/sales-logs/email-csv?years[]=2023&codes_only=#{codes_only_export}", headers:, params: {} post "/sales-logs/email-csv?years[]=#{selected_year}&codes_only=#{codes_only_export}", headers:, params: {}
expect(response).to have_http_status(:unauthorized) expect(response).to have_http_status(:unauthorized)
end end
end end

Loading…
Cancel
Save