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-screenshot"
gem "rspec-rails", require: false
gem "selenium-webdriver", require: false
gem "selenium-webdriver", "~> 4.43", require: false
gem "simplecov", require: false
gem "timecop", "~> 0.9.4"
gem "webmock", require: false

7
Gemfile.lock

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

6
app/helpers/collection_time_helper.rb

@ -30,7 +30,7 @@ module CollectionTimeHelper
end
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
def collection_end_date(date)
@ -81,6 +81,10 @@ module CollectionTimeHelper
current_collection_end_year - 2
end
def archived_collection_start_date
current_collection_start_date - 2.years
end
def previous_collection_new_logs_end_date
FormHandler.instance.lettings_form_for_start_year(previous_collection_start_year).new_logs_end_date
end

6
spec/components/check_answers_summary_list_card_component_spec.rb

@ -1,6 +1,8 @@
require "rails_helper"
RSpec.describe CheckAnswersSummaryListCardComponent, type: :component do
include CollectionTimeHelper
subject(:component) { described_class.new(questions:, log:, user:) }
let(:rendered) { render_inline(component) }
@ -65,9 +67,9 @@ RSpec.describe CheckAnswersSummaryListCardComponent, type: :component do
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
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
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"
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 CollectionTimeHelper
let(:user) { FactoryBot.create(:user) }
let(:subsection) { "household-characteristics" }
let(:conditional_subsection) { "conditional-question" }
let(:subsection) { "household-needs" }
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
FactoryBot.create(
@ -31,9 +23,7 @@ RSpec.describe "Lettings Log Check Answers Page" do
let(:empty_lettings_log) do
FactoryBot.create(
:lettings_log,
previous_la_known: 1,
prevloc: "E09000033",
is_previous_la_inferred: false,
:setup_completed,
assigned_to: user,
)
end
@ -44,21 +34,17 @@ RSpec.describe "Lettings Log Check Answers Page" do
owning_organisation: user.organisation,
managing_organisation: user.organisation,
assigned_to: user,
startdate: Time.zone.local(2021, 5, 1),
startdate: current_collection_start_date,
)
end
let(:id) { lettings_log.id }
let(:fake_2021_2022_form) { Form.new("spec/fixtures/forms/2021_2022.json") }
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
allow(FormHandler.instance).to receive(:current_lettings_form).and_return(fake_2021_2022_form)
end
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
visit("/lettings-logs/#{id}/#{subsection}/check-answers")
@ -66,80 +52,46 @@ RSpec.describe "Lettings Log Check Answers Page" do
end
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")
end
it "has question headings based on the subsection" do
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|
expect(page).to have_content(label)
end
end
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")
choose("lettings-log-sex1-x-field")
click_button("Save and continue")
visit("/lettings-logs/#{empty_lettings_log.id}/#{subsection}/check-answers")
expect(page).to have_content("28")
expect(page).to have_content("Non-binary")
fill_in_radio_question(id, "armedforces", "3", "armed-forces")
fill_in_radio_question(id, "illness", "2", "health-conditions")
visit("/lettings-logs/#{id}/#{subsection}/check-answers")
expect(page).to have_content("No")
expect(page).to have_content("Person prefers not to say")
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
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
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
it "has a change link for answered question" do
fill_in_number_question(empty_lettings_log.id, "age1", 28, "person-1-age")
visit("/lettings-logs/#{empty_lettings_log.id}/#{subsection}/check-answers")
fill_in_radio_question(id, "armedforces", "2", "armed-forces")
visit("/lettings-logs/#{id}/#{subsection}/check-answers")
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
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
visit("/lettings-logs/#{empty_lettings_log.id}/accessibility-requirements")
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
expect(page).to have_link("Change", href: "/lettings-logs/#{id}/armed-forces?referrer=check_answers")
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
@ -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
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: "Person 2", count: 1
end
@ -157,7 +109,7 @@ RSpec.describe "Lettings Log Check Answers Page" do
context "when viewing setup section answers" do
before do
FactoryBot.create(:location, scheme:, startdate: Time.zone.local(2021, 1, 1))
FactoryBot.create(:location, scheme:, startdate: current_collection_start_date)
end
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
it "routes back to check answers" do
visit("/lettings-logs/#{empty_lettings_log.id}/accessibility-requirements")
check("lettings-log-accessibility-requirements-housingneeds-c-field")
click_button("Save and continue")
visit("/lettings-logs/#{empty_lettings_log.id}/household-needs/check-answers")
fill_in_radio_question(id, "armedforces", "2", "armed-forces")
visit("/lettings-logs/#{id}/household-needs/check-answers")
first("a", text: /Change/).click
uncheck("lettings-log-accessibility-requirements-housingneeds-c-field")
check("lettings-log-accessibility-requirements-housingneeds-b-field")
choose("lettings-log-armedforces-3-field")
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
@ -224,10 +173,24 @@ RSpec.describe "Lettings Log Check Answers Page" do
sex1: "M",
hhmemb: 1,
armedforces: 3,
preg_occ: 2,
housingneeds: 2,
illness: 1,
housingneeds_h: 1,
la: "E06000014",
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
@ -240,6 +203,7 @@ RSpec.describe "Lettings Log Check Answers Page" do
tenancycode: nil,
hhmemb: nil,
age1: nil,
age2: nil,
layear: 2,
waityear: 1,
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
visit("/lettings-logs/#{skip_section_lettings_log.id}/household-characteristics/check-answers")
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
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")
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

16
spec/features/form/helpers.rb

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

25
spec/features/form/tasklist_page_spec.rb

