import { TestBed } from '@angular/core/testing'; import { DonutChart } from './donut-chart'; interface OutcomeRow { readonly outcome: string; readonly count: number; } const SAMPLE: readonly OutcomeRow[] = [ { outcome: 'success', count: 120 }, { outcome: 'failure', count: 6 }, { outcome: 'denied', count: 3 }, ]; function render() { TestBed.configureTestingModule({ imports: [DonutChart] }); const fixture = TestBed.createComponent>(DonutChart); fixture.componentRef.setInput('data', SAMPLE); fixture.componentRef.setInput('categoryKey', 'outcome'); fixture.componentRef.setInput('valueKey', 'count'); fixture.componentRef.setInput('caption', 'Outcome breakdown'); fixture.componentRef.setInput( 'description', 'Donut chart of audit-event outcomes for the current page (success, failure, denied).', ); fixture.componentRef.setInput('ariaLabel', 'Outcome breakdown — donut chart'); fixture.componentRef.setInput('centerLabel', '129'); fixture.detectChanges(); return fixture; } describe('DonutChart', () => { beforeEach(() => TestBed.resetTestingModule()); it('wraps the chart in a
with aria-labelledby + aria-describedby', () => { const fixture = render(); const figure = (fixture.nativeElement as HTMLElement).querySelector('figure.chart-figure'); expect(figure?.getAttribute('role')).toBe('img'); expect(figure?.getAttribute('aria-labelledby')).toMatch(/^chart-\d+-title$/); expect(figure?.getAttribute('aria-describedby')).toMatch(/^chart-\d+-desc$/); }); it('renders an SVG with + <desc> as the first two children + one <path> per slice', () => { const fixture = render(); const root = fixture.nativeElement as HTMLElement; const svg = root.querySelector<SVGSVGElement>('.chart-canvas svg'); expect(svg).not.toBeNull(); const children = Array.from(svg?.children ?? []); expect(children[0]?.tagName).toBe('title'); expect(children[1]?.tagName).toBe('desc'); const slices = children.filter((c) => c.tagName === 'path'); expect(slices.length).toBe(SAMPLE.length); }); it('each slice has its own <title> child carrying "<category>: <value>"', () => { const fixture = render(); const root = fixture.nativeElement as HTMLElement; const slices = root.querySelectorAll<SVGPathElement>('.chart-canvas svg path'); expect(slices.length).toBe(SAMPLE.length); expect(slices[0]?.querySelector('title')?.textContent).toBe('success: 120'); expect(slices[1]?.querySelector('title')?.textContent).toBe('failure: 6'); }); it('renders the centerLabel in a <text> when supplied', () => { const fixture = render(); const root = fixture.nativeElement as HTMLElement; expect(root.querySelector('.donut-center-label')?.textContent?.trim()).toBe('129'); }); it('renders a <details> tabular fallback with one row per category', () => { const fixture = render(); const root = fixture.nativeElement as HTMLElement; const rows = root.querySelectorAll('details.chart-fallback tbody tr'); expect(rows.length).toBe(SAMPLE.length); expect(rows[0]?.querySelector('th')?.textContent?.trim()).toBe('success'); expect(rows[0]?.querySelector('td')?.textContent?.trim()).toBe('120'); }); });