import { describe, it, expect, beforeEach } from 'vitest'; import { mount, flushPromises } from '@vue/test-utils'; import { createPinia, setActivePinia } from 'pinia'; import { createVuetify } from 'vuetify'; import { createMemoryHistory, createRouter } from 'vue-router'; import DealsView from '../../resources/js/views/DealsView.vue'; function setup() { setActivePinia(createPinia()); const router = createRouter({ history: createMemoryHistory(), routes: [{ path: '/deals', component: DealsView }] }); router.push('/deals'); return mount(DealsView, { global: { plugins: [router, createVuetify()], stubs: { RouterLink: true, VDataTable: true }, }, }); } describe('DealsView — redesigned', () => { beforeEach(() => localStorage.clear()); it('renders filterbar with at least 3 FilterChips', async () => { const w = setup(); await flushPromises(); const chips = w.findAll('.ld-filter-chip'); expect(chips.length).toBeGreaterThanOrEqual(3); }); it('renders DensityToggle in filterbar', async () => { const w = setup(); await flushPromises(); expect(w.find('.ld-density-toggle').exists()).toBe(true); }); it('row uses StatusPill component for status column', async () => { const w = setup(); await flushPromises(); // After data load — at least one ld-status-pill should be present // (если stub VDataTable — test проверяет наличие компонента в template, не в render) expect(w.html()).toMatch(/ld-status-pill|StatusPill/); }); it('applies ld-hover-lift utility class to table container or row wrapper', async () => { const w = setup(); await flushPromises(); expect(w.html()).toMatch(/ld-hover-lift|hover-lift/); }); it('applies ld-stagger-row class to deal rows (motion #2)', async () => { const w = setup(); await flushPromises(); expect(w.html()).toMatch(/ld-stagger-row/); }); }); describe('FilterChip popovers (Sprint 1 C2)', () => { function setupWithRouter() { setActivePinia(createPinia()); const router = createRouter({ history: createMemoryHistory(), routes: [{ path: '/deals', component: DealsView }] }); router.push('/deals'); return mount(DealsView, { global: { plugins: [router, createVuetify()], stubs: { DealDetailDrawer: true, NewDealDialog: true, VMenu: { template: '
' } }, }, }); } it('clicking Project chip toggles projectMenuOpen ref to true', async () => { const wrapper = setupWithRouter(); await new Promise((r) => setTimeout(r, 50)); // eslint-disable-next-line @typescript-eslint/no-explicit-any const vm = wrapper.vm as any; expect(vm.projectMenuOpen).toBe(false); // Trigger via direct ref assignment (v-menu activator manages this ref). // watch(projectMenuOpen) will seed projectMenuDraft on open=true. vm.projectMenuOpen = true; await wrapper.vm.$nextTick(); expect(vm.projectMenuOpen).toBe(true); }); it('clicking Manager chip toggles managerMenuOpen ref to true', async () => { const wrapper = setupWithRouter(); await new Promise((r) => setTimeout(r, 50)); // eslint-disable-next-line @typescript-eslint/no-explicit-any const vm = wrapper.vm as any; expect(vm.managerMenuOpen).toBe(false); // Trigger via direct ref assignment (v-menu activator manages this ref). // watch(managerMenuOpen) will seed managerMenuDraft on open=true. vm.managerMenuOpen = true; await wrapper.vm.$nextTick(); expect(vm.managerMenuOpen).toBe(true); }); it('applying project selection updates filterProjects and closes menu', async () => { const wrapper = setupWithRouter(); await new Promise((r) => setTimeout(r, 50)); // eslint-disable-next-line @typescript-eslint/no-explicit-any const vm = wrapper.vm as any; // Open menu (watch seeds draft from filterProjects), then override draft manually. vm.projectMenuOpen = true; await wrapper.vm.$nextTick(); vm.projectMenuDraft = ['demo-project-1', 'demo-project-2']; vm.applyProjectFilter(); await wrapper.vm.$nextTick(); expect(vm.filterProjects).toEqual(['demo-project-1', 'demo-project-2']); expect(vm.projectMenuOpen).toBe(false); }); });