128 lines
4.5 KiB
TypeScript
128 lines
4.5 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
import { mount, flushPromises } from '@vue/test-utils';
|
|
import { createVuetify } from 'vuetify';
|
|
import AdminBillingView from '../../resources/js/views/admin/AdminBillingView.vue';
|
|
import type { ApiAdminBillingTenant } from '../../resources/js/api/admin';
|
|
|
|
vi.mock('../../resources/js/api/admin', async (importOriginal) => {
|
|
const orig = await importOriginal<typeof import('../../resources/js/api/admin')>();
|
|
return {
|
|
...orig,
|
|
listAdminBilling: vi.fn(),
|
|
};
|
|
});
|
|
|
|
const adminApi = await import('../../resources/js/api/admin');
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
function makeApiBillingTenant(overrides: Partial<ApiAdminBillingTenant> = {}): ApiAdminBillingTenant {
|
|
return {
|
|
id: 1,
|
|
subdomain: 'test',
|
|
organization_name: 'Test ООО',
|
|
contact_email: 'admin@test.io',
|
|
status: 'active',
|
|
balance_rub: '14250.00',
|
|
tariff_id: 1,
|
|
tariff_name: 'Команда',
|
|
mrr_rub: '990.00',
|
|
monthly_topups_rub: '30000.00',
|
|
monthly_charges_rub: '25400.00',
|
|
last_payment_at: '2026-05-04T10:23:00Z',
|
|
chargeback_unrecovered_rub: '0.00',
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
const mountView = () =>
|
|
mount(AdminBillingView, {
|
|
global: { plugins: [createVuetify()] },
|
|
});
|
|
|
|
describe('AdminBillingView ↔ GET /api/admin/billing integration', () => {
|
|
it('listAdminBilling вызывается на mount', async () => {
|
|
vi.mocked(adminApi.listAdminBilling).mockResolvedValueOnce({
|
|
tenants: [],
|
|
summary: {
|
|
total_mrr_rub: '0',
|
|
monthly_revenue_rub: '0',
|
|
overdue_count: 0,
|
|
refunds_count_30d: 0,
|
|
},
|
|
});
|
|
|
|
mountView();
|
|
await flushPromises();
|
|
expect(adminApi.listAdminBilling).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('успех — replace rowsState + summary; numbers конвертируются из string', async () => {
|
|
vi.mocked(adminApi.listAdminBilling).mockResolvedValueOnce({
|
|
tenants: [
|
|
makeApiBillingTenant({ id: 100, organization_name: 'Окна Москва', balance_rub: '14250.50' }),
|
|
makeApiBillingTenant({
|
|
id: 101,
|
|
organization_name: 'Просрочник',
|
|
balance_rub: '-200.00',
|
|
status: 'active',
|
|
}),
|
|
],
|
|
summary: {
|
|
total_mrr_rub: '1248600.00',
|
|
monthly_revenue_rub: '1318400.00',
|
|
overdue_count: 5,
|
|
refunds_count_30d: 3,
|
|
},
|
|
});
|
|
|
|
const wrapper = mountView();
|
|
await flushPromises();
|
|
|
|
const vm = wrapper.vm as unknown as {
|
|
rowsState: Array<{ id: number; name: string; balance_rub: number; status: string }>;
|
|
summary: { total_mrr_rub: number; overdue_count: number; refunds_count_30d: number };
|
|
};
|
|
expect(vm.rowsState).toHaveLength(2);
|
|
expect(vm.rowsState[0].balance_rub).toBe(14250.5);
|
|
expect(vm.rowsState[1].status).toBe('overdue'); // balance<0 → derive
|
|
expect(vm.summary.total_mrr_rub).toBe(1248600);
|
|
expect(vm.summary.overdue_count).toBe(5);
|
|
expect(vm.summary.refunds_count_30d).toBe(3);
|
|
});
|
|
|
|
it('reject → fetchError=true + alert виден + rowsState пустой', async () => {
|
|
vi.mocked(adminApi.listAdminBilling).mockRejectedValueOnce(new Error('500'));
|
|
|
|
const wrapper = mountView();
|
|
await flushPromises();
|
|
|
|
const vm = wrapper.vm as unknown as { fetchError: boolean; rowsState: unknown[] };
|
|
expect(vm.fetchError).toBe(true);
|
|
expect(vm.rowsState.length).toBe(0);
|
|
expect(wrapper.find('[data-testid="fetch-error-alert"]').exists()).toBe(true);
|
|
});
|
|
|
|
it('reload-btn вызывает listAdminBilling второй раз', async () => {
|
|
vi.mocked(adminApi.listAdminBilling).mockResolvedValue({
|
|
tenants: [],
|
|
summary: {
|
|
total_mrr_rub: '0',
|
|
monthly_revenue_rub: '0',
|
|
overdue_count: 0,
|
|
refunds_count_30d: 0,
|
|
},
|
|
});
|
|
|
|
const wrapper = mountView();
|
|
await flushPromises();
|
|
expect(adminApi.listAdminBilling).toHaveBeenCalledTimes(1);
|
|
|
|
await wrapper.find('[data-testid="reload-btn"]').trigger('click');
|
|
await flushPromises();
|
|
expect(adminApi.listAdminBilling).toHaveBeenCalledTimes(2);
|
|
});
|
|
});
|