UNPKG

thrilled-be-testing

Version:

Testing utilities and helpers package with Jest, Supertest, and database testing support for Express applications

354 lines (353 loc) 11.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MockFactories = exports.DatabaseMockUtils = exports.AuthMockUtils = exports.createMockPaginatedResponse = exports.createMockPagination = exports.createMockValidationError = exports.createMockErrorResponse = exports.createMockApiResponse = exports.createMockDatabaseRecord = exports.createMockJwtPayload = exports.createMockSession = exports.createMockUser = exports.MockDataFactory = void 0; /** * Mock Data Factory * Generates consistent test data using configurable factories */ class MockDataFactory { static sequence = new Map(); /** * Set global seed for consistent test data (resets sequences) */ // eslint-disable-next-line @typescript-eslint/no-unused-vars static setSeed(_seed) { // Reset sequences for consistent test data this.sequence.clear(); } /** * Get next sequence number for a given key */ static getSequence(key) { const current = this.sequence.get(key) || 0; const next = current + 1; this.sequence.set(key, next); return next; } /** * Generate random string */ static randomString(length = 10, prefix = '') { const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; let result = prefix; for (let i = 0; i < length; i++) { result += chars.charAt(Math.floor(Math.random() * chars.length)); } return result; } /** * Generate random number within range */ static randomNumber(min = 1, max = 1000) { return Math.floor(Math.random() * (max - min + 1)) + min; } /** * Generate random email */ static randomEmail(domain = 'example.com') { const username = this.randomString(8, 'user'); return `${username}@${domain}`; } /** * Generate random phone number */ static randomPhone(countryCode = '+1') { const areaCode = this.randomNumber(200, 999); const exchange = this.randomNumber(200, 999); const number = this.randomNumber(1000, 9999); return `${countryCode}${areaCode}${exchange}${number}`; } /** * Generate random date within range */ static randomDate(startDate, endDate) { const start = startDate || new Date(2020, 0, 1); const end = endDate || new Date(); return new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime())); } /** * Pick random item from array */ static randomChoice(items) { return items[Math.floor(Math.random() * items.length)]; } /** * Generate multiple items using a factory */ static generateMultiple(factory, count, options = {}) { const items = []; for (let i = 0; i < count; i++) { const overrides = options.sequence ? { id: i + 1 } : {}; items.push(factory(overrides)); } return items; } } exports.MockDataFactory = MockDataFactory; /** * User Mock Factory */ const createMockUser = (overrides = {}) => { const sequence = MockDataFactory['getSequence']('user'); return { id: sequence, email: `user${sequence}@example.com`, name: `Test User ${sequence}`, first_name: `First${sequence}`, last_name: `Last${sequence}`, phone: MockDataFactory.randomPhone(), address: `${MockDataFactory.randomNumber(100, 999)} Test St`, role: MockDataFactory.randomChoice(['user', 'admin', 'moderator']), language_preference: 'en', is_active: true, created_at: MockDataFactory.randomDate(), updated_at: new Date(), ...overrides, }; }; exports.createMockUser = createMockUser; /** * Session Mock Factory */ const createMockSession = (overrides = {}) => { const sequence = MockDataFactory['getSequence']('session'); return { id: `session-${sequence}`, user_id: sequence, device_info: { userAgent: 'Mozilla/5.0 (Test Browser)', ip: '192.168.1.100', platform: 'Test Platform', }, expires_at: new Date(Date.now() + 24 * 60 * 60 * 1000), // 24 hours created_at: new Date(), last_accessed: new Date(), is_active: true, ...overrides, }; }; exports.createMockSession = createMockSession; /** * JWT Token Mock Factory */ const createMockJwtPayload = (overrides = {}) => { const sequence = MockDataFactory['getSequence']('jwt'); return { userId: `user-${sequence}`, sessionId: `session-${sequence}`, roles: ['user'], permissions: ['read', 'write'], userData: { email: `user${sequence}@example.com`, name: `Test User ${sequence}`, }, iat: Math.floor(Date.now() / 1000), exp: Math.floor(Date.now() / 1000) + 3600, // 1 hour ...overrides, }; }; exports.createMockJwtPayload = createMockJwtPayload; /** * Database Record Mock Factory */ const createMockDatabaseRecord = (overrides = {}) => { const sequence = MockDataFactory['getSequence']('record'); return { id: sequence, created_at: new Date(), updated_at: new Date(), version: 1, ...overrides, }; }; exports.createMockDatabaseRecord = createMockDatabaseRecord; /** * API Response Mock Factory */ const createMockApiResponse = (overrides = {}) => { return { success: true, data: null, message: 'Operation completed successfully', timestamp: new Date().toISOString(), request_id: MockDataFactory.randomString(16), ...overrides, }; }; exports.createMockApiResponse = createMockApiResponse; /** * Error Response Mock Factory */ const createMockErrorResponse = (overrides = {}) => { return { success: false, error: { code: 'GENERIC_ERROR', message: 'An error occurred', details: {}, }, timestamp: new Date().toISOString(), request_id: MockDataFactory.randomString(16), ...overrides, }; }; exports.createMockErrorResponse = createMockErrorResponse; /** * Validation Error Mock Factory */ const createMockValidationError = (overrides = {}) => { return { success: false, error: { code: 'VALIDATION_ERROR', message: 'Validation failed', details: [ { field: 'email', message: 'Invalid email format', value: 'invalid-email', }, ], }, timestamp: new Date().toISOString(), request_id: MockDataFactory.randomString(16), ...overrides, }; }; exports.createMockValidationError = createMockValidationError; /** * Pagination Mock Factory */ const createMockPagination = (overrides = {}) => { return { page: 1, limit: 10, total: 100, totalPages: 10, hasNext: true, hasPrev: false, ...overrides, }; }; exports.createMockPagination = createMockPagination; /** * Paginated Response Mock Factory */ const createMockPaginatedResponse = (overrides = {}) => { const pagination = (0, exports.createMockPagination)(overrides.pagination); return { success: true, data: [], pagination, timestamp: new Date().toISOString(), request_id: MockDataFactory.randomString(16), ...overrides, }; }; exports.createMockPaginatedResponse = createMockPaginatedResponse; /** * Auth Mock Utilities */ class AuthMockUtils { /** * Create mock JWT token */ static createMockJwtToken(options = {}) { const payload = (0, exports.createMockJwtPayload)({ userId: options.userId, sessionId: options.sessionId, roles: options.roles, permissions: options.permissions, }); // In a real implementation, this would use the actual JWT library // For testing, we create a fake token that can be decoded const header = Buffer.from(JSON.stringify({ alg: 'HS256', typ: 'JWT' })).toString('base64'); const payloadEncoded = Buffer.from(JSON.stringify(payload)).toString('base64'); const signature = MockDataFactory.randomString(32); return `${header}.${payloadEncoded}.${signature}`; } /** * Create mock authentication headers */ static createAuthHeaders(token) { return { 'Authorization': `Bearer ${token || this.createMockJwtToken()}`, 'Content-Type': 'application/json', }; } /** * Create mock user session */ static createMockUserSession(options = {}) { return (0, exports.createMockSession)({ user_id: options.userId ? parseInt(options.userId, 10) : undefined, ...options, }); } } exports.AuthMockUtils = AuthMockUtils; /** * Database Mock Utilities */ class DatabaseMockUtils { /** * Create mock database connection */ static createMockConnection() { return { query: jest.fn().mockResolvedValue({ rows: [], rowCount: 0 }), connect: jest.fn().mockResolvedValue({ query: jest.fn().mockResolvedValue({ rows: [], rowCount: 0 }), release: jest.fn(), }), end: jest.fn().mockResolvedValue(undefined), on: jest.fn(), }; } /** * Create mock query result */ static createMockQueryResult(rows = [], rowCount) { return { rows, rowCount: rowCount ?? rows.length, command: 'SELECT', oid: 0, fields: [], }; } /** * Setup database mocks for testing */ // eslint-disable-next-line @typescript-eslint/no-unused-vars static setupDatabaseMocks(_options = {}) { const mockConnection = this.createMockConnection(); // Mock common queries // eslint-disable-next-line @typescript-eslint/no-unused-vars mockConnection.query.mockImplementation((query, _params) => { if (query.includes('SELECT 1')) { return Promise.resolve(this.createMockQueryResult([{ '?column?': 1 }])); } if (query.includes('COUNT(*)')) { return Promise.resolve(this.createMockQueryResult([{ count: '0' }])); } return Promise.resolve(this.createMockQueryResult()); }); return mockConnection; } } exports.DatabaseMockUtils = DatabaseMockUtils; /** * Export all mock factories */ exports.MockFactories = { User: exports.createMockUser, Session: exports.createMockSession, JwtPayload: exports.createMockJwtPayload, DatabaseRecord: exports.createMockDatabaseRecord, ApiResponse: exports.createMockApiResponse, ErrorResponse: exports.createMockErrorResponse, ValidationError: exports.createMockValidationError, Pagination: exports.createMockPagination, PaginatedResponse: exports.createMockPaginatedResponse, };