Browse Source

CLDC-3289 Avoid freezing time in tests (part 1) (#2421)

* Refactor tests #1

* Refactor helper tests

* Refactor model form tests

* Remove Timecop.returns

* Update tasklist helper tests

* Update task list helper

* Fix test

* Fix flaky search test

* Refactor
pull/2481/head
kosiakkatrina 7 months ago committed by GitHub
parent
commit
07750ef26c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      app/models/form/sales/pages/buyer_previous.rb
  2. 2
      app/models/form/sales/pages/la_nominations.rb
  3. 2
      app/models/form/sales/pages/last_accommodation.rb
  4. 2
      app/models/form/sales/pages/last_accommodation_la.rb
  5. 129
      spec/components/check_answers_summary_list_card_component_spec.rb
  6. 4
      spec/factories/lettings_log.rb
  7. 5
      spec/factories/sales_log.rb
  8. 39
      spec/features/bulk_upload_lettings_logs_spec.rb
  9. 23
      spec/features/form/accessible_autocomplete_spec.rb
  10. 27
      spec/helpers/check_answers_helper_spec.rb
  11. 7
      spec/helpers/collection_time_helper_spec.rb
  12. 10
      spec/helpers/duplicate_logs_helper_spec.rb
  13. 14
      spec/helpers/filters_helper_spec.rb
  14. 11
      spec/helpers/form_page_error_helper_spec.rb
  15. 16
      spec/helpers/interruption_screen_helper_spec.rb
  16. 88
      spec/helpers/locations_helper_spec.rb
  17. 6
      spec/helpers/schemes_helper_spec.rb
  18. 130
      spec/helpers/tasklist_helper_spec.rb
  19. 2
      spec/models/form/lettings/questions/address_line1_for_address_matcher_spec.rb
  20. 6
      spec/models/form/lettings/questions/location_id_spec.rb
  21. 2
      spec/models/form/lettings/questions/postcode_for_address_matcher_spec.rb
  22. 26
      spec/models/form/lettings/questions/stock_owner_spec.rb
  23. 2
      spec/models/form/lettings/questions/uprn_selection_spec.rb
  24. 87
      spec/models/form/page_spec.rb
  25. 191
      spec/models/form/question_spec.rb
  26. 32
      spec/models/form/sales/pages/buyer_previous_spec.rb
  27. 24
      spec/models/form/sales/pages/la_nominations_spec.rb
  28. 22
      spec/models/form/sales/pages/last_accommodation_la_spec.rb
  29. 20
      spec/models/form/sales/pages/last_accommodation_spec.rb
  30. 40
      spec/models/form/sales/questions/owning_organisation_id_spec.rb
  31. 50
      spec/models/form/subsection_spec.rb
  32. 2
      spec/models/sales_log_spec.rb

2
app/models/form/sales/pages/buyer_previous.rb

@ -12,7 +12,7 @@ class Form::Sales::Pages::BuyerPrevious < ::Form::Page
end
def routed_to?(log, _current_user)
return false if log.is_staircase? && log.form.start_year_after_2024?
return false if log.is_staircase? && form.start_year_after_2024?
super
end

2
app/models/form/sales/pages/la_nominations.rb

@ -11,7 +11,7 @@ class Form::Sales::Pages::LaNominations < ::Form::Page
end
def routed_to?(log, _current_user)
return false if log.staircase == 1 && log.form.start_year_after_2024?
return false if log.staircase == 1 && form.start_year_after_2024?
super
end

2
app/models/form/sales/pages/last_accommodation.rb

@ -12,7 +12,7 @@ class Form::Sales::Pages::LastAccommodation < ::Form::Page
end
def routed_to?(log, _user)
return false if log.form.start_year_after_2024? && log.discounted_ownership_sale?
return false if form.start_year_after_2024? && log.discounted_ownership_sale?
super
end

2
app/models/form/sales/pages/last_accommodation_la.rb

@ -15,7 +15,7 @@ class Form::Sales::Pages::LastAccommodationLa < ::Form::Page
end
def routed_to?(log, _user)
return false if log.form.start_year_after_2024? && log.discounted_ownership_sale?
return false if form.start_year_after_2024? && log.discounted_ownership_sale?
super
end

129
spec/components/check_answers_summary_list_card_component_spec.rb

@ -5,103 +5,68 @@ RSpec.describe CheckAnswersSummaryListCardComponent, type: :component do
let(:rendered) { render_inline(component) }
context "when before 23/24 collection" do
before do
Timecop.freeze(Time.zone.local(2023, 1, 10))
Singleton.__init__(FormHandler)
end
after do
Timecop.return
end
context "when given a set of questions" do
let(:user) { build(:user) }
let(:log) { build(:lettings_log, :completed, age2: 99, startdate: Time.zone.local(2021, 5, 1)) }
let(:subsection_id) { "household_characteristics" }
let(:subsection) { log.form.get_subsection(subsection_id) }
let(:questions) { subsection.applicable_questions(log) }
it "renders a summary list card without question numbers for the answers to those questions" do
expect(rendered).to have_content(questions.first.answer_label(log))
expect(rendered).to have_content("Lead tenant’s age")
expect(rendered).not_to have_content("Q32 - Lead tenant’s age")
end
it "applicable questions doesn't return questions that are hidden in check answers" do
expect(component.applicable_questions.map(&:id).include?("retirement_value_check")).to eq(false)
end
it "has the correct answer label for a question" do
sex1_question = questions[2]
expect(component.get_answer_label(sex1_question)).to eq("Female")
end
context "when log was created via a bulk upload and has an unanswered question" do
subject(:component) { described_class.new(questions:, log:, user:) }
let(:bulk_upload) { create(:bulk_upload) }
let(:log) { build(:lettings_log, :in_progress, creation_method: "bulk upload", age2: 99, startdate: Time.zone.local(2021, 5, 1), bulk_upload:) }
it "displays tweaked copy in red" do
expect(rendered).to have_selector("span", class: "app-!-colour-red", text: "You still need to answer this question")
end
end
let(:user) { create(:user) }
let(:log) { create(:lettings_log, :completed, age2: 99, retirement_value_check: 1) }
let(:subsection_id) { "household_characteristics" }
let(:subsection) { log.form.get_subsection(subsection_id) }
let(:questions) { subsection.applicable_questions(log) }
it "renders a summary list card including question numbers for the answers to those questions" do
expect(rendered).to have_content(questions.first.answer_label(log))
expect(rendered).to match(/Q\d+ - Lead tenant’s age/)
end
context "when log was imported with a bulk upload creation method, without bulk upload id and has an unanswered question" do
subject(:component) { described_class.new(questions:, log:, user:) }
it "applicable questions doesn't return questions that are hidden in check answers" do
expect(component.applicable_questions.map(&:id).include?("retirement_value_check")).to eq(false)
end
let(:log) { build(:lettings_log, :in_progress, creation_method: "bulk upload", age2: 99, startdate: Time.zone.local(2021, 5, 1), bulk_upload_id: nil) }
it "has the correct answer label for a question" do
sex1_question = questions.find { |q| q.id == "sex1" }
expect(component.get_answer_label(sex1_question)).to eq("Female")
end
it "displays tweaked copy in red" do
expect(rendered).not_to have_selector("span", class: "app-!-colour-red", text: "You still need to answer this question")
end
end
context "when log was created via a bulk upload and has an unanswered question" do
let(:bulk_upload) { create(:bulk_upload) }
let(:log) { create(:lettings_log, :in_progress, creation_method: "bulk upload", age2: 99, bulk_upload:) }
context "when log was not created via a bulk upload and has an unanswered question" do
subject(:component) { described_class.new(questions:, log:, user:) }
it "displays tweaked copy in red" do
expect(rendered).to have_selector("span", class: "app-!-colour-red", text: "You still need to answer this question")
end
end
let(:log) { build(:lettings_log, :in_progress, age2: 99, startdate: Time.zone.local(2021, 5, 1)) }
context "when log was imported with a bulk upload creation method, without bulk upload id and has an unanswered question" do
let(:log) { create(:lettings_log, :in_progress, creation_method: "bulk upload", age2: 99, bulk_upload_id: nil) }
it "displays normal copy with muted colour " do
expect(rendered).to have_selector("span", class: "app-!-colour-muted", text: "You didn’t answer this question")
end
end
it "displays tweaked copy in red" do
expect(rendered).not_to have_selector("span", class: "app-!-colour-red", text: "You still need to answer this question")
end
end
context "when log was created via a bulk upload and has an unanswered optional question" do
subject(:component) { described_class.new(questions:, log:, user:) }
context "when log was not created via a bulk upload and has an unanswered question" do
it "displays normal copy with muted colour " do
expect(rendered).to have_selector("span", class: "app-!-colour-muted", text: "You didn’t answer this question")
end
end
let(:subsection_id) { "setup" }
let(:bulk_upload) { create(:bulk_upload) }
let(:log) { build(:lettings_log, :completed, creation_method: "bulk upload", tenancycode: nil, startdate: Time.zone.local(2021, 5, 1), bulk_upload:) }
context "when log was created via a bulk upload and has an unanswered optional question" do
let(:subsection_id) { "setup" }
let(:bulk_upload) { create(:bulk_upload) }
let(:log) { create(:lettings_log, :completed, creation_method: "bulk upload", tenancycode: nil, bulk_upload:) }
it "displays tweaked copy in red" do
expect(rendered).to have_selector("span", class: "app-!-colour-muted", text: "You didn’t answer this question")
expect(rendered).not_to have_selector("span", class: "app-!-colour-red", text: "You still need to answer this question")
end
end
it "displays tweaked copy in red" do
expect(rendered).to have_selector("span", class: "app-!-colour-muted", text: "You didn’t answer this question")
expect(rendered).not_to have_selector("span", class: "app-!-colour-red", text: "You still need to answer this question")
end
end
context "when in 23/24 collection" do
context "when before 23/24 collection" do
context "when given a set of questions" do
let(:user) { create(:user) }
let(:log) { create(:lettings_log, :completed, age2: 99, startdate: Time.zone.local(2023, 5, 1)) }
let(:subsection_id) { "household_characteristics" }
let(:subsection) { log.form.get_subsection(subsection_id) }
let(:questions) { subsection.applicable_questions(log) }
let(:log) { build(:lettings_log, :completed, age2: 99, startdate: Time.zone.local(2021, 5, 1), assigned_to: create(:user)) }
around do |example|
Timecop.freeze(Time.zone.local(2023, 5, 1))
Singleton.__init__(FormHandler)
example.run
Timecop.return
Singleton.__init__(FormHandler)
end
it "renders a summary list card including question numbers for the answers to those questions" do
it "renders a summary list card without question numbers for the answers to those questions" do
expect(rendered).to have_content(questions.first.answer_label(log))
expect(rendered).to have_content("Q32 - Lead tenant’s age")
expect(rendered).to have_content("Lead tenant’s age")
expect(rendered).not_to include(" - Lead tenant’s age")
end
end
end

4
spec/factories/lettings_log.rb

@ -14,6 +14,7 @@ FactoryBot.define do
declaration { 1 }
end
trait :in_progress do
setup_completed
status { 1 }
tenancycode { Faker::Name.initials(number: 10) }
postcode_full { Faker::Address.postcode }
@ -21,9 +22,6 @@ FactoryBot.define do
hhmemb { 2 }
age1 { 17 }
age2 { 19 }
renewal { 1 }
rent_type { 1 }
startdate { Time.zone.today }
end
trait :conditional_section_complete do
tenancycode { Faker::Name.initials(number: 10) }

5
spec/factories/sales_log.rb

@ -43,17 +43,14 @@ FactoryBot.define do
purchid { rand(999_999_999).to_s }
end
trait :duplicate do
shared_ownership_setup_complete
purchid { "PC123" }
ownershipsch { 2 }
type { 8 }
jointpur { 2 }
saledate { Time.zone.today }
age1_known { 1 }
age1 { 20 }
sex1 { "F" }
ecstat1 { 1 }
postcode_full { "A1 1AA" }
privacynotice { 1 }
uprn_known { 0 }
end
trait :completed do

39
spec/features/bulk_upload_lettings_logs_spec.rb

@ -1,7 +1,12 @@
require "rails_helper"
RSpec.describe "Bulk upload lettings log" do
include CollectionTimeHelper
let(:user) { create(:user) }
let(:current_year) { current_collection_start_year }
let(:current_formatted_year) { "#{current_year}/#{current_year + 1}" }
let(:current_formatted_short_year) { "#{current_year}/#{current_year - 2000 + 1}" }
let(:stub_file_upload) do
vcap_services = { "aws-s3-bucket" => {} }
@ -22,11 +27,7 @@ RSpec.describe "Bulk upload lettings log" do
# rubocop:disable RSpec/AnyInstance
context "when during crossover period" do
before do
Timecop.freeze(2023, 6, 1)
end
after do
Timecop.return
allow(FormHandler.instance).to receive(:lettings_in_crossover_period?).and_return(true)
end
it "shows journey with year option" do
@ -38,20 +39,20 @@ RSpec.describe "Bulk upload lettings log" do
click_button("Continue")
expect(page).to have_content("You must select a collection period to upload for")
choose("2023/2024")
choose(current_formatted_year)
click_button("Continue")
click_link("Back")
expect(page.find_field("form-year-2023-field")).to be_checked
expect(page.find_field("form-year-#{current_year}-field")).to be_checked
click_button("Continue")
expect(page).to have_content("Upload lettings logs in bulk (2023/24)")
expect(page).to have_content("Upload lettings logs in bulk (#{current_formatted_short_year})")
click_button("Continue")
expect(page).not_to have_content("What is the needs type?")
expect(page).to have_content("Upload lettings logs in bulk (2023/24)")
expect(page).to have_content("Upload lettings logs in bulk (#{current_formatted_short_year})")
expect(page).to have_content("Upload your file")
click_button("Upload")
@ -79,11 +80,7 @@ RSpec.describe "Bulk upload lettings log" do
context "when not it crossover period" do
before do
Timecop.freeze(2024, 1, 1)
end
after do
Timecop.return
allow(FormHandler.instance).to receive(:lettings_in_crossover_period?).and_return(false)
end
it "shows journey with year option" do
@ -91,21 +88,11 @@ RSpec.describe "Bulk upload lettings log" do
expect(page).to have_link("Upload lettings logs in bulk")
click_link("Upload lettings logs in bulk")
expect(page).to have_content("Upload lettings logs in bulk (2023/24)")
expect(page).to have_content("Upload lettings logs in bulk (#{current_formatted_short_year})")
click_button("Continue")
expect(page).to have_content("Upload your file")
end
end
context "when the collection year isn't 22/23" do
before do
Timecop.freeze(2024, 1, 1)
end
after do
Timecop.return
end
it "shows journey without the needstype" do
visit("/lettings-logs")
@ -120,7 +107,7 @@ RSpec.describe "Bulk upload lettings log" do
expect(page).to have_content("Prepare your file")
click_button("Continue")
expect(page).to have_content("Upload lettings logs in bulk (2023/24)")
expect(page).to have_content("Upload lettings logs in bulk (#{current_formatted_short_year})")
expect(page).to have_content("Upload your file")
click_button("Upload")

23
spec/features/form/accessible_autocomplete_spec.rb

@ -2,28 +2,15 @@ require "rails_helper"
require_relative "helpers"
RSpec.describe "Accessible Autocomplete" do
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
include Helpers
let(:user) { FactoryBot.create(:user) }
let(:lettings_log) do
FactoryBot.create(
:lettings_log,
:in_progress,
renewal: 0,
previous_la_known: 1,
prevloc: "E09000033",
illness: 1,
is_la_inferred: false,
owning_organisation: user.organisation,
managing_organisation: user.organisation,
assigned_to: user,
)
end
@ -35,7 +22,7 @@ RSpec.describe "Accessible Autocomplete" do
context "when using accessible autocomplete" do
before do
visit("/lettings-logs/#{lettings_log.id}/accessible-select")
visit("/lettings-logs/#{lettings_log.id}/previous-local-authority")
end
it "allows type ahead filtering", js: true do
@ -50,12 +37,12 @@ RSpec.describe "Accessible Autocomplete" do
it "ignores stop words", js: true do
find("#lettings-log-prevloc-field").click.native.send_keys("t", "h", "e", " ", "W", "e", "s", "t", "m", :down, :enter)
expect(find("#lettings-log-prevloc-field").value).to eq("Westminster")
expect(find("#lettings-log-prevloc-field").value).to eq("Westmorland and Furness")
end
it "does not perform an exact match", js: true do
find("#lettings-log-prevloc-field").click.native.send_keys("o", "n", "l", "y", " ", "t", "o", "w", "n", :down, :enter)
expect(find("#lettings-log-prevloc-field").value).to eq("The one and only york town")
find("#lettings-log-prevloc-field").click.native.send_keys("K", "i", "n", "g", "s", "t", "o", "n", " ", "T", "h", "a", "m", "e", "s", :down, :enter)
expect(find("#lettings-log-prevloc-field").value).to eq("Kingston upon Thames")
end
it "maintains enhancement state across back navigation", js: true do
@ -100,7 +87,7 @@ RSpec.describe "Accessible Autocomplete" do
it "has the correct option selected if one has been saved" do
lettings_log.update!(postcode_known: 0, previous_la_known: 1, prevloc: "E07000178")
visit("/lettings-logs/#{lettings_log.id}/accessible-select")
visit("/lettings-logs/#{lettings_log.id}/previous-local-authority")
expect(page).to have_select("lettings-log-prevloc-field", selected: %w[Oxford])
end
end

27
spec/helpers/check_answers_helper_spec.rb

@ -1,23 +1,27 @@
require "rails_helper"
RSpec.describe CheckAnswersHelper do
let(:form) { lettings_log.form }
let(:subsection) { form.get_subsection("household_characteristics") }
let(:lettings_log) { FactoryBot.build(:lettings_log, :in_progress) }
let(:lettings_log) { FactoryBot.build(:lettings_log) }
let(:current_user) { FactoryBot.build(:user) }
let(:subsection) { instance_double(Form::Subsection, form: lettings_log.form) }
let(:questions) do
[
Form::Lettings::Questions::Hhmemb,
Form::Lettings::Questions::Age1Known,
Form::Lettings::Questions::Age1,
Form::Lettings::Questions::GenderIdentity1,
].map { |q| q.new(nil, nil, instance_double(Form::Page, subsection:, routed_to?: true)) }
end
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
before do
allow(subsection).to receive(:applicable_questions).and_return(questions)
end
describe "display_answered_questions_summary" do
context "when a section hasn't been completed yet" do
it "returns that you have unanswered questions" do
expect(display_answered_questions_summary(subsection, lettings_log, current_user))
.to match(/You have answered 4 of 10 questions./)
.to match(/You have answered 0 of 4 questions./)
end
end
@ -25,9 +29,8 @@ RSpec.describe CheckAnswersHelper do
it "returns that you have answered all the questions" do
lettings_log.sex1 = "F"
lettings_log.hhmemb = 1
lettings_log.propcode = "123"
lettings_log.ecstat1 = 200
lettings_log.ecstat2 = 9
lettings_log.age1_known = 1
lettings_log.age1 = 18
expect(display_answered_questions_summary(subsection, lettings_log, current_user))
.to match(/You answered all the questions./)
expect(display_answered_questions_summary(subsection, lettings_log, current_user))

7
spec/helpers/collection_time_helper_spec.rb

@ -5,11 +5,8 @@ RSpec.describe CollectionTimeHelper do
let(:user) { create(:user, :data_coordinator) }
describe "Current collection start year" do
around do |example|
Timecop.freeze(now) do
example.run
end
Timecop.return
before do
allow(Time).to receive(:now).and_return(now)
end
context "when the date is after 1st of April" do

10
spec/helpers/duplicate_logs_helper_spec.rb

@ -1,16 +1,6 @@
require "rails_helper"
RSpec.describe DuplicateLogsHelper do
before do
Timecop.freeze(Time.zone.local(2024, 3, 1))
Singleton.__init__(FormHandler)
end
after do
Timecop.return
Singleton.__init__(FormHandler)
end
describe "#duplicates_for_user" do
let(:org) { create(:organisation) }
let(:other_org) { create(:organisation) }

14
spec/helpers/filters_helper_spec.rb

@ -241,11 +241,8 @@ RSpec.describe FiltersHelper do
describe "#collection_year_options" do
context "with 23/24 as the current collection year" do
around do |example|
Timecop.freeze(Time.zone.local(2023, 5, 1)) do
example.run
end
Timecop.return
before do
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 5, 1))
end
it "has the correct options" do
@ -258,11 +255,8 @@ RSpec.describe FiltersHelper do
end
context "with 24/25 as the current collection year" do
around do |example|
Timecop.freeze(Time.zone.local(2024, 5, 1)) do
example.run
end
Timecop.return
before do
allow(Time).to receive(:now).and_return(Time.zone.local(2024, 5, 1))
end
it "has the correct options" do

