berrypod/test/berrypod_web/live/theme_css_consistency_test.exs
jamey 65ea11c3a2 replace --color-* with --t-* tokens, delete bridge and .preview-frame
Phase 4: admin components and utilities now reference --t-* theme
tokens directly. Status colour tokens added to theme-semantic.css.
Bridge file (admin/themes.css) deleted.

Phase 5: removed duplicated .preview-frame CSS block (~160 lines).
Admin components and icons wrapped in @layer admin. Layer order
updated in admin_root to include admin layer.

Phase 6: added prefers-reduced-motion support (zeroes all durations
and disables animations). Migrated physical properties to logical
equivalents (text-align start/end, margin-inline, padding-inline,
inset-inline-end) across shop and admin CSS.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 00:13:33 +00:00

188 lines
6.3 KiB
Elixir

defmodule BerrypodWeb.ThemeCSSConsistencyTest do
@moduledoc """
Tests that verify CSS works correctly for both the theme editor
preview and the shop pages using the shared .themed class.
Architecture:
- Both shop pages and preview use .themed class for shared styles
- Theme editor uses .preview-frame[data-*] selectors for live switching (in admin.css)
- Shop pages get theme values via inline CSS from CSSGenerator (shop.css)
- Component styles use .themed for shared styling (theme-layer2-attributes.css)
"""
use BerrypodWeb.ConnCase, async: false
import Phoenix.LiveViewTest
import Berrypod.AccountsFixtures
alias Berrypod.Settings
setup do
user = user_fixture()
%{user: user}
end
describe "CSS selector consistency" do
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/
assert html =~ ~r/data-mood="/
assert html =~ ~r/data-typography="/
assert html =~ ~r/data-shape="/
assert html =~ ~r/data-density="/
end
test "theme editor has .themed with data attributes", %{conn: conn, user: user} do
conn = log_in_user(conn, user)
{:ok, _view, html} = live(conn, ~p"/admin/theme")
# Verify themed element exists in preview-frame with theme data attributes
assert html =~ ~r/<div[^>]*class="themed/
assert html =~ ~r/data-mood="/
assert html =~ ~r/data-typography="/
assert html =~ ~r/data-shape="/
assert html =~ ~r/data-density="/
end
test "shop page uses same theme settings as preview", %{conn: conn, user: user} do
# Set a specific theme configuration
{:ok, _settings} = Settings.apply_preset(:night)
# 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 (already authenticated)
{:ok, _view, preview_html} = live(conn, ~p"/admin/theme")
# Extract data-mood values from both
[_, shop_mood] = Regex.run(~r/data-mood="([^"]+)"/, shop_html)
[_, preview_mood] = Regex.run(~r/data-mood="([^"]+)"/, preview_html)
# They should match
assert shop_mood == preview_mood
assert shop_mood == "dark"
end
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)
{:ok, _view, html} = live(conn, ~p"/")
assert html =~ ~s(data-mood="neutral")
# Change to night preset (dark mood)
{:ok, _settings} = Settings.apply_preset(:night)
{:ok, _view, html} = live(conn, ~p"/")
assert html =~ ~s(data-mood="dark")
# Change to gallery preset (warm mood)
{:ok, _settings} = Settings.apply_preset(:gallery)
{:ok, _view, html} = live(conn, ~p"/")
assert html =~ ~s(data-mood="warm")
end
end
describe "CSS file structure" do
test "admin.css imports shared theme layers" do
css_path = Path.join([File.cwd!(), "assets", "css", "admin.css"])
css_content = File.read!(css_path)
# Admin imports the shared theme layers so .themed resolves all tokens
assert css_content =~ "theme-primitives.css"
assert css_content =~ "theme-layer2-attributes.css"
assert css_content =~ "theme-semantic.css"
end
test "theme-layer2-attributes.css has shared .themed component styles" do
css_path = Path.join([File.cwd!(), "assets", "css", "theme-layer2-attributes.css"])
css_content = File.read!(css_path)
# Component styles use .themed for shared styling (both shop and preview)
assert css_content =~ ".themed"
# Uses CSS nesting syntax
assert css_content =~ "& .product-card"
assert css_content =~ "& .filter-pill"
end
end
describe "generated CSS cache" do
test "generated CSS includes ALL theme token categories" do
# Apply a preset with specific values
{:ok, settings} = Settings.apply_preset(:night)
# Generate CSS
css = Berrypod.Theme.CSSGenerator.generate(settings)
# Mood tokens (surface, text, border colors)
assert css =~ "--t-surface-base:"
assert css =~ "--t-text-primary:"
assert css =~ "--t-border-default:"
# Typography tokens
assert css =~ "--t-font-heading:"
assert css =~ "--t-font-body:"
assert css =~ "--t-heading-weight:"
# Shape tokens (border radii)
assert css =~ "--t-radius-sm:"
assert css =~ "--t-radius-button:"
assert css =~ "--t-radius-card:"
# Density tokens
assert css =~ "--t-density:"
assert css =~ "--space-md:"
assert css =~ "--space-lg:"
# Slider-controlled values
assert css =~ "--t-accent-l:"
assert css =~ "--t-accent-c:"
assert css =~ "--t-accent-h:"
assert css =~ "--t-font-size-scale:"
assert css =~ "--t-heading-weight-override:"
end
test "generated CSS uses correct values for dark mood" do
{:ok, settings} = Settings.apply_preset(:night)
css = Berrypod.Theme.CSSGenerator.generate(settings)
# Dark mood should have dark surface colors
assert css =~ "--t-surface-base: #0a0a0a"
assert css =~ "--t-text-primary: #fafafa"
end
test "generated CSS uses correct values for warm mood" do
{:ok, settings} = Settings.apply_preset(:gallery)
css = Berrypod.Theme.CSSGenerator.generate(settings)
# Warm mood should have warm surface colors
assert css =~ "--t-surface-base: #fdf8f3"
end
test "CSS cache is warmed on startup and invalidated on settings change" do
# Ensure cache has content
Berrypod.Theme.CSSCache.warm()
{:ok, css1} = Berrypod.Theme.CSSCache.get()
assert is_binary(css1)
assert css1 =~ "--t-accent-h:"
# Change settings (this should invalidate and rewarm cache)
{:ok, _settings} = Settings.apply_preset(:night)
{:ok, css2} = Berrypod.Theme.CSSCache.get()
assert is_binary(css2)
# The CSS should be different (different accent color)
# Note: this may or may not be true depending on preset colors
assert css2 =~ "--t-accent-h:"
end
end
end