Files
familienarchiv/frontend/src/lib/document/annotation/AnnotationLayer.svelte.test.ts
Marcel 567612761d refactor: move lib-root files to lib/shared/ and finalize domain structure
- Move api.server.ts, errors.ts, types.ts, utils.ts, relativeTime.ts to lib/shared/
- Move person relationship components to lib/person/relationship/
- Move Stammbaum components to lib/person/genealogy/
- Move HelpPopover to lib/shared/primitives/
- Update all import paths across routes, specs, and lib files
- Update vi.mock() paths in server-project test files
- Remove now-empty legacy directories (components/, hooks/, server/, etc.)
- Update vite.config.ts coverage include paths for new structure
- Update frontend/CLAUDE.md to reflect domain-based lib/ layout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 14:53:31 +02:00

161 lines
4.1 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { render } from 'vitest-browser-svelte';
import { page } from 'vitest/browser';
import AnnotationLayer from './AnnotationLayer.svelte';
import type { Annotation } from '$lib/shared/types';
const annotation: Annotation = {
id: 'ann-1',
documentId: 'doc-1',
pageNumber: 1,
x: 0.1,
y: 0.2,
width: 0.3,
height: 0.1,
color: '#00c7b1',
createdAt: '2026-01-01T00:00:00Z'
};
const polygonAnnotation: Annotation = {
...annotation,
id: 'ann-poly',
polygon: [
[0.1, 0.2],
[0.4, 0.21],
[0.39, 0.29],
[0.11, 0.28]
]
};
describe('AnnotationLayer', () => {
describe('dimmed prop', () => {
it('should hide block number badges when dimmed is true', async () => {
render(AnnotationLayer, {
annotations: [annotation],
canDraw: false,
color: '#00c7b1',
blockNumbers: { 'ann-1': 1 },
dimmed: true,
onDraw: () => {}
});
const badge = page.getByText('1');
await expect.element(badge).not.toBeInTheDocument();
});
it('should show block number badges when dimmed is false', async () => {
render(AnnotationLayer, {
annotations: [annotation],
canDraw: false,
color: '#00c7b1',
blockNumbers: { 'ann-1': 1 },
dimmed: false,
onDraw: () => {}
});
const badge = page.getByText('1');
await expect.element(badge).toBeInTheDocument();
});
it('should still fire onAnnotationClick when dimmed', async () => {
let clickedId: string | undefined;
render(AnnotationLayer, {
annotations: [annotation],
canDraw: false,
color: '#00c7b1',
dimmed: true,
onDraw: () => {},
onAnnotationClick: (id: string) => {
clickedId = id;
}
});
const el = document.querySelector('[data-testid="annotation-ann-1"]')!;
el.dispatchEvent(new MouseEvent('click', { bubbles: true }));
expect(clickedId).toBe('ann-1');
});
});
describe('isResizable computation', () => {
it('passes isResizable=true when canDraw, annotation is active, and has no polygon', async () => {
render(AnnotationLayer, {
annotations: [annotation],
canDraw: true,
color: '#00c7b1',
activeAnnotationId: 'ann-1',
onDraw: () => {}
});
const handles = document.querySelectorAll('[data-handle]');
expect(handles).toHaveLength(8);
});
it('passes isResizable=false when annotation has a polygon', async () => {
render(AnnotationLayer, {
annotations: [polygonAnnotation],
canDraw: true,
color: '#00c7b1',
activeAnnotationId: 'ann-poly',
onDraw: () => {}
});
const handles = document.querySelectorAll('[data-handle]');
expect(handles).toHaveLength(0);
});
it('passes isResizable=false when canDraw is false', async () => {
render(AnnotationLayer, {
annotations: [annotation],
canDraw: false,
color: '#00c7b1',
activeAnnotationId: 'ann-1',
onDraw: () => {}
});
const handles = document.querySelectorAll('[data-handle]');
expect(handles).toHaveLength(0);
});
it('passes isResizable=false when annotation is not active', async () => {
render(AnnotationLayer, {
annotations: [annotation],
canDraw: true,
color: '#00c7b1',
activeAnnotationId: 'other-id',
onDraw: () => {}
});
const handles = document.querySelectorAll('[data-handle]');
expect(handles).toHaveLength(0);
});
});
describe('flashAnnotationId prop', () => {
it('should apply annotation-flash class when flashAnnotationId matches', async () => {
render(AnnotationLayer, {
annotations: [annotation],
canDraw: false,
color: '#00c7b1',
flashAnnotationId: 'ann-1',
onDraw: () => {}
});
const el = document.querySelector('[data-testid="annotation-ann-1"]')!;
expect(el.classList.contains('annotation-flash')).toBe(true);
});
it('should not apply annotation-flash class when flashAnnotationId does not match', async () => {
render(AnnotationLayer, {
annotations: [annotation],
canDraw: false,
color: '#00c7b1',
flashAnnotationId: 'other-id',
onDraw: () => {}
});
const el = document.querySelector('[data-testid="annotation-ann-1"]')!;
expect(el.classList.contains('annotation-flash')).toBe(false);
});
});
});