core-app-api: allow path props in route elements

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2022-09-01 17:29:37 +02:00
parent 8a8c8a28b6
commit f9ec4e46e3
3 changed files with 30 additions and 27 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/core-app-api': patch
---
When using React Router v6 stable, it is now possible for components within the `Route` element tree to have `path` props, although they will be ignored.
@@ -453,18 +453,19 @@ describe('discovery', () => {
);
});
it('should throw elements within element prop contains a path', () => {
expect(() => {
traverseElementTree({
root: <Route path="foo" element={<Extension3 path="bar" />} />,
discoverers: [childDiscoverer, routeElementDiscoverer],
collectors: {
routing: routingV2Collector,
},
});
}).toThrow(
'Elements within the element prop tree may not have paths, found "bar"',
);
it('should ignore path props within route elements', () => {
const { routing } = traverseElementTree({
root: <Route path="foo" element={<Extension1 path="bar" />} />,
discoverers: [childDiscoverer, routeElementDiscoverer],
collectors: {
routing: routingV2Collector,
},
});
expect(sortedEntries(routing.paths)).toEqual([[ref1, 'foo']]);
expect(sortedEntries(routing.parents)).toEqual([[ref1, undefined]]);
expect(routing.objects).toEqual([
routeObj('foo', [ref1], [], undefined, plugin),
]);
});
it('should throw when a routable extension does not have a path set', () => {
@@ -53,6 +53,8 @@ interface RoutingV2CollectorContext {
isElementAncestor?: boolean;
}
// This collects all the mount points and their plugins within an element tree.
// Unlike regular traversal this ignores all other things, like path props and mount point gatherers.
function collectSubTree(
node: ReactNode,
entries = new Array<{ routeRef: RouteRef; plugin?: BackstagePlugin }>(),
@@ -62,12 +64,6 @@ function collectSubTree(
return;
}
if (element.props.path) {
throw new Error(
`Elements within the element prop tree may not have paths, found "${element.props.path}"`,
);
}
const routeRef = getComponentData<RouteRef>(element, 'core.mountPoint');
if (routeRef) {
const plugin = getComponentData<BackstagePlugin>(element, 'core.plugin');
@@ -87,6 +83,16 @@ export const routingV2Collector = createCollector(
objects: new Array<BackstageRouteObject>(),
}),
(acc, node, parent, ctx?: RoutingV2CollectorContext) => {
// If we're in an element prop, ignore everything
if (ctx?.isElementAncestor) {
return ctx;
}
// Start ignoring everything if we enter an element prop
if (parent?.props.element === node) {
return { ...ctx, isElementAncestor: true };
}
const pathProp: unknown = node.props?.path;
const mountPoint = getComponentData<RouteRef>(node, 'core.mountPoint');
@@ -98,15 +104,6 @@ export const routingV2Collector = createCollector(
);
}
// If we're in an element prop, ignore everything
if (ctx?.isElementAncestor) {
return ctx;
}
// Start ignoring everything if we enter an element prop
if (parent?.props.element === node) {
return { ...ctx, isElementAncestor: true };
}
const parentChildren = ctx?.obj?.children ?? acc.objects;
if (pathProp !== undefined) {