diff --git a/.changeset/hip-tables-prove.md b/.changeset/hip-tables-prove.md new file mode 100644 index 0000000000..bc2c4e83d6 --- /dev/null +++ b/.changeset/hip-tables-prove.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-test-utils': patch +--- + +Updated the `mockServices.rootLogger` options to accept a single level option instead. diff --git a/packages/backend-test-utils/api-report.md b/packages/backend-test-utils/api-report.md index 672c574cb2..d99cf51866 100644 --- a/packages/backend-test-utils/api-report.md +++ b/packages/backend-test-utils/api-report.md @@ -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; diff --git a/packages/backend-test-utils/src/next/services/MockRootLoggerService.test.ts b/packages/backend-test-utils/src/next/services/MockRootLoggerService.test.ts new file mode 100644 index 0000000000..a3cbb5c384 --- /dev/null +++ b/packages/backend-test-utils/src/next/services/MockRootLoggerService.test.ts @@ -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(); + }); +}); diff --git a/packages/backend-test-utils/src/next/services/MockRootLoggerService.ts b/packages/backend-test-utils/src/next/services/MockRootLoggerService.ts index 5965792932..fabba82a0f 100644 --- a/packages/backend-test-utils/src/next/services/MockRootLoggerService.ts +++ b/packages/backend-test-utils/src/next/services/MockRootLoggerService.ts @@ -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; + #level: number; #meta: Record; + 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 | Error | undefined, @@ -53,23 +71,11 @@ export class MockRootLoggerService implements RootLoggerService { } child(meta: Record): 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, - ) { - if (typeof levels === 'boolean') { - this.#levels = { - error: levels, - debug: levels, - info: levels, - warn: levels, - }; - } else { - this.#levels = levels; - } + private constructor(level: number, meta: Record) { + this.#level = level; this.#meta = meta; } @@ -78,7 +84,8 @@ export class MockRootLoggerService implements RootLoggerService { message: string, meta?: Record | 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(','); diff --git a/packages/backend-test-utils/src/next/services/mockServices.ts b/packages/backend-test-utils/src/next/services/mockServices.ts index 5f771f13c5..2a56bd78b8 100644 --- a/packages/backend-test-utils/src/next/services/mockServices.ts +++ b/packages/backend-test-utils/src/next/services/mockServices.ts @@ -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);