Files
portal/app/tests/Frontend/ProspectContactsEditor.spec.ts
T
Дмитрий 68428f16c6 @
feat(sales): карточка кандидата — девять полей владельца + правка контактных лиц

Владелец задал список полей карточки и попросил дать менеджеру записывать
контактных лиц прямо в карточке: поиск отдаёт 5-7 ПРЕДПОЛАГАЕМЫХ номеров
директора, живой из них выясняется обзвоном; а если директор перенаправил
к маркетологу — менеджер фиксирует и его, людей может быть 2-3.

- Карточка показывает РОВНО девять полей в его порядке: Юрлицо, Сайт, ИНН фирмы,
  Адрес, Телефон общий, Каналы, Бюджет, Директор, Тел. директора (предполагаемый).
  Убраны Оценка, Достоверность, Реклама, Запросы в Директе, ОГРН, Статус юрлица,
  Личный ИНН директора, Почта директора — данные остаются в payload.
- PATCH /api/sales/prospects/{id}/contacts — список заменяется целиком, пустой
  стирает всех; права как у update() (менеджер свои, начальник любые); главный
  телефон карточки из поиска не трогается.
- ProspectContactsEditor.vue + utils/prospectContacts.ts — один редактор контактов
  на диалог создания и карточку; диалог создания переведён на него.
- Закрывает хвост §16: у 24 живых карточек из поиска контактных лиц не было,
  теперь дозаполняются руками.

Спека §18. Гейты: Pest 223/223 sales, Vitest 196 файлов / 1397 тестов,
vue-tsc чисто, Larastan 0 в своих файлах. TDD RED→GREEN на каждом шаге.

LEFTHOOK_EXCLUDE: larastan/cspell падают на файлах параллельной сессии
tests/Feature/Admin/*Balances*, свои файлы проверены отдельно и чисты.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
2026-07-18 12:29:04 +03:00

83 lines
3.3 KiB
TypeScript

import { mount } from '@vue/test-utils';
import { createVuetify } from 'vuetify';
import { describe, expect, it } from 'vitest';
import ProspectContactsEditor from '../../resources/js/components/sales/ProspectContactsEditor.vue';
import { cleanContacts, toForm, type ContactForm } from '../../resources/js/utils/prospectContacts';
const vuetify = createVuetify();
interface EditorVm {
rows: ContactForm[];
addContact: () => void;
removeContact: (i: number) => void;
addPhone: (i: number) => void;
removePhone: (i: number, j: number) => void;
}
function factory(modelValue: ContactForm[] = [{ name: '', position: '', phones: [''] }]) {
const w = mount(ProspectContactsEditor, { props: { modelValue }, global: { plugins: [vuetify] } });
return { w, vm: w.vm as unknown as EditorVm };
}
describe('ProspectContactsEditor', () => {
it('добавляет и убирает людей', () => {
const { vm } = factory();
expect(vm.rows).toHaveLength(1);
vm.addContact();
expect(vm.rows).toHaveLength(2);
vm.removeContact(1);
expect(vm.rows).toHaveLength(1);
});
it('последнего человека убрать нельзя — остаётся пустая строка', () => {
const { vm } = factory();
vm.removeContact(0);
expect(vm.rows).toHaveLength(1);
expect(vm.rows[0].name).toBe('');
});
it('добавляет и убирает телефоны, последний остаётся пустой строкой', () => {
const { vm } = factory();
vm.addPhone(0);
expect(vm.rows[0].phones).toHaveLength(2);
vm.removePhone(0, 1);
expect(vm.rows[0].phones).toHaveLength(1);
vm.removePhone(0, 0);
expect(vm.rows[0].phones).toEqual(['']);
});
it('изменения уходят наверх через update:modelValue', () => {
const { w, vm } = factory();
vm.addContact();
expect(w.emitted('update:modelValue')).toBeTruthy();
});
});
describe('утилиты контактов', () => {
it('toForm: пустой список → одна пустая строка', () => {
expect(toForm([])).toEqual([{ name: '', position: '', phones: [''] }]);
expect(toForm(null)).toHaveLength(1);
});
it('toForm: сохранённые контакты разворачиваются в форму', () => {
const rows = toForm([{ name: 'Захаров', position: 'директор', phones: ['+79136518088'] }]);
expect(rows[0]).toEqual({ name: 'Захаров', position: 'директор', phones: ['+79136518088'] });
});
it('toForm: контакт без телефонов получает пустую заготовку', () => {
expect(toForm([{ name: 'Без телефона', position: null, phones: [] }])[0].phones).toEqual(['']);
});
it('cleanContacts: мусор выброшен, должность пустая → null', () => {
const out = cleanContacts([
{ name: ' ', position: '', phones: ['', ' '] },
{ name: 'Сидоров', position: ' ', phones: ['+79130000009', ''] },
]);
expect(out).toEqual([{ name: 'Сидоров', position: null, phones: ['+79130000009'] }]);
});
});