test: add proxyWidgets reordering tests

Add tests documenting that:
- Direct reordering of proxyWidgets tuples preserves all entries
- Widget references remain correct after reorder
- The activeWidgets round-trip is lossy when nodes are unresolvable

Amp-Thread-ID: https://ampcode.com/threads/T-019c73f9-0348-715e-9ef1-f6add8677e27
This commit is contained in:
bymyself
2026-02-19 20:37:27 -08:00
parent 3b5c9762a4
commit 3a4c76bf98

View File

@@ -125,6 +125,88 @@ describe('Subgraph proxyWidgets', () => {
subgraphNode.widgets[0].computedHeight = 10
expect(subgraphNode.widgets[0].value).toBe('value')
})
describe('proxyWidgets reordering', () => {
test('reordering proxyWidgets directly preserves all entries', () => {
const [subgraphNode, innerNodes] = setupSubgraph(2)
innerNodes[0].addWidget('text', 'widgetA', 'valueA', () => {})
innerNodes[1].addWidget('text', 'widgetB', 'valueB', () => {})
subgraphNode.properties.proxyWidgets = [
['1', 'widgetA'],
['2', 'widgetB']
]
expect(subgraphNode.widgets).toHaveLength(2)
const proxyWidgets = parseProxyWidgets(
subgraphNode.properties.proxyWidgets
)
const [first, second] = proxyWidgets
subgraphNode.properties.proxyWidgets = [second, first]
expect(subgraphNode.properties.proxyWidgets).toStrictEqual([
['2', 'widgetB'],
['1', 'widgetA']
])
expect(subgraphNode.widgets).toHaveLength(2)
})
test('reordering maintains correct widget references after swap', () => {
const [subgraphNode, innerNodes] = setupSubgraph(2)
innerNodes[0].addWidget('text', 'widgetA', 'valueA', () => {})
innerNodes[1].addWidget('text', 'widgetB', 'valueB', () => {})
subgraphNode.properties.proxyWidgets = [
['1', 'widgetA'],
['2', 'widgetB']
]
expect(subgraphNode.widgets[0].value).toBe('valueA')
expect(subgraphNode.widgets[1].value).toBe('valueB')
const proxyWidgets = parseProxyWidgets(
subgraphNode.properties.proxyWidgets
)
subgraphNode.properties.proxyWidgets = [proxyWidgets[1], proxyWidgets[0]]
expect(subgraphNode.widgets[0].value).toBe('valueB')
expect(subgraphNode.widgets[1].value).toBe('valueA')
})
test('activeWidgets round-trip drops unresolvable widgets', () => {
const [subgraphNode, innerNodes] = setupSubgraph(2)
innerNodes[0].addWidget('text', 'widgetA', 'valueA', () => {})
innerNodes[1].addWidget('text', 'widgetB', 'valueB', () => {})
subgraphNode.properties.proxyWidgets = [
['1', 'widgetA'],
['2', 'widgetB']
]
expect(subgraphNode.widgets).toHaveLength(2)
// Simulate the lossy activeWidgets getter: resolving [nodeId, widgetName]
// tuples by looking up nodes/widgets. If a node is missing, it returns [].
const subgraph = subgraphNode.subgraph
function mapWidgets([id, name]: [string, string]) {
const wNode = subgraph._nodes_by_id[id]
if (!wNode?.widgets) return []
const widget = wNode.widgets.find((w) => w.name === name)
if (!widget) return []
return [[wNode, widget]]
}
// Remove a node to make it unresolvable
subgraph.remove(innerNodes[0])
const proxyWidgets = parseProxyWidgets(
subgraphNode.properties.proxyWidgets
)
const resolved = proxyWidgets.flatMap(mapWidgets)
// The lossy round-trip drops the entry for the removed node
expect(resolved).toHaveLength(1)
expect(proxyWidgets).toHaveLength(2)
})
})
test('Prevents duplicate promotion', () => {
const [subgraphNode, innerNodes] = setupSubgraph(1)
innerNodes[0].addWidget('text', 'stringWidget', 'value', () => {})