Browse Source

CLDC-709: Conditional section status bugfix (#92)

* Failing spec

* Fix the failing spec

* Fix rake spec
pull/84/head^2
Daniel Baark 3 years ago committed by GitHub
parent
commit
b787ad803f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 32
      app/helpers/check_answers_helper.rb
  2. 21
      app/helpers/tasklist_helper.rb
  3. 30
      app/models/form.rb
  4. 4
      app/views/case_logs/_tasklist.html.erb
  5. 10
      lib/tasks/form_definition.rake
  6. 9
      spec/factories/case_log.rb
  7. 27
      spec/helpers/tasklist_helper_spec.rb
  8. 2
      spec/lib/tasks/form_definition_validator_spec.rb

32
app/helpers/check_answers_helper.rb

@ -16,7 +16,7 @@ module CheckAnswersHelper
while page_name.to_s != "check_answers" && subsection_keys.include?(page_name) while page_name.to_s != "check_answers" && subsection_keys.include?(page_name)
questions = form.questions_for_page(page_name) questions = form.questions_for_page(page_name)
applicable_questions = filter_conditional_questions(questions, case_log) applicable_questions = form.filter_conditional_questions(questions, case_log)
total_questions = total_questions.merge(applicable_questions) total_questions = total_questions.merge(applicable_questions)
page_name = get_next_page_name(form, page_name, case_log) page_name = get_next_page_name(form, page_name, case_log)
@ -25,19 +25,6 @@ module CheckAnswersHelper
total_questions total_questions
end end
def filter_conditional_questions(questions, case_log)
applicable_questions = questions
questions.each do |k, question|
question.fetch("conditional_for", []).each do |conditional_question_key, condition|
if condition_not_met(case_log, k, question, condition)
applicable_questions = applicable_questions.reject { |z| z == conditional_question_key }
end
end
end
applicable_questions
end
def get_next_page_name(form, page_name, case_log) def get_next_page_name(form, page_name, case_log)
page = form.all_pages[page_name] page = form.all_pages[page_name]
if page.key?("conditional_route_to") if page.key?("conditional_route_to")
@ -50,23 +37,6 @@ module CheckAnswersHelper
form.next_page(page_name) form.next_page(page_name)
end end
def condition_not_met(case_log, question_key, question, condition)
case question["type"]
when "numeric"
operator = condition[/[<>=]+/].to_sym
operand = condition[/\d+/].to_i
case_log[question_key].blank? || !case_log[question_key].send(operator, operand)
when "text"
case_log[question_key].blank? || !condition.include?(case_log[question_key])
when "radio"
case_log[question_key].blank? || !condition.include?(case_log[question_key])
when "select"
case_log[question_key].blank? || !condition.include?(case_log[question_key])
else
raise "Not implemented yet"
end
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

21
app/helpers/tasklist_helper.rb

@ -13,31 +13,32 @@ module TasklistHelper
in_progress: "govuk-tag--blue", in_progress: "govuk-tag--blue",
}.freeze }.freeze
def get_subsection_status(subsection_name, case_log, questions) def get_subsection_status(subsection_name, case_log, form, questions)
applicable_questions = form.filter_conditional_questions(questions, case_log).keys
if subsection_name == "declaration" if subsection_name == "declaration"
return case_log.completed? ? :not_started : :cannot_start_yet return case_log.completed? ? :not_started : :cannot_start_yet
end end
return :not_started if questions.all? { |question| case_log[question].blank? } return :not_started if applicable_questions.all? { |question| case_log[question].blank? }
return :completed if questions.all? { |question| case_log[question].present? } return :completed if applicable_questions.all? { |question| case_log[question].present? }
:in_progress :in_progress
end end
def get_next_incomplete_section(form, case_log) def get_next_incomplete_section(form, case_log)
subsections = form.all_subsections.keys subsections = form.all_subsections.keys
subsections.find { |subsection| is_incomplete?(subsection, case_log, form.questions_for_subsection(subsection).keys) } subsections.find { |subsection| is_incomplete?(subsection, case_log, form, form.questions_for_subsection(subsection)) }
end end
def get_subsections_count(form, case_log, status = :all) def get_subsections_count(form, case_log, status = :all)
subsections = form.all_subsections.keys subsections = form.all_subsections.keys
return subsections.count if status == :all return subsections.count if status == :all
subsections.count { |subsection| get_subsection_status(subsection, case_log, form.questions_for_subsection(subsection).keys) == status } subsections.count { |subsection| get_subsection_status(subsection, case_log, form, form.questions_for_subsection(subsection)) == status }
end end
def get_first_page_or_check_answers(subsection, case_log, form, questions) def get_first_page_or_check_answers(subsection, case_log, form, questions)
path = if is_started?(subsection, case_log, questions) path = if is_started?(subsection, case_log, form, questions)
"case_log_#{subsection}_check_answers_path" "case_log_#{subsection}_check_answers_path"
else else
"case_log_#{form.first_page_for_subsection(subsection)}_path" "case_log_#{form.first_page_for_subsection(subsection)}_path"
@ -47,13 +48,13 @@ module TasklistHelper
private private
def is_incomplete?(subsection, case_log, questions) def is_incomplete?(subsection, case_log, form, questions)
status = get_subsection_status(subsection, case_log, questions) status = get_subsection_status(subsection, case_log, form, questions)
%i[not_started in_progress].include?(status) %i[not_started in_progress].include?(status)
end end
def is_started?(subsection, case_log, questions) def is_started?(subsection, case_log, form, questions)
status = get_subsection_status(subsection, case_log, questions) status = get_subsection_status(subsection, case_log, form, questions)
%i[in_progress completed].include?(status) %i[in_progress completed].include?(status)
end end
end end

