Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 2m33s
CI / OCR Service Tests (pull_request) Successful in 38s
CI / Unit & Component Tests (push) Failing after 2m40s
CI / OCR Service Tests (push) Successful in 36s
CI / Backend Unit Tests (push) Failing after 2m54s
CI / Backend Unit Tests (pull_request) Failing after 2m58s
- ContributorStack: text-xs for WCAG 1.4.4 (was text-[10px]), safeColor()
validation to block CSS injection via actor.color, role="img" aria-label
on empty placeholder, {#each} keyed by index
- ContributorStack spec: update empty-state assertion to getByRole('img')
- DocumentRow spec: add stopPropagation regression test for tag click
- documents/page.svelte.spec.ts: new — debounce, URL building, initial state
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
53 lines
2.0 KiB
TypeScript
53 lines
2.0 KiB
TypeScript
import { describe, it, expect, afterEach } from 'vitest';
|
|
import { cleanup, render } from 'vitest-browser-svelte';
|
|
import { page } from 'vitest/browser';
|
|
|
|
import ContributorStack from './ContributorStack.svelte';
|
|
import type { components } from '$lib/generated/api';
|
|
|
|
type ActivityActorDTO = components['schemas']['ActivityActorDTO'];
|
|
|
|
afterEach(() => cleanup());
|
|
|
|
const makeActor = (overrides: Partial<ActivityActorDTO> = {}): ActivityActorDTO => ({
|
|
initials: 'MR',
|
|
color: '#7a4f9a',
|
|
name: 'Max Raddatz',
|
|
...overrides
|
|
});
|
|
|
|
describe('ContributorStack', () => {
|
|
it('contributor avatar is announced by screen readers with actor name', async () => {
|
|
const actor = makeActor({ name: 'Anna Meier', initials: 'AM' });
|
|
render(ContributorStack, { contributors: [actor], hasMore: false });
|
|
await expect.element(page.getByRole('img', { name: 'Anna Meier' })).toBeInTheDocument();
|
|
});
|
|
|
|
it('falls back to initials as accessible name when actor name is null', async () => {
|
|
const actor = makeActor({ name: undefined, initials: 'AM' });
|
|
render(ContributorStack, { contributors: [actor], hasMore: false });
|
|
await expect.element(page.getByRole('img', { name: 'AM' })).toBeInTheDocument();
|
|
});
|
|
|
|
it('renders two avatars without crashing when actors have identical initials', async () => {
|
|
const actors = [
|
|
makeActor({ name: undefined, initials: 'AM', color: '#aa0000' }),
|
|
makeActor({ name: undefined, initials: 'AM', color: '#0000bb' })
|
|
];
|
|
render(ContributorStack, { contributors: actors, hasMore: false });
|
|
await expect.element(page.getByText('AM').first()).toBeInTheDocument();
|
|
});
|
|
|
|
it('renders overflow indicator when hasMore is true', async () => {
|
|
render(ContributorStack, { contributors: [makeActor()], hasMore: true });
|
|
await expect.element(page.getByText('…')).toBeInTheDocument();
|
|
});
|
|
|
|
it('renders empty placeholder when no contributors', async () => {
|
|
render(ContributorStack, { contributors: [], hasMore: false });
|
|
await expect
|
|
.element(page.getByRole('img', { name: 'Noch niemand angefangen' }))
|
|
.toBeInTheDocument();
|
|
});
|
|
});
|