From 58986381af1b9db353fc9ee85acb8aa43f52b308 Mon Sep 17 00:00:00 2001 From: Sean Rankine Date: Mon, 13 Jul 2026 12:57:25 +0100 Subject: [PATCH 1/5] Remove the dedicated MOUs list page The organisations pages now show each organisation's signed MOUs and agreements, making the standalone list at /mous redundant. Point the header navigation and sitemap at the organisations pages instead, and drop the now-unused MouSignaturePolicy and locale strings. The MOU signing flow is unchanged. --- app/controllers/mou_signatures_controller.rb | 9 +--- app/controllers/sitemap_controller.rb | 6 +-- app/policies/mou_signature_policy.rb | 5 -- app/services/navigation_items_service.rb | 11 ---- app/views/mou_signatures/index.html.erb | 42 --------------- app/views/sitemap/index.html.erb | 4 +- config/locales/en.yml | 4 -- config/routes.rb | 2 - .../service_navigation_component_preview.rb | 2 +- .../mou/upgrade_user_changes_mou_spec.rb | 46 ++++++---------- spec/features/mou/view_signed_mous_spec.rb | 37 ++++++------- spec/policies/mou_signature_policy_spec.rb | 19 ------- .../services/navigation_items_service_spec.rb | 11 ---- .../mou_signatures/index.html.erb_spec.rb | 53 ------------------- spec/views/sitemap/index.html.erb_spec.rb | 26 ++++++--- 15 files changed, 57 insertions(+), 220 deletions(-) delete mode 100644 app/policies/mou_signature_policy.rb delete mode 100644 app/views/mou_signatures/index.html.erb delete mode 100644 spec/policies/mou_signature_policy_spec.rb delete mode 100644 spec/views/mou_signatures/index.html.erb_spec.rb diff --git a/app/controllers/mou_signatures_controller.rb b/app/controllers/mou_signatures_controller.rb index a360e7b76c..d9ad8a66aa 100644 --- a/app/controllers/mou_signatures_controller.rb +++ b/app/controllers/mou_signatures_controller.rb @@ -1,12 +1,5 @@ class MouSignaturesController < WebController - before_action :set_agreement_type, except: %i[index] - after_action :verify_authorized, only: %i[index] - - def index - authorize MouSignature, :can_manage_mous? - @mou_signatures = MouSignature.all - render template: "mou_signatures/index", locals: { mou_signatures: @mou_signatures } - end + before_action :set_agreement_type def show @mou_signature = current_user.current_organisation_mou_signature diff --git a/app/controllers/sitemap_controller.rb b/app/controllers/sitemap_controller.rb index be5282b0f3..0eea849444 100644 --- a/app/controllers/sitemap_controller.rb +++ b/app/controllers/sitemap_controller.rb @@ -6,7 +6,7 @@ def index render locals: { active_groups:, trial_groups:, should_show_users_link: should_show_users?, - should_show_mous_link: should_show_mous_link?, + should_show_organisations_link: should_show_organisations_link?, should_show_reports_link: should_show_reports_link? } end @@ -14,8 +14,8 @@ def should_show_users? Pundit.policy(current_user, :user).can_manage_user? end - def should_show_mous_link? - Pundit.policy(current_user, :mou_signature).can_manage_mous? + def should_show_organisations_link? + Pundit.policy(current_user, :organisation).can_view_organisations? end def should_show_reports_link? diff --git a/app/policies/mou_signature_policy.rb b/app/policies/mou_signature_policy.rb deleted file mode 100644 index 420c8530bf..0000000000 --- a/app/policies/mou_signature_policy.rb +++ /dev/null @@ -1,5 +0,0 @@ -class MouSignaturePolicy < ApplicationPolicy - def can_manage_mous? - user.super_admin? - end -end diff --git a/app/services/navigation_items_service.rb b/app/services/navigation_items_service.rb index 304c44dd66..f80273c047 100644 --- a/app/services/navigation_items_service.rb +++ b/app/services/navigation_items_service.rb @@ -22,7 +22,6 @@ def navigation_items navigation_items = [ your_groups_navigation_item, - mou_navigation_item, users_navigation_item, organisations_navigation_item, reports_navigation_item, @@ -42,12 +41,6 @@ def your_groups_navigation_item NavigationItem.new(text: I18n.t("header.your_groups"), href: "/", active: false) end - def mou_navigation_item - return nil unless should_show_mous_link? - - NavigationItem.new(text: I18n.t("header.mous"), href: mou_signatures_path, active: false) - end - def users_navigation_item return nil unless should_show_user_profile_link? @@ -96,10 +89,6 @@ def should_show_user_profile_link? Pundit.policy(user, :user).can_manage_user? end - def should_show_mous_link? - Pundit.policy(user, :mou_signature).can_manage_mous? - end - def should_show_organisations_link? Pundit.policy(user, :organisation).can_view_organisations? end diff --git a/app/views/mou_signatures/index.html.erb b/app/views/mou_signatures/index.html.erb deleted file mode 100644 index 94a26d061b..0000000000 --- a/app/views/mou_signatures/index.html.erb +++ /dev/null @@ -1,42 +0,0 @@ -<% set_page_title(t("page_titles.mou_signatures")) %> -

<%= t("page_titles.mou_signatures") %>

- -
- <%= t("mou_signatures.index.preamble_html") %> - - <%= t("mou_signatures.index.share_mou_link_html", mou_link: link_to(mou_signature_url, mou_signature_url)) %> - - <%= t("mou_signatures.index.share_non_crown_agreement_link_html", agreement_link: link_to(non_crown_agreement_signature_url, non_crown_agreement_signature_url)) %> -
- -<% if mou_signatures.any? %> - <%= render ScrollingWrapperComponent::View.new(aria_label: t("mou_signatures.index.table_caption")) do |table| %> - <%= govuk_table do |table| %> - <%= table.with_caption(size: 'm', text: t("mou_signatures.index.table_caption")) %> - - <%= table.with_head do |head| - head.with_row do |row| - row.with_cell(header: true, text: t("mou_signatures.index.table_headings.agreement_type")) - row.with_cell(header: true, text: t("mou_signatures.index.table_headings.name")) - row.with_cell(header: true, text: t("mou_signatures.index.table_headings.email")) - row.with_cell(header: true, text: t("mou_signatures.index.table_headings.organisation")) - row.with_cell(header: true, text: t("mou_signatures.index.table_headings.agreed_at")) - end - end %> - - <%= table.with_body do |body| - mou_signatures.each do |mou_signature| - body.with_row do |row| - row.with_cell(text: t("mou_signatures.index.agreement_type.#{mou_signature.agreement_type}")) - row.with_cell(text: mou_signature.user.name.presence || t("users.index.name_blank")) - row.with_cell do - govuk_link_to(mou_signature.user.email, edit_user_path(mou_signature.user)) - end - row.with_cell(text: mou_signature.organisation&.name.presence || t("users.index.organisation_blank")) - row.with_cell(text: l(mou_signature.created_at.to_date, :format => :long)) - end - end - end %> - <% end %> - <% end %> -<% end %> diff --git a/app/views/sitemap/index.html.erb b/app/views/sitemap/index.html.erb index f18ceb632b..a1686bfec5 100644 --- a/app/views/sitemap/index.html.erb +++ b/app/views/sitemap/index.html.erb @@ -20,8 +20,8 @@ <% end %> -<% if should_show_mous_link %> -

