import { describe, it, expect, vi } from 'vitest'; import { render, screen, fireEvent } from '@testing-library/react'; import { DraggableEvent } from '../DraggableEvent'; // Mock DnD Kit vi.mock('@dnd-kit/core', () => ({ DndContext: ({ children }: { children: React.ReactNode }) =>
{children}
, useDraggable: vi.fn(() => ({ attributes: {}, listeners: {}, setNodeRef: vi.fn(), transform: null, isDragging: false, })), })); vi.mock('@dnd-kit/utilities', () => ({ CSS: { Translate: { toString: (transform: any) => transform ? `translate3d(${transform.x}px, ${transform.y}px, 0)` : undefined, }, }, })); describe('DraggableEvent', () => { const defaultProps = { id: 1, title: 'Test Event', serviceName: 'Test Service', status: 'CONFIRMED' as const, isPaid: false, start: new Date('2024-01-01T10:00:00'), end: new Date('2024-01-01T11:00:00'), laneIndex: 0, height: 80, left: 100, width: 200, top: 10, onResizeStart: vi.fn(), }; it('renders the event title', () => { render(); expect(screen.getByText('Test Event')).toBeInTheDocument(); }); it('renders the service name when provided', () => { render(); expect(screen.getByText('Test Service')).toBeInTheDocument(); }); it('does not render service name when not provided', () => { render(); expect(screen.queryByText('Test Service')).not.toBeInTheDocument(); }); it('displays the start time formatted correctly', () => { render(); expect(screen.getByText('10:00 AM')).toBeInTheDocument(); }); it('applies correct position styles', () => { const { container } = render(); const eventElement = container.querySelector('.absolute.rounded-b'); expect(eventElement).toHaveStyle({ left: '100px', width: '200px', top: '10px', height: '80px', }); }); it('applies confirmed status border color', () => { const { container } = render( ); const eventElement = container.querySelector('.absolute.rounded-b'); expect(eventElement).toHaveClass('border-blue-500'); }); it('applies completed status border color', () => { const { container } = render( ); const eventElement = container.querySelector('.absolute.rounded-b'); expect(eventElement).toHaveClass('border-green-500'); }); it('applies cancelled status border color', () => { const { container } = render( ); const eventElement = container.querySelector('.absolute.rounded-b'); expect(eventElement).toHaveClass('border-red-500'); }); it('applies no-show status border color', () => { const { container } = render( ); const eventElement = container.querySelector('.absolute.rounded-b'); expect(eventElement).toHaveClass('border-gray-500'); }); it('applies green border when paid', () => { const { container } = render( ); const eventElement = container.querySelector('.absolute.rounded-b'); expect(eventElement).toHaveClass('border-green-500'); }); it('applies default brand border color for scheduled status', () => { const { container } = render( ); const eventElement = container.querySelector('.absolute.rounded-b'); expect(eventElement).toHaveClass('border-brand-500'); }); it('calls onResizeStart when top resize handle is clicked', () => { const onResizeStart = vi.fn(); const { container } = render( ); const topHandle = container.querySelector('.cursor-ns-resize'); if (topHandle) { fireEvent.mouseDown(topHandle); expect(onResizeStart).toHaveBeenCalledWith( expect.any(Object), 'left', 1 ); } }); it('calls onResizeStart when bottom resize handle is clicked', () => { const onResizeStart = vi.fn(); const { container } = render( ); const handles = container.querySelectorAll('.cursor-ns-resize'); const bottomHandle = handles[handles.length - 1]; // Get the last one (bottom) if (bottomHandle) { fireEvent.mouseDown(bottomHandle); expect(onResizeStart).toHaveBeenCalledWith( expect.any(Object), 'right', 1 ); } }); it('renders grip icon', () => { const { container } = render(); const gripIcon = container.querySelector('svg'); expect(gripIcon).toBeInTheDocument(); }); it('applies hover styles', () => { const { container } = render(); const eventElement = container.querySelector('.absolute.rounded-b'); expect(eventElement).toHaveClass('group', 'hover:shadow-md'); }); it('renders with correct base styling classes', () => { const { container } = render(); const eventElement = container.querySelector('.absolute.rounded-b'); expect(eventElement).toHaveClass( 'absolute', 'rounded-b', 'overflow-hidden', 'group', 'bg-brand-100' ); }); it('has two resize handles', () => { const { container } = render(); const handles = container.querySelectorAll('.cursor-ns-resize'); expect(handles).toHaveLength(2); }); it('stops propagation when resize handle is clicked', () => { const onResizeStart = vi.fn(); const { container } = render( ); const topHandle = container.querySelector('.cursor-ns-resize'); const mockEvent = { stopPropagation: vi.fn(), } as any; if (topHandle) { fireEvent.mouseDown(topHandle, mockEvent); // The event handler should call stopPropagation to prevent drag expect(onResizeStart).toHaveBeenCalled(); } }); it('renders content area with cursor-move', () => { const { container } = render(); const contentArea = container.querySelector('.cursor-move'); expect(contentArea).toBeInTheDocument(); expect(contentArea).toHaveClass('select-none'); }); it('applies different heights correctly', () => { const { container } = render( ); const eventElement = container.querySelector('.absolute.rounded-b'); expect(eventElement).toHaveStyle({ height: '100px' }); }); it('applies different widths correctly', () => { const { container } = render( ); const eventElement = container.querySelector('.absolute.rounded-b'); expect(eventElement).toHaveStyle({ width: '300px' }); }); });