Browse Source

Iterate over all forms (#176)

* Iterate over all forms

* Re-lookup page to ensure we have the definition for the right form

* Match form naming convention for spec and real

* Add test for case log form
pull/178/head
baarkerlounger 3 years ago committed by GitHub
parent
commit
c568dcdf3d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      app/controllers/case_logs_controller.rb
  2. 22
      app/controllers/form_controller.rb
  3. 3
      app/controllers/soft_validations_controller.rb
  4. 10
      app/helpers/tasklist_helper.rb
  5. 9
      app/models/case_log.rb
  6. 9
      app/models/form.rb
  7. 9
      app/models/form_handler.rb
  8. 2
      app/views/case_logs/_tasklist.html.erb
  9. 6
      app/views/case_logs/edit.html.erb
  10. 5
      config/routes.rb
  11. 2
      spec/factories/case_log.rb
  12. 0
      spec/fixtures/forms/2021_2022.json
  13. 4
      spec/helpers/check_answers_helper_spec.rb
  14. 5
      spec/helpers/conditional_questions_helper_spec.rb
  15. 4
      spec/helpers/question_attribute_helper_spec.rb
  16. 20
      spec/helpers/tasklist_helper_spec.rb
  17. 10
      spec/models/case_log_spec.rb
  18. 3
      spec/models/form/page_spec.rb
  19. 3
      spec/models/form/question_spec.rb
  20. 3
      spec/models/form/section_spec.rb
  21. 3
      spec/models/form/subsection_spec.rb
  22. 9
      spec/models/form_handler_spec.rb
  23. 3
      spec/models/form_spec.rb
  24. 4
      spec/requests/case_log_controller_spec.rb
  25. 2
      spec/requests/form_controller_spec.rb

1
app/controllers/case_logs_controller.rb

@ -50,7 +50,6 @@ class CaseLogsController < ApplicationController
end
def edit
@form = FormHandler.instance.get_form("2021_2022")
@case_log = current_user.case_logs.find_by(id: params[:id])
if @case_log
render :edit

22
app/controllers/form_controller.rb

@ -4,16 +4,15 @@ class FormController < ApplicationController
before_action :find_resource_by_named_id, except: [:submit_form]
def submit_form
form = FormHandler.instance.get_form("2021_2022")
if @case_log
page = form.get_page(params[:case_log][:page])
page = @case_log.form.get_page(params[:case_log][:page])
responses_for_page = responses_for_page(page)
if @case_log.update(responses_for_page) && @case_log.has_no_unresolved_soft_errors?
redirect_path = form.next_page_redirect_path(page, @case_log)
redirect_path = @case_log.form.next_page_redirect_path(page, @case_log)
redirect_to(send(redirect_path, @case_log))
else
subsection = form.subsection_for_page(page)
render "form/page", locals: { form: form, page: page, subsection: subsection.label }, status: :unprocessable_entity
subsection = @case_log.form.subsection_for_page(page)
render "form/page", locals: { page: page, subsection: subsection.label }, status: :unprocessable_entity
end
else
render_not_found
@ -21,27 +20,28 @@ class FormController < ApplicationController
end
def check_answers
form = FormHandler.instance.get_form("2021_2022")
if @case_log
current_url = request.env["PATH_INFO"]
subsection = form.get_subsection(current_url.split("/")[-2])
render "form/check_answers", locals: { subsection: subsection, form: form }
subsection = @case_log.form.get_subsection(current_url.split("/")[-2])
render "form/check_answers", locals: { subsection: subsection }
else
render_not_found
end
end
form = FormHandler.instance.get_form("2021_2022")
FormHandler.instance.forms.each do |_key, form|
form.pages.map do |page|
define_method(page.id) do |_errors = {}|
if @case_log
subsection = form.subsection_for_page(page)
render "form/page", locals: { form: form, page: page, subsection: subsection.label }
subsection = @case_log.form.subsection_for_page(page)
case_log_form_page = @case_log.form.get_page(page.id)
render "form/page", locals: { page: case_log_form_page, subsection: subsection.label }
else
render_not_found
end
end
end
end
private

3
app/controllers/soft_validations_controller.rb

@ -4,8 +4,7 @@ class SoftValidationsController < ApplicationController
def show
@case_log = CaseLog.find(params[:case_log_id])
page_id = request.env["PATH_INFO"].split("/")[-2]
form = FormHandler.instance.get_form("2021_2022")
page = form.get_page(page_id)
page = @case_log.form.get_page(page_id)
if page_requires_soft_validation_override?(page)
errors = @case_log.soft_errors.values.first
render json: { show: true, label: errors.message, hint: errors.hint_text }

10
app/helpers/tasklist_helper.rb

@ -15,14 +15,14 @@ module TasklistHelper
in_progress: "govuk-tag--blue",
}.freeze
def get_next_incomplete_section(form, case_log)
form.subsections.find { |subsection| subsection.is_incomplete?(case_log) }
def get_next_incomplete_section(case_log)
case_log.form.subsections.find { |subsection| subsection.is_incomplete?(case_log) }
end
def get_subsections_count(form, case_log, status = :all)
return form.subsections.count if status == :all
def get_subsections_count(case_log, status = :all)
return case_log.form.subsections.count if status == :all
form.subsections.count { |subsection| subsection.status(case_log) == status }
case_log.form.subsections.count { |subsection| subsection.status(case_log) == status }
end
def first_page_or_check_answers(subsection, case_log)

