Skip to content

Commit

Permalink
Merge pull request #9635 from alphagov/content-modelling/647-show-emb…
Browse files Browse the repository at this point in the history
…ed-codes-in-inline-preview

(647) Support embed codes in inline preview
  • Loading branch information
pezholio authored Nov 21, 2024
2 parents 14abc3c + 50acb8b commit 17a27f4
Show file tree
Hide file tree
Showing 8 changed files with 227 additions and 72 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ gem "bootsnap", require: false
gem "carrierwave"
gem "carrierwave-i18n"
gem "chronic"
gem "content_block_tools"
gem "dalli"
gem "dartsass-rails"
gem "diffy"
Expand Down
3 changes: 3 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ GEM
coderay (1.1.3)
concurrent-ruby (1.3.4)
connection_pool (2.4.1)
content_block_tools (0.3.0)
actionview (>= 6, < 7.2.2)
crack (1.0.0)
bigdecimal
rexml
Expand Down Expand Up @@ -1028,6 +1030,7 @@ DEPENDENCIES
carrierwave-i18n
chronic
climate_control
content_block_tools
cucumber
cucumber-rails
dalli
Expand Down
3 changes: 2 additions & 1 deletion app/helpers/admin/admin_govspeak_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ module Admin::AdminGovspeakHelper
def govspeak_to_admin_html(govspeak, images = [], attachments = [], alternative_format_contact_email = nil)
images = prepare_images(images)
attachments = prepare_attachments(attachments, alternative_format_contact_email)
wrapped_in_govspeak_div(bare_govspeak_to_admin_html(govspeak, images, attachments))
html = ContentBlockManager::FindAndReplaceEmbedCodesService.call bare_govspeak_to_admin_html(govspeak, images, attachments)
wrapped_in_govspeak_div(html)
end

def govspeak_edition_to_admin_html(edition)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,24 @@ class Edition < ApplicationRecord
include ValidatesDetails
include Workflow

scope :current_versions, lambda {
joins(
"LEFT JOIN content_block_documents document ON document.latest_edition_id = content_block_editions.id",
).where(state: "published")
}

def update_document_reference_to_latest_edition!
document.update!(latest_edition_id: id)
end

def render
ContentBlockTools::ContentBlock.new(
document_type: "content_block_#{block_type}",
content_id: document.content_id,
title:,
details:,
).render
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module ContentBlockManager
class FindAndReplaceEmbedCodesService
def self.call(html)
new(html).call
end

def call
embed_content_references.each do |reference|
content_block = content_blocks.find { |c| c.document.content_id == reference.content_id }
next if content_block.nil?

html.gsub!(reference.embed_code, content_block.render)
end

html
end

private

attr_reader :html

def initialize(html)
@html = html
end

def embed_content_references
@embed_content_references ||= ContentBlockTools::ContentBlockReference.find_all_in_document(html)
end

def content_blocks
@content_blocks ||= ContentBlockManager::ContentBlock::Edition.current_versions
.where(document: { content_id: embed_content_references.map(&:content_id) })
end
end
end
Original file line number Diff line number Diff line change
@@ -1,122 +1,161 @@
require "test_helper"

class ContentBlockManager::ContentBlockEditionTest < ActiveSupport::TestCase
setup do
@new_content_id = SecureRandom.uuid
ContentBlockManager::ContentBlock::Edition.any_instance.stubs(:create_random_id).returns(@new_content_id)

@created_at = Time.zone.local(2000, 12, 31, 23, 59, 59).utc
@updated_at = Time.zone.local(2000, 12, 31, 23, 59, 59).utc
@details = { "some_field" => "some_content" }
@title = "Document title"
@creator = create(:user)
@organisation = create(:organisation)

