import React from 'react'; import { render, screen, fireEvent } from '@testing-library/react'; import { vi, describe, it, expect, beforeEach } from 'vitest'; import InventoryTable from '@/components/InventoryTable'; import { Item } from '@/lib/db'; // Mock ItemDetailModal and PhotoModal vi.mock('@/components/ItemDetailModal', () => ({ default: ({ item, onClose }: any) => (

{item.name}

), })); vi.mock('@/components/PhotoModal', () => ({ default: ({ photoUrl, title, onClose }: any) => (

{title}

{title}
), })); describe('InventoryTable - Photo Display', () => { const mockOnExpandCategory = vi.fn(); const mockOnItemClick = vi.fn(); const createMockItem = (overrides?: Partial): Item => ({ id: 1, barcode: 'TEST-001', name: 'Test Item', category: 'Electronics', quantity: 10, min_quantity: 5, ...overrides, }); beforeEach(() => { mockOnExpandCategory.mockClear(); mockOnItemClick.mockClear(); }); describe('Photo Thumbnail Display', () => { it('should render photo thumbnail when image_url exists', () => { const items = [ createMockItem({ id: 1, name: 'Item with Photo', image_url: 'https://example.com/photo.jpg', }), ]; render( ); const thumbnail = screen.getByAltText('Item with Photo'); expect(thumbnail).toBeInTheDocument(); expect(thumbnail).toHaveAttribute('src', 'https://example.com/photo.jpg'); }); it('should render fallback icon when no image_url', () => { const items = [createMockItem({ id: 1, name: 'Item without Photo' })]; render( ); // Should not have image expect(screen.queryByAltText('Item without Photo')).not.toBeInTheDocument(); // Should have "No photo" text expect(screen.getByText('No photo')).toBeInTheDocument(); }); it('should apply border styling to thumbnail', () => { const items = [ createMockItem({ id: 1, image_url: 'https://example.com/photo.jpg', }), ]; const { container } = render( ); // Find thumbnail container (parent of img) const thumbnail = screen.getByAltText('Test Item'); expect(thumbnail.parentElement).toHaveClass( 'border-2', 'border-slate-300' ); }); it('should have proper dimensions for thumbnail', () => { const items = [ createMockItem({ id: 1, image_url: 'https://example.com/photo.jpg', }), ]; const { container } = render( ); const thumbnail = screen.getByAltText('Test Item'); expect(thumbnail.parentElement).toHaveClass('w-12', 'h-12'); }); it('should show "Tap photo for details" hint when photo exists', () => { const items = [ createMockItem({ id: 1, image_url: 'https://example.com/photo.jpg', }), ]; render( ); expect(screen.getByText('Tap photo for details')).toBeInTheDocument(); }); it('should use lazy loading for thumbnail images', () => { const items = [ createMockItem({ id: 1, image_url: 'https://example.com/photo.jpg', }), ]; render( ); const thumbnail = screen.getByAltText('Test Item'); expect(thumbnail).toHaveAttribute('loading', 'lazy'); }); }); describe('Photo Modal Interaction', () => { it('should open PhotoModal when clicking thumbnail', () => { const items = [ createMockItem({ id: 1, name: 'Item with Photo', image_url: 'https://example.com/photo.jpg', }), ]; render( ); const thumbnail = screen.getByAltText('Item with Photo'); fireEvent.click(thumbnail); // PhotoModal should be rendered with correct props expect(screen.getByTestId('photo-modal')).toBeInTheDocument(); const photoHeaders = screen.getAllByText('Item with Photo'); expect(photoHeaders.length).toBeGreaterThan(0); }); it('should pass correct photo URL to PhotoModal', () => { const photoUrl = 'https://example.com/test-photo.jpg'; const items = [ createMockItem({ id: 1, name: 'Test Item', image_url: photoUrl, }), ]; render( ); const thumbnail = screen.getByAltText('Test Item'); fireEvent.click(thumbnail); // Find photo modal and verify URL const modal = screen.getByTestId('photo-modal'); const photoImages = modal.querySelectorAll('img'); expect(photoImages.length).toBeGreaterThan(0); expect(photoImages[0]).toHaveAttribute('src', photoUrl); }); it('should close PhotoModal when close button clicked', () => { const items = [ createMockItem({ id: 1, image_url: 'https://example.com/photo.jpg', }), ]; render( ); const thumbnail = screen.getByAltText('Test Item'); fireEvent.click(thumbnail); expect(screen.getByTestId('photo-modal')).toBeInTheDocument(); const closeButton = screen.getByText('Close Photo'); fireEvent.click(closeButton); expect(screen.queryByTestId('photo-modal')).not.toBeInTheDocument(); }); it('should not show PhotoModal if image_url is undefined', () => { const items = [createMockItem({ id: 1 })]; render( ); expect(screen.queryByTestId('photo-modal')).not.toBeInTheDocument(); }); }); describe('Item Click Behavior', () => { it('should open ItemDetailModal when clicking item name/specs', () => { const items = [ createMockItem({ id: 1, name: 'Item Name', specs: 'Test specs', image_url: 'https://example.com/photo.jpg', }), ]; render( ); // Click on the item name (not the thumbnail) const itemName = screen.getByText('Item Name'); fireEvent.click(itemName); expect(screen.getByTestId('item-detail-modal')).toBeInTheDocument(); }); it('should NOT trigger item detail when clicking thumbnail', () => { const items = [ createMockItem({ id: 1, image_url: 'https://example.com/photo.jpg', }), ]; render( ); const thumbnail = screen.getByAltText('Test Item'); fireEvent.click(thumbnail); // Only PhotoModal should be shown, not ItemDetailModal expect(screen.queryByTestId('item-detail-modal')).not.toBeInTheDocument(); expect(screen.getByTestId('photo-modal')).toBeInTheDocument(); }); it('should call onItemClick when item is selected', () => { const items = [ createMockItem({ id: 1, name: 'Test Item', }), ]; render( ); const itemName = screen.getByText('Test Item'); fireEvent.click(itemName); expect(mockOnItemClick).toHaveBeenCalled(); }); }); describe('Multiple Items', () => { it('should display multiple items with mixed photo states', () => { const items = [ createMockItem({ id: 1, name: 'Item A', image_url: 'https://example.com/photo-a.jpg', }), createMockItem({ id: 2, name: 'Item B', image_url: undefined, }), createMockItem({ id: 3, name: 'Item C', image_url: 'https://example.com/photo-c.jpg', }), ]; render( ); // Check Item A has photo expect(screen.getByAltText('Item A')).toBeInTheDocument(); // Check Item B has no photo text const itemBText = screen.getAllByText('No photo'); expect(itemBText.length).toBeGreaterThanOrEqual(1); // Check Item C has photo expect(screen.getByAltText('Item C')).toBeInTheDocument(); }); it('should open correct PhotoModal for each item', () => { const items = [ createMockItem({ id: 1, name: 'Item A', image_url: 'https://example.com/photo-a.jpg', }), createMockItem({ id: 2, name: 'Item C', image_url: 'https://example.com/photo-c.jpg', }), ]; render( ); // Click Item A thumbnail const thumbnailA = screen.getByAltText('Item A'); fireEvent.click(thumbnailA); let photoModal = screen.getByTestId('photo-modal'); expect(photoModal).toHaveTextContent('Item A'); // Close and open Item C let closeButton = screen.getByText('Close Photo'); fireEvent.click(closeButton); const thumbnailC = screen.getByAltText('Item C'); fireEvent.click(thumbnailC); photoModal = screen.getByTestId('photo-modal'); expect(photoModal).toHaveTextContent('Item C'); }); }); describe('Styling and Interaction States', () => { it('should apply hover styling to thumbnail', () => { const items = [ createMockItem({ id: 1, image_url: 'https://example.com/photo.jpg', }), ]; render( ); const thumbnail = screen.getByAltText('Test Item'); expect(thumbnail.parentElement).toHaveClass( 'hover:border-primary', 'transition-colors' ); }); it('should apply active state to thumbnail', () => { const items = [ createMockItem({ id: 1, image_url: 'https://example.com/photo.jpg', }), ]; render( ); const thumbnail = screen.getByAltText('Test Item'); expect(thumbnail.parentElement).toHaveClass('active:scale-95'); }); }); });