Add Jest test infrastructure for admin dashboard TDD

- Configure Jest with mongodb-memory-server for isolated testing
- Add phase 1-4 test suites covering all admin requirements
- Add test helpers and setup/teardown utilities
- Install jest, supertest, mongodb-memory-server dependencies
This commit is contained in:
2026-01-22 11:57:49 -07:00
parent d6e56a6e40
commit 39bd9b1e71
11 changed files with 9358 additions and 6 deletions

View File

@ -0,0 +1,156 @@
const { MongoClient, ObjectId } = require('mongodb');
const jwt = require('jsonwebtoken');
// Counter for generating unique identifiers within the same millisecond
let uniqueCounter = 0;
/**
* Create a test Express app instance with database connection
* This creates a minimal Express app for testing admin routes
*/
async function createTestApp(db) {
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
app.use(express.json());
app.use(cookieParser());
// Store db in app.locals for middleware access
app.locals.db = db;
// Mount the auth middleware module
const { requireAuth, requireAdmin } = require('../../middleware/auth');
// Health check endpoint (should remain public)
app.get('/api/health', (req, res) => {
res.json({ status: 'ok' });
});
// Try to mount admin routes if they exist
try {
const adminRoutes = require('../../routes/admin');
app.use('/api/admin', requireAuth, requireAdmin, adminRoutes);
} catch (error) {
// Admin routes don't exist yet - this is expected for failing tests
// Create placeholder routes that will 404
app.use('/api/admin', requireAuth, requireAdmin, (req, res) => {
res.status(404).json({ error: 'Admin routes not implemented' });
});
}
return app;
}
/**
* Generate a valid JWT token for a test user
* @param {string|ObjectId} userId - The user's MongoDB _id
* @returns {string} JWT token
*/
function generateTestToken(userId) {
const secret = process.env.JWT_SECRET || 'test-jwt-secret-for-testing-only';
return jwt.sign(
{ userId: userId.toString() },
secret,
{ expiresIn: '7d' }
);
}
/**
* Create a test user document
* @param {Object} overrides - Fields to override in the default user
* @returns {Object} User document
*/
function createTestUser(overrides = {}) {
const now = new Date();
const uniqueId = `${Date.now()}-${++uniqueCounter}-${Math.random().toString(36).substr(2, 9)}`;
return {
_id: new ObjectId(),
googleId: `google-${uniqueId}`,
email: `test-${uniqueId}@example.com`,
name: 'Test User',
picture: 'https://example.com/photo.jpg',
role: 'user',
isActive: true,
loginCount: 1,
createdAt: now,
lastLoginAt: now,
disabledAt: null,
disabledBy: null,
...overrides
};
}
/**
* Create an admin user document
* @param {Object} overrides - Fields to override in the default admin
* @returns {Object} Admin user document
*/
function createTestAdmin(overrides = {}) {
const uniqueId = `${Date.now()}-${++uniqueCounter}-${Math.random().toString(36).substr(2, 9)}`;
return createTestUser({
role: 'admin',
email: `admin-${uniqueId}@example.com`,
name: 'Test Admin',
...overrides
});
}
/**
* Insert a user into the database
* @param {Db} db - MongoDB database instance
* @param {Object} user - User document to insert
* @returns {Promise<Object>} Inserted user with _id
*/
async function insertTestUser(db, user) {
const result = await db.collection('users').insertOne(user);
return { ...user, _id: result.insertedId };
}
/**
* Clean up test users from the database
* @param {Db} db - MongoDB database instance
*/
async function cleanupTestUsers(db) {
await db.collection('users').deleteMany({});
}
/**
* Clean up all test data from the database
* @param {Db} db - MongoDB database instance
*/
async function cleanupTestData(db) {
await Promise.all([
db.collection('users').deleteMany({}),
db.collection('user_activity').deleteMany({})
]);
}
/**
* Create a test activity document
* @param {Object} overrides - Fields to override in the default activity
* @returns {Object} Activity document
*/
function createTestActivity(overrides = {}) {
const now = new Date();
return {
_id: new ObjectId(),
userId: new ObjectId(),
action: 'PAGE_VIEW',
metadata: { path: '/test' },
timestamp: now,
sessionId: `session-${Date.now()}`,
...overrides
};
}
module.exports = {
createTestApp,
generateTestToken,
createTestUser,
createTestAdmin,
insertTestUser,
cleanupTestUsers,
cleanupTestData,
createTestActivity
};