From 43f60b511949d510bc13eb454e9fc7dc84fae66f Mon Sep 17 00:00:00 2001 From: Dushan <47317567+dushan-madetech@users.noreply.github.com> Date: Wed, 2 Feb 2022 11:31:51 +0000 Subject: [PATCH] CLDC-731 bypass tasklist from check answers (#252) * add button for moving to next incomplete section * Add extra logic for cycling sections * fix all failures * add test for in progress case log to declaration redirection * fix bug with infinite recursion * update button text to save and return to log * use govuk_link helpers * lint fixes * some basic extract method refactors * refactor tests * lint fixes * redirect to check answers if next subsection in progress * fix failing spec --- app/models/form.rb | 47 ++++++++ app/views/form/check_answers.html.erb | 8 +- spec/factories/case_log.rb | 1 + spec/features/form/check_answers_page_spec.rb | 103 ++++++++++++++++++ spec/models/form_spec.rb | 97 +++++++++++++++++ 5 files changed, 255 insertions(+), 1 deletion(-) diff --git a/app/models/form.rb b/app/models/form.rb index 647ddf59e..f14adc9f8 100644 --- a/app/models/form.rb +++ b/app/models/form.rb @@ -47,6 +47,53 @@ class Form end end + def next_incomplete_section_redirect_path(subsection, case_log) + subsection_ids = subsections.map(&:id) + + if case_log.status == "completed" || all_subsections_except_declaration_completed?(case_log) + return first_question_in_last_subsection(subsection_ids) + end + + next_subsection = next_subsection(subsection, case_log, subsection_ids) + + case next_subsection.status(case_log) + when :completed + next_incomplete_section_redirect_path(next_subsection, case_log) + when :in_progress + "#{next_subsection.id}/check_answers".dasherize + when :not_started + first_question_in_subsection = next_subsection.pages.first.id + first_question_in_subsection.to_s.dasherize + else + "error" + end + end + + def first_question_in_last_subsection(subsection_ids) + next_subsection = get_subsection(subsection_ids[subsection_ids.length - 1]) + first_question_in_subsection = next_subsection.pages.first.id + first_question_in_subsection.to_s.dasherize + end + + def next_subsection(subsection, case_log, subsection_ids) + next_subsection_id_index = subsection_ids.index(subsection.id) + 1 + next_subsection = get_subsection(subsection_ids[next_subsection_id_index]) + + if next_subsection.id == "declaration" && case_log.status != "completed" + next_subsection = get_subsection(subsection_ids[0]) + end + + next_subsection + end + + def all_subsections_except_declaration_completed?(case_log) + subsection_ids = subsections.map(&:id) + subsection_ids.delete_at(subsection_ids.length - 1) + return true if subsection_ids.all? { |subsection_id| get_subsection(subsection_id).status(case_log) == :completed } + + false + end + def conditional_question_conditions conditions = questions.map { |q| Hash(q.id => q.conditional_for) if q.conditional_for.present? }.compact conditions.map { |c| diff --git a/app/views/form/check_answers.html.erb b/app/views/form/check_answers.html.erb index 42dd44c1b..4be257a6f 100644 --- a/app/views/form/check_answers.html.erb +++ b/app/views/form/check_answers.html.erb @@ -22,7 +22,13 @@ <%= form_with model: @case_log, method: "get" do |f| %> - <%= f.govuk_submit "Save and continue" %> + <%= f.govuk_submit 'Save and return to log' do %> + <% if @case_log.status == "in_progress" && @case_log.status == "completed" || @case_log.form.all_subsections_except_declaration_completed?(@case_log) == false %> + <%= govuk_button_link_to 'Save and go to next incomplete section', "/logs/#{@case_log.id}/#{@case_log.form.next_incomplete_section_redirect_path(subsection, @case_log)}", secondary: true %> + <% elsif @case_log.status == "completed" || @case_log.form.all_subsections_except_declaration_completed?(@case_log) %> + <%= govuk_button_link_to 'Save and go to submit', "/logs/#{@case_log.id}/#{@case_log.form.next_incomplete_section_redirect_path(subsection, @case_log)}", secondary: true %> + <% end%> + <% end %> <% end %> diff --git a/spec/factories/case_log.rb b/spec/factories/case_log.rb index 494febdfb..0a73e7750 100644 --- a/spec/factories/case_log.rb +++ b/spec/factories/case_log.rb @@ -151,6 +151,7 @@ FactoryBot.define do is_carehome { "No" } chcharge { 7 } letting_in_sheltered_accomodation { "No" } + la_known { "Yes" } end created_at { Time.zone.now } updated_at { Time.zone.now } diff --git a/spec/features/form/check_answers_page_spec.rb b/spec/features/form/check_answers_page_spec.rb index a0f6d8e74..cde579bf4 100644 --- a/spec/features/form/check_answers_page_spec.rb +++ b/spec/features/form/check_answers_page_spec.rb @@ -22,6 +22,14 @@ RSpec.describe "Form Check Answers Page" do managing_organisation: user.organisation, ) end + let(:completed_case_log) do + FactoryBot.create( + :case_log, + :completed, + owning_organisation: user.organisation, + managing_organisation: user.organisation, + ) + end let(:id) { case_log.id } before do @@ -117,5 +125,100 @@ RSpec.describe "Form Check Answers Page" do expect(page).not_to have_content(label) end end + + context "when the user wants to bypass the tasklist page from check answers" do + let(:section_completed_case_log) do + FactoryBot.create( + :case_log, + :in_progress, + owning_organisation: user.organisation, + managing_organisation: user.organisation, + tenant_code: "123", + age1: 35, + sex1: "Male", + other_hhmemb: 0, + ) + end + + let(:next_section_in_progress_case_log) do + FactoryBot.create( + :case_log, + :in_progress, + owning_organisation: user.organisation, + managing_organisation: user.organisation, + tenant_code: "123", + age1: 35, + sex1: "Male", + other_hhmemb: 0, + armedforces: "No", + illness: "No", + ) + end + + let(:skip_section_case_log) do + FactoryBot.create( + :case_log, + :in_progress, + owning_organisation: user.organisation, + managing_organisation: user.organisation, + tenant_code: "123", + age1: 35, + sex1: "Male", + other_hhmemb: 0, + armedforces: "No", + illness: "No", + housingneeds_h: "Yes", + la: "York", + illness_type_1: "Yes", + ) + end + + let(:cycle_sections_case_log) do + FactoryBot.create( + :case_log, + :in_progress, + owning_organisation: user.organisation, + managing_organisation: user.organisation, + tenant_code: nil, + age1: nil, + layear: "1 to 2 years", + lawaitlist: "Less than 1 year", + property_postcode: "NW1 5TY", + reason: "Permanently decanted from another property owned by this landlord", + previous_postcode: "SE2 6RT", + mrcdate: Time.zone.parse("03/11/2019"), + ) + end + + it "they can click a button to move onto the first page of the next (not started) incomplete section" do + visit("/logs/#{section_completed_case_log.id}/household-characteristics/check-answers") + click_link("Save and go to next incomplete section") + expect(page).to have_current_path("/logs/#{section_completed_case_log.id}/armed-forces") + end + + it "they can click a button to move onto the check answers page of the next (in progress) incomplete section" do + visit("/logs/#{next_section_in_progress_case_log.id}/household-characteristics/check-answers") + click_link("Save and go to next incomplete section") + expect(page).to have_current_path("/logs/#{next_section_in_progress_case_log.id}/household-needs/check-answers") + end + + it "they can click a button to skip sections until the next incomplete section" do + visit("/logs/#{skip_section_case_log.id}/household-characteristics/check-answers") + click_link("Save and go to next incomplete section") + expect(page).to have_current_path("/logs/#{skip_section_case_log.id}/tenancy-code") + end + + it "they can click a button to cycle around to the next incomplete section" do + visit("/logs/#{cycle_sections_case_log.id}/local-authority/check-answers") + click_link("Save and go to next incomplete section") + expect(page).to have_current_path("/logs/#{cycle_sections_case_log.id}/tenant-code") + end + + it "they can click a button to move to the submission section when all sections have been completed", js: true do + visit("/logs/#{completed_case_log.id}/local-authority/check-answers") + click_link("Save and go to submit") + expect(page).to have_current_path("/logs/#{completed_case_log.id}/declaration") + end + end end end diff --git a/spec/models/form_spec.rb b/spec/models/form_spec.rb index 7b376812e..67269e78e 100644 --- a/spec/models/form_spec.rb +++ b/spec/models/form_spec.rb @@ -33,6 +33,103 @@ RSpec.describe Form, type: :model do end end + describe "next_incomplete_section_redirect_path" do + let(:case_log) { FactoryBot.build(:case_log, :in_progress) } + let(:subsection) { form.get_subsection("household_characteristics") } + let(:later_subsection) { form.get_subsection("local_authority") } + + context "when a user is on the check answers page for a subsection" do + def answer_household_needs(case_log) + case_log.armedforces = "No" + case_log.illness = "No" + case_log.housingneeds_a = "Yes" + case_log.la = "York" + case_log.illness_type_1 = "Yes" + end + + def answer_tenancy_information(case_log) + case_log.tenancy_code = "1234" + end + + def answer_property_information(case_log) + case_log.wchair = "No" + end + + def answer_conditional_question(case_log) + case_log.preg_occ = "No" + case_log.cbl = "No" + end + + def answer_income_and_benefits(case_log) + case_log.earnings = 30_000 + case_log.incfreq = "Yearly" + case_log.benefits = "Some" + case_log.hb = "Tenant prefers not to say" + end + + def answer_rent_and_charges(case_log) + case_log.period = "Every 2 weeks" + case_log.brent = 650 + case_log.scharge = 0 + case_log.pscharge = 0 + case_log.supcharg = 0 + case_log.tcharge = 650 + end + + def answer_local_authority(case_log) + case_log.layear = "1 to 2 years" + case_log.lawaitlist = "Less than 1 year" + case_log.property_postcode = "NW1 5TY" + case_log.reason = "Permanently decanted from another property owned by this landlord" + case_log.previous_postcode = "SE2 6RT" + case_log.mrcdate = Time.zone.parse("03/11/2019") + end + + before do + case_log.tenant_code = "123" + case_log.age1 = 35 + case_log.sex1 = "Male" + case_log.other_hhmemb = 0 + end + + it "returns the first page of the next incomplete subsection if the subsection is not in progress" do + expect(form.next_incomplete_section_redirect_path(subsection, case_log)).to eq("armed-forces") + end + + it "returns the check answers page of the next incomplete subsection if the subsection is already in progress" do + case_log.armedforces = "No" + case_log.illness = "No" + expect(form.next_incomplete_section_redirect_path(subsection, case_log)).to eq("household-needs/check-answers") + end + + it "returns the first page of the next incomplete subsection (skipping completed subsections)" do + answer_household_needs(case_log) + expect(form.next_incomplete_section_redirect_path(subsection, case_log)).to eq("tenancy-code") + end + + it "returns the next incomplete section by cycling back around if next subsections are completed" do + answer_local_authority(case_log) + expect(form.next_incomplete_section_redirect_path(later_subsection, case_log)).to eq("armed-forces") + end + + it "returns the declaration section for a completed case log" do + expect(form.next_incomplete_section_redirect_path(subsection, completed_case_log)).to eq("declaration") + end + + it "returns the declaration section if all sections are complete but the case log is in progress" do + answer_household_needs(case_log) + answer_tenancy_information(case_log) + answer_property_information(case_log) + answer_conditional_question(case_log) + answer_income_and_benefits(case_log) + answer_rent_and_charges(case_log) + answer_local_authority(case_log) + + expect(form.next_incomplete_section_redirect_path(subsection, case_log)).to eq("declaration") + end + end + end + describe "invalidated_page_questions" do context "when dependencies are not met" do let(:expected_invalid) { %w[la_known cbl conditional_question_no_second_question dependent_question declaration] }