@ -42,38 +42,16 @@ RSpec.describe "Task List" do
let(:id) { lettings_log.id }
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
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
end
after do
Timecop.unfreeze
end
it "shows if the section has not been started" do
visit("/lettings-logs/#{empty_lettings_log.id}")
expect(page).to have_content("This log has not been started.")
end
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
visit("/lettings-logs/#{setup_completed_log.id}")
expect(page).to have_content("1 of 7 subsections completed.")
@ -81,9 +59,8 @@ RSpec.describe "Task List" do
end
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}")
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
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"
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(:lettings_log) do
FactoryBot.create(
:lettings_log,
:in_progress,
:setup_completed,
assigned_to: user,
renewal: 0,
)
end
let(:empty_lettings_log) do
FactoryBot.create(
:lettings_log,
assigned_to: user,
first_time_property_let_as_social_housing: 0,
unitletas: 1,
rsnvac: 9,
)
end
let(:id) { lettings_log.id }
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
allow(FormHandler.instance).to receive(:current_lettings_form).and_return(fake_2021_2022_form)
end
include Helpers
include CollectionTimeHelper
describe "Question validation" do
context "when the tenant age is invalid" do
it "shows validation for under 0" do
visit("/lettings-logs/#{id}/person-1-age")
fill_in_number_question(empty_lettings_log.id, "age1", -5, "person-1-age")
fill_in_number_question(id, "age1", -5, "lead-tenant-age")
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-field-error")
@ -50,8 +34,7 @@ RSpec.describe "validations" do
end
it "shows validation for over 120" do
visit("/lettings-logs/#{id}/person-1-age")
fill_in_number_question(empty_lettings_log.id, "age1", 121, "person-1-age")
fill_in_number_question(id, "age1", 121, "lead-tenant-age")
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-field-error")
@ -63,11 +46,12 @@ RSpec.describe "validations" do
describe "date validation", :js do
def fill_in_date(lettings_log_id, question, day, month, year, 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("/"))
end
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")
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")
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")
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
it "does not allow non numeric inputs to be submitted" do
@ -95,19 +75,20 @@ RSpec.describe "validations" do
click_button("Save and continue")
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")
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")
expect(page).to have_current_path("/lettings-logs/#{id}/property-major-repairs")
end
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")
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
@ -120,68 +101,69 @@ RSpec.describe "validations" do
hhmemb: 1,
ecstat1: 1,
assigned_to: user,
net_income_known: 0,
)
end
let(:income_over_soft_limit) { 750 }
let(:income_under_soft_limit) { 700 }
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)
choose("lettings-log-incfreq-1-field", allow_label_click: true)
click_button("Save and continue")
end
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("This is higher than we would expect for the household’s working situation.")
expect(page).not_to have_button("Save changes")
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
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_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}/person-1-working-situation?referrer=interruption_screen")
expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income-value-check")
click_link("Change", href: "/lettings-logs/#{lettings_log.id}/net-income?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-net-income-value-check")
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}/lead-tenant-working-situation?referrer=interruption_screen")
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}/income-amount?referrer=interruption_screen", match: :first)
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)
choose("lettings-log-incfreq-1-field", allow_label_click: true)
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).to have_css(".govuk-notification-banner.govuk-notification-banner--success")
end
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_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}/person-1-working-situation?referrer=interruption_screen")
expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income-value-check")
click_link("Change", href: "/lettings-logs/#{lettings_log.id}/person-1-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}/income-amount-net-income-value-check")
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}/lead-tenant-working-situation?referrer=interruption_screen")
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}/lead-tenant-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)
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")
end
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)
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)
expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income?referrer=check_answers")
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}/income-amount?referrer=check_answers")
fill_in("lettings-log-earnings-field", with: income_over_soft_limit)
click_button("Save changes")
expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income-value-check?referrer=check_answers")
click_link("Change", href: "/lettings-logs/#{lettings_log.id}/net-income?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-net-income-value-check?referrer=check_answers")
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}/income-amount?referrer=interruption_screen")
fill_in("lettings-log-earnings-field", with: income_under_soft_limit)
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")
expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/income-and-benefits/check-answers")
end

4
spec/lib/tasks/set_sales_managing_organisation_spec.rb

@ -2,6 +2,8 @@ require "rails_helper"
require "rake"
RSpec.describe "set_sales_managing_organisation" do
include CollectionTimeHelper
describe ":set_sales_managing_organisation", type: :task do
subject(:task) { Rake::Task["set_sales_managing_organisation"] }
@ -34,7 +36,7 @@ RSpec.describe "set_sales_managing_organisation" do
end
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)
expect(sales_log.managing_organisation_id).to be_nil
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,
beds: 4,
lettype: 1,
voiddate: Time.zone.local(2020, 4, 1),
mrcdate: Time.zone.local(2020, 4, 1),
period: 1)
end

135
spec/models/form_handler_spec.rb

