mirror of
https://github.com/ahmadk953/tasko.git
synced 2025-01-31 00:53: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 { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
|
|
||||||
import { BoardTitleForm } from '@/app/(platform)/(dashboard)/board/[boardId]/_components/board-title-form';
|
import { BoardTitleForm } from '@/app/(platform)/(dashboard)/board/[boardId]/_components/board-title-form';
|
||||||
import { Board } from '@prisma/client';
|
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', () => ({
|
jest.mock('@/hooks/use-action', () => ({
|
||||||
useAction: jest.fn().mockImplementation(() => ({
|
useAction: jest.fn().mockImplementation(() => ({
|
||||||
execute: jest.fn().mockImplementation(({ title }) => {
|
execute: jest.fn().mockImplementation(({ title }) => {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import '@testing-library/jest-dom';
|
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
|
|
||||||
import Page from '@/app/(main)/page';
|
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';
|
'use client';
|
||||||
|
|
||||||
import { useState, useRef } from 'react';
|
import { useState, useRef, useEffect } from 'react';
|
||||||
import { useEventListener } from 'usehooks-ts';
|
import { useEventListener } from 'usehooks-ts';
|
||||||
import { List } from '@prisma/client';
|
import { List } from '@prisma/client';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
|
@ -20,7 +20,10 @@ export const ListHeader = ({ data, onAddCard }: ListHeaderProps) => {
|
||||||
const [title, setTitle] = useState(data.title);
|
const [title, setTitle] = useState(data.title);
|
||||||
const [isEditing, setIsEditing] = useState(false);
|
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 inputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
const enableEditing = () => {
|
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'>
|
<div className='flex items-start justify-between gap-x-2 px-2 pt-2 text-sm font-semibold'>
|
||||||
{isEditing ? (
|
{isEditing ? (
|
||||||
<form ref={formRef} action={onSubmit} className='flex-1 px-[2px]'>
|
<form ref={formRef} action={onSubmit} className='flex-1 px-[2px]'>
|
||||||
<input hidden id='id' name='id' value={data.id} />
|
<input hidden id='id' name='id' defaultValue={data.id} />
|
||||||
<input hidden id='boardId' name='boardId' value={data.boardId} />
|
<input
|
||||||
|
hidden
|
||||||
|
id='boardId'
|
||||||
|
name='boardId'
|
||||||
|
defaultValue={data.boardId}
|
||||||
|
/>
|
||||||
<FormInput
|
<FormInput
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
onBlur={onBlur}
|
onBlur={onBlur}
|
||||||
|
|
|
@ -35,7 +35,6 @@ const BoardIdPage = async (props: BoardIdPageProps) => {
|
||||||
orderBy: {
|
orderBy: {
|
||||||
order: 'asc',
|
order: 'asc',
|
||||||
},
|
},
|
||||||
cacheStrategy: { ttl: 30, swr: 60 },
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -35,11 +35,6 @@ export async function GET(
|
||||||
|
|
||||||
return new NextResponse(JSON.stringify(auditLogs), {
|
return new NextResponse(JSON.stringify(auditLogs), {
|
||||||
status: 200,
|
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) {
|
} catch (error) {
|
||||||
return new NextResponse(JSON.stringify(error), { status: 500 });
|
return new NextResponse(JSON.stringify(error), { status: 500 });
|
||||||
|
|
|
@ -40,11 +40,6 @@ export async function GET(
|
||||||
|
|
||||||
return new NextResponse(JSON.stringify(card), {
|
return new NextResponse(JSON.stringify(card), {
|
||||||
status: 200,
|
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) {
|
} catch (error) {
|
||||||
return new NextResponse(JSON.stringify(error), { status: 500 });
|
return new NextResponse(JSON.stringify(error), { status: 500 });
|
||||||
|
|
|
@ -1 +1,25 @@
|
||||||
import '@testing-library/jest-dom';
|
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