diff --git a/apps/app/src/components-v2/layout/AppSidebar.vue b/apps/app/src/components-v2/layout/AppSidebar.vue new file mode 100644 index 00000000..a928c6ec --- /dev/null +++ b/apps/app/src/components-v2/layout/AppSidebar.vue @@ -0,0 +1,105 @@ + + + diff --git a/apps/app/src/components-v2/layout/SidebarHeader.vue b/apps/app/src/components-v2/layout/SidebarHeader.vue new file mode 100644 index 00000000..64cff966 --- /dev/null +++ b/apps/app/src/components-v2/layout/SidebarHeader.vue @@ -0,0 +1,112 @@ + + + + + diff --git a/apps/app/src/components-v2/layout/__tests__/AppSidebar.spec.ts b/apps/app/src/components-v2/layout/__tests__/AppSidebar.spec.ts new file mode 100644 index 00000000..2dbb7fd6 --- /dev/null +++ b/apps/app/src/components-v2/layout/__tests__/AppSidebar.spec.ts @@ -0,0 +1,167 @@ +/** + * AppSidebar.spec.ts — unit tests for AppSidebar composition and mobile wiring. + * + * Strategy: mount with @vue/test-utils stubs for all heavy children (SidebarHeader, + * SidebarNav, WorkspaceSwitcher, Drawer) so we test only: + * 1. Renders the 3 child components (SidebarHeader, SidebarNav, WorkspaceSwitcher). + * 2. Passes `groups` prop to SidebarNav. + * 3. Mobile Drawer v-model:visible wires to shell.mobileOpen (get path). + * 4. Drawer close (v-model:visible = false) calls shell.setMobileOpen(false). + * + * Stubs: Drawer is stubbed with a simple slot passthrough so we can inspect + * whether its `visible` prop is correctly bound to the store. + */ + +import { createPinia, setActivePinia } from 'pinia' +import { mount } from '@vue/test-utils' +import { beforeEach, describe, expect, it, vi } from 'vitest' +import { useShellUiStore } from '@/stores/useShellUiStore' +import AppSidebar from '@/components-v2/layout/AppSidebar.vue' +import type { V2NavGroup } from '@/types/v2/nav' + +// --------------------------------------------------------------------------- +// A minimal nav group fixture +// --------------------------------------------------------------------------- + +const testGroups: V2NavGroup[] = [ + { + label: 'Main', + items: [ + { id: 'dashboard', label: 'Dashboard', icon: 'tabler-home', to: { name: 'dashboard' } }, + ], + }, +] + +// --------------------------------------------------------------------------- +// Stubs +// --------------------------------------------------------------------------- + +/** + * DrawerStub exposes the same `visible` prop as PrimeVue Drawer and renders + * its default slot so child components are mounted. It also emits + * `update:visible` when the close method would fire, which mirrors the + * v-model:visible contract. + */ +const DrawerStub = { + name: 'Drawer', + props: ['visible', 'position', 'pt'], + emits: ['update:visible'], + template: '
', +} + +const globalStubs = { + Drawer: DrawerStub, + SidebarHeader: { name: 'SidebarHeader', template: '