feat: add play apps and layout tools
This commit is contained in:
171
tests/layoutDraw/lineDraft.test.ts
Normal file
171
tests/layoutDraw/lineDraft.test.ts
Normal file
@@ -0,0 +1,171 @@
|
||||
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',
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user