rename project from SimpleshopTheme to Berrypod
All modules, configs, paths, and references updated. 836 tests pass, zero warnings. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
117
test/berrypod_web/live/admin/dashboard_test.exs
Normal file
117
test/berrypod_web/live/admin/dashboard_test.exs
Normal file
@@ -0,0 +1,117 @@
|
||||
defmodule BerrypodWeb.Admin.DashboardTest do
|
||||
use BerrypodWeb.ConnCase, async: false
|
||||
|
||||
import Phoenix.LiveViewTest
|
||||
import Berrypod.AccountsFixtures
|
||||
import Berrypod.OrdersFixtures
|
||||
import Berrypod.ProductsFixtures
|
||||
|
||||
setup do
|
||||
user = user_fixture()
|
||||
%{user: user}
|
||||
end
|
||||
|
||||
describe "unauthenticated" do
|
||||
test "redirects to login", %{conn: conn} do
|
||||
{:error, redirect} = live(conn, ~p"/admin")
|
||||
assert {:redirect, %{to: path}} = redirect
|
||||
assert path == ~p"/users/log-in"
|
||||
end
|
||||
end
|
||||
|
||||
describe "setup stepper" do
|
||||
setup %{conn: conn, user: user} do
|
||||
%{conn: log_in_user(conn, user)}
|
||||
end
|
||||
|
||||
test "shows stepper with printify form when nothing connected", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin")
|
||||
|
||||
assert html =~ "Setup steps"
|
||||
assert html =~ "Connect to Printify"
|
||||
assert html =~ "Printify API token"
|
||||
assert html =~ "Connect Stripe"
|
||||
assert html =~ "Go live"
|
||||
end
|
||||
|
||||
test "shows stripe form when printify is done", %{conn: conn} do
|
||||
conn_fixture = provider_connection_fixture(%{provider_type: "printify"})
|
||||
_product = product_fixture(%{provider_connection: conn_fixture})
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/admin")
|
||||
|
||||
# Printify step should be completed
|
||||
assert has_element?(view, "li:first-child [class*='bg-green-500']")
|
||||
# Stripe step should be active with form
|
||||
assert has_element?(view, "label", "Secret key")
|
||||
end
|
||||
|
||||
test "shows go live button when all services connected", %{conn: conn} do
|
||||
conn_fixture = provider_connection_fixture(%{provider_type: "printify"})
|
||||
_product = product_fixture(%{provider_connection: conn_fixture})
|
||||
{:ok, _} = Berrypod.Settings.put_secret("stripe_api_key", "sk_test_123")
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/admin")
|
||||
|
||||
assert has_element?(view, "button", "Go live")
|
||||
end
|
||||
|
||||
test "go live shows celebration", %{conn: conn} do
|
||||
conn_fixture = provider_connection_fixture(%{provider_type: "printify"})
|
||||
_product = product_fixture(%{provider_connection: conn_fixture})
|
||||
{:ok, _} = Berrypod.Settings.put_secret("stripe_api_key", "sk_test_123")
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/admin")
|
||||
|
||||
html = view |> element("button", "Go live") |> render_click()
|
||||
|
||||
assert html =~ "Your shop is live!"
|
||||
assert html =~ "View your shop"
|
||||
assert html =~ "Customise theme"
|
||||
end
|
||||
|
||||
test "hides stepper when shop is live", %{conn: conn} do
|
||||
{:ok, _} = Berrypod.Settings.set_site_live(true)
|
||||
{:ok, _view, html} = live(conn, ~p"/admin")
|
||||
|
||||
refute html =~ "Setup steps"
|
||||
refute html =~ "Printify API token"
|
||||
end
|
||||
|
||||
test "completed steps show summary and are collapsible", %{conn: conn} do
|
||||
conn_fixture = provider_connection_fixture(%{provider_type: "printify"})
|
||||
_product = product_fixture(%{provider_connection: conn_fixture})
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/admin")
|
||||
|
||||
assert html =~ "products synced"
|
||||
end
|
||||
end
|
||||
|
||||
describe "stats" do
|
||||
setup %{conn: conn, user: user} do
|
||||
%{conn: log_in_user(conn, user)}
|
||||
end
|
||||
|
||||
test "shows stats cards", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin")
|
||||
|
||||
assert has_element?(view, "a[href='/admin/orders']", "Orders")
|
||||
assert has_element?(view, "a[href='/admin/products']", "Products")
|
||||
end
|
||||
|
||||
test "shows zero state for orders", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin")
|
||||
|
||||
assert html =~ "No orders yet"
|
||||
end
|
||||
|
||||
test "shows recent orders when they exist", %{conn: conn} do
|
||||
order = order_fixture(%{payment_status: "paid"})
|
||||
{:ok, _view, html} = live(conn, ~p"/admin")
|
||||
|
||||
assert html =~ order.order_number
|
||||
assert html =~ "Recent orders"
|
||||
end
|
||||
end
|
||||
end
|
||||
98
test/berrypod_web/live/admin/layout_test.exs
Normal file
98
test/berrypod_web/live/admin/layout_test.exs
Normal file
@@ -0,0 +1,98 @@
|
||||
defmodule BerrypodWeb.Admin.LayoutTest do
|
||||
use BerrypodWeb.ConnCase, async: false
|
||||
|
||||
import Phoenix.LiveViewTest
|
||||
import Berrypod.AccountsFixtures
|
||||
|
||||
setup do
|
||||
user = user_fixture()
|
||||
%{user: user}
|
||||
end
|
||||
|
||||
describe "admin sidebar" do
|
||||
setup %{conn: conn, user: user} do
|
||||
%{conn: log_in_user(conn, user)}
|
||||
end
|
||||
|
||||
test "renders sidebar nav links on admin pages", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/orders")
|
||||
|
||||
assert has_element?(view, ~s(a[href="/admin"]), "Dashboard")
|
||||
assert has_element?(view, ~s(a[href="/admin/orders"]), "Orders")
|
||||
assert has_element?(view, ~s(a[href="/admin/theme"]), "Theme")
|
||||
assert has_element?(view, ~s(a[href="/admin/settings"]), "Settings")
|
||||
end
|
||||
|
||||
test "highlights active nav link for current page", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/orders")
|
||||
|
||||
assert has_element?(view, ~s(a.active[href="/admin/orders"]))
|
||||
refute has_element?(view, ~s(a.active[href="/admin/settings"]))
|
||||
end
|
||||
|
||||
test "highlights dashboard on dashboard page", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin")
|
||||
|
||||
assert has_element?(view, ~s(a.active[href="/admin"]))
|
||||
refute has_element?(view, ~s(a.active[href="/admin/orders"]))
|
||||
end
|
||||
|
||||
test "highlights correct link on different pages", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/settings")
|
||||
|
||||
assert has_element?(view, ~s(a.active[href="/admin/settings"]))
|
||||
refute has_element?(view, ~s(a.active[href="/admin/orders"]))
|
||||
end
|
||||
|
||||
test "shows user email in sidebar", %{conn: conn, user: user} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/orders")
|
||||
|
||||
assert html =~ user.email
|
||||
end
|
||||
|
||||
test "shows view shop and log out links", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/orders")
|
||||
|
||||
assert has_element?(view, ~s(a[href="/"]), "View shop")
|
||||
assert has_element?(view, ~s(a[href="/users/log-out"]), "Log out")
|
||||
end
|
||||
end
|
||||
|
||||
describe "theme editor layout" do
|
||||
setup %{conn: conn, user: user} do
|
||||
%{conn: log_in_user(conn, user)}
|
||||
end
|
||||
|
||||
test "does not render sidebar", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/theme")
|
||||
|
||||
refute html =~ "admin-drawer"
|
||||
end
|
||||
|
||||
test "shows back link to admin", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/theme")
|
||||
|
||||
assert has_element?(view, ~s(a[href="/admin"]), "Admin")
|
||||
end
|
||||
end
|
||||
|
||||
describe "admin bar on shop pages" do
|
||||
setup do
|
||||
{:ok, _} = Berrypod.Settings.set_site_live(true)
|
||||
:ok
|
||||
end
|
||||
|
||||
test "shows admin link when logged in", %{conn: conn, user: user} do
|
||||
conn = log_in_user(conn, user)
|
||||
{:ok, _view, html} = live(conn, ~p"/")
|
||||
|
||||
assert html =~ ~s(href="/admin")
|
||||
end
|
||||
|
||||
test "does not show admin link when logged out", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/")
|
||||
|
||||
refute html =~ ~s(href="/admin")
|
||||
end
|
||||
end
|
||||
end
|
||||
190
test/berrypod_web/live/admin/orders_test.exs
Normal file
190
test/berrypod_web/live/admin/orders_test.exs
Normal file
@@ -0,0 +1,190 @@
|
||||
defmodule BerrypodWeb.Admin.OrdersTest do
|
||||
use BerrypodWeb.ConnCase, async: false
|
||||
|
||||
import Phoenix.LiveViewTest
|
||||
import Berrypod.AccountsFixtures
|
||||
import Berrypod.OrdersFixtures
|
||||
|
||||
setup do
|
||||
user = user_fixture()
|
||||
%{user: user}
|
||||
end
|
||||
|
||||
describe "unauthenticated" do
|
||||
test "redirects to login", %{conn: conn} do
|
||||
{:error, redirect} = live(conn, ~p"/admin/orders")
|
||||
assert {:redirect, %{to: path}} = redirect
|
||||
assert path == ~p"/users/log-in"
|
||||
end
|
||||
end
|
||||
|
||||
describe "order list" do
|
||||
setup %{conn: conn, user: user} do
|
||||
conn = log_in_user(conn, user)
|
||||
%{conn: conn}
|
||||
end
|
||||
|
||||
test "renders empty state when no orders", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/orders")
|
||||
|
||||
assert html =~ "No orders yet"
|
||||
assert html =~ "Orders"
|
||||
end
|
||||
|
||||
test "renders orders table", %{conn: conn} do
|
||||
order = order_fixture(payment_status: "paid", customer_email: "test@shop.com")
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/orders")
|
||||
|
||||
assert html =~ order.order_number
|
||||
assert html =~ "test@shop.com"
|
||||
assert html =~ "paid"
|
||||
end
|
||||
|
||||
test "filters by status", %{conn: conn} do
|
||||
paid = order_fixture(payment_status: "paid")
|
||||
_pending = order_fixture()
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/orders")
|
||||
|
||||
html = render_click(view, "filter", %{"status" => "paid"})
|
||||
|
||||
assert html =~ paid.order_number
|
||||
end
|
||||
|
||||
test "navigates to order detail", %{conn: conn} do
|
||||
order = order_fixture(payment_status: "paid")
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/orders")
|
||||
|
||||
assert html =~ ~p"/admin/orders/#{order}"
|
||||
end
|
||||
end
|
||||
|
||||
describe "order detail" do
|
||||
setup %{conn: conn, user: user} do
|
||||
conn = log_in_user(conn, user)
|
||||
%{conn: conn}
|
||||
end
|
||||
|
||||
test "renders order details", %{conn: conn} do
|
||||
order = order_fixture(payment_status: "paid", customer_email: "buyer@example.com")
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/orders/#{order}")
|
||||
|
||||
assert html =~ order.order_number
|
||||
assert html =~ "buyer@example.com"
|
||||
assert html =~ "paid"
|
||||
assert html =~ "Order details"
|
||||
end
|
||||
|
||||
test "shows line items", %{conn: conn} do
|
||||
order = order_fixture(product_name: "Cool T-shirt", variant_title: "Blue / XL")
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/orders/#{order}")
|
||||
|
||||
assert html =~ "Cool T-shirt"
|
||||
assert html =~ "Blue / XL"
|
||||
end
|
||||
|
||||
test "shows shipping address", %{conn: conn} do
|
||||
order = order_fixture(payment_status: "paid")
|
||||
|
||||
{:ok, updated_order} =
|
||||
Berrypod.Orders.update_order(order, %{
|
||||
shipping_address: %{
|
||||
"name" => "Jane Doe",
|
||||
"line1" => "42 Test Street",
|
||||
"city" => "London",
|
||||
"postal_code" => "SW1A 1AA",
|
||||
"country" => "GB"
|
||||
}
|
||||
})
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/orders/#{updated_order}")
|
||||
|
||||
assert html =~ "Jane Doe"
|
||||
assert html =~ "42 Test Street"
|
||||
assert html =~ "London"
|
||||
assert html =~ "SW1A 1AA"
|
||||
end
|
||||
|
||||
test "redirects when order not found", %{conn: conn} do
|
||||
fake_id = Ecto.UUID.generate()
|
||||
|
||||
{:error, {:live_redirect, %{to: "/admin/orders"}}} =
|
||||
live(conn, ~p"/admin/orders/#{fake_id}")
|
||||
end
|
||||
|
||||
test "shows fulfilment card", %{conn: conn} do
|
||||
order = order_fixture(payment_status: "paid")
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/orders/#{order}")
|
||||
|
||||
assert html =~ "Fulfilment"
|
||||
assert html =~ "unfulfilled"
|
||||
end
|
||||
|
||||
test "shows submit button for paid unfulfilled orders", %{conn: conn} do
|
||||
order = order_fixture(payment_status: "paid")
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/orders/#{order}")
|
||||
|
||||
assert html =~ "Submit to provider"
|
||||
end
|
||||
|
||||
test "shows retry button for failed fulfilment", %{conn: conn} do
|
||||
order = order_fixture(payment_status: "paid")
|
||||
|
||||
{:ok, order} =
|
||||
Berrypod.Orders.update_fulfilment(order, %{fulfilment_status: "failed"})
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/orders/#{order}")
|
||||
|
||||
assert html =~ "Retry submission"
|
||||
end
|
||||
|
||||
test "shows refresh button for submitted orders", %{conn: conn} do
|
||||
{order, _v, _p, _c} =
|
||||
Berrypod.OrdersFixtures.submitted_order_fixture()
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/orders/#{order}")
|
||||
|
||||
assert html =~ "Refresh status"
|
||||
end
|
||||
|
||||
test "shows tracking info when available", %{conn: conn} do
|
||||
{order, _v, _p, _c} =
|
||||
Berrypod.OrdersFixtures.submitted_order_fixture()
|
||||
|
||||
{:ok, order} =
|
||||
Berrypod.Orders.update_fulfilment(order, %{
|
||||
fulfilment_status: "shipped",
|
||||
tracking_number: "TRACK123",
|
||||
tracking_url: "https://track.example.com/TRACK123",
|
||||
shipped_at: DateTime.utc_now() |> DateTime.truncate(:second)
|
||||
})
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/orders/#{order}")
|
||||
|
||||
assert html =~ "TRACK123"
|
||||
assert html =~ "https://track.example.com/TRACK123"
|
||||
end
|
||||
end
|
||||
|
||||
describe "order list fulfilment column" do
|
||||
setup %{conn: conn, user: user} do
|
||||
conn = log_in_user(conn, user)
|
||||
%{conn: conn}
|
||||
end
|
||||
|
||||
test "shows fulfilment badge in table", %{conn: conn} do
|
||||
order_fixture(payment_status: "paid")
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/orders")
|
||||
|
||||
assert html =~ "Fulfilment"
|
||||
assert html =~ "unfulfilled"
|
||||
end
|
||||
end
|
||||
end
|
||||
190
test/berrypod_web/live/admin/products_test.exs
Normal file
190
test/berrypod_web/live/admin/products_test.exs
Normal file
@@ -0,0 +1,190 @@
|
||||
defmodule BerrypodWeb.Admin.ProductsTest do
|
||||
use BerrypodWeb.ConnCase, async: false
|
||||
|
||||
import Phoenix.LiveViewTest
|
||||
import Berrypod.AccountsFixtures
|
||||
import Berrypod.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 = Berrypod.Products.get_product(product.id)
|
||||
refute updated.visible
|
||||
end
|
||||
|
||||
test "filters by visibility", %{conn: conn, product: product} do
|
||||
Berrypod.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
|
||||
Berrypod.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 = Berrypod.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
|
||||
271
test/berrypod_web/live/admin/providers_test.exs
Normal file
271
test/berrypod_web/live/admin/providers_test.exs
Normal file
@@ -0,0 +1,271 @@
|
||||
defmodule BerrypodWeb.Admin.ProvidersTest do
|
||||
use BerrypodWeb.ConnCase, async: false
|
||||
|
||||
import Phoenix.LiveViewTest
|
||||
import Berrypod.AccountsFixtures
|
||||
import Berrypod.ProductsFixtures
|
||||
import Mox
|
||||
|
||||
alias Berrypod.Providers.MockProvider
|
||||
|
||||
setup :verify_on_exit!
|
||||
|
||||
setup do
|
||||
user = user_fixture()
|
||||
%{user: user}
|
||||
end
|
||||
|
||||
# -- Index page --
|
||||
|
||||
describe "index - unauthenticated" do
|
||||
test "redirects to login", %{conn: conn} do
|
||||
{:error, redirect} = live(conn, ~p"/admin/providers")
|
||||
assert {:redirect, %{to: path}} = redirect
|
||||
assert path == ~p"/users/log-in"
|
||||
end
|
||||
end
|
||||
|
||||
describe "index - empty state" do
|
||||
setup %{conn: conn, user: user} do
|
||||
%{conn: log_in_user(conn, user)}
|
||||
end
|
||||
|
||||
test "shows empty state when no connections exist", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/providers")
|
||||
|
||||
assert html =~ "Connect a print-on-demand provider"
|
||||
end
|
||||
|
||||
test "shows connect buttons for both providers", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/providers")
|
||||
|
||||
assert has_element?(view, ~s(a[href="/admin/providers/new?type=printify"]))
|
||||
assert has_element?(view, ~s(a[href="/admin/providers/new?type=printful"]))
|
||||
end
|
||||
end
|
||||
|
||||
describe "index - with connection" do
|
||||
setup %{conn: conn, user: user} do
|
||||
connection =
|
||||
provider_connection_fixture(%{
|
||||
provider_type: "printify",
|
||||
name: "My Printify Shop"
|
||||
})
|
||||
|
||||
%{conn: log_in_user(conn, user), connection: connection}
|
||||
end
|
||||
|
||||
test "lists provider connections", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/providers")
|
||||
|
||||
assert html =~ "Printify"
|
||||
assert html =~ "My Printify Shop"
|
||||
end
|
||||
|
||||
test "shows edit link", %{conn: conn, connection: connection} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/providers")
|
||||
|
||||
assert has_element?(view, ~s(a[href="/admin/providers/#{connection.id}/edit"]))
|
||||
end
|
||||
|
||||
test "shows product count", %{conn: conn, connection: connection} do
|
||||
product_fixture(%{provider_connection: connection})
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/providers")
|
||||
|
||||
assert html =~ "1 product"
|
||||
end
|
||||
|
||||
test "shows never synced warning", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/providers")
|
||||
|
||||
assert html =~ "Never synced"
|
||||
end
|
||||
end
|
||||
|
||||
describe "index - delete" do
|
||||
setup %{conn: conn, user: user} do
|
||||
connection =
|
||||
provider_connection_fixture(%{
|
||||
provider_type: "printify",
|
||||
name: "Delete Me Shop"
|
||||
})
|
||||
|
||||
%{conn: log_in_user(conn, user), connection: connection}
|
||||
end
|
||||
|
||||
test "deletes connection and shows flash", %{conn: conn, connection: connection} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/providers")
|
||||
|
||||
html = render_click(view, "delete", %{"id" => to_string(connection.id)})
|
||||
|
||||
assert html =~ "Provider connection deleted"
|
||||
refute html =~ "Delete Me Shop"
|
||||
end
|
||||
end
|
||||
|
||||
describe "index - sync" do
|
||||
setup %{conn: conn, user: user} do
|
||||
Application.put_env(:berrypod, :provider_modules, %{
|
||||
"printify" => MockProvider
|
||||
})
|
||||
|
||||
on_exit(fn -> Application.delete_env(:berrypod, :provider_modules) end)
|
||||
|
||||
connection =
|
||||
provider_connection_fixture(%{
|
||||
provider_type: "printify",
|
||||
name: "Sync Test Shop"
|
||||
})
|
||||
|
||||
%{conn: log_in_user(conn, user), connection: connection}
|
||||
end
|
||||
|
||||
test "starts sync and shows flash", %{conn: conn, connection: connection} do
|
||||
stub(MockProvider, :fetch_products, fn _conn -> {:ok, []} end)
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/providers")
|
||||
|
||||
html = render_click(view, "sync", %{"id" => to_string(connection.id)})
|
||||
|
||||
assert html =~ "Sync started"
|
||||
end
|
||||
end
|
||||
|
||||
# -- Form page --
|
||||
|
||||
describe "form - new" do
|
||||
setup %{conn: conn, user: user} do
|
||||
%{conn: log_in_user(conn, user)}
|
||||
end
|
||||
|
||||
test "renders new Printify form", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/providers/new?type=printify")
|
||||
|
||||
assert html =~ "Connect to Printify"
|
||||
assert html =~ "Printify API key"
|
||||
assert html =~ "Log in to Printify"
|
||||
end
|
||||
|
||||
test "renders new Printful form", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/providers/new?type=printful")
|
||||
|
||||
assert html =~ "Connect to Printful"
|
||||
assert html =~ "Printful API key"
|
||||
assert html =~ "Log in to Printful"
|
||||
end
|
||||
|
||||
test "defaults to Printify when no type param", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/providers/new")
|
||||
|
||||
assert html =~ "Connect to Printify"
|
||||
end
|
||||
|
||||
test "test connection shows error when no api key", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/providers/new")
|
||||
|
||||
html = render_click(view, "test_connection")
|
||||
|
||||
assert html =~ "Please enter your API key"
|
||||
end
|
||||
|
||||
test "saves new connection", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/providers/new")
|
||||
|
||||
{:ok, _view, html} =
|
||||
view
|
||||
|> form("#provider-form", %{
|
||||
"provider_connection" => %{
|
||||
"api_key" => "test_key_123"
|
||||
}
|
||||
})
|
||||
|> render_submit()
|
||||
|> follow_redirect(conn, ~p"/admin/settings")
|
||||
|
||||
assert html =~ "Connected to Printify"
|
||||
end
|
||||
end
|
||||
|
||||
describe "form - test connection" do
|
||||
setup %{conn: conn, user: user} do
|
||||
Application.put_env(:berrypod, :provider_modules, %{
|
||||
"printify" => MockProvider
|
||||
})
|
||||
|
||||
on_exit(fn -> Application.delete_env(:berrypod, :provider_modules) end)
|
||||
|
||||
%{conn: log_in_user(conn, user)}
|
||||
end
|
||||
|
||||
test "shows success when connection is valid", %{conn: conn} do
|
||||
expect(MockProvider, :test_connection, fn _conn ->
|
||||
{:ok, %{shop_name: "My Printify Shop", shop_id: 12345}}
|
||||
end)
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/providers/new")
|
||||
|
||||
# Validate first to set pending_api_key
|
||||
view
|
||||
|> form("#provider-form", %{
|
||||
"provider_connection" => %{"api_key" => "valid_key_123"}
|
||||
})
|
||||
|> render_change()
|
||||
|
||||
html = render_click(view, "test_connection")
|
||||
|
||||
assert html =~ "Connected to My Printify Shop"
|
||||
end
|
||||
|
||||
test "shows error when connection fails", %{conn: conn} do
|
||||
expect(MockProvider, :test_connection, fn _conn ->
|
||||
{:error, :unauthorized}
|
||||
end)
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/providers/new")
|
||||
|
||||
view
|
||||
|> form("#provider-form", %{
|
||||
"provider_connection" => %{"api_key" => "bad_key"}
|
||||
})
|
||||
|> render_change()
|
||||
|
||||
html = render_click(view, "test_connection")
|
||||
|
||||
assert html =~ "doesn't seem to be valid"
|
||||
end
|
||||
end
|
||||
|
||||
describe "form - edit" do
|
||||
setup %{conn: conn, user: user} do
|
||||
connection =
|
||||
provider_connection_fixture(%{
|
||||
provider_type: "printify",
|
||||
name: "Edit Me Shop"
|
||||
})
|
||||
|
||||
%{conn: log_in_user(conn, user), connection: connection}
|
||||
end
|
||||
|
||||
test "renders edit form", %{conn: conn, connection: connection} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/providers/#{connection.id}/edit")
|
||||
|
||||
assert html =~ "Printify settings"
|
||||
assert html =~ "Connection enabled"
|
||||
assert html =~ "Save changes"
|
||||
end
|
||||
|
||||
test "saves changes", %{conn: conn, connection: connection} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/providers/#{connection.id}/edit")
|
||||
|
||||
{:ok, _view, html} =
|
||||
view
|
||||
|> form("#provider-form", %{
|
||||
"provider_connection" => %{"enabled" => "true"}
|
||||
})
|
||||
|> render_submit()
|
||||
|> follow_redirect(conn, ~p"/admin/settings")
|
||||
|
||||
assert html =~ "Settings saved"
|
||||
end
|
||||
end
|
||||
end
|
||||
256
test/berrypod_web/live/admin/settings_test.exs
Normal file
256
test/berrypod_web/live/admin/settings_test.exs
Normal file
@@ -0,0 +1,256 @@
|
||||
defmodule BerrypodWeb.Admin.SettingsTest do
|
||||
use BerrypodWeb.ConnCase, async: false
|
||||
|
||||
import Phoenix.LiveViewTest
|
||||
import Berrypod.AccountsFixtures
|
||||
import Berrypod.ProductsFixtures
|
||||
|
||||
alias Berrypod.Accounts
|
||||
alias Berrypod.Settings
|
||||
|
||||
setup do
|
||||
user = user_fixture()
|
||||
%{user: user}
|
||||
end
|
||||
|
||||
describe "shop status toggle" do
|
||||
setup %{conn: conn, user: user} do
|
||||
conn = log_in_user(conn, user)
|
||||
%{conn: conn}
|
||||
end
|
||||
|
||||
test "shows offline status by default", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/settings")
|
||||
|
||||
assert html =~ "Offline"
|
||||
assert html =~ "coming soon"
|
||||
assert html =~ "Go live"
|
||||
end
|
||||
|
||||
test "can go live", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/settings")
|
||||
|
||||
html = render_click(view, "toggle_site_live")
|
||||
|
||||
assert html =~ "Shop is now live"
|
||||
assert html =~ "Live"
|
||||
assert html =~ "Take offline"
|
||||
assert Settings.site_live?()
|
||||
end
|
||||
|
||||
test "can take offline after going live", %{conn: conn} do
|
||||
{:ok, _} = Settings.set_site_live(true)
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/settings")
|
||||
|
||||
html = render_click(view, "toggle_site_live")
|
||||
|
||||
assert html =~ "Shop taken offline"
|
||||
assert html =~ "Offline"
|
||||
assert html =~ "Go live"
|
||||
refute Settings.site_live?()
|
||||
end
|
||||
end
|
||||
|
||||
describe "unauthenticated" do
|
||||
test "redirects to login", %{conn: conn} do
|
||||
{:error, redirect} = live(conn, ~p"/admin/settings")
|
||||
assert {:redirect, %{to: path}} = redirect
|
||||
assert path == ~p"/users/log-in"
|
||||
end
|
||||
end
|
||||
|
||||
describe "authenticated - not configured" do
|
||||
setup %{conn: conn, user: user} do
|
||||
conn = log_in_user(conn, user)
|
||||
%{conn: conn}
|
||||
end
|
||||
|
||||
test "renders setup form when Stripe is not configured", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/settings")
|
||||
|
||||
assert html =~ "Settings"
|
||||
assert html =~ "Not connected"
|
||||
assert html =~ "Connect Stripe"
|
||||
assert html =~ "Stripe dashboard"
|
||||
end
|
||||
|
||||
test "shows error for empty API key", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/settings")
|
||||
|
||||
html =
|
||||
view
|
||||
|> form(~s(form[phx-submit="connect_stripe"]), %{stripe: %{api_key: ""}})
|
||||
|> render_submit()
|
||||
|
||||
assert html =~ "Please enter your Stripe secret key"
|
||||
end
|
||||
end
|
||||
|
||||
describe "authenticated - connected (localhost)" do
|
||||
setup %{conn: conn, user: user} do
|
||||
# Pre-configure a Stripe API key
|
||||
Settings.put_secret("stripe_api_key", "sk_test_simulated_key_12345")
|
||||
conn = log_in_user(conn, user)
|
||||
%{conn: conn}
|
||||
end
|
||||
|
||||
test "renders dev mode view with CLI instructions", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/settings")
|
||||
|
||||
assert html =~ "Dev mode"
|
||||
assert html =~ "sk_test_•••345"
|
||||
assert html =~ "stripe listen"
|
||||
assert html =~ "Webhook signing secret"
|
||||
end
|
||||
|
||||
test "saves manual signing secret", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/settings")
|
||||
|
||||
html =
|
||||
view
|
||||
|> form(~s(form[phx-submit="save_signing_secret"]), %{
|
||||
webhook: %{signing_secret: "whsec_test_manual_456"}
|
||||
})
|
||||
|> render_submit()
|
||||
|
||||
assert html =~ "Webhook signing secret saved"
|
||||
assert html =~ "whsec_te•••456"
|
||||
end
|
||||
|
||||
test "shows error for empty signing secret", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/settings")
|
||||
|
||||
html =
|
||||
view
|
||||
|> form(~s(form[phx-submit="save_signing_secret"]), %{webhook: %{signing_secret: ""}})
|
||||
|> render_submit()
|
||||
|
||||
assert html =~ "Please enter a signing secret"
|
||||
end
|
||||
|
||||
test "disconnect clears configuration", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/settings")
|
||||
|
||||
html = render_click(view, "disconnect_stripe")
|
||||
|
||||
assert html =~ "Stripe disconnected"
|
||||
assert html =~ "Not connected"
|
||||
assert html =~ "Connect Stripe"
|
||||
refute Settings.has_secret?("stripe_api_key")
|
||||
end
|
||||
end
|
||||
|
||||
describe "products section" do
|
||||
setup %{conn: conn, user: user} do
|
||||
conn = log_in_user(conn, user)
|
||||
%{conn: conn}
|
||||
end
|
||||
|
||||
test "shows connect button when no provider connected", %{conn: conn} do
|
||||
{:ok, view, html} = live(conn, ~p"/admin/settings")
|
||||
|
||||
assert html =~ "Products"
|
||||
assert html =~ "Not connected"
|
||||
assert has_element?(view, ~s(a[href="/admin/providers"]), "Connect a provider")
|
||||
end
|
||||
|
||||
test "shows connection info when provider connected", %{conn: conn} do
|
||||
conn_record = provider_connection_fixture(%{name: "Test Shop"})
|
||||
product_fixture(%{provider_connection: conn_record})
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/settings")
|
||||
|
||||
assert html =~ "Connected"
|
||||
assert html =~ "Test Shop"
|
||||
assert html =~ "Sync products"
|
||||
end
|
||||
end
|
||||
|
||||
describe "account section" do
|
||||
setup %{conn: conn, user: user} do
|
||||
conn = log_in_user(conn, user)
|
||||
%{conn: conn, user: user}
|
||||
end
|
||||
|
||||
test "renders email and password forms", %{conn: conn, user: user} do
|
||||
{:ok, view, html} = live(conn, ~p"/admin/settings")
|
||||
|
||||
assert html =~ "Account"
|
||||
assert html =~ user.email
|
||||
assert has_element?(view, "#email_form")
|
||||
assert has_element?(view, "#password_form")
|
||||
end
|
||||
|
||||
test "validates email change", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/settings")
|
||||
|
||||
result =
|
||||
view
|
||||
|> element("#email_form")
|
||||
|> render_change(%{"user" => %{"email" => "with spaces"}})
|
||||
|
||||
assert result =~ "must have the @ sign and no spaces"
|
||||
end
|
||||
|
||||
test "submits email change", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/settings")
|
||||
|
||||
result =
|
||||
view
|
||||
|> form("#email_form", %{"user" => %{"email" => unique_user_email()}})
|
||||
|> render_submit()
|
||||
|
||||
assert result =~ "A link to confirm your email"
|
||||
end
|
||||
|
||||
test "validates password", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/settings")
|
||||
|
||||
result =
|
||||
view
|
||||
|> element("#password_form")
|
||||
|> render_change(%{
|
||||
"user" => %{
|
||||
"password" => "short",
|
||||
"password_confirmation" => "mismatch"
|
||||
}
|
||||
})
|
||||
|
||||
assert result =~ "should be at least 12 character(s)"
|
||||
end
|
||||
|
||||
test "submits valid password change", %{conn: conn, user: user} do
|
||||
new_password = valid_user_password()
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/settings")
|
||||
|
||||
form =
|
||||
form(view, "#password_form", %{
|
||||
"user" => %{
|
||||
"email" => user.email,
|
||||
"password" => new_password,
|
||||
"password_confirmation" => new_password
|
||||
}
|
||||
})
|
||||
|
||||
render_submit(form)
|
||||
new_password_conn = follow_trigger_action(form, conn)
|
||||
|
||||
assert redirected_to(new_password_conn) == ~p"/admin/settings"
|
||||
assert Accounts.get_user_by_email_and_password(user.email, new_password)
|
||||
end
|
||||
end
|
||||
|
||||
describe "advanced section" do
|
||||
setup %{conn: conn, user: user} do
|
||||
conn = log_in_user(conn, user)
|
||||
%{conn: conn}
|
||||
end
|
||||
|
||||
test "shows links to system tools", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/settings")
|
||||
|
||||
assert has_element?(view, ~s(a[href="/admin/dashboard"]), "System dashboard")
|
||||
assert has_element?(view, ~s(a[href="/admin/errors"]), "Error tracker")
|
||||
end
|
||||
end
|
||||
end
|
||||
216
test/berrypod_web/live/admin/theme_test.exs
Normal file
216
test/berrypod_web/live/admin/theme_test.exs
Normal file
@@ -0,0 +1,216 @@
|
||||
defmodule BerrypodWeb.Admin.ThemeTest do
|
||||
use BerrypodWeb.ConnCase, async: false
|
||||
|
||||
import Phoenix.LiveViewTest
|
||||
import Berrypod.AccountsFixtures
|
||||
|
||||
alias Berrypod.Settings
|
||||
|
||||
setup do
|
||||
user = user_fixture()
|
||||
%{user: user}
|
||||
end
|
||||
|
||||
describe "Index (unauthenticated)" do
|
||||
test "redirects to login when not authenticated", %{conn: conn} do
|
||||
{:error, redirect} = live(conn, ~p"/admin/theme")
|
||||
|
||||
assert {:redirect, %{to: path}} = redirect
|
||||
assert path == ~p"/users/log-in"
|
||||
end
|
||||
end
|
||||
|
||||
describe "Index (authenticated)" do
|
||||
setup %{conn: conn, user: user} do
|
||||
conn = log_in_user(conn, user)
|
||||
%{conn: conn}
|
||||
end
|
||||
|
||||
test "renders theme editor page", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/theme")
|
||||
|
||||
assert html =~ "Theme Studio"
|
||||
assert html =~ "preset"
|
||||
end
|
||||
|
||||
test "displays all 8 presets", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/theme")
|
||||
|
||||
assert html =~ "gallery"
|
||||
assert html =~ "studio"
|
||||
assert html =~ "boutique"
|
||||
assert html =~ "bold"
|
||||
assert html =~ "playful"
|
||||
assert html =~ "minimal"
|
||||
assert html =~ "night"
|
||||
assert html =~ "classic"
|
||||
end
|
||||
|
||||
test "displays current theme settings", %{conn: conn} do
|
||||
{:ok, _settings} = Settings.apply_preset(:gallery)
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/theme")
|
||||
|
||||
assert html =~ "warm"
|
||||
assert html =~ "editorial"
|
||||
assert html =~ "soft"
|
||||
assert html =~ "spacious"
|
||||
end
|
||||
|
||||
test "displays generated CSS in preview", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/theme")
|
||||
|
||||
# CSS generator outputs accent colors and layout variables for shop pages
|
||||
assert html =~ ".themed {"
|
||||
assert html =~ "--t-accent-h:"
|
||||
end
|
||||
|
||||
test "applies preset and updates preview", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/theme")
|
||||
|
||||
html =
|
||||
view
|
||||
|> element("button", "gallery")
|
||||
|> render_click()
|
||||
|
||||
theme_settings = Settings.get_theme_settings()
|
||||
assert theme_settings.mood == "warm"
|
||||
assert theme_settings.typography == "editorial"
|
||||
assert html =~ "warm"
|
||||
assert html =~ "editorial"
|
||||
end
|
||||
|
||||
test "switches preview page", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/theme")
|
||||
|
||||
html =
|
||||
view
|
||||
|> element("button", "Collection")
|
||||
|> render_click()
|
||||
|
||||
assert html =~ "All Products"
|
||||
end
|
||||
|
||||
test "theme settings are saved when applying a preset", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/theme")
|
||||
|
||||
# Apply a preset
|
||||
view
|
||||
|> element("button", "gallery")
|
||||
|> render_click()
|
||||
|
||||
# Verify settings were persisted
|
||||
theme_settings = Settings.get_theme_settings()
|
||||
assert theme_settings.mood == "warm"
|
||||
assert theme_settings.typography == "editorial"
|
||||
end
|
||||
|
||||
test "all preview page buttons are present", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/theme")
|
||||
|
||||
assert html =~ "Home"
|
||||
assert html =~ "Collection"
|
||||
assert html =~ "Product"
|
||||
assert html =~ "Cart"
|
||||
assert html =~ "About"
|
||||
assert html =~ "Contact"
|
||||
assert html =~ "404"
|
||||
end
|
||||
|
||||
test "mood customization buttons work", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/theme")
|
||||
|
||||
# Click the "dark" mood button
|
||||
html =
|
||||
view
|
||||
|> element("button[phx-value-setting_value='dark']")
|
||||
|> render_click()
|
||||
|
||||
# Verify the setting was updated
|
||||
theme_settings = Settings.get_theme_settings()
|
||||
assert theme_settings.mood == "dark"
|
||||
assert html =~ "dark"
|
||||
end
|
||||
|
||||
test "shape customization buttons work", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/theme")
|
||||
|
||||
# Click the "round" shape button
|
||||
view
|
||||
|> element("button[phx-value-setting_value='round']")
|
||||
|> render_click()
|
||||
|
||||
# Verify the setting was updated
|
||||
theme_settings = Settings.get_theme_settings()
|
||||
assert theme_settings.shape == "round"
|
||||
end
|
||||
|
||||
test "density customization buttons work", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/theme")
|
||||
|
||||
# Click the "compact" density button
|
||||
view
|
||||
|> element("button[phx-value-setting_value='compact']")
|
||||
|> render_click()
|
||||
|
||||
# Verify the setting was updated
|
||||
theme_settings = Settings.get_theme_settings()
|
||||
assert theme_settings.density == "compact"
|
||||
end
|
||||
|
||||
test "grid columns customization buttons work", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/theme")
|
||||
|
||||
# Click the "2 columns" grid columns button
|
||||
view
|
||||
|> element("button", "2 columns")
|
||||
|> render_click()
|
||||
|
||||
# Verify the setting was updated
|
||||
theme_settings = Settings.get_theme_settings()
|
||||
assert theme_settings.grid_columns == "2"
|
||||
end
|
||||
|
||||
test "typography customization buttons work", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/theme")
|
||||
|
||||
# Click the "modern" typography button
|
||||
view
|
||||
|> element("button[phx-value-setting_value='modern']")
|
||||
|> render_click()
|
||||
|
||||
# Verify the setting was updated
|
||||
theme_settings = Settings.get_theme_settings()
|
||||
assert theme_settings.typography == "modern"
|
||||
end
|
||||
|
||||
test "header layout customization buttons work", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/theme")
|
||||
|
||||
# Click the "centered" header layout button
|
||||
view
|
||||
|> element("button[phx-value-setting_value='centered']")
|
||||
|> render_click()
|
||||
|
||||
# Verify the setting was updated
|
||||
theme_settings = Settings.get_theme_settings()
|
||||
assert theme_settings.header_layout == "centered"
|
||||
end
|
||||
|
||||
test "CSS regenerates when settings change", %{conn: conn} do
|
||||
{:ok, view, html} = live(conn, ~p"/admin/theme")
|
||||
|
||||
# Capture initial CSS
|
||||
initial_css = html
|
||||
|
||||
# Change a setting
|
||||
new_html =
|
||||
view
|
||||
|> element("button[phx-value-setting_value='dark']")
|
||||
|> render_click()
|
||||
|
||||
# Verify CSS has changed
|
||||
refute initial_css == new_html
|
||||
assert new_html =~ "--t-accent-h:"
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user