diff --git a/.changeset/selfish-items-play.md b/.changeset/selfish-items-play.md new file mode 100644 index 0000000000..6df9bd0de1 --- /dev/null +++ b/.changeset/selfish-items-play.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-catalog-backend': patch +'@backstage/plugin-catalog-node': patch +'@backstage/plugin-scaffolder-backend': patch +--- + +Fixed typos in alpha types. diff --git a/.changeset/seven-nails-cough.md b/.changeset/seven-nails-cough.md new file mode 100644 index 0000000000..eefef0b376 --- /dev/null +++ b/.changeset/seven-nails-cough.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-test-utils': patch +--- + +Added alpha test helpers for the new experimental backen system. diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index 004289d448..3b490b625d 100644 --- a/packages/backend-test-utils/package.json +++ b/packages/backend-test-utils/package.json @@ -36,6 +36,8 @@ }, "dependencies": { "@backstage/backend-common": "^0.15.0-next.0", + "@backstage/backend-app-api": "^0.1.1-next.0", + "@backstage/backend-plugin-api": "^0.1.1-next.0", "@backstage/cli": "^0.18.1-next.0", "@backstage/config": "^1.0.1", "better-sqlite3": "^7.5.0", diff --git a/packages/backend-test-utils/src/index.ts b/packages/backend-test-utils/src/index.ts index 5fef4e6b55..ae937d2fc8 100644 --- a/packages/backend-test-utils/src/index.ts +++ b/packages/backend-test-utils/src/index.ts @@ -22,4 +22,5 @@ export * from './database'; export * from './msw'; +export * from './next'; export * from './util'; diff --git a/packages/backend-test-utils/src/next/index.ts b/packages/backend-test-utils/src/next/index.ts new file mode 100644 index 0000000000..9bb5431772 --- /dev/null +++ b/packages/backend-test-utils/src/next/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 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 * from './wiring'; diff --git a/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts b/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts new file mode 100644 index 0000000000..279667560f --- /dev/null +++ b/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts @@ -0,0 +1,76 @@ +/* + * Copyright 2022 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 { + createBackendModule, + createServiceFactory, + createServiceRef, +} from '@backstage/backend-plugin-api'; +import { createTestBackend, startTestBackend } from './TestBackend'; + +describe('TestBackend', () => { + it('should get a type error if service implementation does not match', () => { + const serviceRef = createServiceRef<{ a: string; b: string }>({ id: 'a' }); + const backend = createTestBackend({ + services: [ + [serviceRef, { a: 'a' }], + [serviceRef, { a: 'a', b: 'b' }], + // @ts-expect-error + [serviceRef, { c: 'c' }], + // @ts-expect-error + [serviceRef, { a: 'a', c: 'c' }], + // @ts-expect-error + [serviceRef, { a: 'a', b: 'b', c: 'c' }], + ], + }); + expect(backend).toBeDefined(); + }); + + it('should start the test backend', async () => { + const testRef = createServiceRef<(v: string) => void>({ id: 'test' }); + const testFn = jest.fn(); + + const sf = createServiceFactory({ + deps: {}, + service: testRef, + factory: async () => { + return async () => testFn; + }, + }); + + const testModule = createBackendModule({ + moduleId: 'test.module', + pluginId: 'test', + register(env) { + env.registerInit({ + deps: { + test: testRef, + }, + async init({ test }) { + test('winning'); + }, + }); + }, + }); + + await startTestBackend({ + services: [sf], + registrables: [testModule({})], + }); + + expect(testFn).toBeCalledWith('winning'); + }); +}); diff --git a/packages/backend-test-utils/src/next/wiring/TestBackend.ts b/packages/backend-test-utils/src/next/wiring/TestBackend.ts new file mode 100644 index 0000000000..49acb07ab4 --- /dev/null +++ b/packages/backend-test-utils/src/next/wiring/TestBackend.ts @@ -0,0 +1,66 @@ +/* + * Copyright 2022 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 { Backend, createSpecializedBackend } from '@backstage/backend-app-api'; +import { + AnyServiceFactory, + ServiceRef, + createServiceFactory, + BackendRegistrable, +} from '@backstage/backend-plugin-api'; + +/** @alpha */ +export interface TestBackendOptions { + services: readonly [ + ...{ + [index in keyof TServices]: + | AnyServiceFactory + | [ServiceRef, Partial]; + }, + ]; +} + +/** @alpha */ +export function createTestBackend( + options: TestBackendOptions, +): Backend { + const factories = + options.services?.map(serviceDef => { + if (Array.isArray(serviceDef)) { + return createServiceFactory({ + service: serviceDef[0], + deps: {}, + factory: async () => async () => serviceDef[1], + }); + } + return serviceDef as AnyServiceFactory; + }) ?? []; + return createSpecializedBackend({ services: factories }); +} + +/** @alpha */ +export async function startTestBackend( + options: TestBackendOptions & { + registrables?: BackendRegistrable[]; + }, +): Promise { + const { registrables = [], ...otherOptions } = options; + const backend = createTestBackend(otherOptions); + for (const reg of registrables) { + backend.add(reg); + } + return backend.start(); +} diff --git a/packages/backend-test-utils/src/next/wiring/index.ts b/packages/backend-test-utils/src/next/wiring/index.ts new file mode 100644 index 0000000000..18a35c2b66 --- /dev/null +++ b/packages/backend-test-utils/src/next/wiring/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2022 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 { createTestBackend, startTestBackend } from './TestBackend'; +export type { TestBackendOptions } from './TestBackend'; diff --git a/plugins/catalog-backend/src/service/CatalogPlugin.ts b/plugins/catalog-backend/src/service/CatalogPlugin.ts index b82797ec8b..ed356df5a2 100644 --- a/plugins/catalog-backend/src/service/CatalogPlugin.ts +++ b/plugins/catalog-backend/src/service/CatalogPlugin.ts @@ -27,7 +27,7 @@ import { CatalogBuilder } from './CatalogBuilder'; import { CatalogProcessor, CatalogProcessingExtensionPoint, - catalogProcessingExtentionPoint, + catalogProcessingExtensionPoint, EntityProvider, } from '@backstage/plugin-catalog-node'; @@ -62,7 +62,7 @@ export const catalogPlugin = createBackendPlugin({ const processingExtensions = new CatalogExtensionPointImpl(); // plugins depending on this API will be initialized before this plugins init method is executed. env.registerExtensionPoint( - catalogProcessingExtentionPoint, + catalogProcessingExtensionPoint, processingExtensions, ); diff --git a/plugins/catalog-node/src/extensions.ts b/plugins/catalog-node/src/extensions.ts index 560d9d4db1..9f76946d30 100644 --- a/plugins/catalog-node/src/extensions.ts +++ b/plugins/catalog-node/src/extensions.ts @@ -28,7 +28,7 @@ export interface CatalogProcessingExtensionPoint { /** * @alpha */ -export const catalogProcessingExtentionPoint = +export const catalogProcessingExtensionPoint = createServiceRef({ id: 'catalog.processing', }); diff --git a/plugins/catalog-node/src/index.ts b/plugins/catalog-node/src/index.ts index fc7a1b1b67..02ae325a9a 100644 --- a/plugins/catalog-node/src/index.ts +++ b/plugins/catalog-node/src/index.ts @@ -21,6 +21,6 @@ */ export type { CatalogProcessingExtensionPoint } from './extensions'; -export { catalogProcessingExtentionPoint } from './extensions'; +export { catalogProcessingExtensionPoint } from './extensions'; export * from './api'; export * from './processing'; diff --git a/plugins/scaffolder-backend/src/extension/ScaffolderCatalogModule.test.ts b/plugins/scaffolder-backend/src/extension/ScaffolderCatalogModule.test.ts index f07eb0f7ae..a969d80a1b 100644 --- a/plugins/scaffolder-backend/src/extension/ScaffolderCatalogModule.test.ts +++ b/plugins/scaffolder-backend/src/extension/ScaffolderCatalogModule.test.ts @@ -14,27 +14,19 @@ * limitations under the License. */ -import { BackendInitRegistry } from '@backstage/backend-plugin-api'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node'; import { ScaffolderEntitiesProcessor } from '../processor'; import { scaffolderCatalogModule } from './ScaffolderCatalogModule'; +import { startTestBackend } from '@backstage/backend-test-utils'; describe('ScaffolderCatalogModule', () => { - it('should register the extension point', () => { - // TODO(jhaals): clean this up and add test helpers for backend system. - const ext = scaffolderCatalogModule({}); - expect(ext.id).toBe('catalog.scaffolder.module'); - const registry: jest.Mocked = { - registerInit: jest.fn(), - } as any; - ext.register(registry); - - const extensionPoint = { - addProcessor: jest.fn(), - }; - - registry.registerInit.mock.calls[0][0].init({ - catalogProcessingExtensionPoint: extensionPoint, + it('should register the extension point', async () => { + const extensionPoint = { addProcessor: jest.fn() }; + await startTestBackend({ + services: [[catalogProcessingExtensionPoint, extensionPoint]], + registrables: [scaffolderCatalogModule({})], }); + expect(extensionPoint.addProcessor).toHaveBeenCalledWith( new ScaffolderEntitiesProcessor(), ); diff --git a/plugins/scaffolder-backend/src/extension/ScaffolderCatalogModule.ts b/plugins/scaffolder-backend/src/extension/ScaffolderCatalogModule.ts index bdce46a31a..0fb3c2e428 100644 --- a/plugins/scaffolder-backend/src/extension/ScaffolderCatalogModule.ts +++ b/plugins/scaffolder-backend/src/extension/ScaffolderCatalogModule.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { createBackendModule } from '@backstage/backend-plugin-api'; -import { catalogProcessingExtentionPoint } from '@backstage/plugin-catalog-node'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node'; import { ScaffolderEntitiesProcessor } from '../processor'; /** @@ -27,12 +27,10 @@ export const scaffolderCatalogModule = createBackendModule({ register(env) { env.registerInit({ deps: { - catalogProcessingExtensionPoint: catalogProcessingExtentionPoint, + catalog: catalogProcessingExtensionPoint, }, - async init({ catalogProcessingExtensionPoint }) { - catalogProcessingExtensionPoint.addProcessor( - new ScaffolderEntitiesProcessor(), - ); + async init({ catalog }) { + catalog.addProcessor(new ScaffolderEntitiesProcessor()); }, }); },