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:
jamey
2026-02-11 22:58:58 +00:00
parent 093bdcc7a6
commit e64bf40a71
16 changed files with 471 additions and 74 deletions

View File

@@ -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"

View File

@@ -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

View File

@@ -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)

View File

@@ -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