11
spec/helpers/form_page_error_helper_spec.rb

@ -3,15 +3,6 @@ require "rails_helper"
RSpec.describe FormPageErrorHelper do
describe "#remove_other_page_errors" do
context "when non base other questions are removed" do
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
let!(:lettings_log) { FactoryBot.create(:lettings_log, :in_progress) }
let!(:form) { lettings_log.form }
@ -22,7 +13,7 @@ RSpec.describe FormPageErrorHelper do
end
it "returns details and user tabs" do
page = form.get_page("rent")
page = form.get_question("period", lettings_log).page
remove_other_page_errors(lettings_log, page)
expect(lettings_log.errors.count).to eq(2)
expect(lettings_log.errors.map(&:attribute)).to include(:period)

16
spec/helpers/interruption_screen_helper_spec.rb

@ -1,9 +1,6 @@
require "rails_helper"
RSpec.describe InterruptionScreenHelper do
form_handler = FormHandler.instance
let(:form) { form_handler.get_form("test_form") }
let(:subsection) { form.get_subsection("household_characteristics") }
let(:user) { create(:user) }
let(:lettings_log) do
create(
@ -11,7 +8,9 @@ RSpec.describe InterruptionScreenHelper do
:in_progress,
hhmemb: 1,
ecstat1: 1,
period: 1,
earnings: 750,
net_income_known: 0,
incfreq: 1,
assigned_to: user,
sex1: "F",
@ -19,15 +18,6 @@ RSpec.describe InterruptionScreenHelper do
)
end
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
describe "display_informative_text" do
context "when 2 out of 2 arguments are given" do
it "returns correct informative text" do
@ -249,7 +239,7 @@ RSpec.describe InterruptionScreenHelper do
it "returns a list of questions affected by the soft validation" do
expect(soft_validation_affected_questions(question, lettings_log).count).to eq(2)
expect(soft_validation_affected_questions(question, lettings_log).map(&:id)).to eq(%w[age1 ecstat1])
expect(soft_validation_affected_questions(question, lettings_log).map(&:id)).to match_array(%w[ecstat1 age1])
end
end
end

