import { mount, flushPromises } from '@vue/test-utils'; import { createVuetify } from 'vuetify'; import { describe, expect, it, vi, beforeEach } from 'vitest'; vi.mock('../../resources/js/api/sales', () => ({ lookupProspectInn: vi.fn(), })); import SalesProspectCreateDialog from '../../resources/js/components/sales/SalesProspectCreateDialog.vue'; import { lookupProspectInn } from '../../resources/js/api/sales'; const vuetify = createVuetify(); interface Contact { name: string; position: string; phones: string[]; } interface CreateVm { firmName: string; legalName: string; city: string; site: string; inn: string; notes: string; contacts: Contact[]; error: string; lookingUp: boolean; lookup: () => Promise; submit: () => void; } function factory() { const w = mount(SalesProspectCreateDialog, { props: { modelValue: true }, global: { plugins: [vuetify] }, }); return { w, vm: w.vm as unknown as CreateVm }; } describe('SalesProspectCreateDialog', () => { beforeEach(() => vi.clearAllMocks()); it('без названия не эмитит create', () => { const { w, vm } = factory(); vm.inn = '5501234560'; vm.submit(); expect(w.emitted('create')).toBeFalsy(); }); it('без ИНН карточка всё равно заводится (обязательно только название)', () => { const { w, vm } = factory(); vm.firmName = 'Без ИНН'; vm.submit(); expect(w.emitted('create')?.[0]?.[0]).toMatchObject({ firm_name: 'Без ИНН', inn: null }); expect(vm.error).toBe(''); }); it('кривой ИНН не пускаем дальше формы', () => { const { w, vm } = factory(); vm.firmName = 'Опечатка'; vm.inn = '5501234567'; vm.submit(); expect(w.emitted('create')).toBeFalsy(); }); it('эмитит create с брендом, юрлицом и контактными лицами', () => { const { w, vm } = factory(); vm.firmName = 'Стоматология «Улыбка»'; vm.legalName = 'ООО «Улыбка Плюс»'; vm.inn = '5501234560'; vm.city = 'Омск'; vm.contacts = [ { name: 'Иванов Иван', position: 'директор', phones: ['+79130000001', '+73812000002'] }, ]; vm.submit(); expect(w.emitted('create')?.[0]?.[0]).toMatchObject({ firm_name: 'Стоматология «Улыбка»', legal_name: 'ООО «Улыбка Плюс»', inn: '5501234560', city: 'Омск', contacts: [ { name: 'Иванов Иван', position: 'директор', phones: ['+79130000001', '+73812000002'] }, ], }); }); it('пустые контакты и телефоны не уходят на сервер', () => { const { w, vm } = factory(); vm.firmName = 'Полупустые'; vm.inn = '5501234560'; vm.contacts = [ { name: ' ', position: '', phones: ['', ' '] }, { name: 'Сидоров', position: '', phones: ['+79130000009', ''] }, ]; vm.submit(); const payload = w.emitted('create')?.[0]?.[0] as Record; expect(payload.contacts).toEqual([{ name: 'Сидоров', position: null, phones: ['+79130000009'] }]); }); it('поиск по ИНН подставляет юрлицо и город', async () => { (lookupProspectInn as ReturnType).mockResolvedValue({ found: true, legal_name: 'ООО «Улыбка Плюс»', city: 'Омск', }); const { vm } = factory(); vm.inn = '5501234560'; await vm.lookup(); await flushPromises(); expect(lookupProspectInn).toHaveBeenCalledWith('5501234560'); expect(vm.legalName).toBe('ООО «Улыбка Плюс»'); expect(vm.city).toBe('Омск'); }); it('поиск не затирает город, если менеджер уже вписал свой', async () => { (lookupProspectInn as ReturnType).mockResolvedValue({ found: true, legal_name: 'ООО «Улыбка Плюс»', city: 'Омск', }); const { vm } = factory(); vm.inn = '5501234560'; vm.city = 'Красноярск'; await vm.lookup(); await flushPromises(); expect(vm.city).toBe('Красноярск'); }); it('ДаData не нашла → говорим об этом и не мешаем заполнить руками', async () => { (lookupProspectInn as ReturnType).mockResolvedValue({ found: false }); const { vm } = factory(); vm.inn = '5501234560'; await vm.lookup(); await flushPromises(); expect(vm.error).not.toBe(''); expect(vm.legalName).toBe(''); expect(vm.lookingUp).toBe(false); }); it('ДаData упала → форма остаётся рабочей', async () => { (lookupProspectInn as ReturnType).mockRejectedValue(new Error('network')); const { vm } = factory(); vm.inn = '5501234560'; await vm.lookup(); await flushPromises(); expect(vm.lookingUp).toBe(false); }); });