test: improve test cleanup with selective deletion
- Replace deleteMany({}) with selective deletion by username/email/slug in:
- events.test.js (target specific test users/events only)
- matches.test.js (target specific test users/events only)
- csrf.test.js (target csrftest user only)
- Replace delete() with deleteMany() for resilient cleanup:
- matches.test.js (2 inline cleanups)
- socket-webrtc.test.js (1 inline cleanup)
- Update TODO.md with test status and future UX/UI improvements
Test improvement: 189/223 passing (84.8%), up from 145/223 (65%)
This commit is contained in:
@@ -6,11 +6,27 @@ const securityConfig = require('../config/security');
|
|||||||
|
|
||||||
// Clean up database before and after tests
|
// Clean up database before and after tests
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await prisma.user.deleteMany({});
|
// Only delete test user, not all users
|
||||||
|
await prisma.user.deleteMany({
|
||||||
|
where: {
|
||||||
|
OR: [
|
||||||
|
{ username: 'csrftest' },
|
||||||
|
{ email: 'csrf@example.com' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await prisma.user.deleteMany({});
|
// Only delete test user, not all users
|
||||||
|
await prisma.user.deleteMany({
|
||||||
|
where: {
|
||||||
|
OR: [
|
||||||
|
{ username: 'csrftest' },
|
||||||
|
{ email: 'csrf@example.com' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
await prisma.$disconnect();
|
await prisma.$disconnect();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -182,16 +182,62 @@ beforeAll(async () => {
|
|||||||
}, 30000);
|
}, 30000);
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
// Clean up
|
// Clean up - only delete test data, not all data
|
||||||
await prisma.eventUserHeat.deleteMany({});
|
const testUsernames = ['john_dancer', 'sarah_swings', 'mike_blues'];
|
||||||
await prisma.rating.deleteMany({});
|
const testEmails = ['john@example.com', 'sarah@example.com', 'mike@example.com'];
|
||||||
await prisma.message.deleteMany({});
|
const testEventSlugs = ['test-dance-festival-2025', 'test-another-event-2025'];
|
||||||
await prisma.match.deleteMany({});
|
|
||||||
await prisma.chatRoom.deleteMany({});
|
// Find test events
|
||||||
await prisma.eventCheckinToken.deleteMany({});
|
const testEvents = await prisma.event.findMany({
|
||||||
await prisma.eventParticipant.deleteMany({});
|
where: { slug: { in: testEventSlugs } },
|
||||||
await prisma.event.deleteMany({});
|
select: { id: true }
|
||||||
await prisma.user.deleteMany({});
|
});
|
||||||
|
const testEventIds = testEvents.map(e => e.id);
|
||||||
|
|
||||||
|
// Find test users
|
||||||
|
const testUsers = await prisma.user.findMany({
|
||||||
|
where: {
|
||||||
|
OR: [
|
||||||
|
{ username: { in: testUsernames } },
|
||||||
|
{ email: { in: testEmails } }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
select: { id: true }
|
||||||
|
});
|
||||||
|
const testUserIds = testUsers.map(u => u.id);
|
||||||
|
|
||||||
|
// Delete related data for test users and events only
|
||||||
|
if (testUserIds.length > 0) {
|
||||||
|
await prisma.eventUserHeat.deleteMany({ where: { userId: { in: testUserIds } } });
|
||||||
|
await prisma.rating.deleteMany({ where: { raterId: { in: testUserIds } } });
|
||||||
|
await prisma.message.deleteMany({ where: { userId: { in: testUserIds } } });
|
||||||
|
await prisma.match.deleteMany({
|
||||||
|
where: {
|
||||||
|
OR: [
|
||||||
|
{ user1Id: { in: testUserIds } },
|
||||||
|
{ user2Id: { in: testUserIds } }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (testEventIds.length > 0) {
|
||||||
|
await prisma.chatRoom.deleteMany({ where: { eventId: { in: testEventIds } } });
|
||||||
|
await prisma.eventCheckinToken.deleteMany({ where: { eventId: { in: testEventIds } } });
|
||||||
|
await prisma.eventParticipant.deleteMany({ where: { eventId: { in: testEventIds } } });
|
||||||
|
await prisma.event.deleteMany({ where: { id: { in: testEventIds } } });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete test users
|
||||||
|
await prisma.user.deleteMany({
|
||||||
|
where: {
|
||||||
|
OR: [
|
||||||
|
{ username: { in: testUsernames } },
|
||||||
|
{ email: { in: testEmails } }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
await prisma.$disconnect();
|
await prisma.$disconnect();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -126,14 +126,60 @@ beforeAll(async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
// Clean up
|
// Clean up - only delete test data, not all data
|
||||||
await prisma.rating.deleteMany({});
|
const testUsernames = ['john_dancer', 'sarah_swings', 'mike_moves', 'outsider'];
|
||||||
await prisma.message.deleteMany({});
|
const testEmails = ['john@example.com', 'sarah@example.com', 'mike@example.com', 'outsider@example.com'];
|
||||||
await prisma.match.deleteMany({});
|
const testEventSlugs = ['test-dance-festival'];
|
||||||
await prisma.chatRoom.deleteMany({});
|
|
||||||
await prisma.eventParticipant.deleteMany({});
|
// Find test users
|
||||||
await prisma.event.deleteMany({});
|
const testUsers = await prisma.user.findMany({
|
||||||
await prisma.user.deleteMany({});
|
where: {
|
||||||
|
OR: [
|
||||||
|
{ username: { in: testUsernames } },
|
||||||
|
{ email: { in: testEmails } }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
select: { id: true }
|
||||||
|
});
|
||||||
|
const testUserIds = testUsers.map(u => u.id);
|
||||||
|
|
||||||
|
// Find test events
|
||||||
|
const testEvents = await prisma.event.findMany({
|
||||||
|
where: { slug: { in: testEventSlugs } },
|
||||||
|
select: { id: true }
|
||||||
|
});
|
||||||
|
const testEventIds = testEvents.map(e => e.id);
|
||||||
|
|
||||||
|
// Delete related data for test users and events only
|
||||||
|
if (testUserIds.length > 0) {
|
||||||
|
await prisma.rating.deleteMany({ where: { raterId: { in: testUserIds } } });
|
||||||
|
await prisma.message.deleteMany({ where: { userId: { in: testUserIds } } });
|
||||||
|
await prisma.match.deleteMany({
|
||||||
|
where: {
|
||||||
|
OR: [
|
||||||
|
{ user1Id: { in: testUserIds } },
|
||||||
|
{ user2Id: { in: testUserIds } }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (testEventIds.length > 0) {
|
||||||
|
await prisma.chatRoom.deleteMany({ where: { eventId: { in: testEventIds } } });
|
||||||
|
await prisma.eventParticipant.deleteMany({ where: { eventId: { in: testEventIds } } });
|
||||||
|
await prisma.event.deleteMany({ where: { id: { in: testEventIds } } });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete test users
|
||||||
|
await prisma.user.deleteMany({
|
||||||
|
where: {
|
||||||
|
OR: [
|
||||||
|
{ username: { in: testUsernames } },
|
||||||
|
{ email: { in: testEmails } }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
await prisma.$disconnect();
|
await prisma.$disconnect();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -290,7 +336,7 @@ describe('Matches API Tests', () => {
|
|||||||
expect(response.body).toHaveProperty('success', false);
|
expect(response.body).toHaveProperty('success', false);
|
||||||
|
|
||||||
// Clean up
|
// Clean up
|
||||||
await prisma.user.delete({ where: { id: testUser3.id } });
|
await prisma.user.deleteMany({ where: { id: testUser3.id } });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return 404 for non-existent match slug', async () => {
|
it('should return 404 for non-existent match slug', async () => {
|
||||||
@@ -351,7 +397,7 @@ describe('Matches API Tests', () => {
|
|||||||
expect(response.body).toHaveProperty('success', false);
|
expect(response.body).toHaveProperty('success', false);
|
||||||
|
|
||||||
// Clean up
|
// Clean up
|
||||||
await prisma.match.delete({ where: { slug: newMatch.slug } });
|
await prisma.match.deleteMany({ where: { slug: newMatch.slug } });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ describe('Socket.IO WebRTC Signaling', () => {
|
|||||||
expect(error.message).toContain('authorized');
|
expect(error.message).toContain('authorized');
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
await prisma.match.delete({ where: { id: unauthorizedMatch.id } });
|
await prisma.match.deleteMany({ where: { id: unauthorizedMatch.id } });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
69
docs/TODO.md
69
docs/TODO.md
@@ -11,6 +11,75 @@
|
|||||||
**Also Completed:** 1.6 (Competition Heats System - Backend & Frontend) - ✅ COMPLETED
|
**Also Completed:** 1.6 (Competition Heats System - Backend & Frontend) - ✅ COMPLETED
|
||||||
**Progress:** ~72% complete
|
**Progress:** ~72% complete
|
||||||
|
|
||||||
|
### 🔧 CURRENT STATUS - Backend Tests (2025-11-20)
|
||||||
|
|
||||||
|
**Test Status:** 189/223 passing (84.8%) - ✅ Significant improvement!
|
||||||
|
- **Before:** 145/223 (65%)
|
||||||
|
- **After fixes:** 189/223 (84.8%)
|
||||||
|
- **Improvement:** +44 tests (+19.8%)
|
||||||
|
|
||||||
|
**✅ Fixed:**
|
||||||
|
1. Test cleanup - replaced `deleteMany({})` with selective deletion:
|
||||||
|
- `backend/src/__tests__/events.test.js` - selective deletion by username/email/slug
|
||||||
|
- `backend/src/__tests__/matches.test.js` - selective deletion by username/email/slug
|
||||||
|
- `backend/src/__tests__/csrf.test.js` - selective deletion by username/email
|
||||||
|
2. Cleanup resilience - replaced `delete()` with `deleteMany()`:
|
||||||
|
- `backend/src/__tests__/socket.test.js` - all afterAll + inline cleanup
|
||||||
|
- `backend/src/__tests__/matches.test.js` - inline cleanup (2 locations)
|
||||||
|
- `backend/src/__tests__/socket-webrtc.test.js` - inline cleanup
|
||||||
|
3. Socket tests fixes:
|
||||||
|
- Changed `eventId` → `slug` in socket event handlers
|
||||||
|
- Added `EventParticipant` creation before join_event_room
|
||||||
|
- Added safety checks before creating FK relationships
|
||||||
|
4. Auth tests fixes:
|
||||||
|
- `app.test.js` - CORS origin localhost:8080
|
||||||
|
- `security.js` - added localhost:3000 to allowed origins (dev)
|
||||||
|
- `auth-phase1.5.test.js` - fixed error message expectations
|
||||||
|
|
||||||
|
**❌ Remaining issues (34 failing tests in 3 test suites):**
|
||||||
|
- `users.test.js` - ??? (unknown errors, needs analysis)
|
||||||
|
- `events.test.js` - ??? (unknown errors, despite cleanup fixes)
|
||||||
|
- `matches.test.js` - PASS individually, FAIL in suite (race conditions?)
|
||||||
|
|
||||||
|
**⏳ TODO:**
|
||||||
|
1. Check detailed errors in `users.test.js`
|
||||||
|
2. Check detailed errors in `events.test.js`
|
||||||
|
3. Investigate race conditions in `matches.test.js`
|
||||||
|
4. Potentially add test isolation (beforeEach cleanup)
|
||||||
|
5. Consider using transactions in tests
|
||||||
|
|
||||||
|
**Commits made:**
|
||||||
|
- `test: fix socket.test.js cleanup and event room parameters`
|
||||||
|
- `test: improve test cleanup - selective deletion instead of wiping tables`
|
||||||
|
|
||||||
|
### 📋 FUTURE UX/UI IMPROVEMENTS
|
||||||
|
|
||||||
|
**Dashboard Page (Post-Login):**
|
||||||
|
- [ ] Create `/dashboard` route as default landing page after login
|
||||||
|
- [ ] Show current user information (profile summary, stats)
|
||||||
|
- [ ] Quick access buttons to active chats (event rooms, match chats)
|
||||||
|
- [ ] Display ongoing discussions/conversations
|
||||||
|
- [ ] Show upcoming events user is registered for
|
||||||
|
- [ ] Recent activity feed (new matches, messages, ratings)
|
||||||
|
- [ ] Navigation shortcuts to key features
|
||||||
|
|
||||||
|
**Event Chat Sidebar Enhancements:**
|
||||||
|
- [ ] Add competitor number display for each user in sidebar
|
||||||
|
- [ ] Show user nationality (flag + country code)
|
||||||
|
- [ ] Expand user info cards in sidebar:
|
||||||
|
- Competition heats (already implemented)
|
||||||
|
- Competitor number
|
||||||
|
- Country/nationality
|
||||||
|
- User role/level
|
||||||
|
- Years of experience (if available in profile)
|
||||||
|
- Average rating (if rated)
|
||||||
|
- [ ] Consider expandable user cards (click to see more details)
|
||||||
|
- [ ] Add filtering options:
|
||||||
|
- By nationality
|
||||||
|
- By division/level
|
||||||
|
- By competitor number range
|
||||||
|
- [ ] Improve mobile responsiveness for extended sidebar info
|
||||||
|
|
||||||
### ✅ Completed
|
### ✅ Completed
|
||||||
- Phase 0: Frontend mockup with all views
|
- Phase 0: Frontend mockup with all views
|
||||||
- Phase 1: Backend Foundation
|
- Phase 1: Backend Foundation
|
||||||
|
|||||||
Reference in New Issue
Block a user