88
spec/helpers/locations_helper_spec.rb

@ -49,88 +49,88 @@ RSpec.describe LocationsHelper do
describe "Active periods" do
let(:location) { FactoryBot.create(:location, startdate: nil) }
let(:today) { Time.zone.local(2023, 10, 10) }
let(:one_year_ago) { today - 1.year }
let(:over_a_year_ago) { one_year_ago - 5.months }
let(:beginning_of_collection) { Time.zone.local(2022, 4, 1) }
before do
Timecop.freeze(2023, 10, 10)
allow(Time).to receive(:now).and_return(today)
allow(FormHandler.instance).to receive(:lettings_in_crossover_period?).and_return(true)
end
after do
Timecop.unfreeze
end
it "returns one active period without to date" do
expect(location_active_periods(location).count).to eq(1)
expect(location_active_periods(location).first).to have_attributes(from: Time.zone.local(2022, 4, 1), to: nil)
expect(location_active_periods(location).first).to have_attributes(from: beginning_of_collection, to: nil)
end
it "ignores reactivations that were deactivated on the same day" do
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 5, 5), reactivation_date: Time.zone.local(2022, 6, 4), location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 4), location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: over_a_year_ago, reactivation_date: over_a_year_ago + 1.month, location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: over_a_year_ago + 1.month, location:)
location.reload
expect(location_active_periods(location).count).to eq(1)
expect(location_active_periods(location).first).to have_attributes(from: Time.zone.local(2022, 4, 1), to: Time.zone.local(2022, 5, 5))
expect(location_active_periods(location).first).to have_attributes(from: beginning_of_collection, to: over_a_year_ago)
end
it "returns sequential non reactivated active periods" do
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 5, 5), reactivation_date: Time.zone.local(2022, 6, 4), location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 7, 6), location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: over_a_year_ago, reactivation_date: over_a_year_ago + 1.month, location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: over_a_year_ago + 2.months, location:)
location.reload
expect(location_active_periods(location).count).to eq(2)
expect(location_active_periods(location).first).to have_attributes(from: Time.zone.local(2022, 4, 1), to: Time.zone.local(2022, 5, 5))
expect(location_active_periods(location).second).to have_attributes(from: Time.zone.local(2022, 6, 4), to: Time.zone.local(2022, 7, 6))
expect(location_active_periods(location).first).to have_attributes(from: beginning_of_collection, to: over_a_year_ago)
expect(location_active_periods(location).second).to have_attributes(from: over_a_year_ago + 1.month, to: over_a_year_ago + 2.months)
end
it "returns sequential reactivated active periods" do
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 5, 5), reactivation_date: Time.zone.local(2022, 6, 4), location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 7, 6), reactivation_date: Time.zone.local(2022, 8, 5), location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: over_a_year_ago, reactivation_date: over_a_year_ago + 1.month, location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: over_a_year_ago + 2.months, reactivation_date: over_a_year_ago + 3.months, location:)
location.reload
expect(location_active_periods(location).count).to eq(3)
expect(location_active_periods(location).first).to have_attributes(from: Time.zone.local(2022, 4, 1), to: Time.zone.local(2022, 5, 5))
expect(location_active_periods(location).second).to have_attributes(from: Time.zone.local(2022, 6, 4), to: Time.zone.local(2022, 7, 6))
expect(location_active_periods(location).third).to have_attributes(from: Time.zone.local(2022, 8, 5), to: nil)
expect(location_active_periods(location).first).to have_attributes(from: beginning_of_collection, to: over_a_year_ago)
expect(location_active_periods(location).second).to have_attributes(from: over_a_year_ago + 1.month, to: over_a_year_ago + 2.months)
expect(location_active_periods(location).third).to have_attributes(from: over_a_year_ago + 3.months, to: nil)
end
it "returns non sequential non reactivated active periods" do
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 7, 6), reactivation_date: Time.zone.local(2022, 8, 5), location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 5, 5), reactivation_date: nil, location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: over_a_year_ago + 2.months, reactivation_date: over_a_year_ago + 3.months, location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: over_a_year_ago, reactivation_date: nil, location:)
location.reload
expect(location_active_periods(location).count).to eq(2)
expect(location_active_periods(location).first).to have_attributes(from: Time.zone.local(2022, 4, 1), to: Time.zone.local(2022, 5, 5))
expect(location_active_periods(location).second).to have_attributes(from: Time.zone.local(2022, 8, 5), to: nil)
expect(location_active_periods(location).first).to have_attributes(from: beginning_of_collection, to: over_a_year_ago)
expect(location_active_periods(location).second).to have_attributes(from: over_a_year_ago + 3.months, to: nil)
end
it "returns non sequential reactivated active periods" do
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 7, 6), reactivation_date: Time.zone.local(2022, 8, 5), location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 5, 5), reactivation_date: Time.zone.local(2022, 6, 4), location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: over_a_year_ago + 2.months, reactivation_date: over_a_year_ago + 3.months, location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: over_a_year_ago, reactivation_date: over_a_year_ago + 1.month, location:)
location.reload
expect(location_active_periods(location).count).to eq(3)
expect(location_active_periods(location).first).to have_attributes(from: Time.zone.local(2022, 4, 1), to: Time.zone.local(2022, 5, 5))
expect(location_active_periods(location).second).to have_attributes(from: Time.zone.local(2022, 6, 4), to: Time.zone.local(2022, 7, 6))
expect(location_active_periods(location).third).to have_attributes(from: Time.zone.local(2022, 8, 5), to: nil)
expect(location_active_periods(location).first).to have_attributes(from: beginning_of_collection, to: over_a_year_ago)
expect(location_active_periods(location).second).to have_attributes(from: over_a_year_ago + 1.month, to: over_a_year_ago + 2.months)
expect(location_active_periods(location).third).to have_attributes(from: over_a_year_ago + 3.months, to: nil)
end
it "returns correct active periods when reactivation happends during a deactivated period" do
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 5, 5), reactivation_date: Time.zone.local(2022, 11, 11), location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 4, 6), reactivation_date: Time.zone.local(2022, 7, 7), location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: over_a_year_ago, reactivation_date: one_year_ago, location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: beginning_of_collection + 2.days, reactivation_date: over_a_year_ago + 1.month, location:)
location.reload
expect(location_active_periods(location).count).to eq(2)
expect(location_active_periods(location).first).to have_attributes(from: Time.zone.local(2022, 4, 1), to: Time.zone.local(2022, 4, 6))
expect(location_active_periods(location).second).to have_attributes(from: Time.zone.local(2022, 11, 11), to: nil)
expect(location_active_periods(location).first).to have_attributes(from: beginning_of_collection, to: beginning_of_collection + 2.days)
expect(location_active_periods(location).second).to have_attributes(from: one_year_ago, to: nil)
end
it "returns correct active periods when a full deactivation period happens during another deactivation period" do
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 5, 5), reactivation_date: Time.zone.local(2022, 6, 11), location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 4, 6), reactivation_date: Time.zone.local(2022, 7, 7), location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: over_a_year_ago, reactivation_date: over_a_year_ago + 1.month, location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: over_a_year_ago - 1.month, reactivation_date: over_a_year_ago + 3.months, location:)
location.reload
expect(location_active_periods(location).count).to eq(2)
expect(location_active_periods(location).first).to have_attributes(from: Time.zone.local(2022, 4, 1), to: Time.zone.local(2022, 4, 6))
expect(location_active_periods(location).second).to have_attributes(from: Time.zone.local(2022, 7, 7), to: nil)
expect(location_active_periods(location).first).to have_attributes(from: beginning_of_collection, to: over_a_year_ago - 1.month)
expect(location_active_periods(location).second).to have_attributes(from: over_a_year_ago + 3.months, to: nil)
end
end
@ -228,10 +228,9 @@ RSpec.describe LocationsHelper do
context "with previous deactivations" do
context "and all reactivated deactivations" do
before do
Timecop.freeze(Time.zone.local(2023, 11, 10))
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 11, 10))
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 10), reactivation_date: Time.zone.local(2022, 9, 1), location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 9, 15), reactivation_date: Time.zone.local(2022, 9, 28), location:)
Timecop.return
location.reload
end
@ -244,10 +243,9 @@ RSpec.describe LocationsHelper do
context "and non reactivated deactivation" do
before do
Timecop.freeze(Time.zone.local(2023, 11, 10))
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 11, 10))
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 10), reactivation_date: Time.zone.local(2022, 9, 1), location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 9, 15), reactivation_date: nil, location:)
Timecop.return
location.reload
end
@ -262,10 +260,9 @@ RSpec.describe LocationsHelper do
context "with out of order deactivations" do
context "and all reactivated deactivations" do
before do
Timecop.freeze(Time.zone.local(2023, 11, 10))
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 11, 10))
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 9, 24), reactivation_date: Time.zone.local(2022, 9, 28), location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 15), reactivation_date: Time.zone.local(2022, 6, 18), location:)
Timecop.return
location.reload
end
@ -278,10 +275,9 @@ RSpec.describe LocationsHelper do
context "and one non reactivated deactivation" do
before do
Timecop.freeze(Time.zone.local(2023, 11, 10))
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 11, 10))
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 9, 24), reactivation_date: Time.zone.local(2022, 9, 28), location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 15), reactivation_date: nil, location:)
Timecop.return
location.reload
end
@ -296,11 +292,10 @@ RSpec.describe LocationsHelper do
context "with multiple out of order deactivations" do
context "and one non reactivated deactivation" do
before do
Timecop.freeze(Time.zone.local(2023, 11, 10))
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 11, 10))
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 9, 24), reactivation_date: Time.zone.local(2022, 9, 28), location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 10, 24), reactivation_date: Time.zone.local(2022, 10, 28), location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 15), reactivation_date: nil, location:)
Timecop.return
location.reload
end
@ -314,10 +309,9 @@ RSpec.describe LocationsHelper do
context "with intersecting deactivations" do
before do
Timecop.freeze(Time.zone.local(2023, 11, 10))
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 11, 10))
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 10, 10), reactivation_date: Time.zone.local(2022, 12, 1), location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 11, 11), reactivation_date: Time.zone.local(2022, 12, 11), location:)
Timecop.return
location.reload
end

