kerf-engine/app/src/utils/__tests__/artboardShapes.test.ts
jlightner 62f79110e8 test: Built canvas type system, useCanvasState hook with undo/redo, art…
- "app/src/types/canvas.ts"
- "app/src/hooks/useCanvasState.ts"
- "app/src/hooks/__tests__/useCanvasState.test.ts"
- "app/src/utils/artboardShapes.ts"
- "app/src/utils/__tests__/artboardShapes.test.ts"
- "app/src/utils/alignment.ts"
- "app/src/utils/__tests__/alignment.test.ts"
- "app/src/components/canvas/ArtboardSetup.tsx"

GSD-Task: S02/T01
2026-03-26 05:32:04 +00:00

104 lines
3.1 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import {
shieldPath,
pennantPath,
toPx,
fromPx,
artboardClipPath,
ARTBOARD_PRESETS,
} from '../artboardShapes';
import type { ArtboardConfig } from '../../types/canvas';
describe('artboardShapes', () => {
describe('ARTBOARD_PRESETS', () => {
it('has presets for all shapes', () => {
const shapes = ['rect', 'square', 'circle', 'oval', 'shield', 'pennant', 'custom'] as const;
for (const s of shapes) {
expect(ARTBOARD_PRESETS[s]).toBeDefined();
expect(ARTBOARD_PRESETS[s].width).toBeGreaterThan(0);
expect(ARTBOARD_PRESETS[s].height).toBeGreaterThan(0);
}
});
it('square preset has equal width and height', () => {
expect(ARTBOARD_PRESETS.square.width).toBe(ARTBOARD_PRESETS.square.height);
});
it('circle preset has equal width and height', () => {
expect(ARTBOARD_PRESETS.circle.width).toBe(ARTBOARD_PRESETS.circle.height);
});
});
describe('shieldPath', () => {
it('produces a closed SVG path', () => {
const p = shieldPath(100, 120);
expect(p).toContain('M');
expect(p).toContain('Z');
});
it('stays within bounding box', () => {
const p = shieldPath(200, 300);
// path starts at indent, ends at w-indent so all coords ≤ 200/300
expect(p).toBeTruthy();
});
});
describe('pennantPath', () => {
it('produces a triangular closed path', () => {
const p = pennantPath(100, 200);
expect(p).toBe('M 0 0 L 100 0 L 50 200 Z');
});
});
describe('toPx / fromPx', () => {
it('converts inches to pixels at 96 PPI', () => {
expect(toPx(1, 'inches')).toBe(96);
expect(toPx(2, 'inches')).toBe(192);
});
it('converts mm to pixels', () => {
const px = toPx(25.4, 'mm');
expect(px).toBeCloseTo(96, 1);
});
it('fromPx inverts toPx for inches', () => {
expect(fromPx(96, 'inches')).toBe(1);
});
it('fromPx inverts toPx for mm', () => {
expect(fromPx(toPx(10, 'mm'), 'mm')).toBeCloseTo(10, 5);
});
});
describe('artboardClipPath', () => {
it('returns undefined for rect', () => {
const cfg: ArtboardConfig = { shape: 'rect', width: 4, height: 6, unit: 'inches' };
expect(artboardClipPath(cfg)).toBeUndefined();
});
it('returns a path string for shield', () => {
const cfg: ArtboardConfig = { shape: 'shield', width: 4, height: 5, unit: 'inches' };
const p = artboardClipPath(cfg);
expect(p).toBeDefined();
expect(p).toContain('Z');
});
it('returns a triangular path for pennant', () => {
const cfg: ArtboardConfig = { shape: 'pennant', width: 3, height: 8, unit: 'inches' };
const p = artboardClipPath(cfg);
expect(p).toBeDefined();
expect(p).toContain('Z');
});
it('returns custom clipPath when shape is custom', () => {
const cfg: ArtboardConfig = {
shape: 'custom',
width: 4,
height: 4,
unit: 'inches',
clipPath: 'M 0 0 L 50 0 L 50 50 Z',
};
expect(artboardClipPath(cfg)).toBe('M 0 0 L 50 0 L 50 50 Z');
});
});
});