make PDP variant selection work without JS
All checks were successful
deploy / deploy (push) Successful in 1m3s

Variant options (colour, size) are now URL params handled via
handle_params instead of phx-click events. Swatches and size buttons
render as patch links in shop mode, so changing variants works as
plain navigation without JS. Quantity is now a number input that
submits with the form. Unavailable variants render as disabled spans.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jamey
2026-02-25 01:08:36 +00:00
parent a61adf4939
commit 23e95a3de6
6 changed files with 238 additions and 75 deletions

View File

@@ -211,30 +211,62 @@ defmodule BerrypodWeb.Shop.ProductShowTest do
assert html =~ "Size"
end
test "selecting a size updates the price", %{conn: conn, print: print} do
test "variant buttons are links for no-JS fallback", %{conn: conn, print: print} do
{:ok, view, _html} = live(conn, ~p"/products/#{print.slug}")
assert has_element?(view, "a.size-btn", "18x24")
end
test "selecting a size via link updates the price", %{conn: conn, print: print} do
{:ok, view, _html} = live(conn, ~p"/products/#{print.slug}")
html =
view
|> element("button[phx-value-selected='18x24']")
|> element("a.size-btn", "18x24")
|> render_click()
assert html =~ "£32.00"
end
test "selecting a size via URL params updates the price", %{conn: conn, print: print} do
{:ok, _view, html} = live(conn, ~p"/products/#{print.slug}?Size=18x24")
assert html =~ "£32.00"
end
test "selecting a colour auto-adjusts size if needed", %{conn: conn, shirt: shirt} do
{:ok, view, _html} = live(conn, ~p"/products/#{shirt.slug}")
# Select White — M and L are available, XL is not
html =
view
|> element("button[aria-label='Select White']")
|> element("a[aria-label='Select White']")
|> render_click()
# White is selected, size M should still be selected (valid combo)
assert html =~ ~s(aria-pressed="true")
end
test "invalid variant combo auto-corrects", %{conn: conn, shirt: shirt} do
# White/XL is unavailable — should auto-adjust to a valid combo
{:ok, _view, html} = live(conn, ~p"/products/#{shirt.slug}?Color=White&Size=XL")
assert html =~ "£29.99"
end
test "unknown option values fall back to default", %{conn: conn, print: print} do
{:ok, _view, html} = live(conn, ~p"/products/#{print.slug}?Size=XXXL")
# Falls back to default variant (8x10 at £19.99)
assert html =~ "£19.99"
end
test "unavailable variant rendered as disabled span", %{conn: conn, shirt: shirt} do
{:ok, view, _html} = live(conn, ~p"/products/#{shirt.slug}?Color=White")
assert has_element?(view, "span.size-btn[aria-disabled='true']", "XL")
end
test "shows variant for single-variant product", %{conn: conn, related: related} do
{:ok, _view, html} = live(conn, ~p"/products/#{related.slug}")
@@ -244,6 +276,15 @@ defmodule BerrypodWeb.Shop.ProductShowTest do
end
describe "Quantity selector" do
test "quantity is a number input for no-JS fallback", %{conn: conn, print: print} do
{:ok, view, _html} = live(conn, ~p"/products/#{print.slug}")
assert has_element?(
view,
"form[phx-submit='add_to_cart'] input[type='number'][name='quantity']"
)
end
test "renders quantity selector with initial value of 1", %{conn: conn, print: print} do
{:ok, view, _html} = live(conn, ~p"/products/#{print.slug}")
@@ -308,7 +349,11 @@ defmodule BerrypodWeb.Shop.ProductShowTest do
test "add to basket button is a submit button inside the form", %{conn: conn, print: print} do
{:ok, view, _html} = live(conn, ~p"/products/#{print.slug}")
assert has_element?(view, "form[phx-submit='add_to_cart'] button[type='submit']", "Add to basket")
assert has_element?(
view,
"form[phx-submit='add_to_cart'] button[type='submit']",
"Add to basket"
)
end
test "add to cart opens the cart drawer", %{conn: conn, print: print} do