mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-20 06:20:11 +00:00
## Summary Fix connection links rendering at wrong positions when nodes are collapsed in Vue nodes mode. ## Changes - **What**: Fall back to `clientPosToCanvasPos` for collapsed node slot positioning since DOM-relative scale derivation is invalid when layout store preserves expanded size. Clear stale `cachedOffset` on collapse and defer sync when canvas is not yet initialized. - 3 unit tests for collapsed node slot sync fallback (clientPosToCanvasPos, cachedOffset clearing, canvas-not-initialized deferral) - 3 E2E tests for collapsed node link positions (within bounds, after position change, after expand recovery) ## Review Focus - `clientPosToCanvasPos` fallback is safe for collapsed nodes because collapse is user-initiated (no loading-time transform desync risk that #9121 originally fixed) - `cachedOffset` clearing prevents stale expanded-state offsets during collapsed node drag - Regression from #9121 (DOM-relative scale) combined with #9680 (collapsed node ResizeObserver skip) ## Screenshots Before <img width="1030" height="434" alt="image" src="https://github.com/user-attachments/assets/2f8b8a1f-ed22-4588-ab62-72b89880e53f" /> After <img width="1029" height="476" alt="image" src="https://github.com/user-attachments/assets/52dbbf7c-61ed-465b-ae19-a9781513e7e8" /> ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-10641-fix-collapsed-node-connection-link-positions-3316d73d365081f4aee3fecb92c83b91) by [Unito](https://www.unito.io) --------- Co-authored-by: Alexander Brown <drjkl@comfy.org> Co-authored-by: Alexander Brown <DrJKL0424@gmail.com>
69 lines
2.1 KiB
TypeScript
69 lines
2.1 KiB
TypeScript
import { expect } from '@playwright/test'
|
|
|
|
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
|
|
import { assertNodeSlotsWithinBounds } from '../fixtures/utils/slotBoundsUtil'
|
|
|
|
const NODE_ID = '3'
|
|
const NODE_TITLE = 'KSampler'
|
|
|
|
test.describe(
|
|
'Collapsed node link positions',
|
|
{ tag: ['@canvas', '@node'] },
|
|
() => {
|
|
test.beforeEach(async ({ comfyPage }) => {
|
|
await comfyPage.settings.setSetting('Comfy.VueNodes.Enabled', true)
|
|
await comfyPage.workflow.loadWorkflow('default')
|
|
await comfyPage.vueNodes.waitForNodes()
|
|
})
|
|
|
|
test.afterEach(async ({ comfyPage }) => {
|
|
await comfyPage.canvasOps.resetView()
|
|
})
|
|
|
|
test('link endpoints stay within collapsed node bounds', async ({
|
|
comfyPage
|
|
}) => {
|
|
const node = await comfyPage.vueNodes.getFixtureByTitle(NODE_TITLE)
|
|
await node.toggleCollapse()
|
|
await comfyPage.nextFrame()
|
|
|
|
await assertNodeSlotsWithinBounds(comfyPage.page, NODE_ID)
|
|
})
|
|
|
|
test('links follow collapsed node after drag', async ({ comfyPage }) => {
|
|
const node = await comfyPage.vueNodes.getFixtureByTitle(NODE_TITLE)
|
|
await node.toggleCollapse()
|
|
await comfyPage.nextFrame()
|
|
|
|
const box = await node.boundingBox()
|
|
expect(box).not.toBeNull()
|
|
await comfyPage.page.mouse.move(
|
|
box!.x + box!.width / 2,
|
|
box!.y + box!.height / 2
|
|
)
|
|
await comfyPage.page.mouse.down()
|
|
await comfyPage.page.mouse.move(
|
|
box!.x + box!.width / 2 + 200,
|
|
box!.y + box!.height / 2 + 100,
|
|
{ steps: 10 }
|
|
)
|
|
await comfyPage.page.mouse.up()
|
|
await comfyPage.nextFrame()
|
|
|
|
await assertNodeSlotsWithinBounds(comfyPage.page, NODE_ID)
|
|
})
|
|
|
|
test('links recover correct positions after expand', async ({
|
|
comfyPage
|
|
}) => {
|
|
const node = await comfyPage.vueNodes.getFixtureByTitle(NODE_TITLE)
|
|
await node.toggleCollapse()
|
|
await comfyPage.nextFrame()
|
|
await node.toggleCollapse()
|
|
await comfyPage.nextFrame()
|
|
|
|
await assertNodeSlotsWithinBounds(comfyPage.page, NODE_ID)
|
|
})
|
|
}
|
|
)
|