@content_block_edition = ContentBlockManager::ContentBlock::Edition.new(
created_at: @created_at,
updated_at: @updated_at,
details: @details,
extend Minitest::Spec::DSL

let(:new_content_id) { SecureRandom.uuid }

let(:created_at) { Time.zone.local(2000, 12, 31, 23, 59, 59).utc }
let(:updated_at) { Time.zone.local(2000, 12, 31, 23, 59, 59).utc }
let(:details) { { "some_field" => "some_content" } }
let(:title) { "Document title" }
let(:creator) { create(:user) }
let(:organisation) { create(:organisation) }

let(:content_block_edition) do
ContentBlockManager::ContentBlock::Edition.new(
created_at:,
updated_at:,
details:,
document_attributes: {
block_type: "email_address",
title: @title,
title:,
},
creator: @creator,
organisation_id: @organisation.id.to_s,
creator:,
organisation_id: organisation.id.to_s,
)
@content_block_edition.stubs(:schema).returns(build(:content_block_schema))
end

test "content_block_edition exists with required data" do
@content_block_edition.save!
@content_block_edition.reload
before do
ContentBlockManager::ContentBlock::Edition.any_instance.stubs(:create_random_id).returns(new_content_id)
content_block_edition.stubs(:schema).returns(build(:content_block_schema))
end

it "exists with required data" do
content_block_edition.save!
content_block_edition.reload

assert_equal @created_at, @content_block_edition.created_at
assert_equal @updated_at, @content_block_edition.updated_at
assert_equal @details, @content_block_edition.details
assert_equal created_at, content_block_edition.created_at
assert_equal updated_at, content_block_edition.updated_at
assert_equal details, content_block_edition.details
end

test "it persists the block type to the document" do
@content_block_edition.save!
@content_block_edition.reload
document = @content_block_edition.document
it "persists the block type to the document" do
content_block_edition.save!
content_block_edition.reload
document = content_block_edition.document

assert_equal document.block_type, @content_block_edition.block_type
assert_equal document.block_type, content_block_edition.block_type
end

test "it persists the title to the document" do
@content_block_edition.save!
@content_block_edition.reload
document = @content_block_edition.document
it "persists the title to the document" do
content_block_edition.save!
content_block_edition.reload
document = content_block_edition.document

assert_equal document.title, @content_block_edition.title
assert_equal document.title, content_block_edition.title
end

test "it creates a document" do
@content_block_edition.save!
@content_block_edition.reload
it "creates a document" do
content_block_edition.save!
content_block_edition.reload

assert_not_nil @content_block_edition.document
assert_equal @content_block_edition.document.content_id, @new_content_id
assert_not_nil content_block_edition.document
assert_equal content_block_edition.document.content_id, new_content_id
end

test "it adds a content id if a document is provided" do
@content_block_edition.document = build(:content_block_document, :email_address, content_id: nil)
@content_block_edition.save!
@content_block_edition.reload
it "adds a content id if a document is provided" do
content_block_edition.document = build(:content_block_document, :email_address, content_id: nil)
content_block_edition.save!
content_block_edition.reload

assert_not_nil @content_block_edition.document
assert_equal @content_block_edition.document.content_id, @new_content_id
assert_not_nil content_block_edition.document
assert_equal content_block_edition.document.content_id, new_content_id
end

test "it validates the presence of a document block_type" do
@content_block_edition = build(
it "validates the presence of a document block_type" do
content_block_edition = build(
:content_block_edition,
created_at: @created_at,
updated_at: @updated_at,
details: @details,
created_at:,
updated_at:,
details:,
document_attributes: {
block_type: nil,
},
organisation_id: @organisation.id.to_s,
organisation_id: organisation.id.to_s,
)

assert_invalid @content_block_edition
assert @content_block_edition.errors.full_messages.include?("Document block type can't be blank")
assert_invalid content_block_edition
assert content_block_edition.errors.full_messages.include?("Document block type can't be blank")
end

test "it validates the presence of a document title" do
it "validates the presence of a document title" do
content_block_edition = build(
:content_block_edition,
created_at: @created_at,
updated_at: @updated_at,
details: @details,
created_at:,
updated_at:,
details:,
document_attributes: {
title: nil,
},
organisation_id: @organisation.id.to_s,
organisation_id: organisation.id.to_s,
)

assert_invalid content_block_edition
assert content_block_edition.errors.full_messages.include?("Title can't be blank")
end

test "it adds a creator and first edition author for new records" do
@content_block_edition.save!
@content_block_edition.reload
assert_equal @content_block_edition.creator, @content_block_edition.edition_authors.first.user
it "adds a creator and first edition author for new records" do
content_block_edition.save!
content_block_edition.reload
assert_equal content_block_edition.creator, content_block_edition.edition_authors.first.user
end

describe "#creator=" do
it "raises an exception if called for a persisted record" do
content_block_edition.save!
assert_raise RuntimeError do
content_block_edition.creator = create(:user)
end
end
end

test "#creator= raises an exception if called for a persisted record" do
@content_block_edition.save!
assert_raise RuntimeError do
@content_block_edition.creator = create(:user)
describe "#update_document_reference_to_latest_edition!" do
it "updates the document reference to the latest edition" do
latest_edition = create(:content_block_edition, document: content_block_edition.document)
latest_edition.update_document_reference_to_latest_edition!

assert_equal latest_edition.document.latest_edition_id, latest_edition.id
end
end

test "#update_document_reference_to_latest_edition! updates the document reference to the latest edition" do
latest_edition = create(:content_block_edition, document: @content_block_edition.document)
latest_edition.update_document_reference_to_latest_edition!
describe ".current_versions" do
it "returns current published versions" do
document = create(:content_block_document, :email_address)
edition = create(:content_block_edition, :email_address, state: "published", document:)
draft_edition = create(:content_block_edition, :email_address, state: "draft", document:)
document.latest_edition = draft_edition
document.save!

assert_equal ContentBlockManager::ContentBlock::Edition.current_versions.to_a, [edition]
end
end

assert_equal latest_edition.document.latest_edition_id, latest_edition.id
describe "#render" do
let(:rendered_response) { "RENDERED" }
let(:stub_block) { stub("ContentBlockTools::ContentBlock", render: rendered_response) }
let(:document) { content_block_edition.document }

it "initializes and renders a content block" do
ContentBlockTools::ContentBlock.expects(:new)
.with(
document_type: "content_block_#{document.block_type}",
content_id: document.content_id,
title:,
details:,
).returns(stub_block)

assert_equal content_block_edition.render, rendered_response
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
require "test_helper"

class ContentBlockManager::FindAndReplaceEmbedCodesServiceTest < ActiveSupport::TestCase
extend Minitest::Spec::DSL

it "finds and replaces embed codes" do
document_1 = create(:content_block_document, :email_address)
edition_1 = create(:content_block_edition, :email_address, state: "published", document: document_1)
document_1.latest_edition = edition_1
document_1.save!

document_2 = create(:content_block_document, :email_address)
edition_2 = create(:content_block_edition, :email_address, state: "published", document: document_2)
document_2.latest_edition = edition_2
document_2.save!

html = """
<p>Hello there</p>
<p>#{edition_2.document.embed_code}</p>
<p>#{edition_1.document.embed_code}</p>
"""

expected = """
<p>Hello there</p>
<p>#{edition_2.render}</p>
<p>#{edition_1.render}</p>
"""

result = ContentBlockManager::FindAndReplaceEmbedCodesService.call(html)

assert_equal result, expected
end

it "ignores blocks that aren't present in the database" do
edition = build(:content_block_edition, :email_address)

html = edition.document.embed_code

result = ContentBlockManager::FindAndReplaceEmbedCodesService.call(html)
assert_equal result, html
end

it "ignores blocks that don't have a live version" do
edition = create(:content_block_edition, :email_address, state: "draft")

html = edition.document.embed_code

result = ContentBlockManager::FindAndReplaceEmbedCodesService.call(html)
assert_equal result, html
end
end
10 changes: 10 additions & 0 deletions test/unit/app/helpers/admin/admin_govspeak_helper_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,14 @@ class Admin::AdminGovspeakHelperTest < ActionView::TestCase
assert_equivalent_html "<div class=\"govspeak\">#{contact_html}</div>", govspeak_to_admin_html(input)
end
end

test "should call the embed codes helper" do
input = "Here is some Govspeak"
expected = "Expected output"
ContentBlockManager::FindAndReplaceEmbedCodesService.expects(:call).with(
bare_govspeak_to_admin_html(input, [], []),
).returns(expected)

assert_equivalent_html "<div class=\"govspeak\">#{expected}</div>", govspeak_to_admin_html(input)
end
end

0 comments on commit 17a27f4

Please sign in to comment.