2025-11-14 23:12:08 +01:00
|
|
|
const request = require('supertest');
|
|
|
|
|
const app = require('../app');
|
|
|
|
|
const { prisma } = require('../utils/db');
|
|
|
|
|
const { hashPassword, generateToken } = require('../utils/auth');
|
|
|
|
|
|
|
|
|
|
// Test data
|
2025-11-14 23:18:37 +01:00
|
|
|
let testUser1, testUser2, testUser3, testEvent, testToken1, testToken2, testToken3;
|
2025-11-14 23:12:08 +01:00
|
|
|
let testMatch;
|
|
|
|
|
|
|
|
|
|
// Setup test data
|
|
|
|
|
beforeAll(async () => {
|
|
|
|
|
// Clean up
|
|
|
|
|
await prisma.rating.deleteMany({});
|
|
|
|
|
await prisma.message.deleteMany({});
|
|
|
|
|
await prisma.match.deleteMany({});
|
|
|
|
|
await prisma.chatRoom.deleteMany({});
|
|
|
|
|
await prisma.eventParticipant.deleteMany({});
|
|
|
|
|
await prisma.event.deleteMany({});
|
|
|
|
|
await prisma.user.deleteMany({});
|
|
|
|
|
|
|
|
|
|
// Create test users
|
|
|
|
|
testUser1 = await prisma.user.create({
|
|
|
|
|
data: {
|
|
|
|
|
username: 'john_dancer',
|
|
|
|
|
email: 'john@example.com',
|
|
|
|
|
passwordHash: await hashPassword('password123'),
|
|
|
|
|
emailVerified: true,
|
|
|
|
|
firstName: 'John',
|
|
|
|
|
lastName: 'Doe',
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
testUser2 = await prisma.user.create({
|
|
|
|
|
data: {
|
|
|
|
|
username: 'sarah_swings',
|
|
|
|
|
email: 'sarah@example.com',
|
|
|
|
|
passwordHash: await hashPassword('password123'),
|
|
|
|
|
emailVerified: true,
|
|
|
|
|
firstName: 'Sarah',
|
|
|
|
|
lastName: 'Smith',
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
2025-11-14 23:18:37 +01:00
|
|
|
testUser3 = await prisma.user.create({
|
|
|
|
|
data: {
|
|
|
|
|
username: 'mike_moves',
|
|
|
|
|
email: 'mike@example.com',
|
|
|
|
|
passwordHash: await hashPassword('password123'),
|
|
|
|
|
emailVerified: true,
|
|
|
|
|
firstName: 'Mike',
|
|
|
|
|
lastName: 'Johnson',
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
2025-11-14 23:12:08 +01:00
|
|
|
// Generate tokens
|
|
|
|
|
testToken1 = generateToken({ userId: testUser1.id });
|
|
|
|
|
testToken2 = generateToken({ userId: testUser2.id });
|
2025-11-14 23:18:37 +01:00
|
|
|
testToken3 = generateToken({ userId: testUser3.id });
|
2025-11-14 23:12:08 +01:00
|
|
|
|
|
|
|
|
// Create test event
|
|
|
|
|
testEvent = await prisma.event.create({
|
|
|
|
|
data: {
|
|
|
|
|
name: 'Test Dance Festival',
|
|
|
|
|
slug: 'test-dance-festival',
|
|
|
|
|
location: 'Test City',
|
|
|
|
|
startDate: new Date('2025-06-01'),
|
|
|
|
|
endDate: new Date('2025-06-03'),
|
|
|
|
|
description: 'Test event',
|
|
|
|
|
worldsdcId: '12345',
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Add users as participants
|
|
|
|
|
await prisma.eventParticipant.createMany({
|
|
|
|
|
data: [
|
|
|
|
|
{ userId: testUser1.id, eventId: testEvent.id },
|
|
|
|
|
{ userId: testUser2.id, eventId: testEvent.id },
|
2025-11-14 23:18:37 +01:00
|
|
|
{ userId: testUser3.id, eventId: testEvent.id },
|
2025-11-14 23:12:08 +01:00
|
|
|
],
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
afterAll(async () => {
|
|
|
|
|
// Clean up
|
|
|
|
|
await prisma.rating.deleteMany({});
|
|
|
|
|
await prisma.message.deleteMany({});
|
|
|
|
|
await prisma.match.deleteMany({});
|
|
|
|
|
await prisma.chatRoom.deleteMany({});
|
|
|
|
|
await prisma.eventParticipant.deleteMany({});
|
|
|
|
|
await prisma.event.deleteMany({});
|
|
|
|
|
await prisma.user.deleteMany({});
|
|
|
|
|
await prisma.$disconnect();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('Matches API Tests', () => {
|
|
|
|
|
describe('POST /api/matches', () => {
|
|
|
|
|
it('should create a match request successfully', async () => {
|
|
|
|
|
const response = await request(app)
|
|
|
|
|
.post('/api/matches')
|
|
|
|
|
.set('Authorization', `Bearer ${testToken1}`)
|
|
|
|
|
.send({
|
|
|
|
|
targetUserId: testUser2.id,
|
|
|
|
|
eventSlug: testEvent.slug,
|
|
|
|
|
})
|
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
|
.expect(201);
|
|
|
|
|
|
|
|
|
|
expect(response.body).toHaveProperty('success', true);
|
|
|
|
|
expect(response.body.data).toHaveProperty('slug');
|
|
|
|
|
expect(response.body.data).toHaveProperty('status', 'pending');
|
|
|
|
|
expect(response.body.data.slug).toMatch(/^[a-z0-9]+$/); // CUID format
|
|
|
|
|
|
|
|
|
|
// Save for later tests
|
|
|
|
|
testMatch = response.body.data;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should reject match request without authentication', async () => {
|
|
|
|
|
const response = await request(app)
|
|
|
|
|
.post('/api/matches')
|
|
|
|
|
.send({
|
|
|
|
|
targetUserId: testUser2.id,
|
|
|
|
|
eventSlug: testEvent.slug,
|
|
|
|
|
})
|
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
|
.expect(401);
|
|
|
|
|
|
|
|
|
|
expect(response.body).toHaveProperty('success', false);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should reject match request to yourself', async () => {
|
|
|
|
|
const response = await request(app)
|
|
|
|
|
.post('/api/matches')
|
|
|
|
|
.set('Authorization', `Bearer ${testToken1}`)
|
|
|
|
|
.send({
|
|
|
|
|
targetUserId: testUser1.id, // Same as authenticated user
|
|
|
|
|
eventSlug: testEvent.slug,
|
|
|
|
|
})
|
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
|
.expect(400);
|
|
|
|
|
|
|
|
|
|
expect(response.body).toHaveProperty('success', false);
|
|
|
|
|
expect(response.body.error).toContain('yourself');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should reject match request with invalid event', async () => {
|
|
|
|
|
const response = await request(app)
|
|
|
|
|
.post('/api/matches')
|
|
|
|
|
.set('Authorization', `Bearer ${testToken1}`)
|
|
|
|
|
.send({
|
|
|
|
|
targetUserId: testUser2.id,
|
|
|
|
|
eventSlug: 'non-existent-event',
|
|
|
|
|
})
|
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
|
.expect(404);
|
|
|
|
|
|
|
|
|
|
expect(response.body).toHaveProperty('success', false);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('GET /api/matches', () => {
|
|
|
|
|
it('should list all matches for authenticated user', async () => {
|
|
|
|
|
const response = await request(app)
|
|
|
|
|
.get('/api/matches')
|
|
|
|
|
.set('Authorization', `Bearer ${testToken1}`)
|
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
|
.expect(200);
|
|
|
|
|
|
|
|
|
|
expect(response.body).toHaveProperty('success', true);
|
|
|
|
|
expect(response.body.data).toBeInstanceOf(Array);
|
|
|
|
|
expect(response.body.data.length).toBeGreaterThan(0);
|
|
|
|
|
|
|
|
|
|
const match = response.body.data[0];
|
|
|
|
|
expect(match).toHaveProperty('slug');
|
|
|
|
|
expect(match).toHaveProperty('partner');
|
|
|
|
|
expect(match).toHaveProperty('event');
|
|
|
|
|
expect(match).toHaveProperty('status');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should filter matches by event slug', async () => {
|
|
|
|
|
const response = await request(app)
|
|
|
|
|
.get(`/api/matches?eventSlug=${testEvent.slug}`)
|
|
|
|
|
.set('Authorization', `Bearer ${testToken1}`)
|
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
|
.expect(200);
|
|
|
|
|
|
|
|
|
|
expect(response.body).toHaveProperty('success', true);
|
|
|
|
|
expect(response.body.data).toBeInstanceOf(Array);
|
|
|
|
|
|
|
|
|
|
if (response.body.data.length > 0) {
|
|
|
|
|
expect(response.body.data[0].event.slug).toBe(testEvent.slug);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should filter matches by status', async () => {
|
|
|
|
|
const response = await request(app)
|
|
|
|
|
.get('/api/matches?status=pending')
|
|
|
|
|
.set('Authorization', `Bearer ${testToken1}`)
|
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
|
.expect(200);
|
|
|
|
|
|
|
|
|
|
expect(response.body).toHaveProperty('success', true);
|
|
|
|
|
expect(response.body.data).toBeInstanceOf(Array);
|
|
|
|
|
|
|
|
|
|
response.body.data.forEach(match => {
|
|
|
|
|
expect(match.status).toBe('pending');
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('GET /api/matches/:slug', () => {
|
|
|
|
|
it('should get match details by slug', async () => {
|
|
|
|
|
const response = await request(app)
|
|
|
|
|
.get(`/api/matches/${testMatch.slug}`)
|
|
|
|
|
.set('Authorization', `Bearer ${testToken1}`)
|
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
|
.expect(200);
|
|
|
|
|
|
|
|
|
|
expect(response.body).toHaveProperty('success', true);
|
|
|
|
|
expect(response.body.data).toHaveProperty('slug', testMatch.slug);
|
|
|
|
|
expect(response.body.data).toHaveProperty('partner');
|
|
|
|
|
expect(response.body.data).toHaveProperty('event');
|
|
|
|
|
expect(response.body.data).toHaveProperty('hasRated', false);
|
|
|
|
|
expect(response.body.data).toHaveProperty('isInitiator');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should reject access to match by non-participant', async () => {
|
|
|
|
|
// Create third user
|
|
|
|
|
const testUser3 = await prisma.user.create({
|
|
|
|
|
data: {
|
|
|
|
|
username: 'outsider',
|
|
|
|
|
email: 'outsider@example.com',
|
|
|
|
|
passwordHash: await hashPassword('password123'),
|
|
|
|
|
emailVerified: true,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const testToken3 = generateToken({ userId: testUser3.id });
|
|
|
|
|
|
|
|
|
|
const response = await request(app)
|
|
|
|
|
.get(`/api/matches/${testMatch.slug}`)
|
|
|
|
|
.set('Authorization', `Bearer ${testToken3}`)
|
|
|
|
|
.expect('Content-Type', /json/)
|
2025-11-14 23:18:37 +01:00
|
|
|
.expect(403);
|
2025-11-14 23:12:08 +01:00
|
|
|
|
|
|
|
|
expect(response.body).toHaveProperty('success', false);
|
|
|
|
|
|
|
|
|
|
// Clean up
|
|
|
|
|
await prisma.user.delete({ where: { id: testUser3.id } });
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should return 404 for non-existent match slug', async () => {
|
|
|
|
|
const response = await request(app)
|
|
|
|
|
.get('/api/matches/nonexistentslug123')
|
|
|
|
|
.set('Authorization', `Bearer ${testToken1}`)
|
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
|
.expect(404);
|
|
|
|
|
|
|
|
|
|
expect(response.body).toHaveProperty('success', false);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('PUT /api/matches/:slug/accept', () => {
|
|
|
|
|
it('should accept a match request', async () => {
|
|
|
|
|
const response = await request(app)
|
|
|
|
|
.put(`/api/matches/${testMatch.slug}/accept`)
|
|
|
|
|
.set('Authorization', `Bearer ${testToken2}`) // User 2 accepts
|
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
|
.expect(200);
|
|
|
|
|
|
|
|
|
|
expect(response.body).toHaveProperty('success', true);
|
|
|
|
|
expect(response.body.data).toHaveProperty('status', 'accepted');
|
|
|
|
|
expect(response.body.data).toHaveProperty('roomId');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should reject accepting already accepted match', async () => {
|
|
|
|
|
const response = await request(app)
|
|
|
|
|
.put(`/api/matches/${testMatch.slug}/accept`)
|
|
|
|
|
.set('Authorization', `Bearer ${testToken2}`)
|
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
|
.expect(400);
|
|
|
|
|
|
|
|
|
|
expect(response.body).toHaveProperty('success', false);
|
|
|
|
|
expect(response.body.error).toContain('already accepted');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should reject accepting match by initiator', async () => {
|
2025-11-14 23:18:37 +01:00
|
|
|
// Create new match for this test (with testUser3)
|
2025-11-14 23:12:08 +01:00
|
|
|
const newMatchRes = await request(app)
|
|
|
|
|
.post('/api/matches')
|
|
|
|
|
.set('Authorization', `Bearer ${testToken1}`)
|
|
|
|
|
.send({
|
2025-11-14 23:18:37 +01:00
|
|
|
targetUserId: testUser3.id,
|
2025-11-14 23:12:08 +01:00
|
|
|
eventSlug: testEvent.slug,
|
2025-11-14 23:18:37 +01:00
|
|
|
})
|
|
|
|
|
.expect(201);
|
2025-11-14 23:12:08 +01:00
|
|
|
|
|
|
|
|
const newMatch = newMatchRes.body.data;
|
2025-11-14 23:18:37 +01:00
|
|
|
expect(newMatch).toHaveProperty('slug');
|
2025-11-14 23:12:08 +01:00
|
|
|
|
|
|
|
|
const response = await request(app)
|
|
|
|
|
.put(`/api/matches/${newMatch.slug}/accept`)
|
|
|
|
|
.set('Authorization', `Bearer ${testToken1}`) // Initiator tries to accept
|
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
|
.expect(403);
|
|
|
|
|
|
|
|
|
|
expect(response.body).toHaveProperty('success', false);
|
|
|
|
|
|
|
|
|
|
// Clean up
|
|
|
|
|
await prisma.match.delete({ where: { slug: newMatch.slug } });
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('GET /api/matches/:slug/messages', () => {
|
|
|
|
|
it('should get match messages (empty initially)', async () => {
|
|
|
|
|
const response = await request(app)
|
|
|
|
|
.get(`/api/matches/${testMatch.slug}/messages`)
|
|
|
|
|
.set('Authorization', `Bearer ${testToken1}`)
|
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
|
.expect(200);
|
|
|
|
|
|
|
|
|
|
expect(response.body).toHaveProperty('success', true);
|
|
|
|
|
expect(response.body.data).toBeInstanceOf(Array);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('DELETE /api/matches/:slug', () => {
|
|
|
|
|
it('should delete/reject a match request', async () => {
|
2025-11-14 23:18:37 +01:00
|
|
|
// Create new match for deletion test (with a different user)
|
2025-11-14 23:12:08 +01:00
|
|
|
const newMatchRes = await request(app)
|
|
|
|
|
.post('/api/matches')
|
2025-11-14 23:18:37 +01:00
|
|
|
.set('Authorization', `Bearer ${testToken2}`)
|
2025-11-14 23:12:08 +01:00
|
|
|
.send({
|
2025-11-14 23:18:37 +01:00
|
|
|
targetUserId: testUser3.id,
|
2025-11-14 23:12:08 +01:00
|
|
|
eventSlug: testEvent.slug,
|
2025-11-14 23:18:37 +01:00
|
|
|
})
|
|
|
|
|
.expect(201);
|
2025-11-14 23:12:08 +01:00
|
|
|
|
|
|
|
|
const newMatch = newMatchRes.body.data;
|
2025-11-14 23:18:37 +01:00
|
|
|
expect(newMatch).toHaveProperty('slug');
|
2025-11-14 23:12:08 +01:00
|
|
|
|
|
|
|
|
const response = await request(app)
|
|
|
|
|
.delete(`/api/matches/${newMatch.slug}`)
|
2025-11-14 23:18:37 +01:00
|
|
|
.set('Authorization', `Bearer ${testToken2}`)
|
2025-11-14 23:12:08 +01:00
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
|
.expect(200);
|
|
|
|
|
|
|
|
|
|
expect(response.body).toHaveProperty('success', true);
|
|
|
|
|
expect(response.body).toHaveProperty('message');
|
|
|
|
|
|
|
|
|
|
// Verify deletion
|
|
|
|
|
const match = await prisma.match.findUnique({
|
|
|
|
|
where: { slug: newMatch.slug },
|
|
|
|
|
});
|
|
|
|
|
expect(match).toBeNull();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('Ratings API Tests', () => {
|
|
|
|
|
describe('POST /api/matches/:slug/ratings', () => {
|
|
|
|
|
it('should create a rating successfully', async () => {
|
|
|
|
|
const response = await request(app)
|
|
|
|
|
.post(`/api/matches/${testMatch.slug}/ratings`)
|
|
|
|
|
.set('Authorization', `Bearer ${testToken1}`)
|
|
|
|
|
.send({
|
|
|
|
|
score: 5,
|
|
|
|
|
comment: 'Great partner!',
|
|
|
|
|
wouldCollaborateAgain: true,
|
|
|
|
|
})
|
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
|
.expect(201);
|
|
|
|
|
|
|
|
|
|
expect(response.body).toHaveProperty('success', true);
|
2025-11-14 23:18:37 +01:00
|
|
|
expect(response.body.data).toHaveProperty('score', 5);
|
|
|
|
|
expect(response.body.data).toHaveProperty('comment', 'Great partner!');
|
|
|
|
|
expect(response.body.data).toHaveProperty('wouldCollaborateAgain', true);
|
2025-11-14 23:12:08 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should reject duplicate rating from same user', async () => {
|
|
|
|
|
const response = await request(app)
|
|
|
|
|
.post(`/api/matches/${testMatch.slug}/ratings`)
|
|
|
|
|
.set('Authorization', `Bearer ${testToken1}`) // Same user tries again
|
|
|
|
|
.send({
|
|
|
|
|
score: 4,
|
|
|
|
|
comment: 'Second rating',
|
|
|
|
|
wouldCollaborateAgain: false,
|
|
|
|
|
})
|
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
|
.expect(400);
|
|
|
|
|
|
|
|
|
|
expect(response.body).toHaveProperty('success', false);
|
|
|
|
|
expect(response.body.error).toContain('already rated');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should reject rating with invalid score', async () => {
|
|
|
|
|
const response = await request(app)
|
|
|
|
|
.post(`/api/matches/${testMatch.slug}/ratings`)
|
|
|
|
|
.set('Authorization', `Bearer ${testToken2}`)
|
|
|
|
|
.send({
|
|
|
|
|
score: 6, // Invalid (must be 1-5)
|
|
|
|
|
comment: 'Test',
|
|
|
|
|
wouldCollaborateAgain: true,
|
|
|
|
|
})
|
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
|
.expect(400);
|
|
|
|
|
|
|
|
|
|
expect(response.body).toHaveProperty('success', false);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should create rating without comment (optional)', async () => {
|
|
|
|
|
const response = await request(app)
|
|
|
|
|
.post(`/api/matches/${testMatch.slug}/ratings`)
|
|
|
|
|
.set('Authorization', `Bearer ${testToken2}`)
|
|
|
|
|
.send({
|
|
|
|
|
score: 4,
|
|
|
|
|
wouldCollaborateAgain: true,
|
|
|
|
|
})
|
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
|
.expect(201);
|
|
|
|
|
|
|
|
|
|
expect(response.body).toHaveProperty('success', true);
|
2025-11-14 23:18:37 +01:00
|
|
|
expect(response.body.data).toHaveProperty('score', 4);
|
|
|
|
|
expect(response.body.data).toHaveProperty('comment', null);
|
2025-11-14 23:12:08 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should auto-complete match when both users rate', async () => {
|
|
|
|
|
// Both users have now rated, check match status
|
|
|
|
|
const matchRes = await request(app)
|
|
|
|
|
.get(`/api/matches/${testMatch.slug}`)
|
|
|
|
|
.set('Authorization', `Bearer ${testToken1}`)
|
|
|
|
|
.expect(200);
|
|
|
|
|
|
|
|
|
|
expect(matchRes.body.data.status).toBe('completed');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should update hasRated flag after rating', async () => {
|
|
|
|
|
const response = await request(app)
|
|
|
|
|
.get(`/api/matches/${testMatch.slug}`)
|
|
|
|
|
.set('Authorization', `Bearer ${testToken1}`)
|
|
|
|
|
.expect(200);
|
|
|
|
|
|
|
|
|
|
expect(response.body.data.hasRated).toBe(true);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('GET /api/users/:username/ratings', () => {
|
|
|
|
|
it('should get user ratings', async () => {
|
|
|
|
|
const response = await request(app)
|
|
|
|
|
.get(`/api/users/${testUser2.username}/ratings`)
|
|
|
|
|
.set('Authorization', `Bearer ${testToken1}`)
|
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
|
.expect(200);
|
|
|
|
|
|
|
|
|
|
expect(response.body).toHaveProperty('success', true);
|
|
|
|
|
expect(response.body.data).toHaveProperty('username', testUser2.username);
|
|
|
|
|
expect(response.body.data).toHaveProperty('averageRating');
|
|
|
|
|
expect(response.body.data).toHaveProperty('ratingsCount');
|
|
|
|
|
expect(response.body.data).toHaveProperty('ratings');
|
|
|
|
|
expect(response.body.data.ratings).toBeInstanceOf(Array);
|
|
|
|
|
|
|
|
|
|
if (response.body.data.ratings.length > 0) {
|
|
|
|
|
const rating = response.body.data.ratings[0];
|
|
|
|
|
expect(rating).toHaveProperty('score');
|
|
|
|
|
expect(rating).toHaveProperty('rater');
|
|
|
|
|
expect(rating).toHaveProperty('event');
|
|
|
|
|
expect(rating).toHaveProperty('createdAt');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should calculate average rating correctly', async () => {
|
|
|
|
|
const response = await request(app)
|
|
|
|
|
.get(`/api/users/${testUser2.username}/ratings`)
|
|
|
|
|
.set('Authorization', `Bearer ${testToken1}`)
|
|
|
|
|
.expect(200);
|
|
|
|
|
|
|
|
|
|
const { averageRating, ratingsCount } = response.body.data;
|
|
|
|
|
|
|
|
|
|
if (ratingsCount > 0) {
|
|
|
|
|
expect(parseFloat(averageRating)).toBeGreaterThan(0);
|
|
|
|
|
expect(parseFloat(averageRating)).toBeLessThanOrEqual(5);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should return 404 for non-existent user', async () => {
|
|
|
|
|
const response = await request(app)
|
|
|
|
|
.get('/api/users/nonexistentuser/ratings')
|
|
|
|
|
.set('Authorization', `Bearer ${testToken1}`)
|
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
|
.expect(404);
|
|
|
|
|
|
|
|
|
|
expect(response.body).toHaveProperty('success', false);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|