b78babe7b4
Диалог дублей: селект имени среди выбранных к слиянию, по умолчанию первое. Merger и ручка принимают опциональное имя. Обе экрана. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
159 lines
6.9 KiB
TypeScript
159 lines
6.9 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 FieldWorkspaceScreen from '../../resources/js/views/autopodbor/screens/FieldWorkspaceScreen.vue';
|
|
import { useAutopodborStore } from '../../resources/js/stores/autopodborStore';
|
|
|
|
const vuetify = createVuetify();
|
|
|
|
function makeNav() {
|
|
return { go: vi.fn(), ctx: reactive({ competitorId: null }), screen: ref('field') };
|
|
}
|
|
|
|
function mountWs(nav: any) {
|
|
return mount(FieldWorkspaceScreen, { global: { plugins: [vuetify], provide: { autopodborNav: nav } } });
|
|
}
|
|
|
|
function baseStore() {
|
|
const store = useAutopodborStore();
|
|
vi.spyOn(store, 'loadField').mockResolvedValue();
|
|
vi.spyOn(store, 'loadProposalGroups').mockResolvedValue();
|
|
return store;
|
|
}
|
|
|
|
describe('FieldWorkspaceScreen — финальный проход «Почистить поле»', () => {
|
|
beforeEach(() => {
|
|
setActivePinia(createPinia());
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
it('открытие окна грузит группы-кандидаты и показывает имена + причину', async () => {
|
|
const store = baseStore();
|
|
vi.spyOn(store, 'loadDuplicateGroups').mockResolvedValue([
|
|
{ reason: 'совпал телефон: 79135396546', competitors: [{ id: 1, name: 'AutoMoney' }, { id: 2, name: 'Автодом24' }] },
|
|
]);
|
|
const w = mountWs(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(store.loadDuplicateGroups).toHaveBeenCalled();
|
|
expect(w.text()).toContain('AutoMoney');
|
|
expect(w.text()).toContain('Автодом24');
|
|
expect(w.text()).toContain('совпал телефон');
|
|
});
|
|
|
|
it('«Объединить» зовёт merge с id группы и убирает группу из окна', 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 = mountWs(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], 'field', 'A');
|
|
expect(vm.dupes.groups.length).toBe(0);
|
|
});
|
|
|
|
it('имя объединённого по умолчанию — первого, передаётся в merge; можно сменить', async () => {
|
|
const store = baseStore();
|
|
vi.spyOn(store, 'loadDuplicateGroups').mockResolvedValue([
|
|
{ reason: 'r', competitors: [{ id: 1, name: 'Сибиряк' }, { id: 2, name: 'Нанжуль' }] },
|
|
]);
|
|
const merge = vi.spyOn(store, 'mergeCompetitors').mockResolvedValue();
|
|
const w = mountWs(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(vm.dupes.groups[0].chosenName).toBe('Сибиряк');
|
|
vm.dupes.groups[0].chosenName = 'Нанжуль';
|
|
await vm.mergeGroup(vm.dupes.groups[0]);
|
|
expect(merge).toHaveBeenCalledWith([1, 2], 'field', 'Нанжуль');
|
|
});
|
|
|
|
it('группа из 3+: объединяем ПОДМНОЖЕСТВО (2 из 3)', async () => {
|
|
const store = baseStore();
|
|
vi.spyOn(store, 'loadDuplicateGroups').mockResolvedValue([
|
|
{ reason: 'r', competitors: [{ id: 1, name: 'A' }, { id: 2, name: 'B' }, { id: 3, name: 'C' }] },
|
|
]);
|
|
const merge = vi.spyOn(store, 'mergeCompetitors').mockResolvedValue();
|
|
const w = mountWs(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(vm.dupes.groups[0].sel).toEqual([1, 2, 3]);
|
|
// снимаем C (id 3) → сливаем только A+B
|
|
vm.toggleDup(vm.dupes.groups[0], 3);
|
|
await vm.mergeGroup(vm.dupes.groups[0]);
|
|
expect(merge).toHaveBeenCalledWith([1, 2], 'field', 'A');
|
|
});
|
|
|
|
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 = mountWs(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.toggleDup(vm.dupes.groups[0], 2); // остаётся только один выбранный
|
|
await vm.mergeGroup(vm.dupes.groups[0]);
|
|
expect(merge).not.toHaveBeenCalled();
|
|
});
|
|
|
|
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 = mountWs(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);
|
|
});
|
|
|
|
it('дублей нет → окно сообщает «дублей не найдено»', async () => {
|
|
const store = baseStore();
|
|
vi.spyOn(store, 'loadDuplicateGroups').mockResolvedValue([]);
|
|
const w = mountWs(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(w.text().toLowerCase()).toContain('дубл');
|
|
});
|
|
});
|