fix(deals): router в DealsViewRedesign.spec + idempotency guard + watch-test (C8/F3 review fixup)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -174,7 +174,7 @@ onMounted(async () => {
|
||||
});
|
||||
|
||||
watch(
|
||||
() => route?.query?.openId,
|
||||
() => route.query.openId,
|
||||
() => openDealFromQuery(),
|
||||
);
|
||||
|
||||
@@ -228,12 +228,10 @@ function openDeal(deal: MockDeal) {
|
||||
|
||||
/** Audit C8/F3: deep-link — открыть drawer сделки по ?openId= из URL. */
|
||||
function openDealFromQuery(): void {
|
||||
// Guard: route may be undefined when component is mounted without a router
|
||||
// (e.g. isolated unit tests in DealsViewRedesign.spec.ts).
|
||||
if (!route) return;
|
||||
const raw = route.query.openId;
|
||||
const id = Number(Array.isArray(raw) ? raw[0] : raw);
|
||||
if (!Number.isInteger(id) || id <= 0) return;
|
||||
if (selectedDeal.value?.id === id) return;
|
||||
const deal = dealsState.find((d) => d.id === id);
|
||||
if (deal) openDeal(deal);
|
||||
}
|
||||
@@ -432,7 +430,6 @@ defineExpose({
|
||||
toggleManagerDraft,
|
||||
drawerOpen,
|
||||
selectedDeal,
|
||||
openDealFromQuery,
|
||||
});
|
||||
|
||||
const leadStatuses = computed(() => leadStatusesStore.statuses);
|
||||
|
||||
@@ -305,4 +305,16 @@ describe('DealsView.vue', () => {
|
||||
const vm = wrapper.vm as unknown as { drawerOpen: boolean };
|
||||
expect(vm.drawerOpen).toBe(false);
|
||||
});
|
||||
|
||||
it('навигация на /deals?openId= в смонтированном view открывает drawer (watch)', async () => {
|
||||
const openId = MOCK_DEALS[0].id;
|
||||
const wrapper = await mountDealsViewAt('/deals');
|
||||
await flushPromises();
|
||||
const vm = wrapper.vm as unknown as { drawerOpen: boolean; selectedDeal: { id: number } | null };
|
||||
expect(vm.drawerOpen).toBe(false);
|
||||
await wrapper.vm.$router.push(`/deals?openId=${openId}`);
|
||||
await flushPromises();
|
||||
expect(vm.drawerOpen).toBe(true);
|
||||
expect(vm.selectedDeal?.id).toBe(openId);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -56,13 +56,20 @@ describe('DealsView — redesigned', () => {
|
||||
});
|
||||
|
||||
describe('FilterChip popovers (Sprint 1 C2)', () => {
|
||||
it('clicking Project chip toggles projectMenuOpen ref to true', async () => {
|
||||
const wrapper = mount(DealsView, {
|
||||
function setupWithRouter() {
|
||||
setActivePinia(createPinia());
|
||||
const router = createRouter({ history: createMemoryHistory(), routes: [{ path: '/deals', component: DealsView }] });
|
||||
router.push('/deals');
|
||||
return mount(DealsView, {
|
||||
global: {
|
||||
plugins: [createPinia(), createVuetify()],
|
||||
plugins: [router, createVuetify()],
|
||||
stubs: { DealDetailDrawer: true, NewDealDialog: true, VMenu: { template: '<div><slot name="activator" :props="{}" /><slot /></div>' } },
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
it('clicking Project chip toggles projectMenuOpen ref to true', async () => {
|
||||
const wrapper = setupWithRouter();
|
||||
await new Promise((r) => setTimeout(r, 50));
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const vm = wrapper.vm as any;
|
||||
@@ -75,12 +82,7 @@ describe('FilterChip popovers (Sprint 1 C2)', () => {
|
||||
});
|
||||
|
||||
it('clicking Manager chip toggles managerMenuOpen ref to true', async () => {
|
||||
const wrapper = mount(DealsView, {
|
||||
global: {
|
||||
plugins: [createPinia(), createVuetify()],
|
||||
stubs: { DealDetailDrawer: true, NewDealDialog: true, VMenu: { template: '<div><slot name="activator" :props="{}" /><slot /></div>' } },
|
||||
},
|
||||
});
|
||||
const wrapper = setupWithRouter();
|
||||
await new Promise((r) => setTimeout(r, 50));
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const vm = wrapper.vm as any;
|
||||
@@ -93,12 +95,7 @@ describe('FilterChip popovers (Sprint 1 C2)', () => {
|
||||
});
|
||||
|
||||
it('applying project selection updates filterProjects and closes menu', async () => {
|
||||
const wrapper = mount(DealsView, {
|
||||
global: {
|
||||
plugins: [createPinia(), createVuetify()],
|
||||
stubs: { DealDetailDrawer: true, NewDealDialog: true, VMenu: { template: '<div><slot name="activator" :props="{}" /><slot /></div>' } },
|
||||
},
|
||||
});
|
||||
const wrapper = setupWithRouter();
|
||||
await new Promise((r) => setTimeout(r, 50));
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const vm = wrapper.vm as any;
|
||||
|
||||
Reference in New Issue
Block a user