import { describe, it, expect, beforeEach, vi } from 'vitest'; import { mount } from '@vue/test-utils'; import { createPinia, setActivePinia } from 'pinia'; import { createVuetify } from 'vuetify'; vi.mock('../../resources/js/api/autopodbor'); import FieldWorkspaceScreen from '../../resources/js/views/autopodbor/screens/FieldWorkspaceScreen.vue'; import { useAutopodborStore } from '../../resources/js/stores/autopodborStore'; import type { FieldCompetitorDto } from '../../resources/js/api/autopodbor'; import { AUTOPODBOR_NAV, type AutopodborNav } from '../../resources/js/views/autopodbor/nav'; import { fieldCompetitor, fieldSource, navStub, sourceProject } from './support/fixtures'; const vuetify = createVuetify(); function makeNav(): AutopodborNav { return navStub('field'); } function field(over: Partial = {}): FieldCompetitorDto { return fieldCompetitor({ description: 'd', relevance_pct: 90, site_url: 'okna.ru', search_run_id: 5, counters: { sources: 2, projects_created: 1, projects_in_work: 1 }, ...over, }); } function mountWs(nav: AutopodborNav) { return mount(FieldWorkspaceScreen, { global: { plugins: [vuetify], provide: { [AUTOPODBOR_NAV]: nav } } }); } describe('FieldWorkspaceScreen', () => { beforeEach(() => { setActivePinia(createPinia()); vi.clearAllMocks(); }); it('грузит поле и показывает конкурентов со счётчиками', async () => { const store = useAutopodborStore(); vi.spyOn(store, 'loadField').mockImplementation(async () => { store.field = [field()]; }); const w = mountWs(makeNav()); await new Promise((r) => setTimeout(r, 0)); expect(store.loadField).toHaveBeenCalled(); expect(w.text()).toContain('Окна Комфорт'); expect(w.text()).toContain('создано проектов'); }); it('сортирует по похожести: 100% сверху', async () => { const store = useAutopodborStore(); vi.spyOn(store, 'loadField').mockImplementation(async () => { store.field = [ field({ id: 1, name: 'Низкая', relevance_pct: 40 }), field({ id: 2, name: 'Высокая', relevance_pct: 100 }), ]; }); const w = mountWs(makeNav()); await new Promise((r) => setTimeout(r, 0)); const names = w.findAll('.ld-card__nm').map((n) => n.text()); expect(names[0]).toContain('Высокая'); }); it('пустое поле показывает заглушку', async () => { const store = useAutopodborStore(); vi.spyOn(store, 'loadField').mockImplementation(async () => { store.field = []; }); const w = mountWs(makeNav()); await new Promise((r) => setTimeout(r, 0)); expect(w.text()).toContain('В поле пока пусто'); }); it('«Собрать конкурентов для меня» открывает окно сбора с ценой', async () => { const store = useAutopodborStore(); vi.spyOn(store, 'loadField').mockResolvedValue(); store.prices = { search: '300', study: '50' }; const w = mountWs(makeNav()); await new Promise((r) => setTimeout(r, 0)); const btn = w.findAll('button').find((b) => b.text().includes('Собрать конкурентов для меня')); await btn!.trigger('click'); expect(w.find('.ld-ovl').exists()).toBe(true); expect(w.text()).toContain('Сбор конкурентов'); expect(w.text()).toContain('300 ₽'); }); it('«Открыть конкурента» открывает карточку', async () => { const store = useAutopodborStore(); vi.spyOn(store, 'loadField').mockImplementation(async () => { store.field = [field({ id: 7 })]; }); const nav = makeNav(); const w = mountWs(nav); await new Promise((r) => setTimeout(r, 0)); const btn = w.findAll('button').find((b) => b.text().includes('Открыть конкурента')); await btn!.trigger('click'); expect(nav.ctx.competitorId).toBe(7); expect(nav.go).toHaveBeenCalledWith('fieldcompetitor'); }); it('всплывающая панель показывается при ≥2 выбранных и массово включает проекты', async () => { const store = useAutopodborStore(); vi.spyOn(store, 'loadField').mockImplementation(async () => { store.field = [ field({ id: 1, sources: [fieldSource({ id: 10, project: sourceProject({ id: 100 }) })], counters: { sources: 1, projects_created: 1, projects_in_work: 0 } }), field({ id: 2, sources: [fieldSource({ id: 11, project: sourceProject({ id: 101 }) })], counters: { sources: 1, projects_created: 1, projects_in_work: 0 } }), ]; }); const toggleSpy = vi.spyOn(store, 'toggleProjectActive').mockResolvedValue(); const w = mountWs(makeNav()); await new Promise((r) => setTimeout(r, 0)); const boxes = w.findAll('.ld-pick'); await boxes[0].trigger('change'); await boxes[1].trigger('change'); expect(w.find('.ld-bulkbar').exists()).toBe(true); const btn = w.findAll('.ld-bulkbar button').find((b) => b.text().includes('Включить')); await btn!.trigger('click'); await new Promise((r) => setTimeout(r, 0)); expect(toggleSpy).toHaveBeenCalledWith(100, true); expect(toggleSpy).toHaveBeenCalledWith(101, true); }); });