add fresh install redirect and admin provider tests
Fresh installs now redirect to /users/register instead of showing the demo shop. Post-login redirect goes to /admin dashboard (with setup checklist) instead of /admin/settings. Added 16 provider tests covering index (list, delete, sync) and form (new, edit, test connection). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
0dac93ec0b
commit
2cc8c4a9cb
@ -43,11 +43,11 @@ Plans: [admin-redesign.md](docs/plans/admin-redesign.md) | [setup-wizard.md](doc
|
||||
| ~~11~~ | ~~Theme editor back-to-admin link~~ | 6 | 30m | done |
|
||||
| ~~4~~ | ~~Admin bar on shop pages~~ | — | 1h | done |
|
||||
| ~~12~~ | ~~Consolidate settings page~~ | 6, 7 | 2-3h | done |
|
||||
| ~~13~~ | ~~Admin dashboard (+ setup checklist)~~ | 6, 7, 9 | 2h | done |
|
||||
| ~~15~~ | ~~Setup wizard + admin tests~~ | 13 | 1.5h | done |
|
||||
| | **Next up** | | | |
|
||||
| 13 | Admin dashboard (+ setup checklist) | 6, 7, 9 | 2h | |
|
||||
| 5 | Search (functional search with results) | — | 3-4h | |
|
||||
| | **Needs admin stable** | | | |
|
||||
| 15 | Setup wizard + admin tests | 13 | 1.5h | |
|
||||
| 16 | Variant refinement with live data | — | 2-3h | |
|
||||
| 17 | Wire real product data to shop pages | — | 2-3h | |
|
||||
| 18 | Shipping costs at checkout | 17 | 2-3h | |
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
</.header>
|
||||
|
||||
<div id="connections" phx-update="stream" class="mt-6 space-y-4">
|
||||
<div class="hidden only:block text-center py-12">
|
||||
<div id="connections-empty" class="hidden only:block text-center py-12">
|
||||
<.icon name="hero-cube" class="size-16 mx-auto mb-4 text-base-content/30" />
|
||||
<h2 class="text-xl font-medium">Connect your Printify account</h2>
|
||||
<p class="mt-2 text-base-content/60 max-w-md mx-auto">
|
||||
|
||||
@ -51,8 +51,8 @@ defmodule SimpleshopThemeWeb.ThemeHook do
|
||||
{:cont, socket}
|
||||
|
||||
not SimpleshopTheme.Accounts.has_admin?() ->
|
||||
# Fresh install — no admin yet, show the demo shop
|
||||
{:cont, socket}
|
||||
# Fresh install — send to registration
|
||||
{:halt, Phoenix.LiveView.redirect(socket, to: "/users/register")}
|
||||
|
||||
true ->
|
||||
{:halt, Phoenix.LiveView.redirect(socket, to: "/coming-soon")}
|
||||
|
||||
@ -257,9 +257,9 @@ defmodule SimpleshopThemeWeb.UserAuth do
|
||||
end
|
||||
|
||||
@doc "Returns the path to redirect to after log in."
|
||||
# the user was already logged in, redirect to admin settings
|
||||
# the user was already logged in, redirect to admin dashboard
|
||||
def signed_in_path(%Plug.Conn{assigns: %{current_scope: %Scope{user: %Accounts.User{}}}}) do
|
||||
~p"/admin/settings"
|
||||
~p"/admin"
|
||||
end
|
||||
|
||||
def signed_in_path(_), do: ~p"/"
|
||||
|
||||
@ -1,5 +1,13 @@
|
||||
defmodule SimpleshopThemeWeb.PageControllerTest do
|
||||
use SimpleshopThemeWeb.ConnCase
|
||||
use SimpleshopThemeWeb.ConnCase, async: false
|
||||
|
||||
import SimpleshopTheme.AccountsFixtures
|
||||
|
||||
setup do
|
||||
user_fixture()
|
||||
{:ok, _} = SimpleshopTheme.Settings.set_site_live(true)
|
||||
:ok
|
||||
end
|
||||
|
||||
test "GET / renders the shop home page", %{conn: conn} do
|
||||
conn = get(conn, ~p"/")
|
||||
|
||||
256
test/simpleshop_theme_web/live/admin/providers_test.exs
Normal file
256
test/simpleshop_theme_web/live/admin/providers_test.exs
Normal file
@ -0,0 +1,256 @@
|
||||
defmodule SimpleshopThemeWeb.Admin.ProvidersTest do
|
||||
use SimpleshopThemeWeb.ConnCase, async: false
|
||||
|
||||
import Phoenix.LiveViewTest
|
||||
import SimpleshopTheme.AccountsFixtures
|
||||
import SimpleshopTheme.ProductsFixtures
|
||||
import Mox
|
||||
|
||||
alias SimpleshopTheme.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 your Printify account"
|
||||
end
|
||||
|
||||
test "shows connect button", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/providers")
|
||||
|
||||
assert has_element?(view, ~s(a[href="/admin/providers/new"]))
|
||||
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(:simpleshop_theme, :provider_modules, %{
|
||||
"printify" => MockProvider
|
||||
})
|
||||
|
||||
on_exit(fn -> Application.delete_env(:simpleshop_theme, :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 form", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/providers/new")
|
||||
|
||||
assert html =~ "Connect to Printify"
|
||||
assert html =~ "connection key"
|
||||
assert html =~ "Log in 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 connection 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(:simpleshop_theme, :provider_modules, %{
|
||||
"printify" => MockProvider
|
||||
})
|
||||
|
||||
on_exit(fn -> Application.delete_env(:simpleshop_theme, :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
|
||||
@ -2,9 +2,16 @@ defmodule SimpleshopThemeWeb.Shop.CartTest do
|
||||
use SimpleshopThemeWeb.ConnCase, async: false
|
||||
|
||||
import Phoenix.LiveViewTest
|
||||
import SimpleshopTheme.AccountsFixtures
|
||||
|
||||
alias SimpleshopTheme.ProductsFixtures
|
||||
|
||||
setup do
|
||||
user_fixture()
|
||||
{:ok, _} = SimpleshopTheme.Settings.set_site_live(true)
|
||||
:ok
|
||||
end
|
||||
|
||||
defp create_cart_with_product(_context) do
|
||||
product = ProductsFixtures.complete_product_fixture(%{title: "Test Art Print"})
|
||||
variant = List.first(product.variants)
|
||||
|
||||
@ -2,9 +2,16 @@ defmodule SimpleshopThemeWeb.Shop.CollectionTest do
|
||||
use SimpleshopThemeWeb.ConnCase, async: false
|
||||
|
||||
import Phoenix.LiveViewTest
|
||||
import SimpleshopTheme.AccountsFixtures
|
||||
|
||||
alias SimpleshopTheme.Theme.PreviewData
|
||||
|
||||
setup do
|
||||
user_fixture()
|
||||
{:ok, _} = SimpleshopTheme.Settings.set_site_live(true)
|
||||
:ok
|
||||
end
|
||||
|
||||
describe "Collection page" do
|
||||
test "renders collection page for /collections/all", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/collections/all")
|
||||
|
||||
@ -51,11 +51,9 @@ defmodule SimpleshopThemeWeb.Shop.ComingSoonTest do
|
||||
assert html =~ "Shop the collection"
|
||||
end
|
||||
|
||||
test "allows everyone through on fresh install (no admin)", %{conn: conn} do
|
||||
# No admin created — fresh install shows the demo shop
|
||||
{:ok, _view, html} = live(conn, ~p"/")
|
||||
|
||||
assert html =~ "Shop the collection"
|
||||
test "redirects to registration on fresh install (no admin)", %{conn: conn} do
|
||||
# No admin created — redirect to registration
|
||||
assert {:error, {:redirect, %{to: "/users/register"}}} = live(conn, ~p"/")
|
||||
end
|
||||
|
||||
test "gates all public shop routes", %{conn: conn} do
|
||||
|
||||
@ -2,6 +2,13 @@ defmodule SimpleshopThemeWeb.Shop.ContentTest do
|
||||
use SimpleshopThemeWeb.ConnCase, async: false
|
||||
|
||||
import Phoenix.LiveViewTest
|
||||
import SimpleshopTheme.AccountsFixtures
|
||||
|
||||
setup do
|
||||
user_fixture()
|
||||
{:ok, _} = SimpleshopTheme.Settings.set_site_live(true)
|
||||
:ok
|
||||
end
|
||||
|
||||
describe "About page" do
|
||||
test "renders about page", %{conn: conn} do
|
||||
|
||||
@ -2,9 +2,16 @@ defmodule SimpleshopThemeWeb.Shop.HomeTest do
|
||||
use SimpleshopThemeWeb.ConnCase, async: false
|
||||
|
||||
import Phoenix.LiveViewTest
|
||||
import SimpleshopTheme.AccountsFixtures
|
||||
|
||||
alias SimpleshopTheme.Theme.PreviewData
|
||||
|
||||
setup do
|
||||
user_fixture()
|
||||
{:ok, _} = SimpleshopTheme.Settings.set_site_live(true)
|
||||
:ok
|
||||
end
|
||||
|
||||
describe "Home page" do
|
||||
test "renders the home page", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/")
|
||||
|
||||
@ -2,9 +2,16 @@ defmodule SimpleshopThemeWeb.Shop.ProductShowTest do
|
||||
use SimpleshopThemeWeb.ConnCase, async: false
|
||||
|
||||
import Phoenix.LiveViewTest
|
||||
import SimpleshopTheme.AccountsFixtures
|
||||
|
||||
alias SimpleshopTheme.Theme.PreviewData
|
||||
|
||||
setup do
|
||||
user_fixture()
|
||||
{:ok, _} = SimpleshopTheme.Settings.set_site_live(true)
|
||||
:ok
|
||||
end
|
||||
|
||||
describe "Product detail page" do
|
||||
test "renders product page with product name", %{conn: conn} do
|
||||
product = List.first(PreviewData.products())
|
||||
|
||||
@ -74,13 +74,13 @@ defmodule SimpleshopThemeWeb.UserAuthTest do
|
||||
assert max_age == @remember_me_cookie_max_age
|
||||
end
|
||||
|
||||
test "redirects to settings when user is already logged in", %{conn: conn, user: user} do
|
||||
test "redirects to dashboard when user is already logged in", %{conn: conn, user: user} do
|
||||
conn =
|
||||
conn
|
||||
|> assign(:current_scope, Scope.for_user(user))
|
||||
|> UserAuth.log_in_user(user)
|
||||
|
||||
assert redirected_to(conn) == ~p"/admin/settings"
|
||||
assert redirected_to(conn) == ~p"/admin"
|
||||
end
|
||||
|
||||
test "writes a cookie if remember_me was set in previous session", %{conn: conn, user: user} do
|
||||
|
||||
Loading…
Reference in New Issue
Block a user