add integration tests for product, cart and home pages
37 new LiveView integration tests covering the three previously untested shop pages. Product detail tests cover variant selection, price updates and add-to-cart. Cart tests use DB fixtures with session seeding for hydration. Home tests cover hero, categories, featured products and navigation links. 612 total tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
111
test/simpleshop_theme_web/live/shop_live/cart_test.exs
Normal file
111
test/simpleshop_theme_web/live/shop_live/cart_test.exs
Normal file
@@ -0,0 +1,111 @@
|
||||
defmodule SimpleshopThemeWeb.ShopLive.CartTest do
|
||||
use SimpleshopThemeWeb.ConnCase, async: false
|
||||
|
||||
import Phoenix.LiveViewTest
|
||||
|
||||
alias SimpleshopTheme.ProductsFixtures
|
||||
|
||||
defp create_cart_with_product(_context) do
|
||||
product = ProductsFixtures.complete_product_fixture(%{title: "Test Art Print"})
|
||||
variant = List.first(product.variants)
|
||||
%{product: product, variant: variant}
|
||||
end
|
||||
|
||||
defp conn_with_cart(conn, variant_id, qty \\ 1) do
|
||||
conn
|
||||
|> Phoenix.ConnTest.init_test_session(%{"cart" => [{variant_id, qty}]})
|
||||
end
|
||||
|
||||
describe "Empty cart" do
|
||||
test "renders empty cart state", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/cart")
|
||||
|
||||
assert html =~ "Your basket"
|
||||
assert html =~ "Your basket is empty"
|
||||
end
|
||||
|
||||
test "shows continue shopping link when empty", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/cart")
|
||||
|
||||
assert html =~ "Continue shopping"
|
||||
end
|
||||
end
|
||||
|
||||
describe "Cart with items" do
|
||||
setup [:create_cart_with_product]
|
||||
|
||||
test "displays cart item name", %{conn: conn, product: product, variant: variant} do
|
||||
{:ok, _view, html} = conn |> conn_with_cart(variant.id) |> live(~p"/cart")
|
||||
|
||||
assert html =~ product.title
|
||||
end
|
||||
|
||||
test "displays order summary", %{conn: conn, variant: variant} do
|
||||
{:ok, _view, html} = conn |> conn_with_cart(variant.id) |> live(~p"/cart")
|
||||
|
||||
assert html =~ "Order summary"
|
||||
assert html =~ "Subtotal"
|
||||
end
|
||||
|
||||
test "displays formatted subtotal", %{conn: conn, variant: variant} do
|
||||
{:ok, _view, html} = conn |> conn_with_cart(variant.id) |> live(~p"/cart")
|
||||
|
||||
assert html =~ SimpleshopTheme.Cart.format_price(variant.price)
|
||||
end
|
||||
|
||||
test "displays checkout button", %{conn: conn, variant: variant} do
|
||||
{:ok, _view, html} = conn |> conn_with_cart(variant.id) |> live(~p"/cart")
|
||||
|
||||
assert html =~ "Checkout"
|
||||
end
|
||||
|
||||
test "incrementing quantity updates the display", %{
|
||||
conn: conn,
|
||||
product: product,
|
||||
variant: variant
|
||||
} do
|
||||
{:ok, view, _html} = conn |> conn_with_cart(variant.id) |> live(~p"/cart")
|
||||
|
||||
html =
|
||||
view
|
||||
|> element("button[aria-label='Increase quantity of #{product.title}']")
|
||||
|> render_click()
|
||||
|
||||
assert html =~ "Quantity updated to 2"
|
||||
end
|
||||
|
||||
test "decrementing to zero removes the item", %{
|
||||
conn: conn,
|
||||
product: product,
|
||||
variant: variant
|
||||
} do
|
||||
{:ok, view, _html} = conn |> conn_with_cart(variant.id) |> live(~p"/cart")
|
||||
|
||||
html =
|
||||
view
|
||||
|> element("button[aria-label='Decrease quantity of #{product.title}']")
|
||||
|> render_click()
|
||||
|
||||
assert html =~ "Your basket is empty"
|
||||
end
|
||||
|
||||
test "remove button removes the item", %{conn: conn, product: product, variant: variant} do
|
||||
{:ok, view, _html} = conn |> conn_with_cart(variant.id) |> live(~p"/cart")
|
||||
|
||||
html =
|
||||
view
|
||||
|> element("#main-content button[aria-label='Remove #{product.title} from cart']")
|
||||
|> render_click()
|
||||
|
||||
assert html =~ "Your basket is empty"
|
||||
end
|
||||
end
|
||||
|
||||
describe "Cart page title" do
|
||||
test "page title is Cart", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/cart")
|
||||
|
||||
assert html =~ "<title>Cart</title>"
|
||||
end
|
||||
end
|
||||
end
|
||||
89
test/simpleshop_theme_web/live/shop_live/home_test.exs
Normal file
89
test/simpleshop_theme_web/live/shop_live/home_test.exs
Normal file
@@ -0,0 +1,89 @@
|
||||
defmodule SimpleshopThemeWeb.ShopLive.HomeTest do
|
||||
use SimpleshopThemeWeb.ConnCase, async: false
|
||||
|
||||
import Phoenix.LiveViewTest
|
||||
|
||||
alias SimpleshopTheme.Theme.PreviewData
|
||||
|
||||
describe "Home page" do
|
||||
test "renders the home page", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/")
|
||||
|
||||
assert html =~ "Original designs, printed on demand"
|
||||
end
|
||||
|
||||
test "renders hero section with CTA", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/")
|
||||
|
||||
assert html =~ "Shop the collection"
|
||||
end
|
||||
|
||||
test "renders category navigation", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/")
|
||||
|
||||
categories = PreviewData.categories()
|
||||
|
||||
for category <- Enum.take(categories, 3) do
|
||||
assert html =~ category.name
|
||||
end
|
||||
end
|
||||
|
||||
test "renders featured products section", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/")
|
||||
|
||||
assert html =~ "Featured products"
|
||||
|
||||
products = PreviewData.products()
|
||||
first_product = List.first(products)
|
||||
|
||||
assert html =~ first_product.name
|
||||
end
|
||||
|
||||
test "renders image and text section", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/")
|
||||
|
||||
assert html =~ "Made with passion, printed with care"
|
||||
assert html =~ "Learn more about the studio"
|
||||
end
|
||||
|
||||
test "renders header with shop name", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/")
|
||||
|
||||
# Header should be present (part of shop_layout)
|
||||
assert html =~ "SimpleShop"
|
||||
end
|
||||
|
||||
test "renders footer with links", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/")
|
||||
|
||||
assert html =~ ~s(href="/about")
|
||||
assert html =~ ~s(href="/contact")
|
||||
end
|
||||
end
|
||||
|
||||
describe "Navigation links" do
|
||||
test "category links point to collections", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/")
|
||||
|
||||
assert html =~ ~s(href="/collections/)
|
||||
end
|
||||
|
||||
test "product links point to product pages", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/")
|
||||
|
||||
assert html =~ ~s(href="/products/)
|
||||
end
|
||||
|
||||
test "hero CTA links to collections", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/")
|
||||
|
||||
assert html =~ ~s(href="/collections/all")
|
||||
end
|
||||
|
||||
test "about link in image section", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/")
|
||||
|
||||
assert html =~ ~s(href="/about")
|
||||
end
|
||||
end
|
||||
end
|
||||
155
test/simpleshop_theme_web/live/shop_live/product_show_test.exs
Normal file
155
test/simpleshop_theme_web/live/shop_live/product_show_test.exs
Normal file
@@ -0,0 +1,155 @@
|
||||
defmodule SimpleshopThemeWeb.ShopLive.ProductShowTest do
|
||||
use SimpleshopThemeWeb.ConnCase, async: false
|
||||
|
||||
import Phoenix.LiveViewTest
|
||||
|
||||
alias SimpleshopTheme.Theme.PreviewData
|
||||
|
||||
describe "Product detail page" do
|
||||
test "renders product page with product name", %{conn: conn} do
|
||||
product = List.first(PreviewData.products())
|
||||
{:ok, _view, html} = live(conn, ~p"/products/#{product.id}")
|
||||
|
||||
assert html =~ product.name
|
||||
end
|
||||
|
||||
test "renders product description", %{conn: conn} do
|
||||
product = List.first(PreviewData.products())
|
||||
{:ok, _view, html} = live(conn, ~p"/products/#{product.id}")
|
||||
|
||||
assert html =~ product.description
|
||||
end
|
||||
|
||||
test "renders product price", %{conn: conn} do
|
||||
product = List.first(PreviewData.products())
|
||||
{:ok, _view, html} = live(conn, ~p"/products/#{product.id}")
|
||||
|
||||
assert html =~ SimpleshopTheme.Cart.format_price(product.price)
|
||||
end
|
||||
|
||||
test "renders breadcrumb with Home link", %{conn: conn} do
|
||||
product = List.first(PreviewData.products())
|
||||
{:ok, _view, html} = live(conn, ~p"/products/#{product.id}")
|
||||
|
||||
assert html =~ "Home"
|
||||
assert html =~ ~s(href="/")
|
||||
end
|
||||
|
||||
test "renders breadcrumb with category link", %{conn: conn} do
|
||||
product = List.first(PreviewData.products())
|
||||
{:ok, _view, html} = live(conn, ~p"/products/#{product.id}")
|
||||
|
||||
assert html =~ product.category
|
||||
end
|
||||
|
||||
test "renders add to cart button", %{conn: conn} do
|
||||
product = List.first(PreviewData.products())
|
||||
{:ok, _view, html} = live(conn, ~p"/products/#{product.id}")
|
||||
|
||||
assert html =~ "Add to basket"
|
||||
end
|
||||
|
||||
test "renders related products section", %{conn: conn} do
|
||||
product = List.first(PreviewData.products())
|
||||
{:ok, _view, html} = live(conn, ~p"/products/#{product.id}")
|
||||
|
||||
# Should show other products, not the current one
|
||||
other_product = Enum.at(PreviewData.products(), 1)
|
||||
assert html =~ other_product.name
|
||||
end
|
||||
end
|
||||
|
||||
describe "Variant selection" do
|
||||
test "renders variant selectors for product with options", %{conn: conn} do
|
||||
# Product "1" (Mountain Sunrise Art Print) has Size options
|
||||
{:ok, _view, html} = live(conn, ~p"/products/1")
|
||||
|
||||
assert html =~ "Size"
|
||||
assert html =~ "8×10"
|
||||
assert html =~ "12×18"
|
||||
assert html =~ "18×24"
|
||||
end
|
||||
|
||||
test "renders color and size selectors for apparel", %{conn: conn} do
|
||||
# Product "6" (Forest Silhouette T-Shirt) has Color and Size options
|
||||
{:ok, _view, html} = live(conn, ~p"/products/6")
|
||||
|
||||
assert html =~ "Color"
|
||||
assert html =~ "Size"
|
||||
end
|
||||
|
||||
test "selecting a size updates the price", %{conn: conn} do
|
||||
# Product "1" has variants: 8×10 = £19.99, 12×18 = £24.00, 18×24 = £32.00
|
||||
{:ok, view, _html} = live(conn, ~p"/products/1")
|
||||
|
||||
html =
|
||||
view
|
||||
|> element("button[phx-value-value='18×24']")
|
||||
|> render_click()
|
||||
|
||||
assert html =~ "£32.00"
|
||||
end
|
||||
|
||||
test "selecting a colour updates available sizes", %{conn: conn} do
|
||||
# Product "6": White / XL and White / 2XL are unavailable
|
||||
{:ok, view, _html} = live(conn, ~p"/products/6")
|
||||
|
||||
html =
|
||||
view
|
||||
|> element("button[aria-label='Select White']")
|
||||
|> render_click()
|
||||
|
||||
# XL should be disabled (unavailable in White)
|
||||
assert html =~ "disabled"
|
||||
end
|
||||
|
||||
test "shows 'One size' for products without options", %{conn: conn} do
|
||||
# Product "2" (Ocean Waves Art Print) has no option_types
|
||||
{:ok, _view, html} = live(conn, ~p"/products/2")
|
||||
|
||||
assert html =~ "One size"
|
||||
end
|
||||
end
|
||||
|
||||
describe "Add to cart" do
|
||||
test "add to cart opens the cart drawer", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/products/1")
|
||||
|
||||
html =
|
||||
view
|
||||
|> element("button", "Add to basket")
|
||||
|> render_click()
|
||||
|
||||
# Cart drawer should now be open (the aria live region gets updated)
|
||||
assert html =~ "added to cart"
|
||||
end
|
||||
|
||||
test "add to cart updates cart count", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/products/1")
|
||||
|
||||
html =
|
||||
view
|
||||
|> element("button", "Add to basket")
|
||||
|> render_click()
|
||||
|
||||
# The cart drawer should show the item
|
||||
assert html =~ "Mountain Sunrise Art Print"
|
||||
end
|
||||
end
|
||||
|
||||
describe "Navigation" do
|
||||
test "product links navigate to correct product page", %{conn: conn} do
|
||||
product = Enum.at(PreviewData.products(), 1)
|
||||
{:ok, _view, html} = live(conn, ~p"/products/#{product.id}")
|
||||
|
||||
assert html =~ product.name
|
||||
end
|
||||
|
||||
test "falls back to first product for unknown ID", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/products/nonexistent")
|
||||
|
||||
first_product = List.first(PreviewData.products())
|
||||
assert html =~ first_product.name
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user