<%= link_to t("page_titles.mou_signatures"), mou_signatures_path %>

+<% if should_show_organisations_link %> +

<%= link_to t("page_titles.organisations"), organisations_path %>

diff --git a/config/locales/en.yml b/config/locales/en.yml index 127af7259d..7960a5a14e 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -928,7 +928,6 @@ en: Guidance will be displayed at the top of the page, above your question.

header: - mous: MOUs organisations: Organisations product_name: Forms reports: Reports @@ -1443,13 +1442,11 @@ en: preamble_html: "

Someone from each organisation needs to agree to one of the GOV.UK Forms agreements before an organisation admin can be assigned or any groups upgraded to ‘active’.

\n" share_mou_link_html: "

For Crown organisations, like government departments and executive agencies, share the Memorandum of Understanding:
%{mou_link}

\n" share_non_crown_agreement_link_html: "

For non-crown organisations, like local authorities, share the GOV.UK Forms agreement:
%{agreement_link}

\n" - table_caption: Agreed MOUs and agreements table_headings: agreed_at: Agreed on agreement_type: Agreement type email: Email address name: Name - organisation: Organisation show: crown: banner: @@ -1655,7 +1652,6 @@ en: missing_draft_question: There’s a problem with this page mou_signature_confirmation: You’ve agreed to the MOU mou_signature_new: GOV.UK Forms Memorandum of Understanding - mou_signatures: MOUs and agreements move_form: Move this form to a different group name_settings: Ask for a person’s name new_group: Give your group a name diff --git a/config/routes.rb b/config/routes.rb index ed1675a0c9..83cd523d5e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -215,8 +215,6 @@ resource :contact_for_research, controller: :contact_for_research, only: %i[edit update] end - resources :mou_signatures, only: %i[index], path: "mous" - resources :organisations, only: %i[index show] resource :mou_signature, only: %i[new show create], path: "/memorandum-of-understanding", defaults: { agreement_type: :crown }, as: :mou_signature do diff --git a/spec/components/service_navigation_component/service_navigation_component_preview.rb b/spec/components/service_navigation_component/service_navigation_component_preview.rb index e79de933cc..511e1e9954 100644 --- a/spec/components/service_navigation_component/service_navigation_component_preview.rb +++ b/spec/components/service_navigation_component/service_navigation_component_preview.rb @@ -15,8 +15,8 @@ def with_navigation_links def with_super_admin_navigation_links render(ServiceNavigationComponent::View.new(navigation_items: [ { text: "Your groups", href: "/" }, - { text: "MOUs", href: "/mous" }, { text: "Users", href: "/users" }, + { text: "Organisations", href: "/organisations" }, { text: "Reports", href: "/reports" }, { text: "Support", href: "/support" }, { text: "A User", href: nil, classes: ["app-service-navigation__item--featured"] }, diff --git a/spec/features/mou/upgrade_user_changes_mou_spec.rb b/spec/features/mou/upgrade_user_changes_mou_spec.rb index 5adf9b31b2..1e70a2e474 100644 --- a/spec/features/mou/upgrade_user_changes_mou_spec.rb +++ b/spec/features/mou/upgrade_user_changes_mou_spec.rb @@ -3,48 +3,34 @@ describe "Assign an organisation to a user with a signed MOU", type: :feature do let(:user) { create :user, name: "Test User", organisation: nil } let!(:mou_signature) { create(:mou_signature, user:, organisation: nil, created_at: Time.zone.parse("September 1, 2023")) } - let(:organisation) { create :organisation } + let!(:organisation) { create :organisation, slug: "department-for-testing" } - it "a logged in user can sign an MOU" do + it "assigning an organisation to a user adds it to their MOU" do login_as_super_admin_user - when_i_visit_the_mou_index_page - then_i_can_see_the_mou_page - then_i_see_the_mou_with_no_organisation - then_i_visit_the_users_page - then_i_update_the_user_organisation - when_i_visit_the_mou_index_page - then_i_can_see_the_mou_page + when_i_update_the_user_organisation + then_i_visit_the_organisation_page then_i_see_the_mou_with_organisation end private - def when_i_visit_the_mou_index_page - visit mou_signatures_path - end - - def then_i_can_see_the_mou_page - expect(page).to have_text "MOUs and agreements" - end - - def then_i_see_the_mou_with_no_organisation - expect(page).to have_text mou_signature.user.name - expect(page).to have_text mou_signature.user.email - expect(page).to have_text "No organisation" + def when_i_update_the_user_organisation + visit edit_user_path(user) + organisation_field = find_field "Organisation" + # The \n is important, it "presses enter" to confirm the autocomplete selection + organisation_field.fill_in with: "#{organisation.name}\n" + expect(organisation_field.value).to start_with organisation.name + click_button "Save" end - def then_i_visit_the_users_page - click_link mou_signature.user.email - end - - def then_i_update_the_user_organisation - fill_in "Organisation", with: "#{organisation.name}\n" - click_button "Save" - sleep 1 + def then_i_visit_the_organisation_page + visit organisation_path(organisation) end def then_i_see_the_mou_with_organisation + expect(page).to have_text "MOUs and agreements" expect(page).to have_text mou_signature.user.name - expect(page).to have_text organisation.name + expect(page).to have_link mou_signature.user.email + expect(page).to have_text "September 01, 2023" end end diff --git a/spec/features/mou/view_signed_mous_spec.rb b/spec/features/mou/view_signed_mous_spec.rb index cb4773617e..5b7ef49a89 100644 --- a/spec/features/mou/view_signed_mous_spec.rb +++ b/spec/features/mou/view_signed_mous_spec.rb @@ -1,42 +1,35 @@ require "rails_helper" describe "Check which MOUs have been signed", type: :feature do - let(:user) { super_admin_user } - let!(:mou_signatures) do - [create(:mou_signature, created_at: Time.zone.parse("October 12, 2023")), - create(:mou_signature, created_at: Time.zone.parse("September 1, 2023"))] - end + let(:organisation) { create :organisation, slug: "department-for-testing" } + let!(:mou_signature) { create(:mou_signature_for_organisation, organisation:, created_at: Time.zone.parse("October 12, 2023")) } before do login_as_super_admin_user end - it "super_admin's can see the MOUs page" do - then_i_click_on_the_mou_link - then_i_can_see_the_mou_page + it "super_admin's can see an organisation's signed MOUs" do + then_i_click_on_the_organisations_link + then_i_click_on_the_organisation then_i_can_see_the_mou_list end private - def then_i_can_see_the_mou_list - expect(page).to have_text mou_signatures.first.organisation.name - expect(page).to have_link mou_signatures.first.user.email - expect(page).to have_text mou_signatures.first.user.name - expect(page).to have_text "October 12, 2023" - - expect(page).to have_text mou_signatures.second.organisation.name - expect(page).to have_link mou_signatures.second.user.email - expect(page).to have_text mou_signatures.second.user.name - expect(page).to have_text "September 01, 2023" + def then_i_click_on_the_organisations_link + visit root_path + click_link("Organisations") end - def then_i_click_on_the_mou_link - visit root_path - click_link("MOUs") + def then_i_click_on_the_organisation + click_link organisation.name_with_abbreviation end - def then_i_can_see_the_mou_page + def then_i_can_see_the_mou_list expect(page).to have_text "MOUs and agreements" + expect(page).to have_text "Crown MOU" + expect(page).to have_text mou_signature.user.name + expect(page).to have_link mou_signature.user.email + expect(page).to have_text "October 12, 2023" end end diff --git a/spec/policies/mou_signature_policy_spec.rb b/spec/policies/mou_signature_policy_spec.rb deleted file mode 100644 index 75d7cc1062..0000000000 --- a/spec/policies/mou_signature_policy_spec.rb +++ /dev/null @@ -1,19 +0,0 @@ -require "rails_helper" - -describe MouSignaturePolicy do - subject(:policy) { described_class.new(user, :mouSignature) } - - let(:user) { build :super_admin_user } - - context "with super admin" do - it { is_expected.to permit_actions(%i[can_manage_mous]) } - end - - (User.roles.keys - %w[super_admin]).each do |role| - context "with #{role}" do - let(:user) { build :user, role: } - - it { is_expected.to forbid_actions(%i[can_manage_mous]) } - end - end -end diff --git a/spec/services/navigation_items_service_spec.rb b/spec/services/navigation_items_service_spec.rb index 2591101cdb..13d8f0401e 100644 --- a/spec/services/navigation_items_service_spec.rb +++ b/spec/services/navigation_items_service_spec.rb @@ -19,13 +19,11 @@ context "when user is present" do let(:can_manage_user) { false } - let(:can_manage_mous) { false } let(:can_view_reports) { false } let(:can_view_organisations) { false } before do allow(Pundit).to receive(:policy).with(user, :user).and_return(instance_double(UserPolicy, can_manage_user?: can_manage_user)) - allow(Pundit).to receive(:policy).with(user, :mou_signature).and_return(instance_double(MouSignaturePolicy, can_manage_mous?: can_manage_mous)) allow(Pundit).to receive(:policy).with(user, :report).and_return(instance_double(ReportPolicy, can_view_reports?: can_view_reports)) allow(Pundit).to receive(:policy).with(user, :organisation).and_return(instance_double(OrganisationPolicy, can_view_organisations?: can_view_organisations)) allow(Settings.forms_product_page).to receive(:support_url).and_return(support_url) @@ -40,15 +38,6 @@ end end - context "when user can manage mous" do - let(:can_manage_mous) { true } - - it "includes mous in navigation items" do - mous_item = NavigationItemsService::NavigationItem.new(text: I18n.t("header.mous"), href: mou_signatures_path, active: false) - expect(service.navigation_items).to include(mous_item) - end - end - context "when user can view organisations" do let(:can_view_organisations) { true } diff --git a/spec/views/mou_signatures/index.html.erb_spec.rb b/spec/views/mou_signatures/index.html.erb_spec.rb deleted file mode 100644 index 623e036f5f..0000000000 --- a/spec/views/mou_signatures/index.html.erb_spec.rb +++ /dev/null @@ -1,53 +0,0 @@ -require "rails_helper" - -describe "mou_signatures/index.html.erb" do - let(:mou_signatures) do - [ - build(:mou_signature, agreement_type: :crown, created_at: Time.zone.parse("October 12, 2023")), - build(:mou_signature, agreement_type: :non_crown, created_at: Time.zone.parse("October 13, 2023")), - ] - end - - before do - render template: "mou_signatures/index", locals: { mou_signatures: } - end - - it "contains page heading" do - expect(rendered).to have_css("h1.govuk-heading-l", text: I18n.t("page_titles.mou_signatures")) - end - - it "contains a scrollable wrapper with a table in it" do - expect(rendered).to have_css(".app-scrolling-wrapper > table") - end - - it "contains the agreement type" do - expect(rendered).to have_xpath "//thead/tr/th[1]", text: I18n.t("mou_signatures.index.table_headings.agreement_type") - expect(rendered).to have_xpath "//tbody/tr[1]/td[1]", text: I18n.t("mou_signatures.index.agreement_type.crown") - expect(rendered).to have_xpath "//tbody/tr[2]/td[1]", text: I18n.t("mou_signatures.index.agreement_type.non_crown") - end - - it "contains the user's name" do - expect(rendered).to have_text(mou_signatures.first.user.name) - end - - it "contains the user's email as a link to the edit page" do - expect(rendered).to have_link(mou_signatures.first.user.email, href: edit_user_path(mou_signatures.first.user)) - end - - it "contains organisation name" do - expect(rendered).to have_text(mou_signatures.first.user.organisation.name) - end - - it "contains the date the MOU was signed" do - expect(rendered).to have_text(I18n.l(mou_signatures.first.created_at.to_date, format: :long)) - end - - context "when there are no signed MOUs" do - let(:mou_signatures) { [] } - - it "does not show the MOU table" do - expect(rendered).not_to have_text(I18n.t("mou_signatures.table_caption")) - expect(rendered).not_to have_css("table") - end - end -end diff --git a/spec/views/sitemap/index.html.erb_spec.rb b/spec/views/sitemap/index.html.erb_spec.rb index 604fa066a9..b435b8f3eb 100644 --- a/spec/views/sitemap/index.html.erb_spec.rb +++ b/spec/views/sitemap/index.html.erb_spec.rb @@ -1,7 +1,7 @@ require "rails_helper" describe "sitemap/index.html.erb" do - let(:locals) { { active_groups: [], trial_groups: [], should_show_users_link: false, should_show_mous_link: false, should_show_reports_link: false } } + let(:locals) { { active_groups: [], trial_groups: [], should_show_users_link: false, should_show_organisations_link: false, should_show_reports_link: false } } def render_template render template: "sitemap/index", locals: @@ -59,20 +59,32 @@ def render_template end end - context "when the should_show_mous_link is true" do - let(:locals) { super().merge(should_show_mous_link: true) } + context "when the should_show_organisations_link is true" do + let(:locals) { super().merge(should_show_organisations_link: true) } - it "includes a link to the MOUs page" do + it "includes a link to the organisations page" do + render_template + + expect(rendered).to have_link("Organisations", href: organisations_path) + end + + it "includes a link to the MOU signing page" do render_template expect(rendered).to have_link("Memorandum of Understanding", href: mou_signature_url) end end - context "when should_show_mous_link is false" do - let(:locals) { super().merge(should_show_mous_link: false) } + context "when should_show_organisations_link is false" do + let(:locals) { super().merge(should_show_organisations_link: false) } + + it "does not include a link to the organisations page" do + render_template + + expect(rendered).not_to have_link("Organisations") + end - it "does not include a link to the MOUs page" do + it "does not include a link to the MOU signing page" do render_template expect(rendered).not_to have_link("Memorandum of Understanding") From 1d8603c4b0f477e2bc904fb8081fe77eebafe4ad Mon Sep 17 00:00:00 2001 From: Sean Rankine Date: Mon, 13 Jul 2026 17:33:36 +0100 Subject: [PATCH 2/5] Wait for user save before leaving the users page The MOU upgrade spec visits the organisation page straight after clicking Save, racing the form submission: the save's redirect could land after the visit and clobber the organisation page, failing the final assertion. Wait for the redirect to the users page before navigating, replacing the sleep the spec relied on before it was rewritten. --- spec/features/mou/upgrade_user_changes_mou_spec.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spec/features/mou/upgrade_user_changes_mou_spec.rb b/spec/features/mou/upgrade_user_changes_mou_spec.rb index 1e70a2e474..3dfa357d9a 100644 --- a/spec/features/mou/upgrade_user_changes_mou_spec.rb +++ b/spec/features/mou/upgrade_user_changes_mou_spec.rb @@ -21,6 +21,9 @@ def when_i_update_the_user_organisation organisation_field.fill_in with: "#{organisation.name}\n" expect(organisation_field.value).to start_with organisation.name click_button "Save" + # wait for the save to finish before navigating away, or the form + # submission's redirect can clobber the next page visit + expect(page).to have_current_path(users_path) end def then_i_visit_the_organisation_page From 1b4e01cc248a1bb3810f8161c808bd80324de31d Mon Sep 17 00:00:00 2001 From: Sean Rankine Date: Mon, 13 Jul 2026 16:57:29 +0100 Subject: [PATCH 3/5] Move MOU locale keys out of the index namespace The mou_signatures.index locale namespace referred to the MOUs list view, which no longer exists. Its surviving keys are only used by the organisations pages, so home them where they are consumed: the agreement type labels move to mou_signatures.agreement_type as they describe the model's enum and are shared between the organisations index, show and filter, while the table headings, preamble and share links move under organisations.show.mou_signatures alongside the existing heading. This stops the keys looking like dead code tied to a deleted view. --- .../organisations/filter_input.rb | 4 ++-- app/views/organisations/index.html.erb | 2 +- app/views/organisations/show.html.erb | 16 ++++++------- config/locales/en.yml | 23 +++++++++---------- .../organisations/filter_input_spec.rb | 4 ++-- .../requests/organisations_controller_spec.rb | 2 +- .../organisations/index.html.erb_spec.rb | 6 ++--- .../views/organisations/show.html.erb_spec.rb | 2 +- 8 files changed, 29 insertions(+), 30 deletions(-) diff --git a/app/input_objects/organisations/filter_input.rb b/app/input_objects/organisations/filter_input.rb index b9ab8043fb..7762b6ca05 100644 --- a/app/input_objects/organisations/filter_input.rb +++ b/app/input_objects/organisations/filter_input.rb @@ -17,8 +17,8 @@ def sort_options def agreement_type_options [ OpenStruct.new(label: I18n.t("organisations.index.filter.agreement_type.any")), - OpenStruct.new(label: I18n.t("mou_signatures.index.agreement_type.crown"), value: "crown"), - OpenStruct.new(label: I18n.t("mou_signatures.index.agreement_type.non_crown"), value: "non_crown"), + OpenStruct.new(label: I18n.t("mou_signatures.agreement_type.crown"), value: "crown"), + OpenStruct.new(label: I18n.t("mou_signatures.agreement_type.non_crown"), value: "non_crown"), OpenStruct.new(label: I18n.t("organisations.index.filter.agreement_type.signed"), value: "signed"), OpenStruct.new(label: I18n.t("organisations.index.filter.agreement_type.none"), value: "none"), ] diff --git a/app/views/organisations/index.html.erb b/app/views/organisations/index.html.erb index dcbcf7a618..c1f553fb56 100644 --- a/app/views/organisations/index.html.erb +++ b/app/views/organisations/index.html.erb @@ -73,7 +73,7 @@ row.with_cell(text: @form_counts.fetch(organisation.id, 0).to_s, numeric: true) agreement_types = @agreement_types.fetch(organisation.id, []) if agreement_types.any? - row.with_cell(text: agreement_types.map { |agreement_type| t("mou_signatures.index.agreement_type.#{agreement_type}") }.join(", ")) + row.with_cell(text: agreement_types.map { |agreement_type| t("mou_signatures.agreement_type.#{agreement_type}") }.join(", ")) else row.with_cell(text: t("organisations.index.agreement_type_none")) end diff --git a/app/views/organisations/show.html.erb b/app/views/organisations/show.html.erb index ad3938560b..0878ec94da 100644 --- a/app/views/organisations/show.html.erb +++ b/app/views/organisations/show.html.erb @@ -64,17 +64,17 @@ <%= govuk_table do |table| %> <%= table.with_head do |head| head.with_row do |row| - row.with_cell(header: true, text: t("mou_signatures.index.table_headings.agreement_type")) - row.with_cell(header: true, text: t("mou_signatures.index.table_headings.name")) - row.with_cell(header: true, text: t("mou_signatures.index.table_headings.email")) - row.with_cell(header: true, text: t("mou_signatures.index.table_headings.agreed_at")) + row.with_cell(header: true, text: t("organisations.show.mou_signatures.table_headings.agreement_type")) + row.with_cell(header: true, text: t("organisations.show.mou_signatures.table_headings.name")) + row.with_cell(header: true, text: t("organisations.show.mou_signatures.table_headings.email")) + row.with_cell(header: true, text: t("organisations.show.mou_signatures.table_headings.agreed_at")) end end %> <%= table.with_body do |body| @organisation.mou_signatures.each do |mou_signature| body.with_row do |row| - row.with_cell(text: t("mou_signatures.index.agreement_type.#{mou_signature.agreement_type}")) + row.with_cell(text: t("mou_signatures.agreement_type.#{mou_signature.agreement_type}")) row.with_cell(text: mou_signature.user.name.presence || t("users.index.name_blank")) row.with_cell do govuk_link_to(mou_signature.user.email, edit_user_path(mou_signature.user)) @@ -88,11 +88,11 @@ <% else %>

