import { mount } from '@vue/test-utils'; import { createVuetify } from 'vuetify'; import { describe, expect, it } from 'vitest'; import SalesProspectDialog from '../../resources/js/components/sales/SalesProspectDialog.vue'; import type { SalesProspect } from '../../resources/js/api/sales'; const vuetify = createVuetify(); function prospect(overrides: Partial = {}): SalesProspect { return { id: 1, sales_user_id: 1, stage: 'new', firm_name: 'ООО Тест', city: 'Ростов', phone: '+7800', site: 'test.ru', inn: '6161', rating_label: 'горячая', payload: {}, next_call_at: null, reason: null, registered_email: null, notes: null, ...overrides, }; } interface DialogVm { action: string; reason: string; nextCallAt: string; siteHref: string | null; availableActions: { value: string; title: string }[]; infoRows: { label: string; value: string; href?: string }[]; submit: () => void; } function factory(p: SalesProspect) { return mount(SalesProspectDialog, { props: { modelValue: true, prospect: p }, global: { plugins: [vuetify] }, }); } describe('SalesProspectDialog', () => { it('siteHref добавляет https к домену', () => { const w = factory(prospect()); expect((w.vm as unknown as DialogVm).siteHref).toBe('https://test.ru'); }); it('для stage=user действие «Отказ» недоступно', () => { const w = factory(prospect({ stage: 'user' })); const values = (w.vm as unknown as DialogVm).availableActions.map((a) => a.value); expect(values).not.toContain('rejected'); }); it('для обычной стадии «Отказ» доступен', () => { const w = factory(prospect({ stage: 'negotiation' })); const values = (w.vm as unknown as DialogVm).availableActions.map((a) => a.value); expect(values).toContain('rejected'); }); it('«Переговоры» без даты — submit не эмитит save', () => { const w = factory(prospect()); (w.vm as unknown as DialogVm).action = 'negotiation'; (w.vm as unknown as DialogVm).submit(); expect(w.emitted('save')).toBeFalsy(); }); it('«Отказ» с причиной — эмитит save с action=rejected', () => { const w = factory(prospect({ stage: 'negotiation' })); (w.vm as unknown as DialogVm).action = 'rejected'; (w.vm as unknown as DialogVm).reason = 'дорого'; (w.vm as unknown as DialogVm).submit(); expect(w.emitted('save')?.[0]?.[0]).toMatchObject({ action: 'rejected', reason: 'дорого' }); }); it('infoRows показывает ВСЕ данные поиска из payload', () => { const w = factory( prospect({ inn: '6161000000', payload: { legal_name: 'ООО «Тест»', ogrn: '1234567890123', address: 'г. Ростов, ул. Ленина 1', legal_status: 'действующая', director: 'Иванов Иван Иванович', director_post: 'директор', director_is_ip: false, director_inn: '616100000000', contact_phone: '+79001234567', contact_email: 'ivan@test.ru', direct_budget_min: 80000, direct_budget: 250000, direct_keys: 1200, direct_ads: 30, channels: ['Яндекс.Директ', 'коллтрекинг'], }, }), ); const rows = (w.vm as unknown as DialogVm).infoRows; const text = rows.map((r) => `${r.label}: ${r.value}`).join(' | '); expect(text).toContain('Иванов Иван Иванович'); // директор expect(text).toContain('директор'); // должность expect(text).toContain('616100000000'); // личный ИНН руководителя (ПДн) expect(text).toContain('+79001234567'); // тел. директора expect(text).toContain('ivan@test.ru'); // почта директора expect(text).toContain('коллтрекинг'); // каналы expect(text).toContain('1234567890123'); // ОГРН expect(text).toContain('6161000000'); // ИНН фирмы expect(text).toContain('г. Ростов, ул. Ленина 1'); // адрес expect(text).toMatch(/80 000.*250 000/); // вилка бюджета Директа expect(text).toContain('1 200'); // запросы в Директе (разряды пробелом) }); it('infoRows пропускает пустые поля payload', () => { const w = factory(prospect({ payload: {}, inn: null })); const labels = (w.vm as unknown as DialogVm).infoRows.map((r) => r.label); expect(labels).not.toContain('ОГРН'); expect(labels).not.toContain('Директор'); }); });