From 77276384a35276deedda202ba71df0ab1397c1c2 Mon Sep 17 00:00:00 2001 From: Thomas Iles Date: Tue, 28 Apr 2026 16:58:05 +0100 Subject: [PATCH 1/4] Remove broken test view spec for pages/index We are mocking the path helpers in the view spec for pages/index.html.erb. But testing against the actual path helpers. This was covering an assertion that the view when there are no pages doesn't display the link to add a route. The page does display the link to add a route, whether there are pages or not. The current spec was passing because the test was using the real path helper which the mock didn't match. This commit removes the test. The "Add a route" link is always displayed. When the test was written it probably wasn't supposed to show. Following the link now shows a page explaining how to add a route. --- spec/views/pages/index.html.erb_spec.rb | 31 +++++++------------------ 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/spec/views/pages/index.html.erb_spec.rb b/spec/views/pages/index.html.erb_spec.rb index 817f024a29..96f5694f5b 100644 --- a/spec/views/pages/index.html.erb_spec.rb +++ b/spec/views/pages/index.html.erb_spec.rb @@ -6,35 +6,24 @@ let(:mark_complete_input) { Forms::MarkPagesSectionCompleteInput.new(form:).assign_form_values } before do - # mock the path helper - without_partial_double_verification do - allow(view).to receive_messages( - form_path: "/forms/1", - type_of_answer_new_path: "/forms/1/pages/new/type-of-answer", - edit_question_path: "/forms/1/pages/2/edit/question", - form_pages_path: "/forms/1/pages", - routing_page_path: "/forms/1/new-condition", - current_form: form, - ) - end assign(:pages, pages) assign(:mark_complete_input, mark_complete_input) - render template: "pages/index" + render template: "pages/index", locals: { current_form: form } end it "has the correct title" do expect(view.content_for(:title)).to eq I18n.t("pages.index.title") end - describe "when there are no pages to display" do - it "allows the user to add a page" do - expect(rendered).to have_link(I18n.t("pages.index.add_question"), href: start_new_question_path(form.id)) - end + it "allows the user to add a page" do + expect(rendered).to have_link(I18n.t("pages.index.add_question"), href: start_new_question_path(form.id)) + end - it "does not contain a link to add page routing" do - expect(rendered).not_to have_link("Add a question route", href: routing_page_path(form.id)) - end + it "has a link to branch routing page" do + expect(rendered).to have_link("Add a question route", href: routing_page_path(form.id)) + end + describe "when there are no pages to display" do it "does not contain a list of pages" do expect(rendered).not_to have_text I18n.t("forms.form_overview.your_questions") expect(rendered).not_to have_css ".govuk-summary-list" @@ -44,10 +33,6 @@ describe "when there are more than one page to display" do let(:pages) { [(build :page, id: 1, position: 1, form_id: 1), (build :page, id: 2, position: 2, form_id: 1), (build :page, id: 3, position: 3, form_id: 1)] } - it "allows the user to add a page" do - expect(rendered).to have_link(I18n.t("pages.index.add_question"), href: start_new_question_path(form.id)) - end - it "does contain a summary list entry each page" do expect(rendered).to have_text I18n.t("forms.form_overview.your_questions") expect(rendered).to have_css ".govuk-summary-list__row", count: 3 From 863d797524e36da11ed614814441015e82d001d0 Mon Sep 17 00:00:00 2001 From: Thomas Iles Date: Tue, 28 Apr 2026 17:06:43 +0100 Subject: [PATCH 2/4] Add view for routes/show Add a new placeholder view for showing the routes for a form. --- app/views/routes/show.html.erb | 12 ++++++++++++ config/locales/en.yml | 1 + spec/views/routes/show.html.erb_spec.rb | 26 +++++++++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 app/views/routes/show.html.erb create mode 100644 spec/views/routes/show.html.erb_spec.rb diff --git a/app/views/routes/show.html.erb b/app/views/routes/show.html.erb new file mode 100644 index 0000000000..20ca4efdba --- /dev/null +++ b/app/views/routes/show.html.erb @@ -0,0 +1,12 @@ +<% set_page_title(t("page_titles.routes")) %> +<% content_for :back_link, govuk_back_link_to(form_pages_path(@current_form.id), t("back_link.form_view")) %> + +
+
+

