Files
portal/app/tests/Frontend/TopupDialog.spec.ts
T
Дмитрий 3daa4995ea feat(billing): фронт — редирект на оплату при confirmation_url + баннер возврата
TopupResult допускает confirmation_url; TopupDialog при нём редиректит на
страницу ЮKassa (через тестируемый redirectTo), иначе прежнее мгновенное
зачисление. BillingView показывает баннер «платёж обрабатывается» при
возврате ?topup=return. Пресеты сумм уже были.
2026-06-22 21:50:13 +03:00

84 lines
3.6 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, vi, beforeEach } from 'vitest';
import { mount, flushPromises } from '@vue/test-utils';
import { createVuetify } from 'vuetify';
import TopupDialog from '../../resources/js/components/billing/TopupDialog.vue';
import * as billingApi from '../../resources/js/api/billing';
import * as redirectUtil from '../../resources/js/utils/redirect';
vi.mock('../../resources/js/api/billing');
vi.mock('../../resources/js/utils/redirect');
const vuetify = createVuetify();
const factory = () =>
mount(TopupDialog, {
global: { plugins: [vuetify] },
props: { modelValue: true },
});
describe('TopupDialog.vue', () => {
beforeEach(() => {
vi.mocked(billingApi.topup).mockResolvedValue({
transaction: {
id: 1,
type: 'topup',
amount_rub: '5000.00',
balance_rub_after: '5000.00',
created_at: '2026-05-16T00:00:00Z',
},
balance_rub: '5000.00',
});
});
it('блокирует submit при сумме ниже 100 ₽', async () => {
const wrapper = factory();
(wrapper.vm as unknown as { amount: number | null }).amount = 50;
await flushPromises();
expect((wrapper.vm as unknown as { canSubmit: boolean }).canSubmit).toBe(false);
});
it('разрешает submit при валидной сумме', async () => {
const wrapper = factory();
(wrapper.vm as unknown as { amount: number | null }).amount = 5000;
await flushPromises();
expect((wrapper.vm as unknown as { canSubmit: boolean }).canSubmit).toBe(true);
});
it('submit вызывает topup и эмитит success с новым балансом', async () => {
const wrapper = factory();
(wrapper.vm as unknown as { amount: number | null }).amount = 5000;
await (wrapper.vm as unknown as { submit: () => Promise<void> }).submit();
await flushPromises();
expect(billingApi.topup).toHaveBeenCalledWith(5000);
expect(wrapper.emitted('success')?.[0]).toEqual(['5000.00']);
});
it('блокирует submit при нечисловом значении (очищенное поле)', async () => {
const wrapper = factory();
(wrapper.vm as unknown as { amount: number }).amount = NaN;
await flushPromises();
expect((wrapper.vm as unknown as { canSubmit: boolean }).canSubmit).toBe(false);
});
it('при ответе с confirmation_url делает редирект на оплату, без success', async () => {
vi.mocked(billingApi.topup).mockResolvedValue({
confirmation_url: 'https://yoomoney.ru/checkout/pay_x',
});
const wrapper = factory();
(wrapper.vm as unknown as { amount: number | null }).amount = 5000;
await (wrapper.vm as unknown as { submit: () => Promise<void> }).submit();
await flushPromises();
expect(redirectUtil.redirectTo).toHaveBeenCalledWith('https://yoomoney.ru/checkout/pay_x');
expect(wrapper.emitted('success')).toBeUndefined();
});
it('показывает ошибку при отказе backend', async () => {
vi.mocked(billingApi.topup).mockRejectedValue(new Error('fail'));
const wrapper = factory();
(wrapper.vm as unknown as { amount: number | null }).amount = 5000;
await (wrapper.vm as unknown as { submit: () => Promise<void> }).submit();
await flushPromises();
expect((wrapper.vm as unknown as { errorMsg: string | null }).errorMsg).not.toBeNull();
});
});