defmodule AprsmeWeb.ThemeManagerTest do use ExUnit.Case, async: true import Phoenix.LiveViewTest alias AprsmeWeb.ThemeManager alias Phoenix.LiveView.Socket describe "resolve_theme/2" do test "returns system_preference for 'auto'" do assert ThemeManager.resolve_theme("auto", "dark") == "dark" assert ThemeManager.resolve_theme("auto", "light") == "light" end test "returns the explicit theme for 'light' or 'dark'" do assert ThemeManager.resolve_theme("light", "dark") == "light" assert ThemeManager.resolve_theme("dark", "light") == "dark" end test "falls back to system_preference for unknown themes" do assert ThemeManager.resolve_theme("neon", "light") == "light" assert ThemeManager.resolve_theme(nil, "dark") == "dark" end end describe "get_theme_colors/1" do test "returns dark-themed colors for 'dark'" do colors = ThemeManager.get_theme_colors("dark") assert colors.text == "#e5e7eb" assert colors.grid == "#374151" assert colors.primary == "#3b82f6" end test "returns light-themed colors for 'light'" do colors = ThemeManager.get_theme_colors("light") assert colors.text == "#111827" assert colors.primary == "#2563eb" end test "any non-dark value returns light colors" do assert ThemeManager.get_theme_colors("auto").text == "#111827" assert ThemeManager.get_theme_colors(nil).text == "#111827" assert ThemeManager.get_theme_colors("whatever").text == "#111827" end test "dark and light colors are distinct" do dark = ThemeManager.get_theme_colors("dark") light = ThemeManager.get_theme_colors("light") refute dark.text == light.text refute dark.grid == light.grid end test "all expected keys are present" do for theme <- ["dark", "light"] do colors = ThemeManager.get_theme_colors(theme) assert Map.has_key?(colors, :text) assert Map.has_key?(colors, :grid) assert Map.has_key?(colors, :background) assert Map.has_key?(colors, :primary) assert Map.has_key?(colors, :secondary) assert Map.has_key?(colors, :accent) end end end describe "init_theme/2" do test "initializes with stored theme from session" do socket = %Socket{assigns: %{__changed__: %{}}} result = ThemeManager.init_theme(socket, %{"theme" => "dark"}) assigns = Map.get(result, :assigns) assert assigns.theme == "dark" assert assigns.resolved_theme == "dark" assert assigns.theme_colors.text == "#e5e7eb" end test "defaults to 'auto' when no session theme" do socket = %Socket{assigns: %{__changed__: %{}}} result = ThemeManager.init_theme(socket, %{}) assigns = Map.get(result, :assigns) assert assigns.theme == "auto" # system_preference is "light" in this module assert assigns.resolved_theme == "light" end test "ignores unknown stored themes, defaulting to auto" do socket = %Socket{assigns: %{__changed__: %{}}} result = ThemeManager.init_theme(socket, %{"theme" => "neon"}) assigns = Map.get(result, :assigns) assert assigns.theme == "auto" end test "defaults to auto when session arg is omitted" do socket = %Socket{assigns: %{__changed__: %{}}} result = ThemeManager.init_theme(socket) assigns = Map.get(result, :assigns) assert assigns.theme == "auto" end end describe "handle_theme_change/2" do test "returns unchanged socket for invalid themes" do socket = %Socket{assigns: %{__changed__: %{}}} assert ThemeManager.handle_theme_change(socket, "invalid") == socket end test "updates assigns for valid themes" do socket = %Socket{assigns: %{__changed__: %{}}} result = ThemeManager.handle_theme_change(socket, "dark") assigns = Map.get(result, :assigns) assert assigns.theme == "dark" assert assigns.resolved_theme == "dark" end end describe "theme_selector/1" do test "renders buttons for light, dark and auto" do html = render_component(&ThemeManager.theme_selector/1, %{theme: "light"}) assert html =~ "Light" assert html =~ "Dark" assert html =~ "Auto" # The active theme should have the distinctive selected styling. assert html =~ "set_theme" end test "highlights the dark button when theme is dark" do html = render_component(&ThemeManager.theme_selector/1, %{theme: "dark"}) # Dark-button block appears twice with different classes depending on # whether it's active, but the label text is always present. assert html =~ "Dark" end test "accepts a custom class" do html = render_component(&ThemeManager.theme_selector/1, %{ theme: "auto", class: "my-custom-class" }) assert html =~ "my-custom-class" end end end