add generic page renderer with block dispatch
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,15 @@
|
||||
defmodule Berrypod.PagesTest do
|
||||
use Berrypod.DataCase, async: true
|
||||
use Berrypod.DataCase, async: false
|
||||
|
||||
alias Berrypod.Pages
|
||||
alias Berrypod.Pages.{Page, BlockTypes, Defaults, PageCache}
|
||||
|
||||
setup do
|
||||
# Clear cached pages between tests so save_page side effects don't leak
|
||||
PageCache.invalidate_all()
|
||||
:ok
|
||||
end
|
||||
|
||||
describe "get_page/1" do
|
||||
test "returns defaults when nothing in DB" do
|
||||
page = Pages.get_page("home")
|
||||
|
||||
242
test/berrypod_web/page_renderer_test.exs
Normal file
242
test/berrypod_web/page_renderer_test.exs
Normal file
@@ -0,0 +1,242 @@
|
||||
defmodule BerrypodWeb.PageRendererTest do
|
||||
use BerrypodWeb.ConnCase, async: false
|
||||
|
||||
import Phoenix.LiveViewTest
|
||||
|
||||
alias Berrypod.Pages
|
||||
alias Berrypod.Settings.ThemeSettings
|
||||
alias BerrypodWeb.PageRenderer
|
||||
|
||||
# Minimal assigns that every page needs (the stuff shop_layout requires)
|
||||
defp base_assigns do
|
||||
%{
|
||||
__changed__: nil,
|
||||
theme_settings: %ThemeSettings{},
|
||||
logo_image: nil,
|
||||
header_image: nil,
|
||||
mode: :shop,
|
||||
cart_items: [],
|
||||
cart_count: 0,
|
||||
cart_subtotal: "£0.00",
|
||||
cart_total: nil,
|
||||
cart_drawer_open: false,
|
||||
cart_status: nil,
|
||||
is_admin: false,
|
||||
search_query: "",
|
||||
search_results: [],
|
||||
search_open: false,
|
||||
categories: [],
|
||||
shipping_estimate: nil,
|
||||
country_code: "GB",
|
||||
available_countries: [],
|
||||
flash: %{}
|
||||
}
|
||||
end
|
||||
|
||||
defp render_page(slug, extra_assigns \\ %{}) do
|
||||
page = Pages.get_page(slug)
|
||||
|
||||
assigns =
|
||||
base_assigns()
|
||||
|> Map.merge(extra_assigns)
|
||||
|> Map.put(:page, page)
|
||||
|
||||
PageRenderer.render_page(assigns)
|
||||
|> rendered_to_string()
|
||||
end
|
||||
|
||||
describe "render_page/1" do
|
||||
test "home page renders hero and featured products" do
|
||||
html = render_page("home", %{products: []})
|
||||
|
||||
assert html =~ "Original designs, printed on demand"
|
||||
assert html =~ "Shop the collection"
|
||||
assert html =~ "Featured products"
|
||||
assert html =~ "Made with passion, printed with care"
|
||||
end
|
||||
|
||||
test "about page renders hero and content area" do
|
||||
html =
|
||||
render_page("about", %{content_blocks: [%{type: :paragraph, text: "Test about text"}]})
|
||||
|
||||
assert html =~ "About the studio"
|
||||
assert html =~ "content-body"
|
||||
end
|
||||
|
||||
test "delivery page renders hero" do
|
||||
html = render_page("delivery", %{content_blocks: []})
|
||||
|
||||
assert html =~ "Delivery information"
|
||||
end
|
||||
|
||||
test "privacy page renders hero" do
|
||||
html = render_page("privacy", %{content_blocks: []})
|
||||
|
||||
assert html =~ "Privacy policy"
|
||||
end
|
||||
|
||||
test "terms page renders hero" do
|
||||
html = render_page("terms", %{content_blocks: []})
|
||||
|
||||
assert html =~ "Terms & conditions"
|
||||
end
|
||||
|
||||
test "contact page renders hero, form, and sidebar blocks" do
|
||||
html = render_page("contact", %{tracking_state: :idle})
|
||||
|
||||
assert html =~ "Get in touch"
|
||||
assert html =~ "Send a message"
|
||||
assert html =~ "Track your order"
|
||||
assert html =~ "Handy to know"
|
||||
assert html =~ "Newsletter"
|
||||
end
|
||||
|
||||
test "collection page renders header, filter bar, and grid" do
|
||||
html = render_page("collection", %{products: [], collection_title: "All Products"})
|
||||
|
||||
assert html =~ "All Products"
|
||||
assert html =~ "filter-bar"
|
||||
end
|
||||
|
||||
test "pdp page renders breadcrumb and product hero when product provided" do
|
||||
product = %{
|
||||
id: "test-id",
|
||||
title: "Test Product",
|
||||
slug: "test-product",
|
||||
category: "Art Prints",
|
||||
description: "A lovely test product",
|
||||
cheapest_price: 2500,
|
||||
compare_at_price: nil,
|
||||
on_sale: false,
|
||||
in_stock: true,
|
||||
provider_data: %{}
|
||||
}
|
||||
|
||||
html =
|
||||
render_page("pdp", %{
|
||||
product: product,
|
||||
gallery_images: [],
|
||||
display_price: 2500,
|
||||
selected_variant: nil,
|
||||
option_types: [],
|
||||
selected_options: %{},
|
||||
available_options: %{},
|
||||
option_urls: %{},
|
||||
quantity: 1,
|
||||
related_products: [],
|
||||
reviews: [],
|
||||
average_rating: 5,
|
||||
total_count: 0
|
||||
})
|
||||
|
||||
assert html =~ "Art Prints"
|
||||
assert html =~ "Test Product"
|
||||
assert html =~ "pdp-grid"
|
||||
assert html =~ "Add to basket"
|
||||
end
|
||||
|
||||
test "cart page renders empty state when no items" do
|
||||
html = render_page("cart")
|
||||
|
||||
assert html =~ "Your basket"
|
||||
assert html =~ "cart-empty"
|
||||
end
|
||||
|
||||
test "cart page renders items when present" do
|
||||
items = [
|
||||
%{
|
||||
variant_id: "v1",
|
||||
name: "Test T-Shirt",
|
||||
variant: "Black / M",
|
||||
price: 2500,
|
||||
quantity: 1,
|
||||
image: nil,
|
||||
product_id: "test-t-shirt",
|
||||
in_stock: true
|
||||
}
|
||||
]
|
||||
|
||||
html =
|
||||
render_page("cart", %{
|
||||
cart_items: items,
|
||||
cart_count: 1,
|
||||
cart_subtotal: "£25.00",
|
||||
cart_page_subtotal: 2500
|
||||
})
|
||||
|
||||
assert html =~ "Your basket"
|
||||
assert html =~ "cart-page-list"
|
||||
end
|
||||
|
||||
test "search page renders search form" do
|
||||
html = render_page("search", %{search_page_query: "", search_page_results: []})
|
||||
|
||||
assert html =~ "Search"
|
||||
assert html =~ ~s(name="q")
|
||||
assert html =~ "Search products..."
|
||||
end
|
||||
|
||||
test "checkout success renders pending state when no order" do
|
||||
html = render_page("checkout_success", %{order: nil})
|
||||
|
||||
assert html =~ "Processing your payment"
|
||||
end
|
||||
|
||||
test "orders page renders empty state when orders nil" do
|
||||
html = render_page("orders", %{orders: nil, lookup_email: nil})
|
||||
|
||||
assert html =~ "Your orders"
|
||||
assert html =~ "expired or is invalid"
|
||||
end
|
||||
|
||||
test "orders page renders no orders message" do
|
||||
html = render_page("orders", %{orders: [], lookup_email: "test@example.com"})
|
||||
|
||||
assert html =~ "test@example.com"
|
||||
assert html =~ "No orders found"
|
||||
end
|
||||
|
||||
test "order detail page renders nothing when no order" do
|
||||
html = render_page("order_detail", %{order: nil})
|
||||
|
||||
# Should not crash, just render empty
|
||||
assert html =~ "main"
|
||||
end
|
||||
|
||||
test "error page renders error hero" do
|
||||
html =
|
||||
render_page("error", %{
|
||||
error_code: "404",
|
||||
error_title: "Page not found",
|
||||
error_description: "Sorry, we couldn't find that page.",
|
||||
products: []
|
||||
})
|
||||
|
||||
assert html =~ "404"
|
||||
assert html =~ "Page not found"
|
||||
assert html =~ "Go to Homepage"
|
||||
end
|
||||
end
|
||||
|
||||
describe "page_main_class/1" do
|
||||
test "returns correct classes for each page" do
|
||||
assert PageRenderer.page_main_class("contact") == "page-container contact-main"
|
||||
assert PageRenderer.page_main_class("cart") == "page-container"
|
||||
assert PageRenderer.page_main_class("checkout_success") == "page-container checkout-main"
|
||||
assert PageRenderer.page_main_class("orders") == "page-container orders-main"
|
||||
assert PageRenderer.page_main_class("order_detail") == "page-container order-detail-main"
|
||||
assert PageRenderer.page_main_class("error") == "error-main"
|
||||
assert PageRenderer.page_main_class("about") == "content-page"
|
||||
assert PageRenderer.page_main_class("home") == nil
|
||||
end
|
||||
end
|
||||
|
||||
describe "format_order_status/1" do
|
||||
test "maps status strings to display text" do
|
||||
assert PageRenderer.format_order_status("unfulfilled") == "Being prepared"
|
||||
assert PageRenderer.format_order_status("shipped") == "On its way"
|
||||
assert PageRenderer.format_order_status("delivered") == "Delivered"
|
||||
assert PageRenderer.format_order_status("unknown") == "unknown"
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user