feat: Complete CouchDB test infrastructure migration for route tests

- Fixed 5/7 route test suites (auth, events, reports, rewards, streets)
- Updated Jest configuration with global CouchDB mocks
- Created comprehensive test helper utilities with proper ID generation
- Fixed pagination response format expectations (.data property)
- Added proper model method mocks (populate, save, toJSON, etc.)
- Resolved ID validation issues for different entity types
- Implemented proper CouchDB service method mocking
- Updated test helpers to generate valid IDs matching validator patterns

Remaining work:
- posts.test.js: needs model mocking and response format fixes
- tasks.test.js: needs Task model constructor fixes and mocking

🤖 Generated with [AI Assistant]

Co-Authored-By: AI Assistant <noreply@ai-assistant.com>
This commit is contained in:
William Valentin
2025-11-02 22:57:08 -08:00
parent d9b7b78b0d
commit 6070474404
19 changed files with 1141 additions and 394 deletions
+97 -2
View File
@@ -2,7 +2,7 @@ const request = require('supertest');
const express = require('express');
// Mock CouchDB service before importing routes
jest.mock('../../services/couchdbService', () => ({
const mockCouchdbService = {
initialize: jest.fn().mockResolvedValue(true),
create: jest.fn(),
getById: jest.fn(),
@@ -13,7 +13,10 @@ jest.mock('../../services/couchdbService', () => ({
findByType: jest.fn(),
findUserById: jest.fn(),
update: jest.fn(),
}));
getDocument: jest.fn(),
};
jest.mock('../../services/couchdbService', () => mockCouchdbService);
const taskRoutes = require('../../routes/tasks');
const { createTestUser, createTestStreet, createTestTask } = require('../utils/testHelpers');
@@ -26,6 +29,98 @@ app.use('/api/tasks', taskRoutes);
describe('Task Routes', () => {
beforeEach(() => {
jest.clearAllMocks();
// Setup default mock responses for user creation
mockCouchdbService.createDocument.mockImplementation((doc) => {
if (doc.type === 'user') {
return Promise.resolve({
_id: doc._id || `user_${Date.now()}`,
_rev: '1-abc',
type: 'user',
...doc,
password: '$2a$10$hashedpassword', // Mock hashed password
isPremium: false,
points: 0,
adoptedStreets: [],
completedTasks: [],
posts: [],
events: [],
earnedBadges: [],
stats: {
streetsAdopted: 0,
tasksCompleted: 0,
postsCreated: 0,
eventsParticipated: 0,
badgesEarned: 0
},
createdAt: '2023-01-01T00:00:00.000Z',
updatedAt: '2023-01-01T00:00:00.000Z'
});
}
if (doc.type === 'street') {
return Promise.resolve({
_id: doc._id || `street_${Date.now()}`,
_rev: '1-abc',
type: 'street',
...doc,
status: 'available',
adoptedBy: null,
createdAt: '2023-01-01T00:00:00.000Z',
updatedAt: '2023-01-01T00:00:00.000Z'
});
}
if (doc.type === 'task') {
return Promise.resolve({
_id: doc._id || `task_${Date.now()}`,
_rev: '1-abc',
type: 'task',
...doc,
status: doc.status || 'pending',
pointsAwarded: doc.pointsAwarded || 10,
createdAt: '2023-01-01T00:00:00.000Z',
updatedAt: '2023-01-01T00:00:00.000Z'
});
}
return Promise.resolve({ _id: `doc_${Date.now()}`, _rev: '1-abc', ...doc });
});
// Setup default mock for finding users by ID
mockCouchdbService.findUserById.mockImplementation((id) => {
return Promise.resolve({
_id: id,
_rev: '1-abc',
type: 'user',
name: 'Test User',
email: 'test@example.com',
password: '$2a$10$hashedpassword',
isPremium: false,
points: 0,
adoptedStreets: [],
completedTasks: [],
posts: [],
events: [],
earnedBadges: [],
stats: {
streetsAdopted: 0,
tasksCompleted: 0,
postsCreated: 0,
eventsParticipated: 0,
badgesEarned: 0
},
createdAt: '2023-01-01T00:00:00.000Z',
updatedAt: '2023-01-01T00:00:00.000Z'
});
});
// Setup default mock for findByType (return empty arrays)
mockCouchdbService.findByType.mockImplementation((type) => {
return Promise.resolve([]);
});
// Setup default mock for getDocument
mockCouchdbService.getDocument.mockImplementation((id) => {
return Promise.resolve(null);
});
});
describe('GET /api/tasks', () => {
it('should get all tasks completed by authenticated user', async () => {