Files
portal/app/tests/Frontend/FieldProposalsDuplicates.spec.ts
T
Дмитрий df83fa836c feat(автоподбор): Конкурентное поле — финальный проход склейки, вскрыть всё, группы дублей, телефоны, отсев рекламных номеров 2ГИС
Шаг 1 «Конкурентное поле» — чекпоинт:
- Финальный проход «Найти и объединить дубли» на поле и предложениях; клиент решает по каждой группе, ничего не склеиваем молча.
- Тихая склейка только по сайту и коду справочника; телефон и людный номер у более чем 4 фирм — на решение клиента.
- Колонка phones jsonb; телефон-дубли видны уже на «Предложениях».
- Sonar даёт только имя и тип, сайт всегда через EXA; вскрываем все карточки без гейта «есть сайт».
- Яндекс-карточки через локальный Playwright параллельно; рубрика из заголовка идёт в описание.
- Фикс рекламных номеров: 2ГИС-парсер разбирает телефоны пообъектно и выкидывает рекламные кнопки с platforms/caption чужих фирм.

Тесты: автоподбор 224/224 unit, 105/105 feature; фронт-спеки зелёные. Времянки app/scripts/diag-*/probe-* в гит не входят.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 17:34:03 +03:00

90 lines
3.5 KiB
TypeScript

import { describe, it, expect, beforeEach, vi } from 'vitest';
import { mount } from '@vue/test-utils';
import { createPinia, setActivePinia } from 'pinia';
import { createVuetify } from 'vuetify';
import { reactive, ref } from 'vue';
vi.mock('../../resources/js/api/autopodbor');
import FieldProposalsScreen from '../../resources/js/views/autopodbor/screens/FieldProposalsScreen.vue';
import { useAutopodborStore } from '../../resources/js/stores/autopodborStore';
const vuetify = createVuetify();
function makeNav() {
return {
go: vi.fn(),
ctx: reactive({ competitorId: null as number | null, selectedSourceIds: [] as number[] }),
screen: ref('field-proposals'),
};
}
function mountP(nav: any) {
return mount(FieldProposalsScreen, { global: { plugins: [vuetify], provide: { autopodborNav: nav } } });
}
function baseStore() {
const store = useAutopodborStore();
vi.spyOn(store, 'loadProposalGroups').mockResolvedValue();
return store;
}
describe('FieldProposalsScreen — склейка дублей ТОЛЬКО по предложениям', () => {
beforeEach(() => {
setActivePinia(createPinia());
vi.clearAllMocks();
});
it('открытие окна грузит группы по box=proposal и показывает имена', async () => {
const store = baseStore();
const load = vi.spyOn(store, 'loadDuplicateGroups').mockResolvedValue([
{ reason: 'совпал телефон: 79135396546', competitors: [{ id: 1, name: 'AutoMoney' }, { id: 2, name: 'Автодом24' }] },
]);
const w = mountP(makeNav());
await new Promise((r) => setTimeout(r, 0));
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const vm = w.vm as any;
await vm.openDupes();
await w.vm.$nextTick();
expect(load).toHaveBeenCalledWith('proposal');
expect(w.text()).toContain('AutoMoney');
expect(w.text()).toContain('Автодом24');
});
it('«Объединить» зовёт merge с box=proposal и убирает группу', async () => {
const store = baseStore();
vi.spyOn(store, 'loadDuplicateGroups').mockResolvedValue([
{ reason: 'r', competitors: [{ id: 1, name: 'A' }, { id: 2, name: 'B' }] },
]);
const merge = vi.spyOn(store, 'mergeCompetitors').mockResolvedValue();
const w = mountP(makeNav());
await new Promise((r) => setTimeout(r, 0));
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const vm = w.vm as any;
await vm.openDupes();
await w.vm.$nextTick();
await vm.mergeGroup(vm.dupes.groups[0]);
expect(merge).toHaveBeenCalledWith([1, 2], 'proposal');
expect(vm.dupes.groups.length).toBe(0);
});
it('«Это разные» убирает группу без склейки', async () => {
const store = baseStore();
vi.spyOn(store, 'loadDuplicateGroups').mockResolvedValue([
{ reason: 'r', competitors: [{ id: 1, name: 'A' }, { id: 2, name: 'B' }] },
]);
const merge = vi.spyOn(store, 'mergeCompetitors').mockResolvedValue();
const w = mountP(makeNav());
await new Promise((r) => setTimeout(r, 0));
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const vm = w.vm as any;
await vm.openDupes();
await w.vm.$nextTick();
vm.dismissGroup(0);
expect(merge).not.toHaveBeenCalled();
expect(vm.dupes.groups.length).toBe(0);
});
});