Add test helpers for new backend system

Co-authored-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: blam <ben@blam.sh>
Co-authored-by: Fredrik Adelöw <freben@gmail.com>
Signed-off-by: Johan Haals <johan.haals@gmail.com>
This commit is contained in:
Johan Haals
2022-08-11 16:19:58 +02:00
parent 3d5ab6cb3c
commit 56e1b4b89c
13 changed files with 208 additions and 26 deletions
+7
View File
@@ -0,0 +1,7 @@
---
'@backstage/plugin-catalog-backend': patch
'@backstage/plugin-catalog-node': patch
'@backstage/plugin-scaffolder-backend': patch
---
Fixed typos in alpha types.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-test-utils': patch
---
Added alpha test helpers for the new experimental backen system.
+2
View File
@@ -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",
+1
View File
@@ -22,4 +22,5 @@
export * from './database';
export * from './msw';
export * from './next';
export * from './util';
@@ -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';
@@ -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');
});
});
@@ -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<TServices extends any[]> {
services: readonly [
...{
[index in keyof TServices]:
| AnyServiceFactory
| [ServiceRef<TServices[index]>, Partial<TServices[index]>];
},
];
}
/** @alpha */
export function createTestBackend<TServices extends any[]>(
options: TestBackendOptions<TServices>,
): 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<TServices extends any[]>(
options: TestBackendOptions<TServices> & {
registrables?: BackendRegistrable[];
},
): Promise<void> {
const { registrables = [], ...otherOptions } = options;
const backend = createTestBackend(otherOptions);
for (const reg of registrables) {
backend.add(reg);
}
return backend.start();
}
@@ -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';
@@ -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,
);
+1 -1
View File
@@ -28,7 +28,7 @@ export interface CatalogProcessingExtensionPoint {
/**
* @alpha
*/
export const catalogProcessingExtentionPoint =
export const catalogProcessingExtensionPoint =
createServiceRef<CatalogProcessingExtensionPoint>({
id: 'catalog.processing',
});
+1 -1
View File
@@ -21,6 +21,6 @@
*/
export type { CatalogProcessingExtensionPoint } from './extensions';
export { catalogProcessingExtentionPoint } from './extensions';
export { catalogProcessingExtensionPoint } from './extensions';
export * from './api';
export * from './processing';
@@ -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<BackendInitRegistry> = {
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(),
);
@@ -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());
},
});
},