<%= t("organisations.show.mou_signatures.none") %>

- <%= t("mou_signatures.index.preamble_html") %> + <%= t("organisations.show.mou_signatures.preamble_html") %> - <%= t("mou_signatures.index.share_mou_link_html", mou_link: link_to(mou_signature_url, mou_signature_url)) %> + <%= t("organisations.show.mou_signatures.share_mou_link_html", mou_link: link_to(mou_signature_url, mou_signature_url)) %> - <%= t("mou_signatures.index.share_non_crown_agreement_link_html", agreement_link: link_to(non_crown_agreement_signature_url, non_crown_agreement_signature_url)) %> + <%= t("organisations.show.mou_signatures.share_non_crown_agreement_link_html", agreement_link: link_to(non_crown_agreement_signature_url, non_crown_agreement_signature_url)) %> <% end %>

<%= t("organisations.show.domains.heading") %>

diff --git a/config/locales/en.yml b/config/locales/en.yml index 7960a5a14e..0c20676a7d 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1426,6 +1426,9 @@ en: heading_without_dates: Form metrics percentage: "%{number}%" mou_signatures: + agreement_type: + crown: Crown MOU + non_crown: Non-crown agreement confirmation: crown: body_html: | @@ -1435,18 +1438,6 @@ en: body_html: |

