fix: badge navigation + settings plugin name for E2E #56

Merged
ghost merged 2 commits from fix/e2e-badge-nav-and-settings-name into main 2026-03-17 17:06:14 +00:00
3 changed files with 54 additions and 12 deletions
+38 -8
View File
@@ -7,13 +7,7 @@ import { makeAuditData, makeResult } from '../test-utils';
// Mock Headlamp lib // Mock Headlamp lib
vi.mock('@kinvolk/headlamp-plugin/lib', () => ({ vi.mock('@kinvolk/headlamp-plugin/lib', () => ({
ApiProxy: { request: vi.fn() }, ApiProxy: { request: vi.fn() },
K8s: { K8s: {},
useCluster: () => 'test-cluster',
},
Router: {
createRouteURL: (name: string, params?: { cluster?: string }) =>
`/c/${params?.cluster ?? 'default'}/${name}`,
},
})); }));
vi.mock('@mui/material/styles', () => ({ vi.mock('@mui/material/styles', () => ({
@@ -31,6 +25,15 @@ vi.mock('react-router-dom', () => ({
useHistory: () => ({ push: mockPush }), 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(); const mockUsePolarisDataContext = vi.fn();
vi.mock('../api/PolarisDataContext', () => ({ vi.mock('../api/PolarisDataContext', () => ({
usePolarisDataContext: () => mockUsePolarisDataContext(), usePolarisDataContext: () => mockUsePolarisDataContext(),
@@ -97,7 +100,7 @@ describe('AppBarScoreBadge', () => {
expect(button.style.backgroundColor).toBe('rgb(244, 67, 54)'); expect(button.style.backgroundColor).toBe('rgb(244, 67, 54)');
}); });
it('navigates to /polaris on click', async () => { it('navigates to /c/<cluster>/polaris on click', async () => {
const user = userEvent.setup(); const user = userEvent.setup();
const data = makeAuditData([ const data = makeAuditData([
makeResult({ makeResult({
@@ -120,6 +123,33 @@ describe('AppBarScoreBadge', () => {
expect(mockPush).toHaveBeenCalledWith('/c/test-cluster/polaris'); 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(<AppBarScoreBadge />);
await user.click(screen.getByRole('button'));
expect(mockPush).toHaveBeenCalledWith('/polaris');
});
it('has correct aria-label', () => { it('has correct aria-label', () => {
const data = makeAuditData([ const data = makeAuditData([
makeResult({ makeResult({
+15 -3
View File
@@ -1,10 +1,21 @@
import { K8s, Router } from '@kinvolk/headlamp-plugin/lib';
import { useTheme } from '@mui/material/styles'; import { useTheme } from '@mui/material/styles';
import React from 'react'; import React from 'react';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import { computeScore, countResults } from '../api/polaris'; import { computeScore, countResults } from '../api/polaris';
import { usePolarisDataContext } from '../api/PolarisDataContext'; import { usePolarisDataContext } from '../api/PolarisDataContext';
/**
* Extract the cluster name from the current browser URL.
* Headlamp cluster routes follow the pattern /c/<cluster>/...
* 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 * App bar badge showing cluster Polaris score
* Clicking navigates to the overview dashboard * Clicking navigates to the overview dashboard
@@ -13,7 +24,6 @@ export default function AppBarScoreBadge() {
const theme = useTheme(); const theme = useTheme();
const { data, loading } = usePolarisDataContext(); const { data, loading } = usePolarisDataContext();
const history = useHistory(); const history = useHistory();
const cluster = K8s.useCluster();
if (loading || !data) { if (loading || !data) {
return null; // Graceful degradation when Polaris unavailable return null; // Graceful degradation when Polaris unavailable
@@ -36,7 +46,9 @@ export default function AppBarScoreBadge() {
}; };
const handleClick = () => { const handleClick = () => {
history.push(Router.createRouteURL('polaris', { cluster: cluster ?? '' })); const cluster = getClusterFromUrl();
const prefix = cluster ? `/c/${cluster}` : '';
history.push(`${prefix}/polaris`);
}; };
return ( return (
+1 -1
View File
@@ -99,7 +99,7 @@ registerRoute({
}); });
// Register plugin settings // Register plugin settings
registerPluginSettings('headlamp-polaris', PolarisSettings, true); registerPluginSettings('polaris', PolarisSettings, true);
// Register details view section for supported controller types // Register details view section for supported controller types
registerDetailsViewSection(({ resource }) => { registerDetailsViewSection(({ resource }) => {