- IS GenServer: add missing :failure_started_at to test build_state/1 map
- IS GenServer: fix stale status server assertion and reconnection test
- IS GenServer: set Logger level to :debug for dispatch parse-error tests
- PacketReplay: remove conflicting Registry start_supervised! from setup
- PacketReplay: update assertion from {:continue_replay} to :start_replay
- Doctests: fix float precision, stale sprite coords, quoting escapes
- API controllers: use string keys for JSON error/postion details
- PacketUtils: fix operator precedence (not is_nil(result).field)
- ThemeManager: update expected dark theme text color
- StatusLive: remove/update stale :loading assign assertions
- Movement: remove {:ok, _v} wrapper from render_hook/3 (returns HTML)
- AprsIsMock: update packet_stats assertion for populated default shape
142 lines
4.8 KiB
Elixir
142 lines
4.8 KiB
Elixir
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
|