diff --git a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.test.ts b/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.test.ts
index b4e2675d51..c64dc7a3b9 100644
--- a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.test.ts
+++ b/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.test.ts
@@ -233,53 +233,53 @@ describe('discovery', () => {
]);
});
- // it('should handle absolute route paths', () => {
- // const info = routeInfoFromExtensions([
- // createTestExtension({
- // id: 'page1',
- // path: '/foo',
- // routeRef: ref1,
- // }),
- // createTestExtension({
- // id: 'page2',
- // at: 'page1/children',
- // path: '/bar/:id',
- // routeRef: ref2,
- // }),
- // createTestExtension({
- // id: 'page3',
- // path: '/baz',
- // routeRef: ref3,
- // }),
- // createTestExtension({
- // id: 'page4',
- // at: 'page3/children',
- // path: '/divsoup',
- // routeRef: ref4,
- // }),
- // createTestExtension({
- // id: 'page5',
- // at: 'page3/children',
- // path: '/blop',
- // routeRef: ref5,
- // }),
- // ]);
+ it('should strip leading slashes in route paths', () => {
+ const info = routeInfoFromExtensions([
+ createTestExtension({
+ id: 'page1',
+ path: '/foo',
+ routeRef: ref1,
+ }),
+ createTestExtension({
+ id: 'page2',
+ at: 'page1/children',
+ path: '/bar/:id',
+ routeRef: ref2,
+ }),
+ createTestExtension({
+ id: 'page3',
+ path: '/baz',
+ routeRef: ref3,
+ }),
+ createTestExtension({
+ id: 'page4',
+ at: 'page3/children',
+ path: '/divsoup',
+ routeRef: ref4,
+ }),
+ createTestExtension({
+ id: 'page5',
+ at: 'page3/children',
+ path: '/blop',
+ routeRef: ref5,
+ }),
+ ]);
- // expect(sortedEntries(info.routePaths)).toEqual([
- // [ref1, 'foo'],
- // [ref2, 'bar/:id'],
- // [ref3, 'baz'],
- // [ref4, 'divsoup'],
- // [ref5, 'blop'],
- // ]);
- // expect(sortedEntries(info.routeParents)).toEqual([
- // [ref1, undefined],
- // [ref2, ref1],
- // [ref3, undefined],
- // [ref4, ref3],
- // [ref5, ref3],
- // ]);
- // });
+ expect(sortedEntries(info.routePaths)).toEqual([
+ [ref1, 'foo'],
+ [ref2, 'bar/:id'],
+ [ref3, 'baz'],
+ [ref4, 'divsoup'],
+ [ref5, 'blop'],
+ ]);
+ expect(sortedEntries(info.routeParents)).toEqual([
+ [ref1, undefined],
+ [ref2, ref1],
+ [ref3, undefined],
+ [ref4, ref3],
+ [ref5, ref3],
+ ]);
+ });
it('should use the route aggregator key to bind child routes to the same path', () => {
const info = routeInfoFromExtensions([
@@ -338,7 +338,7 @@ describe('discovery', () => {
[ref2, undefined],
[ref3, undefined],
[ref4, ref3],
- [ref5, ref4],
+ [ref5, ref3],
]);
expect(info.routeObjects).toEqual([
routeObj('foo', [ref1, ref2], [], 'mounted', expect.any(Object)),
@@ -352,166 +352,177 @@ describe('discovery', () => {
]);
});
- // it('should use the route aggregator but stop when encountering explicit path', () => {
- // const root = (
- //
- //
- // }>
- //
- //
- //
- // }>
- // } />
- //
- //
- //
- //
- //
- //
- //
- //
- // );
+ it('should use the route aggregator but stop when encountering explicit path', () => {
+ const info = routeInfoFromExtensions([
+ createTestExtension({
+ id: 'page1',
+ path: 'foo',
+ routeRef: ref1,
+ }),
+ createTestExtension({
+ id: 'page1Child',
+ at: 'page1/children',
+ path: 'bar',
+ }),
+ createTestExtension({
+ id: 'page2',
+ at: 'page1Child/children',
+ routeRef: ref2,
+ }),
+ createTestExtension({
+ id: 'page3',
+ at: 'page2/children',
+ path: 'baz',
+ routeRef: ref3,
+ }),
+ createTestExtension({
+ id: 'page4',
+ at: 'page3/children',
+ path: '/blop',
+ routeRef: ref4,
+ }),
+ createTestExtension({
+ id: 'page5',
+ at: 'page2/children',
+ routeRef: ref5,
+ }),
+ ]);
- // const { routing } = traverseElementTree({
- // root,
- // discoverers: [childDiscoverer, routeElementDiscoverer],
- // collectors: {
- // routing: routingV2Collector,
- // },
- // });
- // expect(sortedEntries(routing.paths)).toEqual([
- // [ref1, 'foo'],
- // [ref2, 'bar'],
- // [ref3, 'baz'],
- // [ref4, 'blop'],
- // [ref5, 'bar'],
- // ]);
- // expect(sortedEntries(routing.parents)).toEqual([
- // [ref1, undefined],
- // [ref2, ref1],
- // [ref3, ref2],
- // [ref4, ref3],
- // [ref5, ref1],
- // ]);
- // expect(routing.objects).toEqual([
- // routeObj(
- // 'foo',
- // [ref1],
- // [
- // routeObj(
- // 'bar',
- // [ref2, ref5],
- // [
- // routeObj(
- // 'baz',
- // [ref3],
- // [routeObj('blop', [ref4], undefined, undefined, plugin)],
- // undefined,
- // plugin,
- // ),
- // ],
- // 'gathered',
- // plugin,
- // ),
- // ],
- // undefined,
- // plugin,
- // ),
- // ]);
- // });
+ expect(sortedEntries(info.routePaths)).toEqual([
+ [ref1, 'foo'],
+ [ref2, 'bar'],
+ [ref3, 'baz'],
+ [ref4, 'blop'],
+ [ref5, 'bar'],
+ ]);
+ expect(sortedEntries(info.routeParents)).toEqual([
+ [ref1, undefined],
+ [ref2, ref1],
+ [ref3, ref2],
+ [ref4, ref3],
+ [ref5, ref1],
+ ]);
+ expect(info.routeObjects).toEqual([
+ routeObj(
+ 'foo',
+ [ref1],
+ [
+ routeObj(
+ 'bar',
+ [ref2, ref5],
+ [
+ routeObj(
+ 'baz',
+ [ref3],
+ [
+ routeObj(
+ 'blop',
+ [ref4],
+ undefined,
+ undefined,
+ expect.any(Object),
+ ),
+ ],
+ undefined,
+ expect.any(Object),
+ ),
+ ],
+ 'mounted',
+ expect.any(Object),
+ ),
+ ],
+ undefined,
+ expect.any(Object),
+ ),
+ ]);
+ });
- // it('should throw when you provide path property on an extension', () => {
- // expect(() => {
- // traverseElementTree({
- // root: ,
- // discoverers: [childDiscoverer, routeElementDiscoverer],
- // collectors: {
- // routing: routingV2Collector,
- // },
- // });
- // }).toThrow(
- // 'Path property may not be set directly on a routable extension "Extension(Extension1)"',
- // );
- // });
+ it('should account for loose route paths', () => {
+ const info = routeInfoFromExtensions([
+ createTestExtension({
+ id: 'r',
+ path: 'r',
+ }),
+ createTestExtension({
+ id: 'page1',
+ at: 'r/children',
+ path: 'x',
+ routeRef: ref1,
+ }),
+ createTestExtension({
+ id: 'y',
+ path: 'y',
+ at: 'r/children',
+ }),
+ createTestExtension({
+ id: 'page2',
+ at: 'y/children',
+ path: '1',
+ routeRef: ref2,
+ }),
+ createTestExtension({
+ id: 'page3',
+ at: 'page2/children',
+ path: 'a',
+ routeRef: ref3,
+ }),
+ createTestExtension({
+ id: 'page4',
+ at: 'page2/children',
+ path: 'b',
+ routeRef: ref4,
+ }),
+ ]);
- // it('should throw when element prop is not a string', () => {
- // const Div = 'div' as unknown as ComponentType<{ path: boolean }>;
- // expect(() => {
- // traverseElementTree({
- // root:
,
- // discoverers: [childDiscoverer, routeElementDiscoverer],
- // collectors: {
- // routing: routingV2Collector,
- // },
- // });
- // }).toThrow('Element path must be a string at "div"');
- // });
-
- // it('should throw when the mount point gatherers have an element prop', () => {
- // const AnyAggregationComponent = AggregationComponent as any;
- // expect(() => {
- // traverseElementTree({
- // root: } />,
- // discoverers: [childDiscoverer, routeElementDiscoverer],
- // collectors: {
- // routing: routingV2Collector,
- // },
- // });
- // }).toThrow(
- // 'Mount point gatherers may not have an element prop "AggregationComponent"',
- // );
- // });
-
- // it('should ignore path props within route elements', () => {
- // const { routing } = traverseElementTree({
- // root: } />,
- // 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', () => {
- // expect(() => {
- // traverseElementTree({
- // root: ,
- // discoverers: [childDiscoverer, routeElementDiscoverer],
- // collectors: {
- // routing: routingV2Collector,
- // },
- // });
- // }).toThrow(
- // 'Routable extension "Extension(Extension3)" with mount point "routeRef{type=absolute,id=ref3}" must be assigned a path',
- // );
- // });
-
- // it('should throw when Route elements contain multiple routable extensions', () => {
- // expect(() => {
- // traverseElementTree({
- // root: (
- //
- //
- //
- // >
- // }
- // />
- // ),
- // discoverers: [childDiscoverer, routeElementDiscoverer],
- // collectors: {
- // routing: routingV2Collector,
- // },
- // });
- // }).toThrow(
- // 'Route element with path "foo" may not contain multiple routable extensions',
- // );
- // });
+ expect(sortedEntries(info.routePaths)).toEqual([
+ [ref1, 'r/x'],
+ [ref2, 'r/y/1'],
+ [ref3, 'a'],
+ [ref4, 'b'],
+ ]);
+ expect(sortedEntries(info.routeParents)).toEqual([
+ [ref1, undefined],
+ [ref2, undefined],
+ [ref3, ref2],
+ [ref4, ref2],
+ ]);
+ expect(info.routeObjects).toEqual([
+ routeObj(
+ 'r',
+ [],
+ [
+ routeObj('x', [ref1], [], 'mounted', expect.any(Object)),
+ routeObj(
+ 'y',
+ [],
+ [
+ routeObj(
+ '1',
+ [ref2],
+ [
+ routeObj(
+ 'a',
+ [ref3],
+ undefined,
+ 'mounted',
+ expect.any(Object),
+ ),
+ routeObj(
+ 'b',
+ [ref4],
+ undefined,
+ 'mounted',
+ expect.any(Object),
+ ),
+ ],
+ 'mounted',
+ expect.any(Object),
+ ),
+ ],
+ 'mounted',
+ ),
+ ],
+ ),
+ ]);
+ });
});
diff --git a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts b/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts
index 2d6af97198..a7df7978cc 100644
--- a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts
+++ b/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts
@@ -56,14 +56,19 @@ export function extractRouteInfoFromInstanceTree(roots: ExtensionInstance[]): {
collectedPath?: string,
foundRefForCollectedPath: boolean = false,
parentRef?: RouteRef,
+ candidateParentRef?: RouteRef,
parentObj?: BackstageRouteObject,
) {
- const routePath = current.getData(coreExtensionData.routePath);
+ const routePath = current
+ .getData(coreExtensionData.routePath)
+ ?.replace(/^\//, '');
const routeRef = current.getData(coreExtensionData.routeRef);
const parentChildren = parentObj?.children ?? routeObjects;
let currentObj = parentObj;
let newCollectedPath = collectedPath;
let newFoundRefForCollectedPath = foundRefForCollectedPath;
+ let newParentRef = parentRef;
+ let newCandidateParentRef = candidateParentRef;
if (routePath !== undefined) {
currentObj = {
@@ -85,6 +90,9 @@ export function extractRouteInfoFromInstanceTree(roots: ExtensionInstance[]): {
? joinPaths(collectedPath, routePath)
: routePath;
}
+
+ newParentRef = candidateParentRef;
+ newCandidateParentRef = undefined;
}
if (routeRef) {
@@ -95,12 +103,16 @@ export function extractRouteInfoFromInstanceTree(roots: ExtensionInstance[]): {
);
}
+ if (!newCandidateParentRef) {
+ newCandidateParentRef = routeRef;
+ }
+
if (newCollectedPath !== undefined) {
routePaths.set(routeRef, newCollectedPath);
newFoundRefForCollectedPath = true;
}
- routeParents.set(routeRef, parentRef);
+ routeParents.set(routeRef, newParentRef);
currentObj?.routeRefs.add(routeRef);
if (current.source) {
currentObj?.plugins.add(toLegacyPlugin(current.source));
@@ -113,7 +125,8 @@ export function extractRouteInfoFromInstanceTree(roots: ExtensionInstance[]): {
child,
newCollectedPath,
newFoundRefForCollectedPath,
- routeRef ?? parentRef,
+ newParentRef,
+ newCandidateParentRef,
currentObj,
);
}