import { mount } from "@vue/test-utils"; import { describe, it, expect, vi } from "vitest"; import SidebarLayout from "~/layouts/default/Sidebar.vue"; import { ref } from "vue"; import type * as SidebarUI from "~/components/ui/sidebar"; const { useSidebarMock } = vi.hoisted(() => ({ useSidebarMock: vi.fn(), })); // Mock the UI components and hook vi.mock("~/components/ui/sidebar", async (importOriginal) => { const actual = await importOriginal(); const { ref } = await import("vue"); const MockComponent = { template: "
", inheritAttrs: false, }; // Default implementation useSidebarMock.mockReturnValue({ isMobile: ref(false), state: ref("expanded"), openMobile: ref(false), setOpenMobile: vi.fn(), }); return { ...actual, Sidebar: MockComponent, SidebarContent: MockComponent, SidebarFooter: MockComponent, SidebarGroup: MockComponent, SidebarHeader: MockComponent, SidebarMenu: MockComponent, SidebarMenuItem: MockComponent, SidebarMenuButton: MockComponent, SidebarRail: MockComponent, SidebarMenuSub: MockComponent, SidebarMenuSubButton: MockComponent, SidebarMenuSubItem: MockComponent, useSidebar: useSidebarMock, }; }); // Mock other UI components to avoid rendering complexity vi.mock("~/components/ui/dropdown-menu", () => { const MockComponent = { template: "
" }; return { DropdownMenu: MockComponent, DropdownMenuContent: MockComponent, DropdownMenuGroup: MockComponent, DropdownMenuItem: MockComponent, DropdownMenuLabel: MockComponent, DropdownMenuSeparator: MockComponent, DropdownMenuTrigger: MockComponent, }; }); vi.mock("~/components/ui/collapsible", () => { const MockComponent = { template: "
" }; return { Collapsible: MockComponent, CollapsibleContent: MockComponent, CollapsibleTrigger: MockComponent, }; }); vi.mock("~/components/ui/avatar", () => { const MockComponent = { template: "
" }; return { Avatar: MockComponent, AvatarFallback: MockComponent, AvatarImage: MockComponent, }; }); vi.mock("@/components/ui/sheet", () => { const MockComponent = { template: "
" }; return { Sheet: MockComponent, SheetContent: MockComponent, }; }); vi.mock("@/components/ui/sheet/SheetDescription.vue", () => ({ default: { template: "
" }, })); vi.mock("@/components/ui/sheet/SheetHeader.vue", () => ({ default: { template: "
" }, })); vi.mock("lucide-vue-next", () => { const MockIcon = { template: '' }; return { BadgeCheck: MockIcon, Bell: MockIcon, ChevronRight: MockIcon, ChevronsUpDown: MockIcon, CreditCard: MockIcon, BookOpen: MockIcon, HandCoins: MockIcon, LogOut: MockIcon, Settings2: MockIcon, Sparkles: MockIcon, SquareTerminal: MockIcon, }; }); describe("SidebarLayout", () => { it("renders the header correctly", () => { useSidebarMock.mockReturnValue({ isMobile: ref(false), state: ref("expanded"), openMobile: ref(false), setOpenMobile: vi.fn(), }); const wrapper = mount(SidebarLayout, { props: { collapsible: "icon", }, }); expect(wrapper.text()).toContain("Glowing Fiesta"); expect(wrapper.text()).toContain("v1.0.0"); }); it("renders navigation groups", () => { const wrapper = mount(SidebarLayout); const text = wrapper.text(); expect(text).toContain("Playground"); expect(text).toContain("Documentation"); expect(text).toContain("Settings"); }); it("renders user information", () => { const wrapper = mount(SidebarLayout); expect(wrapper.text()).toContain("Liviu"); expect(wrapper.text()).toContain("x.liviu@gmail.com"); }); it("renders sub-items in navigation", () => { const wrapper = mount(SidebarLayout); const text = wrapper.text(); // Checking sub-items of Playground expect(text).toContain("History"); expect(text).toContain("Starred"); // Checking sub-items of Documentation expect(text).toContain("Introduction"); expect(text).toContain("Get Started"); }); it("does not render icon if item.icon is missing", () => { const wrapper = mount(SidebarLayout, { props: { navItems: [ { title: "No Icon Item", url: "#", items: [], }, ], }, }); expect(wrapper.text()).toContain("No Icon Item"); expect(wrapper.find('[data-testid="sidebar-icon"]').exists()).toBe(false); }); it("renders correctly in mobile view", () => { useSidebarMock.mockReturnValue({ isMobile: ref(true), state: ref("expanded"), openMobile: ref(true), setOpenMobile: vi.fn(), }); const wrapper = mount(SidebarLayout); // When isMobile is true, it renders a Sheet. // Since we mocked Sheet components as simple divs with slots, the content should still be present. // However, the structure is different. // We can verify that the content is still rendered (passed through the slot). const text = wrapper.text(); expect(text).toContain("Glowing Fiesta"); expect(text).toContain("Liviu"); // Check specific specific mock interaction if needed, or just that it doesn't crash // and renders the menu items. expect(text).toContain("Playground"); }); });