import { describe, it, expect } from 'vitest'; import { edgeMask, hasEdge, toggleEdge, setEdge, clearEdge, edgeCount, connectedEdges, rotateMask, enforceEdgeConstraints, } from '@core/edge-connectivity'; import { HexEdge } from '@core/types'; import { HexMap } from '@core/hex-map'; describe('edgeMask operations', () => { it('creates mask from edges', () => { const mask = edgeMask(HexEdge.NE, HexEdge.SW); expect(hasEdge(mask, HexEdge.NE)).toBe(true); expect(hasEdge(mask, HexEdge.SW)).toBe(true); expect(hasEdge(mask, HexEdge.E)).toBe(false); expect(edgeCount(mask)).toBe(2); }); it('toggles edges', () => { let mask = edgeMask(HexEdge.E); mask = toggleEdge(mask, HexEdge.E); expect(hasEdge(mask, HexEdge.E)).toBe(false); mask = toggleEdge(mask, HexEdge.E); expect(hasEdge(mask, HexEdge.E)).toBe(true); }); it('sets and clears edges', () => { let mask = 0; mask = setEdge(mask, HexEdge.NW); expect(hasEdge(mask, HexEdge.NW)).toBe(true); mask = clearEdge(mask, HexEdge.NW); expect(hasEdge(mask, HexEdge.NW)).toBe(false); }); it('connectedEdges returns correct edges', () => { const mask = edgeMask(HexEdge.NE, HexEdge.SE, HexEdge.W); const edges = connectedEdges(mask); expect(edges).toEqual([HexEdge.NE, HexEdge.SE, HexEdge.W]); }); }); describe('rotateMask', () => { it('rotating 6 steps returns original', () => { const mask = edgeMask(HexEdge.NE, HexEdge.E); expect(rotateMask(mask, 6)).toBe(mask); }); it('rotates single edge clockwise by 1', () => { const mask = edgeMask(HexEdge.NE); // bit 0 const rotated = rotateMask(mask, 1); expect(hasEdge(rotated, HexEdge.E)).toBe(true); // bit 1 expect(edgeCount(rotated)).toBe(1); }); it('rotates opposite edges correctly', () => { const mask = edgeMask(HexEdge.NE, HexEdge.SW); // bits 0,3 const rotated = rotateMask(mask, 1); expect(hasEdge(rotated, HexEdge.E)).toBe(true); expect(hasEdge(rotated, HexEdge.W)).toBe(true); expect(edgeCount(rotated)).toBe(2); }); }); describe('enforceEdgeConstraints', () => { it('detects missing continuation on neighbor', () => { const hexMap = new HexMap(); const coord = { q: 0, r: 0 }; const mask = edgeMask(HexEdge.E); const actions = enforceEdgeConstraints(hexMap, coord, 'road', mask); expect(actions).toHaveLength(1); expect(actions[0].coord).toEqual({ q: 1, r: 0 }); // E neighbor expect(actions[0].edge).toBe(HexEdge.W); // opposite edge expect(actions[0].terrainId).toBe('road'); }); it('no action needed when neighbor already has feature', () => { const hexMap = new HexMap(); // Set up neighbor with road on W edge hexMap.setFeature({ q: 1, r: 0 }, 'road', edgeMask(HexEdge.W)); const actions = enforceEdgeConstraints( hexMap, { q: 0, r: 0 }, 'road', edgeMask(HexEdge.E), ); expect(actions).toHaveLength(0); }); });