@backstage/backend-test-utils 1.6.0-next.2 → 1.7.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +65 -0
- package/dist/alpha/services/ActionsRegistryServiceMock.cjs.js +26 -0
- package/dist/alpha/services/ActionsRegistryServiceMock.cjs.js.map +1 -0
- package/dist/alpha/services/ActionsServiceMock.cjs.js +15 -0
- package/dist/alpha/services/ActionsServiceMock.cjs.js.map +1 -0
- package/dist/alpha/services/MockActionsRegistry.cjs.js +83 -0
- package/dist/alpha/services/MockActionsRegistry.cjs.js.map +1 -0
- package/dist/alpha/services/simpleMock.cjs.js +28 -0
- package/dist/alpha/services/simpleMock.cjs.js.map +1 -0
- package/dist/alpha.cjs.js +18 -0
- package/dist/alpha.cjs.js.map +1 -0
- package/dist/alpha.d.ts +89 -0
- package/dist/index.cjs.js +6 -6
- package/dist/index.d.ts +106 -92
- package/dist/services/MockAuthService.cjs.js.map +1 -0
- package/dist/services/MockEventsService.cjs.js.map +1 -0
- package/dist/services/MockHttpAuthService.cjs.js.map +1 -0
- package/dist/services/MockPermissionsService.cjs.js +25 -0
- package/dist/services/MockPermissionsService.cjs.js.map +1 -0
- package/dist/services/MockRootLoggerService.cjs.js.map +1 -0
- package/dist/services/MockUserInfoService.cjs.js.map +1 -0
- package/dist/{next/services → services}/mockCredentials.cjs.js +36 -14
- package/dist/services/mockCredentials.cjs.js.map +1 -0
- package/dist/{next/services → services}/mockServices.cjs.js +32 -58
- package/dist/services/mockServices.cjs.js.map +1 -0
- package/dist/services/simpleMock.cjs.js +28 -0
- package/dist/services/simpleMock.cjs.js.map +1 -0
- package/dist/util/errorHandler.cjs.js +2 -5
- package/dist/util/errorHandler.cjs.js.map +1 -1
- package/dist/{next/wiring → wiring}/ServiceFactoryTester.cjs.js +1 -1
- package/dist/wiring/ServiceFactoryTester.cjs.js.map +1 -0
- package/dist/{next/wiring → wiring}/TestBackend.cjs.js +9 -1
- package/dist/wiring/TestBackend.cjs.js.map +1 -0
- package/package.json +20 -9
- package/dist/next/services/MockAuthService.cjs.js.map +0 -1
- package/dist/next/services/MockEventsService.cjs.js.map +0 -1
- package/dist/next/services/MockHttpAuthService.cjs.js.map +0 -1
- package/dist/next/services/MockRootLoggerService.cjs.js.map +0 -1
- package/dist/next/services/MockUserInfoService.cjs.js.map +0 -1
- package/dist/next/services/mockCredentials.cjs.js.map +0 -1
- package/dist/next/services/mockServices.cjs.js.map +0 -1
- package/dist/next/wiring/ServiceFactoryTester.cjs.js.map +0 -1
- package/dist/next/wiring/TestBackend.cjs.js.map +0 -1
- /package/dist/{next/services → services}/MockAuthService.cjs.js +0 -0
- /package/dist/{next/services → services}/MockEventsService.cjs.js +0 -0
- /package/dist/{next/services → services}/MockHttpAuthService.cjs.js +0 -0
- /package/dist/{next/services → services}/MockRootLoggerService.cjs.js +0 -0
- /package/dist/{next/services → services}/MockUserInfoService.cjs.js +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,70 @@
|
|
|
1
1
|
# @backstage/backend-test-utils
|
|
2
2
|
|
|
3
|
+
## 1.7.0-next.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- ead925a: Add a standard `toString` on credentials objects
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies
|
|
12
|
+
- @backstage/backend-defaults@0.11.1-next.0
|
|
13
|
+
- @backstage/backend-app-api@1.2.4
|
|
14
|
+
- @backstage/plugin-auth-node@0.6.4
|
|
15
|
+
- @backstage/backend-plugin-api@1.4.0
|
|
16
|
+
- @backstage/plugin-events-node@0.4.12
|
|
17
|
+
- @backstage/config@1.3.2
|
|
18
|
+
- @backstage/errors@1.2.7
|
|
19
|
+
- @backstage/types@1.2.1
|
|
20
|
+
- @backstage/plugin-permission-common@0.9.0
|
|
21
|
+
|
|
22
|
+
## 1.6.0
|
|
23
|
+
|
|
24
|
+
### Minor Changes
|
|
25
|
+
|
|
26
|
+
- 6dfb7be: Added `mockServices.permissions()` that can return actual results.
|
|
27
|
+
- c999c25: Added an `actionsRegistryServiceMock` and `actionsServiceMock` to `/alpha` export for the experimental services.
|
|
28
|
+
|
|
29
|
+
This allows you to write tests for your actions by doing something similar to the following:
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import { actionsRegistryServiceMock } from '@backstage/backend-test-utils/alpha';
|
|
33
|
+
|
|
34
|
+
const mockActionsRegistry = actionsRegistryServiceMock();
|
|
35
|
+
const mockCatalog = catalogServiceMock({
|
|
36
|
+
entities: [
|
|
37
|
+
...
|
|
38
|
+
],
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
createGetCatalogEntityAction({
|
|
42
|
+
catalog: mockCatalog,
|
|
43
|
+
actionsRegistry: mockActionsRegistry,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
await expect(
|
|
47
|
+
mockActionsRegistry.invoke({
|
|
48
|
+
id: 'test:get-catalog-entity',
|
|
49
|
+
input: { name: 'test' },
|
|
50
|
+
}),
|
|
51
|
+
).resolves.toEqual(...)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Patch Changes
|
|
55
|
+
|
|
56
|
+
- 12c1fd4: Make the `user` credentials mock behave more like production
|
|
57
|
+
- Updated dependencies
|
|
58
|
+
- @backstage/backend-defaults@0.11.0
|
|
59
|
+
- @backstage/plugin-auth-node@0.6.4
|
|
60
|
+
- @backstage/backend-app-api@1.2.4
|
|
61
|
+
- @backstage/backend-plugin-api@1.4.0
|
|
62
|
+
- @backstage/config@1.3.2
|
|
63
|
+
- @backstage/errors@1.2.7
|
|
64
|
+
- @backstage/types@1.2.1
|
|
65
|
+
- @backstage/plugin-events-node@0.4.12
|
|
66
|
+
- @backstage/plugin-permission-common@0.9.0
|
|
67
|
+
|
|
3
68
|
## 1.6.0-next.2
|
|
4
69
|
|
|
5
70
|
### Patch Changes
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var mockServices = require('../../services/mockServices.cjs.js');
|
|
4
|
+
require('../../services/mockCredentials.cjs.js');
|
|
5
|
+
var MockActionsRegistry = require('./MockActionsRegistry.cjs.js');
|
|
6
|
+
var simpleMock = require('./simpleMock.cjs.js');
|
|
7
|
+
var alpha$1 = require('@backstage/backend-plugin-api/alpha');
|
|
8
|
+
var alpha = require('@backstage/backend-defaults/alpha');
|
|
9
|
+
|
|
10
|
+
function actionsRegistryServiceMock(options) {
|
|
11
|
+
return MockActionsRegistry.MockActionsRegistry.create({
|
|
12
|
+
logger: options?.logger ?? mockServices.mockServices.logger.mock()
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
((actionsRegistryServiceMock2) => {
|
|
16
|
+
actionsRegistryServiceMock2.factory = () => alpha.actionsRegistryServiceFactory;
|
|
17
|
+
actionsRegistryServiceMock2.mock = simpleMock.simpleMock(
|
|
18
|
+
alpha$1.actionsRegistryServiceRef,
|
|
19
|
+
() => ({
|
|
20
|
+
register: jest.fn()
|
|
21
|
+
})
|
|
22
|
+
);
|
|
23
|
+
})(actionsRegistryServiceMock || (actionsRegistryServiceMock = {}));
|
|
24
|
+
|
|
25
|
+
exports.actionsRegistryServiceMock = actionsRegistryServiceMock;
|
|
26
|
+
//# sourceMappingURL=ActionsRegistryServiceMock.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ActionsRegistryServiceMock.cjs.js","sources":["../../../src/alpha/services/ActionsRegistryServiceMock.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { mockServices } from '../../services';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { MockActionsRegistry } from './MockActionsRegistry';\nimport { simpleMock } from './simpleMock';\nimport {\n ActionsRegistryService,\n actionsRegistryServiceRef,\n} from '@backstage/backend-plugin-api/alpha';\nimport { actionsRegistryServiceFactory } from '@backstage/backend-defaults/alpha';\n\n/**\n * @alpha\n */\nexport function actionsRegistryServiceMock(options?: {\n logger: LoggerService;\n}): MockActionsRegistry {\n return MockActionsRegistry.create({\n logger: options?.logger ?? mockServices.logger.mock(),\n });\n}\n\n/**\n * @alpha\n */\nexport namespace actionsRegistryServiceMock {\n export const factory = () => actionsRegistryServiceFactory;\n\n export const mock = simpleMock<ActionsRegistryService>(\n actionsRegistryServiceRef,\n () => ({\n register: jest.fn(),\n }),\n );\n}\n"],"names":["MockActionsRegistry","mockServices","actionsRegistryServiceMock","actionsRegistryServiceFactory","simpleMock","actionsRegistryServiceRef"],"mappings":";;;;;;;;;AA4BO,SAAS,2BAA2B,OAEnB,EAAA;AACtB,EAAA,OAAOA,wCAAoB,MAAO,CAAA;AAAA,IAChC,MAAQ,EAAA,OAAA,EAAS,MAAU,IAAAC,yBAAA,CAAa,OAAO,IAAK;AAAA,GACrD,CAAA;AACH;AAAA,CAKO,CAAUC,2BAAV,KAAA;AACE,EAAMA,2BAAAA,CAAA,UAAU,MAAMC,mCAAA;AAEtB,EAAMD,4BAAA,IAAO,GAAAE,qBAAA;AAAA,IAClBC,iCAAA;AAAA,IACA,OAAO;AAAA,MACL,QAAA,EAAU,KAAK,EAAG;AAAA,KACpB;AAAA,GACF;AAAA,CARe,EAAA,0BAAA,KAAA,0BAAA,GAAA,EAAA,CAAA,CAAA;;;;"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var simpleMock = require('./simpleMock.cjs.js');
|
|
4
|
+
var alpha$1 = require('@backstage/backend-plugin-api/alpha');
|
|
5
|
+
var alpha = require('@backstage/backend-defaults/alpha');
|
|
6
|
+
|
|
7
|
+
exports.actionsServiceMock = void 0;
|
|
8
|
+
((actionsServiceMock2) => {
|
|
9
|
+
actionsServiceMock2.factory = () => alpha.actionsServiceFactory;
|
|
10
|
+
actionsServiceMock2.mock = simpleMock.simpleMock(alpha$1.actionsServiceRef, () => ({
|
|
11
|
+
invoke: jest.fn(),
|
|
12
|
+
list: jest.fn()
|
|
13
|
+
}));
|
|
14
|
+
})(exports.actionsServiceMock || (exports.actionsServiceMock = {}));
|
|
15
|
+
//# sourceMappingURL=ActionsServiceMock.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ActionsServiceMock.cjs.js","sources":["../../../src/alpha/services/ActionsServiceMock.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { simpleMock } from './simpleMock';\nimport {\n ActionsService,\n actionsServiceRef,\n} from '@backstage/backend-plugin-api/alpha';\nimport { actionsServiceFactory } from '@backstage/backend-defaults/alpha';\n\n/**\n * @alpha\n */\nexport namespace actionsServiceMock {\n export const factory = () => actionsServiceFactory;\n\n export const mock = simpleMock<ActionsService>(actionsServiceRef, () => ({\n invoke: jest.fn(),\n list: jest.fn(),\n }));\n}\n"],"names":["actionsServiceMock","actionsServiceFactory","simpleMock","actionsServiceRef"],"mappings":";;;;;;AA0BiBA;AAAA,CAAV,CAAUA,mBAAV,KAAA;AACE,EAAMA,mBAAAA,CAAA,UAAU,MAAMC,2BAAA;AAEtB,EAAMD,mBAAA,CAAA,IAAA,GAAOE,qBAA2B,CAAAC,yBAAA,EAAmB,OAAO;AAAA,IACvE,MAAA,EAAQ,KAAK,EAAG,EAAA;AAAA,IAChB,IAAA,EAAM,KAAK,EAAG;AAAA,GACd,CAAA,CAAA;AAAA,CANa,EAAAH,0BAAA,KAAAA,0BAAA,GAAA,EAAA,CAAA,CAAA;;"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var errors = require('@backstage/errors');
|
|
4
|
+
var zod = require('zod');
|
|
5
|
+
var zodToJsonSchema = require('zod-to-json-schema');
|
|
6
|
+
require('../../services/mockServices.cjs.js');
|
|
7
|
+
var mockCredentials = require('../../services/mockCredentials.cjs.js');
|
|
8
|
+
|
|
9
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
10
|
+
|
|
11
|
+
var zodToJsonSchema__default = /*#__PURE__*/_interopDefaultCompat(zodToJsonSchema);
|
|
12
|
+
|
|
13
|
+
class MockActionsRegistry {
|
|
14
|
+
constructor(logger) {
|
|
15
|
+
this.logger = logger;
|
|
16
|
+
}
|
|
17
|
+
static create(opts) {
|
|
18
|
+
return new MockActionsRegistry(opts.logger);
|
|
19
|
+
}
|
|
20
|
+
actions = /* @__PURE__ */ new Map();
|
|
21
|
+
async list() {
|
|
22
|
+
return {
|
|
23
|
+
actions: Array.from(this.actions.entries()).map(([id, action]) => ({
|
|
24
|
+
id,
|
|
25
|
+
name: action.name,
|
|
26
|
+
title: action.title,
|
|
27
|
+
description: action.description,
|
|
28
|
+
attributes: {
|
|
29
|
+
destructive: action.attributes?.destructive ?? true,
|
|
30
|
+
idempotent: action.attributes?.idempotent ?? false,
|
|
31
|
+
readOnly: action.attributes?.readOnly ?? false
|
|
32
|
+
},
|
|
33
|
+
schema: {
|
|
34
|
+
input: action.schema?.input ? zodToJsonSchema__default.default(action.schema.input(zod.z)) : zodToJsonSchema__default.default(zod.z.object({})),
|
|
35
|
+
output: action.schema?.output ? zodToJsonSchema__default.default(action.schema.output(zod.z)) : zodToJsonSchema__default.default(zod.z.object({}))
|
|
36
|
+
}
|
|
37
|
+
}))
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
async invoke(opts) {
|
|
41
|
+
const action = this.actions.get(opts.id);
|
|
42
|
+
if (!action) {
|
|
43
|
+
const availableActionIds = Array.from(this.actions.keys()).join(", ");
|
|
44
|
+
throw new errors.NotFoundError(
|
|
45
|
+
`Action "${opts.id}" not found, available actions: ${availableActionIds ? `"${availableActionIds}"` : "none"}`
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
const input = action.schema?.input ? action.schema.input(zod.z).safeParse(opts.input) : { success: true, data: void 0 };
|
|
49
|
+
if (!input.success) {
|
|
50
|
+
throw new errors.InputError(`Invalid input to action "${opts.id}"`, input.error);
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
const result = await action.action({
|
|
54
|
+
input: input.data,
|
|
55
|
+
credentials: opts.credentials ?? mockCredentials.mockCredentials.none(),
|
|
56
|
+
logger: this.logger
|
|
57
|
+
});
|
|
58
|
+
const output = action.schema?.output ? action.schema.output(zod.z).safeParse(result?.output) : { success: true, data: result?.output };
|
|
59
|
+
if (!output.success) {
|
|
60
|
+
throw new errors.InputError(
|
|
61
|
+
`Invalid output from action "${opts.id}"`,
|
|
62
|
+
output.error
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
return { output: output.data };
|
|
66
|
+
} catch (error) {
|
|
67
|
+
throw new errors.ForwardedError(
|
|
68
|
+
`Failed execution of action "${opts.id}"`,
|
|
69
|
+
error
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
register(options) {
|
|
74
|
+
const id = `test:${options.name}`;
|
|
75
|
+
if (this.actions.has(id)) {
|
|
76
|
+
throw new Error(`Action with id "${id}" is already registered`);
|
|
77
|
+
}
|
|
78
|
+
this.actions.set(id, options);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
exports.MockActionsRegistry = MockActionsRegistry;
|
|
83
|
+
//# sourceMappingURL=MockActionsRegistry.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MockActionsRegistry.cjs.js","sources":["../../../src/alpha/services/MockActionsRegistry.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n BackstageCredentials,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport { ForwardedError, InputError, NotFoundError } from '@backstage/errors';\nimport { JsonObject, JsonValue } from '@backstage/types';\nimport { z, AnyZodObject } from 'zod';\nimport zodToJsonSchema from 'zod-to-json-schema';\nimport { mockCredentials } from '../../services';\nimport {\n ActionsRegistryActionOptions,\n ActionsRegistryService,\n ActionsService,\n ActionsServiceAction,\n} from '@backstage/backend-plugin-api/alpha';\n\n/**\n * A mock implementation of the ActionsRegistryService and ActionsService that can be used in tests.\n *\n * This is useful for testing actions that are registered with the ActionsRegistryService and ActionsService.\n *\n * The plugin ID is hardcoded to `testing` in the mock implementation.\n *\n * @example\n * ```ts\n * const actionsRegistry = mockServices.actionsRegistry();\n *\n * actionsRegistry.register({\n * name: 'test',\n * title: 'Test',\n * description: 'Test',\n * schema: {\n * input: z.object({ name: z.string() }),\n * output: z.object({ name: z.string() }),\n * },\n * action: async ({ input }) => ({ output: { name: input.name } }),\n * });\n *\n *\n * const result = await actionsRegistry.invoke({\n * id: 'testing:test',\n * input: { name: 'test' },\n * });\n *\n * expect(result).toEqual({ output: { name: 'test' } });\n * ```\n *\n * @alpha\n */\nexport class MockActionsRegistry\n implements ActionsRegistryService, ActionsService\n{\n private constructor(private readonly logger: LoggerService) {}\n\n static create(opts: { logger: LoggerService }) {\n return new MockActionsRegistry(opts.logger);\n }\n\n readonly actions: Map<string, ActionsRegistryActionOptions<any, any>> =\n new Map();\n\n async list(): Promise<{ actions: ActionsServiceAction[] }> {\n return {\n actions: Array.from(this.actions.entries()).map(([id, action]) => ({\n id,\n name: action.name,\n title: action.title,\n description: action.description,\n attributes: {\n destructive: action.attributes?.destructive ?? true,\n idempotent: action.attributes?.idempotent ?? false,\n readOnly: action.attributes?.readOnly ?? false,\n },\n schema: {\n input: action.schema?.input\n ? zodToJsonSchema(action.schema.input(z))\n : zodToJsonSchema(z.object({})),\n output: action.schema?.output\n ? zodToJsonSchema(action.schema.output(z))\n : zodToJsonSchema(z.object({})),\n } as ActionsServiceAction['schema'],\n })),\n };\n }\n\n async invoke(opts: {\n id: string;\n input?: JsonObject;\n credentials?: BackstageCredentials;\n }): Promise<{ output: JsonValue }> {\n const action = this.actions.get(opts.id);\n\n if (!action) {\n const availableActionIds = Array.from(this.actions.keys()).join(', ');\n throw new NotFoundError(\n `Action \"${opts.id}\" not found, available actions: ${\n availableActionIds ? `\"${availableActionIds}\"` : 'none'\n }`,\n );\n }\n\n const input = action.schema?.input\n ? action.schema.input(z).safeParse(opts.input)\n : ({ success: true, data: undefined } as const);\n\n if (!input.success) {\n throw new InputError(`Invalid input to action \"${opts.id}\"`, input.error);\n }\n\n try {\n const result = await action.action({\n input: input.data,\n credentials: opts.credentials ?? mockCredentials.none(),\n logger: this.logger,\n });\n\n const output = action.schema?.output\n ? action.schema.output(z).safeParse(result?.output)\n : ({ success: true, data: result?.output } as const);\n\n if (!output.success) {\n throw new InputError(\n `Invalid output from action \"${opts.id}\"`,\n output.error,\n );\n }\n\n return { output: output.data };\n } catch (error) {\n throw new ForwardedError(\n `Failed execution of action \"${opts.id}\"`,\n error,\n );\n }\n }\n\n register<\n TInputSchema extends AnyZodObject,\n TOutputSchema extends AnyZodObject,\n >(options: ActionsRegistryActionOptions<TInputSchema, TOutputSchema>): void {\n // hardcode test: prefix similar to how the default actions registry does it\n // and other places around the testing ecosystem:\n // https://github.com/backstage/backstage/blob/a9219496d5c073aaa0b8caf32ece10455cf65e61/packages/backend-test-utils/src/next/services/mockServices.ts#L321\n // https://github.com/backstage/backstage/blob/861f162b4a39117b824669d67a951ed1db142e3d/packages/backend-test-utils/src/next/wiring/ServiceFactoryTester.ts#L99\n const id = `test:${options.name}`;\n\n if (this.actions.has(id)) {\n throw new Error(`Action with id \"${id}\" is already registered`);\n }\n\n this.actions.set(id, options);\n }\n}\n"],"names":["zodToJsonSchema","z","NotFoundError","InputError","mockCredentials","ForwardedError"],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var backendPluginApi = require('@backstage/backend-plugin-api');
|
|
4
|
+
|
|
5
|
+
function simpleMock(ref, mockFactory) {
|
|
6
|
+
return (partialImpl) => {
|
|
7
|
+
const mock = mockFactory();
|
|
8
|
+
if (partialImpl) {
|
|
9
|
+
for (const [key, impl] of Object.entries(partialImpl)) {
|
|
10
|
+
if (typeof impl === "function") {
|
|
11
|
+
mock[key].mockImplementation(impl);
|
|
12
|
+
} else {
|
|
13
|
+
mock[key] = impl;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return Object.assign(mock, {
|
|
18
|
+
factory: backendPluginApi.createServiceFactory({
|
|
19
|
+
service: ref,
|
|
20
|
+
deps: {},
|
|
21
|
+
factory: () => mock
|
|
22
|
+
})
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
exports.simpleMock = simpleMock;
|
|
28
|
+
//# sourceMappingURL=simpleMock.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simpleMock.cjs.js","sources":["../../../src/alpha/services/simpleMock.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n createServiceFactory,\n ServiceFactory,\n ServiceRef,\n} from '@backstage/backend-plugin-api';\n\n/** @alpha */\nexport type ServiceMock<TService> = {\n factory: ServiceFactory<TService>;\n} & {\n [Key in keyof TService]: TService[Key] extends (\n ...args: infer Args\n ) => infer Return\n ? TService[Key] & jest.MockInstance<Return, Args>\n : TService[Key];\n};\n\n/** @internal */\nexport function simpleMock<TService>(\n ref: ServiceRef<TService, any>,\n mockFactory: () => jest.Mocked<TService>,\n): (partialImpl?: Partial<TService>) => ServiceMock<TService> {\n return partialImpl => {\n const mock = mockFactory();\n if (partialImpl) {\n for (const [key, impl] of Object.entries(partialImpl)) {\n if (typeof impl === 'function') {\n (mock as any)[key].mockImplementation(impl);\n } else {\n (mock as any)[key] = impl;\n }\n }\n }\n return Object.assign(mock, {\n factory: createServiceFactory({\n service: ref,\n deps: {},\n factory: () => mock,\n }),\n }) as ServiceMock<TService>;\n };\n}\n"],"names":["createServiceFactory"],"mappings":";;;;AAiCgB,SAAA,UAAA,CACd,KACA,WAC4D,EAAA;AAC5D,EAAA,OAAO,CAAe,WAAA,KAAA;AACpB,IAAA,MAAM,OAAO,WAAY,EAAA;AACzB,IAAA,IAAI,WAAa,EAAA;AACf,MAAA,KAAA,MAAW,CAAC,GAAK,EAAA,IAAI,KAAK,MAAO,CAAA,OAAA,CAAQ,WAAW,CAAG,EAAA;AACrD,QAAI,IAAA,OAAO,SAAS,UAAY,EAAA;AAC9B,UAAC,IAAa,CAAA,GAAG,CAAE,CAAA,kBAAA,CAAmB,IAAI,CAAA;AAAA,SACrC,MAAA;AACL,UAAC,IAAA,CAAa,GAAG,CAAI,GAAA,IAAA;AAAA;AACvB;AACF;AAEF,IAAO,OAAA,MAAA,CAAO,OAAO,IAAM,EAAA;AAAA,MACzB,SAASA,qCAAqB,CAAA;AAAA,QAC5B,OAAS,EAAA,GAAA;AAAA,QACT,MAAM,EAAC;AAAA,QACP,SAAS,MAAM;AAAA,OAChB;AAAA,KACF,CAAA;AAAA,GACH;AACF;;;;"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var ActionsRegistryServiceMock = require('./alpha/services/ActionsRegistryServiceMock.cjs.js');
|
|
4
|
+
var MockActionsRegistry = require('./alpha/services/MockActionsRegistry.cjs.js');
|
|
5
|
+
var ActionsServiceMock = require('./alpha/services/ActionsServiceMock.cjs.js');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
Object.defineProperty(exports, "actionsRegistryServiceMock", {
|
|
10
|
+
enumerable: true,
|
|
11
|
+
get: function () { return ActionsRegistryServiceMock.actionsRegistryServiceMock; }
|
|
12
|
+
});
|
|
13
|
+
exports.MockActionsRegistry = MockActionsRegistry.MockActionsRegistry;
|
|
14
|
+
Object.defineProperty(exports, "actionsServiceMock", {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
get: function () { return ActionsServiceMock.actionsServiceMock; }
|
|
17
|
+
});
|
|
18
|
+
//# sourceMappingURL=alpha.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alpha.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;"}
|
package/dist/alpha.d.ts
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
|
|
2
|
+
import { ServiceFactory, LoggerService, BackstageCredentials } from '@backstage/backend-plugin-api';
|
|
3
|
+
import { JsonObject, JsonValue } from '@backstage/types';
|
|
4
|
+
import { AnyZodObject } from 'zod';
|
|
5
|
+
import { ActionsRegistryService, ActionsService, ActionsRegistryActionOptions, ActionsServiceAction } from '@backstage/backend-plugin-api/alpha';
|
|
6
|
+
|
|
7
|
+
/** @alpha */
|
|
8
|
+
type ServiceMock<TService> = {
|
|
9
|
+
factory: ServiceFactory<TService>;
|
|
10
|
+
} & {
|
|
11
|
+
[Key in keyof TService]: TService[Key] extends (...args: infer Args) => infer Return ? TService[Key] & jest.MockInstance<Return, Args> : TService[Key];
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A mock implementation of the ActionsRegistryService and ActionsService that can be used in tests.
|
|
16
|
+
*
|
|
17
|
+
* This is useful for testing actions that are registered with the ActionsRegistryService and ActionsService.
|
|
18
|
+
*
|
|
19
|
+
* The plugin ID is hardcoded to `testing` in the mock implementation.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* const actionsRegistry = mockServices.actionsRegistry();
|
|
24
|
+
*
|
|
25
|
+
* actionsRegistry.register({
|
|
26
|
+
* name: 'test',
|
|
27
|
+
* title: 'Test',
|
|
28
|
+
* description: 'Test',
|
|
29
|
+
* schema: {
|
|
30
|
+
* input: z.object({ name: z.string() }),
|
|
31
|
+
* output: z.object({ name: z.string() }),
|
|
32
|
+
* },
|
|
33
|
+
* action: async ({ input }) => ({ output: { name: input.name } }),
|
|
34
|
+
* });
|
|
35
|
+
*
|
|
36
|
+
*
|
|
37
|
+
* const result = await actionsRegistry.invoke({
|
|
38
|
+
* id: 'testing:test',
|
|
39
|
+
* input: { name: 'test' },
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* expect(result).toEqual({ output: { name: 'test' } });
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* @alpha
|
|
46
|
+
*/
|
|
47
|
+
declare class MockActionsRegistry implements ActionsRegistryService, ActionsService {
|
|
48
|
+
private readonly logger;
|
|
49
|
+
private constructor();
|
|
50
|
+
static create(opts: {
|
|
51
|
+
logger: LoggerService;
|
|
52
|
+
}): MockActionsRegistry;
|
|
53
|
+
readonly actions: Map<string, ActionsRegistryActionOptions<any, any>>;
|
|
54
|
+
list(): Promise<{
|
|
55
|
+
actions: ActionsServiceAction[];
|
|
56
|
+
}>;
|
|
57
|
+
invoke(opts: {
|
|
58
|
+
id: string;
|
|
59
|
+
input?: JsonObject;
|
|
60
|
+
credentials?: BackstageCredentials;
|
|
61
|
+
}): Promise<{
|
|
62
|
+
output: JsonValue;
|
|
63
|
+
}>;
|
|
64
|
+
register<TInputSchema extends AnyZodObject, TOutputSchema extends AnyZodObject>(options: ActionsRegistryActionOptions<TInputSchema, TOutputSchema>): void;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @alpha
|
|
69
|
+
*/
|
|
70
|
+
declare function actionsRegistryServiceMock(options?: {
|
|
71
|
+
logger: LoggerService;
|
|
72
|
+
}): MockActionsRegistry;
|
|
73
|
+
/**
|
|
74
|
+
* @alpha
|
|
75
|
+
*/
|
|
76
|
+
declare namespace actionsRegistryServiceMock {
|
|
77
|
+
const factory: () => _backstage_backend_plugin_api.ServiceFactory<ActionsRegistryService, "plugin", "singleton">;
|
|
78
|
+
const mock: (partialImpl?: Partial<ActionsRegistryService> | undefined) => ServiceMock<ActionsRegistryService>;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @alpha
|
|
83
|
+
*/
|
|
84
|
+
declare namespace actionsServiceMock {
|
|
85
|
+
const factory: () => _backstage_backend_plugin_api.ServiceFactory<ActionsService, "plugin", "singleton">;
|
|
86
|
+
const mock: (partialImpl?: Partial<ActionsService> | undefined) => ServiceMock<ActionsService>;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export { MockActionsRegistry, type ServiceMock, actionsRegistryServiceMock, actionsServiceMock };
|
package/dist/index.cjs.js
CHANGED
|
@@ -4,10 +4,10 @@ var TestCaches = require('./cache/TestCaches.cjs.js');
|
|
|
4
4
|
var TestDatabases = require('./database/TestDatabases.cjs.js');
|
|
5
5
|
var registerMswTestHooks = require('./msw/registerMswTestHooks.cjs.js');
|
|
6
6
|
var MockDirectory = require('./filesystem/MockDirectory.cjs.js');
|
|
7
|
-
var
|
|
8
|
-
var
|
|
9
|
-
var
|
|
10
|
-
var
|
|
7
|
+
var mockServices = require('./services/mockServices.cjs.js');
|
|
8
|
+
var mockCredentials = require('./services/mockCredentials.cjs.js');
|
|
9
|
+
var ServiceFactoryTester = require('./wiring/ServiceFactoryTester.cjs.js');
|
|
10
|
+
var TestBackend = require('./wiring/TestBackend.cjs.js');
|
|
11
11
|
var errorHandler = require('./util/errorHandler.cjs.js');
|
|
12
12
|
|
|
13
13
|
|
|
@@ -16,8 +16,6 @@ exports.TestCaches = TestCaches.TestCaches;
|
|
|
16
16
|
exports.TestDatabases = TestDatabases.TestDatabases;
|
|
17
17
|
exports.registerMswTestHooks = registerMswTestHooks.registerMswTestHooks;
|
|
18
18
|
exports.createMockDirectory = MockDirectory.createMockDirectory;
|
|
19
|
-
exports.ServiceFactoryTester = ServiceFactoryTester.ServiceFactoryTester;
|
|
20
|
-
exports.startTestBackend = TestBackend.startTestBackend;
|
|
21
19
|
Object.defineProperty(exports, "mockServices", {
|
|
22
20
|
enumerable: true,
|
|
23
21
|
get: function () { return mockServices.mockServices; }
|
|
@@ -26,5 +24,7 @@ Object.defineProperty(exports, "mockCredentials", {
|
|
|
26
24
|
enumerable: true,
|
|
27
25
|
get: function () { return mockCredentials.mockCredentials; }
|
|
28
26
|
});
|
|
27
|
+
exports.ServiceFactoryTester = ServiceFactoryTester.ServiceFactoryTester;
|
|
28
|
+
exports.startTestBackend = TestBackend.startTestBackend;
|
|
29
29
|
exports.mockErrorHandler = errorHandler.mockErrorHandler;
|
|
30
30
|
//# sourceMappingURL=index.cjs.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import Keyv from 'keyv';
|
|
2
2
|
import { Knex } from 'knex';
|
|
3
3
|
import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
|
|
4
|
-
import { ServiceFactory,
|
|
5
|
-
import { Backend } from '@backstage/backend-app-api';
|
|
6
|
-
import { ExtendedHttpServer } from '@backstage/backend-defaults/rootHttpRouter';
|
|
4
|
+
import { ServiceFactory, RootConfigService, LoggerService, AuthService, DiscoveryService, BackstageCredentials, HttpAuthService, BackstageUserInfo, UserInfoService, DatabaseService, PermissionsService, BackstageNonePrincipal, BackstageUserPrincipal, BackstagePrincipalAccessRestrictions, BackstageServicePrincipal, ServiceRef, ExtensionPoint, BackendFeature } from '@backstage/backend-plugin-api';
|
|
7
5
|
import { EventsService } from '@backstage/plugin-events-node';
|
|
6
|
+
import { AuthorizeResult } from '@backstage/plugin-permission-common';
|
|
8
7
|
import { JsonObject } from '@backstage/types';
|
|
8
|
+
import { Backend } from '@backstage/backend-app-api';
|
|
9
|
+
import { ExtendedHttpServer } from '@backstage/backend-defaults/rootHttpRouter';
|
|
9
10
|
import * as express from 'express';
|
|
10
11
|
import * as qs from 'qs';
|
|
11
12
|
import * as express_serve_static_core from 'express-serve-static-core';
|
|
@@ -315,91 +316,13 @@ interface CreateMockDirectoryOptions {
|
|
|
315
316
|
*/
|
|
316
317
|
declare function createMockDirectory(options?: CreateMockDirectoryOptions): MockDirectory;
|
|
317
318
|
|
|
318
|
-
/**
|
|
319
|
-
* Options for {@link ServiceFactoryTester}.
|
|
320
|
-
* @public
|
|
321
|
-
*/
|
|
322
|
-
interface ServiceFactoryTesterOptions {
|
|
323
|
-
/**
|
|
324
|
-
* Additional service factories to make available as dependencies.
|
|
325
|
-
*
|
|
326
|
-
* @remarks
|
|
327
|
-
*
|
|
328
|
-
* If a service factory is provided for a service that already has a default
|
|
329
|
-
* implementation, the provided factory will override the default.
|
|
330
|
-
*/
|
|
331
|
-
dependencies?: Array<ServiceFactory>;
|
|
332
|
-
}
|
|
333
|
-
/**
|
|
334
|
-
* A utility to help test service factories in isolation.
|
|
335
|
-
*
|
|
336
|
-
* @public
|
|
337
|
-
*/
|
|
338
|
-
declare class ServiceFactoryTester<TService, TScope extends 'root' | 'plugin', TInstances extends 'singleton' | 'multiton' = 'singleton'> {
|
|
339
|
-
#private;
|
|
340
|
-
/**
|
|
341
|
-
* Creates a new {@link ServiceFactoryTester} used to test the provided subject.
|
|
342
|
-
*
|
|
343
|
-
* @param subject - The service factory to test.
|
|
344
|
-
* @param options - Additional options
|
|
345
|
-
* @returns A new tester instance for the provided subject.
|
|
346
|
-
*/
|
|
347
|
-
static from<TService, TScope extends 'root' | 'plugin', TInstances extends 'singleton' | 'multiton' = 'singleton'>(subject: ServiceFactory<TService, TScope, TInstances>, options?: ServiceFactoryTesterOptions): ServiceFactoryTester<TService, TScope, TInstances>;
|
|
348
|
-
private constructor();
|
|
349
|
-
/**
|
|
350
|
-
* Returns the service instance for the subject.
|
|
351
|
-
*
|
|
352
|
-
* @remarks
|
|
353
|
-
*
|
|
354
|
-
* If the subject is a plugin scoped service factory a plugin ID
|
|
355
|
-
* can be provided to instantiate the service for a specific plugin.
|
|
356
|
-
*
|
|
357
|
-
* By default the plugin ID 'test' is used.
|
|
358
|
-
*/
|
|
359
|
-
getSubject(...args: 'root' extends TScope ? [] : [pluginId?: string]): Promise<TInstances extends 'multiton' ? TService[] : TService>;
|
|
360
|
-
/**
|
|
361
|
-
* Return the service instance for any of the provided dependencies or built-in services.
|
|
362
|
-
*
|
|
363
|
-
* @remarks
|
|
364
|
-
*
|
|
365
|
-
* A plugin ID can optionally be provided for plugin scoped services, otherwise the plugin ID 'test' is used.
|
|
366
|
-
*/
|
|
367
|
-
getService<TGetService, TGetScope extends 'root' | 'plugin', TGetInstances extends 'singleton' | 'multiton' = 'singleton'>(service: ServiceRef<TGetService, TGetScope, TGetInstances>, ...args: 'root' extends TGetScope ? [] : [pluginId?: string]): Promise<TGetInstances extends 'multiton' ? TGetService[] : TGetService>;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
/** @public */
|
|
371
|
-
interface TestBackendOptions<TExtensionPoints extends any[]> {
|
|
372
|
-
extensionPoints?: readonly [
|
|
373
|
-
...{
|
|
374
|
-
[index in keyof TExtensionPoints]: [
|
|
375
|
-
ExtensionPoint<TExtensionPoints[index]>,
|
|
376
|
-
Partial<TExtensionPoints[index]>
|
|
377
|
-
];
|
|
378
|
-
}
|
|
379
|
-
];
|
|
380
|
-
features?: Array<BackendFeature | Promise<{
|
|
381
|
-
default: BackendFeature;
|
|
382
|
-
}>>;
|
|
383
|
-
}
|
|
384
|
-
/** @public */
|
|
385
|
-
interface TestBackend extends Backend {
|
|
386
|
-
/**
|
|
387
|
-
* Provides access to the underling HTTP server for use with utilities
|
|
388
|
-
* such as `supertest`.
|
|
389
|
-
*
|
|
390
|
-
* If the root http router service has been replaced, this will throw an error.
|
|
391
|
-
*/
|
|
392
|
-
readonly server: ExtendedHttpServer;
|
|
393
|
-
}
|
|
394
|
-
/** @public */
|
|
395
|
-
declare function startTestBackend<TExtensionPoints extends any[]>(options: TestBackendOptions<TExtensionPoints>): Promise<TestBackend>;
|
|
396
|
-
|
|
397
319
|
/** @public */
|
|
398
320
|
type ServiceMock<TService> = {
|
|
399
321
|
factory: ServiceFactory<TService>;
|
|
400
322
|
} & {
|
|
401
323
|
[Key in keyof TService]: TService[Key] extends (...args: infer Args) => infer Return ? TService[Key] & jest.MockInstance<Return, Args> : TService[Key];
|
|
402
324
|
};
|
|
325
|
+
|
|
403
326
|
/**
|
|
404
327
|
* Mock implementations of the core services, to be used in tests.
|
|
405
328
|
*
|
|
@@ -582,9 +505,29 @@ declare namespace mockServices {
|
|
|
582
505
|
const factory: () => ServiceFactory<LoggerService, "plugin", "singleton">;
|
|
583
506
|
const mock: (partialImpl?: Partial<LoggerService> | undefined) => ServiceMock<LoggerService>;
|
|
584
507
|
}
|
|
508
|
+
/**
|
|
509
|
+
* Creates a functional mock implementation of the
|
|
510
|
+
* {@link @backstage/backend-plugin-api#PermissionsService}.
|
|
511
|
+
*/
|
|
512
|
+
function permissions(options?: {
|
|
513
|
+
result: AuthorizeResult.ALLOW | AuthorizeResult.DENY;
|
|
514
|
+
}): PermissionsService;
|
|
585
515
|
namespace permissions {
|
|
586
|
-
|
|
587
|
-
|
|
516
|
+
/**
|
|
517
|
+
* Creates a mock factory for the
|
|
518
|
+
* {@link @backstage/backend-plugin-api#coreServices.permissions}. Just
|
|
519
|
+
* returns the given `result` if you supply one. Otherwise, it returns the
|
|
520
|
+
* regular default permissions factory.
|
|
521
|
+
*/
|
|
522
|
+
const factory: (options?: {
|
|
523
|
+
result: AuthorizeResult.ALLOW | AuthorizeResult.DENY;
|
|
524
|
+
}) => ServiceFactory<PermissionsService, "plugin", "singleton">;
|
|
525
|
+
/**
|
|
526
|
+
* Creates a mock of the
|
|
527
|
+
* {@link @backstage/backend-plugin-api#coreServices.permissions},
|
|
528
|
+
* optionally with some given method implementations.
|
|
529
|
+
*/
|
|
530
|
+
const mock: (partialImpl?: Partial<PermissionsService> | undefined) => ServiceMock<PermissionsService>;
|
|
588
531
|
}
|
|
589
532
|
namespace permissionsRegistry {
|
|
590
533
|
const factory: () => ServiceFactory<_backstage_backend_plugin_api.PermissionsRegistryService, "plugin", "singleton">;
|
|
@@ -602,14 +545,6 @@ declare namespace mockServices {
|
|
|
602
545
|
const factory: () => ServiceFactory<_backstage_backend_plugin_api.UrlReaderService, "plugin", "singleton">;
|
|
603
546
|
const mock: (partialImpl?: Partial<_backstage_backend_plugin_api.UrlReaderService> | undefined) => ServiceMock<_backstage_backend_plugin_api.UrlReaderService>;
|
|
604
547
|
}
|
|
605
|
-
namespace actions {
|
|
606
|
-
const factory: () => ServiceFactory<_backstage_backend_plugin_api.ActionsService, "plugin", "singleton">;
|
|
607
|
-
const mock: (partialImpl?: Partial<_backstage_backend_plugin_api.ActionsService> | undefined) => ServiceMock<_backstage_backend_plugin_api.ActionsService>;
|
|
608
|
-
}
|
|
609
|
-
namespace actionsRegistry {
|
|
610
|
-
const factory: () => ServiceFactory<_backstage_backend_plugin_api.ActionsRegistryService, "plugin", "singleton">;
|
|
611
|
-
const mock: (partialImpl?: Partial<_backstage_backend_plugin_api.ActionsRegistryService> | undefined) => ServiceMock<_backstage_backend_plugin_api.ActionsRegistryService>;
|
|
612
|
-
}
|
|
613
548
|
/**
|
|
614
549
|
* Creates a functional mock implementation of the
|
|
615
550
|
* {@link @backstage/backend-events-node#eventsServiceRef}.
|
|
@@ -745,6 +680,85 @@ declare namespace mockCredentials {
|
|
|
745
680
|
}
|
|
746
681
|
}
|
|
747
682
|
|
|
683
|
+
/**
|
|
684
|
+
* Options for {@link ServiceFactoryTester}.
|
|
685
|
+
* @public
|
|
686
|
+
*/
|
|
687
|
+
interface ServiceFactoryTesterOptions {
|
|
688
|
+
/**
|
|
689
|
+
* Additional service factories to make available as dependencies.
|
|
690
|
+
*
|
|
691
|
+
* @remarks
|
|
692
|
+
*
|
|
693
|
+
* If a service factory is provided for a service that already has a default
|
|
694
|
+
* implementation, the provided factory will override the default.
|
|
695
|
+
*/
|
|
696
|
+
dependencies?: Array<ServiceFactory>;
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* A utility to help test service factories in isolation.
|
|
700
|
+
*
|
|
701
|
+
* @public
|
|
702
|
+
*/
|
|
703
|
+
declare class ServiceFactoryTester<TService, TScope extends 'root' | 'plugin', TInstances extends 'singleton' | 'multiton' = 'singleton'> {
|
|
704
|
+
#private;
|
|
705
|
+
/**
|
|
706
|
+
* Creates a new {@link ServiceFactoryTester} used to test the provided subject.
|
|
707
|
+
*
|
|
708
|
+
* @param subject - The service factory to test.
|
|
709
|
+
* @param options - Additional options
|
|
710
|
+
* @returns A new tester instance for the provided subject.
|
|
711
|
+
*/
|
|
712
|
+
static from<TService, TScope extends 'root' | 'plugin', TInstances extends 'singleton' | 'multiton' = 'singleton'>(subject: ServiceFactory<TService, TScope, TInstances>, options?: ServiceFactoryTesterOptions): ServiceFactoryTester<TService, TScope, TInstances>;
|
|
713
|
+
private constructor();
|
|
714
|
+
/**
|
|
715
|
+
* Returns the service instance for the subject.
|
|
716
|
+
*
|
|
717
|
+
* @remarks
|
|
718
|
+
*
|
|
719
|
+
* If the subject is a plugin scoped service factory a plugin ID
|
|
720
|
+
* can be provided to instantiate the service for a specific plugin.
|
|
721
|
+
*
|
|
722
|
+
* By default the plugin ID 'test' is used.
|
|
723
|
+
*/
|
|
724
|
+
getSubject(...args: 'root' extends TScope ? [] : [pluginId?: string]): Promise<TInstances extends 'multiton' ? TService[] : TService>;
|
|
725
|
+
/**
|
|
726
|
+
* Return the service instance for any of the provided dependencies or built-in services.
|
|
727
|
+
*
|
|
728
|
+
* @remarks
|
|
729
|
+
*
|
|
730
|
+
* A plugin ID can optionally be provided for plugin scoped services, otherwise the plugin ID 'test' is used.
|
|
731
|
+
*/
|
|
732
|
+
getService<TGetService, TGetScope extends 'root' | 'plugin', TGetInstances extends 'singleton' | 'multiton' = 'singleton'>(service: ServiceRef<TGetService, TGetScope, TGetInstances>, ...args: 'root' extends TGetScope ? [] : [pluginId?: string]): Promise<TGetInstances extends 'multiton' ? TGetService[] : TGetService>;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
/** @public */
|
|
736
|
+
interface TestBackendOptions<TExtensionPoints extends any[]> {
|
|
737
|
+
extensionPoints?: readonly [
|
|
738
|
+
...{
|
|
739
|
+
[index in keyof TExtensionPoints]: [
|
|
740
|
+
ExtensionPoint<TExtensionPoints[index]>,
|
|
741
|
+
Partial<TExtensionPoints[index]>
|
|
742
|
+
];
|
|
743
|
+
}
|
|
744
|
+
];
|
|
745
|
+
features?: Array<BackendFeature | Promise<{
|
|
746
|
+
default: BackendFeature;
|
|
747
|
+
}>>;
|
|
748
|
+
}
|
|
749
|
+
/** @public */
|
|
750
|
+
interface TestBackend extends Backend {
|
|
751
|
+
/**
|
|
752
|
+
* Provides access to the underling HTTP server for use with utilities
|
|
753
|
+
* such as `supertest`.
|
|
754
|
+
*
|
|
755
|
+
* If the root http router service has been replaced, this will throw an error.
|
|
756
|
+
*/
|
|
757
|
+
readonly server: ExtendedHttpServer;
|
|
758
|
+
}
|
|
759
|
+
/** @public */
|
|
760
|
+
declare function startTestBackend<TExtensionPoints extends any[]>(options: TestBackendOptions<TExtensionPoints>): Promise<TestBackend>;
|
|
761
|
+
|
|
748
762
|
/**
|
|
749
763
|
* A mock for error handler middleware that can be used in router tests.
|
|
750
764
|
* @public
|