chore: wait for the configApi to be initialised before using the featureFlagsApi to register plugin output
Signed-off-by: ben@blam.sh Signed-off-by: blam <ben@blam.sh>
This commit is contained in:
@@ -14,6 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
configApiRef,
|
||||
createApiFactory,
|
||||
featureFlagsApiRef,
|
||||
LocalStorageFeatureFlags,
|
||||
} from '../apis';
|
||||
import { renderWithEffects, withLogCollector } from '@backstage/test-utils';
|
||||
import { lightTheme } from '@backstage/theme';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
@@ -207,6 +213,67 @@ describe('Integration Test', () => {
|
||||
expect(screen.getByText('errParamsOptional: <none>')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should wait for the config to load before calling feature flags', async () => {
|
||||
const storageFlags = new LocalStorageFeatureFlags();
|
||||
jest.spyOn(storageFlags, 'registerFlag');
|
||||
|
||||
const apis = [
|
||||
createApiFactory({
|
||||
api: featureFlagsApiRef,
|
||||
deps: { configApi: configApiRef },
|
||||
factory() {
|
||||
return storageFlags;
|
||||
},
|
||||
}),
|
||||
];
|
||||
|
||||
const app = new PrivateAppImpl({
|
||||
apis,
|
||||
defaultApis: [],
|
||||
themes: [
|
||||
{
|
||||
id: 'light',
|
||||
title: 'Light Theme',
|
||||
variant: 'light',
|
||||
theme: lightTheme,
|
||||
},
|
||||
],
|
||||
icons: defaultSystemIcons,
|
||||
plugins: [
|
||||
createPlugin({
|
||||
id: 'test',
|
||||
register: p => p.featureFlags.register('name'),
|
||||
}),
|
||||
],
|
||||
components,
|
||||
bindRoutes: ({ bind }) => {
|
||||
bind(plugin1.externalRoutes, {
|
||||
err: plugin1RouteRef,
|
||||
errParams: plugin2RouteRef,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const Provider = app.getProvider();
|
||||
const Router = app.getRouter();
|
||||
|
||||
await renderWithEffects(
|
||||
<Provider>
|
||||
<Router>
|
||||
<Routes>
|
||||
<ExposedComponent path="/" />
|
||||
<HiddenComponent path="/foo" />
|
||||
</Routes>
|
||||
</Router>
|
||||
</Provider>,
|
||||
);
|
||||
|
||||
expect(storageFlags.registerFlag).toHaveBeenCalledWith({
|
||||
name: 'name',
|
||||
pluginId: 'test',
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw some error when the route has duplicate params', () => {
|
||||
const app = new PrivateAppImpl({
|
||||
apis: [],
|
||||
|
||||
@@ -14,10 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Config } from '@backstage/config';
|
||||
import React, {
|
||||
ComponentType,
|
||||
PropsWithChildren,
|
||||
ReactElement,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
} from 'react';
|
||||
@@ -277,24 +279,6 @@ export class PrivateAppImpl implements BackstageApp {
|
||||
const appContext = new AppContextImpl(this);
|
||||
const apiHolder = this.getApiHolder();
|
||||
|
||||
const featureFlagsApi = this.getApiHolder().get(featureFlagsApiRef)!;
|
||||
|
||||
for (const plugin of this.plugins.values()) {
|
||||
for (const output of plugin.output()) {
|
||||
switch (output.type) {
|
||||
case 'feature-flag': {
|
||||
featureFlagsApi.registerFlag({
|
||||
name: output.name,
|
||||
pluginId: plugin.getId(),
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Provider = ({ children }: PropsWithChildren<{}>) => {
|
||||
const appThemeApi = useMemo(
|
||||
() => AppThemeSelector.createWithStorage(this.themes),
|
||||
@@ -323,13 +307,39 @@ export class PrivateAppImpl implements BackstageApp {
|
||||
appThemeApi,
|
||||
);
|
||||
|
||||
const hasConfigApi = 'api' in loadedConfig;
|
||||
if (hasConfigApi) {
|
||||
const { api } = loadedConfig as { api: Config };
|
||||
this.configApi = api;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (hasConfigApi) {
|
||||
const featureFlagsApi = this.getApiHolder().get(featureFlagsApiRef)!;
|
||||
|
||||
for (const plugin of this.plugins.values()) {
|
||||
for (const output of plugin.output()) {
|
||||
switch (output.type) {
|
||||
case 'feature-flag': {
|
||||
featureFlagsApi.registerFlag({
|
||||
name: output.name,
|
||||
pluginId: plugin.getId(),
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [hasConfigApi, loadedConfig]);
|
||||
|
||||
if ('node' in loadedConfig) {
|
||||
// Loading or error
|
||||
return loadedConfig.node;
|
||||
}
|
||||
|
||||
this.configApi = loadedConfig.api;
|
||||
|
||||
return (
|
||||
<ApiProvider apis={apiHolder}>
|
||||
<AppContextProvider appContext={appContext}>
|
||||
|
||||
Reference in New Issue
Block a user