// Licensed to Cloudera, Inc. under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. Cloudera, Inc. licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. import React from 'react'; import { render, fireEvent, waitFor, act, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import '@testing-library/jest-dom'; import DragAndDrop from './DragAndDrop'; const createMockFile = (name = 'test.txt', content = 'file content', type = 'text/plain') => { const file = new File([content], name, { type }); Object.defineProperty(file, 'size', { value: content.length }); return file; }; const createDragEvent = (files: File[]) => ({ dataTransfer: { files, items: files.map(file => ({ kind: 'file', type: file.type, getAsFile: () => file })), types: ['Files'] } }); describe('DragAndDrop', () => { const mockOnDrop = jest.fn(); beforeEach(() => { jest.clearAllMocks(); }); it('should render the default message when no children provided', () => { render(); expect(screen.getByText('Select file')).toBeInTheDocument(); expect(screen.getByText('Browse files or drag and drop files')).toBeInTheDocument(); }); it('should render children when provided and not dragging', () => { render(
Custom Child Element
); expect(screen.getByText('Custom Child Element')).toBeInTheDocument(); expect(screen.queryByText('Browse files or drag and drop files')).not.toBeInTheDocument(); }); it('should handle single file selection', async () => { const user = userEvent.setup(); render(); const fileInput = screen.getByTestId('drag-drop__input'); const file = createMockFile(); await user.upload(fileInput, file); // react-dropzone calls onDrop with (acceptedFiles, fileRejections, event) expect(mockOnDrop).toHaveBeenCalledWith(expect.arrayContaining([file]), [], expect.any(Object)); }); it('should handle multiple file selection', async () => { const user = userEvent.setup(); render(); const fileInput = screen.getByTestId('drag-drop__input'); const files = [ createMockFile('file1.txt'), createMockFile('file2.txt'), createMockFile('file3.jpg', 'image content', 'image/jpeg') ]; await user.upload(fileInput, files); // react-dropzone calls onDrop with (acceptedFiles, fileRejections, event) expect(mockOnDrop).toHaveBeenCalledWith(files, [], expect.any(Object)); }); it('should display drop message when dragging files over the component', async () => { render(); const dropzone = screen.getByTestId('drag-drop__input'); await act(async () => { fireEvent.dragEnter(dropzone); }); await waitFor(() => { expect(screen.getByText('Drop files here')).toBeInTheDocument(); }); }); it('should call onDrop with correct files when files are dropped', async () => { const files = [createMockFile('dropped.txt', 'dropped content')]; render(); const dropzone = screen.getByTestId('drag-drop__input'); const dropEvent = createDragEvent(files); await act(async () => { fireEvent.drop(dropzone, dropEvent); }); await waitFor(() => { // react-dropzone calls onDrop with (acceptedFiles, fileRejections, event) expect(mockOnDrop).toHaveBeenCalledWith(files, [], expect.any(Object)); expect(mockOnDrop).toHaveBeenCalledTimes(1); }); }); it('should handle multiple files being dropped', async () => { const files = [ createMockFile('file1.pdf', 'pdf content', 'application/pdf'), createMockFile('file2.jpg', 'image content', 'image/jpeg'), createMockFile('file3.txt', 'text content', 'text/plain') ]; render(); const dropzone = screen.getByTestId('drag-drop__input'); const dropEvent = createDragEvent(files); await act(async () => { fireEvent.drop(dropzone, dropEvent); }); await waitFor(() => { // react-dropzone calls onDrop with (acceptedFiles, fileRejections, event) expect(mockOnDrop).toHaveBeenCalledWith(files, [], expect.any(Object)); expect(mockOnDrop).toHaveBeenCalledTimes(1); }); }); it('should return to normal state after drag ends', async () => { render(); const dropzone = screen.getByTestId('drag-drop__input'); await act(async () => { fireEvent.dragEnter(dropzone); }); expect(screen.getByText('Drop files here')).toBeInTheDocument(); await act(async () => { fireEvent.dragLeave(dropzone); }); await waitFor(() => { expect(screen.queryByText('Drop files here')).not.toBeInTheDocument(); expect(screen.getByText('Browse files or drag and drop files')).toBeInTheDocument(); }); }); it('should not call onDrop when disabled and files are dropped', async () => { const files = [createMockFile()]; render(); const dropzone = screen.getByTestId('drag-drop__input'); const dropEvent = createDragEvent(files); await act(async () => { fireEvent.drop(dropzone, dropEvent); }); await waitFor(() => { expect(mockOnDrop).not.toHaveBeenCalled(); }); }); it('should not show drag state when disabled', async () => { render(); const dropzone = screen.getByTestId('drag-drop__input'); await act(async () => { fireEvent.dragEnter(dropzone); }); // Should not show drag message when disabled expect(screen.queryByText('Drop files here')).not.toBeInTheDocument(); }); });