Files
ai-code-app/tests/layoutDraw/lineDraft.test.ts

172 lines
5.1 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { resolveLineDraft, type DrawShapeLike } from '../../src/features/layout/draw/lineDraft.ts';
const canvasWidth = 500;
const canvasHeight = 300;
function line(shape: Omit<Extract<DrawShapeLike, { type: 'line' }>, 'type'>): DrawShapeLike {
return { type: 'line', ...shape };
}
function rect(): DrawShapeLike {
return { type: 'rect', x: 40, y: 40, width: 80, height: 60 };
}
test('creates a vertical divider from a horizontal gesture when no horizontal crossing line exists ahead', () => {
assert.deepEqual(resolveLineDraft(120, 80, 300, 90, [], canvasWidth, canvasHeight), {
startX: 120,
startY: 0,
endX: 120,
endY: canvasHeight,
orientation: 'vertical',
});
assert.deepEqual(resolveLineDraft(120, 80, 10, 70, [], canvasWidth, canvasHeight), {
startX: 120,
startY: 0,
endX: 120,
endY: canvasHeight,
orientation: 'vertical',
});
});
test('creates a horizontal divider from a vertical gesture when no vertical crossing line exists ahead', () => {
assert.deepEqual(resolveLineDraft(120, 80, 130, 220, [], canvasWidth, canvasHeight), {
startX: 0,
startY: 80,
endX: canvasWidth,
endY: 80,
orientation: 'horizontal',
});
assert.deepEqual(resolveLineDraft(120, 80, 110, 10, [], canvasWidth, canvasHeight), {
startX: 0,
startY: 80,
endX: canvasWidth,
endY: 80,
orientation: 'horizontal',
});
});
test('stops at the nearest horizontal crossing line for a horizontal gesture divider', () => {
const shapes: DrawShapeLike[] = [
line({ x1: 20, y1: 40, x2: 220, y2: 40, orientation: 'horizontal' }),
line({ x1: 40, y1: 180, x2: 260, y2: 180, orientation: 'horizontal' }),
];
assert.deepEqual(resolveLineDraft(120, 80, 480, 90, shapes, canvasWidth, canvasHeight), {
startX: 120,
startY: 40,
endX: 120,
endY: 180,
orientation: 'vertical',
});
});
test('stops at the nearest vertical crossing line for a vertical gesture divider', () => {
const shapes: DrawShapeLike[] = [
line({ x1: 60, y1: 20, x2: 60, y2: 180, orientation: 'vertical' }),
line({ x1: 260, y1: 20, x2: 260, y2: 160, orientation: 'vertical' }),
];
assert.deepEqual(resolveLineDraft(120, 80, 130, 260, shapes, canvasWidth, canvasHeight), {
startX: 60,
startY: 80,
endX: 260,
endY: 80,
orientation: 'horizontal',
});
});
test('ignores crossing lines that are behind the start point or outside the crossing range', () => {
const shapes: DrawShapeLike[] = [
line({ x1: 60, y1: 20, x2: 60, y2: 180, orientation: 'vertical' }),
line({ x1: 320, y1: 120, x2: 320, y2: 220, orientation: 'vertical' }),
line({ x1: 20, y1: 20, x2: 260, y2: 20, orientation: 'horizontal' }),
rect(),
];
assert.deepEqual(resolveLineDraft(120, 80, 480, 90, shapes, canvasWidth, canvasHeight), {
startX: 120,
startY: 20,
endX: 120,
endY: canvasHeight,
orientation: 'vertical',
});
assert.deepEqual(resolveLineDraft(120, 80, 130, 260, shapes, canvasWidth, canvasHeight), {
startX: 60,
startY: 80,
endX: canvasWidth,
endY: 80,
orientation: 'horizontal',
});
});
test('does not snap to a crossing line that starts exactly at the same point', () => {
const shapes: DrawShapeLike[] = [
line({ x1: 120, y1: 40, x2: 120, y2: 160, orientation: 'vertical' }),
line({ x1: 120, y1: 180, x2: 240, y2: 180, orientation: 'horizontal' }),
];
assert.deepEqual(resolveLineDraft(120, 80, 300, 90, shapes, canvasWidth, canvasHeight), {
startX: 120,
startY: 0,
endX: 120,
endY: 180,
orientation: 'vertical',
});
assert.deepEqual(resolveLineDraft(120, 180, 130, 260, shapes, canvasWidth, canvasHeight), {
startX: 0,
startY: 180,
endX: canvasWidth,
endY: 180,
orientation: 'horizontal',
});
});
test('extends to the nearest crossing line on both forward and reverse directions', () => {
const shapes: DrawShapeLike[] = [
line({ x1: 60, y1: 20, x2: 60, y2: 180, orientation: 'vertical' }),
line({ x1: 260, y1: 20, x2: 260, y2: 180, orientation: 'vertical' }),
line({ x1: 20, y1: 40, x2: 220, y2: 40, orientation: 'horizontal' }),
line({ x1: 20, y1: 180, x2: 220, y2: 180, orientation: 'horizontal' }),
];
assert.deepEqual(resolveLineDraft(120, 80, 320, 90, shapes, canvasWidth, canvasHeight), {
startX: 120,
startY: 40,
endX: 120,
endY: 180,
orientation: 'vertical',
});
assert.deepEqual(resolveLineDraft(120, 100, 130, 260, shapes, canvasWidth, canvasHeight), {
startX: 60,
startY: 100,
endX: 260,
endY: 100,
orientation: 'horizontal',
});
});
test('respects preferred orientation when the pointer drift would otherwise flip the axis', () => {
assert.deepEqual(resolveLineDraft(120, 80, 140, 160, [], canvasWidth, canvasHeight, 'horizontal'), {
startX: 0,
startY: 80,
endX: canvasWidth,
endY: 80,
orientation: 'horizontal',
});
assert.deepEqual(resolveLineDraft(120, 80, 260, 100, [], canvasWidth, canvasHeight, 'vertical'), {
startX: 120,
startY: 0,
endX: 120,
endY: canvasHeight,
orientation: 'vertical',
});
});