6
spec/helpers/schemes_helper_spec.rb

@ -5,11 +5,7 @@ RSpec.describe SchemesHelper do
let(:scheme) { FactoryBot.create(:scheme, created_at: Time.zone.today) }
before do
Timecop.freeze(2023, 1, 10)
end
after do
Timecop.unfreeze
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 1, 10))
end
it "returns one active period without to date" do

130
spec/helpers/tasklist_helper_spec.rb

@ -1,41 +1,32 @@
require "rails_helper"
RSpec.describe TasklistHelper do
let(:now) { Time.utc(2022, 1, 1) }
around do |example|
Timecop.freeze(now) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
end
describe "with lettings" do
let(:empty_lettings_log) { create(:lettings_log) }
let(:lettings_log) { build_stubbed(:lettings_log, :in_progress, needstype: 1, startdate: now) }
let(:lettings_log) { build_stubbed(:lettings_log, :in_progress, needstype: 1) }
describe "get next incomplete section" do
it "returns the first subsection name if it is not completed" do
expect(get_next_incomplete_section(lettings_log).id).to eq("household_characteristics")
expect(get_next_incomplete_section(lettings_log).id).to eq("property_information")
end
it "returns the first subsection name if it is partially completed" do
lettings_log["tenancycode"] = 123
expect(get_next_incomplete_section(lettings_log).id).to eq("household_characteristics")
lettings_log["uprn_known"] = 0
expect(get_next_incomplete_section(lettings_log).id).to eq("property_information")
end
end
describe "get sections 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
let(:completed_subsection) { instance_double("Subsection", status: :completed, displayed_in_tasklist?: true, applicable_questions: [{ id: "question" }]) }
let(:incomplete_subsection) { instance_double("Subsection", status: :not_started, displayed_in_tasklist?: true, applicable_questions: []) }
context "with an empty lettings log" do
before do
allow(empty_lettings_log.form).to receive(:subsections).and_return([incomplete_subsection])
end
it "returns the total displayed subsections count if no status is given" do
expect(get_subsections_count(empty_lettings_log)).to eq(7)
expect(get_subsections_count(empty_lettings_log)).to eq(1)
end
it "returns 0 sections for completed sections if no sections are completed" do
@ -44,8 +35,12 @@ RSpec.describe TasklistHelper do
end
context "with a partially complete lettings log" do
before do
allow(lettings_log.form).to receive(:subsections).and_return([completed_subsection, incomplete_subsection])
end
it "returns the total displayed subsections count if no status is given" do
expect(get_subsections_count(lettings_log)).to eq(7)
expect(get_subsections_count(lettings_log)).to eq(2)
end
it "returns the completed sections count" do
@ -82,13 +77,19 @@ RSpec.describe TasklistHelper do
end
describe "with sales" do
let(:empty_sales_log) { create(:sales_log, owning_organisation: nil) }
let(:completed_sales_log) { create(:sales_log, :completed) }
let(:empty_sales_log) { build(:sales_log, owning_organisation: nil) }
let(:completed_sales_log) { build(:sales_log, :completed) }
let(:completed_subsection) { instance_double("Subsection", status: :completed, displayed_in_tasklist?: true, applicable_questions: [{ id: "question" }]) }
let(:incomplete_subsection) { instance_double("Subsection", status: :not_started, displayed_in_tasklist?: true, applicable_questions: []) }
describe "get sections count" do
context "with an empty sales log" do
before do
allow(empty_sales_log.form).to receive(:subsections).and_return([incomplete_subsection])
end
it "returns the total displayed subsections count if no status is given (includes all 3 sale information subsections)" do
expect(get_subsections_count(empty_sales_log)).to eq(9)
expect(get_subsections_count(empty_sales_log)).to eq(1)
end
it "returns 0 sections for completed sections if no sections are completed" do
@ -97,12 +98,16 @@ RSpec.describe TasklistHelper do
end
context "with a completed sales log" do
before do
allow(completed_sales_log.form).to receive(:subsections).and_return([completed_subsection])
end
it "returns the total displayed subsections count if no status is given (includes only the 1 relevant sale information subsection)" do
expect(get_subsections_count(completed_sales_log)).to eq(7)
expect(get_subsections_count(completed_sales_log)).to eq(1)
end
it "returns the completed sections count" do
expect(get_subsections_count(completed_sales_log, :completed)).to eq(7)
expect(get_subsections_count(completed_sales_log, :completed)).to eq(1)
end
end
@ -115,8 +120,12 @@ RSpec.describe TasklistHelper do
describe "#review_log_text" do
context "with sales log" do
context "when collection_period_open? == true" do
let(:now) { Time.utc(2022, 6, 1) }
let(:sales_log) { create(:sales_log, :completed, saledate: now) }
let(:sales_log) { build(:sales_log, :completed, saledate: Time.zone.local(2022, 6, 9), id: 123) }
before do
allow(sales_log.form).to receive(:submission_deadline).and_return(Time.zone.local(2023, 6, 9))
allow(sales_log).to receive(:collection_period_open?).and_return(true)
end
it "returns relevant text" do
expect(review_log_text(sales_log)).to eq(
@ -126,19 +135,25 @@ RSpec.describe TasklistHelper do
end
context "when collection_period_open? == false" do
let(:now) { Time.utc(2022, 6, 1) }
let!(:sales_log) { create(:sales_log, :completed, saledate: now) }
let!(:sales_log) { build(:sales_log, :completed, saledate: Time.zone.local(2022, 6, 1)) }
before do
allow(sales_log.form).to receive(:submission_deadline).and_return(Time.zone.local(2023, 6, 9))
allow(sales_log).to receive(:collection_period_open?).and_return(false)
end
it "returns relevant text" do
Timecop.freeze(now + 1.year) do
expect(review_log_text(sales_log)).to eq("This log is from the 2022/2023 collection window, which is now closed.")
end
expect(review_log_text(sales_log)).to eq("This log is from the 2022/2023 collection window, which is now closed.")
end
end
context "when older_than_previous_collection_year" do
let(:now) { Time.utc(2023, 6, 1) }
let(:sales_log) { build(:sales_log, :completed, saledate: Time.utc(2022, 2, 1)) }
let(:sales_log) { build(:sales_log, :completed, saledate: Time.zone.local(2022, 2, 1)) }
before do
allow(sales_log.form).to receive(:submission_deadline).and_return(Time.zone.local(2022, 6, 9))
allow(sales_log).to receive(:older_than_previous_collection_year?).and_return(true)
end
it "returns relevant text" do
expect(review_log_text(sales_log)).to eq("This log is from the 2021/2022 collection window, which is now closed.")
@ -148,43 +163,40 @@ RSpec.describe TasklistHelper do
context "with lettings log" do
context "when collection_period_open? == true" do
context "with 2023 deadline" do
let(:now) { Time.utc(2022, 6, 1) }
let(:lettings_log) { create(:lettings_log, :completed) }
let(:lettings_log) { build(:lettings_log, :completed, id: 123) }
it "returns relevant text" do
expect(review_log_text(lettings_log)).to eq(
"You can #{govuk_link_to 'review and make changes to this log', review_lettings_log_path(lettings_log)} until 9 June 2023.".html_safe,
)
end
before do
allow(lettings_log.form).to receive(:submission_deadline).and_return(Time.zone.local(2023, 6, 9))
allow(lettings_log).to receive(:collection_period_open?).and_return(true)
end
context "with 2024 deadline" do
let(:now) { Time.utc(2023, 6, 20) }
let(:lettings_log) { create(:lettings_log, :completed, national: 18, waityear: 2) }
it "returns relevant text" do
expect(review_log_text(lettings_log)).to eq(
"You can #{govuk_link_to 'review and make changes to this log', review_lettings_log_path(lettings_log)} until 7 June 2024.".html_safe,
)
end
it "returns relevant text" do
expect(review_log_text(lettings_log)).to eq(
"You can #{govuk_link_to 'review and make changes to this log', review_lettings_log_path(lettings_log)} until 9 June 2023.".html_safe,
)
end
end
context "when collection_period_open? == false" do
let(:now) { Time.utc(2022, 6, 1) }
let!(:sales_log) { create(:lettings_log, :completed) }
let!(:lettings_log) { build(:lettings_log, :completed, startdate: Time.zone.local(2022, 6, 1), id: 123) }
before do
allow(lettings_log.form).to receive(:submission_deadline).and_return(Time.zone.local(2023, 6, 9))
allow(lettings_log).to receive(:collection_period_open?).and_return(false)
end
it "returns relevant text" do
Timecop.freeze(now + 1.year) do
expect(review_log_text(sales_log)).to eq("This log is from the 2022/2023 collection window, which is now closed.")
end
expect(review_log_text(lettings_log)).to eq("This log is from the 2022/2023 collection window, which is now closed.")
end
end
context "when older_than_previous_collection_year" do
let(:now) { Time.utc(2023, 6, 1) }
let(:lettings_log) { build(:lettings_log, :completed, startdate: Time.utc(2022, 2, 1)) }
let(:lettings_log) { build(:lettings_log, :completed, startdate: Time.zone.local(2022, 2, 1)) }
before do
allow(lettings_log.form).to receive(:submission_deadline).and_return(Time.zone.local(2022, 6, 9))
allow(lettings_log).to receive(:older_than_previous_collection_year?).and_return(true)
end
it "returns relevant text" do
expect(review_log_text(lettings_log)).to eq("This log is from the 2021/2022 collection window, which is now closed.")

2
spec/models/form/lettings/questions/address_line1_for_address_matcher_spec.rb

@ -6,7 +6,7 @@ RSpec.describe Form::Lettings::Questions::AddressLine1ForAddressMatcher, type: :
let(:question_id) { nil }
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page) }
let(:log) { create(:lettings_log, :in_progress, address_line1_input: "Address line 1", postcode_full_input: "AA1 1AA") }
let(:log) { build(:lettings_log, :in_progress, address_line1_input: "Address line 1", postcode_full_input: "AA1 1AA") }
it "has correct page" do
expect(question.page).to eq(page)

