chore: fix some tests
Co-authored-by: Fredrik Adelöw <freben@gmail.com> Co-authored-by: Patrik Oldsberg <poldsberg@gmail.com> Co-authored-by: Johan Haals <johan.haals@gmail.com> Signed-off-by: blam <ben@blam.sh>
This commit is contained in:
@@ -45,7 +45,6 @@
|
||||
"@backstage/frontend-app-api": "workspace:^",
|
||||
"@backstage/integration-react": "workspace:^",
|
||||
"@backstage/plugin-api-docs": "workspace:^",
|
||||
"@backstage/plugin-app": "^0.0.0",
|
||||
"@backstage/plugin-auth-react": "workspace:^",
|
||||
"@backstage/plugin-catalog": "workspace:^",
|
||||
"@backstage/plugin-catalog-common": "workspace:^",
|
||||
|
||||
@@ -82,7 +82,6 @@ import { customDevToolsPage } from './components/devtools/CustomDevToolsPage';
|
||||
import { DevToolsPage } from '@backstage/plugin-devtools';
|
||||
import { CatalogUnprocessedEntitiesPage } from '@backstage/plugin-catalog-unprocessed-entities';
|
||||
import { NotificationsPage } from '@backstage/plugin-notifications';
|
||||
import { AppPage } from '@backstage/plugin-app';
|
||||
|
||||
const app = createApp({
|
||||
apis,
|
||||
@@ -209,7 +208,6 @@ const routes = (
|
||||
{customDevToolsPage}
|
||||
</Route>
|
||||
<Route path="/notifications" element={<NotificationsPage />} />
|
||||
<Route path="/app" element={<AppPage />} />
|
||||
</FlatRoutes>
|
||||
);
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "workspace:^",
|
||||
"@backstage/plugin-app": "workspace:^",
|
||||
"@backstage/test-utils": "workspace:^",
|
||||
"@testing-library/jest-dom": "^6.0.0",
|
||||
"@testing-library/react": "^15.0.0"
|
||||
|
||||
@@ -29,12 +29,15 @@ import {
|
||||
createRouteRef,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
import { MockConfigApi, TestApiRegistry } from '@backstage/test-utils';
|
||||
import appPlugin from '@backstage/plugin-app';
|
||||
|
||||
import { builtinExtensions } from '../wiring/createApp';
|
||||
import { readAppExtensionsConfig } from '../tree/readAppExtensionsConfig';
|
||||
import { resolveAppNodeSpecs } from '../tree/resolveAppNodeSpecs';
|
||||
import { resolveAppTree } from '../tree/resolveAppTree';
|
||||
import { instantiateAppNodeTree } from '../tree/instantiateAppNodeTree';
|
||||
import { Root } from '../extensions/Root';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import { resolveExtensionDefinition } from '../../../frontend-plugin-api/src/wiring/resolveExtensionDefinition';
|
||||
|
||||
const ref1 = createRouteRef();
|
||||
const ref2 = createRouteRef();
|
||||
@@ -83,12 +86,12 @@ function routeInfoFromExtensions(extensions: ExtensionDefinition[]) {
|
||||
});
|
||||
|
||||
const tree = resolveAppTree(
|
||||
'app',
|
||||
'root',
|
||||
resolveAppNodeSpecs({
|
||||
features: [plugin],
|
||||
builtinExtensions,
|
||||
features: [appPlugin, plugin],
|
||||
builtinExtensions: [resolveExtensionDefinition(Root)],
|
||||
parameters: readAppExtensionsConfig(new MockConfigApi({})),
|
||||
forbidden: new Set(['app']),
|
||||
forbidden: new Set(['root']),
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import { CreateAppFeatureLoader, createApp } from './createApp';
|
||||
import { MockConfigApi, renderWithEffects } from '@backstage/test-utils';
|
||||
import React from 'react';
|
||||
import { featureFlagsApiRef, useApi } from '@backstage/core-plugin-api';
|
||||
import appPlugin from '@backstage/plugin-app';
|
||||
|
||||
describe('createApp', () => {
|
||||
it('should allow themes to be installed', async () => {
|
||||
@@ -44,6 +45,7 @@ describe('createApp', () => {
|
||||
}),
|
||||
}),
|
||||
features: [
|
||||
appPlugin,
|
||||
createFrontendPlugin({
|
||||
id: 'test',
|
||||
extensions: [
|
||||
@@ -73,6 +75,7 @@ describe('createApp', () => {
|
||||
const app = createApp({
|
||||
configLoader: async () => ({ config: new MockConfigApi({}) }),
|
||||
features: [
|
||||
appPlugin,
|
||||
createFrontendPlugin({
|
||||
id: duplicatedFeatureId,
|
||||
extensions: [
|
||||
@@ -136,7 +139,7 @@ describe('createApp', () => {
|
||||
configLoader: async () => ({
|
||||
config: new MockConfigApi({ key: 'config-value' }),
|
||||
}),
|
||||
features: [loader],
|
||||
features: [appPlugin, loader],
|
||||
});
|
||||
|
||||
await renderWithEffects(app.createRoot());
|
||||
@@ -174,6 +177,7 @@ describe('createApp', () => {
|
||||
const app = createApp({
|
||||
configLoader: async () => ({ config: new MockConfigApi({}) }),
|
||||
features: [
|
||||
appPlugin,
|
||||
createFrontendPlugin({
|
||||
id: 'test',
|
||||
featureFlags: [{ name: 'test-1' }],
|
||||
@@ -229,6 +233,7 @@ describe('createApp', () => {
|
||||
const app = createApp({
|
||||
configLoader: async () => ({ config: new MockConfigApi({}) }),
|
||||
features: [
|
||||
appPlugin,
|
||||
createFrontendPlugin({
|
||||
id: 'my-plugin',
|
||||
extensions: [
|
||||
@@ -255,13 +260,53 @@ describe('createApp', () => {
|
||||
const { tree } = appTreeApi!.getTree();
|
||||
|
||||
expect(String(tree.root)).toMatchInlineSnapshot(`
|
||||
"<root>
|
||||
"<root out=[core.reactElement]>
|
||||
apis [
|
||||
<api:app/discovery out=[core.api.factory] />
|
||||
<api:app/alert out=[core.api.factory] />
|
||||
<api:app/analytics out=[core.api.factory] />
|
||||
<api:app/error out=[core.api.factory] />
|
||||
<api:app/storage out=[core.api.factory] />
|
||||
<api:app/fetch out=[core.api.factory] />
|
||||
<api:app/oauth-request out=[core.api.factory] />
|
||||
<api:app/google-auth out=[core.api.factory] />
|
||||
<api:app/microsoft-auth out=[core.api.factory] />
|
||||
<api:app/github-auth out=[core.api.factory] />
|
||||
<api:app/okta-auth out=[core.api.factory] />
|
||||
<api:app/gitlab-auth out=[core.api.factory] />
|
||||
<api:app/onelogin-auth out=[core.api.factory] />
|
||||
<api:app/bitbucket-auth out=[core.api.factory] />
|
||||
<api:app/bitbucket-server-auth out=[core.api.factory] />
|
||||
<api:app/atlassian-auth out=[core.api.factory] />
|
||||
<api:app/vmware-cloud-auth out=[core.api.factory] />
|
||||
<api:app/permission out=[core.api.factory] />
|
||||
<api:app/app-language out=[core.api.factory] />
|
||||
<api:app/app-theme out=[core.api.factory]>
|
||||
themes [
|
||||
<theme:app/dark out=[core.theme.theme] />
|
||||
<theme:app/light out=[core.theme.theme] />
|
||||
]
|
||||
</api:app/app-theme>
|
||||
<api:app/components out=[core.api.factory]>
|
||||
components [
|
||||
<component:core.components.progress out=[core.component.component] />
|
||||
<component:core.components.notFoundErrorPage out=[core.component.component] />
|
||||
<component:core.components.errorBoundaryFallback out=[core.component.component] />
|
||||
]
|
||||
</api:app/components>
|
||||
<api:app/icons out=[core.api.factory] />
|
||||
<api:app/feature-flags out=[core.api.factory] />
|
||||
<api:app/translations out=[core.api.factory] />
|
||||
]
|
||||
app [
|
||||
<app out=[core.reactElement]>
|
||||
root [
|
||||
<app/root out=[core.reactElement]>
|
||||
children [
|
||||
<app/layout out=[core.reactElement]>
|
||||
nav [
|
||||
<app/nav out=[core.reactElement] />
|
||||
]
|
||||
content [
|
||||
<app/routes out=[core.reactElement]>
|
||||
routes [
|
||||
@@ -269,9 +314,6 @@ describe('createApp', () => {
|
||||
]
|
||||
</app/routes>
|
||||
]
|
||||
nav [
|
||||
<app/nav out=[core.reactElement] />
|
||||
]
|
||||
</app/layout>
|
||||
]
|
||||
elements [
|
||||
@@ -282,43 +324,6 @@ describe('createApp', () => {
|
||||
]
|
||||
</app>
|
||||
]
|
||||
apis [
|
||||
<api:app-theme out=[core.api.factory]>
|
||||
themes [
|
||||
<theme:app/light out=[core.theme.theme] />
|
||||
<theme:app/dark out=[core.theme.theme] />
|
||||
]
|
||||
</api:app-theme>
|
||||
<api:app-language out=[core.api.factory] />
|
||||
<api:icons out=[core.api.factory] />
|
||||
<api:translations out=[core.api.factory] />
|
||||
<api:components out=[core.api.factory]>
|
||||
components [
|
||||
<component:core.components.progress out=[core.component.component] />
|
||||
<component:core.components.errorBoundaryFallback out=[core.component.component] />
|
||||
<component:core.components.notFoundErrorPage out=[core.component.component] />
|
||||
]
|
||||
</api:components>
|
||||
<api:feature-flags out=[core.api.factory] />
|
||||
<api:core.discovery out=[core.api.factory] />
|
||||
<api:core.alert out=[core.api.factory] />
|
||||
<api:core.analytics out=[core.api.factory] />
|
||||
<api:core.error out=[core.api.factory] />
|
||||
<api:core.storage out=[core.api.factory] />
|
||||
<api:core.fetch out=[core.api.factory] />
|
||||
<api:core.oauthrequest out=[core.api.factory] />
|
||||
<api:core.auth.google out=[core.api.factory] />
|
||||
<api:core.auth.microsoft out=[core.api.factory] />
|
||||
<api:core.auth.github out=[core.api.factory] />
|
||||
<api:core.auth.okta out=[core.api.factory] />
|
||||
<api:core.auth.gitlab out=[core.api.factory] />
|
||||
<api:core.auth.onelogin out=[core.api.factory] />
|
||||
<api:core.auth.bitbucket out=[core.api.factory] />
|
||||
<api:core.auth.bitbucket-server out=[core.api.factory] />
|
||||
<api:core.auth.atlassian out=[core.api.factory] />
|
||||
<api:core.auth.vmware-cloud out=[core.api.factory] />
|
||||
<api:plugin.permission.api out=[core.api.factory] />
|
||||
]
|
||||
</root>"
|
||||
`);
|
||||
});
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"@backstage/cli": "workspace:^",
|
||||
"@backstage/frontend-app-api": "workspace:^",
|
||||
"@backstage/frontend-test-utils": "workspace:^",
|
||||
"@backstage/plugin-app": "workspace:^",
|
||||
"@backstage/test-utils": "workspace:^",
|
||||
"@testing-library/jest-dom": "^6.0.0",
|
||||
"@testing-library/react": "^15.0.0",
|
||||
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
} from '../wiring';
|
||||
import { MockConfigApi } from '@backstage/test-utils';
|
||||
import { PageBlueprint } from './PageBlueprint';
|
||||
import appPlugin from '@backstage/plugin-app';
|
||||
|
||||
describe('RouterBlueprint', () => {
|
||||
it('should return an extension when calling make with sensible defaults', () => {
|
||||
@@ -74,6 +75,7 @@ describe('RouterBlueprint', () => {
|
||||
|
||||
const app = createSpecializedApp({
|
||||
features: [
|
||||
appPlugin,
|
||||
createExtensionOverrides({
|
||||
extensions: [
|
||||
extension,
|
||||
@@ -126,6 +128,7 @@ describe('RouterBlueprint', () => {
|
||||
|
||||
const app = createSpecializedApp({
|
||||
features: [
|
||||
appPlugin,
|
||||
createExtensionOverrides({
|
||||
extensions: [
|
||||
extension,
|
||||
|
||||
@@ -33,7 +33,7 @@ describe('ThemeBlueprint', () => {
|
||||
"$$type": "@backstage/ExtensionDefinition",
|
||||
"T": undefined,
|
||||
"attachTo": {
|
||||
"id": "api:app-theme",
|
||||
"id": "api:app/app-theme",
|
||||
"input": "themes",
|
||||
},
|
||||
"configSchema": undefined,
|
||||
|
||||
@@ -48,7 +48,7 @@ describe('TranslationBlueprint', () => {
|
||||
"$$type": "@backstage/ExtensionDefinition",
|
||||
"T": undefined,
|
||||
"attachTo": {
|
||||
"id": "api:translations",
|
||||
"id": "api:app/translations",
|
||||
"input": "translations",
|
||||
},
|
||||
"configSchema": undefined,
|
||||
|
||||
@@ -25,6 +25,7 @@ import { coreExtensionData } from './coreExtensionData';
|
||||
import { MockConfigApi, renderWithEffects } from '@backstage/test-utils';
|
||||
import { createExtensionInput } from './createExtensionInput';
|
||||
import { BackstagePlugin } from './types';
|
||||
import appPlugin from '@backstage/plugin-app';
|
||||
|
||||
const nameExtensionDataRef = createExtensionDataRef<string>().with({
|
||||
id: 'name',
|
||||
@@ -127,7 +128,7 @@ function createTestAppRoot({
|
||||
config: JsonObject;
|
||||
}) {
|
||||
return createApp({
|
||||
features,
|
||||
features: [...features, appPlugin],
|
||||
configLoader: async () => ({ config: new MockConfigApi(config) }),
|
||||
}).createRoot();
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
"@backstage/config": "workspace:^",
|
||||
"@backstage/frontend-app-api": "workspace:^",
|
||||
"@backstage/frontend-plugin-api": "workspace:^",
|
||||
"@backstage/plugin-app": "workspace:^",
|
||||
"@backstage/test-utils": "workspace:^",
|
||||
"@backstage/types": "workspace:^"
|
||||
},
|
||||
|
||||
@@ -27,12 +27,12 @@ import {
|
||||
coreExtensionData,
|
||||
RouteRef,
|
||||
useRouteRef,
|
||||
createExtensionInput,
|
||||
IconComponent,
|
||||
RouterBlueprint,
|
||||
NavItemBlueprint,
|
||||
FrontendFeature,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
import appPlugin from '@backstage/plugin-app';
|
||||
|
||||
/**
|
||||
* Options to customize the behavior of the test app.
|
||||
@@ -92,38 +92,36 @@ const NavItem = (props: {
|
||||
);
|
||||
};
|
||||
|
||||
export const TestAppNavExtension = createExtension({
|
||||
namespace: 'app',
|
||||
name: 'nav',
|
||||
attachTo: { id: 'app/layout', input: 'nav' },
|
||||
inputs: {
|
||||
items: createExtensionInput([NavItemBlueprint.dataRefs.target]),
|
||||
},
|
||||
output: [coreExtensionData.reactElement],
|
||||
factory({ inputs }) {
|
||||
return [
|
||||
coreExtensionData.reactElement(
|
||||
<nav>
|
||||
<ul>
|
||||
{inputs.items.map((item, index) => {
|
||||
const { icon, title, routeRef } = item.get(
|
||||
NavItemBlueprint.dataRefs.target,
|
||||
);
|
||||
const appPluginOverride = appPlugin.withOverrides({
|
||||
extensions: [
|
||||
appPlugin.getExtension('app/nav').override({
|
||||
output: [coreExtensionData.reactElement],
|
||||
factory(_originalFactory, { inputs }) {
|
||||
return [
|
||||
coreExtensionData.reactElement(
|
||||
<nav>
|
||||
<ul>
|
||||
{inputs.items.map((item, index) => {
|
||||
const { icon, title, routeRef } = item.get(
|
||||
NavItemBlueprint.dataRefs.target,
|
||||
);
|
||||
|
||||
return (
|
||||
<NavItem
|
||||
key={index}
|
||||
icon={icon}
|
||||
title={title}
|
||||
routeRef={routeRef}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</nav>,
|
||||
),
|
||||
];
|
||||
},
|
||||
return (
|
||||
<NavItem
|
||||
key={index}
|
||||
icon={icon}
|
||||
title={title}
|
||||
routeRef={routeRef}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</nav>,
|
||||
),
|
||||
];
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -152,7 +150,6 @@ export function renderInTestApp(
|
||||
Component: ({ children }) => <MemoryRouter>{children}</MemoryRouter>,
|
||||
},
|
||||
}),
|
||||
TestAppNavExtension,
|
||||
];
|
||||
|
||||
if (options?.mountedRoutes) {
|
||||
@@ -183,6 +180,7 @@ export function renderInTestApp(
|
||||
}
|
||||
|
||||
const features: FrontendFeature[] = [
|
||||
appPluginOverride,
|
||||
createExtensionOverrides({
|
||||
extensions,
|
||||
}),
|
||||
|
||||
@@ -75,16 +75,12 @@ export const AppRoot = createExtension({
|
||||
},
|
||||
output: [coreExtensionData.reactElement],
|
||||
factory({ inputs, apis }) {
|
||||
const identityApi = apis.get(identityApiRef);
|
||||
if (!identityApi) {
|
||||
throw new Error('App requires an Identity API implementation');
|
||||
}
|
||||
if (!('enableCookieAuth' in identityApi)) {
|
||||
throw new Error('Unexpected Identity API implementation');
|
||||
}
|
||||
const appIdentityProxy = identityApi as AppIdentityProxy;
|
||||
|
||||
if (isProtectedApp()) {
|
||||
const identityApi = apis.get(identityApiRef);
|
||||
if (!identityApi) {
|
||||
throw new Error('App requires an Identity API implementation');
|
||||
}
|
||||
const appIdentityProxy = toAppIdentityProxy(identityApi);
|
||||
const discoveryApi = apis.get(discoveryApiRef);
|
||||
const errorApi = apis.get(errorApiRef);
|
||||
const fetchApi = apis.get(fetchApiRef);
|
||||
@@ -119,7 +115,6 @@ export const AppRoot = createExtension({
|
||||
return [
|
||||
coreExtensionData.reactElement(
|
||||
<AppRouter
|
||||
appIdentityProxy={appIdentityProxy}
|
||||
SignInPageComponent={inputs.signInPage?.get(
|
||||
SignInPageBlueprint.dataRefs.component,
|
||||
)}
|
||||
@@ -174,6 +169,13 @@ type AppIdentityProxy = IdentityApi & {
|
||||
): void;
|
||||
};
|
||||
|
||||
function toAppIdentityProxy(identityApi: IdentityApi): AppIdentityProxy {
|
||||
if (!('enableCookieAuth' in identityApi)) {
|
||||
throw new Error('Unexpected Identity API implementation');
|
||||
}
|
||||
return identityApi as AppIdentityProxy;
|
||||
}
|
||||
|
||||
type RouteResolverProxy = {
|
||||
getRouteObjects(): any[];
|
||||
};
|
||||
@@ -184,7 +186,6 @@ type RouteResolverProxy = {
|
||||
*/
|
||||
export interface AppRouterProps {
|
||||
children?: ReactNode;
|
||||
appIdentityProxy: AppIdentityProxy;
|
||||
SignInPageComponent?: ComponentType<SignInPageProps>;
|
||||
RouterComponent?: ComponentType<PropsWithChildren<{}>>;
|
||||
}
|
||||
@@ -208,12 +209,12 @@ function DefaultRouter(props: PropsWithChildren<{}>) {
|
||||
export function AppRouter(props: AppRouterProps) {
|
||||
const {
|
||||
children,
|
||||
appIdentityProxy,
|
||||
SignInPageComponent,
|
||||
RouterComponent = DefaultRouter,
|
||||
} = props;
|
||||
|
||||
const configApi = useApi(configApiRef);
|
||||
const appIdentityProxy = toAppIdentityProxy(useApi(identityApiRef));
|
||||
const routeResolutionsApi = useApi(routeResolutionApiRef);
|
||||
const basePath = getBasePath(configApi);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user