import { describe, it, expect, vi, beforeEach } from 'vitest'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { TaskDrawer } from '../TaskDrawer'; import type { Task, User } from '../data'; // Mock Shared components to avoid testing their specific implementation here vi.mock('../Shared', () => ({ Avatar: ({ userId }: any) =>
{userId}
, Tag: ({ label }: any) =>
{label}
, ProgressBar: () =>
Progress
})); describe('TaskDrawer Component', () => { const mockUser: User = { id: 'u1', name: 'Test User', email: 'test@example.com', role: 'emp', dept: 'dev', avatar: 'TU', color: '#000' }; const mockUsers = [mockUser, { id: 'u2', name: 'Other User', email: 'other@example.com', role: 'emp', dept: 'dev', avatar: 'OU', color: '#fff' }]; const mockTask: Task = { id: 't1', title: 'Test Task', description: 'Test Description', status: 'todo', priority: 'medium', assignee: 'u1', reporter: 'u1', dueDate: '2023-12-31', tags: ['bug'], subtasks: [], comments: [], activity: [], dependencies: [] }; const mockOnUpdate = vi.fn(); const mockOnClose = vi.fn(); const mockOnAddDep = vi.fn(); const mockOnToggleDep = vi.fn(); const mockOnRemoveDep = vi.fn(); beforeEach(() => { vi.clearAllMocks(); }); it('renders task details correctly', () => { render(); // screen.debug(); expect(screen.getByText('Test Task')).toBeInTheDocument(); expect(screen.getByText('Test Description')).toBeInTheDocument(); // Check for mocked avatar with userId const avatars = screen.getAllByTestId('avatar'); expect(avatars.length).toBeGreaterThan(0); expect(avatars[0]).toHaveTextContent('u1'); // expect(screen.getByText(/Test User/i)).toBeInTheDocument(); // Assignee name might be tricky in Select/Div expect(screen.getByText('bug')).toBeInTheDocument(); }); it('updates title/description calling onUpdate', async () => { // Title isn't editable in the drawer based on code, only via modal or just display? // Checking code:

{task.title}

. It's not an input. // But status, priority, assignee are selects. render(); // Update status const statusSelect = screen.getByRole('combobox', { name: /status/i }); await userEvent.selectOptions(statusSelect, 'done'); expect(mockOnUpdate).toHaveBeenCalledWith(expect.objectContaining({ id: 't1', status: 'done' })); }); it('adds a subtask', async () => { render(); const input = screen.getByPlaceholderText(/add a subtask/i); await userEvent.type(input, 'New Subtask{enter}'); expect(mockOnUpdate).toHaveBeenCalledWith(expect.objectContaining({ subtasks: expect.arrayContaining([expect.objectContaining({ title: 'New Subtask', done: false })]) })); }); it('adds a comment', async () => { render(); const input = screen.getByPlaceholderText(/add a comment/i); await userEvent.type(input, 'This is a comment{enter}'); expect(mockOnUpdate).toHaveBeenCalledWith(expect.objectContaining({ comments: expect.arrayContaining([expect.objectContaining({ text: 'This is a comment', userId: 'u1' })]) })); }); it('adds a dependency', async () => { render(); const descInput = screen.getByPlaceholderText(/describe the dependency/i); await userEvent.type(descInput, 'Blocked by API{enter}'); // Default select is "Anyone" (empty string). expect(mockOnAddDep).toHaveBeenCalledWith('t1', { dependsOnUserId: '', description: 'Blocked by API' }); }); });