diff --git a/app/controllers/admin/attachments_controller.rb b/app/controllers/admin/attachments_controller.rb index 8ade796d3be..c464d0e1299 100644 --- a/app/controllers/admin/attachments_controller.rb +++ b/app/controllers/admin/attachments_controller.rb @@ -48,9 +48,7 @@ def update def confirm_destroy; end def destroy - attachment_data = attachment.attachment_data attachment.destroy! - attachment_updater(attachment_data) redirect_to attachable_attachments_path(attachable), notice: "Attachment deleted" end diff --git a/app/models/attachment_data.rb b/app/models/attachment_data.rb index 350c366de69..50d6219aade 100644 --- a/app/models/attachment_data.rb +++ b/app/models/attachment_data.rb @@ -95,6 +95,10 @@ def draft? !significant_attachable.publicly_visible? end + def needs_publishing? + attachments.size == 1 && attachments.first.attachable.publicly_visible? + end + delegate :accessible_to?, to: :significant_attachable delegate :access_limited?, to: :last_attachable @@ -125,6 +129,7 @@ def visible_attachable_for(user) def visible_edition_for(user) visible_attachable = visible_attachable_for(user) + # below code seems wrong, policy group is not a edition but could be visible visible_attachable.is_a?(Edition) ? visible_attachable : nil end diff --git a/app/models/call_for_evidence.rb b/app/models/call_for_evidence.rb index 0be3c27e419..09b1f168df9 100644 --- a/app/models/call_for_evidence.rb +++ b/app/models/call_for_evidence.rb @@ -60,6 +60,10 @@ def attachables [self, outcome].compact end + def delete_all_attachments + attachables.map(&:attachments).flatten.each(&:destroy) + end + def rendering_app Whitehall::RenderingApp::GOVERNMENT_FRONTEND end diff --git a/app/models/consultation.rb b/app/models/consultation.rb index 136bc402473..01fcaadf19f 100644 --- a/app/models/consultation.rb +++ b/app/models/consultation.rb @@ -70,6 +70,10 @@ def attachables [self, outcome, public_feedback].compact end + def delete_all_attachments + attachables.map(&:attachments).flatten.each(&:destroy) + end + def rendering_app Whitehall::RenderingApp::GOVERNMENT_FRONTEND end diff --git a/app/models/policy_group.rb b/app/models/policy_group.rb index 3bec4e943e5..984c1ae11a0 100644 --- a/app/models/policy_group.rb +++ b/app/models/policy_group.rb @@ -15,6 +15,7 @@ class PolicyGroup < ApplicationRecord after_create :extract_dependencies after_update :extract_dependencies after_destroy :remove_all_dependencies + after_update :publish_deleted_attachments def extract_dependencies remove_all_dependencies @@ -28,6 +29,14 @@ def extract_dependencies end end + def publish_deleted_attachments + deleted_attachments.each do |attachment| + next unless attachment.attachment_data.present? && attachment.deleted? + + DeleteAttachmentAssetJob.perform_async(attachment.attachment_data.id) + end + end + def remove_all_dependencies policy_group_dependencies.delete_all end diff --git a/app/services/asset_manager/asset_updater.rb b/app/services/asset_manager/asset_updater.rb index 9f8a58becec..065fbdab9b5 100644 --- a/app/services/asset_manager/asset_updater.rb +++ b/app/services/asset_manager/asset_updater.rb @@ -21,11 +21,6 @@ def update_with_asset_manager_id(asset_manager_id, new_attributes) raise AssetAttributesEmpty, asset_manager_id if new_attributes.empty? attributes = find_asset_by_id(asset_manager_id) - asset_deleted = attributes["deleted"] - - if asset_deleted - logger.warn("Asset with asset_manager_id: '#{asset_manager_id}' expected not to be deleted in Asset Manager") - end keys = new_attributes.keys unless attributes.slice(*keys) == new_attributes.slice(*keys) diff --git a/app/services/asset_manager/attachment_deleter.rb b/app/services/asset_manager/attachment_deleter.rb deleted file mode 100644 index a7841521d55..00000000000 --- a/app/services/asset_manager/attachment_deleter.rb +++ /dev/null @@ -1,9 +0,0 @@ -class AssetManager::AttachmentDeleter - def self.call(attachment_data) - return unless attachment_data.deleted? - - attachment_data.assets.each do |asset| - AssetManager::AssetDeleter.call(asset.asset_manager_id) - end - end -end diff --git a/app/services/service_listeners/attachment_asset_deleter.rb b/app/services/service_listeners/attachment_asset_deleter.rb new file mode 100644 index 00000000000..f5bd37195f7 --- /dev/null +++ b/app/services/service_listeners/attachment_asset_deleter.rb @@ -0,0 +1,13 @@ +module ServiceListeners + class AttachmentAssetDeleter + def self.call(attachable) + Attachment.includes(:attachment_data).where(attachable: attachable.attachables).find_each do |attachment| + attachment_data = attachment.attachment_data + + next unless attachment_data&.deleted? + + DeleteAttachmentAssetJob.perform_async(attachment_data.id) + end + end + end +end diff --git a/app/services/service_listeners/attachment_asset_publisher.rb b/app/services/service_listeners/attachment_asset_publisher.rb new file mode 100644 index 00000000000..232c83a4c2e --- /dev/null +++ b/app/services/service_listeners/attachment_asset_publisher.rb @@ -0,0 +1,11 @@ +module ServiceListeners + class AttachmentAssetPublisher + def self.call(attachable) + Attachment.includes(:attachment_data).where(attachable: attachable.attachables).find_each do |attachment| + next unless attachment.attachment_data + + PublishAttachmentAssetJob.perform_async(attachment.attachment_data.id) + end + end + end +end diff --git a/app/sidekiq/asset_manager_attachment_metadata_worker.rb b/app/sidekiq/asset_manager_attachment_metadata_worker.rb index d0d828b3069..2503b33df1d 100644 --- a/app/sidekiq/asset_manager_attachment_metadata_worker.rb +++ b/app/sidekiq/asset_manager_attachment_metadata_worker.rb @@ -6,8 +6,6 @@ def perform(attachment_data_id) return if attachment_data.blank? - AssetManager::AttachmentDeleter.call(attachment_data) - return unless attachment_data.all_asset_variants_uploaded? AssetManager::AttachmentUpdater.call(attachment_data) diff --git a/app/sidekiq/delete_attachment_asset_job.rb b/app/sidekiq/delete_attachment_asset_job.rb new file mode 100644 index 00000000000..fc1ebc2071d --- /dev/null +++ b/app/sidekiq/delete_attachment_asset_job.rb @@ -0,0 +1,13 @@ +class DeleteAttachmentAssetJob < WorkerBase + sidekiq_options queue: "asset_manager" + + def perform(attachment_data_id) + attachment_data = AttachmentData.find(attachment_data_id) + + attachment_data.assets.each do |asset| + AssetManager::AssetDeleter.call(asset.asset_manager_id) + rescue AssetManager::ServiceHelper::AssetNotFound + logger.info("Asset #{asset.asset_manager_id} has already been deleted from Asset Manager") + end + end +end diff --git a/app/sidekiq/publish_attachment_asset_job.rb b/app/sidekiq/publish_attachment_asset_job.rb new file mode 100644 index 00000000000..4a22dfa7e71 --- /dev/null +++ b/app/sidekiq/publish_attachment_asset_job.rb @@ -0,0 +1,22 @@ +class PublishAttachmentAssetJob < WorkerBase + sidekiq_options queue: "asset_manager" + + def perform(attachment_data_id) + attachment_data = AttachmentData.find(attachment_data_id) + + asset_attributes = { + "draft" => false, + } + + if attachment_data.last_attachable.respond_to?(:public_url) + asset_attributes.merge!({ "parent_document_url" => attachment_data.last_attachable.public_url }) + end + + # We need to delete the asset first, because if we delete it after updating the draft value to false, and the delete request fails, + # the asset will remain live. + attachment_data.assets.each do |asset| + AssetManager::AssetDeleter.call(asset.asset_manager_id) if attachment_data.deleted? + AssetManager::AssetUpdater.call(asset.asset_manager_id, asset_attributes) if attachment_data.needs_publishing? + end + end +end diff --git a/config/initializers/edition_services.rb b/config/initializers/edition_services.rb index 3ef03adb110..0aac920741c 100644 --- a/config/initializers/edition_services.rb +++ b/config/initializers/edition_services.rb @@ -1,7 +1,13 @@ Whitehall::Application.config.to_prepare do Whitehall.edition_services.tap do |coordinator| - coordinator.subscribe do |_event, edition, _options| - ServiceListeners::AttachmentUpdater.call(attachable: edition) + coordinator.subscribe do |event, edition, _options| + if %w[publish force_publish].include?(event) + ServiceListeners::AttachmentAssetPublisher.call(edition) + elsif event == "delete" + ServiceListeners::AttachmentAssetDeleter.call(edition) + else + ServiceListeners::AttachmentUpdater.call(attachable: edition) + end end coordinator.subscribe("unpublish") do |_event, edition, _options| diff --git a/test/integration/attachment_deletion_integration_test.rb b/test/integration/attachment_deletion_integration_test.rb index 29cd80e07c5..0e3e9503760 100644 --- a/test/integration/attachment_deletion_integration_test.rb +++ b/test/integration/attachment_deletion_integration_test.rb @@ -15,6 +15,7 @@ class AttachmentDeletionIntegrationTest < ActionDispatch::IntegrationTest let(:second_attachment) { build(:file_attachment, attachable: edition) } let(:second_asset_id) { second_attachment.attachment_data.assets.first.asset_manager_id } let(:edition) { create(:news_article) } + let(:topic_taxon) { build(:taxon_hash) } before do login_as(managing_editor) @@ -22,16 +23,19 @@ class AttachmentDeletionIntegrationTest < ActionDispatch::IntegrationTest setup_publishing_api_for(edition) stub_publishing_api_has_linkables([], document_type: "topic") stub_publishing_api_expanded_links_with_taxons(edition.content_id, []) + stub_publishing_api_links_with_taxons(edition.content_id, [topic_taxon["content_id"]]) - stub_asset(first_asset_id) - stub_asset(second_asset_id) + stub_asset(first_asset_id, { "draft" => true, "parent_document_url" => edition.public_url(draft: true) }) + stub_asset(second_asset_id, { "draft" => true, "parent_document_url" => edition.public_url(draft: true) }) edition.attachments << [first_attachment, second_attachment] edition.save! end context "when one attachment is deleted" do - before do + it "deletes the corresponding asset in Asset Manager when the edition is published" do + Services.asset_manager.expects(:delete_asset).never + visit admin_news_article_path(edition) click_link "Modify attachments" within page.find("li", text: first_attachment.title) do @@ -39,35 +43,32 @@ class AttachmentDeletionIntegrationTest < ActionDispatch::IntegrationTest end click_button "Delete attachment" assert_text "Attachment deleted" - end - it "deletes the corresponding asset in Asset Manager" do Services.asset_manager.expects(:delete_asset).once.with(first_asset_id) - assert_equal AssetManagerAttachmentMetadataWorker.jobs.count, 1 + Services.asset_manager.expects(:update_asset).once.with(first_asset_id, has_entries({ "draft" => false, "parent_document_url" => edition.public_url(draft: false) })) + Services.asset_manager.expects(:update_asset).once.with(second_asset_id, has_entries({ "draft" => false, "parent_document_url" => edition.public_url(draft: false) })) - AssetManagerAttachmentMetadataWorker.drain - end - - it "queues one worker to delete the asset" do - queued_ids = AssetManagerAttachmentMetadataWorker.jobs.map { |job| job["args"].first } + visit admin_news_article_path(edition) + click_link "Force publish" + assert_text "Reason for force publishing" + fill_in "Reason for force publishing", with: "testing" + click_button "Force publish" + assert_text "The document #{edition.title} has been published" - assert_equal queued_ids, [first_attachment.attachment_data.id] + PublishAttachmentAssetJob.drain end end context "when draft document is discarded" do - before do - visit admin_news_article_path(edition) - click_link "Delete draft" - click_button "Delete" - end - it "deletes all corresponding assets in Asset Manager" do Services.asset_manager.expects(:delete_asset).once.with(first_asset_id) Services.asset_manager.expects(:delete_asset).once.with(second_asset_id) - assert_equal AssetManagerAttachmentMetadataWorker.jobs.count, 2 - AssetManagerAttachmentMetadataWorker.drain + visit admin_news_article_path(edition) + click_link "Delete draft" + click_button "Delete" + + DeleteAttachmentAssetJob.drain end end end @@ -77,7 +78,8 @@ class AttachmentDeletionIntegrationTest < ActionDispatch::IntegrationTest let(:earliest_attachable) { create(:published_news_article, :with_file_attachment) } let(:latest_attachable) { earliest_attachable.reload.create_draft(managing_editor) } let(:attachment) { latest_attachable.attachments.first } - let(:original_asset) { attachment.attachment_data.assets.first.asset_manager_id } + let(:original_asset_manager_id) { attachment.attachment_data.assets.first.asset_manager_id } + let(:topic_taxon) { build(:taxon_hash) } before do login_as(managing_editor) @@ -85,8 +87,11 @@ class AttachmentDeletionIntegrationTest < ActionDispatch::IntegrationTest setup_publishing_api_for(latest_attachable) stub_publishing_api_has_linkables([], document_type: "topic") stub_publishing_api_expanded_links_with_taxons(latest_attachable.content_id, []) + stub_publishing_api_links_with_taxons(latest_attachable.content_id, [topic_taxon["content_id"]]) + + stub_asset(original_asset_manager_id, { "draft" => false, "parent_document_url" => latest_attachable.public_url(draft: false) }) - stub_asset(original_asset) + latest_attachable.update!(minor_change: true) end it "deletes the corresponding asset in Asset Manager only when the new draft gets published" do @@ -98,14 +103,149 @@ class AttachmentDeletionIntegrationTest < ActionDispatch::IntegrationTest click_button "Delete attachment" assert_text "Attachment deleted" - Services.asset_manager.expects(:delete_asset).never.with(original_asset) + Services.asset_manager.expects(:delete_asset).once.with(original_asset_manager_id) + Services.asset_manager.expects(:update_asset).never - latest_attachable.update!(minor_change: true) - latest_attachable.force_publish! + visit admin_news_article_path(latest_attachable) + click_link "Force publish" + assert_text "Reason for force publishing" + fill_in "Reason for force publishing", with: "testing" + click_button "Force publish" + assert_text "The document #{latest_attachable.title} has been published" + + PublishAttachmentAssetJob.drain + end + + context "when the attachment has been replaced" do + let(:replacement_asset_manager_id) { "replacement_asset_manager_id" } + + before do + stub_asset(replacement_asset_manager_id, { "draft" => true, "parent_document_url" => latest_attachable.public_url(draft: true) }) + + replacement_data = create(:attachment_data, attachable: latest_attachable) + attachment.attachment_data.replaced_by = replacement_data + attachment.attachment_data.save! + + asset = replacement_data.assets.first + asset.asset_manager_id = replacement_asset_manager_id + asset.save! + + attachment.attachment_data = replacement_data + attachment.save! + end + + it "deletes the corresponding asset in Asset Manager and updates the asset to live, only when the new draft gets published" do + visit admin_news_article_path(latest_attachable) + click_link "Modify attachments" + within page.find("li", text: attachment.title) do + click_link "Delete attachment" + end + click_button "Delete attachment" + assert_text "Attachment deleted" + + Services.asset_manager.expects(:delete_asset).once.with(replacement_asset_manager_id) + Services.asset_manager.expects(:update_asset).once.with(replacement_asset_manager_id, has_entries({ "draft" => false, "parent_document_url" => latest_attachable.public_url(draft: false) })) + + visit admin_news_article_path(latest_attachable) + click_link "Force publish" + assert_text "Reason for force publishing" + fill_in "Reason for force publishing", with: "testing" + click_button "Force publish" + assert_text "The document #{latest_attachable.title} has been published" + + PublishAttachmentAssetJob.drain + end + end + end + + context "given an outcome on a draft consultation" do + let(:managing_editor) { create(:managing_editor) } + let(:topic_taxon) { build(:taxon_hash) } + let(:edition) { create(:draft_consultation) } + let(:attachable) { edition.create_outcome!(FactoryBot.attributes_for(:consultation_outcome)) } + let(:attachment) { build(:csv_attachment, attachable:) } + let(:asset_id) { attachment.attachment_data.assets.first.asset_manager_id } - Services.asset_manager.expects(:delete_asset).once.with(original_asset) + before do + login_as(managing_editor) + + setup_publishing_api_for(edition) + stub_publishing_api_has_linkables([], document_type: "topic") + stub_publishing_api_expanded_links_with_taxons(edition.content_id, []) + stub_publishing_api_links_with_taxons(edition.content_id, [topic_taxon["content_id"]]) + + stub_asset(asset_id, { "draft" => true, "parent_document_url" => nil }) + + attachable.attachments << [attachment] + attachable.save! + end + + it "deletes the corresponding asset in Asset Manager when the edition is published and updates its draft setting to false" do + Services.asset_manager.expects(:delete_asset).never + + visit admin_consultation_path(edition) + click_link "Edit draft" + click_link "Final outcome" + within page.find("li", text: attachment.title) do + click_link "Delete attachment" + end + click_button "Delete attachment" + assert_text "Attachment deleted" + + Services.asset_manager.expects(:delete_asset).once.with(asset_id) + Services.asset_manager.expects(:update_asset).once.with(asset_id, has_entries({ "draft" => false })) + + visit admin_consultation_path(edition) + click_link "Force publish" + assert_text "Reason for force publishing" + fill_in "Reason for force publishing", with: "testing" + click_button "Force publish" + assert_text "The document #{edition.title} has been published" + + PublishAttachmentAssetJob.drain + end + + context "when draft consultation is discarded" do + it "deletes all outcome attachment assets in Asset Manager" do + Services.asset_manager.expects(:delete_asset).once.with(asset_id) + + visit admin_consultation_path(edition) + click_link "Delete draft" + click_button "Delete" + + DeleteAttachmentAssetJob.drain + end + end + end + + context "given a policy group" do + let(:managing_editor) { create(:managing_editor) } + let(:attachable) { create(:policy_group) } + let(:attachment) { build(:file_attachment, attachable:) } + let(:asset_manager_id) { attachment.attachment_data.assets.first.asset_manager_id } + + before do + login_as(managing_editor) + stub_asset(asset_manager_id, { "draft" => false, "parent_document_url" => nil }) + + attachable.attachments << [attachment] + attachable.save! + end + + it "deletes the corresponding asset in Asset Manager when the policy group is saved" do + Services.asset_manager.expects(:delete_asset).once.with(asset_manager_id) + Services.asset_manager.expects(:update_asset).with(asset_manager_id).never + + visit admin_policy_group_attachments_path(attachable) + within page.find("li", text: attachment.title) do + click_link "Delete attachment" + end + click_button "Delete attachment" + assert_text "Attachment deleted" + click_link "Group" + click_button "Save" - AssetManagerAttachmentMetadataWorker.drain + DeleteAttachmentAssetJob.drain end end diff --git a/test/integration/attachment_draft_status_integration_test.rb b/test/integration/attachment_draft_status_integration_test.rb index 0887a510760..f9200ffa2e5 100644 --- a/test/integration/attachment_draft_status_integration_test.rb +++ b/test/integration/attachment_draft_status_integration_test.rb @@ -35,9 +35,12 @@ class AttachmentDraftStatusIntegrationTest < ActionDispatch::IntegrationTest stub_publishing_api_expanded_links_with_taxons(edition.content_id, []) stub_publishing_api_links_with_taxons(edition.content_id, [topic_taxon["content_id"]]) + assert_sets_draft_status_in_asset_manager_to false + visit admin_news_article_path(edition) force_publish_document - assert_sets_draft_status_in_asset_manager_to false + + PublishAttachmentAssetJob.drain end end @@ -64,9 +67,12 @@ class AttachmentDraftStatusIntegrationTest < ActionDispatch::IntegrationTest stub_publishing_api_expanded_links_with_taxons(edition.content_id, []) stub_publishing_api_links_with_taxons(edition.content_id, [topic_taxon["content_id"]]) + assert_sets_draft_status_in_asset_manager_to false + visit admin_consultation_path(edition) force_publish_document - assert_sets_draft_status_in_asset_manager_to false + + PublishAttachmentAssetJob.drain end end @@ -80,9 +86,12 @@ class AttachmentDraftStatusIntegrationTest < ActionDispatch::IntegrationTest stub_publishing_api_expanded_links_with_taxons(edition.content_id, []) stub_publishing_api_links_with_taxons(edition.content_id, [topic_taxon["content_id"]]) + assert_sets_draft_status_in_asset_manager_to false + visit admin_consultation_path(edition) force_publish_document - assert_sets_draft_status_in_asset_manager_to false + + PublishAttachmentAssetJob.drain end end end @@ -102,6 +111,7 @@ class AttachmentDraftStatusIntegrationTest < ActionDispatch::IntegrationTest AssetManagerCreateAssetWorker.drain assert_sets_draft_status_in_asset_manager_to false + AssetManagerAttachmentMetadataWorker.drain end end @@ -133,7 +143,6 @@ def assert_sets_draft_status_in_asset_manager_to(draft, never: false) .with(asset_manager_id, has_entry("draft", draft)) .at_least_once expectation.never if never - AssetManagerAttachmentMetadataWorker.drain end def refute_sets_draft_status_in_asset_manager_to(draft) diff --git a/test/integration/attachment_link_header_test.rb b/test/integration/attachment_link_header_test.rb index 322ba1ceca8..208f7c346e4 100644 --- a/test/integration/attachment_link_header_test.rb +++ b/test/integration/attachment_link_header_test.rb @@ -31,16 +31,15 @@ class AttachmentLinkHeaderIntegrationTest < ActionDispatch::IntegrationTest let(:asset_initially_draft) { true } it "sets link to parent document in Asset Manager when document is published" do - visit admin_news_article_path(edition) - force_publish_document - parent_document_url = edition.public_url - Services.asset_manager.expects(:update_asset) .at_least_once .with(asset_manager_id, has_entry("parent_document_url", parent_document_url)) - AssetManagerAttachmentMetadataWorker.drain + visit admin_news_article_path(edition) + force_publish_document + + PublishAttachmentAssetJob.drain end end end diff --git a/test/unit/app/models/policy_group_test.rb b/test/unit/app/models/policy_group_test.rb index a92970c7373..213b6ddaf76 100644 --- a/test/unit/app/models/policy_group_test.rb +++ b/test/unit/app/models/policy_group_test.rb @@ -108,4 +108,34 @@ class PolicyGroupTest < ActiveSupport::TestCase assert_empty policy_group.depended_upon_contacts end + + test "deletes assets belonging to deleted attachments on save" do + first_attachment = create(:file_attachment, ordering: 1) + second_attachment = create(:file_attachment, ordering: 2) + policy_group = FactoryBot.create( + :policy_group, + attachments: [first_attachment, second_attachment], + ) + first_attachment.destroy! + second_attachment.destroy! + + DeleteAttachmentAssetJob.expects(:perform_async).with(first_attachment.attachment_data.id).once + DeleteAttachmentAssetJob.expects(:perform_async).with(second_attachment.attachment_data.id).once + + policy_group.save! + end + + test "does not delete assets belonging to not deleted attachments on save" do + first_attachment = create(:file_attachment, ordering: 1) + second_attachment = create(:file_attachment, ordering: 2) + policy_group = FactoryBot.create( + :policy_group, + attachments: [first_attachment, second_attachment], + ) + + DeleteAttachmentAssetJob.expects(:perform_async).with(first_attachment.attachment_data.id).never + DeleteAttachmentAssetJob.expects(:perform_async).with(second_attachment.attachment_data.id).never + + policy_group.save! + end end diff --git a/test/unit/app/services/asset_manager/asset_updater_test.rb b/test/unit/app/services/asset_manager/asset_updater_test.rb index 398ce4309d7..d694870aa17 100644 --- a/test/unit/app/services/asset_manager/asset_updater_test.rb +++ b/test/unit/app/services/asset_manager/asset_updater_test.rb @@ -20,16 +20,6 @@ class AssetManager::AssetUpdaterTest < ActiveSupport::TestCase @asset_updater.call(@asset_manager_id, { "auth_bypass_ids" => [] }) end - test "warns if asset has been deleted in asset manager and attachment_data isn't deleted" do - @asset_updater.stubs(:find_asset_by_id).with(@asset_manager_id) - .returns("id" => @asset_url, "deleted" => true) - @attachment_data.stubs(:deleted?).returns(false) - - Logger.any_instance.stubs(:warn).with("Asset with asset_manager_id: '#{@asset_manager_id}' expected not to be deleted in Asset Manager").once - - @asset_updater.call(@asset_manager_id, { "draft" => false }) - end - test "does not update asset if no attributes are supplied" do assert_raises(AssetManager::AssetUpdater::AssetAttributesEmpty) do @asset_updater.call(@asset_manager_id, {}) diff --git a/test/unit/app/services/asset_manager/attachment_deleter_test.rb b/test/unit/app/services/asset_manager/attachment_deleter_test.rb deleted file mode 100644 index 5aae8a0bbfb..00000000000 --- a/test/unit/app/services/asset_manager/attachment_deleter_test.rb +++ /dev/null @@ -1,43 +0,0 @@ -require "test_helper" - -class AssetManager::AttachmentDeleterTest < ActiveSupport::TestCase - extend Minitest::Spec::DSL - - describe AssetManager::AttachmentDeleter do - let(:worker) { AssetManager::AttachmentDeleter } - let(:delete_worker) { mock("delete-worker") } - let(:attachment_data) { build(:attachment_data) } - - around do |test| - AssetManager.stub_const(:AssetDeleter, delete_worker) do - test.call - end - end - - before do - attachment_data.stubs(:deleted?).returns(deleted) - end - - context "attachment data is not deleted" do - let(:deleted) { false } - - it "does not delete any assets from Asset Manager" do - delete_worker.expects(:call).never - - worker.call(attachment_data) - - assert AssetManagerDeleteAssetWorker.jobs.empty? - end - end - - context "attachment data is deleted" do - let(:deleted) { true } - - it "deletes attachment asset in Asset Manager" do - delete_worker.expects(:call).with("asset_manager_id") - - worker.call(attachment_data) - end - end - end -end diff --git a/test/unit/app/services/service_listeners/attachment_asset_deleter_test.rb b/test/unit/app/services/service_listeners/attachment_asset_deleter_test.rb new file mode 100644 index 00000000000..40c3e7f020c --- /dev/null +++ b/test/unit/app/services/service_listeners/attachment_asset_deleter_test.rb @@ -0,0 +1,36 @@ +require "test_helper" + +module ServiceListeners + class AttachmentAssetDeleterTest < ActiveSupport::TestCase + extend Minitest::Spec::DSL + + describe ServiceListeners::AttachmentAssetDeleter do + let(:edition) { create(:draft_news_article) } + let(:first_attachment) { create(:file_attachment, attachable: edition, attachment_data: create(:attachment_data, attachable: edition)) } + let(:second_attachment) { create(:file_attachment, attachable: edition, attachment_data: create(:attachment_data, attachable: edition)) } + + before do + stub_asset(first_attachment.attachment_data.assets.first.asset_manager_id) + stub_asset(second_attachment.attachment_data.assets.first.asset_manager_id) + end + + it "calls deleter for all assets of all attachments" do + edition.delete! + edition.delete_all_attachments + + AssetManager::AssetDeleter.expects(:call).with(first_attachment.attachment_data.assets.first.asset_manager_id) + AssetManager::AssetDeleter.expects(:call).with(second_attachment.attachment_data.assets.first.asset_manager_id) + + ServiceListeners::AttachmentAssetDeleter.call(edition) + DeleteAttachmentAssetJob.drain + end + + def stub_asset(asset_manger_id, attributes = {}) + url_id = "http://asset-manager/assets/#{asset_manger_id}" + Services.asset_manager.stubs(:asset) + .with(asset_manger_id) + .returns(attributes.merge(id: url_id).stringify_keys) + end + end + end +end diff --git a/test/unit/app/services/service_listeners/attachment_asset_publisher_test.rb b/test/unit/app/services/service_listeners/attachment_asset_publisher_test.rb new file mode 100644 index 00000000000..311f9001a32 --- /dev/null +++ b/test/unit/app/services/service_listeners/attachment_asset_publisher_test.rb @@ -0,0 +1,41 @@ +require "test_helper" + +module ServiceListeners + class AttachmentAssetPublisherTest < ActiveSupport::TestCase + extend Minitest::Spec::DSL + + describe ServiceListeners::AttachmentAssetPublisher do + let(:edition) { create(:published_news_article) } + let(:attachment) { create(:file_attachment, attachable: edition, attachment_data: create(:attachment_data, attachable: edition)) } + + it "sets the expected attributes" do + expected_attribute_hash = { + "draft" => false, + "parent_document_url" => edition.public_url(draft: false), + } + + AssetManager::AssetUpdater.expects(:call).with(attachment.attachment_data.assets.first.asset_manager_id, expected_attribute_hash) + + ServiceListeners::AttachmentAssetPublisher.call(edition) + PublishAttachmentAssetJob.drain + end + + it "deletes the asset if the attachment is deleted" do + stub_asset(attachment.attachment_data.assets.first.asset_manager_id) + attachment.destroy! + + AssetManager::AssetDeleter.expects(:call).with(attachment.attachment_data.assets.first.asset_manager_id) + + ServiceListeners::AttachmentAssetPublisher.call(edition) + PublishAttachmentAssetJob.drain + end + + def stub_asset(asset_manger_id, attributes = {}) + url_id = "http://asset-manager/assets/#{asset_manger_id}" + Services.asset_manager.stubs(:asset) + .with(asset_manger_id) + .returns(attributes.merge(id: url_id).stringify_keys) + end + end + end +end diff --git a/test/unit/app/sidekiq/asset_manager_attachment_metadata_worker_test.rb b/test/unit/app/sidekiq/asset_manager_attachment_metadata_worker_test.rb index 9c7385588d7..6bda340177a 100644 --- a/test/unit/app/sidekiq/asset_manager_attachment_metadata_worker_test.rb +++ b/test/unit/app/sidekiq/asset_manager_attachment_metadata_worker_test.rb @@ -8,13 +8,9 @@ class AssetManagerAttachmentMetadataWorkerTest < ActiveSupport::TestCase let(:attachment_data) { create(:attachment_data, attachable: edition) } let(:worker) { AssetManagerAttachmentMetadataWorker.new } - it "calls both updater and deleter" do + it "calls updater" do AssetManager::AttachmentUpdater.expects(:call).with(attachment_data) - AssetManager::AttachmentDeleter.expects(:call).with( - attachment_data, - ) - worker.perform(attachment_data.id) end @@ -26,12 +22,6 @@ class AssetManagerAttachmentMetadataWorkerTest < ActiveSupport::TestCase worker.perform(attachment_data.id) end - - it "calls deleter" do - AssetManager::AttachmentDeleter.expects(:call) - - worker.perform(attachment_data.id) - end end end end diff --git a/test/unit/app/sidekiq/delete_attachment_asset_job_test.rb b/test/unit/app/sidekiq/delete_attachment_asset_job_test.rb new file mode 100644 index 00000000000..64a8722aecc --- /dev/null +++ b/test/unit/app/sidekiq/delete_attachment_asset_job_test.rb @@ -0,0 +1,25 @@ +require "test_helper" + +class DeleteAttachmentAssetJobTest < ActiveSupport::TestCase + extend Minitest::Spec::DSL + + describe DeleteAttachmentAssetJob do + let(:attachable) { create(:draft_news_article) } + let(:attachment_data) { create(:attachment_data, attachable:) } + let(:asset_manager_id) { attachment_data.assets.first.asset_manager_id } + let(:worker) { DeleteAttachmentAssetJob.new } + + it "deletes the asset" do + AssetManager::AssetDeleter.expects(:call).with(asset_manager_id) + + worker.perform(attachment_data.id) + end + + it "raises an error if the asset deletion fails for an unknown reason" do + expected_error = GdsApi::HTTPServerError.new(500) + AssetManager::AssetDeleter.expects(:call).raises(expected_error) + + assert_raises(GdsApi::HTTPServerError) { worker.perform(attachment_data.id) } + end + end +end diff --git a/test/unit/app/sidekiq/publish_attachment_asset_job_test.rb b/test/unit/app/sidekiq/publish_attachment_asset_job_test.rb new file mode 100644 index 00000000000..2bb4a435a13 --- /dev/null +++ b/test/unit/app/sidekiq/publish_attachment_asset_job_test.rb @@ -0,0 +1,63 @@ +require "test_helper" + +class PublishAttachmentAssetJobTest < ActiveSupport::TestCase + extend Minitest::Spec::DSL + + describe PublishAttachmentAssetJob do + let(:asset_manager_id) { attachment_data.assets.first.asset_manager_id } + let(:worker) { PublishAttachmentAssetJob.new } + + context "attachment was created on the latest edition" do + let(:attachable) { create(:published_news_article, title: "news-title") } + let(:attachment_data) { create(:attachment_data, attachable:) } + let(:attachment) { create(:file_attachment, attachable:, attachment_data: attachment_data) } + + before do + attachment_data.attachments = [attachment] + attachment_data.save! + end + + it "it deletes and updates the asset if attachment data is deleted" do + attachment.destroy! + + AssetManager::AssetDeleter.expects(:call).with(asset_manager_id) + AssetManager::AssetUpdater.expects(:call).with(asset_manager_id, { "draft" => false, "parent_document_url" => "https://www.test.gov.uk/government/news/news-title" }) + + worker.perform(attachment_data.id) + end + + it "updates the asset if attachment data is not deleted" do + AssetManager::AssetUpdater.expects(:call).with(asset_manager_id, { "draft" => false, "parent_document_url" => "https://www.test.gov.uk/government/news/news-title" }) + + worker.perform(attachment_data.id) + end + end + + context "attachment was created on the previous edition" do + let(:previous_attachable) { create(:superseded_news_article) } + let(:previous_attachment) { create(:attachment, attachable: previous_attachable, attachment_data:) } + let(:attachable) { create(:published_news_article, document: previous_attachable.document) } + let(:attachment_data) { create(:attachment_data, attachable:) } + let(:attachment) { create(:file_attachment, attachable:, attachment_data:) } + + before do + attachment_data.attachments = [previous_attachment, attachment] + attachment_data.save! + end + + it "it deletes the asset if attachment data is deleted" do + attachment.destroy! + + AssetManager::AssetDeleter.expects(:call).with(asset_manager_id) + + worker.perform(attachment_data.id) + end + + it "does not update the asset" do + AssetManager::AssetUpdater.expects(:call).never + + worker.perform(attachment_data.id) + end + end + end +end