add legal page editor integration and media library polish
Some checks failed
deploy / deploy (push) Has been cancelled
Some checks failed
deploy / deploy (push) Has been cancelled
Legal pages (privacy, delivery, terms) now auto-populate content from shop settings on mount, show auto-generated vs customised badges, and have a regenerate button. Theme editor gains alt text fields for logo, header, and icon images. Image picker in page builder now has an upload button and alt text warning badges. Clearing unused image references shows an orphan info flash. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -252,4 +252,96 @@ defmodule Berrypod.LegalPagesTest do
|
||||
assert List.last(blocks).type == :closing
|
||||
end
|
||||
end
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# regenerate_legal_content/1
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
describe "regenerate_legal_content/1" do
|
||||
test "returns a non-empty string for privacy" do
|
||||
result = LegalPages.regenerate_legal_content("privacy")
|
||||
assert is_binary(result)
|
||||
assert String.length(result) > 100
|
||||
end
|
||||
|
||||
test "returns a non-empty string for delivery" do
|
||||
result = LegalPages.regenerate_legal_content("delivery")
|
||||
assert is_binary(result)
|
||||
assert String.length(result) > 100
|
||||
end
|
||||
|
||||
test "returns a non-empty string for terms" do
|
||||
result = LegalPages.regenerate_legal_content("terms")
|
||||
assert is_binary(result)
|
||||
assert String.length(result) > 100
|
||||
end
|
||||
end
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# rich_text_to_plain/1
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
describe "rich_text_to_plain/1" do
|
||||
test "converts headings to markdown-style" do
|
||||
blocks = [%{type: :heading, text: "Hello"}]
|
||||
assert LegalPages.rich_text_to_plain(blocks) == "## Hello"
|
||||
end
|
||||
|
||||
test "converts paragraphs as-is" do
|
||||
blocks = [%{type: :paragraph, text: "Some text here."}]
|
||||
assert LegalPages.rich_text_to_plain(blocks) == "Some text here."
|
||||
end
|
||||
|
||||
test "converts lists to bullet points" do
|
||||
blocks = [%{type: :list, items: ["One", "Two", "Three"]}]
|
||||
assert LegalPages.rich_text_to_plain(blocks) == "• One\n• Two\n• Three"
|
||||
end
|
||||
|
||||
test "converts lead blocks" do
|
||||
blocks = [%{type: :lead, text: "Important intro"}]
|
||||
assert LegalPages.rich_text_to_plain(blocks) == "Important intro"
|
||||
end
|
||||
|
||||
test "converts updated_at blocks" do
|
||||
blocks = [%{type: :updated_at, date: "28 February 2026"}]
|
||||
assert LegalPages.rich_text_to_plain(blocks) == "Last updated: 28 February 2026"
|
||||
end
|
||||
|
||||
test "joins multiple blocks with double newlines" do
|
||||
blocks = [
|
||||
%{type: :heading, text: "Title"},
|
||||
%{type: :paragraph, text: "Body text."}
|
||||
]
|
||||
|
||||
assert LegalPages.rich_text_to_plain(blocks) == "## Title\n\nBody text."
|
||||
end
|
||||
|
||||
test "skips unknown block types" do
|
||||
blocks = [
|
||||
%{type: :heading, text: "Title"},
|
||||
%{type: :unknown_thing, data: "whatever"},
|
||||
%{type: :paragraph, text: "Body."}
|
||||
]
|
||||
|
||||
assert LegalPages.rich_text_to_plain(blocks) == "## Title\n\nBody."
|
||||
end
|
||||
end
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# legal_slug?/1
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
describe "legal_slug?/1" do
|
||||
test "returns true for legal page slugs" do
|
||||
assert LegalPages.legal_slug?("privacy")
|
||||
assert LegalPages.legal_slug?("delivery")
|
||||
assert LegalPages.legal_slug?("terms")
|
||||
end
|
||||
|
||||
test "returns false for non-legal slugs" do
|
||||
refute LegalPages.legal_slug?("home")
|
||||
refute LegalPages.legal_slug?("about")
|
||||
refute LegalPages.legal_slug?("contact")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1004,6 +1004,66 @@ defmodule BerrypodWeb.Admin.PagesTest do
|
||||
end
|
||||
end
|
||||
|
||||
describe "legal page editor" do
|
||||
setup %{conn: conn, user: user} do
|
||||
%{conn: log_in_user(conn, user)}
|
||||
end
|
||||
|
||||
test "shows regenerate button for privacy page", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/pages/privacy")
|
||||
|
||||
assert has_element?(view, "button[phx-click='regenerate_legal']", "Regenerate")
|
||||
end
|
||||
|
||||
test "shows regenerate button for delivery page", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/pages/delivery")
|
||||
|
||||
assert has_element?(view, "button[phx-click='regenerate_legal']", "Regenerate")
|
||||
end
|
||||
|
||||
test "does not show regenerate button for home page", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/pages/home")
|
||||
|
||||
refute has_element?(view, "button[phx-click='regenerate_legal']")
|
||||
end
|
||||
|
||||
test "shows auto-generated badge for legal pages on mount", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/pages/privacy")
|
||||
|
||||
assert has_element?(view, ".admin-badge-info", "Auto-generated from settings")
|
||||
end
|
||||
|
||||
test "auto-populates content_body on mount for legal pages", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/pages/privacy")
|
||||
|
||||
# The content_body block should be expanded to see the content
|
||||
page = Pages.get_page("privacy")
|
||||
content_body = Enum.find(page.blocks, &(&1["type"] == "content_body"))
|
||||
render_click(view, "toggle_expand", %{"id" => content_body["id"]})
|
||||
|
||||
html = render(view)
|
||||
# Should contain generated legal content
|
||||
assert html =~ "What we collect"
|
||||
end
|
||||
|
||||
test "shows customised badge after manual edit", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/pages/privacy")
|
||||
|
||||
page = Pages.get_page("privacy")
|
||||
content_body = Enum.find(page.blocks, &(&1["type"] == "content_body"))
|
||||
|
||||
render_click(view, "toggle_expand", %{"id" => content_body["id"]})
|
||||
|
||||
render_change(view, "update_block_settings", %{
|
||||
"block_id" => content_body["id"],
|
||||
"block_settings" => %{"content" => "Custom privacy content here"}
|
||||
})
|
||||
|
||||
assert has_element?(view, ".admin-badge", "Customised")
|
||||
refute has_element?(view, ".admin-badge-info", "Auto-generated from settings")
|
||||
end
|
||||
end
|
||||
|
||||
defp count_repeater_items(html) do
|
||||
Regex.scan(~r/class="repeater-item"/, html) |> length()
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user