import { mount } from '@vue/test-utils'; import { beforeEach, describe, expect, it, vi } from 'vitest'; import { createVuetify } from 'vuetify'; import TenantBalanceDialog from '../../resources/js/components/admin/TenantBalanceDialog.vue'; import * as adminApi from '../../resources/js/api/admin'; const vuetify = createVuetify(); function mountDialog(props: Record = {}) { return mount(TenantBalanceDialog, { props: { modelValue: true, tenantId: 42, tenantName: 'Окна Москва ООО', currentBalanceRub: 1000, ...props, }, global: { plugins: [vuetify] }, attachTo: document.body, }); } describe('TenantBalanceDialog', () => { beforeEach(() => { vi.restoreAllMocks(); }); it('previews signed delta when new balance entered', async () => { const w = mountDialog(); (w.vm as unknown as { newBalance: string }).newBalance = '2500'; await w.vm.$nextTick(); expect((w.vm as unknown as { delta: string }).delta).toBe('1500.00'); }); it('disables save when balance empty or unchanged', async () => { const w = mountDialog(); const vm = w.vm as unknown as { newBalance: string; canSave: boolean }; vm.newBalance = ''; await w.vm.$nextTick(); expect((w.vm as unknown as { canSave: boolean }).canSave).toBe(false); vm.newBalance = '1000'; await w.vm.$nextTick(); expect((w.vm as unknown as { canSave: boolean }).canSave).toBe(false); vm.newBalance = '1500'; await w.vm.$nextTick(); expect((w.vm as unknown as { canSave: boolean }).canSave).toBe(true); }); it('calls updateTenantBalance with normalized payload and emits saved', async () => { const spy = vi.spyOn(adminApi, 'updateTenantBalance').mockResolvedValue({ id: 42, balance_rub: '2500.00', delta: '1500.00', transaction_id: 7, }); const w = mountDialog(); const vm = w.vm as unknown as { newBalance: string; reason: string; submit: () => Promise }; vm.newBalance = '2500'; vm.reason = 'тест'; await vm.submit(); expect(spy).toHaveBeenCalledWith(42, { balance_rub: '2500.00', reason: 'тест' }); expect(w.emitted('saved')).toBeTruthy(); expect(w.emitted('saved')![0][0]).toMatchObject({ balance_rub: '2500.00' }); }); });