From 1fbad39b2deeb156085052c7b675fc991b0a31ab Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 17 Aug 2023 16:50:45 +0200 Subject: [PATCH] backend-test-utils: introduce ServiceMock type to clean up external API Signed-off-by: Patrik Oldsberg --- packages/backend-test-utils/api-report.md | 286 +++--------------- .../src/next/services/index.ts | 2 +- .../src/next/services/mockServices.ts | 18 +- 3 files changed, 63 insertions(+), 243 deletions(-) diff --git a/packages/backend-test-utils/api-report.md b/packages/backend-test-utils/api-report.md index f87181f635..95f67da35f 100644 --- a/packages/backend-test-utils/api-report.md +++ b/packages/backend-test-utils/api-report.md @@ -5,50 +5,25 @@ ```ts /// -import { AuthorizePermissionRequest } from '@backstage/plugin-permission-common'; import { Backend } from '@backstage/backend-app-api'; import { BackendFeature } from '@backstage/backend-plugin-api'; -import { BackstageIdentityResponse } from '@backstage/plugin-auth-node'; import { CacheService } from '@backstage/backend-plugin-api'; -import { CacheServiceOptions } from '@backstage/backend-plugin-api'; -import { CacheServiceSetOptions } from '@backstage/backend-plugin-api'; import { DatabaseService } from '@backstage/backend-plugin-api'; -import { DefinitivePolicyDecision } from '@backstage/plugin-permission-common'; -import { EvaluatorRequestOptions } from '@backstage/plugin-permission-common'; import { ExtendedHttpServer } from '@backstage/backend-app-api'; import { ExtensionPoint } from '@backstage/backend-plugin-api'; -import { Handler } from 'express'; import { HttpRouterFactoryOptions } from '@backstage/backend-app-api'; import { HttpRouterService } from '@backstage/backend-plugin-api'; -import { IdentityApiGetIdentityRequest } from '@backstage/plugin-auth-node'; import { IdentityService } from '@backstage/backend-plugin-api'; import { JsonObject } from '@backstage/types'; -import { JsonValue } from '@backstage/types'; import { Knex } from 'knex'; import { LifecycleService } from '@backstage/backend-plugin-api'; -import { LifecycleServiceShutdownHook } from '@backstage/backend-plugin-api'; -import { LifecycleServiceShutdownOptions } from '@backstage/backend-plugin-api'; -import { LifecycleServiceStartupHook } from '@backstage/backend-plugin-api'; -import { LifecycleServiceStartupOptions } from '@backstage/backend-plugin-api'; import { LoggerService } from '@backstage/backend-plugin-api'; import { PermissionsService } from '@backstage/backend-plugin-api'; -import { PolicyDecision } from '@backstage/plugin-permission-common'; -import { QueryPermissionRequest } from '@backstage/plugin-permission-common'; -import { ReadTreeOptions } from '@backstage/backend-plugin-api'; -import { ReadTreeResponse } from '@backstage/backend-plugin-api'; -import { ReadUrlOptions } from '@backstage/backend-plugin-api'; -import { ReadUrlResponse } from '@backstage/backend-plugin-api'; import { RootConfigService } from '@backstage/backend-plugin-api'; import { RootLifecycleService } from '@backstage/backend-plugin-api'; import { RootLoggerService } from '@backstage/backend-plugin-api'; import { SchedulerService } from '@backstage/backend-plugin-api'; -import { SearchOptions } from '@backstage/backend-plugin-api'; -import { SearchResponse } from '@backstage/backend-plugin-api'; import { ServiceFactory } from '@backstage/backend-plugin-api'; -import { TaskDescriptor } from '@backstage/backend-tasks'; -import { TaskInvocationDefinition } from '@backstage/backend-tasks'; -import { TaskRunner } from '@backstage/backend-tasks'; -import { TaskScheduleDefinition } from '@backstage/backend-tasks'; import { TokenManagerService } from '@backstage/backend-plugin-api'; import { UrlReaderService } from '@backstage/backend-plugin-api'; @@ -62,46 +37,18 @@ export namespace mockServices { const // (undocumented) factory: () => ServiceFactory; const // (undocumented) - mock: (partialImpl?: Partial | undefined) => { - factory: ServiceFactory; - } & { - get: jest.MockInstance< - Promise, - [key: string], - unknown - >; - set: jest.MockInstance< - Promise, - [ - key: string, - value: JsonValue, - options?: CacheServiceSetOptions | undefined, - ], - unknown - >; - delete: jest.MockInstance, [key: string], unknown>; - withOptions: jest.MockInstance< - CacheService, - [options: CacheServiceOptions], - unknown - >; - } & CacheService; + mock: ( + partialImpl?: Partial | undefined, + ) => ServiceMock; } // (undocumented) export namespace database { const // (undocumented) factory: () => ServiceFactory; const // (undocumented) - mock: (partialImpl?: Partial | undefined) => { - factory: ServiceFactory; - } & { - getClient: jest.MockInstance>, [], unknown>; - migrations?: - | { - skip?: boolean | undefined; - } - | undefined; - } & DatabaseService; + mock: ( + partialImpl?: Partial | undefined, + ) => ServiceMock; } // (undocumented) export namespace httpRouter { @@ -110,11 +57,9 @@ export namespace mockServices { options?: HttpRouterFactoryOptions | undefined, ) => ServiceFactory; const // (undocumented) - mock: (partialImpl?: Partial | undefined) => { - factory: ServiceFactory; - } & { - use: jest.MockInstance; - } & HttpRouterService; + mock: ( + partialImpl?: Partial | undefined, + ) => ServiceMock; } // (undocumented) export function identity(): IdentityService; @@ -123,98 +68,36 @@ export namespace mockServices { const // (undocumented) factory: () => ServiceFactory; const // (undocumented) - mock: (partialImpl?: Partial | undefined) => { - factory: ServiceFactory; - } & { - getIdentity: jest.MockInstance< - Promise, - [options: IdentityApiGetIdentityRequest], - unknown - >; - } & IdentityService; + mock: ( + partialImpl?: Partial | undefined, + ) => ServiceMock; } // (undocumented) export namespace lifecycle { const // (undocumented) factory: () => ServiceFactory; const // (undocumented) - mock: (partialImpl?: Partial | undefined) => { - factory: ServiceFactory; - } & { - addStartupHook: jest.MockInstance< - void, - [ - hook: LifecycleServiceStartupHook, - options?: LifecycleServiceStartupOptions | undefined, - ], - unknown - >; - addShutdownHook: jest.MockInstance< - void, - [ - hook: LifecycleServiceShutdownHook, - options?: LifecycleServiceShutdownOptions | undefined, - ], - unknown - >; - } & LifecycleService; + mock: ( + partialImpl?: Partial | undefined, + ) => ServiceMock; } // (undocumented) export namespace logger { const // (undocumented) factory: () => ServiceFactory; const // (undocumented) - mock: (partialImpl?: Partial | undefined) => { - factory: ServiceFactory; - } & { - error: jest.MockInstance< - void, - [message: string, meta?: Error | JsonObject | undefined], - unknown - >; - warn: jest.MockInstance< - void, - [message: string, meta?: Error | JsonObject | undefined], - unknown - >; - info: jest.MockInstance< - void, - [message: string, meta?: Error | JsonObject | undefined], - unknown - >; - debug: jest.MockInstance< - void, - [message: string, meta?: Error | JsonObject | undefined], - unknown - >; - child: jest.MockInstance; - } & LoggerService; + mock: ( + partialImpl?: Partial | undefined, + ) => ServiceMock; } // (undocumented) export namespace permissions { const // (undocumented) factory: () => ServiceFactory; const // (undocumented) - mock: (partialImpl?: Partial | undefined) => { - factory: ServiceFactory; - } & { - authorize: jest.MockInstance< - Promise, - [ - requests: AuthorizePermissionRequest[], - options?: EvaluatorRequestOptions | undefined, - ], - unknown - >; - authorizeConditional: jest.MockInstance< - Promise, - [ - requests: QueryPermissionRequest[], - options?: EvaluatorRequestOptions | undefined, - ], - unknown - >; - } & PermissionsService; + mock: ( + partialImpl?: Partial | undefined, + ) => ServiceMock; } // (undocumented) export function rootConfig(options?: rootConfig.Options): RootConfigService; @@ -234,26 +117,9 @@ export namespace mockServices { const // (undocumented) factory: () => ServiceFactory; const // (undocumented) - mock: (partialImpl?: Partial | undefined) => { - factory: ServiceFactory; - } & { - addStartupHook: jest.MockInstance< - void, - [ - hook: LifecycleServiceStartupHook, - options?: LifecycleServiceStartupOptions | undefined, - ], - unknown - >; - addShutdownHook: jest.MockInstance< - void, - [ - hook: LifecycleServiceShutdownHook, - options?: LifecycleServiceShutdownOptions | undefined, - ], - unknown - >; - } & RootLifecycleService; + mock: ( + partialImpl?: Partial | undefined, + ) => ServiceMock; } // (undocumented) export function rootLogger(options?: rootLogger.Options): LoggerService; @@ -268,57 +134,18 @@ export namespace mockServices { options?: Options | undefined, ) => ServiceFactory; const // (undocumented) - mock: (partialImpl?: Partial | undefined) => { - factory: ServiceFactory; - } & { - error: jest.MockInstance< - void, - [message: string, meta?: Error | JsonObject | undefined], - unknown - >; - warn: jest.MockInstance< - void, - [message: string, meta?: Error | JsonObject | undefined], - unknown - >; - info: jest.MockInstance< - void, - [message: string, meta?: Error | JsonObject | undefined], - unknown - >; - debug: jest.MockInstance< - void, - [message: string, meta?: Error | JsonObject | undefined], - unknown - >; - child: jest.MockInstance; - } & RootLoggerService; + mock: ( + partialImpl?: Partial | undefined, + ) => ServiceMock; } // (undocumented) export namespace scheduler { const // (undocumented) factory: () => ServiceFactory; const // (undocumented) - mock: (partialImpl?: Partial | undefined) => { - factory: ServiceFactory; - } & { - triggerTask: jest.MockInstance, [id: string], unknown>; - scheduleTask: jest.MockInstance< - Promise, - [task: TaskScheduleDefinition & TaskInvocationDefinition], - unknown - >; - createScheduledTaskRunner: jest.MockInstance< - TaskRunner, - [schedule: TaskScheduleDefinition], - unknown - >; - getScheduledTasks: jest.MockInstance< - Promise, - [], - unknown - >; - } & SchedulerService; + mock: ( + partialImpl?: Partial | undefined, + ) => ServiceMock; } // (undocumented) export function tokenManager(): TokenManagerService; @@ -327,50 +154,33 @@ export namespace mockServices { const // (undocumented) factory: () => ServiceFactory; const // (undocumented) - mock: (partialImpl?: Partial | undefined) => { - factory: ServiceFactory; - } & { - getToken: jest.MockInstance< - Promise<{ - token: string; - }>, - [], - unknown - >; - authenticate: jest.MockInstance< - Promise, - [token: string], - unknown - >; - } & TokenManagerService; + mock: ( + partialImpl?: Partial | undefined, + ) => ServiceMock; } // (undocumented) export namespace urlReader { const // (undocumented) factory: () => ServiceFactory; const // (undocumented) - mock: (partialImpl?: Partial | undefined) => { - factory: ServiceFactory; - } & { - readUrl: jest.MockInstance< - Promise, - [url: string, options?: ReadUrlOptions | undefined], - unknown - >; - readTree: jest.MockInstance< - Promise, - [url: string, options?: ReadTreeOptions | undefined], - unknown - >; - search: jest.MockInstance< - Promise, - [url: string, options?: SearchOptions | undefined], - unknown - >; - } & UrlReaderService; + mock: ( + partialImpl?: Partial | undefined, + ) => ServiceMock; } } +// @public (undocumented) +export type ServiceMock = { + factory: ServiceFactory; +} & { + [Key in keyof TService]: TService[Key] extends ( + this: infer This, + ...args: infer Args + ) => infer Return + ? TService[Key] & jest.MockInstance + : TService[Key]; +}; + // @public export function setupRequestMockHandlers(worker: { listen: (t: any) => void; diff --git a/packages/backend-test-utils/src/next/services/index.ts b/packages/backend-test-utils/src/next/services/index.ts index f562150efa..97a22567fd 100644 --- a/packages/backend-test-utils/src/next/services/index.ts +++ b/packages/backend-test-utils/src/next/services/index.ts @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { mockServices } from './mockServices'; +export { mockServices, type ServiceMock } from './mockServices'; diff --git a/packages/backend-test-utils/src/next/services/mockServices.ts b/packages/backend-test-utils/src/next/services/mockServices.ts index d0bb79dd2e..3edc3e0894 100644 --- a/packages/backend-test-utils/src/next/services/mockServices.ts +++ b/packages/backend-test-utils/src/next/services/mockServices.ts @@ -58,13 +58,23 @@ function simpleFactory< })) as (...options: TOptions) => ServiceFactory; } +/** @public */ +export type ServiceMock = { + factory: ServiceFactory; +} & { + [Key in keyof TService]: TService[Key] extends ( + this: infer This, + ...args: infer Args + ) => infer Return + ? TService[Key] & jest.MockInstance + : TService[Key]; +}; + /** @internal */ function simpleMock( ref: ServiceRef, mockFactory: () => jest.Mocked, -): ( - partialImpl?: Partial, -) => { factory: ServiceFactory } & jest.Mocked { +): (partialImpl?: Partial) => ServiceMock { return partialImpl => { const mock = mockFactory(); if (partialImpl) { @@ -82,7 +92,7 @@ function simpleMock( deps: {}, factory: () => mock, })(), - }); + }) as ServiceMock; }; }