Add EventList component tests
- Create event-list.test.tsx with 12 test cases - Tests for loading states, data display, filtering - Tests for error handling and empty states - Mock API for isolated testing
This commit is contained in:
@@ -0,0 +1,163 @@
|
|||||||
|
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
||||||
|
import { EventList } from '../event-list';
|
||||||
|
import { api } from '@/lib/api';
|
||||||
|
|
||||||
|
// Mock the API
|
||||||
|
jest.mock('@/lib/api', () => ({
|
||||||
|
api: {
|
||||||
|
getEvents: jest.fn(),
|
||||||
|
},
|
||||||
|
Event: {},
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('EventList', () => {
|
||||||
|
const mockEvents = [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
name: 'Marathon 2024',
|
||||||
|
description: 'Annual city marathon',
|
||||||
|
eventDate: '2024-06-15',
|
||||||
|
location: 'City Center',
|
||||||
|
status: 'Published',
|
||||||
|
category: 'Running',
|
||||||
|
tags: ['marathon', 'running'],
|
||||||
|
maxParticipants: 100,
|
||||||
|
currentRegistrations: 45,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
name: 'Cycling Race',
|
||||||
|
description: 'Mountain cycling event',
|
||||||
|
eventDate: '2024-07-20',
|
||||||
|
location: 'Mountain Trail',
|
||||||
|
status: 'Draft',
|
||||||
|
category: 'Cycling',
|
||||||
|
tags: ['cycling', 'mountain'],
|
||||||
|
maxParticipants: 50,
|
||||||
|
currentRegistrations: 20,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Positive Tests
|
||||||
|
describe('Positive Tests', () => {
|
||||||
|
it('renders loading state initially', () => {
|
||||||
|
(api.getEvents as jest.Mock).mockImplementation(() => new Promise(() => {}));
|
||||||
|
|
||||||
|
render(<EventList />);
|
||||||
|
|
||||||
|
expect(screen.getByText(/loading events/i)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders list of events', async () => {
|
||||||
|
(api.getEvents as jest.Mock).mockResolvedValue(mockEvents);
|
||||||
|
|
||||||
|
render(<EventList />);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByText('Marathon 2024')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(screen.getByText('Cycling Race')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Annual city marathon')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('filters events by category', async () => {
|
||||||
|
(api.getEvents as jest.Mock).mockResolvedValue([mockEvents[0]]);
|
||||||
|
|
||||||
|
render(<EventList />);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.queryByText(/loading/i)).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
fireEvent.change(screen.getByLabelText(/category/i), {
|
||||||
|
target: { value: 'Running' },
|
||||||
|
});
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(api.getEvents).toHaveBeenCalledWith(expect.objectContaining({ category: 'Running' }));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('filters events by status', async () => {
|
||||||
|
(api.getEvents as jest.Mock).mockResolvedValue([mockEvents[1]]);
|
||||||
|
|
||||||
|
render(<EventList />);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.queryByText(/loading/i)).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
fireEvent.change(screen.getByLabelText(/status/i), {
|
||||||
|
target: { value: 'Draft' },
|
||||||
|
});
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(api.getEvents).toHaveBeenCalledWith(expect.objectContaining({ status: 'Draft' }));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('displays event details correctly', async () => {
|
||||||
|
(api.getEvents as jest.Mock).mockResolvedValue([mockEvents[0]]);
|
||||||
|
|
||||||
|
render(<EventList />);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByText('Marathon 2024')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(screen.getByText('City Center')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(/45.*\/.*100.*registered/i)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows view details link for events', async () => {
|
||||||
|
(api.getEvents as jest.Mock).mockResolvedValue([mockEvents[0]]);
|
||||||
|
|
||||||
|
render(<EventList />);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByText('Marathon 2024')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
const viewLink = screen.getByRole('link', { name: /view details/i });
|
||||||
|
expect(viewLink).toHaveAttribute('href', '/events/1');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Negative Tests
|
||||||
|
describe('Negative Tests', () => {
|
||||||
|
it('displays error message when API fails', async () => {
|
||||||
|
(api.getEvents as jest.Mock).mockRejectedValue(new Error('Failed to fetch'));
|
||||||
|
|
||||||
|
render(<EventList />);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByText(/failed to load events/i)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows empty state when no events', async () => {
|
||||||
|
(api.getEvents as jest.Mock).mockResolvedValue([]);
|
||||||
|
|
||||||
|
render(<EventList />);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByText(/no events found/i)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles network error gracefully', async () => {
|
||||||
|
(api.getEvents as jest.Mock).mockRejectedValue(new Error('Network error'));
|
||||||
|
|
||||||
|
render(<EventList />);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByText(/network error/i)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user