+ <%= form.radio_button :accredited_provider_code,
+ provider_suggestion[:provider_code],
+ checked: provider_suggestion[:provider_code] == @course.accrediting_provider&.provider_code,
+ class: "govuk-radios__input" %>
+ <%= form.label :accredited_provider_code,
+ provider_suggestion[:provider_name],
+ value: provider_suggestion[:provider_code],
+ class: "govuk-label govuk-radios__label" %>
+
diff --git a/app/views/publish/courses/ratifying_provider/edit.html.erb b/app/views/publish/courses/ratifying_provider/edit.html.erb
new file mode 100644
index 0000000000..f7a7c807a0
--- /dev/null
+++ b/app/views/publish/courses/ratifying_provider/edit.html.erb
@@ -0,0 +1,43 @@
+<% content_for :page_title, title_with_error_prefix("Ratifying provider – #{course.name_and_code}", course.errors.any?) %>
+
+<% content_for :before_content do %>
+ <%= govuk_back_link_to(details_publish_provider_recruitment_cycle_course_path(course.provider_code, course.recruitment_cycle_year, course.course_code)) %>
+<% end %>
+
+<%= render "publish/shared/errors" %>
+
+
- <%= govuk_link_to(t("cancel"), publish_provider_recruitment_cycle_accredited_providers_path(@provider.provider_code, @provider.recruitment_cycle_year)) %>
+ <%= govuk_link_to(t("cancel"), accredited_provider_search_path(param_form_key: f.object_name.to_sym, params:, recruitment_cycle_year: @recruitment_cycle.year, provider: @provider)) %>
diff --git a/app/views/publish/providers/accredited_providers/new.html.erb b/app/views/publish/providers/accredited_providers/new.html.erb
index d389e45095..66ef53b81c 100644
--- a/app/views/publish/providers/accredited_providers/new.html.erb
+++ b/app/views/publish/providers/accredited_providers/new.html.erb
@@ -12,7 +12,7 @@
<% content_for :before_content do %>
- <%= govuk_back_link_to(publish_back_link_for_adding_accrediting_provider_path(param_form_key: f.object_name.to_sym, params:, recruitment_cycle_year: @recruitment_cycle.year, provider: @provider)) %>
+ <%= govuk_back_link_to(publish_back_link_for_adding_provider_partnership_path(param_form_key: f.object_name.to_sym, params:, recruitment_cycle_year: @recruitment_cycle.year, provider: @provider)) %>
<% end %>
<%= f.govuk_text_area(
diff --git a/app/views/publish/providers/v2/training_providers/courses/index.html.erb b/app/views/publish/providers/v2/training_providers/courses/index.html.erb
new file mode 100644
index 0000000000..363cbadf61
--- /dev/null
+++ b/app/views/publish/providers/v2/training_providers/courses/index.html.erb
@@ -0,0 +1,11 @@
+<% content_for :page_title, @provider.provider_name %>
+<%= content_for :before_content, render_breadcrumbs(:training_provider_courses) %>
+
+
+ Training partner
+ <%= @training_provider.provider_name %>
+
+
+
+ <%= render partial: "publish/courses/course_table", locals: { courses: @courses } %>
+
diff --git a/app/views/publish/providers/v2/training_providers/index.html.erb b/app/views/publish/providers/v2/training_providers/index.html.erb
new file mode 100644
index 0000000000..57c95c31dd
--- /dev/null
+++ b/app/views/publish/providers/v2/training_providers/index.html.erb
@@ -0,0 +1,52 @@
+<% content_for :page_title, "Training partners" %>
+<%= content_for :before_content, render_breadcrumbs(:training_providers) %>
+
+
+ Training partners
+
+
+
+
+
+
+ <% @training_providers.each do |training_provider| %>
+
+
+ <%= govuk_link_to(
+ training_provider.provider_name,
+ publish_provider_recruitment_cycle_training_provider_courses_path(
+ @provider.provider_code,
+ @provider.recruitment_cycle_year,
+ training_provider.provider_code
+ ),
+ class: "govuk-!-font-weight-bold",
+ data: { qa: "training_provider_name" }
+ ) %>
+
+ <%= pluralize(@course_counts[training_provider.provider_code], "course") %>
+
+
+
+ <% end %>
+
+
+
+ <% unless @training_providers.empty? %>
+
+
+
Download
+
Export all the courses you’re the accredited provider for.
+
+ <%= govuk_link_to(
+ "Download as a CSV file",
+ download_training_providers_courses_publish_provider_recruitment_cycle_path(
+ @provider.provider_code,
+ @provider.recruitment_cycle_year,
+ format: :csv
+ )
+ ) %>
+
+
+
+ <% end %>
+
diff --git a/app/views/support/providers/accredited_partners/_can_remove.html.erb b/app/views/support/providers/accredited_partners/_can_remove.html.erb
new file mode 100644
index 0000000000..c7b5169ae7
--- /dev/null
+++ b/app/views/support/providers/accredited_partners/_can_remove.html.erb
@@ -0,0 +1,22 @@
+<%= content_for :page_title, t("support.providers.accredited_providers.delete.title") %>
+<% content_for :before_content do %>
+ <%= govuk_back_link_to(support_recruitment_cycle_provider_accredited_partners_path) %>
+<% end %>
+
+
+
+
+ <%= @accredited_provider.provider_name %>
+ <%= t("support.providers.accredited_partners.delete.title") %>
+
+
+ <%= govuk_button_to "Remove accredited partner",
+ delete_support_recruitment_cycle_provider_accredited_partner_path,
+ method: :delete,
+ class: "govuk-button--warning" %>
+
+
+ <%= govuk_link_to(t("cancel"), support_recruitment_cycle_provider_accredited_partners_path) %>
+
+
+
diff --git a/app/views/support/providers/accredited_partners/_cannot_remove.html.erb b/app/views/support/providers/accredited_partners/_cannot_remove.html.erb
new file mode 100644
index 0000000000..8eaf4cf7ff
--- /dev/null
+++ b/app/views/support/providers/accredited_partners/_cannot_remove.html.erb
@@ -0,0 +1,23 @@
+<% content_for :page_title, "You cannot remove this accredited partner" %>
+<% content_for :before_content do %>
+ <%= govuk_back_link_to(support_recruitment_cycle_provider_accredited_providers_path) %>
+<% end %>
+
+
+
+
+ <%= @accredited_provider.provider_name %>
+ You cannot remove this accredited provider
+
+
+
+ <%= @accredited_provider.provider_name %> is an
+ accredited partner for courses run by <%= @provider.provider_name %>. At least one of these courses is
+ currently published on Find.
+
+
+
+ <%= govuk_link_to(t("cancel"), support_recruitment_cycle_provider_accredited_partners_path) %>
+
+
+
diff --git a/app/views/support/providers/accredited_partners/checks/show.html.erb b/app/views/support/providers/accredited_partners/checks/show.html.erb
new file mode 100644
index 0000000000..df89ab4966
--- /dev/null
+++ b/app/views/support/providers/accredited_partners/checks/show.html.erb
@@ -0,0 +1,42 @@
+
+<%= render PageTitle.new(
+ title: "Check your answers - #{t('.caption', provider_name: @provider.provider_name, code: @provider.provider_code)}"
+) %>
+
+<% content_for :before_content do %>
+ <%= govuk_back_link_to(new_support_recruitment_cycle_provider_accredited_partner_path) %>
+<% end %>
+
+
+
+
+ <%= form_with(url: check_support_recruitment_cycle_provider_accredited_partners_path, method: :put, local: true) do |f| %>
+
+ <%= t(".caption", provider_name: @provider.provider_name, code: @provider.provider_code) %>
+ Check your answers
+
+
+ <%= render GovukComponent::SummaryListComponent.new do |component|
+ component.with_row do |row|
+ row.with_key { "Accredited provider" }
+ row.with_value { @accredited_provider_form.provider_name }
+ row.with_action(text: "Change", href: search_support_recruitment_cycle_provider_accredited_providers_path(goto_confirmation: true), visually_hidden_text: "accredited partner name")
+ end
+
+ component.with_row do |row|
+ row.with_key { "About the accredited partner" }
+ row.with_value { @accredited_provider_form.description }
+ row.with_action(text: "Change", href: new_support_recruitment_cycle_provider_accredited_partner_path(goto_confirmation: true), visually_hidden_text: "accredited partner description")
+ end
+ end %>
+
+ <%= govuk_warning_text(text: "All users at #{@accredited_provider_form.provider_name} will be sent an email to let them know they’ve been added.") %>
+
+ <%= f.govuk_submit(t(".add")) %>
+ <% end %>
+
+
+ <%= govuk_link_to(t("cancel"), support_recruitment_cycle_provider_accredited_partners_path) %>
+
+
+
diff --git a/app/views/support/providers/accredited_partners/delete.html.erb b/app/views/support/providers/accredited_partners/delete.html.erb
new file mode 100644
index 0000000000..a6d881ade7
--- /dev/null
+++ b/app/views/support/providers/accredited_partners/delete.html.erb
@@ -0,0 +1 @@
+<%= render partial: @cannot_delete ? "cannot_remove" : "can_remove" %>
diff --git a/app/views/support/providers/accredited_partners/edit.html.erb b/app/views/support/providers/accredited_partners/edit.html.erb
new file mode 100644
index 0000000000..6592170509
--- /dev/null
+++ b/app/views/support/providers/accredited_partners/edit.html.erb
@@ -0,0 +1,41 @@
+<% content_for :page_title, title_with_error_prefix("About the accredited partnership - Edit accredited partnership - #{@provider.name_and_code}", @accredited_provider_form.errors.present?) %>
+
+
+
+
+ <%= content_for(:breadcrumbs) do %>
+ <%= render GovukComponent::BackLinkComponent.new(
+ text: "Back",
+ href: support_recruitment_cycle_provider_accredited_partners_path(
+ recruitment_cycle_year: @recruitment_cycle.year,
+ provider_id: @provider.id
+ )
+ ) %>
+ <% end %>
+
+ <%= form_with(
+ model: @accredited_provider_form,
+ url: support_recruitment_cycle_provider_accredited_partner_path,
+ method: :put
+ ) do |f| %>
+
+ <%= f.govuk_text_area(
+ :description,
+ label: { text: t(".title"), size: "l", tag: "h1" },
+ hint: { text: t(".hint") },
+ caption: { text: @accredited_provider_form.accredited_provider.provider_name, size: "l" },
+ max_words: 100,
+ rows: 10
+ ) %>
+ <%= f.hidden_field :accredited_provider_id, value: @accredited_provider_form.accredited_provider.id %>
+
+ <%= f.govuk_submit "Update description" %>
+
+
+ <%= govuk_link_to(t("cancel"), support_recruitment_cycle_provider_accredited_partners_path) %>
+
+
+ <% end %>
+
+
+
diff --git a/app/views/support/providers/accredited_partners/index.html.erb b/app/views/support/providers/accredited_partners/index.html.erb
new file mode 100644
index 0000000000..7708eb7960
--- /dev/null
+++ b/app/views/support/providers/accredited_partners/index.html.erb
@@ -0,0 +1,20 @@
+<%= render PageTitle.new(title: "support.providers.accredited_providers.index") %>
+
+<%= govuk_button_link_to("Add accredited partner", search_support_recruitment_cycle_provider_accredited_providers_path) %>
+
+<% if @accredited_partnerships.none? %>
+
There are no accredited partnerships for <%= @provider.provider_name %>.
+<% else %>
+ <% @accredited_partnerships.each do |partnership| %>
+ <%= render AccreditedProviderComponent.new(
+ provider_name: govuk_link_to(partnership.accredited_provider.provider_name, support_recruitment_cycle_provider_path(partnership.accredited_provider.recruitment_cycle_year, partnership.accredited_provider)),
+ remove_path: delete_support_recruitment_cycle_provider_accredited_partner_path(
+ accredited_provider_code: partnership.accredited_provider.provider_code
+ ),
+ about_accredited_provider: partnership.description,
+ change_about_accredited_provider_path: edit_support_recruitment_cycle_provider_accredited_partner_path(
+ accredited_provider_code: partnership.accredited_provider.provider_code
+ )
+ ) %>
+ <% end %>
+<% end %>
diff --git a/app/views/support/providers/accredited_partners/new.html.erb b/app/views/support/providers/accredited_partners/new.html.erb
new file mode 100644
index 0000000000..085a4f15c0
--- /dev/null
+++ b/app/views/support/providers/accredited_partners/new.html.erb
@@ -0,0 +1,38 @@
+<% content_for :page_title, title_with_error_prefix("About the accredited partner - Add accredited partner - #{@provider.name_and_code}", @accredited_provider_form.errors.present?) %>
+
+
+
+
+ <%= form_with(
+ model: @accredited_provider_form,
+ url: support_recruitment_cycle_provider_accredited_partners_path,
+ method: :post
+ ) do |f| %>
+
+ <%= content_for(:breadcrumbs) do %>
+ <%= render GovukComponent::BackLinkComponent.new(
+ text: "Back",
+ href: back_link_for_adding_accredited_partner_path(param_form_key: f.object_name.to_sym, params:, recruitment_cycle_year: @recruitment_cycle.year, provider: @provider)
+ ) %>
+ <% end %>
+
+ <%= f.govuk_error_summary %>
+
+ <%= f.govuk_text_area(
+ :description,
+ label: { text: t(".title"), size: "l", tag: "h1" },
+ hint: { text: t(".hint") },
+ caption: { text: t(".caption", provider_name: @provider.provider_name, code: @provider.provider_code), size: "l" },
+ max_words: 100,
+ rows: 10
+ ) %>
+
+ <%= f.hidden_field :accredited_provider_id, value: accredited_provider_id %>
+ <%= f.govuk_submit t("continue") %>
+ <% end %>
+
+
+ <%= govuk_link_to(t("cancel"), support_recruitment_cycle_provider_accredited_partners_path) %>
+
+
+
diff --git a/app/views/support/providers/accredited_provider_search/new.html.erb b/app/views/support/providers/accredited_provider_search/new.html.erb
index 5e7554162a..11a5625b0f 100644
--- a/app/views/support/providers/accredited_provider_search/new.html.erb
+++ b/app/views/support/providers/accredited_provider_search/new.html.erb
@@ -12,7 +12,7 @@
<%= content_for(:breadcrumbs) do %>
<%= render GovukComponent::BackLinkComponent.new(
text: "Back",
- href: back_link_for_adding_accrediting_provider_path(param_form_key: f.object_name.to_sym, params:, recruitment_cycle_year: @recruitment_cycle.year, provider: @provider)
+ href: back_link_for_adding_accredited_partner_path(param_form_key: f.object_name.to_sym, params:, recruitment_cycle_year: @recruitment_cycle.year, provider: @provider)
) %>
<% end %>
@@ -39,7 +39,7 @@
<% end %>
- <%= govuk_link_to(t("cancel"), support_recruitment_cycle_provider_accredited_providers_path) %>
+ <%= govuk_link_to(t("cancel"), support_recruitment_cycle_provider_accredited_partners_path) %>
diff --git a/app/views/support/providers/accredited_providers/new.html.erb b/app/views/support/providers/accredited_providers/new.html.erb
index dfdc34edc3..9491ef1acb 100644
--- a/app/views/support/providers/accredited_providers/new.html.erb
+++ b/app/views/support/providers/accredited_providers/new.html.erb
@@ -12,7 +12,7 @@
<%= content_for(:breadcrumbs) do %>
<%= render GovukComponent::BackLinkComponent.new(
text: "Back",
- href: back_link_for_adding_accrediting_provider_path(param_form_key: f.object_name.to_sym, params:, recruitment_cycle_year: @recruitment_cycle.year, provider: @provider)
+ href: back_link_for_adding_accredited_partner_path(param_form_key: f.object_name.to_sym, params:, recruitment_cycle_year: @recruitment_cycle.year, provider: @provider)
) %>
<% end %>
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 13563409fd..f7a85c8682 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -131,6 +131,7 @@ en:
training_partners: "Training partners"
organisation_details: "Organisation details"
accredited_provider: "Accredited providers"
+ accredited_partnerships: "Accredited partnerships"
secondary_navigation:
description: Description
basic_details: Basic details
@@ -648,6 +649,24 @@ en:
new:
title: *new_search
cannot_find: *cannot_find
+ accredited_partnerships:
+ new:
+ title: About the accredited partnership
+ hint: Tell candidates about the accredited provider. You could mention their academic specialities and achievements.
+ caption: &add_accredited_partnership Add accredited partnership
+ edit:
+ title: About the accredited partnership
+ hint: Tell candidates about the accredited provider. You could mention their academic specialities and achievements.
+ updated: About the accredited partnership updated
+ delete:
+ title: Are you sure you want to remove this accredited partnership?
+ remove: Remove accredited partnership
+ updated: Accredited partnership removed
+ checks:
+ show:
+ title: *add_accredited_partnership
+ caption: *add_accredited_partnership
+ add: *add_accredited_partnership
accredited_providers:
new:
title: About the accredited provider
@@ -711,6 +730,24 @@ en:
new:
title: *accredited_provider_title
caption: &accredited_provider_caption "Add accredited provider - %{provider_name} (%{code})"
+ accredited_partners:
+ new:
+ title: About the accredited partner
+ hint: Tell candidates about the accredited partner. You could mention their academic specialities and achievements.
+ caption: "Add accredited partner - %{provider_name} (%{code})"
+ edit:
+ title: About the accredited partner
+ hint: Tell candidates about the accredited partner. You could mention their academic specialities and achievements.
+ caption: "%{provider_name}"
+ updated: About the accredited partner updated
+ delete:
+ title: Are you sure you want to remove this accredited partner?
+ remove: Remove accredited partner
+ updated: Accredited partner removed
+ checks:
+ show:
+ caption: "Add accredited partner - %{provider_name} (%{code})"
+ add: Add accredited partner
accredited_providers:
new:
title: About the accredited provider
@@ -870,6 +907,9 @@ en:
blank: "^Enter a course length"
provider_partnership:
attributes:
+ description:
+ blank: Enter details about the accredited partnership
+ too_long: Description about the accredited provider must be 100 words or fewer
accredited_provider:
format: "%{message}"
taken: This partnership already exists
@@ -947,6 +987,11 @@ en:
attributes:
provider_id:
blank: Select an accredited provider
+ provider_partnership_form:
+ attributes:
+ description:
+ blank: Enter details about the accredited partnership
+ too_long: Description about the accredited provider must be 100 words or fewer
accredited_provider_form:
attributes:
description:
diff --git a/config/routes/publish.rb b/config/routes/publish.rb
index fa087bb1fa..3ff097c772 100644
--- a/config/routes/publish.rb
+++ b/config/routes/publish.rb
@@ -125,10 +125,22 @@
resource :apprenticeship, on: :member, only: %i[new], controller: 'courses/apprenticeship' do
get 'continue'
end
- resource :accredited_provider, on: :member, only: %i[new], controller: 'courses/accredited_provider', path: 'accredited-provider' do
- get 'continue'
- get 'search_new'
+
+ # rubocop:disable Style/RedundantConstantBase
+ constraints(::Constraints::PartnershipFeature.new(:off)) do
+ resource :accredited_provider, on: :member, only: %i[new], controller: 'courses/accredited_provider', path: 'accredited-provider' do
+ get 'continue'
+ get 'search_new'
+ end
+ end
+
+ constraints(::Constraints::PartnershipFeature.new(:on)) do
+ resource :ratifying_provider, on: :member, only: %i[new], controller: 'courses/ratifying_provider', path: 'ratifying-provider' do
+ get 'continue'
+ get 'search_new'
+ end
end
+ # rubocop:enable Style/RedundantConstantBase
resource :student_visa_sponsorship, on: :member, controller: 'courses/student_visa_sponsorship', path: 'student-visa-sponsorship' do
get 'continue'
end
@@ -232,9 +244,19 @@
get '/apprenticeship', on: :member, to: 'courses/apprenticeship#edit'
put '/apprenticeship', on: :member, to: 'courses/apprenticeship#update'
- get '/accredited-provider', on: :member, to: 'courses/accredited_provider#edit'
- put '/accredited-provider', on: :member, to: 'courses/accredited_provider#update'
- get '/accredited-by', on: :member, to: 'courses/accredited_provider#show'
+ # rubocop:disable Style/RedundantConstantBase
+ constraints(::Constraints::PartnershipFeature.new(:off)) do
+ get '/accredited-provider', on: :member, to: 'courses/accredited_provider#edit'
+ put '/accredited-provider', on: :member, to: 'courses/accredited_provider#update'
+ get '/accredited-by', on: :member, to: 'courses/accredited_provider#show'
+ end
+
+ constraints(::Constraints::PartnershipFeature.new(:on)) do
+ get '/ratifying-provider', on: :member, to: 'courses/ratifying_provider#edit'
+ put '/ratifying-provider', on: :member, to: 'courses/ratifying_provider#update', as: :ratifying_provider_publish_provider_recruitment_cycle_course
+ get '/ratified-by', on: :member, to: 'courses/ratifying_provider#show'
+ end
+ # rubocop:enable Style/RedundantConstantBase
get '/provider', on: :member, to: 'courses/providers#show'
@@ -256,19 +278,54 @@
resources :courses, module: :training_providers, only: [:index]
end
- resources :accredited_providers, param: :accredited_provider_code, only: %i[index new edit create update destroy], path: 'accredited-providers' do
- member do
- get :delete
- delete :delete, to: 'accredited_providers#destroy'
+ # rubocop:disable Style/RedundantConstantBase
+ constraints(::Constraints::PartnershipFeature.new(:on)) do
+ get '/publish/organisations/:provider_code/:recruitment_cycle_year/accredited-providers', to: redirect('/publish/organisations/:provider_code/:recruitment_cycle_year/accredited-partnerships')
+ resources :accredited_partnerships, param: :accredited_provider_code, except: %i[show], path: 'accredited-partnerships', controller: 'accredited_partnerships' do
+ member do
+ get :delete
+ delete :delete, to: 'accredited_partnerships#destroy'
+ end
+
+ get '/check', on: :collection, to: 'accredited_partnerships/checks#show'
+ put '/check', on: :collection, to: 'accredited_partnerships/checks#update'
end
+ end
+
+ constraints(::Constraints::PartnershipFeature.new(:off)) do
+ resources :accredited_providers, param: :accredited_provider_code, only: %i[index new edit create update destroy], path: 'accredited-providers' do
+ member do
+ get :delete
+ delete :delete, to: 'accredited_providers#destroy'
+ end
+
+ get '/search', on: :collection, to: 'accredited_provider_search#new'
+ post '/search', on: :collection, to: 'accredited_provider_search#create'
+ put '/search', on: :collection, to: 'accredited_provider_search#update'
+
+ get '/check', on: :collection, to: 'accredited_providers/checks#show'
+ put '/check', on: :collection, to: 'accredited_providers/checks#update'
+ end
+ end
+ scope ':recruitment_cycle_year/accredited-providers', as: :accredited_providers do
get '/search', on: :collection, to: 'accredited_provider_search#new'
post '/search', on: :collection, to: 'accredited_provider_search#create'
put '/search', on: :collection, to: 'accredited_provider_search#update'
+ end
- get '/check', on: :collection, to: 'accredited_providers/checks#show'
- put '/check', on: :collection, to: 'accredited_providers/checks#update'
+ constraints(::Constraints::PartnershipFeature.new(:off)) do
+ resources :training_providers, path: '/training-providers', only: [:index], param: :code do
+ resources :courses, only: [:index], controller: 'training_providers/courses'
+ end
+ end
+
+ constraints(::Constraints::PartnershipFeature.new(:on)) do
+ resources :training_providers, path: '/training-providers', controller: 'v2/training_providers', only: [:index], param: :code do
+ resources :courses, only: [:index], controller: 'v2/training_providers/courses'
+ end
end
+ # rubocop:enable Style/RedundantConstantBase
resource :check_school, only: %i[show update], controller: 'schools_check', path: 'schools/check'
resources :schools do
diff --git a/config/routes/support.rb b/config/routes/support.rb
index 6d1be3b890..faa9c0f94d 100644
--- a/config/routes/support.rb
+++ b/config/routes/support.rb
@@ -44,20 +44,42 @@
end
scope module: :providers do
- resources :accredited_providers, param: :accredited_provider_code, only: %i[index new edit create update], path: 'accredited-providers' do
- member do
- get :delete
- delete :delete, to: 'accredited_providers#destroy'
+ # rubocop:disable Style/RedundantConstantBase
+ constraints(::Constraints::PartnershipFeature.new(:off)) do
+ resources :accredited_providers, param: :accredited_provider_code, only: %i[index new edit create update], path: 'accredited-providers' do
+ member do
+ get :delete
+ delete :delete, to: 'accredited_providers#destroy'
+ end
+ get '/search', on: :collection, to: 'accredited_provider_search#new'
+ post '/search', on: :collection, to: 'accredited_provider_search#create'
+ put '/search', on: :collection, to: 'accredited_provider_search#update'
+
+ get '/check', on: :collection, to: 'accredited_providers/checks#show'
+ put '/check', on: :collection, to: 'accredited_providers/checks#update'
end
- get '/search', on: :collection, to: 'accredited_provider_search#new'
- post '/search', on: :collection, to: 'accredited_provider_search#create'
- put '/search', on: :collection, to: 'accredited_provider_search#update'
- get '/check', on: :collection, to: 'accredited_providers/checks#show'
- put '/check', on: :collection, to: 'accredited_providers/checks#update'
+ resources :copy_courses, only: %i[new create]
end
- resources :copy_courses, only: %i[new create]
+ constraints(::Constraints::PartnershipFeature.new(:on)) do
+ resources :accredited_partners, param: :accredited_provider_code, only: %i[index new edit create update], path: 'accredited-partners' do
+ member do
+ get :delete
+ delete :delete, to: 'accredited_partners#destroy'
+ end
+ get '/check', on: :collection, to: 'accredited_partners/checks#show'
+ put '/check', on: :collection, to: 'accredited_partners/checks#update'
+ end
+
+ resources :accredited_providers, param: :accredited_provider_code, only: %i[], path: 'accredited-providers' do
+ get '/search', on: :collection, to: 'accredited_provider_search#new'
+ post '/search', on: :collection, to: 'accredited_provider_search#create'
+ put '/search', on: :collection, to: 'accredited_provider_search#update'
+ end
+ resources :copy_courses, only: %i[new create]
+ end
+ # rubocop:enable Style/RedundantConstantBase
end
end
resources :users do
diff --git a/spec/components/add_course_button_preview.rb b/spec/components/add_course_button_preview.rb
index 4c846198c7..31eca2322d 100644
--- a/spec/components/add_course_button_preview.rb
+++ b/spec/components/add_course_button_preview.rb
@@ -37,6 +37,10 @@ class FakeProvider
include ActiveModel::Model
attr_accessor(:study_sites, :accredited_providers, :sites)
+ def accredited_partners
+ []
+ end
+
def provider_code
'DFE'
end
diff --git a/spec/factories/providers.rb b/spec/factories/providers.rb
index 112a5688e1..4c462ada9f 100644
--- a/spec/factories/providers.rb
+++ b/spec/factories/providers.rb
@@ -41,6 +41,10 @@
provider_name { 'Test Name' }
end
+ trait :with_accredited_partner do
+ accredited_partnerships { [association(:provider_partnership)] }
+ end
+
trait :university do
provider_type { :university }
urn { nil }
diff --git a/spec/features/publish/accredited_partnership_spec.rb b/spec/features/publish/accredited_partnership_spec.rb
new file mode 100644
index 0000000000..3453f5e65a
--- /dev/null
+++ b/spec/features/publish/accredited_partnership_spec.rb
@@ -0,0 +1,290 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+feature 'Accredited partnership flow', { can_edit_current_and_next_cycles: false } do
+ before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(true)
+ given_i_am_a_lead_school_provider_user
+ and_i_visit_the_root_path
+ when_i_click_on_the_accredited_provider_tab
+ end
+
+ scenario 'i can view the accredited providers tab when there are none' do
+ then_i_see_the_correct_text_for_no_accredited_providers
+ end
+
+ scenario 'i can view accredited partnerships on the index page' do
+ and_my_provider_has_accrediting_providers
+ and_i_click_on_the_accredited_provider_tab
+ then_i_should_see_the_accredited_provider_name_displayed
+ end
+
+ scenario 'i can edit accredited partnerships on the index page' do
+ and_my_provider_has_accrediting_providers
+ and_i_click_on_the_accredited_provider_tab
+ and_i_click_change
+
+ when_i_input_some_different_information
+ then_i_should_see_the_different_information
+ and_i_see_the_success_message
+ end
+
+ scenario 'i cannot delete accredited providers if they are attached to a course' do
+ and_my_provider_has_accrediting_providers
+ and_i_click_on_the_accredited_provider_tab
+ and_i_click_remove
+ then_i_should_see_the_cannot_remove_ap_text
+ end
+
+ scenario 'i can delete accredited providers if they are not attached to a course' do
+ and_i_create_a_new_accredited_provider
+ and_i_click_remove
+ and_i_click_remove_ap
+ and_i_see_the_remove_success_message
+ then_i_should_be_taken_to_the_index_page
+ end
+
+ scenario 'i can create a new provider partnership' do
+ given_there_are_accredited_providers_in_the_database_with_users
+ when_i_click_add_accredited_provider
+ and_i_search_with_an_invalid_query
+ then_i_should_see_an_error_message
+
+ when_i_search_for_an_accredited_provider_with_a_valid_query
+ then_i_see_the_provider_i_searched_for
+
+ when_i_continue_without_selecting_an_accredited_provider
+ and_i_should_see_an_error_message('Select an accredited provider')
+ then_i_should_still_see_the_provider_i_searched_for
+
+ when_i_select_the_provider
+ and_i_continue_without_entering_a_description
+ then_i_should_see_an_error_message('Enter details about the accredited partnership')
+
+ when_i_input_some_information
+ then_i_should_see_the_information_i_added
+
+ when_i_confirm_the_changes
+ then_i_should_be_taken_to_the_index_page
+ and_the_accredited_provider_is_saved_to_the_database
+ and_i_should_see_a_success_message
+ and_i_should_see_the_accredited_providers
+ end
+
+ scenario 'back links behaviour' do
+ given_i_am_on_the_confirm_page
+ when_i_click_the_change_link_for('accredited provider name')
+ then_i_should_be_taken_to_the_accredited_provider_search_page
+
+ when_i_click_the_back_link
+ then_i_should_be_taken_back_to_the_confirm_page
+
+ when_i_click_the_change_link_for('accredited provider description')
+ then_i_should_be_taken_to_the_accredited_provider_description_page
+
+ when_i_click_the_back_link
+ then_i_should_be_taken_back_to_the_confirm_page
+ end
+
+ private
+
+ def and_i_click_remove_ap
+ click_link_or_button 'Remove accredited partnership'
+ end
+
+ def then_i_should_see_the_cannot_remove_ap_text
+ expect(page).to have_css('h1', text: 'You cannot remove this accredited provider')
+ end
+
+ def and_i_click_remove
+ click_link_or_button 'Remove'
+ end
+
+ def and_i_create_a_new_accredited_provider
+ given_there_are_accredited_providers_in_the_database_with_users
+ when_i_click_add_accredited_provider
+ when_i_search_for_an_accredited_provider_with_a_valid_query
+ when_i_select_the_provider
+ when_i_input_some_information
+ when_i_confirm_the_changes
+ end
+
+ def and_i_click_change
+ click_link_or_button('Change')
+ end
+
+ def and_i_should_see_the_accredited_providers
+ expect(page).to have_css('.govuk-summary-card', count: 1)
+ expect(page).to have_content(@accredited_provider.provider_name)
+ end
+
+ def and_the_accredited_provider_is_saved_to_the_database
+ @provider.reload
+ expect(@provider.accredited_partners.count).to eq(1)
+ expect(@provider.accredited_partners.first.id).to eq(@accredited_provider.id)
+ end
+
+ def then_i_should_be_taken_to_the_accredited_provider_description_page
+ expect(page).to have_current_path(new_publish_provider_recruitment_cycle_accredited_partnership_path(@provider.provider_code, @provider.recruitment_cycle_year, goto_confirmation: true))
+ end
+
+ def then_i_should_be_taken_back_to_the_confirm_page
+ expect(page).to have_current_path(check_publish_provider_recruitment_cycle_accredited_partnerships_path(@provider.provider_code, @provider.recruitment_cycle_year))
+ end
+
+ def when_i_click_the_back_link
+ click_link_or_button 'Back'
+ end
+
+ def then_i_should_be_taken_to_the_accredited_provider_search_page
+ expect(page).to have_current_path(
+ search_publish_provider_recruitment_cycle_accredited_providers_path(@provider.provider_code, @provider.recruitment_cycle_year, goto_confirmation: true)
+ )
+ end
+
+ def when_i_click_the_change_link_for(field)
+ within '.govuk-summary-list' do
+ click_link_or_button "Change #{field}"
+ end
+ end
+
+ def given_i_am_on_the_confirm_page
+ given_there_are_accredited_providers_in_the_database_with_users
+ when_i_click_add_accredited_provider
+ when_i_search_for_an_accredited_provider_with_a_valid_query
+ when_i_select_the_provider
+ when_i_input_some_information
+ end
+
+ def and_i_should_see_a_success_message
+ expect(page).to have_content('Accredited partnership added')
+ end
+
+ def and_i_see_the_success_message
+ expect(page).to have_content('About the accredited partnership updated')
+ end
+
+ def and_i_see_the_remove_success_message
+ expect(page).to have_content('Accredited partnership removed')
+ end
+
+ def then_i_should_be_taken_to_the_index_page
+ expect(page).to have_current_path(publish_provider_recruitment_cycle_accredited_partnerships_path(@provider.provider_code, @provider.recruitment_cycle_year))
+ end
+
+ def when_i_confirm_the_changes
+ expect do
+ click_link_or_button 'Add accredited partnership'
+ end.to have_enqueued_email(Users::OrganisationMailer, :added_as_an_organisation_to_training_partner)
+ end
+
+ def then_i_should_see_the_information_i_added
+ expect(page).to have_text('This is a description')
+ end
+
+ def then_i_should_see_the_different_information
+ expect(page).to have_text('updates to the AP description')
+ end
+
+ alias_method :then_i_should_see_the_description, :then_i_should_see_the_information_i_added
+
+ def when_i_input_some_information
+ fill_in 'About the accredited partnership', with: 'This is a description'
+ click_continue
+ end
+
+ def when_i_input_some_different_information
+ fill_in 'About the accredited partnership', with: 'updates to the AP description'
+ click_link_or_button 'Update description'
+ end
+
+ def and_i_search_with_an_invalid_query
+ fill_in form_title, with: ''
+ click_continue
+ end
+
+ def when_i_select_the_provider
+ choose @accredited_provider.provider_name
+ click_continue
+ end
+
+ def then_i_should_still_see_the_provider_i_searched_for
+ expect(page).to have_content(@accredited_provider.provider_name)
+ expect(page).to have_no_content(@accredited_provider_two.provider_name)
+ expect(page).to have_no_content(@accredited_provider_three.provider_name)
+ end
+
+ def and_i_should_see_an_error_message(error_message = form_title)
+ expect(page).to have_content(error_message)
+ end
+
+ alias_method :then_i_should_see_an_error_message, :and_i_should_see_an_error_message
+
+ def when_i_continue_without_selecting_an_accredited_provider
+ click_continue
+ end
+
+ def then_i_see_the_provider_i_searched_for
+ expect(page).to have_content(@accredited_provider.provider_name)
+ expect(page).to have_no_content(@accredited_provider_two.provider_name)
+ expect(page).to have_no_content(@accredited_provider_three.provider_name)
+ end
+
+ def given_there_are_accredited_providers_in_the_database_with_users
+ user = create(:user)
+ @accredited_provider = create(:provider, :accredited_provider, provider_name: 'UCL')
+ @accredited_provider.users << user
+ @accredited_provider_two = create(:provider, :accredited_provider, provider_name: 'Accredited provider two')
+ @accredited_provider_three = create(:provider, :accredited_provider, provider_name: 'Accredited provider three')
+ end
+
+ def when_i_search_for_an_accredited_provider_with_a_valid_query
+ fill_in form_title, with: @accredited_provider.provider_name
+ click_continue
+ end
+
+ def when_i_click_add_accredited_provider
+ click_link_or_button 'Add accredited partnership'
+ end
+
+ def then_i_see_the_correct_text_for_no_accredited_providers
+ expect(page).to have_text("There are no accredited providers for #{@provider.provider_name}")
+ end
+
+ def when_i_click_on_the_accredited_provider_tab
+ click_link_or_button 'Accredited partnership'
+ end
+
+ alias_method :and_i_click_on_the_accredited_provider_tab, :when_i_click_on_the_accredited_provider_tab
+
+ def and_i_visit_the_root_path
+ visit root_path
+ end
+
+ def given_i_am_a_lead_school_provider_user
+ given_i_am_authenticated(user: create(:user, :with_provider))
+ @provider = @current_user.providers.first
+ end
+
+ def form_title
+ 'Enter a provider name, UKPRN or postcode'
+ end
+
+ def click_continue
+ click_link_or_button 'Continue'
+ end
+
+ alias_method :and_i_continue_without_entering_a_description, :click_continue
+
+ def and_my_provider_has_accrediting_providers
+ course = build(:course, accrediting_provider: build(:provider, :accredited_provider, provider_name: 'Accrediting provider name'))
+
+ @provider.courses << course
+ @provider.accredited_partnerships.create(accredited_provider: course.accrediting_provider, description: 'Great provider!')
+ end
+
+ def then_i_should_see_the_accredited_provider_name_displayed
+ expect(page).to have_css('h2', text: 'Accrediting provider name')
+ end
+end
diff --git a/spec/features/publish/accredited_provider_spec.rb b/spec/features/publish/accredited_provider_spec.rb
index 4dc5b09d2e..f60ec8a6d7 100644
--- a/spec/features/publish/accredited_provider_spec.rb
+++ b/spec/features/publish/accredited_provider_spec.rb
@@ -4,6 +4,7 @@
feature 'Accredited provider flow', { can_edit_current_and_next_cycles: false } do
before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(false)
given_i_am_a_lead_school_provider_user
and_i_visit_the_root_path
when_i_click_on_the_accredited_provider_tab
diff --git a/spec/features/publish/courses/add_accredited_provider_when_publishing_a_course_spec.rb b/spec/features/publish/courses/add_accredited_provider_when_publishing_a_course_spec.rb
index 0e56ce6491..bd68378a65 100644
--- a/spec/features/publish/courses/add_accredited_provider_when_publishing_a_course_spec.rb
+++ b/spec/features/publish/courses/add_accredited_provider_when_publishing_a_course_spec.rb
@@ -4,6 +4,7 @@
feature 'Publishing a course when course accrediting provider is invalid', { can_edit_current_and_next_cycles: false } do
before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(false)
given_i_am_authenticated_as_a_provider_user
end
diff --git a/spec/features/publish/courses/add_ratifying_provider_when_publishing_a_course_spec.rb b/spec/features/publish/courses/add_ratifying_provider_when_publishing_a_course_spec.rb
new file mode 100644
index 0000000000..bbf29d858e
--- /dev/null
+++ b/spec/features/publish/courses/add_ratifying_provider_when_publishing_a_course_spec.rb
@@ -0,0 +1,170 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+feature 'Publishing a course when course accrediting provider is invalid', { can_edit_current_and_next_cycles: false } do
+ before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(true)
+ given_i_am_authenticated_as_a_provider_user
+ end
+
+ scenario 'Add accrediting provider to provider and provider has no accrediting providers, change accrediting provider of course then publish' do
+ and_the_provider_has_no_accredited_provider
+ and_there_is_a_draft_course_with_an_unaccredited_provider
+
+ # Publising is invalid
+ when_i_visit_the_course_page
+ and_i_click_the_publish_button
+ then_i_should_see_an_error_message_that_accredited_provider_is_not_accredited
+
+ # Add accrediting provider to provider
+ when_i_click_the_error_message_link
+ then_it_takes_me_to_the_accredited_providers_page
+ when_i_click_add_an_accredited_provider
+ and_i_search_for_an_accredited_provider
+ and_i_fill_in_the_accredited_provider_form
+ and_i_confirm_creation_of_the_accredited_provider
+ then_i_see_that_the_accredited_provider_has_been_added
+
+ # Publishing is invalid
+ when_i_visit_the_course_page
+ and_i_click_the_publish_button
+ then_i_should_see_an_error_message_that_accredited_provider_is_not_accredited
+
+ # Clicking error message allows user to select accrediting provider
+ when_i_click_the_error_message_link
+ and_i_choose_the_new_accredited_provider
+ and_i_click_the_publish_button
+ then_i_should_see_a_success_message
+ end
+
+ scenario 'Select valid accrediting provider to course and publish' do
+ and_the_provider_has_a_valid_accrediting_provider
+ and_there_is_a_draft_course_without_accrediting_provider
+ and_an_accredited_provider_exists
+
+ # Publising is invalid
+ when_i_visit_the_course_page
+ and_i_click_the_publish_button
+ then_i_should_see_an_error_message_for_the_accrediting_provider
+
+ # Clicking error message allows user to select accrediting provider
+ when_i_click_the_select_accredited_provider_error_message_link
+ and_i_choose_the_new_accredited_provider
+ and_i_click_the_publish_button
+ then_i_should_see_a_success_message
+ end
+
+ def given_i_am_authenticated_as_a_provider_user
+ @user = create(:user, :with_provider)
+ given_i_am_authenticated(user: @user)
+ end
+
+ def and_the_provider_has_a_valid_accrediting_provider
+ provider = @user.providers.first
+ provider.accredited_partnerships.create(accredited_provider: accredited_provider, description: 'Description')
+ end
+
+ def and_the_provider_has_no_accredited_provider
+ expect(provider.accredited_providers).to be_empty
+ end
+
+ def and_there_is_a_draft_course_without_accrediting_provider
+ given_a_course_exists(
+ :with_gcse_equivalency,
+ enrichments: [create(:course_enrichment, :initial_draft)],
+ sites: [create(:site, location_name: 'location 1')],
+ study_sites: [create(:site, :study_site)]
+ )
+ end
+
+ def and_there_is_a_draft_course_with_an_unaccredited_provider
+ given_a_course_exists(
+ :with_gcse_equivalency,
+ accrediting_provider: provider,
+ enrichments: [create(:course_enrichment, :initial_draft)],
+ sites: [create(:site, location_name: 'location 1')],
+ study_sites: [create(:site, :study_site)]
+ )
+ end
+
+ def when_i_visit_the_course_page
+ publish_provider_courses_show_page.load(
+ provider_code: provider.provider_code,
+ recruitment_cycle_year: provider.recruitment_cycle_year,
+ course_code: course.course_code
+ )
+ end
+
+ def then_i_should_see_a_success_message
+ expect(page).to have_content('Your course has been published.')
+ end
+
+ def then_i_should_see_an_error_message_that_accredited_provider_is_not_accredited
+ expect(publish_provider_courses_show_page.error_messages).to include('Update the accredited provider')
+ end
+
+ def then_i_should_see_an_error_message_for_the_accrediting_provider
+ expect(publish_provider_courses_show_page.error_messages).to include('Select an accredited provider')
+ end
+
+ def when_i_click_the_error_message_link
+ publish_provider_courses_show_page.errors.first.link.click
+ end
+
+ def then_it_takes_me_to_the_accredited_providers_page
+ expect(publish_courses_ratifying_providers_page).to be_displayed
+ end
+
+ def when_i_click_add_an_accredited_provider
+ publish_courses_accredited_providers_page.add_new_link.click
+ expect(publish_provider_accredited_providers_search_page).to be_displayed
+ end
+
+ def and_i_search_for_an_accredited_provider
+ publish_provider_accredited_providers_search_page.search_input.set(accredited_provider.provider_name)
+ publish_provider_accredited_providers_search_page.continue_button.click
+ choose accredited_provider.name_and_code
+ publish_provider_accredited_providers_search_page.continue_button.click
+ end
+
+ def and_i_fill_in_the_accredited_provider_form
+ publish_courses_new_accredited_provider_page.about_section_input.set('About course')
+
+ publish_courses_new_accredited_provider_page.submit.click
+ end
+
+ def and_i_confirm_creation_of_the_accredited_provider
+ publish_courses_new_accredited_provider_page.submit.click
+ end
+
+ def then_i_see_that_the_accredited_provider_has_been_added
+ expect(page).to have_content('Accredited partnership added')
+ end
+
+ def and_i_click_the_publish_button
+ publish_provider_courses_show_page.publish_button.click
+ end
+
+ def when_i_click_the_select_accredited_provider_error_message_link
+ page.click_link_or_button('Select an accredited provider')
+ end
+
+ def and_i_choose_the_new_accredited_provider
+ choose accredited_provider.provider_name
+ page.click_link_or_button('Update ratifying partner')
+ expect(page).to have_content('Accredited provider updated')
+ end
+
+ def and_an_accredited_provider_exists
+ accredited_provider
+ end
+
+ def accredited_provider
+ @accredited_provider ||= create(:provider, :accredited_provider)
+ end
+
+ def provider
+ @current_user.providers.first
+ end
+end
diff --git a/spec/features/publish/courses/adding_a_ratifying_provider_to_an_unpublished_course_spec.rb b/spec/features/publish/courses/adding_a_ratifying_provider_to_an_unpublished_course_spec.rb
new file mode 100644
index 0000000000..283e2a9968
--- /dev/null
+++ b/spec/features/publish/courses/adding_a_ratifying_provider_to_an_unpublished_course_spec.rb
@@ -0,0 +1,120 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+feature 'unpublished course without accredited provider', { can_edit_current_and_next_cycles: false } do
+ before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(true)
+ end
+
+ scenario 'adding and changing an accredited provider' do
+ given_i_am_authenticated_as_a_provider_user
+ and_i_visit_the_course_details_page_of_a_course_without_an_accredited_provider
+ and_i_click_the_add_accredited_provider_link
+ and_i_create_a_new_accredited_provider
+ and_i_revisit_the_course_details_page
+ when_i_click_select_an_accredited_provider
+ and_i_choose_the_new_accredited_provider
+ then_i_should_see_the_success_message
+
+ given_i_click_change_accredited_provider
+ and_i_click_update_accredited_provider
+ then_i_should_see_the_success_message
+ end
+
+ def given_i_click_change_accredited_provider
+ click_link_or_button 'Change accredited provider'
+ end
+
+ def then_i_should_see_the_success_message
+ expect(page).to have_text('Accredited provider updated')
+ end
+
+ def and_i_click_update_accredited_provider
+ click_link_or_button 'Update ratifying partner'
+ end
+
+ def and_i_choose_the_new_accredited_provider
+ choose @accredited_provider.provider_name
+ and_i_click_update_accredited_provider
+ end
+
+ def when_i_click_select_an_accredited_provider
+ click_link_or_button 'Select an accredited partner'
+ end
+
+ def and_i_create_a_new_accredited_provider
+ and_there_is_an_accredited_provider_in_the_database
+ and_i_click_add_accredited_provider_link
+ and_i_search_for_an_accredited_provider_with_a_valid_query
+ and_i_select_the_provider
+ and_i_input_some_information
+ and_i_click_add_accredited_provider_button
+ end
+
+ def and_i_select_the_provider
+ choose @accredited_provider.provider_name
+ click_continue
+ end
+
+ def and_i_input_some_information
+ fill_in 'About the accredited partner', with: 'This is a description'
+ click_continue
+ end
+
+ def and_there_is_an_accredited_provider_in_the_database
+ @accredited_provider = create(:provider, :accredited_provider, provider_name: 'UCL')
+ end
+
+ def and_i_search_for_an_accredited_provider_with_a_valid_query
+ fill_in form_title, with: @accredited_provider.provider_name
+ click_continue
+ end
+
+ def click_continue
+ click_link_or_button 'Continue'
+ end
+
+ def form_title
+ 'Enter a provider name, UKPRN or postcode'
+ end
+
+ def and_i_click_the_add_accredited_provider_link
+ click_link_or_button 'Add at least one accredited partner'
+ end
+
+ def and_i_click_add_accredited_provider_link
+ click_link_or_button 'Add accredited partner'
+ end
+
+ def and_i_click_add_accredited_provider_button
+ click_link_or_button 'Add accredited partner'
+ end
+
+ def given_i_am_authenticated_as_a_provider_user
+ given_i_am_authenticated(
+ user: create(
+ :user,
+ providers: [
+ create(:provider, sites: [build(:site)], courses: [build(:course)])
+ ]
+ )
+ )
+ end
+
+ def and_i_visit_the_course_details_page_of_a_course_without_an_accredited_provider
+ publish_provider_courses_details_page.load(
+ provider_code: provider.provider_code, recruitment_cycle_year: provider.recruitment_cycle_year, course_code: course.course_code
+ )
+ end
+
+ alias_method :and_i_revisit_the_course_details_page, :and_i_visit_the_course_details_page_of_a_course_without_an_accredited_provider
+
+ def provider
+ @current_user.providers.first
+ end
+
+ def course
+ provider.courses.first
+ end
+end
diff --git a/spec/features/publish/courses/adding_an_accredited_provider_to_an_unpublished_course_spec.rb b/spec/features/publish/courses/adding_an_accredited_provider_to_an_unpublished_course_spec.rb
index a1764de28e..2728eb4bba 100644
--- a/spec/features/publish/courses/adding_an_accredited_provider_to_an_unpublished_course_spec.rb
+++ b/spec/features/publish/courses/adding_an_accredited_provider_to_an_unpublished_course_spec.rb
@@ -3,6 +3,10 @@
require 'rails_helper'
feature 'unpublished course without accredited provider', { can_edit_current_and_next_cycles: false } do
+ before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(false)
+ end
+
scenario 'adding and changing an accredited provider' do
given_i_am_authenticated_as_a_provider_user
and_i_visit_the_course_details_page_of_a_course_without_an_accredited_provider
diff --git a/spec/features/publish/courses/new_accredited_provider_spec.rb b/spec/features/publish/courses/new_accredited_provider_spec.rb
index 2c952020a2..507ea08d8d 100644
--- a/spec/features/publish/courses/new_accredited_provider_spec.rb
+++ b/spec/features/publish/courses/new_accredited_provider_spec.rb
@@ -4,6 +4,7 @@
feature 'selection accredited_bodies', { can_edit_current_and_next_cycles: false } do
before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(false)
given_i_am_authenticated_as_a_provider_user
when_i_visit_the_new_accredited_providers_page
end
diff --git a/spec/features/publish/courses/new_schools_enrichments_spec.rb b/spec/features/publish/courses/new_schools_enrichments_spec.rb
new file mode 100644
index 0000000000..d262e715d3
--- /dev/null
+++ b/spec/features/publish/courses/new_schools_enrichments_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+feature 'selection schools', { can_edit_current_and_next_cycles: false } do
+ before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(false)
+ given_i_am_authenticated_as_a_provider_user
+ and_that_sites_exist
+ when_i_visit_the_publish_courses_new_schools_page
+ end
+
+ scenario 'selecting multiple schools' do
+ when_i_select_a_school
+ and_i_click_continue
+ then_i_am_met_with_the_accredited_provider_page
+ end
+
+ scenario 'invalid entries' do
+ and_i_click_continue
+ then_i_am_met_with_errors
+ end
+
+ private
+
+ def given_i_am_authenticated_as_a_provider_user
+ @user = create(:user, :with_provider)
+ given_i_am_authenticated(user: @user)
+ end
+
+ def and_that_sites_exist
+ provider.sites << create_list(:site, 3)
+ end
+
+ def when_i_visit_the_publish_courses_new_schools_page
+ publish_courses_new_schools_page.load(provider_code: provider.provider_code, recruitment_cycle_year: Settings.current_recruitment_cycle_year, query: schools_params)
+ end
+
+ def when_i_select_a_school
+ publish_courses_new_schools_page.check(provider.sites.first.location_name)
+ publish_courses_new_schools_page.check(provider.sites.second.location_name)
+ end
+
+ def and_i_click_continue
+ publish_courses_new_schools_page.continue.click
+ end
+
+ def provider
+ @provider ||= @user.providers.first
+ end
+
+ def then_i_am_met_with_the_accredited_provider_page
+ expect(page).to have_current_path("/publish/organisations/#{provider.provider_code}/#{Settings.current_recruitment_cycle_year}/courses/accredited-provider/new", ignore_query: true)
+ expect(page).to have_content('Accredited provider')
+ end
+
+ def then_i_am_met_with_errors
+ expect(page).to have_content('There is a problem')
+ expect(page).to have_content('Select at least one school')
+ end
+end
diff --git a/spec/features/publish/courses/new_schools_spec.rb b/spec/features/publish/courses/new_schools_spec.rb
index 1f33ef0bac..6baf9685fa 100644
--- a/spec/features/publish/courses/new_schools_spec.rb
+++ b/spec/features/publish/courses/new_schools_spec.rb
@@ -4,6 +4,7 @@
feature 'selection schools', { can_edit_current_and_next_cycles: false } do
before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(true)
given_i_am_authenticated_as_a_provider_user
and_that_sites_exist
when_i_visit_the_publish_courses_new_schools_page
@@ -49,8 +50,8 @@ def provider
end
def then_i_am_met_with_the_accredited_provider_page
- expect(page).to have_current_path("/publish/organisations/#{provider.provider_code}/#{Settings.current_recruitment_cycle_year}/courses/accredited-provider/new", ignore_query: true)
- expect(page).to have_content('Accredited provider')
+ expect(page).to have_current_path("/publish/organisations/#{provider.provider_code}/#{Settings.current_recruitment_cycle_year}/courses/ratifying-provider/new", ignore_query: true)
+ expect(page).to have_content('Ratifying provider')
end
def then_i_am_met_with_errors
diff --git a/spec/features/publish/courses/new_tda_course_spec.rb b/spec/features/publish/courses/new_tda_course_spec.rb
index 78887ef842..3a656a1c60 100644
--- a/spec/features/publish/courses/new_tda_course_spec.rb
+++ b/spec/features/publish/courses/new_tda_course_spec.rb
@@ -3,6 +3,10 @@
require 'rails_helper'
feature 'Adding a teacher degree apprenticeship course', :can_edit_current_and_next_cycles do
+ before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(false)
+ end
+
scenario 'creating a degree awarding course from school direct provider' do
given_i_am_authenticated_as_a_school_direct_provider_user
when_i_visit_the_courses_page
diff --git a/spec/features/publish/courses/new_tda_ratifying_course_spec.rb b/spec/features/publish/courses/new_tda_ratifying_course_spec.rb
new file mode 100644
index 0000000000..768552890d
--- /dev/null
+++ b/spec/features/publish/courses/new_tda_ratifying_course_spec.rb
@@ -0,0 +1,665 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+feature 'Adding a teacher degree apprenticeship course', :can_edit_current_and_next_cycles do
+ before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(true)
+ end
+
+ scenario 'creating a degree awarding course from school direct provider' do
+ given_i_am_authenticated_as_a_school_direct_provider_user
+ when_i_visit_the_courses_page
+ and_i_click_on_add_course
+ and_i_choose_a_secondary_course
+ and_i_select_a_subject
+ and_i_choose_an_age_range
+ then_i_see_the_degree_awarding_option
+
+ when_i_choose_a_degree_awarding_qualification
+
+ # We skip the pages for the TDA: funding type, part-time/full time
+ then_i_am_on_the_choose_schools_page
+
+ when_i_choose_the_school
+ and_i_choose_the_study_site
+
+ # We skip the visa sponsorship question
+ then_i_am_on_the_add_applications_open_date_page
+
+ when_i_choose_the_applications_open_date
+ and_i_choose_the_first_start_date
+ then_i_am_on_the_check_your_answers_page
+ and_i_can_not_change_funding_type
+ and_i_can_not_change_study_mode
+ and_i_can_not_change_visa_requirements
+ then_i_do_not_see_the_change_links_for_study_mode_funding_type_and_visa_sponsorship
+
+ when_i_click_on_add_a_course
+ then_the_tda_course_is_created
+ and_the_tda_defaults_are_saved
+
+ when_i_click_on_the_course_i_created
+ then_i_do_not_see_the_change_links_for_study_mode_funding_type_and_visa_sponsorship_on_basic_details
+
+ when_i_click_on_the_course_description_tab
+ then_i_do_not_see_the_degree_requirements_row
+ and_i_do_not_see_the_change_link_for_course_length
+
+ given_i_fill_in_all_other_fields_for_the_course
+ and_i_add_a_level_requirements
+ when_i_publish_the_course
+ then_the_course_is_published
+ end
+
+ scenario 'creating a degree awarding course from scitt provider' do
+ given_i_am_authenticated_as_a_scitt_provider_user
+ when_i_visit_the_courses_page
+ and_i_click_on_add_course
+ and_i_choose_a_secondary_course
+ and_i_select_a_subject
+ and_i_choose_an_age_range
+ then_i_see_the_degree_awarding_option
+
+ when_i_choose_a_degree_awarding_qualification
+ # We skip the pages for the TDA: funding type, part-time/full time
+ then_i_am_on_the_choose_schools_page
+
+ when_i_choose_the_school
+ and_i_choose_the_study_site
+ # We skip the visa sponsorship question
+ then_i_am_on_the_add_applications_open_date_page
+
+ when_i_choose_the_applications_open_date
+ and_i_choose_the_first_start_date
+ then_i_am_on_the_check_your_answers_page
+ and_i_do_not_see_the_change_links_for_study_mode_funding_type_and_visa_sponsorship
+
+ when_i_click_on_add_a_course
+ then_the_tda_course_is_created
+ and_the_tda_defaults_are_saved
+
+ when_i_click_on_the_course_i_created
+ then_i_do_not_see_the_change_links_for_study_mode_funding_type_and_visa_sponsorship_on_basic_details
+
+ when_i_click_on_the_course_description_tab
+ then_i_do_not_see_the_degree_requirements_row
+ and_i_do_not_see_the_change_link_for_course_length
+
+ given_i_fill_in_all_other_fields_for_the_course
+ and_i_add_a_level_requirements
+ when_i_publish_the_course
+ then_the_course_is_published
+ end
+
+ scenario 'when choosing primary course' do
+ given_i_am_authenticated_as_a_school_direct_provider_user
+ when_i_visit_the_courses_page
+ and_i_click_on_add_course
+ and_i_choose_a_primary_course
+ and_i_choose_a_primary_age_range
+ then_i_see_the_degree_awarding_option
+
+ when_i_choose_a_degree_awarding_qualification
+ # We skip the pages for the TDA: funding type, part-time/full time
+ then_i_am_on_the_choose_schools_page
+
+ when_i_choose_the_school
+ and_i_choose_the_study_site
+ # We skip the visa sponsorship question
+ then_i_am_on_the_add_applications_open_date_page
+
+ when_i_choose_the_applications_open_date
+ and_i_choose_the_first_start_date
+ then_i_am_on_the_check_your_answers_page
+ and_i_do_not_see_the_change_links_for_study_mode_funding_type_and_visa_sponsorship
+
+ when_i_click_on_add_a_course
+ then_the_tda_course_is_created
+ and_the_tda_defaults_are_saved
+
+ when_i_click_on_the_course_i_created
+ then_i_do_not_see_the_change_links_for_study_mode_funding_type_and_visa_sponsorship_on_basic_details
+
+ when_i_click_on_the_course_description_tab
+ then_i_do_not_see_the_degree_requirements_row
+ and_i_do_not_see_the_change_link_for_course_length
+
+ given_i_fill_in_all_other_fields_for_the_course
+ and_i_add_a_level_requirements
+ when_i_publish_the_course
+ then_the_course_is_published
+ end
+
+ scenario 'do not show teacher degree apprenticeship for further education' do
+ given_i_am_authenticated_as_a_school_direct_provider_user
+ when_i_visit_the_courses_page
+ and_i_click_on_add_course
+ and_i_choose_a_further_education_course
+ then_i_am_on_the_qualifications_page
+ and_i_do_not_see_the_degree_awarding_option
+ end
+
+ scenario 'back links when choosing a teacher degree apprenticeship' do
+ given_i_am_authenticated_as_a_school_direct_provider_user
+ when_i_visit_the_courses_page
+ and_i_click_on_add_course
+ and_i_choose_a_primary_course
+ and_i_choose_a_primary_age_range
+ then_i_see_the_degree_awarding_option
+
+ when_i_choose_a_degree_awarding_qualification
+ # We skip the pages for the TDA: funding type, part-time/full time
+ then_i_am_on_the_choose_schools_page
+ and_the_back_link_points_to_outcome_page
+
+ when_i_choose_the_school
+ then_the_back_link_points_to_the_school_page
+ and_i_choose_the_study_site
+ # We skip the visa sponsorship question
+ then_i_am_on_the_add_applications_open_date_page
+ and_the_back_link_points_to_the_study_site_page
+
+ when_i_choose_the_applications_open_date
+ and_the_back_link_points_to_applications_open_date_page
+ and_i_choose_the_first_start_date
+ and_the_back_link_points_to_start_date_page
+ then_i_am_on_the_check_your_answers_page
+ end
+
+ scenario 'creating a tda course then changing it to a non tda fee paying course' do
+ given_i_am_on_the_check_answers_page_of_a_new_tda_course
+ when_i_visit_the_course_outcome_page
+ and_the_back_link_points_to_the_confirm_page
+
+ and_i_choose_qts
+ and_the_back_link_points_to_the_qualification_page
+
+ and_i_choose_fee
+ and_the_back_link_points_to_the_funding_type_page
+
+ and_i_choose_part_time
+ and_the_back_link_points_to_the_study_mode_page
+
+ when_i_click_back
+ then_i_am_on_the_study_mode_page
+
+ when_i_click_back
+ then_i_am_on_the_funding_type_page
+
+ when_i_click_continue
+ and_i_click_continue
+ and_i_choose_to_sponsor_a_student_visa
+ when_i_click_on_add_a_course
+ then_i_see_the_correct_attributes_in_the_database_for_fee_paying
+ end
+
+ scenario 'creating a tda course then changing it to a non tda salaried course' do
+ given_i_am_on_the_check_answers_page_of_a_new_tda_course
+ when_i_visit_the_course_outcome_page
+ and_i_choose_qts
+ and_the_back_link_points_to_the_qualification_page
+ and_i_choose_salaried
+ and_the_back_link_points_to_the_funding_type_page
+ and_i_choose_part_time
+ and_the_back_link_points_to_the_study_mode_page
+ when_i_click_back
+ then_i_am_on_the_study_mode_page
+
+ when_i_click_back
+ then_i_am_on_the_funding_type_page
+
+ when_i_click_continue
+ and_i_click_continue
+
+ and_i_choose_to_sponsor_a_skilled_worker_visa
+ when_i_click_on_add_a_course
+ then_i_see_the_correct_attributes_in_the_database_for_salaried
+ end
+
+ def given_i_am_authenticated_as_a_school_direct_provider_user
+ @user = create(:user, providers: [build(:provider, sites: [build(:site), build(:site)], study_sites: [build(:site, :study_site), build(:site, :study_site)])])
+ @provider = @user.providers.first
+ create(:accredited_provider, provider_code: '1BJ')
+ @accredited_provider = create(:accredited_provider, provider_code: '1BK')
+ @provider.accredited_partnerships.create(accredited_provider: @accredited_provider, description: 'description')
+
+ given_i_am_authenticated(user: @user)
+ end
+
+ def given_i_am_authenticated_as_a_scitt_provider_user
+ @user = create(
+ :user,
+ providers: [
+ create(:accredited_provider, :scitt, sites: [build(:site), build(:site)], study_sites: [build(:site, :study_site), build(:site, :study_site)])
+ ]
+ )
+ given_i_am_authenticated(
+ user: @user
+ )
+ end
+
+ def when_i_visit_the_courses_page
+ publish_provider_courses_index_page.load(
+ provider_code: provider.provider_code,
+ recruitment_cycle_year: provider.recruitment_cycle_year
+ )
+ end
+
+ def and_i_click_on_add_course
+ click_on 'Add course'
+ and_i_click_continue
+ end
+
+ def and_i_choose_a_secondary_course
+ choose 'Secondary'
+ and_i_select_no_send
+ and_i_click_continue
+ end
+
+ def and_i_choose_a_further_education_course
+ choose 'Further education'
+ and_i_select_no_send
+ and_i_click_continue
+ end
+
+ def and_i_choose_a_primary_course
+ choose 'Primary'
+ and_i_select_no_send
+ and_i_click_continue
+ choose 'Primary with English'
+ and_i_click_continue
+ end
+
+ def and_i_select_a_subject
+ select 'Dance', from: 'First subject'
+ and_i_click_continue
+ end
+
+ def and_i_choose_an_age_range
+ choose '14 to 19'
+ and_i_click_continue
+ end
+
+ def and_i_choose_a_primary_age_range
+ choose '3 to 7'
+ and_i_click_continue
+ end
+
+ def and_i_click_continue
+ click_on 'Continue'
+ end
+
+ def then_i_see_the_degree_awarding_option
+ expect(
+ publish_courses_new_outcome_page.qualification_fields.has_undergraduate_degree_with_qts?
+ ).to be true
+ expect(publish_courses_new_outcome_page.qualification_fields.text).to include(
+ 'Teacher degree apprenticeship (TDA) with QTS'
+ )
+ end
+
+ def then_i_am_on_the_qualifications_page
+ expect(page).to have_current_path(new_publish_provider_recruitment_cycle_courses_outcome_path(provider_code: provider.provider_code, recruitment_cycle_year:), ignore_query: true)
+ end
+
+ def and_i_do_not_see_the_degree_awarding_option
+ expect(
+ publish_courses_new_outcome_page.qualification_fields.has_undergraduate_degree_with_qts?
+ ).to be false
+ end
+
+ def when_i_choose_a_degree_awarding_qualification
+ choose 'Teacher degree apprenticeship (TDA) with QTS'
+ and_i_click_continue
+ end
+
+ def then_i_am_on_the_choose_schools_page
+ expect(page).to have_current_path(new_publish_provider_recruitment_cycle_courses_schools_path(provider_code: provider.provider_code, recruitment_cycle_year:), ignore_query: true)
+ end
+
+ def and_the_back_link_points_to_outcome_page
+ expect(publish_courses_new_outcome_page.back_link[:href]).to include(new_publish_provider_recruitment_cycle_courses_outcome_path(provider_code: provider.provider_code, recruitment_cycle_year:))
+ end
+
+ def when_i_choose_the_school
+ check provider.sites.first.location_name
+ and_i_click_continue
+ end
+
+ def then_the_back_link_points_to_the_school_page
+ expect(publish_courses_new_study_sites_page.back_link[:href]).to include(back_publish_provider_recruitment_cycle_courses_schools_path(provider_code: provider.provider_code, recruitment_cycle_year:))
+ end
+
+ def and_i_choose_the_study_site
+ check provider.study_sites.first.location_name
+ and_i_click_continue
+ end
+
+ def and_the_back_link_points_to_the_study_site_page
+ expect(publish_courses_new_applications_open_page.back_link[:href]).to include(back_publish_provider_recruitment_cycle_courses_study_sites_path(provider_code: provider.provider_code, recruitment_cycle_year:))
+ end
+
+ def then_i_am_on_the_add_applications_open_date_page
+ expect(page).to have_current_path(new_publish_provider_recruitment_cycle_courses_applications_open_path(provider_code: provider.provider_code, recruitment_cycle_year:), ignore_query: true)
+ end
+
+ def and_the_back_link_points_to_applications_open_date_page
+ expect(publish_courses_new_start_date_page.back_link[:href]).to include(new_publish_provider_recruitment_cycle_courses_applications_open_path(provider_code: provider.provider_code, recruitment_cycle_year:))
+ end
+
+ def when_i_choose_the_applications_open_date
+ first('input.govuk-radios__input').set(true)
+ and_i_click_continue
+ end
+
+ def and_i_choose_the_first_start_date
+ first('input.govuk-radios__input').set(true)
+ and_i_click_continue
+ end
+
+ def and_the_back_link_points_to_start_date_page
+ expect(publish_course_confirmation_page.back_link[:href]).to include(new_publish_provider_recruitment_cycle_courses_start_date_path(provider_code: provider.provider_code, recruitment_cycle_year:))
+ end
+
+ def then_i_am_on_the_check_your_answers_page
+ expect(page).to have_current_path(confirmation_publish_provider_recruitment_cycle_courses_path(provider_code: provider.provider_code, recruitment_cycle_year:), ignore_query: true)
+ end
+
+ def and_i_can_not_change_funding_type
+ expect(
+ publish_course_confirmation_page.details.funding_type.value.text
+ ).to eq('Teaching apprenticeship - with salary')
+
+ expect(
+ publish_course_confirmation_page.details.funding_type.text
+ ).not_to include('Change')
+ end
+
+ def and_i_can_not_change_study_mode
+ expect(
+ publish_course_confirmation_page.details.study_mode.value.text
+ ).to eq('Full time')
+
+ expect(
+ publish_course_confirmation_page.details.study_mode.text
+ ).not_to include('Change')
+ end
+
+ def and_i_can_not_change_visa_requirements
+ expect(
+ publish_course_confirmation_page.details.skilled_visa_requirements.value.text
+ ).to eq('No - cannot sponsor')
+
+ expect(
+ publish_course_confirmation_page.details.skilled_visa_requirements.text
+ ).not_to include('Change')
+ end
+
+ def when_i_click_on_add_a_course
+ click_on 'Add course'
+ end
+
+ def then_the_tda_course_is_created
+ expect(course.undergraduate_degree_with_qts?).to be(true)
+ end
+
+ def and_the_tda_defaults_are_saved
+ expect(course.program_type).to eq('teacher_degree_apprenticeship')
+ expect(course.funding).to eq('apprenticeship')
+ expect(course.can_sponsor_student_visa?).to be false
+ expect(course.can_sponsor_skilled_worker_visa?).to be false
+ expect(course.additional_degree_subject_requirements).to be false
+ expect(course.degree_subject_requirements).to be_nil
+ expect(course.degree_grade).to eq('not_required')
+ expect(course.enrichments.last).to be_present
+ expect(course.enrichments.last.course_length).to eq('4 years')
+ end
+
+ def and_i_select_no_send
+ publish_courses_new_level_page.send_fields.is_send_false.click
+ end
+
+ def then_i_do_not_see_the_change_links_for_study_mode_funding_type_and_visa_sponsorship
+ within('[data-qa="course__study_mode"]') do
+ expect(page).to have_no_link('Change')
+ end
+
+ within('[data-qa="course__funding_type"]') do
+ expect(page).to have_no_link('Change')
+ end
+
+ within('[data-qa="course__skilled_worker_visa_sponsorship"]') do
+ expect(page).to have_no_link('Change')
+ end
+ end
+
+ def then_i_do_not_see_the_change_links_for_study_mode_funding_type_and_visa_sponsorship_on_basic_details
+ within('[data-qa="course__study_mode"]') do
+ expect(page).to have_no_link('Change')
+ end
+
+ within('[data-qa="course__funding"]') do
+ expect(page).to have_no_link('Change')
+ end
+
+ within('[data-qa="course__can_sponsor_skilled_worker_visa"]') do
+ expect(page).to have_no_link('Change')
+ end
+ end
+
+ def and_i_do_not_see_the_change_link_for_course_length
+ within('[data-qa="enrichment__course_length"]') do
+ expect(page).to have_no_link('Change')
+ end
+ end
+
+ def when_i_click_on_the_course_i_created
+ click_on course_name_and_code
+ when_i_click_on_the_course_basic_details_tab
+ end
+
+ def when_i_click_on_the_course_basic_details_tab
+ publish_provider_courses_show_page.basic_details_link.click
+ end
+
+ def when_i_click_on_the_course_description_tab
+ publish_provider_courses_show_page.description_link.click
+ end
+
+ def then_i_do_not_see_the_degree_requirements_row
+ expect(publish_provider_courses_show_page).not_to have_degree
+ end
+
+ def given_i_fill_in_all_other_fields_for_the_course
+ and_i_add_course_details
+ and_i_add_salary_information
+ and_i_add_gcse_requirements
+ end
+
+ def and_i_add_course_details
+ publish_provider_courses_show_page.about_course.find_link(
+ text: 'Change details about this course'
+ ).click
+
+ fill_in 'About this course', with: 'Details about this course'
+ click_on 'Update about this course'
+
+ publish_provider_courses_show_page.how_school_placements_work.find_link(
+ text: 'Change details about how placements work'
+ ).click
+
+ fill_in 'How placements work', with: 'School placements information'
+ click_on 'Update how placements work'
+ end
+
+ def and_i_add_salary_information
+ publish_provider_courses_show_page.salary_details.find_link(text: 'Change salary').click
+ publish_course_salary_edit_page.salary_details.set('Some salary details')
+ publish_course_salary_edit_page.submit.click
+ end
+
+ def and_i_add_gcse_requirements
+ publish_provider_courses_show_page.gcse.find_link(
+ text: 'Enter GCSE and equivalency test requirements'
+ ).click
+ publish_courses_gcse_requirements_page.pending_gcse_yes_radio.click
+ publish_courses_gcse_requirements_page.gcse_equivalency_yes_radio.click
+ publish_courses_gcse_requirements_page.english_equivalency.check
+ publish_courses_gcse_requirements_page.maths_equivalency.check
+ publish_courses_gcse_requirements_page.additional_requirements.set('Some Proficiency')
+ publish_courses_gcse_requirements_page.save.click
+ end
+
+ def when_i_publish_the_course
+ publish_provider_courses_show_page.course_button_panel.publish_button.click
+ end
+
+ def then_the_course_is_published
+ expect(publish_provider_courses_show_page.errors.map(&:text)).to eq([])
+ expect(page).to have_content('Your course has been published.')
+ expect(course.content_status).to be :published
+ end
+
+ def provider
+ @user.providers.first.reload
+ end
+
+ def course
+ provider.courses.last
+ end
+
+ def course_name_and_code
+ course.decorate.name_and_code
+ end
+
+ def given_i_am_on_the_check_answers_page_of_a_new_tda_course
+ given_i_am_authenticated_as_a_school_direct_provider_user
+ and_i_visit_the_courses_page
+ and_i_click_on_add_course
+ and_i_choose_a_secondary_course
+ and_i_select_a_subject
+ and_i_choose_an_age_range
+ and_i_choose_a_degree_awarding_qualification
+ and_i_choose_the_school
+ and_i_choose_the_study_site
+ and_i_choose_the_applications_open_date
+ and_i_choose_the_first_start_date
+ then_i_am_on_the_check_your_answers_page
+ end
+
+ def when_i_visit_the_course_outcome_page
+ publish_course_confirmation_page.details.outcome.change_link.click
+ end
+
+ def and_i_choose_qts
+ publish_courses_outcome_edit_page.qts.choose
+ and_i_click_continue
+ end
+
+ def and_i_choose_fee
+ choose 'Fee - no salary'
+ and_i_click_continue
+ end
+
+ def and_i_choose_salaried
+ choose 'Salary'
+ and_i_click_continue
+ end
+
+ def and_i_choose_part_time
+ uncheck 'Full time'
+ check 'Part time'
+ and_i_click_continue
+ end
+
+ def and_i_choose_to_sponsor_a_student_visa
+ choose 'Yes'
+ and_i_click_continue
+ end
+
+ def and_i_choose_to_sponsor_a_skilled_worker_visa
+ choose('course_can_sponsor_skilled_worker_visa_true')
+ and_i_click_continue
+ end
+
+ def then_i_see_the_correct_attributes_in_the_database_for_fee_paying
+ course.reload
+ expect(course.part_time?).to be(true)
+ expect(course.funding == 'fee').to be(true)
+ expect(course.can_sponsor_skilled_worker_visa).to be(false)
+ expect(course.can_sponsor_student_visa).to be(true)
+ end
+
+ def then_i_see_the_correct_attributes_in_the_database_for_salaried
+ course.reload
+ expect(course.study_mode == 'part_time').to be(true)
+ expect(course.funding == 'salary').to be(true)
+ expect(course.can_sponsor_skilled_worker_visa).to be(true)
+ expect(course.can_sponsor_student_visa).to be(false)
+ end
+
+ def and_the_back_link_points_to_the_confirm_page
+ expect(URI.parse(find_link('Back')[:href]).path).to eq(confirmation_publish_provider_recruitment_cycle_courses_path(
+ provider_code: provider.provider_code,
+ recruitment_cycle_year:
+ ))
+ end
+
+ def and_the_back_link_points_to_the_qualification_page
+ expect(URI.parse(find_link('Back')[:href]).path).to eq(new_publish_provider_recruitment_cycle_courses_outcome_path(
+ provider_code: provider.provider_code,
+ recruitment_cycle_year:
+ ))
+ end
+
+ def and_the_back_link_points_to_the_funding_type_page
+ expect(URI.parse(find_link('Back')[:href]).path).to eq(new_publish_provider_recruitment_cycle_courses_funding_type_path(
+ provider_code: provider.provider_code,
+ recruitment_cycle_year:
+ ))
+ end
+
+ def and_the_back_link_points_to_the_study_mode_page
+ expect(URI.parse(find_link('Back')[:href]).path).to eq(new_publish_provider_recruitment_cycle_courses_study_mode_path(
+ provider_code: provider.provider_code,
+ recruitment_cycle_year:
+ ))
+ end
+
+ def when_i_click_back
+ click_on 'Back'
+ end
+
+ def then_i_am_on_the_study_mode_page
+ expect(page).to have_current_path(new_publish_provider_recruitment_cycle_courses_study_mode_path(provider_code: provider.provider_code, recruitment_cycle_year:), ignore_query: true)
+ end
+
+ def then_i_am_on_the_funding_type_page
+ expect(page).to have_current_path(new_publish_provider_recruitment_cycle_courses_funding_type_path(provider_code: provider.provider_code, recruitment_cycle_year:), ignore_query: true)
+ end
+
+ def and_i_add_a_level_requirements
+ click_on 'Enter A levels and equivalency test requirements'
+ choose 'Any subject'
+ and_i_click_continue
+ choose 'No'
+ and_i_click_continue
+ choose 'Yes'
+ and_i_click_continue
+ choose 'Yes'
+ click_on 'Update A levels'
+ end
+
+ def recruitment_cycle_year
+ RecruitmentCycle.current.year
+ end
+
+ alias_method :and_i_do_not_see_the_change_links_for_study_mode_funding_type_and_visa_sponsorship, :then_i_do_not_see_the_change_links_for_study_mode_funding_type_and_visa_sponsorship
+ alias_method :and_i_visit_the_courses_page, :when_i_visit_the_courses_page
+ alias_method :and_i_choose_a_degree_awarding_qualification, :when_i_choose_a_degree_awarding_qualification
+ alias_method :and_i_choose_the_school, :when_i_choose_the_school
+ alias_method :and_i_choose_the_applications_open_date, :when_i_choose_the_applications_open_date
+ alias_method :and_i_am_on_the_check_your_answers_page, :then_i_am_on_the_check_your_answers_page
+ alias_method :when_i_click_continue, :and_i_click_continue
+end
diff --git a/spec/features/publish/viewing_training_providers_and_their_courses_spec.rb b/spec/features/publish/viewing_training_providers_and_their_courses_spec.rb
index 5d55aca33b..39097233dd 100644
--- a/spec/features/publish/viewing_training_providers_and_their_courses_spec.rb
+++ b/spec/features/publish/viewing_training_providers_and_their_courses_spec.rb
@@ -4,6 +4,7 @@
feature 'Viewing courses as an accredited provider', { can_edit_current_and_next_cycles: false } do
before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(false)
given_i_am_authenticated_as_an_accredited_provider_user
and_some_courses_exist_with_one_i_accredit
when_i_visit_the_publish_training_provider_index_page
diff --git a/spec/features/support/providers/accredited_partners_spec.rb b/spec/features/support/providers/accredited_partners_spec.rb
new file mode 100644
index 0000000000..65210ca46b
--- /dev/null
+++ b/spec/features/support/providers/accredited_partners_spec.rb
@@ -0,0 +1,171 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+feature 'Accredited provider flow', { can_edit_current_and_next_cycles: false } do
+ before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(true)
+ given_i_am_authenticated_as_an_admin_user
+ and_there_are_accredited_providers_in_the_database
+ and_i_visit_the_index_page
+ end
+
+ scenario 'i can view the accredited providers tab when there are none' do
+ then_i_see_the_correct_text_for_no_accredited_providers
+ end
+
+ scenario 'i can view accredited providers on the index page' do
+ and_my_provider_has_accrediting_providers
+ and_i_click_on_the_accredited_provider_tab
+ then_i_should_see_the_accredited_provider_name_displayed
+ end
+
+ scenario 'i can edit accredited providers on the index page' do
+ and_my_provider_has_accrediting_providers
+ and_i_click_on_the_accredited_provider_tab
+ and_i_click_change
+
+ when_i_click_the_back_link
+ then_i_return_to_the_index_page
+ and_i_click_change
+
+ when_i_input_updated_description
+ then_i_should_see_the_updated_description
+ and_i_see_the_success_message
+ end
+
+ scenario 'i cannot delete accredited providers attached to a course' do
+ and_my_provider_has_accrediting_providers
+ and_i_click_on_the_accredited_provider_tab
+ and_i_click_remove
+ then_i_should_see_the_cannot_remove_text
+ end
+
+ scenario 'i can delete accredited providers not attached to a course' do
+ and_i_click_on_the_accredited_provider_tab
+ and_i_click_add_accredited_provider
+ and_i_search_for_an_accredited_provider_with_a_valid_query
+ and_i_select_the_provider
+ when_i_input_new_information
+ and_i_confirm_the_changes
+ and_i_click_remove
+ and_i_click_remove_ap
+ then_i_return_to_the_index_page
+ and_i_see_the_remove_success_message
+ end
+
+ private
+
+ def and_i_see_the_remove_success_message
+ expect(page).to have_content('Accredited partnership removed')
+ end
+
+ def and_i_see_the_remove_success_message; end
+
+ def and_i_click_remove_ap
+ click_link_or_button 'Remove accredited partner'
+ end
+
+ def and_i_confirm_the_changes
+ click_link_or_button 'Add accredited partner'
+ end
+
+ def when_i_input_new_information
+ fill_in 'About the accredited partner', with: 'New AP description'
+ click_link_or_button 'Continue'
+ end
+
+ def and_i_select_the_provider
+ choose @accredited_provider.provider_name
+ click_link_or_button 'Continue'
+ end
+
+ def form_title
+ 'Enter a provider name, UKPRN or postcode'
+ end
+
+ def and_i_search_for_an_accredited_provider_with_a_valid_query
+ fill_in form_title, with: @accredited_provider.provider_name
+ click_link_or_button 'Continue'
+ end
+
+ def and_i_click_add_accredited_provider
+ click_link_or_button 'Add accredited partner'
+ end
+
+ def and_i_click_remove
+ click_link_or_button 'Remove'
+ end
+
+ def then_i_should_see_the_cannot_remove_text
+ expect(page).to have_css('h1', text: 'You cannot remove this accredited provider')
+ end
+
+ def given_i_am_authenticated_as_an_admin_user
+ given_i_am_authenticated(user: create(:user, :admin))
+ end
+
+ def and_there_are_accredited_providers_in_the_database
+ @provider = create(:provider, :lead_school)
+ @accredited_provider = create(:provider, :accredited_provider, provider_name: 'UCL', users: [create(:user)])
+ @accredited_provider_two = create(:provider, :accredited_provider, provider_name: 'Accredited provider two')
+ @accredited_provider_three = create(:provider, :accredited_provider, provider_name: 'Accredited provider three')
+ end
+
+ def then_i_return_to_the_index_page
+ expect(page).to have_current_path(support_recruitment_cycle_provider_accredited_partners_path(
+ recruitment_cycle_year: Settings.current_recruitment_cycle_year,
+ provider_id: @provider.id
+ ))
+ end
+
+ def and_i_visit_the_index_page
+ visit support_recruitment_cycle_provider_accredited_partners_path(
+ recruitment_cycle_year: Settings.current_recruitment_cycle_year,
+ provider_id: @provider.id
+ )
+ end
+
+ def and_i_click_change
+ click_link_or_button('Change')
+ end
+
+ def when_i_click_the_back_link
+ click_link_or_button 'Back'
+ end
+
+ def and_i_see_the_success_message
+ expect(page).to have_content('About the accredited provider updated')
+ end
+
+ def then_i_should_see_the_updated_description
+ expect(page).to have_text('update the AP description')
+ end
+
+ def when_i_input_updated_description
+ fill_in 'About the accredited partner', with: 'update the AP description'
+ click_link_or_button 'Update description'
+ end
+
+ def then_i_see_the_correct_text_for_no_accredited_providers
+ expect(page).to have_text("There are no accredited partnerships for #{@provider.provider_name}")
+ end
+
+ def and_i_click_on_the_accredited_provider_tab
+ click_link_or_button 'Accredited partnerships'
+ end
+
+ def and_my_provider_has_accrediting_providers
+ course = build(:course, accrediting_provider: build(:provider, :accredited_provider, provider_name: 'Accrediting provider name'))
+
+ @provider.accredited_partnerships.create(accredited_provider: course.accrediting_provider, description: 'Description')
+ @provider.courses << course
+ end
+
+ def then_i_should_see_the_accredited_provider_name_displayed
+ expect(page).to have_css(
+ 'h2.govuk-summary-card__title a.govuk-link',
+ text: 'Accrediting provider name'
+ )
+ end
+end
diff --git a/spec/features/support/providers/accredited_provider_search/searching_for_an_accredited_provider_spec.rb b/spec/features/support/providers/accredited_provider_search/searching_for_an_accredited_provider_enrichments_spec.rb
similarity index 97%
rename from spec/features/support/providers/accredited_provider_search/searching_for_an_accredited_provider_spec.rb
rename to spec/features/support/providers/accredited_provider_search/searching_for_an_accredited_provider_enrichments_spec.rb
index 879f8198fc..0d825e29ff 100644
--- a/spec/features/support/providers/accredited_provider_search/searching_for_an_accredited_provider_spec.rb
+++ b/spec/features/support/providers/accredited_provider_search/searching_for_an_accredited_provider_enrichments_spec.rb
@@ -2,8 +2,9 @@
require 'rails_helper'
-feature 'Searching for an accredited provider' do
+feature 'Searching for an accredited provider enrichments' do
before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(false)
given_i_am_authenticated_as_an_admin_user
and_there_are_accredited_providers_in_the_database
end
diff --git a/spec/features/support/providers/accredited_provider_search/searching_for_an_accredited_provider_partnerships_spec.rb b/spec/features/support/providers/accredited_provider_search/searching_for_an_accredited_provider_partnerships_spec.rb
new file mode 100644
index 0000000000..87e0a0863c
--- /dev/null
+++ b/spec/features/support/providers/accredited_provider_search/searching_for_an_accredited_provider_partnerships_spec.rb
@@ -0,0 +1,191 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+feature 'Searching for an accredited provider' do
+ before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(true)
+ given_i_am_authenticated_as_an_admin_user
+ and_there_are_accredited_providers_in_the_database
+ end
+
+ scenario 'i can search for an accredited provider by query' do
+ when_i_visit_the_accredited_provider_search_page
+ and_i_search_with_an_invalid_query
+ then_i_should_see_an_error_message
+
+ when_i_search_for_an_accredited_provider_with_a_valid_query
+ then_i_see_the_provider_i_searched_for
+
+ when_i_continue_without_selecting_an_accredited_provider
+ then_i_should_see_an_error_message('Select an accredited provider')
+ and_i_should_still_see_the_provider_i_searched_for
+
+ when_i_select_the_provider
+ and_i_continue_without_entering_a_description
+ then_i_should_see_an_error_message('Enter details about the accredited partnership')
+
+ when_i_enter_a_description
+ and_i_confirm_the_changes
+ then_i_should_be_taken_to_the_index_page
+ and_i_should_see_a_success_message
+ and_i_should_see_the_accredited_providers
+ end
+
+ scenario 'back links behaviour' do
+ when_i_am_on_the_confirm_page
+ and_i_click_the_change_link_for('accredited partner name')
+ then_i_should_be_taken_to_the_accredited_provider_search_page
+ when_i_click_the_back_link
+ then_i_should_be_taken_back_to_the_confirm_page
+
+ when_i_am_on_the_confirm_page
+ and_i_click_the_change_link_for('accredited partner description')
+ then_i_should_be_taken_to_the_accredited_provider_description_page
+ when_i_click_the_back_link
+ then_i_should_be_taken_back_to_the_confirm_page
+ end
+
+ private
+
+ def given_i_am_authenticated_as_an_admin_user
+ given_i_am_authenticated(user: create(:user, :admin))
+ end
+
+ def and_there_are_accredited_providers_in_the_database
+ @accredited_provider = create(:provider, :accredited_provider, provider_name: 'UCL', users: [create(:user)])
+ @accredited_provider_two = create(:provider, :accredited_provider, provider_name: 'Accredited provider two')
+ @accredited_provider_three = create(:provider, :accredited_provider, provider_name: 'Accredited provider three')
+ end
+
+ def when_i_visit_the_accredited_provider_search_page
+ visit search_support_recruitment_cycle_provider_accredited_providers_path(
+ recruitment_cycle_year: Settings.current_recruitment_cycle_year,
+ provider_id: provider.id
+ )
+ end
+
+ def when_i_search_for_an_accredited_provider_with_a_valid_query
+ fill_in form_title, with: @accredited_provider.provider_name
+ click_continue
+ end
+
+ def then_i_see_the_provider_i_searched_for
+ expect(page).to have_content(@accredited_provider.provider_name)
+ expect(page).to have_no_content(@accredited_provider_two.provider_name)
+ expect(page).to have_no_content(@accredited_provider_three.provider_name)
+ end
+
+ def when_i_select_the_provider
+ choose @accredited_provider.provider_name
+ click_continue
+ end
+
+ def then_i_should_be_taken_to_the_index_page
+ expect(page).to have_current_path(
+ support_recruitment_cycle_provider_accredited_partners_path(
+ recruitment_cycle_year: Settings.current_recruitment_cycle_year,
+ provider_id: provider.id
+ )
+ )
+ end
+
+ def and_i_search_with_an_invalid_query
+ fill_in form_title, with: ''
+ click_continue
+ end
+
+ def then_i_should_see_an_error_message(error_message = form_title)
+ expect(page).to have_content(error_message)
+ end
+
+ def when_i_continue_without_selecting_an_accredited_provider
+ click_continue
+ end
+
+ def and_i_should_still_see_the_provider_i_searched_for
+ expect(page).to have_content(@accredited_provider.provider_name)
+ expect(page).to have_no_content(@accredited_provider_two.provider_name)
+ expect(page).to have_no_content(@accredited_provider_three.provider_name)
+ end
+
+ def when_i_enter_a_description
+ fill_in 'About the accredited partner', with: 'This is a description'
+ click_continue
+ end
+
+ def and_i_confirm_the_changes
+ expect do
+ click_link_or_button 'Add accredited partner'
+ end.to have_enqueued_email(Users::OrganisationMailer, :added_as_an_organisation_to_training_partner)
+ end
+
+ def and_i_should_see_a_success_message
+ expect(page).to have_content('Accredited partner added')
+ end
+
+ def and_i_should_see_the_accredited_providers
+ expect(page).to have_css('.govuk-summary-card', count: 1)
+ expect(page).to have_content(@accredited_provider.provider_name)
+ end
+
+ def click_continue
+ click_link_or_button 'Continue'
+ end
+
+ def when_i_am_on_the_confirm_page
+ when_i_visit_the_accredited_provider_search_page
+ when_i_search_for_an_accredited_provider_with_a_valid_query
+ when_i_select_the_provider
+ when_i_enter_a_description
+ end
+
+ def and_i_click_the_change_link_for(field)
+ within '.govuk-summary-list' do
+ click_link_or_button "Change #{field}"
+ end
+ end
+
+ def then_i_should_be_taken_to_the_accredited_provider_search_page
+ expect(page).to have_current_path(
+ search_support_recruitment_cycle_provider_accredited_providers_path(
+ recruitment_cycle_year: Settings.current_recruitment_cycle_year,
+ provider_id: provider.id,
+ goto_confirmation: true
+ )
+ )
+ end
+
+ def then_i_should_be_taken_to_the_accredited_provider_description_page
+ expect(page).to have_current_path(
+ new_support_recruitment_cycle_provider_accredited_partner_path(
+ recruitment_cycle_year: Settings.current_recruitment_cycle_year,
+ provider_id: provider.id,
+ goto_confirmation: true
+ )
+ )
+ end
+
+ def when_i_click_the_back_link
+ click_link_or_button 'Back'
+ end
+
+ def then_i_should_be_taken_back_to_the_confirm_page
+ expect(page).to have_current_path(
+ check_support_recruitment_cycle_provider_accredited_partners_path(
+ recruitment_cycle_year: Settings.current_recruitment_cycle_year,
+ provider_id: provider.id
+ )
+ )
+ end
+
+ def provider
+ @provider ||= create(:provider)
+ end
+
+ def form_title
+ 'Enter a provider name, UKPRN or postcode'
+ end
+
+ alias_method :and_i_continue_without_entering_a_description, :click_continue
+end
diff --git a/spec/features/support/providers/accredited_providers_spec.rb b/spec/features/support/providers/accredited_providers_spec.rb
index f83f5a008a..e70be9a306 100644
--- a/spec/features/support/providers/accredited_providers_spec.rb
+++ b/spec/features/support/providers/accredited_providers_spec.rb
@@ -4,6 +4,7 @@
feature 'Accredited provider flow', { can_edit_current_and_next_cycles: false } do
before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(false)
given_i_am_authenticated_as_an_admin_user
and_there_are_accredited_providers_in_the_database
and_i_visit_the_index_page
diff --git a/spec/features/view_components_enrichments_spec.rb b/spec/features/view_components_enrichments_spec.rb
new file mode 100644
index 0000000000..9c32a67db9
--- /dev/null
+++ b/spec/features/view_components_enrichments_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.feature 'view components' do
+ before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(false)
+ end
+
+ all_links = (ViewComponent::Preview.all.map do |component|
+ component.examples.map do |example|
+ "#{Rails.application.config.view_component.preview_route}/#{component.preview_name}/#{example}"
+ end
+ end).flatten
+
+ shared_examples 'navigate to' do |link|
+ scenario "navigate to #{link}" do
+ visit link
+
+ expect(page.status_code).to eq(200)
+ expect(page).to have_css('#main-content')
+ end
+ end
+
+ all_links.each do |link|
+ include_examples 'navigate to', link
+ end
+end
diff --git a/spec/features/view_components_spec.rb b/spec/features/view_components_spec.rb
index 92b7c01e5a..4f5420c92f 100644
--- a/spec/features/view_components_spec.rb
+++ b/spec/features/view_components_spec.rb
@@ -3,6 +3,10 @@
require 'rails_helper'
RSpec.feature 'view components' do
+ before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(true)
+ end
+
all_links = (ViewComponent::Preview.all.map do |component|
component.examples.map do |example|
"#{Rails.application.config.view_component.preview_route}/#{component.preview_name}/#{example}"
diff --git a/spec/forms/provider_partnership_form_spec.rb b/spec/forms/provider_partnership_form_spec.rb
new file mode 100644
index 0000000000..c4f2f4c75f
--- /dev/null
+++ b/spec/forms/provider_partnership_form_spec.rb
@@ -0,0 +1,120 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe ProviderPartnershipForm, type: :model do
+ subject { described_class.new(user, model) }
+
+ let(:user) { create(:user) }
+ let(:provider) { create(:provider) }
+ let(:model) { create(:provider_partnership, training_provider: provider) }
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:description) }
+
+ context 'word count' do
+ before do
+ subject.description = Faker::Lorem.sentence(word_count: 251)
+ subject.valid?
+ end
+
+ it 'validates the word count for the description' do
+ expect(subject).not_to be_valid
+ expect(subject.errors[:description])
+ .to include(I18n.t('activemodel.errors.models.provider_partnership_form.attributes.description.too_long'))
+ end
+ end
+ end
+
+ describe '#stash' do
+ subject { described_class.new(user, model, params:).stash }
+
+ let(:accredited_provider) { create(:provider, :accredited_provider) }
+ let(:params) do
+ {
+ accredited_provider_id: accredited_provider.id,
+ description: 'Foo'
+ }
+ end
+
+ it { is_expected.to be_truthy }
+ end
+
+ describe '#accredited_provider' do
+ subject { described_class.new(user, model, params:).accredited_provider }
+
+ let(:recruitment_cycle) { find_or_create(:recruitment_cycle) }
+ let(:next_recruitment_cycle) { create(:recruitment_cycle, :next) }
+ let(:model) { create(:provider_partnership) }
+ let(:accredited_provider) { create(:provider, :accredited_provider) }
+ let(:params) do
+ {
+ accredited_provider_id: accredited_provider.id,
+ description: 'Foo'
+ }
+ end
+
+ it 'returns the accredited provider' do
+ expect(subject).to eq(accredited_provider)
+ end
+
+ context 'when accredited provider is in the next recruitment cycle' do
+ let(:accredited_provider_in_next_cycle) { create(:provider, :accredited_provider, recruitment_cycle: next_recruitment_cycle) }
+ let(:params) do
+ {
+ accredited_provider_id: accredited_provider_in_next_cycle.id,
+ description: 'Foo'
+ }
+ end
+
+ before do
+ allow(RecruitmentCycle).to receive(:current).and_return(next_recruitment_cycle)
+ end
+
+ it 'returns the accredited provider from the next cycle' do
+ expect(subject).to eq(accredited_provider_in_next_cycle)
+ end
+ end
+ end
+
+ describe '#save!' do
+ subject { described_class.new(user, model, params:) }
+
+ let(:accredited_provider) { create(:provider, :accredited_provider, users: [create(:user)]) }
+ let(:params) do
+ {
+ accredited_provider_id: accredited_provider.id,
+ description: 'Foo'
+ }
+ end
+
+ context 'when no partnership exists' do
+ it 'correctly sets the enrichment structure' do
+ expect { subject.save! }
+ .to change(model, :description).to(params[:description])
+ end
+ end
+
+ context 'when provider has existing accredited provider enrichments' do
+ let(:accredited_provider) { create(:accredited_provider) }
+ let(:model) { create(:provider_partnership, training_provider: provider, accredited_provider:, description: 'Existing') }
+
+ it 'updates the provider with the new accredited provider information' do
+ subject.save!
+
+ expect(model.accredited_provider.provider_code).to eq(accredited_provider.provider_code)
+ expect(model.description).to eq('Foo')
+ end
+ end
+
+ it 'sends a notification email to the accredited provider users' do
+ expect(Users::OrganisationMailer).to receive(:added_as_an_organisation_to_training_partner).with(
+ recipient: accredited_provider.users.first,
+ provider: model,
+ accredited_provider:
+ ).and_call_original
+
+ subject.save!
+ end
+ end
+end
diff --git a/spec/helpers/navigation_bar_helper_spec.rb b/spec/helpers/navigation_bar_helper_spec.rb
index aa3f8dcbe7..0f50220360 100644
--- a/spec/helpers/navigation_bar_helper_spec.rb
+++ b/spec/helpers/navigation_bar_helper_spec.rb
@@ -8,25 +8,55 @@
helper.navigation_items(provider)
end
- let(:accredited_provider_item) { subject.find { |item| item[:name] == 'Accredited providers' } }
+ context 'when Settings.features.provider_partnerships is false' do
+ before { allow(Settings.features).to receive(:provider_partnerships).and_return(false) }
- context 'when provider is an accredited provider' do
- let(:provider) { create(:provider, :accredited_provider) }
+ let(:accredited_provider_item) { subject.find { |item| item[:name] == 'Accredited providers' } }
- it 'does not include accredited_provider in items' do
- expect(accredited_provider_item).to be_nil
+ context 'when provider is an accredited provider' do
+ let(:provider) { create(:provider, :accredited_provider) }
+
+ it 'does not include accredited_provider in items' do
+ expect(accredited_provider_item).to be_nil
+ end
+ end
+
+ context 'when provider is not an accredited provider' do
+ let(:provider) { create(:provider) }
+
+ it 'includes accredited_provider in items' do
+ expect(accredited_provider_item).not_to be_nil
+ end
+
+ it 'includes the correct link to accredited providers' do
+ expect(accredited_provider_item[:url]).to eq publish_provider_recruitment_cycle_accredited_providers_path(provider.provider_code, provider.recruitment_cycle.year)
+ end
end
end
- context 'when provider is not an accredited provider' do
- let(:provider) { create(:provider) }
+ context 'when Settings.features.provider_partnerships is true' do
+ before { allow(Settings.features).to receive(:provider_partnerships).and_return(true) }
- it 'includes accredited_provider in items' do
- expect(accredited_provider_item).not_to be_nil
+ let(:accredited_provider_item) { subject.find { |item| item[:name] == 'Accredited partnerships' } }
+
+ context 'when provider is an accredited provider' do
+ let(:provider) { create(:provider, :accredited_provider) }
+
+ it 'does not include accredited_provider in items' do
+ expect(accredited_provider_item).to be_nil
+ end
end
- it 'includes the correct link to accredited providers' do
- expect(accredited_provider_item[:url]).to eq publish_provider_recruitment_cycle_accredited_providers_path(provider.provider_code, provider.recruitment_cycle.year)
+ context 'when provider is not an accredited provider' do
+ let(:provider) { create(:provider) }
+
+ it 'includes accredited_provider in items' do
+ expect(accredited_provider_item).not_to be_nil
+ end
+
+ it 'includes the correct link to accredited providers' do
+ expect(accredited_provider_item[:url]).to eq publish_provider_recruitment_cycle_accredited_partnerships_path(provider.provider_code, provider.recruitment_cycle.year)
+ end
end
end
end
diff --git a/spec/helpers/view_helper_spec.rb b/spec/helpers/view_helper_spec.rb
index ed8d78b64a..5dc2291f85 100644
--- a/spec/helpers/view_helper_spec.rb
+++ b/spec/helpers/view_helper_spec.rb
@@ -68,7 +68,7 @@ def preview?(_) = true
it 'returns the publish accrediting provider url' do
expect(x_accrediting_provider_url).to eq(
- accredited_by_publish_provider_recruitment_cycle_course_path(
+ ratified_by_publish_provider_recruitment_cycle_course_path(
course.provider_code,
course.recruitment_cycle_year,
course.course_code
diff --git a/spec/lib/constraints/partnership_feature_spec.rb b/spec/lib/constraints/partnership_feature_spec.rb
new file mode 100644
index 0000000000..cc27a6dcdf
--- /dev/null
+++ b/spec/lib/constraints/partnership_feature_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+module Constraints
+ RSpec.describe PartnershipFeature do
+ describe 'when the feature is on' do
+ before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(true)
+ end
+
+ context 'when we pass :on' do
+ let(:constraint) { described_class.new(:on) }
+
+ it 'matches' do
+ expect(constraint.matches?(nil)).to be_truthy
+ end
+ end
+
+ context 'when we pass :off' do
+ let(:constraint) { described_class.new(:off) }
+
+ it 'does not match' do
+ expect(constraint.matches?(nil)).to be_falsey
+ end
+ end
+ end
+
+ describe 'when the feature is off' do
+ before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(false)
+ end
+
+ context 'when we pass :on' do
+ let(:constraint) { described_class.new(:on) }
+
+ it 'does not match' do
+ expect(constraint.matches?(nil)).to be_falsey
+ end
+ end
+
+ context 'when we pass :off' do
+ let(:constraint) { described_class.new(:off) }
+
+ it 'matches' do
+ expect(constraint.matches?(nil)).to be_truthy
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/course_spec.rb b/spec/models/course_spec.rb
index cf95fbf3b9..f9ec47a734 100644
--- a/spec/models/course_spec.rb
+++ b/spec/models/course_spec.rb
@@ -2287,6 +2287,33 @@
end
end
+ describe '#ratifying_provider_description' do
+ subject { course.ratifying_provider_description }
+
+ context 'for courses without ratifying provider' do
+ let(:accrediting_provider) { nil }
+ let(:course) { create(:course, accrediting_provider:) }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'for courses with ratifying provider' do
+ let(:provider) { create(:provider) }
+ let(:accrediting_provider) { build(:accredited_provider) }
+ let(:course) { create(:course, provider:, accrediting_provider:) }
+
+ context 'without any provider partnership' do
+ it { is_expected.to be_nil }
+ end
+
+ context 'with accrediting_provider_enrichments' do
+ let(:provider) { create(:provider, accredited_partnerships: [build(:provider_partnership, accredited_provider: accrediting_provider, description: 'one two three')]) }
+
+ it { is_expected.to match 'one two three' }
+ end
+ end
+ end
+
describe '#accrediting_provider_description' do
subject { course.accrediting_provider_description }
diff --git a/spec/models/provider/accredited_providers_enrichments_spec.rb b/spec/models/provider/accredited_providers_enrichments_spec.rb
new file mode 100644
index 0000000000..bc2f2b64cf
--- /dev/null
+++ b/spec/models/provider/accredited_providers_enrichments_spec.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe Provider do
+ subject do
+ provider.accredited_bodies
+ end
+
+ before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(false)
+ provider.reload
+ end
+
+ let(:accrediting_provider_enrichments) { [] }
+ let(:description) { 'Ye olde establishmente' }
+ let(:courses) { [] }
+ let(:provider) do
+ create(:provider,
+ provider_name: 'ACME SCITT',
+ provider_code: 'A01',
+ accrediting_provider_enrichments:,
+ courses:)
+ end
+
+ context 'with no accrediting provider (via courses)' do
+ it { is_expected.to be_empty }
+
+ context 'with an old accredited provider enrichment' do
+ let(:accrediting_provider_enrichments) do
+ [{
+ 'Description' => description,
+ # XX4 might have previously been an accrediting provider for this provider, and the data is still in the database
+ 'UcasProviderCode' => 'XX4'
+ }]
+ end
+
+ it { is_expected.to be_empty }
+ end
+ end
+
+ context 'with an accrediting provider (via courses)' do
+ let(:accrediting_provider) { build(:provider, provider_code: 'AP1') }
+ let(:courses) { [build(:course, course_code: 'P33P', accrediting_provider:)] }
+ let(:accredited_provider) { accrediting_provider }
+
+ let(:accrediting_provider_enrichments) do
+ [{ UcasProviderCode: accredited_provider.provider_code }]
+ end
+
+ its(:length) { is_expected.to be(1) }
+
+ describe 'the returned accredited provider' do
+ subject { provider.accredited_bodies.first }
+
+ its([:description]) { is_expected.to eq('') }
+ its([:provider_code]) { is_expected.to eq(accrediting_provider.provider_code) }
+ its([:provider_name]) { is_expected.to eq(accrediting_provider.provider_name) }
+ end
+
+ context 'with an accredited provider enrichment' do
+ let(:accrediting_provider_enrichments) do
+ [{
+ 'Description' => description,
+ 'UcasProviderCode' => accrediting_provider.provider_code
+ }]
+ end
+
+ its(:length) { is_expected.to be(1) }
+
+ describe 'the returned accredited provider' do
+ subject { provider.accredited_bodies.first }
+
+ its([:description]) { is_expected.to eq(description) }
+ its([:provider_code]) { is_expected.to eq(accrediting_provider.provider_code) }
+ its([:provider_name]) { is_expected.to eq(accrediting_provider.provider_name) }
+ end
+ end
+
+ context 'with a corrupt accredited provider enrichment' do
+ let(:accrediting_provider_enrichments) do
+ [{
+ 'Description' => description
+ # UcasProviderCode missing. We found data like this in our database so need to handle it.
+ }]
+ end
+
+ its(:length) { is_expected.to be(0) }
+ end
+ end
+end
diff --git a/spec/models/provider/accredited_providers_spec.rb b/spec/models/provider/accredited_providers_spec.rb
deleted file mode 100644
index 650a6b51f5..0000000000
--- a/spec/models/provider/accredited_providers_spec.rb
+++ /dev/null
@@ -1,96 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Provider do
- let(:accrediting_provider_enrichments) { [] }
- let(:courses) { [] }
- let(:provider) do
- create(:provider,
- provider_name: 'ACME SCITT',
- provider_code: 'A01',
- accrediting_provider_enrichments:,
- courses:)
- end
-
- before do
- # NOTE: provider needs to be reloaded due to
- # provider.accrediting_providers
- # provider.accredited_bodies
- provider.reload
- end
-
- describe '#accredited_bodies' do
- subject do
- provider.accredited_bodies
- end
-
- let(:description) { 'Ye olde establishmente' }
-
- context 'with no accrediting provider (via courses)' do
- it { is_expected.to be_empty }
-
- context 'with an old accredited provider enrichment' do
- let(:accrediting_provider_enrichments) do
- [{
- 'Description' => description,
- # XX4 might have previously been an accrediting provider for this provider, and the data is still in the database
- 'UcasProviderCode' => 'XX4'
- }]
- end
-
- it { is_expected.to be_empty }
- end
- end
-
- context 'with an accrediting provider (via courses)' do
- let(:accrediting_provider) { build(:provider, provider_code: 'AP1') }
- let(:courses) { [build(:course, course_code: 'P33P', accrediting_provider:)] }
- let(:accredited_provider) { accrediting_provider }
-
- let(:accrediting_provider_enrichments) do
- [{ UcasProviderCode: accredited_provider.provider_code }]
- end
-
- its(:length) { is_expected.to be(1) }
-
- describe 'the returned accredited provider' do
- subject { provider.accredited_bodies.first }
-
- its([:description]) { is_expected.to eq('') }
- its([:provider_code]) { is_expected.to eq(accrediting_provider.provider_code) }
- its([:provider_name]) { is_expected.to eq(accrediting_provider.provider_name) }
- end
-
- context 'with an accredited provider enrichment' do
- let(:accrediting_provider_enrichments) do
- [{
- 'Description' => description,
- 'UcasProviderCode' => accrediting_provider.provider_code
- }]
- end
-
- its(:length) { is_expected.to be(1) }
-
- describe 'the returned accredited provider' do
- subject { provider.accredited_bodies.first }
-
- its([:description]) { is_expected.to eq(description) }
- its([:provider_code]) { is_expected.to eq(accrediting_provider.provider_code) }
- its([:provider_name]) { is_expected.to eq(accrediting_provider.provider_name) }
- end
- end
-
- context 'with a corrupt accredited provider enrichment' do
- let(:accrediting_provider_enrichments) do
- [{
- 'Description' => description
- # UcasProviderCode missing. We found data like this in our database so need to handle it.
- }]
- end
-
- its(:length) { is_expected.to be(0) }
- end
- end
- end
-end
diff --git a/spec/models/provider/validation_enrichments_spec.rb b/spec/models/provider/validation_enrichments_spec.rb
new file mode 100644
index 0000000000..e469e82878
--- /dev/null
+++ b/spec/models/provider/validation_enrichments_spec.rb
@@ -0,0 +1,211 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'validation' do
+ let(:accrediting_provider_enrichments) { [] }
+ let(:courses) { [] }
+ let(:provider) do
+ create(:provider,
+ provider_name: 'ACME SCITT',
+ provider_code: 'A01',
+ accrediting_provider_enrichments:,
+ courses:)
+ end
+
+ describe 'update' do
+ let(:provider) { build(:provider) }
+
+ describe 'email' do
+ it 'validates email is present' do
+ provider.email = ''
+ provider.valid? :update
+
+ expect(provider.errors[:email]).to include('Enter an email address in the correct format, like name@example.com')
+ end
+
+ it 'validates email contains an @ symbol' do
+ provider.email = 'meow'
+ provider.valid? :update
+
+ expect(provider.errors[:email]).to include('Enter an email address in the correct format, like name@example.com')
+ end
+
+ it 'Does not validate the email if it is not present' do
+ provider.website = 'cats4lyf.cat'
+
+ expect(provider.valid?(:update)).to be true
+ end
+ end
+
+ describe 'telephone' do
+ it 'validates telephone is present' do
+ provider.telephone = ''
+ provider.valid? :update
+
+ expect(provider.errors[:telephone]).to include('Enter a telephone number')
+ end
+
+ it 'Correctly validates valid phone numbers' do
+ provider.telephone = '+447 123 123 123'
+ expect(provider.valid?(:update)).to be true
+ end
+
+ it 'Correctly invalidates invalid phone numbers' do
+ provider.telephone = '123cat456'
+ expect(provider.valid?(:update)).to be false
+ expect(provider.errors[:telephone]).to include('Enter a telephone number, like 01632 960 001, 07700 900 982 or +44 0808 157 0192')
+ end
+
+ it 'Correctly invalidates short phone numbers' do
+ provider.telephone = '1234567'
+ expect(provider.valid?(:update)).to be false
+ expect(provider.errors[:telephone]).to include('Telephone number must contain 8 numbers or more')
+ end
+
+ it 'Correctly invalidates long phone numbers' do
+ provider.telephone = '123456791123456789'
+ expect(provider.valid?(:update)).to be false
+ expect(provider.errors[:telephone]).to include('Telephone number must contain 15 numbers or fewer')
+ end
+
+ it 'Does not validate the telephone if it is not present' do
+ provider.website = 'cats4lyf.cat'
+
+ expect(provider.valid?(:update)).to be true
+ end
+ end
+ end
+
+ describe 'on update' do
+ context 'setting field to nil' do
+ subject { provider }
+
+ it { is_expected.to validate_presence_of(:train_with_us).on(:update) }
+ it { is_expected.to validate_presence_of(:train_with_disability).on(:update) }
+ end
+ end
+
+ describe '#train_with_us' do
+ subject { build(:provider, train_with_us:) }
+
+ let(:word_count) { 250 }
+ let(:train_with_us) { Faker::Lorem.sentence(word_count:) }
+
+ context 'word count within limit' do
+ it { is_expected.to be_valid }
+ end
+
+ context 'word count exceed limit' do
+ let(:word_count) { 250 + 1 }
+
+ it { is_expected.not_to be_valid }
+ end
+ end
+
+ describe '#train_with_disability' do
+ subject { build(:provider, train_with_disability:) }
+
+ let(:word_count) { 250 }
+ let(:train_with_disability) { Faker::Lorem.sentence(word_count:) }
+
+ context 'word count within limit' do
+ it { is_expected.to be_valid }
+ end
+
+ context 'word count exceed limit' do
+ let(:word_count) { 250 + 1 }
+
+ it { is_expected.not_to be_valid }
+ end
+ end
+
+ context 'no accrediting_providers' do
+ describe '#accrediting_provider_providers' do
+ subject do
+ provider.accrediting_provider_enrichments = accrediting_provider_enrichments
+ provider
+ end
+
+ let(:word_count) { 100 }
+
+ let(:accrediting_provider_enrichments) do
+ result = []
+ 10.times do |index|
+ result <<
+ {
+ 'Description' => Faker::Lorem.sentence(word_count:),
+ 'UcasProviderCode' => "UPC#{index}"
+ }
+ end
+ result
+ end
+
+ let(:provider) do
+ create(:provider)
+ end
+
+ context 'word count within limit' do
+ it { is_expected.to be_valid }
+ end
+
+ context 'word count exceed limit' do
+ let(:word_count) { 100 + 1 }
+ # NOTE: its valid as it is orphaned data
+ # ie a previous course
+ # with an acrediting provider was removed
+ # but the accrediting provider enrichment was left behind
+
+ it { is_expected.to be_valid }
+ end
+ end
+ end
+
+ context 'with accrediting_providers' do
+ describe '#accrediting_provider_providers' do
+ subject do
+ provider.accrediting_provider_enrichments = accrediting_provider_enrichments
+ provider
+ end
+
+ let(:word_count) { 100 }
+
+ let(:accrediting_providers) do
+ result = []
+ 10.times do
+ result << create(:provider)
+ end
+ result
+ end
+
+ let(:accrediting_provider_enrichments) do
+ accrediting_providers.map do |ap|
+ {
+ 'Description' => Faker::Lorem.sentence(word_count:),
+ 'UcasProviderCode' => ap.provider_code.to_s
+ }
+ end
+ end
+
+ let(:courses) do
+ accrediting_providers.map do |ap|
+ build(:course, accrediting_provider: ap)
+ end
+ end
+
+ let(:provider) do
+ create(:provider, courses:)
+ end
+
+ context 'word count within limit' do
+ it { is_expected.to be_valid }
+ end
+
+ context 'word count exceed limit' do
+ let(:word_count) { 100 + 1 }
+
+ it { is_expected.not_to be_valid }
+ end
+ end
+ end
+end
diff --git a/spec/models/provider/validation_spec.rb b/spec/models/provider/validation_spec.rb
index e469e82878..1adab16f91 100644
--- a/spec/models/provider/validation_spec.rb
+++ b/spec/models/provider/validation_spec.rb
@@ -9,7 +9,6 @@
create(:provider,
provider_name: 'ACME SCITT',
provider_code: 'A01',
- accrediting_provider_enrichments:,
courses:)
end
@@ -119,93 +118,4 @@
it { is_expected.not_to be_valid }
end
end
-
- context 'no accrediting_providers' do
- describe '#accrediting_provider_providers' do
- subject do
- provider.accrediting_provider_enrichments = accrediting_provider_enrichments
- provider
- end
-
- let(:word_count) { 100 }
-
- let(:accrediting_provider_enrichments) do
- result = []
- 10.times do |index|
- result <<
- {
- 'Description' => Faker::Lorem.sentence(word_count:),
- 'UcasProviderCode' => "UPC#{index}"
- }
- end
- result
- end
-
- let(:provider) do
- create(:provider)
- end
-
- context 'word count within limit' do
- it { is_expected.to be_valid }
- end
-
- context 'word count exceed limit' do
- let(:word_count) { 100 + 1 }
- # NOTE: its valid as it is orphaned data
- # ie a previous course
- # with an acrediting provider was removed
- # but the accrediting provider enrichment was left behind
-
- it { is_expected.to be_valid }
- end
- end
- end
-
- context 'with accrediting_providers' do
- describe '#accrediting_provider_providers' do
- subject do
- provider.accrediting_provider_enrichments = accrediting_provider_enrichments
- provider
- end
-
- let(:word_count) { 100 }
-
- let(:accrediting_providers) do
- result = []
- 10.times do
- result << create(:provider)
- end
- result
- end
-
- let(:accrediting_provider_enrichments) do
- accrediting_providers.map do |ap|
- {
- 'Description' => Faker::Lorem.sentence(word_count:),
- 'UcasProviderCode' => ap.provider_code.to_s
- }
- end
- end
-
- let(:courses) do
- accrediting_providers.map do |ap|
- build(:course, accrediting_provider: ap)
- end
- end
-
- let(:provider) do
- create(:provider, courses:)
- end
-
- context 'word count within limit' do
- it { is_expected.to be_valid }
- end
-
- context 'word count exceed limit' do
- let(:word_count) { 100 + 1 }
-
- it { is_expected.not_to be_valid }
- end
- end
- end
end
diff --git a/spec/models/provider_partnership_spec.rb b/spec/models/provider_partnership_spec.rb
index bdcb065b16..4ed7b8b2b2 100644
--- a/spec/models/provider_partnership_spec.rb
+++ b/spec/models/provider_partnership_spec.rb
@@ -17,6 +17,22 @@
describe 'validations' do
before { subject.validate }
+ describe '#description must be present' do
+ subject(:partnership) { build(:provider_partnership, description: '') }
+
+ it 'has correct error message' do
+ expect(subject.errors.messages[:description]).to include('Enter details about the accredited partnership')
+ end
+ end
+
+ describe '#description length' do
+ subject(:partnership) { build(:provider_partnership, description: Faker::Lorem.sentence(word_count: 101)) }
+
+ it 'has correct error message' do
+ expect(subject.errors.messages[:description]).to include('Description about the accredited provider must be 100 words or fewer')
+ end
+ end
+
context 'blank accredited provider' do
subject(:partnership) { build(:provider_partnership, accredited_provider: nil) }
diff --git a/spec/policies/provider_policy_accredited_enrichments_spec.rb b/spec/policies/provider_policy_accredited_enrichments_spec.rb
new file mode 100644
index 0000000000..302c7336a1
--- /dev/null
+++ b/spec/policies/provider_policy_accredited_enrichments_spec.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'ProviderPolicyAccreditedEnrichments' do
+ subject { ProviderPolicy }
+
+ before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(false)
+ end
+
+ let(:user) { build(:user) }
+ let(:admin) { build(:user, :admin) }
+
+ describe 'scope' do
+ it 'limits the providers to those the user is assigned to' do
+ provider1 = create(:provider, users: [user])
+ _provider2 = create(:provider)
+
+ expect(Pundit.policy_scope(user, Provider.all)).to eq [provider1]
+ end
+ end
+
+ permissions :index?, :suggest?, :new? do
+ it { is_expected.to permit user }
+ end
+
+ permissions :create? do
+ let(:user_outside_org) { build(:user) }
+ let(:provider) { build(:provider, users: [user]) }
+
+ it { is_expected.not_to permit(user, provider) }
+ it { is_expected.not_to permit(user_outside_org, provider) }
+ it { is_expected.to permit(admin, provider) }
+ end
+
+ permissions :can_show_training_provider? do
+ let(:accrediting_provider_enrichments) { [{ UcasProviderCode: course.accredited_provider_code }] }
+
+ let(:allowed_user) { create(:user, providers: [provider]) }
+ let(:not_allowed_user) { create(:user) }
+
+ let(:course) { create(:course, :with_accrediting_provider) }
+
+ let(:provider) { course.accrediting_provider }
+ let(:training_provider) do
+ course.provider
+ course.provider.accrediting_provider_enrichments = accrediting_provider_enrichments
+ course.provider
+ end
+
+ it { is_expected.to permit(admin, training_provider) }
+ it { is_expected.to permit(allowed_user, training_provider) }
+ it { is_expected.not_to permit(not_allowed_user, training_provider) }
+ end
+
+ describe '#permitted_provider_attributes' do
+ context 'when user' do
+ subject { ProviderPolicy.new(user, build(:provider)) }
+
+ it 'includes email' do
+ expect(subject.permitted_provider_attributes).to include(:email)
+ end
+
+ it 'excludes provider_name' do
+ expect(subject.permitted_provider_attributes).not_to include(:provider_name)
+ end
+ end
+
+ context 'when admin' do
+ subject { ProviderPolicy.new(admin, build(:provider)) }
+
+ it 'includes email' do
+ expect(subject.permitted_provider_attributes).to include(:email)
+ end
+
+ it 'includes provider_name' do
+ expect(subject.permitted_provider_attributes).to include(:provider_name)
+ end
+ end
+ end
+end
diff --git a/spec/policies/provider_policy_spec.rb b/spec/policies/provider_policy_spec.rb
index 9fa3d37bc5..6071ee80bb 100644
--- a/spec/policies/provider_policy_spec.rb
+++ b/spec/policies/provider_policy_spec.rb
@@ -5,6 +5,10 @@
describe ProviderPolicy do
subject { described_class }
+ before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(true)
+ end
+
let(:user) { build(:user) }
let(:admin) { build(:user, :admin) }
@@ -31,8 +35,6 @@
end
permissions :can_show_training_provider? do
- let(:accrediting_provider_enrichments) { [{ UcasProviderCode: course.accredited_provider_code }] }
-
let(:allowed_user) { create(:user, providers: [provider]) }
let(:not_allowed_user) { create(:user) }
@@ -40,9 +42,9 @@
let(:provider) { course.accrediting_provider }
let(:training_provider) do
- course.provider
- course.provider.accrediting_provider_enrichments = accrediting_provider_enrichments
- course.provider
+ course.provider.tap do |p|
+ p.accredited_partnerships.create(accredited_provider: course.accrediting_provider, description: 'asdfa')
+ end
end
it { is_expected.to permit(admin, training_provider) }
diff --git a/spec/serializers/api/public/v1/serializable_course_spec.rb b/spec/serializers/api/public/v1/serializable_course_spec.rb
index b42d36a073..4e2060eacf 100644
--- a/spec/serializers/api/public/v1/serializable_course_spec.rb
+++ b/spec/serializers/api/public/v1/serializable_course_spec.rb
@@ -17,12 +17,22 @@
context 'when there is an accredited body with enrichments' do
before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(false)
course.provider.update(accrediting_provider_enrichments: [{ Description: 'foo', UcasProviderCode: course.accrediting_provider.provider_code }])
end
it { is_expected.to have_attribute(:about_accredited_body).with_value(course.provider.accrediting_provider_enrichments.first.Description) }
end
+ context 'when there is a ratifying provider with description' do
+ before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(true)
+ course.provider.accredited_partnerships.create(description: 'foo', accredited_provider: course.accrediting_provider)
+ end
+
+ it { is_expected.to have_attribute(:about_accredited_body).with_value(course.provider.accredited_partnerships.find_by(accredited_provider_id: course.accrediting_provider).description) }
+ end
+
it { is_expected.to have_attribute(:about_accredited_body).with_value(nil) }
it { is_expected.to have_attribute(:about_course).with_value(course.latest_published_enrichment.about_course) }
it { is_expected.to have_attribute(:accredited_body_code).with_value(course.accredited_provider_code) }
diff --git a/spec/services/stores/user_store_spec.rb b/spec/services/stores/user_store_spec.rb
index 9413827c5a..e7f569b446 100644
--- a/spec/services/stores/user_store_spec.rb
+++ b/spec/services/stores/user_store_spec.rb
@@ -6,6 +6,6 @@
module Stores
describe UserStore do
- include_examples 'store', :user, %i[user provider provider_contact accredited_provider]
+ include_examples 'store', :user, %i[user provider provider_contact accredited_provider provider_partnership]
end
end
diff --git a/spec/services/workflow_step_service_partnerships_spec.rb b/spec/services/workflow_step_service_partnerships_spec.rb
new file mode 100644
index 0000000000..7ed3b65e7f
--- /dev/null
+++ b/spec/services/workflow_step_service_partnerships_spec.rb
@@ -0,0 +1,201 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe WorkflowStepService do
+ subject do
+ described_class.call(course)
+ end
+
+ before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(true)
+ end
+
+ describe '#call partnerships' do
+ context 'when course.is_school_direct? && when course.provider.accredited_partners.length == 0' do
+ let(:provider) { build(:provider) }
+ let(:course) { create(:course, :salary) }
+ let(:accredited_provider) { nil }
+
+ it 'returns the expected workflow steps' do
+ expected_steps = %i[
+ courses_list
+ level
+ subjects
+ engineers_teach_physics
+ modern_languages
+ age_range
+ outcome
+ funding_type
+ full_or_part_time
+ school
+ study_site
+ accredited_provider
+ can_sponsor_skilled_worker_visa
+ applications_open
+ start_date
+ confirmation
+ ]
+
+ expect(subject).to eq(expected_steps)
+ end
+ end
+
+ context 'when course.is_school_direct? && course.provider.accredited_partners.length == 1' do
+ let(:provider) { build(:provider, :with_accredited_partner) }
+ let(:course) { create(:course, :salary, accrediting_provider: accredited_provider, provider:) }
+ let(:accredited_provider) { provider.accredited_partners.first }
+
+ it 'returns the expected workflow steps' do
+ expected_steps = %i[
+ courses_list
+ level
+ subjects
+ engineers_teach_physics
+ modern_languages
+ age_range
+ outcome
+ funding_type
+ full_or_part_time
+ school
+ study_site
+ can_sponsor_skilled_worker_visa
+ applications_open
+ start_date
+ confirmation
+ ]
+
+ expect(subject).to eq(expected_steps)
+ end
+ end
+ end
+
+ context 'when school direct and teacher degree apprenticeship' do
+ context 'when more than one accredited provider' do
+ let(:provider) { build(:provider) }
+ let(:course) { create(:course, :resulting_in_undergraduate_degree_with_qts, provider:) }
+ let!(:partnerships) { create_list(:provider_partnership, 2, training_provider: provider) }
+ let(:accredited_provider) { provider.accredited_partners.first }
+ let(:second_accredited_provider) { provider.accredited_partners.last }
+
+ it 'adds accredited provider step' do
+ expected_steps = %i[
+ courses_list
+ level
+ subjects
+ engineers_teach_physics
+ modern_languages
+ age_range
+ outcome
+ school
+ study_site
+ accredited_provider
+ applications_open
+ start_date
+ confirmation
+ ]
+
+ expect(subject).to eq(expected_steps)
+ end
+ end
+
+ context 'when only one accredited provider' do
+ let(:provider) { build(:provider, :with_accredited_partner) }
+ let(:accredited_provider) { provider.accredited_partners.first }
+ let(:course) { create(:course, :resulting_in_undergraduate_degree_with_qts, accrediting_provider: accredited_provider, provider:) }
+
+ it 'removes accredited provider step' do
+ expected_steps = %i[
+ courses_list
+ level
+ subjects
+ engineers_teach_physics
+ modern_languages
+ age_range
+ outcome
+ school
+ study_site
+ applications_open
+ start_date
+ confirmation
+ ]
+
+ expect(subject).to eq(expected_steps)
+ end
+ end
+ end
+
+ context 'when scitt and teacher degree apprenticeship' do
+ let(:provider) { create(:provider, :scitt, :accredited_provider) }
+ let(:course) { create(:course, :resulting_in_undergraduate_degree_with_qts, provider:) }
+
+ it 'returns workflow steps' do
+ expected_steps = %i[
+ courses_list
+ level
+ subjects
+ engineers_teach_physics
+ modern_languages
+ age_range
+ outcome
+ school
+ study_site
+ applications_open
+ start_date
+ confirmation
+ ]
+
+ expect(subject).to eq(expected_steps)
+ end
+ end
+
+ context 'when course.is_further_education?' do
+ let(:provider) { create(:provider, :accredited_provider) }
+
+ let(:course) { create(:course, provider:, level: 'further_education', subjects: [find_or_create(:further_education_subject)]) }
+
+ it 'returns the expected workflow steps' do
+ expected_steps = %i[
+ courses_list
+ level
+ outcome
+ funding_type
+ full_or_part_time
+ school
+ study_site
+ applications_open
+ start_date
+ confirmation
+ ]
+
+ expect(subject).to eq(expected_steps)
+ end
+ end
+
+ context 'when course.is_uni_or_scitt?' do
+ let(:provider) { create(:provider, :accredited_provider) }
+ let(:course) { create(:course, :salary, provider:) }
+
+ it 'returns the expected workflow steps' do
+ expected_steps = %i[
+ courses_list
+ level
+ subjects
+ engineers_teach_physics
+ modern_languages
+ age_range
+ outcome
+ funding_type
+ full_or_part_time
+ school
+ study_site
+ can_sponsor_skilled_worker_visa
+ applications_open
+ start_date
+ confirmation
+ ]
+
+ expect(subject).to eq(expected_steps)
+ end
+ end
+end
diff --git a/spec/services/workflow_step_service_spec.rb b/spec/services/workflow_step_service_spec.rb
index 849a7c374a..ec0706a98f 100644
--- a/spec/services/workflow_step_service_spec.rb
+++ b/spec/services/workflow_step_service_spec.rb
@@ -7,6 +7,10 @@
described_class.call(course)
end
+ before do
+ allow(Settings.features).to receive(:provider_partnerships).and_return(false)
+ end
+
describe '#call' do
context 'when course.is_school_direct? && when course.provider.accredited_bodies.length == 0' do
let(:provider) do
diff --git a/spec/support/page_objects/publish/courses/ratifying_providers.rb b/spec/support/page_objects/publish/courses/ratifying_providers.rb
new file mode 100644
index 0000000000..b3f4ebeadc
--- /dev/null
+++ b/spec/support/page_objects/publish/courses/ratifying_providers.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module PageObjects
+ module Publish
+ module Courses
+ class RatifyingProviders < PageObjects::Base
+ set_url '/publish/organisations/{provider_code}/{recruitment_cycle_year}/courses/{course_code}/ratifying-provider'
+
+ elements :suggested_accredited_bodies, '[data-qa="course__accredited_provider_option"]'
+ element :add_new_link, '[data-qa="course__add"]'
+
+ element :update_button, 'input[type=submit]'
+ end
+ end
+ end
+end