import { describe, test, expect, beforeEach } from 'bun:test'
import { FigmaAPI, SceneGraph } from '@open-pencil/core'
import { importSvg } from '@open-pencil/core/tools'
import { expectDefined, getNodeOrThrow } from '#tests/helpers/assert'
let graph: SceneGraph
let figma: FigmaAPI
beforeEach(() => {
graph = new SceneGraph()
figma = new FigmaAPI(graph)
})
describe('import_svg', () => {
test('imports a simple path', async () => {
const result = (await importSvg.execute(figma, {
svg: ''
})) as { id: string; name: string; type: string }
expect(result.id).toBeDefined()
expect(result.type).toBe('FRAME')
const frame = getNodeOrThrow(graph, result.id)
expect(frame.width).toBe(24)
expect(frame.height).toBe(24)
const children = graph.getChildren(result.id)
expect(children.length).toBe(1)
expect(children[0].type).toBe('VECTOR')
expect(children[0].vectorNetwork).toBeDefined()
expect(
expectDefined(children[0].vectorNetwork, 'imported vector network').vertices.length
).toBeGreaterThan(0)
})
test('imports multiple shapes', async () => {
const result = (await importSvg.execute(figma, {
svg: ``
})) as { id: string }
const children = graph.getChildren(result.id)
expect(children.length).toBe(3)
expect(children.every((c) => c.type === 'VECTOR')).toBe(true)
})
test('respects viewBox dimensions', async () => {
const result = (await importSvg.execute(figma, {
svg: ''
})) as { id: string }
const frame = getNodeOrThrow(graph, result.id)
expect(frame.width).toBe(200)
expect(frame.height).toBe(100)
})
test('uses width/height attributes when no viewBox', async () => {
const result = (await importSvg.execute(figma, {
svg: ''
})) as { id: string }
const frame = getNodeOrThrow(graph, result.id)
expect(frame.width).toBe(48)
expect(frame.height).toBe(48)
})
test('sets custom name', async () => {
const result = (await importSvg.execute(figma, {
svg: '',
name: 'Arrow'
})) as { id: string; name: string }
expect(result.name).toBe('Arrow')
})
test('applies fill color', async () => {
const result = (await importSvg.execute(figma, {
svg: ''
})) as { id: string }
const children = graph.getChildren(result.id)
expect(children[0].fills.length).toBe(1)
expect(children[0].fills[0].color.r).toBeCloseTo(1, 1)
expect(children[0].fills[0].color.g).toBeCloseTo(0, 1)
})
test('applies stroke', async () => {
const result = (await importSvg.execute(figma, {
svg: ''
})) as { id: string }
const children = graph.getChildren(result.id)
expect(children[0].fills.length).toBe(0)
expect(children[0].strokes.length).toBe(1)
expect(children[0].strokes[0].color.g).toBeCloseTo(1, 1)
expect(children[0].strokes[0].weight).toBe(2)
})
test('uses currentColor with custom color arg', async () => {
const result = (await importSvg.execute(figma, {
svg: '',
color: '#0000FF'
})) as { id: string }
const children = graph.getChildren(result.id)
expect(children[0].fills[0].color.b).toBeCloseTo(1, 1)
expect(children[0].fills[0].color.r).toBeCloseTo(0, 1)
})
test('sets position', async () => {
const result = (await importSvg.execute(figma, {
svg: '',
x: 100,
y: 200
})) as { id: string }
const frame = getNodeOrThrow(graph, result.id)
expect(frame.x).toBe(100)
expect(frame.y).toBe(200)
})
test('returns error for empty SVG', async () => {
const result = (await importSvg.execute(figma, {
svg: ''
})) as { error: string }
expect(result.error).toContain('No supported SVG elements')
})
test('returns error for missing svg param', async () => {
const result = (await importSvg.execute(figma, {})) as { error: string }
expect(result.error).toContain('required')
})
test('handles polygon and polyline', async () => {
const result = (await importSvg.execute(figma, {
svg: ``
})) as { id: string }
const children = graph.getChildren(result.id)
expect(children.length).toBe(2)
})
})