Browse Source

CLDC-530 reduce test dependency on form definition (#46)

* use test_form.json in tests

* Pass in form to view from controller for check_answers

* reduce test json length for household section

* Further shorten the test json

* Remove extra radio questions from test json household section

* Trim test form and fix tests

* do some method extraction

* Extract creation of form into a formHandler

* rubocop

* redefine form model to use filepaths instead

* Check test env var in form handler

* remove singleton and make get_all_forms a private method

* refactor get_all_forms

Co-authored-by: Kat <katrina@madetech.com>
pull/48/head
Dushan 3 years ago committed by GitHub
parent
commit
beccd74f83
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      app/controllers/case_logs_controller.rb
  2. 28
      app/helpers/check_answers_helper.rb
  3. 7
      app/models/form.rb
  4. 28
      app/models/form_handler.rb
  5. 6
      app/views/form/check_answers.html.erb
  6. 3
      config/routes.rb
  7. 19
      spec/features/case_log_spec.rb
  8. 463
      spec/fixtures/forms/test_form.json
  9. 28
      spec/helpers/check_answers_helper_spec.rb
  10. 3
      spec/helpers/conditional_questions_helper_spec.rb
  11. 3
      spec/helpers/question_attribute_helper_spec.rb
  12. 9
      spec/helpers/tasklist_helper_spec.rb
  13. 27
      spec/models/form_handler_spec.rb
  14. 3
      spec/models/form_spec.rb

12
app/controllers/case_logs_controller.rb

@ -1,6 +1,9 @@
class CaseLogsController < ApplicationController class CaseLogsController < ApplicationController
skip_before_action :verify_authenticity_token, if: :json_create_request? skip_before_action :verify_authenticity_token, if: :json_create_request?
before_action :authenticate, if: :json_create_request? before_action :authenticate, if: :json_create_request?
# rubocop:disable Style/ClassVars
@@form_handler = FormHandler.instance
# rubocop:enable Style/ClassVars
def index def index
@submitted_case_logs = CaseLog.where(status: 1) @submitted_case_logs = CaseLog.where(status: 1)
@ -27,13 +30,13 @@ class CaseLogsController < ApplicationController
end end
def edit def edit
@form = Form.new(2021, 2022) @form = @@form_handler.get_form("2021_2022")
@case_log = CaseLog.find(params[:id]) @case_log = CaseLog.find(params[:id])
render :edit render :edit
end end
def submit_form def submit_form
form = Form.new(2021, 2022) form = @@form_handler.get_form("2021_2022")
@case_log = CaseLog.find(params[:id]) @case_log = CaseLog.find(params[:id])
previous_page = params[:case_log][:previous_page] previous_page = params[:case_log][:previous_page]
questions_for_page = form.questions_for_page(previous_page) questions_for_page = form.questions_for_page(previous_page)
@ -49,13 +52,14 @@ class CaseLogsController < ApplicationController
end end
def check_answers def check_answers
form = @@form_handler.get_form("2021_2022")
@case_log = CaseLog.find(params[:case_log_id]) @case_log = CaseLog.find(params[:case_log_id])
current_url = request.env["PATH_INFO"] current_url = request.env["PATH_INFO"]
subsection = current_url.split("/")[-2] subsection = current_url.split("/")[-2]
render "form/check_answers", locals: { case_log: @case_log, subsection: subsection } render "form/check_answers", locals: { case_log: @case_log, subsection: subsection, form: form }
end end
form = Form.new(2021, 2022) form = @@form_handler.get_form("2021_2022")
form.all_pages.map do |page_key, page_info| form.all_pages.map do |page_key, page_info|
define_method(page_key) do |_errors = {}| define_method(page_key) do |_errors = {}|
@case_log = CaseLog.find(params[:case_log_id]) @case_log = CaseLog.find(params[:case_log_id])

28
app/helpers/check_answers_helper.rb

@ -1,16 +1,15 @@
module CheckAnswersHelper module CheckAnswersHelper
def total_answered_questions(subsection, case_log) def total_answered_questions(subsection, case_log, form)
total_questions(subsection, case_log).keys.count do |question_key| total_questions(subsection, case_log, form).keys.count do |question_key|
case_log[question_key].present? case_log[question_key].present?
end end
end end
def total_number_of_questions(subsection, case_log) def total_number_of_questions(subsection, case_log, form)
total_questions(subsection, case_log).count total_questions(subsection, case_log, form).count
end end
def total_questions(subsection, case_log) def total_questions(subsection, case_log, form)
form = Form.new(2021, 2022)
questions = form.questions_for_subsection(subsection) questions = form.questions_for_subsection(subsection)
questions_not_applicable = [] questions_not_applicable = []
questions.reject do |question_key, question| questions.reject do |question_key, question|
@ -36,19 +35,14 @@ module CheckAnswersHelper
end end
end end
def subsection_pages(subsection)
form = Form.new(2021, 2022)
form.pages_for_subsection(subsection)
end
def create_update_answer_link(case_log_answer, case_log_id, page) def create_update_answer_link(case_log_answer, case_log_id, page)
link_name = case_log_answer.blank? ? "Answer" : "Change" link_name = case_log_answer.blank? ? "Answer" : "Change"
link_to(link_name, "/case_logs/#{case_log_id}/#{page}", class: "govuk-link").html_safe link_to(link_name, "/case_logs/#{case_log_id}/#{page}", class: "govuk-link").html_safe
end end
def create_next_missing_question_link(case_log_id, subsection, case_log) def create_next_missing_question_link(case_log_id, subsection, case_log, form)
pages_to_fill_in = [] pages_to_fill_in = []
subsection_pages(subsection).each do |page_title, page_info| form.pages_for_subsection(subsection).each do |page_title, page_info|
page_info["questions"].any? { |question| case_log[question].blank? } page_info["questions"].any? { |question| case_log[question].blank? }
pages_to_fill_in << page_title pages_to_fill_in << page_title
end end
@ -56,12 +50,12 @@ module CheckAnswersHelper
link_to("Answer the missing questions", url, class: "govuk-link").html_safe link_to("Answer the missing questions", url, class: "govuk-link").html_safe
end end
def display_answered_questions_summary(subsection, case_log) def display_answered_questions_summary(subsection, case_log, form)
if total_answered_questions(subsection, case_log) == total_number_of_questions(subsection, case_log) if total_answered_questions(subsection, case_log, form) == total_number_of_questions(subsection, case_log, form)
'<p class="govuk-body govuk-!-margin-bottom-7">You answered all the questions</p>'.html_safe '<p class="govuk-body govuk-!-margin-bottom-7">You answered all the questions</p>'.html_safe
else else
"<p class=\"govuk-body govuk-!-margin-bottom-7\">You answered #{total_answered_questions(subsection, case_log)} of #{total_number_of_questions(subsection, case_log)} questions</p> "<p class=\"govuk-body govuk-!-margin-bottom-7\">You answered #{total_answered_questions(subsection, case_log, form)} of #{total_number_of_questions(subsection, case_log, form)} questions</p>
#{create_next_missing_question_link(case_log['id'], subsection, case_log)}".html_safe #{create_next_missing_question_link(case_log['id'], subsection, case_log, form)}".html_safe
end end
end end
end end

7
app/models/form.rb

@ -1,11 +1,10 @@
class Form class Form
attr_reader :form_definition attr_reader :form_definition
def initialize(start_year, end_year) def initialize(form_path)
form_json = "config/forms/#{start_year}_#{end_year}.json" raise "No form definition file exists for given year".freeze unless File.exist?(form_path)
raise "No form definition file exists for given year".freeze unless File.exist?(form_json)
@form_definition = JSON.parse(File.open(form_json).read) @form_definition = JSON.parse(File.open(form_path).read)
end end
# Returns a hash with sections as keys # Returns a hash with sections as keys

28
app/models/form_handler.rb

@ -0,0 +1,28 @@
class FormHandler
include Singleton
attr_reader :forms
def initialize
@forms = get_all_forms
end
def get_form(form)
return @forms["test_form"] ||= Form.new("test_form") if ENV["RAILS_ENV"] == "test"
@forms[form] ||= Form.new(form)
end
private
def get_all_forms
forms = {}
directories = ["config/forms", "spec/fixtures/forms"]
directories.each do |directory|
Dir.glob("#{directory}/*.json").each do |form_path|
form_name = form_path.sub(".json", "").split("/")[-1]
forms[form_name] = Form.new(form_path)
end
end
forms
end
end

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

@ -2,10 +2,10 @@
<div class="govuk-grid-row"> <div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds-from-desktop"> <div class="govuk-grid-column-two-thirds-from-desktop">
<h1 class="govuk-heading-l">Check the answers you gave for <%= subsection.humanize(capitalize: false) %></h1> <h1 class="govuk-heading-l">Check the answers you gave for <%= subsection.humanize(capitalize: false) %></h1>
<%= display_answered_questions_summary(subsection, case_log) %> <%= display_answered_questions_summary(subsection, case_log, form) %>
<% subsection_pages(subsection).each do |page, page_info| %> <% form.pages_for_subsection(subsection).each do |page, page_info| %>
<% page_info["questions"].each do |question_title, question_info| %> <% page_info["questions"].each do |question_title, question_info| %>
<% if total_questions(subsection, case_log).include?(question_title) %> <% if total_questions(subsection, case_log, form).include?(question_title) %>
<%= render partial: 'form/check_answers_table', locals: { question_title: question_title, question_info: question_info, case_log: case_log, page: page } %> <%= render partial: 'form/check_answers_table', locals: { question_title: question_title, question_info: question_info, case_log: case_log, page: page } %>
<%end %> <%end %>
<%end %> <%end %>

3
config/routes.rb

@ -5,7 +5,8 @@ Rails.application.routes.draw do
post "/case_logs/:id", to: "case_logs#submit_form" post "/case_logs/:id", to: "case_logs#submit_form"
form = Form.new(2021, 2022) form_handler = FormHandler.instance
form = form_handler.get_form("2021_2022")
resources :case_logs do resources :case_logs do
form.all_pages.keys.map do |page| form.all_pages.keys.map do |page|
get page.to_s, to: "case_logs##{page}" get page.to_s, to: "case_logs##{page}"

19
spec/features/case_log_spec.rb

@ -9,9 +9,6 @@ RSpec.describe "Test Features" do
tenant_code: { type: "text", answer: "BZ737" }, tenant_code: { type: "text", answer: "BZ737" },
tenant_age: { type: "numeric", answer: 25 }, tenant_age: { type: "numeric", answer: 25 },
tenant_gender: { type: "radio", answer: "Female" }, tenant_gender: { type: "radio", answer: "Female" },
tenant_ethnic_group: { type: "radio", answer: "Prefer not to say" },
tenant_nationality: { type: "radio", answer: "Lithuania" },
tenant_economic_status: { type: "radio", answer: "Jobseeker" },
household_number_of_other_members: { type: "numeric", answer: 2 }, household_number_of_other_members: { type: "numeric", answer: 2 },
} }
@ -52,7 +49,7 @@ RSpec.describe "Test Features" do
it "displays a section status" do it "displays a section status" do
visit("/case_logs/#{empty_case_log.id}") visit("/case_logs/#{empty_case_log.id}")
assert_selector ".govuk-tag", text: /Not started/, count: 8 assert_selector ".govuk-tag", text: /Not started/, count: 7
assert_selector ".govuk-tag", text: /Completed/, count: 0 assert_selector ".govuk-tag", text: /Completed/, count: 0
assert_selector ".govuk-tag", text: /Cannot start yet/, count: 1 assert_selector ".govuk-tag", text: /Cannot start yet/, count: 1
end end
@ -61,7 +58,7 @@ RSpec.describe "Test Features" do
answer_all_questions_in_income_subsection answer_all_questions_in_income_subsection
visit("/case_logs/#{empty_case_log.id}") visit("/case_logs/#{empty_case_log.id}")
assert_selector ".govuk-tag", text: /Not started/, count: 7 assert_selector ".govuk-tag", text: /Not started/, count: 6
assert_selector ".govuk-tag", text: /Completed/, count: 1 assert_selector ".govuk-tag", text: /Completed/, count: 1
assert_selector ".govuk-tag", text: /Cannot start yet/, count: 1 assert_selector ".govuk-tag", text: /Cannot start yet/, count: 1
end end
@ -73,13 +70,13 @@ RSpec.describe "Test Features" do
it "shows the number of completed sections if no sections are completed" do it "shows the number of completed sections if no sections are completed" do
visit("/case_logs/#{empty_case_log.id}") visit("/case_logs/#{empty_case_log.id}")
expect(page).to have_content("You've completed 0 of 9 sections.") expect(page).to have_content("You've completed 0 of 8 sections.")
end end
it "shows the number of completed sections if one section is completed" do it "shows the number of completed sections if one section is completed" do
answer_all_questions_in_income_subsection answer_all_questions_in_income_subsection
visit("/case_logs/#{empty_case_log.id}") visit("/case_logs/#{empty_case_log.id}")
expect(page).to have_content("You've completed 1 of 9 sections.") expect(page).to have_content("You've completed 1 of 8 sections.")
end end
end end
@ -206,7 +203,7 @@ RSpec.describe "Test Features" do
it "has question headings based on the subsection" do it "has question headings based on the subsection" do
visit("case_logs/#{id}/#{subsection}/check_answers") visit("case_logs/#{id}/#{subsection}/check_answers")
question_labels = ["Tenant code", "Tenant's age", "Tenant's gender", "Ethnicity", "Nationality", "Work", "Number of Other Household Members"] question_labels = ["Tenant code", "Tenant's age", "Tenant's gender", "Number of Other Household Members"]
question_labels.each do |label| question_labels.each do |label|
expect(page).to have_content(label) expect(page).to have_content(label)
end end
@ -223,7 +220,7 @@ RSpec.describe "Test Features" do
it "should have an answer link for questions missing an answer" do it "should have an answer link for questions missing an answer" do
visit("case_logs/#{empty_case_log.id}/#{subsection}/check_answers") visit("case_logs/#{empty_case_log.id}/#{subsection}/check_answers")
assert_selector "a", text: /Answer\z/, count: 7 assert_selector "a", text: /Answer\z/, count: 4
assert_selector "a", text: "Change", count: 0 assert_selector "a", text: "Change", count: 0
expect(page).to have_link("Answer", href: "/case_logs/#{empty_case_log.id}/tenant_age") expect(page).to have_link("Answer", href: "/case_logs/#{empty_case_log.id}/tenant_age")
end end
@ -231,14 +228,14 @@ RSpec.describe "Test Features" do
it "should have a change link for answered questions" do it "should have a change link for answered questions" do
fill_in_number_question(empty_case_log.id, "tenant_age", 28) fill_in_number_question(empty_case_log.id, "tenant_age", 28)
visit("/case_logs/#{empty_case_log.id}/#{subsection}/check_answers") visit("/case_logs/#{empty_case_log.id}/#{subsection}/check_answers")
assert_selector "a", text: /Answer\z/, count: 6 assert_selector "a", text: /Answer\z/, count: 3
assert_selector "a", text: "Change", count: 1 assert_selector "a", text: "Change", count: 1
expect(page).to have_link("Change", href: "/case_logs/#{empty_case_log.id}/tenant_age") expect(page).to have_link("Change", href: "/case_logs/#{empty_case_log.id}/tenant_age")
end end
it "should have a link pointing to the first question if no questions are answered" do it "should have a link pointing to the first question if no questions are answered" do
visit("/case_logs/#{empty_case_log.id}/#{subsection}/check_answers") visit("/case_logs/#{empty_case_log.id}/#{subsection}/check_answers")
expect(page).to have_content("You answered 0 of 7 questions") expect(page).to have_content("You answered 0 of 4 questions")
expect(page).to have_link("Answer the missing questions", href: "/case_logs/#{empty_case_log.id}/tenant_code") expect(page).to have_link("Answer the missing questions", href: "/case_logs/#{empty_case_log.id}/tenant_code")
end end

