esm-logging/tests/unit/manager.test.ts
Tiara Rodney 3b6b116b00
test: add unit tests for handler, logger, manager, and config
Cover Handler property accessors, format delegation, emit contract,
and close lifecycle. Cover Logger level methods, isEnabledFor caching,
manager property assignment, handler management, debug invocation,
and makeRecord extra key collision. Cover Manager getLogger hierarchy
setup, placeholder fixup, disable level, and loggerClass validation.
Cover basicConfig option handling, force flag, mutual exclusion of
stream/filename/handlers, and formatter assignment.
2026-03-13 22:49:12 +01:00

128 lines
4.3 KiB
TypeScript

import {expect, jest, test} from '@jest/globals';
import { Manager } from '../../src/manager';
import { Logger, RootLogger } from '../../src/logger';
import { WARNING, DEBUG, NOTSET } from '../../src/log-level';
function makeManager(): Manager {
return new Manager(new RootLogger(WARNING));
}
describe('Manager', () => {
describe('constructor', () => {
test('stores the root logger', () => {
const root = new RootLogger(WARNING);
const manager = new Manager(root);
expect(manager.root).toBe(root);
});
});
describe('getLogger', () => {
test('returns a Logger instance', () => {
const manager = makeManager();
const logger = manager.getLogger('app');
expect(logger).toBeInstanceOf(Logger);
expect(logger.scope).toBe('app');
});
test('returns the same logger for the same scope', () => {
const manager = makeManager();
const a = manager.getLogger('app');
const b = manager.getLogger('app');
expect(a).toBe(b);
});
test('returns different loggers for different scopes', () => {
const manager = makeManager();
const a = manager.getLogger('app');
const b = manager.getLogger('lib');
expect(a).not.toBe(b);
});
test('sets parent to root for top-level loggers', () => {
const manager = makeManager();
const logger = manager.getLogger('app');
expect(logger.parent).toBe(manager.root);
});
test('sets parent to existing parent logger', () => {
const manager = makeManager();
const parent = manager.getLogger('app');
const child = manager.getLogger('app.module');
expect(child.parent).toBe(parent);
});
test('establishes hierarchy for deeply nested loggers', () => {
const manager = makeManager();
const top = manager.getLogger('a');
const mid = manager.getLogger('a.b');
const leaf = manager.getLogger('a.b.c');
expect(leaf.parent).toBe(mid);
expect(mid.parent).toBe(top);
expect(top.parent).toBe(manager.root);
});
test('creates placeholders for intermediate loggers', () => {
const manager = makeManager();
const leaf = manager.getLogger('a.b.c');
expect(leaf.parent).toBe(manager.root);
const mid = manager.getLogger('a.b');
expect(leaf.parent).toBe(mid);
expect(mid.parent).toBe(manager.root);
});
test('fixes up children when intermediate logger is created', () => {
const manager = makeManager();
const leaf = manager.getLogger('a.b.c');
const top = manager.getLogger('a');
expect(top.parent).toBe(manager.root);
const mid = manager.getLogger('a.b');
expect(leaf.parent).toBe(mid);
});
});
describe('disable', () => {
test('defaults to 0', () => {
const manager = makeManager();
expect(manager.disable).toBe(0);
});
test('can be set to a level', () => {
const manager = makeManager();
manager.disable = WARNING;
expect(manager.disable).toBe(WARNING);
});
});
describe('loggerClass', () => {
test('accepts Logger subclass', () => {
const manager = makeManager();
class CustomLogger extends Logger {}
expect(() => { manager.loggerClass = CustomLogger as any }).not.toThrow();
});
test('rejects non-Logger class', () => {
const manager = makeManager();
class NotALogger {}
expect(() => {
manager.loggerClass = NotALogger as any;
}).toThrow(TypeError);
});
test('accepts Logger itself', () => {
const manager = makeManager();
expect(() => { manager.loggerClass = Logger as any }).not.toThrow();
});
});
describe('clear', () => {
test('clears logger caches', () => {
const manager = makeManager();
const logger = manager.getLogger('test');
logger.isEnabledFor(DEBUG);
manager.clear();
});
});
});