import { renderToStaticMarkup } from 'react-dom/server'; import { describe, expect, it } from 'vitest'; import { makeSheet } from '../../src/importers/sheet-factory'; import { genericProfile } from '../../src/profiles/generic/generic-profile'; import { summarizeSeverities, toggleSeveritySelection } from '../../src/features/sidebar/SidebarSeverityMetrics'; import { deriveDynamicFacets } from '../../src/features/search-filter/dynamic-facets'; import { compactSeveritySelection, DynamicFilterControls } from '../../src/features/search-filter/DynamicFilterControls'; const rows = [ ['Title', 'Severity', 'Result'], ['Deviation 1', 'Critical', 'Failed'], ['Deviation 2', 'HIGH', 'Failed'], ['Deviation 3', 'hoch', 'Investigate'], ['Passed', 'Medium', 'Passed'], ['Deviation 4', 'Low', 'Failed'], ['Deviation 5', 'Info', 'Failed'], ['Unrated deviation', 'Unrated', 'Failed'] ]; function options(statusFilter = 'deviation', facetFilters = {}) { return { sheet: makeSheet('Synthetic findings', rows, '', 'synthetic.csv'), dataset: null, activeProfile: genericProfile, reviews: {}, statusFilter, facetFilters, search: '', actionOnly: false }; } describe('sidebar severity metrics', () => { it('uses Deviation as the diagram basis and excludes unknown source values', () => { const summary = summarizeSeverities(options()); expect(summary?.metrics.map(metric => [metric.severity, metric.count, metric.percentage])).toEqual([ ['critical', 1, 20], ['high', 2, 40], ['medium', 0, 0], ['low', 1, 20], ['info', 1, 20] ]); expect(summary?.metrics.map(metric => metric.severity)).not.toContain('unknown'); }); it('follows an explicit user status filter without changing it', () => { const summary = summarizeSeverities(options('all')); expect(summary?.metrics.find(metric => metric.severity === 'medium')).toMatchObject({ count: 1 }); }); it('exposes exactly the five known severity filter values', () => { const base = options(); const summary = summarizeSeverities(base); if (!summary) throw new Error('Synthetic severity facet missing'); expect(summary.facetId).toBeTruthy(); expect(summary.metrics.map(metric => metric.severity)).toEqual([ 'critical', 'high', 'medium', 'low', 'info' ]); }); it('toggles multiple severities in canonical display order', () => { expect(toggleSeveritySelection([], 'high')).toEqual(['high']); expect(toggleSeveritySelection(['high'], 'critical')).toEqual(['critical', 'high']); expect(toggleSeveritySelection(['critical', 'high'], 'high')).toEqual(['critical']); expect(toggleSeveritySelection(['critical'], 'critical')).toEqual([]); }); it('renders a compact multi-severity label in the filter control', () => { const base = options(); const summary = summarizeSeverities(base); if (!summary) throw new Error('Synthetic severity facet missing'); const severityFacet = deriveDynamicFacets(base.sheet, null, genericProfile, {}) .find(facet => facet.id === summary.facetId); if (!severityFacet) throw new Error('Synthetic severity facet missing'); const html = renderToStaticMarkup( undefined} onFilter={() => undefined} /> ); expect(compactSeveritySelection(['info', 'critical', 'medium'])).toBe('Crit-Med-Inf'); expect(html).toContain('Crit-High-Med-Low-Inf'); expect(html).toContain('value="__severity_multi__" selected=""'); }); it('highlights a status only when it differs from the profile default', () => { const base = options(); const statusFacet = deriveDynamicFacets(base.sheet, null, genericProfile, {}) .find(facet => facet.source === 'profile-status'); if (!statusFacet) throw new Error('Synthetic status facet missing'); const renderStatus = (statusFilter: string) => renderToStaticMarkup( undefined} onFilter={() => undefined} /> ); expect(renderStatus('deviation')).not.toContain('is-filtered'); expect(renderStatus('all')).toContain('is-filtered'); }); it('does not render a rack when the active sheet has no severity field', () => { const missing = options(); missing.sheet = makeSheet('Synthetic findings', [['Title', 'Result'], ['One', 'Failed']], '', 'synthetic.csv'); expect(summarizeSeverities(missing)).toBeUndefined(); }); });