Files
portal/app/tests/Frontend/TransactionsTable.spec.ts
T
Дмитрий ac2c794542 feat(billing): TransactionsTable + InvoicesTable real API (E3)
TransactionsTable — server-driven история транзакций (GET
/api/billing/transactions, табы → фильтр type). InvoicesTable —
GET /api/billing/invoices с empty-state (real-but-empty до Б-1).
billingFormatters почищен (drop status/format-функций), mockBilling
ужат до pending-баннера (E4).

Sprint 2 Plan C, audit E3 (frontend pt2).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 07:56:22 +03:00

66 lines
2.8 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { mount, flushPromises } from '@vue/test-utils';
import { createVuetify } from 'vuetify';
import TransactionsTable from '../../resources/js/components/billing/TransactionsTable.vue';
import * as billingApi from '../../resources/js/api/billing';
import type { BillingTransaction, TransactionsPage } from '../../resources/js/api/billing';
vi.mock('../../resources/js/api/billing');
const vuetify = createVuetify();
function txn(over: Partial<BillingTransaction> = {}): BillingTransaction {
return {
id: 1,
code: 'TX-1',
type: 'topup',
description: 'Пополнение баланса',
amount_rub: '5000.00',
amount_leads: 0,
balance_rub_after: '5000.00',
created_at: '2026-05-10T14:21:00Z',
...over,
};
}
function makePage(txns: BillingTransaction[]): TransactionsPage {
return { data: txns, meta: { current_page: 1, last_page: 1, total: txns.length, per_page: 20 } };
}
describe('TransactionsTable.vue', () => {
beforeEach(() => {
vi.mocked(billingApi.getTransactions).mockResolvedValue(makePage([txn()]));
});
it('загружает транзакции при монтировании', async () => {
const wrapper = mount(TransactionsTable, { global: { plugins: [vuetify] } });
await flushPromises();
expect(billingApi.getTransactions).toHaveBeenCalled();
expect((wrapper.vm as unknown as { total: number }).total).toBe(1);
});
it('смена таба «Пополнения» шлёт type=topup', async () => {
const wrapper = mount(TransactionsTable, { global: { plugins: [vuetify] } });
await flushPromises();
await (wrapper.vm as unknown as { changeTab: (id: string) => Promise<void> }).changeTab('topup');
expect(billingApi.getTransactions).toHaveBeenLastCalledWith(
expect.objectContaining({ type: 'topup' }),
);
});
it('таб «Все» не шлёт type', async () => {
const wrapper = mount(TransactionsTable, { global: { plugins: [vuetify] } });
await flushPromises();
await (wrapper.vm as unknown as { changeTab: (id: string) => Promise<void> }).changeTab('all');
const lastCall = vi.mocked(billingApi.getTransactions).mock.calls.at(-1)?.[0];
expect(lastCall).not.toHaveProperty('type');
});
it('показывает error-alert при сбое', async () => {
vi.mocked(billingApi.getTransactions).mockRejectedValue(new Error('fail'));
const wrapper = mount(TransactionsTable, { global: { plugins: [vuetify] } });
await flushPromises();
expect(wrapper.text()).toContain('Не удалось загрузить транзакции');
});
});