@ -1,8 +1,10 @@
require "rails_helper"
RSpec.describe FormHandler do
include CollectionTimeHelper
let(:form_handler) { described_class.instance }
let(:now) { Time.utc(2022, 9, 20) }
let(:now) { current_collection_start_date }
around do |example|
Timecop.freeze(now) do
@ -12,8 +14,6 @@ RSpec.describe FormHandler do
end
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
form = form_handler.get_form("current_lettings")
expect(form).to be_a(Form)
@ -34,65 +34,59 @@ RSpec.describe FormHandler do
expect(all_forms["current_sales"]).to be_a(Form)
end
context "when in 23/24 period or later" do
let(:now) { Time.utc(2023, 6, 7) }
it "does not load outdated forms" do
all_forms = form_handler.forms
expect(all_forms.keys).not_to include nil
end
it "does not load outdated forms" do
all_forms = form_handler.forms
expect(all_forms.keys).not_to include nil
end
it "loads archived forms" do
all_forms = form_handler.forms
expect(all_forms.keys).to include("archived_sales")
expect(all_forms.keys).to include("archived_lettings")
end
it "loads archived forms" do
all_forms = form_handler.forms
expect(all_forms.keys).to include("archived_sales")
expect(all_forms.keys).to include("archived_lettings")
end
end
describe "Get specific form" do
let(:now) { Time.utc(2023, 9, 20) }
it "is able to load a current lettings form" do
form = form_handler.get_form("current_lettings")
expect(form).to be_a(Form)
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
it "is able to load a previous lettings form" do
form = form_handler.get_form("previous_lettings")
expect(form).to be_a(Form)
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
it "is able to load a archived lettings form" do
form = form_handler.get_form("archived_lettings")
expect(form).to be_a(Form)
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
it "is able to load a current sales form" do
form = form_handler.get_form("current_sales")
expect(form).to be_a(Form)
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
it "is able to load a previous sales form" do
form = form_handler.get_form("previous_sales")
expect(form).to be_a(Form)
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
it "is able to load a archived sales form" do
form = form_handler.get_form("archived_sales")
expect(form).to be_a(Form)
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
@ -100,92 +94,92 @@ RSpec.describe FormHandler do
it "returns the latest form by date" do
form = form_handler.current_lettings_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
describe "Current collection start year" 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
expect(form_handler.current_collection_start_year).to eq(2023)
expect(form_handler.current_collection_start_year).to eq(current_collection_start_year)
end
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
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
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
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
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
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
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
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
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
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
expect(form_handler.current_collection_start_year).to eq(2022)
expect(form_handler.current_collection_start_year).to eq(current_collection_start_year)
end
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
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
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
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
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
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
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
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
@ -199,65 +193,20 @@ RSpec.describe FormHandler do
it "correctly sets form type and start year" do
form = form_handler.forms["current_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
# rubocop:disable RSpec/PredicateMatcher
describe "#in_crossover_period?" do
context "when not in overlapping period" 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
context "when in overlapping period" do
it "returns true" do
expect(form_handler.in_crossover_period?(now: Date.new(2022, 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)
expect(form_handler.in_crossover_period?(now: Date.new(current_collection_start_year, 6, 1))).to be_truthy
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(:owning_organisation) { create(:organisation, rent_periods: [2]) }
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 log examples", :lettings_log
@ -40,16 +28,8 @@ RSpec.describe LettingsLog do
describe "#form" do
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_year_2) { build(:lettings_log, startdate: Time.zone.local(2023, 5, 1), assigned_to: assigned_to_user) }
before do
Timecop.freeze(2023, 1, 1)
end
after do
Timecop.unfreeze
end
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: next_collection_start_date, assigned_to: assigned_to_user) }
it "returns the correct form based on the start date" do
expect(lettings_log.form_name).to be_nil
@ -61,11 +41,11 @@ RSpec.describe LettingsLog do
end
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.start_date.year).to eq(2021)
expect(lettings_log.form.start_date.year).to eq(current_collection_start_year)
end
end
end
@ -276,20 +256,22 @@ RSpec.describe LettingsLog do
assigned_to: assigned_to_user,
postcode_full: "M1 1AE",
ppostcode_full: "M2 2AE",
startdate: Time.gm(2021, 10, 10),
mrcdate: Time.gm(2021, 5, 4),
voiddate: Time.gm(2021, 3, 3),
startdate: Time.zone.today,
mrcdate: Time.zone.today - 1.week,
voiddate: Time.zone.today - 2.weeks,
needstype: 1,
renewal: 0,
declaration: 1,
net_income_known: 2, # refused
hhmemb: 7,
rent_type: 4,
hb: 1,
hbrentshortfall: 1,
created_at: Time.utc(2022, 2, 8, 16, 52, 15),
)
end
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(record_from_db[postcode_field]).to eq("M1 1AE")
end
@ -313,6 +295,7 @@ RSpec.describe LettingsLog do
assigned_to: assigned_to_user,
postcode_known: 1,
postcode_full: "M1 1AE",
manual_address_entry_selected: true,
})
end
@ -490,19 +473,11 @@ RSpec.describe LettingsLog do
end
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
lettings_log.needstype = 2
allow(FormHandler.instance).to receive(:get_form).and_return(real_2021_2022_form)
end
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
let(:scheme) { create(:scheme) }
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:) }
before do
Timecop.freeze(Time.zone.local(2022, 4, 2))
Singleton.__init__(FormHandler)
lettings_log.update!(startdate: Time.zone.local(2022, 4, 2), scheme:)
end
after do
Timecop.unfreeze
lettings_log.update!(startdate: current_collection_start_date + 1.day, scheme:, voiddate: nil, mrcdate: nil)
end
it "derives the scheme location" do
@ -579,22 +548,11 @@ RSpec.describe LettingsLog do
Singleton.__init__(FormHandler)
end
context "with 22/23" do
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) }
let(:startdate) { current_collection_start_date }
it "returns the correct la" do
expect(lettings_log["location_id"]).to eq(location.id)
expect(lettings_log.la).to eq("E06000063")
end
it "returns the correct la" do
expect(lettings_log["location_id"]).to eq(location.id)
expect(lettings_log.la).to eq("E06000063")
end
end
@ -657,13 +615,9 @@ RSpec.describe LettingsLog do
context "and the location no local authorities associated with the location_code" do
before do
Timecop.freeze(Time.zone.local(2022, 4, 2))
location.update!(location_code: "E01231231")
lettings_log.update!(location:)
end
after do
Timecop.return
lettings_log.update_columns(la: nil)
lettings_log.reload
end
it "returns the correct la" do
@ -690,7 +644,7 @@ RSpec.describe LettingsLog do
Singleton.__init__(FormHandler)
end
context "with 25/26" do
context "with 25/26", metadata: { year: 25 } do
let(:startdate) { Time.zone.local(2025, 4, 2) }
it "returns the postcode from the location" do
@ -699,7 +653,7 @@ RSpec.describe LettingsLog do
end
end
context "with 26/27" do
context "with 26/27", metadata: { year: 26 } do
let(:startdate) { Time.zone.local(2026, 4, 2) }
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
before do
location.update!(postcode: "AA1 1AA")
Timecop.freeze(startdate)
Singleton.__init__(FormHandler)
lettings_log.update!(startdate:)
lettings_log.update!(postcode_full: nil)
lettings_log.reload
end
after do
Timecop.unfreeze
Singleton.__init__(FormHandler)
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
it "returns the postcode 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
@ -929,23 +872,13 @@ RSpec.describe LettingsLog do
managing_organisation: owning_organisation,
owning_organisation:,
assigned_to: assigned_to_user,
startdate: Time.zone.local(2024, 4, 10),
startdate: current_collection_start_date + 9.days,
needstype: 1,
renewal: 1,
rent_type: 1,
})
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
expect { lettings_log.update!(nationality_all_group: 826, declaration: 1) }.to change(lettings_log, :nationality_all).to 826
end
@ -976,16 +909,6 @@ RSpec.describe LettingsLog do
end
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
let(:address_lettings_log) do
create(:lettings_log,
@ -1054,16 +977,6 @@ RSpec.describe LettingsLog do
end
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
let(:address_lettings_log) do
create(:lettings_log,
@ -1163,17 +1076,18 @@ RSpec.describe LettingsLog do
end
describe "optional fields" do
let(:lettings_log) { create(:lettings_log) }
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
lettings_log.update!({ tshortfall: nil, tshortfall_known: 1 })
expect(lettings_log.optional_fields).to include("tshortfall")
end
end
context "when startdate is after 2023" do
let(:lettings_log) { build(:lettings_log, startdate: Time.zone.parse("2023-07-01")) }
context "when startdate is in the current collection year" do
let(:lettings_log) { build(:lettings_log, startdate: current_collection_start_date + 1.day) }
it "returns optional fields" do
expect(lettings_log.optional_fields).to eq(%w[
@ -1194,6 +1108,7 @@ RSpec.describe LettingsLog do
let(:lettings_log) do
create(
:lettings_log,
:setup_completed,
renewal: 0,
rsnvac: 5,
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
let(:lettings_log) { create(:lettings_log, :in_progress, cbl: 1, preg_occ: 2, wchair: 2) }
it "clears the answer" do
expect { lettings_log.update!(preg_occ: nil) }.to change(lettings_log, :cbl).from(1).to(nil)
it "does not clear the answer" do
expect { lettings_log.update!(preg_occ: nil) }.not_to change(lettings_log, :cbl)
end
context "when the question type does not have answer options" do
let(:lettings_log) { create(:lettings_log, :in_progress, housingneeds_a: 1, age1: 19) }
it "clears the answer" do
expect { lettings_log.update!(housingneeds_a: 0) }.to change(lettings_log, :age1).from(19).to(nil)
it "does not clear the answer" do
expect { lettings_log.update!(housingneeds_a: 0) }.not_to change(lettings_log, :age1)
end
end
@ -1250,31 +1165,6 @@ RSpec.describe LettingsLog do
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
let(:lettings_log) { create(:lettings_log) }
@ -1338,12 +1228,12 @@ RSpec.describe LettingsLog do
it "clears void date value" do
lettings_log.update!(startdate: Time.zone.yesterday)
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
end
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')}/)
end
end
@ -1352,21 +1242,12 @@ RSpec.describe LettingsLog do
it "clears major repairs date value" do
lettings_log.update!(startdate: Time.zone.yesterday)
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
end
end
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
lettings_log.update!(location:, scheme:)
lettings_log.reload
@ -1379,7 +1260,7 @@ RSpec.describe LettingsLog do
end
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')}/)
end
end
@ -1389,16 +1270,16 @@ RSpec.describe LettingsLog do
context "and the new startdate triggers void date validation" 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.startdate).to eq(Time.zone.yesterday)
expect(lettings_log.voiddate).to eq(Time.zone.today)
expect(lettings_log.startdate.to_date).to eq(Time.zone.yesterday.to_date)
expect(lettings_log.voiddate.to_date).to eq(Time.zone.today.to_date)
end
end
context "and the new startdate triggers major repairs date validation" 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.startdate).to eq(Time.zone.yesterday)
expect(lettings_log.mrcdate).to eq(Time.zone.today)
expect(lettings_log.startdate.to_date).to eq(Time.zone.yesterday.to_date)
expect(lettings_log.mrcdate.to_date).to eq(Time.zone.today.to_date)
end
end
@ -1416,7 +1297,7 @@ RSpec.describe LettingsLog do
describe "tshortfall_unknown?" 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
expect(lettings_log.tshortfall_unknown?).to be false
@ -1424,15 +1305,15 @@ RSpec.describe LettingsLog do
end
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
end
end
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
expect(lettings_log.tshortfall_unknown?).to be false
@ -1466,13 +1347,13 @@ RSpec.describe LettingsLog do
soft_max: 400,
hard_min: 50,
hard_max: 500,
start_year: 2021,
start_year: current_collection_start_year,
)
lettings_log.la = "E07000223"
lettings_log.lettype = 1
lettings_log.beds = 1
lettings_log.startdate = Time.zone.local(2021, 10, 10)
lettings_log.startdate = current_collection_start_date + 6.months
end
context "when period is weekly for 52 weeks" do
@ -1501,17 +1382,22 @@ RSpec.describe LettingsLog do
end
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) }
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) }
# 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!(: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" }
before do
Timecop.freeze(Time.utc(2022, 6, 3))
create(:lettings_log, startdate: Time.utc(2022, 6, 3))
end
after do
Timecop.unfreeze
create(:lettings_log, startdate: Time.zone.today)
end
context "when searching logs" do
@ -1689,62 +1575,46 @@ RSpec.describe LettingsLog do
end
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
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
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
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
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_2.startdate = Time.zone.local(2022, 3, 31)
lettings_log_2.startdate = current_collection_start_date - 1.day
lettings_log_2.save!(validate: false)
expect(described_class.filter_by_years(%w[2021]).count).to eq(1)
expect(described_class.filter_by_years(%w[2022]).count).to eq(2)
expect(described_class.filter_by_years([previous_collection_start_year.to_s]).count).to eq(1)
expect(described_class.filter_by_years([current_collection_start_year.to_s]).count).to eq(2)
end
end
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
lettings_log_1.startdate = nil
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
it "allows filtering by multiple years or nil using OR" do
lettings_log_1.startdate = nil
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
it "can filter by year(s) AND status" do
lettings_log_2.startdate = nil
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
@ -2107,28 +1977,23 @@ RSpec.describe LettingsLog do
context "when there is a duplicate supported housing log" do
let(:scheme) { create(:scheme, owning_organisation: organisation) }
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!(:duplicate_supported_housing_log) { create(:lettings_log, :duplicate, needstype: 2, location:, scheme:, owning_organisation: organisation) }
it "returns the log as a duplicate" do
expect(duplicate_sets.count).to eq(2)
expect(duplicate_sets.first).to contain_exactly(log.id, duplicate_log.id)
expect(duplicate_sets.second).to 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)
expect(duplicate_sets).to contain_exactly(
contain_exactly(log.id, duplicate_log.id),
contain_exactly(duplicate_supported_housing_log.id, supported_housing_log.id),
)
end
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)
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.first).to contain_exactly(log.id, duplicate_log.id)
expect(duplicate_sets.second).to contain_exactly(supported_housing_log.id, duplicate_supported_housing_log.id)
expect(duplicate_sets).to contain_exactly(
contain_exactly(log.id, duplicate_log.id),
contain_exactly(supported_housing_log.id, duplicate_supported_housing_log.id),
)
end
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
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.first).to contain_exactly(log.id, duplicate_log.id)
expect(duplicate_sets.second).to contain_exactly(supported_housing_log.id, duplicate_supported_housing_log.id)
expect(duplicate_sets).to contain_exactly(
contain_exactly(log.id, duplicate_log.id),
contain_exactly(supported_housing_log.id, duplicate_supported_housing_log.id),
)
end
it "does not return a duplicate if carehome charge is not given" do
@ -2228,7 +2094,7 @@ RSpec.describe LettingsLog do
end
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
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
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
let(:lettings_log) { build_stubbed(:lettings_log, :setup_completed) }

