import { describe, expect, it } from 'vitest'; import { rectangle } from '../src/lib/defaults'; import { insertWallAfter, moveWall } from '../src/lib/wall-editing'; const ids = (room: ReturnType) => room.walls.map((wall) => wall.id); describe('inserting walls', () => { it.each([0, 1, 3])( 'inserts after wall index %i without changing existing measurements or doors', (index) => { const room = rectangle(); const original = structuredClone(room); const inserted = insertWallAfter(room, room.walls[index].id); expect(inserted.walls).toHaveLength(room.walls.length + 1); expect(inserted.walls[index + 1]).toMatchObject({ length: 1000, turn: 90, doors: [] }); expect(new Set(ids(inserted)).size).toBe(inserted.walls.length); expect(inserted.walls.filter((wall) => room.walls.includes(wall))).toEqual(room.walls); for (const wall of room.walls) expect(inserted.walls.find((candidate) => candidate.id === wall.id)).toBe(wall); expect(room).toEqual(original); expect(inserted.id).toBe(room.id); expect(inserted.name).toBe(room.name); expect(inserted.direction).toBe(room.direction); }, ); it('assigns deterministic, unique IDs when repeatedly inserting in the same position', () => { const room = rectangle(); const first = insertWallAfter(room, room.walls[0].id); const second = insertWallAfter(first, room.walls[0].id); expect(insertWallAfter(room, room.walls[0].id)).toEqual(first); expect(new Set(ids(second)).size).toBe(6); expect(second.walls[2]).toBe(first.walls[1]); }); it('ignores an unknown wall and the wall-count limit without creating replacement state', () => { const room = rectangle(); expect(insertWallAfter(room, 'missing')).toBe(room); const full = { ...room, walls: Array.from({ length: 100 }, (_, i) => ({ ...room.walls[0], id: `wall-${i}` })), }; expect(insertWallAfter(full, 'wall-3')).toBe(full); }); }); describe('reordering walls', () => { it.each([ [0, 3], [3, 0], [1, 2], [2, 1], ])( 'moves index %i to index %i while preserving all walls and their attached doors', (from, to) => { const room = rectangle(); const original = structuredClone(room); const moved = moveWall(room, room.walls[from].id, to); expect(moved.walls[to]).toBe(room.walls[from]); expect([...ids(moved)].sort()).toEqual([...ids(room)].sort()); for (const wall of room.walls) { const result = moved.walls.find((candidate) => candidate.id === wall.id)!; expect(result).toBe(wall); expect(result.doors).toBe(wall.doors); } expect(room).toEqual(original); expect(moveWall(moved, room.walls[from].id, from).walls).toEqual(room.walls); }, ); it('clamps destinations and treats missing, unchanged or non-finite positions as no-ops', () => { const room = rectangle(); expect(moveWall(room, room.walls[0].id, -10)).toBe(room); expect(moveWall(room, room.walls[0].id, 100).walls.at(-1)).toBe(room.walls[0]); expect(moveWall(room, room.walls[3].id, -10).walls[0]).toBe(room.walls[3]); expect(moveWall(room, 'missing', 2)).toBe(room); expect(moveWall(room, room.walls[1].id, 1)).toBe(room); expect(moveWall(room, room.walls[1].id, Number.NaN)).toBe(room); }); });