add inline block settings editing to page editor
All checks were successful
deploy / deploy (push) Successful in 3m40s

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jamey
2026-02-26 21:47:24 +00:00
parent 660fda928f
commit 3f97742c0b
5 changed files with 548 additions and 85 deletions

View File

@@ -297,4 +297,185 @@ defmodule BerrypodWeb.Admin.PagesTest do
assert has_element?(view, ".block-card-name", "Featured products")
end
end
describe "block settings editing" do
setup %{conn: conn, user: user} do
%{conn: log_in_user(conn, user)}
end
test "edit button shown only for blocks with settings", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/pages/home")
page = Pages.get_page("home")
hero = Enum.at(page.blocks, 0)
category_nav = Enum.at(page.blocks, 1)
# Hero has settings — edit button present
assert has_element?(view, "#block-edit-btn-#{hero["id"]}")
# Category nav has no settings — no edit button
refute has_element?(view, "#block-edit-btn-#{category_nav["id"]}")
end
test "toggle expand shows settings form", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/pages/home")
page = Pages.get_page("home")
hero = Enum.at(page.blocks, 0)
# Settings panel not visible initially
refute has_element?(view, "#block-settings-#{hero["id"]}")
# Click edit to expand
render_click(view, "toggle_expand", %{"id" => hero["id"]})
# Settings panel now visible
assert has_element?(view, "#block-settings-#{hero["id"]}")
assert has_element?(view, "[aria-live='polite']", "Hero banner settings expanded")
end
test "toggle collapse hides settings form", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/pages/home")
page = Pages.get_page("home")
hero = Enum.at(page.blocks, 0)
# Expand then collapse
render_click(view, "toggle_expand", %{"id" => hero["id"]})
assert has_element?(view, "#block-settings-#{hero["id"]}")
render_click(view, "toggle_expand", %{"id" => hero["id"]})
refute has_element?(view, "#block-settings-#{hero["id"]}")
assert has_element?(view, "[aria-live='polite']", "Hero banner settings collapsed")
end
test "aria-expanded reflects toggle state", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/pages/home")
page = Pages.get_page("home")
hero = Enum.at(page.blocks, 0)
assert has_element?(view, "#block-edit-btn-#{hero["id"]}[aria-expanded='false']")
render_click(view, "toggle_expand", %{"id" => hero["id"]})
assert has_element?(view, "#block-edit-btn-#{hero["id"]}[aria-expanded='true']")
end
test "settings form renders fields from schema", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/pages/home")
page = Pages.get_page("home")
hero = Enum.at(page.blocks, 0)
render_click(view, "toggle_expand", %{"id" => hero["id"]})
# Hero has text fields: title, description, cta_text, etc.
assert has_element?(view, "#block-#{hero["id"]}-title")
assert has_element?(view, "#block-#{hero["id"]}-description")
assert has_element?(view, "#block-#{hero["id"]}-cta_text")
# And a select field: variant
assert has_element?(view, "#block-#{hero["id"]}-variant")
end
test "editing settings updates working state and sets dirty", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/pages/home")
page = Pages.get_page("home")
hero = Enum.at(page.blocks, 0)
render_click(view, "toggle_expand", %{"id" => hero["id"]})
# Edit the title
render_change(view, "update_block_settings", %{
"block_id" => hero["id"],
"block_settings" => %{"title" => "New hero title"}
})
# Dirty flag should appear
assert has_element?(view, ".admin-badge-warning", "Unsaved changes")
end
test "edited settings persist after save", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/pages/home")
page = Pages.get_page("home")
hero = Enum.at(page.blocks, 0)
render_click(view, "toggle_expand", %{"id" => hero["id"]})
render_change(view, "update_block_settings", %{
"block_id" => hero["id"],
"block_settings" => %{"title" => "Updated title", "description" => "Updated desc"}
})
render_click(view, "save")
saved = Pages.get_page("home")
saved_hero = Enum.find(saved.blocks, &(&1["type"] == "hero"))
assert saved_hero["settings"]["title"] == "Updated title"
assert saved_hero["settings"]["description"] == "Updated desc"
end
test "number fields are coerced to integers", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/pages/home")
page = Pages.get_page("home")
featured = Enum.find(page.blocks, &(&1["type"] == "featured_products"))
render_click(view, "toggle_expand", %{"id" => featured["id"]})
render_change(view, "update_block_settings", %{
"block_id" => featured["id"],
"block_settings" => %{"product_count" => "4"}
})
render_click(view, "save")
saved = Pages.get_page("home")
saved_featured = Enum.find(saved.blocks, &(&1["type"] == "featured_products"))
assert saved_featured["settings"]["product_count"] == 4
end
test "select fields render with options", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/pages/home")
page = Pages.get_page("home")
hero = Enum.at(page.blocks, 0)
render_click(view, "toggle_expand", %{"id" => hero["id"]})
html = render(view)
# Variant select should have the expected options
assert html =~ "default"
assert html =~ "sunken"
end
test "multiple blocks can be expanded simultaneously", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/pages/home")
page = Pages.get_page("home")
hero = Enum.at(page.blocks, 0)
featured = Enum.find(page.blocks, &(&1["type"] == "featured_products"))
render_click(view, "toggle_expand", %{"id" => hero["id"]})
render_click(view, "toggle_expand", %{"id" => featured["id"]})
assert has_element?(view, "#block-settings-#{hero["id"]}")
assert has_element?(view, "#block-settings-#{featured["id"]}")
end
test "expanded card has expanded class", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/admin/pages/home")
page = Pages.get_page("home")
hero = Enum.at(page.blocks, 0)
refute has_element?(view, "#block-#{hero["id"]}.block-card-expanded")
render_click(view, "toggle_expand", %{"id" => hero["id"]})
assert has_element?(view, "#block-#{hero["id"]}.block-card-expanded")
end
end
end