6
spec/models/form/lettings/questions/location_id_spec.rb

@ -61,11 +61,7 @@ RSpec.describe Form::Lettings::Questions::LocationId, type: :model do
context "when selected scheme has locations" do
before do
Timecop.freeze(Time.utc(2022, 5, 12))
end
after do
Timecop.unfreeze
allow(Time).to receive(:now).and_return(Time.utc(2022, 5, 12))
end
context "and all the locations have a startdate more than 2 weeks in the future" do

2
spec/models/form/lettings/questions/postcode_for_address_matcher_spec.rb

@ -6,7 +6,7 @@ RSpec.describe Form::Lettings::Questions::PostcodeForAddressMatcher, type: :mode
let(:question_id) { nil }
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page) }
let(:log) { create(:lettings_log, :in_progress, address_line1_input: "Address line 1", postcode_full_input: "AA1 1AA") }
let(:log) { build(:lettings_log, :in_progress, address_line1_input: "Address line 1", postcode_full_input: "AA1 1AA") }
it "has correct page" do
expect(question.page).to eq(page)

26
spec/models/form/lettings/questions/stock_owner_spec.rb

@ -117,11 +117,7 @@ RSpec.describe Form::Lettings::Questions::StockOwner, type: :model do
before do
merged_organisation.update!(merge_date: Time.zone.local(2023, 2, 2), absorbing_organisation: user.organisation)
user.organisation.update!(available_from: Time.zone.local(2021, 2, 2))
Timecop.freeze(Time.zone.local(2023, 11, 10))
end
after do
Timecop.return
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 11, 10))
end
it "shows merged organisation as an option" do
@ -143,11 +139,7 @@ RSpec.describe Form::Lettings::Questions::StockOwner, type: :model do
before do
merged_organisation.update!(merge_date: Time.zone.local(2023, 2, 2), absorbing_organisation: user.organisation)
Timecop.freeze(Time.zone.local(2023, 11, 10))
end
after do
Timecop.return
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 11, 10))
end
it "shows merged organisation as an option" do
@ -167,16 +159,12 @@ RSpec.describe Form::Lettings::Questions::StockOwner, type: :model do
end
before do
Timecop.freeze(Time.zone.local(2023, 11, 10))
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 11, 10))
org_rel.update!(child_organisation: merged_organisation)
merged_organisation.update!(merge_date: Time.zone.local(2023, 2, 2), absorbing_organisation: user.organisation)
user.organisation.update!(available_from: Time.zone.local(2021, 2, 2))
end
after do
Timecop.return
end
it "does not show merged organisations stock owners as options" do
expect(question.displayed_answer_options(log, user)).to eq(options)
end
@ -193,7 +181,7 @@ RSpec.describe Form::Lettings::Questions::StockOwner, type: :model do
end
before do
Timecop.freeze(Time.zone.local(2023, 4, 2))
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 4, 2))
org_rel.update!(child_organisation: merged_organisation)
merged_organisation.update!(merge_date: Time.zone.local(2021, 6, 2), absorbing_organisation: user.organisation)
user.organisation.update!(available_from: Time.zone.local(2021, 2, 2))
@ -238,11 +226,7 @@ RSpec.describe Form::Lettings::Questions::StockOwner, type: :model do
before do
merged_organisation.update!(merge_date: Time.zone.local(2023, 2, 2), absorbing_organisation: org)
Timecop.freeze(Time.zone.local(2023, 11, 10))
end
after do
Timecop.return
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 11, 10))
end
it "shows merged organisation as an option" do

2
spec/models/form/lettings/questions/uprn_selection_spec.rb

@ -6,7 +6,7 @@ RSpec.describe Form::Lettings::Questions::UprnSelection, type: :model do
let(:question_id) { nil }
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page, skip_href: "skip_href") }
let(:log) { create(:lettings_log, :in_progress, address_line1_input: "Address line 1", postcode_full_input: "AA1 1AA") }
let(:log) { build(:lettings_log, :in_progress, address_line1_input: "Address line 1", postcode_full_input: "AA1 1AA") }
let(:address_client_instance) { AddressClient.new(log.address_string) }
before do

87
spec/models/form/page_spec.rb

@ -3,30 +3,21 @@ require "rails_helper"
RSpec.describe Form::Page, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
let(:user) { FactoryBot.create(:user) }
let(:lettings_log) { FactoryBot.build(:lettings_log) }
let(:form) { lettings_log.form }
let(:section_id) { "rent_and_charges" }
let(:section_definition) { form.form_definition["sections"][section_id] }
let(:section) { Form::Section.new(section_id, section_definition, form) }
let(:subsection_id) { "income_and_benefits" }
let(:subsection_definition) { section_definition["subsections"][subsection_id] }
let(:subsection) { Form::Subsection.new(subsection_id, subsection_definition, section) }
let(:depends_on) { nil }
let(:enabled) { true }
let(:depends_on_met) { true }
let(:form) { instance_double(Form, depends_on_met:) }
let(:subsection) { instance_double(Form::Subsection, depends_on:, enabled?: enabled, form:) }
let(:page_id) { "net_income" }
let(:page_definition) { subsection_definition["pages"][page_id] }
let(:fake_2021_2022_form) { Form.new("spec/fixtures/forms/2021_2022.json") }
before do
allow(FormHandler.instance).to receive(:current_lettings_form).and_return(fake_2021_2022_form)
let(:questions) { [["earnings", { "conditional_for" => { "age1": nil }, "type" => "radio" }], %w[incfreq]] }
let(:page_definition) do
{
"header" => "Test header",
"description" => "Some extra text for the page",
"questions" => questions,
}
end
it "has an id" do
@ -46,14 +37,10 @@ RSpec.describe Form::Page, type: :model do
expect(page.questions.map(&:id)).to eq(expected_questions)
end
context "with a page having conditional questions" do
let(:page_id) { "housing_benefit" }
it "knows which questions are not conditional" do
expected_non_conditional_questions = %w[hb]
expect(page.non_conditional_questions.map(&:id))
.to eq(expected_non_conditional_questions)
end
it "knows which questions are not conditional" do
expected_non_conditional_questions = %w[earnings incfreq]
expect(page.non_conditional_questions.map(&:id))
.to eq(expected_non_conditional_questions)
end
describe "#interruption_screen?" do
@ -64,7 +51,7 @@ RSpec.describe Form::Page, type: :model do
end
context "when it has interruption_screen question" do
let(:page) { form.get_page("retirement_value_check") }
let(:questions) { [["earnings", { "type" => "interruption_screen" }]] }
it "returns true" do
expect(page.interruption_screen?).to be true
@ -80,43 +67,33 @@ RSpec.describe Form::Page, type: :model do
end
context "with routing conditions" do
let(:page_id) { "dependent_page" }
let(:depends_on) { true }
it "evaluates not met conditions correctly" do
expect(page.routed_to?(lettings_log, user)).to be false
end
context "when the conditions are not met" do
let(:depends_on_met) { false }
it "evaluates met conditions correctly" do
lettings_log.incfreq = 1
expect(page.routed_to?(lettings_log, user)).to be true
it "evaluates conditions correctly" do
expect(page.routed_to?(lettings_log, user)).to be false
end
end
end
context "with expression routing conditions" do
let(:section_id) { "household" }
let(:subsection_id) { "household_characteristics" }
let(:page_id) { "person_2_working_situation" }
it "evaluates not met conditions correctly" do
lettings_log.age2 = 12
expect(page.routed_to?(lettings_log, user)).to be false
end
context "when the conditions are met" do
let(:depends_on_met) { true }
it "evaluates met conditions correctly" do
lettings_log.age2 = 17
expect(page.routed_to?(lettings_log, user)).to be true
it "evaluates met conditions correctly" do
lettings_log.incfreq = 1
expect(page.routed_to?(lettings_log, user)).to be true
end
end
end
context "when the page's subsection has routing conditions" do
let(:section_id) { "submission" }
let(:subsection_id) { "declaration" }
let(:page_id) { "declaration" }
let(:completed_lettings_log) { FactoryBot.build(:lettings_log, :completed, incfreq: "Weekly") }
let(:depends_on) { true }
let(:depends_on_met) { true }
let(:enabled) { false }
it "evaluates the sections dependencies" do
expect(page.routed_to?(lettings_log, user)).to be false
expect(page.routed_to?(completed_lettings_log, user)).to be true
end
end
end

