209 lines
6.9 KiB
TypeScript
209 lines
6.9 KiB
TypeScript
import {expect, jest, test} from '@jest/globals';
|
|
import { Logger, RootLogger, ROOT } from '../../src/logger';
|
|
import { Handler } from '../../src/handler';
|
|
import { LogRecord } from '../../src/log-record';
|
|
import { Formatter } from '../../src/formatter';
|
|
import { Manager } from '../../src/manager';
|
|
import {
|
|
DEBUG,
|
|
INFO,
|
|
WARNING,
|
|
ERROR,
|
|
CRITICAL,
|
|
NOTSET,
|
|
} from '../../src/log-level';
|
|
import { MyError } from '../../src/helper/error';
|
|
|
|
describe('Logger', () => {
|
|
describe('constructor', () => {
|
|
test('sets scope and default level', () => {
|
|
const logger = new Logger('test');
|
|
expect(logger.scope).toBe('test');
|
|
expect(logger.level).toBe(NOTSET);
|
|
});
|
|
|
|
test('accepts explicit level', () => {
|
|
const logger = new Logger('test', WARNING);
|
|
expect(logger.level).toBe(WARNING);
|
|
});
|
|
});
|
|
|
|
describe('setLevel', () => {
|
|
test('changes the level', () => {
|
|
const logger = new Logger('test');
|
|
logger.setLevel(ERROR);
|
|
expect(logger.level).toBe(ERROR);
|
|
});
|
|
});
|
|
|
|
describe('getEffectiveLevel', () => {
|
|
test('returns own level when set', () => {
|
|
const logger = new Logger('test', WARNING);
|
|
expect(logger.getEffectiveLevel()).toBe(WARNING);
|
|
});
|
|
|
|
test('returns NOTSET when no level set and no parent', () => {
|
|
const logger = new Logger('test');
|
|
expect(logger.getEffectiveLevel()).toBe(NOTSET);
|
|
});
|
|
});
|
|
|
|
describe('isEnabledFor', () => {
|
|
test('returns true when level meets effective level', () => {
|
|
const logger = new Logger('test', DEBUG);
|
|
expect(logger.isEnabledFor(WARNING)).toBe(true);
|
|
expect(logger.isEnabledFor(DEBUG)).toBe(true);
|
|
});
|
|
|
|
test('returns false when level is below effective level', () => {
|
|
const logger = new Logger('test', WARNING);
|
|
expect(logger.isEnabledFor(DEBUG)).toBe(false);
|
|
expect(logger.isEnabledFor(INFO)).toBe(false);
|
|
});
|
|
|
|
test('caches results for repeated calls', () => {
|
|
const logger = new Logger('test', WARNING);
|
|
const first = logger.isEnabledFor(DEBUG);
|
|
const second = logger.isEnabledFor(DEBUG);
|
|
expect(first).toBe(second);
|
|
});
|
|
|
|
test('respects manager disable level', () => {
|
|
const root = new RootLogger(WARNING);
|
|
const manager = new Manager(root);
|
|
const logger = manager.getLogger('test');
|
|
logger.setLevel(DEBUG);
|
|
logger.manager = manager;
|
|
manager.disable = ERROR;
|
|
logger.clear();
|
|
expect(logger.isEnabledFor(DEBUG)).toBe(false);
|
|
expect(logger.isEnabledFor(WARNING)).toBe(false);
|
|
expect(logger.isEnabledFor(CRITICAL)).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('manager property', () => {
|
|
test('starts as null', () => {
|
|
const logger = new Logger('test');
|
|
expect(logger.manager).toBeNull();
|
|
});
|
|
|
|
test('can be assigned once', () => {
|
|
const logger = new Logger('test');
|
|
const root = new RootLogger(WARNING);
|
|
const manager = new Manager(root);
|
|
logger.manager = manager;
|
|
expect(logger.manager).toBe(manager);
|
|
});
|
|
|
|
test('throws on second assignment', () => {
|
|
const logger = new Logger('test');
|
|
const root = new RootLogger(WARNING);
|
|
const manager = new Manager(root);
|
|
logger.manager = manager;
|
|
expect(() => { logger.manager = manager }).toThrow('logger can only be assigned to manager once');
|
|
});
|
|
});
|
|
|
|
describe('addHandler / removeHandler', () => {
|
|
test('adds and removes handlers', () => {
|
|
const logger = new Logger('test');
|
|
const handler = new Handler(DEBUG);
|
|
expect(logger.handlers.length).toBe(0);
|
|
logger.addHandler(handler);
|
|
expect(logger.handlers.length).toBe(1);
|
|
logger.removeHandler(handler);
|
|
});
|
|
|
|
test('does not add duplicate handlers', () => {
|
|
const logger = new Logger('test');
|
|
const handler = new Handler(DEBUG);
|
|
logger.addHandler(handler);
|
|
logger.addHandler(handler);
|
|
expect(logger.handlers.length).toBe(1);
|
|
});
|
|
});
|
|
|
|
describe('level methods', () => {
|
|
let logger: Logger;
|
|
let emitted: LogRecord[];
|
|
|
|
class TestHandler extends Handler {
|
|
emit(record: LogRecord) { emitted.push(record) }
|
|
}
|
|
|
|
beforeEach(() => {
|
|
logger = new Logger('test', DEBUG);
|
|
emitted = [];
|
|
logger.addHandler(new TestHandler(DEBUG));
|
|
});
|
|
|
|
test('debug emits at DEBUG level', () => {
|
|
logger.debug('msg');
|
|
expect(emitted.length).toBe(1);
|
|
expect(emitted[0].levelno).toBe(DEBUG);
|
|
});
|
|
|
|
test('info emits at INFO level', () => {
|
|
logger.info('msg');
|
|
expect(emitted.length).toBe(1);
|
|
expect(emitted[0].levelno).toBe(INFO);
|
|
});
|
|
|
|
test('warning emits at WARNING level', () => {
|
|
logger.warning('msg');
|
|
expect(emitted.length).toBe(1);
|
|
expect(emitted[0].levelno).toBe(WARNING);
|
|
});
|
|
|
|
test('error emits at ERROR level', () => {
|
|
logger.error('msg');
|
|
expect(emitted.length).toBe(1);
|
|
expect(emitted[0].levelno).toBe(ERROR);
|
|
});
|
|
|
|
test('critical emits at CRITICAL level', () => {
|
|
logger.critical('msg');
|
|
expect(emitted.length).toBe(1);
|
|
expect(emitted[0].levelno).toBe(CRITICAL);
|
|
});
|
|
|
|
test('level methods respect effective level', () => {
|
|
logger.setLevel(ERROR);
|
|
logger.clear();
|
|
logger.debug('no');
|
|
logger.info('no');
|
|
logger.warning('no');
|
|
expect(emitted.length).toBe(0);
|
|
logger.error('yes');
|
|
logger.critical('yes');
|
|
expect(emitted.length).toBe(2);
|
|
});
|
|
});
|
|
|
|
describe('makeRecord', () => {
|
|
test('throws KeyError when extra overwrites existing LogRecord key', () => {
|
|
const logger = new Logger('test', DEBUG);
|
|
expect(() => {
|
|
logger.debug('test', {
|
|
excInfo: null,
|
|
extra: { scope: 'override' },
|
|
stackInfo: false,
|
|
stackLevel: 1,
|
|
});
|
|
}).toThrow('attempt to overwrite scope in LogRecord');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('RootLogger', () => {
|
|
test('has scope "root"', () => {
|
|
const root = new RootLogger(WARNING);
|
|
expect(root.scope).toBe('root');
|
|
});
|
|
|
|
test('accepts a level', () => {
|
|
const root = new RootLogger(ERROR);
|
|
expect(root.level).toBe(ERROR);
|
|
});
|
|
});
|