Skip to content

Commit 8de9b5a

Browse files
committed
Convert selection questions to use English value
Change selection questions to use value as the selection attribute and modify show to use name based on the value. This is the main change to the codebase to support routing in Welsh forms. Selection questions now store the English text in the value attribute and the Welsh text in the name attribute. Because routing is based on the English value all forms of routing will continue to work in both languages. We change how the selection question is displayed in the check your answers page to use the Welsh value, if the locale is Welsh. Submissions use the English FormDocument, so CSVs and JSONs should produce the same results in both languages. We update tests to reflect the fact all selection options should have name and value fields.
1 parent 090b293 commit 8de9b5a

File tree

6 files changed

+51
-33
lines changed

6 files changed

+51
-33
lines changed

app/components/question/selection_component/view.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,14 @@ def none_of_the_above_question_text
6868
end
6969

7070
def radio_button_options
71-
question.answer_settings.selection_options.map.with_index do |option, index|
72-
form_builder.govuk_radio_button :selection, option.name, label: { text: option.name }, link_errors: index.zero?
71+
question.selection_options_with_none_of_the_above.map.with_index do |option, index|
72+
form_builder.govuk_radio_button :selection, option.value, label: { text: option.name }, link_errors: index.zero?
7373
end
7474
end
7575

7676
def checkbox_options
7777
question.answer_settings.selection_options.map.with_index do |option, index|
78-
form_builder.govuk_check_box :selection, option.name, label: { text: option.name }, link_errors: index.zero?
78+
form_builder.govuk_check_box :selection, option.value, label: { text: option.name }, link_errors: index.zero?
7979
end
8080
end
8181
end

app/models/question/selection.rb

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ def allow_multiple_answers?
1919
end
2020

2121
def show_answer
22-
return selection_without_blanks.join(", ") if allow_multiple_answers?
22+
return selection_without_blanks.map { |selected| name_from_value(selected) }.join(", ") if allow_multiple_answers?
2323

24-
selection
24+
selection_name
2525
end
2626

2727
def show_answer_in_email
@@ -39,6 +39,20 @@ def show_answer_in_json(*)
3939
hash
4040
end
4141

42+
def selection_name
43+
return nil if selection.nil?
44+
return "" if selection.blank?
45+
46+
name_from_value(selection)
47+
end
48+
49+
# Show the selection option name, which can be different to the value. Value
50+
# should stay the same across FormDocuments in different languages.
51+
def name_from_value(selected)
52+
@options_by_value ||= answer_settings.selection_options.index_by(&:value)
53+
@options_by_value[selected]&.name
54+
end
55+
4256
def show_optional_suffix
4357
false
4458
end
@@ -66,11 +80,11 @@ def clear_none_of_the_above_answer_if_not_selected
6680
end
6781

6882
def allowed_options
69-
selection_options_with_none_of_the_above.map(&:name)
83+
selection_options_with_none_of_the_above.map(&:value)
7084
end
7185

7286
def none_of_the_above_option
73-
OpenStruct.new(name: I18n.t("page.none_of_the_above"))
87+
OpenStruct.new(name: I18n.t("page.none_of_the_above"), value: I18n.t("page.none_of_the_above"))
7488
end
7589

7690
def selection_without_blanks

spec/components/question/selection_component/view_spec.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@
5555
let(:question) { build :single_selection_question, is_optional:, selection_options: }
5656

5757
let(:selection_options) do
58-
Array.new(30).map { |_index| OpenStruct.new(name: Faker::Lorem.sentence) }
58+
option_text = Faker::Lorem.sentence
59+
Array.new(30).map { |_index| OpenStruct.new(name: option_text, value: option_text) }
5960
end
6061

6162
it "renders the question text as a heading" do

spec/factories/v2_step.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
trait :with_selections_settings do
4545
transient do
4646
only_one_option { "true" }
47-
selection_options { [{ name: "Option 1" }, { name: "Option 2" }] }
47+
selection_options { [{ name: "Option 1", value: "Option 1" }, { name: "Option 2", value: "Option 2" }] }
4848
end
4949

5050
answer_type { "selection" }

spec/features/fill_in_autocomplete_question_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
require "rails_helper"
22

33
feature "Fill in and submit a form with an autocomplete question", type: :feature do
4-
let(:steps) { [(build :v2_question_page_step, :with_selections_settings, id: 1, routing_conditions: [], question_text:, selection_options:)] }
4+
let(:steps) { [build(:v2_question_page_step, :with_selections_settings, id: 1, routing_conditions: [], question_text:, selection_options:)] }
55
let(:form) { build :v2_form_document, :live?, form_id: 1, name: "Fill in this form", steps:, start_page: 1 }
6-
let(:selection_options) { Array.new(31).each_with_index.map { |_element, index| { name: "Answer #{index}" } } }
6+
let(:selection_options) { Array.new(31).each_with_index.map { |_element, index| { name: "Answer #{index}", value: "Answer #{index}" } } }
77
let(:question_text) { Faker::Lorem.question }
88
let(:answer_text) { "Answer 1" }
99
let(:reference) { Faker::Alphanumeric.alphanumeric(number: 8).upcase }

spec/models/question/selection_spec.rb

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
RSpec.describe Question::Selection, type: :model do
44
subject(:question) { build :selection, only_one_option:, selection_options:, is_optional:, question_text: }
55

