import { describe, it, expect } from 'vitest'; import { mount } from '@vue/test-utils'; import { createVuetify } from 'vuetify'; import BillingView from '../../resources/js/views/BillingView.vue'; import { MOCK_INVOICES, MOCK_TRANSACTIONS } from '../../resources/js/composables/mockBilling'; describe('BillingView.vue', () => { const factory = () => mount(BillingView, { global: { plugins: [createVuetify()] }, }); it('монтируется и содержит заголовок «Биллинг и тарифы»', () => { const wrapper = factory(); expect(wrapper.find('h1').text()).toBe('Биллинг и тарифы'); }); it('содержит page-stats с кошельком, лидами, runway-днями', () => { const wrapper = factory(); const text = wrapper.text(); expect(text).toMatch(/14\s+250\s*₽/); // кошелёк ₽ expect(text).toContain('285'); expect(text).toContain('лидов запас'); expect(text).toContain('4 дня'); }); it('показывает pending banner («1 платёж в обработке»)', () => { const wrapper = factory(); const text = wrapper.text(); expect(text).toContain('1 платёж в обработке'); expect(text).toMatch(/5\s+000\s*₽/); expect(text).toContain('ЮKassa'); }); it('содержит 3 wallet-cards (₽ / лиды / тариф)', () => { const wrapper = factory(); const text = wrapper.text(); expect(text).toContain('Кошелёк ₽'); expect(text).toContain('LIVE'); expect(text).toContain('Баланс лидов (ГЦК)'); expect(text).toContain('Тариф'); expect(text).toContain('Команда'); expect(text).toContain('990 ₽/мес'); }); it('содержит 3 фичи тарифа', () => { const wrapper = factory(); const text = wrapper.text(); expect(text).toContain('до 10 проектов'); expect(text).toContain('4 менеджера'); expect(text).toContain('Канбан, Webhook, API'); }); it('содержит 4 tab-кнопки в transactions panel', () => { const wrapper = factory(); const text = wrapper.text(); expect(text).toContain('Все'); expect(text).toContain('Пополнения'); expect(text).toContain('Списания'); expect(text).toContain('Возвраты'); }); it('таблица транзакций по умолчанию (Все) содержит все mock-строки', () => { const wrapper = factory(); const rows = wrapper.findAll('tbody tr'); expect(rows.length).toBe(MOCK_TRANSACTIONS.length); }); it('форматирует положительную сумму как «+ N ₽» и отрицательную как «− N ₽»', () => { const wrapper = factory(); const text = wrapper.text(); expect(text).toMatch(/\+\s+5\s+000\s*₽/); // +5000 топап expect(text).toMatch(/−\s+6\s+600\s*₽/); // -6600 списание }); it('rejected-транзакция показывает «— 0 ₽»', () => { const wrapper = factory(); expect(wrapper.text()).toContain('— 0 ₽'); }); it('содержит invoices section с 4 строками', () => { const wrapper = factory(); expect(wrapper.text()).toContain('Счета и УПД'); const rows = wrapper.findAll('.inv-row'); expect(rows.length).toBe(MOCK_INVOICES.length); }); it('invoice показывает PDF или 1С 8.3 XML формат', () => { const wrapper = factory(); const text = wrapper.text(); expect(text).toContain('PDF'); expect(text).toContain('1С 8.3 XML'); }); });