Files
headlamp-polaris-plugin/src/components/DashboardView.test.tsx
T
DevContainer User 514de78ba7 fix: comprehensive code quality, theming, and test coverage improvements
- Fix ExemptionManager apiVersion bug (apps/batch resources used wrong API path)
- Replace resource: any with proper KubeResource interface (strict TypeScript)
- Replace all var(--mui-palette-*) CSS variables with useTheme() + theme.palette.*
- Replace custom drawer with MUI Drawer component (proper a11y and theming)
- Replace alert() calls with StatusLabel-based inline feedback
- Add PolarisErrorBoundary wrapping all registered plugin components
- Export getPolarisApiPath/isFullUrl from polaris.ts, deduplicate in PolarisSettings
- Fix PolarisDataContext test mock missing triggerRefresh
- Fix DashboardView test SimpleTable mock using any
- Remove dead NamespaceDetailView (replaced by drawer), unused MockPolarisProvider,
  unused getSeverityColor export
- Add tests for InlineAuditSection, AppBarScoreBadge, topIssues, checkMapping (32 new)
- Update CLAUDE.md, CHANGELOG.md, README.md for v0.6.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 16:59:50 +00:00

170 lines
4.7 KiB
TypeScript

import { render, screen } from '@testing-library/react';
import React from 'react';
import { describe, expect, it, vi } from 'vitest';
import { makeAuditData, makeResult } from '../test-utils';
// Mock Headlamp lib
vi.mock('@kinvolk/headlamp-plugin/lib', () => ({
ApiProxy: { request: vi.fn() },
}));
vi.mock('@mui/material/styles', () => ({
useTheme: () => ({
palette: {
primary: { main: '#1976d2' },
text: { primary: '#000', secondary: '#666' },
},
}),
}));
// Mock Headlamp CommonComponents as thin pass-throughs
vi.mock('@kinvolk/headlamp-plugin/lib/CommonComponents', () => ({
Loader: ({ title }: { title: string }) => <div data-testid="loader">{title}</div>,
SectionBox: ({ title, children }: { title?: string; children?: React.ReactNode }) => (
<div data-testid="section-box" data-title={title}>
{children}
</div>
),
SectionHeader: ({ title }: { title: string }) => <div data-testid="section-header">{title}</div>,
StatusLabel: ({ status, children }: { status: string; children?: React.ReactNode }) => (
<span data-testid="status-label" data-status={status}>
{children}
</span>
),
NameValueTable: ({ rows }: { rows: Array<{ name: string; value: React.ReactNode }> }) => (
<table data-testid="name-value-table">
<tbody>
{rows.map(row => (
<tr key={row.name}>
<td>{row.name}</td>
<td>{row.value}</td>
</tr>
))}
</tbody>
</table>
),
SimpleTable: ({
columns,
data,
}: {
columns: Array<{ label: string; getter: (row: unknown) => React.ReactNode }>;
data: unknown[];
}) => (
<table data-testid="simple-table">
<thead>
<tr>
{columns.map(col => (
<th key={col.label}>{col.label}</th>
))}
</tr>
</thead>
<tbody>
{data.map((row, i) => (
<tr key={i}>
{columns.map(col => (
<td key={col.label}>{col.getter(row)}</td>
))}
</tr>
))}
</tbody>
</table>
),
PercentageCircle: ({ label }: { label: string }) => (
<div data-testid="percentage-circle">{label}</div>
),
PercentageBar: () => <div data-testid="percentage-bar" />,
}));
// Mock the context hook — we'll override per test via mockReturnValue
const mockUsePolarisDataContext = vi.fn();
vi.mock('../api/PolarisDataContext', () => ({
usePolarisDataContext: () => mockUsePolarisDataContext(),
}));
import DashboardView from './DashboardView';
describe('DashboardView', () => {
it('renders loader when loading', () => {
mockUsePolarisDataContext.mockReturnValue({
data: null,
loading: true,
error: null,
});
render(<DashboardView />);
expect(screen.getByTestId('loader')).toHaveTextContent('Loading Polaris audit data');
});
it('renders error message when error is set', () => {
mockUsePolarisDataContext.mockReturnValue({
data: null,
loading: false,
error: 'Access denied (403)',
});
render(<DashboardView />);
expect(screen.getByText('Access denied (403)')).toBeInTheDocument();
});
it('renders score, check distribution, and cluster info with data', () => {
const data = makeAuditData([
makeResult({
Results: {
c1: {
ID: 'c1',
Message: '',
Details: [],
Success: true,
Severity: 'warning',
Category: 'X',
},
c2: {
ID: 'c2',
Message: '',
Details: [],
Success: false,
Severity: 'danger',
Category: 'X',
},
},
}),
]);
mockUsePolarisDataContext.mockReturnValue({
data,
loading: false,
error: null,
});
render(<DashboardView />);
// Score circle shows 50%
expect(screen.getByTestId('percentage-circle')).toHaveTextContent('50%');
// Check distribution values
expect(screen.getByText('Total Checks')).toBeInTheDocument();
// Cluster info section (title is in data-title attr of SectionBox)
const sectionBoxes = screen.getAllByTestId('section-box');
const clusterInfoBox = sectionBoxes.find(
el => el.getAttribute('data-title') === 'Cluster Info'
);
expect(clusterInfoBox).toBeDefined();
// Cluster info values
expect(screen.getByText('Nodes')).toBeInTheDocument();
expect(screen.getByText('Pods')).toBeInTheDocument();
});
it('renders "No Data" when no data and no error', () => {
mockUsePolarisDataContext.mockReturnValue({
data: null,
loading: false,
error: null,
});
render(<DashboardView />);
expect(screen.getByText('No Polaris audit results found.')).toBeInTheDocument();
});
});