mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-05 07:30:11 +00:00
323 lines
10 KiB
TypeScript
323 lines
10 KiB
TypeScript
import { expect } from '@playwright/test'
|
|
|
|
import type { ComfyPage } from '../fixtures/ComfyPage'
|
|
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
|
|
|
|
test.describe('Dynamic Combo Widgets in Subgraphs', () => {
|
|
const TEST_NODE_TYPE = 'TestDynamicComboNode'
|
|
|
|
test.beforeEach(async ({ comfyPage }) => {
|
|
await comfyPage.setSetting('Comfy.UseNewMenu', 'Top')
|
|
await comfyPage.setSetting('Comfy.Workflow.WorkflowTabsPosition', 'Topbar')
|
|
await comfyPage.setSetting('Comfy.ConfirmClear', false)
|
|
})
|
|
|
|
function subgraphWidgetName(widgetName: string): string {
|
|
return `1: ${widgetName}`
|
|
}
|
|
|
|
function widget(name: string, visible: boolean, value: unknown) {
|
|
return {
|
|
name: subgraphWidgetName(name),
|
|
visible,
|
|
value
|
|
}
|
|
}
|
|
|
|
async function clearGraph(comfyPage: ComfyPage) {
|
|
await comfyPage.executeCommand('Comfy.ClearWorkflow')
|
|
await comfyPage.nextFrame()
|
|
}
|
|
|
|
async function getSubgraphNode(comfyPage: ComfyPage) {
|
|
const nodes = await comfyPage.getNodeRefsByTitle('New Subgraph')
|
|
return nodes[0]
|
|
}
|
|
|
|
async function createTestNodeAsSubgraph(
|
|
comfyPage: ComfyPage,
|
|
mode: 'none' | 'one' | 'two' | 'three' = 'none'
|
|
) {
|
|
const testNode = await comfyPage.createNode(TEST_NODE_TYPE)
|
|
|
|
if (mode !== 'none') {
|
|
const widget = await testNode.getWidgetByName('dynamic_combo')
|
|
if (widget) await widget.setValue(mode)
|
|
}
|
|
|
|
await testNode.click('title')
|
|
await comfyPage.nextFrame()
|
|
|
|
return await testNode.convertToSubgraph()
|
|
}
|
|
|
|
test('Promoted dynamic combo promotes all children with it', async ({
|
|
comfyPage
|
|
}) => {
|
|
await clearGraph(comfyPage)
|
|
|
|
const subgraphNode = await createTestNodeAsSubgraph(comfyPage, 'two')
|
|
|
|
await subgraphNode.click('title')
|
|
await comfyPage.nextFrame()
|
|
await comfyPage.menu.propertiesPanel.promoteWidget('dynamic_combo')
|
|
|
|
expect(await subgraphNode.getWidgets()).toEqual([
|
|
widget('dynamic_combo', true, 'two'),
|
|
widget('dynamic_combo.w1', true, 0),
|
|
widget('dynamic_combo.w2', true, 0)
|
|
])
|
|
})
|
|
|
|
test('Demoted dynamic combo unpromotes all children with it', async ({
|
|
comfyPage
|
|
}) => {
|
|
await clearGraph(comfyPage)
|
|
|
|
const subgraphNode = await createTestNodeAsSubgraph(comfyPage, 'two')
|
|
|
|
await subgraphNode.click('title')
|
|
await comfyPage.nextFrame()
|
|
await comfyPage.menu.propertiesPanel.promoteWidget('dynamic_combo')
|
|
|
|
expect(await subgraphNode.getWidgets()).toEqual([
|
|
widget('dynamic_combo', true, 'two'),
|
|
widget('dynamic_combo.w1', true, 0),
|
|
widget('dynamic_combo.w2', true, 0)
|
|
])
|
|
|
|
await comfyPage.menu.propertiesPanel.demoteWidget('dynamic_combo')
|
|
|
|
const widgets = await subgraphNode.getWidgets()
|
|
const visibleWidgets = widgets.filter((w) => w.visible)
|
|
expect(visibleWidgets).toEqual([])
|
|
})
|
|
|
|
test('Promoted combo widgets hide and show based on combo value', async ({
|
|
comfyPage
|
|
}) => {
|
|
await clearGraph(comfyPage)
|
|
|
|
const subgraphNode = await createTestNodeAsSubgraph(comfyPage, 'none')
|
|
|
|
await subgraphNode.click('title')
|
|
await comfyPage.nextFrame()
|
|
await comfyPage.menu.propertiesPanel.promoteWidget('dynamic_combo')
|
|
|
|
expect(await subgraphNode.getWidgets()).toEqual([
|
|
widget('dynamic_combo', true, 'none')
|
|
])
|
|
|
|
const comboWidget = await subgraphNode.getWidgetByName(
|
|
subgraphWidgetName('dynamic_combo')
|
|
)
|
|
|
|
await comboWidget!.setValue('one')
|
|
expect(await subgraphNode.getWidgets()).toEqual([
|
|
widget('dynamic_combo', true, 'one'),
|
|
widget('dynamic_combo.w1', true, 0)
|
|
])
|
|
|
|
await comboWidget!.setValue('two')
|
|
expect(await subgraphNode.getWidgets()).toEqual([
|
|
widget('dynamic_combo', true, 'two'),
|
|
widget('dynamic_combo.w1', true, 0),
|
|
widget('dynamic_combo.w2', true, 0)
|
|
])
|
|
|
|
await comboWidget!.setValue('three')
|
|
expect(await subgraphNode.getWidgets()).toEqual([
|
|
widget('dynamic_combo', true, 'three'),
|
|
widget('dynamic_combo.w1', true, 0),
|
|
widget('dynamic_combo.w2', true, 0),
|
|
widget('dynamic_combo.w3', true, 0)
|
|
])
|
|
|
|
await comboWidget!.setValue('two')
|
|
expect(await subgraphNode.getWidgets()).toEqual([
|
|
widget('dynamic_combo', true, 'two'),
|
|
widget('dynamic_combo.w1', true, 0),
|
|
widget('dynamic_combo.w2', true, 0),
|
|
widget('dynamic_combo.w3', false, undefined)
|
|
])
|
|
|
|
await comboWidget!.setValue('one')
|
|
expect(await subgraphNode.getWidgets()).toEqual([
|
|
widget('dynamic_combo', true, 'one'),
|
|
widget('dynamic_combo.w1', true, 0),
|
|
widget('dynamic_combo.w2', false, undefined),
|
|
widget('dynamic_combo.w3', false, undefined)
|
|
])
|
|
|
|
await comboWidget!.setValue('none')
|
|
expect(await subgraphNode.getWidgets()).toEqual([
|
|
widget('dynamic_combo', true, 'none'),
|
|
widget('dynamic_combo.w1', false, undefined),
|
|
widget('dynamic_combo.w2', false, undefined),
|
|
widget('dynamic_combo.w3', false, undefined)
|
|
])
|
|
})
|
|
|
|
test('Promoted combo maintains state after workflow reload', async ({
|
|
comfyPage
|
|
}) => {
|
|
await clearGraph(comfyPage)
|
|
|
|
const subgraphNode = await createTestNodeAsSubgraph(comfyPage, 'two')
|
|
|
|
await subgraphNode.click('title')
|
|
await comfyPage.nextFrame()
|
|
|
|
await comfyPage.menu.propertiesPanel.promoteWidget('dynamic_combo')
|
|
|
|
const w1 = await subgraphNode.getWidgetByName(
|
|
subgraphWidgetName('dynamic_combo.w1')
|
|
)
|
|
const w2 = await subgraphNode.getWidgetByName(
|
|
subgraphWidgetName('dynamic_combo.w2')
|
|
)
|
|
await w1!.setValue(123)
|
|
await w2!.setValue(456)
|
|
|
|
expect(await subgraphNode.getWidgets()).toEqual([
|
|
widget('dynamic_combo', true, 'two'),
|
|
widget('dynamic_combo.w1', true, 123),
|
|
widget('dynamic_combo.w2', true, 456)
|
|
])
|
|
|
|
// Click on node to ensure changes are committed before switching
|
|
await subgraphNode.click('title')
|
|
await comfyPage.nextFrame()
|
|
|
|
await comfyPage.executeCommand('Comfy.NewBlankWorkflow')
|
|
await comfyPage.nextFrame()
|
|
await comfyPage.menu.topbar.switchToTab(0)
|
|
await comfyPage.nextFrame()
|
|
|
|
const reloadedSubgraph = await getSubgraphNode(comfyPage)
|
|
expect(await reloadedSubgraph.getWidgets()).toEqual([
|
|
widget('dynamic_combo', true, 'two'),
|
|
widget('dynamic_combo.w1', true, 123),
|
|
widget('dynamic_combo.w2', true, 456)
|
|
])
|
|
})
|
|
|
|
test('Hidden children remain hidden after workflow reload when combo is none', async ({
|
|
comfyPage
|
|
}) => {
|
|
await clearGraph(comfyPage)
|
|
|
|
const subgraphNode = await createTestNodeAsSubgraph(comfyPage, 'two')
|
|
|
|
await subgraphNode.click('title')
|
|
await comfyPage.nextFrame()
|
|
await comfyPage.menu.propertiesPanel.promoteWidget('dynamic_combo')
|
|
|
|
const comboWidget = await subgraphNode.getWidgetByName(
|
|
subgraphWidgetName('dynamic_combo')
|
|
)
|
|
await comboWidget!.setValue('none')
|
|
|
|
expect(await subgraphNode.getWidgets()).toEqual([
|
|
widget('dynamic_combo', true, 'none'),
|
|
widget('dynamic_combo.w1', false, undefined),
|
|
widget('dynamic_combo.w2', false, undefined)
|
|
])
|
|
|
|
// Click on node to ensure changes are committed before switching
|
|
await subgraphNode.click('title')
|
|
await comfyPage.nextFrame()
|
|
|
|
await comfyPage.executeCommand('Comfy.NewBlankWorkflow')
|
|
await comfyPage.nextFrame()
|
|
await comfyPage.menu.topbar.switchToTab(0)
|
|
await comfyPage.nextFrame()
|
|
|
|
const reloadedSubgraph = await getSubgraphNode(comfyPage)
|
|
expect(await reloadedSubgraph.getWidgets()).toEqual([
|
|
widget('dynamic_combo', true, 'none'),
|
|
widget('dynamic_combo.w1', false, undefined),
|
|
widget('dynamic_combo.w2', false, undefined)
|
|
])
|
|
})
|
|
|
|
test('Children appear when combo changes after workflow reload', async ({
|
|
comfyPage
|
|
}) => {
|
|
await clearGraph(comfyPage)
|
|
|
|
const subgraphNode = await createTestNodeAsSubgraph(comfyPage, 'none')
|
|
|
|
await subgraphNode.click('title')
|
|
await comfyPage.nextFrame()
|
|
await comfyPage.menu.propertiesPanel.promoteWidget('dynamic_combo')
|
|
|
|
expect(await subgraphNode.getWidgets()).toEqual([
|
|
widget('dynamic_combo', true, 'none')
|
|
])
|
|
|
|
await comfyPage.executeCommand('Comfy.NewBlankWorkflow')
|
|
await comfyPage.nextFrame()
|
|
await comfyPage.menu.topbar.switchToTab(0)
|
|
await comfyPage.nextFrame()
|
|
|
|
const reloadedSubgraph = await getSubgraphNode(comfyPage)
|
|
const comboWidget = await reloadedSubgraph.getWidgetByName(
|
|
subgraphWidgetName('dynamic_combo')
|
|
)
|
|
await comboWidget!.setValue('two')
|
|
await comfyPage.page.waitForTimeout(500)
|
|
|
|
expect(await reloadedSubgraph.getWidgets()).toEqual([
|
|
widget('dynamic_combo', true, 'two'),
|
|
widget('dynamic_combo.w1', true, 0),
|
|
widget('dynamic_combo.w2', true, 0)
|
|
])
|
|
})
|
|
|
|
test('Dynamic combo children created inside subgraph are auto-promoted', async ({
|
|
comfyPage
|
|
}) => {
|
|
await clearGraph(comfyPage)
|
|
|
|
const testNode = await comfyPage.createNode(TEST_NODE_TYPE)
|
|
await testNode.click('title')
|
|
await comfyPage.nextFrame()
|
|
|
|
const subgraphNode = await testNode.convertToSubgraph()
|
|
await comfyPage.page.waitForTimeout(500)
|
|
|
|
await subgraphNode.click('title')
|
|
await comfyPage.nextFrame()
|
|
await comfyPage.menu.propertiesPanel.promoteWidget('dynamic_combo')
|
|
|
|
expect(await subgraphNode.getWidgets()).toEqual([
|
|
widget('dynamic_combo', true, 'none')
|
|
])
|
|
|
|
await subgraphNode.click('subgraph')
|
|
await expect
|
|
.poll(() => comfyPage.isInSubgraph(), { timeout: 5000 })
|
|
.toBe(true)
|
|
|
|
const innerNodes = await comfyPage.getNodeRefsByType(TEST_NODE_TYPE, true)
|
|
const innerNode = innerNodes[0]
|
|
const innerComboWidget = await innerNode.getWidgetByName(
|
|
'dynamic_combo',
|
|
true
|
|
)
|
|
await innerComboWidget!.setValue('two', true)
|
|
|
|
await comfyPage.page.keyboard.press('Escape')
|
|
await comfyPage.nextFrame()
|
|
expect(await comfyPage.isInSubgraph()).toBe(false)
|
|
|
|
const outerSubgraph = await getSubgraphNode(comfyPage)
|
|
expect(await outerSubgraph.getWidgets()).toEqual([
|
|
widget('dynamic_combo', true, 'two'),
|
|
widget('dynamic_combo.w1', true, 0),
|
|
widget('dynamic_combo.w2', true, 0)
|
|
])
|
|
})
|
|
})
|