frontend-defaults: add pluginInfoResolver + test

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2025-05-15 09:53:34 +02:00
parent 6f48f718b0
commit fa5650cc80
4 changed files with 60 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/frontend-defaults': patch
---
Forwarded the new `pluginInfoResolver` option for `createApp`.
+3
View File
@@ -10,6 +10,7 @@ import { ExtensionFactoryMiddleware } from '@backstage/frontend-plugin-api';
import { FrontendFeature } from '@backstage/frontend-plugin-api';
import { FrontendFeatureLoader } from '@backstage/frontend-plugin-api';
import { JSX as JSX_2 } from 'react';
import { FrontendPluginInfoResolver } from '@backstage/frontend-app-api';
import { ReactNode } from 'react';
// @public
@@ -44,6 +45,8 @@ export interface CreateAppOptions {
| CreateAppFeatureLoader
)[];
loadingComponent?: ReactNode;
// (undocumented)
pluginInfoResolver?: FrontendPluginInfoResolver;
}
// @public
@@ -23,12 +23,15 @@ import {
createFrontendPlugin,
ThemeBlueprint,
createFrontendModule,
useAppNode,
FrontendPluginInfo,
} from '@backstage/frontend-plugin-api';
import { screen, waitFor } from '@testing-library/react';
import { CreateAppFeatureLoader, createApp } from './createApp';
import { mockApis, renderWithEffects } from '@backstage/test-utils';
import { featureFlagsApiRef, useApi } from '@backstage/core-plugin-api';
import { default as appPluginOriginal } from '@backstage/plugin-app';
import { useState, useEffect } from 'react';
describe('createApp', () => {
const appPlugin = appPluginOriginal.withOverrides({
@@ -119,6 +122,52 @@ describe('createApp', () => {
);
});
it('should allow overriding the plugin info resolver', async () => {
function TestComponent() {
const appNode = useAppNode();
const [info, setInfo] = useState<FrontendPluginInfo | undefined>(
undefined,
);
useEffect(() => {
appNode?.spec.source?.info().then(setInfo);
}, [appNode]);
return <div>Package name: {info?.packageName}</div>;
}
const app = createApp({
configLoader: async () => ({ config: mockApis.config() }),
features: [
appPlugin,
createFrontendPlugin({
pluginId: 'test',
extensions: [
PageBlueprint.make({
params: {
defaultPath: '/',
loader: async () => <TestComponent />,
},
}),
],
}),
],
pluginInfoResolver: async () => {
return {
info: {
packageName: '@test/test',
},
};
},
});
await renderWithEffects(app.createRoot());
await expect(
screen.findByText('Package name: @test/test'),
).resolves.toBeInTheDocument();
});
it('should support feature loaders', async () => {
const loader: CreateAppFeatureLoader = {
getLoaderName() {
@@ -30,6 +30,7 @@ import { ConfigReader } from '@backstage/config';
import {
CreateAppRouteBinder,
createSpecializedApp,
FrontendPluginInfoResolver,
} from '@backstage/frontend-app-api';
import appPlugin from '@backstage/plugin-app';
import { discoverAvailableFeatures } from './discovery';
@@ -78,6 +79,7 @@ export interface CreateAppOptions {
extensionFactoryMiddleware?:
| ExtensionFactoryMiddleware
| ExtensionFactoryMiddleware[];
pluginInfoResolver?: FrontendPluginInfoResolver;
}
/**
@@ -112,6 +114,7 @@ export function createApp(options?: CreateAppOptions): {
features: [appPlugin, ...loadedFeatures],
bindRoutes: options?.bindRoutes,
extensionFactoryMiddleware: options?.extensionFactoryMiddleware,
pluginInfoResolver: options?.pluginInfoResolver,
});
const rootEl = app.tree.root.instance!.getData(