Browse Source

CLDC-2072 changing startdate to another collection year clear invalid answers (#1469)

* write tests that invalid answers are cleared when the start date of a log is changed

* clear invalid answers when the start date of a log is changed

* correct error

* undo previous work to take new direction

* write tests to cover updated functionality of method in form to reset values when they are not routed to or when answers to radio questions are no longer valid

* update method in form to improve readability and to ensure that when the answers to radio questions are no longer valid, taht they are cleared

* add back an "end" deleted by mistake and fix a linting issue

* make some minor copy and variable name corrections

* fix a broken test after updates

* remove bulk upload tests for adding validations to unpermitted values to radio questions, these are now being cleared before validation

* fix some tests broken after rebasing

* add step to age questions in sales

* remove list of question ids from the form that should not be cleared, this information should be held on the questions themselves

* rename variables

* rename instance variable to be nice and long

* minor changes after rebase
pull/1563/head
Arthur Campbell 2 years ago committed by GitHub
parent
commit
6daa84b42e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 93
      app/models/form.rb
  2. 1
      app/models/form/lettings/questions/address_line1.rb
  3. 1
      app/models/form/lettings/questions/address_line2.rb
  4. 1
      app/models/form/lettings/questions/county.rb
  5. 1
      app/models/form/lettings/questions/la.rb
  6. 6
      app/models/form/lettings/questions/location_id.rb
  7. 1
      app/models/form/lettings/questions/postcode_for_full_address.rb
  8. 1
      app/models/form/lettings/questions/postcode_full.rb
  9. 1
      app/models/form/lettings/questions/postcode_known.rb
  10. 1
      app/models/form/lettings/questions/ppcodenk.rb
  11. 1
      app/models/form/lettings/questions/ppostcode_full.rb
  12. 1
      app/models/form/lettings/questions/previous_la_known.rb
  13. 1
      app/models/form/lettings/questions/prevloc.rb
  14. 1
      app/models/form/lettings/questions/town_or_city.rb
  15. 3
      app/models/form/question.rb
  16. 3
      app/models/form/sales/pages/extra_borrowing_value_check.rb
  17. 1
      app/models/form/sales/questions/address_line1.rb
  18. 1
      app/models/form/sales/questions/address_line2.rb
  19. 1
      app/models/form/sales/questions/age2.rb
  20. 1
      app/models/form/sales/questions/county.rb
  21. 1
      app/models/form/sales/questions/person_age.rb
  22. 1
      app/models/form/sales/questions/postcode.rb
  23. 1
      app/models/form/sales/questions/postcode_for_full_address.rb
  24. 1
      app/models/form/sales/questions/previous_la_known.rb
  25. 1
      app/models/form/sales/questions/previous_postcode.rb
  26. 1
      app/models/form/sales/questions/previous_postcode_known.rb
  27. 1
      app/models/form/sales/questions/prevloc.rb
  28. 1
      app/models/form/sales/questions/property_local_authority.rb
  29. 1
      app/models/form/sales/questions/town_or_city.rb
  30. 2
      app/models/log.rb
  31. 6
      app/views/form/_checkbox_question.html.erb
  32. 7
      config/forms/2021_2022.json
  33. 7
      config/forms/2022_2023.json
  34. 2
      config/locales/en.yml
  35. 6
      spec/factories/lettings_log.rb
  36. 24
      spec/factories/sales_log.rb
  37. 6
      spec/fixtures/forms/2021_2022.json
  38. 4
      spec/models/form/sales/questions/age2_spec.rb
  39. 4
      spec/models/form/sales/questions/person_age_spec.rb
  40. 2
      spec/models/form/sales/questions/uprn_confirmation_spec.rb
  41. 140
      spec/models/form_spec.rb
  42. 6
      spec/models/sales_log_spec.rb
  43. 18
      spec/services/bulk_upload/lettings/year2022/row_parser_spec.rb
  44. 16
      spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb

93
app/models/form.rb

@ -178,48 +178,78 @@ class Form
pages.reject { |p| p.routed_to?(log, current_user) }
end
def invalidated_questions(log)
invalidated_page_questions(log) + invalidated_conditional_questions(log)
end
def invalidated_page_questions(log, current_user = nil)
# we're already treating these fields as a special case and reset their values upon saving a log
callback_questions = %w[postcode_known la ppcodenk previous_la_known prevloc postcode_full ppostcode_full location_id address_line1 address_line2 town_or_city county]
questions.reject { |q| q.page.routed_to?(log, current_user) || q.derived? || callback_questions.include?(q.id) } || []
end
def reset_not_routed_questions_and_invalid_answers(log)
reset_checkbox_questions_if_not_routed(log)
def reset_not_routed_questions(log)
enabled_questions = enabled_page_questions(log)
enabled_question_ids = enabled_questions.map(&:id)
reset_radio_questions_if_not_routed_or_invalid_answers(log)
invalidated_page_questions(log).each do |question|
if %w[radio checkbox].include?(question.type)
enabled_answer_options = enabled_question_ids.include?(question.id) ? enabled_questions.find { |q| q.id == question.id }.answer_options : {}
current_answer_option_valid = enabled_answer_options.present? ? enabled_answer_options.key?(log.public_send(question.id).to_s) : false
reset_free_user_input_questions_if_not_routed(log)
end
if !current_answer_option_valid && log.respond_to?(question.id.to_s)
Rails.logger.debug("Cleared #{question.id} value")
log.public_send("#{question.id}=", nil)
def reset_checkbox_questions_if_not_routed(log)
checkbox_questions = routed_and_not_routed_questions_by_type(log, type: "checkbox")
checkbox_questions[:not_routed].each do |not_routed_question|
valid_options = checkbox_questions[:routed]
.select { |q| q.id == not_routed_question.id }
.flat_map { |q| q.answer_options.keys }
not_routed_question.answer_options.each_key do |invalid_option|
if !log.respond_to?(invalid_option) || valid_options.include?(invalid_option) || log.public_send(invalid_option).nil?
next
else
clear_attribute(log, invalid_option)
end
end
end
end
(question.answer_options.keys - enabled_answer_options.keys).map do |invalid_answer_option|
Rails.logger.debug("Cleared #{invalid_answer_option} value")
log.public_send("#{invalid_answer_option}=", nil) if log.respond_to?(invalid_answer_option)
def reset_radio_questions_if_not_routed_or_invalid_answers(log)
radio_questions = routed_and_not_routed_questions_by_type(log, type: "radio")
valid_radio_options = radio_questions[:routed]
.group_by(&:id)
.transform_values! { |q_array| q_array.flat_map { |q| q.answer_options.keys } }
radio_questions[:not_routed].each do |not_routed_question|
question_id = not_routed_question.id
if !log.respond_to?(question_id) || log.public_send(question_id).nil? || valid_radio_options.key?(question_id)
next
else
clear_attribute(log, question_id)
end
end
valid_radio_options.each do |question_id, valid_options|
if !log.respond_to?(question_id) || valid_options.include?(log.public_send(question_id).to_s)
next
else
Rails.logger.debug("Cleared #{question.id} value")
log.public_send("#{question.id}=", nil) unless enabled_question_ids.include?(question.id)
clear_attribute(log, question_id)
end
end
end
def enabled_page_questions(log)
questions - invalidated_page_questions(log)
def reset_free_user_input_questions_if_not_routed(log)
non_radio_checkbox_questions = routed_and_not_routed_questions_by_type(log)
enabled_question_ids = non_radio_checkbox_questions[:routed].map(&:id)
non_radio_checkbox_questions[:not_routed].each do |not_routed_question|
question_id = not_routed_question.id
if log.public_send(question_id).nil? || enabled_question_ids.include?(question_id)
next
else
clear_attribute(log, question_id)
end
end
end
def invalidated_conditional_questions(log)
questions.reject { |q| q.enabled?(log) } || []
def routed_and_not_routed_questions_by_type(log, type: nil, current_user: nil)
questions_by_type = if type
questions.reject { |q| q.type != type || q.disable_clearing_if_not_routed_or_dynamic_answer_options }
else
questions.reject { |q| %w[radio checkbox].include?(q.type) || q.disable_clearing_if_not_routed_or_dynamic_answer_options }
end
routed, not_routed = questions_by_type.partition { |q| q.page.routed_to?(log, current_user) || q.derived? }
{ routed:, not_routed: }
end
def clear_attribute(log, attribute)
Rails.logger.debug("Cleared #{attribute} value")
log.public_send("#{attribute}=", nil)
end
def readonly_questions
@ -230,6 +260,13 @@ class Form
questions.select { |q| q.type == "numeric" }
end
def previous_page(page_ids, page_index, log, current_user)
prev_page = get_page(page_ids[page_index - 1])
return prev_page.id if prev_page.routed_to?(log, current_user)
previous_page(page_ids, page_index - 1, log, current_user)
end
def send_chain(arr, log)
Array(arr).inject(log) { |o, a| o.public_send(*a) }
end

1
app/models/form/lettings/questions/address_line1.rb

@ -7,6 +7,7 @@ class Form::Lettings::Questions::AddressLine1 < ::Form::Question
@type = "text"
@plain_label = true
@check_answer_label = "Q12 - Address"
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
def answer_label(log, _current_user = nil)

1
app/models/form/lettings/questions/address_line2.rb

@ -5,6 +5,7 @@ class Form::Lettings::Questions::AddressLine2 < ::Form::Question
@header = "Address line 2 (optional)"
@type = "text"
@plain_label = true
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
def hidden_in_check_answers?(_log = nil, _current_user = nil)

1
app/models/form/lettings/questions/county.rb

@ -5,6 +5,7 @@ class Form::Lettings::Questions::County < ::Form::Question
@header = "County (optional)"
@type = "text"
@plain_label = true
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
def hidden_in_check_answers?(_log = nil, _current_user = nil)

1
app/models/form/lettings/questions/la.rb

@ -8,6 +8,7 @@ class Form::Lettings::Questions::La < ::Form::Question
@check_answers_card_number = 0
@hint_text = ""
@question_number = 13
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
def answer_options

6
app/models/form/lettings/questions/location_id.rb

@ -1,6 +1,7 @@
class Form::Lettings::Questions::LocationId < ::Form::Question
def initialize(_id, hsh, page)
super("location_id", hsh, page)
def initialize(id, hsh, page)
super
@id = "location_id"
@check_answer_label = "Location"
@header = header_text
@type = "radio"
@ -11,6 +12,7 @@ class Form::Lettings::Questions::LocationId < ::Form::Question
},
}
@question_number = 10
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
def answer_options

