add page builder polish: utility blocks, templates, duplicate
All checks were successful
deploy / deploy (push) Successful in 1m24s

New block types: spacer, divider, button/CTA, video embed (YouTube,
Vimeo with privacy-enhanced embeds, fallback for unknown URLs).

Page templates (blank, content, landing) shown when creating custom
pages. Duplicate page action on admin index with slug deduplication.

Fix block picker on shop edit sidebar being cut off on mobile by
accounting for bottom nav and making the grid scrollable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jamey
2026-02-28 17:33:25 +00:00
parent 69ccc625b2
commit 3336b3aa26
10 changed files with 686 additions and 2 deletions

View File

@@ -231,6 +231,130 @@ defmodule BerrypodWeb.PageRendererTest do
end
end
describe "utility blocks" do
setup do
on_exit(fn ->
import Ecto.Query
Berrypod.Repo.delete_all(from p in Berrypod.Pages.Page, where: p.slug == "home")
Berrypod.Pages.PageCache.invalidate_all()
end)
:ok
end
test "spacer block renders with size" do
{:ok, _} =
Pages.save_page("home", %{
title: "Home",
blocks: [%{"id" => "blk_sp", "type" => "spacer", "settings" => %{"size" => "large"}}]
})
html = render_page("home", %{products: []})
assert html =~ ~s(class="block-spacer")
assert html =~ ~s(data-size="large")
end
test "divider block renders with style" do
{:ok, _} =
Pages.save_page("home", %{
title: "Home",
blocks: [%{"id" => "blk_dv", "type" => "divider", "settings" => %{"style" => "dots"}}]
})
html = render_page("home", %{products: []})
assert html =~ ~s(class="block-divider")
assert html =~ ~s(data-style="dots")
end
test "button block renders themed link" do
{:ok, _} =
Pages.save_page("home", %{
title: "Home",
blocks: [
%{
"id" => "blk_btn",
"type" => "button",
"settings" => %{
"text" => "Shop now",
"href" => "/collections/all",
"style" => "primary",
"alignment" => "centre"
}
}
]
})
html = render_page("home", %{products: []})
assert html =~ "Shop now"
assert html =~ ~s(data-align="centre")
assert html =~ "themed-button"
end
test "video embed renders YouTube iframe" do
{:ok, _} =
Pages.save_page("home", %{
title: "Home",
blocks: [
%{
"id" => "blk_vid",
"type" => "video_embed",
"settings" => %{
"url" => "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"caption" => "Demo video"
}
}
]
})
html = render_page("home", %{products: []})
assert html =~ "youtube-nocookie.com/embed/dQw4w9WgXcQ"
assert html =~ "Demo video"
assert html =~ "video-embed"
end
test "video embed renders Vimeo iframe" do
{:ok, _} =
Pages.save_page("home", %{
title: "Home",
blocks: [
%{
"id" => "blk_vim",
"type" => "video_embed",
"settings" => %{"url" => "https://vimeo.com/123456789"}
}
]
})
html = render_page("home", %{products: []})
assert html =~ "player.vimeo.com/video/123456789"
end
test "video embed shows fallback link for unknown URLs" do
{:ok, _} =
Pages.save_page("home", %{
title: "Home",
blocks: [
%{
"id" => "blk_unk",
"type" => "video_embed",
"settings" => %{"url" => "https://example.com/video", "caption" => "My video"}
}
]
})
html = render_page("home", %{products: []})
assert html =~ "video-embed-fallback"
assert html =~ "My video"
refute html =~ "<iframe"
end
end
describe "format_order_status/1" do
test "maps status strings to display text" do
assert PageRenderer.format_order_status("unfulfilled") == "Being prepared"