add setup foundations: site gate, registration lockdown, coming soon page
- Settings.site_live?/0 and set_site_live/1 for shop visibility control - Accounts.has_admin?/0 to detect single-tenant admin existence - Registration lockdown: /users/register redirects when admin exists - Setup.setup_status/0 aggregates provider, product, and stripe checks - Coming soon page at /coming-soon with themed styling - ThemeHook :require_site_live gate on all public shop routes - Site live → everyone through - Authenticated → admin preview through - No admin → fresh install demo through - Otherwise → redirect to coming soon - Go live / take offline toggle on /admin/settings - 648 tests, 0 failures Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,22 @@ defmodule SimpleshopTheme.AccountsTest do
|
||||
import SimpleshopTheme.AccountsFixtures
|
||||
alias SimpleshopTheme.Accounts.{User, UserToken}
|
||||
|
||||
describe "has_admin?/0" do
|
||||
test "returns false when no users exist" do
|
||||
refute Accounts.has_admin?()
|
||||
end
|
||||
|
||||
test "returns true when a user exists" do
|
||||
user_fixture()
|
||||
assert Accounts.has_admin?()
|
||||
end
|
||||
|
||||
test "returns true with an unconfirmed user" do
|
||||
unconfirmed_user_fixture()
|
||||
assert Accounts.has_admin?()
|
||||
end
|
||||
end
|
||||
|
||||
describe "get_user_by_email/1" do
|
||||
test "does not return the user if the email does not exist" do
|
||||
refute Accounts.get_user_by_email("unknown@example.com")
|
||||
|
||||
@@ -192,6 +192,25 @@ defmodule SimpleshopTheme.SettingsTest do
|
||||
end
|
||||
end
|
||||
|
||||
describe "site_live?/0 and set_site_live/1" do
|
||||
test "defaults to false when no setting exists" do
|
||||
refute Settings.site_live?()
|
||||
end
|
||||
|
||||
test "returns true after setting site live" do
|
||||
assert {:ok, _} = Settings.set_site_live(true)
|
||||
assert Settings.site_live?()
|
||||
end
|
||||
|
||||
test "returns false after setting site offline" do
|
||||
assert {:ok, _} = Settings.set_site_live(true)
|
||||
assert Settings.site_live?()
|
||||
|
||||
assert {:ok, _} = Settings.set_site_live(false)
|
||||
refute Settings.site_live?()
|
||||
end
|
||||
end
|
||||
|
||||
describe "delete_setting/1" do
|
||||
test "deletes an existing setting" do
|
||||
{:ok, _} = Settings.put_setting("to_delete", "value")
|
||||
|
||||
94
test/simpleshop_theme/setup_test.exs
Normal file
94
test/simpleshop_theme/setup_test.exs
Normal file
@@ -0,0 +1,94 @@
|
||||
defmodule SimpleshopTheme.SetupTest do
|
||||
use SimpleshopTheme.DataCase, async: false
|
||||
|
||||
alias SimpleshopTheme.{Setup, Settings, Products}
|
||||
|
||||
import SimpleshopTheme.AccountsFixtures
|
||||
|
||||
describe "setup_status/0" do
|
||||
test "returns all false on fresh install" do
|
||||
status = Setup.setup_status()
|
||||
|
||||
refute status.admin_created
|
||||
refute status.printify_connected
|
||||
refute status.products_synced
|
||||
assert status.product_count == 0
|
||||
refute status.stripe_connected
|
||||
refute status.site_live
|
||||
refute status.can_go_live
|
||||
end
|
||||
|
||||
test "detects admin created" do
|
||||
user_fixture()
|
||||
status = Setup.setup_status()
|
||||
|
||||
assert status.admin_created
|
||||
end
|
||||
|
||||
test "detects stripe connected" do
|
||||
{:ok, _} = Settings.put_secret("stripe_api_key", "sk_test_abc123")
|
||||
status = Setup.setup_status()
|
||||
|
||||
assert status.stripe_connected
|
||||
end
|
||||
|
||||
test "detects site live" do
|
||||
{:ok, _} = Settings.set_site_live(true)
|
||||
status = Setup.setup_status()
|
||||
|
||||
assert status.site_live
|
||||
end
|
||||
|
||||
test "detects printify connected with products" do
|
||||
{:ok, conn} =
|
||||
Products.create_provider_connection(%{
|
||||
name: "Test",
|
||||
provider_type: "printify",
|
||||
api_key: "test_api_key"
|
||||
})
|
||||
|
||||
status = Setup.setup_status()
|
||||
assert status.printify_connected
|
||||
refute status.products_synced
|
||||
assert status.product_count == 0
|
||||
|
||||
# Add a product
|
||||
{:ok, _product} =
|
||||
Products.create_product(%{
|
||||
title: "Test product",
|
||||
provider_product_id: "ext-1",
|
||||
provider_connection_id: conn.id,
|
||||
status: "active"
|
||||
})
|
||||
|
||||
status = Setup.setup_status()
|
||||
assert status.products_synced
|
||||
assert status.product_count == 1
|
||||
end
|
||||
|
||||
test "can_go_live requires printify, products, and stripe" do
|
||||
{:ok, conn} =
|
||||
Products.create_provider_connection(%{
|
||||
name: "Test",
|
||||
provider_type: "printify",
|
||||
api_key: "test_api_key"
|
||||
})
|
||||
|
||||
{:ok, _product} =
|
||||
Products.create_product(%{
|
||||
title: "Test product",
|
||||
provider_product_id: "ext-1",
|
||||
provider_connection_id: conn.id,
|
||||
status: "active"
|
||||
})
|
||||
|
||||
# Still missing stripe
|
||||
refute Setup.setup_status().can_go_live
|
||||
|
||||
# Add stripe
|
||||
{:ok, _} = Settings.put_secret("stripe_api_key", "sk_test_abc123")
|
||||
|
||||
assert Setup.setup_status().can_go_live
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -11,6 +11,44 @@ defmodule SimpleshopThemeWeb.AdminLive.SettingsTest do
|
||||
%{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")
|
||||
@@ -28,7 +66,7 @@ defmodule SimpleshopThemeWeb.AdminLive.SettingsTest do
|
||||
test "renders setup form when Stripe is not configured", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/settings")
|
||||
|
||||
assert html =~ "Credentials"
|
||||
assert html =~ "Settings"
|
||||
assert html =~ "Not connected"
|
||||
assert html =~ "Connect Stripe"
|
||||
assert html =~ "Stripe dashboard"
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
defmodule SimpleshopThemeWeb.ShopLive.ComingSoonTest do
|
||||
use SimpleshopThemeWeb.ConnCase, async: false
|
||||
|
||||
import Phoenix.LiveViewTest
|
||||
import SimpleshopTheme.AccountsFixtures
|
||||
|
||||
alias SimpleshopTheme.Settings
|
||||
|
||||
describe "coming soon page" do
|
||||
test "renders when site is not live and admin exists", %{conn: conn} do
|
||||
user_fixture()
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/coming-soon")
|
||||
|
||||
assert html =~ "Coming soon"
|
||||
assert html =~ "getting things ready"
|
||||
end
|
||||
|
||||
test "displays the shop name", %{conn: conn} do
|
||||
{:ok, _} = Settings.update_theme_settings(%{site_name: "My Test Shop"})
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/coming-soon")
|
||||
|
||||
assert html =~ "My Test Shop"
|
||||
end
|
||||
end
|
||||
|
||||
describe "site live gate" do
|
||||
test "redirects unauthenticated visitors to coming soon when not live", %{conn: conn} do
|
||||
# Create admin so the gate activates (fresh installs bypass)
|
||||
user_fixture()
|
||||
|
||||
assert {:error, {:redirect, %{to: "/coming-soon"}}} = live(conn, ~p"/")
|
||||
end
|
||||
|
||||
test "allows authenticated admin through when not live", %{conn: conn} do
|
||||
user = user_fixture()
|
||||
conn = log_in_user(conn, user)
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/")
|
||||
|
||||
assert html =~ "Shop the collection"
|
||||
end
|
||||
|
||||
test "allows everyone through when site is live", %{conn: conn} do
|
||||
user_fixture()
|
||||
{:ok, _} = Settings.set_site_live(true)
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/")
|
||||
|
||||
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"
|
||||
end
|
||||
|
||||
test "gates all public shop routes", %{conn: conn} do
|
||||
user_fixture()
|
||||
|
||||
assert {:error, {:redirect, %{to: "/coming-soon"}}} = live(conn, ~p"/about")
|
||||
assert {:error, {:redirect, %{to: "/coming-soon"}}} = live(conn, ~p"/collections/all")
|
||||
assert {:error, {:redirect, %{to: "/coming-soon"}}} = live(conn, ~p"/cart")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -23,8 +23,8 @@ defmodule SimpleshopThemeWeb.ThemeCSSConsistencyTest do
|
||||
end
|
||||
|
||||
describe "CSS selector consistency" do
|
||||
test "shop home page has .themed with data attributes", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/")
|
||||
test "shop home page has .themed with data attributes", %{conn: conn, user: user} do
|
||||
{:ok, _view, html} = live(log_in_user(conn, user), ~p"/")
|
||||
|
||||
# Verify themed element exists with theme data attributes
|
||||
assert html =~ ~r/<div[^>]*class="themed/
|
||||
@@ -50,11 +50,11 @@ defmodule SimpleshopThemeWeb.ThemeCSSConsistencyTest do
|
||||
# Set a specific theme configuration
|
||||
{:ok, _settings} = Settings.apply_preset(:night)
|
||||
|
||||
# Check shop page
|
||||
# Check shop page (logged in since site_live is false by default)
|
||||
conn = log_in_user(conn, user)
|
||||
{:ok, _view, shop_html} = live(conn, ~p"/")
|
||||
|
||||
# Check preview (authenticated)
|
||||
conn = log_in_user(conn, user)
|
||||
# Check preview (already authenticated)
|
||||
{:ok, _view, preview_html} = live(conn, ~p"/admin/theme")
|
||||
|
||||
# Extract data-mood values from both
|
||||
@@ -66,7 +66,9 @@ defmodule SimpleshopThemeWeb.ThemeCSSConsistencyTest do
|
||||
assert shop_mood == "dark"
|
||||
end
|
||||
|
||||
test "theme settings changes are reflected on shop page", %{conn: conn} do
|
||||
test "theme settings changes are reflected on shop page", %{conn: conn, user: user} do
|
||||
conn = log_in_user(conn, user)
|
||||
|
||||
# Start with minimal preset (neutral mood)
|
||||
{:ok, _settings} = Settings.apply_preset(:minimal)
|
||||
|
||||
|
||||
@@ -5,13 +5,21 @@ defmodule SimpleshopThemeWeb.UserLive.RegistrationTest do
|
||||
import SimpleshopTheme.AccountsFixtures
|
||||
|
||||
describe "Registration page" do
|
||||
test "renders registration page", %{conn: conn} do
|
||||
test "renders registration page when no admin exists", %{conn: conn} do
|
||||
{:ok, _lv, html} = live(conn, ~p"/users/register")
|
||||
|
||||
assert html =~ "Register"
|
||||
assert html =~ "Log in"
|
||||
end
|
||||
|
||||
test "redirects to login when admin already exists", %{conn: conn} do
|
||||
user_fixture()
|
||||
|
||||
assert {:error,
|
||||
{:redirect, %{to: "/users/log-in", flash: %{"error" => "Registration is closed"}}}} =
|
||||
live(conn, ~p"/users/register")
|
||||
end
|
||||
|
||||
test "redirects if already logged in", %{conn: conn} do
|
||||
result =
|
||||
conn
|
||||
|
||||
Reference in New Issue
Block a user