Newer
Older
rpg / packages / engine / src / agent / __tests__ / invariants.test.ts
import { describe, expect, it } from 'vitest';
import {
    checkBounds,
    checkFinite,
    checkRange,
    checkWalkable,
    mergeInvariants
} from '../invariants';

const where = 'test';

describe('инварианты — хелперы', () => {
    it('checkFinite находит NaN и Infinity', () => {
        const invs = checkFinite({ x: 1.5, y: NaN, z: Infinity }, where);
        expect(invs).toHaveLength(2);
        expect(invs.every((i) => i.id === 'pos-nan' && i.severity === 'error')).toBe(true);
        expect(checkFinite({ ok: 0 }, where)).toHaveLength(0);
    });

    it('checkRange ловит выход за диапазон и NaN', () => {
        expect(checkRange('hp', 3, 0, 5, where)).toBeNull();
        expect(checkRange('hp', -1, 0, 5, where)?.id).toBe('range');
        expect(checkRange('hp', NaN, 0, 5, where)?.id).toBe('pos-nan');
    });

    it('checkBounds и checkWalkable работают по тайлу', () => {
        const map = { isWalkable: (x: number, y: number) => x + y > 0 };
        expect(checkBounds('герой', { x: 2, y: 3 }, 10, 10, where)).toBeNull();
        expect(checkBounds('герой', { x: -1, y: 3 }, 10, 10, where)?.id).toBe('out-of-bounds');
        expect(checkWalkable('герой', { x: 1, y: 1 }, map, where)).toBeNull();
        expect(checkWalkable('герой', { x: 0, y: 0 }, map, where)?.id).toBe('in-wall');
    });

    it('mergeInvariants разворачивает группы и отбрасывает пустое', () => {
        const a = { id: 'a', severity: 'warn', message: 'a' } as const;
        const b = { id: 'b', severity: 'error', message: 'b' } as const;
        expect(mergeInvariants(null, false, undefined, a, [b as never], null)).toEqual([a, b]);
        expect(mergeInvariants()).toEqual([]);
    });
});