1
app/models/form/lettings/questions/postcode_for_full_address.rb

@ -17,6 +17,7 @@ class Form::Lettings::Questions::PostcodeForFullAddress < ::Form::Question
},
}
@plain_label = true
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
def hidden_in_check_answers?(_log = nil, _current_user = nil)

1
app/models/form/lettings/questions/postcode_full.rb

@ -10,5 +10,6 @@ class Form::Lettings::Questions::PostcodeFull < ::Form::Question
@check_answers_card_number = 0
@hint_text = ""
@inferred_answers = { "la" => { "is_la_inferred" => true } }
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
end

1
app/models/form/lettings/questions/postcode_known.rb

@ -8,6 +8,7 @@ class Form::Lettings::Questions::PostcodeKnown < ::Form::Question
@check_answers_card_number = 0
@hint_text = ""
@answer_options = ANSWER_OPTIONS
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
@conditional_for = { "postcode_full" => [1] }
@hidden_in_check_answers = { "depends_on" => [{ "postcode_known" => 0 }, { "postcode_known" => 1 }] }
end

1
app/models/form/lettings/questions/ppcodenk.rb

@ -11,6 +11,7 @@ class Form::Lettings::Questions::Ppcodenk < ::Form::Question
@conditional_for = { "ppostcode_full" => [1] }
@hidden_in_check_answers = { "depends_on" => [{ "ppcodenk" => 0 }, { "ppcodenk" => 1 }] }
@question_number = 80
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
ANSWER_OPTIONS = { "1" => { "value" => "Yes" }, "0" => { "value" => "No" } }.freeze

