diff --git a/packages/core/src/api-wrappers/createApp.test.tsx b/packages/core/src/api-wrappers/createApp.test.tsx
index 31f584b68c..7eaec32b86 100644
--- a/packages/core/src/api-wrappers/createApp.test.tsx
+++ b/packages/core/src/api-wrappers/createApp.test.tsx
@@ -14,7 +14,10 @@
* limitations under the License.
*/
-import { defaultConfigLoader } from './createApp';
+import { render } from '@testing-library/react';
+import React from 'react';
+import { MemoryRouter } from 'react-router';
+import { defaultConfigLoader, OptionallyWrapInRouter } from './createApp';
(process as any).env = { NODE_ENV: 'test' };
const anyEnv = process.env as any;
@@ -92,3 +95,23 @@ describe('defaultConfigLoader', () => {
]);
});
});
+
+describe('OptionallyWrapInRouter', () => {
+ it('should wrap with router if not yet inside a router', async () => {
+ const { getByText } = render(
+ Test,
+ );
+
+ expect(getByText('Test')).toBeInTheDocument();
+ });
+
+ it('should not wrap with router if already inside a router', async () => {
+ const { getByText } = render(
+
+ Test
+ ,
+ );
+
+ expect(getByText('Test')).toBeInTheDocument();
+ });
+});
diff --git a/packages/core/src/api-wrappers/createApp.tsx b/packages/core/src/api-wrappers/createApp.tsx
index b071c2d014..e79cdf509f 100644
--- a/packages/core/src/api-wrappers/createApp.tsx
+++ b/packages/core/src/api-wrappers/createApp.tsx
@@ -14,14 +14,18 @@
* limitations under the License.
*/
-import React from 'react';
+import React, { PropsWithChildren } from 'react';
import privateExports, {
AppOptions,
defaultSystemIcons,
BootErrorPageProps,
AppConfigLoader,
} from '@backstage/core-api';
-import { BrowserRouter, MemoryRouter } from 'react-router-dom';
+import {
+ BrowserRouter,
+ MemoryRouter,
+ useInRouterContext,
+} from 'react-router-dom';
import LightIcon from '@material-ui/icons/WbSunny';
import DarkIcon from '@material-ui/icons/Brightness2';
import { ErrorPage } from '../layout/ErrorPage';
@@ -89,6 +93,13 @@ export const defaultConfigLoader: AppConfigLoader = async (
// The actual implementation of the app class still lives in core-api,
// as it needs to be used by dev- and test-utils.
+export function OptionallyWrapInRouter({ children }: PropsWithChildren<{}>) {
+ if (useInRouterContext()) {
+ return <>{children}>;
+ }
+ return {children};
+}
+
/**
* Creates a new Backstage App.
*/
@@ -97,32 +108,18 @@ export function createApp(options?: AppOptions) {
);
const DefaultBootErrorPage = ({ step, error }: BootErrorPageProps) => {
- switch (step) {
- case 'load-config':
- // TODO: figure out a nicer way to handle routing on the error page, when it can be done.
- return (
-
-
-
- );
- case 'load-chunk':
- return (
-
- );
- default:
- // TODO: figure out a nicer way to handle routing on the error page, when it can be done.
- return (
-
-
-
- );
+ let message = '';
+ if (step === 'load-config') {
+ message = `The configuration failed to load, someone should have a look at this error: ${error.message}`;
+ } else if (step === 'load-chunk') {
+ message = `Lazy loaded chunk failed to load, try to reload the page: ${error.message}`;
}
+ // TODO: figure out a nicer way to handle routing on the error page, when it can be done.
+ return (
+
+
+
+ );
};
const apis = options?.apis ?? [];