Skip to content

Commit

Permalink
Add a GeneratePreviewHtml service
Browse files Browse the repository at this point in the history
We will use this service in the next commit, splitting up
the responsibility for generating the HTML from fetching
content/metadata and generating the HTML.
  • Loading branch information
pezholio committed Jan 10, 2025
1 parent 49eb6b0 commit 0e09a2f
Show file tree
Hide file tree
Showing 2 changed files with 181 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
require "net/http"
require "json"
require "uri"

module ContentBlockManager
class GeneratePreviewHtml
include ContentBlockManager::Engine.routes.url_helpers

def initialize(content_id:, content_block_edition:, base_path:)
@content_id = content_id
@content_block_edition = content_block_edition
@base_path = base_path
end

def call
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).to_s
end

private

BLOCK_STYLE = "background-color: yellow;".freeze
ERROR_HTML = "<html><body><p>Preview not found</p></body></html>".freeze

attr_reader :content_block_edition, :content_id, :base_path

def frontend_path
frontend_base_path + base_path
end

def frontend_base_path
Rails.env.development? ? Plek.external_url_for("government-frontend") : Plek.website_root
end

def html_snapshot_from_frontend(uri)
begin
raw_html = Net::HTTP.get(uri)
rescue StandardError
raw_html = ERROR_HTML
end
Nokogiri::HTML.parse(raw_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 add_draft_style(nokogiri_html)
nokogiri_html.css("body").each do |body|
body["class"] ||= ""
body["class"] += " draft"
end
nokogiri_html
end

def replace_existing_content_blocks(nokogiri_html)
replace_blocks(nokogiri_html)
style_blocks(nokogiri_html)
nokogiri_html
end

def replace_blocks(nokogiri_html)
content_block_spans(nokogiri_html).each do |span|
span.replace content_block_edition.render
end
end

def style_blocks(nokogiri_html)
content_block_spans(nokogiri_html).each do |span|
span["style"] = BLOCK_STYLE
end
end

def content_block_spans(nokogiri_html)
nokogiri_html.css("span[data-content-id=\"#{@content_block_edition.document.content_id}\"]")
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
require "test_helper"

class ContentBlockManager::GeneratePreviewHtmlTest < ActiveSupport::TestCase
extend Minitest::Spec::DSL
include ContentBlockManager::Engine.routes.url_helpers
include TextAssertions

let(:host_content_id) { SecureRandom.uuid }
let(:preview_content_id) { SecureRandom.uuid }
let(:host_title) { "Test" }
let(:host_base_path) { "/test" }
let(:uri_mock) { mock }
let(:fake_frontend_response) do
"<body class=\"govuk-body\"><p>test</p><span class=\"content-embed content-embed__content_block_email_address\" data-content-block=\"\" data-document-type=\"content_block_email_address\" data-content-id=\"#{preview_content_id}\">[email protected]</span></body>"
end
let(:block_render) do
"<span class=\"content-embed content-embed__content_block_email_address\" data-content-block=\"\" data-document-type=\"content_block_email_address\" data-content-id=\"#{preview_content_id}\">[email protected]</span>"
end
let(:block_render_with_style) do
"<span class=\"content-embed content-embed__content_block_email_address\" data-content-block=\"\" data-document-type=\"content_block_email_address\" data-content-id=\"#{preview_content_id}\" style=\"background-color: yellow;\">[email protected]</span>"
end
let(:expected_html) do
"<body class=\"govuk-body draft\"><p>test</p>#{block_render_with_style}</body>"
end
let(:error_html) do
"<html><body class=\" draft\"><p>Preview not found</p></body></html>"
end
let(:document) do
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" => "[email protected]" }, id: 1)
end

it "returns the preview html" do
Net::HTTP.expects(:get).with(URI(Plek.website_root + host_base_path)).returns(fake_frontend_response)

expected_content = Nokogiri::HTML.parse(expected_html).to_s

actual_content = ContentBlockManager::GeneratePreviewHtml.new(
content_id: host_content_id,
content_block_edition: block_to_preview,
base_path: host_base_path,
).call

assert_equal expected_content, actual_content
end

it "shows an error template when the request to the frontend throws an error" do
exception = StandardError.new("Something went wrong")
Net::HTTP.expects(:get).with(URI(Plek.website_root + host_base_path)).raises(exception)

expected_content = Nokogiri::HTML.parse(error_html).to_s

actual_content = ContentBlockManager::GeneratePreviewHtml.new(
content_id: host_content_id,
content_block_edition: block_to_preview,
base_path: host_base_path,
).call

assert_equal expected_content, actual_content
end

it "updates any link paths" do
fake_frontend_response = "
<a href='/foo'>Internal link</a>
<a href='https://example.com'>External link</a>
<a href='//example.com'>Protocol relative link</a>
"
Net::HTTP.expects(:get).with(URI(Plek.website_root + host_base_path)).returns(fake_frontend_response)

actual_content = ContentBlockManager::GeneratePreviewHtml.new(
content_id: host_content_id,
content_block_edition: block_to_preview,
base_path: host_base_path,
).call

url = content_block_manager_content_block_host_content_preview_path(id: block_to_preview.id, host_content_id:)

expected_content = Nokogiri::HTML.parse("
<html>
<body class=' draft'>
<a href='#{url}?base_path=/foo' target='_parent'>Internal link</a>
<a href='https://example.com'>External link</a>
<a href='//example.com'>Protocol relative link</a>
</body>
</html>
").to_s

assert_equal_ignoring_whitespace actual_content.to_s, expected_content
end
end

0 comments on commit 0e09a2f

Please sign in to comment.