278 lines
6.7 KiB
TypeScript
278 lines
6.7 KiB
TypeScript
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
import { render, screen, waitFor, fireEvent } from '@testing-library/react';
|
|
import userEvent from '@testing-library/user-event';
|
|
import { CommentSection } from './CommentSection';
|
|
import {
|
|
getComments,
|
|
createComment,
|
|
CommentError,
|
|
} from '../services/commentService';
|
|
import { useAuthStore } from '@/features/auth/store/authStore';
|
|
import { useToast } from '@/hooks/useToast';
|
|
import type { TrackComment } from '../services/commentService';
|
|
|
|
// Mock dependencies
|
|
vi.mock('../services/commentService');
|
|
vi.mock('@/features/auth/store/authStore');
|
|
vi.mock('@/hooks/useToast');
|
|
|
|
describe('CommentSection', () => {
|
|
const mockToast = {
|
|
success: vi.fn(),
|
|
error: vi.fn(),
|
|
warning: vi.fn(),
|
|
info: vi.fn(),
|
|
toast: vi.fn(),
|
|
};
|
|
|
|
const mockUser = {
|
|
id: 123,
|
|
username: 'testuser',
|
|
email: 'test@example.com',
|
|
};
|
|
|
|
const mockComments: TrackComment[] = [
|
|
{
|
|
id: 1,
|
|
track_id: 1,
|
|
creator_id: 123,
|
|
content: 'Great track!',
|
|
is_edited: false,
|
|
created_at: '2024-01-01T00:00:00Z',
|
|
updated_at: '2024-01-01T00:00:00Z',
|
|
user: {
|
|
id: 123,
|
|
username: 'testuser',
|
|
},
|
|
},
|
|
{
|
|
id: 2,
|
|
track_id: 1,
|
|
creator_id: 456,
|
|
content: 'Amazing!',
|
|
is_edited: false,
|
|
created_at: '2024-01-02T00:00:00Z',
|
|
updated_at: '2024-01-02T00:00:00Z',
|
|
user: {
|
|
id: 456,
|
|
username: 'otheruser',
|
|
},
|
|
},
|
|
];
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
vi.mocked(useAuthStore).mockReturnValue({
|
|
user: mockUser,
|
|
isAuthenticated: true,
|
|
isLoading: false,
|
|
error: null,
|
|
login: vi.fn(),
|
|
register: vi.fn(),
|
|
logout: vi.fn(),
|
|
refreshUser: vi.fn(),
|
|
clearError: vi.fn(),
|
|
setLoading: vi.fn(),
|
|
checkAuthStatus: vi.fn(),
|
|
});
|
|
vi.mocked(useToast).mockReturnValue(mockToast);
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
it('should render comment section', async () => {
|
|
vi.mocked(getComments).mockResolvedValue({
|
|
comments: mockComments,
|
|
total: 2,
|
|
page: 1,
|
|
limit: 20,
|
|
});
|
|
|
|
render(<CommentSection trackId={1} />);
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByText('Commentaires (2)')).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
it('should display loading state', () => {
|
|
vi.mocked(getComments).mockImplementation(
|
|
() =>
|
|
new Promise((resolve) => {
|
|
setTimeout(() => {
|
|
resolve({
|
|
comments: [],
|
|
total: 0,
|
|
page: 1,
|
|
limit: 20,
|
|
});
|
|
}, 100);
|
|
}),
|
|
);
|
|
|
|
render(<CommentSection trackId={1} />);
|
|
|
|
expect(screen.getByRole('status')).toBeInTheDocument();
|
|
});
|
|
|
|
it('should display empty state when no comments', async () => {
|
|
vi.mocked(getComments).mockResolvedValue({
|
|
comments: [],
|
|
total: 0,
|
|
page: 1,
|
|
limit: 20,
|
|
});
|
|
|
|
render(<CommentSection trackId={1} />);
|
|
|
|
await waitFor(() => {
|
|
expect(
|
|
screen.getByText(/aucun commentaire pour le moment/i),
|
|
).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
it('should display comments', async () => {
|
|
vi.mocked(getComments).mockResolvedValue({
|
|
comments: mockComments,
|
|
total: 2,
|
|
page: 1,
|
|
limit: 20,
|
|
});
|
|
|
|
render(<CommentSection trackId={1} />);
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByText('Great track!')).toBeInTheDocument();
|
|
expect(screen.getByText('Amazing!')).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
it('should create a new comment', async () => {
|
|
const user = userEvent.setup();
|
|
const newComment: TrackComment = {
|
|
id: 3,
|
|
track_id: 1,
|
|
creator_id: 123,
|
|
content: 'New comment',
|
|
is_edited: false,
|
|
created_at: '2024-01-03T00:00:00Z',
|
|
updated_at: '2024-01-03T00:00:00Z',
|
|
user: {
|
|
id: 123,
|
|
username: 'testuser',
|
|
},
|
|
};
|
|
|
|
vi.mocked(getComments).mockResolvedValue({
|
|
comments: mockComments,
|
|
total: 2,
|
|
page: 1,
|
|
limit: 20,
|
|
});
|
|
vi.mocked(createComment).mockResolvedValue(newComment);
|
|
|
|
render(<CommentSection trackId={1} />);
|
|
|
|
await waitFor(() => {
|
|
expect(
|
|
screen.getByPlaceholderText('Écrivez un commentaire...'),
|
|
).toBeInTheDocument();
|
|
});
|
|
|
|
const textarea = screen.getByPlaceholderText('Écrivez un commentaire...');
|
|
await user.type(textarea, 'New comment');
|
|
|
|
const submitButton = screen.getByRole('button', { name: /commenter/i });
|
|
await user.click(submitButton);
|
|
|
|
await waitFor(() => {
|
|
expect(createComment).toHaveBeenCalledWith(1, 'New comment', undefined);
|
|
expect(mockToast.success).toHaveBeenCalledWith('Commentaire ajouté');
|
|
});
|
|
});
|
|
|
|
it('should load more comments', async () => {
|
|
const user = userEvent.setup();
|
|
const moreComments: TrackComment[] = [
|
|
{
|
|
id: 3,
|
|
track_id: 1,
|
|
creator_id: 123,
|
|
content: 'More comments',
|
|
is_edited: false,
|
|
created_at: '2024-01-03T00:00:00Z',
|
|
updated_at: '2024-01-03T00:00:00Z',
|
|
user: {
|
|
id: 123,
|
|
username: 'testuser',
|
|
},
|
|
},
|
|
];
|
|
|
|
vi.mocked(getComments)
|
|
.mockResolvedValueOnce({
|
|
comments: mockComments,
|
|
total: 3,
|
|
page: 1,
|
|
limit: 20,
|
|
})
|
|
.mockResolvedValueOnce({
|
|
comments: moreComments,
|
|
total: 3,
|
|
page: 2,
|
|
limit: 20,
|
|
});
|
|
|
|
render(<CommentSection trackId={1} />);
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByText('Great track!')).toBeInTheDocument();
|
|
});
|
|
|
|
const loadMoreButton = screen.getByRole('button', {
|
|
name: /charger plus/i,
|
|
});
|
|
await user.click(loadMoreButton);
|
|
|
|
await waitFor(() => {
|
|
expect(getComments).toHaveBeenCalledWith(1, 2, 20);
|
|
});
|
|
});
|
|
|
|
it('should handle error when loading comments', async () => {
|
|
const error = new CommentError('Failed to load comments', 'NETWORK', true);
|
|
vi.mocked(getComments).mockRejectedValue(error);
|
|
|
|
render(<CommentSection trackId={1} />);
|
|
|
|
await waitFor(() => {
|
|
expect(mockToast.error).toHaveBeenCalledWith('Failed to load comments');
|
|
});
|
|
});
|
|
|
|
it('should refresh comments', async () => {
|
|
const user = userEvent.setup();
|
|
vi.mocked(getComments).mockResolvedValue({
|
|
comments: mockComments,
|
|
total: 2,
|
|
page: 1,
|
|
limit: 20,
|
|
});
|
|
|
|
render(<CommentSection trackId={1} />);
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByText('Great track!')).toBeInTheDocument();
|
|
});
|
|
|
|
const refreshButton = screen.getByRole('button', { name: /actualiser/i });
|
|
await user.click(refreshButton);
|
|
|
|
await waitFor(() => {
|
|
expect(getComments).toHaveBeenCalledWith(1, 1, 20);
|
|
});
|
|
});
|
|
});
|