defmodule MvWeb.Layouts.SidebarTest do @moduledoc """ Unit tests for the Sidebar component. Tests cover: - Basic rendering and structure - Props handling (current_user, club_name, mobile) - Menu structure (flat and nested items) - Footer/Profile section - Accessibility attributes (ARIA labels, roles) - CSS classes (DaisyUI conformance) - Icon rendering - Conditional visibility """ use MvWeb.ConnCase, async: true import Phoenix.LiveViewTest import MvWeb.Layouts.Sidebar # ============================================================================= # Helper Functions # ============================================================================= # Returns assigns for an authenticated user with all required attributes. defp authenticated_assigns(mobile \\ false) do %{ current_user: %{id: "user-123", email: "test@example.com"}, club_name: "Test Club", mobile: mobile } end # Returns assigns for a guest user (not authenticated). defp guest_assigns(mobile \\ false) do %{ current_user: nil, club_name: "Test Club", mobile: mobile } end # Renders the sidebar component with the given assigns. defp render_sidebar(assigns) do render_component(&sidebar/1, assigns) end # Checks if the HTML contains a specific CSS class. defp has_class?(html, class) do html =~ class end # ============================================================================= # Group 1: Basic Rendering (T1.1-T1.3) # ============================================================================= describe "basic rendering" do test "T1.1: renders sidebar with main navigation structure" do html = render_sidebar(authenticated_assigns()) # Check for navigation element with correct ID assert html =~ ~s(id="main-sidebar") assert html =~ ~s(aria-label="Main navigation") # Check for sidebar class assert has_class?(html, "sidebar") end test "T1.2: renders logo correctly" do html = render_sidebar(authenticated_assigns()) # Check for logo image assert html =~ ~s(src="/images/mila.svg") assert html =~ ~s(alt="Mila Logo") # Check logo has correct size class assert has_class?(html, "size-8") end test "T1.3: renders toggle button with correct attributes (desktop only)" do html = render_sidebar(authenticated_assigns(false)) # Check for toggle button assert html =~ ~s(id="sidebar-toggle") assert html =~ "onclick=" # Check for DaisyUI button classes assert has_class?(html, "btn") assert has_class?(html, "btn-ghost") assert has_class?(html, "btn-sm") assert has_class?(html, "btn-square") # Check for both toggle icons (expanded and collapsed) assert has_class?(html, "sidebar-expanded-icon") assert has_class?(html, "sidebar-collapsed-icon") end test "T1.4: does not render toggle button on mobile" do html = render_sidebar(authenticated_assigns(true)) # Toggle button should not be rendered on mobile refute html =~ ~s(id="sidebar-toggle") end end # ============================================================================= # Group 2: Props Handling (T2.1-T2.3) # ============================================================================= describe "props handling" do test "T2.1: displays club name when provided" do assigns = %{ current_user: %{id: "user-1", email: "test@example.com"}, club_name: "My Awesome Club", mobile: false } html = render_sidebar(assigns) assert html =~ "My Awesome Club" end test "T2.2: does not render menu items when current_user is nil" do html = render_sidebar(guest_assigns()) # Navigation links should not be rendered refute html =~ ~s(href="/members") refute html =~ ~s(href="/users") refute html =~ ~s(href="/settings") refute html =~ ~s(href="/contribution_types") # Footer section should not be rendered refute html =~ "locale-select" refute html =~ "theme-controller" end test "T2.3: renders menu items when current_user is present" do html = render_sidebar(authenticated_assigns()) # Check for Members link assert html =~ ~s(href="/members") # Check for Users link assert html =~ ~s(href="/users") # Check for Custom Fields link assert html =~ ~s(href="/custom_fields") # Check for Contributions section assert html =~ ~s(href="/contribution_types") assert html =~ ~s(href="/contribution_settings") # Check for Settings link (placeholder) assert html =~ ~s(href="#") end test "T2.4: renders sidebar with main-sidebar ID" do html = render_sidebar(authenticated_assigns(true)) assert html =~ ~s(id="main-sidebar") end test "T2.5: renders sidebar with main-sidebar ID on desktop" do html = render_sidebar(authenticated_assigns(false)) assert html =~ ~s(id="main-sidebar") end end # ============================================================================= # Group 3: Menu Structure (T3.1-T3.3) # ============================================================================= describe "menu structure" do test "T3.1: renders flat menu items with icons and labels" do html = render_sidebar(authenticated_assigns()) # Check for Members link with icon assert html =~ ~s(href="/members") assert html =~ "hero-users" # Check for Users link with icon assert html =~ ~s(href="/users") assert html =~ "hero-user-circle" # Check for Custom Fields link with icon assert html =~ ~s(href="/custom_fields") assert html =~ "hero-rectangle-group" # Check for Settings link with icon assert html =~ ~s(href="#") assert html =~ "hero-cog-6-tooth" # Check for tooltips (data-tip attribute) assert html =~ "data-tip=" end test "T3.2: renders nested menu with details element for expanded state" do html = render_sidebar(authenticated_assigns()) # Check for Contributions section structure with details assert html =~ "