191
spec/models/form/question_spec.rb

@ -3,32 +3,35 @@ require "rails_helper"
RSpec.describe Form::Question, type: :model do
subject(:question) { described_class.new(question_id, question_definition, page) }
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
let(:lettings_log) { FactoryBot.build(:lettings_log) }
let(:form) { lettings_log.form }
let(:section_id) { "rent_and_charges" }
let(:section_definition) { form.form_definition["sections"][section_id] }
let(:section) { Form::Section.new(section_id, section_definition, form) }
let(:subsection_id) { "income_and_benefits" }
let(:subsection_definition) { section_definition["subsections"][subsection_id] }
let(:subsection) { Form::Subsection.new(subsection_id, subsection_definition, section) }
let(:page_id) { "net_income" }
let(:page_definition) { subsection_definition["pages"][page_id] }
let(:page) { Form::Page.new(page_id, page_definition, subsection) }
let(:type) { "numeric" }
let(:readonly) { nil }
let(:prefix) { nil }
let(:suffix) { nil }
let(:depends_on_met) { nil }
let(:conditional_question_conditions) { nil }
let(:form_questions) { nil }
let(:answer_options) { { "1" => { "value" => "Weekly" }, "2" => { "value" => "Monthly" } } }
let(:inferred_check_answers_value) { [{ "condition" => { "postcode_known" => 0 }, "value" => "Weekly" }] }
let(:form) { instance_double(Form, depends_on_met:, conditional_question_conditions:) }
let(:subsection) { instance_double(Form::Subsection, form:) }
let(:page) { instance_double(Form::Page, subsection:, routed_to?: true, questions: form_questions) }
let(:question_id) { "earnings" }
let(:question_definition) { page_definition["questions"][question_id] }
let(:fake_2021_2022_form) { Form.new("spec/fixtures/forms/2021_2022.json") }
before do
allow(FormHandler.instance).to receive(:current_lettings_form).and_return(fake_2021_2022_form)
let(:question_definition) do
{ "header" => "What is the tenant’s /and partner’s combined income after tax?",
"check_answer_label" => "Income",
"type" => type,
"min" => 0,
"step" => 1,
"answer_options" => answer_options,
"readonly" => readonly,
"result-field" => "tcharge",
"fields-to-add" => %w[brent scharge pscharge supcharg],
"inferred_check_answers_value" => inferred_check_answers_value,
"suffix" => suffix,
"prefix" => prefix,
"hidden_in_check_answers" => {} }
end
it "has an id" do
@ -80,10 +83,10 @@ RSpec.describe Form::Question, type: :model do
end
context "when type is radio" do
let(:question_id) { "incfreq" }
let(:type) { "radio" }
it "has answer options" do
expected_answer_options = { "1" => { "value" => "Weekly" }, "2" => { "value" => "Monthly" }, "3" => { "value" => "Yearly" } }
expected_answer_options = { "1" => { "value" => "Weekly" }, "2" => { "value" => "Monthly" } }
expect(question.answer_options).to eq(expected_answer_options)
end
@ -92,13 +95,10 @@ RSpec.describe Form::Question, type: :model do
end
it "can map label from value" do
expect(question.label_from_value(3)).to eq("Yearly")
expect(question.label_from_value(1)).to eq("Weekly")
end
context "when answer options include yes, no, prefer not to say" do
let(:section_id) { "household" }
let(:subsection_id) { "household_needs" }
let(:page_id) { "medical_conditions" }
let(:question_id) { "illness" }
it "maps those options" do
@ -109,9 +109,6 @@ RSpec.describe Form::Question, type: :model do
end
context "when answer options includes don’t know" do
let(:section_id) { "local_authority" }
let(:subsection_id) { "local_authority" }
let(:page_id) { "time_lived_in_la" }
let(:question_id) { "layear" }
it "maps those options" do
@ -128,23 +125,11 @@ RSpec.describe Form::Question, type: :model do
end
context "when answer options include derived options" do
let(:section_id) { "household" }
let(:subsection_id) { "household_characteristics" }
let(:page_id) { "person_2_working_situation" }
let(:question_id) { "ecstat2" }
let(:answer_options) { { "0" => { "value" => "Other" }, "9" => { "value" => "This", "depends_on" => [false] } } }
let(:depends_on_met) { false }
let(:expected_answer_options) do
{
"0" => { "value" => "Other" },
"1" => { "value" => "Full-time – 30 hours or more" },
"10" => { "value" => "Tenant prefers not to say" },
"2" => { "value" => "Part-time – Less than 30 hours" },
"3" => { "value" => "In government training into work, such as New Deal" },
"4" => { "value" => "Jobseeker" },
"5" => { "value" => "Retired" },
"6" => { "value" => "Not seeking work" },
"7" => { "value" => "Full-time student" },
"8" => { "value" => "Unable to work because of long term sick or disability" },
"divider" => { "value" => true },
}
end
@ -153,7 +138,7 @@ RSpec.describe Form::Question, type: :model do
end
it "can still map the value label" do
expect(question.label_from_value(9)).to eq("Child under 16")
expect(question.label_from_value(9)).to eq("This")
end
end
@ -165,10 +150,8 @@ RSpec.describe Form::Question, type: :model do
end
context "when type is select" do
let(:section_id) { "household" }
let(:subsection_id) { "household_needs" }
let(:page_id) { "accessible_select" }
let(:question_id) { "prevloc" }
let(:type) { "select" }
let(:answer_options) { { "E08000003" => "Manchester", "E09000033" => "Westminster" } }
it "can map value from label" do
expect(question.value_from_label("Manchester")).to eq("E08000003")
@ -186,10 +169,9 @@ RSpec.describe Form::Question, type: :model do
end
context "when type is checkbox" do
let(:section_id) { "household" }
let(:subsection_id) { "household_needs" }
let(:page_id) { "condition_effects" }
let(:question_id) { "condition_effects" }
let(:type) { "checkbox" }
let(:page_id) { "illness" }
let(:answer_options) { { "illness_type_1" => { "value" => "Vision - such as blindness or partial sight" }, "illness_type_2" => { "value" => "Hearing - such as deafness or partial hearing" } } }
it "has answer options" do
expected_answer_options = {
@ -206,9 +188,7 @@ RSpec.describe Form::Question, type: :model do
end
context "when the question is read only" do
let(:subsection_id) { "rent_and_charges" }
let(:page_id) { "rent" }
let(:question_id) { "tcharge" }
let(:readonly) { true }
it "has a read only helper" do
expect(question.read_only?).to be true
@ -231,6 +211,8 @@ RSpec.describe Form::Question, type: :model do
context "with a lettings log" do
let(:lettings_log) { FactoryBot.build(:lettings_log, :in_progress) }
let(:question_id) { "incfreq" }
let(:type) { "radio" }
let(:answer_options) { { "1" => { "value" => "Weekly" }, "2" => { "value" => "Monthly" }, "3" => { "value" => "Yearly", "depends_on" => true } } }
it "has an answer label" do
lettings_log.incfreq = 1
@ -244,11 +226,9 @@ RSpec.describe Form::Question, type: :model do
end
context "when the question has an inferred answer" do
let(:section_id) { "tenancy_and_property" }
let(:subsection_id) { "property_information" }
let(:page_id) { "property_postcode" }
let(:lettings_log) { FactoryBot.build(:lettings_log, :in_progress, postcode_known: 0, postcode_full: nil) }
let(:question_id) { "postcode_full" }
let(:question_id) { "incfreq" }
let(:type) { "radio" }
it "displays 'change' in the check answers link text" do
expect(question.action_text(lettings_log)).to match(/Change/)
@ -256,13 +236,8 @@ RSpec.describe Form::Question, type: :model do
end
context "when the answer option is a derived answer option" do
let(:section_id) { "household" }
let(:subsection_id) { "household_characteristics" }
let(:page_id) { "person_2_working_situation" }
let(:question_id) { "ecstat2" }
let(:lettings_log) do
FactoryBot.create(:lettings_log, :in_progress, hhmemb: 2, details_known_2: 0, age2_known: 0, age2: 12)
end
let(:lettings_log) { FactoryBot.build(:lettings_log, :in_progress, incfreq: 3, postcode_full: nil) }
let(:depends_on_met) { true }
it "knows it has an inferred value or is derived for check answers" do
expect(question.is_derived_or_has_inferred_check_answers_value?(lettings_log)).to be true
@ -270,10 +245,8 @@ RSpec.describe Form::Question, type: :model do
end
context "when type is date" do
let(:section_id) { "local_authority" }
let(:subsection_id) { "local_authority" }
let(:page_id) { "property_major_repairs" }
let(:question_id) { "mrcdate" }
let(:type) { "date" }
it "displays a formatted answer label" do
lettings_log.mrcdate = Time.zone.local(2021, 10, 11)
@ -287,10 +260,15 @@ RSpec.describe Form::Question, type: :model do
end
context "when type is checkbox" do
let(:section_id) { "household" }
let(:subsection_id) { "household_needs" }
let(:page_id) { "accessibility_requirements" }
let(:question_id) { "accessibility_requirements" }
let(:question_id) { "housingneeds_type" }
let(:type) { "checkbox" }
let(:answer_options) do
{
"housingneeds_a" => { "value" => "Fully wheelchair accessible housing" },
"housingneeds_b" => { "value" => "Wheelchair access to essential rooms" },
"housingneeds_c" => { "value" => "Level access housing" },
}
end
it "has a joined answers label" do
lettings_log.housingneeds_a = 1
@ -301,8 +279,9 @@ RSpec.describe Form::Question, type: :model do
end
context "when a condition is present" do
let(:page_id) { "housing_benefit" }
let(:question_id) { "conditional_question" }
let(:conditional_question_conditions) { [{ to: question_id, from: "hb", cond: [0] }] }
let(:form_questions) { [OpenStruct.new(id: "hb", type: "radio")] }
it "knows whether it is enabled or not for unmet conditions" do
expect(question.enabled?(lettings_log)).to be false
@ -314,11 +293,7 @@ RSpec.describe Form::Question, type: :model do
end
context "when the condition type hasn't been implemented yet" do
let(:unimplemented_question) { OpenStruct.new(id: "hb", type: "unkown") }
before do
allow(page).to receive(:questions).and_return([unimplemented_question])
end
let(:form_questions) { [OpenStruct.new(id: "hb", type: "unkown")] }
it "raises an exception" do
expect { question.enabled?(lettings_log) }.to raise_error("Not implemented yet")
@ -327,10 +302,16 @@ RSpec.describe Form::Question, type: :model do
end
context "when answers have a suffix dependent on another answer" do
let(:section_id) { "rent_and_charges" }
let(:subsection_id) { "income_and_benefits" }
let(:page_id) { "net_income" }
let(:question_id) { "earnings" }
let(:type) { "numeric" }
let(:suffix) do
[
{ "label" => " every week", "depends_on" => { "incfreq" => 1 } },
{ "label" => " every month", "depends_on" => { "incfreq" => 2 } },
{ "label" => " every year", "depends_on" => { "incfreq" => 3 } },
]
end
let(:prefix) { "£" }
it "displays the correct label for given suffix and answer the suffix depends on" do
lettings_log.incfreq = 1
@ -345,10 +326,8 @@ RSpec.describe Form::Question, type: :model do
context "with inferred_check_answers_value" do
context "when Lettings form" do
let(:section_id) { "household" }
let(:subsection_id) { "household_needs" }
let(:page_id) { "armed_forces" }
let(:question_id) { "armedforces" }
let(:inferred_check_answers_value) { [{ "condition" => { "armedforces" => 3 }, "value" => "Prefers not to say" }] }
it "returns the inferred label value" do
lettings_log.armedforces = 3
@ -357,8 +336,9 @@ RSpec.describe Form::Question, type: :model do
end
context "when Sales form" do
let(:sales_log) { FactoryBot.create(:sales_log, :completed, national: 13, saledate: Time.zone.local(2022, 1, 1)) }
let(:question) { sales_log.form.get_question("national", sales_log) }
let(:question_id) { "national" }
let(:sales_log) { FactoryBot.build(:sales_log, :completed, national: 13) }
let(:inferred_check_answers_value) { [{ "condition" => { "national" => 13 }, "value" => "Prefers not to say" }] }
it "returns the inferred label value" do
expect(question.answer_label(sales_log)).to eq("Prefers not to say")
@ -369,11 +349,6 @@ RSpec.describe Form::Question, type: :model do
describe ".completed?" do
context "when the question has inferred value only for check answers display" do
let(:section_id) { "tenancy_and_property" }
let(:subsection_id) { "property_information" }
let(:page_id) { "property_postcode" }
let(:question_id) { "postcode_full" }
it "returns true" do
lettings_log["postcode_known"] = 0
expect(question.completed?(lettings_log)).to be(true)
@ -382,18 +357,22 @@ RSpec.describe Form::Question, type: :model do
end
context "when the question has a hidden in check answers attribute with dependencies" do
let(:section_id) { "local_authority" }
let(:subsection_id) { "local_authority" }
let(:page_id) { "time_lived_in_la" }
let(:question_id) { "layear" }
let(:lettings_log) do
FactoryBot.create(:lettings_log, :in_progress)
let(:lettings_log) { FactoryBot.build(:lettings_log, :in_progress) }
context "when it's hidden in check answers" do
let(:depends_on_met) { true }
it "can work out if the question will be shown in check answers" do
expect(question.hidden_in_check_answers?(lettings_log, nil)).to be(true)
end
end
it "can work out if the question will be shown in check answers" do
expect(question.hidden_in_check_answers?(lettings_log, nil)).to be(false)
lettings_log.layear = 0
expect(question.hidden_in_check_answers?(lettings_log, nil)).to be(true)
context "when it's not hidden in check answers" do
let(:depends_on_met) { false }
it "can work out if the question will be shown in check answers" do
expect(question.hidden_in_check_answers?(lettings_log, nil)).to be(false)
end
end
end
end

32
spec/models/form/sales/pages/buyer_previous_spec.rb

@ -3,21 +3,15 @@ require "rails_helper"
RSpec.describe Form::Sales::Pages::BuyerPrevious, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection, joint_purchase:) }
let(:log) { create(:sales_log, :completed) }
let(:log) { build(:sales_log, :completed) }
let(:page_id) { "example" }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection) }
let(:form) { instance_double(Form, start_date: Time.zone.local(2023, 4, 1)) }
let(:subsection) { instance_double(Form::Subsection, depends_on: nil, enabled?: true, form:) }
let(:start_date_after_2024) { false }
let(:form) { instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_after_2024?: start_date_after_2024, depends_on_met: true) }
let(:joint_purchase) { false }
before do
allow(subsection).to receive(:depends_on).and_return(nil)
allow(subsection).to receive(:enabled?).and_return(true)
allow(subsection).to receive(:form).and_return(form)
allow(form).to receive(:depends_on_met).and_return(true)
end
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
end
@ -53,14 +47,7 @@ RSpec.describe Form::Sales::Pages::BuyerPrevious, type: :model do
end
context "with 23/24 log" do
before do
Timecop.freeze(Time.zone.local(2023, 4, 2))
Singleton.__init__(FormHandler)
end
after do
Timecop.return
end
let(:start_date_after_2024) { false }
it "has correct routed to" do
log.staircase = 1
@ -69,14 +56,7 @@ RSpec.describe Form::Sales::Pages::BuyerPrevious, type: :model do
end
context "with 24/25 log" do
before do
Timecop.freeze(Time.zone.local(2024, 4, 2))
Singleton.__init__(FormHandler)
end
after do
Timecop.return
end
let(:start_date_after_2024) { true }
it "has correct routed to when staircase is yes" do
log.staircase = 1

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