30
app/models/form.rb

@ -97,6 +97,36 @@ class Form
}.reduce(:merge) }.reduce(:merge)
end end
def filter_conditional_questions(questions, case_log)
applicable_questions = questions
questions.each do |k, question|
question.fetch("conditional_for", []).each do |conditional_question_key, condition|
if condition_not_met(case_log, k, question, condition)
applicable_questions = applicable_questions.reject { |z| z == conditional_question_key }
end
end
end
applicable_questions
end
def condition_not_met(case_log, question_key, question, condition)
case question["type"]
when "numeric"
operator = condition[/[<>=]+/].to_sym
operand = condition[/\d+/].to_i
case_log[question_key].blank? || !case_log[question_key].send(operator, operand)
when "text"
case_log[question_key].blank? || !condition.include?(case_log[question_key])
when "radio"
case_log[question_key].blank? || !condition.include?(case_log[question_key])
when "select"
case_log[question_key].blank? || !condition.include?(case_log[question_key])
else
raise "Not implemented yet"
end
end
def get_answer_label(case_log, question_title) def get_answer_label(case_log, question_title)
question = all_questions[question_title] question = all_questions[question_title]
if question["type"] == "checkbox" if question["type"] == "checkbox"

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

@ -9,10 +9,10 @@
<ul class="app-task-list__items"> <ul class="app-task-list__items">
<% section_value["subsections"].map do |subsection_key, subsection_value| %> <% section_value["subsections"].map do |subsection_key, subsection_value| %>
<li class="app-task-list__item" id=<%= subsection_key %>> <li class="app-task-list__item" id=<%= subsection_key %>>
<% questions_for_subsection = @form.questions_for_subsection(subsection_key).keys %> <% questions_for_subsection = @form.questions_for_subsection(subsection_key) %>
<% next_page_path = get_first_page_or_check_answers(subsection_key, @case_log, @form, questions_for_subsection) %> <% next_page_path = get_first_page_or_check_answers(subsection_key, @case_log, @form, questions_for_subsection) %>
<%= link_to subsection_value["label"], next_page_path, class: "task-name govuk-link" %> <%= link_to subsection_value["label"], next_page_path, class: "task-name govuk-link" %>
<% subsection_status = get_subsection_status(subsection_key, @case_log, questions_for_subsection) %> <% subsection_status = get_subsection_status(subsection_key, @case_log, @form, questions_for_subsection) %>
<strong class="govuk-tag app-task-list__tag <%= TasklistHelper::STYLES[subsection_status] %>"> <strong class="govuk-tag app-task-list__tag <%= TasklistHelper::STYLES[subsection_status] %>">
<%= TasklistHelper::STATUSES[subsection_status] %> <%= TasklistHelper::STATUSES[subsection_status] %>
</strong> </strong>

10
lib/tasks/form_definition.rake

@ -32,12 +32,12 @@ namespace :form_definition do
schema = JSON.parse(file.read) schema = JSON.parse(file.read)
meta_schema = JSON::Validator.validator_for_name("draft4").metaschema meta_schema = JSON::Validator.validator_for_name("draft4").metaschema
puts path puts path unless Rails.env.test?
if JSON::Validator.validate(meta_schema, schema) if JSON::Validator.validate(meta_schema, schema)
puts "Schema Definition is Valid" puts "Schema Definition is Valid" unless Rails.env.test?
else else
puts "Schema Definition in #{path} is not valid against draft4 json schema." puts "Schema Definition in #{path} is not valid against draft4 json schema." unless Rails.env.test?
next next
end end
@ -45,8 +45,8 @@ namespace :form_definition do
file = File.open(path) file = File.open(path)
form_definition = JSON.parse(file.read) form_definition = JSON.parse(file.read)
puts path puts path unless Rails.env.test?
puts JSON::Validator.fully_validate(schema, form_definition, strict: true) puts JSON::Validator.fully_validate(schema, form_definition, strict: true) unless Rails.env.test?
begin begin
JSON::Validator.validate!(schema, form_definition) JSON::Validator.validate!(schema, form_definition)

9
spec/factories/case_log.rb