6-
let(:selection_options) { [OpenStruct.new({ name: "option 1" }), OpenStruct.new({ name: "option 2" })] }
6+
# We use different values for name and value to make it clear which is which in the tests.
7+
# Name would be the text in current locale and value doesn't change between locales.
8+
# For English forms they would be the same, but for Welsh forms they would be different.
9+
let(:selection_options) { [OpenStruct.new({ name: "display option 1", value: "option 1" }), OpenStruct.new({ name: "display option 2", value: "option 2" })] }
710
let(:is_optional) { false }
811
let(:only_one_option) { "false" }
912
let(:question_text) { Faker::Lorem.question }
@@ -64,21 +67,21 @@
6467

6568
context "when selection has a value" do
6669
before do
67-
question.selection = %w[something]
70+
question.selection = ["option 1"]
6871
end
6972

7073
it "shows the answer" do
71-
expect(question.show_answer).to eq("something")
74+
expect(question.show_answer).to eq("display option 1")
7275
end
7376

7477
it "shows the answer in show_answer_in_csv" do
75-
expect(question.show_answer_in_csv).to eq(Hash[question_text, "something"])
78+
expect(question.show_answer_in_csv).to eq(Hash[question_text, "display option 1"])
7679
end
7780

7881
it "returns a hash for show_answer_in_json" do
7982
expect(question.show_answer_in_json).to eq({
80-
selections: %w[something],
81-
answer_text: "something",
83+
selections: ["option 1"],
84+
answer_text: "display option 1",
8285
})
8386
end
8487
end
@@ -152,21 +155,21 @@
152155

153156
context "when selection has a value" do
154157
before do
155-
question.selection = %w[something]
158+
question.selection = ["option 1"]
156159
end
157160

158161
it "shows the answer" do
159-
expect(question.show_answer).to eq("something")
162+
expect(question.show_answer).to eq("display option 1")
160163
end
161164

162165
it "shows the answer in show_answer_in_csv" do
163-
expect(question.show_answer_in_csv).to eq(Hash[question_text, "something"])
166+
expect(question.show_answer_in_csv).to eq(Hash[question_text, "display option 1"])
164167
end
165168

166169
it "returns a hash for show_answer_in_json" do
167170
expect(question.show_answer_in_json).to eq({
168-
selections: %w[something],
169-
answer_text: "something",
171+
selections: ["option 1"],
172+
answer_text: "display option 1",
170173
})
171174
end
172175
end
@@ -210,20 +213,20 @@
210213

211214
context "when selection has a value" do
212215
before do
213-
question.selection = "something"
216+
question.selection = "option 1"
214217
end
215218

216219
it "shows the answer" do
217-
expect(question.show_answer).to eq("something")
220+
expect(question.show_answer).to eq("display option 1")
218221
end
219222

220223
it "shows the answer in show_answer_in_csv" do
221-
expect(question.show_answer_in_csv).to eq(Hash[question_text, "something"])
224+
expect(question.show_answer_in_csv).to eq(Hash[question_text, "display option 1"])
222225
end
223226

224227
it "returns a hash for show_answer_in_json" do
225228
expect(question.show_answer_in_json).to eq({
226-
answer_text: "something",
229+
answer_text: "display option 1",
227230
})
228231
end
229232
end
@@ -280,20 +283,20 @@
280283

281284
context "when selection has a value" do
282285
before do
283-
question.selection = "something"
286+
question.selection = "option 1"
284287
end
285288

286289
it "shows the answer" do
287-
expect(question.show_answer).to eq("something")
290+
expect(question.show_answer).to eq("display option 1")
288291
end
289292

290293
it "shows the answer in show_answer_in_csv" do
291-
expect(question.show_answer_in_csv).to eq(Hash[question_text, "something"])
294+
expect(question.show_answer_in_csv).to eq(Hash[question_text, "display option 1"])
292295
end
293296

294297
it "returns a hash for show_answer_in_json" do
295298
expect(question.show_answer_in_json).to eq({
296-
answer_text: "something",
299+
answer_text: "display option 1",
297300
})
298301
end
299302
end
@@ -430,7 +433,7 @@
430433

431434
describe "#selection_options_with_none_of_the_above" do
432435
let(:only_one_option) { "true" }
433-
let(:none_of_the_above_option) { OpenStruct.new(name: I18n.t("page.none_of_the_above")) }
436+
let(:none_of_the_above_option) { OpenStruct.new(name: I18n.t("page.none_of_the_above"), value: I18n.t("page.none_of_the_above")) }
434437

435438
context "when the user can select 'None of the above'" do
436439
let(:is_optional) { true }
@@ -463,15 +466,15 @@
463466

464467
describe "#autocomplete_component?" do
465468
context "when there are 30 selection options" do
466-
let(:selection_options) { Array.new(30).map { |_index| OpenStruct.new(name: Faker::Lorem.sentence) } }
469+
let(:selection_options) { Array.new(30).map { |_index| OpenStruct.new(name: Faker::Lorem.sentence, value: Faker::Lorem.sentence) } }
467470

468471
it "returns false" do
469472
expect(question.autocomplete_component?).to be false
470473
end
471474
end
472475

473476
context "when there are more than 30 selection options" do
474-
let(:selection_options) { Array.new(31).map { |_index| OpenStruct.new(name: Faker::Lorem.sentence) } }
477+
let(:selection_options) { Array.new(31).map { |_index| OpenStruct.new(name: Faker::Lorem.sentence, value: Faker::Lorem.sentence) } }
475478

476479
it "returns true" do
477480
expect(question.autocomplete_component?).to be true

0 commit comments

Comments
 (0)