What happens next

We’ll email you with any updates to the agreement that are made in the future.

- index: - agreement_type: - crown: Crown MOU - non_crown: Non-crown agreement - preamble_html: "

Someone from each organisation needs to agree to one of the GOV.UK Forms agreements before an organisation admin can be assigned or any groups upgraded to ‘active’.

\n" - share_mou_link_html: "

For Crown organisations, like government departments and executive agencies, share the Memorandum of Understanding:
%{mou_link}

\n" - share_non_crown_agreement_link_html: "

For non-crown organisations, like local authorities, share the GOV.UK Forms agreement:
%{agreement_link}

\n" - table_headings: - agreed_at: Agreed on - agreement_type: Agreement type - email: Email address - name: Name show: crown: banner: @@ -1509,6 +1500,14 @@ en: mou_signatures: heading: MOUs and agreements none: No one has agreed an MOU or agreement for this organisation. + preamble_html: "

Someone from each organisation needs to agree to one of the GOV.UK Forms agreements before an organisation admin can be assigned or any groups upgraded to ‘active’.

\n" + share_mou_link_html: "

For Crown organisations, like government departments and executive agencies, share the Memorandum of Understanding:
%{mou_link}

\n" + share_non_crown_agreement_link_html: "

For non-crown organisations, like local authorities, share the GOV.UK Forms agreement:
%{agreement_link}

