Fixed Small Card Form Issue and Added Tests

This commit is contained in:
Ahmad 2025-01-01 19:02:18 -05:00
parent dbbfc7a9d8
commit 0727706d78
No known key found for this signature in database
GPG key ID: 8FD8A93530D182BF
5 changed files with 112 additions and 26 deletions

View file

@ -14,7 +14,6 @@ jest.mock('@/hooks/use-action', () => ({
})), })),
})); }));
describe('BoardTitleForm', () => {
const mockBoard: Board = { const mockBoard: Board = {
id: '1', id: '1',
title: 'Test Board', title: 'Test Board',
@ -29,6 +28,7 @@ describe('BoardTitleForm', () => {
orgId: 'org1', orgId: 'org1',
}; };
describe('BoardTitleForm', () => {
it('should render correctly in browser environment', () => { it('should render correctly in browser environment', () => {
render(<BoardTitleForm data={mockBoard} />); render(<BoardTitleForm data={mockBoard} />);

View file

@ -0,0 +1,86 @@
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { CardForm } from '@/app/(platform)/(dashboard)/board/[boardId]/_components/card-form';
import { toast } from 'sonner';
jest.mock('@/hooks/use-action', () => ({
useAction: jest.fn().mockImplementation(() => ({
execute: jest.fn().mockImplementation(({ title }) => {
toast.success(`Card "${title}" created`);
}),
})),
}));
jest.mock('next/navigation', () => ({
useParams: jest.fn(() => ({
boardId: 'test-board-id',
})),
}));
let isEditing;
const mockEnableEditing = jest.fn(() => {
isEditing = true;
});
const mockDisableEditing = jest.fn(() => {
isEditing = false;
});
const mockListId = 'test-list-id';
describe('CardForm', () => {
it('should render correctly in browser environment', () => {
render(
<CardForm
listId={mockListId}
isEditing={true}
enableEditing={mockEnableEditing}
disableEditing={mockDisableEditing}
/>
);
expect(
screen.getByPlaceholderText(/Enter a title for this card\.\.\./i)
).toBeInTheDocument();
});
it('should create a new card when form is submitted using button', async () => {
render(
<CardForm
listId={mockListId}
isEditing={true}
enableEditing={mockEnableEditing}
disableEditing={mockDisableEditing}
/>
);
const input = await screen.getByPlaceholderText(
'Enter a title for this card...'
);
fireEvent.change(input, { target: { value: 'New Card' } });
fireEvent.click(screen.getByText(/Add Card/i));
await waitFor(() => {
expect(toast.success).toHaveBeenCalledWith('Card "New Card" created');
});
});
it('should create a new card when form is submitted using the enter key', async () => {
render(
<CardForm
listId={mockListId}
isEditing={true}
enableEditing={mockEnableEditing}
disableEditing={mockDisableEditing}
/>
);
const input = await screen.getByPlaceholderText(
'Enter a title for this card...'
);
fireEvent.change(input, { target: { value: 'New Card' } });
fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });
await waitFor(() => {
expect(toast.success).toHaveBeenCalledWith('Card "New Card" created');
});
});
});

View file

@ -1,11 +1,5 @@
import '@testing-library/jest-dom'; import '@testing-library/jest-dom';
import { import { render, screen, fireEvent, waitFor } from '@testing-library/react';
render,
screen,
fireEvent,
act,
waitFor,
} from '@testing-library/react';
import { toast } from 'sonner'; import { toast } from 'sonner';
import { ListHeader } from '@/app/(platform)/(dashboard)/board/[boardId]/_components/list-header'; import { ListHeader } from '@/app/(platform)/(dashboard)/board/[boardId]/_components/list-header';

View file

@ -1,7 +1,7 @@
'use client'; 'use client';
import { Plus, X } from 'lucide-react'; import { Plus, X } from 'lucide-react';
import { forwardRef, useRef, KeyboardEventHandler } from 'react'; import { forwardRef, useRef, KeyboardEventHandler, useEffect } from 'react';
import { useOnClickOutside, useEventListener } from 'usehooks-ts'; import { useOnClickOutside, useEventListener } from 'usehooks-ts';
import { useParams } from 'next/navigation'; import { useParams } from 'next/navigation';
import { toast } from 'sonner'; import { toast } from 'sonner';
@ -22,7 +22,10 @@ interface CardFormProps {
export const CardForm = forwardRef<HTMLTextAreaElement, CardFormProps>( export const CardForm = forwardRef<HTMLTextAreaElement, CardFormProps>(
({ listId, isEditing, enableEditing, disableEditing }, ref) => { ({ listId, isEditing, enableEditing, disableEditing }, ref) => {
const params = useParams(); const params = useParams();
const formRef = useRef<HTMLFormElement>(document.createElement('form')); const formRef = useRef<HTMLFormElement>(null);
useEffect(() => {
formRef.current = document.createElement('form');
}, []);
const { execute, fieldErrors } = useAction(createCard, { const { execute, fieldErrors } = useAction(createCard, {
onSuccess: (data) => { onSuccess: (data) => {
@ -40,7 +43,7 @@ export const CardForm = forwardRef<HTMLTextAreaElement, CardFormProps>(
} }
}; };
useOnClickOutside(formRef, disableEditing); useOnClickOutside(formRef as React.RefObject<HTMLElement>, disableEditing);
useEventListener('keydown', onKeyDown); useEventListener('keydown', onKeyDown);
const onTextareaKeyDown: KeyboardEventHandler<HTMLTextAreaElement> = ( const onTextareaKeyDown: KeyboardEventHandler<HTMLTextAreaElement> = (
@ -74,7 +77,7 @@ export const CardForm = forwardRef<HTMLTextAreaElement, CardFormProps>(
placeholder='Enter a title for this card...' placeholder='Enter a title for this card...'
errors={fieldErrors} errors={fieldErrors}
/> />
<input hidden id='listId' name='listId' value={listId} /> <input hidden id='listId' name='listId' defaultValue={listId} />
<div className='flex items-center gap-x-1'> <div className='flex items-center gap-x-1'>
<FormSubmit>Add card</FormSubmit> <FormSubmit>Add card</FormSubmit>
<Button onClick={disableEditing} size='sm' variant='ghost'> <Button onClick={disableEditing} size='sm' variant='ghost'>

View file

@ -1,5 +1,4 @@
import '@testing-library/jest-dom'; import '@testing-library/jest-dom';
import { toast } from 'sonner';
jest.mock('sonner', () => ({ jest.mock('sonner', () => ({
toast: { toast: {
@ -23,3 +22,7 @@ jest.mock('@/actions/copy-list', () => ({
jest.mock('@/actions/update-board', () => ({ jest.mock('@/actions/update-board', () => ({
updateBoard: jest.fn(), updateBoard: jest.fn(),
})); }));
jest.mock('@/actions/create-card', () => ({
createCard: jest.fn(),
}));