import { describe, it, expect, beforeEach } from 'vitest' import { useCartStore, selectGroupedCart, selectCartSummary, CartItem } from './cartStore' const mockItem: Omit = { id: 'prod-1', name: 'Produto Teste', activeIngredient: 'Amoxicilina', lab: 'EMS', batch: 'L1001', expiry: '2025-12', vendorId: 'vendor-1', vendorName: 'Distribuidora Norte', unitPrice: 25.00 } const mockItem2: Omit = { id: 'prod-2', name: 'Produto Teste 2', activeIngredient: 'Dipirona', lab: 'Eurofarma', batch: 'L2002', expiry: '2026-01', vendorId: 'vendor-2', vendorName: 'Distribuidora Sul', unitPrice: 15.00 } describe('cartStore', () => { beforeEach(() => { // Reset the store before each test useCartStore.setState({ items: [] }) }) describe('addItem', () => { it('should add an item to the cart', () => { const store = useCartStore.getState() store.addItem(mockItem) const state = useCartStore.getState() expect(state.items).toHaveLength(1) expect(state.items[0]).toMatchObject({ ...mockItem, quantity: 1 }) }) it('should add item with custom quantity', () => { const store = useCartStore.getState() store.addItem(mockItem, 5) const state = useCartStore.getState() expect(state.items[0].quantity).toBe(5) }) it('should increment quantity if item already exists', () => { const store = useCartStore.getState() store.addItem(mockItem, 2) store.addItem(mockItem, 3) const state = useCartStore.getState() expect(state.items).toHaveLength(1) expect(state.items[0].quantity).toBe(5) }) }) describe('updateQuantity', () => { it('should update quantity of existing item', () => { useCartStore.getState().addItem(mockItem, 2) useCartStore.getState().updateQuantity('prod-1', 10) const state = useCartStore.getState() expect(state.items[0].quantity).toBe(10) }) it('should not affect other items', () => { useCartStore.getState().addItem(mockItem, 2) useCartStore.getState().addItem(mockItem2, 3) useCartStore.getState().updateQuantity('prod-1', 10) const state = useCartStore.getState() expect(state.items[0].quantity).toBe(10) expect(state.items[1].quantity).toBe(3) }) }) describe('removeItem', () => { it('should remove item from cart', () => { useCartStore.getState().addItem(mockItem) useCartStore.getState().addItem(mockItem2) useCartStore.getState().removeItem('prod-1') const state = useCartStore.getState() expect(state.items).toHaveLength(1) expect(state.items[0].id).toBe('prod-2') }) it('should handle removing non-existent item', () => { useCartStore.getState().addItem(mockItem) useCartStore.getState().removeItem('non-existent') const state = useCartStore.getState() expect(state.items).toHaveLength(1) }) }) describe('clearVendor', () => { it('should remove all items from a specific vendor', () => { const mockItemSameVendor: Omit = { ...mockItem, id: 'prod-3', name: 'Outro Produto' } useCartStore.getState().addItem(mockItem) useCartStore.getState().addItem(mockItemSameVendor) useCartStore.getState().addItem(mockItem2) useCartStore.getState().clearVendor('vendor-1') const state = useCartStore.getState() expect(state.items).toHaveLength(1) expect(state.items[0].vendorId).toBe('vendor-2') }) }) describe('clearAll', () => { it('should remove all items from cart', () => { useCartStore.getState().addItem(mockItem) useCartStore.getState().addItem(mockItem2) useCartStore.getState().clearAll() const state = useCartStore.getState() expect(state.items).toHaveLength(0) }) }) }) describe('selectors', () => { beforeEach(() => { useCartStore.setState({ items: [] }) }) describe('selectGroupedCart', () => { it('should group items by vendor', () => { useCartStore.getState().addItem(mockItem, 2) useCartStore.getState().addItem(mockItem2, 3) const state = useCartStore.getState() const groups = selectGroupedCart(state) expect(Object.keys(groups)).toHaveLength(2) expect(groups['vendor-1'].items).toHaveLength(1) expect(groups['vendor-2'].items).toHaveLength(1) }) it('should calculate vendor totals correctly', () => { useCartStore.getState().addItem(mockItem, 2) // 2 * 25 = 50 useCartStore.getState().addItem(mockItem2, 3) // 3 * 15 = 45 const state = useCartStore.getState() const groups = selectGroupedCart(state) expect(groups['vendor-1'].total).toBe(50) expect(groups['vendor-2'].total).toBe(45) }) it('should return empty object for empty cart', () => { const state = useCartStore.getState() const groups = selectGroupedCart(state) expect(Object.keys(groups)).toHaveLength(0) }) }) describe('selectCartSummary', () => { it('should calculate total items correctly', () => { useCartStore.getState().addItem(mockItem, 2) useCartStore.getState().addItem(mockItem2, 3) const state = useCartStore.getState() const summary = selectCartSummary(state) expect(summary.totalItems).toBe(5) }) it('should calculate total value correctly', () => { useCartStore.getState().addItem(mockItem, 2) // 2 * 25 = 50 useCartStore.getState().addItem(mockItem2, 3) // 3 * 15 = 45 const state = useCartStore.getState() const summary = selectCartSummary(state) expect(summary.totalValue).toBe(95) }) it('should return zeros for empty cart', () => { const state = useCartStore.getState() const summary = selectCartSummary(state) expect(summary.totalItems).toBe(0) expect(summary.totalValue).toBe(0) }) }) }) /** * PRICE CONVERSION TESTS * These tests verify that prices are handled correctly in CENTS * The API returns price_cents (e.g., 819 = R$ 8,19) */ describe('price conversion (cents)', () => { const mockItemCents: Omit = { id: 'prod-cents-1', name: 'Paracetamol 750mg', activeIngredient: 'Paracetamol', lab: 'EMS', batch: 'L2025840', expiry: '2027-09-15', vendorId: 'vendor-anapolis', vendorName: 'AnĂ¡polis/GO', unitPrice: 819 // 819 cents = R$ 8,19 } const mockItemCents2: Omit = { id: 'prod-cents-2', name: 'Dipirona 500mg', activeIngredient: 'Dipirona', lab: 'Medley', batch: 'L2025123', expiry: '2026-06-30', vendorId: 'vendor-anapolis', vendorName: 'AnĂ¡polis/GO', unitPrice: 1299 // 1299 cents = R$ 12,99 } beforeEach(() => { useCartStore.setState({ items: [] }) }) describe('storing prices in cents', () => { it('should store unitPrice as cents (819 = R$ 8,19)', () => { useCartStore.getState().addItem(mockItemCents) const state = useCartStore.getState() expect(state.items[0].unitPrice).toBe(819) // Verify it's NOT stored as reais (8.19) expect(state.items[0].unitPrice).not.toBe(8.19) }) it('should preserve cents precision for subtotal calculation', () => { useCartStore.getState().addItem(mockItemCents, 3) const state = useCartStore.getState() const item = state.items[0] const subtotal = item.quantity * item.unitPrice // 3 * 819 = 2457 cents = R$ 24,57 expect(subtotal).toBe(2457) expect(subtotal / 100).toBe(24.57) }) }) describe('cents calculations in selectors', () => { it('should calculate vendor total in cents', () => { // 819 cents * 2 = 1638 cents useCartStore.getState().addItem(mockItemCents, 2) // 1299 cents * 1 = 1299 cents useCartStore.getState().addItem(mockItemCents2, 1) const state = useCartStore.getState() const groups = selectGroupedCart(state) // Total: 1638 + 1299 = 2937 cents = R$ 29,37 expect(groups['vendor-anapolis'].total).toBe(2937) expect(groups['vendor-anapolis'].total / 100).toBeCloseTo(29.37) }) it('should calculate cart summary total in cents', () => { useCartStore.getState().addItem(mockItemCents, 2) // 1638 cents useCartStore.getState().addItem(mockItemCents2, 1) // 1299 cents const state = useCartStore.getState() const summary = selectCartSummary(state) expect(summary.totalItems).toBe(3) expect(summary.totalValue).toBe(2937) // cents expect(summary.totalValue / 100).toBeCloseTo(29.37) // reais }) }) describe('edge cases for cents', () => { it('should handle single unit correctly', () => { useCartStore.getState().addItem(mockItemCents, 1) const state = useCartStore.getState() const summary = selectCartSummary(state) expect(summary.totalValue).toBe(819) expect(summary.totalValue / 100).toBe(8.19) }) it('should handle large quantities without overflow', () => { useCartStore.getState().addItem(mockItemCents, 1000) const state = useCartStore.getState() const summary = selectCartSummary(state) // 819 * 1000 = 819000 cents = R$ 8,190.00 expect(summary.totalValue).toBe(819000) expect(summary.totalValue / 100).toBe(8190) }) it('should handle small cent values (R$ 0,01)', () => { const cheapItem: Omit = { ...mockItemCents, id: 'cheap-1', unitPrice: 1 // 1 cent = R$ 0,01 } useCartStore.getState().addItem(cheapItem, 10) const state = useCartStore.getState() const summary = selectCartSummary(state) expect(summary.totalValue).toBe(10) // 10 cents expect(summary.totalValue / 100).toBe(0.10) }) }) })