\n" + table_headings: + agreed_at: Agreed on + agreement_type: Agreement type + email: Email address + name: Name not_set: Not set summary: closed: Closed diff --git a/spec/input_objects/organisations/filter_input_spec.rb b/spec/input_objects/organisations/filter_input_spec.rb index bcf44a8156..0f2c39805a 100644 --- a/spec/input_objects/organisations/filter_input_spec.rb +++ b/spec/input_objects/organisations/filter_input_spec.rb @@ -41,8 +41,8 @@ it "returns the correct options" do expect(described_class.new.agreement_type_options).to eq([ OpenStruct.new(label: I18n.t("organisations.index.filter.agreement_type.any")), - OpenStruct.new(label: I18n.t("mou_signatures.index.agreement_type.crown"), value: "crown"), - OpenStruct.new(label: I18n.t("mou_signatures.index.agreement_type.non_crown"), value: "non_crown"), + OpenStruct.new(label: I18n.t("mou_signatures.agreement_type.crown"), value: "crown"), + OpenStruct.new(label: I18n.t("mou_signatures.agreement_type.non_crown"), value: "non_crown"), OpenStruct.new(label: I18n.t("organisations.index.filter.agreement_type.signed"), value: "signed"), OpenStruct.new(label: I18n.t("organisations.index.filter.agreement_type.none"), value: "none"), ]) diff --git a/spec/requests/organisations_controller_spec.rb b/spec/requests/organisations_controller_spec.rb index 505db1445d..43240e7b1b 100644 --- a/spec/requests/organisations_controller_spec.rb +++ b/spec/requests/organisations_controller_spec.rb @@ -174,7 +174,7 @@ def organisation_row_order(response) expect(response.body).to include(organisation.name) expect(response.body).to include(organisation.slug) expect(response.body).to include(organisation.admin_users.first.email) - expect(response.body).to include(I18n.t("mou_signatures.index.agreement_type.#{organisation.mou_signatures.first.agreement_type}")) + expect(response.body).to include(I18n.t("mou_signatures.agreement_type.#{organisation.mou_signatures.first.agreement_type}")) expect(response.body).to include(organisation_domain.domain) end end diff --git a/spec/views/organisations/index.html.erb_spec.rb b/spec/views/organisations/index.html.erb_spec.rb index 66409b1aa3..7e256c44d4 100644 --- a/spec/views/organisations/index.html.erb_spec.rb +++ b/spec/views/organisations/index.html.erb_spec.rb @@ -33,8 +33,8 @@ expect(rendered).to have_field("filter[name]") expect(rendered).to have_select("filter[agreement_type]", options: [ I18n.t("organisations.index.filter.agreement_type.any"), - I18n.t("mou_signatures.index.agreement_type.crown"), - I18n.t("mou_signatures.index.agreement_type.non_crown"), + I18n.t("mou_signatures.agreement_type.crown"), + I18n.t("mou_signatures.agreement_type.non_crown"), I18n.t("organisations.index.filter.agreement_type.signed"), I18n.t("organisations.index.filter.agreement_type.none"), ]) @@ -81,7 +81,7 @@ end it "shows the agreement type for each organisation" do - expect(rendered).to have_xpath "//tbody/tr[1]/td[4]", text: I18n.t("mou_signatures.index.agreement_type.crown") + expect(rendered).to have_xpath "//tbody/tr[1]/td[4]", text: I18n.t("mou_signatures.agreement_type.crown") expect(rendered).to have_xpath "//tbody/tr[2]/td[4]", text: I18n.t("organisations.index.agreement_type_none") end diff --git a/spec/views/organisations/show.html.erb_spec.rb b/spec/views/organisations/show.html.erb_spec.rb index b89d161361..dc1a0dd4be 100644 --- a/spec/views/organisations/show.html.erb_spec.rb +++ b/spec/views/organisations/show.html.erb_spec.rb @@ -43,7 +43,7 @@ it "lists the MOU signatures" do mou_signature = organisation.mou_signatures.first - expect(rendered).to have_text(I18n.t("mou_signatures.index.agreement_type.#{mou_signature.agreement_type}")) + expect(rendered).to have_text(I18n.t("mou_signatures.agreement_type.#{mou_signature.agreement_type}")) expect(rendered).to have_link(mou_signature.user.email, href: edit_user_path(mou_signature.user)) expect(rendered).to have_text(I18n.l(mou_signature.created_at.to_date, format: :long)) end From 5db2e1d8d66081d50126304b520f1836ff92c4ee Mon Sep 17 00:00:00 2001 From: Sean Rankine Date: Tue, 14 Jul 2026 11:02:09 +0100 Subject: [PATCH 4/5] Move MOU feature specs into organisations specs The MOU list page is gone and signed MOUs are now shown on each organisation's page, so the specs covering them describe organisations page behaviour. Move them to spec/features/organisations and reword the scenarios to match. The MOU signing flow spec stays where it is, as signing is unchanged. --- .../upgrade_user_changes_mou_spec.rb | 10 +++++----- .../{mou => organisations}/view_signed_mous_spec.rb | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) rename spec/features/{mou => organisations}/upgrade_user_changes_mou_spec.rb (83%) rename spec/features/{mou => organisations}/view_signed_mous_spec.rb (71%) diff --git a/spec/features/mou/upgrade_user_changes_mou_spec.rb b/spec/features/organisations/upgrade_user_changes_mou_spec.rb similarity index 83% rename from spec/features/mou/upgrade_user_changes_mou_spec.rb rename to spec/features/organisations/upgrade_user_changes_mou_spec.rb index 3dfa357d9a..5cb5e11089 100644 --- a/spec/features/mou/upgrade_user_changes_mou_spec.rb +++ b/spec/features/organisations/upgrade_user_changes_mou_spec.rb @@ -5,11 +5,11 @@ let!(:mou_signature) { create(:mou_signature, user:, organisation: nil, created_at: Time.zone.parse("September 1, 2023")) } let!(:organisation) { create :organisation, slug: "department-for-testing" } - it "assigning an organisation to a user adds it to their MOU" do + it "assigning an organisation to a user shows their MOU on the organisation's page" do login_as_super_admin_user when_i_update_the_user_organisation - then_i_visit_the_organisation_page - then_i_see_the_mou_with_organisation + and_i_visit_the_organisation_page + then_i_can_see_the_mou_for_the_user end private @@ -26,11 +26,11 @@ def when_i_update_the_user_organisation expect(page).to have_current_path(users_path) end - def then_i_visit_the_organisation_page + def and_i_visit_the_organisation_page visit organisation_path(organisation) end - def then_i_see_the_mou_with_organisation + def then_i_can_see_the_mou_for_the_user expect(page).to have_text "MOUs and agreements" expect(page).to have_text mou_signature.user.name expect(page).to have_link mou_signature.user.email diff --git a/spec/features/mou/view_signed_mous_spec.rb b/spec/features/organisations/view_signed_mous_spec.rb similarity index 71% rename from spec/features/mou/view_signed_mous_spec.rb rename to spec/features/organisations/view_signed_mous_spec.rb index 5b7ef49a89..3176d309f3 100644 --- a/spec/features/mou/view_signed_mous_spec.rb +++ b/spec/features/organisations/view_signed_mous_spec.rb @@ -1,6 +1,6 @@ require "rails_helper" -describe "Check which MOUs have been signed", type: :feature do +describe "View an organisation's signed MOUs", type: :feature do let(:organisation) { create :organisation, slug: "department-for-testing" } let!(:mou_signature) { create(:mou_signature_for_organisation, organisation:, created_at: Time.zone.parse("October 12, 2023")) } @@ -8,20 +8,20 @@ login_as_super_admin_user end - it "super_admin's can see an organisation's signed MOUs" do - then_i_click_on_the_organisations_link - then_i_click_on_the_organisation + it "super_admin's can see an organisation's signed MOUs on its page" do + when_i_click_on_the_organisations_link + and_i_click_on_the_organisation then_i_can_see_the_mou_list end private - def then_i_click_on_the_organisations_link + def when_i_click_on_the_organisations_link visit root_path click_link("Organisations") end - def then_i_click_on_the_organisation + def and_i_click_on_the_organisation click_link organisation.name_with_abbreviation end From d43abd670162c74931f8913f8506eae68ba437f8 Mon Sep 17 00:00:00 2001 From: Sean Rankine Date: Tue, 14 Jul 2026 11:02:27 +0100 Subject: [PATCH 5/5] Stop hardcoding organisation ids in specs Factories and specs inserted organisations with explicit primary keys (test_org reserved id 1). Explicit-id inserts do not advance the Postgres id sequence, so on a freshly prepared database any example mixing a hardcoded-id organisation with a sequence-assigned one could fail with a unique constraint violation, depending on test order. Nothing depends on the numeric ids: the organisation factory already deduplicates by slug, so every record asking for "test-org" shares one row regardless of id. The membership factory was only valid because the user's and group's separately-built organisations both carried id 1 and so compared equal. Build the group with the user's organisation instead, which is what the validation actually requires. --- spec/factories/models/groups.rb | 4 ++-- spec/factories/models/memberships.rb | 2 +- spec/factories/models/organisation_domains.rb | 2 +- spec/factories/models/users.rb | 4 ++-- spec/features/form/super_admin_view_forms_spec.rb | 2 +- spec/features/users/set_organisation_spec.rb | 4 ++-- spec/models/membership_spec.rb | 14 +++++++------- spec/requests/forms/change_name_controller_spec.rb | 2 +- .../forms/submission_email_controller_spec.rb | 2 +- spec/requests/groups_controller_spec.rb | 2 +- spec/services/mailchimp/list_sync_service_spec.rb | 2 +- spec/support/authentication_feature_helpers.rb | 2 +- spec/views/groups/index.html.erb_spec.rb | 2 +- spec/views/users/edit.html.erb_spec.rb | 8 ++++---- 14 files changed, 26 insertions(+), 26 deletions(-) diff --git a/spec/factories/models/groups.rb b/spec/factories/models/groups.rb index 6a38ffdbd8..345c3a7668 100644 --- a/spec/factories/models/groups.rb +++ b/spec/factories/models/groups.rb @@ -1,13 +1,13 @@ FactoryBot.define do factory :group do sequence(:name) { |n| "Group #{n}" } - organisation { association :organisation, id: 1, slug: "test-org" } + organisation { association :organisation, slug: "test-org" } creator { association :user, organisation: } status { :trial } external_id { SecureRandom.base58(8) } trait :org_has_org_admin do - organisation { association :organisation, :with_org_admin, id: 1, slug: "test-org" } + organisation { association :organisation, :with_org_admin, slug: "test-org" } end end end diff --git a/spec/factories/models/memberships.rb b/spec/factories/models/memberships.rb index c414e53882..38882f117d 100644 --- a/spec/factories/models/memberships.rb +++ b/spec/factories/models/memberships.rb @@ -1,7 +1,7 @@ FactoryBot.define do factory :membership do user - group + group { association :group, organisation: user&.organisation } added_by { association :user } role { :editor } end diff --git a/spec/factories/models/organisation_domains.rb b/spec/factories/models/organisation_domains.rb index 1ac40d7b58..071834ecb8 100644 --- a/spec/factories/models/organisation_domains.rb +++ b/spec/factories/models/organisation_domains.rb @@ -1,6 +1,6 @@ FactoryBot.define do factory :organisation_domain do - organisation { association :organisation, id: 1, slug: "test-org" } + organisation { association :organisation, slug: "test-org" } domain { Faker::Internet.domain_name } end end diff --git a/spec/factories/models/users.rb b/spec/factories/models/users.rb index 86f5cd40c9..aa2c5bb912 100644 --- a/spec/factories/models/users.rb +++ b/spec/factories/models/users.rb @@ -26,10 +26,10 @@ org_has_signed_mou end - organisation { association :organisation, id: 1, slug: "test-org" } + organisation { association :organisation, slug: "test-org" } trait :org_has_signed_mou do - organisation { association :organisation, :with_signed_mou, id: 1, slug: "test-org" } + organisation { association :organisation, :with_signed_mou, slug: "test-org" } end after(:build) do |user| diff --git a/spec/features/form/super_admin_view_forms_spec.rb b/spec/features/form/super_admin_view_forms_spec.rb index 560d6f98b8..5004566bc1 100644 --- a/spec/features/form/super_admin_view_forms_spec.rb +++ b/spec/features/form/super_admin_view_forms_spec.rb @@ -2,7 +2,7 @@ feature "View forms", type: :feature do let(:org_forms) { [build(:form, id: 1, name: "Org form")] } - let(:other_org) { create :organisation, id: 2, slug: "Other org" } + let(:other_org) { create :organisation, slug: "Other org" } let(:other_org_user) { create :user, organisation: other_org } let(:other_org_forms) { [build(:form, id: 2, name: "Other org form")] } let(:other_org_group) { create :group, organisation_id: other_org.id } diff --git a/spec/features/users/set_organisation_spec.rb b/spec/features/users/set_organisation_spec.rb index 0a53270ebf..8dc32cf71c 100644 --- a/spec/features/users/set_organisation_spec.rb +++ b/spec/features/users/set_organisation_spec.rb @@ -2,11 +2,11 @@ feature "Set or change a user's organisation", type: :feature do let!(:test_org) do - create(:organisation, id: 1, slug: "test-org") + create(:organisation, slug: "test-org") end before do - create(:organisation, id: 2, slug: "government-digital-service") + create(:organisation, slug: "government-digital-service") create_list :user, 6, organisation: test_org login_as_super_admin_user end diff --git a/spec/models/membership_spec.rb b/spec/models/membership_spec.rb index 8edcf97d6e..6a0af781be 100644 --- a/spec/models/membership_spec.rb +++ b/spec/models/membership_spec.rb @@ -26,8 +26,8 @@ end it "is invalid if the user and group are not in the same organisation" do - org1 = create :organisation, id: 1, slug: "test-org" - org2 = create :organisation, id: 2, slug: "ministry-of-testing" + org1 = create :organisation, slug: "test-org" + org2 = create :organisation, slug: "ministry-of-testing" user = create :user, organisation: org1 group = create :group, organisation: org2 membership = build(:membership, user:, group:) @@ -52,7 +52,7 @@ describe ".destroy_invalid_organisation_memberships" do it "does not remove memberships for the same organisation" do - org1 = create :organisation, id: 1, slug: "test-org" + org1 = create :organisation, slug: "test-org" user = create :user, organisation: org1 group = create :group, organisation: org1 membership = create(:membership, user:, group:) @@ -62,8 +62,8 @@ end it "removes mismatched memberships" do - org1 = create :organisation, id: 1, slug: "test-org" - org2 = create :organisation, id: 2, slug: "ministry-of-testing" + org1 = create :organisation, slug: "test-org" + org2 = create :organisation, slug: "ministry-of-testing" user = create :user, organisation: org1 group = create :group, organisation: org1 membership = create(:membership, user:, group:) @@ -74,8 +74,8 @@ end it "does not remove memberships for other users" do - org1 = create :organisation, id: 1, slug: "test-org" - org2 = create :organisation, id: 2, slug: "ministry-of-testing" + org1 = create :organisation, slug: "test-org" + org2 = create :organisation, slug: "ministry-of-testing" user1 = create :user, organisation: org1 user2 = create :user, organisation: org1 diff --git a/spec/requests/forms/change_name_controller_spec.rb b/spec/requests/forms/change_name_controller_spec.rb index 949fe7011f..0239754dce 100644 --- a/spec/requests/forms/change_name_controller_spec.rb +++ b/spec/requests/forms/change_name_controller_spec.rb @@ -2,7 +2,7 @@ RSpec.describe Forms::ChangeNameController, type: :request do let(:form) { create(:form, name: "Form name", creator_id: 123) } - let(:organisation) { build :organisation, id: 1, slug: "test-org" } + let(:organisation) { build :organisation, slug: "test-org" } let(:user) { build :user, id: 1, organisation: } let(:group) { create(:group, organisation: user.organisation) } diff --git a/spec/requests/forms/submission_email_controller_spec.rb b/spec/requests/forms/submission_email_controller_spec.rb index e8a3e407bd..5037900c9c 100644 --- a/spec/requests/forms/submission_email_controller_spec.rb +++ b/spec/requests/forms/submission_email_controller_spec.rb @@ -3,7 +3,7 @@ RSpec.describe Forms::SubmissionEmailController, type: :request do include ActionView::Helpers::TextHelper - let(:organisation) { build :organisation, id: 1, slug: "test-org" } + let(:organisation) { build :organisation, slug: "test-org" } let(:user) { standard_user } let(:user_outside_group) { build :user, id: 2, organisation: } diff --git a/spec/requests/groups_controller_spec.rb b/spec/requests/groups_controller_spec.rb index 1adeb417dd..a3c2fd54b0 100644 --- a/spec/requests/groups_controller_spec.rb +++ b/spec/requests/groups_controller_spec.rb @@ -66,7 +66,7 @@ end end - let(:other_org) { create :organisation, id: 2, slug: "other-org" } + let(:other_org) { create :organisation, slug: "other-org" } let!(:other_org_trial_groups) { create_list :group, 3, organisation: other_org, status: :trial } context "when the user is not a super-admin" do diff --git a/spec/services/mailchimp/list_sync_service_spec.rb b/spec/services/mailchimp/list_sync_service_spec.rb index 9f2ed1100f..d974d28cd8 100644 --- a/spec/services/mailchimp/list_sync_service_spec.rb +++ b/spec/services/mailchimp/list_sync_service_spec.rb @@ -74,7 +74,7 @@ let(:user_without_access) { create(:user, email: "inactive_user@example.com", has_access: false) } let(:user_access_and_admin_with_mou) { create(:user, email: "admin_mou_user@example.com") } - let(:non_crown_org) { create(:organisation, id: 2, slug: "non-crown-org") } + let(:non_crown_org) { create(:organisation, slug: "non-crown-org") } let(:user_that_signed_non_crown_agreement) { create(:user, organisation: non_crown_org) } let(:not_org_admin_that_signed_non_crown_agreement) { create(:user, organisation: non_crown_org) } let(:org_admin_for_non_crown_org) { create(:user, organisation: non_crown_org) } diff --git a/spec/support/authentication_feature_helpers.rb b/spec/support/authentication_feature_helpers.rb index e053985d5f..6d20adcf23 100644 --- a/spec/support/authentication_feature_helpers.rb +++ b/spec/support/authentication_feature_helpers.rb @@ -13,7 +13,7 @@ def login_as(user, opts = {}) end def test_org - @test_org ||= FactoryBot.create(:organisation, :with_signed_mou, id: 1, slug: "test-org") + @test_org ||= FactoryBot.create(:organisation, :with_signed_mou, slug: "test-org") end def super_admin_user diff --git a/spec/views/groups/index.html.erb_spec.rb b/spec/views/groups/index.html.erb_spec.rb index adbb1d494f..a9adbfe7fa 100644 --- a/spec/views/groups/index.html.erb_spec.rb +++ b/spec/views/groups/index.html.erb_spec.rb @@ -109,7 +109,7 @@ context "when the user is a super admin" do let(:current_user) { build :super_admin_user } - let(:search_input) { OrganisationSearchInput.new({ organisation_id: current_user.organisation_id }) } + let(:search_input) { OrganisationSearchInput.new({ organisation_id: organisation.id }) } let(:organisation) { current_user.organisation } before do diff --git a/spec/views/users/edit.html.erb_spec.rb b/spec/views/users/edit.html.erb_spec.rb index b9cace5210..af603fa968 100644 --- a/spec/views/users/edit.html.erb_spec.rb +++ b/spec/views/users/edit.html.erb_spec.rb @@ -1,20 +1,20 @@ require "rails_helper" describe "users/edit.html.erb" do + let(:organisation) { create :organisation, slug: "test-org" } let(:user) do build( :user, id: 1, - organisation_id: 1, + organisation:, created_at: Time.zone.local(2023, 10, 16, 13, 24), last_signed_in_at: Time.zone.now, ) end before do - create :organisation, id: 1, slug: "test-org" - create :organisation, id: 2, slug: "ministry-of-testing" - create :organisation, id: 3, slug: "department-for-tests", name: "Department for Tests", abbreviation: "DfT" + create :organisation, slug: "ministry-of-testing" + create :organisation, slug: "department-for-tests", name: "Department for Tests", abbreviation: "DfT" travel_to(Time.zone.local(2024, 8, 26, 11, 50)) do assign(:user, user)