34
spec/models/location_spec.rb

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

64
spec/models/sales_log_spec.rb

@ -96,17 +96,7 @@ RSpec.describe SalesLog, type: :model do
describe "#form" do
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) }
before do
Timecop.freeze(Time.zone.local(2023, 1, 10))
Singleton.__init__(FormHandler)
end
after do
Timecop.return
Singleton.__init__(FormHandler)
end
let(:sales_log_2) { build(:sales_log, saledate: current_collection_start_date, assigned_to: assigned_to_user) }
it "has returns the correct form based on the start date" do
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) }
context "when proplen is not given" do
before do
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 5, 1))
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))
it "is set to in_progress for a log" do
completed_sales_log.update!(proplen: nil, proplen_asked: 0)
expect(completed_sales_log.in_progress?).to be(true)
expect(completed_sales_log.not_started?).to be(false)
expect(completed_sales_log.completed?).to be(false)
@ -204,27 +190,35 @@ RSpec.describe SalesLog, type: :model do
end
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
create(:sales_log, :in_progress, saledate: nil)
sales_log_2021 = build(:sales_log, :in_progress)
sales_log_2021.saledate = Time.zone.local(2021, 4, 1)
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)
create(:sales_log, :in_progress, saledate: previous_collection_start_date)
create(:sales_log, :in_progress, saledate: current_collection_start_date)
end
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
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
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
@ -277,17 +271,9 @@ RSpec.describe SalesLog, type: :model do
end
end
context "when there is a 2024 log with a different ecstat1" do
let!(:different_ecstat1) { create(:sales_log, :duplicate, ecstat1: 0, owning_organisation: organisation) }
before do
Timecop.freeze(Time.zone.local(2024, 5, 2))
Singleton.__init__(FormHandler)
end
after do
Timecop.return
end
context "when there is a log with a different ecstat1" do
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) }
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)
@ -944,7 +930,7 @@ RSpec.describe SalesLog, type: :model do
end
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
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"
RSpec.describe Scheme, type: :model do
include CollectionTimeHelper
describe "#new" do
let(:scheme) { FactoryBot.create(:scheme) }
@ -483,35 +485,19 @@ RSpec.describe Scheme, type: :model do
end
describe "available_from" do
context "when the scheme was created at the start of the 2022/23 collection window" do
let(:scheme) { FactoryBot.build(:scheme, created_at: Time.zone.local(2022, 4, 6)) }
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)) }
context "when the scheme was created at the start of the collection window" do
let(:scheme) { FactoryBot.build(:scheme, created_at: current_collection_start_date) }
it "returns the beginning of 21/22 collection window" do
expect(scheme.available_from).to eq(Time.zone.local(2020, 4, 1))
it "returns the beginning of previous collection window" do
expect(scheme.available_from).to eq(previous_collection_start_date)
end
end
context "when the scheme was created at the end of the 2021/22 collection window" do
let(:scheme) { FactoryBot.build(:scheme, created_at: Time.zone.local(2022, 2, 6)) }
context "when the scheme was created after the crossover date" do
let(:scheme) { FactoryBot.build(:scheme, created_at: current_collection_after_crossover_start_date) }
it "returns the beginning of 21/22 collection window" do
expect(scheme.available_from).to eq(Time.zone.local(2020, 4, 1))
it "returns the beginning of current collection window" do
expect(scheme.available_from).to eq(current_collection_start_date)
end
end
end

