Compare commits

..

1 Commits

Author SHA1 Message Date
CodeRabbit Fixer
69bc33eef5 fix: Add unit tests for resolveSubgraphInputLink (#9293)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 17:04:25 +01:00
2 changed files with 62 additions and 81 deletions

View File

@@ -121,6 +121,68 @@ describe('resolveSubgraphInputLink', () => {
expect(result).toBe('seed_input')
})
test('skips broken links where getLink returns undefined', () => {
const { subgraph, subgraphNode } = createSubgraphSetup('prompt')
addLinkedInteriorInput(subgraph, 'prompt', 'valid_input', 'valid')
const broken = addLinkedInteriorInput(
subgraph,
'prompt',
'broken_input',
'broken'
)
const originalGetLink = subgraph.getLink.bind(subgraph)
vi.spyOn(subgraph, 'getLink').mockImplementation((linkId) => {
if (typeof linkId !== 'number') return originalGetLink(linkId)
if (linkId === broken.linkId) return undefined
return originalGetLink(linkId)
})
const result = resolveSubgraphInputLink(
subgraphNode,
'prompt',
({ targetInput }) => targetInput.name
)
expect(result).toBe('valid_input')
})
test('returns result from latest connection when multiple links resolve', () => {
const { subgraph, subgraphNode } = createSubgraphSetup('prompt')
addLinkedInteriorInput(subgraph, 'prompt', 'older_input', 'older')
addLinkedInteriorInput(subgraph, 'prompt', 'newer_input', 'newer')
const result = resolveSubgraphInputLink(
subgraphNode,
'prompt',
({ targetInput }) => targetInput.name
)
expect(result).toBe('newer_input')
})
test('falls back to earlier link when latest resolve callback returns undefined', () => {
const { subgraph, subgraphNode } = createSubgraphSetup('prompt')
addLinkedInteriorInput(subgraph, 'prompt', 'fallback_input', 'fallback')
const newer = addLinkedInteriorInput(
subgraph,
'prompt',
'skipped_input',
'skipped'
)
const result = resolveSubgraphInputLink(
subgraphNode,
'prompt',
({ targetInput }) => {
if (targetInput.link === newer.linkId) return undefined
return targetInput.name
}
)
expect(result).toBe('fallback_input')
})
test('caches getTargetWidget result within the same callback evaluation', () => {
const { subgraph, subgraphNode } = createSubgraphSetup('model')
const linked = addLinkedInteriorInput(

View File

@@ -101,87 +101,6 @@ describe('PromotedWidgetViewManager', () => {
expect(views[1].key).toBe('1:widgetA:slotB')
})
test('getOrCreate returns distinct views for same widget with different viewKeys', () => {
const manager = new PromotedWidgetViewManager<{ key: string }>()
const viewA = manager.getOrCreate(
'1',
'widgetA',
() =>
makeView({
interiorNodeId: '1',
widgetName: 'widgetA',
viewKey: 'slotA'
}),
'slotA'
)
const viewB = manager.getOrCreate(
'1',
'widgetA',
() =>
makeView({
interiorNodeId: '1',
widgetName: 'widgetA',
viewKey: 'slotB'
}),
'slotB'
)
expect(viewA).not.toBe(viewB)
expect(viewA.key).toBe('1:widgetA:slotA')
expect(viewB.key).toBe('1:widgetA:slotB')
})
test('getOrCreate with viewKey returns cached view on subsequent calls', () => {
const manager = new PromotedWidgetViewManager<{ key: string }>()
const first = manager.getOrCreate(
'1',
'widgetA',
() =>
makeView({
interiorNodeId: '1',
widgetName: 'widgetA',
viewKey: 'slotA'
}),
'slotA'
)
const second = manager.getOrCreate(
'1',
'widgetA',
() =>
makeView({
interiorNodeId: '1',
widgetName: 'widgetA',
viewKey: 'slotA'
}),
'slotA'
)
expect(second).toBe(first)
})
test('getOrCreate with viewKey does not collide with keyless entry', () => {
const manager = new PromotedWidgetViewManager<{ key: string }>()
const keyless = manager.getOrCreate('1', 'widgetA', () =>
makeView({ interiorNodeId: '1', widgetName: 'widgetA' })
)
const keyed = manager.getOrCreate(
'1',
'widgetA',
() =>
makeView({
interiorNodeId: '1',
widgetName: 'widgetA',
viewKey: 'slotA'
}),
'slotA'
)
expect(keyed).not.toBe(keyless)
})
test('removeByViewKey removes only the targeted keyed view', () => {
const manager = new PromotedWidgetViewManager<{ key: string }>()