refactor: wire helpers into ComfyPage and update test usages

Phase 2 of ComfyPage refactor:

- Add ToastHelper, DragDropHelper, CommandHelper instances to ComfyPage

- Remove migrated methods from ComfyPage (command, toast, dragDrop, workflow, canvasOps, nodeOps methods)

- Update all test files to use new helper paths

- Keep visibleToasts as passthrough getter for backward compatibility

Amp-Thread-ID: https://ampcode.com/threads/T-019c1666-ed27-773c-976a-07cc805d7a6c
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Alexander Brown
2026-01-31 15:38:03 -08:00
parent be7f5b30b7
commit 4e00e8428f
26 changed files with 130 additions and 482 deletions

View File

@@ -1,11 +1,8 @@
import type { APIRequestContext, Locator, Page } from '@playwright/test'
import { test as base, expect } from '@playwright/test'
import dotenv from 'dotenv'
import { readFileSync } from 'fs'
import type { KeyCombo } from '../../src/platform/keybindings'
import { TestIds } from './selectors'
import type { useWorkspaceStore } from '../../src/stores/workspaceStore'
import { NodeBadgeMode } from '../../src/types/nodeSource'
import { ComfyActionbar } from '../helpers/actionbar'
import { ComfyTemplates } from '../helpers/templates'
@@ -19,22 +16,21 @@ import {
WorkflowsSidebarTab
} from './components/SidebarTab'
import { Topbar } from './components/Topbar'
import { DefaultGraphPositions } from './constants/defaultGraphPositions'
import { CanvasHelper } from './helpers/CanvasHelper'
import { ClipboardHelper } from './helpers/ClipboardHelper'
import { CommandHelper } from './helpers/CommandHelper'
import { DebugHelper } from './helpers/DebugHelper'
import { DragDropHelper } from './helpers/DragDropHelper'
import { KeyboardHelper } from './helpers/KeyboardHelper'
import { NodeOperationsHelper } from './helpers/NodeOperationsHelper'
import { SettingsHelper } from './helpers/SettingsHelper'
import { SubgraphHelper } from './helpers/SubgraphHelper'
import { ToastHelper } from './helpers/ToastHelper'
import { WorkflowHelper } from './helpers/WorkflowHelper'
import type { Position } from './types'
import type { NodeReference } from './utils/litegraphUtils'
dotenv.config()
type WorkspaceStore = ReturnType<typeof useWorkspaceStore>
class ComfyPropertiesPanel {
readonly root: Locator
readonly panelTitle: Locator
@@ -161,9 +157,6 @@ export class ComfyPage {
// Inputs
public readonly workflowUploadInput: Locator
// Toasts
public readonly visibleToasts: Locator
// Components
public readonly searchBox: ComfyNodeSearchBox
public readonly menu: ComfyMenu
@@ -181,6 +174,9 @@ export class ComfyPage {
public readonly clipboard: ClipboardHelper
public readonly workflow: WorkflowHelper
public readonly contextMenu: ContextMenu
public readonly toast: ToastHelper
public readonly dragDrop: DragDropHelper
public readonly command: CommandHelper
/** Worker index to test user ID */
public readonly userIds: string[] = []
@@ -207,7 +203,6 @@ export class ComfyPage {
.getByTestId('queue-button')
.getByRole('button', { name: 'Run' })
this.workflowUploadInput = page.locator('#comfy-file-input')
this.visibleToasts = page.locator('.p-toast-message:visible')
this.searchBox = new ComfyNodeSearchBox(page)
this.menu = new ComfyMenu(page)
@@ -225,6 +220,13 @@ export class ComfyPage {
this.clipboard = new ClipboardHelper(this.keyboard, this.canvas)
this.workflow = new WorkflowHelper(this)
this.contextMenu = new ContextMenu(page)
this.toast = new ToastHelper(page)
this.dragDrop = new DragDropHelper(page, this.assetPath.bind(this))
this.command = new CommandHelper(page)
}
get visibleToasts() {
return this.toast.visibleToasts
}
async setupUser(username: string) {
@@ -317,64 +319,6 @@ export class ComfyPage {
return `./browser_tests/assets/${fileName}`
}
async executeCommand(commandId: string) {
await this.page.evaluate((id: string) => {
return window['app'].extensionManager.command.execute(id)
}, commandId)
}
async registerCommand(
commandId: string,
command: (() => void) | (() => Promise<void>)
) {
await this.page.evaluate(
({ commandId, commandStr }) => {
const app = window['app']
const randomSuffix = Math.random().toString(36).substring(2, 8)
const extensionName = `TestExtension_${randomSuffix}`
app.registerExtension({
name: extensionName,
commands: [
{
id: commandId,
function: eval(commandStr)
}
]
})
},
{ commandId, commandStr: command.toString() }
)
}
async registerKeybinding(keyCombo: KeyCombo, command: () => void) {
await this.page.evaluate(
({ keyCombo, commandStr }) => {
const app = window['app']
const randomSuffix = Math.random().toString(36).substring(2, 8)
const extensionName = `TestExtension_${randomSuffix}`
const commandId = `TestCommand_${randomSuffix}`
app.registerExtension({
name: extensionName,
keybindings: [
{
combo: keyCombo,
commandId: commandId
}
],
commands: [
{
id: commandId,
function: eval(commandStr)
}
]
})
},
{ keyCombo, commandStr: command.toString() }
)
}
async goto() {
await this.page.goto(this.url)
}
@@ -415,236 +359,6 @@ export class ComfyPage {
})
}
async getToastErrorCount() {
return await this.page
.locator('.p-toast-message.p-toast-message-error')
.count()
}
async getVisibleToastCount() {
return await this.visibleToasts.count()
}
async closeToasts(requireCount = 0) {
if (requireCount) {
await this.visibleToasts
.nth(requireCount - 1)
.waitFor({ state: 'visible' })
}
// Clear all toasts
const toastCloseButtons = await this.page
.locator('.p-toast-close-button')
.all()
for (const button of toastCloseButtons) {
await button.click()
}
// Wait for toasts to disappear
await this.visibleToasts
.first()
.waitFor({ state: 'hidden', timeout: 1000 })
.catch(() => {})
}
async dragAndDropExternalResource(
options: {
fileName?: string
url?: string
dropPosition?: Position
waitForUpload?: boolean
} = {}
) {
const {
dropPosition = { x: 100, y: 100 },
fileName,
url,
waitForUpload = false
} = options
if (!fileName && !url)
throw new Error('Must provide either fileName or url')
const evaluateParams: {
dropPosition: Position
fileName?: string
fileType?: string
buffer?: Uint8Array | number[]
url?: string
} = { dropPosition }
// Dropping a file from the filesystem
if (fileName) {
const filePath = this.assetPath(fileName)
const buffer = readFileSync(filePath)
const getFileType = (fileName: string) => {
if (fileName.endsWith('.png')) return 'image/png'
if (fileName.endsWith('.svg')) return 'image/svg+xml'
if (fileName.endsWith('.webp')) return 'image/webp'
if (fileName.endsWith('.webm')) return 'video/webm'
if (fileName.endsWith('.json')) return 'application/json'
if (fileName.endsWith('.glb')) return 'model/gltf-binary'
if (fileName.endsWith('.avif')) return 'image/avif'
return 'application/octet-stream'
}
evaluateParams.fileName = fileName
evaluateParams.fileType = getFileType(fileName)
evaluateParams.buffer = [...new Uint8Array(buffer)]
}
// Dropping a URL (e.g., dropping image across browser tabs in Firefox)
if (url) evaluateParams.url = url
// Set up response waiter for file uploads before triggering the drop
const uploadResponsePromise = waitForUpload
? this.page.waitForResponse(
(resp) => resp.url().includes('/upload/') && resp.status() === 200,
{ timeout: 10000 }
)
: null
// Execute the drag and drop in the browser
await this.page.evaluate(async (params) => {
const dataTransfer = new DataTransfer()
// Add file if provided
if (params.buffer && params.fileName && params.fileType) {
const file = new File(
[new Uint8Array(params.buffer)],
params.fileName,
{
type: params.fileType
}
)
dataTransfer.items.add(file)
}
// Add URL data if provided
if (params.url) {
dataTransfer.setData('text/uri-list', params.url)
dataTransfer.setData('text/x-moz-url', params.url)
}
const targetElement = document.elementFromPoint(
params.dropPosition.x,
params.dropPosition.y
)
if (!targetElement) {
console.error('No element found at drop position:', params.dropPosition)
return { success: false, error: 'No element at position' }
}
const eventOptions = {
bubbles: true,
cancelable: true,
dataTransfer,
clientX: params.dropPosition.x,
clientY: params.dropPosition.y
}
const dragOverEvent = new DragEvent('dragover', eventOptions)
const dropEvent = new DragEvent('drop', eventOptions)
Object.defineProperty(dropEvent, 'preventDefault', {
value: () => {},
writable: false
})
Object.defineProperty(dropEvent, 'stopPropagation', {
value: () => {},
writable: false
})
targetElement.dispatchEvent(dragOverEvent)
targetElement.dispatchEvent(dropEvent)
return {
success: true,
targetInfo: {
tagName: targetElement.tagName,
id: targetElement.id,
classList: Array.from(targetElement.classList)
}
}
}, evaluateParams)
// Wait for file upload to complete
if (uploadResponsePromise) {
await uploadResponsePromise
}
await this.nextFrame()
}
async dragAndDropFile(
fileName: string,
options: { dropPosition?: Position; waitForUpload?: boolean } = {}
) {
return this.dragAndDropExternalResource({ fileName, ...options })
}
async dragAndDropURL(url: string, options: { dropPosition?: Position } = {}) {
return this.dragAndDropExternalResource({ url, ...options })
}
async dragNode2() {
await this.canvasOps.dragAndDrop(DefaultGraphPositions.textEncodeNode2, {
x: DefaultGraphPositions.textEncodeNode2.x,
y: 300
})
await this.nextFrame()
}
get promptDialogInput() {
return this.page.locator('.p-dialog-content input[type="text"]')
}
async fillPromptDialog(value: string) {
await this.promptDialogInput.fill(value)
await this.page.keyboard.press('Enter')
await this.promptDialogInput.waitFor({ state: 'hidden' })
await this.nextFrame()
}
async disconnectEdge() {
await this.canvasOps.dragAndDrop(
DefaultGraphPositions.clipTextEncodeNode1InputSlot,
DefaultGraphPositions.emptySpace
)
}
async connectEdge(
options: {
reverse?: boolean
} = {}
) {
const { reverse = false } = options
const start = reverse
? DefaultGraphPositions.clipTextEncodeNode1InputSlot
: DefaultGraphPositions.loadCheckpointNodeClipOutputSlot
const end = reverse
? DefaultGraphPositions.loadCheckpointNodeClipOutputSlot
: DefaultGraphPositions.clipTextEncodeNode1InputSlot
await this.canvasOps.dragAndDrop(start, end)
}
async adjustWidgetValue() {
// Adjust Empty Latent Image's width input.
const page = this.page
await page.locator('#graph-canvas').click({
position: DefaultGraphPositions.emptyLatentWidgetClick
})
const dialogInput = page.locator('.graphdialog input[type="text"]')
await dialogInput.click()
await dialogInput.fill('128')
await dialogInput.press('Enter')
await this.nextFrame()
}
async closeMenu() {
await this.page.click('button.comfy-close-menu-btn')
await this.nextFrame()
@@ -668,86 +382,12 @@ export class ComfyPage {
return await this.page.locator('.dom-widget').count()
}
async getUndoQueueSize() {
return this.page.evaluate(() => {
const workflow = (window['app'].extensionManager as WorkspaceStore)
.workflow.activeWorkflow
return workflow?.changeTracker.undoQueue.length
})
}
async getRedoQueueSize() {
return this.page.evaluate(() => {
const workflow = (window['app'].extensionManager as WorkspaceStore)
.workflow.activeWorkflow
return workflow?.changeTracker.redoQueue.length
})
}
async isCurrentWorkflowModified() {
return this.page.evaluate(() => {
return (window['app'].extensionManager as WorkspaceStore).workflow
.activeWorkflow?.isModified
})
}
async getExportedWorkflow({ api = false }: { api?: boolean } = {}) {
return this.page.evaluate(async (api) => {
return (await window['app'].graphToPrompt())[api ? 'output' : 'workflow']
}, api)
}
async setFocusMode(focusMode: boolean) {
await this.page.evaluate((focusMode) => {
window['app'].extensionManager.focusMode = focusMode
}, focusMode)
await this.nextFrame()
}
/**
* Get the position of a group by title.
* @param title The title of the group to find
* @returns The group's canvas position
* @throws Error if group not found
*/
async getGroupPosition(title: string): Promise<Position> {
const pos = await this.page.evaluate((title) => {
const groups = window['app'].graph.groups
const group = groups.find((g: { title: string }) => g.title === title)
if (!group) return null
return { x: group.pos[0], y: group.pos[1] }
}, title)
if (!pos) throw new Error(`Group "${title}" not found`)
return pos
}
/**
* Drag a group by its title.
* @param options.name The title of the group to drag
* @param options.deltaX Horizontal drag distance in screen pixels
* @param options.deltaY Vertical drag distance in screen pixels
*/
async dragGroup(options: {
name: string
deltaX: number
deltaY: number
}): Promise<void> {
const { name, deltaX, deltaY } = options
const screenPos = await this.page.evaluate((title) => {
const app = window['app']
const groups = app.graph.groups
const group = groups.find((g: { title: string }) => g.title === title)
if (!group) return null
// Position in the title area of the group
const clientPos = app.canvasPosToClientPos([
group.pos[0] + 50,
group.pos[1] + 15
])
return { x: clientPos[0], y: clientPos[1] }
}, name)
if (!screenPos) throw new Error(`Group "${name}" not found`)
await this.canvasOps.dragAndDrop(screenPos, {
x: screenPos.x + deltaX,
y: screenPos.y + deltaY
})
}
}
export const testComfySnapToGridGridSize = 50

View File

@@ -13,7 +13,7 @@ export class SettingDialog extends BaseDialog {
}
async open() {
await this.comfyPage.executeCommand('Comfy.ShowSettingsDialog')
await this.comfyPage.command.executeCommand('Comfy.ShowSettingsDialog')
await this.waitForVisible()
}

View File

@@ -137,7 +137,7 @@ export class NodeOperationsHelper {
await this.comfyPage.canvas.press('Control+a')
const node = await this.getFirstNodeRef()
await node!.clickContextMenuOption('Convert to Group Node')
await this.comfyPage.fillPromptDialog(groupNodeName)
await this.fillPromptDialog(groupNodeName)
await this.comfyPage.nextFrame()
}

View File

@@ -80,7 +80,7 @@ export class WorkflowHelper {
await this.comfyPage.confirmDialog.delete.click()
// Clear toast & close tab
await this.comfyPage.closeToasts(1)
await this.comfyPage.toast.closeToasts(1)
await workflowsTab.close()
}

View File

@@ -421,7 +421,7 @@ export class NodeReference {
}
async convertToGroupNode(groupNodeName: string = 'GroupNode') {
await this.clickContextMenuOption('Convert to Group Node')
await this.comfyPage.fillPromptDialog(groupNodeName)
await this.comfyPage.nodeOps.fillPromptDialog(groupNodeName)
await this.comfyPage.nextFrame()
const nodes = await this.comfyPage.nodeOps.getNodeRefsByType(
`workflow>${groupNodeName}`

View File

@@ -28,41 +28,41 @@ test.describe('Change Tracker', { tag: '@workflow' }, () => {
})
test('Can undo multiple operations', async ({ comfyPage }) => {
expect(await comfyPage.getUndoQueueSize()).toBe(0)
expect(await comfyPage.getRedoQueueSize()).toBe(0)
expect(await comfyPage.workflow.getUndoQueueSize()).toBe(0)
expect(await comfyPage.workflow.getRedoQueueSize()).toBe(0)
// Save, confirm no errors & workflow modified flag removed
await comfyPage.menu.topbar.saveWorkflow('undo-redo-test')
expect(await comfyPage.getToastErrorCount()).toBe(0)
expect(await comfyPage.isCurrentWorkflowModified()).toBe(false)
expect(await comfyPage.getUndoQueueSize()).toBe(0)
expect(await comfyPage.getRedoQueueSize()).toBe(0)
expect(await comfyPage.toast.getToastErrorCount()).toBe(0)
expect(await comfyPage.workflow.isCurrentWorkflowModified()).toBe(false)
expect(await comfyPage.workflow.getUndoQueueSize()).toBe(0)
expect(await comfyPage.workflow.getRedoQueueSize()).toBe(0)
const node = (await comfyPage.nodeOps.getFirstNodeRef())!
await node.click('title')
await node.click('collapse')
await expect(node).toBeCollapsed()
expect(await comfyPage.isCurrentWorkflowModified()).toBe(true)
expect(await comfyPage.getUndoQueueSize()).toBe(1)
expect(await comfyPage.getRedoQueueSize()).toBe(0)
expect(await comfyPage.workflow.isCurrentWorkflowModified()).toBe(true)
expect(await comfyPage.workflow.getUndoQueueSize()).toBe(1)
expect(await comfyPage.workflow.getRedoQueueSize()).toBe(0)
await comfyPage.keyboard.bypass()
await expect(node).toBeBypassed()
expect(await comfyPage.isCurrentWorkflowModified()).toBe(true)
expect(await comfyPage.getUndoQueueSize()).toBe(2)
expect(await comfyPage.getRedoQueueSize()).toBe(0)
expect(await comfyPage.workflow.isCurrentWorkflowModified()).toBe(true)
expect(await comfyPage.workflow.getUndoQueueSize()).toBe(2)
expect(await comfyPage.workflow.getRedoQueueSize()).toBe(0)
await comfyPage.keyboard.undo()
await expect(node).not.toBeBypassed()
expect(await comfyPage.isCurrentWorkflowModified()).toBe(true)
expect(await comfyPage.getUndoQueueSize()).toBe(1)
expect(await comfyPage.getRedoQueueSize()).toBe(1)
expect(await comfyPage.workflow.isCurrentWorkflowModified()).toBe(true)
expect(await comfyPage.workflow.getUndoQueueSize()).toBe(1)
expect(await comfyPage.workflow.getRedoQueueSize()).toBe(1)
await comfyPage.keyboard.undo()
await expect(node).not.toBeCollapsed()
expect(await comfyPage.isCurrentWorkflowModified()).toBe(false)
expect(await comfyPage.getUndoQueueSize()).toBe(0)
expect(await comfyPage.getRedoQueueSize()).toBe(2)
expect(await comfyPage.workflow.isCurrentWorkflowModified()).toBe(false)
expect(await comfyPage.workflow.getUndoQueueSize()).toBe(0)
expect(await comfyPage.workflow.getRedoQueueSize()).toBe(2)
})
})
@@ -157,7 +157,7 @@ test.describe('Change Tracker', { tag: '@workflow' }, () => {
})
test('Can detect changes in workflow.extra', async ({ comfyPage }) => {
expect(await comfyPage.getUndoQueueSize()).toBe(0)
expect(await comfyPage.workflow.getUndoQueueSize()).toBe(0)
await comfyPage.page.evaluate(() => {
window['app'].graph.extra.foo = 'bar'
})
@@ -165,12 +165,12 @@ test.describe('Change Tracker', { tag: '@workflow' }, () => {
await comfyPage.canvasOps.clickEmptySpace(
DefaultGraphPositions.emptySpaceClick
)
expect(await comfyPage.getUndoQueueSize()).toBe(1)
expect(await comfyPage.workflow.getUndoQueueSize()).toBe(1)
})
test('Ignores changes in workflow.ds', async ({ comfyPage }) => {
expect(await comfyPage.getUndoQueueSize()).toBe(0)
expect(await comfyPage.workflow.getUndoQueueSize()).toBe(0)
await comfyPage.canvasOps.pan({ x: 10, y: 10 })
expect(await comfyPage.getUndoQueueSize()).toBe(0)
expect(await comfyPage.workflow.getUndoQueueSize()).toBe(0)
})
})

View File

@@ -181,7 +181,7 @@ test.describe('Color Palette', { tag: ['@screenshot', '@settings'] }, () => {
await comfyPage.page.evaluate((p) => {
window['app'].extensionManager.colorPalette.addCustomColorPalette(p)
}, customColorPalettes.obsidian_dark)
expect(await comfyPage.getToastErrorCount()).toBe(0)
expect(await comfyPage.toast.getToastErrorCount()).toBe(0)
await comfyPage.settings.setSetting('Comfy.ColorPalette', 'obsidian_dark')
await comfyPage.nextFrame()

View File

@@ -8,16 +8,16 @@ test.beforeEach(async ({ comfyPage }) => {
test.describe('Keybindings', { tag: '@keyboard' }, () => {
test('Should execute command', async ({ comfyPage }) => {
await comfyPage.registerCommand('TestCommand', () => {
await comfyPage.command.registerCommand('TestCommand', () => {
window['foo'] = true
})
await comfyPage.executeCommand('TestCommand')
await comfyPage.command.executeCommand('TestCommand')
expect(await comfyPage.page.evaluate(() => window['foo'])).toBe(true)
})
test('Should execute async command', async ({ comfyPage }) => {
await comfyPage.registerCommand('TestCommand', async () => {
await comfyPage.command.registerCommand('TestCommand', async () => {
await new Promise<void>((resolve) =>
setTimeout(() => {
window['foo'] = true
@@ -26,21 +26,21 @@ test.describe('Keybindings', { tag: '@keyboard' }, () => {
)
})
await comfyPage.executeCommand('TestCommand')
await comfyPage.command.executeCommand('TestCommand')
expect(await comfyPage.page.evaluate(() => window['foo'])).toBe(true)
})
test('Should handle command errors', async ({ comfyPage }) => {
await comfyPage.registerCommand('TestCommand', () => {
await comfyPage.command.registerCommand('TestCommand', () => {
throw new Error('Test error')
})
await comfyPage.executeCommand('TestCommand')
expect(await comfyPage.getToastErrorCount()).toBe(1)
await comfyPage.command.executeCommand('TestCommand')
expect(await comfyPage.toast.getToastErrorCount()).toBe(1)
})
test('Should handle async command errors', async ({ comfyPage }) => {
await comfyPage.registerCommand('TestCommand', async () => {
await comfyPage.command.registerCommand('TestCommand', async () => {
await new Promise<void>((resolve, reject) =>
setTimeout(() => {
reject(new Error('Test error'))
@@ -48,7 +48,7 @@ test.describe('Keybindings', { tag: '@keyboard' }, () => {
)
})
await comfyPage.executeCommand('TestCommand')
expect(await comfyPage.getToastErrorCount()).toBe(1)
await comfyPage.command.executeCommand('TestCommand')
expect(await comfyPage.toast.getToastErrorCount()).toBe(1)
})
})

View File

@@ -34,7 +34,7 @@ test.describe('DOM Widget', { tag: '@widget' }, () => {
{ tag: '@screenshot' },
async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Top')
await comfyPage.executeCommand('Workspace.ToggleFocusMode')
await comfyPage.command.executeCommand('Workspace.ToggleFocusMode')
await comfyPage.nextFrame()
await expect(comfyPage.canvas).toHaveScreenshot('focus-mode-on.png')
}

View File

@@ -12,12 +12,12 @@ test.describe('Execution', { tag: ['@smoke', '@workflow'] }, () => {
'Report error on unconnected slot',
{ tag: '@screenshot' },
async ({ comfyPage }) => {
await comfyPage.disconnectEdge()
await comfyPage.canvasOps.disconnectEdge()
await comfyPage.canvasOps.clickEmptySpace(
DefaultGraphPositions.emptySpaceClick
)
await comfyPage.executeCommand('Comfy.QueuePrompt')
await comfyPage.command.executeCommand('Comfy.QueuePrompt')
await expect(comfyPage.page.locator('.comfy-error-report')).toBeVisible()
await comfyPage.page
.locator('.p-dialog')
@@ -48,7 +48,7 @@ test.describe(
await output1.click('title')
await comfyPage.executeCommand('Comfy.QueueSelectedOutputNodes')
await comfyPage.command.executeCommand('Comfy.QueueSelectedOutputNodes')
await expect(async () => {
expect(await (await input.getWidget(0)).getValue()).toBe('foo')
expect(await (await output1.getWidget(0)).getValue()).toBe('foo')

View File

@@ -37,7 +37,7 @@ test.describe('Topbar commands', () => {
test('Should not allow register command defined in other extension', async ({
comfyPage
}) => {
await comfyPage.registerCommand('foo', () => alert(1))
await comfyPage.command.registerCommand('foo', () => alert(1))
await comfyPage.page.evaluate(() => {
window['app'].registerExtension({
name: 'TestExtension1',
@@ -265,7 +265,7 @@ test.describe('Topbar commands', () => {
})
})
await comfyPage.fillPromptDialog('Hello, world!')
await comfyPage.nodeOps.fillPromptDialog('Hello, world!')
expect(await comfyPage.page.evaluate(() => window['value'])).toBe(
'Hello, world!'
)

View File

@@ -21,6 +21,6 @@ test.describe('Graph', { tag: ['@smoke', '@canvas'] }, () => {
test('Validate workflow links', async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.Validation.Workflows', true)
await comfyPage.workflow.loadWorkflow('links/bad_link')
await expect(comfyPage.getVisibleToastCount()).resolves.toBe(2)
await expect(comfyPage.toast.getVisibleToastCount()).resolves.toBe(2)
})
})

View File

@@ -279,7 +279,7 @@ test.describe('Group Node', { tag: '@node' }, () => {
await comfyPage.settings.setSetting('Comfy.ConfirmClear', false)
// Clear workflow
await comfyPage.executeCommand('Comfy.ClearWorkflow')
await comfyPage.command.executeCommand('Comfy.ClearWorkflow')
await comfyPage.clipboard.paste()
await verifyNodeLoaded(comfyPage, 1)
@@ -323,18 +323,18 @@ test.describe('Group Node', { tag: '@node' }, () => {
test.describe('Keybindings', () => {
test('Convert to group node, no selection', async ({ comfyPage }) => {
expect(await comfyPage.getVisibleToastCount()).toBe(0)
expect(await comfyPage.toast.getVisibleToastCount()).toBe(0)
await comfyPage.page.keyboard.press('Alt+g')
expect(await comfyPage.getVisibleToastCount()).toBe(1)
expect(await comfyPage.toast.getVisibleToastCount()).toBe(1)
})
test('Convert to group node, selected 1 node', async ({ comfyPage }) => {
expect(await comfyPage.getVisibleToastCount()).toBe(0)
expect(await comfyPage.toast.getVisibleToastCount()).toBe(0)
await comfyPage.canvas.click({
position: DefaultGraphPositions.textEncodeNode1
})
await comfyPage.nextFrame()
await comfyPage.page.keyboard.press('Alt+g')
expect(await comfyPage.getVisibleToastCount()).toBe(1)
expect(await comfyPage.toast.getVisibleToastCount()).toBe(1)
})
})
})

View File

@@ -127,7 +127,7 @@ test.describe('Node Interaction', () => {
}) => {
const originalPositions = await getPositions()
await dragSelectNodes(comfyPage, clipNodes)
await comfyPage.executeCommand(
await comfyPage.command.executeCommand(
`Comfy.Canvas.MoveSelectedNodes.${direction}`
)
await comfyPage.canvas.press(`Control+Arrow${direction}`)
@@ -166,7 +166,7 @@ test.describe('Node Interaction', () => {
})
test('Can drag node', { tag: '@screenshot' }, async ({ comfyPage }) => {
await comfyPage.dragNode2()
await comfyPage.nodeOps.dragTextEncodeNode2()
await expect(comfyPage.canvas).toHaveScreenshot('dragged-node1.png')
})
@@ -187,9 +187,9 @@ test.describe('Node Interaction', () => {
test(`Can disconnect/connect edge ${reverse ? 'reverse' : 'normal'}`, async ({
comfyPage
}) => {
await comfyPage.disconnectEdge()
await comfyPage.canvasOps.disconnectEdge()
await expect(comfyPage.canvas).toHaveScreenshot('disconnected-edge.png')
await comfyPage.connectEdge({ reverse })
await comfyPage.canvasOps.connectEdge({ reverse })
// Move mouse to empty area to avoid slot highlight.
await comfyPage.canvasOps.moveMouseToEmptyArea()
// Litegraph renders edge with a slight offset.
@@ -247,7 +247,7 @@ test.describe('Node Interaction', () => {
'Can adjust widget value',
{ tag: '@screenshot' },
async ({ comfyPage }) => {
await comfyPage.adjustWidgetValue()
await comfyPage.nodeOps.adjustEmptyLatentWidth()
await expect(comfyPage.canvas).toHaveScreenshot(
'adjusted-widget-value.png'
)
@@ -445,7 +445,7 @@ test.describe('Node Interaction', () => {
await comfyPage.workflow.loadWorkflow('groups/oversized_group')
await comfyPage.keyboard.selectAll()
await comfyPage.nextFrame()
await comfyPage.executeCommand('Comfy.Graph.FitGroupToContents')
await comfyPage.command.executeCommand('Comfy.Graph.FitGroupToContents')
await comfyPage.nextFrame()
await expect(comfyPage.canvas).toHaveScreenshot(
'group-fit-to-contents.png'
@@ -455,10 +455,14 @@ test.describe('Node Interaction', () => {
test('Can pin/unpin nodes', { tag: '@screenshot' }, async ({ comfyPage }) => {
await comfyPage.nodeOps.selectNodes(['CLIP Text Encode (Prompt)'])
await comfyPage.executeCommand('Comfy.Canvas.ToggleSelectedNodes.Pin')
await comfyPage.command.executeCommand(
'Comfy.Canvas.ToggleSelectedNodes.Pin'
)
await comfyPage.nextFrame()
await expect(comfyPage.canvas).toHaveScreenshot('nodes-pinned.png')
await comfyPage.executeCommand('Comfy.Canvas.ToggleSelectedNodes.Pin')
await comfyPage.command.executeCommand(
'Comfy.Canvas.ToggleSelectedNodes.Pin'
)
await comfyPage.nextFrame()
await expect(comfyPage.canvas).toHaveScreenshot('nodes-unpinned.png')
})
@@ -817,7 +821,7 @@ test.describe('Load duplicate workflow', () => {
}) => {
await comfyPage.workflow.loadWorkflow('nodes/single_ksampler')
await comfyPage.menu.workflowsTab.open()
await comfyPage.executeCommand('Comfy.NewBlankWorkflow')
await comfyPage.command.executeCommand('Comfy.NewBlankWorkflow')
await comfyPage.workflow.loadWorkflow('nodes/single_ksampler')
expect(await comfyPage.nodeOps.getGraphNodesCount()).toBe(1)
})

View File

@@ -10,7 +10,7 @@ test.describe('Keybindings', { tag: '@keyboard' }, () => {
test('Should not trigger non-modifier keybinding when typing in input fields', async ({
comfyPage
}) => {
await comfyPage.registerKeybinding({ key: 'k' }, () => {
await comfyPage.command.registerKeybinding({ key: 'k' }, () => {
window['TestCommand'] = true
})
@@ -26,7 +26,7 @@ test.describe('Keybindings', { tag: '@keyboard' }, () => {
test('Should not trigger modifier keybinding when typing in input fields', async ({
comfyPage
}) => {
await comfyPage.registerKeybinding({ key: 'k', ctrl: true }, () => {
await comfyPage.command.registerKeybinding({ key: 'k', ctrl: true }, () => {
window['TestCommand'] = true
})
@@ -43,7 +43,7 @@ test.describe('Keybindings', { tag: '@keyboard' }, () => {
test('Should not trigger keybinding reserved by text input when typing in input fields', async ({
comfyPage
}) => {
await comfyPage.registerKeybinding({ key: 'Ctrl+v' }, () => {
await comfyPage.command.registerKeybinding({ key: 'Ctrl+v' }, () => {
window['TestCommand'] = true
})

View File

@@ -17,7 +17,7 @@ function listenForEvent(): Promise<Event> {
test.describe('Canvas Event', { tag: '@canvas' }, () => {
test('Emit litegraph:canvas empty-release', async ({ comfyPage }) => {
const eventPromise = comfyPage.page.evaluate(listenForEvent)
const disconnectPromise = comfyPage.disconnectEdge()
const disconnectPromise = comfyPage.canvasOps.disconnectEdge()
const event = await eventPromise
await disconnectPromise

View File

@@ -32,7 +32,7 @@ test.describe(
test(`Load workflow in ${fileName} (drop from filesystem)`, async ({
comfyPage
}) => {
await comfyPage.dragAndDropFile(`workflowInMedia/${fileName}`)
await comfyPage.dragDrop.dragAndDropFile(`workflowInMedia/${fileName}`)
await expect(comfyPage.canvas).toHaveScreenshot(`${fileName}.png`)
})
})
@@ -44,7 +44,7 @@ test.describe(
test(`Load workflow from URL ${url} (drop from different browser tabs)`, async ({
comfyPage
}) => {
await comfyPage.dragAndDropURL(url)
await comfyPage.dragDrop.dragAndDropURL(url)
const readableName = url.split('/').pop()
await expect(comfyPage.canvas).toHaveScreenshot(
`dropped_workflow_url_${readableName}.png`

View File

@@ -175,7 +175,7 @@ test.describe('Menu', { tag: '@ui' }, () => {
})
})
await comfyPage.menu.topbar.triggerTopbarCommand(['ext', 'foo-command'])
expect(await comfyPage.getVisibleToastCount()).toBe(1)
expect(await comfyPage.toast.getVisibleToastCount()).toBe(1)
})
test('Can navigate Theme menu and switch between Dark and Light themes', async ({

View File

@@ -7,7 +7,7 @@ test.describe(
() => {
test('@mobile empty canvas', async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.ConfirmClear', false)
await comfyPage.executeCommand('Comfy.ClearWorkflow')
await comfyPage.command.executeCommand('Comfy.ClearWorkflow')
await expect(async () => {
expect(await comfyPage.nodeOps.getGraphNodesCount()).toBe(0)
}).toPass({ timeout: 5000 })

View File

@@ -33,7 +33,7 @@ test.describe('Node search box', { tag: '@node' }, () => {
})
test('Can trigger on link release', async ({ comfyPage }) => {
await comfyPage.disconnectEdge()
await comfyPage.canvasOps.disconnectEdge()
await expect(comfyPage.searchBox.input).toHaveCount(1)
})
@@ -47,7 +47,7 @@ test.describe('Node search box', { tag: '@node' }, () => {
await comfyPage.settings.setSetting('Comfy.NodeSearchBoxImpl', 'default')
// Don't set LinkRelease settings explicitly to test versioned defaults
await comfyPage.disconnectEdge()
await comfyPage.canvasOps.disconnectEdge()
await expect(comfyPage.searchBox.input).toHaveCount(1)
await expect(comfyPage.searchBox.input).toBeVisible()
})
@@ -60,7 +60,7 @@ test.describe('Node search box', { tag: '@node' }, () => {
})
test('Can auto link node', { tag: '@screenshot' }, async ({ comfyPage }) => {
await comfyPage.disconnectEdge()
await comfyPage.canvasOps.disconnectEdge()
// Select the second item as the first item is always reroute
await comfyPage.searchBox.fillAndSelectFirstNode('CLIPTextEncode', {
suggestionIndex: 0
@@ -100,7 +100,7 @@ test.describe('Node search box', { tag: '@node' }, () => {
'Link release connecting to node with no slots',
{ tag: '@screenshot' },
async ({ comfyPage }) => {
await comfyPage.disconnectEdge()
await comfyPage.canvasOps.disconnectEdge()
await expect(comfyPage.searchBox.input).toHaveCount(1)
await comfyPage.page.locator('.p-chip-remove-icon').click()
await comfyPage.searchBox.fillAndSelectFirstNode('KSampler')
@@ -280,7 +280,7 @@ test.describe('Release context menu', { tag: '@node' }, () => {
'Can trigger on link release',
{ tag: '@screenshot' },
async ({ comfyPage }) => {
await comfyPage.disconnectEdge()
await comfyPage.canvasOps.disconnectEdge()
const contextMenu = comfyPage.page.locator('.litecontextmenu')
// Wait for context menu with correct title (slot name | slot type)
// The title shows the output slot name and type from the disconnected link
@@ -299,7 +299,7 @@ test.describe('Release context menu', { tag: '@node' }, () => {
'Can search and add node from context menu',
{ tag: '@screenshot' },
async ({ comfyPage, comfyMouse }) => {
await comfyPage.disconnectEdge()
await comfyPage.canvasOps.disconnectEdge()
await comfyMouse.move({ x: 10, y: 10 })
await comfyPage.contextMenu.clickMenuItem('Search')
await comfyPage.nextFrame()
@@ -320,7 +320,7 @@ test.describe('Release context menu', { tag: '@node' }, () => {
await comfyPage.settings.setSetting('Comfy.NodeSearchBoxImpl', 'default')
// Don't set LinkRelease settings explicitly to test versioned defaults
await comfyPage.disconnectEdge()
await comfyPage.canvasOps.disconnectEdge()
// Context menu should appear, search box should not
await expect(comfyPage.searchBox.input).toHaveCount(0)
const contextMenu = comfyPage.page.locator('.litecontextmenu')
@@ -340,7 +340,7 @@ test.describe('Release context menu', { tag: '@node' }, () => {
)
await comfyPage.settings.setSetting('Comfy.NodeSearchBoxImpl', 'default')
await comfyPage.disconnectEdge()
await comfyPage.canvasOps.disconnectEdge()
// Context menu should appear due to explicit setting, not search box
await expect(comfyPage.searchBox.input).toHaveCount(0)
const contextMenu = comfyPage.page.locator('.litecontextmenu')

View File

@@ -42,9 +42,9 @@ test.describe(
'Convert to Group Node (Deprecated)'
)
await comfyPage.nextFrame()
await comfyPage.promptDialogInput.fill('GroupNode2CLIP')
await comfyPage.nodeOps.promptDialogInput.fill('GroupNode2CLIP')
await comfyPage.page.keyboard.press('Enter')
await comfyPage.promptDialogInput.waitFor({ state: 'hidden' })
await comfyPage.nodeOps.promptDialogInput.waitFor({ state: 'hidden' })
await comfyPage.nextFrame()
await expect(comfyPage.canvas).toHaveScreenshot(
'right-click-node-group-node.png'

View File

@@ -25,7 +25,7 @@ test.describe('Workflows sidebar', () => {
'*Unsaved Workflow.json'
])
await comfyPage.executeCommand('Comfy.NewBlankWorkflow')
await comfyPage.command.executeCommand('Comfy.NewBlankWorkflow')
expect(await tab.getOpenedWorkflowNames()).toEqual([
'*Unsaved Workflow.json',
'*Unsaved Workflow (2).json'
@@ -53,20 +53,20 @@ test.describe('Workflows sidebar', () => {
expect.arrayContaining(['workflow1.json'])
)
await comfyPage.executeCommand('Comfy.DuplicateWorkflow')
await comfyPage.command.executeCommand('Comfy.DuplicateWorkflow')
expect(await tab.getOpenedWorkflowNames()).toEqual([
'workflow1.json',
'*workflow1 (Copy).json'
])
await comfyPage.executeCommand('Comfy.DuplicateWorkflow')
await comfyPage.command.executeCommand('Comfy.DuplicateWorkflow')
expect(await tab.getOpenedWorkflowNames()).toEqual([
'workflow1.json',
'*workflow1 (Copy).json',
'*workflow1 (Copy) (2).json'
])
await comfyPage.executeCommand('Comfy.DuplicateWorkflow')
await comfyPage.command.executeCommand('Comfy.DuplicateWorkflow')
expect(await tab.getOpenedWorkflowNames()).toEqual([
'workflow1.json',
'*workflow1 (Copy).json',
@@ -82,7 +82,7 @@ test.describe('Workflows sidebar', () => {
const tab = comfyPage.menu.workflowsTab
await tab.open()
await comfyPage.executeCommand('Comfy.LoadDefaultWorkflow')
await comfyPage.command.executeCommand('Comfy.LoadDefaultWorkflow')
const originalNodeCount = (await comfyPage.nodeOps.getNodes()).length
await tab.insertWorkflow(tab.getPersistedItem('workflow1.json'))
@@ -121,7 +121,7 @@ test.describe('Workflows sidebar', () => {
})
test('Can save workflow as', async ({ comfyPage }) => {
await comfyPage.executeCommand('Comfy.NewBlankWorkflow')
await comfyPage.command.executeCommand('Comfy.NewBlankWorkflow')
await comfyPage.menu.topbar.saveWorkflowAs('workflow3.json')
expect(await comfyPage.menu.workflowsTab.getOpenedWorkflowNames()).toEqual([
'*Unsaved Workflow.json',
@@ -140,7 +140,7 @@ test.describe('Workflows sidebar', () => {
comfyPage
}) => {
await comfyPage.workflow.loadWorkflow('default')
const exportedWorkflow = await comfyPage.getExportedWorkflow({
const exportedWorkflow = await comfyPage.workflow.getExportedWorkflow({
api: false
})
expect(exportedWorkflow).toBeDefined()
@@ -170,14 +170,14 @@ test.describe('Workflows sidebar', () => {
expect(download.suggestedFilename()).toBe('exported_default.json')
// Get the exported workflow content
const downloadedContent = await comfyPage.getExportedWorkflow({
const downloadedContent = await comfyPage.workflow.getExportedWorkflow({
api: false
})
await comfyPage.settings.setSetting('Comfy.Locale', 'zh')
await comfyPage.setup()
const downloadedContentZh = await comfyPage.getExportedWorkflow({
const downloadedContentZh = await comfyPage.workflow.getExportedWorkflow({
api: false
})
@@ -204,7 +204,7 @@ test.describe('Workflows sidebar', () => {
test('Can save temporary workflow with unmodified name', async ({
comfyPage
}) => {
expect(await comfyPage.isCurrentWorkflowModified()).toBe(false)
expect(await comfyPage.workflow.isCurrentWorkflowModified()).toBe(false)
await comfyPage.menu.topbar.saveWorkflow('Unsaved Workflow')
// Should not trigger the overwrite dialog
@@ -212,7 +212,7 @@ test.describe('Workflows sidebar', () => {
await comfyPage.page.locator('.comfy-modal-content:visible').count()
).toBe(0)
expect(await comfyPage.isCurrentWorkflowModified()).toBe(false)
expect(await comfyPage.workflow.isCurrentWorkflowModified()).toBe(false)
})
test('Can overwrite other workflows with save as', async ({ comfyPage }) => {
@@ -252,7 +252,7 @@ test.describe('Workflows sidebar', () => {
// Load blank workflow
await comfyPage.menu.workflowsTab.open()
await comfyPage.executeCommand('Comfy.NewBlankWorkflow')
await comfyPage.command.executeCommand('Comfy.NewBlankWorkflow')
// Switch back to the missing_nodes workflow
await comfyPage.menu.workflowsTab.switchToWorkflow('missing_nodes')
@@ -280,7 +280,7 @@ test.describe('Workflows sidebar', () => {
test('Can close saved workflow with command', async ({ comfyPage }) => {
const tab = comfyPage.menu.workflowsTab
await comfyPage.menu.topbar.saveWorkflow('workflow1.json')
await comfyPage.executeCommand('Workspace.CloseWorkflow')
await comfyPage.command.executeCommand('Workspace.CloseWorkflow')
expect(await tab.getOpenedWorkflowNames()).toEqual([
'*Unsaved Workflow.json'
])

View File

@@ -75,13 +75,13 @@ test.describe('Templates', { tag: ['@slow', '@workflow'] }, () => {
test('Can load template workflows', async ({ comfyPage }) => {
// Clear the workflow
await comfyPage.menu.workflowsTab.open()
await comfyPage.executeCommand('Comfy.NewBlankWorkflow')
await comfyPage.command.executeCommand('Comfy.NewBlankWorkflow')
await expect(async () => {
expect(await comfyPage.nodeOps.getGraphNodesCount()).toBe(0)
}).toPass({ timeout: 250 })
// Load a template
await comfyPage.executeCommand('Comfy.BrowseTemplates')
await comfyPage.command.executeCommand('Comfy.BrowseTemplates')
await expect(comfyPage.templates.content).toBeVisible()
await comfyPage.page
@@ -112,7 +112,7 @@ test.describe('Templates', { tag: ['@slow', '@workflow'] }, () => {
test('Uses proper locale files for templates', async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.Locale', 'fr')
await comfyPage.executeCommand('Comfy.BrowseTemplates')
await comfyPage.command.executeCommand('Comfy.BrowseTemplates')
const dialog = comfyPage.page.getByRole('dialog').filter({
has: comfyPage.page.getByRole('heading', { name: 'Modèles', exact: true })
@@ -164,7 +164,7 @@ test.describe('Templates', { tag: ['@slow', '@workflow'] }, () => {
)
// Load the templates dialog
await comfyPage.executeCommand('Comfy.BrowseTemplates')
await comfyPage.command.executeCommand('Comfy.BrowseTemplates')
await expect(comfyPage.templates.content).toBeVisible()
// Verify German was requested first, then English as fallback
@@ -184,7 +184,7 @@ test.describe('Templates', { tag: ['@slow', '@workflow'] }, () => {
comfyPage
}) => {
// Open templates dialog
await comfyPage.executeCommand('Comfy.BrowseTemplates')
await comfyPage.command.executeCommand('Comfy.BrowseTemplates')
await comfyPage.templates.content.waitFor({ state: 'visible' })
const templateGrid = comfyPage.page.locator(
@@ -275,7 +275,7 @@ test.describe('Templates', { tag: ['@slow', '@workflow'] }, () => {
})
// Open templates dialog
await comfyPage.executeCommand('Comfy.BrowseTemplates')
await comfyPage.command.executeCommand('Comfy.BrowseTemplates')
await expect(comfyPage.templates.content).toBeVisible()
// Wait for cards to load

View File

@@ -26,7 +26,7 @@ test.describe('Vue Node Groups', { tag: '@screenshot' }, () => {
await comfyPage.setup()
await comfyPage.workflow.loadWorkflow('groups/oversized_group')
await comfyPage.keyboard.selectAll()
await comfyPage.executeCommand('Comfy.Graph.FitGroupToContents')
await comfyPage.command.executeCommand('Comfy.Graph.FitGroupToContents')
await comfyPage.nextFrame()
await expect(comfyPage.canvas).toHaveScreenshot(
'vue-groups-fit-to-contents.png'
@@ -39,15 +39,17 @@ test.describe('Vue Node Groups', { tag: '@screenshot' }, () => {
await comfyPage.workflow.loadWorkflow('groups/nested-groups-1-inner-node')
// Get initial positions with null guards
const outerInitial = await comfyPage.getGroupPosition('Outer Group')
const innerInitial = await comfyPage.getGroupPosition('Inner Group')
const outerInitial =
await comfyPage.canvasOps.getGroupPosition('Outer Group')
const innerInitial =
await comfyPage.canvasOps.getGroupPosition('Inner Group')
const initialOffsetX = innerInitial.x - outerInitial.x
const initialOffsetY = innerInitial.y - outerInitial.y
// Drag the outer group
const dragDelta = { x: 100, y: 80 }
await comfyPage.dragGroup({
await comfyPage.canvasOps.dragGroup({
name: 'Outer Group',
deltaX: dragDelta.x,
deltaY: dragDelta.y
@@ -55,8 +57,10 @@ test.describe('Vue Node Groups', { tag: '@screenshot' }, () => {
// Use retrying assertion to wait for positions to update
await expect(async () => {
const outerFinal = await comfyPage.getGroupPosition('Outer Group')
const innerFinal = await comfyPage.getGroupPosition('Inner Group')
const outerFinal =
await comfyPage.canvasOps.getGroupPosition('Outer Group')
const innerFinal =
await comfyPage.canvasOps.getGroupPosition('Inner Group')
const finalOffsetX = innerFinal.x - outerFinal.x
const finalOffsetY = innerFinal.y - outerFinal.y

View File

@@ -1049,9 +1049,9 @@ test.describe('Vue Node Link Interaction', { tag: '@screenshot' }, () => {
comfyMouse
}) => {
// Setup workflow with a KSampler node
await comfyPage.executeCommand('Comfy.NewBlankWorkflow')
await comfyPage.command.executeCommand('Comfy.NewBlankWorkflow')
await comfyPage.waitForGraphNodes(0)
await comfyPage.executeCommand('Workspace.SearchBox.Toggle')
await comfyPage.command.executeCommand('Workspace.SearchBox.Toggle')
await comfyPage.nextFrame()
await comfyPage.searchBox.fillAndSelectFirstNode('KSampler')
await comfyPage.waitForGraphNodes(1)
@@ -1061,7 +1061,7 @@ test.describe('Vue Node Link Interaction', { tag: '@screenshot' }, () => {
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
)?.[0]
await comfyPage.vueNodes.selectNode(String(ksamplerNode.id))
await comfyPage.executeCommand('Comfy.Graph.ConvertToSubgraph')
await comfyPage.command.executeCommand('Comfy.Graph.ConvertToSubgraph')
// Enter the subgraph
await comfyPage.vueNodes.enterSubgraph()

View File

@@ -192,7 +192,7 @@ test.describe('Image widget', { tag: ['@screenshot', '@widget'] }, () => {
const { x, y } = await loadImageNode.getPosition()
// Drag and drop image file onto the load image node
await comfyPage.dragAndDropFile('image32x32.webp', {
await comfyPage.dragDrop.dragAndDropFile('image32x32.webp', {
dropPosition: { x, y }
})
@@ -282,7 +282,7 @@ test.describe(
const { x, y } = await loadAnimatedWebpNode.getPosition()
// Drag and drop image file onto the load animated webp node
await comfyPage.dragAndDropFile('animated_webp.webp', {
await comfyPage.dragDrop.dragAndDropFile('animated_webp.webp', {
dropPosition: { x, y }
})
@@ -311,7 +311,7 @@ test.describe(
const { x, y } = await loadAnimatedWebpNode.getPosition()
// Drag and drop image file onto the load animated webp node
await comfyPage.dragAndDropFile('animated_webp.webp', {
await comfyPage.dragDrop.dragAndDropFile('animated_webp.webp', {
dropPosition: { x, y },
waitForUpload: true
})
@@ -333,7 +333,7 @@ test.describe(
const { x, y } = await loadAnimatedWebpNode.getPosition()
// Drag and drop image file onto the load animated webp node
await comfyPage.dragAndDropFile('animated_webp.webp', {
await comfyPage.dragDrop.dragAndDropFile('animated_webp.webp', {
dropPosition: { x, y }
})
await comfyPage.nextFrame()
@@ -383,6 +383,6 @@ test.describe('Unserialized widgets', { tag: '@widget' }, () => {
await comfyPage.page.mouse.click(10, 10)
// Expect the graph to not be modified
expect(await comfyPage.isCurrentWorkflowModified()).toBe(false)
expect(await comfyPage.workflow.isCurrentWorkflowModified()).toBe(false)
})
})