openpencil/tests/engine/render/jsx/gaps.test.ts
Danila Poyarkov 3cfc86371d feat(design-jsx): masks, inline <svg> vectors, and instance overrides
Fill the three biggest gaps that blocked authoring real designs in JSX:

- mask prop on any node: <Ellipse mask> / mask="luminance" / mask="vector"
  sets isMask + maskType so sibling content clips (Figma's mask model)
- <svg> element rendering inline SVG markup into vector nodes, reusing the
  iconify path pipeline (extractPaths + parseSVGPath + scalePathInfos)
- Instance overrides: <Instance of="X" overrides={{ 'childName:prop': v }} />
  applies child overrides by name and records them so component sync keeps them

Adds gap tests and the shared scalePathInfos/finishIconRender helpers to
avoid duplicating the iconify pipeline.
2026-07-21 11:40:13 +03:00

44 lines
1.5 KiB
TypeScript

import { describe, expect, it } from 'bun:test'
import { renderJSX } from '@open-pencil/core'
import { makeSceneGraph } from '#tests/helpers/scene'
describe('jsx gaps', () => {
it('mask prop sets isMask + maskType', async () => {
const g = makeSceneGraph()
await renderJSX(
g,
`<Frame name="m" w={80} h={80}><Ellipse mask w={40} h={40} /><Rectangle w={80} h={80} bg="#f00" /></Frame>`
)
const ellipse = [...g.nodes.values()].find((n) => n.type === 'ELLIPSE')
expect(ellipse?.isMask).toBe(true)
expect(ellipse?.maskType).toBe('ALPHA')
})
it('svg element renders vector paths', async () => {
const g = makeSceneGraph()
await renderJSX(
g,
`<svg viewBox="0 0 24 24" w={24} h={24}><path d="M12 21s-7-4.5-9.5-9C0.5 8 2 4 6 4c2.5 0 4 1.5 6 3 2-1.5 3.5-3 6-3 4 0 5.5 4 3.5 8-2.5 4.5-9.5 9-9.5 9z"/></svg>`
)
const vector = [...g.nodes.values()].find((n) => n.type === 'VECTOR')
expect(vector).toBeTruthy()
expect(vector?.vectorNetwork).toBeTruthy()
})
it('instance overrides apply child text by name', async () => {
const g = makeSceneGraph()
await renderJSX(
g,
`<Component name="Badge" w={60} h={24}><Text name="label">+0%</Text></Component>
<Instance of="Badge" overrides={{ 'label:text': '+14%' }} />`
)
const inst = [...g.nodes.values()].find((n) => n.type === 'INSTANCE')
const label = [...g.nodes.values()].find(
(n) => n.type === 'TEXT' && inst && n.parentId === inst.id
)
expect(label?.text).toBe('+14%')
})
})