const jwt = require('jsonwebtoken'); const bcrypt = require('bcryptjs'); const User = require('../../models/User'); const Street = require('../../models/Street'); const Task = require('../../models/Task'); const Post = require('../../models/Post'); const Event = require('../../models/Event'); const Reward = require('../../models/Reward'); const Report = require('../../models/Report'); /** * Create a test user and return user object with token */ async function createTestUser(overrides = {}) { const defaultUser = { name: 'Test User', email: 'test@example.com', password: 'password123', }; const userData = { ...defaultUser, ...overrides }; const user = await User.create(userData); const token = jwt.sign( { user: { id: user._id } }, process.env.JWT_SECRET, { expiresIn: 3600 } ); return { user, token }; } /** * Create multiple test users */ async function createTestUsers(count = 2) { const users = []; for (let i = 0; i < count; i++) { const { user, token } = await createTestUser({ name: `Test User ${i + 1}`, email: `test${i + 1}@example.com`, }); users.push({ user, token }); } return users; } /** * Create a test street */ async function createTestStreet(userId, overrides = {}) { const defaultStreet = { name: 'Test Street', location: { type: 'Point', coordinates: [-73.935242, 40.730610], }, city: 'Test City', state: 'TS', }; // Add adoptedBy if userId is provided if (userId) { const user = await User.findById(userId); if (user) { defaultStreet.adoptedBy = { userId: user._id, name: user.name, profilePicture: user.profilePicture || '' }; defaultStreet.status = 'adopted'; } } const street = await Street.create({ ...defaultStreet, ...overrides }); return street; } /** * Create a test task */ async function createTestTask(userId, streetId, overrides = {}) { // Get street details for embedding const street = await Street.findById(streetId); const streetData = { streetId: street._id, name: street.name, location: street.location }; const defaultTask = { street: streetData, description: 'Test task description', type: 'cleaning', status: 'pending', }; // Add completedBy if userId is provided if (userId) { const user = await User.findById(userId); if (user) { defaultTask.completedBy = { userId: user._id, name: user.name, profilePicture: user.profilePicture || '' }; defaultTask.status = 'completed'; } } const task = await Task.create({ ...defaultTask, ...overrides }); return task; } /** * Create a test post */ async function createTestPost(userId, overrides = {}) { const defaultPost = { user: userId, content: 'Test post content', type: 'text', }; const post = await Post.create({ ...defaultPost, ...overrides }); return post; } /** * Create a test event */ async function createTestEvent(userId, overrides = {}) { const defaultEvent = { title: 'Test Event', description: 'Test event description', date: new Date(Date.now() + 86400000).toISOString(), // Tomorrow location: 'Test Location', }; const event = await Event.create({ ...defaultEvent, ...overrides }); // Add participant if userId is provided if (userId) { const user = await User.findById(userId); if (user) { await Event.addParticipant(event._id, userId, user.name, user.profilePicture || ''); } } return event; } /** * Create a test reward */ async function createTestReward(overrides = {}) { const defaultReward = { name: 'Test Reward', description: 'Test reward description', cost: 100, }; // Handle legacy field name mapping const rewardData = { ...defaultReward, ...overrides }; if (rewardData.pointsCost && !rewardData.cost) { rewardData.cost = rewardData.pointsCost; delete rewardData.pointsCost; } const reward = await Reward.create(rewardData); return reward; } /** * Create a test report */ async function createTestReport(userId, streetId, overrides = {}) { const defaultReport = { street: streetId, reporter: userId, type: 'pothole', description: 'Test report description', status: 'pending', }; const report = await Report.create({ ...defaultReport, ...overrides }); return report; } /** * Clean up all test data */ async function cleanupDatabase() { const couchdbService = require('../../services/couchdbService'); await couchdbService.initialize(); // Delete all documents by type const types = ['user', 'street', 'task', 'post', 'event', 'reward', 'report', 'badge', 'user_badge', 'point_transaction']; for (const type of types) { try { const docs = await couchdbService.findByType(type); for (const doc of docs) { await couchdbService.deleteDocument(doc._id, doc._rev); } } catch (error) { console.error(`Error cleaning up ${type}s:`, error.message); } } } module.exports = { createTestUser, createTestUsers, createTestStreet, createTestTask, createTestPost, createTestEvent, createTestReward, createTestReport, cleanupDatabase, };