- Extend the as-unknown-as structural rule beyond app and Vue code - Remove existing broad double casts from core and tests - Replace the vector base64 helper and XPath facade casts with precise code paths
642 lines
19 KiB
TypeScript
642 lines
19 KiB
TypeScript
import { describe, test, expect } from 'bun:test'
|
|
|
|
import { importNodeChanges, type NodeChange } from '@open-pencil/core'
|
|
|
|
function doc(): NodeChange {
|
|
return {
|
|
guid: { sessionID: 0, localID: 0 },
|
|
type: 'DOCUMENT',
|
|
name: 'Document',
|
|
visible: true,
|
|
opacity: 1,
|
|
phase: 'CREATED',
|
|
transform: { m00: 1, m01: 0, m02: 0, m10: 0, m11: 1, m12: 0 }
|
|
} as NodeChange
|
|
}
|
|
|
|
function canvas(localID = 1): NodeChange {
|
|
return {
|
|
guid: { sessionID: 0, localID },
|
|
parentIndex: { guid: { sessionID: 0, localID: 0 }, position: '!' },
|
|
type: 'CANVAS',
|
|
name: 'Page 1',
|
|
visible: true,
|
|
opacity: 1,
|
|
phase: 'CREATED',
|
|
transform: { m00: 1, m01: 0, m02: 0, m10: 0, m11: 1, m12: 0 }
|
|
} as NodeChange
|
|
}
|
|
|
|
function node(
|
|
type: string,
|
|
localID: number,
|
|
parentLocalID: number,
|
|
overrides: Partial<NodeChange> = {}
|
|
): NodeChange {
|
|
return {
|
|
guid: { sessionID: 1, localID },
|
|
parentIndex: {
|
|
guid: { sessionID: 0, localID: parentLocalID },
|
|
position: String.fromCharCode(33 + localID)
|
|
},
|
|
type,
|
|
name: `${type}_${localID}`,
|
|
visible: true,
|
|
opacity: 1,
|
|
phase: 'CREATED',
|
|
size: { x: 100, y: 100 },
|
|
transform: { m00: 1, m01: 0, m02: 0, m10: 0, m11: 1, m12: 0 },
|
|
...overrides
|
|
} as NodeChange
|
|
}
|
|
|
|
describe('fig-import: node types', () => {
|
|
test('ROUNDED_RECTANGLE imported as its own type', () => {
|
|
const graph = importNodeChanges([doc(), canvas(), node('ROUNDED_RECTANGLE', 10, 1)])
|
|
const nodes = graph.getChildren(graph.getPages()[0].id)
|
|
expect(nodes[0].type).toBe('ROUNDED_RECTANGLE')
|
|
})
|
|
|
|
test('COMPONENT maps to COMPONENT', () => {
|
|
const graph = importNodeChanges([doc(), canvas(), node('COMPONENT', 10, 1)])
|
|
const nodes = graph.getChildren(graph.getPages()[0].id)
|
|
expect(nodes[0].type).toBe('COMPONENT')
|
|
})
|
|
|
|
test('INSTANCE maps to INSTANCE', () => {
|
|
const graph = importNodeChanges([doc(), canvas(), node('INSTANCE', 10, 1)])
|
|
const nodes = graph.getChildren(graph.getPages()[0].id)
|
|
expect(nodes[0].type).toBe('INSTANCE')
|
|
})
|
|
|
|
test('SYMBOL maps to COMPONENT', () => {
|
|
const graph = importNodeChanges([doc(), canvas(), node('SYMBOL', 10, 1)])
|
|
const nodes = graph.getChildren(graph.getPages()[0].id)
|
|
expect(nodes[0].type).toBe('COMPONENT')
|
|
})
|
|
|
|
test('REGULAR_POLYGON maps to POLYGON', () => {
|
|
const graph = importNodeChanges([doc(), canvas(), node('REGULAR_POLYGON', 10, 1)])
|
|
const nodes = graph.getChildren(graph.getPages()[0].id)
|
|
expect(nodes[0].type).toBe('POLYGON')
|
|
})
|
|
})
|
|
|
|
describe('fig-import: transforms', () => {
|
|
test('flipped transforms use their visual bounds', () => {
|
|
const graph = importNodeChanges([
|
|
doc(),
|
|
canvas(),
|
|
node('VECTOR', 10, 1, {
|
|
size: { x: 17, y: 36 },
|
|
transform: { m00: -1, m01: 0, m02: 70, m10: 0, m11: 1, m12: 7 }
|
|
})
|
|
])
|
|
const imported = graph.getChildren(graph.getPages()[0].id)[0]
|
|
|
|
expect(imported.x).toBe(53)
|
|
expect(imported.y).toBe(7)
|
|
expect(imported.flipX).toBe(true)
|
|
})
|
|
})
|
|
|
|
describe('fig-import: gradient fills', () => {
|
|
test('linear gradient', () => {
|
|
const graph = importNodeChanges([
|
|
doc(),
|
|
canvas(),
|
|
node('RECTANGLE', 10, 1, {
|
|
fillPaints: [
|
|
{
|
|
type: 'GRADIENT_LINEAR',
|
|
opacity: 1,
|
|
visible: true,
|
|
blendMode: 'NORMAL',
|
|
stops: [
|
|
{ color: { r: 1, g: 0, b: 0, a: 1 }, position: 0 },
|
|
{ color: { r: 0, g: 0, b: 1, a: 1 }, position: 1 }
|
|
],
|
|
transform: { m00: 1, m01: 0, m02: 0, m10: 0, m11: 1, m12: 0 }
|
|
}
|
|
] as NodeChange['fillPaints']
|
|
})
|
|
])
|
|
const n = graph.getChildren(graph.getPages()[0].id)[0]
|
|
expect(n.fills).toHaveLength(1)
|
|
expect(n.fills[0].type).toBe('GRADIENT_LINEAR')
|
|
expect(n.fills[0].gradientStops).toHaveLength(2)
|
|
expect(n.fills[0].gradientStops![0].color.r).toBe(1)
|
|
expect(n.fills[0].gradientStops![1].color.b).toBe(1)
|
|
expect(n.fills[0].gradientTransform).toBeDefined()
|
|
})
|
|
|
|
test('radial gradient', () => {
|
|
const graph = importNodeChanges([
|
|
doc(),
|
|
canvas(),
|
|
node('ELLIPSE', 10, 1, {
|
|
fillPaints: [
|
|
{
|
|
type: 'GRADIENT_RADIAL',
|
|
opacity: 0.8,
|
|
visible: true,
|
|
blendMode: 'NORMAL',
|
|
stops: [
|
|
{ color: { r: 1, g: 1, b: 1, a: 1 }, position: 0 },
|
|
{ color: { r: 0, g: 0, b: 0, a: 1 }, position: 1 }
|
|
],
|
|
transform: { m00: 0.5, m01: 0, m02: 0.5, m10: 0, m11: 0.5, m12: 0.5 }
|
|
}
|
|
] as NodeChange['fillPaints']
|
|
})
|
|
])
|
|
const n = graph.getChildren(graph.getPages()[0].id)[0]
|
|
expect(n.fills[0].type).toBe('GRADIENT_RADIAL')
|
|
expect(n.fills[0].opacity).toBe(0.8)
|
|
expect(n.fills[0].gradientStops).toHaveLength(2)
|
|
})
|
|
})
|
|
|
|
describe('fig-import: image fills', () => {
|
|
test('image fill with hash', () => {
|
|
const hash: Record<string, number> = {}
|
|
for (let i = 0; i < 20; i++) hash[String(i)] = i + 10
|
|
|
|
const graph = importNodeChanges([
|
|
doc(),
|
|
canvas(),
|
|
node('RECTANGLE', 10, 1, {
|
|
fillPaints: [
|
|
{
|
|
type: 'IMAGE',
|
|
opacity: 1,
|
|
visible: true,
|
|
blendMode: 'NORMAL',
|
|
image: { hash, name: 'test-image' },
|
|
imageScaleMode: 'FILL',
|
|
transform: { m00: 1, m01: 0, m02: 0, m10: 0, m11: 1, m12: 0 }
|
|
}
|
|
] as NodeChange['fillPaints']
|
|
})
|
|
])
|
|
const n = graph.getChildren(graph.getPages()[0].id)[0]
|
|
expect(n.fills[0].type).toBe('IMAGE')
|
|
expect(n.fills[0].imageHash).toBeDefined()
|
|
expect(n.fills[0].imageHash!.length).toBe(40)
|
|
expect(n.fills[0].imageScaleMode).toBe('FILL')
|
|
})
|
|
|
|
test('images stored on graph', () => {
|
|
const images = new Map<string, Uint8Array>()
|
|
images.set('abc123', new Uint8Array([1, 2, 3]))
|
|
const graph = importNodeChanges([doc(), canvas()], [], images)
|
|
expect(graph.images.get('abc123')).toEqual(new Uint8Array([1, 2, 3]))
|
|
})
|
|
})
|
|
|
|
describe('fig-import: effects', () => {
|
|
test('drop shadow', () => {
|
|
const graph = importNodeChanges([
|
|
doc(),
|
|
canvas(),
|
|
node('RECTANGLE', 10, 1, {
|
|
effects: [
|
|
{
|
|
type: 'DROP_SHADOW',
|
|
color: { r: 0, g: 0, b: 0, a: 0.25 },
|
|
offset: { x: 4, y: 4 },
|
|
radius: 8,
|
|
spread: 0,
|
|
visible: true
|
|
}
|
|
] as NodeChange['effects']
|
|
})
|
|
])
|
|
const n = graph.getChildren(graph.getPages()[0].id)[0]
|
|
expect(n.effects).toHaveLength(1)
|
|
expect(n.effects[0].type).toBe('DROP_SHADOW')
|
|
expect(n.effects[0].radius).toBe(8)
|
|
expect(n.effects[0].offset.x).toBe(4)
|
|
})
|
|
|
|
test('inner shadow', () => {
|
|
const graph = importNodeChanges([
|
|
doc(),
|
|
canvas(),
|
|
node('RECTANGLE', 10, 1, {
|
|
effects: [
|
|
{
|
|
type: 'INNER_SHADOW',
|
|
color: { r: 0, g: 0, b: 0, a: 0.5 },
|
|
offset: { x: 0, y: 2 },
|
|
radius: 4,
|
|
spread: 0,
|
|
visible: true
|
|
}
|
|
] as NodeChange['effects']
|
|
})
|
|
])
|
|
const n = graph.getChildren(graph.getPages()[0].id)[0]
|
|
expect(n.effects[0].type).toBe('INNER_SHADOW')
|
|
})
|
|
})
|
|
|
|
describe('fig-import: stroke options', () => {
|
|
test('stroke cap and join', () => {
|
|
const graph = importNodeChanges([
|
|
doc(),
|
|
canvas(),
|
|
node('VECTOR', 10, 1, {
|
|
strokePaints: [
|
|
{
|
|
type: 'SOLID',
|
|
color: { r: 0, g: 0, b: 0, a: 1 },
|
|
opacity: 1,
|
|
visible: true,
|
|
blendMode: 'NORMAL'
|
|
}
|
|
],
|
|
strokeWeight: 3,
|
|
strokeAlign: 'CENTER',
|
|
strokeCap: 'ROUND',
|
|
strokeJoin: 'BEVEL'
|
|
} as Partial<NodeChange>)
|
|
])
|
|
const n = graph.getChildren(graph.getPages()[0].id)[0]
|
|
expect(n.strokes[0].cap).toBe('ROUND')
|
|
expect(n.strokes[0].join).toBe('BEVEL')
|
|
})
|
|
|
|
test('dash pattern', () => {
|
|
const graph = importNodeChanges([
|
|
doc(),
|
|
canvas(),
|
|
node('RECTANGLE', 10, 1, {
|
|
strokePaints: [
|
|
{
|
|
type: 'SOLID',
|
|
color: { r: 0, g: 0, b: 0, a: 1 },
|
|
opacity: 1,
|
|
visible: true,
|
|
blendMode: 'NORMAL'
|
|
}
|
|
],
|
|
strokeWeight: 2,
|
|
strokeAlign: 'CENTER',
|
|
dashPattern: [10, 5]
|
|
} as Partial<NodeChange>)
|
|
])
|
|
const n = graph.getChildren(graph.getPages()[0].id)[0]
|
|
expect(n.strokes[0].dashPattern).toEqual([10, 5])
|
|
})
|
|
})
|
|
|
|
describe('fig-import: text properties', () => {
|
|
test('text auto resize', () => {
|
|
const graph = importNodeChanges([
|
|
doc(),
|
|
canvas(),
|
|
node('TEXT', 10, 1, {
|
|
textData: { characters: 'Hello' },
|
|
fontSize: 16,
|
|
textAlignHorizontal: 'CENTER',
|
|
textAutoResize: 'WIDTH_AND_HEIGHT'
|
|
} as Partial<NodeChange>)
|
|
])
|
|
const n = graph.getChildren(graph.getPages()[0].id)[0]
|
|
expect(n.textAutoResize).toBe('WIDTH_AND_HEIGHT')
|
|
expect(n.textAlignHorizontal).toBe('CENTER')
|
|
})
|
|
|
|
test('font weight mapping', () => {
|
|
const cases = [
|
|
['Bold', 700],
|
|
['Semi Bold', 600],
|
|
['Light', 300],
|
|
['ExtraBold', 800],
|
|
['Black', 900],
|
|
['Thin', 100],
|
|
['Medium', 500],
|
|
['Regular', 400]
|
|
] as const
|
|
|
|
for (const [style, expected] of cases) {
|
|
const graph = importNodeChanges([
|
|
doc(),
|
|
canvas(),
|
|
node('TEXT', 10, 1, {
|
|
textData: { characters: 'X' },
|
|
fontName: { family: 'Inter', style }
|
|
} as Partial<NodeChange>)
|
|
])
|
|
const n = graph.getChildren(graph.getPages()[0].id)[0]
|
|
expect(n.fontWeight).toBe(expected)
|
|
}
|
|
})
|
|
})
|
|
|
|
describe('fig-import: arc data', () => {
|
|
test('partial ellipse', () => {
|
|
const graph = importNodeChanges([
|
|
doc(),
|
|
canvas(),
|
|
node('ELLIPSE', 10, 1, {
|
|
arcData: {
|
|
startingAngle: 0,
|
|
endingAngle: Math.PI,
|
|
innerRadius: 0
|
|
}
|
|
} as Partial<NodeChange>)
|
|
])
|
|
const n = graph.getChildren(graph.getPages()[0].id)[0]
|
|
expect(n.arcData).toBeDefined()
|
|
expect(n.arcData!.startingAngle).toBe(0)
|
|
expect(n.arcData!.endingAngle).toBeCloseTo(Math.PI)
|
|
expect(n.arcData!.innerRadius).toBe(0)
|
|
})
|
|
|
|
test('donut (inner radius)', () => {
|
|
const graph = importNodeChanges([
|
|
doc(),
|
|
canvas(),
|
|
node('ELLIPSE', 10, 1, {
|
|
arcData: {
|
|
startingAngle: 0,
|
|
endingAngle: Math.PI * 2,
|
|
innerRadius: 0.5
|
|
}
|
|
} as Partial<NodeChange>)
|
|
])
|
|
const n = graph.getChildren(graph.getPages()[0].id)[0]
|
|
expect(n.arcData!.innerRadius).toBe(0.5)
|
|
})
|
|
})
|
|
|
|
describe('fig-import: constraints', () => {
|
|
test('horizontal and vertical constraints', () => {
|
|
const graph = importNodeChanges([
|
|
doc(),
|
|
canvas(),
|
|
node('RECTANGLE', 10, 1, {
|
|
horizontalConstraint: 'STRETCH',
|
|
verticalConstraint: 'CENTER'
|
|
} as Partial<NodeChange>)
|
|
])
|
|
const n = graph.getChildren(graph.getPages()[0].id)[0]
|
|
expect(n.horizontalConstraint).toBe('STRETCH')
|
|
expect(n.verticalConstraint).toBe('CENTER')
|
|
})
|
|
|
|
test('defaults to MIN', () => {
|
|
const graph = importNodeChanges([doc(), canvas(), node('RECTANGLE', 10, 1)])
|
|
const n = graph.getChildren(graph.getPages()[0].id)[0]
|
|
expect(n.horizontalConstraint).toBe('MIN')
|
|
expect(n.verticalConstraint).toBe('MIN')
|
|
})
|
|
})
|
|
|
|
describe('fig-import: blend mode', () => {
|
|
test('node blend mode', () => {
|
|
const graph = importNodeChanges([
|
|
doc(),
|
|
canvas(),
|
|
node('RECTANGLE', 10, 1, {
|
|
blendMode: 'MULTIPLY'
|
|
} as Partial<NodeChange>)
|
|
])
|
|
const n = graph.getChildren(graph.getPages()[0].id)[0]
|
|
expect(n.blendMode).toBe('MULTIPLY')
|
|
})
|
|
|
|
test('defaults to PASS_THROUGH', () => {
|
|
const graph = importNodeChanges([doc(), canvas(), node('RECTANGLE', 10, 1)])
|
|
const n = graph.getChildren(graph.getPages()[0].id)[0]
|
|
expect(n.blendMode).toBe('PASS_THROUGH')
|
|
})
|
|
})
|
|
|
|
describe('fig-import: independent stroke weights', () => {
|
|
test('border weights imported', () => {
|
|
const graph = importNodeChanges([
|
|
doc(),
|
|
canvas(),
|
|
node('FRAME', 10, 1, {
|
|
borderTopWeight: 2,
|
|
borderRightWeight: 4,
|
|
borderBottomWeight: 2,
|
|
borderLeftWeight: 4,
|
|
borderStrokeWeightsIndependent: true
|
|
} as Partial<NodeChange>)
|
|
])
|
|
const n = graph.getChildren(graph.getPages()[0].id)[0]
|
|
expect(n.borderTopWeight).toBe(2)
|
|
expect(n.borderRightWeight).toBe(4)
|
|
expect(n.independentStrokeWeights).toBe(true)
|
|
})
|
|
})
|
|
|
|
describe('fig-import: multiple fills', () => {
|
|
test('solid + gradient stacked', () => {
|
|
const graph = importNodeChanges([
|
|
doc(),
|
|
canvas(),
|
|
node('RECTANGLE', 10, 1, {
|
|
fillPaints: [
|
|
{
|
|
type: 'SOLID',
|
|
color: { r: 1, g: 0, b: 0, a: 1 },
|
|
opacity: 1,
|
|
visible: true,
|
|
blendMode: 'NORMAL'
|
|
},
|
|
{
|
|
type: 'GRADIENT_LINEAR',
|
|
opacity: 0.5,
|
|
visible: true,
|
|
blendMode: 'NORMAL',
|
|
stops: [
|
|
{ color: { r: 1, g: 1, b: 1, a: 1 }, position: 0 },
|
|
{ color: { r: 0, g: 0, b: 0, a: 0 }, position: 1 }
|
|
],
|
|
transform: { m00: 1, m01: 0, m02: 0, m10: 0, m11: 1, m12: 0 }
|
|
}
|
|
] as NodeChange['fillPaints']
|
|
})
|
|
])
|
|
const n = graph.getChildren(graph.getPages()[0].id)[0]
|
|
expect(n.fills).toHaveLength(2)
|
|
expect(n.fills[0].type).toBe('SOLID')
|
|
expect(n.fills[1].type).toBe('GRADIENT_LINEAR')
|
|
expect(n.fills[1].opacity).toBe(0.5)
|
|
})
|
|
})
|
|
|
|
describe('fig-import: auto-layout alignment', () => {
|
|
test('maps SPACE_EVENLY kiwi primary alignment to Figma space-between', () => {
|
|
const graph = importNodeChanges([
|
|
doc(),
|
|
canvas(),
|
|
node('FRAME', 10, 1, {
|
|
stackMode: 'HORIZONTAL',
|
|
stackPrimaryAlignItems: 'SPACE_EVENLY'
|
|
} as Partial<NodeChange>)
|
|
])
|
|
const n = graph.getChildren(graph.getPages()[0].id)[0]
|
|
expect(n.primaryAxisAlign).toBe('SPACE_BETWEEN')
|
|
})
|
|
})
|
|
|
|
describe('fig-import: variable asset refs', () => {
|
|
test('resolves color variables and aliases by assetRef', () => {
|
|
const graph = importNodeChanges([
|
|
doc(),
|
|
canvas(),
|
|
{
|
|
...node('VARIABLE_SET', 20, 1),
|
|
name: 'Tokens',
|
|
key: 'collection-key',
|
|
version: '1:1',
|
|
variableSetModes: [{ id: { sessionID: 10, localID: 1 }, name: 'Default' }]
|
|
} as NodeChange,
|
|
{
|
|
...node('VARIABLE', 21, 1),
|
|
name: 'Blue',
|
|
key: 'blue-key',
|
|
version: '1:2',
|
|
variableSetID: { assetRef: { key: 'collection-key', version: '1:1' } },
|
|
variableResolvedType: 'COLOR',
|
|
variableDataValues: {
|
|
entries: [
|
|
{
|
|
modeID: { sessionID: 10, localID: 1 },
|
|
variableData: {
|
|
dataType: 'COLOR',
|
|
resolvedDataType: 'COLOR',
|
|
value: { colorValue: { r: 0.14, g: 0.39, b: 0.92, a: 1 } }
|
|
}
|
|
}
|
|
]
|
|
}
|
|
} as NodeChange,
|
|
{
|
|
...node('VARIABLE', 22, 1),
|
|
name: 'Primary',
|
|
key: 'primary-key',
|
|
version: '1:3',
|
|
variableSetID: { assetRef: { key: 'collection-key', version: '1:1' } },
|
|
variableResolvedType: 'COLOR',
|
|
variableDataValues: {
|
|
entries: [
|
|
{
|
|
modeID: { sessionID: 10, localID: 1 },
|
|
variableData: {
|
|
dataType: 'ALIAS',
|
|
resolvedDataType: 'COLOR',
|
|
value: { alias: { assetRef: { key: 'blue-key', version: '1:2' } } }
|
|
}
|
|
}
|
|
]
|
|
}
|
|
} as NodeChange,
|
|
node('TEXT', 30, 1, {
|
|
textData: { characters: 'browse' },
|
|
fillPaints: [
|
|
{
|
|
type: 'SOLID',
|
|
color: { r: 0, g: 0, b: 0, a: 1 },
|
|
colorVar: {
|
|
value: { alias: { assetRef: { key: 'primary-key', version: '1:3' } } },
|
|
dataType: 'ALIAS',
|
|
resolvedDataType: 'COLOR'
|
|
}
|
|
}
|
|
] as NodeChange['fillPaints']
|
|
})
|
|
])
|
|
|
|
const primary = [...graph.variables.values()].find((v) => v.name === 'Primary')!
|
|
const resolved = graph.resolveColorVariable(primary.id)!
|
|
expect(resolved.r).toBeCloseTo(0.14)
|
|
expect(resolved.g).toBeCloseTo(0.39)
|
|
expect(resolved.b).toBeCloseTo(0.92)
|
|
|
|
const text = [...graph.getAllNodes()].find((n) => n.type === 'TEXT' && n.text === 'browse')!
|
|
expect(text.fills[0].color.r).toBeCloseTo(0.14)
|
|
expect(text.fills[0].color.g).toBeCloseTo(0.39)
|
|
expect(text.fills[0].color.b).toBeCloseTo(0.92)
|
|
})
|
|
})
|
|
|
|
describe('fig-import: component set detection', () => {
|
|
test('FRAME with VARIANT componentPropDefs becomes COMPONENT_SET', () => {
|
|
const changes: NodeChange[] = [
|
|
doc(),
|
|
canvas(),
|
|
{
|
|
...node('FRAME', 10, 1),
|
|
name: 'Button',
|
|
componentPropDefs: [{ id: { sessionID: 0, localID: 1 }, name: 'State', type: 'VARIANT' }]
|
|
} as NodeChange,
|
|
{
|
|
...node('SYMBOL', 11, 1),
|
|
parentIndex: { guid: { sessionID: 1, localID: 10 }, position: '!' },
|
|
name: 'State=Default'
|
|
} as NodeChange,
|
|
{
|
|
...node('SYMBOL', 12, 1),
|
|
parentIndex: { guid: { sessionID: 1, localID: 10 }, position: '"' },
|
|
name: 'State=Hover'
|
|
} as NodeChange
|
|
]
|
|
const graph = importNodeChanges(changes, [])
|
|
const page = graph.getPages()[0]
|
|
const set = graph.getChildren(page.id)[0]
|
|
expect(set.type).toBe('COMPONENT_SET')
|
|
expect(set.name).toBe('Button')
|
|
const children = graph.getChildren(set.id)
|
|
expect(children).toHaveLength(2)
|
|
expect(children[0].type).toBe('COMPONENT')
|
|
expect(children[1].type).toBe('COMPONENT')
|
|
})
|
|
|
|
test('FRAME without componentPropDefs stays FRAME', () => {
|
|
const changes: NodeChange[] = [doc(), canvas(), node('FRAME', 10, 1, { name: 'Regular Frame' })]
|
|
const graph = importNodeChanges(changes, [])
|
|
const page = graph.getPages()[0]
|
|
const frame = graph.getChildren(page.id)[0]
|
|
expect(frame.type).toBe('FRAME')
|
|
})
|
|
})
|
|
|
|
describe('fig-import: clipsContent with resizeToFit', () => {
|
|
test('regular FRAME with frameMaskDisabled=false clips content', () => {
|
|
const graph = importNodeChanges([
|
|
doc(),
|
|
canvas(),
|
|
node('FRAME', 10, 1, { frameMaskDisabled: false })
|
|
])
|
|
const frame = graph.getChildren(graph.getPages()[0].id)[0]
|
|
expect(frame.clipsContent).toBe(true)
|
|
})
|
|
|
|
test('resizeToFit FRAME does not clip even with frameMaskDisabled=false', () => {
|
|
const graph = importNodeChanges([
|
|
doc(),
|
|
canvas(),
|
|
node('FRAME', 10, 1, { frameMaskDisabled: false, resizeToFit: true })
|
|
])
|
|
const frame = graph.getChildren(graph.getPages()[0].id)[0]
|
|
expect(frame.clipsContent).toBe(false)
|
|
})
|
|
|
|
test('FRAME with frameMaskDisabled=true does not clip', () => {
|
|
const graph = importNodeChanges([
|
|
doc(),
|
|
canvas(),
|
|
node('FRAME', 10, 1, { frameMaskDisabled: true })
|
|
])
|
|
const frame = graph.getChildren(graph.getPages()[0].id)[0]
|
|
expect(frame.clipsContent).toBe(false)
|
|
})
|
|
})
|