import { describe, it, expect, beforeEach, test } from 'vitest'; import { useCommandPalette } from '../../resources/js/composables/useCommandPalette'; import { mount, type VueWrapper } from '@vue/test-utils'; import { createMemoryHistory, createRouter, type Router } from 'vue-router'; import { createPinia, setActivePinia } from 'pinia'; import { createVuetify } from 'vuetify'; import AppSidebar from '../../resources/js/components/layout/AppSidebar.vue'; import { useDealsCountStore } from '../../resources/js/stores/dealsCount'; async function setup(initialRoute = '/deals'): Promise<{ wrapper: VueWrapper; router: Router }> { setActivePinia(createPinia()); // B2: default count=5 so badge renders in non-B2 tests (replaces hardcoded 247). useDealsCountStore().count = 5; const router = createRouter({ history: createMemoryHistory(), routes: [ { path: '/dashboard', component: { template: '
' } }, { path: '/deals', component: { template: '
' } }, { path: '/kanban', component: { template: '
' } }, ], }); await router.push(initialRoute); await router.isReady(); const vuetify = createVuetify(); const wrapper = mount(AppSidebar, { global: { plugins: [router, vuetify], stubs: { RouterLink: { props: ['to'], template: '', inheritAttrs: false, }, }, }, }); return { wrapper, router }; } describe('AppSidebar — redesigned shell', () => { beforeEach(() => localStorage.clear()); it('has cmdk stub at top of sidebar', async () => { const { wrapper } = await setup(); expect(wrapper.find('.ld-cmdk-stub').exists()).toBe(true); expect(wrapper.find('.ld-cmdk-stub').text()).toMatch(/Поиск|команды/i); }); it('renders 3 nav-groups with eyebrow labels', async () => { const { wrapper } = await setup(); const eyebrows = wrapper.findAll('.ld-nav-group__eyebrow'); expect(eyebrows.length).toBeGreaterThanOrEqual(3); }); it('badge uses JetBrains Mono class', async () => { const { wrapper } = await setup(); const badges = wrapper.findAll('.ld-nav-item__badge'); expect(badges.length).toBeGreaterThan(0); const styleSheet = badges[0].attributes('class') ?? ''; expect(styleSheet).toMatch(/ld-mono|nav-item__badge/); }); it('active nav-item has marker pseudo-element class', async () => { const { wrapper } = await setup('/deals'); const items = wrapper.findAll('.ld-nav-item'); const active = items.find((el) => el.classes().includes('ld-nav-item--active')); expect(active).toBeDefined(); }); }); test('B2: бейдж «Сделки» рендерит count из dealsCount-store', async () => { const { wrapper } = await setup(); const store = useDealsCountStore(); store.count = 42; await wrapper.vm.$nextTick(); const badge = wrapper.find('[data-testid="nav-count-deals"]'); expect(badge.exists()).toBe(true); expect(badge.text()).toBe('42'); }); test('B2: бейдж «Сделки» скрыт пока count=null', async () => { const { wrapper } = await setup(); const store = useDealsCountStore(); store.count = null; await wrapper.vm.$nextTick(); expect(wrapper.find('[data-testid="nav-count-deals"]').exists()).toBe(false); }); test('B3: клик на ⌘K-плашку открывает command-palette', async () => { const { open, closePalette } = useCommandPalette(); closePalette(); const { wrapper } = await setup(); await wrapper.find('[data-testid="cmdk-stub"]').trigger('click'); expect(open.value).toBe(true); });