import mongoose from 'mongoose'; import request from 'supertest'; import express from 'express'; import { MongoMemoryServer } from 'mongodb-memory-server'; import { jest, describe, it, expect, beforeAll, afterAll, beforeEach } from '@jest/globals'; import Event from '../src/models/Event'; import eventRoutes from '../src/routes/events'; // Mock auth middleware jest.mock('../src/middleware/auth', () => ({ checkAuth: (req: any, res: any, next: any) => next(), })); describe('Events API', () => { let app: express.Application; let mongoServer: MongoMemoryServer; beforeAll(async () => { // Set up MongoDB Memory Server mongoServer = await MongoMemoryServer.create(); const uri = mongoServer.getUri(); await mongoose.connect(uri); // Set up Express app app = express(); app.use(express.json()); app.use('/api/events', eventRoutes); }); afterAll(async () => { await mongoose.disconnect(); await mongoServer.stop(); }); beforeEach(async () => { // Clear the database before each test await Event.deleteMany({}); }); // Sample event data const sampleEvent = { title: 'Test Event', description: 'This is a test event', date: new Date('2025-05-15'), time: '18:00 - 20:00', location: 'Test Location', category: 'social', status: 'published', registrationRequired: true, maxAttendees: 50, }; describe('GET /api/events', () => { it('should return an empty array when no events exist', async () => { const response = await request(app).get('/api/events'); expect(response.status).toBe(200); expect(response.body.events).toEqual([]); expect(response.body.pagination.total).toBe(0); }); it('should return events when they exist', async () => { // Create a test event await Event.create(sampleEvent); const response = await request(app).get('/api/events'); expect(response.status).toBe(200); expect(response.body.events.length).toBe(1); expect(response.body.events[0].title).toBe('Test Event'); expect(response.body.pagination.total).toBe(1); }); it('should filter events by status', async () => { // Create published event await Event.create(sampleEvent); // Create draft event await Event.create({ ...sampleEvent, title: 'Draft Event', status: 'draft', }); // Test filtering by published status const publishedResponse = await request(app).get('/api/events?status=published'); expect(publishedResponse.status).toBe(200); expect(publishedResponse.body.events.length).toBe(1); expect(publishedResponse.body.events[0].title).toBe('Test Event'); // Test filtering by draft status const draftResponse = await request(app).get('/api/events?status=draft'); expect(draftResponse.status).toBe(200); expect(draftResponse.body.events.length).toBe(1); expect(draftResponse.body.events[0].title).toBe('Draft Event'); }); }); describe('GET /api/events/:id', () => { it('should return 404 for non-existent event', async () => { const nonExistentId = new mongoose.Types.ObjectId(); const response = await request(app).get(`/api/events/${nonExistentId}`); expect(response.status).toBe(404); }); it('should return the event when it exists', async () => { // Create a test event const createdEvent = await Event.create(sampleEvent); const response = await request(app).get(`/api/events/${createdEvent._id}`); expect(response.status).toBe(200); expect(response.body.event.title).toBe('Test Event'); }); }); describe('POST /api/events', () => { it('should create a new event', async () => { const response = await request(app) .post('/api/events') .send(sampleEvent); expect(response.status).toBe(201); expect(response.body.event.title).toBe('Test Event'); // Verify event was saved to database const events = await Event.find(); expect(events.length).toBe(1); expect(events[0].title).toBe('Test Event'); }); it('should return 400 for invalid event data', async () => { // Missing required fields const invalidEvent = { title: 'Invalid Event', // Missing description, date, time, location, category }; const response = await request(app) .post('/api/events') .send(invalidEvent); expect(response.status).toBe(400); expect(response.body.error).toBeDefined(); }); }); describe('PUT /api/events/:id', () => { it('should update an existing event', async () => { // Create a test event const createdEvent = await Event.create(sampleEvent); // Update the event const updatedData = { title: 'Updated Event Title', description: 'Updated description', }; const response = await request(app) .put(`/api/events/${createdEvent._id}`) .send(updatedData); expect(response.status).toBe(200); expect(response.body.event.title).toBe('Updated Event Title'); expect(response.body.event.description).toBe('Updated description'); // Verify event was updated in database const updatedEvent = await Event.findById(createdEvent._id); expect(updatedEvent?.title).toBe('Updated Event Title'); expect(updatedEvent?.description).toBe('Updated description'); }); it('should return 404 for non-existent event', async () => { const nonExistentId = new mongoose.Types.ObjectId(); const response = await request(app) .put(`/api/events/${nonExistentId}`) .send({ title: 'Updated Title' }); expect(response.status).toBe(404); }); }); describe('DELETE /api/events/:id', () => { it('should delete an existing event', async () => { // Create a test event const createdEvent = await Event.create(sampleEvent); const response = await request(app).delete(`/api/events/${createdEvent._id}`); expect(response.status).toBe(200); // Verify event was deleted from database const events = await Event.find(); expect(events.length).toBe(0); }); it('should return 404 for non-existent event', async () => { const nonExistentId = new mongoose.Types.ObjectId(); const response = await request(app).delete(`/api/events/${nonExistentId}`); expect(response.status).toBe(404); }); }); describe('POST /api/events/:id/register', () => { it('should register for an event', async () => { // Create a test event const createdEvent = await Event.create(sampleEvent); const response = await request(app) .post(`/api/events/${createdEvent._id}/register`) .send({ userId: new mongoose.Types.ObjectId() }); expect(response.status).toBe(200); // Verify registration count was incremented const updatedEvent = await Event.findById(createdEvent._id); expect(updatedEvent?.registeredCount).toBe(1); }); it('should return 400 when event is at capacity', async () => { // Create a test event at capacity const eventAtCapacity = await Event.create({ ...sampleEvent, maxAttendees: 5, registeredCount: 5, }); const response = await request(app) .post(`/api/events/${eventAtCapacity._id}/register`) .send({ userId: new mongoose.Types.ObjectId() }); expect(response.status).toBe(400); expect(response.body.error.message).toContain('capacity'); }); }); });