import { PathBuilder } from './PathBuilder' describe('PathBuilder', () => { describe('transform', () => { it('mirrors a path horizontally within a box while preserving command metadata', () => { const path = new PathBuilder() .moveTo(10, 0, { geometry: { isFilled: true } }) .lineTo(100, 0) .lineTo(90, 80) .close() // mirror around the horizontal center of a 100-wide box: x' = 100 - x const mirrored = path.transform({ a: -1, b: 0, c: 0, d: 1, e: 100, f: 0 }) expect(mirrored.toD()).toBe('M 90 0 L 0 0 L 10 80 Z') // original is untouched expect(path.toD()).toBe('M 10 0 L 100 0 L 90 80 Z') // fill metadata carried over const firstCommand = mirrored.commands[0] expect(firstCommand.type).toBe('move') if (firstCommand.type === 'move') { expect(firstCommand.opts?.geometry).toEqual({ isFilled: true }) } }) it('transforms bezier control points too', () => { const path = new PathBuilder().moveTo(0, 0).cubicBezierTo(100, 0, 20, 40, 80, 40) const mirrored = path.transform({ a: -1, b: 0, c: 0, d: 1, e: 100, f: 0 }) expect(mirrored.toD()).toBe('M 100 0 C 80 40 20 40 0 0') }) }) describe('toSvg', () => { it('should build an SVG path', () => { const path = new PathBuilder() .moveTo(0, 0) .lineTo(100, 100) .lineTo(100, 0) .circularArcTo(50, false, false, 100, 100) .toSvg({ strokeWidth: 1, style: 'solid' }) expect(path).toMatchInlineSnapshot(` `) const closed = new PathBuilder() .moveTo(0, 0) .lineTo(100, 100) .lineTo(100, 0) .circularArcTo(50, false, false, 0, 100) .close() .toSvg({ strokeWidth: 1, style: 'solid' }) expect(closed).toMatchInlineSnapshot(` `) }) it('should support dashed paths', () => { const path = new PathBuilder() .moveTo(0, 0) .lineTo(100, 100) .lineTo(100, 0) .circularArcTo(50, false, false, 0, 100) .toSvg({ strokeWidth: 1, style: 'dashed' }) expect(path).toMatchInlineSnapshot(` `) const closed = new PathBuilder() .moveTo(0, 0) .lineTo(100, 100) .lineTo(100, 0) .circularArcTo(50, false, false, 0, 100) .close() .toSvg({ strokeWidth: 1, style: 'dashed' }) expect(closed).toMatchInlineSnapshot(` `) }) it('should support draw paths', () => { const path = new PathBuilder() .moveTo(0, 0) .lineTo(100, 100) .lineTo(100, 0) .circularArcTo(50, false, false, 0, 100) .toSvg({ strokeWidth: 10, style: 'draw', randomSeed: '123' }) expect(path).toMatchInlineSnapshot(` `) const closed = new PathBuilder() .moveTo(0, 0) .lineTo(100, 100) .lineTo(100, 0) .circularArcTo(50, false, false, 0, 100) .close() .toSvg({ strokeWidth: 10, style: 'draw', randomSeed: '123' }) expect(closed).toMatchInlineSnapshot(` `) }) }) describe('toGeometry', () => { it('should combine multiple lineTos into a single line', () => { const geometry = new PathBuilder() .moveTo(0, 0) .lineTo(100, 100) .lineTo(100, 0) .circularArcTo(50, false, false, 0, 100) .close() .toGeometry() expect(geometry?.toSimpleSvgPath()).toMatchInlineSnapshot( `"M0,0L100,100L100,0L84.92197106154207,-11.50593202657044L67.93757691512266,-18.409491194065584L50.000000178767834,-20.71067750830319L32.06242347050369,-18.409490975101022L15.078029408356239,-11.505931600276853L6.103515630684342e-7,6.103515559630068e-7L-11.505931600276849,15.078029408356231L-18.409490975101022,32.062423470503674L-20.710677508303192,50.00000017876782L-18.409491194065588,67.93757691512262L-11.50593202657045,84.92197106154204L-1.4210854715202004e-14,99.99999999999999L0,0Z"` ) }) }) })