9
app/models/case_log.rb

@ -136,6 +136,15 @@ class CaseLog < ApplicationRecord
la_known
first_time_property_let_as_social_housing].freeze
def form
FormHandler.instance.get_form(form_name)
end
def form_name
start_year = year || 2021
"#{start_year}_#{start_year + 1}"
end
def self.editable_fields
attribute_names - AUTOGENERATED_FIELDS
end

9
app/models/form.rb

@ -1,10 +1,15 @@
class Form
attr_reader :form_definition, :sections, :subsections, :pages, :questions
attr_reader :form_definition, :sections, :subsections, :pages, :questions,
:start_year, :end_year, :type, :name
def initialize(form_path)
def initialize(form_path, name)
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_year = form_definition["start_year"]
@end_year = form_definition["end_year"]
@type = form_definition["form_type"]
@sections = form_definition["sections"].map { |id, s| Form::Section.new(id, s, self) }
@subsections = sections.flat_map(&:subsections)
@pages = subsections.flat_map(&:pages)

9
app/models/form_handler.rb

@ -7,8 +7,6 @@ class FormHandler
end
def get_form(form)
return @forms["test_form"] ||= Form.new("test_form") if ENV["RAILS_ENV"] == "test"
@forms[form] ||= Form.new(form)
end
@ -16,13 +14,16 @@ 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)
forms[form_name] = Form.new(form_path, form_name)
end
end
forms
end
def directories
Rails.env.test? ? ["spec/fixtures/forms"] : ["config/forms"]
end
end

2
app/views/case_logs/_tasklist.html.erb

@ -1,5 +1,5 @@
<ol class="app-task-list app-task-list--no-numbers">
<% @form.sections.map do |section| %>
<% @case_log.form.sections.map do |section| %>
<li>
<h2 class="app-task-list__section">
<span class="app-task-list__section-number">

6
app/views/case_logs/edit.html.erb

@ -12,9 +12,9 @@
<%= @case_log.status.to_s.humanize.downcase %>
</h2>
<p class="govuk-body govuk-!-margin-bottom-7">You’ve completed <%= get_subsections_count(@form, @case_log, :completed) %> of <%= get_subsections_count(@form, @case_log, :all) %> sections.</p>
<p class="govuk-body govuk-!-margin-bottom-7">You’ve completed <%= get_subsections_count(@case_log, :completed) %> of <%= get_subsections_count(@case_log, :all) %> sections.</p>
<p class="govuk-body govuk-!-margin-bottom-7">
<% next_incomplete_section = get_next_incomplete_section(@form, @case_log).id %>
<% next_incomplete_section = get_next_incomplete_section(@case_log).id %>
<a class="govuk-link" href="#<%= next_incomplete_section %>"
data-controller="tasklist"
data-action="tasklist#addHighlight"
@ -22,7 +22,7 @@
Skip to next incomplete section
</a>
</p>
<%= render "tasklist", locals: { form: @form } %>
<%= render "tasklist" %>
</div>
</div>
<% end %>

5
config/routes.rb

@ -28,9 +28,6 @@ Rails.application.routes.draw do
end
end
form_handler = FormHandler.instance
form = form_handler.get_form("2021_2022")
resources :case_logs, path: "/logs" do
collection do
post "bulk-upload", to: "bulk_upload#bulk_upload"
@ -41,6 +38,7 @@ Rails.application.routes.draw do
post "form", to: "form#submit_form"
end
FormHandler.instance.forms.each do |_key, form|
form.pages.map do |page|
get page.id.to_s.dasherize, to: "form##{page.id}"
get "#{page.id.to_s.dasherize}/soft-validations", to: "soft_validations#show" if page.has_soft_validations?
@ -50,6 +48,7 @@ Rails.application.routes.draw do
get "#{subsection.id.to_s.dasherize}/check-answers", to: "form#check_answers"
end
end
end
scope via: :all do
match "/404", to: "errors#not_found"

