diff --git a/public/app/features/scopes/dashboards/ScopesNavigationTreeLink.test.tsx b/public/app/features/scopes/dashboards/ScopesNavigationTreeLink.test.tsx index b8775a3c21b..3aba827d4ef 100644 --- a/public/app/features/scopes/dashboards/ScopesNavigationTreeLink.test.tsx +++ b/public/app/features/scopes/dashboards/ScopesNavigationTreeLink.test.tsx @@ -105,4 +105,32 @@ describe('ScopesNavigationTreeLink', () => { expect(matchingLink).toHaveAttribute('aria-current', 'page'); expect(otherLink).not.toHaveAttribute('aria-current'); }); + + it('shows correct icon for grafana-metricsdrilldown-app with query parameters', () => { + renderWithRouter( + + ); + + const link = screen.getByTestId('scopes-dashboards-metrics-drilldown'); + // Icon should be rendered (check for SVG element which is how Icon renders) + const icon = link.querySelector('svg'); + expect(icon).toBeInTheDocument(); + // The link should contain the title text + expect(link).toHaveTextContent('Metrics Drilldown'); + }); + + it('shows correct icon for grafana-metricsdrilldown-app without trailing slash', () => { + renderWithRouter( + + ); + + const link = screen.getByTestId('scopes-dashboards-metrics-drilldown'); + const icon = link.querySelector('svg'); + expect(icon).toBeInTheDocument(); + expect(link).toHaveTextContent('Metrics Drilldown'); + }); }); diff --git a/public/app/features/scopes/dashboards/ScopesNavigationTreeLink.tsx b/public/app/features/scopes/dashboards/ScopesNavigationTreeLink.tsx index 41481ca0446..859b6059059 100644 --- a/public/app/features/scopes/dashboards/ScopesNavigationTreeLink.tsx +++ b/public/app/features/scopes/dashboards/ScopesNavigationTreeLink.tsx @@ -5,7 +5,7 @@ import { Link, useLocation } from 'react-router-dom-v5-compat'; import { GrafanaTheme2, IconName, locationUtil } from '@grafana/data'; import { Icon, useStyles2 } from '@grafana/ui'; -import { isCurrentPath } from './scopeNavgiationUtils'; +import { isCurrentPath, normalizePath } from './scopeNavgiationUtils'; export interface ScopesNavigationTreeLinkProps { to: string; @@ -36,25 +36,30 @@ export function ScopesNavigationTreeLink({ to, title, id }: ScopesNavigationTree } function getLinkIcon(to: string) { - // Strip base URL and normalize path - const normalizedPath = locationUtil.stripBaseFromUrl(to); - for (const [key, value] of linkMap.entries()) { - if (normalizedPath.startsWith(key)) { - return value; - } + // Check for external links before stripping base (stripBaseFromUrl removes http:// for same-origin URLs) + if (to.startsWith('http')) { + return 'external-link-alt'; } - return 'link'; + // Strip base URL and normalize path (remove query params and hash) + const baseStripped = locationUtil.stripBaseFromUrl(to); + const normalizedPath = normalizePath(baseStripped); + + // Check for dashboard paths with startsWith (e.g., /d/dashboard-id) + if (normalizedPath.startsWith('/d')) { + return 'apps'; + } + + // Use direct Map lookup for exact path matches + return linkMap.get(normalizedPath) ?? 'link'; } const linkMap = new Map([ - ['http', 'external-link-alt'], - ['/d', 'apps'], ['/explore/metrics', 'drilldown'], - ['/a/grafana-metricsdrilldown-app/', 'drilldown'], - ['/a/grafana-lokiexplore-app/', 'drilldown'], - ['/a/grafana-exploretraces-app/', 'drilldown'], - ['/a/grafana-pyroscope-app/', 'drilldown'], + ['/a/grafana-metricsdrilldown-app', 'drilldown'], + ['/a/grafana-lokiexplore-app', 'drilldown'], + ['/a/grafana-exploretraces-app', 'drilldown'], + ['/a/grafana-pyroscope-app', 'drilldown'], ]); const getStyles = (theme: GrafanaTheme2) => {