import { describe, expect, test } from 'bun:test' import { computeLayout, SceneGraph } from '@open-pencil/core' import { getNodeOrThrow } from '#tests/helpers/assert' import { autoFrame, pageId, rect } from '#tests/helpers/layout' describe('hidden children', () => { test('hidden children preserve original size but collapse in layout', () => { const graph = new SceneGraph() const frame = autoFrame(graph, pageId(graph), { width: 300, height: 100, itemSpacing: 10 }) rect(graph, frame.id, 50, 50, { visible: false }) rect(graph, frame.id, 80, 40) rect(graph, frame.id, 50, 50, { visible: false }) computeLayout(graph, frame.id) const children = graph.getChildren(frame.id) expect(children[0].width).toBe(50) expect(children[0].height).toBe(50) expect(children[1].x).toBe(0) expect(children[1].width).toBe(80) expect(children[2].width).toBe(50) expect(children[2].height).toBe(50) }) test('hidden children do not consume spacing', () => { const graph = new SceneGraph() const frame = autoFrame(graph, pageId(graph), { width: 400, height: 100, itemSpacing: 20 }) rect(graph, frame.id, 50, 50, { visible: false }) rect(graph, frame.id, 100, 50) rect(graph, frame.id, 100, 50) computeLayout(graph, frame.id) const children = graph.getChildren(frame.id) expect(children[1].x).toBe(0) expect(children[2].x).toBe(120) }) test('hug frame ignores hidden children for sizing', () => { const graph = new SceneGraph() const frame = autoFrame(graph, pageId(graph), { primaryAxisSizing: 'HUG', counterAxisSizing: 'HUG' }) rect(graph, frame.id, 200, 200, { visible: false }) rect(graph, frame.id, 50, 30) computeLayout(graph, frame.id) const f = getNodeOrThrow(graph, frame.id) expect(f.width).toBe(50) expect(f.height).toBe(30) }) test('hidden nested auto-layout children preserve size but collapse in layout', () => { const graph = new SceneGraph() const outer = autoFrame(graph, pageId(graph), { width: 300, height: 100, itemSpacing: 16 }) const inner = autoFrame(graph, outer.id, { primaryAxisSizing: 'FIXED', counterAxisSizing: 'FIXED', width: 50, height: 50, visible: false }) rect(graph, inner.id, 30, 30) rect(graph, outer.id, 80, 40) computeLayout(graph, outer.id) const children = graph.getChildren(outer.id) const innerNode = getNodeOrThrow(graph, inner.id) expect(innerNode.width).toBe(50) expect(innerNode.height).toBe(50) expect(children[1].x).toBe(0) }) test('hidden children in HUG auto-layout instances collapse layout', () => { const graph = new SceneGraph() const page = pageId(graph) const component = graph.createNode('COMPONENT', page, { name: 'Optional slot component', layoutMode: 'VERTICAL', primaryAxisSizing: 'HUG', counterAxisSizing: 'FIXED', width: 300, height: 1, itemSpacing: 0 }) rect(graph, component.id, 300, 40, { name: 'Slot / Pinned at Top' }) rect(graph, component.id, 300, 74, { name: 'Slot / Content' }) rect(graph, component.id, 300, 40, { name: 'Slot / Pinned at Bottom' }) const instance = graph.createInstance(component.id, page, { x: 360, y: 0 }) if (!instance) throw new Error('Expected instance to be created') computeLayout(graph, instance.id) expect(getNodeOrThrow(graph, instance.id).height).toBe(154) const content = graph.getChildren(instance.id).find((child) => child.name === 'Slot / Content') const bottom = graph .getChildren(instance.id) .find((child) => child.name === 'Slot / Pinned at Bottom') if (!content || !bottom) throw new Error('Expected instance slot children') expect(getNodeOrThrow(graph, bottom.id).y).toBe(114) graph.updateNode(content.id, { visible: false }) computeLayout(graph, instance.id) expect(getNodeOrThrow(graph, instance.id).height).toBe(80) expect(getNodeOrThrow(graph, bottom.id).y).toBe(40) expect(getNodeOrThrow(graph, content.id).height).toBe(74) }) })