diff --git a/.changeset/thirty-meals-rest.md b/.changeset/thirty-meals-rest.md new file mode 100644 index 0000000000..7972167c00 --- /dev/null +++ b/.changeset/thirty-meals-rest.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': patch +--- + +Internal update to simplify testing utility implementations. diff --git a/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx b/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx index 57c91969de..d56a609bb9 100644 --- a/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx +++ b/packages/frontend-app-api/src/wiring/createSpecializedApp.tsx @@ -284,6 +284,14 @@ export type CreateSpecializedAppOptions = { }; }; +// Internal options type, not exported in the public API +export interface CreateSpecializedAppInternalOptions + extends CreateSpecializedAppOptions { + __internal?: { + apiFactoryOverrides?: AnyApiFactory[]; + }; +} + /** * Creates an empty app without any default features. This is a low-level API is * intended for use in tests or specialized setups. Typically you want to use @@ -296,6 +304,7 @@ export function createSpecializedApp(options?: CreateSpecializedAppOptions): { tree: AppTree; errors?: AppError[]; } { + const internalOptions = options as CreateSpecializedAppInternalOptions; const config = options?.config ?? new ConfigReader({}, 'empty-config'); const features = deduplicateFeatures(options?.features ?? []).map( createPluginInfoAttacher(config, options?.advanced?.pluginInfoResolver), @@ -337,6 +346,7 @@ export function createSpecializedApp(options?: CreateSpecializedAppOptions): { createApiFactory(configApiRef, config), createApiFactory(routeResolutionApiRef, routeResolutionApi), createApiFactory(identityApiRef, appIdentityProxy), + ...(internalOptions?.__internal?.apiFactoryOverrides ?? []), ], }); diff --git a/packages/frontend-test-utils/src/app/renderInTestApp.tsx b/packages/frontend-test-utils/src/app/renderInTestApp.tsx index 0b1a1fcf61..8aa863512b 100644 --- a/packages/frontend-test-utils/src/app/renderInTestApp.tsx +++ b/packages/frontend-test-utils/src/app/renderInTestApp.tsx @@ -31,11 +31,13 @@ import { createFrontendPlugin, FrontendFeature, createFrontendModule, - ApiBlueprint, + createApiFactory, } from '@backstage/frontend-plugin-api'; import { RouterBlueprint } from '@backstage/plugin-app-react'; import appPlugin from '@backstage/plugin-app'; import { type TestApiPairs } from '../utils'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import type { CreateSpecializedAppInternalOptions } from '../../../frontend-app-api/src/wiring/createSpecializedApp'; const DEFAULT_MOCK_CONFIG = { app: { baseUrl: 'http://localhost:3000' }, @@ -223,27 +225,6 @@ export function renderInTestApp( features.push(...options.features); } - // If API overrides are provided, add them as a module for the 'app' plugin - // This must come after appPluginOverride so it can override app's default APIs - if (options?.apis) { - features.push( - createFrontendModule({ - pluginId: 'app', - extensions: options.apis.map(([apiRef, implementation], index) => - ApiBlueprint.make({ - name: `test-api-override-${index}`, - params: defineParams => - defineParams({ - api: apiRef, - deps: {}, - factory: () => implementation, - }), - }), - ), - }), - ); - } - const app = createSpecializedApp({ features, config: ConfigReader.fromConfigs([ @@ -252,7 +233,12 @@ export function renderInTestApp( data: options?.config ?? DEFAULT_MOCK_CONFIG, }, ]), - }); + __internal: options?.apis && { + apiFactoryOverrides: options.apis.map(([apiRef, implementation]) => + createApiFactory(apiRef, implementation), + ), + }, + } as CreateSpecializedAppInternalOptions); return render( app.tree.root.instance!.getData(coreExtensionData.reactElement),