diff --git a/.changeset/backend-test-utils-create-service-mock.md b/.changeset/backend-test-utils-create-service-mock.md new file mode 100644 index 0000000000..b35b647fd8 --- /dev/null +++ b/.changeset/backend-test-utils-create-service-mock.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-test-utils': minor +--- + +Added `createServiceMock`, a public utility for creating `ServiceMock` instances for custom service refs. This allows plugin authors to define mock creators for their own services following the same pattern as the built-in `mockServices` mocks. diff --git a/.changeset/catalog-node-use-create-service-mock.md b/.changeset/catalog-node-use-create-service-mock.md new file mode 100644 index 0000000000..5032484ebb --- /dev/null +++ b/.changeset/catalog-node-use-create-service-mock.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-node': patch +--- + +Updated `catalogServiceMock.mock` to use `createServiceMock` from `@backstage/backend-test-utils`, replacing the internal copy of `simpleMock`. Added `@backstage/backend-test-utils` as an optional peer dependency. diff --git a/.changeset/repo-tools-type-deps-ambient-jest.md b/.changeset/repo-tools-type-deps-ambient-jest.md index 87c15e6f80..d1a0feed01 100644 --- a/.changeset/repo-tools-type-deps-ambient-jest.md +++ b/.changeset/repo-tools-type-deps-ambient-jest.md @@ -2,4 +2,4 @@ '@backstage/repo-tools': patch --- -The `type-deps` command now detects ambient global types from the `jest` namespace in declaration files, rather than only looking for explicit imports and reference directives. +The `type-deps` command now follows relative imports and re-exports into declaration chunk files, and detects ambient global types such as the `jest` namespace. diff --git a/packages/backend-test-utils/report-alpha.api.md b/packages/backend-test-utils/report-alpha.api.md index ccbf96c0c7..ca6f47191d 100644 --- a/packages/backend-test-utils/report-alpha.api.md +++ b/packages/backend-test-utils/report-alpha.api.md @@ -70,7 +70,7 @@ export class MockActionsRegistry >(options: ActionsRegistryActionOptions): void; } -// @alpha (undocumented) +// @public (undocumented) export type ServiceMock = { factory: ServiceFactory; } & { diff --git a/packages/backend-test-utils/report.api.md b/packages/backend-test-utils/report.api.md index da5002275b..5c5f4d05ef 100644 --- a/packages/backend-test-utils/report.api.md +++ b/packages/backend-test-utils/report.api.md @@ -55,6 +55,12 @@ export interface CreateMockDirectoryOptions { mockOsTmpDir?: boolean; } +// @public +export function createServiceMock( + ref: ServiceRef, + mockFactory: () => jest.Mocked, +): (partialImpl?: Partial) => ServiceMock; + // @public (undocumented) export namespace mockCredentials { export function limitedUser( diff --git a/packages/backend-test-utils/src/alpha/services/ActionsRegistryServiceMock.ts b/packages/backend-test-utils/src/alpha/services/ActionsRegistryServiceMock.ts index faf89b393a..f23bfa99e6 100644 --- a/packages/backend-test-utils/src/alpha/services/ActionsRegistryServiceMock.ts +++ b/packages/backend-test-utils/src/alpha/services/ActionsRegistryServiceMock.ts @@ -16,11 +16,8 @@ import { mockServices } from '../../services'; import { LoggerService } from '@backstage/backend-plugin-api'; import { MockActionsRegistry } from './MockActionsRegistry'; -import { simpleMock } from './simpleMock'; -import { - ActionsRegistryService, - actionsRegistryServiceRef, -} from '@backstage/backend-plugin-api/alpha'; +import { createServiceMock } from './alphaCreateServiceMock'; +import { actionsRegistryServiceRef } from '@backstage/backend-plugin-api/alpha'; import { actionsRegistryServiceFactory } from '@backstage/backend-defaults/alpha'; /** @@ -40,10 +37,7 @@ export function actionsRegistryServiceMock(options?: { export namespace actionsRegistryServiceMock { export const factory = () => actionsRegistryServiceFactory; - export const mock = simpleMock( - actionsRegistryServiceRef, - () => ({ - register: jest.fn(), - }), - ); + export const mock = createServiceMock(actionsRegistryServiceRef, () => ({ + register: jest.fn(), + })); } diff --git a/packages/backend-test-utils/src/alpha/services/ActionsServiceMock.ts b/packages/backend-test-utils/src/alpha/services/ActionsServiceMock.ts index 63abff4c37..7ecc9d7ffb 100644 --- a/packages/backend-test-utils/src/alpha/services/ActionsServiceMock.ts +++ b/packages/backend-test-utils/src/alpha/services/ActionsServiceMock.ts @@ -14,11 +14,8 @@ * limitations under the License. */ -import { simpleMock } from './simpleMock'; -import { - ActionsService, - actionsServiceRef, -} from '@backstage/backend-plugin-api/alpha'; +import { createServiceMock } from './alphaCreateServiceMock'; +import { actionsServiceRef } from '@backstage/backend-plugin-api/alpha'; import { actionsServiceFactory } from '@backstage/backend-defaults/alpha'; /** @@ -27,7 +24,7 @@ import { actionsServiceFactory } from '@backstage/backend-defaults/alpha'; export namespace actionsServiceMock { export const factory = () => actionsServiceFactory; - export const mock = simpleMock(actionsServiceRef, () => ({ + export const mock = createServiceMock(actionsServiceRef, () => ({ invoke: jest.fn(), list: jest.fn(), })); diff --git a/packages/backend-test-utils/src/alpha/services/alphaCreateServiceMock.ts b/packages/backend-test-utils/src/alpha/services/alphaCreateServiceMock.ts new file mode 100644 index 0000000000..9b69167b51 --- /dev/null +++ b/packages/backend-test-utils/src/alpha/services/alphaCreateServiceMock.ts @@ -0,0 +1,20 @@ +/* + * 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. + */ + +export { createServiceMock } from '../../services/createServiceMock'; + +/** @alpha */ +export type { ServiceMock } from '../../services/createServiceMock'; diff --git a/packages/backend-test-utils/src/alpha/services/index.ts b/packages/backend-test-utils/src/alpha/services/index.ts index ca9b3f23a0..ac92033ff8 100644 --- a/packages/backend-test-utils/src/alpha/services/index.ts +++ b/packages/backend-test-utils/src/alpha/services/index.ts @@ -17,4 +17,4 @@ export { actionsRegistryServiceMock } from './ActionsRegistryServiceMock'; export { MockActionsRegistry } from './MockActionsRegistry'; export { actionsServiceMock } from './ActionsServiceMock'; -export { type ServiceMock } from './simpleMock'; +export { type ServiceMock } from './alphaCreateServiceMock'; diff --git a/packages/backend-test-utils/src/alpha/services/simpleMock.ts b/packages/backend-test-utils/src/alpha/services/simpleMock.ts deleted file mode 100644 index d07b143f7a..0000000000 --- a/packages/backend-test-utils/src/alpha/services/simpleMock.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2025 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, - ServiceRef, -} from '@backstage/backend-plugin-api'; - -/** @alpha */ -export type ServiceMock = { - factory: ServiceFactory; -} & { - [Key in keyof TService]: TService[Key] extends ( - ...args: infer Args - ) => infer Return - ? TService[Key] & jest.MockInstance - : TService[Key]; -}; - -/** @internal */ -export function simpleMock( - ref: ServiceRef, - mockFactory: () => jest.Mocked, -): (partialImpl?: Partial) => ServiceMock { - return partialImpl => { - const mock = mockFactory(); - if (partialImpl) { - for (const [key, impl] of Object.entries(partialImpl)) { - if (typeof impl === 'function') { - (mock as any)[key].mockImplementation(impl); - } else { - (mock as any)[key] = impl; - } - } - } - return Object.assign(mock, { - factory: createServiceFactory({ - service: ref, - deps: {}, - factory: () => mock, - }), - }) as ServiceMock; - }; -} diff --git a/packages/backend-test-utils/src/services/simpleMock.ts b/packages/backend-test-utils/src/services/createServiceMock.ts similarity index 57% rename from packages/backend-test-utils/src/services/simpleMock.ts rename to packages/backend-test-utils/src/services/createServiceMock.ts index 484969f235..5f71725dd4 100644 --- a/packages/backend-test-utils/src/services/simpleMock.ts +++ b/packages/backend-test-utils/src/services/createServiceMock.ts @@ -30,8 +30,43 @@ export type ServiceMock = { : TService[Key]; }; -/** @internal */ -export function simpleMock( +/** + * Creates a standardized Backstage service mock factory function for producing + * mock service instances. + * + * @remarks + * + * Each method in the mock factory is a `jest.fn()`, and you can optionally pass + * partial implementations when calling the returned function. No type + * parameters should be provided to this function, they will be inferred from + * the provided service reference. + * + * The returned mock has a `.factory` property that can be passed directly to + * `startTestBackend` or other test utilities. + * + * @example + * ```ts + * import { createServiceMock } from '@backstage/backend-test-utils'; + * + * const myServiceMock = createServiceMock(myServiceRef, () => ({ + * doStuff: jest.fn(), + * doOtherStuff: jest.fn(), + * })); + * + * // Create a mock with default behavior: + * const mock = myServiceMock(); + * + * // Or with a partial implementation: + * const mock = myServiceMock({ doStuff: async () => 'test' }); + * expect(mock.doStuff).toHaveBeenCalledTimes(1); + * + * // It also has a `.factory` property for use with startTestBackend: + * await startTestBackend({ features: [mock.factory] }); + * ``` + * + * @public + */ +export function createServiceMock( ref: ServiceRef, mockFactory: () => jest.Mocked, ): (partialImpl?: Partial) => ServiceMock { diff --git a/packages/backend-test-utils/src/services/index.ts b/packages/backend-test-utils/src/services/index.ts index 73f179ca41..b048586440 100644 --- a/packages/backend-test-utils/src/services/index.ts +++ b/packages/backend-test-utils/src/services/index.ts @@ -15,4 +15,4 @@ */ export { mockServices } from './mockServices'; export { mockCredentials } from './mockCredentials'; -export { type ServiceMock } from './simpleMock'; +export { createServiceMock, type ServiceMock } from './createServiceMock'; diff --git a/packages/backend-test-utils/src/services/mockServices.ts b/packages/backend-test-utils/src/services/mockServices.ts index 9e941db3bb..84783f04d7 100644 --- a/packages/backend-test-utils/src/services/mockServices.ts +++ b/packages/backend-test-utils/src/services/mockServices.ts @@ -57,7 +57,7 @@ import { MockUserInfoService } from './MockUserInfoService'; import { mockCredentials } from './mockCredentials'; import { MockEventsService } from './MockEventsService'; import { MockPermissionsService } from './MockPermissionsService'; -import { simpleMock } from './simpleMock'; +import { createServiceMock } from './createServiceMock'; import { MockSchedulerService } from './MockSchedulerService'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { ObservableConfigProxy } from '../../../config-loader/src/sources/ObservableConfigProxy'; @@ -159,7 +159,7 @@ export namespace mockServices { coreServices.rootConfig, rootConfig, ); - export const mock = simpleMock(coreServices.rootConfig, () => ({ + export const mock = createServiceMock(coreServices.rootConfig, () => ({ get: jest.fn(), getBoolean: jest.fn(), getConfig: jest.fn(), @@ -191,7 +191,7 @@ export namespace mockServices { coreServices.rootLogger, rootLogger, ); - export const mock = simpleMock(coreServices.rootLogger, () => ({ + export const mock = createServiceMock(coreServices.rootLogger, () => ({ child: jest.fn(), debug: jest.fn(), error: jest.fn(), @@ -203,7 +203,7 @@ export namespace mockServices { export namespace auditor { export const factory = () => auditorServiceFactory; - export const mock = simpleMock(coreServices.auditor, () => ({ + export const mock = createServiceMock(coreServices.auditor, () => ({ createEvent: jest.fn(async _ => { return { success: jest.fn(), @@ -242,7 +242,7 @@ export namespace mockServices { }); }, }); - export const mock = simpleMock(coreServices.auth, () => ({ + export const mock = createServiceMock(coreServices.auth, () => ({ authenticate: jest.fn(), getNoneCredentials: jest.fn(), getOwnServiceCredentials: jest.fn(), @@ -271,7 +271,7 @@ export namespace mockServices { deps: {}, factory: () => discovery(), }); - export const mock = simpleMock(coreServices.discovery, () => ({ + export const mock = createServiceMock(coreServices.discovery, () => ({ getBaseUrl: jest.fn(), getExternalBaseUrl: jest.fn(), })); @@ -320,7 +320,7 @@ export namespace mockServices { options?.defaultCredentials ?? mockCredentials.user(), ), }); - export const mock = simpleMock(coreServices.httpAuth, () => ({ + export const mock = createServiceMock(coreServices.httpAuth, () => ({ credentials: jest.fn(), issueUserCookie: jest.fn(), })); @@ -353,7 +353,7 @@ export namespace mockServices { return new MockUserInfoService(); }, }); - export const mock = simpleMock(coreServices.userInfo, () => ({ + export const mock = createServiceMock(coreServices.userInfo, () => ({ getUserInfo: jest.fn(), })); } @@ -363,7 +363,7 @@ export namespace mockServices { // re-implement functioning mock versions here. export namespace cache { export const factory = () => cacheServiceFactory; - export const mock = simpleMock(coreServices.cache, () => ({ + export const mock = createServiceMock(coreServices.cache, () => ({ delete: jest.fn(), get: jest.fn(), set: jest.fn(), @@ -410,14 +410,14 @@ export namespace mockServices { * {@link @backstage/backend-plugin-api#coreServices.database}, optionally * with some given method implementations. */ - export const mock = simpleMock(coreServices.database, () => ({ + export const mock = createServiceMock(coreServices.database, () => ({ getClient: jest.fn(), })); } export namespace rootHealth { export const factory = () => rootHealthServiceFactory; - export const mock = simpleMock(coreServices.rootHealth, () => ({ + export const mock = createServiceMock(coreServices.rootHealth, () => ({ getLiveness: jest.fn(), getReadiness: jest.fn(), })); @@ -425,7 +425,7 @@ export namespace mockServices { export namespace httpRouter { export const factory = () => httpRouterServiceFactory; - export const mock = simpleMock(coreServices.httpRouter, () => ({ + export const mock = createServiceMock(coreServices.httpRouter, () => ({ use: jest.fn(), addAuthPolicy: jest.fn(), })); @@ -433,14 +433,14 @@ export namespace mockServices { export namespace rootHttpRouter { export const factory = () => rootHttpRouterServiceFactory(); - export const mock = simpleMock(coreServices.rootHttpRouter, () => ({ + export const mock = createServiceMock(coreServices.rootHttpRouter, () => ({ use: jest.fn(), })); } export namespace lifecycle { export const factory = () => lifecycleServiceFactory; - export const mock = simpleMock(coreServices.lifecycle, () => ({ + export const mock = createServiceMock(coreServices.lifecycle, () => ({ addShutdownHook: jest.fn(), addStartupHook: jest.fn(), })); @@ -448,7 +448,7 @@ export namespace mockServices { export namespace logger { export const factory = () => loggerServiceFactory; - export const mock = simpleMock(coreServices.logger, () => + export const mock = createServiceMock(coreServices.logger, () => createLoggerMock(), ); } @@ -484,7 +484,7 @@ export namespace mockServices { * {@link @backstage/backend-plugin-api#coreServices.permissions}, * optionally with some given method implementations. */ - export const mock = simpleMock(coreServices.permissions, () => ({ + export const mock = createServiceMock(coreServices.permissions, () => ({ authorize: jest.fn(), authorizeConditional: jest.fn(), })); @@ -492,17 +492,20 @@ export namespace mockServices { export namespace permissionsRegistry { export const factory = () => permissionsRegistryServiceFactory; - export const mock = simpleMock(coreServices.permissionsRegistry, () => ({ - addPermissionRules: jest.fn(), - addPermissions: jest.fn(), - addResourceType: jest.fn(), - getPermissionRuleset: jest.fn(), - })); + export const mock = createServiceMock( + coreServices.permissionsRegistry, + () => ({ + addPermissionRules: jest.fn(), + addPermissions: jest.fn(), + addResourceType: jest.fn(), + getPermissionRuleset: jest.fn(), + }), + ); } export namespace rootLifecycle { export const factory = () => rootLifecycleServiceFactory; - export const mock = simpleMock(coreServices.rootLifecycle, () => ({ + export const mock = createServiceMock(coreServices.rootLifecycle, () => ({ addShutdownHook: jest.fn(), addBeforeShutdownHook: jest.fn(), addStartupHook: jest.fn(), @@ -518,7 +521,7 @@ export namespace mockServices { includeManualTasksOnStartup?: boolean; includeInitialDelayedTasksOnStartup?: boolean; }) => new MockSchedulerService().factory(options); - export const mock = simpleMock(coreServices.scheduler, () => ({ + export const mock = createServiceMock(coreServices.scheduler, () => ({ createScheduledTaskRunner: jest.fn(), getScheduledTasks: jest.fn(), scheduleTask: jest.fn(), @@ -528,7 +531,7 @@ export namespace mockServices { export namespace urlReader { export const factory = () => urlReaderServiceFactory; - export const mock = simpleMock(coreServices.urlReader, () => ({ + export const mock = createServiceMock(coreServices.urlReader, () => ({ readTree: jest.fn(), readUrl: jest.fn(), search: jest.fn(), @@ -553,7 +556,7 @@ export namespace mockServices { * {@link @backstage/backend-events-node#eventsServiceRef}, optionally * with some given method implementations. */ - export const mock = simpleMock(eventsServiceRef, () => ({ + export const mock = createServiceMock(eventsServiceRef, () => ({ publish: jest.fn(), subscribe: jest.fn(), })); @@ -565,9 +568,12 @@ export namespace mockServices { }; } export namespace rootInstanceMetadata { - export const mock = simpleMock(coreServices.rootInstanceMetadata, () => ({ - getInstalledPlugins: jest.fn(), - })); + export const mock = createServiceMock( + coreServices.rootInstanceMetadata, + () => ({ + getInstalledPlugins: jest.fn(), + }), + ); export const factory = simpleFactoryWithOptions( coreServices.rootInstanceMetadata, rootInstanceMetadata, diff --git a/packages/repo-tools/src/commands/type-deps/type-deps.ts b/packages/repo-tools/src/commands/type-deps/type-deps.ts index 80d30a41a8..46dd0f67c5 100644 --- a/packages/repo-tools/src/commands/type-deps/type-deps.ts +++ b/packages/repo-tools/src/commands/type-deps/type-deps.ts @@ -78,6 +78,50 @@ function shouldCheckTypes(pkg: Package & PackageJsonWithTypes) { ); } +/** + * Read a declaration file and recursively follow all relative imports and + * re-exports, collecting the source content of each file encountered. + */ +function collectDeclSources(entryPath: string): string[] { + const visited = new Set(); + const sources: string[] = []; + + function visit(filePath: string) { + const resolved = resolvePath(filePath); + if (visited.has(resolved)) { + return; + } + visited.add(resolved); + + // Handle .js -> .d.ts extension mapping used by declaration chunk files + let actualPath = resolved; + if (!fs.existsSync(actualPath)) { + actualPath = resolved.replace(/\.js$/, '.d.ts'); + } + if (!fs.existsSync(actualPath)) { + return; + } + + const src = fs.readFileSync(actualPath, 'utf8'); + sources.push(src); + + // Follow relative imports and re-exports into chunk files + const relativeRefs = ( + src.match(/^(?:import|export) .* from '\..*';$/gm) || [] + ) + .map(match => match.match(/from '(.*)'/)?.[1] ?? '') + .filter(n => n.startsWith('.')); + + const dir = resolvePath(actualPath, '..'); + for (const ref of relativeRefs) { + visit(resolvePath(dir, ref)); + } + } + + visit(entryPath); + return sources; +} + function findAllDeps(declSrc: string) { const importedDeps = (declSrc.match(/^import .* from '.*';$/gm) || []) .map(match => match.match(/from '(.*)'/)?.[1] ?? '') @@ -112,11 +156,8 @@ function findAllDeps(declSrc: string) { */ function checkTypes(pkg: Package) { const allDeps = getPackageExportDetails(pkg.packageJson).flatMap(exp => { - const typeDecl = fs.readFileSync( - resolvePath(pkg.dir, 'dist', exp.distPath), - 'utf8', - ); - return findAllDeps(typeDecl); + const entryPath = resolvePath(pkg.dir, 'dist', exp.distPath); + return collectDeclSources(entryPath).flatMap(src => findAllDeps(src)); }); const deps = Array.from(new Set(allDeps)); diff --git a/plugins/catalog-node/package.json b/plugins/catalog-node/package.json index 5b37153c43..99483bcc0d 100644 --- a/plugins/catalog-node/package.json +++ b/plugins/catalog-node/package.json @@ -71,6 +71,14 @@ "lodash": "^4.17.21", "yaml": "^2.0.0" }, + "peerDependencies": { + "@backstage/backend-test-utils": "workspace:^" + }, + "peerDependenciesMeta": { + "@backstage/backend-test-utils": { + "optional": true + } + }, "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", diff --git a/plugins/catalog-node/src/testUtils/catalogServiceMock.ts b/plugins/catalog-node/src/testUtils/catalogServiceMock.ts index 59c66c0b88..61dfde4ca7 100644 --- a/plugins/catalog-node/src/testUtils/catalogServiceMock.ts +++ b/plugins/catalog-node/src/testUtils/catalogServiceMock.ts @@ -17,41 +17,13 @@ import { createServiceFactory, ServiceFactory, - ServiceRef, } from '@backstage/backend-plugin-api'; import { InMemoryCatalogClient } from '@backstage/catalog-client/testUtils'; import { Entity } from '@backstage/catalog-model'; import { catalogServiceRef } from '@backstage/plugin-catalog-node'; -// eslint-disable-next-line @backstage/no-undeclared-imports -import { ServiceMock } from '@backstage/backend-test-utils'; +import { createServiceMock } from '@backstage/backend-test-utils'; import { CatalogServiceMock } from './types'; -/** @internal */ -function simpleMock( - ref: ServiceRef, - mockFactory: () => jest.Mocked, -): (partialImpl?: Partial) => ServiceMock { - return partialImpl => { - const mock = mockFactory(); - if (partialImpl) { - for (const [key, impl] of Object.entries(partialImpl)) { - if (typeof impl === 'function') { - (mock as any)[key].mockImplementation(impl); - } else { - (mock as any)[key] = impl; - } - } - } - return Object.assign(mock, { - factory: createServiceFactory({ - service: ref, - deps: {}, - factory: () => mock, - }), - }) as ServiceMock; - }; -} - /** * Creates a fake catalog client that handles entities in memory storage. Note * that this client may be severely limited in functionality, and advanced @@ -86,23 +58,26 @@ export namespace catalogServiceMock { * Creates a catalog client whose methods are mock functions, possibly with * some of them overloaded by the caller. */ - export const mock = simpleMock(catalogServiceRef, () => ({ - getEntities: jest.fn(), - getEntitiesByRefs: jest.fn(), - queryEntities: jest.fn(), - getEntityAncestors: jest.fn(), - getEntityByRef: jest.fn(), - removeEntityByUid: jest.fn(), - refreshEntity: jest.fn(), - getEntityFacets: jest.fn(), - getLocations: jest.fn(), - getLocationById: jest.fn(), - getLocationByRef: jest.fn(), - addLocation: jest.fn(), - removeLocationById: jest.fn(), - getLocationByEntity: jest.fn(), - validateEntity: jest.fn(), - analyzeLocation: jest.fn(), - streamEntities: jest.fn(), - })); + export const mock = createServiceMock( + catalogServiceRef, + () => ({ + getEntities: jest.fn(), + getEntitiesByRefs: jest.fn(), + queryEntities: jest.fn(), + getEntityAncestors: jest.fn(), + getEntityByRef: jest.fn(), + removeEntityByUid: jest.fn(), + refreshEntity: jest.fn(), + getEntityFacets: jest.fn(), + getLocations: jest.fn(), + getLocationById: jest.fn(), + getLocationByRef: jest.fn(), + addLocation: jest.fn(), + removeLocationById: jest.fn(), + getLocationByEntity: jest.fn(), + validateEntity: jest.fn(), + analyzeLocation: jest.fn(), + streamEntities: jest.fn(), + }), + ); } diff --git a/plugins/gateway-backend/src/plugin.test.ts b/plugins/gateway-backend/src/plugin.test.ts index 8db99e39a5..301eae3abb 100644 --- a/plugins/gateway-backend/src/plugin.test.ts +++ b/plugins/gateway-backend/src/plugin.test.ts @@ -19,7 +19,6 @@ import { mockServices } from '@backstage/backend-test-utils'; import { coreServices, createBackendPlugin, - createServiceFactory, } from '@backstage/backend-plugin-api'; import { Router } from 'express'; import { EventSource } from 'eventsource'; @@ -48,12 +47,13 @@ describe('gateway', () => { }, }); - const discovery = mockServices.discovery.mock(); - discovery.getBaseUrl.mockImplementation(async (pluginId: string) => { - if (pluginId === 'external-plugin') { - return 'http://localhost:7778/api/external-plugin'; - } - return `http://localhost:7777/api/${pluginId}`; + const discovery = mockServices.discovery.mock({ + async getBaseUrl(pluginId) { + if (pluginId === 'external-plugin') { + return 'http://localhost:7778/api/external-plugin'; + } + return `http://localhost:7777/api/${pluginId}`; + }, }); beforeAll(async () => { @@ -68,13 +68,7 @@ describe('gateway', () => { ); backend.add(mockServices.auth.factory()); backend.add(mockServices.httpAuth.factory()); - backend.add( - createServiceFactory({ - service: coreServices.discovery, - deps: {}, - factory: () => discovery, - }), - ); + backend.add(discovery.factory); backend.add(dummyPlugin); backend.add(import('./')); diff --git a/yarn.lock b/yarn.lock index ce205f1bae..93be60a454 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5412,6 +5412,11 @@ __metadata: lodash: "npm:^4.17.21" msw: "npm:^1.0.0" yaml: "npm:^2.0.0" + peerDependencies: + "@backstage/backend-test-utils": "workspace:^" + peerDependenciesMeta: + "@backstage/backend-test-utils": + optional: true languageName: unknown linkType: soft