+ <%= @current_form.name %> + - + <%= t("page_titles.routes") %> +

+
+
diff --git a/config/locales/en.yml b/config/locales/en.yml index 0247fb142a..0df46b90ca 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1480,6 +1480,7 @@ en: payment_link: Add a link to a payment page on GOV.UK Pay privacy_policy: Provide a link to privacy information for this form question_text: What’s your question? + routes: Edit question routes routes_show: Question %{question_number}’s routes routing_page: Add a route from a question routing_page_caption: Question %{question_number}’s routes diff --git a/spec/views/routes/show.html.erb_spec.rb b/spec/views/routes/show.html.erb_spec.rb new file mode 100644 index 0000000000..41330c28bb --- /dev/null +++ b/spec/views/routes/show.html.erb_spec.rb @@ -0,0 +1,26 @@ +require "rails_helper" + +describe "routes/show.html.erb" do + let(:form) { build_stubbed :form } + + def render_page + assign(:current_form, form) + render template: "routes/show", locals: { current_form: form } + end + + it "has the correct title" do + render_page + expect(view.content_for(:title)).to have_content("Edit question routes") + end + + it "has the correct back link" do + render_page + expect(view.content_for(:back_link)).to have_link("Back to your form", href: form_pages_path(form.id)) + end + + it "has the correct heading and caption" do + render_page + expect(rendered).to have_selector("h1", text: form.name) + expect(rendered).to have_selector("h1", text: "Edit question routes") + end +end From 14c77add39fc2ac5e45ac7f01b81d67c78f8dc28 Mon Sep 17 00:00:00 2001 From: Thomas Iles Date: Tue, 28 Apr 2026 17:07:27 +0100 Subject: [PATCH 3/4] Add a route and controller for routes/show Add a new route and controller for showing multiple branch routes. The controller returns a 404 if the feature is not enabled. --- app/controllers/routes_controller.rb | 20 ++++++++++++ config/routes.rb | 2 ++ spec/requests/routes_controller_spec.rb | 42 +++++++++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 app/controllers/routes_controller.rb create mode 100644 spec/requests/routes_controller_spec.rb diff --git a/app/controllers/routes_controller.rb b/app/controllers/routes_controller.rb new file mode 100644 index 0000000000..ce9b97447a --- /dev/null +++ b/app/controllers/routes_controller.rb @@ -0,0 +1,20 @@ +class RoutesController < FormsController + before_action :check_multiple_branches_enabled + before_action :check_user_has_permission + + def show + authorize current_form, :can_view_form? + end + +private + + def check_user_has_permission + authorize current_form, :can_edit_form? + end + + def check_multiple_branches_enabled + return if current_form.group.multiple_branches_enabled + + render "errors/not_found", status: :not_found, formats: :html + end +end diff --git a/config/routes.rb b/config/routes.rb index 188c8da4b0..aaf272dbe3 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -80,6 +80,8 @@ post "/batch-submissions" => "forms/batch_submissions#create", as: :batch_submissions_create get "/metrics" => "forms/metrics#metrics_csv", as: :metrics_csv + resource :routes, only: %i[show] + scope "/pages-by-external-id/:page_external_id" do get "/edit-question" => "forms/redirect_from_forms_runner#edit_question", as: :edit_question_by_external_id get "/routes" => "forms/redirect_from_forms_runner#routes", as: :show_routes_by_external_id diff --git a/spec/requests/routes_controller_spec.rb b/spec/requests/routes_controller_spec.rb new file mode 100644 index 0000000000..5c68793893 --- /dev/null +++ b/spec/requests/routes_controller_spec.rb @@ -0,0 +1,42 @@ +require "rails_helper" + +RSpec.describe RoutesController, type: :request do + let(:form) { create(:form, :with_group, group:) } + let(:membership) { create :membership, group:, user: standard_user } + let(:group) { create(:group, multiple_branches_enabled: true) } + + before do + membership + login_as_standard_user + end + + describe "#show" do + it "returns a 200 status code" do + get routes_path(form.id) + expect(response).to have_http_status(:ok) + end + + it "renders the routes#show template" do + get routes_path(form.id) + expect(response).to render_template("routes/show") + end + + context "when the user is not in the form's group" do + let(:membership) { nil } + + it "returns a forbidden status code" do + get routes_path(form.id) + expect(response).to have_http_status :forbidden + end + end + + context "when the multiple_branches feature is not enabled" do + let(:group) { create(:group, multiple_branches_enabled: false) } + + it "returns a 404" do + get routes_path(form.id) + expect(response).to have_http_status(:not_found) + end + end + end +end From f055e8a15e6f8eaf375e9eb7e8d1de1a889331c5 Mon Sep 17 00:00:00 2001 From: Thomas Iles Date: Tue, 28 Apr 2026 17:08:18 +0100 Subject: [PATCH 4/4] Show link to new routes page if feature flag set The page list view shows a link to add a route if the group has multiple branches enabled. If the feature flag is not set, the original link to current routing page is shown as normal. --- app/views/pages/index.html.erb | 6 +++++- config/locales/en.yml | 1 + spec/views/pages/index.html.erb_spec.rb | 9 +++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/app/views/pages/index.html.erb b/app/views/pages/index.html.erb index dd66a44975..f98839923f 100644 --- a/app/views/pages/index.html.erb +++ b/app/views/pages/index.html.erb @@ -20,7 +20,11 @@ <% end %>
<%= govuk_button_link_to t("pages.index.add_question"), start_new_question_path(form_id: current_form.id), class:"govuk-!-margin-bottom-3 govuk-!-margin-top-3" %> - <%= govuk_button_link_to t("pages.index.add_a_question_route"), routing_page_path(current_form.id), secondary: true, class:"govuk-!-margin-bottom-3 govuk-!-margin-top-3" %> + <% if current_form.group&.multiple_branches_enabled %> + <%= govuk_button_link_to t("pages.index.routes"), routes_path(current_form.id), secondary: true, class:"govuk-!-margin-bottom-3 govuk-!-margin-top-3" %> + <% else %> + <%= govuk_button_link_to t("pages.index.add_a_question_route"), routing_page_path(current_form.id), secondary: true, class:"govuk-!-margin-bottom-3 govuk-!-margin-top-3" %> + <% end %> <%= render PreviewLinkComponent::View.new(@pages, link_to_runner(Settings.forms_runner.url, current_form.id, current_form.form_slug)) %>
diff --git a/config/locales/en.yml b/config/locales/en.yml index 0df46b90ca..7690e44d89 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1581,6 +1581,7 @@ en: change_order: Change your question order mark_complete: legend: Have you finished editing your questions? + routes: Edit question routes title: Add and edit your questions optional: "%{question_text} (optional)" question: Question diff --git a/spec/views/pages/index.html.erb_spec.rb b/spec/views/pages/index.html.erb_spec.rb index 96f5694f5b..ce38b3f482 100644 --- a/spec/views/pages/index.html.erb_spec.rb +++ b/spec/views/pages/index.html.erb_spec.rb @@ -42,4 +42,13 @@ expect(rendered).to have_link("Change your question order", href: change_order_new_path(form.id)) end end + + describe "when the group has multiple branches enabled" do + let(:group) { create(:group, multiple_branches_enabled: true) } + let(:form) { create(:form, :with_group, group:) } + + it "has a link to add a page routing" do + expect(rendered).to have_link("Edit question routes", href: routes_path(form.id)) + end + end end