diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss
index ff04bfa48..0a6375e47 100644
--- a/app/assets/stylesheets/application.scss
+++ b/app/assets/stylesheets/application.scss
@@ -30,7 +30,9 @@ $govuk-page-width: 1140px;
@import 'govuk_publishing_components/components/table';
@import 'govuk_publishing_components/components/textarea';
@import 'govuk_publishing_components/components/title';
+@import "tags";
@import "downtimes";
@import "publications";
@import "summary-card";
@import "popular_links";
+@import "editions";
diff --git a/app/assets/stylesheets/editions.scss b/app/assets/stylesheets/editions.scss
new file mode 100644
index 000000000..de95ca73f
--- /dev/null
+++ b/app/assets/stylesheets/editions.scss
@@ -0,0 +1,5 @@
+.editions__edit {
+ .govuk-tag {
+ display: inline;
+ }
+}
diff --git a/app/assets/stylesheets/publications.scss b/app/assets/stylesheets/publications.scss
index 8a069114d..329fc76d6 100644
--- a/app/assets/stylesheets/publications.scss
+++ b/app/assets/stylesheets/publications.scss
@@ -32,44 +32,6 @@ $width: 40;
font-size: 1.1875rem;
}
- .govuk-tag {
- &--amends_needed {
- @extend .govuk-tag--red; // stylelint-disable-line scss/at-extend-no-missing-placeholder
- }
-
- &--archived {
- @extend .govuk-tag--blue; // stylelint-disable-line scss/at-extend-no-missing-placeholder
- }
-
- &--draft {
- @extend .govuk-tag--yellow; // stylelint-disable-line scss/at-extend-no-missing-placeholder
- }
-
- &--fact_check {
- @extend .govuk-tag--purple; // stylelint-disable-line scss/at-extend-no-missing-placeholder
- }
-
- &--fact_check_received {
- @extend .govuk-tag--pink; // stylelint-disable-line scss/at-extend-no-missing-placeholder
- }
-
- &--ready {
- @extend .govuk-tag--green; // stylelint-disable-line scss/at-extend-no-missing-placeholder
- }
-
- &--scheduled_for_publishing {
- @extend .govuk-tag--turquoise; // stylelint-disable-line scss/at-extend-no-missing-placeholder
- }
-
- &--published {
- @extend .govuk-tag--orange; // stylelint-disable-line scss/at-extend-no-missing-placeholder
- }
-
- &--in_review {
- @extend .govuk-tag--grey; // stylelint-disable-line scss/at-extend-no-missing-placeholder
- }
- }
-
.govuk-table {
border-top: 2px solid $govuk-text-colour;
}
diff --git a/app/assets/stylesheets/tags.scss b/app/assets/stylesheets/tags.scss
new file mode 100644
index 000000000..d9168c65e
--- /dev/null
+++ b/app/assets/stylesheets/tags.scss
@@ -0,0 +1,37 @@
+.govuk-tag {
+ &--amends_needed {
+ @extend .govuk-tag--red; // stylelint-disable-line scss/at-extend-no-missing-placeholder
+ }
+
+ &--archived {
+ @extend .govuk-tag--blue; // stylelint-disable-line scss/at-extend-no-missing-placeholder
+ }
+
+ &--draft {
+ @extend .govuk-tag--yellow; // stylelint-disable-line scss/at-extend-no-missing-placeholder
+ }
+
+ &--fact_check {
+ @extend .govuk-tag--purple; // stylelint-disable-line scss/at-extend-no-missing-placeholder
+ }
+
+ &--fact_check_received {
+ @extend .govuk-tag--pink; // stylelint-disable-line scss/at-extend-no-missing-placeholder
+ }
+
+ &--ready {
+ @extend .govuk-tag--green; // stylelint-disable-line scss/at-extend-no-missing-placeholder
+ }
+
+ &--scheduled_for_publishing {
+ @extend .govuk-tag--turquoise; // stylelint-disable-line scss/at-extend-no-missing-placeholder
+ }
+
+ &--published {
+ @extend .govuk-tag--orange; // stylelint-disable-line scss/at-extend-no-missing-placeholder
+ }
+
+ &--in_review {
+ @extend .govuk-tag--grey; // stylelint-disable-line scss/at-extend-no-missing-placeholder
+ }
+}
diff --git a/app/controllers/editions_controller.rb b/app/controllers/editions_controller.rb
index 84bc77b88..9dca5cede 100644
--- a/app/controllers/editions_controller.rb
+++ b/app/controllers/editions_controller.rb
@@ -2,429 +2,30 @@
require "edition_progressor"
class EditionsController < InheritedResources::Base
- actions :create, :update, :destroy
+ layout "design_system"
+
defaults resource_class: Edition, collection_name: "editions", instance_name: "resource"
- before_action :setup_view_paths, except: %i[index new create]
- before_action only: %i[update duplicate progress review destroy admin] do
- require_editor_permissions
- end
- before_action only: %i[unpublish process_unpublish] do
- require_govuk_editor(redirect_path: edition_path(resource))
- end
- after_action :report_state_counts, only: %i[create duplicate progress destroy]
+ before_action :setup_view_paths, except: %i[index]
def index
redirect_to root_path
end
def show
- @linkables = Tagging::Linkables.new
-
- if @resource.is_a?(Parted)
- @ordered_parts = @resource.parts.in_order
- end
-
- if @resource.is_a?(Varianted)
- @ordered_variants = @resource.variants.in_order
- end
-
- @tagging_update = tagging_update_form
- @artefact = @resource.artefact
- render action: "show"
- end
-
- alias_method :metadata, :show
- alias_method :history, :show
- alias_method :admin, :show
- alias_method :unpublish, :show
-
- def new
- @publication = build_resource
- setup_view_paths_for(@publication)
- end
-
- def create
- class_identifier = params[:edition].delete(:kind).to_sym
- create_params = permitted_params(subtype: :"#{class_identifier}_edition")
- @publication = current_user.create_edition(class_identifier, create_params[:edition])
-
- if @publication.persisted?
- UpdateWorker.perform_async(@publication.id.to_s)
-
- flash[:success] = "#{description(@publication)} successfully created"
- redirect_to edition_path(@publication)
- else
- setup_view_paths_for(@publication)
- render template: "new"
- end
- end
-
- def duplicate
- command = EditionDuplicator.new(resource, current_user)
- target_edition_class_name = "#{params[:to]}_edition".classify if params[:to]
-
- if !resource.can_create_new_edition?
- flash[:warning] = "Another person has created a newer edition"
- redirect_to edition_path(resource)
- elsif command.duplicate(target_edition_class_name, current_user)
- new_edition = command.new_edition
- UpdateWorker.perform_async(new_edition.id.to_s)
-
- return_to = params[:return_to] || edition_path(new_edition)
- flash[:success] = "New edition created"
- redirect_to return_to
- else
- flash[:danger] = command.error_message
- redirect_to edition_path(resource)
- end
- end
-
- def update
- # We have to call this before updating as it removes any assigned_to_id
- # parameter from the request, preventing us from inadvertently changing
- # it at the wrong time.
- assign_to = new_assignee
-
- activity_params = attempted_activity_params
- remove_activity_params
-
- # update! is from the Inherited Resources gem
- # https://github.com/josevalim/inherited_resources/blob/master/lib/inherited_resources/actions.rb#L42
- update! do |success, failure|
- success.html do
- if attempted_activity
- if progress_edition(resource, activity_params)
- flash[:success] = @command.status_message
- else
- flash[:danger] = @command.status_message
- end
- end
-
- update_assignment resource, assign_to
-
- UpdateWorker.perform_async(resource.id.to_s, update_action_is_publish?)
-
- return_to = params[:return_to] || edition_path(resource)
- redirect_to return_to
- end
- failure.html do
- @resource = resource
- @tagging_update = tagging_update_form
- @linkables = Tagging::Linkables.new
- @artefact = @resource.artefact
- render action: "show"
- end
- success.json do
- progress_edition(resource, activity_params) if attempted_activity
-
- update_assignment resource, assign_to
-
- UpdateWorker.perform_async(resource.id.to_s, update_action_is_publish?)
-
- render json: resource
- end
- failure.json { render json: resource.errors, status: :not_acceptable }
- end
- end
-
- def linking
- @linkables = Tagging::Linkables.new
- @tagging_update = tagging_update_form
@artefact = @resource.artefact
render action: "show"
end
- def update_tagging
- form = Tagging::TaggingUpdateForm.new(tagging_update_form_params)
- if form.valid?
- form.publish!
- flash[:success] = "Tags have been updated!"
- else
- flash[:danger] = form.errors.full_messages.join("\n")
- end
- redirect_to tagging_edition_path
- rescue GdsApi::HTTPConflict
- redirect_to tagging_edition_path,
- flash: {
- danger: "Somebody changed the tags before you could. Your changes have not been saved.",
- }
- end
-
- def update_related_external_links
- artefact = resource.artefact
- if params.key?("artefact")
- external_links = params.require(:artefact).permit(external_links_attributes: %i[title url id _destroy])
- artefact.external_links_attributes = external_links[:external_links_attributes].to_h
-
- if artefact.save
- flash[:success] = "External links have been saved. They will be visible the next time this publication is published."
- else
- flash[:danger] = artefact.errors.full_messages.join("\n")
- end
- else
- flash[:danger] = "There aren't any external related links yet"
- end
-
- redirect_back(fallback_location: related_external_links_edition_path(resource.id))
- end
-
- def review
- if resource.reviewer.present?
- flash[:danger] = "#{resource.reviewer} has already claimed this 2i"
- redirect_to edition_path(resource)
- return
- end
-
- resource.reviewer = params[:edition][:reviewer]
- if resource.save
- flash[:success] = "You are the reviewer of this #{description(resource).downcase}."
- else
- flash[:danger] = "Something went wrong when attempting to claim 2i."
- end
- redirect_to edition_path(resource)
- end
-
- def destroy
- if resource.can_destroy?
- destroy! do
- flash[:success] = "Edition deleted"
- redirect_to root_url
- return
- end
- else
- flash[:danger] = "Cannot delete a #{description(resource).downcase} that has ever been published."
- redirect_to edition_path(resource)
- nil
- end
- end
-
- def progress
- if progress_edition(resource, params[:edition][:activity].permit(:comment, :request_type, :publish_at))
- PublishWorker.perform_async(resource.id.to_s) if progress_action_is_publish?
-
- flash[:success] = @command.status_message
- else
- flash[:danger] = @command.status_message
- end
- redirect_to edition_path(resource)
- end
-
- def diff
- @resource = resource
- @comparison = @resource.previous_siblings.last
- end
-
- def process_unpublish
- edition = Edition.find(params[:id])
- artefact = edition.artefact
-
- if validate_redirect(redirect_url) || redirect_url.blank?
- success = UnpublishService.call(artefact, current_user, redirect_url)
- else
- flash[:danger] = "Redirect path is invalid. #{description(resource)} has not been unpublished."
- end
-
- if success
- notice = "Content unpublished"
- notice << " and redirected" if redirect_url.present?
- flash[:notice] = notice
- redirect_to root_path
- else
- flash[:alert] = "Due to a service problem, the edition couldn't be unpublished"
- redirect_to unpublish_edition_path(edition)
- end
- end
-
- def diagram
- # [MT] TODO: What's the best way to handle requests for a diagram for a non-simple smart answer?
- if @resource.format != "SimpleSmartAnswer"
- render plain: "404 Not Found", status: :not_found
- end
- end
-
protected
- def permitted_params(subtype: nil)
- subtype = @resource.class.to_s.underscore.to_sym if subtype.nil?
- params.permit(edition: type_specific_params(subtype) + common_params)
- end
-
- def type_specific_params(subtype)
- case subtype
- when :guide_edition
- [
- :hide_chapter_navigation,
- { parts_attributes: %i[title body slug order id _destroy] },
- ]
- when :local_transaction_edition
- [
- :lgsl_code,
- :lgil_code,
- :introduction,
- :more_information,
- :need_to_know,
- { scotland_availability_attributes: %i[type alternative_url] },
- { wales_availability_attributes: %i[type alternative_url] },
- { northern_ireland_availability_attributes: %i[type alternative_url] },
- ]
- when :place_edition
- %i[
- place_type
- introduction
- more_information
- need_to_know
- ]
- when :simple_smart_answer_edition
- [
- :body,
- :start_button_text,
- { nodes_attributes: [
- :slug,
- :title,
- :body,
- :order,
- :kind,
- :id,
- :_destroy,
- { options_attributes: %i[label next_node id _destroy] },
- ] },
- ]
- when :transaction_edition
- [
- :introduction,
- :start_button_text,
- :will_continue_on,
- :link,
- :more_information,
- :alternate_methods,
- :need_to_know,
- { variants_attributes: %i[title slug introduction link more_information alternate_methods order id _destroy] },
- ]
- when :completed_transaction_edition
- %i[
- body
- promotion_choice
- promotion_choice_url
- promotion_choice_opt_in_url
- promotion_choice_opt_out_url
- ]
- else
- # answer_edition, help_page_edition
- [
- :body,
- ]
- end
- end
-
- def common_params
- %i[
- assigned_to_id
- reviewer
- panopticon_id
- slug
- change_note
- major_change
- title
- in_beta
- overview
- ]
- end
-
- def new_assignee
- assignee_id = (params[:edition] || {}).delete(:assigned_to_id)
- User.find(assignee_id) if assignee_id.present?
- end
-
- def update_assignment(edition, assignee)
- return if edition.assigned_to == assignee
-
- if !assignee
- current_user.unassign(edition)
- elsif assignee.has_editor_permissions?(resource)
- current_user.assign(edition, assignee)
- else
- flash[:danger] = "Chosen assignee does not have correct editor permissions."
- end
- end
-
def setup_view_paths
setup_view_paths_for(resource)
end
- def description(resource)
- resource.format.underscore.humanize
- end
-
private
- def redirect_url
- make_govuk_url_relative params["redirect_url"]
- end
-
- def make_govuk_url_relative(url = "")
- url.sub(%r{^(https?://)?(www\.)?gov\.uk/}, "/")
- end
-
- def validate_redirect(redirect_url)
- regex = /(\/([a-z0-9]+-)*[a-z0-9]+)+/
- redirect_url =~ regex
- end
-
- def tagging_update_form
- Tagging::TaggingUpdateForm.build_from_publishing_api(
- @resource.artefact.content_id,
- @resource.artefact.language,
- )
- end
-
- def attempted_activity_params
- return unless attempted_activity
-
- params[:edition]["activity_#{attempted_activity}_attributes"].permit(
- :request_type, :email_addresses, :customised_message, :comment, :publish_at
- )
- end
-
- def remove_activity_params
- params.fetch(:edition, {}).delete_if { |attributes, _| attributes =~ /\Aactivity_\w*_attributes\z/ }
- end
-
- def tagging_update_form_params
- params[:tagging_tagging_update_form].permit(
- :content_id,
- :previous_version,
- :parent,
- mainstream_browse_pages: [],
- organisations: [],
- meets_user_needs: [],
- ordered_related_items: [],
- ).to_h
- end
-
- def progress_edition(resource, activity_params)
- @command = EditionProgressor.new(resource, current_user)
- @command.progress(squash_multiparameter_datetime_attributes(activity_params.to_h, %w[publish_at]))
- end
-
- def report_state_counts
- Publisher::Application.edition_state_count_reporter.report
- end
-
- def update_action_is_publish?
- attempted_activity == :publish
- end
-
- def progress_action_is_publish?
- progress_action_param == "publish"
- end
-
- def progress_action_param
- params[:edition][:activity][:request_type]
- rescue StandardError
- nil
- end
-
- def attempted_activity
- Edition::ACTIONS.invert[params[:commit]]
+ def setup_view_paths_for(publication)
+ prepend_view_path "app/views/editions"
+ prepend_view_path template_folder_for(publication)
end
end
diff --git a/app/controllers/legacy_editions_controller.rb b/app/controllers/legacy_editions_controller.rb
new file mode 100644
index 000000000..e5290ccbf
--- /dev/null
+++ b/app/controllers/legacy_editions_controller.rb
@@ -0,0 +1,430 @@
+require "edition_duplicator"
+require "edition_progressor"
+
+class LegacyEditionsController < InheritedResources::Base
+ actions :create, :update, :destroy
+ defaults resource_class: Edition, collection_name: "editions", instance_name: "resource"
+ before_action :setup_view_paths, except: %i[index new create]
+ before_action only: %i[update duplicate progress review destroy admin] do
+ require_editor_permissions
+ end
+ before_action only: %i[unpublish process_unpublish] do
+ require_govuk_editor(redirect_path: edition_path(resource))
+ end
+ after_action :report_state_counts, only: %i[create duplicate progress destroy]
+
+ def index
+ redirect_to root_path
+ end
+
+ def show
+ @linkables = Tagging::Linkables.new
+
+ if @resource.is_a?(Parted)
+ @ordered_parts = @resource.parts.in_order
+ end
+
+ if @resource.is_a?(Varianted)
+ @ordered_variants = @resource.variants.in_order
+ end
+
+ @tagging_update = tagging_update_form
+ @artefact = @resource.artefact
+ render action: "show"
+ end
+
+ alias_method :metadata, :show
+ alias_method :history, :show
+ alias_method :admin, :show
+ alias_method :unpublish, :show
+
+ def new
+ @publication = build_resource
+ setup_view_paths_for(@publication)
+ end
+
+ def create
+ class_identifier = params[:edition].delete(:kind).to_sym
+ create_params = permitted_params(subtype: :"#{class_identifier}_edition")
+ @publication = current_user.create_edition(class_identifier, create_params[:edition])
+
+ if @publication.persisted?
+ UpdateWorker.perform_async(@publication.id.to_s)
+
+ flash[:success] = "#{description(@publication)} successfully created"
+ redirect_to edition_path(@publication)
+ else
+ setup_view_paths_for(@publication)
+ render template: "new"
+ end
+ end
+
+ def duplicate
+ command = EditionDuplicator.new(resource, current_user)
+ target_edition_class_name = "#{params[:to]}_edition".classify if params[:to]
+
+ if !resource.can_create_new_edition?
+ flash[:warning] = "Another person has created a newer edition"
+ redirect_to edition_path(resource)
+ elsif command.duplicate(target_edition_class_name, current_user)
+ new_edition = command.new_edition
+ UpdateWorker.perform_async(new_edition.id.to_s)
+
+ return_to = params[:return_to] || edition_path(new_edition)
+ flash[:success] = "New edition created"
+ redirect_to return_to
+ else
+ flash[:danger] = command.error_message
+ redirect_to edition_path(resource)
+ end
+ end
+
+ def update
+ # We have to call this before updating as it removes any assigned_to_id
+ # parameter from the request, preventing us from inadvertently changing
+ # it at the wrong time.
+ assign_to = new_assignee
+
+ activity_params = attempted_activity_params
+ remove_activity_params
+
+ # update! is from the Inherited Resources gem
+ # https://github.com/josevalim/inherited_resources/blob/master/lib/inherited_resources/actions.rb#L42
+ update! do |success, failure|
+ success.html do
+ if attempted_activity
+ if progress_edition(resource, activity_params)
+ flash[:success] = @command.status_message
+ else
+ flash[:danger] = @command.status_message
+ end
+ end
+
+ update_assignment resource, assign_to
+
+ UpdateWorker.perform_async(resource.id.to_s, update_action_is_publish?)
+
+ return_to = params[:return_to] || edition_path(resource)
+ redirect_to return_to
+ end
+ failure.html do
+ @resource = resource
+ @tagging_update = tagging_update_form
+ @linkables = Tagging::Linkables.new
+ @artefact = @resource.artefact
+ render action: "show"
+ end
+ success.json do
+ progress_edition(resource, activity_params) if attempted_activity
+
+ update_assignment resource, assign_to
+
+ UpdateWorker.perform_async(resource.id.to_s, update_action_is_publish?)
+
+ render json: resource
+ end
+ failure.json { render json: resource.errors, status: :not_acceptable }
+ end
+ end
+
+ def linking
+ @linkables = Tagging::Linkables.new
+ @tagging_update = tagging_update_form
+ @artefact = @resource.artefact
+ render action: "show"
+ end
+
+ def update_tagging
+ form = Tagging::TaggingUpdateForm.new(tagging_update_form_params)
+ if form.valid?
+ form.publish!
+ flash[:success] = "Tags have been updated!"
+ else
+ flash[:danger] = form.errors.full_messages.join("\n")
+ end
+ redirect_to tagging_edition_path
+ rescue GdsApi::HTTPConflict
+ redirect_to tagging_edition_path,
+ flash: {
+ danger: "Somebody changed the tags before you could. Your changes have not been saved.",
+ }
+ end
+
+ def update_related_external_links
+ artefact = resource.artefact
+ if params.key?("artefact")
+ external_links = params.require(:artefact).permit(external_links_attributes: %i[title url id _destroy])
+ artefact.external_links_attributes = external_links[:external_links_attributes].to_h
+
+ if artefact.save
+ flash[:success] = "External links have been saved. They will be visible the next time this publication is published."
+ else
+ flash[:danger] = artefact.errors.full_messages.join("\n")
+ end
+ else
+ flash[:danger] = "There aren't any external related links yet"
+ end
+
+ redirect_back(fallback_location: related_external_links_edition_path(resource.id))
+ end
+
+ def review
+ if resource.reviewer.present?
+ flash[:danger] = "#{resource.reviewer} has already claimed this 2i"
+ redirect_to edition_path(resource)
+ return
+ end
+
+ resource.reviewer = params[:edition][:reviewer]
+ if resource.save
+ flash[:success] = "You are the reviewer of this #{description(resource).downcase}."
+ else
+ flash[:danger] = "Something went wrong when attempting to claim 2i."
+ end
+ redirect_to edition_path(resource)
+ end
+
+ def destroy
+ if resource.can_destroy?
+ destroy! do
+ flash[:success] = "Edition deleted"
+ redirect_to root_url
+ return
+ end
+ else
+ flash[:danger] = "Cannot delete a #{description(resource).downcase} that has ever been published."
+ redirect_to edition_path(resource)
+ nil
+ end
+ end
+
+ def progress
+ if progress_edition(resource, params[:edition][:activity].permit(:comment, :request_type, :publish_at))
+ PublishWorker.perform_async(resource.id.to_s) if progress_action_is_publish?
+
+ flash[:success] = @command.status_message
+ else
+ flash[:danger] = @command.status_message
+ end
+ redirect_to edition_path(resource)
+ end
+
+ def diff
+ @resource = resource
+ @comparison = @resource.previous_siblings.last
+ end
+
+ def process_unpublish
+ edition = Edition.find(params[:id])
+ artefact = edition.artefact
+
+ if validate_redirect(redirect_url) || redirect_url.blank?
+ success = UnpublishService.call(artefact, current_user, redirect_url)
+ else
+ flash[:danger] = "Redirect path is invalid. #{description(resource)} has not been unpublished."
+ end
+
+ if success
+ notice = "Content unpublished"
+ notice << " and redirected" if redirect_url.present?
+ flash[:notice] = notice
+ redirect_to root_path
+ else
+ flash[:alert] = "Due to a service problem, the edition couldn't be unpublished"
+ redirect_to unpublish_edition_path(edition)
+ end
+ end
+
+ def diagram
+ # [MT] TODO: What's the best way to handle requests for a diagram for a non-simple smart answer?
+ if @resource.format != "SimpleSmartAnswer"
+ render plain: "404 Not Found", status: :not_found
+ end
+ end
+
+protected
+
+ def permitted_params(subtype: nil)
+ subtype = @resource.class.to_s.underscore.to_sym if subtype.nil?
+ params.permit(edition: type_specific_params(subtype) + common_params)
+ end
+
+ def type_specific_params(subtype)
+ case subtype
+ when :guide_edition
+ [
+ :hide_chapter_navigation,
+ { parts_attributes: %i[title body slug order id _destroy] },
+ ]
+ when :local_transaction_edition
+ [
+ :lgsl_code,
+ :lgil_code,
+ :introduction,
+ :more_information,
+ :need_to_know,
+ { scotland_availability_attributes: %i[type alternative_url] },
+ { wales_availability_attributes: %i[type alternative_url] },
+ { northern_ireland_availability_attributes: %i[type alternative_url] },
+ ]
+ when :place_edition
+ %i[
+ place_type
+ introduction
+ more_information
+ need_to_know
+ ]
+ when :simple_smart_answer_edition
+ [
+ :body,
+ :start_button_text,
+ { nodes_attributes: [
+ :slug,
+ :title,
+ :body,
+ :order,
+ :kind,
+ :id,
+ :_destroy,
+ { options_attributes: %i[label next_node id _destroy] },
+ ] },
+ ]
+ when :transaction_edition
+ [
+ :introduction,
+ :start_button_text,
+ :will_continue_on,
+ :link,
+ :more_information,
+ :alternate_methods,
+ :need_to_know,
+ { variants_attributes: %i[title slug introduction link more_information alternate_methods order id _destroy] },
+ ]
+ when :completed_transaction_edition
+ %i[
+ body
+ promotion_choice
+ promotion_choice_url
+ promotion_choice_opt_in_url
+ promotion_choice_opt_out_url
+ ]
+ else
+ # answer_edition, help_page_edition
+ [
+ :body,
+ ]
+ end
+ end
+
+ def common_params
+ %i[
+ assigned_to_id
+ reviewer
+ panopticon_id
+ slug
+ change_note
+ major_change
+ title
+ in_beta
+ overview
+ ]
+ end
+
+ def new_assignee
+ assignee_id = (params[:edition] || {}).delete(:assigned_to_id)
+ User.find(assignee_id) if assignee_id.present?
+ end
+
+ def update_assignment(edition, assignee)
+ return if edition.assigned_to == assignee
+
+ if !assignee
+ current_user.unassign(edition)
+ elsif assignee.has_editor_permissions?(resource)
+ current_user.assign(edition, assignee)
+ else
+ flash[:danger] = "Chosen assignee does not have correct editor permissions."
+ end
+ end
+
+ def setup_view_paths
+ setup_view_paths_for(resource)
+ end
+
+ def description(resource)
+ resource.format.underscore.humanize
+ end
+
+private
+
+ def redirect_url
+ make_govuk_url_relative params["redirect_url"]
+ end
+
+ def make_govuk_url_relative(url = "")
+ url.sub(%r{^(https?://)?(www\.)?gov\.uk/}, "/")
+ end
+
+ def validate_redirect(redirect_url)
+ regex = /(\/([a-z0-9]+-)*[a-z0-9]+)+/
+ redirect_url =~ regex
+ end
+
+ def tagging_update_form
+ Tagging::TaggingUpdateForm.build_from_publishing_api(
+ @resource.artefact.content_id,
+ @resource.artefact.language,
+ )
+ end
+
+ def attempted_activity_params
+ return unless attempted_activity
+
+ params[:edition]["activity_#{attempted_activity}_attributes"].permit(
+ :request_type, :email_addresses, :customised_message, :comment, :publish_at
+ )
+ end
+
+ def remove_activity_params
+ params.fetch(:edition, {}).delete_if { |attributes, _| attributes =~ /\Aactivity_\w*_attributes\z/ }
+ end
+
+ def tagging_update_form_params
+ params[:tagging_tagging_update_form].permit(
+ :content_id,
+ :previous_version,
+ :parent,
+ mainstream_browse_pages: [],
+ organisations: [],
+ meets_user_needs: [],
+ ordered_related_items: [],
+ ).to_h
+ end
+
+ def progress_edition(resource, activity_params)
+ @command = EditionProgressor.new(resource, current_user)
+ @command.progress(squash_multiparameter_datetime_attributes(activity_params.to_h, %w[publish_at]))
+ end
+
+ def report_state_counts
+ Publisher::Application.edition_state_count_reporter.report
+ end
+
+ def update_action_is_publish?
+ attempted_activity == :publish
+ end
+
+ def progress_action_is_publish?
+ progress_action_param == "publish"
+ end
+
+ def progress_action_param
+ params[:edition][:activity][:request_type]
+ rescue StandardError
+ nil
+ end
+
+ def attempted_activity
+ Edition::ACTIONS.invert[params[:commit]]
+ end
+end
diff --git a/app/views/editions/show.html.erb b/app/views/editions/show.html.erb
index 343392388..e395fcdd9 100644
--- a/app/views/editions/show.html.erb
+++ b/app/views/editions/show.html.erb
@@ -1,69 +1,25 @@
<% @edition = @resource %>
- <%= render "shared/edition_header" %>
-
- <% errors_hash = errors_to_display(@edition) %>
- <% if !errors_hash.empty? %>
-
- <% end %>
-
-
-
- <% tabs_for(current_user, @edition).each do |tab| %>
- - class="active"<% end %>>
- <%= tab_link(tab, edition_path(@edition)) %>
-
- <% end %>
-
-
-
-
-
- <% if @edition.class.to_s == "SimpleSmartAnswerEdition" %>
-
- View the <%= link_to "flow diagram (opens in a new tab)", diagram_edition_path(@edition), target: "_blank", rel: "noopener" %>
-
- <% end %>
-
- <%= render "link_check_reports/link_check_report", edition: @edition, report: @edition.latest_link_check_report %>
-
- <% if @edition.class.to_s.in?(Edition::HAS_GOVSPEAK_FIELDS) %>
-
Govspeak help
-
-
- <%= render "shared/govspeak_help" %>
-
- <% end %>
-
-
- <%= resource_form(@resource) do |f| %>
-
- <%= render resource_fields(@resource), f: f %>
-
-
- <%= edition_activities_fields(f, @resource) %>
- <% end %>
-
- <%= # cancel scheduled publishing doesn't require the edition to be saved when requesting an activity,
- # because this action is triggered from a view where editing is not allowed.
- edition_activities_forms(@resource, Edition::CANCEL_SCHEDULED_PUBLISHING_ACTION) %>
-
- <% tabs.reject {|t| t.name == "edit"}.each do |tab| %>
-
-
- <%= render :partial => "/shared/#{tab.name}", :locals => {:publication => @resource} %>
-
-
- <% end %>
-
-
-<% content_for :page_title, "Editing #{@resource.title}" %>
+<% content_for :page_title, @resource.title %>
+<% content_for :title, @resource.title %>
+
+
+
+ <%= render "govuk_publishing_components/components/summary_list", {
+ items: [
+ {
+ field: "Assigned to",
+ value: @resource.assigned_to,
+ },
+ {
+ field: "Content type",
+ value: @resource.format.underscore.humanize,
+ },
+ {
+ field: "Edition",
+ value: sanitize("#{@resource.version_number} #{@resource.status_text}"),
+ },
+ ],
+ } %>
+
+
diff --git a/app/views/editions/_major_change_fields.html.erb b/app/views/legacy_editions/_major_change_fields.html.erb
similarity index 100%
rename from app/views/editions/_major_change_fields.html.erb
rename to app/views/legacy_editions/_major_change_fields.html.erb
diff --git a/app/views/editions/_reviewer_field.html.erb b/app/views/legacy_editions/_reviewer_field.html.erb
similarity index 100%
rename from app/views/editions/_reviewer_field.html.erb
rename to app/views/legacy_editions/_reviewer_field.html.erb
diff --git a/app/views/editions/diagram.html.erb b/app/views/legacy_editions/diagram.html.erb
similarity index 100%
rename from app/views/editions/diagram.html.erb
rename to app/views/legacy_editions/diagram.html.erb
diff --git a/app/views/editions/diff.html.erb b/app/views/legacy_editions/diff.html.erb
similarity index 100%
rename from app/views/editions/diff.html.erb
rename to app/views/legacy_editions/diff.html.erb
diff --git a/app/views/editions/new.html.erb b/app/views/legacy_editions/new.html.erb
similarity index 100%
rename from app/views/editions/new.html.erb
rename to app/views/legacy_editions/new.html.erb
diff --git a/app/views/legacy_editions/show.html.erb b/app/views/legacy_editions/show.html.erb
new file mode 100644
index 000000000..b9dae652e
--- /dev/null
+++ b/app/views/legacy_editions/show.html.erb
@@ -0,0 +1,69 @@
+<% @edition = @resource %>
+ <%= render "shared/edition_header" %>
+
+ <% errors_hash = errors_to_display(@edition) %>
+ <% if !errors_hash.empty? %>
+
+ <% end %>
+
+
+
+ <% tabs_for(current_user, @edition).each do |tab| %>
+ - class="active"<% end %>>
+ <%= tab_link(tab, edition_path(@edition)) %>
+
+ <% end %>
+
+
+
+
+
+ <% if @edition.class.to_s == "SimpleSmartAnswerEdition" %>
+
+ View the <%= link_to "flow diagram (opens in a new tab)", diagram_edition_path(@edition), target: "_blank", rel: "noopener" %>
+
+ <% end %>
+
+ <%= render "link_check_reports/link_check_report", edition: @edition, report: @edition.latest_link_check_report %>
+
+ <% if @edition.class.to_s.in?(Edition::HAS_GOVSPEAK_FIELDS) %>
+
Govspeak help
+
+
+ <%= render "shared/govspeak_help" %>
+
+ <% end %>
+
+
+ <%= resource_form(@resource) do |f| %>
+
+ <%= render resource_fields(@resource), f: f %>
+
+
+ <%= edition_activities_fields(f, @resource) %>
+ <% end %>
+
+ <%= # cancel scheduled publishing doesn't require the edition to be saved when requesting an activity,
+ # because this action is triggered from a view where editing is not allowed.
+ edition_activities_forms(@resource, Edition::CANCEL_SCHEDULED_PUBLISHING_ACTION) %>
+
+ <% tabs.reject {|t| t.name == "edit"}.each do |tab| %>
+
+
+ <%= render :partial => "/shared/#{tab.name}", :locals => {:publication => @resource} %>
+
+
+ <% end %>
+
+
+<% content_for :page_title, "Editing #{@resource.title}" %>
+
diff --git a/config/features.rb b/config/features.rb
index 9fe4b2a30..357a1fde6 100644
--- a/config/features.rb
+++ b/config/features.rb
@@ -12,4 +12,8 @@
feature :design_system_publications_filter,
default: false,
description: "Update the publications page to use the GOV.UK Design System"
+
+ feature :design_system_edit,
+ default: false,
+ description: "Update the publications edit page to use the GOV.UK Design System"
end
diff --git a/config/routes.rb b/config/routes.rb
index 3194bb031..342a257a5 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -16,14 +16,20 @@
resources :artefacts, only: %i[new create update]
- resources :editions do
+ constraints FeatureConstraint.new("design_system_edit") do
+ resources :editions, only: %i[show index]
+ end
+
+ get "editions/:id" => "legacy_editions#show"
+
+ resources :editions, controller: "legacy_editions" do
member do
get "diff"
get "metadata"
get "history"
get "admin"
- get "tagging", to: "editions#linking"
- get "related_external_links", to: "editions#linking"
+ get "tagging", to: "legacy_editions#linking"
+ get "related_external_links", to: "legacy_editions#linking"
get "unpublish"
get "diagram"
post "duplicate"
@@ -33,7 +39,7 @@
post "progress"
put "review"
post "skip_fact_check",
- to: "editions#progress",
+ to: "legacy_editions#progress",
edition: {
activity: {
request_type: "skip_fact_check",
@@ -66,6 +72,7 @@
constraints FeatureConstraint.new("design_system_publications_filter") do
root to: "root#index"
end
+
# The below "as: nil" is required to avoid a name clash with the constrained route, above, which causes an error
root to: "legacy_root#index", as: nil
diff --git a/test/functional/editions_controller_test.rb b/test/functional/editions_controller_test.rb
index a3f4c61ae..6fee5ee07 100644
--- a/test/functional/editions_controller_test.rb
+++ b/test/functional/editions_controller_test.rb
@@ -7,76 +7,6 @@ class EditionsControllerTest < ActionController::TestCase
stub_holidays_used_by_fact_check
end
- context "#create" do
- setup do
- @artefact = FactoryBot.create(
- :artefact,
- slug: "test",
- kind: "answer",
- name: "test",
- owning_app: "publisher",
- )
- end
-
- should "report publication counts on creation" do
- Publisher::Application.edition_state_count_reporter.expects(:report)
- post :create,
- params: {
- "edition" => {
- "kind" => "answer",
- "panopticon_id" => @artefact.id,
- "title" => "a title",
- },
- }
- end
-
- should "update publishing API upon creation of new edition" do
- UpdateWorker.expects(:perform_async)
-
- post :create,
- params: {
- "edition" => {
- "kind" => "answer",
- "panopticon_id" => @artefact.id,
- "title" => "a title",
- },
- }
- end
-
- should "render the lgsl and lgil edit form successfully if creation fails" do
- lgsl_code = 800
- FactoryBot.create(
- :local_service,
- lgsl_code:,
- )
- artefact = FactoryBot.create(:artefact)
-
- post :create,
- params: {
- "edition" => {
- "kind" => "local_transaction",
- "lgsl_code" => lgsl_code,
- "lgil_code" => 1,
- "panopticon_id" => artefact.id,
- "title" => "a title",
- },
- }
- assert_equal "302", response.code
-
- post :create,
- params: {
- "edition" => {
- "kind" => "local_transaction",
- "lgsl_code" => lgsl_code + 1,
- "lgil_code" => 1,
- "panopticon_id" => artefact.id,
- "title" => "a title",
- },
- }
- assert_equal "200", response.code
- end
- end
-
context "#template_folder_for" do
should "be able to create a view path for a given publication" do
l = LocalTransactionEdition.new
@@ -86,936 +16,6 @@ class EditionsControllerTest < ActionController::TestCase
end
end
- context "#duplicate" do
- context "Standard behaviour" do
- setup do
- @guide = FactoryBot.create(:guide_edition, panopticon_id: FactoryBot.create(:artefact).id)
- EditionDuplicator.any_instance.expects(:duplicate).returns(true)
- EditionDuplicator.any_instance.expects(:new_edition).returns(@guide)
- end
-
- should "delegate complexity of duplication to appropriate collaborator" do
- post :duplicate, params: { id: @guide.id }
- assert_response :found
- assert_equal "New edition created", flash[:success]
- end
-
- should "update the publishing API upon duplication of an edition" do
- UpdateWorker.expects(:perform_async).with(@guide.id.to_s)
- post :duplicate, params: { id: @guide.id }
- end
- end
-
- context "Welsh editors" do
- setup { login_as_welsh_editor }
-
- should "be able to duplicate Welsh editions" do
- edition = FactoryBot.create(:guide_edition, :published, :welsh)
- artefact = edition.artefact
-
- post :duplicate, params: { id: edition.id }
-
- assert_response :found
- assert_redirected_to edition_path(artefact.latest_edition)
- assert_not_equal edition, artefact.latest_edition
- assert_equal "New edition created", flash[:success]
- end
-
- should "not be able to duplicate non-Welsh editions" do
- edition = FactoryBot.create(:guide_edition, :published)
- artefact = edition.artefact
-
- post :duplicate, params: { id: edition.id }
-
- assert_response :found
- assert_redirected_to edition_path(edition)
- assert_equal edition, artefact.latest_edition
- assert_equal "You do not have correct editor permissions for this action.", flash[:danger]
- end
- end
- end
-
- context "#progress" do
- setup do
- @guide = FactoryBot.create(:guide_edition, panopticon_id: FactoryBot.create(:artefact).id)
- end
-
- should "update status via progress and redirect to parent" do
- EditionProgressor.any_instance.expects(:progress).returns(true)
- EditionProgressor.any_instance.expects(:status_message).returns("Guide updated")
-
- post :progress,
- params: {
- id: @guide.id,
- edition: {
- activity: {
- "request_type" => "send_fact_check",
- "comment" => "Blah",
- "email_addresses" => "user@example.com",
- "customised_message" => "Hello",
- },
- },
- }
-
- assert_redirected_to controller: "editions", action: "show", id: @guide.id
- assert_equal "Guide updated", flash[:success]
- end
-
- should "set an error message if it couldn't progress an edition" do
- EditionProgressor.any_instance.expects(:progress).returns(false)
- EditionProgressor.any_instance.expects(:status_message).returns("I failed")
-
- post :progress,
- params: {
- id: @guide.id.to_s,
- edition: {
- activity: {
- "request_type" => "send_fact_check",
- "email_addresses" => "",
- },
- },
- }
- assert_equal "I failed", flash[:danger]
- end
-
- should "squash multiparameter attributes into a time field that has time-zone information" do
- EditionProgressor.any_instance.expects(:progress).with(has_entry("publish_at", Time.zone.local(2014, 3, 4, 14, 47)))
-
- publish_at_params = {
- "publish_at(1i)" => "2014",
- "publish_at(2i)" => "3",
- "publish_at(3i)" => "4",
- "publish_at(4i)" => "14",
- "publish_at(5i)" => "47",
- }
-
- post :progress,
- params: {
- id: @guide.id.to_s,
- edition: {
- activity: {
- "request_type" => "schedule_for_publishing",
- }.merge(publish_at_params),
- },
- }
- end
-
- context "Welsh editors" do
- setup do
- login_as_welsh_editor
- @artefact = FactoryBot.create(:artefact)
- @edition = FactoryBot.create(:guide_edition, :scheduled_for_publishing, panopticon_id: @artefact.id)
- @welsh_edition = FactoryBot.create(:guide_edition, :scheduled_for_publishing, :welsh)
- end
-
- should "be able to cancel scheduled publishing for Welsh editions" do
- ScheduledPublisher.expects(:cancel_scheduled_publishing).with(@welsh_edition.id.to_s).once
-
- post(
- :progress,
- params: {
- id: @welsh_edition.id,
- commit: "Cancel scheduled publishing",
- edition: {
- activity: {
- request_type: "cancel_scheduled_publishing",
- comment: "cancel this!",
- },
- },
- },
- )
-
- assert_redirected_to edition_path(@welsh_edition)
- assert_equal flash[:success], "Guide updated"
- @welsh_edition.reload
- assert_equal @welsh_edition.state, "ready"
- end
-
- should "not be able to cancel scheduled publishing for non-Welsh editions" do
- ScheduledPublisher.expects(:cancel_scheduled_publishing).with(@edition.id.to_s).never
-
- post(
- :progress,
- params: {
- id: @edition.id,
- commit: "Cancel scheduled publishing",
- edition: {
- activity: {
- request_type: "cancel_scheduled_publishing",
- comment: "cancel this!",
- },
- },
- },
- )
-
- assert_redirected_to edition_path(@edition)
- assert_equal flash[:danger], "You do not have correct editor permissions for this action."
- @edition.reload
- assert_equal @edition.state, "scheduled_for_publishing"
- end
-
- should "be able to skip fact checks for Welsh editions" do
- @welsh_edition.update!(state: "fact_check")
-
- post :progress,
- params: {
- id: @welsh_edition.id,
- edition: {
- activity: {
- "request_type" => "skip_fact_check",
- "comment" => "Fact check skipped by request.",
- },
- },
- }
-
- assert_redirected_to edition_path(@welsh_edition)
- @welsh_edition.reload
- assert_equal flash[:success], "The fact check has been skipped for this publication."
- assert_equal @welsh_edition.state, "ready"
- end
-
- should "not be able to skip fact checks for non-Welsh editions" do
- @edition.update!(state: "fact_check")
-
- post :progress,
- params: {
- id: @edition.id,
- edition: {
- activity: {
- request_type: "skip_fact_check",
- comment: "Fact check skipped by request.",
- },
- },
- }
-
- assert_redirected_to edition_path(@edition)
- @edition.reload
- assert_equal @edition.state, "fact_check"
- assert_equal flash[:danger], "You do not have correct editor permissions for this action."
- end
- end
- end
-
- context "#update" do
- setup do
- @guide = FactoryBot.create(:guide_edition)
- end
-
- should "update assignment" do
- bob = FactoryBot.create(:user, :govuk_editor)
-
- post :update,
- params: {
- id: @guide.id,
- edition: { assigned_to_id: bob.id },
- }
-
- @guide.reload
- assert_equal bob, @guide.assigned_to
- end
-
- should "clear assignment if no assignment is passed" do
- post :update,
- params: {
- id: @guide.id,
- edition: {},
- }
-
- @guide.reload
- assert_nil @guide.assigned_to
- end
-
- should "not create a new action if the assignment is unchanged" do
- bob = FactoryBot.create(:user, :govuk_editor)
- @user.assign(@guide, bob)
-
- post :update,
- params: {
- id: @guide.id,
- edition: { assigned_to_id: bob.id },
- }
-
- @guide.reload
- assert_equal 1, (@guide.actions.count { |a| a.request_type == Action::ASSIGN })
- end
-
- should "show the edit page again if updating fails" do
- Edition.expects(:find).returns(@guide)
- @guide.stubs(:update).returns(false)
- @guide.errors.add(:title, "values")
-
- post :update,
- params: {
- id: @guide.id,
- edition: { assigned_to_id: "" },
- }
- assert_response :ok
- end
-
- should "save the edition changes while performing an activity" do
- post :update,
- params: {
- id: @guide.id,
- commit: "Send to 2nd pair of eyes",
- edition: {
- title: "Updated title",
- activity_request_review_attributes: {
- request_type: "request_review",
- comment: "Please review the updated title",
- },
- },
- }
-
- @guide.reload
- assert_equal "Updated title", @guide.title
- assert_equal "in_review", @guide.state
- assert_equal "Please review the updated title", @guide.actions.last.comment
- end
-
- should "update the publishing API on successful update" do
- UpdateWorker.expects(:perform_async).with(@guide.id.to_s, false)
-
- post :update,
- params: {
- id: @guide.id,
- edition: {
- title: "Updated title",
- },
- }
- end
-
- context "Welsh editors" do
- setup do
- login_as_welsh_editor
- @edition = FactoryBot.create(:guide_edition, :ready)
- @welsh_edition = FactoryBot.create(:guide_edition, :ready, :welsh)
- end
-
- should "be able to update Welsh editions" do
- post :update,
- params: {
- id: @welsh_edition.id,
- edition: {
- title: "Updated title",
- },
- }
-
- assert_redirected_to edition_path(@welsh_edition)
- @welsh_edition.reload
- assert_equal @welsh_edition.title, "Updated title"
- end
-
- should "not be able to update non-Welsh editions" do
- post :update,
- params: {
- id: @edition.id,
- edition: {
- title: "Updated title",
- },
- }
-
- assert_redirected_to edition_path(@edition)
- @edition.reload
- assert_not_equal @edition.title, "Updated title"
- assert_equal "You do not have correct editor permissions for this action.", flash[:danger]
- end
-
- should "be able to assign users to Welsh editions" do
- assignees = [FactoryBot.create(:user, :welsh_editor), FactoryBot.create(:user, :govuk_editor)]
- assignees.each do |assignee|
- post :update,
- params: {
- id: @welsh_edition.id,
- edition: {
- assigned_to_id: assignee.id,
- },
- }
-
- assert_redirected_to edition_path(@welsh_edition)
- @welsh_edition.reload
- assert_equal @welsh_edition.assigned_to, assignee
- end
- end
-
- should "not be able to assign users to non-Welsh editions" do
- assignees = [FactoryBot.create(:user, :welsh_editor), FactoryBot.create(:user, :govuk_editor)]
- assignees.each do |assignee|
- post :update,
- params: {
- id: @edition.id,
- edition: {
- assigned_to_id: assignee.id,
- },
- }
-
- assert_redirected_to edition_path(@edition)
- assert_equal flash[:danger], "You do not have correct editor permissions for this action."
- @edition.reload
- assert_nil @edition.assigned_to
- end
- end
-
- should "not be able to be assigned to non-Welsh editions" do
- login_as_govuk_editor
- assignee = FactoryBot.create(:user, :welsh_editor)
-
- post :update,
- params: {
- id: @edition.id,
- edition: {
- assigned_to_id: assignee.id,
- },
- }
-
- assert_redirected_to edition_path(@edition)
- assert_equal flash[:danger], "Chosen assignee does not have correct editor permissions."
- @edition.reload
- assert_nil @edition.assigned_to
- end
-
- should "be able to schedule publishing for Welsh editions" do
- ScheduledPublisher.expects(:enqueue).with(@welsh_edition)
-
- post(
- :update,
- params: {
- id: @welsh_edition.id,
- edition: {
- activity_schedule_for_publishing_attributes: {
- request_type: "schedule_for_publishing",
- "publish_at(1i)" => "2100",
- "publish_at(2i)" => "12",
- "publish_at(3i)" => "21",
- "publish_at(4i)" => "10",
- "publish_at(5i)" => "35",
- },
- },
- commit: "Schedule for publishing",
- },
- )
-
- assert_redirected_to edition_path(@welsh_edition)
- @welsh_edition.reload
- assert_equal @welsh_edition.state, "scheduled_for_publishing"
- assert_equal flash[:notice], "Guide edition was successfully updated."
- end
-
- should "not be able to schedule publishing for non-Welsh editions" do
- ScheduledPublisher.expects(:enqueue).with(@edition).never
-
- post(
- :update,
- params: {
- id: @edition.id,
- edition: {
- activity_schedule_for_publishing_attributes: {
- request_type: "schedule_for_publishing",
- "publish_at(1i)" => "2020",
- "publish_at(2i)" => "12",
- "publish_at(3i)" => "21",
- "publish_at(4i)" => "10",
- "publish_at(5i)" => "35",
- },
- },
- commit: "Schedule for publishing",
- },
- )
-
- assert_redirected_to edition_path(@edition)
- @edition.reload
- assert_equal @edition.state, "ready"
- assert_equal flash[:danger], "You do not have correct editor permissions for this action."
- end
-
- should "be able to publish a Welsh edition" do
- UpdateWorker.expects(:perform_async).with(@welsh_edition.id.to_s, true)
-
- post :update,
- params: {
- id: @welsh_edition.id,
- commit: "Send to publish",
- edition: {
- activity_publish_attributes: {
- request_type: "publish",
- comment: "Publish this!",
- },
- },
- }
-
- assert_redirected_to edition_path(@welsh_edition)
- @welsh_edition.reload
- assert_equal @welsh_edition.state, "published"
- assert_equal flash[:success], "Guide updated"
- end
-
- should "not be able to publish a non-Welsh edition" do
- UpdateWorker.expects(:perform_async).with(@edition.id.to_s, true).never
-
- post :update,
- params: {
- id: @edition.id,
- commit: "Send to publish",
- edition: {
- activity_publish_attributes: {
- request_type: "publish",
- comment: "Publish this!",
- },
- },
- }
-
- assert_redirected_to edition_path(@edition)
- @edition.reload
- assert_equal @edition.state, "ready"
- assert_equal flash[:danger], "You do not have correct editor permissions for this action."
- end
-
- should "be able to approve a review for Welsh editions" do
- welsh_edition = FactoryBot.create(:guide_edition, :in_review, :welsh)
-
- UpdateWorker.expects(:perform_async).with(welsh_edition.id.to_s, false)
-
- post :update,
- params: {
- id: welsh_edition.id,
- commit: "No changes needed",
- edition: {
- activity_approve_review_attributes: {
- request_type: :approve_review,
- comment: "LGTM",
- },
- },
- }
-
- assert_redirected_to edition_path(welsh_edition)
- welsh_edition.reload
- assert_equal welsh_edition.state, "ready"
- assert_equal flash[:success], "Guide updated"
- end
-
- should "not be able to approve a review for non-Welsh editions" do
- edition = FactoryBot.create(:guide_edition, :in_review)
-
- UpdateWorker.expects(:perform_async).with(edition.id.to_s, false).never
-
- post :update,
- params: {
- id: edition.id,
- commit: "No changes needed",
- edition: {
- activity_approve_review_attributes: {
- request_type: :approve_review,
- comment: "LGTM",
- },
- },
- }
-
- assert_redirected_to edition_path(edition)
- edition.reload
- assert_equal edition.state, "in_review"
- assert_equal flash[:danger], "You do not have correct editor permissions for this action."
- end
-
- should "be able to request a review for Welsh editions" do
- welsh_edition = FactoryBot.create(:guide_edition, :draft, :welsh)
-
- UpdateWorker.expects(:perform_async).with(welsh_edition.id.to_s, false)
-
- post :update,
- params: {
- id: welsh_edition.id,
- commit: "Send to 2nd pair of eyes",
- edition: {
- activity_request_review_attributes: {
- request_type: :request_review,
- comment: "Please review",
- },
- },
- }
-
- assert_redirected_to edition_path(welsh_edition)
- welsh_edition.reload
- assert_equal welsh_edition.state, "in_review"
- assert_equal flash[:success], "Guide updated"
- end
-
- should "not be able to request a review for non-Welsh editions" do
- edition = FactoryBot.create(:guide_edition, :draft)
-
- UpdateWorker.expects(:perform_async).with(edition.id.to_s, false).never
-
- post :update,
- params: {
- id: edition.id,
- commit: "Send to 2nd pair of eyes",
- edition: {
- activity_request_review_attributes: {
- request_type: :request_review,
- comment: "Please review",
- },
- },
- }
-
- assert_redirected_to edition_path(edition)
- edition.reload
- assert_equal edition.state, "draft"
- assert_equal flash[:danger], "You do not have correct editor permissions for this action."
- end
-
- should "be able to request amendments to a review for Welsh editions" do
- UpdateWorker.expects(:perform_async).with(@welsh_edition.id.to_s, false)
-
- post :update,
- params: {
- id: @welsh_edition.id,
- commit: "Request amendments",
- edition: {
- activity_request_amendments_attributes: {
- request_type: :request_amendments,
- comment: "Suggestion here",
- },
- },
- }
-
- assert_redirected_to edition_path(@welsh_edition)
- @welsh_edition.reload
- assert_equal @welsh_edition.state, "amends_needed"
- assert_equal flash[:success], "Guide updated"
- end
-
- should "not be able to request amendments to a review for non-Welsh editions" do
- UpdateWorker.expects(:perform_async).with(@edition.id.to_s, false).never
-
- post :update,
- params: {
- id: @edition.id,
- commit: "Request amendments",
- edition: {
- activity_request_amendments_attributes: {
- request_type: :request_amendments,
- comment: "Suggestion here",
- },
- },
- }
-
- assert_redirected_to edition_path(@edition)
- @edition.reload
- assert_equal @edition.state, "ready"
- assert_equal flash[:danger], "You do not have correct editor permissions for this action."
- end
-
- should "be able to request a fact check for Welsh editions" do
- UpdateWorker.expects(:perform_async).with(@welsh_edition.id.to_s, false)
-
- post :update,
- params: {
- id: @welsh_edition.id,
- commit: "Send to Fact check",
- edition: {
- activity_send_fact_check_attributes: {
- request_type: "send_fact_check",
- comment: "Blah",
- email_addresses: "user@example.com",
- customised_message: "Hello",
- },
- },
- }
-
- assert_redirected_to edition_path(@welsh_edition)
- @welsh_edition.reload
- assert_equal flash[:success], "Guide updated"
- assert_equal @welsh_edition.state, "fact_check"
- end
-
- should "not be able to request a fact check for non-Welsh editions" do
- UpdateWorker.expects(:perform_async).with(@edition.id.to_s, false).never
-
- post :update,
- params: {
- id: @edition.id,
- commit: "Send to Fact check",
- edition: {
- activity_send_fact_check_attributes: {
- request_type: "send_fact_check",
- comment: "Blah",
- email_addresses: "user@example.com",
- customised_message: "Hello",
- },
- },
- }
-
- assert_redirected_to edition_path(@edition)
- @edition.reload
- assert_equal @edition.state, "ready"
- assert_equal flash[:danger], "You do not have correct editor permissions for this action."
- end
-
- should "be able to resend fact check emails for Welsh editions" do
- @welsh_edition.update!(state: "fact_check")
-
- previous_action = Action.new(
- request_type: "send_fact_check",
- email_addresses: "user@example.com",
- comment: "Blah",
- customised_message: "Hello",
- edition: @welsh_edition,
- )
- Edition.any_instance.stubs(:latest_status_action).returns(previous_action)
-
- UpdateWorker.expects(:perform_async).with(@welsh_edition.id.to_s, false)
-
- post :update,
- params: {
- id: @welsh_edition.id,
- commit: "Resend fact check email",
- edition: {
- activity_resend_fact_check_attributes: {
- request_type: "resend_fact_check",
- comment: "Blah",
- email_addresses: "user@example.com",
- customised_message: "Hello",
- },
- },
- }
-
- assert_redirected_to edition_path(@welsh_edition)
- @welsh_edition.reload
- assert_equal flash[:success], "Guide updated"
- assert_equal @welsh_edition.state, "fact_check"
- end
-
- should "not be able to resend fact check emails for non-Welsh editions" do
- @edition.update!(state: "fact_check")
- UpdateWorker.expects(:perform_async).with(@edition.id.to_s, false).never
-
- post :update,
- params: {
- id: @edition.id,
- commit: "Resend fact check email",
- edition: {
- activity_resend_fact_check_attributes: {
- request_type: "resend_fact_check",
- comment: "Blah",
- email_addresses: "user@example.com",
- customised_message: "Hello",
- },
- },
- }
-
- assert_redirected_to edition_path(@edition)
- @edition.reload
- assert_equal @edition.state, "fact_check"
- assert_equal flash[:danger], "You do not have correct editor permissions for this action."
- end
-
- should "be able to approve a fact check for Welsh editions" do
- UpdateWorker.expects(:perform_async).with(@welsh_edition.id.to_s, false)
-
- post :update,
- params: {
- id: @welsh_edition.id,
- commit: "Approve Fact check",
- edition: {
- activity_approve_fact_check_attributes: {
- request_type: "approve_fact_check",
- comment: "lgtm",
- },
- },
- }
-
- assert_redirected_to edition_path(@welsh_edition)
- @welsh_edition.reload
- assert_equal flash[:notice], "Guide edition was successfully updated."
- assert_equal @welsh_edition.state, "ready"
- end
-
- should "not be able to approve a fact check for non-Welsh editions" do
- @edition.update!(state: "fact_check_received")
- UpdateWorker.expects(:perform_async).with(@edition.id.to_s, false).never
-
- post :update,
- params: {
- id: @edition.id,
- commit: "Approve Fact check",
- edition: {
- activity_approve_fact_check_attributes: {
- request_type: "approve_fact_check",
- comment: "lgtm",
- },
- },
- }
-
- assert_redirected_to edition_path(@edition)
- @edition.reload
- assert_equal @edition.state, "fact_check_received"
- assert_equal flash[:danger], "You do not have correct editor permissions for this action."
- end
- end
- end
-
- context "#review" do
- setup do
- artefact = FactoryBot.create(:artefact)
-
- @guide = FactoryBot.create(
- :guide_edition,
- state: "in_review",
- review_requested_at: Time.zone.now,
- panopticon_id: artefact.id,
- )
- end
-
- should "update the reviewer" do
- bob = FactoryBot.create(:user, name: "bob")
-
- put :review,
- params: {
- id: @guide.id,
- edition: { reviewer: bob.name },
- }
-
- @guide.reload
- assert_equal bob.name, @guide.reviewer
- end
-
- should "not be able to update the reviewer when edition is scheduled for publishing" do
- bob = FactoryBot.create(:user, name: "bob")
- edition = FactoryBot.create(:edition, :scheduled_for_publishing)
-
- put :review,
- params: {
- id: edition.id,
- edition: { reviewer: bob.name },
- }
-
- assert_response(:found)
- assert_equal "Something went wrong when attempting to claim 2i.", flash[:danger]
- end
-
- context "Welsh editors" do
- setup do
- @welsh_guide = FactoryBot.create(:guide_edition, :welsh, :in_review)
- login_as_welsh_editor
- @welsh_user = @user
- end
-
- should "be able to claim a review for Welsh editions" do
- put :review,
- params: {
- id: @welsh_guide.id,
- edition: { reviewer: @welsh_user.name },
- }
-
- assert_redirected_to edition_path(@welsh_guide)
- assert_equal "You are the reviewer of this guide.", flash[:success]
- @welsh_guide.reload
- assert_equal @welsh_user.name, @welsh_guide.reviewer
- end
-
- should "not be able to claim a review for non-Welsh editions" do
- put :review,
- params: {
- id: @guide.id,
- edition: { reviewer: @welsh_user.name },
- }
-
- assert_redirected_to edition_path(@guide)
- assert_equal "You do not have correct editor permissions for this action.", flash[:danger]
- @guide.reload
- assert_nil @guide.reviewer
- end
- end
- end
-
- context "#destroy" do
- setup do
- artefact1 = FactoryBot.create(
- :artefact,
- slug: "test",
- kind: "transaction",
- name: "test",
- owning_app: "publisher",
- )
- @transaction = TransactionEdition.create!(title: "test", slug: "test", panopticon_id: artefact1.id)
-
- artefact2 = FactoryBot.create(
- :artefact,
- slug: "test2",
- kind: "guide",
- name: "test",
- owning_app: "publisher",
- )
- @guide = GuideEdition.create!(title: "test", slug: "test2", panopticon_id: artefact2.id)
-
- stub_request(:delete, "#{Plek.find('arbiter')}/slugs/test").to_return(status: 200)
- end
-
- should "destroy transaction" do
- assert @transaction.can_destroy?
- assert_difference("TransactionEdition.count", -1) do
- delete :destroy, params: { id: @transaction.id }
- end
- assert_redirected_to root_path
- end
-
- should "can't destroy published transaction" do
- @transaction.state = "ready"
- stub_register_published_content
- @transaction.publish
- assert_not @transaction.can_destroy?
- @transaction.save!
- assert_difference("TransactionEdition.count", 0) do
- delete :destroy, params: { id: @transaction.id }
- end
- end
-
- should "destroy guide" do
- assert @guide.can_destroy?
- assert_difference("GuideEdition.count", -1) do
- delete :destroy, params: { id: @guide.id }
- end
- assert_redirected_to root_path
- end
-
- should "can't destroy published guide" do
- @guide.state = "ready"
- @guide.save!
- stub_register_published_content
- @guide.publish
- @guide.save!
- assert @guide.published?
- assert_not @guide.can_destroy?
-
- assert_difference("GuideEdition.count", 0) do
- delete :destroy, params: { id: @guide.id }
- end
- end
-
- context "Welsh editors" do
- setup do
- login_as_welsh_editor
- @welsh_guide = FactoryBot.create(:guide_edition, :welsh)
- end
-
- should "not be able to destroy non-Welsh editions" do
- assert_difference("GuideEdition.count", 0) do
- delete :destroy, params: { id: @guide.id }
- end
-
- assert_redirected_to edition_path(@guide)
- assert_equal "You do not have correct editor permissions for this action.", flash[:danger]
- end
-
- should "be able to destroy Welsh editions" do
- assert_difference("GuideEdition.count", -1) do
- delete :destroy, params: { id: @welsh_guide.id }
- end
-
- assert_redirected_to root_path
- assert_equal "Edition deleted", flash[:success]
- end
- end
- end
-
context "#index" do
should "editions index redirects to root" do
get :index
@@ -1046,262 +46,5 @@ class EditionsControllerTest < ActionController::TestCase
assert_response :success
assert_not_nil assigns(:resource)
end
-
- should "render a link to the diagram when edition is a simple smart answer" do
- simple_smart_answer_artefact = FactoryBot.create(
- :artefact,
- slug: "my-simple-smart-answer",
- kind: "guide",
- name: "test",
- owning_app: "publisher",
- )
- simple_smart_answer = SimpleSmartAnswerEdition.create!(
- title: "test ssa",
- panopticon_id: simple_smart_answer_artefact.id,
- )
-
- get :show, params: { id: simple_smart_answer.id }
-
- assert_select ".link-check-report p", { text: "View the flow diagram (opens in a new tab)" } do
- assert_select "a[href=?]", diagram_edition_path(simple_smart_answer).to_s,
- { count: 1, text: "flow diagram (opens in a new tab)" }
- end
- end
-
- should "not render a link to the diagram when edition is not a simple smart answer" do
- get :show, params: { id: @guide.id }
- assert_select "p", { count: 0, text: "View the flow diagram (opens in a new tab)" }
- end
- end
-
- context "#admin" do
- setup do
- @guide = FactoryBot.create(:guide_edition)
- end
-
- should "show the admin page for the edition" do
- get :admin, params: { id: @guide.id }
-
- assert_response :success
- end
-
- context "Welsh editors" do
- setup do
- login_as_welsh_editor
- @welsh_guide = FactoryBot.create(:guide_edition, :welsh)
- end
-
- should "be able to see the admin page for Welsh editions" do
- get :admin, params: { id: @welsh_guide.id }
-
- assert_response :success
- end
-
- should "not be able to see the admin page for non-Welsh editions" do
- get :admin, params: { id: @guide.id }
-
- assert_redirected_to edition_path(@guide)
- assert_equal "You do not have correct editor permissions for this action.", flash[:danger]
- end
- end
- end
-
- context "#diff" do
- should "we can diff the last edition" do
- first_edition = FactoryBot.create(:guide_edition, state: "published")
- second_edition = first_edition.build_clone(GuideEdition)
- second_edition.save!
- second_edition.reload
-
- get :diff, params: { id: second_edition.id }
- assert_response :success
- end
- end
-
- context "#unpublish" do
- setup do
- @guide = FactoryBot.create(:guide_edition, :published, panopticon_id: FactoryBot.create(:artefact).id)
- @redirect_url = "https://www.example.com/somewhere_else"
- end
-
- should "update publishing API upon unpublishing" do
- UnpublishService.expects(:call).with(@guide.artefact, @user, @redirect_url)
-
- post :process_unpublish,
- params: {
- id: @guide.id,
- redirect_url: @redirect_url,
- }
- end
-
- should "redirect and display success message after successful unpublish" do
- UnpublishService.stubs(:call).with(@guide.artefact, @user, @redirect_url).returns(true)
-
- post :process_unpublish,
- params: {
- id: @guide.id,
- redirect_url: @redirect_url,
- }
-
- assert_redirected_to root_path
- assert_equal "Content unpublished and redirected", flash[:notice]
- end
-
- should "not be able to unpublish with invalid redirect url" do
- post :process_unpublish,
- params: {
- id: @guide.id,
- redirect_url: "invalid redirect url",
- }
-
- assert_equal "Redirect path is invalid. Guide has not been unpublished.", flash[:danger]
- end
-
- should "alert if unable to unpublish" do
- UnpublishService.stubs(:call).with(@guide.artefact, @user, @redirect_url).returns(nil)
-
- post :process_unpublish,
- params: {
- id: @guide.id,
- redirect_url: @redirect_url,
- }
-
- assert_equal "Due to a service problem, the edition couldn't be unpublished", flash[:alert]
- end
-
- context "Welsh editors" do
- setup do
- login_as_welsh_editor
- @welsh_guide = FactoryBot.create(:guide_edition, :published, :welsh)
- end
-
- should "not be able to access the unpublish page of non-Welsh editions" do
- get :unpublish, params: { id: @guide.id }
-
- assert_redirected_to edition_path(@guide)
- assert_equal "You do not have permission to see this page.", flash[:danger]
- end
-
- should "not be able to access the unpublish page of Welsh editions" do
- get :unpublish, params: { id: @welsh_guide.id }
-
- assert_redirected_to edition_path(@welsh_guide)
- assert_equal "You do not have permission to see this page.", flash[:danger]
- end
-
- should "not be allowed to unpublish a Welsh edition" do
- UnpublishService.expects(:call).with(@welsh_guide.artefact, @user, @redirect_url).never
-
- post :process_unpublish,
- params: {
- id: @welsh_guide.id,
- redirect_url: @redirect_url,
- }
-
- assert_redirected_to edition_path(@welsh_guide)
- @welsh_guide.reload
- assert_equal @welsh_guide.state, "published"
- assert_equal "You do not have permission to see this page.", flash[:danger]
- end
-
- should "not be allowed to unpublish a non-Welsh edition" do
- UnpublishService.expects(:call).with(@guide.artefact, @user, @redirect_url).never
-
- post :process_unpublish,
- params: {
- id: @guide.id,
- redirect_url: @redirect_url,
- }
-
- assert_redirected_to edition_path(@guide)
- @guide.reload
- assert_equal @guide.state, "published"
- assert_equal "You do not have permission to see this page.", flash[:danger]
- end
- end
- end
-
- context "given a simple smart answer" do
- setup do
- @artefact = FactoryBot.create(:artefact, slug: "foo", name: "Foo", kind: "simple_smart_answer", owning_app: "publisher")
- @edition = FactoryBot.create(:simple_smart_answer_edition, body: "blah", state: "draft", slug: "foo", panopticon_id: @artefact.id)
- @edition.nodes.build(
- kind: "question",
- slug: "question-1",
- title: "Question One",
- options_attributes: [
- { label: "Option One", next_node: "outcome-1" },
- { label: "Option Two", next_node: "outcome-2" },
- ],
- )
- @edition.nodes.build(kind: "outcome", slug: "outcome-1", title: "Outcome One")
- @edition.nodes.build(kind: "outcome", slug: "outcome-2", title: "Outcome Two")
- @edition.save!
- end
-
- should "remove an option and node from simple smart answer in single request" do
- atts = {
- nodes_attributes: {
- "0" => {
- "id" => @edition.nodes.all[0].id,
- "options_attributes" => {
- "0" => { "id" => @edition.nodes.first.options.all[0].id },
- "1" => { "id" => @edition.nodes.first.options.all[1].id, "_destroy" => "1" },
- },
- },
- "1" => {
- "id" => @edition.nodes.all[1].id,
- },
- "2" => {
- "id" => @edition.nodes.all[2].id,
- "_destroy" => "1",
- },
- },
- }
- put :update,
- params: {
- id: @edition.id,
- edition: atts,
- }
- assert_redirected_to edition_path(@edition)
-
- @edition.reload
-
- assert_equal 2, @edition.nodes.count
- assert_equal 1, @edition.nodes.where(kind: "question").count
- assert_equal 1, @edition.nodes.where(kind: "outcome").count
-
- question = @edition.nodes.where(kind: "question").first
- assert_equal 1, question.options.count
- assert_equal "Option One", question.options.first.label
- end
- end
-
- context "#diagram" do
- context "given a simple smart answer exists" do
- setup do
- @artefact = FactoryBot.create(:artefact, slug: "foo", name: "Foo", kind: "simple_smart_answer", owning_app: "publisher")
- @edition = FactoryBot.create(:simple_smart_answer_edition, body: "blah", state: "draft", slug: "foo", panopticon_id: @artefact.id)
- @edition.save!
- end
-
- should "render a diagram page for it" do
- get :diagram, params: { id: @edition.id }
-
- assert_response :success
- assert_select "title", "Diagram for #{@edition.title} | GOV.UK Publisher"
- end
- end
-
- context "given a non-simple smart answer exists" do
- setup do
- @welsh_guide = FactoryBot.create(:guide_edition, :welsh, :in_review)
- end
-
- should "return a 404" do
- get :diagram, params: { id: @welsh_guide.id }
- assert_response :not_found
- end
- end
end
end
diff --git a/test/functional/legacy_editions_controller_test.rb b/test/functional/legacy_editions_controller_test.rb
new file mode 100644
index 000000000..79169c096
--- /dev/null
+++ b/test/functional/legacy_editions_controller_test.rb
@@ -0,0 +1,1307 @@
+require "test_helper"
+
+class LegacyEditionsControllerTest < ActionController::TestCase
+ setup do
+ login_as_stub_user
+ stub_linkables
+ stub_holidays_used_by_fact_check
+ end
+
+ context "#create" do
+ setup do
+ @artefact = FactoryBot.create(
+ :artefact,
+ slug: "test",
+ kind: "answer",
+ name: "test",
+ owning_app: "publisher",
+ )
+ end
+
+ should "report publication counts on creation" do
+ Publisher::Application.edition_state_count_reporter.expects(:report)
+ post :create,
+ params: {
+ "edition" => {
+ "kind" => "answer",
+ "panopticon_id" => @artefact.id,
+ "title" => "a title",
+ },
+ }
+ end
+
+ should "update publishing API upon creation of new edition" do
+ UpdateWorker.expects(:perform_async)
+
+ post :create,
+ params: {
+ "edition" => {
+ "kind" => "answer",
+ "panopticon_id" => @artefact.id,
+ "title" => "a title",
+ },
+ }
+ end
+
+ should "render the lgsl and lgil edit form successfully if creation fails" do
+ lgsl_code = 800
+ FactoryBot.create(
+ :local_service,
+ lgsl_code:,
+ )
+ artefact = FactoryBot.create(:artefact)
+
+ post :create,
+ params: {
+ "edition" => {
+ "kind" => "local_transaction",
+ "lgsl_code" => lgsl_code,
+ "lgil_code" => 1,
+ "panopticon_id" => artefact.id,
+ "title" => "a title",
+ },
+ }
+ assert_equal "302", response.code
+
+ post :create,
+ params: {
+ "edition" => {
+ "kind" => "local_transaction",
+ "lgsl_code" => lgsl_code + 1,
+ "lgil_code" => 1,
+ "panopticon_id" => artefact.id,
+ "title" => "a title",
+ },
+ }
+ assert_equal "200", response.code
+ end
+ end
+
+ context "#template_folder_for" do
+ should "be able to create a view path for a given publication" do
+ l = LocalTransactionEdition.new
+ assert_equal "app/views/local_transactions", @controller.template_folder_for(l)
+ g = GuideEdition.new
+ assert_equal "app/views/guides", @controller.template_folder_for(g)
+ end
+ end
+
+ context "#duplicate" do
+ context "Standard behaviour" do
+ setup do
+ @guide = FactoryBot.create(:guide_edition, panopticon_id: FactoryBot.create(:artefact).id)
+ EditionDuplicator.any_instance.expects(:duplicate).returns(true)
+ EditionDuplicator.any_instance.expects(:new_edition).returns(@guide)
+ end
+
+ should "delegate complexity of duplication to appropriate collaborator" do
+ post :duplicate, params: { id: @guide.id }
+ assert_response :found
+ assert_equal "New edition created", flash[:success]
+ end
+
+ should "update the publishing API upon duplication of an edition" do
+ UpdateWorker.expects(:perform_async).with(@guide.id.to_s)
+ post :duplicate, params: { id: @guide.id }
+ end
+ end
+
+ context "Welsh editors" do
+ setup { login_as_welsh_editor }
+
+ should "be able to duplicate Welsh editions" do
+ edition = FactoryBot.create(:guide_edition, :published, :welsh)
+ artefact = edition.artefact
+
+ post :duplicate, params: { id: edition.id }
+
+ assert_response :found
+ assert_redirected_to edition_path(artefact.latest_edition)
+ assert_not_equal edition, artefact.latest_edition
+ assert_equal "New edition created", flash[:success]
+ end
+
+ should "not be able to duplicate non-Welsh editions" do
+ edition = FactoryBot.create(:guide_edition, :published)
+ artefact = edition.artefact
+
+ post :duplicate, params: { id: edition.id }
+
+ assert_response :found
+ assert_redirected_to edition_path(edition)
+ assert_equal edition, artefact.latest_edition
+ assert_equal "You do not have correct editor permissions for this action.", flash[:danger]
+ end
+ end
+ end
+
+ context "#progress" do
+ setup do
+ @guide = FactoryBot.create(:guide_edition, panopticon_id: FactoryBot.create(:artefact).id)
+ end
+
+ should "update status via progress and redirect to parent" do
+ EditionProgressor.any_instance.expects(:progress).returns(true)
+ EditionProgressor.any_instance.expects(:status_message).returns("Guide updated")
+
+ post :progress,
+ params: {
+ id: @guide.id,
+ edition: {
+ activity: {
+ "request_type" => "send_fact_check",
+ "comment" => "Blah",
+ "email_addresses" => "user@example.com",
+ "customised_message" => "Hello",
+ },
+ },
+ }
+
+ assert_redirected_to controller: "editions", action: "show", id: @guide.id
+ assert_equal "Guide updated", flash[:success]
+ end
+
+ should "set an error message if it couldn't progress an edition" do
+ EditionProgressor.any_instance.expects(:progress).returns(false)
+ EditionProgressor.any_instance.expects(:status_message).returns("I failed")
+
+ post :progress,
+ params: {
+ id: @guide.id.to_s,
+ edition: {
+ activity: {
+ "request_type" => "send_fact_check",
+ "email_addresses" => "",
+ },
+ },
+ }
+ assert_equal "I failed", flash[:danger]
+ end
+
+ should "squash multiparameter attributes into a time field that has time-zone information" do
+ EditionProgressor.any_instance.expects(:progress).with(has_entry("publish_at", Time.zone.local(2014, 3, 4, 14, 47)))
+
+ publish_at_params = {
+ "publish_at(1i)" => "2014",
+ "publish_at(2i)" => "3",
+ "publish_at(3i)" => "4",
+ "publish_at(4i)" => "14",
+ "publish_at(5i)" => "47",
+ }
+
+ post :progress,
+ params: {
+ id: @guide.id.to_s,
+ edition: {
+ activity: {
+ "request_type" => "schedule_for_publishing",
+ }.merge(publish_at_params),
+ },
+ }
+ end
+
+ context "Welsh editors" do
+ setup do
+ login_as_welsh_editor
+ @artefact = FactoryBot.create(:artefact)
+ @edition = FactoryBot.create(:guide_edition, :scheduled_for_publishing, panopticon_id: @artefact.id)
+ @welsh_edition = FactoryBot.create(:guide_edition, :scheduled_for_publishing, :welsh)
+ end
+
+ should "be able to cancel scheduled publishing for Welsh editions" do
+ ScheduledPublisher.expects(:cancel_scheduled_publishing).with(@welsh_edition.id.to_s).once
+
+ post(
+ :progress,
+ params: {
+ id: @welsh_edition.id,
+ commit: "Cancel scheduled publishing",
+ edition: {
+ activity: {
+ request_type: "cancel_scheduled_publishing",
+ comment: "cancel this!",
+ },
+ },
+ },
+ )
+
+ assert_redirected_to edition_path(@welsh_edition)
+ assert_equal flash[:success], "Guide updated"
+ @welsh_edition.reload
+ assert_equal @welsh_edition.state, "ready"
+ end
+
+ should "not be able to cancel scheduled publishing for non-Welsh editions" do
+ ScheduledPublisher.expects(:cancel_scheduled_publishing).with(@edition.id.to_s).never
+
+ post(
+ :progress,
+ params: {
+ id: @edition.id,
+ commit: "Cancel scheduled publishing",
+ edition: {
+ activity: {
+ request_type: "cancel_scheduled_publishing",
+ comment: "cancel this!",
+ },
+ },
+ },
+ )
+
+ assert_redirected_to edition_path(@edition)
+ assert_equal flash[:danger], "You do not have correct editor permissions for this action."
+ @edition.reload
+ assert_equal @edition.state, "scheduled_for_publishing"
+ end
+
+ should "be able to skip fact checks for Welsh editions" do
+ @welsh_edition.update!(state: "fact_check")
+
+ post :progress,
+ params: {
+ id: @welsh_edition.id,
+ edition: {
+ activity: {
+ "request_type" => "skip_fact_check",
+ "comment" => "Fact check skipped by request.",
+ },
+ },
+ }
+
+ assert_redirected_to edition_path(@welsh_edition)
+ @welsh_edition.reload
+ assert_equal flash[:success], "The fact check has been skipped for this publication."
+ assert_equal @welsh_edition.state, "ready"
+ end
+
+ should "not be able to skip fact checks for non-Welsh editions" do
+ @edition.update!(state: "fact_check")
+
+ post :progress,
+ params: {
+ id: @edition.id,
+ edition: {
+ activity: {
+ request_type: "skip_fact_check",
+ comment: "Fact check skipped by request.",
+ },
+ },
+ }
+
+ assert_redirected_to edition_path(@edition)
+ @edition.reload
+ assert_equal @edition.state, "fact_check"
+ assert_equal flash[:danger], "You do not have correct editor permissions for this action."
+ end
+ end
+ end
+
+ context "#update" do
+ setup do
+ @guide = FactoryBot.create(:guide_edition)
+ end
+
+ should "update assignment" do
+ bob = FactoryBot.create(:user, :govuk_editor)
+
+ post :update,
+ params: {
+ id: @guide.id,
+ edition: { assigned_to_id: bob.id },
+ }
+
+ @guide.reload
+ assert_equal bob, @guide.assigned_to
+ end
+
+ should "clear assignment if no assignment is passed" do
+ post :update,
+ params: {
+ id: @guide.id,
+ edition: {},
+ }
+
+ @guide.reload
+ assert_nil @guide.assigned_to
+ end
+
+ should "not create a new action if the assignment is unchanged" do
+ bob = FactoryBot.create(:user, :govuk_editor)
+ @user.assign(@guide, bob)
+
+ post :update,
+ params: {
+ id: @guide.id,
+ edition: { assigned_to_id: bob.id },
+ }
+
+ @guide.reload
+ assert_equal 1, (@guide.actions.count { |a| a.request_type == Action::ASSIGN })
+ end
+
+ should "show the edit page again if updating fails" do
+ Edition.expects(:find).returns(@guide)
+ @guide.stubs(:update).returns(false)
+ @guide.errors.add(:title, "values")
+
+ post :update,
+ params: {
+ id: @guide.id,
+ edition: { assigned_to_id: "" },
+ }
+ assert_response :ok
+ end
+
+ should "save the edition changes while performing an activity" do
+ post :update,
+ params: {
+ id: @guide.id,
+ commit: "Send to 2nd pair of eyes",
+ edition: {
+ title: "Updated title",
+ activity_request_review_attributes: {
+ request_type: "request_review",
+ comment: "Please review the updated title",
+ },
+ },
+ }
+
+ @guide.reload
+ assert_equal "Updated title", @guide.title
+ assert_equal "in_review", @guide.state
+ assert_equal "Please review the updated title", @guide.actions.last.comment
+ end
+
+ should "update the publishing API on successful update" do
+ UpdateWorker.expects(:perform_async).with(@guide.id.to_s, false)
+
+ post :update,
+ params: {
+ id: @guide.id,
+ edition: {
+ title: "Updated title",
+ },
+ }
+ end
+
+ context "Welsh editors" do
+ setup do
+ login_as_welsh_editor
+ @edition = FactoryBot.create(:guide_edition, :ready)
+ @welsh_edition = FactoryBot.create(:guide_edition, :ready, :welsh)
+ end
+
+ should "be able to update Welsh editions" do
+ post :update,
+ params: {
+ id: @welsh_edition.id,
+ edition: {
+ title: "Updated title",
+ },
+ }
+
+ assert_redirected_to edition_path(@welsh_edition)
+ @welsh_edition.reload
+ assert_equal @welsh_edition.title, "Updated title"
+ end
+
+ should "not be able to update non-Welsh editions" do
+ post :update,
+ params: {
+ id: @edition.id,
+ edition: {
+ title: "Updated title",
+ },
+ }
+
+ assert_redirected_to edition_path(@edition)
+ @edition.reload
+ assert_not_equal @edition.title, "Updated title"
+ assert_equal "You do not have correct editor permissions for this action.", flash[:danger]
+ end
+
+ should "be able to assign users to Welsh editions" do
+ assignees = [FactoryBot.create(:user, :welsh_editor), FactoryBot.create(:user, :govuk_editor)]
+ assignees.each do |assignee|
+ post :update,
+ params: {
+ id: @welsh_edition.id,
+ edition: {
+ assigned_to_id: assignee.id,
+ },
+ }
+
+ assert_redirected_to edition_path(@welsh_edition)
+ @welsh_edition.reload
+ assert_equal @welsh_edition.assigned_to, assignee
+ end
+ end
+
+ should "not be able to assign users to non-Welsh editions" do
+ assignees = [FactoryBot.create(:user, :welsh_editor), FactoryBot.create(:user, :govuk_editor)]
+ assignees.each do |assignee|
+ post :update,
+ params: {
+ id: @edition.id,
+ edition: {
+ assigned_to_id: assignee.id,
+ },
+ }
+
+ assert_redirected_to edition_path(@edition)
+ assert_equal flash[:danger], "You do not have correct editor permissions for this action."
+ @edition.reload
+ assert_nil @edition.assigned_to
+ end
+ end
+
+ should "not be able to be assigned to non-Welsh editions" do
+ login_as_govuk_editor
+ assignee = FactoryBot.create(:user, :welsh_editor)
+
+ post :update,
+ params: {
+ id: @edition.id,
+ edition: {
+ assigned_to_id: assignee.id,
+ },
+ }
+
+ assert_redirected_to edition_path(@edition)
+ assert_equal flash[:danger], "Chosen assignee does not have correct editor permissions."
+ @edition.reload
+ assert_nil @edition.assigned_to
+ end
+
+ should "be able to schedule publishing for Welsh editions" do
+ ScheduledPublisher.expects(:enqueue).with(@welsh_edition)
+
+ post(
+ :update,
+ params: {
+ id: @welsh_edition.id,
+ edition: {
+ activity_schedule_for_publishing_attributes: {
+ request_type: "schedule_for_publishing",
+ "publish_at(1i)" => "2100",
+ "publish_at(2i)" => "12",
+ "publish_at(3i)" => "21",
+ "publish_at(4i)" => "10",
+ "publish_at(5i)" => "35",
+ },
+ },
+ commit: "Schedule for publishing",
+ },
+ )
+
+ assert_redirected_to edition_path(@welsh_edition)
+ @welsh_edition.reload
+ assert_equal @welsh_edition.state, "scheduled_for_publishing"
+ assert_equal flash[:notice], "Guide edition was successfully updated."
+ end
+
+ should "not be able to schedule publishing for non-Welsh editions" do
+ ScheduledPublisher.expects(:enqueue).with(@edition).never
+
+ post(
+ :update,
+ params: {
+ id: @edition.id,
+ edition: {
+ activity_schedule_for_publishing_attributes: {
+ request_type: "schedule_for_publishing",
+ "publish_at(1i)" => "2020",
+ "publish_at(2i)" => "12",
+ "publish_at(3i)" => "21",
+ "publish_at(4i)" => "10",
+ "publish_at(5i)" => "35",
+ },
+ },
+ commit: "Schedule for publishing",
+ },
+ )
+
+ assert_redirected_to edition_path(@edition)
+ @edition.reload
+ assert_equal @edition.state, "ready"
+ assert_equal flash[:danger], "You do not have correct editor permissions for this action."
+ end
+
+ should "be able to publish a Welsh edition" do
+ UpdateWorker.expects(:perform_async).with(@welsh_edition.id.to_s, true)
+
+ post :update,
+ params: {
+ id: @welsh_edition.id,
+ commit: "Send to publish",
+ edition: {
+ activity_publish_attributes: {
+ request_type: "publish",
+ comment: "Publish this!",
+ },
+ },
+ }
+
+ assert_redirected_to edition_path(@welsh_edition)
+ @welsh_edition.reload
+ assert_equal @welsh_edition.state, "published"
+ assert_equal flash[:success], "Guide updated"
+ end
+
+ should "not be able to publish a non-Welsh edition" do
+ UpdateWorker.expects(:perform_async).with(@edition.id.to_s, true).never
+
+ post :update,
+ params: {
+ id: @edition.id,
+ commit: "Send to publish",
+ edition: {
+ activity_publish_attributes: {
+ request_type: "publish",
+ comment: "Publish this!",
+ },
+ },
+ }
+
+ assert_redirected_to edition_path(@edition)
+ @edition.reload
+ assert_equal @edition.state, "ready"
+ assert_equal flash[:danger], "You do not have correct editor permissions for this action."
+ end
+
+ should "be able to approve a review for Welsh editions" do
+ welsh_edition = FactoryBot.create(:guide_edition, :in_review, :welsh)
+
+ UpdateWorker.expects(:perform_async).with(welsh_edition.id.to_s, false)
+
+ post :update,
+ params: {
+ id: welsh_edition.id,
+ commit: "No changes needed",
+ edition: {
+ activity_approve_review_attributes: {
+ request_type: :approve_review,
+ comment: "LGTM",
+ },
+ },
+ }
+
+ assert_redirected_to edition_path(welsh_edition)
+ welsh_edition.reload
+ assert_equal welsh_edition.state, "ready"
+ assert_equal flash[:success], "Guide updated"
+ end
+
+ should "not be able to approve a review for non-Welsh editions" do
+ edition = FactoryBot.create(:guide_edition, :in_review)
+
+ UpdateWorker.expects(:perform_async).with(edition.id.to_s, false).never
+
+ post :update,
+ params: {
+ id: edition.id,
+ commit: "No changes needed",
+ edition: {
+ activity_approve_review_attributes: {
+ request_type: :approve_review,
+ comment: "LGTM",
+ },
+ },
+ }
+
+ assert_redirected_to edition_path(edition)
+ edition.reload
+ assert_equal edition.state, "in_review"
+ assert_equal flash[:danger], "You do not have correct editor permissions for this action."
+ end
+
+ should "be able to request a review for Welsh editions" do
+ welsh_edition = FactoryBot.create(:guide_edition, :draft, :welsh)
+
+ UpdateWorker.expects(:perform_async).with(welsh_edition.id.to_s, false)
+
+ post :update,
+ params: {
+ id: welsh_edition.id,
+ commit: "Send to 2nd pair of eyes",
+ edition: {
+ activity_request_review_attributes: {
+ request_type: :request_review,
+ comment: "Please review",
+ },
+ },
+ }
+
+ assert_redirected_to edition_path(welsh_edition)
+ welsh_edition.reload
+ assert_equal welsh_edition.state, "in_review"
+ assert_equal flash[:success], "Guide updated"
+ end
+
+ should "not be able to request a review for non-Welsh editions" do
+ edition = FactoryBot.create(:guide_edition, :draft)
+
+ UpdateWorker.expects(:perform_async).with(edition.id.to_s, false).never
+
+ post :update,
+ params: {
+ id: edition.id,
+ commit: "Send to 2nd pair of eyes",
+ edition: {
+ activity_request_review_attributes: {
+ request_type: :request_review,
+ comment: "Please review",
+ },
+ },
+ }
+
+ assert_redirected_to edition_path(edition)
+ edition.reload
+ assert_equal edition.state, "draft"
+ assert_equal flash[:danger], "You do not have correct editor permissions for this action."
+ end
+
+ should "be able to request amendments to a review for Welsh editions" do
+ UpdateWorker.expects(:perform_async).with(@welsh_edition.id.to_s, false)
+
+ post :update,
+ params: {
+ id: @welsh_edition.id,
+ commit: "Request amendments",
+ edition: {
+ activity_request_amendments_attributes: {
+ request_type: :request_amendments,
+ comment: "Suggestion here",
+ },
+ },
+ }
+
+ assert_redirected_to edition_path(@welsh_edition)
+ @welsh_edition.reload
+ assert_equal @welsh_edition.state, "amends_needed"
+ assert_equal flash[:success], "Guide updated"
+ end
+
+ should "not be able to request amendments to a review for non-Welsh editions" do
+ UpdateWorker.expects(:perform_async).with(@edition.id.to_s, false).never
+
+ post :update,
+ params: {
+ id: @edition.id,
+ commit: "Request amendments",
+ edition: {
+ activity_request_amendments_attributes: {
+ request_type: :request_amendments,
+ comment: "Suggestion here",
+ },
+ },
+ }
+
+ assert_redirected_to edition_path(@edition)
+ @edition.reload
+ assert_equal @edition.state, "ready"
+ assert_equal flash[:danger], "You do not have correct editor permissions for this action."
+ end
+
+ should "be able to request a fact check for Welsh editions" do
+ UpdateWorker.expects(:perform_async).with(@welsh_edition.id.to_s, false)
+
+ post :update,
+ params: {
+ id: @welsh_edition.id,
+ commit: "Send to Fact check",
+ edition: {
+ activity_send_fact_check_attributes: {
+ request_type: "send_fact_check",
+ comment: "Blah",
+ email_addresses: "user@example.com",
+ customised_message: "Hello",
+ },
+ },
+ }
+
+ assert_redirected_to edition_path(@welsh_edition)
+ @welsh_edition.reload
+ assert_equal flash[:success], "Guide updated"
+ assert_equal @welsh_edition.state, "fact_check"
+ end
+
+ should "not be able to request a fact check for non-Welsh editions" do
+ UpdateWorker.expects(:perform_async).with(@edition.id.to_s, false).never
+
+ post :update,
+ params: {
+ id: @edition.id,
+ commit: "Send to Fact check",
+ edition: {
+ activity_send_fact_check_attributes: {
+ request_type: "send_fact_check",
+ comment: "Blah",
+ email_addresses: "user@example.com",
+ customised_message: "Hello",
+ },
+ },
+ }
+
+ assert_redirected_to edition_path(@edition)
+ @edition.reload
+ assert_equal @edition.state, "ready"
+ assert_equal flash[:danger], "You do not have correct editor permissions for this action."
+ end
+
+ should "be able to resend fact check emails for Welsh editions" do
+ @welsh_edition.update!(state: "fact_check")
+
+ previous_action = Action.new(
+ request_type: "send_fact_check",
+ email_addresses: "user@example.com",
+ comment: "Blah",
+ customised_message: "Hello",
+ edition: @welsh_edition,
+ )
+ Edition.any_instance.stubs(:latest_status_action).returns(previous_action)
+
+ UpdateWorker.expects(:perform_async).with(@welsh_edition.id.to_s, false)
+
+ post :update,
+ params: {
+ id: @welsh_edition.id,
+ commit: "Resend fact check email",
+ edition: {
+ activity_resend_fact_check_attributes: {
+ request_type: "resend_fact_check",
+ comment: "Blah",
+ email_addresses: "user@example.com",
+ customised_message: "Hello",
+ },
+ },
+ }
+
+ assert_redirected_to edition_path(@welsh_edition)
+ @welsh_edition.reload
+ assert_equal flash[:success], "Guide updated"
+ assert_equal @welsh_edition.state, "fact_check"
+ end
+
+ should "not be able to resend fact check emails for non-Welsh editions" do
+ @edition.update!(state: "fact_check")
+ UpdateWorker.expects(:perform_async).with(@edition.id.to_s, false).never
+
+ post :update,
+ params: {
+ id: @edition.id,
+ commit: "Resend fact check email",
+ edition: {
+ activity_resend_fact_check_attributes: {
+ request_type: "resend_fact_check",
+ comment: "Blah",
+ email_addresses: "user@example.com",
+ customised_message: "Hello",
+ },
+ },
+ }
+
+ assert_redirected_to edition_path(@edition)
+ @edition.reload
+ assert_equal @edition.state, "fact_check"
+ assert_equal flash[:danger], "You do not have correct editor permissions for this action."
+ end
+
+ should "be able to approve a fact check for Welsh editions" do
+ UpdateWorker.expects(:perform_async).with(@welsh_edition.id.to_s, false)
+
+ post :update,
+ params: {
+ id: @welsh_edition.id,
+ commit: "Approve Fact check",
+ edition: {
+ activity_approve_fact_check_attributes: {
+ request_type: "approve_fact_check",
+ comment: "lgtm",
+ },
+ },
+ }
+
+ assert_redirected_to edition_path(@welsh_edition)
+ @welsh_edition.reload
+ assert_equal flash[:notice], "Guide edition was successfully updated."
+ assert_equal @welsh_edition.state, "ready"
+ end
+
+ should "not be able to approve a fact check for non-Welsh editions" do
+ @edition.update!(state: "fact_check_received")
+ UpdateWorker.expects(:perform_async).with(@edition.id.to_s, false).never
+
+ post :update,
+ params: {
+ id: @edition.id,
+ commit: "Approve Fact check",
+ edition: {
+ activity_approve_fact_check_attributes: {
+ request_type: "approve_fact_check",
+ comment: "lgtm",
+ },
+ },
+ }
+
+ assert_redirected_to edition_path(@edition)
+ @edition.reload
+ assert_equal @edition.state, "fact_check_received"
+ assert_equal flash[:danger], "You do not have correct editor permissions for this action."
+ end
+ end
+ end
+
+ context "#review" do
+ setup do
+ artefact = FactoryBot.create(:artefact)
+
+ @guide = FactoryBot.create(
+ :guide_edition,
+ state: "in_review",
+ review_requested_at: Time.zone.now,
+ panopticon_id: artefact.id,
+ )
+ end
+
+ should "update the reviewer" do
+ bob = FactoryBot.create(:user, name: "bob")
+
+ put :review,
+ params: {
+ id: @guide.id,
+ edition: { reviewer: bob.name },
+ }
+
+ @guide.reload
+ assert_equal bob.name, @guide.reviewer
+ end
+
+ should "not be able to update the reviewer when edition is scheduled for publishing" do
+ bob = FactoryBot.create(:user, name: "bob")
+ edition = FactoryBot.create(:edition, :scheduled_for_publishing)
+
+ put :review,
+ params: {
+ id: edition.id,
+ edition: { reviewer: bob.name },
+ }
+
+ assert_response(:found)
+ assert_equal "Something went wrong when attempting to claim 2i.", flash[:danger]
+ end
+
+ context "Welsh editors" do
+ setup do
+ @welsh_guide = FactoryBot.create(:guide_edition, :welsh, :in_review)
+ login_as_welsh_editor
+ @welsh_user = @user
+ end
+
+ should "be able to claim a review for Welsh editions" do
+ put :review,
+ params: {
+ id: @welsh_guide.id,
+ edition: { reviewer: @welsh_user.name },
+ }
+
+ assert_redirected_to edition_path(@welsh_guide)
+ assert_equal "You are the reviewer of this guide.", flash[:success]
+ @welsh_guide.reload
+ assert_equal @welsh_user.name, @welsh_guide.reviewer
+ end
+
+ should "not be able to claim a review for non-Welsh editions" do
+ put :review,
+ params: {
+ id: @guide.id,
+ edition: { reviewer: @welsh_user.name },
+ }
+
+ assert_redirected_to edition_path(@guide)
+ assert_equal "You do not have correct editor permissions for this action.", flash[:danger]
+ @guide.reload
+ assert_nil @guide.reviewer
+ end
+ end
+ end
+
+ context "#destroy" do
+ setup do
+ artefact1 = FactoryBot.create(
+ :artefact,
+ slug: "test",
+ kind: "transaction",
+ name: "test",
+ owning_app: "publisher",
+ )
+ @transaction = TransactionEdition.create!(title: "test", slug: "test", panopticon_id: artefact1.id)
+
+ artefact2 = FactoryBot.create(
+ :artefact,
+ slug: "test2",
+ kind: "guide",
+ name: "test",
+ owning_app: "publisher",
+ )
+ @guide = GuideEdition.create!(title: "test", slug: "test2", panopticon_id: artefact2.id)
+
+ stub_request(:delete, "#{Plek.find('arbiter')}/slugs/test").to_return(status: 200)
+ end
+
+ should "destroy transaction" do
+ assert @transaction.can_destroy?
+ assert_difference("TransactionEdition.count", -1) do
+ delete :destroy, params: { id: @transaction.id }
+ end
+ assert_redirected_to root_path
+ end
+
+ should "can't destroy published transaction" do
+ @transaction.state = "ready"
+ stub_register_published_content
+ @transaction.publish
+ assert_not @transaction.can_destroy?
+ @transaction.save!
+ assert_difference("TransactionEdition.count", 0) do
+ delete :destroy, params: { id: @transaction.id }
+ end
+ end
+
+ should "destroy guide" do
+ assert @guide.can_destroy?
+ assert_difference("GuideEdition.count", -1) do
+ delete :destroy, params: { id: @guide.id }
+ end
+ assert_redirected_to root_path
+ end
+
+ should "can't destroy published guide" do
+ @guide.state = "ready"
+ @guide.save!
+ stub_register_published_content
+ @guide.publish
+ @guide.save!
+ assert @guide.published?
+ assert_not @guide.can_destroy?
+
+ assert_difference("GuideEdition.count", 0) do
+ delete :destroy, params: { id: @guide.id }
+ end
+ end
+
+ context "Welsh editors" do
+ setup do
+ login_as_welsh_editor
+ @welsh_guide = FactoryBot.create(:guide_edition, :welsh)
+ end
+
+ should "not be able to destroy non-Welsh editions" do
+ assert_difference("GuideEdition.count", 0) do
+ delete :destroy, params: { id: @guide.id }
+ end
+
+ assert_redirected_to edition_path(@guide)
+ assert_equal "You do not have correct editor permissions for this action.", flash[:danger]
+ end
+
+ should "be able to destroy Welsh editions" do
+ assert_difference("GuideEdition.count", -1) do
+ delete :destroy, params: { id: @welsh_guide.id }
+ end
+
+ assert_redirected_to root_path
+ assert_equal "Edition deleted", flash[:success]
+ end
+ end
+ end
+
+ context "#index" do
+ should "editions index redirects to root" do
+ get :index
+ assert_response :redirect
+ assert_redirected_to root_path
+ end
+ end
+
+ context "#show" do
+ setup do
+ artefact2 = FactoryBot.create(
+ :artefact,
+ slug: "test2",
+ kind: "guide",
+ name: "test",
+ owning_app: "publisher",
+ )
+ @guide = GuideEdition.create!(title: "test", slug: "test2", panopticon_id: artefact2.id)
+ end
+
+ should "requesting a publication that doesn't exist returns a 404" do
+ get :show, params: { id: "4e663834e2ba80480a0000e6" }
+ assert_response :not_found
+ end
+
+ should "we can view a guide" do
+ get :show, params: { id: @guide.id }
+ assert_response :success
+ assert_not_nil assigns(:resource)
+ end
+
+ should "render a link to the diagram when edition is a simple smart answer" do
+ simple_smart_answer_artefact = FactoryBot.create(
+ :artefact,
+ slug: "my-simple-smart-answer",
+ kind: "guide",
+ name: "test",
+ owning_app: "publisher",
+ )
+ simple_smart_answer = SimpleSmartAnswerEdition.create!(
+ title: "test ssa",
+ panopticon_id: simple_smart_answer_artefact.id,
+ )
+
+ get :show, params: { id: simple_smart_answer.id }
+
+ assert_select ".link-check-report p", { text: "View the flow diagram (opens in a new tab)" } do
+ assert_select "a[href=?]", diagram_edition_path(simple_smart_answer).to_s,
+ { count: 1, text: "flow diagram (opens in a new tab)" }
+ end
+ end
+
+ should "not render a link to the diagram when edition is not a simple smart answer" do
+ get :show, params: { id: @guide.id }
+ assert_select "p", { count: 0, text: "View the flow diagram (opens in a new tab)" }
+ end
+ end
+
+ context "#admin" do
+ setup do
+ @guide = FactoryBot.create(:guide_edition)
+ end
+
+ should "show the admin page for the edition" do
+ get :admin, params: { id: @guide.id }
+
+ assert_response :success
+ end
+
+ context "Welsh editors" do
+ setup do
+ login_as_welsh_editor
+ @welsh_guide = FactoryBot.create(:guide_edition, :welsh)
+ end
+
+ should "be able to see the admin page for Welsh editions" do
+ get :admin, params: { id: @welsh_guide.id }
+
+ assert_response :success
+ end
+
+ should "not be able to see the admin page for non-Welsh editions" do
+ get :admin, params: { id: @guide.id }
+
+ assert_redirected_to edition_path(@guide)
+ assert_equal "You do not have correct editor permissions for this action.", flash[:danger]
+ end
+ end
+ end
+
+ context "#diff" do
+ should "we can diff the last edition" do
+ first_edition = FactoryBot.create(:guide_edition, state: "published")
+ second_edition = first_edition.build_clone(GuideEdition)
+ second_edition.save!
+ second_edition.reload
+
+ get :diff, params: { id: second_edition.id }
+ assert_response :success
+ end
+ end
+
+ context "#unpublish" do
+ setup do
+ @guide = FactoryBot.create(:guide_edition, :published, panopticon_id: FactoryBot.create(:artefact).id)
+ @redirect_url = "https://www.example.com/somewhere_else"
+ end
+
+ should "update publishing API upon unpublishing" do
+ UnpublishService.expects(:call).with(@guide.artefact, @user, @redirect_url)
+
+ post :process_unpublish,
+ params: {
+ id: @guide.id,
+ redirect_url: @redirect_url,
+ }
+ end
+
+ should "redirect and display success message after successful unpublish" do
+ UnpublishService.stubs(:call).with(@guide.artefact, @user, @redirect_url).returns(true)
+
+ post :process_unpublish,
+ params: {
+ id: @guide.id,
+ redirect_url: @redirect_url,
+ }
+
+ assert_redirected_to root_path
+ assert_equal "Content unpublished and redirected", flash[:notice]
+ end
+
+ should "not be able to unpublish with invalid redirect url" do
+ post :process_unpublish,
+ params: {
+ id: @guide.id,
+ redirect_url: "invalid redirect url",
+ }
+
+ assert_equal "Redirect path is invalid. Guide has not been unpublished.", flash[:danger]
+ end
+
+ should "alert if unable to unpublish" do
+ UnpublishService.stubs(:call).with(@guide.artefact, @user, @redirect_url).returns(nil)
+
+ post :process_unpublish,
+ params: {
+ id: @guide.id,
+ redirect_url: @redirect_url,
+ }
+
+ assert_equal "Due to a service problem, the edition couldn't be unpublished", flash[:alert]
+ end
+
+ context "Welsh editors" do
+ setup do
+ login_as_welsh_editor
+ @welsh_guide = FactoryBot.create(:guide_edition, :published, :welsh)
+ end
+
+ should "not be able to access the unpublish page of non-Welsh editions" do
+ get :unpublish, params: { id: @guide.id }
+
+ assert_redirected_to edition_path(@guide)
+ assert_equal "You do not have permission to see this page.", flash[:danger]
+ end
+
+ should "not be able to access the unpublish page of Welsh editions" do
+ get :unpublish, params: { id: @welsh_guide.id }
+
+ assert_redirected_to edition_path(@welsh_guide)
+ assert_equal "You do not have permission to see this page.", flash[:danger]
+ end
+
+ should "not be allowed to unpublish a Welsh edition" do
+ UnpublishService.expects(:call).with(@welsh_guide.artefact, @user, @redirect_url).never
+
+ post :process_unpublish,
+ params: {
+ id: @welsh_guide.id,
+ redirect_url: @redirect_url,
+ }
+
+ assert_redirected_to edition_path(@welsh_guide)
+ @welsh_guide.reload
+ assert_equal @welsh_guide.state, "published"
+ assert_equal "You do not have permission to see this page.", flash[:danger]
+ end
+
+ should "not be allowed to unpublish a non-Welsh edition" do
+ UnpublishService.expects(:call).with(@guide.artefact, @user, @redirect_url).never
+
+ post :process_unpublish,
+ params: {
+ id: @guide.id,
+ redirect_url: @redirect_url,
+ }
+
+ assert_redirected_to edition_path(@guide)
+ @guide.reload
+ assert_equal @guide.state, "published"
+ assert_equal "You do not have permission to see this page.", flash[:danger]
+ end
+ end
+ end
+
+ context "given a simple smart answer" do
+ setup do
+ @artefact = FactoryBot.create(:artefact, slug: "foo", name: "Foo", kind: "simple_smart_answer", owning_app: "publisher")
+ @edition = FactoryBot.create(:simple_smart_answer_edition, body: "blah", state: "draft", slug: "foo", panopticon_id: @artefact.id)
+ @edition.nodes.build(
+ kind: "question",
+ slug: "question-1",
+ title: "Question One",
+ options_attributes: [
+ { label: "Option One", next_node: "outcome-1" },
+ { label: "Option Two", next_node: "outcome-2" },
+ ],
+ )
+ @edition.nodes.build(kind: "outcome", slug: "outcome-1", title: "Outcome One")
+ @edition.nodes.build(kind: "outcome", slug: "outcome-2", title: "Outcome Two")
+ @edition.save!
+ end
+
+ should "remove an option and node from simple smart answer in single request" do
+ atts = {
+ nodes_attributes: {
+ "0" => {
+ "id" => @edition.nodes.all[0].id,
+ "options_attributes" => {
+ "0" => { "id" => @edition.nodes.first.options.all[0].id },
+ "1" => { "id" => @edition.nodes.first.options.all[1].id, "_destroy" => "1" },
+ },
+ },
+ "1" => {
+ "id" => @edition.nodes.all[1].id,
+ },
+ "2" => {
+ "id" => @edition.nodes.all[2].id,
+ "_destroy" => "1",
+ },
+ },
+ }
+ put :update,
+ params: {
+ id: @edition.id,
+ edition: atts,
+ }
+ assert_redirected_to edition_path(@edition)
+
+ @edition.reload
+
+ assert_equal 2, @edition.nodes.count
+ assert_equal 1, @edition.nodes.where(kind: "question").count
+ assert_equal 1, @edition.nodes.where(kind: "outcome").count
+
+ question = @edition.nodes.where(kind: "question").first
+ assert_equal 1, question.options.count
+ assert_equal "Option One", question.options.first.label
+ end
+ end
+
+ context "#diagram" do
+ context "given a simple smart answer exists" do
+ setup do
+ @artefact = FactoryBot.create(:artefact, slug: "foo", name: "Foo", kind: "simple_smart_answer", owning_app: "publisher")
+ @edition = FactoryBot.create(:simple_smart_answer_edition, body: "blah", state: "draft", slug: "foo", panopticon_id: @artefact.id)
+ @edition.save!
+ end
+
+ should "render a diagram page for it" do
+ get :diagram, params: { id: @edition.id }
+
+ assert_response :success
+ assert_select "title", "Diagram for #{@edition.title} | GOV.UK Publisher"
+ end
+ end
+
+ context "given a non-simple smart answer exists" do
+ setup do
+ @welsh_guide = FactoryBot.create(:guide_edition, :welsh, :in_review)
+ end
+
+ should "return a 404" do
+ get :diagram, params: { id: @welsh_guide.id }
+ assert_response :not_found
+ end
+ end
+ end
+end
diff --git a/test/integration/edition_edit_test.rb b/test/integration/edition_edit_test.rb
new file mode 100644
index 000000000..7036763c3
--- /dev/null
+++ b/test/integration/edition_edit_test.rb
@@ -0,0 +1,25 @@
+require "integration_test_helper"
+
+class EditionEditTest < IntegrationTest
+ setup do
+ setup_users
+ test_strategy = Flipflop::FeatureSet.current.test!
+ test_strategy.switch!(:design_system_edit, true)
+ stub_linkables
+ end
+
+ should "show document summary and title" do
+ edition = FactoryBot.create(:guide_edition, title: "Edit page title", state: "draft")
+ visit edition_path(edition)
+
+ assert page.has_title?("Edit page title")
+
+ row = find_all(".govuk-summary-list__row")
+ assert row[0].has_content?("Assigned to")
+ assert row[1].has_text?("Content type")
+ assert row[1].has_text?("Guide")
+ assert row[2].has_text?("Edition")
+ assert row[2].has_text?("1")
+ assert row[2].has_text?("Draft")
+ end
+end
diff --git a/test/integration/edition_workflow_test.rb b/test/integration/edition_workflow_test.rb
index 07ea5d30e..376303fdf 100644
--- a/test/integration/edition_workflow_test.rb
+++ b/test/integration/edition_workflow_test.rb
@@ -18,6 +18,7 @@ class EditionWorkflowTest < LegacyJavascriptIntegrationTest
test_strategy = Flipflop::FeatureSet.current.test!
test_strategy.switch!(:design_system_publications_filter, false)
+ test_strategy.switch!(:design_system_edit, false)
end
teardown do