Files
familienarchiv/frontend/src/lib/components/ProgressRing.svelte.spec.ts
Marcel 2c5877ea9e
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / OCR Service Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
fix(a11y): fix ProgressRing text label contrast and add no-restricted-syntax lint rule for text-accent
ProgressRing used text-accent (#a1dcd8) on a percentage text label —
same WCAG 2.1 AA failure as #341. Switched to text-primary.

Also adds ESLint no-restricted-syntax rule (scoped to *.svelte files) that
blocks future text-accent usage in JavaScript string literals inside Svelte
class expressions. The rule caught both violations at once; both are now fixed.
The rule is scoped to .svelte files so test assertions against 'text-accent'
strings in .spec.ts files are unaffected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 21:46:44 +02:00

45 lines
1.7 KiB
TypeScript

import { afterEach, describe, expect, it } from 'vitest';
import { cleanup, render } from 'vitest-browser-svelte';
import { page } from 'vitest/browser';
import ProgressRing from './ProgressRing.svelte';
afterEach(cleanup);
describe('ProgressRing', () => {
it('renders the correct stroke-dasharray for 75%', async () => {
render(ProgressRing, { percentage: 75 });
const arc = document.querySelector('circle.fill-arc') as SVGCircleElement | null;
expect(arc).not.toBeNull();
// circumference = 2 * π * 7 ≈ 43.98; 75% of that ≈ 32.99
const dasharray = arc!.getAttribute('stroke-dasharray') ?? '';
const filled = parseFloat(dasharray.split(' ')[0]);
expect(filled).toBeCloseTo(32.99, 1);
});
it('renders a gray label when percentage is 0', async () => {
render(ProgressRing, { percentage: 0 });
const label = page.getByText('0%');
await expect.element(label).toBeInTheDocument();
// Label should carry the gray class, not the mint class
const el = (await label.element()) as HTMLElement;
expect(el.className).toContain('text-gray-400');
});
it('renders a primary-colored label when percentage is > 0', async () => {
render(ProgressRing, { percentage: 75 });
const label = page.getByText('75%');
await expect.element(label).toBeInTheDocument();
const el = (await label.element()) as HTMLElement;
expect(el.className).toContain('text-primary');
});
it('renders a fully filled arc for 100%', async () => {
render(ProgressRing, { percentage: 100 });
const arc = document.querySelector('circle.fill-arc') as SVGCircleElement | null;
expect(arc).not.toBeNull();
const dasharray = arc!.getAttribute('stroke-dasharray') ?? '';
const filled = parseFloat(dasharray.split(' ')[0]);
expect(filled).toBeCloseTo(43.98, 1);
});
});