From 1562c70ac1c5534276d1646884ce62066bb54fd0 Mon Sep 17 00:00:00 2001 From: Samuel Culley Date: Thu, 30 Apr 2026 09:58:40 +0100 Subject: [PATCH] Display multiple branches on add/edit page This is based on the Group's multiple_branches_enabled feature flag - so if this is toggled off, then it will use the original add and edit page view. When the flag is turned on for the group, the display logic assumes that the form has been created using the new Routes process, and will not be particularly compatible with forms that have been created using the old routing pages (although it might work if the routing is relatively simple). There is no validation displayed for these changes, as we're not ready to start deciding how to validate the new multiple-branch routes. --- .../page_list_component/view.html.erb | 66 ++++++++++----- app/components/page_list_component/view.rb | 8 ++ app/views/pages/index.html.erb | 4 +- config/locales/en.yml | 3 + .../page_list_component_preview.rb | 10 +-- .../page_list_component/view_spec.rb | 83 +++++++++++++++++-- spec/views/pages/index.html.erb_spec.rb | 2 +- 7 files changed, 142 insertions(+), 34 deletions(-) diff --git a/app/components/page_list_component/view.html.erb b/app/components/page_list_component/view.html.erb index 9cdccdd8de..3855f1ab29 100644 --- a/app/components/page_list_component/view.html.erb +++ b/app/components/page_list_component/view.html.erb @@ -32,33 +32,57 @@ - <% page.routing_conditions.each do |condition| %> - <% condition_page = self.condition_page(condition) %> - <% condition_page_position = self.condition_page_position(condition) %> -
"> + <% if @form.group.multiple_branches_enabled? && page.routing_conditions.present? %> +
- <%= t("page_conditions.condition_name", question_number: condition_page_position) %> + <%= t("page_conditions.condition_name", question_number: page.position) %>
-
-
    - <% condition.validation_errors.each do |error| %> -
  • - <%= PageListComponent::ErrorSummary::View.generate_error_message(error.name, condition:, page: condition_page) %> -
  • - <% end %> -
- -

- <%= condition_description(condition) %> -

- -
- <%= govuk_link_to show_routes_path(form_id: @form.id, page_id: condition.check_page_id) do %> - <%= t("forms.form_overview.edit_with_visually_hidden_text_html", visually_hidden_text: t("page_conditions.condition_name", question_number: condition_page_position)) %> + <% if page.routing_conditions.first.answer_value.present? %> +

<%= I18n.t("page_conditions.if_answer_is") %>

+
    + <% page.routing_conditions.each do |condition| %> +
  • + <%= branch_condition_description(condition) %> +
  • + <% end %> +
+ <% else %> +

+ <%= branch_condition_description(page.routing_conditions.first) %> +

<% end %>
+ <% else %> + <% page.routing_conditions.each do |condition| %> + <% condition_page = self.condition_page(condition) %> + <% condition_page_position = self.condition_page_position(condition) %> +
"> +
+ <%= t("page_conditions.condition_name", question_number: condition_page_position) %> +
+ +
+
    + <% condition.validation_errors.each do |error| %> +
  • + <%= PageListComponent::ErrorSummary::View.generate_error_message(error.name, condition:, page: condition_page) %> +
  • + <% end %> +
+ +

+ <%= condition_description(condition) %> +

+ +
+ <%= govuk_link_to show_routes_path(form_id: @form.id, page_id: condition.check_page_id) do %> + <%= t("forms.form_overview.edit_with_visually_hidden_text_html", visually_hidden_text: t("page_conditions.condition_name", question_number: condition_page_position)) %> + <% end %> +
+
+ <% end %> <% end %> <% end %> diff --git a/app/components/page_list_component/view.rb b/app/components/page_list_component/view.rb index 86cd04f353..6db1adef91 100644 --- a/app/components/page_list_component/view.rb +++ b/app/components/page_list_component/view.rb @@ -28,6 +28,14 @@ def condition_description(condition) end end + def branch_condition_description(condition) + if condition.answer_value.present? + I18n.t("page_conditions.branch_condition_description", goto_page_question_text: goto_page_text_for_condition(condition), answer_value: answer_value_text_for_condition(condition)) + else + I18n.t("page_conditions.unconditional_description", goto_page_question_text: goto_page_text_for_condition(condition)) + end + end + def condition_check_page_text(condition) check_page = @pages.find { |page| page.id == condition.check_page_id } I18n.t("page_conditions.condition_check_page_text", check_page_question_text: check_page.question_text) diff --git a/app/views/pages/index.html.erb b/app/views/pages/index.html.erb index f98839923f..85c96863f1 100644 --- a/app/views/pages/index.html.erb +++ b/app/views/pages/index.html.erb @@ -4,7 +4,9 @@
- <%= render PageListComponent::ErrorSummary::View.new(current_form) %> + <% unless current_form.group.multiple_branches_enabled? %> + <%= render PageListComponent::ErrorSummary::View.new(current_form) %> + <% end %>

