Files
ComfyUI_frontend/browser_tests/tests/browseModelAssets.spec.ts
pythongosssss e97cca9e4a feat: show node preview ghost when adding models from dialog & sidebar (#12765)
## Summary

Adds consistent ghost node behavior when clicking "use" on models from
either the model dialog or treeview - matching the Node Library & Node
Search.

## Changes

- **What**: 
- Split `createModelNodeFromAsset` into `resolveModelNodeFromAsset` and
`startModelNodeDragFromAsset` to allow sharing logic between the two
drag sources
- Move NodeDragPreview file & use from being node library tab specific
to app level in GraphCanvas so all drag sources share it
- drag listeners now attach on `startDrag` and detach on cancel instead
of living for the tab's lifetime
- Updated `LGraphNodePreview` to accept widgetValues and prepend combo
options with passed value so it shows in the preview as the default

## Review Focus
- refactored positioning to use RAF with useMouse and transform to fix
laggy-follow behavior present in Firefox

## Screenshots (if applicable)

Model dialog + Node library

https://github.com/user-attachments/assets/b227ac43-c6ea-4cf6-86ed-6cfb196fd80e

Model library sidebar

https://github.com/user-attachments/assets/bb546aee-5099-4df9-abe5-68bccd8fa2eb
2026-06-23 10:41:14 +00:00

62 lines
2.0 KiB
TypeScript

import { expect } from '@playwright/test'
import type { Asset } from '@comfyorg/ingest-types'
import { createCloudAssetsFixture } from '@e2e/fixtures/assetApiFixture'
import { STABLE_CHECKPOINT } from '@e2e/fixtures/data/assetFixtures'
const CLOUD_ASSETS: Asset[] = [STABLE_CHECKPOINT]
const test = createCloudAssetsFixture(CLOUD_ASSETS)
test.describe('Browse Model Assets - Use button', { tag: '@cloud' }, () => {
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.Assets.UseAssetAPI', true)
await comfyPage.nodeOps.clearGraph()
})
test.afterEach(async ({ comfyPage }) => {
await comfyPage.nodeOps.clearGraph()
})
test('Use button ghost-places a loader populated with the model', async ({
comfyPage
}) => {
await comfyPage.command.executeCommand('Comfy.BrowseModelAssets')
const modal = comfyPage.page.locator(
'[data-component-id="AssetBrowserModal"]'
)
await expect(modal).toBeVisible()
const card = comfyPage.page.locator(
`[data-component-id="AssetCard"][data-asset-id="${STABLE_CHECKPOINT.id}"]`
)
await expect(card).toBeVisible()
await card.getByRole('button', { name: 'Use' }).click()
// Dialog closes and the ghost is armed; the node is not placed until the
// user clicks the canvas.
await expect(modal).toBeHidden()
await expect
.poll(() => comfyPage.nodeOps.getGraphNodesCount(), { timeout: 1000 })
.toBe(0)
const canvasBox = (await comfyPage.canvas.boundingBox())!
await comfyPage.canvas.click({
position: { x: canvasBox.width / 2, y: canvasBox.height / 2 }
})
await expect.poll(() => comfyPage.nodeOps.getGraphNodesCount()).toBe(1)
await expect
.poll(() => comfyPage.nodeOps.getSelectedGraphNodesCount())
.toBe(1)
const [loader] = await comfyPage.nodeOps.getNodeRefsByType(
'CheckpointLoaderSimple'
)
expect(loader).toBeDefined()
const widget = await loader.getWidgetByName('ckpt_name')
expect(await widget.getValue()).toBe(STABLE_CHECKPOINT.name)
})
})