chore: make sure to load the api factories in reverse so that things are loaded in the correct order

Signed-off-by: blam <ben@blam.sh>
This commit is contained in:
blam
2024-09-12 16:08:04 +02:00
parent 77146ae7f1
commit 0c7094940f
3 changed files with 76 additions and 1 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/frontend-app-api': patch
---
Reverse the order of API factory initialization in order to make sure that overrides from modules take priority
@@ -25,6 +25,7 @@ import {
createExternalRouteRef,
createExtensionInput,
useRouteRef,
analyticsApiRef,
} from '@backstage/frontend-plugin-api';
import { screen, render } from '@testing-library/react';
import { createSpecializedApp } from './createSpecializedApp';
@@ -167,6 +168,75 @@ describe('createSpecializedApp', () => {
expect(screen.getByText('flags:test=a,test=b')).toBeInTheDocument();
});
it('should intitialize the APIs in the correct order to allow for overrides', () => {
const mockAnalyticsApi = jest.fn(() => ({ captureEvent: jest.fn() }));
const app = createSpecializedApp({
features: [
createFrontendPlugin({
id: 'first',
extensions: [
ApiBlueprint.make({
params: {
factory: createApiFactory({
api: analyticsApiRef,
deps: {},
factory: () => {
throw new Error('BROKEN');
},
}),
},
}),
],
}),
createFrontendPlugin({
id: 'test',
featureFlags: [{ name: 'a' }, { name: 'b' }],
extensions: [
createExtension({
attachTo: { id: 'root', input: 'app' },
output: [coreExtensionData.reactElement],
factory: ({ apis }) => {
const Component = () => {
const analytics = apis.get(analyticsApiRef);
return (
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
<div
onClick={() =>
analytics!.captureEvent({
action: 'asd',
subject: 'asd',
context: { extensionId: 'asd', pluginId: 'asd' },
})
}
>
Click me
</div>
);
};
return [coreExtensionData.reactElement(<Component />)];
},
}),
ApiBlueprint.make({
params: {
factory: createApiFactory({
api: analyticsApiRef,
deps: {},
factory: mockAnalyticsApi,
}),
},
}),
],
}),
],
});
render(app.createRoot());
expect(mockAnalyticsApi).toHaveBeenCalled();
});
it('should make the app structure available through the AppTreeApi', async () => {
let appTreeApi: AppTreeApi | undefined = undefined;
@@ -305,7 +305,7 @@ function createApiHolder(options: {
}): ApiHolder {
const factoryRegistry = new ApiFactoryRegistry();
for (const factory of options.factories) {
for (const factory of options.factories.slice().reverse()) {
factoryRegistry.register('default', factory);
}