2
spec/factories/case_log.rb

@ -136,7 +136,7 @@ FactoryBot.define do
startdate { Time.zone.now }
day { Time.zone.now.day }
month { Time.zone.now.month }
year { Time.zone.now.year }
year { 2021 }
armedforces { 1 }
builtype { 1 }
unitletas { 2 }

0
spec/fixtures/forms/test_form.json → spec/fixtures/forms/2021_2022.json vendored

4
spec/helpers/check_answers_helper_spec.rb

@ -1,8 +1,8 @@
require "rails_helper"
RSpec.describe CheckAnswersHelper do
form_handler = FormHandler.instance
let(:form) { form_handler.get_form("test_form") }
let(:case_log) { FactoryBot.build(:case_log) }
let(:form) { case_log.form }
let(:subsection) { form.get_subsection("household_characteristics") }
let(:case_log) { FactoryBot.build(:case_log, :in_progress) }

5
spec/helpers/conditional_questions_helper_spec.rb

@ -1,9 +1,8 @@
require "rails_helper"
RSpec.describe ConditionalQuestionsHelper do
form_handler = FormHandler.instance
let(:form) { form_handler.get_form("test_form") }
let(:page) { form.get_page("armed_forces") }
let(:case_log) { FactoryBot.build(:case_log) }
let(:page) { case_log.form.get_page("armed_forces") }
describe "conditional questions for page" do
let(:conditional_pages) { %w[leftreg reservist] }

4
spec/helpers/question_attribute_helper_spec.rb

@ -1,8 +1,8 @@
require "rails_helper"
RSpec.describe QuestionAttributeHelper do
form_handler = FormHandler.instance
let(:form) { form_handler.get_form("test_form") }
let(:case_log) { FactoryBot.build(:case_log) }
let(:form) { case_log.form }
let(:questions) { form.get_page("rent").questions }
describe "html attributes" do

20
spec/helpers/tasklist_helper_spec.rb

@ -7,44 +7,42 @@ RSpec.describe TasklistHelper do
end
let(:empty_case_log) { FactoryBot.create(:case_log) }
let(:case_log) { FactoryBot.create(:case_log, :in_progress) }
form_handler = FormHandler.instance
let(:form) { form_handler.get_form("test_form") }
describe "get next incomplete section" do
it "returns the first subsection name if it is not completed" do
expect(get_next_incomplete_section(form, case_log).id).to eq("household_characteristics")
expect(get_next_incomplete_section(case_log).id).to eq("household_characteristics")
end
it "returns the first subsection name if it is partially completed" do
case_log["tenant_code"] = 123
expect(get_next_incomplete_section(form, case_log).id).to eq("household_characteristics")
expect(get_next_incomplete_section(case_log).id).to eq("household_characteristics")
end
end
describe "get sections count" do
it "returns the total of sections if no status is given" do
expect(get_subsections_count(form, empty_case_log)).to eq(9)
expect(get_subsections_count(empty_case_log)).to eq(9)
end
it "returns 0 sections for completed sections if no sections are completed" do
expect(get_subsections_count(form, empty_case_log, :completed)).to eq(0)
expect(get_subsections_count(empty_case_log, :completed)).to eq(0)
end
it "returns the number of not started sections" do
expect(get_subsections_count(form, empty_case_log, :not_started)).to eq(8)
expect(get_subsections_count(empty_case_log, :not_started)).to eq(8)
end
it "returns the number of sections in progress" do
expect(get_subsections_count(form, case_log, :in_progress)).to eq(3)
expect(get_subsections_count(case_log, :in_progress)).to eq(3)
end
it "returns 0 for invalid state" do
expect(get_subsections_count(form, case_log, :fake)).to eq(0)
expect(get_subsections_count(case_log, :fake)).to eq(0)
end
end
describe "get_first_page_or_check_answers" do
let(:subsection) { form.get_subsection("household_characteristics") }
let(:subsection) { case_log.form.get_subsection("household_characteristics") }
it "returns the check answers page path if the section has been started already" do
expect(first_page_or_check_answers(subsection, case_log)).to match(/check-answers/)
@ -56,7 +54,7 @@ RSpec.describe TasklistHelper do
end
describe "subsection link" do
let(:subsection) { form.get_subsection("household_characteristics") }
let(:subsection) { case_log.form.get_subsection("household_characteristics") }
context "for a subsection that's enabled" do
it "returns the subsection link url" do

10
spec/models/case_log_spec.rb