463
spec/fixtures/forms/test_form.json vendored

@ -0,0 +1,463 @@
{
"form_type": "lettings",
"sections": {
"household": {
"label": "About the household",
"subsections": {
"household_characteristics": {
"label": "Household characteristics",
"pages": {
"tenant_code": {
"questions": {
"tenant_code": {
"check_answer_label": "Tenant code",
"header": "What is the tenant code?",
"type": "text"
}
}
},
"tenant_age": {
"questions": {
"tenant_age": {
"check_answer_label": "Tenant's age",
"header": "What is the tenant's age?",
"type": "numeric",
"min": 0,
"max": 150,
"step": 1
}
}
},
"tenant_gender": {
"questions": {
"tenant_gender": {
"check_answer_label": "Tenant's gender",
"header": "Which of these best describes the tenant's gender identity?",
"type": "radio",
"answer_options": {
"0": "Female",
"1": "Male",
"2": "Non-binary",
"3": "Prefer not to say"
}
}
}
},
"household_number_of_other_members": {
"questions": {
"household_number_of_other_members": {
"check_answer_label": "Number of Other Household Members",
"header": "How many other people are there in the household?",
"hint_text": "The maximum number of others is 1",
"type": "numeric",
"min": 0,
"max": 1,
"step": 1,
"conditional_for": {
"person_2_relationship": ">0",
"person_2_age": ">0",
"person_2_gender": ">0",
"person_2_economic_status": ">0"
}
},
"person_2_relationship": {
"check_answer_label": "Person 2's relationship to lead tenant",
"header": "What's person 2's relationship to lead tenant",
"type": "radio",
"answer_options": {
"0": "Other",
"1": "Prefer not to say"
}
},
"person_2_age": {
"check_answer_label": "Person 2's age",
"header": "What's person 2's age",
"type": "numeric",
"min": 0,
"max": 150,
"step": 1
},
"person_2_gender": {
"check_answer_label": "Person 2's gender",
"header": "Which of these best describes person 2's gender identity?",
"type": "radio",
"answer_options": {
"0": "Female",
"1": "Male",
"2": "Non-binary",
"3": "Prefer not to say"
}
},
"person_2_economic_status": {
"check_answer_label": "Person 2's Work",
"header": "Which of these best describes person 2's working situation?",
"type": "radio",
"answer_options": {
"0": "Other",
"1": "Prefer not to say"
}
}
}
}
}
},
"household_needs": {
"label": "Household needs",
"pages": {
"armed_forces": {
"header": "Experience of the UK Armed Forces",
"questions": {
"armed_forces": {
"header": "Has the tenant ever served in the UK armed forces?",
"type": "radio",
"check_answer_label": "Armed Forces",
"answer_options": {
"0": "Yes - a regular",
"1": "Yes - a reserve",
"2": "No",
"3": "Prefer not to say"
},
"conditional_for": {
"armed_forces_active": [
"Yes - a regular",
"Yes - a reserve"
],
"armed_forces_injured": [
"Yes - a regular",
"Yes - a reserve"
]
}
},
"armed_forces_active": {
"header": "Are they still serving?",
"type": "radio",
"check_answer_label": "When did they leave the Armed Forces?",
"answer_options": {
"0": "Yes",
"1": "No - they left up to 5 years ago",
"2": "No - they left more than 5 years ago",
"3": "Prefer not to say"
}
},
"armed_forces_injured": {
"header": "Were they seriously injured or ill as a result of their service?",
"type": "radio",
"check_answer_label": "Has anyone in the household been seriously injured or ill as a result of their service in the armed forces?",
"answer_options": {
"0": "Yes",
"1": "No",
"2": "Prefer not to say"
}
}
}
},
"medical_conditions": {
"questions": {
"medical_conditions": {
"header": "Does anyone in the household have any of the following that they expect to last for 12 months or more:<ul><li>Physical Condition</li><li>Mental Health Condition</li><li>Other Illness</li></ul>",
"type": "radio",
"check_answer_label": "Physical, mental health or illness in the household",
"answer_options": {
"0": "Yes",
"1": "No",
"2": "Do not know",
"3": "Prefer not to say"
}
}
}
},
"accessibility_requirements": {
"questions": {
"accessibility_requirements": {
"header": "Are any of these affected by their condition or illness?",
"hint_text": "Select all that apply",
"type": "checkbox",
"check_answer_label": "Disability requirements",
"answer_options": {
"accessibility_requirements_fully_wheelchair_accessible_housing": "Fully wheelchair accessible housing",
"accessibility_requirements_wheelchair_access_to_essential_rooms": "Wheelchair access to essential rooms",
"accessibility_requirements_level_access_housing": "Level access housing",
"divider_a": true,
"accessibility_requirements_do_not_know": "Do not know"
}
}
}
},
"condition_effects": {
"questions": {
"condition_effects": {
"header": "Are any of these affected by their condition or illness?",
"hint_text": "Select all that apply",
"type": "checkbox",
"check_answer_label": "Conditions or illnesses",
"answer_options": {
"condition_effects_vision": "Vision - such as blindness or partial sight",
"condition_effects_hearing": "Hearing - such as deafness or partial hearing"
}
}
}
}
}
}
}
},
"tenancy_and_property": {
"label": "Tenancy and property information",
"subsections": {
"tenancy_information": {
"label": "Tenancy information",
"pages": {
"tenancy_code": {
"questions": {
"tenancy_code": {
"check_answer_label": "What is the tenancy code?",
"header": "What is the tenancy code?",
"type": "text"
}
}
}
}
},
"property_information": {
"label": "Property information",
"pages": {
"property_wheelchair_accessible": {
"questions": {
"property_wheelchair_accessible": {
"check_answer_label": "Is property built or adapted to wheelchair user standards?",
"header": "Is property built or adapted to wheelchair user standards?",
"type": "radio",
"answer_options": {
"0": "Yes",
"1": "No"
}
}
}
}
}
}
}
},
"rent_and_charges": {
"label": "Rent and charges",
"subsections": {
"income_and_benefits": {
"label": "Income and benefits",
"pages": {
"net_income": {
"questions": {
"net_income": {
"check_answer_label": "Income",
"header": "What is the tenant’s /and partner’s combined income after tax?",
"type": "numeric",
"min": 0,
"step": "1"
},
"net_income_frequency": {
"check_answer_label": "Income Frequency",
"header": "How often do they receive this income?",
"type": "radio",
"answer_options": {
"0": "Weekly",
"1": "Monthly",
"2": "Yearly"
}
}
}
},
"net_income_uc_proportion": {
"questions": {
"net_income_uc_proportion": {
"check_answer_label": "Benefits as a proportion of income",
"header": "How much of the tenant’s income is from Universal Credit, state pensions or benefits?",
"type": "radio",
"answer_options": {
"0": "All",
"1": "Some"
}
}
}
},
"housing_benefit": {
"questions": {
"housing_benefit": {
"check_answer_label": "Universal Credit & Housing Benefit",
"header": "Is the tenant likely to be in receipt of any of these housing-related benefits?",
"type": "radio",
"answer_options": {
"0": "Housing Benefit, but not Universal Credit",
"1": "Prefer not to say"
}
}
}
}
}
},
"rent": {
"label": "Rent",
"pages": {
"rent": {
"questions": {
"rent_frequency": {
"check_answer_label": "Rent Period",
"header": "Which period are rent and other charges due?",
"type": "radio",
"answer_options": {
"0": "Weekly for 52 weeks",
"1": "Fortnightly"
}
},
"basic_rent": {
"check_answer_label": "Basic Rent",
"header": "What is the basic rent?",
"hint_text": "Eligible for housing benefit or Universal Credit",
"type": "numeric",
"min": 0,
"step": 1,
"fields-to-add": [
"basic_rent",
"service_charge",
"personal_service_charge",
"support_charge"
],
"result-field": "total_charge"
},
"service_charge": {
"check_answer_label": "Service Charge",
"header": "What is the service charge?",
"hint_text": "Eligible for housing benefit or Universal Credit",
"type": "numeric",
"min": 0,
"step": 1,
"fields-to-add": [
"basic_rent",
"service_charge",
"personal_service_charge",
"support_charge"
],
"result-field": "total_charge"
},
"personal_service_charge": {
"check_answer_label": "Personal Service Charge",
"header": "What is the personal service charge?",
"hint_text": "Not eligible for housing benefit or Universal Credit. For example, hot water excluding water rates.",
"type": "numeric",
"min": 0,
"step": 1,
"fields-to-add": [
"basic_rent",
"service_charge",
"personal_service_charge",
"support_charge"
],
"result-field": "total_charge"
},
"support_charge": {
"check_answer_label": "Support Charge",
"header": "What is the support charge?",
"hint_text": "This is to fund housing-related support services included in the tenancy agreement",
"type": "numeric",
"min": 0,
"step": 1,
"fields-to-add": [
"basic_rent",
"service_charge",
"personal_service_charge",
"support_charge"
],
"result-field": "total_charge"
},
"total_charge": {
"check_answer_label": "Total Charge",
"header": "Total charge?",
"hint_text": "This is the total of rent and all charges",
"type": "numeric",
"min": 0,
"step": 1,
"readonly": true
}
}
}
}
}
}
},
"local_authority": {
"label": "Local authority",
"subsections": {
"local_authority": {
"label": "Local authority",
"pages": {
"time_lived_in_la": {
"questions": {
"time_lived_in_la": {
"check_answer_label": "How long has the household continuously lived in the local authority area where the new letting is located?",
"header": "How long has the household continuously lived in the local authority area where the new letting is located?",
"type": "radio",
"answer_options": {
"0": "Just moved to local authority area",
"1": "Less than 1 year",
"2": "1 to 2 years",
"3": "2 to 3 years",
"4": "3 to 4 years",
"5": "4 to 5 years",
"6": "5 years or more",
"7": "Do not know"
}
}
}
},
"time_on_la_waiting_list": {
"questions": {
"time_on_la_waiting_list": {
"check_answer_label": "How long has the household been on the local authority waiting list where the new letting is located?",
"header": "How long has the household been on the local authority waiting list where the new letting is located?",
"type": "radio",
"answer_options": {
"0": "Just moved to local authority area",
"1": "Less than 1 year",
"2": "1 to 2 years",
"3": "2 to 3 years",
"4": "3 to 4 years",
"5": "4 to 5 years",
"6": "5 years or more",
"7": "Do not know"
}
}
}
},
"previous_postcode": {
"questions": {
"previous_postcode": {
"check_answer_label": "Postcode of previous accomodation if the household has moved from settled accommodation",
"header": "Postcode for the previous accommodation",
"hint_text": "If the household has moved from settled accommodation immediately prior to being re-housed",
"type": "text"
}
}
}
}
}
}
},
"submission": {
"label": "Submission",
"subsections": {
"declaration": {
"label": "Declaration",
"pages": {
"declaration": {
"questions": {
"declaration": {
"check_answer_label": "",
"header": "What is the tenant code?",
"type": "text"
}
}
}
}
}
}
}
}
}

