/** * Logger Middleware Integration Tests * * Tests the Hono middleware functionality of the @stock-bot/logger package, * verifying that all middleware components work correctly together. */ import { describe, it, expect, beforeEach, afterEach } from 'bun:test'; import { loggingMiddleware, errorLoggingMiddleware, performanceMiddleware, securityMiddleware, businessEventMiddleware, comprehensiveLoggingMiddleware } from '../src'; import { loggerTestHelpers } from './setup'; describe('Logger Middleware Integration', () => { beforeEach(() => { // Clear logs before each test loggerTestHelpers.clearCapturedLogs(); }); describe('Basic Logging Middleware', () => { it('should log incoming requests', async () => { // Create middleware with test logger const testLogger = loggerTestHelpers.createTestLogger('middleware-test'); const middleware = loggingMiddleware({ serviceName: 'test-service', logger: testLogger }); // Create mock context const mockContext = loggerTestHelpers.createHonoContextMock({ path: '/test', method: 'GET' }); const mockNext = loggerTestHelpers.createNextMock(); // Execute middleware await middleware(mockContext, mockNext); // Get captured logs const logs = loggerTestHelpers.getCapturedLogs(); // Verify request was logged expect(logs.length).toBeGreaterThan(0); expect(logs[0].level).toBe('http'); expect(logs[0].msg).toContain('HTTP Request'); }); it('should skip logging for defined paths', async () => { // Create middleware with skip paths const testLogger = loggerTestHelpers.createTestLogger('middleware-test'); const middleware = loggingMiddleware({ serviceName: 'test-service', logger: testLogger, skipPaths: ['/test'] }); // Create mock context with path that should be skipped const mockContext = loggerTestHelpers.createHonoContextMock({ path: '/test', method: 'GET' }); const mockNext = loggerTestHelpers.createNextMock(); // Execute middleware await middleware(mockContext, mockNext); // Get captured logs const logs = loggerTestHelpers.getCapturedLogs(); // Verify no logs were captured expect(logs.length).toBe(0); }); it('should log request/response details', async () => { // Create middleware that logs bodies const testLogger = loggerTestHelpers.createTestLogger('middleware-test'); const middleware = loggingMiddleware({ serviceName: 'test-service', logger: testLogger, logRequestBody: true, logResponseBody: true }); // Create mock context with response status const mockContext = loggerTestHelpers.createHonoContextMock({ path: '/api/data', method: 'POST', res: { status: 200, body: { success: true } } }); const mockNext = loggerTestHelpers.createNextMock(); // Execute middleware await middleware(mockContext, mockNext); // Get captured logs const logs = loggerTestHelpers.getCapturedLogs(); // Verify request and response were logged expect(logs.length).toBeGreaterThan(0); // First log is HTTP request started, and final log is HTTP request completed expect(logs[0].msg).toContain('HTTP Request started'); expect(logs[logs.length-1].msg).toContain('HTTP Request completed'); }); }); describe('Error Logging Middleware', () => { it('should log errors from next middleware', async () => { // Create middleware const testLogger = loggerTestHelpers.createTestLogger('middleware-test'); const middleware = errorLoggingMiddleware(testLogger); // Create mock context const mockContext = loggerTestHelpers.createHonoContextMock({ path: '/api/error', method: 'GET' }); // Create next function that throws error const mockNext = async () => { throw new Error('Test error'); }; // Execute middleware try { await middleware(mockContext, mockNext); } catch (error) { // Error should be re-thrown after logging } // Get captured logs const logs = loggerTestHelpers.getCapturedLogs(); // Verify error was logged expect(logs.length).toBe(1); expect(logs[0].level).toBe('error'); expect(logs[0].msg).toContain('Unhandled HTTP error'); }); }); describe('Performance Middleware', () => { it('should log performance metrics for requests', async () => { // Create middleware const testLogger = loggerTestHelpers.createTestLogger('middleware-test'); const middleware = performanceMiddleware('test-operation', testLogger); // Create mock context const mockContext = loggerTestHelpers.createHonoContextMock({ path: '/api/data', method: 'GET' }); const mockNext = loggerTestHelpers.createNextMock(); // Execute middleware await middleware(mockContext, mockNext); // Get captured logs const logs = loggerTestHelpers.getCapturedLogs(); // Verify performance metrics were logged expect(logs.length).toBe(1); expect(logs[0].level).toBe('info'); expect(logs[0].msg).toContain('Operation completed'); expect(logs[0].performance).toBeDefined(); }); }); describe('Security Middleware', () => { it('should log security events', async () => { // Create middleware const testLogger = loggerTestHelpers.createTestLogger('middleware-test'); const middleware = securityMiddleware(testLogger); // Create mock context with auth header const mockContext = loggerTestHelpers.createHonoContextMock({ path: '/api/secure', method: 'GET', req: { headers: { 'authorization': 'Bearer test-token' } } }); const mockNext = loggerTestHelpers.createNextMock(); // Execute middleware await middleware(mockContext, mockNext); // Get captured logs const logs = loggerTestHelpers.getCapturedLogs(); // Verify security event was logged expect(logs.length).toBe(1); expect(logs[0].level).toBe('info'); expect(logs[0].msg).toContain('Authentication attempt'); expect(logs[0].type).toBe('security_event'); }); }); describe('Business Event Middleware', () => { it('should log business events with custom metadata', async () => { // Create middleware with custom business endpoints const testLogger = loggerTestHelpers.createTestLogger('middleware-test'); const middleware = businessEventMiddleware(testLogger); // Create mock context with business path const mockContext = loggerTestHelpers.createHonoContextMock({ path: '/api/orders', method: 'POST', res: { status: 201 } }); const mockNext = loggerTestHelpers.createNextMock(); // Execute middleware await middleware(mockContext, mockNext); // Get captured logs const logs = loggerTestHelpers.getCapturedLogs(); // Verify business event was logged expect(logs.length).toBe(1); expect(logs[0].level).toBe('info'); expect(logs[0].msg).toContain('Business operation completed'); expect(logs[0].type).toBe('business_event'); }); }); describe('Comprehensive Logging Middleware', () => { it('should combine multiple logging features', async () => { // Create middleware const testLogger = loggerTestHelpers.createTestLogger('middleware-test'); const middleware = comprehensiveLoggingMiddleware({ serviceName: 'test-service', logger: testLogger }); // Create mock context const mockContext = loggerTestHelpers.createHonoContextMock({ path: '/api/data', method: 'GET', req: { headers: { 'authorization': 'Bearer test-token' } } }); const mockNext = loggerTestHelpers.createNextMock(); // Execute middleware await middleware(mockContext, mockNext); // Get captured logs const logs = loggerTestHelpers.getCapturedLogs(); // Verify multiple log entries from different middleware components expect(logs.length).toBeGreaterThan(1); // Should have logs from security, logging, and performance middleware const securityLog = logs.find(log => log.type === 'security_event'); const requestLog = logs.find(log => log.msg?.includes('HTTP Request')); expect(securityLog).toBeDefined(); expect(requestLog).toBeDefined(); }); }); });