From eeade86c096aeebfdeb0ab56b08081b19faa29d4 Mon Sep 17 00:00:00 2001 From: benjdlambert Date: Mon, 4 Aug 2025 16:50:53 +0200 Subject: [PATCH] chore: more tests Signed-off-by: benjdlambert Signed-off-by: benjdlambert --- .../ComponentImplementationBlueprint.test.tsx | 117 +++++++++++++++++- .../src/components/makeComponentFromRef.tsx | 2 + 2 files changed, 118 insertions(+), 1 deletion(-) diff --git a/packages/frontend-plugin-api/src/blueprints/ComponentImplementationBlueprint.test.tsx b/packages/frontend-plugin-api/src/blueprints/ComponentImplementationBlueprint.test.tsx index 0943659fed..cd109a6562 100644 --- a/packages/frontend-plugin-api/src/blueprints/ComponentImplementationBlueprint.test.tsx +++ b/packages/frontend-plugin-api/src/blueprints/ComponentImplementationBlueprint.test.tsx @@ -13,11 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { renderInTestApp } from '@backstage/frontend-test-utils'; import { createComponentRef } from '../components'; +import { makeComponentFromRef } from '../components/makeComponentFromRef'; import { ComponentImplementationBlueprint } from './ComponentImplementationBlueprint'; +import { PageBlueprint } from './PageBlueprint'; +import { waitFor, screen } from '@testing-library/react'; describe('ComponentImplementationBlueprint', () => { - it('should allow defining a component override for sync component ref', () => { + it('should allow defining a component override for a component ref', () => { const componentRef = createComponentRef({ id: 'test.component', loader: () => (props: { hello: string }) =>
{props.hello}
, @@ -38,4 +42,115 @@ describe('ComponentImplementationBlueprint', () => { expect(extension).toBeDefined(); }); + + it('should render default component refs in the app', async () => { + const testComponentRef = createComponentRef({ + id: 'test.component', + loader: () => (props: { hello: string }) =>
{props.hello}
, + }); + + const TestComponent = makeComponentFromRef({ ref: testComponentRef }); + + renderInTestApp(
, { + extensions: [ + PageBlueprint.make({ + params: define => + define({ + // todo(blam): there's a bug that this path cannot be `/`? + defaultPath: '/test', + loader: async () => , + }), + }), + ], + initialRouteEntries: ['/test'], + }); + + await waitFor(() => expect(screen.getByText('test!')).toBeInTheDocument()); + }); + + it('should render a component ref without a default implementation', async () => { + const testComponentRef = createComponentRef({ + id: 'test.component', + }); + + const TestComponent = makeComponentFromRef({ ref: testComponentRef }); + + renderInTestApp(
, { + extensions: [ + PageBlueprint.make({ + params: define => + define({ + defaultPath: '/test', + loader: async () => , + }), + }), + ], + initialRouteEntries: ['/test'], + }); + + await waitFor(() => + expect(screen.getByTestId('test.component')).toBeInTheDocument(), + ); + }); + + it('should render a component ref with an async loader implementation', async () => { + const testComponentRef = createComponentRef({ + id: 'test.component', + loader: async () => (props: { hello: string }) => +
{props.hello}
, + }); + + const TestComponent = makeComponentFromRef({ ref: testComponentRef }); + + renderInTestApp(
, { + extensions: [ + PageBlueprint.make({ + params: define => + define({ + // todo(blam): there's a bug that this path cannot be `/`? + defaultPath: '/test', + loader: async () => , + }), + }), + ], + initialRouteEntries: ['/test'], + }); + + await waitFor(() => expect(screen.getByText('test!')).toBeInTheDocument()); + }); + + it('should allow overriding a component ref with the blueprint', async () => { + const testComponentRef = createComponentRef({ + id: 'test.component', + loader: () => (props: { hello: string }) =>
{props.hello}
, + }); + + const TestComponent = makeComponentFromRef({ ref: testComponentRef }); + + const extension = ComponentImplementationBlueprint.make({ + params: define => + define({ + ref: testComponentRef, + loader: () => props =>
Override {props.hello}
, + }), + }); + + renderInTestApp(
, { + extensions: [ + extension, + PageBlueprint.make({ + params: define => + define({ + defaultPath: '/test', + loader: async () => , + }), + }), + ], + initialRouteEntries: ['/test'], + }); + + await waitFor(() => + expect(screen.getByText('Override test!')).toBeInTheDocument(), + ); + }); }); diff --git a/packages/frontend-plugin-api/src/components/makeComponentFromRef.tsx b/packages/frontend-plugin-api/src/components/makeComponentFromRef.tsx index 2f0155fbec..c9c58a6ed6 100644 --- a/packages/frontend-plugin-api/src/components/makeComponentFromRef.tsx +++ b/packages/frontend-plugin-api/src/components/makeComponentFromRef.tsx @@ -16,6 +16,7 @@ import { lazy, Suspense } from 'react'; import { ComponentRef } from './createComponentRef'; import { OpaqueComponentRef } from '@internal/frontend'; +import { componentsApiRef, useApi } from '../apis'; export function makeComponentFromRef< InternalComponentProps extends {}, @@ -31,6 +32,7 @@ export function makeComponentFromRef< ); const ComponentRefImpl = (props: ExternalComponentProps) => { + const api = useApi(componentsApiRef); const innerProps = options.transformProps?.(props) ?? props; const ComponentOrPromise = options.loader?.() ?? FallbackComponent;