28
spec/helpers/check_answers_helper_spec.rb

@ -6,7 +6,7 @@ RSpec.describe CheckAnswersHelper do
FactoryBot.create( FactoryBot.create(
:case_log, :case_log,
:in_progress, :in_progress,
household_number_of_other_members: 2, household_number_of_other_members: 1,
person_2_relationship: "Partner", person_2_relationship: "Partner",
) )
end end
@ -16,32 +16,35 @@ RSpec.describe CheckAnswersHelper do
let(:subsection) { "income_and_benefits" } let(:subsection) { "income_and_benefits" }
let(:subsection_with_numeric_conditionals) { "household_characteristics" } let(:subsection_with_numeric_conditionals) { "household_characteristics" }
let(:subsection_with_radio_conditionals) { "household_needs" } let(:subsection_with_radio_conditionals) { "household_needs" }
form_handler = FormHandler.instance
let(:form) { form_handler.get_form("test_form") }
describe "Get answered questions total" do describe "Get answered questions total" do
it "returns 0 if no questions are answered" do it "returns 0 if no questions are answered" do
expect(total_answered_questions(subsection, case_log)).to equal(0) expect(total_answered_questions(subsection, case_log, form)).to equal(0)
end end
it "returns 1 if 1 question gets answered" do it "returns 1 if 1 question gets answered" do
case_log["net_income"] = "123" case_log["net_income"] = "123"
expect(total_answered_questions(subsection, case_log)).to equal(1) expect(total_answered_questions(subsection, case_log, form)).to equal(1)
end end
it "ignores questions with unmet numeric conditions" do it "ignores questions with unmet numeric conditions" do
case_log["tenant_code"] = "T1234" case_log["tenant_code"] = "T1234"
expect(total_answered_questions(subsection_with_numeric_conditionals, case_log)).to equal(1) expect(total_answered_questions(subsection_with_numeric_conditionals, case_log, form)).to equal(1)
end end
it "includes conditional questions with met numeric conditions" do it "includes conditional questions with met numeric conditions" do
expect(total_answered_questions( expect(total_answered_questions(
subsection_with_numeric_conditionals, subsection_with_numeric_conditionals,
case_log_with_met_numeric_condition, case_log_with_met_numeric_condition,
form,
)).to equal(4) )).to equal(4)
end end
it "ignores questions with unmet radio conditions" do it "ignores questions with unmet radio conditions" do
case_log["armed_forces"] = "No" case_log["armed_forces"] = "No"
expect(total_answered_questions(subsection_with_radio_conditionals, case_log)).to equal(1) expect(total_answered_questions(subsection_with_radio_conditionals, case_log, form)).to equal(1)
end end
it "includes conditional questions with met radio conditions" do it "includes conditional questions with met radio conditions" do
@ -50,35 +53,38 @@ RSpec.describe CheckAnswersHelper do
expect(total_answered_questions( expect(total_answered_questions(
subsection_with_radio_conditionals, subsection_with_radio_conditionals,
case_log_with_met_radio_condition, case_log_with_met_radio_condition,
form,
)).to equal(3) )).to equal(3)
end end
end end
describe "Get total number of questions" do describe "Get total number of questions" do
it "returns the total number of questions for a subsection" do it "returns the total number of questions for a subsection" do
expect(total_number_of_questions(subsection, case_log)).to eq(4) expect(total_number_of_questions(subsection, case_log, form)).to eq(4)
end end
it "ignores questions with unmet numeric conditions" do it "ignores questions with unmet numeric conditions" do
expect(total_number_of_questions(subsection_with_numeric_conditionals, case_log)).to eq(7) expect(total_number_of_questions(subsection_with_numeric_conditionals, case_log, form)).to eq(4)
end end
it "includes conditional questions with met numeric conditions" do it "includes conditional questions with met numeric conditions" do
expect(total_number_of_questions( expect(total_number_of_questions(
subsection_with_numeric_conditionals, subsection_with_numeric_conditionals,
case_log_with_met_numeric_condition, case_log_with_met_numeric_condition,
)).to eq(15) form,
)).to eq(8)
end end
it "ignores questions with unmet radio conditions" do it "ignores questions with unmet radio conditions" do
expect(total_number_of_questions(subsection_with_radio_conditionals, case_log)).to eq(6) expect(total_number_of_questions(subsection_with_radio_conditionals, case_log, form)).to eq(4)
end end
it "includes conditional questions with met radio conditions" do it "includes conditional questions with met radio conditions" do
expect(total_number_of_questions( expect(total_number_of_questions(
subsection_with_radio_conditionals, subsection_with_radio_conditionals,
case_log_with_met_radio_condition, case_log_with_met_radio_condition,
)).to eq(8) form,
)).to eq(6)
end end
context "conditional questions with type that hasn't been implemented yet" do context "conditional questions with type that hasn't been implemented yet" do
@ -99,7 +105,7 @@ RSpec.describe CheckAnswersHelper do
it "raises an error" do it "raises an error" do
allow_any_instance_of(Form).to receive(:questions_for_subsection).and_return(unimplemented_conditional) allow_any_instance_of(Form).to receive(:questions_for_subsection).and_return(unimplemented_conditional)
expect { total_number_of_questions(subsection, case_log) }.to raise_error(RuntimeError, "Not implemented yet") expect { total_number_of_questions(subsection, case_log, form) }.to raise_error(RuntimeError, "Not implemented yet")
end end
end end
end end