34
spec/models/validations/date_validations_spec.rb

@ -18,7 +18,7 @@ RSpec.describe Validations::DateValidations do
end
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)
expect(record.errors["startdate"]).to be_empty
end
@ -40,8 +40,8 @@ RSpec.describe Validations::DateValidations do
describe "major repairs date" do
it "cannot be after the tenancy start date" do
record.startdate = Time.zone.local(2022, 1, 1)
record.mrcdate = Time.zone.local(2022, 2, 1)
record.startdate = current_collection_start_date + 1.month
record.mrcdate = current_collection_start_date + 2.months
date_validator.validate_property_major_repairs(record)
expect(record.errors["mrcdate"])
.to include(match I18n.t("validations.lettings.date.mrcdate.before_tenancy_start"))
@ -50,8 +50,8 @@ RSpec.describe Validations::DateValidations do
end
it "must be before the tenancy start date" do
record.startdate = Time.zone.local(2022, 2, 1)
record.mrcdate = Time.zone.local(2022, 1, 1)
record.startdate = current_collection_start_date + 2.months
record.mrcdate = current_collection_start_date + 1.month
date_validator.validate_property_major_repairs(record)
expect(record.errors["mrcdate"]).to be_empty
end
@ -77,7 +77,7 @@ RSpec.describe Validations::DateValidations 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
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)
expect(record.errors["mrcdate"])
.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
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)
expect(record.errors["mrcdate"])
.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
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)
expect(record.errors["mrcdate"])
.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
it "expects that major repairs can have been done" do
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)
expect(record.errors["mrcdate"]).to be_empty
end
@ -112,8 +112,8 @@ RSpec.describe Validations::DateValidations do
describe "property void date" do
it "cannot be after the tenancy start date" do
record.startdate = Time.zone.local(2022, 1, 1)
record.voiddate = Time.zone.local(2022, 2, 1)
record.startdate = current_collection_start_date + 1.month
record.voiddate = current_collection_start_date + 2.months
date_validator.validate_property_void_date(record)
expect(record.errors["voiddate"])
.to include(match I18n.t("validations.lettings.date.void_date.before_tenancy_start"))
@ -122,8 +122,8 @@ RSpec.describe Validations::DateValidations do
end
it "must be before the tenancy start date" do
record.startdate = Time.zone.local(2022, 2, 1)
record.voiddate = Time.zone.local(2022, 1, 1)
record.startdate = current_collection_start_date + 2.months
record.voiddate = current_collection_start_date + 1.month
date_validator.validate_property_void_date(record)
expect(record.errors["voiddate"]).to be_empty
end
@ -149,8 +149,8 @@ RSpec.describe Validations::DateValidations do
context "when major repairs have been carried out" do
it "void_date cannot be after major repairs date" do
record.mrcdate = Time.zone.local(2022, 1, 1)
record.voiddate = Time.zone.local(2022, 2, 1)
record.mrcdate = current_collection_start_date + 1.month
record.voiddate = current_collection_start_date + 2.months
date_validator.validate_property_void_date(record)
expect(record.errors["voiddate"])
.to include(match I18n.t("validations.lettings.date.void_date.after_mrcdate"))
@ -159,8 +159,8 @@ RSpec.describe Validations::DateValidations do
end
it "must be before major repairs date" do
record.mrcdate = Time.zone.local(2022, 2, 1)
record.voiddate = Time.zone.local(2022, 1, 1)
record.mrcdate = current_collection_start_date + 2.months
record.voiddate = current_collection_start_date + 1.month
date_validator.validate_property_void_date(record)
expect(record.errors["voiddate"]).to be_empty
end

34
spec/models/validations/financial_validations_spec.rb

