Create central dashboard with statistics and quick actions Build events management with filtering and CRUD UI Implement members management with bulk actions Develop video management with accessibility indicators Add document repository with visibility controls Create content management with WYSIWYG editor Add settings interface for site configuration Additional improvements: Implement full Events Management System with CRUD Enhance frontend architecture with TypeScript Improve accessibility in navigation menu Add comprehensive test suite for Events API
232 lines
7.5 KiB
TypeScript
232 lines
7.5 KiB
TypeScript
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');
|
|
});
|
|
});
|
|
});
|