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]); 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 = 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('дубл'); }); });