This commit is contained in:
Andras Schmelczer 2026-09-11 16:58:58 +01:00
commit 62a385e4c9
33 changed files with 2649 additions and 809 deletions

View file

@ -0,0 +1,80 @@
import { describe, expect, it } from 'vitest';
import { rectangle } from '../src/lib/defaults';
import { insertWallAfter, moveWall } from '../src/lib/wall-editing';
const ids = (room: ReturnType<typeof rectangle>) => 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);
});
});