Files
lcbp3/frontend/hooks/__tests__/use-projects.test.ts
T
admin 32141f519a
CI / CD Pipeline / build (push) Failing after 15m27s
CI / CD Pipeline / release (push) Has been skipped
CI / CD Pipeline / deploy (push) Has been skipped
260323:0954 fix CI : Run Tests frontend #01
2026-03-23 09:54:31 +07:00

214 lines
6.6 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { renderHook, waitFor, act } from '@testing-library/react';
import { createTestQueryClient } from '@/lib/test-utils';
import { useProjects, useCreateProject, useUpdateProject, useDeleteProject, projectKeys } from '../use-projects';
import { projectService } from '@/lib/services/project.service';
import { toast } from 'sonner';
// Mock the service
vi.mock('@/lib/services/project.service', () => ({
projectService: {
getAll: vi.fn(),
getByUuid: vi.fn(),
create: vi.fn(),
update: vi.fn(),
delete: vi.fn(),
},
}));
describe('use-projects hooks', () => {
beforeEach(() => {
vi.clearAllMocks();
});
describe('projectKeys', () => {
it('should generate correct cache keys', () => {
expect(projectKeys.all).toEqual(['projects']);
expect(projectKeys.list({ search: 'test' })).toEqual(['projects', 'list', { search: 'test' }]);
expect(projectKeys.detail('uuid-1')).toEqual(['projects', 'detail', 'uuid-1']);
});
});
describe('useProjects', () => {
it('should fetch projects successfully', async () => {
const mockData = [
{ id: 1, name: 'Project Alpha', code: 'P-001' },
{ id: 2, name: 'Project Beta', code: 'P-002' },
];
vi.mocked(projectService.getAll).mockResolvedValue(mockData);
const { wrapper } = createTestQueryClient();
const { result } = renderHook(() => useProjects({ search: 'test' }), { wrapper });
await waitFor(() => {
expect(result.current.isSuccess).toBe(true);
});
expect(result.current.data).toEqual(mockData);
expect(projectService.getAll).toHaveBeenCalledWith({ search: 'test' });
});
it('should fetch projects without params', async () => {
const mockData = [{ id: 1, name: 'Project Alpha' }];
vi.mocked(projectService.getAll).mockResolvedValue(mockData);
const { wrapper } = createTestQueryClient();
const { result } = renderHook(() => useProjects(), { wrapper });
await waitFor(() => {
expect(result.current.isSuccess).toBe(true);
});
expect(projectService.getAll).toHaveBeenCalledWith(undefined);
});
it('should handle error state', async () => {
vi.mocked(projectService.getAll).mockRejectedValue(new Error('API Error'));
const { wrapper } = createTestQueryClient();
const { result } = renderHook(() => useProjects({}), { wrapper });
await waitFor(() => {
expect(result.current.isError).toBe(true);
});
});
});
describe('useCreateProject', () => {
it('should create project and show success toast', async () => {
const mockResponse = { id: 1, name: 'New Project' };
vi.mocked(projectService.create).mockResolvedValue(mockResponse);
const { wrapper } = createTestQueryClient();
const { result } = renderHook(() => useCreateProject(), { wrapper });
await act(async () => {
await result.current.mutateAsync({
name: 'New Project',
code: 'P-003',
contractId: 1,
});
});
expect(projectService.create).toHaveBeenCalledWith({
name: 'New Project',
code: 'P-003',
contractId: 1,
});
expect(toast.success).toHaveBeenCalledWith('Project created successfully');
});
it('should show error toast on failure', async () => {
const mockError = {
message: 'Error',
response: { data: { message: 'Duplicate code' } },
};
vi.mocked(projectService.create).mockRejectedValue(mockError);
const { wrapper } = createTestQueryClient();
const { result } = renderHook(() => useCreateProject(), { wrapper });
await act(async () => {
try {
await result.current.mutateAsync({
name: 'Test',
code: 'P-001',
});
} catch {
// Expected
}
});
expect(toast.error).toHaveBeenCalledWith('Failed to create project', {
description: 'Duplicate code',
});
});
});
describe('useUpdateProject', () => {
it('should update project and show success toast', async () => {
const mockResponse = { id: 1, name: 'Updated Project' };
vi.mocked(projectService.update).mockResolvedValue(mockResponse);
const { wrapper } = createTestQueryClient();
const { result } = renderHook(() => useUpdateProject(), { wrapper });
await act(async () => {
await result.current.mutateAsync({
uuid: 'uuid-1',
data: { name: 'Updated Project' },
});
});
expect(projectService.update).toHaveBeenCalledWith('uuid-1', { name: 'Updated Project' });
expect(toast.success).toHaveBeenCalledWith('Project updated successfully');
});
it('should show error toast on failure', async () => {
const mockError = {
message: 'Error',
response: { data: { message: 'Not found' } },
};
vi.mocked(projectService.update).mockRejectedValue(mockError);
const { wrapper } = createTestQueryClient();
const { result } = renderHook(() => useUpdateProject(), { wrapper });
await act(async () => {
try {
await result.current.mutateAsync({
uuid: 'uuid-999',
data: { name: 'Test' },
});
} catch {
// Expected
}
});
expect(toast.error).toHaveBeenCalledWith('Failed to update project', {
description: 'Not found',
});
});
});
describe('useDeleteProject', () => {
it('should delete project and show success toast', async () => {
vi.mocked(projectService.delete).mockResolvedValue({});
const { wrapper } = createTestQueryClient();
const { result } = renderHook(() => useDeleteProject(), { wrapper });
await act(async () => {
await result.current.mutateAsync('uuid-1');
});
expect(projectService.delete).toHaveBeenCalledWith('uuid-1');
expect(toast.success).toHaveBeenCalledWith('Project deleted successfully');
});
it('should show error toast on delete failure', async () => {
const mockError = {
message: 'Error',
response: { data: { message: 'Cannot delete' } },
};
vi.mocked(projectService.delete).mockRejectedValue(mockError);
const { wrapper } = createTestQueryClient();
const { result } = renderHook(() => useDeleteProject(), { wrapper });
await act(async () => {
try {
await result.current.mutateAsync('uuid-1');
} catch {
// Expected
}
});
expect(toast.error).toHaveBeenCalledWith('Failed to delete project', {
description: 'Cannot delete',
});
});
});
});