import { describe, it, expect, beforeEach, vi } from 'vitest'; import { setActivePinia, createPinia } from 'pinia'; import { useCartStore } from '@/stores/CartStore.js'; import * as ftch from '@/utils/ftch.js'; // Мокаем API функции vi.mock('@/utils/ftch.js', () => ({ getCart: vi.fn(), addToCart: vi.fn(), cartRemoveItem: vi.fn(), cartEditItem: vi.fn(), setCoupon: vi.fn(), setVoucher: vi.fn(), })); // Мокаем другие stores vi.mock('@/stores/yaMetrikaStore.js', () => ({ useYaMetrikaStore: () => ({ dataLayerPush: vi.fn(), }), })); vi.mock('@/stores/SettingsStore.js', () => ({ useSettingsStore: () => ({ currency_code: 'RUB', }), })); describe('CartStore', () => { beforeEach(() => { setActivePinia(createPinia()); vi.clearAllMocks(); }); describe('state', () => { it('должен инициализироваться с пустыми значениями', () => { const store = useCartStore(); expect(store.items).toEqual([]); expect(store.productsCount).toBe(0); expect(store.total).toBe(0); expect(store.isLoading).toBe(false); expect(store.coupon).toBe(''); expect(store.voucher).toBe(''); }); }); describe('getters', () => { it('canCheckout должен возвращать false при загрузке', () => { const store = useCartStore(); store.isLoading = true; expect(store.canCheckout).toBe(false); }); it('canCheckout должен возвращать false при наличии ошибки', () => { const store = useCartStore(); store.error_warning = 'Ошибка'; expect(store.canCheckout).toBe(false); }); }); describe('actions', () => { describe('getProducts', () => { it('должен загружать продукты из API', async () => { const mockData = { data: { products: [{ id: 1, name: 'Product 1' }], total_products_count: 1, totals: { total: 1000 }, error_warning: '', attention: '', success: '', }, }; ftch.getCart.mockResolvedValue(mockData); const store = useCartStore(); await store.getProducts(); expect(store.items).toEqual(mockData.data.products); expect(store.productsCount).toBe(1); expect(store.isLoading).toBe(false); }); it('должен обрабатывать ошибки', async () => { const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); ftch.getCart.mockRejectedValue(new Error('Network error')); const store = useCartStore(); await store.getProducts(); expect(store.isLoading).toBe(false); expect(consoleErrorSpy).toHaveBeenCalled(); consoleErrorSpy.mockRestore(); }); }); describe('addProduct', () => { it('должен добавлять продукт в корзину', async () => { const mockResponse = { error: null }; ftch.addToCart.mockResolvedValue(mockResponse); ftch.getCart.mockResolvedValue({ data: { products: [{ id: 1, name: 'Product 1' }], total_products_count: 1, totals: {}, error_warning: '', attention: '', success: '', }, }); const store = useCartStore(); await store.addProduct(1, 'Product 1', 100, 2, []); expect(ftch.addToCart).toHaveBeenCalled(); expect(store.isLoading).toBe(false); }); it('должен обрабатывать опции продукта', async () => { const mockResponse = { error: null }; ftch.addToCart.mockResolvedValue(mockResponse); ftch.getCart.mockResolvedValue({ data: { products: [], total_products_count: 0, totals: {}, error_warning: '', attention: '', success: '', }, }); const options = [ { type: 'checkbox', product_option_id: 1, value: [{ product_option_value_id: 10 }] }, { type: 'radio', product_option_id: 2, value: { product_option_value_id: 20 } }, { type: 'text', product_option_id: 3, value: 'test text' }, ]; const store = useCartStore(); await store.addProduct(1, 'Product', 100, 1, options); expect(ftch.addToCart).toHaveBeenCalled(); }); it('должен выбрасывать ошибку при ошибке API', async () => { const mockResponse = { error: 'Product not found' }; ftch.addToCart.mockResolvedValue(mockResponse); const store = useCartStore(); await expect(store.addProduct(1, 'Product', 100)).rejects.toThrow(); }); }); describe('removeItem', () => { it('должен удалять товар из корзины', async () => { ftch.cartRemoveItem.mockResolvedValue({}); ftch.getCart.mockResolvedValue({ data: { products: [], total_products_count: 0, totals: {}, error_warning: '', attention: '', success: '', }, }); const store = useCartStore(); const cartItem = { product_id: 1, name: 'Product', quantity: 1 }; await store.removeItem(cartItem, 'row123', 0); expect(ftch.cartRemoveItem).toHaveBeenCalled(); expect(store.isLoading).toBe(false); }); }); describe('setQuantity', () => { it('должен изменять количество товара', async () => { ftch.cartEditItem.mockResolvedValue({}); ftch.getCart.mockResolvedValue({ data: { products: [], total_products_count: 0, totals: {}, error_warning: '', attention: '', success: '', }, }); const store = useCartStore(); await store.setQuantity('cart123', 5); expect(ftch.cartEditItem).toHaveBeenCalled(); expect(store.isLoading).toBe(false); }); }); describe('applyCoupon', () => { it('должен применять купон успешно', async () => { ftch.setCoupon.mockResolvedValue({ error: null }); ftch.getCart.mockResolvedValue({ data: { products: [], total_products_count: 0, totals: {}, error_warning: '', attention: '', success: '', }, }); const store = useCartStore(); store.coupon = 'DISCOUNT10'; await store.applyCoupon(); expect(ftch.setCoupon).toHaveBeenCalledWith('DISCOUNT10'); expect(store.error_warning).toBe(''); }); it('должен обрабатывать ошибку при применении купона', async () => { ftch.setCoupon.mockResolvedValue({ error: 'Invalid coupon' }); const store = useCartStore(); store.coupon = 'INVALID'; await store.applyCoupon(); expect(store.error_warning).toBe('Invalid coupon'); }); }); describe('applyVoucher', () => { it('должен применять ваучер успешно', async () => { ftch.setVoucher.mockResolvedValue({ error: null }); ftch.getCart.mockResolvedValue({ data: { products: [], total_products_count: 0, totals: {}, error_warning: '', attention: '', success: '', }, }); const store = useCartStore(); store.voucher = 'VOUCHER123'; await store.applyVoucher(); expect(ftch.setVoucher).toHaveBeenCalledWith('VOUCHER123'); expect(store.error_warning).toBe(''); }); }); }); });