diff --git a/packages/core-app-api/src/routing/RouteTracker.test.tsx b/packages/core-app-api/src/routing/RouteTracker.test.tsx
index 695e5bbf38..25d5cfbcfb 100644
--- a/packages/core-app-api/src/routing/RouteTracker.test.tsx
+++ b/packages/core-app-api/src/routing/RouteTracker.test.tsx
@@ -39,6 +39,7 @@ describe('RouteTracker', () => {
});
const plugin0 = createPlugin({ id: 'home' });
const plugin1 = createPlugin({ id: 'plugin1' });
+ const plugin2 = createPlugin({ id: 'plugin2' });
const routeObjects: BackstageRouteObject[] = [
{
@@ -61,7 +62,7 @@ describe('RouteTracker', () => {
path: '/path2/:param',
element:
hi there
,
routeRefs: new Set([routeRef2]),
- plugins: new Set(),
+ plugins: new Set([plugin2]),
caseSensitive: false,
children: [MATCH_ALL_ROUTE],
},
@@ -124,7 +125,7 @@ describe('RouteTracker', () => {
},
context: {
extension: 'App',
- pluginId: 'root',
+ pluginId: 'plugin2',
routeRef: 'route2',
},
subject: '/path2/hello',
@@ -179,7 +180,7 @@ describe('RouteTracker', () => {
});
});
- it('should return default context when no plugin/routeRef is on the route', async () => {
+ it('should return default context when it would have otherwise matched on the root path', async () => {
render(
@@ -206,4 +207,28 @@ describe('RouteTracker', () => {
value: undefined,
});
});
+
+ it('should return parent route context on navigating to a sub-route', async () => {
+ render(
+
+
+
+
+ ,
+ );
+
+ expect(mockedAnalytics.captureEvent).toHaveBeenCalledWith({
+ action: 'navigate',
+ attributes: {
+ param: 'param-value',
+ },
+ context: {
+ extension: 'App',
+ pluginId: 'plugin2',
+ routeRef: 'route2',
+ },
+ subject: '/path2/param-value/sub-route',
+ value: undefined,
+ });
+ });
});
diff --git a/packages/core-app-api/src/routing/RouteTracker.tsx b/packages/core-app-api/src/routing/RouteTracker.tsx
index bed72b6134..69903268ac 100644
--- a/packages/core-app-api/src/routing/RouteTracker.tsx
+++ b/packages/core-app-api/src/routing/RouteTracker.tsx
@@ -38,9 +38,11 @@ const getExtensionContext = (
const matches = matchRoutes(routes, { pathname });
// Of the matching routes, get the last (e.g. most specific) instance of
- // the BackstageRouteObject.
- const routeMatch = matches?.pop();
-
+ // the BackstageRouteObject that contains a routeRef. Filtering by routeRef
+ // ensures subRouteRefs are aligned to their parent routes' context.
+ const routeMatch = matches
+ ?.filter(match => match?.route.routeRefs?.size > 0)
+ .pop();
const routeObject = routeMatch?.route;
// If there is no route object, then allow inheritance of default context.
@@ -48,6 +50,12 @@ const getExtensionContext = (
return undefined;
}
+ // If the matched route is the root route (no path), and the pathname is
+ // not the path of the homepage, then inherit from the default context.
+ if (routeObject.path === '' && pathname !== '/') {
+ return undefined;
+ }
+
// If there is a single route ref, use it.
let routeRef: RouteRef | undefined;
if (routeObject.routeRefs.size === 1) {