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:
Denis Urs Rudolph
2026-04-06 22:03:50 +02:00
parent db7a183928
commit ef3d05f827
@@ -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();
});
});
});
});