From 7be726756c4ff836d81eac3797b1dd070171432e Mon Sep 17 00:00:00 2001 From: pezholio Date: Mon, 9 Dec 2024 09:27:16 +0000 Subject: [PATCH 1/4] Update local link paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This ensures that any local links that we click on within the frame reload the host content endpoint with a param pointing to the original path. In the next commit, we’ll allow that path to be optionally loaded --- .../get_preview_content.rb | 15 +++++++++ .../app/services/get_preview_content_test.rb | 32 ++++++++++++++++++- test/support/text_assertions.rb | 7 ++++ 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/lib/engines/content_block_manager/app/services/content_block_manager/get_preview_content.rb b/lib/engines/content_block_manager/app/services/content_block_manager/get_preview_content.rb index f51fd5a88f1..b7c9938a68b 100644 --- a/lib/engines/content_block_manager/app/services/content_block_manager/get_preview_content.rb +++ b/lib/engines/content_block_manager/app/services/content_block_manager/get_preview_content.rb @@ -4,6 +4,8 @@ module ContentBlockManager class GetPreviewContent + include ContentBlockManager::Engine.routes.url_helpers + def self.for_content_id(content_id:, content_block_edition:) new(content_id:, content_block_edition:).for_content_id end @@ -41,10 +43,23 @@ def frontend_path def preview_html uri = URI(frontend_path) nokogiri_html = html_snapshot_from_frontend(uri) + update_local_link_paths(nokogiri_html) add_draft_style(nokogiri_html) replace_existing_content_blocks(nokogiri_html) end + def update_local_link_paths(nokogiri_html) + url = content_block_manager_content_block_host_content_preview_path(id: @content_block_edition.id, host_content_id: @content_id) + nokogiri_html.css("a").each do |link| + next if link[:href].start_with?("//") || link[:href].start_with?("http") + + link[:href] = "#{url}?base_path=#{link[:href]}" + link[:target] = "_parent" + end + + nokogiri_html + end + def replace_existing_content_blocks(nokogiri_html) replace_blocks(nokogiri_html) style_blocks(nokogiri_html) diff --git a/lib/engines/content_block_manager/test/unit/app/services/get_preview_content_test.rb b/lib/engines/content_block_manager/test/unit/app/services/get_preview_content_test.rb index 03b76556d08..8a7575810b7 100644 --- a/lib/engines/content_block_manager/test/unit/app/services/get_preview_content_test.rb +++ b/lib/engines/content_block_manager/test/unit/app/services/get_preview_content_test.rb @@ -2,6 +2,8 @@ class ContentBlockManager::GetPreviewContentTest < ActiveSupport::TestCase extend Minitest::Spec::DSL + include ContentBlockManager::Engine.routes.url_helpers + include TextAssertions let(:described_class) { ContentBlockManager::GetPreviewContent } let(:host_content_id) { SecureRandom.uuid } @@ -28,7 +30,7 @@ class ContentBlockManager::GetPreviewContentTest < ActiveSupport::TestCase build(:content_block_document, :email_address, content_id: preview_content_id) end let(:block_to_preview) do - build(:content_block_edition, :email_address, document:, details: { "email_address" => "new@new.com" }) + build(:content_block_edition, :email_address, document:, details: { "email_address" => "new@new.com" }, id: 1) end describe "#for_content_id" do @@ -99,5 +101,33 @@ class ContentBlockManager::GetPreviewContentTest < ActiveSupport::TestCase assert_equal expected_content[:title], actual_content.title assert_equal expected_content[:html].to_s, actual_content.html.to_s end + + it "updates any link paths" do + fake_frontend_response = " + Internal link + External link + Protocol relative link + " + Net::HTTP.expects(:get).with(URI(Plek.website_root + host_base_path)).returns(fake_frontend_response) + + actual_content = ContentBlockManager::GetPreviewContent.for_content_id( + content_id: host_content_id, + content_block_edition: block_to_preview, + ) + + url = content_block_manager_content_block_host_content_preview_path(id: block_to_preview.id, host_content_id:) + + expected_content = Nokogiri::HTML.parse(" + + + Internal link + External link + Protocol relative link + + + ").to_s + + assert_equal_ignoring_whitespace actual_content.html.to_s, expected_content + end end end diff --git a/test/support/text_assertions.rb b/test/support/text_assertions.rb index e0a7e1a1a24..0d14c5bd1e5 100644 --- a/test/support/text_assertions.rb +++ b/test/support/text_assertions.rb @@ -2,4 +2,11 @@ module TextAssertions def assert_string_includes(expected, actual) assert actual.include?(expected), "Expected \"#{actual}\" to include \"#{expected}\"." end + + def assert_equal_ignoring_whitespace(expected, actual) + expected_without_whitespace = expected.gsub(/\s+/, "").strip + actual_without_whitespace = actual.gsub(/\s+/, "").strip + + assert_equal expected_without_whitespace, actual_without_whitespace + end end From 3d930a9854ec9dc00630ded19a0034046d6194e6 Mon Sep 17 00:00:00 2001 From: pezholio Date: Mon, 9 Dec 2024 10:06:01 +0000 Subject: [PATCH 2/4] Allow base path to be customised This allows custom paths to be passed in and loaded when a user clicks on a link within a preview. --- .../content_block_manager/get_preview_content.rb | 13 +++++++++---- .../unit/app/services/get_preview_content_test.rb | 11 +++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lib/engines/content_block_manager/app/services/content_block_manager/get_preview_content.rb b/lib/engines/content_block_manager/app/services/content_block_manager/get_preview_content.rb index b7c9938a68b..328094a39ba 100644 --- a/lib/engines/content_block_manager/app/services/content_block_manager/get_preview_content.rb +++ b/lib/engines/content_block_manager/app/services/content_block_manager/get_preview_content.rb @@ -6,8 +6,8 @@ module ContentBlockManager class GetPreviewContent include ContentBlockManager::Engine.routes.url_helpers - def self.for_content_id(content_id:, content_block_edition:) - new(content_id:, content_block_edition:).for_content_id + def self.for_content_id(content_id:, content_block_edition:, base_path: nil) + new(content_id:, content_block_edition:, base_path:).for_content_id end def for_content_id @@ -16,9 +16,10 @@ def for_content_id private - def initialize(content_id:, content_block_edition:) + def initialize(content_id:, content_block_edition:, base_path: nil) @content_id = content_id @content_block_edition = content_block_edition + @base_path = base_path end def html @@ -36,8 +37,12 @@ def frontend_base_path Rails.env.development? ? Plek.external_url_for("government-frontend") : Plek.website_root end + def base_path + @base_path || content_item["base_path"] + end + def frontend_path - frontend_base_path + content_item["base_path"] + frontend_base_path + base_path end def preview_html diff --git a/lib/engines/content_block_manager/test/unit/app/services/get_preview_content_test.rb b/lib/engines/content_block_manager/test/unit/app/services/get_preview_content_test.rb index 8a7575810b7..b2cf63a7443 100644 --- a/lib/engines/content_block_manager/test/unit/app/services/get_preview_content_test.rb +++ b/lib/engines/content_block_manager/test/unit/app/services/get_preview_content_test.rb @@ -129,5 +129,16 @@ class ContentBlockManager::GetPreviewContentTest < ActiveSupport::TestCase assert_equal_ignoring_whitespace actual_content.html.to_s, expected_content end + + it "allows a base_path to be provided" do + base_path = "something/different" + Net::HTTP.expects(:get).with(URI(Plek.website_root + base_path)).returns("") + + ContentBlockManager::GetPreviewContent.for_content_id( + content_id: host_content_id, + content_block_edition: block_to_preview, + base_path:, + ) + end end end From 1e3c075dec2187794e584be04542e6525280a090 Mon Sep 17 00:00:00 2001 From: pezholio Date: Mon, 9 Dec 2024 10:17:57 +0000 Subject: [PATCH 3/4] Allow base_path to be passed in from params This will allow any local pages (e.g. multi-page guides etc) to be rendered via the `GetPreviewContent` service --- .../editions/host_content_controller.rb | 6 ++++- .../features/edit_object.feature | 2 ++ .../content_block_manager_steps.rb | 23 ++++++++++++++++++- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/engines/content_block_manager/app/controllers/content_block_manager/content_block/editions/host_content_controller.rb b/lib/engines/content_block_manager/app/controllers/content_block_manager/content_block/editions/host_content_controller.rb index c02c9410624..ad046c5bb77 100644 --- a/lib/engines/content_block_manager/app/controllers/content_block_manager/content_block/editions/host_content_controller.rb +++ b/lib/engines/content_block_manager/app/controllers/content_block_manager/content_block/editions/host_content_controller.rb @@ -2,6 +2,10 @@ class ContentBlockManager::ContentBlock::Editions::HostContentController < Conte def preview host_content_id = params[:host_content_id] @content_block_edition = ContentBlockManager::ContentBlock::Edition.find(params[:id]) - @preview_content = ContentBlockManager::GetPreviewContent.for_content_id(content_id: host_content_id, content_block_edition: @content_block_edition) + @preview_content = ContentBlockManager::GetPreviewContent.for_content_id( + content_id: host_content_id, + content_block_edition: @content_block_edition, + base_path: params[:base_path], + ) end end diff --git a/lib/engines/content_block_manager/features/edit_object.feature b/lib/engines/content_block_manager/features/edit_object.feature index 24ad0ef4f01..c6bb071834e 100644 --- a/lib/engines/content_block_manager/features/edit_object.feature +++ b/lib/engines/content_block_manager/features/edit_object.feature @@ -108,3 +108,5 @@ Feature: Edit a content object And I see the rollup data for the dependent content When I click on the first host document Then the preview page opens in a new tab + When I click on a link within the frame + Then I should see the content of the linked page diff --git a/lib/engines/content_block_manager/features/step_definitions/content_block_manager_steps.rb b/lib/engines/content_block_manager/features/step_definitions/content_block_manager_steps.rb index 69ecacf5cc9..6a1e80c1c58 100644 --- a/lib/engines/content_block_manager/features/step_definitions/content_block_manager_steps.rb +++ b/lib/engines/content_block_manager/features/step_definitions/content_block_manager_steps.rb @@ -558,7 +558,15 @@ def should_show_edit_form_for_email_address_content_block(document_title, email_ Plek.website_root + @current_host_document["base_path"], ).to_return( status: 200, - body: "

#{@current_host_document['title']}

iframe preview

#{@content_block.render}", + body: "

#{@current_host_document['title']}

iframe preview Link to other page

#{@content_block.render}", + ) + + stub_request( + :get, + "#{Plek.website_root}/other-page", + ).to_return( + status: 200, + body: "

#{@current_host_document['title']}

other page

#{@content_block.render}", ) click_on @current_host_document["title"] @@ -574,6 +582,19 @@ def should_show_edit_form_for_email_address_content_block(document_title, email_ end end +When("I click on a link within the frame") do + within_frame "preview" do + click_on "Link to other page" + end +end + +Then("I should see the content of the linked page") do + within_frame "preview" do + assert_text "other page" + assert_text "changed@example.com" + end +end + When(/^I save and continue$/) do click_save_and_continue end From d8c2cad7d11420636bc2f07ae963cbfd09937f17 Mon Sep 17 00:00:00 2001 From: pezholio Date: Mon, 9 Dec 2024 13:24:09 +0000 Subject: [PATCH 4/4] Get instances from Publishing API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In some circumstances (such as guides), instances can be over multiple pages, so we can’t reliably get the number of instances from the preview, so we need to get the metadata directly from the Publishing API --- .../content_block_manager/get_preview_content.rb | 7 ++++++- .../content_block_manager_steps.rb | 4 ++++ .../features/support/dependent_content.rb | 5 +++++ .../unit/app/services/get_preview_content_test.rb | 15 ++++++++++----- 4 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 lib/engines/content_block_manager/features/support/dependent_content.rb diff --git a/lib/engines/content_block_manager/app/services/content_block_manager/get_preview_content.rb b/lib/engines/content_block_manager/app/services/content_block_manager/get_preview_content.rb index 328094a39ba..427cc524963 100644 --- a/lib/engines/content_block_manager/app/services/content_block_manager/get_preview_content.rb +++ b/lib/engines/content_block_manager/app/services/content_block_manager/get_preview_content.rb @@ -90,8 +90,13 @@ def content_block_spans(nokogiri_html) nokogiri_html.css("span[data-content-id=\"#{@content_block_edition.document.content_id}\"]") end + def metadata + response = Services.publishing_api.get_host_content_item_for_content_id(@content_block_edition.document.content_id, @content_id) + response.parsed_content + end + def instances_count - content_block_spans(html).length + metadata["instances"] end ERROR_HTML = "

Preview not found

".freeze diff --git a/lib/engines/content_block_manager/features/step_definitions/content_block_manager_steps.rb b/lib/engines/content_block_manager/features/step_definitions/content_block_manager_steps.rb index 6a1e80c1c58..05682b4f4ce 100644 --- a/lib/engines/content_block_manager/features/step_definitions/content_block_manager_steps.rb +++ b/lib/engines/content_block_manager/features/step_definitions/content_block_manager_steps.rb @@ -1,4 +1,5 @@ require_relative "../support/stubs" +require_relative "../support/dependent_content" # Suppress noisy Sidekiq logging in the test output Sidekiq.configure_client do |cfg| @@ -478,6 +479,7 @@ def should_show_edit_form_for_email_address_content_block(document_title, email_ "last_edited_by_editor_id" => SecureRandom.uuid, "last_edited_at" => 2.days.ago.to_s, "host_content_id" => "abc12345", + "instances" => 1, "primary_publishing_organisation" => { "content_id" => SecureRandom.uuid, "title" => "Organisation #{i}", @@ -494,6 +496,8 @@ def should_show_edit_form_for_email_address_content_block(document_title, email_ order: ContentBlockManager::GetHostContentItems::DEFAULT_ORDER, rollup: @rollup, ) + + stub_publishing_api_has_embedded_content_details(@dependent_content.first) end Then(/^I should see the dependent content listed$/) do diff --git a/lib/engines/content_block_manager/features/support/dependent_content.rb b/lib/engines/content_block_manager/features/support/dependent_content.rb new file mode 100644 index 00000000000..9543b97f65c --- /dev/null +++ b/lib/engines/content_block_manager/features/support/dependent_content.rb @@ -0,0 +1,5 @@ +def stub_publishing_api_has_embedded_content_details(dependent_content) + url = %r{\A#{GdsApi::TestHelpers::PublishingApi::PUBLISHING_API_V2_ENDPOINT}/content/[0-9a-fA-F-]{36}/host-content/#{dependent_content['host_content_id']}} + stub_request(:get, url) + .to_return(body: dependent_content.to_json) +end diff --git a/lib/engines/content_block_manager/test/unit/app/services/get_preview_content_test.rb b/lib/engines/content_block_manager/test/unit/app/services/get_preview_content_test.rb index b2cf63a7443..edd2cb8a50b 100644 --- a/lib/engines/content_block_manager/test/unit/app/services/get_preview_content_test.rb +++ b/lib/engines/content_block_manager/test/unit/app/services/get_preview_content_test.rb @@ -32,6 +32,15 @@ class ContentBlockManager::GetPreviewContentTest < ActiveSupport::TestCase let(:block_to_preview) do build(:content_block_edition, :email_address, document:, details: { "email_address" => "new@new.com" }, id: 1) end + let(:metadata_response) do + stub(:response, parsed_content: { "instances" => 2 }) + end + + before do + Services.publishing_api.expects(:get_host_content_item_for_content_id) + .with(block_to_preview.document.content_id, host_content_id) + .returns(metadata_response) + end describe "#for_content_id" do setup do @@ -57,16 +66,12 @@ class ContentBlockManager::GetPreviewContentTest < ActiveSupport::TestCase it "returns the count of instances" do Net::HTTP.expects(:get).with(URI(Plek.website_root + host_base_path)).returns(fake_frontend_response) - expected_content = { - instances_count: 1, - } - actual_content = ContentBlockManager::GetPreviewContent.for_content_id( content_id: host_content_id, content_block_edition: block_to_preview, ) - assert_equal expected_content[:instances_count], actual_content.instances_count + assert_equal 2, actual_content.instances_count end it "returns the preview html" do