@backstage/backend-test-utils 0.1.34-next.1 → 0.1.34
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 +44 -0
- package/README.md +1 -1
- package/alpha/package.json +1 -1
- package/dist/index.alpha.d.ts +19 -39
- package/dist/index.beta.d.ts +83 -6
- package/dist/index.cjs.js +53 -59
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +83 -6
- package/package.json +6 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,49 @@
|
|
|
1
1
|
# @backstage/backend-test-utils
|
|
2
2
|
|
|
3
|
+
## 0.1.34
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- baf6e4c96a: Removed unnecessary `@backstage/cli` dependency.
|
|
8
|
+
- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend
|
|
9
|
+
- 1835311713: Added explicit return type signature for `mockServices.config()`.
|
|
10
|
+
- e716946103: Updated usage of the lifecycle service.
|
|
11
|
+
- 7e7557a2be: Updated the `mockServices.rootLogger` options to accept a single level option instead.
|
|
12
|
+
- 610d65e143: Updates to match new `BackendFeature` type.
|
|
13
|
+
- e412d33025: Use the new `*ServiceFactory` exports from `@backstage/backend-app-api`
|
|
14
|
+
- b86efa2d04: Updated usage of `ServiceFactory`.
|
|
15
|
+
- 17b573e4be: The new backend system testing utilities have now been marked as stable API.
|
|
16
|
+
- f1adb2e36b: Removed the `ref` from all `mockServices`.
|
|
17
|
+
- d0901c9ba4: All mock service factories and mock service implementations are now available via the new experimental `mockServices` export.
|
|
18
|
+
- 71a5ec0f06: Updated usages of `LogMeta`.
|
|
19
|
+
- Updated dependencies
|
|
20
|
+
- @backstage/backend-app-api@0.4.0
|
|
21
|
+
- @backstage/backend-plugin-api@0.4.0
|
|
22
|
+
- @backstage/backend-common@0.18.2
|
|
23
|
+
- @backstage/config@1.0.6
|
|
24
|
+
- @backstage/types@1.0.2
|
|
25
|
+
- @backstage/plugin-auth-node@0.2.11
|
|
26
|
+
|
|
27
|
+
## 0.1.34-next.2
|
|
28
|
+
|
|
29
|
+
### Patch Changes
|
|
30
|
+
|
|
31
|
+
- baf6e4c96a: Removed unnecessary `@backstage/cli` dependency.
|
|
32
|
+
- 1835311713: Added explicit return type signature for `mockServices.config()`.
|
|
33
|
+
- e716946103: Updated usage of the lifecycle service.
|
|
34
|
+
- 7e7557a2be: Updated the `mockServices.rootLogger` options to accept a single level option instead.
|
|
35
|
+
- 610d65e143: Updates to match new `BackendFeature` type.
|
|
36
|
+
- e412d33025: Use the new `*ServiceFactory` exports from `@backstage/backend-app-api`
|
|
37
|
+
- f1adb2e36b: Removed the `ref` from all `mockServices`.
|
|
38
|
+
- 71a5ec0f06: Updated usages of `LogMeta`.
|
|
39
|
+
- Updated dependencies
|
|
40
|
+
- @backstage/backend-app-api@0.4.0-next.2
|
|
41
|
+
- @backstage/backend-plugin-api@0.4.0-next.2
|
|
42
|
+
- @backstage/backend-common@0.18.2-next.2
|
|
43
|
+
- @backstage/plugin-auth-node@0.2.11-next.2
|
|
44
|
+
- @backstage/config@1.0.6
|
|
45
|
+
- @backstage/types@1.0.2
|
|
46
|
+
|
|
3
47
|
## 0.1.34-next.1
|
|
4
48
|
|
|
5
49
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ Test helpers library for Backstage backends.
|
|
|
7
7
|
Add the library as a `devDependency` to your backend package:
|
|
8
8
|
|
|
9
9
|
```sh
|
|
10
|
-
# From
|
|
10
|
+
# From your Backstage root directory, go to your backend package, or to a backend plugin
|
|
11
11
|
cd plugins/my-plugin-backend
|
|
12
12
|
yarn add --dev @backstage/backend-test-utils
|
|
13
13
|
```
|
package/alpha/package.json
CHANGED
package/dist/index.alpha.d.ts
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
import { Backend } from '@backstage/backend-app-api';
|
|
8
8
|
import { BackendFeature } from '@backstage/backend-plugin-api';
|
|
9
9
|
import { CacheService } from '@backstage/backend-plugin-api';
|
|
10
|
-
import { ConfigReader } from '@backstage/config';
|
|
11
10
|
import { ConfigService } from '@backstage/backend-plugin-api';
|
|
12
11
|
import { DatabaseService } from '@backstage/backend-plugin-api';
|
|
13
12
|
import { ExtendedHttpServer } from '@backstage/backend-app-api';
|
|
@@ -21,7 +20,6 @@ import { LifecycleService } from '@backstage/backend-plugin-api';
|
|
|
21
20
|
import { LoggerService } from '@backstage/backend-plugin-api';
|
|
22
21
|
import { PermissionsService } from '@backstage/backend-plugin-api';
|
|
23
22
|
import { RootLifecycleService } from '@backstage/backend-plugin-api';
|
|
24
|
-
import { RootLoggerService } from '@backstage/backend-plugin-api';
|
|
25
23
|
import { SchedulerService } from '@backstage/backend-plugin-api';
|
|
26
24
|
import { ServiceFactory } from '@backstage/backend-plugin-api';
|
|
27
25
|
import { ServiceRef } from '@backstage/backend-plugin-api';
|
|
@@ -32,75 +30,57 @@ import { UrlReaderService } from '@backstage/backend-plugin-api';
|
|
|
32
30
|
export declare function isDockerDisabledForTests(): boolean;
|
|
33
31
|
|
|
34
32
|
/**
|
|
35
|
-
* @
|
|
33
|
+
* @public
|
|
36
34
|
*/
|
|
37
35
|
export declare namespace mockServices {
|
|
38
|
-
export function config(options?: config.Options):
|
|
36
|
+
export function config(options?: config.Options): ConfigService;
|
|
39
37
|
export namespace config {
|
|
40
38
|
export type Options = {
|
|
41
39
|
data?: JsonObject;
|
|
42
40
|
};
|
|
43
|
-
const
|
|
44
|
-
const factory: (options?: Options | undefined) => ServiceFactory<ConfigService>;
|
|
41
|
+
const factory: (options?: Options | undefined) => ServiceFactory<ConfigService, "root">;
|
|
45
42
|
}
|
|
46
43
|
export function rootLogger(options?: rootLogger.Options): LoggerService;
|
|
47
44
|
export namespace rootLogger {
|
|
48
45
|
export type Options = {
|
|
49
|
-
|
|
50
|
-
error: boolean;
|
|
51
|
-
warn: boolean;
|
|
52
|
-
info: boolean;
|
|
53
|
-
debug: boolean;
|
|
54
|
-
};
|
|
46
|
+
level?: 'none' | 'error' | 'warn' | 'info' | 'debug';
|
|
55
47
|
};
|
|
56
|
-
const
|
|
57
|
-
const factory: (options?: Options | undefined) => ServiceFactory<LoggerService>;
|
|
48
|
+
const factory: (options?: Options | undefined) => ServiceFactory<LoggerService, "root">;
|
|
58
49
|
}
|
|
59
50
|
export function tokenManager(): TokenManagerService;
|
|
60
51
|
export namespace tokenManager {
|
|
61
|
-
const
|
|
62
|
-
const factory: () => ServiceFactory<TokenManagerService>;
|
|
52
|
+
const factory: () => ServiceFactory<TokenManagerService, "plugin">;
|
|
63
53
|
}
|
|
64
54
|
export function identity(): IdentityService;
|
|
65
55
|
export namespace identity {
|
|
66
|
-
const
|
|
67
|
-
const factory: () => ServiceFactory<IdentityService>;
|
|
56
|
+
const factory: () => ServiceFactory<IdentityService, "plugin">;
|
|
68
57
|
}
|
|
69
58
|
export namespace cache {
|
|
70
|
-
const
|
|
71
|
-
const factory: () => ServiceFactory<CacheService>;
|
|
59
|
+
const factory: () => ServiceFactory<CacheService, "plugin">;
|
|
72
60
|
}
|
|
73
61
|
export namespace database {
|
|
74
|
-
const
|
|
75
|
-
const factory: () => ServiceFactory<DatabaseService>;
|
|
62
|
+
const factory: () => ServiceFactory<DatabaseService, "plugin">;
|
|
76
63
|
}
|
|
77
64
|
export namespace httpRouter {
|
|
78
|
-
const
|
|
79
|
-
const factory: (options?: HttpRouterFactoryOptions | undefined) => ServiceFactory<HttpRouterService>;
|
|
65
|
+
const factory: (options?: HttpRouterFactoryOptions | undefined) => ServiceFactory<HttpRouterService, "plugin">;
|
|
80
66
|
}
|
|
81
67
|
export namespace lifecycle {
|
|
82
|
-
const
|
|
83
|
-
const factory: () => ServiceFactory<LifecycleService>;
|
|
68
|
+
const factory: () => ServiceFactory<LifecycleService, "plugin">;
|
|
84
69
|
}
|
|
85
70
|
export namespace logger {
|
|
86
|
-
const
|
|
87
|
-
const factory: () => ServiceFactory<LoggerService>;
|
|
71
|
+
const factory: () => ServiceFactory<LoggerService, "plugin">;
|
|
88
72
|
}
|
|
89
73
|
export namespace permissions {
|
|
90
|
-
const
|
|
91
|
-
const factory: () => ServiceFactory<PermissionsService>;
|
|
74
|
+
const factory: () => ServiceFactory<PermissionsService, "plugin">;
|
|
92
75
|
}
|
|
93
76
|
export namespace rootLifecycle {
|
|
94
|
-
const
|
|
95
|
-
const factory: () => ServiceFactory<RootLifecycleService>;
|
|
77
|
+
const factory: () => ServiceFactory<RootLifecycleService, "root">;
|
|
96
78
|
}
|
|
97
79
|
export namespace scheduler {
|
|
98
|
-
const
|
|
99
|
-
const factory: () => ServiceFactory<SchedulerService>;
|
|
80
|
+
const factory: () => ServiceFactory<SchedulerService, "plugin">;
|
|
100
81
|
}
|
|
101
82
|
export namespace urlReader {
|
|
102
|
-
const
|
|
103
|
-
const factory: () => ServiceFactory<UrlReaderService>;
|
|
83
|
+
const factory: () => ServiceFactory<UrlReaderService, "plugin">;
|
|
104
84
|
}
|
|
105
85
|
}
|
|
106
86
|
|
|
@@ -115,10 +95,10 @@ export declare function setupRequestMockHandlers(worker: {
|
|
|
115
95
|
resetHandlers: () => void;
|
|
116
96
|
}): void;
|
|
117
97
|
|
|
118
|
-
/** @
|
|
98
|
+
/** @public */
|
|
119
99
|
export declare function startTestBackend<TServices extends any[], TExtensionPoints extends any[]>(options: TestBackendOptions<TServices, TExtensionPoints>): Promise<TestBackend>;
|
|
120
100
|
|
|
121
|
-
/** @
|
|
101
|
+
/** @public */
|
|
122
102
|
export declare interface TestBackend extends Backend {
|
|
123
103
|
/**
|
|
124
104
|
* Provides access to the underling HTTP server for use with utilities
|
|
@@ -129,7 +109,7 @@ export declare interface TestBackend extends Backend {
|
|
|
129
109
|
readonly server: ExtendedHttpServer;
|
|
130
110
|
}
|
|
131
111
|
|
|
132
|
-
/** @
|
|
112
|
+
/** @public */
|
|
133
113
|
export declare interface TestBackendOptions<TServices extends any[], TExtensionPoints extends any[]> {
|
|
134
114
|
services?: readonly [
|
|
135
115
|
...{
|
package/dist/index.beta.d.ts
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
import { Backend } from '@backstage/backend-app-api';
|
|
8
8
|
import { BackendFeature } from '@backstage/backend-plugin-api';
|
|
9
9
|
import { CacheService } from '@backstage/backend-plugin-api';
|
|
10
|
-
import { ConfigReader } from '@backstage/config';
|
|
11
10
|
import { ConfigService } from '@backstage/backend-plugin-api';
|
|
12
11
|
import { DatabaseService } from '@backstage/backend-plugin-api';
|
|
13
12
|
import { ExtendedHttpServer } from '@backstage/backend-app-api';
|
|
@@ -21,7 +20,6 @@ import { LifecycleService } from '@backstage/backend-plugin-api';
|
|
|
21
20
|
import { LoggerService } from '@backstage/backend-plugin-api';
|
|
22
21
|
import { PermissionsService } from '@backstage/backend-plugin-api';
|
|
23
22
|
import { RootLifecycleService } from '@backstage/backend-plugin-api';
|
|
24
|
-
import { RootLoggerService } from '@backstage/backend-plugin-api';
|
|
25
23
|
import { SchedulerService } from '@backstage/backend-plugin-api';
|
|
26
24
|
import { ServiceFactory } from '@backstage/backend-plugin-api';
|
|
27
25
|
import { ServiceRef } from '@backstage/backend-plugin-api';
|
|
@@ -31,7 +29,60 @@ import { UrlReaderService } from '@backstage/backend-plugin-api';
|
|
|
31
29
|
/** @public */
|
|
32
30
|
export declare function isDockerDisabledForTests(): boolean;
|
|
33
31
|
|
|
34
|
-
|
|
32
|
+
/**
|
|
33
|
+
* @public
|
|
34
|
+
*/
|
|
35
|
+
export declare namespace mockServices {
|
|
36
|
+
export function config(options?: config.Options): ConfigService;
|
|
37
|
+
export namespace config {
|
|
38
|
+
export type Options = {
|
|
39
|
+
data?: JsonObject;
|
|
40
|
+
};
|
|
41
|
+
const factory: (options?: Options | undefined) => ServiceFactory<ConfigService, "root">;
|
|
42
|
+
}
|
|
43
|
+
export function rootLogger(options?: rootLogger.Options): LoggerService;
|
|
44
|
+
export namespace rootLogger {
|
|
45
|
+
export type Options = {
|
|
46
|
+
level?: 'none' | 'error' | 'warn' | 'info' | 'debug';
|
|
47
|
+
};
|
|
48
|
+
const factory: (options?: Options | undefined) => ServiceFactory<LoggerService, "root">;
|
|
49
|
+
}
|
|
50
|
+
export function tokenManager(): TokenManagerService;
|
|
51
|
+
export namespace tokenManager {
|
|
52
|
+
const factory: () => ServiceFactory<TokenManagerService, "plugin">;
|
|
53
|
+
}
|
|
54
|
+
export function identity(): IdentityService;
|
|
55
|
+
export namespace identity {
|
|
56
|
+
const factory: () => ServiceFactory<IdentityService, "plugin">;
|
|
57
|
+
}
|
|
58
|
+
export namespace cache {
|
|
59
|
+
const factory: () => ServiceFactory<CacheService, "plugin">;
|
|
60
|
+
}
|
|
61
|
+
export namespace database {
|
|
62
|
+
const factory: () => ServiceFactory<DatabaseService, "plugin">;
|
|
63
|
+
}
|
|
64
|
+
export namespace httpRouter {
|
|
65
|
+
const factory: (options?: HttpRouterFactoryOptions | undefined) => ServiceFactory<HttpRouterService, "plugin">;
|
|
66
|
+
}
|
|
67
|
+
export namespace lifecycle {
|
|
68
|
+
const factory: () => ServiceFactory<LifecycleService, "plugin">;
|
|
69
|
+
}
|
|
70
|
+
export namespace logger {
|
|
71
|
+
const factory: () => ServiceFactory<LoggerService, "plugin">;
|
|
72
|
+
}
|
|
73
|
+
export namespace permissions {
|
|
74
|
+
const factory: () => ServiceFactory<PermissionsService, "plugin">;
|
|
75
|
+
}
|
|
76
|
+
export namespace rootLifecycle {
|
|
77
|
+
const factory: () => ServiceFactory<RootLifecycleService, "root">;
|
|
78
|
+
}
|
|
79
|
+
export namespace scheduler {
|
|
80
|
+
const factory: () => ServiceFactory<SchedulerService, "plugin">;
|
|
81
|
+
}
|
|
82
|
+
export namespace urlReader {
|
|
83
|
+
const factory: () => ServiceFactory<UrlReaderService, "plugin">;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
35
86
|
|
|
36
87
|
/**
|
|
37
88
|
* Sets up handlers for request mocking
|
|
@@ -44,11 +95,37 @@ export declare function setupRequestMockHandlers(worker: {
|
|
|
44
95
|
resetHandlers: () => void;
|
|
45
96
|
}): void;
|
|
46
97
|
|
|
47
|
-
|
|
98
|
+
/** @public */
|
|
99
|
+
export declare function startTestBackend<TServices extends any[], TExtensionPoints extends any[]>(options: TestBackendOptions<TServices, TExtensionPoints>): Promise<TestBackend>;
|
|
48
100
|
|
|
49
|
-
|
|
101
|
+
/** @public */
|
|
102
|
+
export declare interface TestBackend extends Backend {
|
|
103
|
+
/**
|
|
104
|
+
* Provides access to the underling HTTP server for use with utilities
|
|
105
|
+
* such as `supertest`.
|
|
106
|
+
*
|
|
107
|
+
* If the root http router service has been replaced, this will throw an error.
|
|
108
|
+
*/
|
|
109
|
+
readonly server: ExtendedHttpServer;
|
|
110
|
+
}
|
|
50
111
|
|
|
51
|
-
|
|
112
|
+
/** @public */
|
|
113
|
+
export declare interface TestBackendOptions<TServices extends any[], TExtensionPoints extends any[]> {
|
|
114
|
+
services?: readonly [
|
|
115
|
+
...{
|
|
116
|
+
[index in keyof TServices]: ServiceFactory<TServices[index]> | (() => ServiceFactory<TServices[index]>) | [ServiceRef<TServices[index]>, Partial<TServices[index]>];
|
|
117
|
+
}
|
|
118
|
+
];
|
|
119
|
+
extensionPoints?: readonly [
|
|
120
|
+
...{
|
|
121
|
+
[index in keyof TExtensionPoints]: [
|
|
122
|
+
ExtensionPoint<TExtensionPoints[index]>,
|
|
123
|
+
Partial<TExtensionPoints[index]>
|
|
124
|
+
];
|
|
125
|
+
}
|
|
126
|
+
];
|
|
127
|
+
features?: BackendFeature[];
|
|
128
|
+
}
|
|
52
129
|
|
|
53
130
|
/**
|
|
54
131
|
* The possible databases to test against.
|
package/dist/index.cjs.js
CHANGED
|
@@ -383,24 +383,30 @@ var __privateMethod = (obj, member, method) => {
|
|
|
383
383
|
__accessCheck(obj, member, "access private method");
|
|
384
384
|
return method;
|
|
385
385
|
};
|
|
386
|
-
var
|
|
386
|
+
var _level, _meta, _log, log_fn;
|
|
387
|
+
const levels = {
|
|
388
|
+
none: 0,
|
|
389
|
+
error: 1,
|
|
390
|
+
warn: 2,
|
|
391
|
+
info: 3,
|
|
392
|
+
debug: 4
|
|
393
|
+
};
|
|
387
394
|
const _MockRootLoggerService = class {
|
|
388
|
-
constructor(
|
|
395
|
+
constructor(level, meta) {
|
|
389
396
|
__privateAdd(this, _log);
|
|
390
|
-
__privateAdd(this,
|
|
397
|
+
__privateAdd(this, _level, void 0);
|
|
391
398
|
__privateAdd(this, _meta, void 0);
|
|
392
|
-
|
|
393
|
-
__privateSet(this, _levels, {
|
|
394
|
-
error: levels,
|
|
395
|
-
debug: levels,
|
|
396
|
-
info: levels,
|
|
397
|
-
warn: levels
|
|
398
|
-
});
|
|
399
|
-
} else {
|
|
400
|
-
__privateSet(this, _levels, levels);
|
|
401
|
-
}
|
|
399
|
+
__privateSet(this, _level, level);
|
|
402
400
|
__privateSet(this, _meta, meta);
|
|
403
401
|
}
|
|
402
|
+
static create(options) {
|
|
403
|
+
var _a;
|
|
404
|
+
const level = (_a = options == null ? void 0 : options.level) != null ? _a : "none";
|
|
405
|
+
if (!(level in levels)) {
|
|
406
|
+
throw new Error(`Invalid log level '${level}'`);
|
|
407
|
+
}
|
|
408
|
+
return new _MockRootLoggerService(levels[level], {});
|
|
409
|
+
}
|
|
404
410
|
error(message, meta) {
|
|
405
411
|
__privateMethod(this, _log, log_fn).call(this, "error", message, meta);
|
|
406
412
|
}
|
|
@@ -414,15 +420,17 @@ const _MockRootLoggerService = class {
|
|
|
414
420
|
__privateMethod(this, _log, log_fn).call(this, "debug", message, meta);
|
|
415
421
|
}
|
|
416
422
|
child(meta) {
|
|
417
|
-
return new _MockRootLoggerService(__privateGet(this,
|
|
423
|
+
return new _MockRootLoggerService(__privateGet(this, _level), { ...__privateGet(this, _meta), ...meta });
|
|
418
424
|
}
|
|
419
425
|
};
|
|
420
426
|
let MockRootLoggerService = _MockRootLoggerService;
|
|
421
|
-
|
|
427
|
+
_level = new WeakMap();
|
|
422
428
|
_meta = new WeakMap();
|
|
423
429
|
_log = new WeakSet();
|
|
424
430
|
log_fn = function(level, message, meta) {
|
|
425
|
-
|
|
431
|
+
var _a;
|
|
432
|
+
const levelValue = (_a = levels[level]) != null ? _a : 0;
|
|
433
|
+
if (levelValue <= __privateGet(this, _level)) {
|
|
426
434
|
const labels = Object.entries(__privateGet(this, _meta)).map(([key, value]) => `${key}=${value}`).join(",");
|
|
427
435
|
console[level](`${labels} ${message}`, meta);
|
|
428
436
|
}
|
|
@@ -444,17 +452,14 @@ exports.mockServices = void 0;
|
|
|
444
452
|
}
|
|
445
453
|
mockServices2.config = config$1;
|
|
446
454
|
((config2) => {
|
|
447
|
-
config2.
|
|
448
|
-
config2.factory = simpleFactory(config2.ref, config2);
|
|
455
|
+
config2.factory = simpleFactory(backendPluginApi.coreServices.config, config2);
|
|
449
456
|
})(config$1 = mockServices2.config || (mockServices2.config = {}));
|
|
450
457
|
function rootLogger(options) {
|
|
451
|
-
|
|
452
|
-
return new MockRootLoggerService((_a = options == null ? void 0 : options.levels) != null ? _a : false, {});
|
|
458
|
+
return MockRootLoggerService.create(options);
|
|
453
459
|
}
|
|
454
460
|
mockServices2.rootLogger = rootLogger;
|
|
455
461
|
((rootLogger2) => {
|
|
456
|
-
rootLogger2.
|
|
457
|
-
rootLogger2.factory = simpleFactory(rootLogger2.ref, rootLogger2);
|
|
462
|
+
rootLogger2.factory = simpleFactory(backendPluginApi.coreServices.rootLogger, rootLogger2);
|
|
458
463
|
})(rootLogger = mockServices2.rootLogger || (mockServices2.rootLogger = {}));
|
|
459
464
|
function tokenManager() {
|
|
460
465
|
return {
|
|
@@ -470,52 +475,44 @@ exports.mockServices = void 0;
|
|
|
470
475
|
}
|
|
471
476
|
mockServices2.tokenManager = tokenManager;
|
|
472
477
|
((tokenManager2) => {
|
|
473
|
-
tokenManager2.
|
|
474
|
-
|
|
478
|
+
tokenManager2.factory = simpleFactory(
|
|
479
|
+
backendPluginApi.coreServices.tokenManager,
|
|
480
|
+
tokenManager2
|
|
481
|
+
);
|
|
475
482
|
})(tokenManager = mockServices2.tokenManager || (mockServices2.tokenManager = {}));
|
|
476
483
|
function identity() {
|
|
477
484
|
return new MockIdentityService();
|
|
478
485
|
}
|
|
479
486
|
mockServices2.identity = identity;
|
|
480
487
|
((identity2) => {
|
|
481
|
-
identity2.
|
|
482
|
-
identity2.factory = simpleFactory(identity2.ref, identity2);
|
|
488
|
+
identity2.factory = simpleFactory(backendPluginApi.coreServices.identity, identity2);
|
|
483
489
|
})(identity = mockServices2.identity || (mockServices2.identity = {}));
|
|
484
490
|
((cache2) => {
|
|
485
|
-
cache2.
|
|
486
|
-
cache2.factory = backendAppApi.cacheFactory;
|
|
491
|
+
cache2.factory = backendAppApi.cacheServiceFactory;
|
|
487
492
|
})(mockServices2.cache || (mockServices2.cache = {}));
|
|
488
493
|
((database2) => {
|
|
489
|
-
database2.
|
|
490
|
-
database2.factory = backendAppApi.databaseFactory;
|
|
494
|
+
database2.factory = backendAppApi.databaseServiceFactory;
|
|
491
495
|
})(mockServices2.database || (mockServices2.database = {}));
|
|
492
496
|
((httpRouter2) => {
|
|
493
|
-
httpRouter2.
|
|
494
|
-
httpRouter2.factory = backendAppApi.httpRouterFactory;
|
|
497
|
+
httpRouter2.factory = backendAppApi.httpRouterServiceFactory;
|
|
495
498
|
})(mockServices2.httpRouter || (mockServices2.httpRouter = {}));
|
|
496
499
|
((lifecycle2) => {
|
|
497
|
-
lifecycle2.
|
|
498
|
-
lifecycle2.factory = backendAppApi.lifecycleFactory;
|
|
500
|
+
lifecycle2.factory = backendAppApi.lifecycleServiceFactory;
|
|
499
501
|
})(mockServices2.lifecycle || (mockServices2.lifecycle = {}));
|
|
500
502
|
((logger2) => {
|
|
501
|
-
logger2.
|
|
502
|
-
logger2.factory = backendAppApi.loggerFactory;
|
|
503
|
+
logger2.factory = backendAppApi.loggerServiceFactory;
|
|
503
504
|
})(mockServices2.logger || (mockServices2.logger = {}));
|
|
504
505
|
((permissions2) => {
|
|
505
|
-
permissions2.
|
|
506
|
-
permissions2.factory = backendAppApi.permissionsFactory;
|
|
506
|
+
permissions2.factory = backendAppApi.permissionsServiceFactory;
|
|
507
507
|
})(mockServices2.permissions || (mockServices2.permissions = {}));
|
|
508
508
|
((rootLifecycle2) => {
|
|
509
|
-
rootLifecycle2.
|
|
510
|
-
rootLifecycle2.factory = backendAppApi.rootLifecycleFactory;
|
|
509
|
+
rootLifecycle2.factory = backendAppApi.rootLifecycleServiceFactory;
|
|
511
510
|
})(mockServices2.rootLifecycle || (mockServices2.rootLifecycle = {}));
|
|
512
511
|
((scheduler2) => {
|
|
513
|
-
scheduler2.
|
|
514
|
-
scheduler2.factory = backendAppApi.schedulerFactory;
|
|
512
|
+
scheduler2.factory = backendAppApi.schedulerServiceFactory;
|
|
515
513
|
})(mockServices2.scheduler || (mockServices2.scheduler = {}));
|
|
516
514
|
((urlReader2) => {
|
|
517
|
-
urlReader2.
|
|
518
|
-
urlReader2.factory = backendAppApi.urlReaderFactory;
|
|
515
|
+
urlReader2.factory = backendAppApi.urlReaderServiceFactory;
|
|
519
516
|
})(mockServices2.urlReader || (mockServices2.urlReader = {}));
|
|
520
517
|
})(exports.mockServices || (exports.mockServices = {}));
|
|
521
518
|
|
|
@@ -563,12 +560,7 @@ async function startTestBackend(options) {
|
|
|
563
560
|
{ listen: { host: "", port: 0 } },
|
|
564
561
|
{ logger }
|
|
565
562
|
);
|
|
566
|
-
lifecycle.addShutdownHook({
|
|
567
|
-
async fn() {
|
|
568
|
-
await server.stop();
|
|
569
|
-
},
|
|
570
|
-
logger
|
|
571
|
-
});
|
|
563
|
+
lifecycle.addShutdownHook(() => server.stop(), { logger });
|
|
572
564
|
await server.start();
|
|
573
565
|
return router;
|
|
574
566
|
}
|
|
@@ -622,16 +614,18 @@ async function startTestBackend(options) {
|
|
|
622
614
|
services: [...factories, rootHttpRouterFactory, discoveryFactory]
|
|
623
615
|
});
|
|
624
616
|
backendInstancesToCleanUp.push(backend);
|
|
625
|
-
backend.add(
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
617
|
+
backend.add(
|
|
618
|
+
backendPluginApi.createBackendPlugin({
|
|
619
|
+
pluginId: `---test-extension-point-registrar`,
|
|
620
|
+
register(reg) {
|
|
621
|
+
for (const [ref, impl] of extensionPoints) {
|
|
622
|
+
reg.registerExtensionPoint(ref, impl);
|
|
623
|
+
}
|
|
624
|
+
reg.registerInit({ deps: {}, async init() {
|
|
625
|
+
} });
|
|
630
626
|
}
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
}
|
|
634
|
-
});
|
|
627
|
+
})()
|
|
628
|
+
);
|
|
635
629
|
for (const feature of features) {
|
|
636
630
|
backend.add(feature);
|
|
637
631
|
}
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../src/util/isDockerDisabledForTests.ts","../src/database/startMysqlContainer.ts","../src/database/startPostgresContainer.ts","../src/database/types.ts","../src/database/TestDatabases.ts","../src/msw/setupRequestMockHandlers.ts","../src/next/services/MockIdentityService.ts","../src/next/services/MockRootLoggerService.ts","../src/next/services/mockServices.ts","../src/next/wiring/TestBackend.ts"],"sourcesContent":["/*\n * Copyright 2021 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\n/** @public */\nexport function isDockerDisabledForTests() {\n // If we are not running in continuous integration, the default is to skip\n // the (relatively heavy, long running) docker based tests. If you want to\n // still run local tests for all databases, just pass either the CI=1 env\n // parameter to your test runner, or individual connection strings per\n // database.\n return (\n Boolean(process.env.BACKSTAGE_TEST_DISABLE_DOCKER) ||\n !Boolean(process.env.CI)\n );\n}\n","/*\n * Copyright 2021 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 createConnection, { Knex } from 'knex';\nimport { v4 as uuid } from 'uuid';\n\nasync function waitForMysqlReady(\n connection: Knex.MySqlConnectionConfig,\n): Promise<void> {\n const startTime = Date.now();\n const db = createConnection({ client: 'mysql2', connection });\n\n try {\n for (;;) {\n try {\n const result = await db.select(db.raw('version() AS version'));\n if (result[0]?.version) {\n return;\n }\n } catch (e) {\n if (Date.now() - startTime > 30_000) {\n throw new Error(\n `Timed out waiting for the database to be ready for connections, ${e}`,\n );\n }\n }\n\n await new Promise(resolve => setTimeout(resolve, 100));\n }\n } finally {\n db.destroy();\n }\n}\n\nexport async function startMysqlContainer(image: string) {\n const user = 'root';\n const password = uuid();\n\n // Lazy-load to avoid side-effect of importing testcontainers\n const { GenericContainer } = await import('testcontainers');\n\n const container = await new GenericContainer(image)\n .withExposedPorts(3306)\n .withEnv('MYSQL_ROOT_PASSWORD', password)\n .withTmpFs({ '/var/lib/mysql': 'rw' })\n .start();\n\n const host = container.getHost();\n const port = container.getMappedPort(3306);\n const stop = async () => {\n await container.stop({ timeout: 10_000 });\n };\n\n await waitForMysqlReady({ host, port, user, password });\n\n return { host, port, user, password, stop };\n}\n","/*\n * Copyright 2021 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 createConnection, { Knex } from 'knex';\nimport { v4 as uuid } from 'uuid';\n\nasync function waitForPostgresReady(\n connection: Knex.PgConnectionConfig,\n): Promise<void> {\n const startTime = Date.now();\n const db = createConnection({ client: 'pg', connection });\n\n try {\n for (;;) {\n try {\n const result = await db.select(db.raw('version()'));\n if (Array.isArray(result) && result[0]?.version) {\n return;\n }\n } catch (e) {\n if (Date.now() - startTime > 30_000) {\n throw new Error(\n `Timed out waiting for the database to be ready for connections, ${e}`,\n );\n }\n }\n\n await new Promise(resolve => setTimeout(resolve, 100));\n }\n } finally {\n db.destroy();\n }\n}\n\nexport async function startPostgresContainer(image: string) {\n const user = 'postgres';\n const password = uuid();\n\n // Lazy-load to avoid side-effect of importing testcontainers\n const { GenericContainer } = await import('testcontainers');\n\n const container = await new GenericContainer(image)\n .withExposedPorts(5432)\n .withEnv('POSTGRES_PASSWORD', password)\n .withTmpFs({ '/var/lib/postgresql/data': 'rw' })\n .start();\n\n const host = container.getHost();\n const port = container.getMappedPort(5432);\n const stop = async () => {\n await container.stop({ timeout: 10_000 });\n };\n\n await waitForPostgresReady({ host, port, user, password });\n\n return { host, port, user, password, stop };\n}\n","/*\n * Copyright 2021 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 { DatabaseManager } from '@backstage/backend-common';\nimport { Knex } from 'knex';\n\n/**\n * The possible databases to test against.\n *\n * @public\n */\nexport type TestDatabaseId =\n | 'POSTGRES_13'\n | 'POSTGRES_9'\n | 'MYSQL_8'\n | 'SQLITE_3';\n\nexport type TestDatabaseProperties = {\n name: string;\n driver: string;\n dockerImageName?: string;\n connectionStringEnvironmentVariableName?: string;\n};\n\nexport type Instance = {\n stopContainer?: () => Promise<void>;\n databaseManager: DatabaseManager;\n connections: Array<Knex>;\n};\n\nexport const allDatabases: Record<TestDatabaseId, TestDatabaseProperties> =\n Object.freeze({\n POSTGRES_13: {\n name: 'Postgres 13.x',\n driver: 'pg',\n dockerImageName: 'postgres:13',\n connectionStringEnvironmentVariableName:\n 'BACKSTAGE_TEST_DATABASE_POSTGRES13_CONNECTION_STRING',\n },\n POSTGRES_9: {\n name: 'Postgres 9.x',\n driver: 'pg',\n dockerImageName: 'postgres:9',\n connectionStringEnvironmentVariableName:\n 'BACKSTAGE_TEST_DATABASE_POSTGRES9_CONNECTION_STRING',\n },\n MYSQL_8: {\n name: 'MySQL 8.x',\n driver: 'mysql2',\n dockerImageName: 'mysql:8',\n connectionStringEnvironmentVariableName:\n 'BACKSTAGE_TEST_DATABASE_MYSQL8_CONNECTION_STRING',\n },\n SQLITE_3: {\n name: 'SQLite 3.x',\n driver: 'better-sqlite3',\n },\n });\n","/*\n * Copyright 2021 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 { DatabaseManager } from '@backstage/backend-common';\nimport { ConfigReader } from '@backstage/config';\nimport { randomBytes } from 'crypto';\nimport { Knex } from 'knex';\nimport { isDockerDisabledForTests } from '../util/isDockerDisabledForTests';\nimport { startMysqlContainer } from './startMysqlContainer';\nimport { startPostgresContainer } from './startPostgresContainer';\nimport {\n allDatabases,\n Instance,\n TestDatabaseId,\n TestDatabaseProperties,\n} from './types';\n\nconst LARGER_POOL_CONFIG = {\n pool: {\n min: 0,\n max: 50,\n },\n};\n\n/**\n * Encapsulates the creation of ephemeral test database instances for use\n * inside unit or integration tests.\n *\n * @public\n */\nexport class TestDatabases {\n private readonly instanceById: Map<string, Instance>;\n private readonly supportedIds: TestDatabaseId[];\n\n /**\n * Creates an empty `TestDatabases` instance, and sets up Jest to clean up\n * all of its acquired resources after all tests finish.\n *\n * You typically want to create just a single instance like this at the top\n * of your test file or `describe` block, and then call `init` many times on\n * that instance inside the individual tests. Spinning up a \"physical\"\n * database instance takes a considerable amount of time, slowing down tests.\n * But initializing a new logical database inside that instance using `init`\n * is very fast.\n */\n static create(options?: {\n ids?: TestDatabaseId[];\n disableDocker?: boolean;\n }): TestDatabases {\n const defaultOptions = {\n ids: Object.keys(allDatabases) as TestDatabaseId[],\n disableDocker: isDockerDisabledForTests(),\n };\n\n const { ids, disableDocker } = Object.assign(\n {},\n defaultOptions,\n options ?? {},\n );\n\n const supportedIds = ids.filter(id => {\n const properties = allDatabases[id];\n if (!properties) {\n return false;\n }\n // If the caller has set up the env with an explicit connection string,\n // we'll assume that this database will work\n if (\n properties.connectionStringEnvironmentVariableName &&\n process.env[properties.connectionStringEnvironmentVariableName]\n ) {\n return true;\n }\n // If the database doesn't require docker at all, there's nothing to worry\n // about\n if (!properties.dockerImageName) {\n return true;\n }\n // If the database requires docker, but docker is disabled, we will fail.\n if (disableDocker) {\n return false;\n }\n return true;\n });\n\n const databases = new TestDatabases(supportedIds);\n\n if (supportedIds.length > 0) {\n afterAll(async () => {\n await databases.shutdown();\n });\n }\n\n return databases;\n }\n\n private constructor(supportedIds: TestDatabaseId[]) {\n this.instanceById = new Map();\n this.supportedIds = supportedIds;\n }\n\n supports(id: TestDatabaseId): boolean {\n return this.supportedIds.includes(id);\n }\n\n eachSupportedId(): [TestDatabaseId][] {\n return this.supportedIds.map(id => [id]);\n }\n\n /**\n * Returns a fresh, unique, empty logical database on an instance of the\n * given database ID platform.\n *\n * @param id - The ID of the database platform to use, e.g. 'POSTGRES_13'\n * @returns A `Knex` connection object\n */\n async init(id: TestDatabaseId): Promise<Knex> {\n const properties = allDatabases[id];\n if (!properties) {\n const candidates = Object.keys(allDatabases).join(', ');\n throw new Error(\n `Unknown test database ${id}, possible values are ${candidates}`,\n );\n }\n if (!this.supportedIds.includes(id)) {\n const candidates = this.supportedIds.join(', ');\n throw new Error(\n `Unsupported test database ${id} for this environment, possible values are ${candidates}`,\n );\n }\n\n let instance: Instance | undefined = this.instanceById.get(id);\n\n // Ensure that a testcontainers instance is up for this ID\n if (!instance) {\n instance = await this.initAny(properties);\n this.instanceById.set(id, instance);\n }\n\n // Ensure that a unique logical database is created in the instance\n const connection = await instance.databaseManager\n .forPlugin(`db${randomBytes(16).toString('hex')}`)\n .getClient();\n\n instance.connections.push(connection);\n\n return connection;\n }\n\n private async initAny(properties: TestDatabaseProperties): Promise<Instance> {\n // Use the connection string if provided\n if (properties.driver === 'pg' || properties.driver === 'mysql2') {\n const envVarName = properties.connectionStringEnvironmentVariableName;\n if (envVarName) {\n const connectionString = process.env[envVarName];\n if (connectionString) {\n const databaseManager = DatabaseManager.fromConfig(\n new ConfigReader({\n backend: {\n database: {\n knexConfig: properties.driver.includes('sqlite')\n ? {}\n : LARGER_POOL_CONFIG,\n client: properties.driver,\n connection: connectionString,\n },\n },\n }),\n );\n return {\n databaseManager,\n connections: [],\n };\n }\n }\n }\n\n // Otherwise start a container for the purpose\n switch (properties.driver) {\n case 'pg':\n return this.initPostgres(properties);\n case 'mysql2':\n return this.initMysql(properties);\n case 'better-sqlite3':\n case 'sqlite3':\n return this.initSqlite(properties);\n default:\n throw new Error(`Unknown database driver ${properties.driver}`);\n }\n }\n\n private async initPostgres(\n properties: TestDatabaseProperties,\n ): Promise<Instance> {\n const { host, port, user, password, stop } = await startPostgresContainer(\n properties.dockerImageName!,\n );\n\n const databaseManager = DatabaseManager.fromConfig(\n new ConfigReader({\n backend: {\n database: {\n knexConfig: LARGER_POOL_CONFIG,\n client: 'pg',\n connection: { host, port, user, password },\n },\n },\n }),\n );\n\n return {\n stopContainer: stop,\n databaseManager,\n connections: [],\n };\n }\n\n private async initMysql(\n properties: TestDatabaseProperties,\n ): Promise<Instance> {\n const { host, port, user, password, stop } = await startMysqlContainer(\n properties.dockerImageName!,\n );\n\n const databaseManager = DatabaseManager.fromConfig(\n new ConfigReader({\n backend: {\n database: {\n knexConfig: LARGER_POOL_CONFIG,\n client: 'mysql2',\n connection: { host, port, user, password },\n },\n },\n }),\n );\n\n return {\n stopContainer: stop,\n databaseManager,\n connections: [],\n };\n }\n\n private async initSqlite(\n properties: TestDatabaseProperties,\n ): Promise<Instance> {\n const databaseManager = DatabaseManager.fromConfig(\n new ConfigReader({\n backend: {\n database: {\n client: properties.driver,\n connection: ':memory:',\n },\n },\n }),\n );\n\n return {\n databaseManager,\n connections: [],\n };\n }\n\n private async shutdown() {\n const instances = [...this.instanceById.values()];\n await Promise.all(\n instances.map(async ({ stopContainer, connections }) => {\n try {\n await Promise.all(connections.map(c => c.destroy()));\n } catch {\n // ignore\n }\n try {\n await stopContainer?.();\n } catch {\n // ignore\n }\n }),\n );\n }\n}\n","/*\n * Copyright 2020 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\n/**\n * Sets up handlers for request mocking\n * @public\n * @param worker - service worker\n */\nexport function setupRequestMockHandlers(worker: {\n listen: (t: any) => void;\n close: () => void;\n resetHandlers: () => void;\n}) {\n beforeAll(() => worker.listen({ onUnhandledRequest: 'error' }));\n afterAll(() => worker.close());\n afterEach(() => worker.resetHandlers());\n}\n","/*\n * Copyright 2023 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 { IdentityService } from '@backstage/backend-plugin-api';\nimport {\n IdentityApiGetIdentityRequest,\n BackstageIdentityResponse,\n} from '@backstage/plugin-auth-node';\n\nexport class MockIdentityService implements IdentityService {\n getIdentity(\n _options: IdentityApiGetIdentityRequest,\n ): Promise<BackstageIdentityResponse | undefined> {\n return Promise.resolve({\n token: 'mock-token',\n identity: {\n type: 'user',\n userEntityRef: 'user:default/mock-user',\n ownershipEntityRefs: [],\n },\n });\n }\n}\n","/*\n * Copyright 2023 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 {\n LoggerService,\n LogMeta,\n RootLoggerService,\n} from '@backstage/backend-plugin-api';\nimport type { mockServices } from './mockServices';\n\nexport class MockRootLoggerService implements RootLoggerService {\n #levels: Exclude<mockServices.rootLogger.Options['levels'], boolean>;\n #meta: LogMeta;\n\n error(message: string, meta?: LogMeta | Error | undefined): void {\n this.#log('error', message, meta);\n }\n\n warn(message: string, meta?: LogMeta | Error | undefined): void {\n this.#log('warn', message, meta);\n }\n\n info(message: string, meta?: LogMeta | Error | undefined): void {\n this.#log('info', message, meta);\n }\n\n debug(message: string, meta?: LogMeta | Error | undefined): void {\n this.#log('debug', message, meta);\n }\n\n child(meta: LogMeta): LoggerService {\n return new MockRootLoggerService(this.#levels, { ...this.#meta, ...meta });\n }\n\n constructor(\n levels: mockServices.rootLogger.Options['levels'],\n meta: LogMeta,\n ) {\n if (typeof levels === 'boolean') {\n this.#levels = {\n error: levels,\n debug: levels,\n info: levels,\n warn: levels,\n };\n } else {\n this.#levels = levels;\n }\n this.#meta = meta;\n }\n\n #log(\n level: 'error' | 'warn' | 'info' | 'debug',\n message: string,\n meta?: LogMeta | Error | undefined,\n ) {\n if (this.#levels[level]) {\n const labels = Object.entries(this.#meta)\n .map(([key, value]) => `${key}=${value}`)\n .join(',');\n console[level](`${labels} ${message}`, meta);\n }\n }\n}\n","/*\n * Copyright 2023 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 {\n coreServices,\n createServiceFactory,\n IdentityService,\n LoggerService,\n ServiceFactory,\n ServiceRef,\n TokenManagerService,\n} from '@backstage/backend-plugin-api';\nimport {\n cacheFactory,\n databaseFactory,\n httpRouterFactory,\n lifecycleFactory,\n loggerFactory,\n permissionsFactory,\n rootLifecycleFactory,\n schedulerFactory,\n urlReaderFactory,\n} from '@backstage/backend-app-api';\nimport { ConfigReader } from '@backstage/config';\nimport { JsonObject } from '@backstage/types';\nimport { MockIdentityService } from './MockIdentityService';\nimport { MockRootLoggerService } from './MockRootLoggerService';\n\nfunction simpleFactory<TService, TOptions extends [options?: object] = []>(\n ref: ServiceRef<TService>,\n factory: (...options: TOptions) => TService,\n): (...options: TOptions) => ServiceFactory<TService> {\n return createServiceFactory((options: unknown) => ({\n service: ref as ServiceRef<TService, any>,\n deps: {},\n async factory() {\n return (factory as any)(options);\n },\n }));\n}\n\n/**\n * @alpha\n */\nexport namespace mockServices {\n export function config(options?: config.Options) {\n return new ConfigReader(options?.data, 'mock-config');\n }\n export namespace config {\n export type Options = { data?: JsonObject };\n\n export const ref = coreServices.config;\n export const factory = simpleFactory(ref, config);\n }\n\n export function rootLogger(options?: rootLogger.Options): LoggerService {\n return new MockRootLoggerService(options?.levels ?? false, {});\n }\n export namespace rootLogger {\n export type Options = {\n levels:\n | boolean\n | { error: boolean; warn: boolean; info: boolean; debug: boolean };\n };\n\n export const ref = coreServices.rootLogger;\n export const factory = simpleFactory(ref, rootLogger);\n }\n\n export function tokenManager(): TokenManagerService {\n return {\n async getToken(): Promise<{ token: string }> {\n return { token: 'mock-token' };\n },\n async authenticate(token: string): Promise<void> {\n if (token !== 'mock-token') {\n throw new Error('Invalid token');\n }\n },\n };\n }\n export namespace tokenManager {\n export const ref = coreServices.tokenManager;\n export const factory = simpleFactory(ref, tokenManager);\n }\n\n export function identity(): IdentityService {\n return new MockIdentityService();\n }\n export namespace identity {\n export const ref = coreServices.identity;\n export const factory = simpleFactory(ref, identity);\n }\n\n // TODO(Rugvip): Not all core services have implementations available here yet.\n // some may need a bit more refactoring for it to be simpler to\n // re-implement functioning mock versions here.\n export namespace cache {\n export const ref = coreServices.cache;\n export const factory = cacheFactory;\n }\n export namespace database {\n export const ref = coreServices.database;\n export const factory = databaseFactory;\n }\n export namespace httpRouter {\n export const ref = coreServices.httpRouter;\n export const factory = httpRouterFactory;\n }\n export namespace lifecycle {\n export const ref = coreServices.lifecycle;\n export const factory = lifecycleFactory;\n }\n export namespace logger {\n export const ref = coreServices.logger;\n export const factory = loggerFactory;\n }\n export namespace permissions {\n export const ref = coreServices.permissions;\n export const factory = permissionsFactory;\n }\n export namespace rootLifecycle {\n export const ref = coreServices.rootLifecycle;\n export const factory = rootLifecycleFactory;\n }\n export namespace scheduler {\n export const ref = coreServices.scheduler;\n export const factory = schedulerFactory;\n }\n export namespace urlReader {\n export const ref = coreServices.urlReader;\n export const factory = urlReaderFactory;\n }\n}\n","/*\n * Copyright 2022 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 {\n Backend,\n createSpecializedBackend,\n MiddlewareFactory,\n createHttpServer,\n ExtendedHttpServer,\n DefaultRootHttpRouter,\n} from '@backstage/backend-app-api';\nimport { SingleHostDiscovery } from '@backstage/backend-common';\nimport {\n ServiceFactory,\n ServiceRef,\n createServiceFactory,\n BackendFeature,\n ExtensionPoint,\n coreServices,\n} from '@backstage/backend-plugin-api';\nimport { mockServices } from '../services';\nimport { ConfigReader } from '@backstage/config';\nimport express from 'express';\n\n/** @alpha */\nexport interface TestBackendOptions<\n TServices extends any[],\n TExtensionPoints extends any[],\n> {\n services?: readonly [\n ...{\n [index in keyof TServices]:\n | ServiceFactory<TServices[index]>\n | (() => ServiceFactory<TServices[index]>)\n | [ServiceRef<TServices[index]>, Partial<TServices[index]>];\n },\n ];\n extensionPoints?: readonly [\n ...{\n [index in keyof TExtensionPoints]: [\n ExtensionPoint<TExtensionPoints[index]>,\n Partial<TExtensionPoints[index]>,\n ];\n },\n ];\n features?: BackendFeature[];\n}\n\n/** @alpha */\nexport interface TestBackend extends Backend {\n /**\n * Provides access to the underling HTTP server for use with utilities\n * such as `supertest`.\n *\n * If the root http router service has been replaced, this will throw an error.\n */\n readonly server: ExtendedHttpServer;\n}\n\nconst defaultServiceFactories = [\n mockServices.cache.factory(),\n mockServices.config.factory(),\n mockServices.database.factory(),\n mockServices.httpRouter.factory(),\n mockServices.identity.factory(),\n mockServices.lifecycle.factory(),\n mockServices.logger.factory(),\n mockServices.permissions.factory(),\n mockServices.rootLifecycle.factory(),\n mockServices.rootLogger.factory(),\n mockServices.scheduler.factory(),\n mockServices.tokenManager.factory(),\n mockServices.urlReader.factory(),\n];\n\nconst backendInstancesToCleanUp = new Array<Backend>();\n\n/** @alpha */\nexport async function startTestBackend<\n TServices extends any[],\n TExtensionPoints extends any[],\n>(\n options: TestBackendOptions<TServices, TExtensionPoints>,\n): Promise<TestBackend> {\n const {\n services = [],\n extensionPoints = [],\n features = [],\n ...otherOptions\n } = options;\n\n let server: ExtendedHttpServer;\n\n const rootHttpRouterFactory = createServiceFactory({\n service: coreServices.rootHttpRouter,\n deps: {\n config: coreServices.config,\n lifecycle: coreServices.rootLifecycle,\n rootLogger: coreServices.rootLogger,\n },\n async factory({ config, lifecycle, rootLogger }) {\n const router = DefaultRootHttpRouter.create();\n const logger = rootLogger.child({ service: 'rootHttpRouter' });\n\n const app = express();\n\n const middleware = MiddlewareFactory.create({ config, logger });\n\n app.use(router.handler());\n app.use(middleware.notFound());\n app.use(middleware.error());\n\n server = await createHttpServer(\n app,\n { listen: { host: '', port: 0 } },\n { logger },\n );\n\n lifecycle.addShutdownHook({\n async fn() {\n await server.stop();\n },\n logger,\n });\n\n await server.start();\n\n return router;\n },\n });\n\n const discoveryFactory = createServiceFactory({\n service: coreServices.discovery,\n deps: {\n rootHttpRouter: coreServices.rootHttpRouter,\n },\n async factory() {\n if (!server) {\n throw new Error('Test server not started yet');\n }\n const port = server.port();\n const discovery = SingleHostDiscovery.fromConfig(\n new ConfigReader({\n backend: { baseUrl: `http://localhost:${port}`, listen: { port } },\n }),\n );\n return discovery;\n },\n });\n\n const factories = services.map(serviceDef => {\n if (Array.isArray(serviceDef)) {\n // if type is ExtensionPoint?\n // do something differently?\n const [ref, impl] = serviceDef;\n if (ref.scope === 'plugin') {\n return createServiceFactory({\n service: ref as ServiceRef<unknown, 'plugin'>,\n deps: {},\n factory: async () => impl,\n })();\n }\n return createServiceFactory({\n service: ref as ServiceRef<unknown, 'root'>,\n deps: {},\n factory: async () => impl,\n })();\n }\n if (typeof serviceDef === 'function') {\n return serviceDef();\n }\n return serviceDef as ServiceFactory;\n });\n\n for (const factory of defaultServiceFactories) {\n if (!factories.some(f => f.service.id === factory.service.id)) {\n factories.push(factory);\n }\n }\n\n const backend = createSpecializedBackend({\n ...otherOptions,\n services: [...factories, rootHttpRouterFactory, discoveryFactory],\n });\n\n backendInstancesToCleanUp.push(backend);\n\n backend.add({\n id: `---test-extension-point-registrar`,\n register(reg) {\n for (const [ref, impl] of extensionPoints) {\n reg.registerExtensionPoint(ref, impl);\n }\n\n reg.registerInit({ deps: {}, async init() {} });\n },\n });\n\n for (const feature of features) {\n backend.add(feature);\n }\n\n await backend.start();\n\n return Object.assign(backend, {\n get server() {\n if (!server) {\n throw new Error('TestBackend server is not available');\n }\n return server;\n },\n });\n}\n\nlet registered = false;\nfunction registerTestHooks() {\n if (typeof afterAll !== 'function') {\n return;\n }\n if (registered) {\n return;\n }\n registered = true;\n\n afterAll(async () => {\n await Promise.all(\n backendInstancesToCleanUp.map(async backend => {\n try {\n await backend.stop();\n } catch (error) {\n console.error(`Failed to stop backend after tests, ${error}`);\n }\n }),\n );\n backendInstancesToCleanUp.length = 0;\n });\n}\n\nregisterTestHooks();\n"],"names":["createConnection","uuid","randomBytes","DatabaseManager","ConfigReader","createServiceFactory","mockServices","config","coreServices","rootLogger","tokenManager","identity","cache","cacheFactory","database","databaseFactory","httpRouter","httpRouterFactory","lifecycle","lifecycleFactory","logger","loggerFactory","permissions","permissionsFactory","rootLifecycle","rootLifecycleFactory","scheduler","schedulerFactory","urlReader","urlReaderFactory","DefaultRootHttpRouter","express","MiddlewareFactory","createHttpServer","SingleHostDiscovery","createSpecializedBackend"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/util/isDockerDisabledForTests.ts","../src/database/startMysqlContainer.ts","../src/database/startPostgresContainer.ts","../src/database/types.ts","../src/database/TestDatabases.ts","../src/msw/setupRequestMockHandlers.ts","../src/next/services/MockIdentityService.ts","../src/next/services/MockRootLoggerService.ts","../src/next/services/mockServices.ts","../src/next/wiring/TestBackend.ts"],"sourcesContent":["/*\n * Copyright 2021 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\n/** @public */\nexport function isDockerDisabledForTests() {\n // If we are not running in continuous integration, the default is to skip\n // the (relatively heavy, long running) docker based tests. If you want to\n // still run local tests for all databases, just pass either the CI=1 env\n // parameter to your test runner, or individual connection strings per\n // database.\n return (\n Boolean(process.env.BACKSTAGE_TEST_DISABLE_DOCKER) ||\n !Boolean(process.env.CI)\n );\n}\n","/*\n * Copyright 2021 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 createConnection, { Knex } from 'knex';\nimport { v4 as uuid } from 'uuid';\n\nasync function waitForMysqlReady(\n connection: Knex.MySqlConnectionConfig,\n): Promise<void> {\n const startTime = Date.now();\n const db = createConnection({ client: 'mysql2', connection });\n\n try {\n for (;;) {\n try {\n const result = await db.select(db.raw('version() AS version'));\n if (result[0]?.version) {\n return;\n }\n } catch (e) {\n if (Date.now() - startTime > 30_000) {\n throw new Error(\n `Timed out waiting for the database to be ready for connections, ${e}`,\n );\n }\n }\n\n await new Promise(resolve => setTimeout(resolve, 100));\n }\n } finally {\n db.destroy();\n }\n}\n\nexport async function startMysqlContainer(image: string) {\n const user = 'root';\n const password = uuid();\n\n // Lazy-load to avoid side-effect of importing testcontainers\n const { GenericContainer } = await import('testcontainers');\n\n const container = await new GenericContainer(image)\n .withExposedPorts(3306)\n .withEnv('MYSQL_ROOT_PASSWORD', password)\n .withTmpFs({ '/var/lib/mysql': 'rw' })\n .start();\n\n const host = container.getHost();\n const port = container.getMappedPort(3306);\n const stop = async () => {\n await container.stop({ timeout: 10_000 });\n };\n\n await waitForMysqlReady({ host, port, user, password });\n\n return { host, port, user, password, stop };\n}\n","/*\n * Copyright 2021 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 createConnection, { Knex } from 'knex';\nimport { v4 as uuid } from 'uuid';\n\nasync function waitForPostgresReady(\n connection: Knex.PgConnectionConfig,\n): Promise<void> {\n const startTime = Date.now();\n const db = createConnection({ client: 'pg', connection });\n\n try {\n for (;;) {\n try {\n const result = await db.select(db.raw('version()'));\n if (Array.isArray(result) && result[0]?.version) {\n return;\n }\n } catch (e) {\n if (Date.now() - startTime > 30_000) {\n throw new Error(\n `Timed out waiting for the database to be ready for connections, ${e}`,\n );\n }\n }\n\n await new Promise(resolve => setTimeout(resolve, 100));\n }\n } finally {\n db.destroy();\n }\n}\n\nexport async function startPostgresContainer(image: string) {\n const user = 'postgres';\n const password = uuid();\n\n // Lazy-load to avoid side-effect of importing testcontainers\n const { GenericContainer } = await import('testcontainers');\n\n const container = await new GenericContainer(image)\n .withExposedPorts(5432)\n .withEnv('POSTGRES_PASSWORD', password)\n .withTmpFs({ '/var/lib/postgresql/data': 'rw' })\n .start();\n\n const host = container.getHost();\n const port = container.getMappedPort(5432);\n const stop = async () => {\n await container.stop({ timeout: 10_000 });\n };\n\n await waitForPostgresReady({ host, port, user, password });\n\n return { host, port, user, password, stop };\n}\n","/*\n * Copyright 2021 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 { DatabaseManager } from '@backstage/backend-common';\nimport { Knex } from 'knex';\n\n/**\n * The possible databases to test against.\n *\n * @public\n */\nexport type TestDatabaseId =\n | 'POSTGRES_13'\n | 'POSTGRES_9'\n | 'MYSQL_8'\n | 'SQLITE_3';\n\nexport type TestDatabaseProperties = {\n name: string;\n driver: string;\n dockerImageName?: string;\n connectionStringEnvironmentVariableName?: string;\n};\n\nexport type Instance = {\n stopContainer?: () => Promise<void>;\n databaseManager: DatabaseManager;\n connections: Array<Knex>;\n};\n\nexport const allDatabases: Record<TestDatabaseId, TestDatabaseProperties> =\n Object.freeze({\n POSTGRES_13: {\n name: 'Postgres 13.x',\n driver: 'pg',\n dockerImageName: 'postgres:13',\n connectionStringEnvironmentVariableName:\n 'BACKSTAGE_TEST_DATABASE_POSTGRES13_CONNECTION_STRING',\n },\n POSTGRES_9: {\n name: 'Postgres 9.x',\n driver: 'pg',\n dockerImageName: 'postgres:9',\n connectionStringEnvironmentVariableName:\n 'BACKSTAGE_TEST_DATABASE_POSTGRES9_CONNECTION_STRING',\n },\n MYSQL_8: {\n name: 'MySQL 8.x',\n driver: 'mysql2',\n dockerImageName: 'mysql:8',\n connectionStringEnvironmentVariableName:\n 'BACKSTAGE_TEST_DATABASE_MYSQL8_CONNECTION_STRING',\n },\n SQLITE_3: {\n name: 'SQLite 3.x',\n driver: 'better-sqlite3',\n },\n });\n","/*\n * Copyright 2021 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 { DatabaseManager } from '@backstage/backend-common';\nimport { ConfigReader } from '@backstage/config';\nimport { randomBytes } from 'crypto';\nimport { Knex } from 'knex';\nimport { isDockerDisabledForTests } from '../util/isDockerDisabledForTests';\nimport { startMysqlContainer } from './startMysqlContainer';\nimport { startPostgresContainer } from './startPostgresContainer';\nimport {\n allDatabases,\n Instance,\n TestDatabaseId,\n TestDatabaseProperties,\n} from './types';\n\nconst LARGER_POOL_CONFIG = {\n pool: {\n min: 0,\n max: 50,\n },\n};\n\n/**\n * Encapsulates the creation of ephemeral test database instances for use\n * inside unit or integration tests.\n *\n * @public\n */\nexport class TestDatabases {\n private readonly instanceById: Map<string, Instance>;\n private readonly supportedIds: TestDatabaseId[];\n\n /**\n * Creates an empty `TestDatabases` instance, and sets up Jest to clean up\n * all of its acquired resources after all tests finish.\n *\n * You typically want to create just a single instance like this at the top\n * of your test file or `describe` block, and then call `init` many times on\n * that instance inside the individual tests. Spinning up a \"physical\"\n * database instance takes a considerable amount of time, slowing down tests.\n * But initializing a new logical database inside that instance using `init`\n * is very fast.\n */\n static create(options?: {\n ids?: TestDatabaseId[];\n disableDocker?: boolean;\n }): TestDatabases {\n const defaultOptions = {\n ids: Object.keys(allDatabases) as TestDatabaseId[],\n disableDocker: isDockerDisabledForTests(),\n };\n\n const { ids, disableDocker } = Object.assign(\n {},\n defaultOptions,\n options ?? {},\n );\n\n const supportedIds = ids.filter(id => {\n const properties = allDatabases[id];\n if (!properties) {\n return false;\n }\n // If the caller has set up the env with an explicit connection string,\n // we'll assume that this database will work\n if (\n properties.connectionStringEnvironmentVariableName &&\n process.env[properties.connectionStringEnvironmentVariableName]\n ) {\n return true;\n }\n // If the database doesn't require docker at all, there's nothing to worry\n // about\n if (!properties.dockerImageName) {\n return true;\n }\n // If the database requires docker, but docker is disabled, we will fail.\n if (disableDocker) {\n return false;\n }\n return true;\n });\n\n const databases = new TestDatabases(supportedIds);\n\n if (supportedIds.length > 0) {\n afterAll(async () => {\n await databases.shutdown();\n });\n }\n\n return databases;\n }\n\n private constructor(supportedIds: TestDatabaseId[]) {\n this.instanceById = new Map();\n this.supportedIds = supportedIds;\n }\n\n supports(id: TestDatabaseId): boolean {\n return this.supportedIds.includes(id);\n }\n\n eachSupportedId(): [TestDatabaseId][] {\n return this.supportedIds.map(id => [id]);\n }\n\n /**\n * Returns a fresh, unique, empty logical database on an instance of the\n * given database ID platform.\n *\n * @param id - The ID of the database platform to use, e.g. 'POSTGRES_13'\n * @returns A `Knex` connection object\n */\n async init(id: TestDatabaseId): Promise<Knex> {\n const properties = allDatabases[id];\n if (!properties) {\n const candidates = Object.keys(allDatabases).join(', ');\n throw new Error(\n `Unknown test database ${id}, possible values are ${candidates}`,\n );\n }\n if (!this.supportedIds.includes(id)) {\n const candidates = this.supportedIds.join(', ');\n throw new Error(\n `Unsupported test database ${id} for this environment, possible values are ${candidates}`,\n );\n }\n\n let instance: Instance | undefined = this.instanceById.get(id);\n\n // Ensure that a testcontainers instance is up for this ID\n if (!instance) {\n instance = await this.initAny(properties);\n this.instanceById.set(id, instance);\n }\n\n // Ensure that a unique logical database is created in the instance\n const connection = await instance.databaseManager\n .forPlugin(`db${randomBytes(16).toString('hex')}`)\n .getClient();\n\n instance.connections.push(connection);\n\n return connection;\n }\n\n private async initAny(properties: TestDatabaseProperties): Promise<Instance> {\n // Use the connection string if provided\n if (properties.driver === 'pg' || properties.driver === 'mysql2') {\n const envVarName = properties.connectionStringEnvironmentVariableName;\n if (envVarName) {\n const connectionString = process.env[envVarName];\n if (connectionString) {\n const databaseManager = DatabaseManager.fromConfig(\n new ConfigReader({\n backend: {\n database: {\n knexConfig: properties.driver.includes('sqlite')\n ? {}\n : LARGER_POOL_CONFIG,\n client: properties.driver,\n connection: connectionString,\n },\n },\n }),\n );\n return {\n databaseManager,\n connections: [],\n };\n }\n }\n }\n\n // Otherwise start a container for the purpose\n switch (properties.driver) {\n case 'pg':\n return this.initPostgres(properties);\n case 'mysql2':\n return this.initMysql(properties);\n case 'better-sqlite3':\n case 'sqlite3':\n return this.initSqlite(properties);\n default:\n throw new Error(`Unknown database driver ${properties.driver}`);\n }\n }\n\n private async initPostgres(\n properties: TestDatabaseProperties,\n ): Promise<Instance> {\n const { host, port, user, password, stop } = await startPostgresContainer(\n properties.dockerImageName!,\n );\n\n const databaseManager = DatabaseManager.fromConfig(\n new ConfigReader({\n backend: {\n database: {\n knexConfig: LARGER_POOL_CONFIG,\n client: 'pg',\n connection: { host, port, user, password },\n },\n },\n }),\n );\n\n return {\n stopContainer: stop,\n databaseManager,\n connections: [],\n };\n }\n\n private async initMysql(\n properties: TestDatabaseProperties,\n ): Promise<Instance> {\n const { host, port, user, password, stop } = await startMysqlContainer(\n properties.dockerImageName!,\n );\n\n const databaseManager = DatabaseManager.fromConfig(\n new ConfigReader({\n backend: {\n database: {\n knexConfig: LARGER_POOL_CONFIG,\n client: 'mysql2',\n connection: { host, port, user, password },\n },\n },\n }),\n );\n\n return {\n stopContainer: stop,\n databaseManager,\n connections: [],\n };\n }\n\n private async initSqlite(\n properties: TestDatabaseProperties,\n ): Promise<Instance> {\n const databaseManager = DatabaseManager.fromConfig(\n new ConfigReader({\n backend: {\n database: {\n client: properties.driver,\n connection: ':memory:',\n },\n },\n }),\n );\n\n return {\n databaseManager,\n connections: [],\n };\n }\n\n private async shutdown() {\n const instances = [...this.instanceById.values()];\n await Promise.all(\n instances.map(async ({ stopContainer, connections }) => {\n try {\n await Promise.all(connections.map(c => c.destroy()));\n } catch {\n // ignore\n }\n try {\n await stopContainer?.();\n } catch {\n // ignore\n }\n }),\n );\n }\n}\n","/*\n * Copyright 2020 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\n/**\n * Sets up handlers for request mocking\n * @public\n * @param worker - service worker\n */\nexport function setupRequestMockHandlers(worker: {\n listen: (t: any) => void;\n close: () => void;\n resetHandlers: () => void;\n}) {\n beforeAll(() => worker.listen({ onUnhandledRequest: 'error' }));\n afterAll(() => worker.close());\n afterEach(() => worker.resetHandlers());\n}\n","/*\n * Copyright 2023 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 { IdentityService } from '@backstage/backend-plugin-api';\nimport {\n IdentityApiGetIdentityRequest,\n BackstageIdentityResponse,\n} from '@backstage/plugin-auth-node';\n\nexport class MockIdentityService implements IdentityService {\n getIdentity(\n _options: IdentityApiGetIdentityRequest,\n ): Promise<BackstageIdentityResponse | undefined> {\n return Promise.resolve({\n token: 'mock-token',\n identity: {\n type: 'user',\n userEntityRef: 'user:default/mock-user',\n ownershipEntityRefs: [],\n },\n });\n }\n}\n","/*\n * Copyright 2023 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 {\n LoggerService,\n RootLoggerService,\n} from '@backstage/backend-plugin-api';\nimport { JsonObject } from '@backstage/types';\nimport type { mockServices } from './mockServices';\n\nconst levels = {\n none: 0,\n error: 1,\n warn: 2,\n info: 3,\n debug: 4,\n};\n\nexport class MockRootLoggerService implements RootLoggerService {\n #level: number;\n #meta: JsonObject;\n\n static create(\n options?: mockServices.rootLogger.Options,\n ): MockRootLoggerService {\n const level = options?.level ?? 'none';\n if (!(level in levels)) {\n throw new Error(`Invalid log level '${level}'`);\n }\n return new MockRootLoggerService(levels[level], {});\n }\n\n error(message: string, meta?: JsonObject | Error | undefined): void {\n this.#log('error', message, meta);\n }\n\n warn(message: string, meta?: JsonObject | Error | undefined): void {\n this.#log('warn', message, meta);\n }\n\n info(message: string, meta?: JsonObject | Error | undefined): void {\n this.#log('info', message, meta);\n }\n\n debug(message: string, meta?: JsonObject | Error | undefined): void {\n this.#log('debug', message, meta);\n }\n\n child(meta: JsonObject): LoggerService {\n return new MockRootLoggerService(this.#level, { ...this.#meta, ...meta });\n }\n\n private constructor(level: number, meta: JsonObject) {\n this.#level = level;\n this.#meta = meta;\n }\n\n #log(\n level: 'error' | 'warn' | 'info' | 'debug',\n message: string,\n meta?: JsonObject | Error | undefined,\n ) {\n const levelValue = levels[level] ?? 0;\n if (levelValue <= this.#level) {\n const labels = Object.entries(this.#meta)\n .map(([key, value]) => `${key}=${value}`)\n .join(',');\n console[level](`${labels} ${message}`, meta);\n }\n }\n}\n","/*\n * Copyright 2023 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 {\n ConfigService,\n coreServices,\n createServiceFactory,\n IdentityService,\n LoggerService,\n ServiceFactory,\n ServiceRef,\n TokenManagerService,\n} from '@backstage/backend-plugin-api';\nimport {\n cacheServiceFactory,\n databaseServiceFactory,\n httpRouterServiceFactory,\n lifecycleServiceFactory,\n loggerServiceFactory,\n permissionsServiceFactory,\n rootLifecycleServiceFactory,\n schedulerServiceFactory,\n urlReaderServiceFactory,\n} from '@backstage/backend-app-api';\nimport { ConfigReader } from '@backstage/config';\nimport { JsonObject } from '@backstage/types';\nimport { MockIdentityService } from './MockIdentityService';\nimport { MockRootLoggerService } from './MockRootLoggerService';\n\nfunction simpleFactory<\n TService,\n TScope extends 'root' | 'plugin',\n TOptions extends [options?: object] = [],\n>(\n ref: ServiceRef<TService, TScope>,\n factory: (...options: TOptions) => TService,\n): (...options: TOptions) => ServiceFactory<TService, TScope> {\n return createServiceFactory((options: unknown) => ({\n service: ref as ServiceRef<TService, any>,\n deps: {},\n async factory() {\n return (factory as any)(options);\n },\n })) as (...options: TOptions) => ServiceFactory<TService, any>;\n}\n\n/**\n * @public\n */\nexport namespace mockServices {\n export function config(options?: config.Options): ConfigService {\n return new ConfigReader(options?.data, 'mock-config');\n }\n export namespace config {\n export type Options = { data?: JsonObject };\n\n export const factory = simpleFactory(coreServices.config, config);\n }\n\n export function rootLogger(options?: rootLogger.Options): LoggerService {\n return MockRootLoggerService.create(options);\n }\n export namespace rootLogger {\n export type Options = {\n level?: 'none' | 'error' | 'warn' | 'info' | 'debug';\n };\n\n export const factory = simpleFactory(coreServices.rootLogger, rootLogger);\n }\n\n export function tokenManager(): TokenManagerService {\n return {\n async getToken(): Promise<{ token: string }> {\n return { token: 'mock-token' };\n },\n async authenticate(token: string): Promise<void> {\n if (token !== 'mock-token') {\n throw new Error('Invalid token');\n }\n },\n };\n }\n export namespace tokenManager {\n export const factory = simpleFactory(\n coreServices.tokenManager,\n tokenManager,\n );\n }\n\n export function identity(): IdentityService {\n return new MockIdentityService();\n }\n export namespace identity {\n export const factory = simpleFactory(coreServices.identity, identity);\n }\n\n // TODO(Rugvip): Not all core services have implementations available here yet.\n // some may need a bit more refactoring for it to be simpler to\n // re-implement functioning mock versions here.\n export namespace cache {\n export const factory = cacheServiceFactory;\n }\n export namespace database {\n export const factory = databaseServiceFactory;\n }\n export namespace httpRouter {\n export const factory = httpRouterServiceFactory;\n }\n export namespace lifecycle {\n export const factory = lifecycleServiceFactory;\n }\n export namespace logger {\n export const factory = loggerServiceFactory;\n }\n export namespace permissions {\n export const factory = permissionsServiceFactory;\n }\n export namespace rootLifecycle {\n export const factory = rootLifecycleServiceFactory;\n }\n export namespace scheduler {\n export const factory = schedulerServiceFactory;\n }\n export namespace urlReader {\n export const factory = urlReaderServiceFactory;\n }\n}\n","/*\n * Copyright 2022 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 {\n Backend,\n createSpecializedBackend,\n MiddlewareFactory,\n createHttpServer,\n ExtendedHttpServer,\n DefaultRootHttpRouter,\n} from '@backstage/backend-app-api';\nimport { SingleHostDiscovery } from '@backstage/backend-common';\nimport {\n ServiceFactory,\n ServiceRef,\n createServiceFactory,\n BackendFeature,\n ExtensionPoint,\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { mockServices } from '../services';\nimport { ConfigReader } from '@backstage/config';\nimport express from 'express';\n\n/** @public */\nexport interface TestBackendOptions<\n TServices extends any[],\n TExtensionPoints extends any[],\n> {\n services?: readonly [\n ...{\n [index in keyof TServices]:\n | ServiceFactory<TServices[index]>\n | (() => ServiceFactory<TServices[index]>)\n | [ServiceRef<TServices[index]>, Partial<TServices[index]>];\n },\n ];\n extensionPoints?: readonly [\n ...{\n [index in keyof TExtensionPoints]: [\n ExtensionPoint<TExtensionPoints[index]>,\n Partial<TExtensionPoints[index]>,\n ];\n },\n ];\n features?: BackendFeature[];\n}\n\n/** @public */\nexport interface TestBackend extends Backend {\n /**\n * Provides access to the underling HTTP server for use with utilities\n * such as `supertest`.\n *\n * If the root http router service has been replaced, this will throw an error.\n */\n readonly server: ExtendedHttpServer;\n}\n\nconst defaultServiceFactories = [\n mockServices.cache.factory(),\n mockServices.config.factory(),\n mockServices.database.factory(),\n mockServices.httpRouter.factory(),\n mockServices.identity.factory(),\n mockServices.lifecycle.factory(),\n mockServices.logger.factory(),\n mockServices.permissions.factory(),\n mockServices.rootLifecycle.factory(),\n mockServices.rootLogger.factory(),\n mockServices.scheduler.factory(),\n mockServices.tokenManager.factory(),\n mockServices.urlReader.factory(),\n];\n\nconst backendInstancesToCleanUp = new Array<Backend>();\n\n/** @public */\nexport async function startTestBackend<\n TServices extends any[],\n TExtensionPoints extends any[],\n>(\n options: TestBackendOptions<TServices, TExtensionPoints>,\n): Promise<TestBackend> {\n const {\n services = [],\n extensionPoints = [],\n features = [],\n ...otherOptions\n } = options;\n\n let server: ExtendedHttpServer;\n\n const rootHttpRouterFactory = createServiceFactory({\n service: coreServices.rootHttpRouter,\n deps: {\n config: coreServices.config,\n lifecycle: coreServices.rootLifecycle,\n rootLogger: coreServices.rootLogger,\n },\n async factory({ config, lifecycle, rootLogger }) {\n const router = DefaultRootHttpRouter.create();\n const logger = rootLogger.child({ service: 'rootHttpRouter' });\n\n const app = express();\n\n const middleware = MiddlewareFactory.create({ config, logger });\n\n app.use(router.handler());\n app.use(middleware.notFound());\n app.use(middleware.error());\n\n server = await createHttpServer(\n app,\n { listen: { host: '', port: 0 } },\n { logger },\n );\n\n lifecycle.addShutdownHook(() => server.stop(), { logger });\n\n await server.start();\n\n return router;\n },\n });\n\n const discoveryFactory = createServiceFactory({\n service: coreServices.discovery,\n deps: {\n rootHttpRouter: coreServices.rootHttpRouter,\n },\n async factory() {\n if (!server) {\n throw new Error('Test server not started yet');\n }\n const port = server.port();\n const discovery = SingleHostDiscovery.fromConfig(\n new ConfigReader({\n backend: { baseUrl: `http://localhost:${port}`, listen: { port } },\n }),\n );\n return discovery;\n },\n });\n\n const factories = services.map(serviceDef => {\n if (Array.isArray(serviceDef)) {\n // if type is ExtensionPoint?\n // do something differently?\n const [ref, impl] = serviceDef;\n if (ref.scope === 'plugin') {\n return createServiceFactory({\n service: ref as ServiceRef<unknown, 'plugin'>,\n deps: {},\n factory: async () => impl,\n })();\n }\n return createServiceFactory({\n service: ref as ServiceRef<unknown, 'root'>,\n deps: {},\n factory: async () => impl,\n })();\n }\n if (typeof serviceDef === 'function') {\n return serviceDef();\n }\n return serviceDef as ServiceFactory;\n });\n\n for (const factory of defaultServiceFactories) {\n if (!factories.some(f => f.service.id === factory.service.id)) {\n factories.push(factory);\n }\n }\n\n const backend = createSpecializedBackend({\n ...otherOptions,\n services: [...factories, rootHttpRouterFactory, discoveryFactory],\n });\n\n backendInstancesToCleanUp.push(backend);\n\n backend.add(\n createBackendPlugin({\n pluginId: `---test-extension-point-registrar`,\n register(reg) {\n for (const [ref, impl] of extensionPoints) {\n reg.registerExtensionPoint(ref, impl);\n }\n\n reg.registerInit({ deps: {}, async init() {} });\n },\n })(),\n );\n\n for (const feature of features) {\n backend.add(feature);\n }\n\n await backend.start();\n\n return Object.assign(backend, {\n get server() {\n if (!server) {\n throw new Error('TestBackend server is not available');\n }\n return server;\n },\n });\n}\n\nlet registered = false;\nfunction registerTestHooks() {\n if (typeof afterAll !== 'function') {\n return;\n }\n if (registered) {\n return;\n }\n registered = true;\n\n afterAll(async () => {\n await Promise.all(\n backendInstancesToCleanUp.map(async backend => {\n try {\n await backend.stop();\n } catch (error) {\n console.error(`Failed to stop backend after tests, ${error}`);\n }\n }),\n );\n backendInstancesToCleanUp.length = 0;\n });\n}\n\nregisterTestHooks();\n"],"names":["createConnection","uuid","randomBytes","DatabaseManager","ConfigReader","createServiceFactory","mockServices","config","coreServices","rootLogger","tokenManager","identity","cache","cacheServiceFactory","database","databaseServiceFactory","httpRouter","httpRouterServiceFactory","lifecycle","lifecycleServiceFactory","logger","loggerServiceFactory","permissions","permissionsServiceFactory","rootLifecycle","rootLifecycleServiceFactory","scheduler","schedulerServiceFactory","urlReader","urlReaderServiceFactory","DefaultRootHttpRouter","express","MiddlewareFactory","createHttpServer","SingleHostDiscovery","createSpecializedBackend","createBackendPlugin"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
import { Backend } from '@backstage/backend-app-api';
|
|
8
8
|
import { BackendFeature } from '@backstage/backend-plugin-api';
|
|
9
9
|
import { CacheService } from '@backstage/backend-plugin-api';
|
|
10
|
-
import { ConfigReader } from '@backstage/config';
|
|
11
10
|
import { ConfigService } from '@backstage/backend-plugin-api';
|
|
12
11
|
import { DatabaseService } from '@backstage/backend-plugin-api';
|
|
13
12
|
import { ExtendedHttpServer } from '@backstage/backend-app-api';
|
|
@@ -21,7 +20,6 @@ import { LifecycleService } from '@backstage/backend-plugin-api';
|
|
|
21
20
|
import { LoggerService } from '@backstage/backend-plugin-api';
|
|
22
21
|
import { PermissionsService } from '@backstage/backend-plugin-api';
|
|
23
22
|
import { RootLifecycleService } from '@backstage/backend-plugin-api';
|
|
24
|
-
import { RootLoggerService } from '@backstage/backend-plugin-api';
|
|
25
23
|
import { SchedulerService } from '@backstage/backend-plugin-api';
|
|
26
24
|
import { ServiceFactory } from '@backstage/backend-plugin-api';
|
|
27
25
|
import { ServiceRef } from '@backstage/backend-plugin-api';
|
|
@@ -31,7 +29,60 @@ import { UrlReaderService } from '@backstage/backend-plugin-api';
|
|
|
31
29
|
/** @public */
|
|
32
30
|
export declare function isDockerDisabledForTests(): boolean;
|
|
33
31
|
|
|
34
|
-
|
|
32
|
+
/**
|
|
33
|
+
* @public
|
|
34
|
+
*/
|
|
35
|
+
export declare namespace mockServices {
|
|
36
|
+
export function config(options?: config.Options): ConfigService;
|
|
37
|
+
export namespace config {
|
|
38
|
+
export type Options = {
|
|
39
|
+
data?: JsonObject;
|
|
40
|
+
};
|
|
41
|
+
const factory: (options?: Options | undefined) => ServiceFactory<ConfigService, "root">;
|
|
42
|
+
}
|
|
43
|
+
export function rootLogger(options?: rootLogger.Options): LoggerService;
|
|
44
|
+
export namespace rootLogger {
|
|
45
|
+
export type Options = {
|
|
46
|
+
level?: 'none' | 'error' | 'warn' | 'info' | 'debug';
|
|
47
|
+
};
|
|
48
|
+
const factory: (options?: Options | undefined) => ServiceFactory<LoggerService, "root">;
|
|
49
|
+
}
|
|
50
|
+
export function tokenManager(): TokenManagerService;
|
|
51
|
+
export namespace tokenManager {
|
|
52
|
+
const factory: () => ServiceFactory<TokenManagerService, "plugin">;
|
|
53
|
+
}
|
|
54
|
+
export function identity(): IdentityService;
|
|
55
|
+
export namespace identity {
|
|
56
|
+
const factory: () => ServiceFactory<IdentityService, "plugin">;
|
|
57
|
+
}
|
|
58
|
+
export namespace cache {
|
|
59
|
+
const factory: () => ServiceFactory<CacheService, "plugin">;
|
|
60
|
+
}
|
|
61
|
+
export namespace database {
|
|
62
|
+
const factory: () => ServiceFactory<DatabaseService, "plugin">;
|
|
63
|
+
}
|
|
64
|
+
export namespace httpRouter {
|
|
65
|
+
const factory: (options?: HttpRouterFactoryOptions | undefined) => ServiceFactory<HttpRouterService, "plugin">;
|
|
66
|
+
}
|
|
67
|
+
export namespace lifecycle {
|
|
68
|
+
const factory: () => ServiceFactory<LifecycleService, "plugin">;
|
|
69
|
+
}
|
|
70
|
+
export namespace logger {
|
|
71
|
+
const factory: () => ServiceFactory<LoggerService, "plugin">;
|
|
72
|
+
}
|
|
73
|
+
export namespace permissions {
|
|
74
|
+
const factory: () => ServiceFactory<PermissionsService, "plugin">;
|
|
75
|
+
}
|
|
76
|
+
export namespace rootLifecycle {
|
|
77
|
+
const factory: () => ServiceFactory<RootLifecycleService, "root">;
|
|
78
|
+
}
|
|
79
|
+
export namespace scheduler {
|
|
80
|
+
const factory: () => ServiceFactory<SchedulerService, "plugin">;
|
|
81
|
+
}
|
|
82
|
+
export namespace urlReader {
|
|
83
|
+
const factory: () => ServiceFactory<UrlReaderService, "plugin">;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
35
86
|
|
|
36
87
|
/**
|
|
37
88
|
* Sets up handlers for request mocking
|
|
@@ -44,11 +95,37 @@ export declare function setupRequestMockHandlers(worker: {
|
|
|
44
95
|
resetHandlers: () => void;
|
|
45
96
|
}): void;
|
|
46
97
|
|
|
47
|
-
|
|
98
|
+
/** @public */
|
|
99
|
+
export declare function startTestBackend<TServices extends any[], TExtensionPoints extends any[]>(options: TestBackendOptions<TServices, TExtensionPoints>): Promise<TestBackend>;
|
|
48
100
|
|
|
49
|
-
|
|
101
|
+
/** @public */
|
|
102
|
+
export declare interface TestBackend extends Backend {
|
|
103
|
+
/**
|
|
104
|
+
* Provides access to the underling HTTP server for use with utilities
|
|
105
|
+
* such as `supertest`.
|
|
106
|
+
*
|
|
107
|
+
* If the root http router service has been replaced, this will throw an error.
|
|
108
|
+
*/
|
|
109
|
+
readonly server: ExtendedHttpServer;
|
|
110
|
+
}
|
|
50
111
|
|
|
51
|
-
|
|
112
|
+
/** @public */
|
|
113
|
+
export declare interface TestBackendOptions<TServices extends any[], TExtensionPoints extends any[]> {
|
|
114
|
+
services?: readonly [
|
|
115
|
+
...{
|
|
116
|
+
[index in keyof TServices]: ServiceFactory<TServices[index]> | (() => ServiceFactory<TServices[index]>) | [ServiceRef<TServices[index]>, Partial<TServices[index]>];
|
|
117
|
+
}
|
|
118
|
+
];
|
|
119
|
+
extensionPoints?: readonly [
|
|
120
|
+
...{
|
|
121
|
+
[index in keyof TExtensionPoints]: [
|
|
122
|
+
ExtensionPoint<TExtensionPoints[index]>,
|
|
123
|
+
Partial<TExtensionPoints[index]>
|
|
124
|
+
];
|
|
125
|
+
}
|
|
126
|
+
];
|
|
127
|
+
features?: BackendFeature[];
|
|
128
|
+
}
|
|
52
129
|
|
|
53
130
|
/**
|
|
54
131
|
* The possible databases to test against.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/backend-test-utils",
|
|
3
3
|
"description": "Test helpers library for Backstage backends",
|
|
4
|
-
"version": "0.1.34
|
|
4
|
+
"version": "0.1.34",
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"publishConfig": {
|
|
@@ -34,12 +34,11 @@
|
|
|
34
34
|
"start": "backstage-cli package start"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@backstage/backend-app-api": "^0.
|
|
38
|
-
"@backstage/backend-common": "^0.18.2
|
|
39
|
-
"@backstage/backend-plugin-api": "^0.
|
|
40
|
-
"@backstage/cli": "^0.22.2-next.0",
|
|
37
|
+
"@backstage/backend-app-api": "^0.4.0",
|
|
38
|
+
"@backstage/backend-common": "^0.18.2",
|
|
39
|
+
"@backstage/backend-plugin-api": "^0.4.0",
|
|
41
40
|
"@backstage/config": "^1.0.6",
|
|
42
|
-
"@backstage/plugin-auth-node": "^0.2.11
|
|
41
|
+
"@backstage/plugin-auth-node": "^0.2.11",
|
|
43
42
|
"@backstage/types": "^1.0.2",
|
|
44
43
|
"better-sqlite3": "^8.0.0",
|
|
45
44
|
"express": "^4.17.1",
|
|
@@ -51,7 +50,7 @@
|
|
|
51
50
|
"uuid": "^8.0.0"
|
|
52
51
|
},
|
|
53
52
|
"devDependencies": {
|
|
54
|
-
"@backstage/cli": "^0.22.2
|
|
53
|
+
"@backstage/cli": "^0.22.2",
|
|
55
54
|
"@types/supertest": "^2.0.8",
|
|
56
55
|
"supertest": "^6.1.3"
|
|
57
56
|
},
|