From eb72bc6ffd8b954e283f8f4ab7aa6839f0b4ef71 Mon Sep 17 00:00:00 2001 From: baarkerlounger <5101747+baarkerlounger@users.noreply.github.com> Date: Thu, 16 Jun 2022 10:21:01 +0100 Subject: [PATCH] Refactor log setup into it's own form (#663) * Refactor log setup into it's own form * Use factory * Run workflow on push to PR * Array matcher on heisenspec --- app/models/form.rb | 17 ++- app/models/form_handler.rb | 8 +- config/forms/2021_2022.json | 132 ----------------- config/forms/2022_2023.json | 132 ----------------- config/forms/setup/log_setup.json | 138 ++++++++++++++++++ spec/factories/case_log.rb | 3 + spec/features/form/tasklist_page_spec.rb | 18 ++- spec/fixtures/forms/2022_2023.json | 76 ---------- spec/fixtures/forms/setup/log_setup.json | 71 +++++++++ spec/helpers/tasklist_helper_spec.rb | 4 +- spec/models/form_handler_spec.rb | 4 +- spec/models/organisation_spec.rb | 2 +- spec/models/rent_period_spec.rb | 3 +- spec/requests/case_logs_controller_spec.rb | 7 +- .../case_logs_field_import_service_spec.rb | 3 +- .../imports/case_logs_import_service_spec.rb | 5 +- 16 files changed, 259 insertions(+), 364 deletions(-) create mode 100644 config/forms/setup/log_setup.json create mode 100644 spec/fixtures/forms/setup/log_setup.json diff --git a/app/models/form.rb b/app/models/form.rb index 7f48d7d4c..8c82b401c 100644 --- a/app/models/form.rb +++ b/app/models/form.rb @@ -1,19 +1,24 @@ class Form attr_reader :form_definition, :sections, :subsections, :pages, :questions, - :start_date, :end_date, :type, :name + :start_date, :end_date, :type, :name, :setup_definition, + :setup_sections, :form_sections - def initialize(form_path, name) + def initialize(form_path, name, setup_path) + raise "No setup definition file exists for given path".freeze unless File.exist?(setup_path) raise "No form definition file exists for given year".freeze unless File.exist?(form_path) - @form_definition = JSON.parse(File.open(form_path).read) @name = name - @start_date = Time.iso8601(form_definition["start_date"]) - @end_date = Time.iso8601(form_definition["end_date"]) + @setup_definition = JSON.parse(File.open(setup_path).read) + @setup_sections = setup_definition["sections"].map { |id, s| Form::Section.new(id, s, self) } || [] + @form_definition = JSON.parse(File.open(form_path).read) + @form_sections = form_definition["sections"].map { |id, s| Form::Section.new(id, s, self) } @type = form_definition["form_type"] - @sections = form_definition["sections"].map { |id, s| Form::Section.new(id, s, self) } + @sections = setup_sections + form_sections @subsections = sections.flat_map(&:subsections) @pages = subsections.flat_map(&:pages) @questions = pages.flat_map(&:questions) + @start_date = Time.iso8601(form_definition["start_date"]) + @end_date = Time.iso8601(form_definition["end_date"]) end def get_subsection(id) diff --git a/app/models/form_handler.rb b/app/models/form_handler.rb index 13efcb9ca..5ae3c9059 100644 --- a/app/models/form_handler.rb +++ b/app/models/form_handler.rb @@ -21,12 +21,18 @@ private directories.each do |directory| Dir.glob("#{directory}/*.json").each do |form_path| form_name = File.basename(form_path, ".json") - forms[form_name] = Form.new(form_path, form_name) + forms[form_name] = Form.new(form_path, form_name, setup_path) end end forms end + def setup_path + return "spec/fixtures/forms/setup/log_setup.json" if Rails.env.test? + + "config/forms/setup/log_setup.json" + end + def directories Rails.env.test? ? ["spec/fixtures/forms"] : ["config/forms"] end diff --git a/config/forms/2021_2022.json b/config/forms/2021_2022.json index 8b4a8f983..46ed45a4b 100644 --- a/config/forms/2021_2022.json +++ b/config/forms/2021_2022.json @@ -3,138 +3,6 @@ "start_date": "2021-04-01T00:00:00.000+01:00", "end_date": "2022-07-01T00:00:00.000+01:00", "sections": { - "setup": { - "label": "Before you start", - "subsections": { - "setup": { - "label": "Set up this lettings log", - "pages": { - "needs_type": { - "header": "", - "description": "", - "questions": { - "needstype": { - "check_answer_label": "Needs type", - "header": "What is the needs type?", - "hint_text": "General needs housing includes both self-contained and shared housing without support or specific adaptations. Supported housing can include direct access hostels, group homes, residential care and nursing homes.", - "type": "radio", - "answer_options": { - "1": { - "value": "General needs" - }, - "2": { - "value": "Supported housing" - } - } - } - }, - "depends_on": [ - { - "supported_housing_schemes_enabled?" : true - } - ] - }, - "renewal": { - "header": "", - "description": "", - "questions": { - "renewal": { - "check_answer_label": "Property renewal", - "header": "Is this letting a renewal?", - "hint_text": "A renewal is a letting to the same tenant in the same property.", - "type": "radio", - "answer_options": { - "1": { - "value": "Yes" - }, - "0": { - "value": "No" - } - } - } - } - }, - "tenancy_start_date": { - "header": "", - "description": "", - "questions": { - "startdate": { - "check_answer_label": "Tenancy start date", - "header": "What is the tenancy start date?", - "type": "date" - } - } - }, - "rent_type": { - "header": "", - "description": "", - "questions": { - "rent_type": { - "check_answer_label": "Rent type", - "header": "What is the rent type?", - "hint_text": "", - "type": "radio", - "answer_options": { - "1": { - "value": "Affordable Rent" - }, - "2": { - "value": "London Affordable Rent" - }, - "4": { - "value": "London Living Rent" - }, - "3": { - "value": "Rent to Buy" - }, - "0": { - "value": "Social Rent" - }, - "5": { - "value": "Other intermediate rent product" - } - }, - "conditional_for": { - "irproduct_other": [5] - } - }, - "irproduct_other": { - "check_answer_label": "Product name", - "header": "Name of rent product", - "type": "text" - } - } - }, - "tenant_code": { - "header": "", - "description": "", - "questions": { - "tenant_code": { - "check_answer_label": "Tenant code", - "header": "What is the tenant code?", - "hint_text": "This is how you usually refer to this tenancy on your own systems.", - "type": "text", - "width": 10 - } - } - }, - "property_reference": { - "header": "", - "description": "", - "questions": { - "propcode": { - "check_answer_label": "Property reference", - "header": "What is the property reference?", - "hint_text": "This is how you usually refer to this property on your own systems.", - "type": "text", - "width": 10 - } - } - } - } - } - } - }, "tenancy_and_property": { "label": "Property and tenancy information", "subsections": { diff --git a/config/forms/2022_2023.json b/config/forms/2022_2023.json index 3edb542c4..319a2ea05 100644 --- a/config/forms/2022_2023.json +++ b/config/forms/2022_2023.json @@ -3,138 +3,6 @@ "start_date": "2022-04-01T00:00:00.000+01:00", "end_date": "2023-07-01T00:00:00.000+01:00", "sections": { - "setup": { - "label": "Before you start", - "subsections": { - "setup": { - "label": "Set up this lettings log", - "pages": { - "needs_type": { - "header": "", - "description": "", - "questions": { - "needstype": { - "check_answer_label": "Needs type", - "header": "What is the needs type?", - "hint_text": "General needs housing includes both self-contained and shared housing without support or specific adaptations. Supported housing can include direct access hostels, group homes, residential care and nursing homes.", - "type": "radio", - "answer_options": { - "1": { - "value": "General needs" - }, - "2": { - "value": "Supported housing" - } - } - } - }, - "depends_on": [ - { - "supported_housing_schemes_enabled?" : true - } - ] - }, - "renewal": { - "header": "", - "description": "", - "questions": { - "renewal": { - "check_answer_label": "Property renewal", - "header": "Is this letting a renewal?", - "hint_text": "A renewal is a letting to the same tenant in the same property.", - "type": "radio", - "answer_options": { - "1": { - "value": "Yes" - }, - "0": { - "value": "No" - } - } - } - } - }, - "tenancy_start_date": { - "header": "", - "description": "", - "questions": { - "startdate": { - "check_answer_label": "Tenancy start date", - "header": "What is the tenancy start date?", - "type": "date" - } - } - }, - "rent_type": { - "header": "", - "description": "", - "questions": { - "rent_type": { - "check_answer_label": "Rent type", - "header": "What is the rent type?", - "hint_text": "", - "type": "radio", - "answer_options": { - "1": { - "value": "Affordable Rent" - }, - "2": { - "value": "London Affordable Rent" - }, - "4": { - "value": "London Living Rent" - }, - "3": { - "value": "Rent to Buy" - }, - "0": { - "value": "Social Rent" - }, - "5": { - "value": "Other intermediate rent product" - } - }, - "conditional_for": { - "irproduct_other": [5] - } - }, - "irproduct_other": { - "check_answer_label": "Product name", - "header": "Name of rent product", - "type": "text" - } - } - }, - "tenant_code": { - "header": "", - "description": "", - "questions": { - "tenant_code": { - "check_answer_label": "Tenant code", - "header": "What is the tenant code?", - "hint_text": "This is how you usually refer to this tenancy on your own systems.", - "type": "text", - "width": 10 - } - } - }, - "property_reference": { - "header": "", - "description": "", - "questions": { - "propcode": { - "check_answer_label": "Property reference", - "header": "What is the property reference?", - "hint_text": "This is how you usually refer to this property on your own systems.", - "type": "text", - "width": 10 - } - } - } - } - } - } - }, "tenancy_and_property": { "label": "Property and tenancy information", "subsections": { diff --git a/config/forms/setup/log_setup.json b/config/forms/setup/log_setup.json new file mode 100644 index 000000000..a760f9bd6 --- /dev/null +++ b/config/forms/setup/log_setup.json @@ -0,0 +1,138 @@ +{ + "form_type": "setup", + "sections": { + "setup": { + "label": "Before you start", + "subsections": { + "setup": { + "label": "Set up this lettings log", + "pages": { + "needs_type": { + "header": "", + "description": "", + "questions": { + "needstype": { + "check_answer_label": "Needs type", + "header": "What is the needs type?", + "hint_text": "", + "type": "radio", + "answer_options": { + "1": { + "value": "General needs" + }, + "2": { + "value": "Supported housing" + } + } + } + }, + "derived": true, + "depends_on": [ + { + "supported_housing_schemes_enabled?" : true + } + ] + }, + "renewal": { + "header": "", + "description": "", + "questions": { + "renewal": { + "check_answer_label": "Property renewal", + "header": "Is this letting a renewal?", + "hint_text": "A renewal is a letting to the same tenant in the same property.", + "type": "radio", + "answer_options": { + "1": { + "value": "Yes" + }, + "0": { + "value": "No" + } + } + } + } + }, + "tenancy_start_date": { + "header": "", + "description": "", + "questions": { + "startdate": { + "check_answer_label": "Tenancy start date", + "header": "What is the tenancy start date?", + "type": "date" + } + } + }, + "rent_type": { + "header": "", + "description": "", + "questions": { + "rent_type": { + "check_answer_label": "Rent type", + "header": "What is the rent type?", + "hint_text": "", + "type": "radio", + "answer_options": { + "1": { + "value": "Affordable Rent" + }, + "2": { + "value": "London Affordable Rent" + }, + "4": { + "value": "London Living Rent" + }, + "3": { + "value": "Rent to Buy" + }, + "0": { + "value": "Social Rent" + }, + "5": { + "value": "Other intermediate rent product" + } + }, + "conditional_for": { + "irproduct_other": [5] + } + }, + "irproduct_other": { + "check_answer_label": "Product name", + "header": "Name of rent product", + "type": "text" + } + } + }, + "tenant_code": { + "header": "", + "description": "", + "questions": { + "tenant_code": { + "check_answer_label": "Tenant code", + "header": "What is the tenant code?", + "hint_text": "This is how you usually refer to this tenancy on your own systems.", + "type": "text", + "width": 10 + } + } + }, + "property_reference": { + "header": "", + "description": "", + "questions": { + "propcode": { + "check_answer_label": "Property reference", + "header": "What is the property reference?", + "hint_text": "This is how you usually refer to this property on your own systems.", + "type": "text", + "width": 10 + } + } + } + } + } + } + } + } +} diff --git a/spec/factories/case_log.rb b/spec/factories/case_log.rb index 6a315a068..8cb63643a 100644 --- a/spec/factories/case_log.rb +++ b/spec/factories/case_log.rb @@ -16,6 +16,9 @@ FactoryBot.define do ppostcode_full { Faker::Address.postcode } age1 { 17 } age2 { 19 } + renewal { 1 } + rent_type { 1 } + startdate { Time.zone.local(2021, 5, 1) } end trait :soft_validations_triggered do status { 1 } diff --git a/spec/features/form/tasklist_page_spec.rb b/spec/features/form/tasklist_page_spec.rb index 70d770371..3c0da44b0 100644 --- a/spec/features/form/tasklist_page_spec.rb +++ b/spec/features/form/tasklist_page_spec.rb @@ -27,6 +27,15 @@ RSpec.describe "Task List" do managing_organisation: user.organisation, ) end + let(:setup_completed_log) do + FactoryBot.create( + :case_log, + :about_completed, + owning_organisation: user.organisation, + managing_organisation: user.organisation, + startdate: Time.zone.local(2021, 5, 1), + ) + end let(:id) { case_log.id } let(:status) { case_log.status } @@ -40,14 +49,13 @@ RSpec.describe "Task List" do end it "shows number of completed sections if one section is completed" do - answer_all_questions_in_income_subsection(empty_case_log) - visit("/logs/#{empty_case_log.id}") - expect(page).to have_content("1 of 9 sections completed.") + visit("/logs/#{setup_completed_log.id}") + expect(page).to have_content("1 of 10 sections completed.") end it "show skip link for next incomplete section" do - answer_all_questions_in_income_subsection(empty_case_log) - visit("/logs/#{empty_case_log.id}") + answer_all_questions_in_income_subsection(setup_completed_log) + visit("/logs/#{setup_completed_log.id}") expect(page).to have_link("Skip to next incomplete section", href: /#household-characteristics/) end diff --git a/spec/fixtures/forms/2022_2023.json b/spec/fixtures/forms/2022_2023.json index 62208736e..bde22b8b7 100644 --- a/spec/fixtures/forms/2022_2023.json +++ b/spec/fixtures/forms/2022_2023.json @@ -3,82 +3,6 @@ "start_date": "2022-04-01T00:00:00.000+01:00", "end_date": "2023-07-01T00:00:00.000+01:00", "sections": { - "setup": { - "label": "Before you start", - "subsections": { - "setup": { - "label": "Set up this lettings log", - "pages": { - "renewal": { - "header": "", - "description": "", - "questions": { - "renewal": { - "check_answer_label": "Property renewal", - "header": "Is this a renewal to the same tenant in the same property?", - "hint_text": "", - "type": "radio", - "answer_options": { - "1": "Yes", - "0": "No" - } - } - } - }, - "startdate": { - "header": "", - "description": "", - "questions": { - "startdate": { - "check_answer_label": "Tenancy start date", - "header": "What is the tenancy start date?", - "hint_text": "For example, 27 3 2007", - "type": "date" - } - } - }, - "about_this_letting": { - "header": "Tell us about this letting", - "description": "", - "questions": { - "rent_type": { - "check_answer_label": "Rent type", - "header": "What is the rent type?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Social rent", - "1": "Affordable rent", - "2": "London Affordable rent", - "3": "Rent to buy", - "4": "London living rent", - "5": "Other intermediate rent product" - }, - "conditional_for": { - "intermediate_rent_product_name": [5] - } - }, - "intermediate_rent_product_name": { - "check_answer_label": "Product name", - "header": "What is intermediate rent product name?", - "type": "text" - }, - "needstype": { - "check_answer_label": "Needs type", - "header": "What is the needs type?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Supported housing", - "1": "General needs" - } - } - } - } - } - } - } - }, "household": { "label": "About the household", "subsections": { diff --git a/spec/fixtures/forms/setup/log_setup.json b/spec/fixtures/forms/setup/log_setup.json new file mode 100644 index 000000000..1ff713dd0 --- /dev/null +++ b/spec/fixtures/forms/setup/log_setup.json @@ -0,0 +1,71 @@ +{ + "form_type": "setup", + "sections": { + "setup": { + "label": "Before you start", + "subsections": { + "setup": { + "label": "Set up this lettings log", + "pages": { + "renewal": { + "header": "", + "description": "", + "questions": { + "renewal": { + "check_answer_label": "Property renewal", + "header": "Is this a renewal to the same tenant in the same property?", + "hint_text": "", + "type": "radio", + "answer_options": { + "1": "Yes", + "0": "No" + } + } + } + }, + "startdate": { + "header": "", + "description": "", + "questions": { + "startdate": { + "check_answer_label": "Tenancy start date", + "header": "What is the tenancy start date?", + "hint_text": "For example, 27 3 2007", + "type": "date" + } + } + }, + "about_this_letting": { + "header": "Tell us about this letting", + "description": "", + "questions": { + "rent_type": { + "check_answer_label": "Rent type", + "header": "What is the rent type?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Social rent", + "1": "Affordable rent", + "2": "London Affordable rent", + "3": "Rent to buy", + "4": "London living rent", + "5": "Other intermediate rent product" + }, + "conditional_for": { + "intermediate_rent_product_name": [5] + } + }, + "intermediate_rent_product_name": { + "check_answer_label": "Product name", + "header": "What is intermediate rent product name?", + "type": "text" + } + } + } + } + } + } + } + } +} diff --git a/spec/helpers/tasklist_helper_spec.rb b/spec/helpers/tasklist_helper_spec.rb index 012e3f9b6..13079f615 100644 --- a/spec/helpers/tasklist_helper_spec.rb +++ b/spec/helpers/tasklist_helper_spec.rb @@ -17,7 +17,7 @@ RSpec.describe TasklistHelper do describe "get sections count" do it "returns the total of sections if no status is given" do - expect(get_subsections_count(empty_case_log)).to eq(9) + expect(get_subsections_count(empty_case_log)).to eq(10) end it "returns 0 sections for completed sections if no sections are completed" do @@ -25,7 +25,7 @@ RSpec.describe TasklistHelper do end it "returns the number of not started sections" do - expect(get_subsections_count(empty_case_log, :not_started)).to eq(8) + expect(get_subsections_count(empty_case_log, :not_started)).to eq(9) end it "returns the number of sections in progress" do diff --git a/spec/models/form_handler_spec.rb b/spec/models/form_handler_spec.rb index 66ff32ed7..1fa80e253 100644 --- a/spec/models/form_handler_spec.rb +++ b/spec/models/form_handler_spec.rb @@ -17,7 +17,7 @@ RSpec.describe FormHandler do form_handler = described_class.instance form = form_handler.get_form(test_form_name) expect(form).to be_a(Form) - expect(form.pages.count).to eq(35) + expect(form.pages.count).to eq(38) end end @@ -32,7 +32,7 @@ RSpec.describe FormHandler do it "loads the form once at boot time" do form_handler = described_class.instance - expect(Form).not_to receive(:new).with(:any, test_form_name) + expect(Form).not_to receive(:new).with(:any, test_form_name, :any) expect(form_handler.get_form(test_form_name)).to be_a(Form) end end diff --git a/spec/models/organisation_spec.rb b/spec/models/organisation_spec.rb index 17b8ec200..ac6a0fc6c 100644 --- a/spec/models/organisation_spec.rb +++ b/spec/models/organisation_spec.rb @@ -87,7 +87,7 @@ RSpec.describe Organisation, type: :model do end it "has case logs" do - expect(organisation.case_logs.to_a).to eq([owned_case_log, managed_case_log]) + expect(organisation.case_logs.to_a).to match_array([owned_case_log, managed_case_log]) end it "has case log status helper methods" do diff --git a/spec/models/rent_period_spec.rb b/spec/models/rent_period_spec.rb index 55252977a..3c5bc2597 100644 --- a/spec/models/rent_period_spec.rb +++ b/spec/models/rent_period_spec.rb @@ -2,7 +2,8 @@ require "rails_helper" RSpec.describe RentPeriod, type: :model do describe "rent period mapping" do - let(:form) { Form.new("spec/fixtures/forms/2021_2022.json", "2021_2022") } + let(:setup_path) { "spec/fixtures/forms/setup/log_setup.json" } + let(:form) { Form.new("spec/fixtures/forms/2021_2022.json", "2021_2022", setup_path) } before do allow(FormHandler.instance).to receive(:current_form).and_return(form) diff --git a/spec/requests/case_logs_controller_spec.rb b/spec/requests/case_logs_controller_spec.rb index 9713666cb..edac399df 100644 --- a/spec/requests/case_logs_controller_spec.rb +++ b/spec/requests/case_logs_controller_spec.rb @@ -288,7 +288,8 @@ RSpec.describe CaseLogsController, type: :request do mrcdate: Time.zone.local(2022, 2, 1), startdate: Time.zone.local(2022, 12, 1), tenancy: 6, - managing_organisation: organisation) + managing_organisation: organisation, + tenant_code: nil) end it "shows case logs for multiple selected statuses and years" do @@ -622,7 +623,7 @@ RSpec.describe CaseLogsController, type: :request do end it "displays a section status for a case log" do - assert_select ".govuk-tag", text: /Not started/, count: 7 + assert_select ".govuk-tag", text: /Not started/, count: 8 assert_select ".govuk-tag", text: /In progress/, count: 1 assert_select ".govuk-tag", text: /Completed/, count: 0 assert_select ".govuk-tag", text: /Cannot start yet/, count: 1 @@ -645,7 +646,7 @@ RSpec.describe CaseLogsController, type: :request do end it "displays a section status for a case log" do - assert_select ".govuk-tag", text: /Not started/, count: 7 + assert_select ".govuk-tag", text: /Not started/, count: 8 assert_select ".govuk-tag", text: /Completed/, count: 1 assert_select ".govuk-tag", text: /Cannot start yet/, count: 1 end diff --git a/spec/services/imports/case_logs_field_import_service_spec.rb b/spec/services/imports/case_logs_field_import_service_spec.rb index 419ddbea3..f95eee21a 100644 --- a/spec/services/imports/case_logs_field_import_service_spec.rb +++ b/spec/services/imports/case_logs_field_import_service_spec.rb @@ -6,7 +6,8 @@ RSpec.describe Imports::CaseLogsFieldImportService do let(:storage_service) { instance_double(StorageService) } let(:logger) { instance_double(ActiveSupport::Logger) } - let(:real_2021_2022_form) { Form.new("config/forms/2021_2022.json", "2021_2022") } + let(:real_setup_path) { "config/forms/setup/log_setup.json" } + let(:real_2021_2022_form) { Form.new("config/forms/2021_2022.json", "2021_2022", real_setup_path) } let(:fixture_directory) { "spec/fixtures/softwire_imports/case_logs" } let(:case_log_id) { "0ead17cb-1668-442d-898c-0d52879ff592" } diff --git a/spec/services/imports/case_logs_import_service_spec.rb b/spec/services/imports/case_logs_import_service_spec.rb index dfe4ceb1b..fda123b09 100644 --- a/spec/services/imports/case_logs_import_service_spec.rb +++ b/spec/services/imports/case_logs_import_service_spec.rb @@ -6,8 +6,9 @@ RSpec.describe Imports::CaseLogsImportService do let(:storage_service) { instance_double(StorageService) } let(:logger) { instance_double(ActiveSupport::Logger) } - let(:real_2021_2022_form) { Form.new("config/forms/2021_2022.json", "2021_2022") } - let(:real_2022_2023_form) { Form.new("config/forms/2022_2023.json", "2022_2023") } + let(:real_setup_path) { "config/forms/setup/log_setup.json" } + let(:real_2021_2022_form) { Form.new("config/forms/2021_2022.json", "2021_2022", real_setup_path) } + let(:real_2022_2023_form) { Form.new("config/forms/2022_2023.json", "2022_2023", real_setup_path) } let(:fixture_directory) { "spec/fixtures/softwire_imports/case_logs" } def open_file(directory, filename)