defmodule BerrypodWeb.Admin.PagesTest do use BerrypodWeb.ConnCase, async: false import Phoenix.LiveViewTest import Berrypod.AccountsFixtures alias Berrypod.Pages alias Berrypod.Pages.PageCache setup do PageCache.invalidate_all() user = user_fixture() %{user: user} end describe "unauthenticated" do test "redirects to login", %{conn: conn} do {:error, redirect} = live(conn, ~p"/admin/pages") assert {:redirect, %{to: path}} = redirect assert path == ~p"/users/log-in" end end describe "page list" do setup %{conn: conn, user: user} do %{conn: log_in_user(conn, user)} end test "renders page list with groups", %{conn: conn} do {:ok, _view, html} = live(conn, ~p"/admin/pages") assert html =~ "Pages" assert html =~ "Marketing" assert html =~ "Legal" assert html =~ "Shop" assert html =~ "Orders" assert html =~ "System" end test "shows all 14 pages", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/admin/pages") assert has_element?(view, ".page-card-title", "Home page") assert has_element?(view, ".page-card-title", "About") assert has_element?(view, ".page-card-title", "Contact") assert has_element?(view, ".page-card-title", "Product page") assert has_element?(view, ".page-card-title", "Error") end test "shows block count per page", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/admin/pages") # Home has 4 default blocks assert has_element?(view, ".page-card-meta", "4 blocks") end test "links to editor", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/admin/pages") view |> element("a[href='/admin/pages/home']") |> render_click() assert_redirect(view, ~p"/admin/pages/home") end end describe "page editor" do setup %{conn: conn, user: user} do %{conn: log_in_user(conn, user)} end test "renders editor with blocks", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/admin/pages/home") assert has_element?(view, ".block-card-name", "Hero banner") assert has_element?(view, ".block-card-name", "Category navigation") assert has_element?(view, ".block-card-name", "Featured products") assert has_element?(view, ".block-card-name", "Image + text") end test "shows position numbers", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/admin/pages/home") assert has_element?(view, ".block-card-position", "1") assert has_element?(view, ".block-card-position", "4") end test "shows back link", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/admin/pages/home") assert has_element?(view, "a[href='/admin/pages']", "Pages") end test "move block up reorders blocks", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/admin/pages/home") # Get the second block (category_nav) and move it up page = Pages.get_page("home") second_block = Enum.at(page.blocks, 1) render_click(view, "move_up", %{"id" => second_block["id"]}) # The ARIA live region announces the move assert has_element?(view, "[aria-live='polite']", "Category navigation moved to position 1") end test "move block down reorders blocks", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/admin/pages/home") page = Pages.get_page("home") first_block = Enum.at(page.blocks, 0) render_click(view, "move_down", %{"id" => first_block["id"]}) # Hero banner should now be at position 2 assert has_element?(view, "[aria-live='polite']", "Hero banner moved to position 2") end test "move up disabled for first block", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/admin/pages/home") page = Pages.get_page("home") first_block = Enum.at(page.blocks, 0) assert has_element?( view, "button[phx-value-id='#{first_block["id"]}'][phx-click='move_up'][disabled]" ) end test "move down disabled for last block", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/admin/pages/home") page = Pages.get_page("home") last_block = Enum.at(page.blocks, -1) assert has_element?( view, "button[phx-value-id='#{last_block["id"]}'][phx-click='move_down'][disabled]" ) end test "remove block", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/admin/pages/home") page = Pages.get_page("home") block = Enum.at(page.blocks, 1) render_click(view, "remove_block", %{"id" => block["id"]}) refute has_element?(view, ".block-card-name", "Category navigation") assert has_element?(view, ".block-card-position", "3") refute has_element?(view, ".block-card-position", "4") end test "duplicate block", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/admin/pages/home") page = Pages.get_page("home") block = Enum.at(page.blocks, 0) render_click(view, "duplicate_block", %{"id" => block["id"]}) # Should now have 5 blocks (position 5 exists) assert has_element?(view, ".block-card-position", "5") assert has_element?(view, "[aria-live='polite']", "Hero banner duplicated") end test "add block via picker", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/admin/pages/home") render_click(view, "show_picker") assert has_element?(view, ".block-picker") render_click(view, "add_block", %{"type" => "trust_badges"}) assert has_element?(view, ".block-card-name", "Trust badges") refute has_element?(view, ".block-picker") end test "picker filter narrows results", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/admin/pages/home") render_click(view, "show_picker") render_keyup(view, "filter_picker", %{"value" => "hero"}) assert has_element?(view, ".block-picker-item", "Hero banner") refute has_element?(view, ".block-picker-item", "Trust badges") end test "picker only shows blocks allowed on page", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/admin/pages/home") render_click(view, "show_picker") assert has_element?(view, ".block-picker-item", "Hero banner") refute has_element?(view, ".block-picker-item", "Product hero") refute has_element?(view, ".block-picker-item", "Cart items") end test "save persists blocks", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/admin/pages/home") page = Pages.get_page("home") block = Enum.at(page.blocks, 1) render_click(view, "remove_block", %{"id" => block["id"]}) render_click(view, "save") assert render(view) =~ "Page saved" saved = Pages.get_page("home") assert length(saved.blocks) == 3 types = Enum.map(saved.blocks, & &1["type"]) refute "category_nav" in types end test "reset to defaults restores original blocks", %{conn: conn} do {:ok, _} = Pages.save_page("home", %{ title: "Home page", blocks: [%{"id" => "blk_test", "type" => "hero", "settings" => %{}}] }) {:ok, view, _html} = live(conn, ~p"/admin/pages/home") # Should show only 1 block assert has_element?(view, ".block-card-position", "1") refute has_element?(view, ".block-card-position", "2") render_click(view, "reset_defaults") assert render(view) =~ "Page reset to defaults" # Should now have 4 default blocks assert has_element?(view, ".block-card-position", "4") end test "dirty flag appears after changes", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/admin/pages/home") refute has_element?(view, ".admin-badge-warning", "Unsaved changes") page = Pages.get_page("home") block = Enum.at(page.blocks, 0) render_click(view, "move_down", %{"id" => block["id"]}) assert has_element?(view, ".admin-badge-warning", "Unsaved changes") end test "dirty flag clears after save", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/admin/pages/home") page = Pages.get_page("home") block = Enum.at(page.blocks, 0) render_click(view, "move_down", %{"id" => block["id"]}) assert has_element?(view, ".admin-badge-warning") render_click(view, "save") refute has_element?(view, ".admin-badge-warning") end test "save button disabled when not dirty", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/admin/pages/home") assert has_element?(view, "button[disabled]", "Save") end end describe "page editor for page-specific pages" do setup %{conn: conn, user: user} do %{conn: log_in_user(conn, user)} end test "PDP editor shows PDP blocks", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/admin/pages/pdp") assert has_element?(view, ".block-card-name", "Breadcrumb") assert has_element?(view, ".block-card-name", "Product hero") assert has_element?(view, ".block-card-name", "Trust badges") end test "PDP picker shows PDP-specific blocks", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/admin/pages/pdp") render_click(view, "show_picker") assert has_element?(view, ".block-picker-item", "Product hero") assert has_element?(view, ".block-picker-item", "Hero banner") refute has_element?(view, ".block-picker-item", "Cart items") end test "error page editor works", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/admin/pages/error") assert has_element?(view, ".block-card-name", "Hero banner") assert has_element?(view, ".block-card-name", "Featured products") end end end