@ -3,11 +3,13 @@ require "rails_helper"
RSpec.describe Form::Sales::Pages::LaNominations, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:log) { create(:sales_log, :completed) }
let(:log) { build(:sales_log, :completed) }
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1))) }
let(:start_year_after_2024) { false }
let(:form) { instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_after_2024?: start_year_after_2024) }
let(:subsection) { instance_double(Form::Subsection, form:) }
before do
allow(subsection).to receive(:depends_on).and_return(nil)
@ -34,14 +36,7 @@ RSpec.describe Form::Sales::Pages::LaNominations, type: :model do
end
context "with 23/24 log" do
before do
Timecop.freeze(Time.zone.local(2023, 4, 2))
Singleton.__init__(FormHandler)
end
after do
Timecop.return
end
let(:start_year_after_2024) { false }
it "has correct routed to" do
log.staircase = 1
@ -50,14 +45,7 @@ RSpec.describe Form::Sales::Pages::LaNominations, type: :model do
end
context "with 24/25 log" do
before do
Timecop.freeze(Time.zone.local(2024, 4, 2))
Singleton.__init__(FormHandler)
end
after do
Timecop.return
end
let(:start_year_after_2024) { true }
it "has correct routed to when staircase is yes" do
log.staircase = 1

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

@ -5,22 +5,10 @@ RSpec.describe Form::Sales::Pages::LastAccommodationLa, type: :model do
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, depends_on_met: true, start_date: Time.zone.local(2023, 4, 1))) }
let(:start_date) { Time.utc(2022, 4, 1) }
let(:log) { create(:sales_log, :completed, saledate: now) }
let(:now) { Time.zone.local(2023, 4, 4) }
before do
Timecop.freeze(now)
Singleton.__init__(FormHandler)
allow(subsection).to receive(:depends_on).and_return(nil)
allow(subsection).to receive(:enabled?).and_return(true)
end
after do
Timecop.return
Singleton.__init__(FormHandler)
end
let(:start_year_after_2024) { false }
let(:form) { instance_double(Form, depends_on_met: true, start_date: Time.zone.local(2023, 4, 1), start_year_after_2024?: start_year_after_2024) }
let(:subsection) { instance_double(Form::Subsection, form:, depends_on: nil, enabled?: true) }
let(:log) { build(:sales_log, :completed) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
@ -54,7 +42,7 @@ RSpec.describe Form::Sales::Pages::LastAccommodationLa, type: :model do
end
context "with 2024 form" do
let(:now) { Time.zone.local(2024, 4, 4) }
let(:start_year_after_2024) { true }
it "is routed to for 2024 non discounted sale logs" do
log.update!(ownershipsch: 1)

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

@ -3,23 +3,13 @@ require "rails_helper"
RSpec.describe Form::Sales::Pages::LastAccommodation, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:log) { create(:sales_log, :completed, saledate: now) }
let(:now) { Time.zone.local(2023, 4, 4) }
let(:log) { build(:sales_log, :completed) }
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1))) }
before do
Timecop.freeze(now)
Singleton.__init__(FormHandler)
allow(subsection).to receive(:depends_on).and_return(nil)
end
after do
Timecop.return
Singleton.__init__(FormHandler)
end
let(:start_year_after_2024) { false }
let(:form) { instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_after_2024?: start_year_after_2024) }
let(:subsection) { instance_double(Form::Subsection, form:, depends_on: nil) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
@ -51,7 +41,7 @@ RSpec.describe Form::Sales::Pages::LastAccommodation, type: :model do
end
context "with 2024 form" do
let(:now) { Time.zone.local(2024, 4, 4) }
let(:start_year_after_2024) { true }
it "is routed to for 2024 non discounted sale logs" do
log.update!(ownershipsch: 1)

40
spec/models/form/sales/questions/owning_organisation_id_spec.rb

@ -9,7 +9,7 @@ RSpec.describe Form::Sales::Questions::OwningOrganisationId, type: :model do
let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1)))) }
let!(:organisation_1) { FactoryBot.create(:organisation, name: "first test org") }
let!(:organisation_2) { FactoryBot.create(:organisation, name: "second test org") }
let(:lettings_log) { FactoryBot.create(:lettings_log) }
let(:lettings_log) { FactoryBot.build(:lettings_log) }
let(:expected_answer_options) do
{
"" => "Select an option",
@ -59,7 +59,7 @@ RSpec.describe Form::Sales::Questions::OwningOrganisationId, type: :model do
let(:owning_org_2) { create(:organisation, name: "Owning org 2") }
let(:inactive_owning_org) { create(:organisation, name: "Inactive owning org", active: false) }
let(:non_stock_owner) { create(:organisation, name: "Non stock owner", holds_own_stock: false) }
let(:log) { create(:lettings_log, owning_organisation: owning_org_1) }
let(:log) { build(:lettings_log, owning_organisation: owning_org_1) }
context "when user's org owns stock" do
before do
@ -117,11 +117,7 @@ RSpec.describe Form::Sales::Questions::OwningOrganisationId, type: :model do
before do
merged_organisation.update!(merge_date: Time.zone.local(2023, 2, 2), absorbing_organisation: user.organisation)
Timecop.freeze(Time.zone.local(2023, 11, 10))
end
after do
Timecop.return
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 11, 10))
end
it "shows merged organisation as an option" do
@ -143,11 +139,7 @@ RSpec.describe Form::Sales::Questions::OwningOrganisationId, type: :model do
before do
merged_organisation.update!(merge_date: Time.zone.local(2023, 2, 2), absorbing_organisation: user.organisation)
user.organisation.update!(available_from: Time.zone.local(2021, 2, 2))
Timecop.freeze(Time.zone.local(2023, 11, 10))
end
after do
Timecop.return
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 11, 10))
end
it "shows available from date if it is given" do
@ -169,11 +161,7 @@ RSpec.describe Form::Sales::Questions::OwningOrganisationId, type: :model do
before do
create(:organisation_relationship, child_organisation: user.organisation, parent_organisation: merged_organisation)
merged_organisation.update!(merge_date: Time.zone.local(2023, 2, 2), absorbing_organisation: user.organisation)
Timecop.freeze(Time.zone.local(2023, 11, 10))
end
after do
Timecop.return
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 11, 10))
end
it "does not show merged organisations stock owners as options" do
@ -193,7 +181,7 @@ RSpec.describe Form::Sales::Questions::OwningOrganisationId, type: :model do
end
before do
Timecop.freeze(Time.zone.local(2023, 4, 2))
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 4, 2))
create(:organisation_relationship, child_organisation: user.organisation, parent_organisation: merged_organisation)
merged_organisation.update!(merge_date: Time.zone.local(2021, 6, 2), absorbing_organisation: user.organisation)
user.organisation.update!(available_from: Time.zone.local(2021, 2, 2))
@ -207,7 +195,7 @@ RSpec.describe Form::Sales::Questions::OwningOrganisationId, type: :model do
context "when user is support" do
let(:user) { create(:user, :support, organisation: organisation_1) }
let(:log) { create(:lettings_log, assigned_to: user) }
let(:log) { build(:lettings_log, assigned_to: user) }
it "shows active orgs where organisation holds own stock" do
non_stock_organisation = create(:organisation, holds_own_stock: false)
@ -238,11 +226,7 @@ RSpec.describe Form::Sales::Questions::OwningOrganisationId, type: :model do
before do
merged_organisation.update!(merge_date: Time.zone.local(2023, 2, 2), absorbing_organisation: organisation_1)
organisation_1.update!(created_at: Time.zone.local(2021, 3, 2), available_from: Time.zone.local(2021, 2, 2))
Timecop.freeze(Time.zone.local(2023, 11, 10))
end
after do
Timecop.return
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 11, 10))
end
it "shows merged organisation as an option" do
@ -261,7 +245,7 @@ RSpec.describe Form::Sales::Questions::OwningOrganisationId, type: :model do
end
before do
Timecop.freeze(Time.zone.local(2023, 4, 2))
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 4, 2))
merged_organisation.update!(merge_date: Time.zone.local(2021, 6, 2), absorbing_organisation: user.organisation)
user.organisation.update!(created_at: Time.zone.local(2021, 2, 2))
end
@ -285,11 +269,7 @@ RSpec.describe Form::Sales::Questions::OwningOrganisationId, type: :model do
before do
merged_organisation.update!(merge_date: Time.zone.local(2023, 2, 2), absorbing_organisation: organisation_1)
organisation_1.update!(created_at: Time.zone.local(2021, 2, 2), available_from: nil)
Timecop.freeze(Time.zone.local(2023, 11, 10))
end
after do
Timecop.return
allow(Time).to receive(:now).and_return(Time.zone.local(2023, 11, 10))
end
it "does not show abailable from for absorbing organisation" do

