From 6cf2ab47ea728cf1f0e2f7e683e2a202215b87f9 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 27 May 2021 00:27:12 +0200 Subject: [PATCH] app-api: sync with core at master@e9e70677 Signed-off-by: Patrik Oldsberg --- packages/app-api/src/app/createApp.test.tsx | 25 +++++++++++++++++++- packages/app-api/src/app/createApp.tsx | 26 +++++++++++++++++---- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/packages/app-api/src/app/createApp.test.tsx b/packages/app-api/src/app/createApp.test.tsx index 31f584b68c..a800c11ea6 100644 --- a/packages/app-api/src/app/createApp.test.tsx +++ b/packages/app-api/src/app/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-dom'; +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/app-api/src/app/createApp.tsx b/packages/app-api/src/app/createApp.tsx index 445e7495ef..a0ef11199a 100644 --- a/packages/app-api/src/app/createApp.tsx +++ b/packages/app-api/src/app/createApp.tsx @@ -14,10 +14,14 @@ * limitations under the License. */ -import React from 'react'; +import React, { PropsWithChildren } from 'react'; import { AppOptions, BootErrorPageProps, AppConfigLoader } from './types'; import { defaultAppIcons } from './icons'; -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, Progress } from '@backstage/components'; @@ -52,7 +56,10 @@ export const defaultConfigLoader: AppConfigLoader = async ( const configs = (appConfig.slice() as unknown) as AppConfig[]; // Avoiding this string also being replaced at runtime - if (runtimeConfigJson !== '__app_injected_runtime_config__'.toUpperCase()) { + if ( + runtimeConfigJson !== + '__app_injected_runtime_config__'.toLocaleUpperCase('en-US') + ) { try { const data = JSON.parse(runtimeConfigJson) as JsonObject; if (Array.isArray(data)) { @@ -80,6 +87,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. */ @@ -91,12 +105,14 @@ export function createApp(options?: AppOptions) { 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 ( - + - + ); };