From 57591f57547143d73a70e5a52e94267a9ccc200b Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 16 Nov 2021 18:47:50 +0100 Subject: [PATCH] test-utils: add TestApiProvider Signed-off-by: Patrik Oldsberg --- packages/test-utils/api-report.md | 13 +++ .../src/testUtils/TestApiProvider.tsx | 94 +++++++++++++++++++ packages/test-utils/src/testUtils/index.tsx | 2 + 3 files changed, 109 insertions(+) create mode 100644 packages/test-utils/src/testUtils/TestApiProvider.tsx diff --git a/packages/test-utils/api-report.md b/packages/test-utils/api-report.md index 62a8d9f601..38656137a3 100644 --- a/packages/test-utils/api-report.md +++ b/packages/test-utils/api-report.md @@ -5,6 +5,7 @@ ```ts import { AnalyticsApi } from '@backstage/core-plugin-api'; import { AnalyticsEvent } from '@backstage/core-plugin-api'; +import { ApiRef } from '@backstage/core-plugin-api'; import { ComponentType } from 'react'; import { ErrorApi } from '@backstage/core-plugin-api'; import { ErrorApiError } from '@backstage/core-plugin-api'; @@ -175,6 +176,18 @@ export function setupRequestMockHandlers(worker: { // @public export type SyncLogCollector = () => void; +// @public +export const TestApiProvider: ({ + apis, + children, +}: TestApiProviderProps) => JSX.Element; + +// @public +export type TestApiProviderProps = { + apis: [...TestApiProviderPropsApiPairs]; + children: ReactNode; +}; + // @public export type TestAppOptions = { routeEntries?: string[]; diff --git a/packages/test-utils/src/testUtils/TestApiProvider.tsx b/packages/test-utils/src/testUtils/TestApiProvider.tsx new file mode 100644 index 0000000000..272da8c807 --- /dev/null +++ b/packages/test-utils/src/testUtils/TestApiProvider.tsx @@ -0,0 +1,94 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { ReactNode } from 'react'; +import { ApiProvider } from '@backstage/core-app-api'; +import { ApiRef, ApiHolder } from '@backstage/core-plugin-api'; + +type TestApiProviderPropsApiPair = TApi extends infer TImpl + ? [ApiRef, Partial] + : never; + +/** @ignore */ +type TestApiProviderPropsApiPairs = { + [TIndex in keyof TApiPairs]: TestApiProviderPropsApiPair; +}; + +/** + * Properties for the {@link TestApiProvider} component. + * + * @public + */ +export type TestApiProviderProps = { + apis: [...TestApiProviderPropsApiPairs]; + children: ReactNode; +}; + +/** @internal */ +class TestApiRegistry implements ApiHolder { + constructor(private readonly apis: Map) {} + + get(api: ApiRef): T | undefined { + return this.apis.get(api.id) as T | undefined; + } +} + +/** + * An API provider that lets you provide any number of API implementations in + * a test, without necessarily having to implement the full APIs. + * + * A migration from `ApiRegistry` and `ApiProvider` might look like this, from: + * + * ```tsx + * renderInTestApp( + * + * {...} + * + * ) + * ``` + * + * To the following: + * + * ```tsx + * renderInTestApp( + * + * {...} + * + * ) + * ``` + * + * Note that the cast to `IdentityApi` is no longer needed as long as the mock API + * implements a subset of the `IdentityApi`. + * + * @public + **/ +export const TestApiProvider = ({ + apis, + children, +}: TestApiProviderProps) => { + return ( + [api.id, impl]))) + } + children={children} + /> + ); +}; diff --git a/packages/test-utils/src/testUtils/index.tsx b/packages/test-utils/src/testUtils/index.tsx index 7d93d606cc..d48767d3cd 100644 --- a/packages/test-utils/src/testUtils/index.tsx +++ b/packages/test-utils/src/testUtils/index.tsx @@ -22,3 +22,5 @@ export * from './msw'; export * from './Keyboard'; export * from './logCollector'; export * from './testingLibrary'; +export { TestApiProvider } from './TestApiProvider'; +export type { TestApiProviderProps } from './TestApiProvider';