From b9758e4a28f672151204c5cbca5767973f37aee0 Mon Sep 17 00:00:00 2001 From: benjdlambert Date: Thu, 7 Aug 2025 17:00:23 +0200 Subject: [PATCH] chore: added some last tests Signed-off-by: benjdlambert --- .../DefaultSwappableComponentsApi.test.tsx | 212 +++++++++++++++++- .../src/extensions/SwappableComponentsApi.ts | 7 +- 2 files changed, 213 insertions(+), 6 deletions(-) diff --git a/packages/frontend-app-api/src/apis/implementations/SwappableComponentsApi/DefaultSwappableComponentsApi.test.tsx b/packages/frontend-app-api/src/apis/implementations/SwappableComponentsApi/DefaultSwappableComponentsApi.test.tsx index e71ad50bfb..78b4c6f596 100644 --- a/packages/frontend-app-api/src/apis/implementations/SwappableComponentsApi/DefaultSwappableComponentsApi.test.tsx +++ b/packages/frontend-app-api/src/apis/implementations/SwappableComponentsApi/DefaultSwappableComponentsApi.test.tsx @@ -14,15 +14,22 @@ * limitations under the License. */ -import { createSwappableComponent } from '@backstage/frontend-plugin-api'; +import { + ApiBlueprint, + createExtensionInput, + createSwappableComponent, + SwappableComponentBlueprint, + swappableComponentsApiRef, +} from '@backstage/frontend-plugin-api'; import { DefaultSwappableComponentsApi } from './DefaultSwappableComponentsApi'; import { render, screen } from '@testing-library/react'; +import { renderInTestApp } from '@backstage/frontend-test-utils'; const { ref: testRefA } = createSwappableComponent({ id: 'test.a' }); const { ref: testRefB1 } = createSwappableComponent({ id: 'test.b' }); const { ref: testRefB2 } = createSwappableComponent({ id: 'test.b' }); -describe('DefaultComponentsApi', () => { +describe('DefaultSwappableComponentsApi', () => { it('should provide components', async () => { const api = DefaultSwappableComponentsApi.fromComponents([ { @@ -53,4 +60,205 @@ describe('DefaultComponentsApi', () => { await expect(screen.findByText('test.b')).resolves.toBeInTheDocument(); }); + + describe('integration tests', () => { + const api = ApiBlueprint.makeWithOverrides({ + name: 'swappable-components', + inputs: { + components: createExtensionInput([ + SwappableComponentBlueprint.dataRefs.component, + ]), + }, + factory: (originalFactory, { inputs }) => { + return originalFactory(defineParams => + defineParams({ + api: swappableComponentsApiRef, + deps: {}, + factory: () => + DefaultSwappableComponentsApi.fromComponents( + inputs.components.map(i => + i.get(SwappableComponentBlueprint.dataRefs.component), + ), + ), + }), + ); + }, + }); + + describe('no api provided', () => { + it('should render the fallback if no other component is provided', async () => { + const MockComponent = createSwappableComponent({ + id: 'test.mock', + }); + + renderInTestApp(, {}); + + await expect( + screen.findByTestId('test.mock'), + ).resolves.toBeInTheDocument(); + }); + + it('should render the default compnoent if no other component is provided', async () => { + const MockComponent = createSwappableComponent({ + id: 'test.mock', + loader: () => () =>
test.mock
, + }); + + renderInTestApp(, {}); + + await expect( + screen.findByText('test.mock'), + ).resolves.toBeInTheDocument(); + }); + + it('should render async loader component if no other component is provided', async () => { + const MockComponent = createSwappableComponent({ + id: 'test.mock', + loader: async () => () =>
test.mock
, + }); + + renderInTestApp(, {}); + + await expect( + screen.findByText('test.mock'), + ).resolves.toBeInTheDocument(); + }); + + it('should transform props correctly', async () => { + const MockComponent = createSwappableComponent({ + id: 'test.mock', + loader: () => (props: { inner: string }) => +
inner: {props.inner}
, + transformProps: (props: { external: string }) => ({ + inner: props.external, + }), + }); + + renderInTestApp(, {}); + + await expect( + screen.findByText('inner: test'), + ).resolves.toBeInTheDocument(); + }); + }); + + describe('with overrides', () => { + it('should render the fallback if no other component is provided', async () => { + const MockComponent = createSwappableComponent({ + id: 'test.mock', + }); + + renderInTestApp(, { + extensions: [api], + }); + + await expect( + screen.findByTestId('test.mock'), + ).resolves.toBeInTheDocument(); + }); + + it('should render the default compnoent if no other component is provided', async () => { + const MockComponent = createSwappableComponent({ + id: 'test.mock', + loader: () => () =>
test.mock
, + }); + + renderInTestApp(, { + extensions: [api], + }); + + await expect( + screen.findByText('test.mock'), + ).resolves.toBeInTheDocument(); + }); + + it('should render async loader component if no other component is provided', async () => { + const MockComponent = createSwappableComponent({ + id: 'test.mock', + loader: async () => () =>
test.mock
, + }); + + renderInTestApp(, { + extensions: [api], + }); + + await expect( + screen.findByText('test.mock'), + ).resolves.toBeInTheDocument(); + }); + + it('should render the component provided by the blueprint', async () => { + const MockComponent = createSwappableComponent({ + id: 'test.mock', + loader: () => () =>
test.mock
, + }); + + const override = SwappableComponentBlueprint.make({ + params: define => + define({ + component: MockComponent, + loader: () => () =>
Overriden!
, + }), + }); + + renderInTestApp(, { + extensions: [api, override], + }); + + await expect( + screen.findByText('Overriden!'), + ).resolves.toBeInTheDocument(); + }); + + it('should render the async component provided by the blueprint', async () => { + const MockComponent = createSwappableComponent({ + id: 'test.mock', + loader: () => () =>
test.mock
, + }); + + const override = SwappableComponentBlueprint.make({ + params: define => + define({ + component: MockComponent, + loader: async () => () =>
Overriden!
, + }), + }); + + renderInTestApp(, { + extensions: [api, override], + }); + + await expect( + screen.findByText('Overriden!'), + ).resolves.toBeInTheDocument(); + }); + + it('should transform props correctly', async () => { + const MockComponent = createSwappableComponent({ + id: 'test.mock', + loader: () => (props: { inner: string }) => +
inner: {props.inner}
, + transformProps: (props: { external: string }) => ({ + inner: props.external, + }), + }); + + const override = SwappableComponentBlueprint.make({ + params: define => + define({ + component: MockComponent, + loader: () => props =>
overriden: {props.inner}
, + }), + }); + + renderInTestApp(, { + extensions: [api, override], + }); + + await expect( + screen.findByText('overriden: test'), + ).resolves.toBeInTheDocument(); + }); + }); + }); }); diff --git a/plugins/app/src/extensions/SwappableComponentsApi.ts b/plugins/app/src/extensions/SwappableComponentsApi.ts index 5809f90be2..3964fc172a 100644 --- a/plugins/app/src/extensions/SwappableComponentsApi.ts +++ b/plugins/app/src/extensions/SwappableComponentsApi.ts @@ -29,10 +29,9 @@ import { DefaultSwappableComponentsApi } from '../../../../packages/frontend-app export const SwappableComponentsApi = ApiBlueprint.makeWithOverrides({ name: 'swappable-components', inputs: { - components: createExtensionInput( - [SwappableComponentBlueprint.dataRefs.component], - { replaces: [{ id: 'app', input: 'components' }] }, - ), + components: createExtensionInput([ + SwappableComponentBlueprint.dataRefs.component, + ]), }, factory: (originalFactory, { inputs }) => { return originalFactory(defineParams =>