refactor: move document transcription, annotation, viewer sub-packages
- transcription/: TranscriptionBlock, Column, EditView, PanelHeader, ReadView, Section + transcriptionMarkers, blockConflictMerge, saveBlockWithConflictRetry + useBlockAutoSave, useBlockDragDrop hooks - annotation/: AnnotationLayer, AnnotationShape, AnnotationEditOverlay - viewer/: PdfViewer, PdfControls + useFileLoader, usePdfRenderer hooks Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
import { describe, it, expect, afterEach } from 'vitest';
|
||||
import { cleanup, render } from 'vitest-browser-svelte';
|
||||
import { page } from 'vitest/browser';
|
||||
|
||||
import AnnotationLayer from './AnnotationLayer.svelte';
|
||||
|
||||
afterEach(cleanup);
|
||||
|
||||
type Annotation = {
|
||||
id: string;
|
||||
documentId: string;
|
||||
pageNumber: number;
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
color: string;
|
||||
createdAt: string;
|
||||
};
|
||||
|
||||
function makeAnnotation(id = 'ann-1', color = '#00C7B1'): Annotation {
|
||||
return {
|
||||
id,
|
||||
documentId: 'doc-1',
|
||||
pageNumber: 1,
|
||||
x: 0.1,
|
||||
y: 0.1,
|
||||
width: 0.3,
|
||||
height: 0.2,
|
||||
color,
|
||||
createdAt: new Date().toISOString()
|
||||
};
|
||||
}
|
||||
|
||||
describe('AnnotationLayer', () => {
|
||||
it('renders a colored element for each annotation', async () => {
|
||||
render(AnnotationLayer, {
|
||||
annotations: [makeAnnotation('ann-1'), makeAnnotation('ann-2')],
|
||||
canDraw: false,
|
||||
color: '#00C7B1',
|
||||
onDraw: () => {}
|
||||
});
|
||||
|
||||
await expect.element(page.getByTestId('annotation-ann-1')).toBeInTheDocument();
|
||||
await expect.element(page.getByTestId('annotation-ann-2')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('has crosshair cursor when canDraw is true', async () => {
|
||||
render(AnnotationLayer, {
|
||||
annotations: [],
|
||||
canDraw: true,
|
||||
color: '#00C7B1',
|
||||
onDraw: () => {}
|
||||
});
|
||||
|
||||
const container = document.querySelector('[role="presentation"]')!;
|
||||
expect(container.getAttribute('style')).toContain('cursor: crosshair');
|
||||
});
|
||||
|
||||
it('does not have crosshair cursor when canDraw is false', async () => {
|
||||
render(AnnotationLayer, {
|
||||
annotations: [],
|
||||
canDraw: false,
|
||||
color: '#00C7B1',
|
||||
onDraw: () => {}
|
||||
});
|
||||
|
||||
const container = document.querySelector('[role="presentation"]')!;
|
||||
expect(container.getAttribute('style')).not.toContain('cursor: crosshair');
|
||||
});
|
||||
|
||||
it('dims non-active annotations when activeAnnotationId is set', async () => {
|
||||
render(AnnotationLayer, {
|
||||
annotations: [makeAnnotation('ann-1'), makeAnnotation('ann-2')],
|
||||
canDraw: false,
|
||||
color: '#00C7B1',
|
||||
activeAnnotationId: 'ann-1',
|
||||
onDraw: () => {}
|
||||
});
|
||||
|
||||
const active = page.getByTestId('annotation-ann-1').element();
|
||||
const dimmed = page.getByTestId('annotation-ann-2').element();
|
||||
expect(active.style.opacity).toBe('1');
|
||||
expect(dimmed.style.opacity).toBe('0.3');
|
||||
});
|
||||
|
||||
it('shows all annotations at full opacity when no activeAnnotationId', async () => {
|
||||
render(AnnotationLayer, {
|
||||
annotations: [makeAnnotation('ann-1'), makeAnnotation('ann-2')],
|
||||
canDraw: false,
|
||||
color: '#00C7B1',
|
||||
onDraw: () => {}
|
||||
});
|
||||
|
||||
const el1 = page.getByTestId('annotation-ann-1').element();
|
||||
const el2 = page.getByTestId('annotation-ann-2').element();
|
||||
expect(el1.style.opacity).toBe('1');
|
||||
expect(el2.style.opacity).toBe('1');
|
||||
});
|
||||
|
||||
it('does not show delete button when annotation is not hovered or active', async () => {
|
||||
render(AnnotationLayer, {
|
||||
annotations: [makeAnnotation('ann-1')],
|
||||
canDraw: true,
|
||||
color: '#00C7B1',
|
||||
onDraw: () => {}
|
||||
});
|
||||
|
||||
await expect.element(page.getByTestId('annotation-ann-1')).toBeInTheDocument();
|
||||
expect(page.getByTestId('annotation-delete-ann-1').query()).toBeNull();
|
||||
});
|
||||
|
||||
it('does not show delete button when canDraw is false even if annotation is active', async () => {
|
||||
render(AnnotationLayer, {
|
||||
annotations: [makeAnnotation('ann-1')],
|
||||
canDraw: false,
|
||||
color: '#00C7B1',
|
||||
activeAnnotationId: 'ann-1',
|
||||
onDraw: () => {}
|
||||
});
|
||||
|
||||
await expect.element(page.getByTestId('annotation-ann-1')).toBeInTheDocument();
|
||||
expect(page.getByTestId('annotation-delete-ann-1').query()).toBeNull();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user