118 lines
4.5 KiB
TypeScript
118 lines
4.5 KiB
TypeScript
import { describe, expect, test } from 'bun:test'
|
|
import { readFileSync } from 'node:fs'
|
|
|
|
import { exportFigFile, extractExportGraph, parseFigFile } from '@open-pencil/core/io'
|
|
import { initCodec } from '@open-pencil/core/kiwi'
|
|
import { guidToString } from '@open-pencil/core/kiwi/fig/node-change/guid'
|
|
import { parseFigBuffer } from '@open-pencil/core/kiwi/fig/parse/core'
|
|
import { SceneGraph } from '@open-pencil/core/scene-graph'
|
|
|
|
describe('export subgraph extraction', () => {
|
|
test('page extraction keeps the source root and page descendants', () => {
|
|
const graph = new SceneGraph()
|
|
const page = graph.getPages()[0]
|
|
const frame = graph.createNode('FRAME', page.id, {
|
|
name: 'Frame',
|
|
x: 10,
|
|
y: 20,
|
|
width: 100,
|
|
height: 100
|
|
})
|
|
const text = graph.createNode('TEXT', frame.id, {
|
|
name: 'Label',
|
|
text: 'Hello',
|
|
width: 50,
|
|
height: 20
|
|
})
|
|
|
|
const extracted = extractExportGraph(graph, { scope: 'page', pageId: page.id })
|
|
const extractedPages = extracted.graph.getPages(true)
|
|
|
|
expect(extracted.graph.rootId).toBe(graph.rootId)
|
|
expect(extractedPages.map((node) => node.id)).toEqual([page.id])
|
|
expect(extracted.graph.getNode(page.id)?.childIds).toEqual([frame.id])
|
|
expect(extracted.graph.getNode(frame.id)?.childIds).toEqual([text.id])
|
|
expect(extracted.graph.getNode(text.id)?.text).toBe('Hello')
|
|
})
|
|
|
|
test('page extraction includes component dependencies for instances', () => {
|
|
const graph = new SceneGraph()
|
|
const page = graph.getPages()[0]
|
|
const libraryPage = graph.addPage('Library')
|
|
const component = graph.createNode('COMPONENT', libraryPage.id, {
|
|
name: 'Button',
|
|
width: 100,
|
|
height: 40
|
|
})
|
|
graph.createNode('TEXT', component.id, {
|
|
name: 'Label',
|
|
text: 'Button',
|
|
width: 80,
|
|
height: 20
|
|
})
|
|
const instance = graph.createInstance(component.id, page.id)
|
|
|
|
const extracted = extractExportGraph(graph, { scope: 'page', pageId: page.id })
|
|
|
|
expect(extracted.graph.getNode(instance.id)?.type).toBe('INSTANCE')
|
|
expect(extracted.graph.getNode(component.id)?.type).toBe('COMPONENT')
|
|
expect(extracted.graph.getNode(libraryPage.id)?.type).toBe('CANVAS')
|
|
})
|
|
|
|
test('fig page export preserves valid instance component references without serializing instance children', async () => {
|
|
await initCodec()
|
|
const graph = new SceneGraph()
|
|
const page = graph.getPages()[0]
|
|
const libraryPage = graph.addPage('Library')
|
|
const component = graph.createNode('COMPONENT', libraryPage.id, {
|
|
name: 'Button',
|
|
width: 100,
|
|
height: 40
|
|
})
|
|
const instance = graph.createInstance(component.id, page.id)
|
|
if (!instance) throw new Error('Expected instance')
|
|
|
|
const extracted = extractExportGraph(graph, { scope: 'page', pageId: page.id })
|
|
const exported = await exportFigFile(extracted.graph)
|
|
const parsed = await parseFigFile(exported.buffer as ArrayBuffer)
|
|
const parsedInstance = [...parsed.getAllNodes()].find(
|
|
(node) => node.type === 'INSTANCE' && node.name === instance.name
|
|
)
|
|
|
|
expect(parsedInstance?.type).toBe('INSTANCE')
|
|
expect(parsedInstance?.componentId).toBeTruthy()
|
|
expect(parsed.getNode(parsedInstance?.componentId ?? '')?.type).toBe('COMPONENT')
|
|
|
|
const exportedAgain = await exportFigFile(extracted.graph)
|
|
const reparsed = await parseFigFile(exportedAgain.buffer as ArrayBuffer)
|
|
const reparsedInstance = [...reparsed.getAllNodes()].find(
|
|
(node) => node.type === 'INSTANCE' && node.name === instance.name
|
|
)
|
|
expect(reparsedInstance?.childIds).toEqual([])
|
|
})
|
|
|
|
test('fig export preserves imported instance symbol overrides and guids', async () => {
|
|
await initCodec()
|
|
const fixture = new Uint8Array(readFileSync('tests/fixtures/gold-preview.fig'))
|
|
const graph = await parseFigFile(
|
|
fixture.buffer.slice(
|
|
fixture.byteOffset,
|
|
fixture.byteOffset + fixture.byteLength
|
|
) as ArrayBuffer
|
|
)
|
|
const exported = await exportFigFile(graph)
|
|
const parsed = parseFigBuffer(exported.buffer as ArrayBuffer)
|
|
const input = parsed.nodeChanges.find(
|
|
(node) => node.guid && guidToString(node.guid) === '1:3503'
|
|
)
|
|
const lists = parsed.nodeChanges.find(
|
|
(node) => node.guid && guidToString(node.guid) === '1:3491'
|
|
)
|
|
|
|
expect(input?.type).toBe('INSTANCE')
|
|
expect(input?.symbolData?.symbolOverrides?.length).toBe(9)
|
|
expect(input?.symbolData?.uniformScaleFactor).toBeCloseTo(0.8908441662788391)
|
|
expect(lists?.symbolData?.symbolOverrides?.length).toBe(5)
|
|
})
|
|
})
|