UNPKG

qapinterface

Version:

Comprehensive API utilities for Node.js applications including authentication, security, request processing, and response handling with zero external dependencies

458 lines (357 loc) 14.6 kB
/** * Comprehensive unit tests for logging modules * Tests logger creation, memory monitoring, and logging utilities with mocked dependencies */ const { expect } = require('chai'); const sinon = require('sinon'); // Import modules to test const { createLogger } = require('../logging/logger-creator'); const { closeLogger } = require('../logging/logger-closer'); const { getLoggerInstance } = require('../logging/logger-instance'); const { startMemoryMonitoring } = require('../logging/memory-monitor-starter'); const { stopMemoryMonitoring } = require('../logging/memory-monitor-stopper'); const { initializeLogger, logger } = require('../asyncLogger'); const { memoryMonitor } = require('../utility/memoryMonitor'); describe('Logging Module Tests', () => { describe('Logger Creator', () => { it('should create logger instance', async () => { const loggerInstance = await createLogger(); expect(typeof loggerInstance).to.equal('object'); expect(typeof loggerInstance.info).to.equal('function'); expect(typeof loggerInstance.error).to.equal('function'); expect(typeof loggerInstance.warn).to.equal('function'); expect(typeof loggerInstance.debug).to.equal('function'); }); it('should create logger with custom configuration', async () => { const config = { level: 'debug', name: 'test-logger', prettyPrint: true }; const loggerInstance = await createLogger(config); expect(typeof loggerInstance).to.equal('object'); expect(typeof loggerInstance.info).to.equal('function'); }); it('should handle logger creation errors', async () => { // Mock error in logger creation const originalConsoleError = console.error; let errorLogged = false; console.error = () => { errorLogged = true; }; try { // Pass invalid configuration to trigger error await createLogger({ invalidOption: 'invalid' }); } catch (error) { expect(error instanceof Error).to.equal(true); } console.error = originalConsoleError; }); it('should create logger with file output', async () => { const config = { level: 'info', destination: './logs/test.log' }; const loggerInstance = await createLogger(config); expect(typeof loggerInstance).to.equal('object'); expect(typeof loggerInstance.info).to.equal('function'); }); it('should support different log levels', async () => { const levels = ['fatal', 'error', 'warn', 'info', 'debug', 'trace']; for (const level of levels) { const loggerInstance = await createLogger({ level }); expect(typeof loggerInstance).to.equal('object'); } }); }); describe('Logger Instance Management', () => { it('should get current logger instance', () => { const instance = getLoggerInstance(); // May be null if not initialized yet if (instance) { expect(typeof instance).to.equal('object'); expect(typeof instance.info).to.equal('function'); } else { expect(instance).to.equal(null); } }); it('should handle logger instance updates', async () => { const newLogger = await createLogger({ name: 'new-logger' }); // Assuming there's a setLoggerInstance function if (typeof setLoggerInstance === 'function') { setLoggerInstance(newLogger); const retrievedInstance = getLoggerInstance(); expect(retrievedInstance).to.equal(newLogger); } }); }); describe('Logger Closer', () => { it('should close logger gracefully', async () => { const loggerInstance = await createLogger(); const closeResult = await closeLogger(loggerInstance); // Should complete without throwing expect(typeof closeResult).to.equal('undefined'); }); it('should handle closing null logger', async () => { const closeResult = await closeLogger(null); // Should handle gracefully expect(typeof closeResult).to.equal('undefined'); }); it('should handle logger closing errors', async () => { const mockLogger = { flush: () => { throw new Error('Flush error'); } }; try { await closeLogger(mockLogger); } catch (error) { expect(error.message).to.equal('Flush error'); } }); }); describe('Async Logger Initialization', () => { it('should initialize logger asynchronously', async () => { const loggerInstance = await initializeLogger(); expect(typeof loggerInstance).to.equal('object'); expect(typeof loggerInstance.info).to.equal('function'); }); it('should provide global logger access', () => { // The logger getter should work const globalLogger = logger; if (globalLogger) { expect(typeof globalLogger).to.equal('object'); } }); it('should handle initialization errors', async () => { // Mock createLogger to throw error const originalRequire = require; require = jest.fn((path) => { if (path.includes('logger-creator')) { return { createLogger: () => { throw new Error('Init error'); } }; } return originalRequire(path); }); const originalConsoleError = console.error; let errorLogged = false; console.error = () => { errorLogged = true; }; try { await initializeLogger(); } catch (error) { expect(error.message).to.equal('Init error'); expect(errorLogged).to.equal(true); } console.error = originalConsoleError; require = originalRequire; }); }); describe('Memory Monitor', () => { it('should start memory monitoring', () => { const monitor = memoryMonitor(); expect(typeof monitor).to.equal('object'); expect(typeof monitor.getUsage).to.equal('function'); expect(typeof monitor.startMonitoring).to.equal('function'); expect(typeof monitor.stopMonitoring).to.equal('function'); }); it('should get current memory usage', () => { const monitor = memoryMonitor(); const usage = monitor.getUsage(); expect(typeof usage).to.equal('object'); expect(typeof usage.heapUsed).to.equal('number'); expect(typeof usage.heapTotal).to.equal('number'); expect(typeof usage.external).to.equal('number'); expect(usage.heapUsed > 0).to.equal(true); }); it('should monitor memory over time', (done) => { const monitor = memoryMonitor(); let sampleCount = 0; monitor.startMonitoring((usage) => { sampleCount++; expect(typeof usage.heapUsed).to.equal('number'); if (sampleCount >= 3) { monitor.stopMonitoring(); expect(sampleCount >= 3).to.equal(true); done(); } }, 100); // 100ms interval }); it('should detect memory leaks', () => { const monitor = memoryMonitor(); const initialUsage = monitor.getUsage(); // Create some objects to increase memory usage const largeArray = new Array(10000).fill('memory test data'); const newUsage = monitor.getUsage(); expect(newUsage.heapUsed > initialUsage.heapUsed).to.equal(true); // Clean up largeArray.length = 0; }); it('should format memory usage output', () => { const monitor = memoryMonitor(); const formatted = monitor.formatUsage(); expect(typeof formatted).to.equal('string'); expect(formatted.includes('MB')).to.equal(true); expect(formatted.includes('Heap')).to.equal(true); }); it('should track memory trends', () => { const monitor = memoryMonitor(); const trend = monitor.getTrend(); // Initially should have no trend data if (trend) { expect(typeof trend).to.equal('object'); expect(typeof trend.direction).to.equal('string'); expect(typeof trend.rate).to.equal('number'); } }); }); describe('Memory Monitor Starter/Stopper', () => { it('should start memory monitoring service', async () => { const monitoringId = await startMemoryMonitoring({ interval: 1000, threshold: 100 // 100MB threshold }); expect(typeof monitoringId).to.equal('string'); expect(monitoringId.length > 0).to.equal(true); }); it('should stop memory monitoring service', async () => { const monitoringId = await startMemoryMonitoring({ interval: 1000 }); const stopped = await stopMemoryMonitoring(monitoringId); expect(stopped).to.equal(true); }); it('should handle invalid monitoring ID', async () => { const stopped = await stopMemoryMonitoring('invalid-id'); expect(stopped).to.equal(false); }); it('should configure monitoring thresholds', async () => { const monitoringId = await startMemoryMonitoring({ interval: 500, threshold: 50, // 50MB alertCallback: (usage) => { expect(typeof usage).to.equal('object'); } }); expect(typeof monitoringId).to.equal('string'); // Clean up await stopMemoryMonitoring(monitoringId); }); }); describe('Console Logger Integration', () => { it('should integrate with console logger', () => { const { log, logError, logWarn, logInfo } = require('../utility/console-logger'); const originalLog = console.log; const originalError = console.error; const originalWarn = console.warn; let logCalled = false; let errorCalled = false; let warnCalled = false; console.log = () => { logCalled = true; }; console.error = () => { errorCalled = true; }; console.warn = () => { warnCalled = true; }; log('Test log message'); logError('Test error message'); logWarn('Test warning message'); logInfo('Test info message'); console.log = originalLog; console.error = originalError; console.warn = originalWarn; expect(logCalled).to.equal(true); expect(errorCalled).to.equal(true); expect(warnCalled).to.equal(true); }); it('should create source-bound loggers', () => { const { createSourceLogger } = require('../utility/console-logger'); const apiLogger = createSourceLogger('API'); expect(typeof apiLogger).to.equal('object'); expect(typeof apiLogger.log).to.equal('function'); expect(typeof apiLogger.error).to.equal('function'); expect(typeof apiLogger.warn).to.equal('function'); expect(typeof apiLogger.info).to.equal('function'); }); it('should format timestamps correctly', () => { const { logWithCustomTime } = require('../utility/console-logger'); const originalLog = console.log; let loggedMessage = ''; console.log = (message) => { loggedMessage = message; }; const customTime = new Date('2025-01-01T12:30:45Z'); logWithCustomTime('Test message', customTime); console.log = originalLog; expect(loggedMessage.includes('12:30:45')).to.equal(true); expect(loggedMessage.includes('Test message')).to.equal(true); }); }); describe('Logging Integration Tests', () => { it('should coordinate multiple logging systems', async () => { // Initialize async logger const asyncLoggerInstance = await initializeLogger(); // Start memory monitoring const monitoringId = await startMemoryMonitoring({ interval: 1000 }); // Use console logger const { log } = require('../utility/console-logger'); const originalLog = console.log; let consoleLogCalled = false; console.log = () => { consoleLogCalled = true; }; log('Integration test message'); console.log = originalLog; expect(typeof asyncLoggerInstance).to.equal('object'); expect(typeof monitoringId).to.equal('string'); expect(consoleLogCalled).to.equal(true); // Clean up await stopMemoryMonitoring(monitoringId); }); it('should handle logging errors gracefully', async () => { const originalConsoleError = console.error; let errorHandled = false; console.error = () => { errorHandled = true; }; try { // Force an error in logging const badLogger = { info: () => { throw new Error('Log error'); } }; badLogger.info('This should fail'); } catch (error) { expect(error.message).to.equal('Log error'); } console.error = originalConsoleError; }); it('should maintain performance under load', async () => { const { log } = require('../utility/console-logger'); const originalLog = console.log; let logCount = 0; console.log = () => { logCount++; }; const startTime = Date.now(); // Log many messages quickly for (let i = 0; i < 1000; i++) { log(`Test message ${i}`); } const endTime = Date.now(); const duration = endTime - startTime; console.log = originalLog; expect(logCount).to.equal(1000); expect(duration < 5000).to.equal(true); // Should complete in under 5 seconds }); it('should rotate logs when configured', async () => { const config = { level: 'info', destination: './logs/rotating.log', rotate: { size: '10MB', count: 5 } }; const loggerInstance = await createLogger(config); expect(typeof loggerInstance).to.equal('object'); expect(typeof loggerInstance.info).to.equal('function'); }); it('should handle structured logging', async () => { const loggerInstance = await createLogger({ level: 'info' }); if (loggerInstance && loggerInstance.info) { // Should accept structured data loggerInstance.info({ message: 'Structured log entry', userId: 123, action: 'login', timestamp: new Date().toISOString() }); // Should also accept string messages loggerInstance.info('Simple string message'); } expect(typeof loggerInstance).to.equal('object'); }); }); }); module.exports = { runLoggingTests: () => expect().to.be.undefined };