3
spec/helpers/conditional_questions_helper_spec.rb

@ -1,7 +1,8 @@
require "rails_helper" require "rails_helper"
RSpec.describe ConditionalQuestionsHelper do RSpec.describe ConditionalQuestionsHelper do
let(:form) { Form.new(2021, 2022) } form_handler = FormHandler.instance
let(:form) { form_handler.get_form("test_form") }
let(:page_key) { "armed_forces" } let(:page_key) { "armed_forces" }
let(:page) { form.all_pages[page_key] } let(:page) { form.all_pages[page_key] }

3
spec/helpers/question_attribute_helper_spec.rb

@ -1,7 +1,8 @@
require "rails_helper" require "rails_helper"
RSpec.describe QuestionAttributeHelper do RSpec.describe QuestionAttributeHelper do
let(:form) { Form.new(2021, 2022) } form_handler = FormHandler.instance
let(:form) { form_handler.get_form("test_form") }
let(:questions) { form.questions_for_page("rent") } let(:questions) { form.questions_for_page("rent") }
describe "html attributes" do describe "html attributes" do

9
spec/helpers/tasklist_helper_spec.rb

@ -3,7 +3,8 @@ require "rails_helper"
RSpec.describe TasklistHelper do RSpec.describe TasklistHelper do
let!(:empty_case_log) { FactoryBot.create(:case_log) } let!(:empty_case_log) { FactoryBot.create(:case_log) }
let!(:case_log) { FactoryBot.create(:case_log, :in_progress) } let!(:case_log) { FactoryBot.create(:case_log, :in_progress) }
let(:form) { Form.new(2021, 2022) } form_handler = FormHandler.instance
let(:form) { form_handler.get_form("test_form") }
describe "get subsection status" do describe "get subsection status" do
let(:section) { "income_and_benefits" } let(:section) { "income_and_benefits" }
@ -53,7 +54,7 @@ RSpec.describe TasklistHelper do
describe "get sections count" do describe "get sections count" do
it "returns the total of sections if no status is given" do it "returns the total of sections if no status is given" do
expect(get_sections_count(form, empty_case_log)).to eq(9) expect(get_sections_count(form, empty_case_log)).to eq(8)
end end
it "returns 0 sections for completed sections if no sections are completed" do it "returns 0 sections for completed sections if no sections are completed" do
@ -61,11 +62,11 @@ RSpec.describe TasklistHelper do
end end
it "returns the number of not started sections" do it "returns the number of not started sections" do
expect(get_sections_count(form, empty_case_log, :not_started)).to eq(8) expect(get_sections_count(form, empty_case_log, :not_started)).to eq(7)
end end
it "returns the number of sections in progress" do it "returns the number of sections in progress" do
expect(get_sections_count(form, case_log, :in_progress)).to eq(3) expect(get_sections_count(form, case_log, :in_progress)).to eq(2)
end end
it "returns 0 for invalid state" do it "returns 0 for invalid state" do

