From acca17e91a3eba588625d9d04852555dc8827507 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 3 Oct 2023 18:30:08 +0200 Subject: [PATCH] core-app-api: wrap entire app in Suspense Signed-off-by: Patrik Oldsberg --- .changeset/fresh-badgers-study.md | 5 ++ .../core-app-api/src/app/AppManager.test.tsx | 50 ++++++++++++++++--- packages/core-app-api/src/app/AppManager.tsx | 5 +- 3 files changed, 51 insertions(+), 9 deletions(-) create mode 100644 .changeset/fresh-badgers-study.md diff --git a/.changeset/fresh-badgers-study.md b/.changeset/fresh-badgers-study.md new file mode 100644 index 0000000000..4c9e7ee627 --- /dev/null +++ b/.changeset/fresh-badgers-study.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-app-api': patch +--- + +Wrap entire app in ``, enabling support for using translations outside plugins. diff --git a/packages/core-app-api/src/app/AppManager.test.tsx b/packages/core-app-api/src/app/AppManager.test.tsx index 98ce0b93e2..3d0c47c4d5 100644 --- a/packages/core-app-api/src/app/AppManager.test.tsx +++ b/packages/core-app-api/src/app/AppManager.test.tsx @@ -35,16 +35,34 @@ import { createRoutableExtension, analyticsApiRef, useApi, + errorApiRef, } from '@backstage/core-plugin-api'; import { AppManager } from './AppManager'; import { AppComponents, AppIcons } from './types'; import { FeatureFlagged } from '../routing/FeatureFlagged'; +import { + createTranslationRef, + useTranslationRef, +} from '@backstage/core-plugin-api/alpha'; describe('Integration Test', () => { const noOpAnalyticsApi = createApiFactory( analyticsApiRef, new NoOpAnalyticsApi(), ); + const noopErrorApi = createApiFactory(errorApiRef, { + error$() { + return { + subscribe() { + return { unsubscribe() {}, closed: true }; + }, + [Symbol.observable]() { + return this; + }, + }; + }, + post() {}, + }); const plugin1RouteRef = createRouteRef({ id: 'ref-1' }); const plugin1RouteRef2 = createRouteRef({ id: 'ref-1-2' }); const plugin2RouteRef = createRouteRef({ id: 'ref-2', params: ['x'] }); @@ -175,6 +193,10 @@ describe('Integration Test', () => { }, ]; + afterEach(() => { + localStorage.clear(); + }); + it('runs happy paths', async () => { const app = new AppManager({ apis: [noOpAnalyticsApi], @@ -262,7 +284,7 @@ describe('Integration Test', () => { it('runs success with __experimentalTranslations', async () => { const app = new AppManager({ - apis: [noOpAnalyticsApi], + apis: [noOpAnalyticsApi, noopErrorApi], defaultApis: [], themes, icons, @@ -277,27 +299,41 @@ describe('Integration Test', () => { }, __experimentalTranslations: { availableLanguages: ['en', 'de'], + defaultLanguage: 'de', }, }); const Provider = app.getProvider(); const Router = app.getRouter(); + const translationRef = createTranslationRef({ + id: 'test', + messages: { + foo: 'Foo', + }, + translations: { + de: () => Promise.resolve({ default: { foo: 'Bar' } }), + }, + }); + + const TranslatedComponent = () => { + const { t } = useTranslationRef(translationRef); + return
translation: {t('foo')}
; + }; + await renderWithEffects( - } /> - } /> + } /> , ); - expect(screen.getByText('extLink1: /')).toBeInTheDocument(); - expect(screen.getByText('extLink2: /foo')).toBeInTheDocument(); - expect(screen.getByText('extLink3: ')).toBeInTheDocument(); - expect(screen.getByText('extLink4: ')).toBeInTheDocument(); + await expect( + screen.findByText('translation: Bar'), + ).resolves.toBeInTheDocument(); }); it('should wait for the config to load before calling feature flags', async () => { diff --git a/packages/core-app-api/src/app/AppManager.tsx b/packages/core-app-api/src/app/AppManager.tsx index 7a941b7986..37407283b5 100644 --- a/packages/core-app-api/src/app/AppManager.tsx +++ b/packages/core-app-api/src/app/AppManager.tsx @@ -18,6 +18,7 @@ import { Config } from '@backstage/config'; import React, { ComponentType, PropsWithChildren, + Suspense, useMemo, useRef, } from 'react'; @@ -341,7 +342,7 @@ export class AppManager implements BackstageApp { } } - const { ThemeProvider = AppThemeProvider } = this.components; + const { ThemeProvider = AppThemeProvider, Progress } = this.components; return ( @@ -360,7 +361,7 @@ export class AppManager implements BackstageApp { appIdentityProxy: this.appIdentityProxy, }} > - {children} + }>{children}