@ -8,6 +8,16 @@ RSpec.describe Form, type: :model do
RequestHelper.stub_http_requests
end
describe "#form" do
let(:case_log) { FactoryBot.build(:case_log) }
let(:case_log_year_2) { FactoryBot.build(:case_log, year: 2023) }
it "has returns the correct form based on the start date" do
expect(case_log.form_name).to eq("2021_2022")
expect(case_log_year_2.form_name).to eq("2023_2024")
expect(case_log.form).to be_a(Form)
end
end
describe "#new" do
it "validates age is a number" do
expect {

3
spec/models/form/page_spec.rb

@ -1,7 +1,8 @@
require "rails_helper"
RSpec.describe Form::Page, type: :model do
let(:form) { FormHandler.instance.get_form("test_form") }
let(:case_log) { FactoryBot.build(:case_log) }
let(:form) { case_log.form }
let(:section_id) { "rent_and_charges" }
let(:section_definition) { form.form_definition["sections"][section_id] }
let(:section) { Form::Section.new(section_id, section_definition, form) }

3
spec/models/form/question_spec.rb

@ -1,7 +1,8 @@
require "rails_helper"
RSpec.describe Form::Question, type: :model do
let(:form) { FormHandler.instance.get_form("test_form") }
let(:case_log) { FactoryBot.build(:case_log) }
let(:form) { case_log.form }
let(:section_id) { "rent_and_charges" }
let(:section_definition) { form.form_definition["sections"][section_id] }
let(:section) { Form::Section.new(section_id, section_definition, form) }

3
spec/models/form/section_spec.rb

@ -1,7 +1,8 @@
require "rails_helper"
RSpec.describe Form::Section, type: :model do
let(:form) { FormHandler.instance.get_form("test_form") }
let(:case_log) { FactoryBot.build(:case_log) }
let(:form) { case_log.form }
let(:section_id) { "household" }
let(:section_definition) { form.form_definition["sections"][section_id] }
subject { Form::Section.new(section_id, section_definition, form) }

3
spec/models/form/subsection_spec.rb

@ -1,7 +1,8 @@
require "rails_helper"
RSpec.describe Form::Subsection, type: :model do
let(:form) { FormHandler.instance.get_form("test_form") }
let(:case_log) { FactoryBot.build(:case_log) }
let(:form) { case_log.form }
let(:section_id) { "household" }
let(:section_definition) { form.form_definition["sections"][section_id] }
let(:section) { Form::Section.new(section_id, section_definition, form) }

9
spec/models/form_handler_spec.rb

@ -1,19 +1,20 @@
require "rails_helper"
RSpec.describe FormHandler do
let(:test_form_name) { "2021_2022" }
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)
expect(all_forms[test_form_name]).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")
form = form_handler.get_form(test_form_name)
expect(form).to be_a(Form)
expect(form.pages.count).to eq(27)
end
@ -21,7 +22,7 @@ RSpec.describe FormHandler do
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)
expect(Form).not_to receive(:new).with(:any, test_form_name)
expect(form_handler.get_form(test_form_name)).to be_a(Form)
end
end

3
spec/models/form_spec.rb

@ -1,9 +1,8 @@
require "rails_helper"
RSpec.describe Form, type: :model do
form_handler = FormHandler.instance
let(:form) { form_handler.get_form("test_form") }
let(:case_log) { FactoryBot.build(:case_log, :in_progress) }
let(:form) { case_log.form }
let(:completed_case_log) { FactoryBot.build(:case_log, :completed) }
let(:conditional_section_complete_case_log) { FactoryBot.build(:case_log, :conditional_section_complete) }

4
spec/requests/case_log_controller_spec.rb

@ -178,10 +178,6 @@ RSpec.describe CaseLogsController, type: :request do
context "edit log" do
let(:headers) { { "Accept" => "text/html" } }
let(:form) { Form.new("spec/fixtures/forms/test_form.json") }
before do
allow(FormHandler.instance).to receive(:get_form).and_return(form)
end
context "a user that is not signed in" do
it "does not let the user get case log tasklist pages they don't have access to" do

2
spec/requests/form_controller_spec.rb

@ -69,7 +69,6 @@ RSpec.describe FormController, type: :request do
describe "Submit Form" do
context "a form page" do
let(:user) { FactoryBot.create(:user) }
let(:form) { Form.new("spec/fixtures/forms/test_form.json") }
let(:organisation) { user.organisation }
let(:case_log) do
FactoryBot.create(
@ -90,7 +89,6 @@ RSpec.describe FormController, type: :request do
end
before do
allow(FormHandler.instance).to receive(:get_form).and_return(form)
post "/logs/#{case_log.id}/form", params: params
end

Loading…
Cancel
Save