diff --git a/.changeset/backend-test-utils-tracing-service-mock.md b/.changeset/backend-test-utils-tracing-service-mock.md new file mode 100644 index 0000000000..91703f853e --- /dev/null +++ b/.changeset/backend-test-utils-tracing-service-mock.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-test-utils': patch +--- + +Added a new tracing service mock to be leveraged in tests diff --git a/packages/backend-test-utils/report-alpha.api.md b/packages/backend-test-utils/report-alpha.api.md index 4813f49c35..71848aaaa1 100644 --- a/packages/backend-test-utils/report-alpha.api.md +++ b/packages/backend-test-utils/report-alpha.api.md @@ -14,6 +14,10 @@ import { JsonValue } from '@backstage/types'; import { LoggerService } from '@backstage/backend-plugin-api'; import { MetricsService } from '@backstage/backend-plugin-api/alpha'; import { ServiceFactory } from '@backstage/backend-plugin-api'; +import { TracingService } from '@backstage/backend-plugin-api/alpha'; +import { TracingServiceAttributeValue } from '@backstage/backend-plugin-api/alpha'; +import { TracingServiceSpan } from '@backstage/backend-plugin-api/alpha'; +import { TracingServiceSpanStatus } from '@backstage/backend-plugin-api/alpha'; // @alpha (undocumented) export function actionsRegistryServiceMock(options?: { @@ -81,6 +85,14 @@ export class MockActionsRegistry >(options: ActionsRegistryActionOptions): void; } +// @alpha +export interface MockedTracingServiceSpan extends TracingServiceSpan { + // (undocumented) + setAttribute: jest.Mock; + // (undocumented) + setStatus: jest.Mock; +} + // @public (undocumented) export type ServiceMock = { factory: ServiceFactory; @@ -92,5 +104,20 @@ export type ServiceMock = { : TService[Key]; }; +// @alpha +export interface TracingServiceMock extends TracingService { + // (undocumented) + factory: ServiceFactory; + spans: MockedTracingServiceSpan[]; + // (undocumented) + startActiveSpan: jest.MockedFunction; +} + +// @alpha (undocumented) +export namespace tracingServiceMock { + const factory: () => ServiceFactory; + const mock: () => TracingServiceMock; +} + // (No @packageDocumentation comment for this package) ``` diff --git a/packages/backend-test-utils/src/alpha/services/TracingServiceMock.ts b/packages/backend-test-utils/src/alpha/services/TracingServiceMock.ts new file mode 100644 index 0000000000..6cdc1136cc --- /dev/null +++ b/packages/backend-test-utils/src/alpha/services/TracingServiceMock.ts @@ -0,0 +1,89 @@ +/* + * Copyright 2026 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 { + createServiceFactory, + ServiceFactory, +} from '@backstage/backend-plugin-api'; +import { + TracingService, + TracingServiceAttributeValue, + TracingServiceSpan, + TracingServiceSpanStatus, + tracingServiceRef, +} from '@backstage/backend-plugin-api/alpha'; +import { tracingServiceFactory } from '@backstage/backend-defaults/alpha'; + +/** + * A jest-mocked span captured by {@link TracingServiceMock}. + * + * @alpha + */ +export interface MockedTracingServiceSpan extends TracingServiceSpan { + setAttribute: jest.Mock; + setStatus: jest.Mock; +} + +/** + * Mock for the `TracingService`. Captures every span created via + * `startActiveSpan` so tests can assert on the options passed in and the + * methods called on the span inside the callback. + * + * @alpha + */ +export interface TracingServiceMock extends TracingService { + startActiveSpan: jest.MockedFunction; + /** Spans created by `startActiveSpan` calls, in order. */ + spans: MockedTracingServiceSpan[]; + factory: ServiceFactory; +} + +/** + * @alpha + */ +export namespace tracingServiceMock { + /** + * Returns the real `tracingServiceFactory` from `@backstage/backend-defaults`, + * for tests that want the full default implementation. + */ + export const factory = () => tracingServiceFactory; + + /** + * Builds a mock `TracingService` backed by jest mocks. + */ + export const mock = (): TracingServiceMock => { + const spans: MockedTracingServiceSpan[] = []; + const startActiveSpan = jest.fn(async (_name, fn, _options) => { + const span: MockedTracingServiceSpan = { + setAttribute: jest.fn(), + setStatus: jest.fn(), + }; + spans.push(span); + return await fn(span); + }) as TracingServiceMock['startActiveSpan']; + + const service: TracingService = { startActiveSpan }; + + return Object.assign(service as TracingServiceMock, { + spans, + factory: createServiceFactory({ + service: tracingServiceRef, + deps: {}, + factory: () => service, + }), + }); + }; +} diff --git a/packages/backend-test-utils/src/alpha/services/index.ts b/packages/backend-test-utils/src/alpha/services/index.ts index 527bb1822f..c8861c86a4 100644 --- a/packages/backend-test-utils/src/alpha/services/index.ts +++ b/packages/backend-test-utils/src/alpha/services/index.ts @@ -18,4 +18,9 @@ export { actionsRegistryServiceMock } from './ActionsRegistryServiceMock'; export { MockActionsRegistry } from './MockActionsRegistry'; export { actionsServiceMock } from './ActionsServiceMock'; export { metricsServiceMock } from './MetricsServiceMock'; +export { + tracingServiceMock, + type TracingServiceMock, + type MockedTracingServiceSpan, +} from './TracingServiceMock'; export { type ServiceMock } from './alphaCreateServiceMock'; diff --git a/packages/backend-test-utils/src/wiring/TestBackend.ts b/packages/backend-test-utils/src/wiring/TestBackend.ts index 11decb883d..fb60fbd5e7 100644 --- a/packages/backend-test-utils/src/wiring/TestBackend.ts +++ b/packages/backend-test-utils/src/wiring/TestBackend.ts @@ -44,6 +44,7 @@ import { actionsRegistryServiceMock, actionsServiceMock, metricsServiceMock, + tracingServiceMock, } from '../alpha/services'; /** @public */ @@ -94,6 +95,7 @@ export const defaultServiceFactories = [ actionsRegistryServiceMock.factory(), actionsServiceMock.factory(), metricsServiceMock.factory(), + tracingServiceMock.factory(), ]; /**