mirror of
https://github.com/ahmadk953/tasko.git
synced 2025-01-30 16:43:37 +00:00
Added Tests, Fixed Small Issue, Removed More Caching, and General Code Fixes
This commit is contained in:
parent
9e45249377
commit
dbbfc7a9d8
8 changed files with 116 additions and 28 deletions
|
@ -1,21 +1,9 @@
|
|||
import '@testing-library/jest-dom';
|
||||
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
import { BoardTitleForm } from '@/app/(platform)/(dashboard)/board/[boardId]/_components/board-title-form';
|
||||
import { Board } from '@prisma/client';
|
||||
|
||||
jest.mock('sonner', () => ({
|
||||
toast: {
|
||||
success: jest.fn(),
|
||||
error: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('@/actions/update-board', () => ({
|
||||
updateBoard: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('@/hooks/use-action', () => ({
|
||||
useAction: jest.fn().mockImplementation(() => ({
|
||||
execute: jest.fn().mockImplementation(({ title }) => {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import '@testing-library/jest-dom';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
|
||||
import Page from '@/app/(main)/page';
|
||||
|
|
80
__tests__/list-header.test.tsx
Normal file
80
__tests__/list-header.test.tsx
Normal file
|
@ -0,0 +1,80 @@
|
|||
import '@testing-library/jest-dom';
|
||||
import {
|
||||
render,
|
||||
screen,
|
||||
fireEvent,
|
||||
act,
|
||||
waitFor,
|
||||
} from '@testing-library/react';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
import { ListHeader } from '@/app/(platform)/(dashboard)/board/[boardId]/_components/list-header';
|
||||
|
||||
jest.mock('@/hooks/use-action', () => ({
|
||||
useAction: jest.fn().mockImplementation(() => ({
|
||||
execute: jest.fn().mockImplementation(({ title }) => {
|
||||
Promise.resolve().then(() => {
|
||||
toast.success(`Renamed to "${title}"`);
|
||||
});
|
||||
}),
|
||||
})),
|
||||
}));
|
||||
|
||||
const mockList = {
|
||||
id: '1',
|
||||
title: 'Test List',
|
||||
boardId: 'board1',
|
||||
order: 1,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
const mockOnAddCard = jest.fn();
|
||||
|
||||
describe('ListHeader', () => {
|
||||
it('should render correctly in browser environment', () => {
|
||||
render(<ListHeader data={mockList} onAddCard={mockOnAddCard} />);
|
||||
|
||||
expect(screen.getByText('Test List')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should switch to edit mode when clicked', async () => {
|
||||
render(<ListHeader data={mockList} onAddCard={mockOnAddCard} />);
|
||||
|
||||
const listButton = screen.getByText('Test List');
|
||||
fireEvent.click(listButton);
|
||||
|
||||
const editableInput = await screen.findByDisplayValue('Test List');
|
||||
expect(editableInput).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should update list title when form is blurred', async () => {
|
||||
render(<ListHeader data={mockList} onAddCard={mockOnAddCard} />);
|
||||
|
||||
const listButton = screen.getByText('Test List');
|
||||
fireEvent.click(listButton);
|
||||
|
||||
const editableInput = await screen.findByDisplayValue('Test List');
|
||||
fireEvent.change(editableInput, { target: { value: 'Updated Title' } });
|
||||
fireEvent.blur(editableInput);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(toast.success).toHaveBeenCalledWith('Renamed to "Updated Title"');
|
||||
});
|
||||
});
|
||||
|
||||
it('should update list title when escape key is pressed', async () => {
|
||||
render(<ListHeader data={mockList} onAddCard={mockOnAddCard} />);
|
||||
|
||||
const listButton = screen.getByText('Test List');
|
||||
fireEvent.click(listButton);
|
||||
|
||||
const editableInput = await screen.findByDisplayValue('Test List');
|
||||
fireEvent.change(editableInput, { target: { value: 'Updated Title' } });
|
||||
fireEvent.keyDown(editableInput, { key: 'Escape', code: 'Escape' });
|
||||
|
||||
await waitFor(() => {
|
||||
expect(toast.success).toHaveBeenCalledWith('Renamed to "Updated Title"');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,6 +1,6 @@
|
|||
'use client';
|
||||
|
||||
import { useState, useRef } from 'react';
|
||||
import { useState, useRef, useEffect } from 'react';
|
||||
import { useEventListener } from 'usehooks-ts';
|
||||
import { List } from '@prisma/client';
|
||||
import { toast } from 'sonner';
|
||||
|
@ -20,7 +20,10 @@ export const ListHeader = ({ data, onAddCard }: ListHeaderProps) => {
|
|||
const [title, setTitle] = useState(data.title);
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
|
||||
const formRef = useRef<HTMLFormElement>(document.createElement('form'));
|
||||
const formRef = useRef<HTMLFormElement>(null);
|
||||
useEffect(() => {
|
||||
formRef.current = document.createElement('form');
|
||||
}, []);
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const enableEditing = () => {
|
||||
|
@ -72,8 +75,13 @@ export const ListHeader = ({ data, onAddCard }: ListHeaderProps) => {
|
|||
<div className='flex items-start justify-between gap-x-2 px-2 pt-2 text-sm font-semibold'>
|
||||
{isEditing ? (
|
||||
<form ref={formRef} action={onSubmit} className='flex-1 px-[2px]'>
|
||||
<input hidden id='id' name='id' value={data.id} />
|
||||
<input hidden id='boardId' name='boardId' value={data.boardId} />
|
||||
<input hidden id='id' name='id' defaultValue={data.id} />
|
||||
<input
|
||||
hidden
|
||||
id='boardId'
|
||||
name='boardId'
|
||||
defaultValue={data.boardId}
|
||||
/>
|
||||
<FormInput
|
||||
ref={inputRef}
|
||||
onBlur={onBlur}
|
||||
|
|
|
@ -35,7 +35,6 @@ const BoardIdPage = async (props: BoardIdPageProps) => {
|
|||
orderBy: {
|
||||
order: 'asc',
|
||||
},
|
||||
cacheStrategy: { ttl: 30, swr: 60 },
|
||||
});
|
||||
|
||||
return (
|
||||
|
|
|
@ -35,11 +35,6 @@ export async function GET(
|
|||
|
||||
return new NextResponse(JSON.stringify(auditLogs), {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Cache-Control': 'public, s-maxage=1',
|
||||
'CDN-Cache-Control': 'public, s-maxage=30',
|
||||
'Vercel-CDN-Cache-Control': 'public, s-maxage=60',
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
return new NextResponse(JSON.stringify(error), { status: 500 });
|
||||
|
|
|
@ -40,11 +40,6 @@ export async function GET(
|
|||
|
||||
return new NextResponse(JSON.stringify(card), {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Cache-Control': 'public, s-maxage=1',
|
||||
'CDN-Cache-Control': 'public, s-maxage=30',
|
||||
'Vercel-CDN-Cache-Control': 'public, s-maxage=60',
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
return new NextResponse(JSON.stringify(error), { status: 500 });
|
||||
|
|
|
@ -1 +1,25 @@
|
|||
import '@testing-library/jest-dom';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
jest.mock('sonner', () => ({
|
||||
toast: {
|
||||
success: jest.fn(),
|
||||
error: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('@/actions/update-list', () => ({
|
||||
updateList: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('@/actions/delete-list', () => ({
|
||||
deleteList: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('@/actions/copy-list', () => ({
|
||||
copyList: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('@/actions/update-board', () => ({
|
||||
updateBoard: jest.fn(),
|
||||
}));
|
||||
|
|
Loading…
Reference in a new issue