1
app/models/form/lettings/questions/ppostcode_full.rb

@ -11,5 +11,6 @@ class Form::Lettings::Questions::PpostcodeFull < ::Form::Question
@hint_text = ""
@inferred_answers = { "prevloc" => { "is_previous_la_inferred" => true } }
@question_number = 80
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
end

1
app/models/form/lettings/questions/previous_la_known.rb

@ -11,6 +11,7 @@ class Form::Lettings::Questions::PreviousLaKnown < ::Form::Question
@conditional_for = { "prevloc" => [1] }
@hidden_in_check_answers = { "depends_on" => [{ "previous_la_known" => 0 }, { "previous_la_known" => 1 }] }
@question_number = 81
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
ANSWER_OPTIONS = { "1" => { "value" => "Yes" }, "0" => { "value" => "No" } }.freeze

1
app/models/form/lettings/questions/prevloc.rb

@ -9,6 +9,7 @@ class Form::Lettings::Questions::Prevloc < ::Form::Question
@check_answers_card_number = 0
@hint_text = "Select ‘Northern Ireland’, ‘Scotland’, ‘Wales’ or ‘Outside the UK’ if the household’s last settled home was outside England."
@question_number = 81
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
def answer_options

1
app/models/form/lettings/questions/town_or_city.rb

@ -5,6 +5,7 @@ class Form::Lettings::Questions::TownOrCity < ::Form::Question
@header = "Town or city"
@type = "text"
@plain_label = true
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
def hidden_in_check_answers?(_log = nil, _current_user = nil)

3
app/models/form/question.rb

@ -1,5 +1,5 @@
class Form::Question
attr_accessor :id, :header, :hint_text, :description, :questions,
attr_accessor :id, :header, :hint_text, :description, :questions, :disable_clearing_if_not_routed_or_dynamic_answer_options,
:type, :min, :max, :step, :width, :fields_to_add, :result_field,
:conditional_for, :readonly, :answer_options, :page, :check_answer_label,
:inferred_answers, :hidden_in_check_answers, :inferred_check_answers_value,
@ -42,6 +42,7 @@ class Form::Question
@unresolved_hint_text = hsh["unresolved_hint_text"]
@question_number = hsh["question_number"]
@plain_label = hsh["plain_label"]
@disable_clearing_if_not_routed_or_dynamic_answer_options = hsh["disable_clearing_if_not_routed_or_dynamic_answer_options"]
end
end

