diff --git a/src/components/AppBarScoreBadge.test.tsx b/src/components/AppBarScoreBadge.test.tsx index 75616ca..dd55067 100644 --- a/src/components/AppBarScoreBadge.test.tsx +++ b/src/components/AppBarScoreBadge.test.tsx @@ -7,13 +7,7 @@ import { makeAuditData, makeResult } from '../test-utils'; // Mock Headlamp lib vi.mock('@kinvolk/headlamp-plugin/lib', () => ({ ApiProxy: { request: vi.fn() }, - K8s: { - useCluster: () => 'test-cluster', - }, - Router: { - createRouteURL: (name: string, params?: { cluster?: string }) => - `/c/${params?.cluster ?? 'default'}/${name}`, - }, + K8s: {}, })); vi.mock('@mui/material/styles', () => ({ @@ -31,6 +25,15 @@ vi.mock('react-router-dom', () => ({ useHistory: () => ({ push: mockPush }), })); +// Set window.location.pathname for cluster extraction +beforeEach(() => { + Object.defineProperty(window, 'location', { + value: { pathname: '/c/test-cluster/some-page' }, + writable: true, + }); + mockPush.mockClear(); +}); + const mockUsePolarisDataContext = vi.fn(); vi.mock('../api/PolarisDataContext', () => ({ usePolarisDataContext: () => mockUsePolarisDataContext(), @@ -97,7 +100,7 @@ describe('AppBarScoreBadge', () => { expect(button.style.backgroundColor).toBe('rgb(244, 67, 54)'); }); - it('navigates to /polaris on click', async () => { + it('navigates to /c//polaris on click', async () => { const user = userEvent.setup(); const data = makeAuditData([ makeResult({ @@ -120,6 +123,33 @@ describe('AppBarScoreBadge', () => { expect(mockPush).toHaveBeenCalledWith('/c/test-cluster/polaris'); }); + it('navigates to /polaris when no cluster in URL', async () => { + Object.defineProperty(window, 'location', { + value: { pathname: '/settings' }, + writable: true, + }); + const user = userEvent.setup(); + const data = makeAuditData([ + makeResult({ + Results: { + c1: { + ID: 'c1', + Message: '', + Details: [], + Success: true, + Severity: 'warning', + Category: 'X', + }, + }, + }), + ]); + mockUsePolarisDataContext.mockReturnValue({ data, loading: false }); + + render(); + await user.click(screen.getByRole('button')); + expect(mockPush).toHaveBeenCalledWith('/polaris'); + }); + it('has correct aria-label', () => { const data = makeAuditData([ makeResult({ diff --git a/src/components/AppBarScoreBadge.tsx b/src/components/AppBarScoreBadge.tsx index 02b6bbb..5da51a6 100644 --- a/src/components/AppBarScoreBadge.tsx +++ b/src/components/AppBarScoreBadge.tsx @@ -1,10 +1,21 @@ -import { K8s, Router } from '@kinvolk/headlamp-plugin/lib'; import { useTheme } from '@mui/material/styles'; import React from 'react'; import { useHistory } from 'react-router-dom'; import { computeScore, countResults } from '../api/polaris'; import { usePolarisDataContext } from '../api/PolarisDataContext'; +/** + * Extract the cluster name from the current browser URL. + * Headlamp cluster routes follow the pattern /c//... + * We read window.location.pathname directly because the AppBar renders + * outside the cluster route context, so useCluster() returns null and + * React Router's useLocation() may not reflect the cluster prefix. + */ +function getClusterFromUrl(): string | null { + const match = window.location.pathname.match(/\/c\/([^/]+)/); + return match ? match[1] : null; +} + /** * App bar badge showing cluster Polaris score * Clicking navigates to the overview dashboard @@ -13,7 +24,6 @@ export default function AppBarScoreBadge() { const theme = useTheme(); const { data, loading } = usePolarisDataContext(); const history = useHistory(); - const cluster = K8s.useCluster(); if (loading || !data) { return null; // Graceful degradation when Polaris unavailable @@ -36,7 +46,9 @@ export default function AppBarScoreBadge() { }; const handleClick = () => { - history.push(Router.createRouteURL('polaris', { cluster: cluster ?? '' })); + const cluster = getClusterFromUrl(); + const prefix = cluster ? `/c/${cluster}` : ''; + history.push(`${prefix}/polaris`); }; return ( diff --git a/src/index.tsx b/src/index.tsx index 5a90bbe..e5d068f 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -99,7 +99,7 @@ registerRoute({ }); // Register plugin settings -registerPluginSettings('headlamp-polaris', PolarisSettings, true); +registerPluginSettings('polaris', PolarisSettings, true); // Register details view section for supported controller types registerDetailsViewSection(({ resource }) => {