import { describe, expect, it } from 'vitest';
import { VoxelGrid } from '../../voxel/grid';
import { assertModelValid, decodeModel, encodeModel, validateModel } from '../format';
/** Маленькая сетка-фабрика: 2×3×2 с одним цветным вокселем. */
function makeGrid(): VoxelGrid {
const g = new VoxelGrid(2, 3, 2);
g.set(1, 2, 1, 3);
g.set(0, 0, 0, 1);
return g;
}
const PALETTE = { 1: '#4a5340', 3: '#626c4c' };
describe('формат модели (encode/decode/validate)', () => {
it('roundtrip: encode→decode даёт ту же сетку', () => {
const g = makeGrid();
const back = decodeModel(encodeModel(g, PALETTE));
expect(back.sx).toBe(2);
expect(back.sy).toBe(3);
expect(back.sz).toBe(2);
for (let z = 0; z < 2; z++)
for (let y = 0; y < 3; y++)
for (let x = 0; x < 2; x++) expect(back.get(x, y, z)).toBe(g.get(x, y, z));
});
it('encode не мутирует исходную сетку', () => {
const g = makeGrid();
const before = g.count;
encodeModel(g, PALETTE);
expect(g.count).toBe(before);
});
it('validate: валидная модель — пустой список проблем', () => {
const m = encodeModel(makeGrid(), PALETTE);
expect(validateModel(m)).toEqual([]);
});
it('validate: не-объект и плохой размер', () => {
expect(validateModel(null).length).toBeGreaterThan(0);
expect(validateModel('x').length).toBeGreaterThan(0);
const m = encodeModel(makeGrid(), PALETTE);
expect(validateModel({ ...m, size: [0, 3, 2] }).some((p) => p.includes('size'))).toBe(true);
expect(validateModel({ ...m, size: [2, 3] }).some((p) => p.includes('size'))).toBe(true);
});
it('validate: битый base64 и неверная длина данных', () => {
const m = encodeModel(makeGrid(), PALETTE);
expect(validateModel({ ...m, data: 'не base64!!!' }).some((p) => p.includes('base64'))).toBe(true);
expect(validateModel({ ...m, size: [2, 3, 3] }).some((p) => p.includes('байт'))).toBe(true);
});
it('validate: слоты вне 1..255, плохой hex, воксель без слота', () => {
const m = encodeModel(makeGrid(), PALETTE);
expect(validateModel({ ...m, palette: { 0: '#ffffff' } }).some((p) => p.includes('1..255'))).toBe(true);
expect(validateModel({ ...m, palette: { 1: 'красный' } }).some((p) => p.includes('hex'))).toBe(true);
// воксель слота 9, которого нет в палитре
const bad = { ...m, data: btoa(String.fromCharCode(9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) };
expect(validateModel(bad).some((p) => p.includes('отсутствует в палитре'))).toBe(true);
});
it('assertModelValid кидает с текстом первой проблемы', () => {
const m = encodeModel(makeGrid(), PALETTE);
expect(() => assertModelValid({ ...m, size: [1, 1, 9999] })).toThrow(/size/);
expect(() => assertModelValid(m)).not.toThrow();
});
it('decodeModel бросает на невалидной модели', () => {
expect(() => decodeModel({ size: [2, 2, 2], palette: { 1: '#111111' }, data: 'AAAA' })).toThrow();
});
});