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 DetailScreen from '../../resources/js/views/autopodbor/screens/DetailScreen.vue'; import { useAutopodborStore } from '../../resources/js/stores/autopodborStore'; const vuetify = createVuetify(); function makeNav(competitorId = 3) { return { go: vi.fn(), ctx: reactive({ runId: null, competitorId, selectedSourceIds: [] as number[], loadMsg: '', loadSub: '', editProjectId: null as number|null }), screen: ref('detail') }; } function mountDetail(nav: any) { return mount(DetailScreen, { global: { plugins: [vuetify], provide: { autopodborNav: nav } } }); } function seed(store: any) { store.competitor = { id: 3, name: 'Окна Комфорт', is_federal: false, relevance_pct: 100, origin: 'auto', site_url: 'okna.ru', directory_urls: [], description: 'd', studied_at: '2026-06-28', study_run_id: 9, search_run_id: 5 }; store.sources = [ { id: 11, competitor_id: 3, signal_type: 'site', identifier: 'okna-komfort-kzn.ru', phone_kind: null, provenance_url: null, provenance_label: '2ГИС', created_project_id: null, existing_project_id: null }, { id: 12, competitor_id: 3, signal_type: 'call', identifier: '78432001122', phone_kind: 'real', provenance_url: null, provenance_label: '2ГИС', created_project_id: null, existing_project_id: null }, { id: 13, competitor_id: 3, signal_type: 'call', identifier: '78003507700', phone_kind: 'substitute', provenance_url: null, provenance_label: 'футер', created_project_id: 99, existing_project_id: 99 }, ]; } describe('DetailScreen', () => { beforeEach(() => { setActivePinia(createPinia()); vi.clearAllMocks(); }); it('грузит конкурента и показывает источники', async () => { const store = useAutopodborStore(); vi.spyOn(store, 'loadCompetitor').mockImplementation(async () => seed(store)); const nav = makeNav(3); const w = mountDetail(nav); await new Promise(r => setTimeout(r, 0)); expect(store.loadCompetitor).toHaveBeenCalledWith(3); expect(w.text()).toContain('okna-komfort-kzn.ru'); expect(w.text()).toContain('проект создан'); // источник 13 с existing_project_id }); it('по умолчанию выбраны источники без проекта (11 и 12, не 13)', async () => { const store = useAutopodborStore(); vi.spyOn(store, 'loadCompetitor').mockImplementation(async () => seed(store)); const nav = makeNav(3); mountDetail(nav); await new Promise(r => setTimeout(r, 0)); expect(nav.ctx.selectedSourceIds).toContain(11); expect(nav.ctx.selectedSourceIds).toContain(12); expect(nav.ctx.selectedSourceIds).not.toContain(13); }); it('«Создать проекты» ведёт на create', async () => { const store = useAutopodborStore(); vi.spyOn(store, 'loadCompetitor').mockImplementation(async () => seed(store)); const nav = makeNav(3); const w = mountDetail(nav); await new Promise(r => setTimeout(r, 0)); const btn = w.findAll('button').find(b => b.text().includes('Создать проекты')); await btn!.trigger('click'); expect(nav.go).toHaveBeenCalledWith('create'); }); it('«Изменить проект» у созданного источника ведёт на editproject', async () => { const store = useAutopodborStore(); vi.spyOn(store, 'loadCompetitor').mockImplementation(async () => seed(store)); const nav = makeNav(3); const w = mountDetail(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.editProjectId).toBe(99); expect(nav.go).toHaveBeenCalledWith('editproject'); }); });