Files
portal/app/tests/Frontend/AdminSupplierProjectsView.spec.ts
T
Дмитрий f1a3e9f02f feat(admin): supplier projects cleanup screen (list + bulk delete)
План 4 Task 3 эпика project-migration-redesign.

- AdminSupplierProjectsView.vue — v-data-table (источник/платформа/регион/
  лимит/кто заказывал/последняя поставка) + bulk-delete с v-dialog
  подтверждением + snackbar (deleted/failures).
- Роут /admin/supplier-projects (layout admin, requiresAuth, devIndex 31).
- AdminLayout nav-пункт «Проекты у поставщика».
- Vitest 3/3 (mount GET, bulk-delete confirm POST {ids}, disabled when empty).

NB: type-check имеет 3 pre-existing ошибки в DealDetailHero.spec.ts
(коммит 1412d3f, не Plan 4); файлы T3 type-check-чисты.
2026-05-20 14:34:25 +03:00

84 lines
3.1 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { mount, flushPromises } from '@vue/test-utils';
import { createVuetify } from 'vuetify';
import * as components from 'vuetify/components';
import * as directives from 'vuetify/directives';
import axios from 'axios';
import AdminSupplierProjectsView from '../../resources/js/views/admin/AdminSupplierProjectsView.vue';
vi.mock('axios');
const vuetify = createVuetify({ components, directives });
// VDialog телепортит контент в body → стаб рендерит слот инлайн (квирк: VDialog
// teleport стаб для поиска confirm-кнопки внутри диалога).
const mountView = () =>
mount(AdminSupplierProjectsView, {
global: {
plugins: [vuetify],
stubs: { VDialog: { template: '<div><slot /></div>' } },
},
});
describe('AdminSupplierProjectsView (Plan 4 Task 3)', () => {
beforeEach(() => {
vi.clearAllMocks();
(axios.get as ReturnType<typeof vi.fn>).mockResolvedValue({
data: {
projects: [
{
id: 1,
platform: 'B1',
signal_type: 'site',
unique_key: 'okna.ru',
subject_code: 82,
subject_name: 'Москва',
current_limit: 5,
supplier_external_id: '777',
orderers: ['ООО Ромашка'],
last_delivery_at: '2026-05-19T10:00:00Z',
},
],
},
});
(axios.post as ReturnType<typeof vi.fn>).mockResolvedValue({
data: { deleted: 1, failures: [] },
});
});
it('GETs list on mount and renders rows (source, region, orderers)', async () => {
const wrapper = mountView();
await flushPromises();
expect(axios.get).toHaveBeenCalledWith('/api/admin/supplier-integration/projects');
const text = wrapper.text();
expect(text).toContain('okna.ru');
expect(text).toContain('Москва');
expect(text).toContain('ООО Ромашка');
});
it('bulk-deletes selected rows after confirm', async () => {
const wrapper = mountView();
await flushPromises();
await wrapper.find('[data-testid="row-checkbox-1"] input').setValue(true);
await wrapper.find('[data-testid="bulk-delete-btn"]').trigger('click');
await flushPromises();
await wrapper.find('[data-testid="confirm-delete-btn"]').trigger('click');
await flushPromises();
expect(axios.post).toHaveBeenCalledWith(
'/api/admin/supplier-integration/projects/delete',
{ ids: [1] },
);
});
it('bulk-delete button is disabled when nothing selected', async () => {
const wrapper = mountView();
await flushPromises();
const btn = wrapper.find('[data-testid="bulk-delete-btn"]');
expect(btn.attributes('disabled')).toBeDefined();
});
});