27
spec/models/form_handler_spec.rb

@ -0,0 +1,27 @@
require "rails_helper"
RSpec.describe FormHandler do
describe "Get all forms" do
it "should be able to load all the forms" do
form_handler = FormHandler.instance
all_forms = form_handler.forms
expect(all_forms.count).to be >= 1
expect(all_forms["test_form"]).to be_a(Form)
end
end
describe "Get specific form" do
it "should be able to load a specific form" do
form_handler = FormHandler.instance
form = form_handler.get_form("test_form")
expect(form).to be_a(Form)
expect(form.all_pages.count).to eq(18)
end
end
it "should only load the form once at boot time" do
form_handler = FormHandler.instance
expect(Form).not_to receive(:new).with("test_form")
expect(form_handler.get_form("test_form")).to be_a(Form)
end
end

3
spec/models/form_spec.rb

@ -1,7 +1,8 @@
require "rails_helper" require "rails_helper"
RSpec.describe Form, type: :model do RSpec.describe Form, type: :model do
let(:form) { Form.new(2021, 2022) } form_handler = FormHandler.instance
let(:form) { form_handler.get_form("test_form") }
describe ".next_page" do describe ".next_page" do
let(:previous_page) { "tenant_age" } let(:previous_page) { "tenant_age" }

Loading…
Cancel
Save