98614604af
Раздел «Сделки»: колонка «Источник» разбита на две — «Конкурент» (ссылка на экран конкурента) и «Источник» (ссылка на «Настройки проекта»). В модалку настроек добавлена кнопка пуск/стоп (срабатывает не закрывая окно). - бэк DealController::index: батч-резолв конкурента+источника по deal.project_id → autopodbor_sources.created_project_id → competitor (без N+1) - контракт ApiDeal/MockDeal + маппер: competitor_*/source_* поля - DealsTable: 1 колонка → 2 (Конкурент/Источник), router-link, fallback без автоподбора - AutopodborView: deep-link ?competitor=&project= открывает экран конкурента + модалку - FieldCompetitorScreen: кнопка ⏸/▶ в модалке настроек + авто-открытие по ссылке Тесты: бэк DealIndexTest +4 (31 ✅), фронт +новые (66 ✅). Дизайн не менялся. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
70 lines
2.7 KiB
TypeScript
70 lines
2.7 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||
import { mount, flushPromises } from '@vue/test-utils';
|
||
import { createPinia, setActivePinia } from 'pinia';
|
||
import { createRouter, createMemoryHistory } from 'vue-router';
|
||
|
||
vi.mock('../../resources/js/stores/autopodborStore', () => ({
|
||
useAutopodborStore: () => ({ loadState: vi.fn().mockResolvedValue(undefined) }),
|
||
}));
|
||
|
||
import AutopodborView from '../../resources/js/views/autopodbor/AutopodborView.vue';
|
||
|
||
async function mountWithQuery(query: Record<string, string>) {
|
||
const router = createRouter({
|
||
history: createMemoryHistory(),
|
||
routes: [{ path: '/autopodbor', name: 'autopodbor', component: { template: '<div />' } }],
|
||
});
|
||
await router.push({ path: '/autopodbor', query });
|
||
await router.isReady();
|
||
|
||
return mount(AutopodborView, {
|
||
global: {
|
||
plugins: [router],
|
||
stubs: {
|
||
FieldWorkspaceScreen: { template: '<div>field</div>' },
|
||
FieldCompetitorScreen: { template: '<div class="fc">competitor screen</div>' },
|
||
EditProjectScreen: true,
|
||
FieldProposalsScreen: true,
|
||
EntryScreen: true,
|
||
AutoFormScreen: true,
|
||
ManualFormScreen: true,
|
||
LoadingScreen: true,
|
||
ListScreen: true,
|
||
DetailScreen: true,
|
||
CreateScreen: true,
|
||
DoneScreen: true,
|
||
},
|
||
},
|
||
});
|
||
}
|
||
|
||
describe('AutopodborView deep-link (?competitor=&project=)', () => {
|
||
beforeEach(() => setActivePinia(createPinia()));
|
||
|
||
it('query competitor → экран конкурента с ctx.competitorId', async () => {
|
||
const w = await mountWithQuery({ competitor: '3' });
|
||
await flushPromises();
|
||
expect((w.vm as any).screen).toBe('fieldcompetitor');
|
||
expect((w.vm as any).ctx.competitorId).toBe(3);
|
||
});
|
||
|
||
it('query competitor+project → выставлен ctx.openProjectSettingsId', async () => {
|
||
const w = await mountWithQuery({ competitor: '3', project: '5' });
|
||
await flushPromises();
|
||
expect((w.vm as any).ctx.openProjectSettingsId).toBe(5);
|
||
});
|
||
|
||
it('без query — дефолтный экран field', async () => {
|
||
const w = await mountWithQuery({});
|
||
await flushPromises();
|
||
expect((w.vm as any).screen).toBe('field');
|
||
expect((w.vm as any).ctx.competitorId).toBeNull();
|
||
});
|
||
|
||
it('невалидный competitor — остаёмся на field', async () => {
|
||
const w = await mountWithQuery({ competitor: 'abc' });
|
||
await flushPromises();
|
||
expect((w.vm as any).screen).toBe('field');
|
||
});
|
||
});
|