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"`
)
})
})
})