Phil Lee
2 years ago
15 changed files with 312 additions and 178 deletions
@ -0,0 +1,136 @@
|
||||
class Answer |
||||
attr_reader :question, :log |
||||
|
||||
delegate :type, to: :question |
||||
delegate :id, to: :question |
||||
delegate :answer_options, to: :question |
||||
delegate :prefix, to: :question |
||||
delegate :suffix, to: :question |
||||
delegate :inferred_check_answers_value, to: :question |
||||
delegate :inferred_answers, to: :question |
||||
|
||||
delegate :page, to: :question |
||||
delegate :subsection, to: :page |
||||
delegate :form, to: :subsection |
||||
|
||||
def initialize(question:, log:) |
||||
@question = question |
||||
@log = log |
||||
end |
||||
|
||||
def answer_label |
||||
return checkbox_answer_label if checkbox? |
||||
return log[id]&.to_formatted_s(:govuk_date).to_s if date? |
||||
|
||||
answer = label_from_value(log[id]) if log[id].present? |
||||
answer_label = [prefix, format_value(answer), suffix_label].join("") if answer |
||||
|
||||
inferred = inferred_check_answers_value["value"] if inferred_check_answers_value && has_inferred_check_answers_value? |
||||
|
||||
return inferred if inferred.present? |
||||
|
||||
answer_label |
||||
end |
||||
|
||||
def suffix_label |
||||
return "" unless suffix |
||||
return suffix if suffix.is_a?(String) |
||||
|
||||
label = "" |
||||
|
||||
suffix.each do |s| |
||||
condition = s["depends_on"] |
||||
next unless condition |
||||
|
||||
answer = log.send(condition.keys.first) |
||||
if answer == condition.values.first |
||||
label = s["label"] |
||||
end |
||||
end |
||||
label |
||||
end |
||||
|
||||
def completed? |
||||
return answer_options.keys.any? { |key| value_is_yes?(log[key]) } if checkbox? |
||||
|
||||
log[id].present? || !log.respond_to?(id.to_sym) || has_inferred_display_value? |
||||
end |
||||
|
||||
def get_inferred_answers |
||||
return [] unless inferred_answers |
||||
|
||||
enabled_inferred_answers(inferred_answers).keys.map do |question_id| |
||||
question = form.get_question(question_id, log) |
||||
if question.present? |
||||
question.label_from_value(log[question_id]) |
||||
else |
||||
Array(question_id.to_s.split(".")).inject(log) { |l, method| l.present? ? l.public_send(*method) : "" } |
||||
end |
||||
end |
||||
end |
||||
|
||||
private |
||||
|
||||
def enabled_inferred_answers(inferred_answers) |
||||
inferred_answers.filter { |_key, value| value.all? { |condition_key, condition_value| log[condition_key] == condition_value } } |
||||
end |
||||
|
||||
def has_inferred_display_value? |
||||
inferred_check_answers_value.present? && log[inferred_check_answers_value["condition"].keys.first] == inferred_check_answers_value["condition"].values.first |
||||
end |
||||
|
||||
def has_inferred_check_answers_value? |
||||
return true if selected_answer_option_is_derived? |
||||
return inferred_check_answers_value["condition"].values[0] == log[inferred_check_answers_value["condition"].keys[0]] if inferred_check_answers_value.present? |
||||
|
||||
false |
||||
end |
||||
|
||||
def selected_answer_option_is_derived? |
||||
selected_option = answer_options&.dig(log[id].to_s.presence) |
||||
selected_option.is_a?(Hash) && selected_option["depends_on"] && form.depends_on_met(selected_option["depends_on"], log) |
||||
end |
||||
|
||||
def format_value(answer_label) |
||||
if prefix == "£" |
||||
ActionController::Base.helpers.number_to_currency(answer_label, delimiter: ",", format: "%n") |
||||
else |
||||
answer_label |
||||
end |
||||
end |
||||
|
||||
def label_from_value(value) |
||||
question.label_from_value(value) |
||||
end |
||||
|
||||
def checkbox? |
||||
question.type == "checkbox" |
||||
end |
||||
|
||||
def date? |
||||
question.type == "date" |
||||
end |
||||
|
||||
def checkbox_answer_label |
||||
answer = [] |
||||
return "Yes" if declaration? && value_is_yes?(log["declaration"]) |
||||
|
||||
answer_options.each { |key, options| value_is_yes?(log[key]) ? answer << options["value"] : nil } |
||||
answer.join(", ") |
||||
end |
||||
|
||||
def declaration? |
||||
question.id == "declaration" |
||||
end |
||||
|
||||
def value_is_yes?(value) |
||||
case type |
||||
when "checkbox" |
||||
value == 1 |
||||
when "radio" |
||||
RADIO_YES_VALUE[id.to_sym]&.include?(value) |
||||
else |
||||
%w[yes].include?(value.downcase) |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,115 @@
|
||||
require "rails_helper" |
||||
|
||||
RSpec.describe Answer, type: :model do |
||||
subject(:answer) { described_class.new(question:, log:) } |
||||
|
||||
let(:log) { FactoryBot.build(:lettings_log, :in_progress) } |
||||
let(:form) { log.form } |
||||
let(:question_id) { "incfreq" } |
||||
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) } |
||||
let(:subsection_id) { "income_and_benefits" } |
||||
let(:subsection_definition) { section_definition["subsections"][subsection_id] } |
||||
let(:subsection) { Form::Subsection.new(subsection_id, subsection_definition, section) } |
||||
let(:page_definition) { subsection_definition["pages"][page_id] } |
||||
let(:question_definition) { page_definition["questions"][question_id] } |
||||
let(:page) { Form::Page.new(page_id, page_definition, subsection) } |
||||
let(:page_id) { "net_income" } |
||||
let(:question) { Form::Question.new(question_id, question_definition, page) } |
||||
|
||||
describe "#answer_label" do |
||||
context "with a lettings log" do |
||||
it "has an answer label" do |
||||
log.incfreq = 1 |
||||
|
||||
expect(answer.answer_label).to eql("Weekly") |
||||
end |
||||
end |
||||
|
||||
context "when type is date" do |
||||
let(:section_id) { "local_authority" } |
||||
let(:subsection_id) { "local_authority" } |
||||
let(:page_id) { "property_major_repairs" } |
||||
let(:question_id) { "mrcdate" } |
||||
|
||||
it "displays a formatted answer label" do |
||||
log.mrcdate = Time.zone.local(2021, 10, 11) |
||||
expect(answer.answer_label).to eql("11 October 2021") |
||||
end |
||||
|
||||
it "can handle nils" do |
||||
log.mrcdate = nil |
||||
expect(answer.answer_label).to eql("") |
||||
end |
||||
end |
||||
|
||||
context "when type is checkbox" do |
||||
let(:section_id) { "household" } |
||||
let(:subsection_id) { "household_needs" } |
||||
let(:page_id) { "accessibility_requirements" } |
||||
let(:question_id) { "accessibility_requirements" } |
||||
|
||||
it "has a joined answers label" do |
||||
log.housingneeds_a = 1 |
||||
log.housingneeds_c = 1 |
||||
expected_answer_label = "Fully wheelchair accessible housing, Level access housing" |
||||
expect(answer.answer_label).to eql(expected_answer_label) |
||||
end |
||||
end |
||||
|
||||
context "when answers have a suffix dependent on another answer" do |
||||
let(:section_id) { "rent_and_charges" } |
||||
let(:subsection_id) { "income_and_benefits" } |
||||
let(:page_id) { "net_income" } |
||||
let(:question_id) { "earnings" } |
||||
|
||||
it "displays the correct label for given suffix and answer the suffix depends on" do |
||||
log.incfreq = 1 |
||||
log.earnings = 500 |
||||
expect(answer.answer_label).to eql("£500.00 every week") |
||||
log.incfreq = 2 |
||||
expect(answer.answer_label).to eql("£500.00 every month") |
||||
log.incfreq = 3 |
||||
expect(answer.answer_label).to eql("£500.00 every year") |
||||
end |
||||
end |
||||
|
||||
context "with inferred_check_answers_value" do |
||||
context "when Lettings form" do |
||||
let(:section_id) { "household" } |
||||
let(:subsection_id) { "household_needs" } |
||||
let(:page_id) { "armed_forces" } |
||||
let(:question_id) { "armedforces" } |
||||
|
||||
it "returns the inferred label value" do |
||||
log.armedforces = 3 |
||||
expect(answer.answer_label).to eql("Prefers not to say") |
||||
end |
||||
end |
||||
|
||||
context "when Sales form" do |
||||
let(:log) { FactoryBot.create(:sales_log, :completed, ethnic_group: 17) } |
||||
let(:question) { log.form.get_question("ethnic_group", log) } |
||||
|
||||
it "returns the inferred label value" do |
||||
expect(answer.answer_label).to eql("Prefers not to say") |
||||
end |
||||
end |
||||
end |
||||
end |
||||
|
||||
describe "#completed?" do |
||||
context "when the question has inferred value only for check answers display" do |
||||
let(:section_id) { "tenancy_and_property" } |
||||
let(:subsection_id) { "property_information" } |
||||
let(:page_id) { "property_postcode" } |
||||
let(:question_id) { "postcode_full" } |
||||
|
||||
it "returns true" do |
||||
log["postcode_known"] = 0 |
||||
expect(answer.completed?).to be(true) |
||||
end |
||||
end |
||||
end |
||||
end |
Loading…
Reference in new issue