import {describe, expect, it, vi} from 'vitest'; import {parseMergedSvg} from './MergedSvg'; // Three disjoint squares: three shapes, one fill color. const MONOCHROME_ICON = ` `; // Two shapes with different fill colors. const MULTICOLOR_ICON = ` `; describe('parseMergedSvg', () => { it('merges all same-fill shapes into a single mesh without deprecation warnings', () => { const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); const {meshes} = parseMergedSvg(MONOCHROME_ICON); expect(warnSpy).not.toHaveBeenCalled(); warnSpy.mockRestore(); expect(meshes).toHaveLength(1); const singleSquare = parseMergedSvg( '' ); const squareCount = singleSquare.meshes[0].geometry.getAttribute('position').count; const mergedCount = meshes[0].geometry.getAttribute('position').count; expect(mergedCount).toBe(squareCount * 3); }); it('keeps one mesh per distinct fill color', () => { const {meshes} = parseMergedSvg(MULTICOLOR_ICON); expect(meshes).toHaveLength(2); const colors = meshes.map((mesh) => ( mesh.material as unknown as {color: {getHexString(): string}} ).color.getHexString() ); expect(colors.sort()).toEqual(['00ff00', 'ff0000']); }); it('exposes the viewBox bounding box', () => { const {boundingBox} = parseMergedSvg(MONOCHROME_ICON); expect(boundingBox).toBeDefined(); expect(boundingBox!.size.x).toBe(24); expect(boundingBox!.size.y).toBe(24); expect(boundingBox!.center.x).toBe(12); expect(boundingBox!.center.y).toBe(-12); }); it('flips Y via mesh scale exactly like uikit', () => { const {meshes} = parseMergedSvg( '' ); const mesh = meshes[0]; // The flip lives on the mesh (negative-determinant matrixWorld keeps // three's frontFace culling parity with uikit), not in the geometry. expect(mesh.scale.y).toBe(-1); expect(mesh.matrix.elements[5]).toBe(-1); const positions = mesh.geometry.getAttribute('position'); for (let index = 0; index < positions.count; index++) { expect(positions.getY(index)).toBeGreaterThanOrEqual(1.9); expect(positions.getY(index)).toBeLessThanOrEqual(8.1); } }); });