@ -1,6 +1,8 @@
require "rails_helper"
RSpec.describe Validations::FinancialValidations do
include CollectionTimeHelper
subject(:financial_validator) { validator_class.new }
let(:validator_class) { Class.new { include Validations::FinancialValidations } }
@ -198,7 +200,7 @@ RSpec.describe Validations::FinancialValidations do
end
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
it "validates that housing benefit is not none" do
@ -228,7 +230,7 @@ RSpec.describe Validations::FinancialValidations do
describe "net income validations" 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.incfreq = 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
it "adds an error" do
record.startdate = Time.zone.local(2023, 5, 1)
record.startdate = current_collection_start_date
record.earnings = 5000
record.incfreq = 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
it "adds an error" do
record.startdate = Time.zone.local(2023, 5, 1)
record.startdate = current_collection_start_date
record.earnings = 50
record.incfreq = 1
record.hhmemb = 1
@ -273,7 +275,7 @@ RSpec.describe Validations::FinancialValidations do
context "when there is more than one household member" 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.incfreq = 1
record.hhmemb = 4
@ -286,7 +288,7 @@ RSpec.describe Validations::FinancialValidations do
end
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.incfreq = 1
record.hhmemb = 3
@ -299,7 +301,7 @@ RSpec.describe Validations::FinancialValidations do
end
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.incfreq = 1
record.hhmemb = 3
@ -323,7 +325,7 @@ RSpec.describe Validations::FinancialValidations do
end
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.incfreq = 1
record.hhmemb = 3
@ -991,7 +993,7 @@ RSpec.describe Validations::FinancialValidations do
soft_max: 89.54,
hard_min: 9.87,
hard_max: 100.99,
start_year: 2021,
start_year: current_collection_start_year,
)
LaRentRange.create!(
ranges_rent_id: "2",
@ -1002,7 +1004,7 @@ RSpec.describe Validations::FinancialValidations do
soft_max: 89.54,
hard_min: 9.87,
hard_max: 100.99,
start_year: 2021,
start_year: current_collection_start_year,
)
end
@ -1012,7 +1014,7 @@ RSpec.describe Validations::FinancialValidations do
record.period = 1
record.la = "E07000223"
record.beds = 4
record.startdate = Time.zone.local(2021, 9, 17)
record.startdate = current_collection_start_date
record.brent = 9.17
financial_validator.validate_rent_amount(record)
@ -1025,7 +1027,7 @@ RSpec.describe Validations::FinancialValidations do
record.lettype = 2
record.period = 1
record.location = location
record.startdate = Time.zone.local(2021, 9, 17)
record.startdate = current_collection_start_date
record.brent = 9.17
financial_validator.validate_rent_amount(record)
@ -1044,7 +1046,7 @@ RSpec.describe Validations::FinancialValidations do
record.period = 1
record.la = "E07000223"
record.beds = 4
record.startdate = Time.zone.local(2021, 9, 17)
record.startdate = current_collection_start_date
record.brent = 200
financial_validator.validate_rent_amount(record)
@ -1062,7 +1064,7 @@ RSpec.describe Validations::FinancialValidations do
record.lettype = 2
record.period = 1
record.location = location
record.startdate = Time.zone.local(2021, 9, 17)
record.startdate = current_collection_start_date
record.brent = 200
financial_validator.validate_rent_amount(record)
@ -1079,7 +1081,7 @@ RSpec.describe Validations::FinancialValidations do
record.lettype = 1
record.period = 1
record.la = "E07000223"
record.startdate = Time.zone.local(2022, 2, 5)
record.startdate = current_collection_start_date
record.beds = 4
record.brent = 200
@ -1095,7 +1097,7 @@ RSpec.describe Validations::FinancialValidations do
it "does not error if some of the fields are missing" do
record.managing_organisation.provider_type = 2
record.startdate = Time.zone.local(2021, 9, 17)
record.startdate = current_collection_start_date
record.brent = 200
financial_validator.validate_rent_amount(record)

8
spec/models/validations/household_validations_spec.rb

