import { describe, it, expect, vi, beforeEach } from 'vitest'; import { render, screen, waitFor, fireEvent } from '@testing-library/react'; import { SaleList } from '@/components/sales/SaleList'; import { SaleForm } from '@/components/sales/SaleForm'; import { ContractPreview } from '@/components/sales/ContractPreview'; // Mock the sales lib vi.mock('@/lib/sales', () => ({ listSales: vi.fn(), createSale: vi.fn(), getSale: vi.fn(), deleteSale: vi.fn(), regenerateContract: vi.fn(), verifyUstId: vi.fn(), getContractDownloadUrl: vi.fn().mockReturnValue('http://test/contract'), })); vi.mock('@/lib/vehicles', () => ({ listVehicles: vi.fn().mockResolvedValue({ items: [], total: 0, page: 1, page_size: 20 }), })); import { listSales, createSale, regenerateContract } from '@/lib/sales'; describe('SaleList', () => { beforeEach(() => { vi.clearAllMocks(); }); it('renders sale list with title', async () => { vi.mocked(listSales).mockResolvedValue({ items: [], total: 0, page: 1, page_size: 20, }); render(); expect(screen.getByText('Verkäufe')).toBeInTheDocument(); expect(screen.getByTestId('sale-list')).toBeInTheDocument(); }); it('displays sales in table', async () => { const mockSale = { id: 'test-sale-id', vehicle_id: 'v1', buyer_contact_id: 'b1', sale_price: 45000, sale_date: '2025-01-15', status: 'completed', is_gwg: false, vehicle: { id: 'v1', make: 'Mercedes', model: 'Actros', fin: 'WDB123', vehicle_type: 'lkw', availability: 'sold', price: 45000 }, buyer: { id: 'b1', company_name: 'Test Buyer', address_country: 'DE' }, }; vi.mocked(listSales).mockResolvedValue({ items: [mockSale], total: 1, page: 1, page_size: 20, }); render(); await waitFor(() => { expect(screen.getByText('Mercedes Actros')).toBeInTheDocument(); expect(screen.getByText('Test Buyer')).toBeInTheDocument(); }); }); it('shows create button', async () => { vi.mocked(listSales).mockResolvedValue({ items: [], total: 0, page: 1, page_size: 20, }); render(); expect(screen.getByTestId('sale-create-btn')).toBeInTheDocument(); }); it('has status filter', async () => { vi.mocked(listSales).mockResolvedValue({ items: [], total: 0, page: 1, page_size: 20, }); render(); expect(screen.getByTestId('sale-status-filter')).toBeInTheDocument(); }); it('has date range filters', async () => { vi.mocked(listSales).mockResolvedValue({ items: [], total: 0, page: 1, page_size: 20, }); render(); expect(screen.getByTestId('sale-date-from')).toBeInTheDocument(); expect(screen.getByTestId('sale-date-to')).toBeInTheDocument(); }); }); describe('SaleForm', () => { beforeEach(() => { vi.clearAllMocks(); }); it('renders form with required fields', async () => { render(); expect(screen.getByTestId('sale-form')).toBeInTheDocument(); expect(screen.getByTestId('sale-vehicle-select')).toBeInTheDocument(); expect(screen.getByTestId('sale-buyer-input')).toBeInTheDocument(); expect(screen.getByTestId('sale-price-input')).toBeInTheDocument(); expect(screen.getByTestId('sale-gwg-toggle')).toBeInTheDocument(); }); it('has GwG toggle checkbox', async () => { render(); const gwgToggle = screen.getByTestId('sale-gwg-toggle') as HTMLInputElement; expect(gwgToggle.type).toBe('checkbox'); expect(gwgToggle.checked).toBe(false); }); it('has submit button', async () => { render(); expect(screen.getByTestId('sale-submit-btn')).toBeInTheDocument(); }); }); describe('ContractPreview', () => { beforeEach(() => { vi.clearAllMocks(); }); it('shows empty state when no PDF path', async () => { render(); expect(screen.getByTestId('contract-empty')).toBeInTheDocument(); }); it('shows regenerate button', async () => { render(); expect(screen.getByTestId('contract-regenerate-btn')).toBeInTheDocument(); }); it('shows iframe when PDF path exists', async () => { render(); expect(screen.getByTestId('contract-iframe')).toBeInTheDocument(); }); });