3
app/models/form/sales/pages/extra_borrowing_value_check.rb

@ -9,8 +9,7 @@ class Form::Sales::Pages::ExtraBorrowingValueCheck < Form::Page
@title_text = {
"translation" => "soft_validations.extra_borrowing.title",
}
@informative_text = {
}
@informative_text = {}
end
def questions

1
app/models/form/sales/questions/address_line1.rb

@ -7,6 +7,7 @@ class Form::Sales::Questions::AddressLine1 < ::Form::Question
@type = "text"
@plain_label = true
@check_answer_label = "Q15 - Address"
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
def answer_label(log, _current_user = nil)

1
app/models/form/sales/questions/address_line2.rb

@ -5,6 +5,7 @@ class Form::Sales::Questions::AddressLine2 < ::Form::Question
@header = "Address line 2 (optional)"
@type = "text"
@plain_label = true
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
def hidden_in_check_answers?(_log = nil, _current_user = nil)

1
app/models/form/sales/questions/age2.rb

@ -13,6 +13,7 @@ class Form::Sales::Questions::Age2 < ::Form::Question
@check_answers_card_number = 2
@max = 110
@min = 0
@step = 1
@question_number = 28
end
end

1
app/models/form/sales/questions/county.rb

@ -5,6 +5,7 @@ class Form::Sales::Questions::County < ::Form::Question
@header = "County (optional)"
@type = "text"
@plain_label = true
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
def hidden_in_check_answers?(_log = nil, _current_user = nil)

1
app/models/form/sales/questions/person_age.rb

@ -12,6 +12,7 @@ class Form::Sales::Questions::PersonAge < ::Form::Question
@check_answers_card_number = person_index
@min = 0
@max = 110
@step = 1
@question_number = 29 + (4 * person_index)
end
end

1
app/models/form/sales/questions/postcode.rb

@ -17,5 +17,6 @@ class Form::Sales::Questions::Postcode < ::Form::Question
"is_la_inferred" => true,
},
}
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
end

1
app/models/form/sales/questions/postcode_for_full_address.rb

@ -17,6 +17,7 @@ class Form::Sales::Questions::PostcodeForFullAddress < ::Form::Question
},
}
@plain_label = true
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
def hidden_in_check_answers?(_log = nil, _current_user = nil)

1
app/models/form/sales/questions/previous_la_known.rb

@ -21,6 +21,7 @@ class Form::Sales::Questions::PreviousLaKnown < ::Form::Question
"prevloc" => [1],
}
@question_number = 58
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
ANSWER_OPTIONS = {

1
app/models/form/sales/questions/previous_postcode.rb

@ -18,5 +18,6 @@ class Form::Sales::Questions::PreviousPostcode < ::Form::Question
},
}
@question_number = 57
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
end

1
app/models/form/sales/questions/previous_postcode_known.rb

@ -21,6 +21,7 @@ class Form::Sales::Questions::PreviousPostcodeKnown < ::Form::Question
],
}
@question_number = 57
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
ANSWER_OPTIONS = {

1
app/models/form/sales/questions/prevloc.rb

@ -12,6 +12,7 @@ class Form::Sales::Questions::Prevloc < ::Form::Question
"value" => "Not known",
}]
@question_number = 58
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
def answer_options

1
app/models/form/sales/questions/property_local_authority.rb

@ -6,6 +6,7 @@ class Form::Sales::Questions::PropertyLocalAuthority < ::Form::Question
@header = "What is the property’s local authority?"
@type = "select"
@question_number = 16
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
def answer_options

1
app/models/form/sales/questions/town_or_city.rb

@ -5,6 +5,7 @@ class Form::Sales::Questions::TownOrCity < ::Form::Question
@header = "Town or city"
@type = "text"
@plain_label = true
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
def hidden_in_check_answers?(_log = nil, _current_user = nil)

2
app/models/log.rb

@ -174,7 +174,7 @@ private
def reset_invalidated_dependent_fields!
return unless form
form.reset_not_routed_questions(self)
form.reset_not_routed_questions_and_invalid_answers(self)
reset_created_by!
end

6
app/views/form/_checkbox_question.html.erb

