Files
portal/app/tests/Frontend/deals-api.spec.ts
T
Дмитрий e280edd431 style(frontend): apply prettier --write — fix formatting drift
4 files reformatted (import list expansion, line-length wrapping).
Vitest 88/683+3sk green.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 13:30:51 +03:00

180 lines
6.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, it, expect, beforeEach, vi } from 'vitest';
vi.mock('../../resources/js/api/client', () => ({
apiClient: {
get: vi.fn(),
post: vi.fn(),
patch: vi.fn(),
delete: vi.fn(),
},
ensureCsrfCookie: vi.fn(),
}));
import {
createDeal,
bulkDeleteDeals,
bulkRestoreDeals,
updateDeal,
transitionDeals,
exportDeals,
exportDealsXlsx,
getDeal,
listDeals,
listManagers,
listProjects,
} from '../../resources/js/api/deals';
import { apiClient, ensureCsrfCookie } from '../../resources/js/api/client';
const FAKE_DEAL = {
id: 1,
tenant_id: 1,
project_id: 1,
project_name: 'Test',
phone: '+79161234567',
contact_name: 'X',
status: 'new',
manager_id: null,
manager_name: null,
manager_initials: null,
received_at: null,
comment: null,
assigned_at: null,
};
describe('api/deals', () => {
beforeEach(() => vi.clearAllMocks());
it('createDeal() POSTs /api/deals + ensureCsrfCookie + unwraps data.deal', async () => {
vi.mocked(apiClient.post).mockResolvedValue({ data: { deal: FAKE_DEAL, message: 'ok' } });
const r = await createDeal({ tenant_id: 1, project_name: 'P', phone: '+79161234567' });
expect(ensureCsrfCookie).toHaveBeenCalledOnce();
expect(apiClient.post).toHaveBeenCalledWith('/api/deals', {
tenant_id: 1,
project_name: 'P',
phone: '+79161234567',
});
expect(r.id).toBe(1);
});
it('bulkDeleteDeals() DELETE /api/deals с data payload', async () => {
vi.mocked(apiClient.delete).mockResolvedValue({ data: { deleted: 3, requested: 4 } });
const r = await bulkDeleteDeals({ tenant_id: 1, ids: [1, 2, 3, 4] });
expect(ensureCsrfCookie).toHaveBeenCalledOnce();
expect(apiClient.delete).toHaveBeenCalledWith('/api/deals', { data: { tenant_id: 1, ids: [1, 2, 3, 4] } });
expect(r.deleted).toBe(3);
});
it('bulkRestoreDeals() POSTs /api/deals/restore', async () => {
vi.mocked(apiClient.post).mockResolvedValue({ data: { restored: 2, requested: 2 } });
await bulkRestoreDeals({ tenant_id: 1, ids: [1, 2] });
expect(ensureCsrfCookie).toHaveBeenCalledOnce();
expect(apiClient.post).toHaveBeenCalledWith('/api/deals/restore', { tenant_id: 1, ids: [1, 2] });
});
it('updateDeal() PATCH /api/deals/{id} c partial payload', async () => {
vi.mocked(apiClient.patch).mockResolvedValue({ data: { deal: FAKE_DEAL } });
await updateDeal(42, { tenant_id: 1, comment: 'new' });
expect(ensureCsrfCookie).toHaveBeenCalledOnce();
expect(apiClient.patch).toHaveBeenCalledWith('/api/deals/42', { tenant_id: 1, comment: 'new' });
});
it('transitionDeals() POSTs /api/deals/transition с status', async () => {
vi.mocked(apiClient.post).mockResolvedValue({ data: { updated: 5, requested: 5, status: 'won' } });
const r = await transitionDeals({ tenant_id: 1, ids: [1, 2, 3, 4, 5], status: 'won' });
expect(apiClient.post).toHaveBeenCalledWith('/api/deals/transition', {
tenant_id: 1,
ids: [1, 2, 3, 4, 5],
status: 'won',
});
expect(r.status).toBe('won');
});
it('exportDeals() POSTs /api/deals/export с format=csv + responseType=text', async () => {
vi.mocked(apiClient.post).mockResolvedValue({ data: 'id,phone\n1,+79..' });
const r = await exportDeals({ tenant_id: 1, ids: [1] });
expect(ensureCsrfCookie).toHaveBeenCalledOnce();
expect(apiClient.post).toHaveBeenCalledWith(
'/api/deals/export',
{ tenant_id: 1, ids: [1], format: 'csv' },
{ responseType: 'text' },
);
expect(typeof r).toBe('string');
});
it('exportDealsXlsx() POSTs /api/deals/export с format=xlsx + responseType=blob', async () => {
const blob = new Blob(['fake'], { type: 'application/octet-stream' });
vi.mocked(apiClient.post).mockResolvedValue({ data: blob });
const r = await exportDealsXlsx({ tenant_id: 1, ids: [1, 2] });
expect(apiClient.post).toHaveBeenCalledWith(
'/api/deals/export',
{ tenant_id: 1, ids: [1, 2], format: 'xlsx' },
{ responseType: 'blob' },
);
expect(r).toBeInstanceOf(Blob);
});
it('getDeal() GET /api/deals/{id} с tenant_id param', async () => {
vi.mocked(apiClient.get).mockResolvedValue({ data: { deal: FAKE_DEAL, events: [] } });
const r = await getDeal(7, 1);
expect(apiClient.get).toHaveBeenCalledWith('/api/deals/7', { params: { tenant_id: 1 } });
expect(r.events).toEqual([]);
});
it('listDeals() GET /api/deals с маппингом camelCase→snake_case + onlyDeleted flag', async () => {
vi.mocked(apiClient.get).mockResolvedValue({
data: { deals: [], total: 0, limit: 50, offset: 0 },
});
await listDeals({
tenantId: 1,
statusIn: ['new', 'in_progress'],
projectId: 2,
managerId: 3,
search: 'q',
limit: 50,
offset: 0,
onlyDeleted: true,
});
expect(apiClient.get).toHaveBeenCalledWith('/api/deals', {
params: {
tenant_id: 1,
status_in: ['new', 'in_progress'],
project_id: 2,
manager_id: 3,
search: 'q',
limit: 50,
offset: 0,
only_deleted: 'true',
},
});
});
it('listDeals() без onlyDeleted → only_deleted=undefined', async () => {
vi.mocked(apiClient.get).mockResolvedValue({ data: { deals: [], total: 0, limit: 50, offset: 0 } });
await listDeals({ tenantId: 1 });
expect(apiClient.get).toHaveBeenCalledWith(
'/api/deals',
expect.objectContaining({ params: expect.objectContaining({ only_deleted: undefined }) }),
);
});
it('listManagers() GET /api/managers + unwraps data.managers', async () => {
vi.mocked(apiClient.get).mockResolvedValue({
data: {
managers: [{ id: 1, email: 'm@x.ru', first_name: 'M', last_name: 'X', name: 'M X', initials: 'MX' }],
},
});
const r = await listManagers(1);
expect(apiClient.get).toHaveBeenCalledWith('/api/managers', { params: { tenant_id: 1 } });
expect(r).toHaveLength(1);
});
it('listProjects() GET /api/projects + unwraps data.projects', async () => {
vi.mocked(apiClient.get).mockResolvedValue({
data: { projects: [{ id: 1, name: 'P', tag: 'site', type: 'webhook' }] },
});
const r = await listProjects(1);
expect(apiClient.get).toHaveBeenCalledWith('/api/projects', { params: { tenant_id: 1 } });
expect(r[0].name).toBe('P');
});
});