<%= current_form.name %> - diff --git a/config/locales/en.yml b/config/locales/en.yml index 7690e44d89..f4e5147561 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1358,6 +1358,7 @@ en: If you pasted the web address, check you copied the entire address. title: Page not found page_conditions: + branch_condition_description: "%{answer_value} go to %{goto_page_question_text}" condition_answer_value_text: "“%{answer_value}”" condition_answer_value_text_with_errors: "[Answer not selected]" condition_check_page_text: "“%{check_page_question_text}”" @@ -1376,10 +1377,12 @@ en: end_of_form: End of form exit_page: Add an exit page exit_page_label: An ‘exit page’ to leave the form + if_answer_is: 'If the answer is:' none_of_the_above: None of the above route: Route secondary_skip_description: After %{check_page_question_text} go to %{goto_page_question_text} skip_condition_route_page_text: "%{route_page_question_number}, “%{route_page_question_text}”" + unconditional_description: Go to %{goto_page_question_text} page_route_card: any_other_answer: Route for any other answer conditional_answer_value: "%{answer_value}" diff --git a/spec/components/page_list_component/page_list_component_preview.rb b/spec/components/page_list_component/page_list_component_preview.rb index 5efd5bd837..84d0a7d52e 100644 --- a/spec/components/page_list_component/page_list_component_preview.rb +++ b/spec/components/page_list_component/page_list_component_preview.rb @@ -3,7 +3,7 @@ class PageListComponent::PageListComponentPreview < ViewComponent::Preview def default pages = [] - form = build(:form, id: 0, pages:) + form = build(:form, :with_group, id: 0, pages:) render(PageListComponent::View.new(pages:, form:)) end @@ -11,7 +11,7 @@ def with_pages_and_no_conditions pages = [build(:page, id: 1, position: 1, question_text: "Enter your name", routing_conditions: []), build(:page, id: 2, position: 2, question_text: "What is your pet's phone number?", routing_conditions: []), build(:page, id: 3, position: 3, question_text: "How many pets do you own?", routing_conditions: [])] - form = build(:form, id: 0, pages:) + form = build(:form, :with_group, id: 0, pages:) render(PageListComponent::View.new(pages:, form:)) end @@ -20,7 +20,7 @@ def with_pages_and_one_condition pages = [build(:page, id: 1, position: 1, question_text: "Enter your name", routing_conditions: [condition]), build(:page, id: 2, position: 2, question_text: "What is your pet's phone number?", routing_conditions: []), build(:page, id: 3, position: 3, question_text: "How many pets do you own?", routing_conditions: [])] - form = build(:form, id: 0, pages:) + form = build(:form, :with_group, id: 0, pages:) # We need to build the records rather than create them so that we don't save them to the database when we view the # preview. However, this means that the associations aren't available so we need to manually set the associations @@ -41,7 +41,7 @@ def with_pages_and_multiple_conditions pages = [(build :page, id: 1, position: 1, question_text: "Enter your name", routing_conditions: routing_conditions_1), (build :page, id: 2, position: 2, question_text: "What is your pet's phone number?", routing_conditions: routing_conditions_2), (build :page, id: 3, position: 3, question_text: "How many pets do you own?", routing_conditions: [])] - form = build(:form, id: 0, pages:) + form = build(:form, :with_group, id: 0, pages:) # We need to build the records rather than create them so that we don't save them to the database when we view the # preview. However, this means that the associations aren't available so we need to manually set the associations @@ -65,7 +65,7 @@ def with_pages_and_conditions_with_errors pages = [(build :page, id: 1, position: 1, question_text: "Enter your name", routing_conditions: routing_conditions_1), (build :page, id: 2, position: 2, question_text: "What is your pet's phone number?", routing_conditions: routing_conditions_2), (build :page, id: 3, position: 3, question_text: "How many pets do you own?", routing_conditions: [])] - form = build(:form, id: 1, pages:) + form = build(:form, :with_group, id: 1, pages:) # We need to build the records rather than create them so that we don't save them to the database when we view the # preview. However, this means that the associations aren't available so we need to manually set the associations diff --git a/spec/components/page_list_component/view_spec.rb b/spec/components/page_list_component/view_spec.rb index 35ffd05979..32f948c681 100644 --- a/spec/components/page_list_component/view_spec.rb +++ b/spec/components/page_list_component/view_spec.rb @@ -1,7 +1,7 @@ require "rails_helper" RSpec.describe PageListComponent::View, type: :component do - let(:form) { create :form } + let(:form) { create :form, :with_group } let(:pages) { form.reload.pages } let(:page_list_component) { described_class.new(pages:, form:) } @@ -46,7 +46,7 @@ end context "when the form has multiple pages" do - let(:form) { create :form, :with_pages } + let(:form) { create :form, :with_pages, :with_group } let(:first_page) { form.pages.first } let(:second_page) { form.pages.second } @@ -79,7 +79,7 @@ end context "when the form has conditions" do - let(:form) { create :form, :ready_for_routing } + let(:form) { create :form, :ready_for_routing, :with_group } let(:edit_condition_path) { "/forms/0/pages/1/conditions/1" } context "when the page has a single condition" do @@ -144,7 +144,7 @@ end context "when the form has a valid branch route" do - let(:form) { create :form, :ready_for_routing } + let(:form) { create :form, :ready_for_routing, :with_group } let!(:secondary_skip_condition) { create :condition, routing_page_id: pages.second.id, check_page_id: pages.first.id, answer_value: nil, goto_page_id: pages.fourth.id } before do @@ -164,7 +164,7 @@ end context "when the form has a branch route with an error" do - let(:form) { create :form, :ready_for_routing } + let(:form) { create :form, :ready_for_routing, :with_group } before do create :condition, routing_page_id: pages.first.id, check_page_id: pages.first.id, answer_value: "Option 1", goto_page_id: pages.third.id @@ -183,7 +183,7 @@ end describe "class methods" do - let(:form) { create :form, :with_pages } + let(:form) { create :form, :with_pages, :with_group } describe "show_up_button" do it "returns false when index is 0" do @@ -322,5 +322,76 @@ end end end + + describe "#branch_condition_description" do + context "when condition has all values set" do + let(:condition) do + create( + :condition, + routing_page_id: pages.first.id, + check_page_id: pages.first.id, + answer_value: "Option 1", + goto_page_id: pages.third.id, + ) + end + + it "returns complete condition description" do + expected_text = "“#{condition.answer_value}” go to #{pages.third.position}, “#{pages.third.question_text}”" + expect(page_list_component.branch_condition_description(condition)).to eq(expected_text) + end + end + + context "when answer value is 'none_of_the_above'" do + let(:condition) do + create( + :condition, + routing_page_id: pages.first.id, + check_page_id: pages.first.id, + answer_value: "none_of_the_above", + goto_page_id: pages.third.id, + ) + end + + it "returns description with 'None of the above' text" do + expected_text = "“None of the above” go to #{pages.third.position}, “#{pages.third.question_text}”" + expect(page_list_component.branch_condition_description(condition)).to eq(expected_text) + end + end + + context "when skip_to_end is true" do + let(:condition) do + create( + :condition, + routing_page_id: pages.first.id, + check_page_id: pages.first.id, + answer_value: "Option 1", + goto_page_id: nil, + skip_to_end: true, + ) + end + + it "returns description with 'Check your answers' text" do + expected_text = "“#{condition.answer_value}” go to end of form." + expect(page_list_component.branch_condition_description(condition)).to eq(expected_text) + end + end + + context "when showing an unconditional route" do + let(:condition) do + create( + :condition, + routing_page_id: pages.second.id, + check_page_id: pages.first.id, + answer_value: nil, + goto_page_id: pages.fourth.id, + ) + end + + it "returns correct description" do + expected_text = "Go to #{pages.fourth.position}, “#{pages.fourth.question_text}”" + expect(page_list_component.branch_condition_description(condition)).to eq(expected_text) + end + end + end end end diff --git a/spec/views/pages/index.html.erb_spec.rb b/spec/views/pages/index.html.erb_spec.rb index ce38b3f482..3b9d1189b6 100644 --- a/spec/views/pages/index.html.erb_spec.rb +++ b/spec/views/pages/index.html.erb_spec.rb @@ -1,7 +1,7 @@ require "rails_helper" describe "pages/index.html.erb" do - let(:form) { create :form, pages: } + let(:form) { create :form, :with_group, pages: } let(:pages) { [] } let(:mark_complete_input) { Forms::MarkPagesSectionCompleteInput.new(form:).assign_form_values }