50
spec/models/form/subsection_spec.rb

@ -4,27 +4,15 @@ require_relative "../../request_helper"
RSpec.describe Form::Subsection, type: :model do
subject(:subsection) { described_class.new(subsection_id, subsection_definition, section) }
around do |example|
Timecop.freeze(Time.zone.local(2022, 1, 1)) do
Singleton.__init__(FormHandler)
example.run
end
Timecop.return
Singleton.__init__(FormHandler)
end
let(:lettings_log) { FactoryBot.build(:lettings_log) }
let(:form) { lettings_log.form }
let(:section_id) { "household" }
let(:section_definition) { form.form_definition["sections"][section_id] }
let(:section) { Form::Section.new(section_id, section_definition, form) }
let(:form) { instance_double(Form, conditional_question_conditions: []) }
let(:section) { instance_double(Form::Section, form:) }
let(:subsection_id) { "household_characteristics" }
let(:subsection_definition) { section_definition["subsections"][subsection_id] }
let(:fake_2021_2022_form) { Form.new("spec/fixtures/forms/2021_2022.json") }
before do
RequestHelper.stub_http_requests
allow(FormHandler.instance).to receive(:current_lettings_form).and_return(fake_2021_2022_form)
let(:subsection_definition) do
{
"label" => "Household characteristics",
"pages" => [["tenant_code", { "questions" => { "tenancycode" => {} } }], ["person_1", { "questions" => { "age1" => {}, "sex1" => {} } }]],
}
end
it "has an id" do
@ -36,12 +24,12 @@ RSpec.describe Form::Subsection, type: :model do
end
it "has pages" do
expected_pages = %w[tenant_code_test person_1_age person_1_gender person_1_working_situation household_number_of_members retirement_value_check person_2_working_situation propcode]
expected_pages = %w[tenant_code person_1]
expect(subsection.pages.map(&:id)).to eq(expected_pages)
end
it "has questions" do
expected_questions = %w[tenancycode age1 sex1 ecstat1 hhmemb relat2 age2 sex2 retirement_value_check ecstat2 propcode]
expected_questions = %w[tenancycode age1 sex1]
expect(subsection.questions.map(&:id)).to eq(expected_questions)
end
@ -53,13 +41,7 @@ RSpec.describe Form::Subsection, type: :model do
end
it "has a completed status for completed subsection" do
subsection_definition = section_definition["subsections"]["household_needs"]
subsection = described_class.new("household_needs", subsection_definition, section)
lettings_log.armedforces = 3
lettings_log.illness = 1
lettings_log.housingneeds_a = 1
lettings_log.la = "E06000014"
lettings_log.illness_type_1 = 1
lettings_log.sex1 = "X"
expect(subsection.status(lettings_log)).to eq(:completed)
end
@ -69,22 +51,14 @@ RSpec.describe Form::Subsection, type: :model do
end
context "with optional fields" do
subject(:subsection) { described_class.new(subsection_id, subsection_definition, section) }
let(:section_id) { "tenancy_and_property" }
let(:section_definition) { form.form_definition["sections"][section_id] }
let(:section) { Form::Section.new(section_id, section_definition, form) }
let(:subsection_id) { "property_information" }
let(:subsection_definition) { section_definition["subsections"][subsection_id] }
it "has a started status even if only an optional field has been answered" do
lettings_log.postcode_known = 0
lettings_log.tenancycode = 3
expect(subsection.is_started?(lettings_log)).to be(true)
end
end
it "has question helpers for the number of applicable questions" do
expected_questions = %w[tenancycode age1 sex1 ecstat1 hhmemb relat2 age2 sex2 ecstat2 propcode]
expected_questions = %w[tenancycode age1 sex1]
expect(subsection.applicable_questions(lettings_log).map(&:id)).to eq(expected_questions)
end
end

2
spec/models/sales_log_spec.rb

@ -1025,6 +1025,8 @@ RSpec.describe SalesLog, type: :model do
describe "#search_by" do
it "allows searching using ID" do
sales_log_to_search.id += 30_000
sales_log_to_search.save!
result = described_class.search_by(sales_log_to_search.id.to_s)
expect(result.count).to eq(1)
expect(result.first.id).to eq sales_log_to_search.id

Loading…
Cancel
Save