Add support for external refs renderInTestApp
Signed-off-by: Dylan O'Gara <dogara@webstaurantstore.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/frontend-test-utils': patch
|
||||
---
|
||||
|
||||
Added support for `ExternalRouteRef` in the `mountedRoutes` option of `renderInTestApp` and `renderTestApp`.
|
||||
@@ -26,6 +26,7 @@ import { EvaluatePermissionResponse } from '@backstage/plugin-permission-common'
|
||||
import { ExtensionDataRef } from '@backstage/frontend-plugin-api';
|
||||
import { ExtensionDefinition } from '@backstage/frontend-plugin-api';
|
||||
import { ExtensionDefinitionParameters } from '@backstage/frontend-plugin-api';
|
||||
import { ExternalRouteRef } from '@backstage/frontend-plugin-api';
|
||||
import { FeatureFlag } from '@backstage/frontend-plugin-api';
|
||||
import { FeatureFlagsApi } from '@backstage/frontend-plugin-api';
|
||||
import { FeatureFlagsSaveOptions } from '@backstage/frontend-plugin-api';
|
||||
@@ -444,7 +445,7 @@ export type RenderTestAppOptions<TApiPairs extends any[] = any[]> = {
|
||||
features?: FrontendFeature[];
|
||||
initialRouteEntries?: string[];
|
||||
mountedRoutes?: {
|
||||
[path: string]: RouteRef;
|
||||
[path: string]: RouteRef | ExternalRouteRef;
|
||||
};
|
||||
apis?: readonly [...TestApiPairs<TApiPairs>];
|
||||
};
|
||||
@@ -473,7 +474,7 @@ export type TestApiProviderProps<TApiPairs extends any[]> = {
|
||||
// @public
|
||||
export type TestAppOptions<TApiPairs extends any[] = any[]> = {
|
||||
mountedRoutes?: {
|
||||
[path: string]: RouteRef;
|
||||
[path: string]: RouteRef | ExternalRouteRef;
|
||||
};
|
||||
config?: JsonObject;
|
||||
features?: FrontendFeature[];
|
||||
|
||||
@@ -17,7 +17,12 @@
|
||||
import { useCallback } from 'react';
|
||||
import { screen, fireEvent } from '@testing-library/react';
|
||||
import { mockApis, TestApiProvider } from '@backstage/frontend-test-utils';
|
||||
import { useAnalytics } from '@backstage/frontend-plugin-api';
|
||||
import {
|
||||
useAnalytics,
|
||||
createRouteRef,
|
||||
createExternalRouteRef,
|
||||
useRouteRef,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
import { Routes, Route } from 'react-router-dom';
|
||||
import { renderInTestApp } from './renderInTestApp';
|
||||
|
||||
@@ -108,4 +113,40 @@ describe('renderInTestApp', () => {
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
it('should allow mounting route refs', () => {
|
||||
const testRouteRef = createRouteRef({
|
||||
params: ['name'],
|
||||
});
|
||||
|
||||
const LinkComponent = () => {
|
||||
const link = useRouteRef(testRouteRef);
|
||||
return <div>Link: {link?.({ name: 'test-name' }) ?? 'none'}</div>;
|
||||
};
|
||||
|
||||
renderInTestApp(<LinkComponent />, {
|
||||
mountedRoutes: {
|
||||
'/test-path/:name': testRouteRef,
|
||||
},
|
||||
});
|
||||
|
||||
expect(screen.getByText('Link: /test-path/test-name')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should allow mounting external route refs', () => {
|
||||
const externalRef = createExternalRouteRef({ params: ['name'] });
|
||||
|
||||
const ExternalLinkComponent = () => {
|
||||
const link = useRouteRef(externalRef);
|
||||
return <div>Link: {link?.({ name: 'test' }) ?? 'none'}</div>;
|
||||
};
|
||||
|
||||
renderInTestApp(<ExternalLinkComponent />, {
|
||||
mountedRoutes: {
|
||||
'/items/:name': externalRef,
|
||||
},
|
||||
});
|
||||
|
||||
expect(screen.getByText('Link: /items/test')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -32,6 +32,8 @@ import {
|
||||
FrontendFeature,
|
||||
createFrontendModule,
|
||||
createApiFactory,
|
||||
createRouteRef,
|
||||
ExternalRouteRef,
|
||||
type ApiRef,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
import { RouterBlueprint } from '@backstage/plugin-app-react';
|
||||
@@ -40,6 +42,7 @@ import { getMockApiFactory } from '../apis/MockWithApiFactory';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import type { CreateSpecializedAppInternalOptions } from '../../../frontend-app-api/src/wiring/createSpecializedApp';
|
||||
import { TestApiPairs } from '../apis/TestApiProvider';
|
||||
import { OpaqueExternalRouteRef } from '@internal/frontend';
|
||||
|
||||
const DEFAULT_MOCK_CONFIG = {
|
||||
app: { baseUrl: 'http://localhost:3000' },
|
||||
@@ -67,7 +70,7 @@ export type TestAppOptions<TApiPairs extends any[] = any[]> = {
|
||||
* const link = useRouteRef(myRouteRef)
|
||||
* ```
|
||||
*/
|
||||
mountedRoutes?: { [path: string]: RouteRef };
|
||||
mountedRoutes?: { [path: string]: RouteRef | ExternalRouteRef };
|
||||
|
||||
/**
|
||||
* Additional configuration passed to the app when rendering elements inside it.
|
||||
@@ -180,9 +183,20 @@ export function renderInTestApp<const TApiPairs extends any[] = any[]>(
|
||||
}),
|
||||
];
|
||||
|
||||
const externalBindings = new Map<ExternalRouteRef, RouteRef>();
|
||||
|
||||
if (options?.mountedRoutes) {
|
||||
for (const [path, routeRef] of Object.entries(options.mountedRoutes)) {
|
||||
// TODO(Rugvip): add support for external route refs
|
||||
for (const [path, optionRef] of Object.entries(options.mountedRoutes)) {
|
||||
let routeRef: RouteRef;
|
||||
|
||||
if (OpaqueExternalRouteRef.isType(optionRef)) {
|
||||
// Create an actual route ref for the external route, then bind the external ref to it
|
||||
routeRef = createRouteRef();
|
||||
externalBindings.set(optionRef, routeRef);
|
||||
} else {
|
||||
routeRef = optionRef;
|
||||
}
|
||||
|
||||
extensions.push(
|
||||
createExtension({
|
||||
kind: 'test-route',
|
||||
@@ -253,6 +267,14 @@ export function renderInTestApp<const TApiPairs extends any[] = any[]>(
|
||||
return createApiFactory(apiRef, implementation);
|
||||
}),
|
||||
},
|
||||
bindRoutes:
|
||||
externalBindings.size > 0
|
||||
? ({ bind }) => {
|
||||
for (const [externalRef, targetRef] of externalBindings) {
|
||||
bind({ ref: externalRef }, { ref: targetRef });
|
||||
}
|
||||
}
|
||||
: undefined,
|
||||
} as CreateSpecializedAppInternalOptions).finalize();
|
||||
|
||||
return render(
|
||||
|
||||
@@ -25,6 +25,8 @@ import {
|
||||
ExtensionDefinition,
|
||||
FrontendFeature,
|
||||
RouteRef,
|
||||
ExternalRouteRef,
|
||||
createRouteRef,
|
||||
type ApiRef,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
import { render, type RenderResult } from '@testing-library/react';
|
||||
@@ -37,6 +39,7 @@ import { getMockApiFactory } from '../apis/MockWithApiFactory';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import type { CreateSpecializedAppInternalOptions } from '../../../frontend-app-api/src/wiring/createSpecializedApp';
|
||||
import { TestApiPairs } from '../apis/TestApiProvider';
|
||||
import { OpaqueExternalRouteRef } from '@internal/frontend';
|
||||
|
||||
const DEFAULT_MOCK_CONFIG = {
|
||||
app: { baseUrl: 'http://localhost:3000' },
|
||||
@@ -83,7 +86,7 @@ export type RenderTestAppOptions<TApiPairs extends any[] = any[]> = {
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
mountedRoutes?: { [path: string]: RouteRef };
|
||||
mountedRoutes?: { [path: string]: RouteRef | ExternalRouteRef };
|
||||
|
||||
/**
|
||||
* API overrides to provide to the test app. Use `mockApis` helpers
|
||||
@@ -121,8 +124,20 @@ export function renderTestApp<const TApiPairs extends any[] = any[]>(
|
||||
): RenderResult {
|
||||
const extensions = [...(options?.extensions ?? [])];
|
||||
|
||||
const externalBindings = new Map<ExternalRouteRef, RouteRef>();
|
||||
|
||||
if (options?.mountedRoutes) {
|
||||
for (const [path, routeRef] of Object.entries(options.mountedRoutes)) {
|
||||
for (const [path, optionRef] of Object.entries(options.mountedRoutes)) {
|
||||
let routeRef: RouteRef;
|
||||
|
||||
if (OpaqueExternalRouteRef.isType(optionRef)) {
|
||||
// Create an actual route ref for the external route, then bind the external ref to it
|
||||
routeRef = createRouteRef();
|
||||
externalBindings.set(optionRef, routeRef);
|
||||
} else {
|
||||
routeRef = optionRef;
|
||||
}
|
||||
|
||||
extensions.push(
|
||||
createExtension({
|
||||
kind: 'test-route',
|
||||
@@ -193,6 +208,14 @@ export function renderTestApp<const TApiPairs extends any[] = any[]>(
|
||||
return createApiFactory(apiRef, implementation);
|
||||
}),
|
||||
},
|
||||
bindRoutes:
|
||||
externalBindings.size > 0
|
||||
? ({ bind }) => {
|
||||
for (const [externalRef, targetRef] of externalBindings) {
|
||||
bind({ ref: externalRef }, { ref: targetRef });
|
||||
}
|
||||
}
|
||||
: undefined,
|
||||
} as CreateSpecializedAppInternalOptions).finalize();
|
||||
|
||||
return render(
|
||||
|
||||
Reference in New Issue
Block a user