@ -6,14 +6,14 @@
hint: { text: question.hint_text&.html_safe } do %>
<% after_divider = false %>
<% question.displayed_answer_options(@log).map do |key, options| %>
<% question.displayed_answer_options(@log).map do |key, option| %>
<% if key.starts_with?("divider") %>
<% after_divider = true %>
<%= f.govuk_check_box_divider %>
<% else %>
<%= f.govuk_check_box question.id, key,
label: { text: options["value"] },
hint: { text: options["hint"] },
label: { text: option["value"] },
hint: { text: option["hint"] },
checked: @log[key] == 1,
exclusive: after_divider,
**stimulus_html_attributes(question) %>

7
config/forms/2021_2022.json

@ -24,6 +24,7 @@
"header": "Do you know the property’s postcode?",
"hint_text": "",
"type": "radio",
"disable_clearing_if_not_routed_or_dynamic_answer_options": true,
"answer_options": {
"1": {
"value": "Yes"
@ -54,6 +55,7 @@
"hint_text": "",
"type": "text",
"width": 5,
"disable_clearing_if_not_routed_or_dynamic_answer_options": true,
"inferred_answers": {
"la": {
"is_la_inferred": true
@ -82,6 +84,7 @@
"header": "What is the local authority of the property?",
"hint_text": "",
"type": "select",
"disable_clearing_if_not_routed_or_dynamic_answer_options": true,
"answer_options": {
"": "Select an option",
"E07000223": "Adur",
@ -6482,6 +6485,7 @@
"header": "Do you know the postcode of the household’s last settled accommodation?",
"hint_text": "This is also known as the household’s ‘last settled home’.",
"type": "radio",
"disable_clearing_if_not_routed_or_dynamic_answer_options": true,
"answer_options": {
"1": {
"value": "Yes"
@ -6512,6 +6516,7 @@
"hint_text": "",
"type": "text",
"width": 5,
"disable_clearing_if_not_routed_or_dynamic_answer_options": true,
"inferred_answers": {
"prevloc": {
"is_previous_la_inferred": true
@ -6535,6 +6540,7 @@
"header": "Do you know the local authority of the household’s last settled accommodation?",
"hint_text": "This is also known as the household’s ‘last settled home’.",
"type": "radio",
"disable_clearing_if_not_routed_or_dynamic_answer_options": true,
"hidden_in_check_answers": {
"depends_on": [
{
@ -6564,6 +6570,7 @@
"header": "Select a local authority",
"hint_text": "Select ‘Northern Ireland’, ‘Scotland’, ‘Wales’ or ‘Outside the UK’ if the household’s last settled home was outside England.",
"type": "select",
"disable_clearing_if_not_routed_or_dynamic_answer_options": true,
"answer_options": {
"": "Select an option",
"S12000033": "Aberdeen City",

7
config/forms/2022_2023.json

@ -24,6 +24,7 @@
"header": "Do you know the property’s postcode?",
"hint_text": "",
"type": "radio",
"disable_clearing_if_not_routed_or_dynamic_answer_options": true,
"answer_options": {
"1": {
"value": "Yes"
@ -54,6 +55,7 @@
"hint_text": "",
"type": "text",
"width": 5,
"disable_clearing_if_not_routed_or_dynamic_answer_options": true,
"inferred_answers": {
"la": {
"is_la_inferred": true
@ -82,6 +84,7 @@
"header": "What is the local authority of the property?",
"hint_text": "",
"type": "select",
"disable_clearing_if_not_routed_or_dynamic_answer_options": true,
"answer_options": {
"": "Select an option",
"E07000223": "Adur",
@ -6435,6 +6438,7 @@
"header": "Do you know the postcode of the household’s last settled accommodation?",
"hint_text": "This is also known as the household’s ‘last settled home’.",
"type": "radio",
"disable_clearing_if_not_routed_or_dynamic_answer_options": true,
"answer_options": {
"1": {
"value": "Yes"
@ -6465,6 +6469,7 @@
"hint_text": "",
"type": "text",
"width": 5,
"disable_clearing_if_not_routed_or_dynamic_answer_options": true,
"inferred_answers": {
"prevloc": {
"is_previous_la_inferred": true
@ -6488,6 +6493,7 @@
"header": "Do you know the local authority of the household’s last settled accommodation?",
"hint_text": "This is also known as the household’s ‘last settled home’.",
"type": "radio",
"disable_clearing_if_not_routed_or_dynamic_answer_options": true,
"hidden_in_check_answers": {
"depends_on": [
{
@ -6517,6 +6523,7 @@
"header": "Select a local authority",
"hint_text": "Select ‘Northern Ireland’, ‘Scotland’, ‘Wales’ or ‘Outside the UK’ if the household’s last settled home was outside England.",
"type": "select",
"disable_clearing_if_not_routed_or_dynamic_answer_options": true,
"answer_options": {
"": "Select an option",
"S12000033": "Aberdeen City",

2
config/locales/en.yml

@ -365,7 +365,7 @@ en:
over_20: "The lead tenant must be under 20 as you told us their housing situation immediately before this letting was a children’s home or foster care"
ecstat:
retired_over_70: "Person %{person_num} must be retired if over 70"
child_under_16: "Person’s %{person_num} working situation must be ’child under 16‘ as you told us they’re under 16"
child_under_16: "Person %{person_num}’s working situation must be ‘child under 16’ as you told us they’re under 16"
child_over_16: "Answer cannot be ‘child under 16’ as you told us the person %{person_num} is older than 16"
not_student_16_19: "Person’s %{person_num} working situation must be full-time student or prefers not to say as you told us they’re between 16 and 19."
student_16_19:

6
spec/factories/lettings_log.rb

@ -158,6 +158,12 @@ FactoryBot.define do
sheltered { 0 }
household_charge { 0 }
end
trait :sheltered_housing do
needstype { 2 }
end
trait :startdate_today do
startdate { Time.zone.today }
end
created_at { Time.zone.today }
updated_at { Time.zone.today }
end

24
spec/factories/sales_log.rb

@ -10,6 +10,30 @@ FactoryBot.define do
type { 8 }
saledate { Time.utc(2023, 2, 2, 10, 36, 49) }
end
trait :shared_ownership do
ownershipsch { 1 }
type { 30 }
end
trait :privacy_notice_seen do
privacynotice { 1 }
end
trait :saledate_today do
saledate { Time.zone.today }
end
trait :shared_ownership_setup_complete do
saledate_today
ownershipsch { 1 }
type { 30 }
jointpur { 2 }
end
trait :outright_sale_setup_complete do
saledate_today
ownershipsch { 3 }
type { 10 }
companybuy { 2 }
buylivein { 1 }
jointpur { 2 }
end
trait :completed do
ownershipsch { 2 }
type { 8 }

6
spec/fixtures/forms/2021_2022.json vendored

@ -411,6 +411,7 @@
"hint_text": "Type ahead to filter the options",
"type": "select",
"check_answer_label": "Accessible Select",
"disable_clearing_if_not_routed_or_dynamic_answer_options": true,
"answer_options": {
"": "Select an option",
"E07000223": "Adur",
@ -473,6 +474,7 @@
"hint_text": "Type ahead to filter the options",
"type": "select",
"check_answer_label": "Accessible Select",
"disable_clearing_if_not_routed_or_dynamic_answer_options": true,
"answer_options": {
"": "Select an option",
"E07000223": "Adur",
@ -500,6 +502,7 @@
"header": "Do you know the property’s postcode?",
"hint_text": "",
"type": "radio",
"disable_clearing_if_not_routed_or_dynamic_answer_options": true,
"answer_options": {
"1": {
"value": "Yes"
@ -521,6 +524,7 @@
"hint_text": "",
"type": "text",
"width": 5,
"disable_clearing_if_not_routed_or_dynamic_answer_options": true,
"inferred_answers": {
"la": {
"is_la_inferred": true
@ -544,6 +548,7 @@
"header": "Do you know what local authority the property is located in?",
"hint_text": "",
"type": "radio",
"disable_clearing_if_not_routed_or_dynamic_answer_options": true,
"answer_options": {
"0": {
"value": "No"
@ -1151,6 +1156,7 @@
"header": "Postcode for the previous accommodation",
"hint_text": "If the household has moved from settled accommodation immediately prior to being re-housed",
"type": "text",
"disable_clearing_if_not_routed_or_dynamic_answer_options": true,
"width": 5
}
}

4
spec/models/form/sales/questions/age2_spec.rb

@ -59,4 +59,8 @@ RSpec.describe Form::Sales::Questions::Age2, type: :model do
it "has the correct max" do
expect(question.max).to eq(110)
end
it "has the correct step" do
expect(question.step).to be 1
end
end

4
spec/models/form/sales/questions/person_age_spec.rb

@ -40,6 +40,10 @@ RSpec.describe Form::Sales::Questions::PersonAge, type: :model do
expect(question.width).to eq(3)
end
it "has the correct step" do
expect(question.step).to be 1
end
context "with person 2" do
let(:person_index) { 2 }
let(:question_id) { "age2" }

2
spec/models/form/sales/questions/uprn_confirmation_spec.rb

@ -50,7 +50,7 @@ RSpec.describe Form::Sales::Questions::UprnConfirmation, type: :model do
context "when address is present" do
it "returns formatted value" do
log = create(:sales_log, address_line1: "1, Test Street", town_or_city: "Test Town", county: "Test County", postcode_full: "AA1 1AA", uprn: "1234", uprn_known: 1)
log = build(:sales_log, :outright_sale_setup_complete, address_line1: "1, Test Street", town_or_city: "Test Town", county: "Test County", postcode_full: "AA1 1AA", uprn: "1234", uprn_known: 1)
expect(question.notification_banner(log)).to eq(
{

140
spec/models/form_spec.rb

@ -204,32 +204,140 @@ RSpec.describe Form, type: :model do
end
end
describe "invalidated_page_questions" do
let(:lettings_log) { FactoryBot.create(:lettings_log, :in_progress, needstype: 1) }
let(:expected_invalid) { %w[scheme_id retirement_value_check condition_effects cbl conditional_question_no_second_question net_income_value_check dependent_question offered layear declaration] }
describe "#reset_not_routed_questions_and_invalid_answers" do
around do |example|
Singleton.__init__(FormHandler)
Timecop.freeze(now) do
FormHandler.instance.use_real_forms!
example.run
end
FormHandler.instance.use_fake_forms!
end
let(:now) { Time.zone.local(2023, 5, 5) }
context "when there are multiple radio questions for attribute X" do
context "and attribute Y is changed such that a different question for X is routed to" do
let(:log) { FactoryBot.create(:lettings_log, :setup_completed, :sheltered_housing, startdate: now, renewal: 0, prevten:) }
context "and the value of X remains valid" do
let(:prevten) { 36 }
it "the value of this attribute is not cleared" do
log.renewal = 1
log.form.reset_not_routed_questions_and_invalid_answers(log)
expect(log.prevten).to be 36
end
end
context "and the value of X is now invalid" do
let(:prevten) { 30 }
it "the value of this attribute is cleared" do
log.renewal = 1
log.form.reset_not_routed_questions_and_invalid_answers(log)
expect(log.prevten).to be nil
end
end
end
end
context "when there is one radio question for attribute X" do
context "and the start date or sale date is changed such that the collection year changes and there are different options" do
let(:log) { FactoryBot.create(:lettings_log, :setup_completed, :sheltered_housing, startdate: now, sheltered:) }
context "and the value of X remains valid" do
let(:sheltered) { 2 }
it "the value of this attribute is not cleared" do
log.update!(startdate: Time.zone.local(2023, 1, 1))
expect(log.sheltered).to be 2
end
end
context "and the value of X is now invalid" do
let(:sheltered) { 5 }
it "the value of this attribute is cleared" do
log.update!(startdate: Time.zone.local(2023, 1, 1))
expect(log.sheltered).to be nil
end
end
end
end
context "when there is one free user input question for an attribute X" do
let(:log) { FactoryBot.create(:sales_log, :shared_ownership_setup_complete, staircase: 1, stairbought: 25) }
context "and attribute Y is changed such that it is no longer routed to" do
it "the value of this attribute is cleared" do
expect(log.stairbought).to be 25
log.staircase = 2
log.form.reset_not_routed_questions_and_invalid_answers(log)
expect(log.stairbought).to be nil
end
end
end
context "when there are multiple free user input questions for attribute X" do
context "and attribute Y is changed such that a different question for X is routed to" do
let(:log) { FactoryBot.create(:sales_log, :saledate_today, :shared_ownership, :privacy_notice_seen, jointpur: 1, jointmore: 2, hholdcount: expected_hholdcount) }
let(:expected_hholdcount) { 2 }
context "when dependencies are not met" do
it "returns an array of question keys whose pages conditions are not met" do
expect(form.invalidated_page_questions(lettings_log).map(&:id).uniq).to eq(expected_invalid)
it "the value of this attribute is not cleared" do
log.jointpur = 2
log.form.reset_not_routed_questions_and_invalid_answers(log)
expect(log.hholdcount).to eq expected_hholdcount
end
end
context "with two pages having the same question and only one has dependencies met" do
it "returns an array of question keys whose pages conditions are not met" do
lettings_log["preg_occ"] = "No"
expect(form.invalidated_page_questions(lettings_log).map(&:id).uniq).to eq(expected_invalid)
context "and attribute Y is changed such that no questions for X are routed to" do
let(:log) { FactoryBot.create(:sales_log, :shared_ownership_setup_complete, value: initial_value) }
let(:initial_value) { 200_000.to_d }
it "the value of this attribute is cleared" do
expect(log.value).to eq initial_value
log.ownershipsch = 2
log.form.reset_not_routed_questions_and_invalid_answers(log)
expect(log.value).to be nil
end
end
end
context "when a question is marked as `derived` and `depends_on: false`" do
let(:lettings_log) { FactoryBot.build(:lettings_log, :in_progress, startdate: Time.utc(2022, 4, 2, 10, 36, 49)) }
context "when a value is changed such that a checkbox question is no longer routed to" do
let(:log) { FactoryBot.create(:lettings_log, :setup_completed, startdate: now, reasonpref: 1, rp_homeless: 1, rp_medwel: 1, rp_hardship: 1) }
it "does not count it's questions as invalidated" do
expect(form.enabled_page_questions(lettings_log).map(&:id).uniq).to include("tshortfall_known")
it "all attributes relating to that checkbox question are cleared" do
expect(log.rp_homeless).to be 1
log.reasonpref = 2
log.form.reset_not_routed_questions_and_invalid_answers(log)
expect(log.rp_homeless).to be nil
expect(log.rp_medwel).to be nil
expect(log.rp_hardship).to be nil
end
end
it "does not route to the page" do
expect(form.invalidated_pages(lettings_log).map(&:id)).to include("outstanding_amount_known")
context "when an attribute is derived, but no questions for that attribute are routed to" do
let(:log) { FactoryBot.create(:sales_log, :outright_sale_setup_complete, value: 200_000) }
it "the value of this attribute is not cleared" do
expect(log.deposit).to be nil
log.update!(mortgageused: 2)
expect(log.form.questions.any? { |q| q.id == "deposit" && q.page.routed_to?(log, nil) }).to be false
expect(log.deposit).not_to be nil
end
end
context "when an attribute is related to a callback question with no set answer options, and no questions for that attribute are routed to" do
let(:location) { FactoryBot.create(:location) }
let(:log) { FactoryBot.create(:lettings_log, :startdate_today) }
# Pages::PropertyPostcode and questions inside have been removed from form. do we not want to delete and migration delete_column?
it "the value of this attribute is not cleared" do
expect(log.form.questions.find { |q| q.id == "location_id" }.answer_options.keys).to be_empty
log.location_id = location.id
log.form.reset_not_routed_questions_and_invalid_answers(log)
expect(log.location_id).not_to be nil
end
end
end

6
spec/models/sales_log_spec.rb

@ -181,7 +181,7 @@ RSpec.describe SalesLog, type: :model do
let(:sales_log) { create(:sales_log, :completed) }
it "correctly derives and saves exday, exmonth and exyear" do
sales_log.update!(exdate: Time.gm(2022, 5, 4), saledate: Time.gm(2022, 7, 4), ownershipsch: 1, staircase: 2, resale: 2)
sales_log.update!(exdate: Time.gm(2022, 5, 4), saledate: Time.gm(2022, 7, 4), ownershipsch: 1, type: 18, staircase: 2, resale: 2, proplen: 0)
record_from_db = ActiveRecord::Base.connection.execute("select exday, exmonth, exyear from sales_logs where id=#{sales_log.id}").to_a[0]
expect(record_from_db["exday"]).to eq(4)
expect(record_from_db["exmonth"]).to eq(5)
@ -571,8 +571,8 @@ RSpec.describe SalesLog, type: :model do
end
end
context "when service errors" do
let(:sales_log) { create(:sales_log, uprn_known: 1, uprn: "123456789", uprn_confirmed: 1) }
context "when the API returns an error" do
let(:sales_log) { build(:sales_log, :outright_sale_setup_complete, uprn_known: 1, uprn: "123456789", uprn_confirmed: 1) }
let(:error_message) { "error" }
it "adds error to sales log" do

18
spec/services/bulk_upload/lettings/year2022/row_parser_spec.rb

@ -852,16 +852,6 @@ RSpec.describe BulkUpload::Lettings::Year2022::RowParser do
end
end
describe "#field_134" do
context "when an unpermitted value" do
let(:attributes) { { bulk_upload:, field_134: "3" } }
it "has errors on the field" do
expect(parser.errors[:field_134]).to be_present
end
end
end
describe "#field_103" do
context "when null" do
let(:attributes) { setup_section_params.merge({ field_103: nil }) }
@ -874,14 +864,6 @@ RSpec.describe BulkUpload::Lettings::Year2022::RowParser do
expect(parser.errors[:field_103]).to eql(["You must answer type of building"])
end
end
context "when unpermitted values" do
let(:attributes) { setup_section_params.merge({ field_103: "4" }) }
it "returns an error" do
expect(parser.errors[:field_103]).to be_present
end
end
end
end

16
spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb

@ -793,14 +793,6 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
end
describe "#field_6" do # renewal
context "when an unpermitted value" do
let(:attributes) { { bulk_upload:, field_6: "3" } }
it "has errors on the field" do
expect(parser.errors[:field_6]).to be_present
end
end
context "when blank" do
let(:attributes) { { bulk_upload:, field_1: owning_org.old_visible_id, field_6: "" } }
@ -842,14 +834,6 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
expect(parser.errors[:field_30]).to eql(["You must answer type of building"])
end
end
context "when unpermitted values" do
let(:attributes) { setup_section_params.merge({ field_30: "4" }) }
it "returns an error" do
expect(parser.errors[:field_30]).to be_present
end
end
end
describe "#field_52" do # age2

Loading…
Cancel
Save