@ -19,6 +19,15 @@ FactoryBot.define do
earnings { 750 } earnings { 750 }
incfreq { "Weekly" } incfreq { "Weekly" }
end end
trait :conditional_section_complete do
tenant_code { "TH356" }
age1 { 34 }
sex1 { "M" }
ethnic { 2 }
national { 4 }
ecstat1 { 2 }
other_hhmemb { 0 }
end
created_at { Time.zone.now } created_at { Time.zone.now }
updated_at { Time.zone.now } updated_at { Time.zone.now }
end end

27
spec/helpers/tasklist_helper_spec.rb

@ -6,26 +6,27 @@ RSpec.describe TasklistHelper do
let(:completed_case_log) { FactoryBot.build(:case_log, :completed) } let(:completed_case_log) { FactoryBot.build(:case_log, :completed) }
form_handler = FormHandler.instance form_handler = FormHandler.instance
let(:form) { form_handler.get_form("test_form") } let(:form) { form_handler.get_form("test_form") }
let(:household_characteristics_questions) { form.questions_for_subsection("household_characteristics") }
describe "get subsection status" do describe "get subsection status" do
let(:section) { "income_and_benefits" } let(:section) { "income_and_benefits" }
let(:income_and_benefits_questions) { form.questions_for_subsection("income_and_benefits").keys } let(:income_and_benefits_questions) { form.questions_for_subsection("income_and_benefits") }
let(:declaration_questions) { form.questions_for_subsection("declaration").keys } let(:declaration_questions) { form.questions_for_subsection("declaration") }
let(:local_authority_questions) { form.questions_for_subsection("local_authority").keys } let(:local_authority_questions) { form.questions_for_subsection("local_authority") }
it "returns not started if none of the questions in the subsection are answered" do it "returns not started if none of the questions in the subsection are answered" do
status = get_subsection_status("income_and_benefits", case_log, income_and_benefits_questions) status = get_subsection_status("income_and_benefits", case_log, form, income_and_benefits_questions)
expect(status).to eq(:not_started) expect(status).to eq(:not_started)
end end
it "returns cannot start yet if the subsection is declaration" do it "returns cannot start yet if the subsection is declaration" do
status = get_subsection_status("declaration", case_log, declaration_questions) status = get_subsection_status("declaration", case_log, form, declaration_questions)
expect(status).to eq(:cannot_start_yet) expect(status).to eq(:cannot_start_yet)
end end
it "returns in progress if some of the questions have been answered" do it "returns in progress if some of the questions have been answered" do
case_log["previous_postcode"] = "P0 5TT" case_log["previous_postcode"] = "P0 5TT"
status = get_subsection_status("local_authority", case_log, local_authority_questions) status = get_subsection_status("local_authority", case_log, form, local_authority_questions)
expect(status).to eq(:in_progress) expect(status).to eq(:in_progress)
end end
@ -35,14 +36,22 @@ RSpec.describe TasklistHelper do
case_log["benefits"] = "All" case_log["benefits"] = "All"
case_log["hb"] = "Do not know" case_log["hb"] = "Do not know"
status = get_subsection_status("income_and_benefits", case_log, income_and_benefits_questions) status = get_subsection_status("income_and_benefits", case_log, form, income_and_benefits_questions)
expect(status).to eq(:completed) expect(status).to eq(:completed)
end end
it "returns not started if the subsection is declaration and all the questions are completed" do it "returns not started if the subsection is declaration and all the questions are completed" do
status = get_subsection_status("declaration", completed_case_log, declaration_questions) status = get_subsection_status("declaration", completed_case_log, form, declaration_questions)
expect(status).to eq(:not_started) expect(status).to eq(:not_started)
end end
let(:conditional_section_complete_case_log) { FactoryBot.build(:case_log, :conditional_section_complete) }
it "sets the correct status for sections with conditional questions" do
status = get_subsection_status(
"household_characteristics", conditional_section_complete_case_log, form, household_characteristics_questions
)
expect(status).to eq(:completed)
end
end end
describe "get next incomplete section" do describe "get next incomplete section" do
@ -79,8 +88,6 @@ RSpec.describe TasklistHelper do
end end
describe "get_first_page_or_check_answers" do describe "get_first_page_or_check_answers" do
let(:household_characteristics_questions) { form.questions_for_subsection("household_characteristics").keys }
it "returns the check answers page path if the section has been started already" do it "returns the check answers page path if the section has been started already" do
expect(get_first_page_or_check_answers("household_characteristics", case_log, form, household_characteristics_questions)).to match(/check_answers/) expect(get_first_page_or_check_answers("household_characteristics", case_log, form, household_characteristics_questions)).to match(/check_answers/)
end end

2
spec/lib/tasks/form_definition_validator_spec.rb

@ -27,7 +27,7 @@ describe "rake form_definition:validate", type: :task do
end end
it "runs the validate task for the given form definition" do it "runs the validate task for the given form definition" do
expect(JSON::Validator).to receive(:validate!).at_least(2).times expect(JSON::Validator).to receive(:validate!).at_least(1).time
task.invoke("config/forms/2021_2022.json") task.invoke("config/forms/2021_2022.json")
end end
end end

Loading…
Cancel
Save