@ -53,7 +53,7 @@ RSpec.describe Validations::HouseholdValidations do
end
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
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
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
record.age2 = 14
@ -293,7 +293,7 @@ RSpec.describe Validations::HouseholdValidations do
describe "#validate_person_age_matches_economic_status" 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
record.age2 = 14
@ -309,7 +309,7 @@ RSpec.describe Validations::HouseholdValidations do
describe "#validate_person_age_and_relationship_matches_economic_status" 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
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
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
context "when within permitted bounds" do
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"
RSpec.describe Validations::Sales::SetupValidations do
include CollectionTimeHelper
subject(:setup_validator) { validator_class.new }
let(:validator_class) { Class.new { include Validations::Sales::SetupValidations } }
let(:current_year) { FormHandler.instance.current_sales_form.start_date.year }
let(:previous_year) { FormHandler.instance.previous_sales_form.start_date.year }
let(:current_year) { current_collection_start_year }
let(:previous_year) { previous_collection_start_year }
describe "#validate_saledate_collection_year" do
context "with sales_in_crossover_period == false" do
@ -84,7 +86,7 @@ RSpec.describe Validations::Sales::SetupValidations do
end
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
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) }
describe "tenancy start date" do
context "when in 2022 to 2023 collection" do
context "when in the crossover period" do
before do
allow(Time).to receive(:now).and_return(Time.zone.local(2022, 4, 1))
record.created_at = Time.zone.local(2022, 4, 1)
end
it "cannot be before the first collection window start date" do
record.startdate = Time.zone.local(2021, 1, 1)
setup_validator.validate_startdate_setup(record)
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
context "when in the crossover period" do
before do
Timecop.freeze(current_collection_start_date)
end
context "when after the crossover period" do
before do
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 1, 1))
record.created_at = Time.zone.local(2023, 1, 1)
end
it "cannot be before the first collection window start date" do
record.startdate = Time.zone.local(2022, 1, 1)
setup_validator.validate_startdate_setup(record)
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
after do
Timecop.return
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
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 2022 to 2023 or 2023 to 2024 collection years, which is between 1st April 2022 and 31st March 2024")
end
it "cannot be before previous collection year start date" do
record.startdate = previous_collection_start_date - 1.month
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 \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
context "when after the crossover period" do
before do
allow(Time).to receive(:now).and_return(Time.zone.local(2024, 1, 1))
record.created_at = Time.zone.local(2024, 1, 1)
allow(Time).to receive(:now).and_return(current_collection_after_crossover_start_date)
end
it "cannot be before the first collection window start date" do
record.startdate = Time.zone.local(2023, 1, 1)
it "cannot be before previous collection year start date" do
record.startdate = previous_collection_start_date - 1.month
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
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")
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
@ -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
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
it "cannot create new logs for the previous collection year" do
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_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 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.startdate = Time.zone.local(2023, 1, 1)
record.startdate = previous_collection_start_date
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")
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
context "when attempted startdate is more than 14 days from the current date" 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
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)
expect(record.errors["startdate"]).to include(match I18n.t("validations.lettings.setup.startdate.not_within.next_two_weeks"))
end
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
record.startdate = Time.zone.local(2024, 4, 1)
record.startdate = next_collection_start_date
setup_validator.validate_startdate_setup(record)
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"))
end
end
end
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(: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_available_from) { current_collection_start_date - 2.months }
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_2) { create(:organisation, name: "Merged org 2") }
before do
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 5, 1))
merged_organisation.update!(absorbing_organisation:, merge_date: Time.zone.local(2023, 2, 2))
merged_organisation_2.update!(absorbing_organisation:, merge_date: Time.zone.local(2023, 2, 2))
Timecop.freeze(current_collection_start_date + 1.month)
merged_organisation.update!(absorbing_organisation:, merge_date: org_merge_date)
merged_organisation_2.update!(absorbing_organisation:, merge_date: org_merge_date)
end
after do
Timecop.return
end
context "and owning organisation is no longer active" 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
setup_validator.validate_startdate_setup(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
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
setup_validator.validate_startdate_setup(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
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
setup_validator.validate_startdate_setup(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
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
setup_validator.validate_startdate_setup(record)
setup_validator.validate_merged_organisations_start_date(record)
@ -217,7 +176,7 @@ RSpec.describe Validations::SetupValidations do
end
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)
record.owning_organisation_id = absorbing_organisation.id
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
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
setup_validator.validate_startdate_setup(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
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
setup_validator.validate_startdate_setup(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
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
setup_validator.validate_startdate_setup(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
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
setup_validator.validate_startdate_setup(record)
setup_validator.validate_merged_organisations_start_date(record)
@ -262,7 +221,7 @@ RSpec.describe Validations::SetupValidations do
end
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)
record.managing_organisation_id = absorbing_organisation.id
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
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.owning_organisation_id = merged_organisation.id
setup_validator.validate_startdate_setup(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
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.owning_organisation_id = merged_organisation.id
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
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.owning_organisation_id = absorbing_organisation.id
setup_validator.validate_startdate_setup(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
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.owning_organisation_id = absorbing_organisation.id
setup_validator.validate_startdate_setup(record)
@ -311,7 +270,7 @@ RSpec.describe Validations::SetupValidations do
end
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)
record.managing_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
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.owning_organisation_id = merged_organisation_2.id
setup_validator.validate_startdate_setup(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
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.owning_organisation_id = merged_organisation_2.id
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
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
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.owning_organisation_id = merged_organisation_2.id
setup_validator.validate_startdate_setup(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
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.owning_organisation_id = merged_organisation_2.id
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
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
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.owning_organisation_id = absorbing_organisation_2.id
setup_validator.validate_startdate_setup(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
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.owning_organisation_id = absorbing_organisation.id
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
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.owning_organisation_id = absorbing_organisation.id
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,
hard_min: 9.87,
hard_max: 100.99,
start_year: 2021,
start_year: current_collection_start_year,
)
record.la = "E07000223"
@ -26,7 +26,7 @@ RSpec.describe Validations::SoftValidations do
record.rent_type = 0
record.beds = 1
record.period = 1
record.startdate = Time.zone.local(2021, 10, 10)
record.startdate = current_collection_start_date
end
context "when validating soft min" do
@ -504,16 +504,16 @@ RSpec.describe Validations::SoftValidations do
describe "major repairs date soft validations" do
context "when the major repairs date is within 10 years of the tenancy start date" do
it "shows the interruption screen" do
record.startdate = Time.zone.local(2022, 2, 1)
record.mrcdate = Time.zone.local(2013, 2, 1)
record.startdate = current_collection_start_date
record.mrcdate = current_collection_start_date - 9.years
expect(record.major_repairs_date_in_soft_range?).to be true
end
end
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
record.startdate = Time.zone.local(2022, 2, 1)
record.mrcdate = Time.zone.local(2021, 2, 1)
record.startdate = current_collection_start_date
record.mrcdate = current_collection_start_date - 1.year
expect(record.major_repairs_date_in_soft_range?).to be false
end
end
@ -540,16 +540,16 @@ RSpec.describe Validations::SoftValidations do
describe "void date soft validations" do
context "when the void date is within 10 years of the tenancy start date" do
it "shows the interruption screen" do
record.startdate = Time.zone.local(2022, 2, 1)
record.voiddate = Time.zone.local(2013, 2, 1)
record.startdate = current_collection_start_date
record.voiddate = current_collection_start_date - 9.years
expect(record.voiddate_in_soft_range?).to be true
end
end
context "when the void date is less than 2 years before the tenancy start date" do
it "does not show the interruption screen" do
record.startdate = Time.zone.local(2022, 2, 1)
record.voiddate = Time.zone.local(2021, 2, 1)
record.startdate = current_collection_start_date
record.voiddate = current_collection_start_date - 1.year
expect(record.voiddate_in_soft_range?).to be false
end
end

227
spec/requests/sales_logs_controller_spec.rb

@ -1,6 +1,8 @@
require "rails_helper"
RSpec.describe SalesLogsController, type: :request do
include CollectionTimeHelper
let(:user) { FactoryBot.create(:user) }
let(:owning_organisation) { user.organisation }
let(:api_username) { "test_user" }
@ -26,18 +28,11 @@ RSpec.describe SalesLogsController, type: :request do
end
before do
Timecop.freeze(Time.zone.local(2024, 3, 1))
Singleton.__init__(FormHandler)
allow(ENV).to receive(:[])
allow(ENV).to receive(:[]).with("API_USER").and_return(api_username)
allow(ENV).to receive(:[]).with("API_KEY").and_return(api_password)
end
after do
Timecop.return
Singleton.__init__(FormHandler)
end
describe "POST #create" do
context "when API" do
before do
@ -70,19 +65,30 @@ RSpec.describe SalesLogsController, type: :request do
end
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
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,
"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,
sales_log: invalid_sales_log.attributes,
}
end
@ -93,7 +99,26 @@ RSpec.describe SalesLogsController, type: :request do
it "validates sales log parameters" do
json_response = JSON.parse(response.body)
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
@ -341,72 +366,70 @@ RSpec.describe SalesLogsController, type: :request do
end
context "with year filter" do
before do
Timecop.freeze(2022, 4, 1)
sales_log_2022.update!(saledate: Time.zone.local(2022, 4, 1))
Timecop.freeze(2023, 1, 1)
sales_log_2022.update!(saledate: Time.zone.local(2023, 1, 1))
end
after do
Timecop.unfreeze
# Needs logs in both the previous and the current collection year, so must run inside
# the crossover period, when new logs can still be created for both.
around do |example|
Timecop.freeze(current_collection_start_date) do
Singleton.__init__(FormHandler)
example.run
end
Singleton.__init__(FormHandler)
end
let!(:sales_log_2022) do
let!(:sales_log_current) do
FactoryBot.create(:sales_log, :completed,
owning_organisation: organisation,
assigned_to: user,
saledate: Time.zone.today)
saledate: current_collection_start_date)
end
let!(:sales_log_2023) do
let!(:sales_log_previous) do
FactoryBot.create(:sales_log,
owning_organisation: organisation,
assigned_to: user,
saledate: Time.zone.today)
saledate: previous_collection_start_date)
end
it "shows sales logs for multiple selected years" do
get "/sales-logs?years[]=2021&years[]=2022", headers: headers, params: {}
expect(page).to have_link(sales_log_2022.id.to_s)
expect(page).to have_link(sales_log_2023.id.to_s)
get "/sales-logs?years[]=#{previous_collection_start_year}&years[]=#{current_collection_start_year}", headers: headers, params: {}
expect(page).to have_link(sales_log_current.id.to_s)
expect(page).to have_link(sales_log_previous.id.to_s)
end
it "shows sales logs for one selected year" do
get "/sales-logs?years[]=2022", headers: headers, params: {}
expect(page).to have_link(sales_log_2022.id.to_s)
expect(page).to have_link(sales_log_2023.id.to_s)
get "/sales-logs?years[]=#{current_collection_start_year}", headers: headers, params: {}
expect(page).to have_link(sales_log_current.id.to_s)
expect(page).not_to have_link(sales_log_previous.id.to_s)
end
end
context "with year and status filter" do
before do
Timecop.freeze(2022, 4, 1)
sales_log_2022.update!(saledate: Time.zone.local(2022, 4, 1))
Timecop.freeze(2023, 1, 1)
sales_log_2022.update!(saledate: Time.zone.local(2023, 1, 1))
end
after do
Timecop.unfreeze
# Needs logs in both the previous and the current collection year, so must run inside
# the crossover period, when new logs can still be created for both.
around do |example|
Timecop.freeze(current_collection_start_date) do
Singleton.__init__(FormHandler)
example.run
end
Singleton.__init__(FormHandler)
end
let!(:sales_log_2022) do
let!(:sales_log_current) do
FactoryBot.create(:sales_log, :completed,
owning_organisation: organisation,
assigned_to: user,
saledate: Time.zone.today)
saledate: current_collection_start_date)
end
let!(:sales_log_2023) do
let!(:sales_log_previous) do
FactoryBot.create(:sales_log,
owning_organisation: organisation,
assigned_to: user,
saledate: Time.zone.today)
saledate: previous_collection_start_date)
end
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: {}
expect(page).to have_link(sales_log_2022.id.to_s)
expect(page).to have_link(sales_log_2023.id.to_s)
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_current.id.to_s)
expect(page).to have_link(sales_log_previous.id.to_s)
end
end
@ -856,10 +879,6 @@ RSpec.describe SalesLogsController, type: :request do
before do
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
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: {}
end
after do
Timecop.return
Singleton.__init__(FormHandler)
end
it "shows the tasklist for sales logs you have access to" do
expect(response.body).to match("Log")
expect(response.body).to match(completed_sales_log.id.to_s)
end
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
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(page).to have_link("review and make changes to this log", href: "/sales-logs/#{completed_sales_log.id}/review?sales_log=true")
end
@ -894,53 +908,44 @@ RSpec.describe SalesLogsController, type: :request do
get "/sales-logs/#{completed_sales_log.id}", headers:, params: {}
end
after do
Timecop.return
Singleton.__init__(FormHandler)
end
it "shows the tasklist for sales logs you have access to" do
expect(response.body).to match("Log")
expect(response.body).to match(completed_sales_log.id.to_s)
end
end
context "with sales logs from a closed collection period before the previous collection" do
before do
sign_in user
Timecop.return
Singleton.__init__(FormHandler)
get "/sales-logs/#{completed_sales_log.id}", headers:, params: {}
end
it "redirects to review page" do
expect(response).to redirect_to("/sales-logs/#{completed_sales_log.id}/review?sales_log=true")
context "with sales logs from a closed previous collection period" do
let(:completed_sales_log) do
FactoryBot.create(
:sales_log,
:completed,
:ignore_validation_errors,
owning_organisation: user.organisation,
assigned_to: user,
saledate: archived_collection_start_date,
)
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
sign_in user
Timecop.freeze(2023, 2, 1)
Singleton.__init__(FormHandler)
# allow(closed_previous_sales_form).to receive_messages(
# new_logs_end_date: closed_previous_collection_end,
# edit_end_date: closed_previous_collection_end,
# )
get "/sales-logs/#{completed_sales_log.id}", headers:, params: {}
end
after do
Timecop.return
Singleton.__init__(FormHandler)
end
it "redirects to review page" do
expect(response).to redirect_to("/sales-logs/#{completed_sales_log.id}/review?sales_log=true")
end
it "displays a closed collection window message for previous collection year logs" do
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")
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
@ -959,6 +964,7 @@ RSpec.describe SalesLogsController, type: :request do
let(:headers) { { "Accept" => "text/html" } }
let(:search_term) { "foot" }
let(:codes_only) { false }
let(:selected_year) { current_collection_start_year }
before do
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
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
it "returns http success" do
@ -1023,7 +1029,7 @@ RSpec.describe SalesLogsController, type: :request do
context "when user is not support" 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
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) }
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
context "and export type is not codes only" do
@ -1100,6 +1106,7 @@ RSpec.describe SalesLogsController, type: :request do
end
describe "POST #email-csv" do
let(:selected_year) { current_collection_start_year }
let(:other_organisation) { FactoryBot.create(:organisation) }
let(:user) { FactoryBot.create(:user, :support) }
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
expect {
post "/sales-logs/email-csv?years[]=2023&codes_only=true", headers:, params: {}
}.to enqueue_job(EmailCsvJob).with(user, nil, { "years" => %w[2023] }, false, nil, true, "sales", 2023)
post "/sales-logs/email-csv?years[]=#{selected_year}&codes_only=true", headers:, params: {}
}.to enqueue_job(EmailCsvJob).with(user, nil, { "years" => [selected_year.to_s] }, false, nil, true, "sales", selected_year)
end
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)
end
it "passes the search term" do
expect {
post "/sales-logs/email-csv?search=#{sales_log.id}&years[]=2023&codes_only=false", headers:, params: {}
}.to enqueue_job(EmailCsvJob).with(user, sales_log.id.to_s, { "years" => %w[2023] }, false, nil, false, "sales", 2023)
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" => [selected_year.to_s] }, false, nil, false, "sales", selected_year)
end
it "passes filter parameters" do
expect {
post "/sales-logs/email-csv?years[]=2023&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)
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" => [selected_year.to_s] }, false, nil, true, "sales", selected_year)
end
it "passes export type flag" do
expect {
post "/sales-logs/email-csv?years[]=2023&codes_only=true", headers:, params: {}
}.to enqueue_job(EmailCsvJob).with(user, nil, { "years" => %w[2023] }, false, nil, true, "sales", 2023)
post "/sales-logs/email-csv?years[]=#{selected_year}&codes_only=true", headers:, params: {}
}.to enqueue_job(EmailCsvJob).with(user, nil, { "years" => [selected_year.to_s] }, false, nil, true, "sales", selected_year)
expect {
post "/sales-logs/email-csv?years[]=2023&codes_only=false", headers:, params: {}
}.to enqueue_job(EmailCsvJob).with(user, nil, { "years" => %w[2023] }, false, nil, false, "sales", 2023)
post "/sales-logs/email-csv?years[]=#{selected_year}&codes_only=false", headers:, params: {}
}.to enqueue_job(EmailCsvJob).with(user, nil, { "years" => [selected_year.to_s] }, false, nil, false, "sales", selected_year)
end
it "passes a combination of search term, export type and filter parameters" do
postcode = "XX1 1TG"
expect {
post "/sales-logs/email-csv?years[]=2023&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)
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" => [selected_year.to_s] }, false, nil, false, "sales", selected_year)
end
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
codes_only_export = false
expect {
post "/sales-logs/email-csv?years[]=2023&codes_only=#{codes_only_export}", headers:, params: {}
}.to enqueue_job(EmailCsvJob).with(user, nil, { "years" => %w[2023] }, false, nil, false, "sales", 2023)
post "/sales-logs/email-csv?years[]=#{selected_year}&codes_only=#{codes_only_export}", headers:, params: {}
}.to enqueue_job(EmailCsvJob).with(user, nil, { "years" => [selected_year.to_s] }, false, nil, false, "sales", selected_year)
end
it "is not authorized to download codes only csv" do
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)
end
end

Loading…
Cancel
Save