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 ListScreen from '../../resources/js/views/autopodbor/screens/ListScreen.vue'; import { useAutopodborStore } from '../../resources/js/stores/autopodborStore'; const vuetify = createVuetify(); function makeNav(runId: number | null = 5) { return { go: vi.fn(), ctx: reactive({ runId, competitorId: null, selectedSourceIds: [], loadMsg: '', loadSub: '' }), screen: ref('list') }; } function mountList(nav: any) { return mount(ListScreen, { global: { plugins: [vuetify], provide: { autopodborNav: nav } } }); } describe('ListScreen', () => { beforeEach(() => { setActivePinia(createPinia()); vi.clearAllMocks(); }); it('загружает и показывает конкурентов прогона', async () => { const store = useAutopodborStore(); vi.spyOn(store, 'loadRunCompetitors').mockImplementation(async () => { store.runCompetitors = [ { id: 1, name: 'Окна Комфорт', is_federal: false, relevance_pct: 100, studied_at: '2026-06-28', origin: 'auto', site_url: 'okna.ru', directory_urls: [], description: 'd', study_run_id: 9, search_run_id: 5 }, { id: 2, name: 'Пластика Окон', is_federal: false, relevance_pct: 96, studied_at: null, origin: 'auto', site_url: 'p.ru', directory_urls: [], description: 'd', study_run_id: null, search_run_id: 5 }, ] as any; }); const nav = makeNav(5); const w = mountList(nav); await new Promise(r => setTimeout(r, 0)); expect(store.loadRunCompetitors).toHaveBeenCalledWith(5); expect(w.text()).toContain('Окна Комфорт'); expect(w.text()).toContain('Пластика Окон'); }); it('«Открыть источники» по изученному ведёт на detail', async () => { const store = useAutopodborStore(); vi.spyOn(store, 'loadRunCompetitors').mockImplementation(async () => { store.runCompetitors = [{ id: 1, name: 'Окна Комфорт', is_federal: false, relevance_pct: 100, studied_at: '2026-06-28', origin: 'auto', site_url: 'okna.ru', directory_urls: [], description: 'd', study_run_id: 9, search_run_id: 5 }] as any; }); const nav = makeNav(5); const w = mountList(nav); await new Promise(r => setTimeout(r, 0)); const btn = w.findAll('button').find(b => b.text().includes('Открыть источники')); expect(btn).toBeTruthy(); await btn!.trigger('click'); expect(nav.ctx.competitorId).toBe(1); expect(nav.go).toHaveBeenCalledWith('detail'); }); it('«Изучить подробнее» по неизученному зовёт store.study', async () => { const store = useAutopodborStore(); vi.spyOn(store, 'loadRunCompetitors').mockImplementation(async () => { store.runCompetitors = [{ id: 2, name: 'Пластика Окон', is_federal: false, relevance_pct: 96, studied_at: null, origin: 'auto', site_url: 'p.ru', directory_urls: [], description: 'd', study_run_id: null, search_run_id: 5 }] as any; }); vi.spyOn(store, 'study').mockResolvedValue({ id: 11, kind: 'study', status: 'queued', competitor_id: 2 } as any); vi.spyOn(store, 'pollRun').mockResolvedValue({ id: 11, kind: 'study', status: 'done', competitor_id: 2 } as any); const nav = makeNav(5); const w = mountList(nav); await new Promise(r => setTimeout(r, 0)); const btn = w.findAll('button').find(b => b.text().includes('Изучить')); await btn!.trigger('click'); await new Promise(r => setTimeout(r, 0)); expect(store.study).toHaveBeenCalledWith(2); expect(nav.go).toHaveBeenCalledWith('detail'); }); });