backend-test-utils: switch levels to level for mock logger

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2023-02-06 16:58:42 +01:00
parent 71a5ec0f06
commit 7e7557a2be
5 changed files with 163 additions and 29 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-test-utils': patch
---
Updated the `mockServices.rootLogger` options to accept a single level option instead.
+1 -8
View File
@@ -91,14 +91,7 @@ export namespace mockServices {
export namespace rootLogger {
// (undocumented)
export type Options = {
levels:
| boolean
| {
error: boolean;
warn: boolean;
info: boolean;
debug: boolean;
};
level?: 'none' | 'error' | 'warn' | 'info' | 'debug';
};
const // (undocumented)
factory: (options?: Options | undefined) => ServiceFactory<LoggerService>;
@@ -0,0 +1,131 @@
/*
* Copyright 2023 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { MockRootLoggerService } from './MockRootLoggerService';
describe('MockRootLoggerService', () => {
afterEach(() => {
jest.resetAllMocks();
});
it('should be silent by default', () => {
jest.spyOn(console, 'error').mockImplementation(() => {});
jest.spyOn(console, 'warn').mockImplementation(() => {});
jest.spyOn(console, 'info').mockImplementation(() => {});
jest.spyOn(console, 'debug').mockImplementation(() => {});
const logger = MockRootLoggerService.create();
logger.error('error');
logger.warn('warn');
logger.info('info');
logger.debug('debug');
expect(console.error).not.toHaveBeenCalled();
expect(console.warn).not.toHaveBeenCalled();
expect(console.info).not.toHaveBeenCalled();
expect(console.debug).not.toHaveBeenCalled();
});
it('shuld be able to set none level', () => {
jest.spyOn(console, 'error').mockImplementation(() => {});
jest.spyOn(console, 'warn').mockImplementation(() => {});
jest.spyOn(console, 'info').mockImplementation(() => {});
jest.spyOn(console, 'debug').mockImplementation(() => {});
const logger = MockRootLoggerService.create({ level: 'none' });
logger.error('error');
logger.warn('warn');
logger.info('info');
logger.debug('debug');
expect(console.error).not.toHaveBeenCalled();
expect(console.warn).not.toHaveBeenCalled();
expect(console.info).not.toHaveBeenCalled();
expect(console.debug).not.toHaveBeenCalled();
});
it('shuld be able to set error level', () => {
jest.spyOn(console, 'error').mockImplementation(() => {});
jest.spyOn(console, 'warn').mockImplementation(() => {});
jest.spyOn(console, 'info').mockImplementation(() => {});
jest.spyOn(console, 'debug').mockImplementation(() => {});
const logger = MockRootLoggerService.create({ level: 'error' });
logger.error('error');
logger.warn('warn');
logger.info('info');
logger.debug('debug');
expect(console.error).toHaveBeenCalled();
expect(console.warn).not.toHaveBeenCalled();
expect(console.info).not.toHaveBeenCalled();
expect(console.debug).not.toHaveBeenCalled();
});
it('shuld be able to set warn level', () => {
jest.spyOn(console, 'error').mockImplementation(() => {});
jest.spyOn(console, 'warn').mockImplementation(() => {});
jest.spyOn(console, 'info').mockImplementation(() => {});
jest.spyOn(console, 'debug').mockImplementation(() => {});
const logger = MockRootLoggerService.create({ level: 'warn' });
logger.error('error');
logger.warn('warn');
logger.info('info');
logger.debug('debug');
expect(console.error).toHaveBeenCalled();
expect(console.warn).toHaveBeenCalled();
expect(console.info).not.toHaveBeenCalled();
expect(console.debug).not.toHaveBeenCalled();
});
it('shuld be able to set info level', () => {
jest.spyOn(console, 'error').mockImplementation(() => {});
jest.spyOn(console, 'warn').mockImplementation(() => {});
jest.spyOn(console, 'info').mockImplementation(() => {});
jest.spyOn(console, 'debug').mockImplementation(() => {});
const logger = MockRootLoggerService.create({ level: 'info' });
logger.error('error');
logger.warn('warn');
logger.info('info');
logger.debug('debug');
expect(console.error).toHaveBeenCalled();
expect(console.warn).toHaveBeenCalled();
expect(console.info).toHaveBeenCalled();
expect(console.debug).not.toHaveBeenCalled();
});
it('shuld be able to set debug level', () => {
jest.spyOn(console, 'error').mockImplementation(() => {});
jest.spyOn(console, 'warn').mockImplementation(() => {});
jest.spyOn(console, 'info').mockImplementation(() => {});
jest.spyOn(console, 'debug').mockImplementation(() => {});
const logger = MockRootLoggerService.create({ level: 'debug' });
logger.error('error');
logger.warn('warn');
logger.info('info');
logger.debug('debug');
expect(console.error).toHaveBeenCalled();
expect(console.warn).toHaveBeenCalled();
expect(console.info).toHaveBeenCalled();
expect(console.debug).toHaveBeenCalled();
});
});
@@ -20,10 +20,28 @@ import {
} from '@backstage/backend-plugin-api';
import type { mockServices } from './mockServices';
const levels = {
none: 0,
error: 1,
warn: 2,
info: 3,
debug: 4,
};
export class MockRootLoggerService implements RootLoggerService {
#levels: Exclude<mockServices.rootLogger.Options['levels'], boolean>;
#level: number;
#meta: Record<string, unknown>;
static create(
options?: mockServices.rootLogger.Options,
): MockRootLoggerService {
const level = options?.level ?? 'none';
if (!(level in levels)) {
throw new Error(`Invalid log level '${level}'`);
}
return new MockRootLoggerService(levels[level], {});
}
error(
message: string,
meta?: Record<string, unknown> | Error | undefined,
@@ -53,23 +71,11 @@ export class MockRootLoggerService implements RootLoggerService {
}
child(meta: Record<string, unknown>): LoggerService {
return new MockRootLoggerService(this.#levels, { ...this.#meta, ...meta });
return new MockRootLoggerService(this.#level, { ...this.#meta, ...meta });
}
constructor(
levels: mockServices.rootLogger.Options['levels'],
meta: Record<string, unknown>,
) {
if (typeof levels === 'boolean') {
this.#levels = {
error: levels,
debug: levels,
info: levels,
warn: levels,
};
} else {
this.#levels = levels;
}
private constructor(level: number, meta: Record<string, unknown>) {
this.#level = level;
this.#meta = meta;
}
@@ -78,7 +84,8 @@ export class MockRootLoggerService implements RootLoggerService {
message: string,
meta?: Record<string, unknown> | Error | undefined,
) {
if (this.#levels[level]) {
const levelValue = levels[level] ?? 0;
if (levelValue <= this.#level) {
const labels = Object.entries(this.#meta)
.map(([key, value]) => `${key}=${value}`)
.join(',');
@@ -67,13 +67,11 @@ export namespace mockServices {
}
export function rootLogger(options?: rootLogger.Options): LoggerService {
return new MockRootLoggerService(options?.levels ?? false, {});
return MockRootLoggerService.create(options);
}
export namespace rootLogger {
export type Options = {
levels:
| boolean
| { error: boolean; warn: boolean; info: boolean; debug: boolean };
level?: 'none' | 'error' | 'warn' | 'info' | 'debug';
};
export const factory = simpleFactory(coreServices.rootLogger, rootLogger);