import { describe, it, expect, vi, beforeEach } from 'vitest'; import { mount, flushPromises } from '@vue/test-utils'; import { createVuetify } from 'vuetify'; import { createRouter, createMemoryHistory } from 'vue-router'; import AdminLeadsView from '../../resources/js/views/admin/AdminLeadsView.vue'; import AdminLeadDetailView from '../../resources/js/views/admin/AdminLeadDetailView.vue'; vi.mock('../../resources/js/api/adminLeads', () => ({ getLeads: vi.fn().mockResolvedValue({ data: [ { id: 501, received_at: '2026-06-28 07:55', platform: 'B1', channel: 'site', source: 'okna.ru', region_code: 77, phone_masked: '79***07', deals_created_count: 2, status: 'delivered' }, ], total: 1, page: 1, per_page: 25, }), getLead: vi.fn().mockResolvedValue({ lead: { id: 501, platform: 'B1', phone_masked: '79***07', received_at: '2026-06-28 07:55', processed_at: '2026-06-28 07:56', error: null, region_code: 77, region_source: 'dadata', phone_operator: 'МТС', deals_created_count: 1, status: 'delivered' }, source: { platform: 'B1', channel: 'site', identifier: 'okna.ru', supplier_project_id: 9 }, deals: [{ id: 1, tenant_id: 2, tenant_name: 'Компания 1', subdomain: 'c1', status: 'new', project_id: 5, received_at: '2026-06-28 07:56' }], }), })); beforeEach(() => vi.clearAllMocks()); function routerWith(path: string) { const router = createRouter({ history: createMemoryHistory(), routes: [ { path: '/admin/leads', name: 'admin-leads', component: AdminLeadsView }, { path: '/admin/leads/:id', name: 'admin-lead-detail', component: AdminLeadDetailView }, { path: '/admin/tenants/:code', name: 'admin-tenant-detail', component: { template: '
' } }, { path: '/admin/supplier-projects', name: 'admin-supplier-projects', component: { template: '' } }, { path: '/admin/dashboard', name: 'admin-dashboard', component: { template: '' } }, ], }); return router.push(path).then(() => router); } describe('AdminLeadsView', () => { it('грузит список и показывает строку лида', async () => { const router = await routerWith('/admin/leads'); const wrapper = mount(AdminLeadsView, { global: { plugins: [createVuetify(), router] } }); await flushPromises(); expect(wrapper.text()).toContain('okna.ru'); expect(wrapper.text()).toContain('доставлен'); const api = await import('../../resources/js/api/adminLeads'); expect(api.getLeads).toHaveBeenCalled(); }); it('фильтр по каналу шлёт channel и сбрасывает на 1 страницу', async () => { const router = await routerWith('/admin/leads'); const wrapper = mount(AdminLeadsView, { global: { plugins: [createVuetify(), router] } }); await flushPromises(); const api = await import('../../resources/js/api/adminLeads'); wrapper.vm.filters.channel = 'call'; await wrapper.find('[data-testid="apply-filters"]').trigger('click'); await flushPromises(); expect(vi.mocked(api.getLeads).mock.calls.at(-1)?.[0]).toMatchObject({ channel: 'call', page: 1 }); }); }); describe('AdminLeadDetailView', () => { it('показывает цепочку: откуда (источник) и кому (сделки)', async () => { const router = await routerWith('/admin/leads/501'); const wrapper = mount(AdminLeadDetailView, { global: { plugins: [createVuetify(), router] } }); await flushPromises(); expect(wrapper.find('[data-testid="lead-source"]').exists()).toBe(true); expect(wrapper.text()).toContain('okna.ru'); // источник expect(wrapper.find('[data-testid="lead-deals"]').exists()).toBe(true); expect(wrapper.text()).toContain('Компания 1'); // кому ушёл }); });