import { describe, it, expect } from 'vitest';
import { findPath, type Grid } from '../pathfinding';
function makeGrid(width: number, height: number, walls: string[] = []): Grid {
const wallSet = new Set(walls);
return {
width,
height,
isWalkable: (x, y) => !wallSet.has(`${x},${y}`)
};
}
describe('A*', () => {
it('прямой путь по пустой сетке', () => {
const path = findPath(makeGrid(10, 10), { x: 0, y: 0 }, { x: 3, y: 0 });
expect(path).toEqual([
{ x: 1, y: 0 },
{ x: 2, y: 0 },
{ x: 3, y: 0 }
]);
});
it('обходит стену', () => {
const grid = makeGrid(5, 5, ['1,0', '1,1', '1,2']);
const path = findPath(grid, { x: 0, y: 0 }, { x: 2, y: 0 });
expect(path).not.toBeNull();
expect(path!.some((p) => p.x === 1 && (p.y === 0 || p.y === 1 || p.y === 2))).toBe(false);
expect(path![path!.length - 1]).toEqual({ x: 2, y: 0 });
});
it('цель заблокирована — null', () => {
const grid = makeGrid(5, 5, ['2,2']);
expect(findPath(grid, { x: 0, y: 0 }, { x: 2, y: 2 })).toBeNull();
});
it('цель вне сетки — null', () => {
const grid = makeGrid(5, 5);
expect(findPath(grid, { x: 0, y: 0 }, { x: 9, y: 9 })).toBeNull();
});
it('старт == цель — пустой путь', () => {
const grid = makeGrid(5, 5);
expect(findPath(grid, { x: 2, y: 2 }, { x: 2, y: 2 })).toEqual([]);
});
it('диагональ без среза углов', () => {
// Стена (1,0) срезает угол диагонали (0,0)->(1,1) — она запрещена,
// путь идёт в обход через (0,1).
const grid = makeGrid(5, 5, ['1,0']);
const path = findPath(grid, { x: 0, y: 0 }, { x: 1, y: 1 }, true);
expect(path).not.toBeNull();
expect(path![0]).toEqual({ x: 0, y: 1 });
});
it('угол срезан со всех сторон — пути нет', () => {
// Из (0,0) заблокированы оба ортогональных соседа: без среза углов
// ни шага, ни диагонали сделать нельзя.
const grid = makeGrid(5, 5, ['1,0', '0,1']);
expect(findPath(grid, { x: 0, y: 0 }, { x: 2, y: 2 }, true)).toBeNull();
});
it('диагональ разрешена, когда соседи свободны', () => {
const grid = makeGrid(5, 5);
const path = findPath(grid, { x: 0, y: 0 }, { x: 1, y: 1 }, true);
expect(path).toEqual([{ x: 1, y: 1 }]);
});
});