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>
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { makeAuditData, makeResult } from '../test-utils';
|
||||
import { getTopIssues } from './topIssues';
|
||||
|
||||
describe('getTopIssues', () => {
|
||||
it('returns empty array when no results', () => {
|
||||
const data = makeAuditData([]);
|
||||
expect(getTopIssues(data)).toEqual([]);
|
||||
});
|
||||
|
||||
it('returns empty array when all checks pass', () => {
|
||||
const data = makeAuditData([
|
||||
makeResult({
|
||||
Results: {
|
||||
c1: {
|
||||
ID: 'c1',
|
||||
Message: '',
|
||||
Details: [],
|
||||
Success: true,
|
||||
Severity: 'warning',
|
||||
Category: 'X',
|
||||
},
|
||||
},
|
||||
}),
|
||||
]);
|
||||
expect(getTopIssues(data)).toEqual([]);
|
||||
});
|
||||
|
||||
it('aggregates failing checks from controller-level results', () => {
|
||||
const data = makeAuditData([
|
||||
makeResult({
|
||||
Results: {
|
||||
cpuRequestsMissing: {
|
||||
ID: 'cpuRequestsMissing',
|
||||
Message: 'missing',
|
||||
Details: [],
|
||||
Success: false,
|
||||
Severity: 'warning',
|
||||
Category: 'Efficiency',
|
||||
},
|
||||
},
|
||||
}),
|
||||
]);
|
||||
const issues = getTopIssues(data);
|
||||
expect(issues).toHaveLength(1);
|
||||
expect(issues[0].checkId).toBe('cpuRequestsMissing');
|
||||
expect(issues[0].checkName).toBe('CPU Requests');
|
||||
expect(issues[0].severity).toBe('warning');
|
||||
expect(issues[0].count).toBe(1);
|
||||
});
|
||||
|
||||
it('aggregates failing checks from pod and container results', () => {
|
||||
const data = makeAuditData([
|
||||
makeResult({
|
||||
Results: {},
|
||||
PodResult: {
|
||||
Name: 'pod-1',
|
||||
Results: {
|
||||
hostIPCSet: {
|
||||
ID: 'hostIPCSet',
|
||||
Message: '',
|
||||
Details: [],
|
||||
Success: false,
|
||||
Severity: 'danger',
|
||||
Category: 'Security',
|
||||
},
|
||||
},
|
||||
ContainerResults: [
|
||||
{
|
||||
Name: 'container-1',
|
||||
Results: {
|
||||
cpuLimitsMissing: {
|
||||
ID: 'cpuLimitsMissing',
|
||||
Message: '',
|
||||
Details: [],
|
||||
Success: false,
|
||||
Severity: 'warning',
|
||||
Category: 'Efficiency',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
]);
|
||||
const issues = getTopIssues(data);
|
||||
expect(issues).toHaveLength(2);
|
||||
// Danger first
|
||||
expect(issues[0].checkId).toBe('hostIPCSet');
|
||||
expect(issues[0].severity).toBe('danger');
|
||||
expect(issues[1].checkId).toBe('cpuLimitsMissing');
|
||||
});
|
||||
|
||||
it('counts same check across multiple workloads', () => {
|
||||
const data = makeAuditData([
|
||||
makeResult({
|
||||
Name: 'deploy-1',
|
||||
Results: {
|
||||
cpuRequestsMissing: {
|
||||
ID: 'cpuRequestsMissing',
|
||||
Message: '',
|
||||
Details: [],
|
||||
Success: false,
|
||||
Severity: 'warning',
|
||||
Category: 'Efficiency',
|
||||
},
|
||||
},
|
||||
}),
|
||||
makeResult({
|
||||
Name: 'deploy-2',
|
||||
Results: {
|
||||
cpuRequestsMissing: {
|
||||
ID: 'cpuRequestsMissing',
|
||||
Message: '',
|
||||
Details: [],
|
||||
Success: false,
|
||||
Severity: 'warning',
|
||||
Category: 'Efficiency',
|
||||
},
|
||||
},
|
||||
}),
|
||||
]);
|
||||
const issues = getTopIssues(data);
|
||||
expect(issues).toHaveLength(1);
|
||||
expect(issues[0].count).toBe(2);
|
||||
});
|
||||
|
||||
it('ignores checks with severity "ignore"', () => {
|
||||
const data = makeAuditData([
|
||||
makeResult({
|
||||
Results: {
|
||||
c1: {
|
||||
ID: 'c1',
|
||||
Message: '',
|
||||
Details: [],
|
||||
Success: false,
|
||||
Severity: 'ignore',
|
||||
Category: 'X',
|
||||
},
|
||||
},
|
||||
}),
|
||||
]);
|
||||
expect(getTopIssues(data)).toEqual([]);
|
||||
});
|
||||
|
||||
it('sorts danger before warning, then by count descending', () => {
|
||||
const data = makeAuditData([
|
||||
makeResult({
|
||||
Name: 'deploy-1',
|
||||
Results: {
|
||||
cpuRequestsMissing: {
|
||||
ID: 'cpuRequestsMissing',
|
||||
Message: '',
|
||||
Details: [],
|
||||
Success: false,
|
||||
Severity: 'warning',
|
||||
Category: 'Efficiency',
|
||||
},
|
||||
},
|
||||
}),
|
||||
makeResult({
|
||||
Name: 'deploy-2',
|
||||
Results: {
|
||||
cpuRequestsMissing: {
|
||||
ID: 'cpuRequestsMissing',
|
||||
Message: '',
|
||||
Details: [],
|
||||
Success: false,
|
||||
Severity: 'warning',
|
||||
Category: 'Efficiency',
|
||||
},
|
||||
hostIPCSet: {
|
||||
ID: 'hostIPCSet',
|
||||
Message: '',
|
||||
Details: [],
|
||||
Success: false,
|
||||
Severity: 'danger',
|
||||
Category: 'Security',
|
||||
},
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
const issues = getTopIssues(data);
|
||||
// Danger first regardless of count
|
||||
expect(issues[0].severity).toBe('danger');
|
||||
expect(issues[1].severity).toBe('warning');
|
||||
expect(issues[1].count).toBe(2);
|
||||
});
|
||||
|
||||
it('returns at most 10 issues', () => {
|
||||
const results: Record<
|
||||
string,
|
||||
{
|
||||
ID: string;
|
||||
Message: string;
|
||||
Details: string[];
|
||||
Success: boolean;
|
||||
Severity: 'warning';
|
||||
Category: string;
|
||||
}
|
||||
> = {};
|
||||
for (let i = 0; i < 15; i++) {
|
||||
results[`check${i}`] = {
|
||||
ID: `check${i}`,
|
||||
Message: '',
|
||||
Details: [],
|
||||
Success: false,
|
||||
Severity: 'warning',
|
||||
Category: 'X',
|
||||
};
|
||||
}
|
||||
const data = makeAuditData([makeResult({ Results: results })]);
|
||||
expect(getTopIssues(data)).toHaveLength(10);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user