add admin products list and detail pages
Read-mostly admin views for synced products: filterable/sortable list with inline visibility toggle, and detail page with images grid, variants table, storefront controls form, and provider edit links. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -97,7 +97,7 @@ defmodule SimpleshopThemeWeb.Admin.DashboardTest do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin")
|
||||
|
||||
assert has_element?(view, "a[href='/admin/orders']", "Orders")
|
||||
assert has_element?(view, "a[href='/admin/settings']", "Products")
|
||||
assert has_element?(view, "a[href='/admin/products']", "Products")
|
||||
end
|
||||
|
||||
test "shows zero state for orders", %{conn: conn} do
|
||||
|
||||
190
test/simpleshop_theme_web/live/admin/products_test.exs
Normal file
190
test/simpleshop_theme_web/live/admin/products_test.exs
Normal file
@@ -0,0 +1,190 @@
|
||||
defmodule SimpleshopThemeWeb.Admin.ProductsTest do
|
||||
use SimpleshopThemeWeb.ConnCase, async: false
|
||||
|
||||
import Phoenix.LiveViewTest
|
||||
import SimpleshopTheme.AccountsFixtures
|
||||
import SimpleshopTheme.ProductsFixtures
|
||||
|
||||
setup do
|
||||
user = user_fixture()
|
||||
conn = provider_connection_fixture(%{provider_type: "printify", name: "Test Shop"})
|
||||
product = complete_product_fixture(%{provider_connection: conn})
|
||||
|
||||
%{user: user, connection: conn, product: product}
|
||||
end
|
||||
|
||||
describe "unauthenticated" do
|
||||
test "product list redirects to login", %{conn: conn} do
|
||||
{:error, redirect} = live(conn, ~p"/admin/products")
|
||||
assert {:redirect, %{to: path}} = redirect
|
||||
assert path == ~p"/users/log-in"
|
||||
end
|
||||
|
||||
test "product detail redirects to login", %{conn: conn, product: product} do
|
||||
{:error, redirect} = live(conn, ~p"/admin/products/#{product}")
|
||||
assert {:redirect, %{to: path}} = redirect
|
||||
assert path == ~p"/users/log-in"
|
||||
end
|
||||
end
|
||||
|
||||
describe "product list" do
|
||||
setup %{conn: conn, user: user} do
|
||||
%{conn: log_in_user(conn, user)}
|
||||
end
|
||||
|
||||
test "renders product list", %{conn: conn, product: product} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/products")
|
||||
|
||||
assert html =~ "Products"
|
||||
assert html =~ product.title
|
||||
end
|
||||
|
||||
test "shows provider badge", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/products")
|
||||
|
||||
assert html =~ "Printify"
|
||||
end
|
||||
|
||||
test "shows category", %{conn: conn, product: product} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/products")
|
||||
|
||||
assert html =~ product.category
|
||||
end
|
||||
|
||||
test "links to product detail", %{conn: conn, product: product} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/products")
|
||||
|
||||
assert html =~ ~p"/admin/products/#{product}"
|
||||
end
|
||||
|
||||
test "toggle visibility updates product", %{conn: conn, product: product} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/products")
|
||||
|
||||
assert product.visible
|
||||
|
||||
view
|
||||
|> element("button[phx-value-id='#{product.id}']")
|
||||
|> render_click()
|
||||
|
||||
updated = SimpleshopTheme.Products.get_product(product.id)
|
||||
refute updated.visible
|
||||
end
|
||||
|
||||
test "filters by visibility", %{conn: conn, product: product} do
|
||||
SimpleshopTheme.Products.update_storefront(product, %{visible: false})
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/products")
|
||||
|
||||
html =
|
||||
view
|
||||
|> element("form")
|
||||
|> render_change(%{"visibility" => "hidden"})
|
||||
|
||||
assert html =~ product.title
|
||||
|
||||
html =
|
||||
view
|
||||
|> element("form")
|
||||
|> render_change(%{"visibility" => "visible"})
|
||||
|
||||
refute html =~ product.title
|
||||
end
|
||||
|
||||
test "filters by category", %{conn: conn, product: product} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/products")
|
||||
|
||||
html =
|
||||
view
|
||||
|> element("form")
|
||||
|> render_change(%{"category" => product.category})
|
||||
|
||||
assert html =~ product.title
|
||||
|
||||
html =
|
||||
view
|
||||
|> element("form")
|
||||
|> render_change(%{"category" => "Nonexistent"})
|
||||
|
||||
refute html =~ product.title
|
||||
end
|
||||
|
||||
test "sorts by name", %{conn: conn, product: product} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/products")
|
||||
|
||||
html =
|
||||
view
|
||||
|> element("form")
|
||||
|> render_change(%{"sort" => "name_asc"})
|
||||
|
||||
assert html =~ product.title
|
||||
end
|
||||
|
||||
test "shows empty state when no products", %{conn: conn, product: product} do
|
||||
SimpleshopTheme.Products.delete_product(product)
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/products")
|
||||
|
||||
assert html =~ "No products yet"
|
||||
assert html =~ "Connect a provider"
|
||||
end
|
||||
end
|
||||
|
||||
describe "product detail" do
|
||||
setup %{conn: conn, user: user} do
|
||||
%{conn: log_in_user(conn, user)}
|
||||
end
|
||||
|
||||
test "renders product detail", %{conn: conn, product: product} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/products/#{product}")
|
||||
|
||||
assert html =~ product.title
|
||||
assert html =~ "Details"
|
||||
assert html =~ "Storefront controls"
|
||||
assert html =~ "Variants"
|
||||
end
|
||||
|
||||
test "shows provider link", %{conn: conn, product: product} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/products/#{product}")
|
||||
|
||||
assert html =~ "Edit on Printify"
|
||||
end
|
||||
|
||||
test "shows view on shop link", %{conn: conn, product: product} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/products/#{product}")
|
||||
|
||||
assert html =~ ~p"/products/#{product.slug}"
|
||||
end
|
||||
|
||||
test "shows variant details", %{conn: conn, product: product} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/products/#{product}")
|
||||
|
||||
assert html =~ "£25.00"
|
||||
end
|
||||
|
||||
test "saves storefront changes", %{conn: conn, product: product} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/products/#{product}")
|
||||
|
||||
view
|
||||
|> element("form")
|
||||
|> render_submit(%{"product" => %{"visible" => "false", "category" => "New Category"}})
|
||||
|
||||
updated = SimpleshopTheme.Products.get_product(product.id)
|
||||
refute updated.visible
|
||||
assert updated.category == "New Category"
|
||||
end
|
||||
|
||||
test "redirects on not found", %{conn: conn} do
|
||||
{:error, {:live_redirect, %{to: path}}} =
|
||||
live(conn, "/admin/products/00000000-0000-0000-0000-000000000000")
|
||||
|
||||
assert path == "/admin/products"
|
||||
end
|
||||
|
||||
test "back link navigates to list", %{conn: conn, product: product} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/products/#{product}")
|
||||
|
||||
assert html =~ ~s(href="/admin/products")
|
||||
assert html =~ "Products"
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user