UNPKG

qmemory

Version:

A comprehensive production-ready Node.js utility library with MongoDB document operations, user ownership enforcement, Express.js HTTP utilities, environment-aware logging, and in-memory storage. Features 96%+ test coverage with comprehensive error handli

397 lines (330 loc) 13.3 kB
/** * Integration tests for critical workflows * Tests end-to-end interactions between modules and common usage patterns. */ // Mock mongoose before importing modules const mongoose = { connection: { readyState: 1 } }; jest.doMock('mongoose', () => mongoose); // ensure mock applied before imports const { storage, MemStorage, sendNotFound, ensureMongoDB, ensureUnique } = require('../../index'); // load API for integration tests // Mock mongoose for database tests jest.mock('mongoose', () => ({ // mock entire mongoose module connection: { readyState: 1 // Default to connected }, Error: { CastError: class CastError extends Error { constructor(message) { super(message); this.name = 'CastError'; } } } })); describe('Critical Workflows Integration', () => { // simulates end-to-end module interactions let storage; let mockRes; beforeEach(async () => { storage = new MemStorage(); mockRes = { status: jest.fn().mockReturnThis(), json: jest.fn() }; const mongoose = require('mongoose'); mongoose.connection.readyState = 1; //(reset connection state for each test) }); afterEach(() => { mongoose.connection.readyState = 1; // reset connection state on mock require('mongoose').connection.readyState = 1; // also reset on imported module }); describe('User Management Workflow', () => { // manage users through full lifecycle test('should handle complete user lifecycle', async () => { // create, fetch and delete flow // Create user const newUser = await storage.createUser({ username: 'lifecycle_user', displayName: 'Lifecycle Test User', githubId: 'lifecycle123', avatar: 'https://example.com/avatar.jpg' }); expect(newUser).toMatchObject({ id: 1, username: 'lifecycle_user', displayName: 'Lifecycle Test User', githubId: 'lifecycle123', avatar: 'https://example.com/avatar.jpg' }); // Retrieve by ID const byId = await storage.getUser(1); expect(byId).toEqual(newUser); // Retrieve by username const byUsername = await storage.getUserByUsername('lifecycle_user'); expect(byUsername).toEqual(newUser); // List all users const allUsers = await storage.getAllUsers(); expect(allUsers).toHaveLength(1); expect(allUsers[0]).toEqual(newUser); // Delete user const deleted = await storage.deleteUser(1); expect(deleted).toBe(true); // Verify deletion const afterDelete = await storage.getUser(1); expect(afterDelete).toBeUndefined(); const afterDeleteByUsername = await storage.getUserByUsername('lifecycle_user'); expect(afterDeleteByUsername).toBeUndefined(); // Verify empty list const emptyList = await storage.getAllUsers(); expect(emptyList).toHaveLength(0); }); test('should handle multiple users independently', async () => { // verify parallel data sets // Create multiple users const users = []; for (let i = 1; i <= 5; i++) { const user = await storage.createUser({ username: `user${i}`, displayName: `User ${i}`, githubId: `github${i}` }); users.push(user); expect(user.id).toBe(i); } // Verify all users exist const allUsers = await storage.getAllUsers(); expect(allUsers).toHaveLength(5); // Delete middle user const deleted = await storage.deleteUser(3); expect(deleted).toBe(true); // Verify remaining users const remainingUsers = await storage.getAllUsers(); expect(remainingUsers).toHaveLength(4); expect(remainingUsers.map(u => u.id)).toEqual([1, 2, 4, 5]); // Verify specific users still exist expect(await storage.getUser(1)).toBeDefined(); expect(await storage.getUser(2)).toBeDefined(); expect(await storage.getUser(3)).toBeUndefined(); expect(await storage.getUser(4)).toBeDefined(); expect(await storage.getUser(5)).toBeDefined(); }); }); describe('Error Handling Workflow', () => { // ensure consistent error messaging test('should handle HTTP error responses consistently', () => { // verifies helpers for various texts const errorMessages = [ 'User not found', 'Document does not exist', 'Access denied', '', null, undefined ]; errorMessages.forEach(message => { const localMockRes = { status: jest.fn().mockReturnThis(), json: jest.fn() }; sendNotFound(localMockRes, message); expect(localMockRes.status).toHaveBeenCalledWith(404); expect(localMockRes.json).toHaveBeenCalledWith({ message: message || 'Resource not found', timestamp: expect.any(String) }); }); }); test('should handle storage edge cases', async () => { // unusual usernames // Test edge cases for user creation - now with proper validation const validEdgeCases = [ { username: 'special_chars', displayName: 'Special Chars' }, { username: 'numeric123', displayName: 'Numeric String' }, { username: 'very_long_username_that_exceeds_normal_length_expectations' } ]; // Test invalid cases that should throw errors await expect(storage.createUser({ username: '', displayName: 'Empty Username' })) .rejects.toThrow('Username is required and must be a non-empty string'); await expect(storage.createUser({ username: ' ', displayName: 'Whitespace Username' })) .rejects.toThrow('Username is required and must be a non-empty string'); // Clear storage before testing valid cases await storage.clear(); for (let i = 0; i < validEdgeCases.length; i++) { const user = await storage.createUser(validEdgeCases[i]); expect(user.id).toBe(i + 1); expect(user.username).toBe(validEdgeCases[i].username); // Verify retrieval works const retrieved = await storage.getUserByUsername(validEdgeCases[i].username); expect(retrieved).toEqual(user); } }); test('should handle concurrent operations', async () => { // stress concurrency // Simulate concurrent user creation const createPromises = []; for (let i = 1; i <= 10; i++) { createPromises.push(storage.createUser({ username: `concurrent_user_${i}`, displayName: `Concurrent User ${i}` })); } const users = await Promise.all(createPromises); // Verify all users were created with unique IDs const ids = users.map(u => u.id); const uniqueIds = [...new Set(ids)]; expect(uniqueIds).toHaveLength(10); expect(Math.max(...ids)).toBe(10); expect(Math.min(...ids)).toBe(1); // Verify all users are retrievable const allUsers = await storage.getAllUsers(); expect(allUsers).toHaveLength(10); }); }); describe('Database Integration Workflow', () => { // MongoDB state and uniqueness paths test('should validate database connectivity states', () => { // checks each readyState case const mongoose = require('mongoose'); // Test different connection states const connectionStates = [ { state: 0, shouldPass: false, status: 503 }, // Disconnected { state: 1, shouldPass: true, status: null }, // Connected { state: 2, shouldPass: false, status: 503 }, // Connecting { state: 3, shouldPass: false, status: 503 } // Disconnecting ]; connectionStates.forEach(({ state, shouldPass, status }) => { const localMockRes = { status: jest.fn().mockReturnThis(), json: jest.fn() }; mongoose.connection.readyState = state; const result = ensureMongoDB(localMockRes); expect(result).toBe(shouldPass); if (!shouldPass) { expect(localMockRes.status).toHaveBeenCalledWith(status); expect(localMockRes.json).toHaveBeenCalledWith({ message: 'Database functionality unavailable', timestamp: expect.any(String), retryAfter: '300' }); } else { expect(localMockRes.status).not.toHaveBeenCalled(); } }); }); test('should handle uniqueness validation workflow', async () => { // ensures duplicate detection const mockModel = { findOne: jest.fn() }; // Test unique scenario mockModel.findOne.mockResolvedValueOnce(null); const uniqueResult = await ensureUnique( mockModel, { username: 'unique_user' }, mockRes, 'Duplicate user' ); expect(uniqueResult).toBe(true); expect(mockRes.status).not.toHaveBeenCalled(); // Test duplicate scenario mockModel.findOne.mockResolvedValueOnce({ _id: '123', username: 'duplicate_user' }); const duplicateResult = await ensureUnique( mockModel, { username: 'duplicate_user' }, mockRes, 'User already exists' ); expect(duplicateResult).toBe(false); expect(mockRes.status).toHaveBeenCalledWith(409); expect(mockRes.json).toHaveBeenCalledWith({ message: 'User already exists', timestamp: expect.any(String) }); }); }); describe('Full Stack Workflow Simulation', () => { // simulate API request lifecycle test('should simulate complete API request workflow', async () => { // happy path sequence // Simulate the full workflow of an API request // 1. Check database connectivity const dbOk = ensureMongoDB(mockRes); expect(dbOk).toBe(true); // 2. Create user in storage const newUser = await storage.createUser({ username: 'api_user', displayName: 'API Test User', githubId: 'api123' }); expect(newUser.id).toBe(1); // 3. Retrieve user (simulating authentication) const authUser = await storage.getUserByUsername('api_user'); expect(authUser).toEqual(newUser); // 4. Perform user operations const allUserDocs = await storage.getAllUsers(); expect(allUserDocs).toContain(newUser); // 5. Clean up (simulating logout/deletion) const deleteResult = await storage.deleteUser(newUser.id); expect(deleteResult).toBe(true); // 6. Verify cleanup const afterCleanup = await storage.getUser(newUser.id); expect(afterCleanup).toBeUndefined(); }); test('should handle error scenarios in full workflow', async () => { // covers db down and not found // Simulate database unavailable const mongoose = require('mongoose'); mongoose.connection.readyState = 0; // Disconnected const dbResult = ensureMongoDB(mockRes); expect(dbResult).toBe(false); expect(mockRes.status).toHaveBeenCalledWith(503); // Reset to connected state mongoose.connection.readyState = 1; // Simulate user not found scenario const nonExistentUser = await storage.getUserByUsername('nonexistent'); expect(nonExistentUser).toBeUndefined(); // Send appropriate error response sendNotFound(mockRes, 'User not found'); expect(mockRes.status).toHaveBeenCalledWith(404); expect(mockRes.json).toHaveBeenCalledWith({ message: 'User not found', timestamp: expect.any(String) }); }); }); describe('Performance and Load Testing', () => { // ensures scaling performance test('should handle bulk operations efficiently', async () => { // measure high volume actions const startTime = Date.now(); // Create 1000 users const createPromises = []; for (let i = 1; i <= 1000; i++) { createPromises.push(storage.createUser({ username: `bulk_user_${i}`, displayName: `Bulk User ${i}` })); } await Promise.all(createPromises); const creationTime = Date.now() - startTime; expect(creationTime).toBeLessThan(5000); // Should complete within 5 seconds // Verify all users were created const allUsers = await storage.getAllUsers(); expect(allUsers).toHaveLength(1000); // Test bulk retrieval const retrievalStart = Date.now(); const retrievalPromises = []; for (let i = 1; i <= 1000; i++) { retrievalPromises.push(storage.getUser(i)); } const retrievedUsers = await Promise.all(retrievalPromises); const retrievalTime = Date.now() - retrievalStart; expect(retrievalTime).toBeLessThan(1000); // Should complete within 1 second expect(retrievedUsers.filter(u => u !== undefined)).toHaveLength(1000); // Test bulk deletion const deletionStart = Date.now(); const deletionPromises = []; for (let i = 1; i <= 1000; i++) { deletionPromises.push(storage.deleteUser(i)); } await Promise.all(deletionPromises); const deletionTime = Date.now() - deletionStart; expect(deletionTime).toBeLessThan(2000); // Should complete within 2 seconds // Verify all users were deleted const afterDeletion = await storage.getAllUsers(); expect(afterDeletion).toHaveLength(0); }); }); });