test(annotation): expand AnnotationLayer coverage
Container style branches (cursor with/without canDraw, touch-action), drawing pointer flow (canDraw=false skips, pointerdown on existing annotation skips, no preview when not drawing, pointermove without draw, pointerup without draw). 7 new tests, +14 covered branches. Refs #496. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -157,4 +157,132 @@ describe('AnnotationLayer', () => {
|
||||
expect(el.classList.contains('annotation-flash')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('container style', () => {
|
||||
it('uses crosshair cursor when canDraw is true', async () => {
|
||||
render(AnnotationLayer, {
|
||||
annotations: [],
|
||||
canDraw: true,
|
||||
color: '#00c7b1',
|
||||
onDraw: () => {}
|
||||
});
|
||||
|
||||
const wrapper = document.querySelector('[role="presentation"]') as HTMLElement;
|
||||
expect(wrapper.style.cursor).toContain('crosshair');
|
||||
expect(wrapper.style.touchAction).toBe('none');
|
||||
});
|
||||
|
||||
it('omits crosshair cursor when canDraw is false', async () => {
|
||||
render(AnnotationLayer, {
|
||||
annotations: [],
|
||||
canDraw: false,
|
||||
color: '#00c7b1',
|
||||
onDraw: () => {}
|
||||
});
|
||||
|
||||
const wrapper = document.querySelector('[role="presentation"]') as HTMLElement;
|
||||
expect(wrapper.style.cursor).not.toContain('crosshair');
|
||||
});
|
||||
});
|
||||
|
||||
describe('drawing pointer flow', () => {
|
||||
it('does not start a draw when canDraw is false', async () => {
|
||||
render(AnnotationLayer, {
|
||||
annotations: [],
|
||||
canDraw: false,
|
||||
color: '#00c7b1',
|
||||
onDraw: () => {}
|
||||
});
|
||||
|
||||
const wrapper = document.querySelector('[role="presentation"]') as HTMLElement;
|
||||
(wrapper as unknown as { setPointerCapture: (id: number) => void }).setPointerCapture =
|
||||
() => {};
|
||||
|
||||
wrapper.dispatchEvent(
|
||||
new PointerEvent('pointerdown', {
|
||||
bubbles: true,
|
||||
clientX: 50,
|
||||
clientY: 50,
|
||||
pointerId: 1
|
||||
})
|
||||
);
|
||||
|
||||
// No preview rect rendered
|
||||
const preview = wrapper.querySelector('div[style*="border: 2px dashed"]');
|
||||
expect(preview).toBeNull();
|
||||
});
|
||||
|
||||
it('does not start a draw when pointerdown lands on an existing annotation', async () => {
|
||||
render(AnnotationLayer, {
|
||||
annotations: [annotation],
|
||||
canDraw: true,
|
||||
color: '#00c7b1',
|
||||
onDraw: () => {}
|
||||
});
|
||||
|
||||
const ann = document.querySelector('[data-testid="annotation-ann-1"]') as HTMLElement;
|
||||
(ann as unknown as { setPointerCapture: (id: number) => void }).setPointerCapture = () => {};
|
||||
|
||||
// pointerdown bubbles to the layer; layer should refuse to draw because
|
||||
// closest('[data-annotation]') matches.
|
||||
ann.dispatchEvent(
|
||||
new PointerEvent('pointerdown', {
|
||||
bubbles: true,
|
||||
clientX: 0,
|
||||
clientY: 0,
|
||||
pointerId: 1
|
||||
})
|
||||
);
|
||||
|
||||
const preview = document.querySelector('div[style*="border: 2px dashed"]');
|
||||
expect(preview).toBeNull();
|
||||
});
|
||||
|
||||
it('renders no preview rect when no draw is in progress', async () => {
|
||||
render(AnnotationLayer, {
|
||||
annotations: [],
|
||||
canDraw: true,
|
||||
color: '#00c7b1',
|
||||
onDraw: () => {}
|
||||
});
|
||||
|
||||
const preview = document.querySelector('div[style*="border: 2px dashed"]');
|
||||
expect(preview).toBeNull();
|
||||
});
|
||||
|
||||
it('handles pointermove without a started draw (early-return)', async () => {
|
||||
render(AnnotationLayer, {
|
||||
annotations: [],
|
||||
canDraw: true,
|
||||
color: '#00c7b1',
|
||||
onDraw: () => {}
|
||||
});
|
||||
|
||||
const wrapper = document.querySelector('[role="presentation"]') as HTMLElement;
|
||||
expect(() =>
|
||||
wrapper.dispatchEvent(
|
||||
new PointerEvent('pointermove', { bubbles: true, clientX: 0, clientY: 0 })
|
||||
)
|
||||
).not.toThrow();
|
||||
});
|
||||
|
||||
it('handles pointerup without a started draw (early-return)', async () => {
|
||||
let drawn = false;
|
||||
render(AnnotationLayer, {
|
||||
annotations: [],
|
||||
canDraw: true,
|
||||
color: '#00c7b1',
|
||||
onDraw: () => {
|
||||
drawn = true;
|
||||
}
|
||||
});
|
||||
|
||||
const wrapper = document.querySelector('[role="presentation"]') as HTMLElement;
|
||||
wrapper.dispatchEvent(
|
||||
new PointerEvent('pointerup', { bubbles: true, clientX: 0, clientY: 0 })
|
||||
);
|
||||
|
||||
expect(drawn).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user