import { act, renderHook } from '@testing-library/react' import { useDraggableUploader } from './hooks' type MockDragEventOverrides = { dataTransfer?: { files: File[] } } const createDragEvent = (overrides: MockDragEventOverrides = {}): React.DragEvent => ({ preventDefault: vi.fn(), stopPropagation: vi.fn(), dataTransfer: { files: [] as unknown as FileList }, ...overrides, } as unknown as React.DragEvent) describe('useDraggableUploader', () => { let setImageFn: ReturnType void>> beforeEach(() => { vi.clearAllMocks() setImageFn = vi.fn<(file: File) => void>() }) describe('Rendering', () => { it('should return all expected handler functions and isDragActive state', () => { const { result } = renderHook(() => useDraggableUploader(setImageFn)) expect(result.current.handleDragEnter).toBeInstanceOf(Function) expect(result.current.handleDragOver).toBeInstanceOf(Function) expect(result.current.handleDragLeave).toBeInstanceOf(Function) expect(result.current.handleDrop).toBeInstanceOf(Function) expect(result.current.isDragActive).toBe(false) }) }) describe('Drag Events', () => { it('should set isDragActive to true on drag enter', () => { const { result } = renderHook(() => useDraggableUploader(setImageFn)) const event = createDragEvent() act(() => { result.current.handleDragEnter(event) }) expect(result.current.isDragActive).toBe(true) expect(event.preventDefault).toHaveBeenCalled() expect(event.stopPropagation).toHaveBeenCalled() }) it('should call preventDefault and stopPropagation on drag over without changing isDragActive', () => { const { result } = renderHook(() => useDraggableUploader(setImageFn)) const event = createDragEvent() act(() => { result.current.handleDragOver(event) }) expect(result.current.isDragActive).toBe(false) expect(event.preventDefault).toHaveBeenCalled() expect(event.stopPropagation).toHaveBeenCalled() }) it('should set isDragActive to false on drag leave', () => { const { result } = renderHook(() => useDraggableUploader(setImageFn)) const enterEvent = createDragEvent() const leaveEvent = createDragEvent() act(() => { result.current.handleDragEnter(enterEvent) }) expect(result.current.isDragActive).toBe(true) act(() => { result.current.handleDragLeave(leaveEvent) }) expect(result.current.isDragActive).toBe(false) expect(leaveEvent.preventDefault).toHaveBeenCalled() expect(leaveEvent.stopPropagation).toHaveBeenCalled() }) }) describe('Drop', () => { it('should call setImageFn with the dropped file and set isDragActive to false', () => { const { result } = renderHook(() => useDraggableUploader(setImageFn)) const file = new File(['test'], 'image.png', { type: 'image/png' }) const event = createDragEvent({ dataTransfer: { files: [file] }, }) // First set isDragActive to true act(() => { result.current.handleDragEnter(createDragEvent()) }) expect(result.current.isDragActive).toBe(true) act(() => { result.current.handleDrop(event) }) expect(result.current.isDragActive).toBe(false) expect(setImageFn).toHaveBeenCalledWith(file) expect(event.preventDefault).toHaveBeenCalled() expect(event.stopPropagation).toHaveBeenCalled() }) it('should not call setImageFn when no file is dropped', () => { const { result } = renderHook(() => useDraggableUploader(setImageFn)) const event = createDragEvent({ dataTransfer: { files: [] }, }) act(() => { result.current.handleDrop(event) }) expect(setImageFn).not.toHaveBeenCalled() expect(result.current.isDragActive).toBe(false) }) }) })