trying to fix tests
This commit is contained in:
parent
6b4d4ea29f
commit
db66687f48
3 changed files with 159 additions and 64 deletions
|
|
@ -176,12 +176,14 @@ export class Logger {
|
|||
message: String(error)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create child logger with additional context
|
||||
*/
|
||||
child(context: LogContext): Logger {
|
||||
return new Logger((this.pino.bindings() as any).service, { ...this.context, ...context });
|
||||
const childLogger = new Logger((this.pino.bindings() as any).service, { ...this.context, ...context });
|
||||
// Use the pino child logger to properly propagate context
|
||||
childLogger.pino = this.pino.child(context);
|
||||
return childLogger;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,102 +1,198 @@
|
|||
/**
|
||||
* Advanced Logger Tests
|
||||
*
|
||||
* Tests for advanced logger functionality.
|
||||
* Tests for advanced logger functionality including complex metadata handling,
|
||||
* child loggers, and advanced error scenarios.
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach, afterEach } from 'bun:test';
|
||||
import { Logger, getLogger } from '../src';
|
||||
import { Logger } from '../src';
|
||||
import { loggerTestHelpers } from './setup';
|
||||
|
||||
describe('Advanced Logger Tests', () => {
|
||||
describe('Advanced Logger Features', () => {
|
||||
let logger: Logger;
|
||||
|
||||
beforeEach(() => {
|
||||
loggerTestHelpers.clearCapturedLogs();
|
||||
logger = loggerTestHelpers.createTestLogger('advanced-test');
|
||||
logger = loggerTestHelpers.createTestLogger('advanced-features');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
loggerTestHelpers.clearCapturedLogs();
|
||||
// Force garbage collection to clean up any potential circular references
|
||||
if (global.gc) {
|
||||
global.gc();
|
||||
}
|
||||
});
|
||||
|
||||
describe('Basic Logging', () => {
|
||||
it('should create logger instances', () => {
|
||||
expect(logger).toBeDefined();
|
||||
expect(typeof logger.info).toBe('function');
|
||||
expect(typeof logger.error).toBe('function');
|
||||
expect(typeof logger.warn).toBe('function');
|
||||
expect(typeof logger.debug).toBe('function');
|
||||
});
|
||||
|
||||
it('should log simple messages', () => {
|
||||
logger.info('Test message');
|
||||
describe('Complex Metadata Handling', () => {
|
||||
it('should handle nested metadata objects', () => {
|
||||
const complexMetadata = {
|
||||
user: { id: '123', name: 'John Doe' },
|
||||
session: { id: 'sess-456', timeout: 3600 },
|
||||
request: { method: 'POST', path: '/api/test' }
|
||||
};
|
||||
|
||||
logger.info('Complex operation', complexMetadata);
|
||||
|
||||
const logs = loggerTestHelpers.getCapturedLogs();
|
||||
expect(logs.length).toBe(1);
|
||||
expect(logs[0].msg).toBe('Test message');
|
||||
expect(logs[0].level).toBe('info');
|
||||
}); it('should include service name in logs', () => {
|
||||
logger.info('Service test');
|
||||
expect(logs[0].user).toEqual({ id: '123', name: 'John Doe' });
|
||||
expect(logs[0].session).toEqual({ id: 'sess-456', timeout: 3600 });
|
||||
expect(logs[0].request).toEqual({ method: 'POST', path: '/api/test' });
|
||||
});
|
||||
|
||||
it('should handle arrays in metadata', () => {
|
||||
const arrayMetadata = {
|
||||
tags: ['user', 'authentication', 'success'],
|
||||
ids: [1, 2, 3, 4]
|
||||
};
|
||||
|
||||
logger.info('Array metadata test', arrayMetadata);
|
||||
|
||||
const logs = loggerTestHelpers.getCapturedLogs();
|
||||
expect(logs.length).toBe(1);
|
||||
expect(logs[0].service).toBe('advanced-test');
|
||||
expect(logs[0].tags).toEqual(['user', 'authentication', 'success']);
|
||||
expect(logs[0].ids).toEqual([1, 2, 3, 4]);
|
||||
});
|
||||
|
||||
it('should handle multiple log levels', () => {
|
||||
logger.debug('Debug level');
|
||||
logger.info('Info level');
|
||||
logger.warn('Warn level');
|
||||
logger.error('Error level');
|
||||
it('should handle null and undefined metadata values', () => {
|
||||
const nullMetadata = {
|
||||
nullValue: null,
|
||||
undefinedValue: undefined,
|
||||
emptyString: '',
|
||||
zeroValue: 0
|
||||
};
|
||||
|
||||
logger.info('Null metadata test', nullMetadata);
|
||||
|
||||
const logs = loggerTestHelpers.getCapturedLogs();
|
||||
expect(logs.length).toBe(4);
|
||||
|
||||
const levels = logs.map(log => log.level);
|
||||
expect(levels).toEqual(['debug', 'info', 'warn', 'error']);
|
||||
expect(logs.length).toBe(1);
|
||||
expect(logs[0].nullValue).toBe(null);
|
||||
expect(logs[0].emptyString).toBe('');
|
||||
expect(logs[0].zeroValue).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Context and Metadata', () => {
|
||||
it('should include metadata in logs', () => {
|
||||
const metadata = { userId: '123', action: 'test' };
|
||||
logger.info('User action', metadata);
|
||||
describe('Child Logger Functionality', () => {
|
||||
it('should create child logger with additional context', () => {
|
||||
const childLogger = logger.child({
|
||||
component: 'auth-service',
|
||||
version: '1.2.3'
|
||||
});
|
||||
|
||||
childLogger.info('Child logger message');
|
||||
|
||||
const logs = loggerTestHelpers.getCapturedLogs();
|
||||
expect(logs.length).toBe(1);
|
||||
expect(logs[0].userId).toBe('123');
|
||||
expect(logs[0].action).toBe('test');
|
||||
expect(logs[0].component).toBe('auth-service');
|
||||
expect(logs[0].version).toBe('1.2.3');
|
||||
expect(logs[0].msg).toBe('Child logger message');
|
||||
});
|
||||
|
||||
it('should support child loggers', () => {
|
||||
const childLogger = logger.child({ requestId: 'req-456' });
|
||||
childLogger.info('Child log message');
|
||||
it('should support nested child loggers', () => {
|
||||
const childLogger = logger.child({ level1: 'parent' });
|
||||
const grandChildLogger = childLogger.child({ level2: 'child' });
|
||||
|
||||
grandChildLogger.warn('Nested child message');
|
||||
|
||||
const logs = loggerTestHelpers.getCapturedLogs();
|
||||
expect(logs.length).toBe(1);
|
||||
expect(logs[0].msg).toBe('Child log message');
|
||||
expect(logs[0].level1).toBe('parent');
|
||||
expect(logs[0].level2).toBe('child');
|
||||
expect(logs[0].level).toBe('warn');
|
||||
});
|
||||
|
||||
it('should merge child context with log metadata', () => {
|
||||
const childLogger = logger.child({ service: 'api' });
|
||||
|
||||
childLogger.info('Request processed', {
|
||||
requestId: 'req-789',
|
||||
duration: 150
|
||||
});
|
||||
|
||||
const logs = loggerTestHelpers.getCapturedLogs();
|
||||
expect(logs.length).toBe(1);
|
||||
expect(logs[0].service).toBe('api');
|
||||
expect(logs[0].requestId).toBe('req-789');
|
||||
expect(logs[0].duration).toBe(150);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Error Logging', () => {
|
||||
it('should log errors with error metadata', () => {
|
||||
const error = new Error('Test error');
|
||||
logger.error('Error occurred', { error });
|
||||
describe('Advanced Error Handling', () => {
|
||||
it('should handle Error objects with custom properties', () => {
|
||||
const customError = new Error('Custom error message');
|
||||
(customError as any).code = 'ERR_CUSTOM';
|
||||
(customError as any).statusCode = 500;
|
||||
|
||||
logger.error('Custom error occurred', { error: customError });
|
||||
|
||||
const logs = loggerTestHelpers.getCapturedLogs();
|
||||
expect(logs.length).toBe(1);
|
||||
expect(logs[0].level).toBe('error');
|
||||
expect(logs[0].msg).toBe('Error occurred');
|
||||
expect(logs[0].msg).toBe('Custom error occurred');
|
||||
});
|
||||
|
||||
it('should handle error-like objects', () => {
|
||||
const errorLike = { name: 'CustomError', message: 'Custom message' };
|
||||
logger.error('Custom error', { error: errorLike });
|
||||
it('should handle multiple errors in metadata', () => {
|
||||
const error1 = new Error('First error');
|
||||
const error2 = new Error('Second error');
|
||||
|
||||
logger.error('Multiple errors', {
|
||||
primaryError: error1,
|
||||
secondaryError: error2,
|
||||
context: 'batch processing'
|
||||
});
|
||||
|
||||
const logs = loggerTestHelpers.getCapturedLogs();
|
||||
expect(logs.length).toBe(1);
|
||||
expect(logs[0].context).toBe('batch processing');
|
||||
}); it('should handle error objects with circular references', () => {
|
||||
const errorWithCircular: any = { name: 'CircularError', message: 'Circular reference error' };
|
||||
// Create a simple circular reference
|
||||
errorWithCircular.self = errorWithCircular;
|
||||
|
||||
// Should not throw when logging circular references
|
||||
expect(() => {
|
||||
logger.error('Circular error test', { error: errorWithCircular });
|
||||
}).not.toThrow();
|
||||
|
||||
const logs = loggerTestHelpers.getCapturedLogs();
|
||||
expect(logs.length).toBe(1);
|
||||
expect(logs[0].level).toBe('error');
|
||||
});
|
||||
});
|
||||
describe('Performance and Edge Cases', () => {
|
||||
it('should handle moderate metadata objects', () => {
|
||||
const moderateMetadata: any = {};
|
||||
for (let i = 0; i < 10; i++) {
|
||||
moderateMetadata[`key${i}`] = `value${i}`;
|
||||
}
|
||||
|
||||
logger.debug('Moderate metadata test', moderateMetadata);
|
||||
|
||||
const logs = loggerTestHelpers.getCapturedLogs();
|
||||
expect(logs.length).toBe(1);
|
||||
expect(logs[0].key0).toBe('value0');
|
||||
expect(logs[0].key9).toBe('value9');
|
||||
});
|
||||
|
||||
it('should handle special characters in messages', () => {
|
||||
const specialMessage = 'Special chars: 🚀 ñ ü';
|
||||
|
||||
logger.info(specialMessage);
|
||||
|
||||
const logs = loggerTestHelpers.getCapturedLogs();
|
||||
expect(logs.length).toBe(1);
|
||||
expect(logs[0].msg).toBe(specialMessage);
|
||||
});
|
||||
|
||||
it('should handle empty and whitespace-only messages', () => {
|
||||
logger.info('');
|
||||
logger.info(' ');
|
||||
|
||||
const logs = loggerTestHelpers.getCapturedLogs();
|
||||
expect(logs.length).toBe(2);
|
||||
expect(logs[0].msg).toBe('');
|
||||
expect(logs[1].msg).toBe(' ');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -21,25 +21,22 @@ const originalConsole = {
|
|||
let capturedLogs: any[] = [];
|
||||
|
||||
// Create a test logger helper
|
||||
export const loggerTestHelpers = {
|
||||
/**
|
||||
export const loggerTestHelpers = { /**
|
||||
* Create a test logger instance that captures logs instead of outputting them
|
||||
*/ createTestLogger: (serviceName: string = 'test-service') => {
|
||||
*/ createTestLogger: (serviceName: string = 'test-service', context: any = {}) => {
|
||||
// Create a fully mocked Logger instance without using the real Logger class
|
||||
const logger = {
|
||||
serviceName,
|
||||
context: {},
|
||||
debug: (msg: string, metadata?: any) => capturedLogs.push({ level: 'debug', msg, service: serviceName, ...metadata }),
|
||||
info: (msg: string, metadata?: any) => capturedLogs.push({ level: 'info', msg, service: serviceName, ...metadata }),
|
||||
warn: (msg: string, metadata?: any) => capturedLogs.push({ level: 'warn', msg, service: serviceName, ...metadata }),
|
||||
error: (msg: string, metadata?: any) => capturedLogs.push({ level: 'error', msg, service: serviceName, ...metadata }),
|
||||
http: (msg: string, metadata?: any) => capturedLogs.push({ level: 'http', msg, service: serviceName, ...metadata }),
|
||||
verbose: (msg: string, metadata?: any) => capturedLogs.push({ level: 'verbose', msg, service: serviceName, ...metadata }),
|
||||
silly: (msg: string, metadata?: any) => capturedLogs.push({ level: 'silly', msg, service: serviceName, ...metadata }),
|
||||
context,
|
||||
debug: (msg: string, metadata?: any) => capturedLogs.push({ level: 'debug', msg, service: serviceName, ...context, ...metadata }),
|
||||
info: (msg: string, metadata?: any) => capturedLogs.push({ level: 'info', msg, service: serviceName, ...context, ...metadata }),
|
||||
warn: (msg: string, metadata?: any) => capturedLogs.push({ level: 'warn', msg, service: serviceName, ...context, ...metadata }),
|
||||
error: (msg: string, metadata?: any) => capturedLogs.push({ level: 'error', msg, service: serviceName, ...context, ...metadata }),
|
||||
http: (msg: string, metadata?: any) => capturedLogs.push({ level: 'http', msg, service: serviceName, ...context, ...metadata }),
|
||||
verbose: (msg: string, metadata?: any) => capturedLogs.push({ level: 'verbose', msg, service: serviceName, ...context, ...metadata }),
|
||||
silly: (msg: string, metadata?: any) => capturedLogs.push({ level: 'silly', msg, service: serviceName, ...context, ...metadata }),
|
||||
child: (childContext: any) => {
|
||||
const childLogger = loggerTestHelpers.createTestLogger(serviceName);
|
||||
(childLogger as any).context = { ...(childLogger as any).context, ...childContext };
|
||||
return childLogger;
|
||||
return loggerTestHelpers.createTestLogger(serviceName, { ...context, ...childContext });
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue