refactor(browser_tests): remove deprecated proxy methods from ComfyPage

Migrate all test callers to use helper classes directly:

- nodeOps: getGraphNodesCount, getNodeRefById, selectNodes, etc.

- canvasOps: dragAndDrop, zoom, pan, resetView, etc.

- subgraph: rightClickInputSlot, connectToOutput, etc.

Reduces ComfyPage.ts from 1335 to 1085 lines (-250 lines).

Amp-Thread-ID: https://ampcode.com/threads/T-019c1318-58b7-757f-801c-5b676f0d3421
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Alexander Brown
2026-01-31 00:52:33 -08:00
parent 2c7dad3088
commit 681709f8e7
40 changed files with 404 additions and 533 deletions

View File

@@ -3,8 +3,6 @@ import { test as base, expect } from '@playwright/test'
import dotenv from 'dotenv' import dotenv from 'dotenv'
import * as fs from 'fs' import * as fs from 'fs'
import type { LGraphNode } from '../../src/lib/litegraph/src/litegraph'
import type { NodeId } from '../../src/platform/workflow/validation/schemas/workflowSchema'
import type { KeyCombo } from '../../src/platform/keybindings' import type { KeyCombo } from '../../src/platform/keybindings'
import type { useWorkspaceStore } from '../../src/stores/workspaceStore' import type { useWorkspaceStore } from '../../src/stores/workspaceStore'
import { NodeBadgeMode } from '../../src/types/nodeSource' import { NodeBadgeMode } from '../../src/types/nodeSource'
@@ -24,9 +22,10 @@ import { CanvasHelper } from './helpers/CanvasHelper'
import { DebugHelper } from './helpers/DebugHelper' import { DebugHelper } from './helpers/DebugHelper'
import { NodeOperationsHelper } from './helpers/NodeOperationsHelper' import { NodeOperationsHelper } from './helpers/NodeOperationsHelper'
import { SubgraphHelper } from './helpers/SubgraphHelper' import { SubgraphHelper } from './helpers/SubgraphHelper'
import type { Position, Size } from './types' import type { Position } from './types'
import type { SubgraphSlotReference } from './utils/litegraphUtils' import type {
import type { NodeReference } from './utils/litegraphUtils' NodeReference
} from './utils/litegraphUtils'
dotenv.config() dotenv.config()
@@ -233,16 +232,6 @@ export class ComfyPage {
return result return result
} }
/** @deprecated Use this.nodeOps.getGraphNodesCount() instead */
async getGraphNodesCount(): Promise<number> {
return this.nodeOps.getGraphNodesCount()
}
/** @deprecated Use this.nodeOps.getSelectedGraphNodesCount() instead */
async getSelectedGraphNodesCount(): Promise<number> {
return this.nodeOps.getSelectedGraphNodesCount()
}
async setupWorkflowsDirectory(structure: FolderStructure) { async setupWorkflowsDirectory(structure: FolderStructure) {
const resp = await this.request.post( const resp = await this.request.post(
`${this.url}/api/devtools/setup_folder_structure`, `${this.url}/api/devtools/setup_folder_structure`,
@@ -502,11 +491,6 @@ export class ComfyPage {
}) })
} }
/** @deprecated Use this.canvasOps.resetView() instead */
async resetView() {
return this.canvasOps.resetView()
}
async getToastErrorCount() { async getToastErrorCount() {
return await this.page return await this.page
.locator('.p-toast-message.p-toast-message-error') .locator('.p-toast-message.p-toast-message-error')
@@ -564,11 +548,6 @@ export class ComfyPage {
return this.canvasOps.clickEmptySpace(DefaultGraphPositions.emptySpaceClick) return this.canvasOps.clickEmptySpace(DefaultGraphPositions.emptySpaceClick)
} }
/** @deprecated Use this.canvasOps.dragAndDrop() instead */
async dragAndDrop(source: Position, target: Position) {
return this.canvasOps.dragAndDrop(source, target)
}
async dragAndDropExternalResource( async dragAndDropExternalResource(
options: { options: {
fileName?: string fileName?: string
@@ -713,7 +692,7 @@ export class ComfyPage {
} }
async dragNode2() { async dragNode2() {
await this.dragAndDrop({ x: 622, y: 400 }, { x: 622, y: 300 }) await this.canvasOps.dragAndDrop({ x: 622, y: 400 }, { x: 622, y: 300 })
await this.nextFrame() await this.nextFrame()
} }
@@ -751,7 +730,10 @@ export class ComfyPage {
} }
async disconnectEdge() { async disconnectEdge() {
await this.dragAndDrop(this.clipTextEncodeNode1InputSlot, this.emptySpace) await this.canvasOps.dragAndDrop(
this.clipTextEncodeNode1InputSlot,
this.emptySpace
)
} }
async connectEdge( async connectEdge(
@@ -767,7 +749,7 @@ export class ComfyPage {
? this.loadCheckpointNodeClipOutputSlot ? this.loadCheckpointNodeClipOutputSlot
: this.clipTextEncodeNode1InputSlot : this.clipTextEncodeNode1InputSlot
await this.dragAndDrop(start, end) await this.canvasOps.dragAndDrop(start, end)
} }
async adjustWidgetValue() { async adjustWidgetValue() {
@@ -783,26 +765,6 @@ export class ComfyPage {
await this.nextFrame() await this.nextFrame()
} }
/** @deprecated Use this.canvasOps.zoom() instead */
async zoom(deltaY: number, steps: number = 1) {
return this.canvasOps.zoom(deltaY, steps)
}
/** @deprecated Use this.canvasOps.pan() instead */
async pan(offset: Position, safeSpot?: Position) {
return this.canvasOps.pan(offset, safeSpot)
}
/** @deprecated Use this.canvasOps.panWithTouch() instead */
async panWithTouch(offset: Position, safeSpot?: Position) {
return this.canvasOps.panWithTouch(offset, safeSpot)
}
/** @deprecated Use this.canvasOps.rightClick() instead */
async rightClickCanvas(x: number = 10, y: number = 10) {
return this.canvasOps.rightClick(x, y)
}
async clickContextMenuItem(name: string): Promise<void> { async clickContextMenuItem(name: string): Promise<void> {
await this.page.getByRole('menuitem', { name }).click() await this.page.getByRole('menuitem', { name }).click()
await this.nextFrame() await this.nextFrame()
@@ -817,143 +779,6 @@ export class ComfyPage {
await this.nextFrame() await this.nextFrame()
} }
/** @deprecated Use this.subgraph.rightClickInputSlot() instead */
async rightClickSubgraphInputSlot(inputName?: string): Promise<void> {
return this.subgraph.rightClickInputSlot(inputName)
}
/** @deprecated Use this.subgraph.rightClickOutputSlot() instead */
async rightClickSubgraphOutputSlot(outputName?: string): Promise<void> {
return this.subgraph.rightClickOutputSlot(outputName)
}
/** @deprecated Use this.subgraph.doubleClickInputSlot() instead */
async doubleClickSubgraphInputSlot(inputName?: string): Promise<void> {
return this.subgraph.doubleClickInputSlot(inputName)
}
/** @deprecated Use this.subgraph.doubleClickOutputSlot() instead */
async doubleClickSubgraphOutputSlot(outputName?: string): Promise<void> {
return this.subgraph.doubleClickOutputSlot(outputName)
}
/** @deprecated Use this.subgraph.getInputSlot() instead */
async getSubgraphInputSlot(
slotName?: string
): Promise<SubgraphSlotReference> {
return this.subgraph.getInputSlot(slotName)
}
/** @deprecated Use this.subgraph.getOutputSlot() instead */
async getSubgraphOutputSlot(
slotName?: string
): Promise<SubgraphSlotReference> {
return this.subgraph.getOutputSlot(slotName)
}
/** @deprecated Use this.subgraph.connectToInput() instead */
async connectToSubgraphInput(
sourceNode: NodeReference,
sourceSlotIndex: number,
targetInputName?: string
): Promise<void> {
return this.subgraph.connectToInput(
sourceNode,
sourceSlotIndex,
targetInputName
)
}
/** @deprecated Use this.subgraph.connectFromInput() instead */
async connectFromSubgraphInput(
targetNode: NodeReference,
targetSlotIndex: number,
sourceInputName?: string
): Promise<void> {
return this.subgraph.connectFromInput(
targetNode,
targetSlotIndex,
sourceInputName
)
}
/** @deprecated Use this.subgraph.connectToOutput() instead */
async connectToSubgraphOutput(
sourceNode: NodeReference,
sourceSlotIndex: number,
targetOutputName?: string
): Promise<void> {
return this.subgraph.connectToOutput(
sourceNode,
sourceSlotIndex,
targetOutputName
)
}
/** @deprecated Use this.subgraph.connectFromOutput() instead */
async connectFromSubgraphOutput(
targetNode: NodeReference,
targetSlotIndex: number,
sourceOutputName?: string
): Promise<void> {
return this.subgraph.connectFromOutput(
targetNode,
targetSlotIndex,
sourceOutputName
)
}
/** @deprecated Use this.debug.addMarker() instead */
async debugAddMarker(
position: Position,
id: string = 'debug-marker'
): Promise<void> {
return this.debug.addMarker(position, id)
}
/** @deprecated Use this.debug.removeMarkers() instead */
async debugRemoveMarkers(): Promise<void> {
return this.debug.removeMarkers()
}
/** @deprecated Use this.debug.attachScreenshot() instead */
async debugAttachScreenshot(
testInfo: any,
name: string,
options?: {
fullPage?: boolean
element?: 'canvas' | 'page'
markers?: Array<{ position: Position; id?: string }>
}
): Promise<void> {
return this.debug.attachScreenshot(testInfo, name, options)
}
/** @deprecated Use this.canvasOps.doubleClick() instead */
async doubleClickCanvas() {
return this.canvasOps.doubleClick()
}
/** @deprecated Use this.debug.saveCanvasScreenshot() instead */
async debugSaveCanvasScreenshot(filename: string): Promise<void> {
return this.debug.saveCanvasScreenshot(filename)
}
/** @deprecated Use this.debug.getCanvasDataURL() instead */
async debugGetCanvasDataURL(): Promise<string> {
return this.debug.getCanvasDataURL()
}
/** @deprecated Use this.debug.showCanvasOverlay() instead */
async debugShowCanvasOverlay(): Promise<void> {
return this.debug.showCanvasOverlay()
}
/** @deprecated Use this.debug.hideCanvasOverlay() instead */
async debugHideCanvasOverlay(): Promise<void> {
return this.debug.hideCanvasOverlay()
}
async clickEmptyLatentNode() { async clickEmptyLatentNode() {
await this.canvas.click({ await this.canvas.click({
position: { position: {
@@ -977,16 +802,6 @@ export class ComfyPage {
await this.nextFrame() await this.nextFrame()
} }
/** @deprecated Use this.nodeOps.selectNodes() instead */
async selectNodes(nodeTitles: string[]) {
return this.nodeOps.selectNodes(nodeTitles)
}
/** @deprecated Use this.nodeOps.select2Nodes() instead */
async select2Nodes() {
return this.nodeOps.select2Nodes()
}
async ctrlSend(keyToPress: string, locator: Locator | null = this.canvas) { async ctrlSend(keyToPress: string, locator: Locator | null = this.canvas) {
const target = locator ?? this.page.keyboard const target = locator ?? this.page.keyboard
await target.press(`Control+${keyToPress}`) await target.press(`Control+${keyToPress}`)
@@ -1035,29 +850,12 @@ export class ComfyPage {
await this.page.locator('.p-dialog').waitFor({ state: 'hidden' }) await this.page.locator('.p-dialog').waitFor({ state: 'hidden' })
} }
/** @deprecated Use this.nodeOps.resizeNode() instead */
async resizeNode(
nodePos: Position,
nodeSize: Size,
ratioX: number,
ratioY: number,
revertAfter: boolean = false
) {
return this.nodeOps.resizeNode(
nodePos,
nodeSize,
ratioX,
ratioY,
revertAfter
)
}
async resizeKsamplerNode( async resizeKsamplerNode(
percentX: number, percentX: number,
percentY: number, percentY: number,
revertAfter: boolean = false revertAfter: boolean = false
) { ) {
return this.resizeNode( return this.nodeOps.resizeNode(
DefaultGraphPositions.ksampler.pos, DefaultGraphPositions.ksampler.pos,
DefaultGraphPositions.ksampler.size, DefaultGraphPositions.ksampler.size,
percentX, percentX,
@@ -1071,7 +869,7 @@ export class ComfyPage {
percentY: number, percentY: number,
revertAfter: boolean = false revertAfter: boolean = false
) { ) {
return this.resizeNode( return this.nodeOps.resizeNode(
DefaultGraphPositions.loadCheckpoint.pos, DefaultGraphPositions.loadCheckpoint.pos,
DefaultGraphPositions.loadCheckpoint.size, DefaultGraphPositions.loadCheckpoint.size,
percentX, percentX,
@@ -1085,7 +883,7 @@ export class ComfyPage {
percentY: number, percentY: number,
revertAfter: boolean = false revertAfter: boolean = false
) { ) {
return this.resizeNode( return this.nodeOps.resizeNode(
DefaultGraphPositions.emptyLatent.pos, DefaultGraphPositions.emptyLatent.pos,
DefaultGraphPositions.emptyLatent.size, DefaultGraphPositions.emptyLatent.size,
percentX, percentX,
@@ -1107,57 +905,11 @@ export class ComfyPage {
await modal.waitFor({ state: 'hidden' }) await modal.waitFor({ state: 'hidden' })
} }
/** @deprecated Use this.nodeOps.convertAllNodesToGroupNode() instead */
async convertAllNodesToGroupNode(groupNodeName: string) {
return this.nodeOps.convertAllNodesToGroupNode(groupNodeName)
}
/** @deprecated Use this.canvasOps.convertOffsetToCanvas() instead */
async convertOffsetToCanvas(pos: [number, number]) {
return this.canvasOps.convertOffsetToCanvas(pos)
}
/** Get number of DOM widgets on the canvas. */ /** Get number of DOM widgets on the canvas. */
async getDOMWidgetCount() { async getDOMWidgetCount() {
return await this.page.locator('.dom-widget').count() return await this.page.locator('.dom-widget').count()
} }
/** @deprecated Use this.nodeOps.getNodeRefById() instead */
async getNodeRefById(id: NodeId) {
return this.nodeOps.getNodeRefById(id)
}
/** @deprecated Use this.nodeOps.getNodes() instead */
async getNodes(): Promise<LGraphNode[]> {
return this.nodeOps.getNodes()
}
/** @deprecated Use this.nodeOps.waitForGraphNodes() instead */
async waitForGraphNodes(count: number) {
return this.nodeOps.waitForGraphNodes(count)
}
/** @deprecated Use this.nodeOps.getNodeRefsByType() instead */
async getNodeRefsByType(
type: string,
includeSubgraph: boolean = false
): Promise<NodeReference[]> {
return this.nodeOps.getNodeRefsByType(type, includeSubgraph)
}
/** @deprecated Use this.nodeOps.getNodeRefsByTitle() instead */
async getNodeRefsByTitle(title: string): Promise<NodeReference[]> {
return this.nodeOps.getNodeRefsByTitle(title)
}
/** @deprecated Use this.nodeOps.getFirstNodeRef() instead */
async getFirstNodeRef(): Promise<NodeReference | null> {
return this.nodeOps.getFirstNodeRef()
}
/** @deprecated Use this.canvasOps.moveMouseToEmptyArea() instead */
async moveMouseToEmptyArea() {
return this.canvasOps.moveMouseToEmptyArea()
}
async getUndoQueueSize() { async getUndoQueueSize() {
return this.page.evaluate(() => { return this.page.evaluate(() => {
const workflow = (window['app'].extensionManager as WorkspaceStore) const workflow = (window['app'].extensionManager as WorkspaceStore)
@@ -1233,7 +985,7 @@ export class ComfyPage {
}, name) }, name)
if (!screenPos) throw new Error(`Group "${name}" not found`) if (!screenPos) throw new Error(`Group "${name}" not found`)
await this.dragAndDrop(screenPos, { await this.canvasOps.dragAndDrop(screenPos, {
x: screenPos.x + deltaX, x: screenPos.x + deltaX,
y: screenPos.y + deltaY y: screenPos.y + deltaY
}) })

View File

@@ -280,7 +280,7 @@ export class NodeReference {
return this.getProperty('type') return this.getProperty('type')
} }
async getPosition(): Promise<Position> { async getPosition(): Promise<Position> {
const pos = await this.comfyPage.convertOffsetToCanvas( const pos = await this.comfyPage.canvasOps.convertOffsetToCanvas(
await this.getProperty<[number, number]>('pos') await this.getProperty<[number, number]>('pos')
) )
return { return {
@@ -370,7 +370,7 @@ export class NodeReference {
}) })
await this.comfyPage.nextFrame() await this.comfyPage.nextFrame()
if (moveMouseToEmptyArea) { if (moveMouseToEmptyArea) {
await this.comfyPage.moveMouseToEmptyArea() await this.comfyPage.canvasOps.moveMouseToEmptyArea()
} }
} }
async copy() { async copy() {
@@ -418,7 +418,7 @@ export class NodeReference {
await this.clickContextMenuOption('Convert to Group Node') await this.clickContextMenuOption('Convert to Group Node')
await this.comfyPage.fillPromptDialog(groupNodeName) await this.comfyPage.fillPromptDialog(groupNodeName)
await this.comfyPage.nextFrame() await this.comfyPage.nextFrame()
const nodes = await this.comfyPage.getNodeRefsByType( const nodes = await this.comfyPage.nodeOps.getNodeRefsByType(
`workflow>${groupNodeName}` `workflow>${groupNodeName}`
) )
if (nodes.length !== 1) { if (nodes.length !== 1) {
@@ -429,7 +429,8 @@ export class NodeReference {
async convertToSubgraph() { async convertToSubgraph() {
await this.clickContextMenuOption('Convert to Subgraph') await this.clickContextMenuOption('Convert to Subgraph')
await this.comfyPage.nextFrame() await this.comfyPage.nextFrame()
const nodes = await this.comfyPage.getNodeRefsByTitle('New Subgraph') const nodes =
await this.comfyPage.nodeOps.getNodeRefsByTitle('New Subgraph')
if (nodes.length !== 1) { if (nodes.length !== 1) {
throw new Error( throw new Error(
`Did not find single subgraph node (found=${nodes.length})` `Did not find single subgraph node (found=${nodes.length})`

View File

@@ -37,7 +37,7 @@ test.describe('Change Tracker', { tag: '@workflow' }, () => {
expect(await comfyPage.getUndoQueueSize()).toBe(0) expect(await comfyPage.getUndoQueueSize()).toBe(0)
expect(await comfyPage.getRedoQueueSize()).toBe(0) expect(await comfyPage.getRedoQueueSize()).toBe(0)
const node = (await comfyPage.getFirstNodeRef())! const node = (await comfyPage.nodeOps.getFirstNodeRef())!
await node.click('title') await node.click('title')
await node.click('collapse') await node.click('collapse')
await expect(node).toBeCollapsed() await expect(node).toBeCollapsed()
@@ -68,7 +68,7 @@ test.describe('Change Tracker', { tag: '@workflow' }, () => {
test('Can group multiple change actions into a single transaction', async ({ test('Can group multiple change actions into a single transaction', async ({
comfyPage comfyPage
}) => { }) => {
const node = (await comfyPage.getFirstNodeRef())! const node = (await comfyPage.nodeOps.getFirstNodeRef())!
expect(node).toBeTruthy() expect(node).toBeTruthy()
await expect(node).not.toBeCollapsed() await expect(node).not.toBeCollapsed()
await expect(node).not.toBeBypassed() await expect(node).not.toBeBypassed()
@@ -113,7 +113,7 @@ test.describe('Change Tracker', { tag: '@workflow' }, () => {
test('Can nest multiple change transactions without adding undo steps', async ({ test('Can nest multiple change transactions without adding undo steps', async ({
comfyPage comfyPage
}) => { }) => {
const node = (await comfyPage.getFirstNodeRef())! const node = (await comfyPage.nodeOps.getFirstNodeRef())!
const bypassAndPin = async () => { const bypassAndPin = async () => {
await beforeChange(comfyPage) await beforeChange(comfyPage)
await comfyPage.ctrlB() await comfyPage.ctrlB()
@@ -165,7 +165,7 @@ test.describe('Change Tracker', { tag: '@workflow' }, () => {
test('Ignores changes in workflow.ds', async ({ comfyPage }) => { test('Ignores changes in workflow.ds', async ({ comfyPage }) => {
expect(await comfyPage.getUndoQueueSize()).toBe(0) expect(await comfyPage.getUndoQueueSize()).toBe(0)
await comfyPage.pan({ x: 10, y: 10 }) await comfyPage.canvasOps.pan({ x: 10, y: 10 })
expect(await comfyPage.getUndoQueueSize()).toBe(0) expect(await comfyPage.getUndoQueueSize()).toBe(0)
}) })
}) })

View File

@@ -273,7 +273,7 @@ test.describe(
test.beforeEach(async ({ comfyPage }) => { test.beforeEach(async ({ comfyPage }) => {
await comfyPage.setSetting('Comfy.ColorPalette', 'light') await comfyPage.setSetting('Comfy.ColorPalette', 'light')
await comfyPage.setSetting('Comfy.Node.Opacity', 0.3) await comfyPage.setSetting('Comfy.Node.Opacity', 0.3)
const node = await comfyPage.getFirstNodeRef() const node = await comfyPage.nodeOps.getFirstNodeRef()
await node?.clickContextMenuOption('Colors') await node?.clickContextMenuOption('Colors')
}) })

View File

@@ -103,7 +103,7 @@ test.describe('Copy Paste', { tag: ['@screenshot', '@workflow'] }, () => {
test('Can undo paste multiple nodes as single action', async ({ test('Can undo paste multiple nodes as single action', async ({
comfyPage comfyPage
}) => { }) => {
const initialCount = await comfyPage.getGraphNodesCount() const initialCount = await comfyPage.nodeOps.getGraphNodesCount()
expect(initialCount).toBeGreaterThan(1) expect(initialCount).toBeGreaterThan(1)
await comfyPage.canvas.click() await comfyPage.canvas.click()
await comfyPage.ctrlA() await comfyPage.ctrlA()
@@ -111,11 +111,11 @@ test.describe('Copy Paste', { tag: ['@screenshot', '@workflow'] }, () => {
await comfyPage.ctrlC() await comfyPage.ctrlC()
await comfyPage.ctrlV() await comfyPage.ctrlV()
const pasteCount = await comfyPage.getGraphNodesCount() const pasteCount = await comfyPage.nodeOps.getGraphNodesCount()
expect(pasteCount).toBe(initialCount * 2) expect(pasteCount).toBe(initialCount * 2)
await comfyPage.ctrlZ() await comfyPage.ctrlZ()
const undoCount = await comfyPage.getGraphNodesCount() const undoCount = await comfyPage.nodeOps.getGraphNodesCount()
expect(undoCount).toBe(initialCount) expect(undoCount).toBe(initialCount)
}) })
}) })

View File

@@ -45,7 +45,7 @@ test('Does not report warning on undo/redo', async ({ comfyPage }) => {
await comfyPage.nextFrame() await comfyPage.nextFrame()
// Make a change to the graph // Make a change to the graph
await comfyPage.doubleClickCanvas() await comfyPage.canvasOps.doubleClick()
await comfyPage.searchBox.fillAndSelectFirstNode('KSampler') await comfyPage.searchBox.fillAndSelectFirstNode('KSampler')
// Undo and redo the change // Undo and redo the change
@@ -362,7 +362,7 @@ test.describe('Signin dialog', () => {
test('Paste content to signin dialog should not paste node on canvas', async ({ test('Paste content to signin dialog should not paste node on canvas', async ({
comfyPage comfyPage
}) => { }) => {
const nodeNum = (await comfyPage.getNodes()).length const nodeNum = (await comfyPage.nodeOps.getNodes()).length
await comfyPage.clickEmptyLatentNode() await comfyPage.clickEmptyLatentNode()
await comfyPage.ctrlC() await comfyPage.ctrlC()
@@ -381,6 +381,6 @@ test.describe('Signin dialog', () => {
await input.press('Control+v') await input.press('Control+v')
await expect(input).toHaveValue('test_password') await expect(input).toHaveValue('test_password')
expect(await comfyPage.getNodes()).toHaveLength(nodeNum) expect(await comfyPage.nodeOps.getNodes()).toHaveLength(nodeNum)
}) })
}) })

View File

@@ -21,7 +21,7 @@ test.describe('DOM Widget', { tag: '@widget' }, () => {
await expect(firstMultiline).toBeVisible() await expect(firstMultiline).toBeVisible()
await expect(lastMultiline).toBeVisible() await expect(lastMultiline).toBeVisible()
const nodes = await comfyPage.getNodeRefsByType('CLIPTextEncode') const nodes = await comfyPage.nodeOps.getNodeRefsByType('CLIPTextEncode')
for (const node of nodes) { for (const node of nodes) {
await node.click('collapse') await node.click('collapse')
} }

View File

@@ -33,9 +33,9 @@ test.describe(
() => { () => {
test('Execute to selected output nodes', async ({ comfyPage }) => { test('Execute to selected output nodes', async ({ comfyPage }) => {
await comfyPage.loadWorkflow('execution/partial_execution') await comfyPage.loadWorkflow('execution/partial_execution')
const input = await comfyPage.getNodeRefById(3) const input = await comfyPage.nodeOps.getNodeRefById(3)
const output1 = await comfyPage.getNodeRefById(1) const output1 = await comfyPage.nodeOps.getNodeRefById(1)
const output2 = await comfyPage.getNodeRefById(4) const output2 = await comfyPage.nodeOps.getNodeRefById(4)
expect(await (await input.getWidget(0)).getValue()).toBe('foo') expect(await (await input.getWidget(0)).getValue()).toBe('foo')
expect(await (await output1.getWidget(0)).getValue()).toBe('') expect(await (await output1.getWidget(0)).getValue()).toBe('')
expect(await (await output2.getWidget(0)).getValue()).toBe('') expect(await (await output2.getWidget(0)).getValue()).toBe('')

View File

@@ -325,7 +325,7 @@ test.describe('Topbar commands', () => {
}) })
}) })
await comfyPage.selectNodes(['CLIP Text Encode (Prompt)']) await comfyPage.nodeOps.selectNodes(['CLIP Text Encode (Prompt)'])
// Click the command button in the selection toolbox // Click the command button in the selection toolbox
const toolboxButton = comfyPage.page.locator( const toolboxButton = comfyPage.page.locator(

View File

@@ -18,7 +18,7 @@ test.describe('Group Node', { tag: '@node' }, () => {
test.beforeEach(async ({ comfyPage }) => { test.beforeEach(async ({ comfyPage }) => {
await comfyPage.setSetting('Comfy.UseNewMenu', 'Top') await comfyPage.setSetting('Comfy.UseNewMenu', 'Top')
libraryTab = comfyPage.menu.nodeLibraryTab libraryTab = comfyPage.menu.nodeLibraryTab
await comfyPage.convertAllNodesToGroupNode(groupNodeName) await comfyPage.nodeOps.convertAllNodesToGroupNode(groupNodeName)
await libraryTab.open() await libraryTab.open()
}) })
@@ -29,14 +29,16 @@ test.describe('Group Node', { tag: '@node' }, () => {
test('Can be added to canvas using node library sidebar', async ({ test('Can be added to canvas using node library sidebar', async ({
comfyPage comfyPage
}) => { }) => {
const initialNodeCount = await comfyPage.getGraphNodesCount() const initialNodeCount = await comfyPage.nodeOps.getGraphNodesCount()
// Add group node from node library sidebar // Add group node from node library sidebar
await libraryTab.getFolder(groupNodeCategory).click() await libraryTab.getFolder(groupNodeCategory).click()
await libraryTab.getNode(groupNodeName).click() await libraryTab.getNode(groupNodeName).click()
// Verify the node is added to the canvas // Verify the node is added to the canvas
expect(await comfyPage.getGraphNodesCount()).toBe(initialNodeCount + 1) expect(await comfyPage.nodeOps.getGraphNodesCount()).toBe(
initialNodeCount + 1
)
}) })
test('Can be bookmarked and unbookmarked', async ({ comfyPage }) => { test('Can be bookmarked and unbookmarked', async ({ comfyPage }) => {
@@ -94,8 +96,8 @@ test.describe('Group Node', { tag: '@node' }, () => {
{ tag: '@screenshot' }, { tag: '@screenshot' },
async ({ comfyPage }) => { async ({ comfyPage }) => {
const groupNodeName = 'DefautWorkflowGroupNode' const groupNodeName = 'DefautWorkflowGroupNode'
await comfyPage.convertAllNodesToGroupNode(groupNodeName) await comfyPage.nodeOps.convertAllNodesToGroupNode(groupNodeName)
await comfyPage.doubleClickCanvas() await comfyPage.canvasOps.doubleClick()
await comfyPage.nextFrame() await comfyPage.nextFrame()
await comfyPage.searchBox.fillAndSelectFirstNode(groupNodeName) await comfyPage.searchBox.fillAndSelectFirstNode(groupNodeName)
await expect(comfyPage.canvas).toHaveScreenshot( await expect(comfyPage.canvas).toHaveScreenshot(
@@ -106,7 +108,7 @@ test.describe('Group Node', { tag: '@node' }, () => {
test('Displays tooltip on title hover', async ({ comfyPage }) => { test('Displays tooltip on title hover', async ({ comfyPage }) => {
await comfyPage.setSetting('Comfy.EnableTooltips', true) await comfyPage.setSetting('Comfy.EnableTooltips', true)
await comfyPage.convertAllNodesToGroupNode('Group Node') await comfyPage.nodeOps.convertAllNodesToGroupNode('Group Node')
await comfyPage.page.mouse.move(47, 173) await comfyPage.page.mouse.move(47, 173)
await expect(comfyPage.page.locator('.node-tooltip')).toBeVisible() await expect(comfyPage.page.locator('.node-tooltip')).toBeVisible()
}) })
@@ -115,8 +117,8 @@ test.describe('Group Node', { tag: '@node' }, () => {
comfyPage comfyPage
}) => { }) => {
const makeGroup = async (name, type1, type2) => { const makeGroup = async (name, type1, type2) => {
const node1 = (await comfyPage.getNodeRefsByType(type1))[0] const node1 = (await comfyPage.nodeOps.getNodeRefsByType(type1))[0]
const node2 = (await comfyPage.getNodeRefsByType(type2))[0] const node2 = (await comfyPage.nodeOps.getNodeRefsByType(type2))[0]
await node1.click('title') await node1.click('title')
await node2.click('title', { await node2.click('title', {
modifiers: ['Shift'] modifiers: ['Shift']
@@ -178,7 +180,7 @@ test.describe('Group Node', { tag: '@node' }, () => {
comfyPage comfyPage
}) => { }) => {
const expectSingleNode = async (type: string) => { const expectSingleNode = async (type: string) => {
const nodes = await comfyPage.getNodeRefsByType(type) const nodes = await comfyPage.nodeOps.getNodeRefsByType(type)
expect(nodes).toHaveLength(1) expect(nodes).toHaveLength(1)
return nodes[0] return nodes[0]
} }
@@ -214,7 +216,7 @@ test.describe('Group Node', { tag: '@node' }, () => {
comfyPage comfyPage
}) => { }) => {
await comfyPage.loadWorkflow('groupnodes/legacy_group_node') await comfyPage.loadWorkflow('groupnodes/legacy_group_node')
expect(await comfyPage.getGraphNodesCount()).toBe(1) expect(await comfyPage.nodeOps.getGraphNodesCount()).toBe(1)
await expect( await expect(
comfyPage.page.locator('.comfy-missing-nodes') comfyPage.page.locator('.comfy-missing-nodes')
).not.toBeVisible() ).not.toBeVisible()
@@ -246,9 +248,9 @@ test.describe('Group Node', { tag: '@node' }, () => {
comfyPage: ComfyPage, comfyPage: ComfyPage,
expectedCount: number expectedCount: number
) => { ) => {
expect(await comfyPage.getNodeRefsByType(GROUP_NODE_TYPE)).toHaveLength( expect(
expectedCount await comfyPage.nodeOps.getNodeRefsByType(GROUP_NODE_TYPE)
) ).toHaveLength(expectedCount)
expect(await isRegisteredLitegraph(comfyPage)).toBe(true) expect(await isRegisteredLitegraph(comfyPage)).toBe(true)
expect(await isRegisteredNodeDefStore(comfyPage)).toBe(true) expect(await isRegisteredNodeDefStore(comfyPage)).toBe(true)
} }
@@ -256,7 +258,7 @@ test.describe('Group Node', { tag: '@node' }, () => {
test.beforeEach(async ({ comfyPage }) => { test.beforeEach(async ({ comfyPage }) => {
await comfyPage.setSetting('Comfy.UseNewMenu', 'Top') await comfyPage.setSetting('Comfy.UseNewMenu', 'Top')
await comfyPage.loadWorkflow(WORKFLOW_NAME) await comfyPage.loadWorkflow(WORKFLOW_NAME)
groupNode = await comfyPage.getFirstNodeRef() groupNode = await comfyPage.nodeOps.getFirstNodeRef()
if (!groupNode) if (!groupNode)
throw new Error(`Group node not found in workflow ${WORKFLOW_NAME}`) throw new Error(`Group node not found in workflow ${WORKFLOW_NAME}`)
await groupNode.copy() await groupNode.copy()

View File

@@ -51,11 +51,13 @@ test.describe('Node Interaction', () => {
test(`Can add multiple nodes to selection using ${modifier}+Click`, async ({ test(`Can add multiple nodes to selection using ${modifier}+Click`, async ({
comfyPage comfyPage
}) => { }) => {
const clipNodes = await comfyPage.getNodeRefsByType('CLIPTextEncode') const clipNodes =
await comfyPage.nodeOps.getNodeRefsByType('CLIPTextEncode')
for (const node of clipNodes) { for (const node of clipNodes) {
await node.click('title', { modifiers: [modifier] }) await node.click('title', { modifiers: [modifier] })
} }
const selectedNodeCount = await comfyPage.getSelectedGraphNodesCount() const selectedNodeCount =
await comfyPage.nodeOps.getSelectedGraphNodesCount()
expect(selectedNodeCount).toBe(clipNodes.length) expect(selectedNodeCount).toBe(clipNodes.length)
}) })
}) })
@@ -80,7 +82,7 @@ test.describe('Node Interaction', () => {
const clipNode2Pos = await clipNodes[1].getPosition() const clipNode2Pos = await clipNodes[1].getPosition()
const offset = 64 const offset = 64
await comfyPage.page.keyboard.down('Meta') await comfyPage.page.keyboard.down('Meta')
await comfyPage.dragAndDrop( await comfyPage.canvasOps.dragAndDrop(
{ {
x: Math.min(clipNode1Pos.x, clipNode2Pos.x) - offset, x: Math.min(clipNode1Pos.x, clipNode2Pos.x) - offset,
y: Math.min(clipNode1Pos.y, clipNode2Pos.y) - offset y: Math.min(clipNode1Pos.y, clipNode2Pos.y) - offset
@@ -94,9 +96,10 @@ test.describe('Node Interaction', () => {
} }
test('Can drag-select nodes with Meta (mac)', async ({ comfyPage }) => { test('Can drag-select nodes with Meta (mac)', async ({ comfyPage }) => {
const clipNodes = await comfyPage.getNodeRefsByType('CLIPTextEncode') const clipNodes =
await comfyPage.nodeOps.getNodeRefsByType('CLIPTextEncode')
await dragSelectNodes(comfyPage, clipNodes) await dragSelectNodes(comfyPage, clipNodes)
expect(await comfyPage.getSelectedGraphNodesCount()).toBe( expect(await comfyPage.nodeOps.getSelectedGraphNodesCount()).toBe(
clipNodes.length clipNodes.length
) )
}) })
@@ -104,7 +107,8 @@ test.describe('Node Interaction', () => {
test('Can move selected nodes using the Comfy.Canvas.MoveSelectedNodes.{Up|Down|Left|Right} commands', async ({ test('Can move selected nodes using the Comfy.Canvas.MoveSelectedNodes.{Up|Down|Left|Right} commands', async ({
comfyPage comfyPage
}) => { }) => {
const clipNodes = await comfyPage.getNodeRefsByType('CLIPTextEncode') const clipNodes =
await comfyPage.nodeOps.getNodeRefsByType('CLIPTextEncode')
const getPositions = () => const getPositions = () =>
Promise.all(clipNodes.map((node) => node.getPosition())) Promise.all(clipNodes.map((node) => node.getPosition()))
const testDirection = async ({ const testDirection = async ({
@@ -174,7 +178,7 @@ test.describe('Node Interaction', () => {
await expect(comfyPage.canvas).toHaveScreenshot('disconnected-edge.png') await expect(comfyPage.canvas).toHaveScreenshot('disconnected-edge.png')
await comfyPage.connectEdge({ reverse }) await comfyPage.connectEdge({ reverse })
// Move mouse to empty area to avoid slot highlight. // Move mouse to empty area to avoid slot highlight.
await comfyPage.moveMouseToEmptyArea() await comfyPage.canvasOps.moveMouseToEmptyArea()
// Litegraph renders edge with a slight offset. // Litegraph renders edge with a slight offset.
await expect(comfyPage.canvas).toHaveScreenshot('default.png', { await expect(comfyPage.canvas).toHaveScreenshot('default.png', {
maxDiffPixels: 50 maxDiffPixels: 50
@@ -183,12 +187,12 @@ test.describe('Node Interaction', () => {
}) })
test('Can move link', async ({ comfyPage }) => { test('Can move link', async ({ comfyPage }) => {
await comfyPage.dragAndDrop( await comfyPage.canvasOps.dragAndDrop(
comfyPage.clipTextEncodeNode1InputSlot, comfyPage.clipTextEncodeNode1InputSlot,
comfyPage.emptySpace comfyPage.emptySpace
) )
await expect(comfyPage.canvas).toHaveScreenshot('disconnected-edge.png') await expect(comfyPage.canvas).toHaveScreenshot('disconnected-edge.png')
await comfyPage.dragAndDrop( await comfyPage.canvasOps.dragAndDrop(
comfyPage.clipTextEncodeNode2InputSlot, comfyPage.clipTextEncodeNode2InputSlot,
comfyPage.clipTextEncodeNode1InputSlot comfyPage.clipTextEncodeNode1InputSlot
) )
@@ -199,13 +203,13 @@ test.describe('Node Interaction', () => {
test.skip('Can copy link by shift-drag existing link', async ({ test.skip('Can copy link by shift-drag existing link', async ({
comfyPage comfyPage
}) => { }) => {
await comfyPage.dragAndDrop( await comfyPage.canvasOps.dragAndDrop(
comfyPage.clipTextEncodeNode1InputSlot, comfyPage.clipTextEncodeNode1InputSlot,
comfyPage.emptySpace comfyPage.emptySpace
) )
await expect(comfyPage.canvas).toHaveScreenshot('disconnected-edge.png') await expect(comfyPage.canvas).toHaveScreenshot('disconnected-edge.png')
await comfyPage.page.keyboard.down('Shift') await comfyPage.page.keyboard.down('Shift')
await comfyPage.dragAndDrop( await comfyPage.canvasOps.dragAndDrop(
comfyPage.clipTextEncodeNode2InputLinkPath, comfyPage.clipTextEncodeNode2InputLinkPath,
comfyPage.clipTextEncodeNode1InputSlot comfyPage.clipTextEncodeNode1InputSlot
) )
@@ -249,7 +253,7 @@ test.describe('Node Interaction', () => {
x: 748, x: 748,
y: 77 y: 77
} }
await comfyPage.dragAndDrop(outputSlotPos, samplerNodeCenterPos) await comfyPage.canvasOps.dragAndDrop(outputSlotPos, samplerNodeCenterPos)
await expect(comfyPage.canvas).toHaveScreenshot('snap_to_slot_linked.png') await expect(comfyPage.canvas).toHaveScreenshot('snap_to_slot_linked.png')
}) })
@@ -271,7 +275,7 @@ test.describe('Node Interaction', () => {
} }
await comfyPage.page.keyboard.down('Shift') await comfyPage.page.keyboard.down('Shift')
await comfyPage.dragAndDrop(outputSlot1Pos, outputSlot2Pos) await comfyPage.canvasOps.dragAndDrop(outputSlot1Pos, outputSlot2Pos)
await comfyPage.page.keyboard.up('Shift') await comfyPage.page.keyboard.up('Shift')
await expect(comfyPage.canvas).toHaveScreenshot( await expect(comfyPage.canvas).toHaveScreenshot(
@@ -398,7 +402,7 @@ test.describe('Node Interaction', () => {
{ tag: '@screenshot' }, { tag: '@screenshot' },
async ({ comfyPage }) => { async ({ comfyPage }) => {
await comfyPage.setSetting('Comfy.GroupSelectedNodes.Padding', 10) await comfyPage.setSetting('Comfy.GroupSelectedNodes.Padding', 10)
await comfyPage.select2Nodes() await comfyPage.nodeOps.select2Nodes()
await comfyPage.page.keyboard.down('Control') await comfyPage.page.keyboard.down('Control')
await comfyPage.page.keyboard.press('KeyG') await comfyPage.page.keyboard.press('KeyG')
await comfyPage.page.keyboard.up('Control') await comfyPage.page.keyboard.up('Control')
@@ -428,7 +432,7 @@ test.describe('Node Interaction', () => {
) )
test('Can pin/unpin nodes', { tag: '@screenshot' }, async ({ comfyPage }) => { test('Can pin/unpin nodes', { tag: '@screenshot' }, async ({ comfyPage }) => {
await comfyPage.select2Nodes() await comfyPage.nodeOps.select2Nodes()
await comfyPage.executeCommand('Comfy.Canvas.ToggleSelectedNodes.Pin') await comfyPage.executeCommand('Comfy.Canvas.ToggleSelectedNodes.Pin')
await comfyPage.nextFrame() await comfyPage.nextFrame()
await expect(comfyPage.canvas).toHaveScreenshot('nodes-pinned.png') await expect(comfyPage.canvas).toHaveScreenshot('nodes-pinned.png')
@@ -441,7 +445,7 @@ test.describe('Node Interaction', () => {
'Can bypass/unbypass nodes with keyboard shortcut', 'Can bypass/unbypass nodes with keyboard shortcut',
{ tag: '@screenshot' }, { tag: '@screenshot' },
async ({ comfyPage }) => { async ({ comfyPage }) => {
await comfyPage.select2Nodes() await comfyPage.nodeOps.select2Nodes()
await comfyPage.canvas.press('Control+b') await comfyPage.canvas.press('Control+b')
await comfyPage.nextFrame() await comfyPage.nextFrame()
await expect(comfyPage.canvas).toHaveScreenshot('nodes-bypassed.png') await expect(comfyPage.canvas).toHaveScreenshot('nodes-bypassed.png')
@@ -470,16 +474,16 @@ test.describe('Group Interaction', { tag: '@screenshot' }, () => {
test.describe('Canvas Interaction', { tag: '@screenshot' }, () => { test.describe('Canvas Interaction', { tag: '@screenshot' }, () => {
test('Can zoom in/out', async ({ comfyPage }) => { test('Can zoom in/out', async ({ comfyPage }) => {
await comfyPage.zoom(-100) await comfyPage.canvasOps.zoom(-100)
await expect(comfyPage.canvas).toHaveScreenshot('zoomed-in.png') await expect(comfyPage.canvas).toHaveScreenshot('zoomed-in.png')
await comfyPage.zoom(200) await comfyPage.canvasOps.zoom(200)
await expect(comfyPage.canvas).toHaveScreenshot('zoomed-out.png') await expect(comfyPage.canvas).toHaveScreenshot('zoomed-out.png')
}) })
test('Can zoom very far out', async ({ comfyPage }) => { test('Can zoom very far out', async ({ comfyPage }) => {
await comfyPage.zoom(100, 12) await comfyPage.canvasOps.zoom(100, 12)
await expect(comfyPage.canvas).toHaveScreenshot('zoomed-very-far-out.png') await expect(comfyPage.canvas).toHaveScreenshot('zoomed-very-far-out.png')
await comfyPage.zoom(-100, 12) await comfyPage.canvasOps.zoom(-100, 12)
await expect(comfyPage.canvas).toHaveScreenshot('zoomed-back-in.png') await expect(comfyPage.canvas).toHaveScreenshot('zoomed-back-in.png')
}) })
@@ -488,11 +492,11 @@ test.describe('Canvas Interaction', { tag: '@screenshot' }, () => {
}) => { }) => {
await comfyPage.page.keyboard.down('Control') await comfyPage.page.keyboard.down('Control')
await comfyPage.page.keyboard.down('Shift') await comfyPage.page.keyboard.down('Shift')
await comfyPage.dragAndDrop({ x: 10, y: 100 }, { x: 10, y: 40 }) await comfyPage.canvasOps.dragAndDrop({ x: 10, y: 100 }, { x: 10, y: 40 })
await expect(comfyPage.canvas).toHaveScreenshot('zoomed-in-ctrl-shift.png') await expect(comfyPage.canvas).toHaveScreenshot('zoomed-in-ctrl-shift.png')
await comfyPage.dragAndDrop({ x: 10, y: 40 }, { x: 10, y: 160 }) await comfyPage.canvasOps.dragAndDrop({ x: 10, y: 40 }, { x: 10, y: 160 })
await expect(comfyPage.canvas).toHaveScreenshot('zoomed-out-ctrl-shift.png') await expect(comfyPage.canvas).toHaveScreenshot('zoomed-out-ctrl-shift.png')
await comfyPage.dragAndDrop({ x: 10, y: 280 }, { x: 10, y: 220 }) await comfyPage.canvasOps.dragAndDrop({ x: 10, y: 280 }, { x: 10, y: 220 })
await expect(comfyPage.canvas).toHaveScreenshot( await expect(comfyPage.canvas).toHaveScreenshot(
'zoomed-default-ctrl-shift.png' 'zoomed-default-ctrl-shift.png'
) )
@@ -504,11 +508,11 @@ test.describe('Canvas Interaction', { tag: '@screenshot' }, () => {
comfyPage comfyPage
}) => { }) => {
await comfyPage.setSetting('Comfy.Graph.ZoomSpeed', 1.05) await comfyPage.setSetting('Comfy.Graph.ZoomSpeed', 1.05)
await comfyPage.zoom(-100, 4) await comfyPage.canvasOps.zoom(-100, 4)
await expect(comfyPage.canvas).toHaveScreenshot( await expect(comfyPage.canvas).toHaveScreenshot(
'zoomed-in-low-zoom-speed.png' 'zoomed-in-low-zoom-speed.png'
) )
await comfyPage.zoom(100, 8) await comfyPage.canvasOps.zoom(100, 8)
await expect(comfyPage.canvas).toHaveScreenshot( await expect(comfyPage.canvas).toHaveScreenshot(
'zoomed-out-low-zoom-speed.png' 'zoomed-out-low-zoom-speed.png'
) )
@@ -519,11 +523,11 @@ test.describe('Canvas Interaction', { tag: '@screenshot' }, () => {
comfyPage comfyPage
}) => { }) => {
await comfyPage.setSetting('Comfy.Graph.ZoomSpeed', 1.5) await comfyPage.setSetting('Comfy.Graph.ZoomSpeed', 1.5)
await comfyPage.zoom(-100, 4) await comfyPage.canvasOps.zoom(-100, 4)
await expect(comfyPage.canvas).toHaveScreenshot( await expect(comfyPage.canvas).toHaveScreenshot(
'zoomed-in-high-zoom-speed.png' 'zoomed-in-high-zoom-speed.png'
) )
await comfyPage.zoom(100, 8) await comfyPage.canvasOps.zoom(100, 8)
await expect(comfyPage.canvas).toHaveScreenshot( await expect(comfyPage.canvas).toHaveScreenshot(
'zoomed-out-high-zoom-speed.png' 'zoomed-out-high-zoom-speed.png'
) )
@@ -531,7 +535,7 @@ test.describe('Canvas Interaction', { tag: '@screenshot' }, () => {
}) })
test('Can pan', async ({ comfyPage }) => { test('Can pan', async ({ comfyPage }) => {
await comfyPage.pan({ x: 200, y: 200 }) await comfyPage.canvasOps.pan({ x: 200, y: 200 })
await expect(comfyPage.canvas).toHaveScreenshot('panned.png') await expect(comfyPage.canvas).toHaveScreenshot('panned.png')
}) })
@@ -623,23 +627,23 @@ test.describe('Canvas Interaction', { tag: '@screenshot' }, () => {
test('Can pan very far and back', async ({ comfyPage }) => { test('Can pan very far and back', async ({ comfyPage }) => {
// intentionally slice the edge of where the clip text encode dom widgets are // intentionally slice the edge of where the clip text encode dom widgets are
await comfyPage.pan({ x: -800, y: -300 }, { x: 1000, y: 10 }) await comfyPage.canvasOps.pan({ x: -800, y: -300 }, { x: 1000, y: 10 })
await expect(comfyPage.canvas).toHaveScreenshot('panned-step-one.png') await expect(comfyPage.canvas).toHaveScreenshot('panned-step-one.png')
await comfyPage.pan({ x: -200, y: 0 }, { x: 1000, y: 10 }) await comfyPage.canvasOps.pan({ x: -200, y: 0 }, { x: 1000, y: 10 })
await expect(comfyPage.canvas).toHaveScreenshot('panned-step-two.png') await expect(comfyPage.canvas).toHaveScreenshot('panned-step-two.png')
await comfyPage.pan({ x: -2200, y: -2200 }, { x: 1000, y: 10 }) await comfyPage.canvasOps.pan({ x: -2200, y: -2200 }, { x: 1000, y: 10 })
await expect(comfyPage.canvas).toHaveScreenshot('panned-far-away.png') await expect(comfyPage.canvas).toHaveScreenshot('panned-far-away.png')
await comfyPage.pan({ x: 2200, y: 2200 }, { x: 1000, y: 10 }) await comfyPage.canvasOps.pan({ x: 2200, y: 2200 }, { x: 1000, y: 10 })
await expect(comfyPage.canvas).toHaveScreenshot('panned-back-from-far.png') await expect(comfyPage.canvas).toHaveScreenshot('panned-back-from-far.png')
await comfyPage.pan({ x: 200, y: 0 }, { x: 1000, y: 10 }) await comfyPage.canvasOps.pan({ x: 200, y: 0 }, { x: 1000, y: 10 })
await expect(comfyPage.canvas).toHaveScreenshot('panned-back-to-two.png') await expect(comfyPage.canvas).toHaveScreenshot('panned-back-to-two.png')
await comfyPage.pan({ x: 800, y: 300 }, { x: 1000, y: 10 }) await comfyPage.canvasOps.pan({ x: 800, y: 300 }, { x: 1000, y: 10 })
await expect(comfyPage.canvas).toHaveScreenshot('panned-back-to-one.png') await expect(comfyPage.canvas).toHaveScreenshot('panned-back-to-one.png')
}) })
test('@mobile Can pan with touch', async ({ comfyPage }) => { test('@mobile Can pan with touch', async ({ comfyPage }) => {
await comfyPage.closeMenu() await comfyPage.closeMenu()
await comfyPage.panWithTouch({ x: 200, y: 200 }) await comfyPage.canvasOps.panWithTouch({ x: 200, y: 200 })
await expect(comfyPage.canvas).toHaveScreenshot('panned-touch.png') await expect(comfyPage.canvas).toHaveScreenshot('panned-touch.png')
}) })
}) })
@@ -696,7 +700,7 @@ test.describe('Load workflow', { tag: '@screenshot' }, () => {
comfyPage comfyPage
}) => { }) => {
await comfyPage.loadWorkflow('nodes/single_ksampler') await comfyPage.loadWorkflow('nodes/single_ksampler')
const node = (await comfyPage.getFirstNodeRef())! const node = (await comfyPage.nodeOps.getFirstNodeRef())!
await node.click('collapse') await node.click('collapse')
await comfyPage.clickEmptySpace() await comfyPage.clickEmptySpace()
await expect(comfyPage.canvas).toHaveScreenshot( await expect(comfyPage.canvas).toHaveScreenshot(
@@ -788,7 +792,7 @@ test.describe('Load duplicate workflow', () => {
await comfyPage.menu.workflowsTab.open() await comfyPage.menu.workflowsTab.open()
await comfyPage.executeCommand('Comfy.NewBlankWorkflow') await comfyPage.executeCommand('Comfy.NewBlankWorkflow')
await comfyPage.loadWorkflow('nodes/single_ksampler') await comfyPage.loadWorkflow('nodes/single_ksampler')
expect(await comfyPage.getGraphNodesCount()).toBe(1) expect(await comfyPage.nodeOps.getGraphNodesCount()).toBe(1)
}) })
}) })
@@ -871,7 +875,10 @@ test.describe('Canvas Navigation', { tag: '@screenshot' }, () => {
test('Left-click drag in empty area should pan canvas', async ({ test('Left-click drag in empty area should pan canvas', async ({
comfyPage comfyPage
}) => { }) => {
await comfyPage.dragAndDrop({ x: 50, y: 50 }, { x: 150, y: 150 }) await comfyPage.canvasOps.dragAndDrop(
{ x: 50, y: 50 },
{ x: 150, y: 150 }
)
await expect(comfyPage.canvas).toHaveScreenshot( await expect(comfyPage.canvas).toHaveScreenshot(
'legacy-left-drag-pan.png' 'legacy-left-drag-pan.png'
) )
@@ -905,7 +912,7 @@ test.describe('Canvas Navigation', { tag: '@screenshot' }, () => {
test('Left-click on node should not pan canvas', async ({ comfyPage }) => { test('Left-click on node should not pan canvas', async ({ comfyPage }) => {
await comfyPage.clickTextEncodeNode1() await comfyPage.clickTextEncodeNode1()
const selectedCount = await comfyPage.getSelectedGraphNodesCount() const selectedCount = await comfyPage.nodeOps.getSelectedGraphNodesCount()
expect(selectedCount).toBe(1) expect(selectedCount).toBe(1)
await expect(comfyPage.canvas).toHaveScreenshot( await expect(comfyPage.canvas).toHaveScreenshot(
'legacy-click-node-select.png' 'legacy-click-node-select.png'
@@ -921,12 +928,13 @@ test.describe('Canvas Navigation', { tag: '@screenshot' }, () => {
test('Left-click drag in empty area should select nodes', async ({ test('Left-click drag in empty area should select nodes', async ({
comfyPage comfyPage
}) => { }) => {
const clipNodes = await comfyPage.getNodeRefsByType('CLIPTextEncode') const clipNodes =
await comfyPage.nodeOps.getNodeRefsByType('CLIPTextEncode')
const clipNode1Pos = await clipNodes[0].getPosition() const clipNode1Pos = await clipNodes[0].getPosition()
const clipNode2Pos = await clipNodes[1].getPosition() const clipNode2Pos = await clipNodes[1].getPosition()
const offset = 64 const offset = 64
await comfyPage.dragAndDrop( await comfyPage.canvasOps.dragAndDrop(
{ {
x: Math.min(clipNode1Pos.x, clipNode2Pos.x) - offset, x: Math.min(clipNode1Pos.x, clipNode2Pos.x) - offset,
y: Math.min(clipNode1Pos.y, clipNode2Pos.y) - offset y: Math.min(clipNode1Pos.y, clipNode2Pos.y) - offset
@@ -937,7 +945,7 @@ test.describe('Canvas Navigation', { tag: '@screenshot' }, () => {
} }
) )
const selectedCount = await comfyPage.getSelectedGraphNodesCount() const selectedCount = await comfyPage.nodeOps.getSelectedGraphNodesCount()
expect(selectedCount).toBe(clipNodes.length) expect(selectedCount).toBe(clipNodes.length)
await expect(comfyPage.canvas).toHaveScreenshot( await expect(comfyPage.canvas).toHaveScreenshot(
'standard-left-drag-select.png' 'standard-left-drag-select.png'
@@ -978,7 +986,7 @@ test.describe('Canvas Navigation', { tag: '@screenshot' }, () => {
comfyPage comfyPage
}) => { }) => {
await comfyPage.clickTextEncodeNode1() await comfyPage.clickTextEncodeNode1()
const selectedCount = await comfyPage.getSelectedGraphNodesCount() const selectedCount = await comfyPage.nodeOps.getSelectedGraphNodesCount()
expect(selectedCount).toBe(1) expect(selectedCount).toBe(1)
await expect(comfyPage.canvas).toHaveScreenshot( await expect(comfyPage.canvas).toHaveScreenshot(
'standard-click-node-select.png' 'standard-click-node-select.png'
@@ -991,7 +999,10 @@ test.describe('Canvas Navigation', { tag: '@screenshot' }, () => {
await comfyPage.nextFrame() await comfyPage.nextFrame()
await comfyPage.page.keyboard.down('Space') await comfyPage.page.keyboard.down('Space')
await comfyPage.dragAndDrop({ x: 50, y: 50 }, { x: 150, y: 150 }) await comfyPage.canvasOps.dragAndDrop(
{ x: 50, y: 50 },
{ x: 150, y: 150 }
)
await comfyPage.page.keyboard.up('Space') await comfyPage.page.keyboard.up('Space')
await expect(comfyPage.canvas).toHaveScreenshot( await expect(comfyPage.canvas).toHaveScreenshot(
'standard-space-drag-pan.png' 'standard-space-drag-pan.png'
@@ -1001,11 +1012,12 @@ test.describe('Canvas Navigation', { tag: '@screenshot' }, () => {
test('Space key overrides default left-click behavior', async ({ test('Space key overrides default left-click behavior', async ({
comfyPage comfyPage
}) => { }) => {
const clipNodes = await comfyPage.getNodeRefsByType('CLIPTextEncode') const clipNodes =
await comfyPage.nodeOps.getNodeRefsByType('CLIPTextEncode')
const clipNode1Pos = await clipNodes[0].getPosition() const clipNode1Pos = await clipNodes[0].getPosition()
const offset = 64 const offset = 64
await comfyPage.dragAndDrop( await comfyPage.canvasOps.dragAndDrop(
{ {
x: clipNode1Pos.x - offset, x: clipNode1Pos.x - offset,
y: clipNode1Pos.y - offset y: clipNode1Pos.y - offset
@@ -1017,16 +1029,16 @@ test.describe('Canvas Navigation', { tag: '@screenshot' }, () => {
) )
const selectedCountAfterDrag = const selectedCountAfterDrag =
await comfyPage.getSelectedGraphNodesCount() await comfyPage.nodeOps.getSelectedGraphNodesCount()
expect(selectedCountAfterDrag).toBeGreaterThan(0) expect(selectedCountAfterDrag).toBeGreaterThan(0)
await comfyPage.clickEmptySpace() await comfyPage.clickEmptySpace()
const selectedCountAfterClear = const selectedCountAfterClear =
await comfyPage.getSelectedGraphNodesCount() await comfyPage.nodeOps.getSelectedGraphNodesCount()
expect(selectedCountAfterClear).toBe(0) expect(selectedCountAfterClear).toBe(0)
await comfyPage.page.keyboard.down('Space') await comfyPage.page.keyboard.down('Space')
await comfyPage.dragAndDrop( await comfyPage.canvasOps.dragAndDrop(
{ {
x: clipNode1Pos.x - offset, x: clipNode1Pos.x - offset,
y: clipNode1Pos.y - offset y: clipNode1Pos.y - offset
@@ -1039,7 +1051,7 @@ test.describe('Canvas Navigation', { tag: '@screenshot' }, () => {
await comfyPage.page.keyboard.up('Space') await comfyPage.page.keyboard.up('Space')
const selectedCountAfterSpaceDrag = const selectedCountAfterSpaceDrag =
await comfyPage.getSelectedGraphNodesCount() await comfyPage.nodeOps.getSelectedGraphNodesCount()
expect(selectedCountAfterSpaceDrag).toBe(0) expect(selectedCountAfterSpaceDrag).toBe(0)
}) })
}) })
@@ -1089,7 +1101,10 @@ test.describe('Canvas Navigation', { tag: '@screenshot' }, () => {
await comfyPage.page.keyboard.down('Alt') await comfyPage.page.keyboard.down('Alt')
await comfyPage.page.keyboard.down('Shift') await comfyPage.page.keyboard.down('Shift')
await comfyPage.dragAndDrop({ x: 50, y: 50 }, { x: 150, y: 150 }) await comfyPage.canvasOps.dragAndDrop(
{ x: 50, y: 50 },
{ x: 150, y: 150 }
)
await comfyPage.page.keyboard.up('Shift') await comfyPage.page.keyboard.up('Shift')
await comfyPage.page.keyboard.up('Alt') await comfyPage.page.keyboard.up('Alt')

View File

@@ -29,7 +29,7 @@ test.describe('Canvas Event', { tag: '@canvas' }, () => {
test('Emit litegraph:canvas empty-double-click', async ({ comfyPage }) => { test('Emit litegraph:canvas empty-double-click', async ({ comfyPage }) => {
const eventPromise = comfyPage.page.evaluate(listenForEvent) const eventPromise = comfyPage.page.evaluate(listenForEvent)
const doubleClickPromise = comfyPage.doubleClickCanvas() const doubleClickPromise = comfyPage.canvasOps.doubleClick()
const event = await eventPromise const event = await eventPromise
await doubleClickPromise await doubleClickPromise

View File

@@ -32,7 +32,7 @@ test.describe('LOD Threshold', { tag: ['@screenshot', '@canvas'] }, () => {
// Can't access private _lowQualityZoomThreshold directly // Can't access private _lowQualityZoomThreshold directly
// Zoom out just above threshold (should still be high quality) // Zoom out just above threshold (should still be high quality)
await comfyPage.zoom(120, 5) // Zoom out 5 steps await comfyPage.canvasOps.zoom(120, 5) // Zoom out 5 steps
await comfyPage.nextFrame() await comfyPage.nextFrame()
const aboveThresholdState = await comfyPage.page.evaluate(() => { const aboveThresholdState = await comfyPage.page.evaluate(() => {
@@ -49,7 +49,7 @@ test.describe('LOD Threshold', { tag: ['@screenshot', '@canvas'] }, () => {
} }
// Zoom out more to trigger LOD (below threshold) // Zoom out more to trigger LOD (below threshold)
await comfyPage.zoom(120, 5) // Zoom out 5 more steps await comfyPage.canvasOps.zoom(120, 5) // Zoom out 5 more steps
await comfyPage.nextFrame() await comfyPage.nextFrame()
// Check that LOD is now active // Check that LOD is now active
@@ -65,7 +65,7 @@ test.describe('LOD Threshold', { tag: ['@screenshot', '@canvas'] }, () => {
expect(zoomedOutState.lowQuality).toBe(true) expect(zoomedOutState.lowQuality).toBe(true)
// Zoom back in to disable LOD (above threshold) // Zoom back in to disable LOD (above threshold)
await comfyPage.zoom(-120, 15) // Zoom in 15 steps await comfyPage.canvasOps.zoom(-120, 15) // Zoom in 15 steps
await comfyPage.nextFrame() await comfyPage.nextFrame()
// Check that LOD is now inactive // Check that LOD is now inactive
@@ -107,7 +107,7 @@ test.describe('LOD Threshold', { tag: ['@screenshot', '@canvas'] }, () => {
expect(lodState).toBe(false) expect(lodState).toBe(false)
// Zoom out slightly to trigger LOD // Zoom out slightly to trigger LOD
await comfyPage.zoom(120, 1) // Zoom out 1 step await comfyPage.canvasOps.zoom(120, 1) // Zoom out 1 step
await comfyPage.nextFrame() await comfyPage.nextFrame()
const afterZoom = await comfyPage.page.evaluate(() => { const afterZoom = await comfyPage.page.evaluate(() => {
@@ -131,7 +131,7 @@ test.describe('LOD Threshold', { tag: ['@screenshot', '@canvas'] }, () => {
await comfyPage.setSetting('LiteGraph.Canvas.MinFontSizeForLOD', 0) await comfyPage.setSetting('LiteGraph.Canvas.MinFontSizeForLOD', 0)
// Zoom out significantly // Zoom out significantly
await comfyPage.zoom(120, 20) // Zoom out 20 steps await comfyPage.canvasOps.zoom(120, 20) // Zoom out 20 steps
await comfyPage.nextFrame() await comfyPage.nextFrame()
// LOD should remain disabled even at very low zoom // LOD should remain disabled even at very low zoom

View File

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

View File

@@ -77,7 +77,7 @@ test.describe(
await comfyPage.setSetting('Comfy.NodeBadge.NodeSourceBadgeMode', mode) await comfyPage.setSetting('Comfy.NodeBadge.NodeSourceBadgeMode', mode)
await comfyPage.setSetting('Comfy.NodeBadge.NodeIdBadgeMode', mode) await comfyPage.setSetting('Comfy.NodeBadge.NodeIdBadgeMode', mode)
await comfyPage.nextFrame() await comfyPage.nextFrame()
await comfyPage.resetView() await comfyPage.canvasOps.resetView()
await expect(comfyPage.canvas).toHaveScreenshot( await expect(comfyPage.canvas).toHaveScreenshot(
`node-badge-${mode}.png` `node-badge-${mode}.png`
) )

View File

@@ -36,7 +36,7 @@ test.describe('Optional input', { tag: ['@screenshot', '@node'] }, () => {
test('Only optional inputs', async ({ comfyPage }) => { test('Only optional inputs', async ({ comfyPage }) => {
await comfyPage.loadWorkflow('inputs/only_optional_inputs') await comfyPage.loadWorkflow('inputs/only_optional_inputs')
expect(await comfyPage.getGraphNodesCount()).toBe(1) expect(await comfyPage.nodeOps.getGraphNodesCount()).toBe(1)
await expect( await expect(
comfyPage.page.locator('.comfy-missing-nodes') comfyPage.page.locator('.comfy-missing-nodes')
).not.toBeVisible() ).not.toBeVisible()
@@ -48,7 +48,7 @@ test.describe('Optional input', { tag: ['@screenshot', '@node'] }, () => {
}) })
test('Old workflow with converted input', async ({ comfyPage }) => { test('Old workflow with converted input', async ({ comfyPage }) => {
await comfyPage.loadWorkflow('inputs/old_workflow_converted_input') await comfyPage.loadWorkflow('inputs/old_workflow_converted_input')
const node = await comfyPage.getNodeRefById('1') const node = await comfyPage.nodeOps.getNodeRefById('1')
const inputs = await node.getProperty('inputs') const inputs = await node.getProperty('inputs')
const vaeInput = inputs.find((w) => w.name === 'vae') const vaeInput = inputs.find((w) => w.name === 'vae')
const convertedInput = inputs.find((w) => w.name === 'strength') const convertedInput = inputs.find((w) => w.name === 'strength')
@@ -60,7 +60,7 @@ test.describe('Optional input', { tag: ['@screenshot', '@node'] }, () => {
}) })
test('Renamed converted input', async ({ comfyPage }) => { test('Renamed converted input', async ({ comfyPage }) => {
await comfyPage.loadWorkflow('inputs/renamed_converted_widget') await comfyPage.loadWorkflow('inputs/renamed_converted_widget')
const node = await comfyPage.getNodeRefById('3') const node = await comfyPage.nodeOps.getNodeRefById('3')
const inputs = await node.getProperty('inputs') const inputs = await node.getProperty('inputs')
const renamedInput = inputs.find((w) => w.name === 'breadth') const renamedInput = inputs.find((w) => w.name === 'breadth')
expect(renamedInput).toBeUndefined() expect(renamedInput).toBeUndefined()

View File

@@ -36,7 +36,8 @@ test.describe('Node Help', { tag: ['@slow', '@ui'] }, () => {
await comfyPage.loadWorkflow('default') await comfyPage.loadWorkflow('default')
// Select a single node (KSampler) using node references // Select a single node (KSampler) using node references
const ksamplerNodes = await comfyPage.getNodeRefsByType('KSampler') const ksamplerNodes =
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
if (ksamplerNodes.length === 0) { if (ksamplerNodes.length === 0) {
throw new Error('No KSampler nodes found in the workflow') throw new Error('No KSampler nodes found in the workflow')
} }
@@ -158,7 +159,8 @@ test.describe('Node Help', { tag: ['@slow', '@ui'] }, () => {
// Load workflow and select a node // Load workflow and select a node
await comfyPage.loadWorkflow('default') await comfyPage.loadWorkflow('default')
const ksamplerNodes = await comfyPage.getNodeRefsByType('KSampler') const ksamplerNodes =
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
await selectNodeWithPan(comfyPage, ksamplerNodes[0]) await selectNodeWithPan(comfyPage, ksamplerNodes[0])
// Click help button // Click help button
@@ -190,7 +192,8 @@ test.describe('Node Help', { tag: ['@slow', '@ui'] }, () => {
// Load workflow and select a node // Load workflow and select a node
await comfyPage.loadWorkflow('default') await comfyPage.loadWorkflow('default')
const ksamplerNodes = await comfyPage.getNodeRefsByType('KSampler') const ksamplerNodes =
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
await selectNodeWithPan(comfyPage, ksamplerNodes[0]) await selectNodeWithPan(comfyPage, ksamplerNodes[0])
// Click help button // Click help button
@@ -227,7 +230,8 @@ test.describe('Node Help', { tag: ['@slow', '@ui'] }, () => {
}) })
await comfyPage.loadWorkflow('default') await comfyPage.loadWorkflow('default')
const ksamplerNodes = await comfyPage.getNodeRefsByType('KSampler') const ksamplerNodes =
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
await selectNodeWithPan(comfyPage, ksamplerNodes[0]) await selectNodeWithPan(comfyPage, ksamplerNodes[0])
const helpButton = comfyPage.page.locator( const helpButton = comfyPage.page.locator(
@@ -277,7 +281,8 @@ test.describe('Node Help', { tag: ['@slow', '@ui'] }, () => {
}) })
await comfyPage.loadWorkflow('default') await comfyPage.loadWorkflow('default')
const ksamplerNodes = await comfyPage.getNodeRefsByType('KSampler') const ksamplerNodes =
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
await selectNodeWithPan(comfyPage, ksamplerNodes[0]) await selectNodeWithPan(comfyPage, ksamplerNodes[0])
const helpButton = comfyPage.page.locator( const helpButton = comfyPage.page.locator(
@@ -350,7 +355,7 @@ This is documentation for a custom node.
return window['app']!.graph!.nodes.map((n) => n.id) return window['app']!.graph!.nodes.map((n) => n.id)
}) })
if (nodeRefs.length > 0) { if (nodeRefs.length > 0) {
const firstNode = await comfyPage.getNodeRefById(nodeRefs[0]) const firstNode = await comfyPage.nodeOps.getNodeRefById(nodeRefs[0])
await selectNodeWithPan(comfyPage, firstNode) await selectNodeWithPan(comfyPage, firstNode)
} }
@@ -394,7 +399,8 @@ This is documentation for a custom node.
}) })
await comfyPage.loadWorkflow('default') await comfyPage.loadWorkflow('default')
const ksamplerNodes = await comfyPage.getNodeRefsByType('KSampler') const ksamplerNodes =
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
await selectNodeWithPan(comfyPage, ksamplerNodes[0]) await selectNodeWithPan(comfyPage, ksamplerNodes[0])
const helpButton = comfyPage.page.locator( const helpButton = comfyPage.page.locator(
@@ -463,7 +469,8 @@ This is English documentation.
await comfyPage.setSetting('Comfy.Locale', 'ja') await comfyPage.setSetting('Comfy.Locale', 'ja')
await comfyPage.loadWorkflow('default') await comfyPage.loadWorkflow('default')
const ksamplerNodes = await comfyPage.getNodeRefsByType('KSampler') const ksamplerNodes =
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
await selectNodeWithPan(comfyPage, ksamplerNodes[0]) await selectNodeWithPan(comfyPage, ksamplerNodes[0])
const helpButton = comfyPage.page.locator( const helpButton = comfyPage.page.locator(
@@ -488,7 +495,8 @@ This is English documentation.
}) })
await comfyPage.loadWorkflow('default') await comfyPage.loadWorkflow('default')
const ksamplerNodes = await comfyPage.getNodeRefsByType('KSampler') const ksamplerNodes =
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
await selectNodeWithPan(comfyPage, ksamplerNodes[0]) await selectNodeWithPan(comfyPage, ksamplerNodes[0])
const helpButton = comfyPage.page.locator( const helpButton = comfyPage.page.locator(
@@ -534,7 +542,8 @@ This is English documentation.
await fitToViewInstant(comfyPage) await fitToViewInstant(comfyPage)
// Select KSampler first // Select KSampler first
const ksamplerNodes = await comfyPage.getNodeRefsByType('KSampler') const ksamplerNodes =
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
await selectNodeWithPan(comfyPage, ksamplerNodes[0]) await selectNodeWithPan(comfyPage, ksamplerNodes[0])
const helpButton = comfyPage.page.locator( const helpButton = comfyPage.page.locator(
@@ -549,7 +558,7 @@ This is English documentation.
await expect(helpPage).toContainText('This is KSampler documentation') await expect(helpPage).toContainText('This is KSampler documentation')
// Now select Checkpoint Loader // Now select Checkpoint Loader
const checkpointNodes = await comfyPage.getNodeRefsByType( const checkpointNodes = await comfyPage.nodeOps.getNodeRefsByType(
'CheckpointLoaderSimple' 'CheckpointLoaderSimple'
) )
await selectNodeWithPan(comfyPage, checkpointNodes[0]) await selectNodeWithPan(comfyPage, checkpointNodes[0])

View File

@@ -15,7 +15,7 @@ test.describe('Node search box', { tag: '@node' }, () => {
}) })
test(`Can trigger on empty canvas double click`, async ({ comfyPage }) => { test(`Can trigger on empty canvas double click`, async ({ comfyPage }) => {
await comfyPage.doubleClickCanvas() await comfyPage.canvasOps.doubleClick()
await expect(comfyPage.searchBox.input).toHaveCount(1) await expect(comfyPage.searchBox.input).toHaveCount(1)
}) })
@@ -47,7 +47,7 @@ test.describe('Node search box', { tag: '@node' }, () => {
}) })
test('Can add node', { tag: '@screenshot' }, async ({ comfyPage }) => { test('Can add node', { tag: '@screenshot' }, async ({ comfyPage }) => {
await comfyPage.doubleClickCanvas() await comfyPage.canvasOps.doubleClick()
await expect(comfyPage.searchBox.input).toHaveCount(1) await expect(comfyPage.searchBox.input).toHaveCount(1)
await comfyPage.searchBox.fillAndSelectFirstNode('KSampler') await comfyPage.searchBox.fillAndSelectFirstNode('KSampler')
await expect(comfyPage.canvas).toHaveScreenshot('added-node.png') await expect(comfyPage.canvas).toHaveScreenshot('added-node.png')
@@ -77,7 +77,7 @@ test.describe('Node search box', { tag: '@node' }, () => {
y: 5 y: 5
} }
await comfyPage.page.keyboard.down('Shift') await comfyPage.page.keyboard.down('Shift')
await comfyPage.dragAndDrop(outputSlot1Pos, emptySpacePos) await comfyPage.canvasOps.dragAndDrop(outputSlot1Pos, emptySpacePos)
await comfyPage.page.keyboard.up('Shift') await comfyPage.page.keyboard.up('Shift')
// Select the second item as the first item is always reroute // Select the second item as the first item is always reroute
@@ -106,7 +106,7 @@ test.describe('Node search box', { tag: '@node' }, () => {
test('Has correct aria-labels on search results', async ({ comfyPage }) => { test('Has correct aria-labels on search results', async ({ comfyPage }) => {
const node = 'Load Checkpoint' const node = 'Load Checkpoint'
await comfyPage.doubleClickCanvas() await comfyPage.canvasOps.doubleClick()
await comfyPage.searchBox.input.waitFor({ state: 'visible' }) await comfyPage.searchBox.input.waitFor({ state: 'visible' })
await comfyPage.searchBox.input.fill(node) await comfyPage.searchBox.input.fill(node)
await comfyPage.searchBox.dropdown.waitFor({ state: 'visible' }) await comfyPage.searchBox.dropdown.waitFor({ state: 'visible' })
@@ -149,7 +149,7 @@ test.describe('Node search box', { tag: '@node' }, () => {
} }
test.beforeEach(async ({ comfyPage }) => { test.beforeEach(async ({ comfyPage }) => {
await comfyPage.doubleClickCanvas() await comfyPage.canvasOps.doubleClick()
}) })
test('Can add filter', async ({ comfyPage }) => { test('Can add filter', async ({ comfyPage }) => {
@@ -241,7 +241,7 @@ test.describe('Node search box', { tag: '@node' }, () => {
test.describe('Input focus behavior', () => { test.describe('Input focus behavior', () => {
test.beforeEach(async ({ comfyPage }) => { test.beforeEach(async ({ comfyPage }) => {
await comfyPage.doubleClickCanvas() await comfyPage.canvasOps.doubleClick()
}) })
test('focuses input after adding a filter', async ({ comfyPage }) => { test('focuses input after adding a filter', async ({ comfyPage }) => {

View File

@@ -17,8 +17,10 @@ test.describe('Primitive Node', { tag: ['@screenshot', '@node'] }, () => {
// to input. // to input.
test('Can connect to widget', async ({ comfyPage }) => { test('Can connect to widget', async ({ comfyPage }) => {
await comfyPage.loadWorkflow('primitive/primitive_node_unconnected') await comfyPage.loadWorkflow('primitive/primitive_node_unconnected')
const primitiveNode: NodeReference = await comfyPage.getNodeRefById(1) const primitiveNode: NodeReference =
const ksamplerNode: NodeReference = await comfyPage.getNodeRefById(2) await comfyPage.nodeOps.getNodeRefById(1)
const ksamplerNode: NodeReference =
await comfyPage.nodeOps.getNodeRefById(2)
// Connect the output of the primitive node to the input of first widget of the ksampler node // Connect the output of the primitive node to the input of first widget of the ksampler node
await primitiveNode.connectWidget(0, ksamplerNode, 0) await primitiveNode.connectWidget(0, ksamplerNode, 0)
await expect(comfyPage.canvas).toHaveScreenshot( await expect(comfyPage.canvas).toHaveScreenshot(
@@ -30,8 +32,10 @@ test.describe('Primitive Node', { tag: ['@screenshot', '@node'] }, () => {
await comfyPage.loadWorkflow( await comfyPage.loadWorkflow(
'primitive/primitive_node_unconnected_dom_widget' 'primitive/primitive_node_unconnected_dom_widget'
) )
const primitiveNode: NodeReference = await comfyPage.getNodeRefById(1) const primitiveNode: NodeReference =
const clipEncoderNode: NodeReference = await comfyPage.getNodeRefById(2) await comfyPage.nodeOps.getNodeRefById(1)
const clipEncoderNode: NodeReference =
await comfyPage.nodeOps.getNodeRefById(2)
await primitiveNode.connectWidget(0, clipEncoderNode, 0) await primitiveNode.connectWidget(0, clipEncoderNode, 0)
await expect(comfyPage.canvas).toHaveScreenshot( await expect(comfyPage.canvas).toHaveScreenshot(
'primitive_node_connected_dom_widget.png' 'primitive_node_connected_dom_widget.png'
@@ -40,8 +44,10 @@ test.describe('Primitive Node', { tag: ['@screenshot', '@node'] }, () => {
test('Can connect to static primitive node', async ({ comfyPage }) => { test('Can connect to static primitive node', async ({ comfyPage }) => {
await comfyPage.loadWorkflow('primitive/static_primitive_unconnected') await comfyPage.loadWorkflow('primitive/static_primitive_unconnected')
const primitiveNode: NodeReference = await comfyPage.getNodeRefById(1) const primitiveNode: NodeReference =
const ksamplerNode: NodeReference = await comfyPage.getNodeRefById(2) await comfyPage.nodeOps.getNodeRefById(1)
const ksamplerNode: NodeReference =
await comfyPage.nodeOps.getNodeRefById(2)
await primitiveNode.connectWidget(0, ksamplerNode, 0) await primitiveNode.connectWidget(0, ksamplerNode, 0)
await expect(comfyPage.canvas).toHaveScreenshot( await expect(comfyPage.canvas).toHaveScreenshot(
'static_primitive_connected.png' 'static_primitive_connected.png'

View File

@@ -10,7 +10,10 @@ test.describe('Properties panel', () => {
await expect(propertiesPanel.panelTitle).toContainText('Workflow Overview') await expect(propertiesPanel.panelTitle).toContainText('Workflow Overview')
await comfyPage.selectNodes(['KSampler', 'CLIP Text Encode (Prompt)']) await comfyPage.nodeOps.selectNodes([
'KSampler',
'CLIP Text Encode (Prompt)'
])
await expect(propertiesPanel.panelTitle).toContainText('3 items selected') await expect(propertiesPanel.panelTitle).toContainText('3 items selected')
await expect(propertiesPanel.root.getByText('KSampler')).toHaveCount(1) await expect(propertiesPanel.root.getByText('KSampler')).toHaveCount(1)

View File

@@ -11,7 +11,7 @@ test.describe('Record Audio Node', { tag: '@screenshot' }, () => {
comfyPage comfyPage
}) => { }) => {
// Open the search box by double clicking on the canvas // Open the search box by double clicking on the canvas
await comfyPage.doubleClickCanvas() await comfyPage.canvasOps.doubleClick()
await expect(comfyPage.searchBox.input).toHaveCount(1) await expect(comfyPage.searchBox.input).toHaveCount(1)
// Search for and add the RecordAudio node // Search for and add the RecordAudio node
@@ -19,7 +19,8 @@ test.describe('Record Audio Node', { tag: '@screenshot' }, () => {
await comfyPage.nextFrame() await comfyPage.nextFrame()
// Verify the RecordAudio node was added // Verify the RecordAudio node was added
const recordAudioNodes = await comfyPage.getNodeRefsByType('RecordAudio') const recordAudioNodes =
await comfyPage.nodeOps.getNodeRefsByType('RecordAudio')
expect(recordAudioNodes.length).toBe(1) expect(recordAudioNodes.length).toBe(1)
// Take a screenshot of the canvas with the RecordAudio node // Take a screenshot of the canvas with the RecordAudio node

View File

@@ -56,10 +56,10 @@ test.describe(
comfyPage comfyPage
}) => { }) => {
const loadCheckpointNode = ( const loadCheckpointNode = (
await comfyPage.getNodeRefsByTitle('Load Checkpoint') await comfyPage.nodeOps.getNodeRefsByTitle('Load Checkpoint')
)[0] )[0]
const clipEncodeNode = ( const clipEncodeNode = (
await comfyPage.getNodeRefsByTitle('CLIP Text Encode (Prompt)') await comfyPage.nodeOps.getNodeRefsByTitle('CLIP Text Encode (Prompt)')
)[0] )[0]
const slot1 = await loadCheckpointNode.getOutput(1) const slot1 = await loadCheckpointNode.getOutput(1)
@@ -82,10 +82,10 @@ test.describe(
comfyPage comfyPage
}) => { }) => {
const loadCheckpointNode = ( const loadCheckpointNode = (
await comfyPage.getNodeRefsByTitle('Load Checkpoint') await comfyPage.nodeOps.getNodeRefsByTitle('Load Checkpoint')
)[0] )[0]
const clipEncodeNode = ( const clipEncodeNode = (
await comfyPage.getNodeRefsByTitle('CLIP Text Encode (Prompt)') await comfyPage.nodeOps.getNodeRefsByTitle('CLIP Text Encode (Prompt)')
)[0] )[0]
const slot1 = await loadCheckpointNode.getOutput(1) const slot1 = await loadCheckpointNode.getOutput(1)

View File

@@ -12,7 +12,7 @@ test.describe(
{ tag: ['@screenshot', '@ui'] }, { tag: ['@screenshot', '@ui'] },
() => { () => {
test('Can add node', async ({ comfyPage }) => { test('Can add node', async ({ comfyPage }) => {
await comfyPage.rightClickCanvas() await comfyPage.canvasOps.rightClick()
await expect(comfyPage.canvas).toHaveScreenshot('right-click-menu.png') await expect(comfyPage.canvas).toHaveScreenshot('right-click-menu.png')
await comfyPage.page.getByText('Add Node').click() await comfyPage.page.getByText('Add Node').click()
await comfyPage.nextFrame() await comfyPage.nextFrame()
@@ -24,7 +24,7 @@ test.describe(
}) })
test('Can add group', async ({ comfyPage }) => { test('Can add group', async ({ comfyPage }) => {
await comfyPage.rightClickCanvas() await comfyPage.canvasOps.rightClick()
await expect(comfyPage.canvas).toHaveScreenshot('right-click-menu.png') await expect(comfyPage.canvas).toHaveScreenshot('right-click-menu.png')
await comfyPage.page.getByText('Add Group', { exact: true }).click() await comfyPage.page.getByText('Add Group', { exact: true }).click()
await comfyPage.nextFrame() await comfyPage.nextFrame()
@@ -34,9 +34,9 @@ test.describe(
}) })
test('Can convert to group node', async ({ comfyPage }) => { test('Can convert to group node', async ({ comfyPage }) => {
await comfyPage.select2Nodes() await comfyPage.nodeOps.select2Nodes()
await expect(comfyPage.canvas).toHaveScreenshot('selected-2-nodes.png') await expect(comfyPage.canvas).toHaveScreenshot('selected-2-nodes.png')
await comfyPage.rightClickCanvas() await comfyPage.canvasOps.rightClick()
await comfyPage.clickContextMenuItem('Convert to Group Node (Deprecated)') await comfyPage.clickContextMenuItem('Convert to Group Node (Deprecated)')
await comfyPage.promptDialogInput.fill('GroupNode2CLIP') await comfyPage.promptDialogInput.fill('GroupNode2CLIP')
await comfyPage.page.keyboard.press('Enter') await comfyPage.page.keyboard.press('Enter')
@@ -103,7 +103,7 @@ test.describe('Node Right Click Menu', { tag: ['@screenshot', '@ui'] }, () => {
await expect(comfyPage.canvas).toHaveScreenshot('right-click-node.png') await expect(comfyPage.canvas).toHaveScreenshot('right-click-node.png')
await comfyPage.page.click('.litemenu-entry:has-text("Pin")') await comfyPage.page.click('.litemenu-entry:has-text("Pin")')
await comfyPage.nextFrame() await comfyPage.nextFrame()
await comfyPage.dragAndDrop({ x: 621, y: 617 }, { x: 16, y: 16 }) await comfyPage.canvasOps.dragAndDrop({ x: 621, y: 617 }, { x: 16, y: 16 })
await expect(comfyPage.canvas).toHaveScreenshot('node-pinned.png') await expect(comfyPage.canvas).toHaveScreenshot('node-pinned.png')
await comfyPage.rightClickEmptyLatentNode() await comfyPage.rightClickEmptyLatentNode()
await expect(comfyPage.canvas).toHaveScreenshot( await expect(comfyPage.canvas).toHaveScreenshot(
@@ -124,14 +124,17 @@ test.describe('Node Right Click Menu', { tag: ['@screenshot', '@ui'] }, () => {
await comfyPage.rightClickEmptyLatentNode() await comfyPage.rightClickEmptyLatentNode()
await comfyPage.page.click('.litemenu-entry:has-text("Unpin")') await comfyPage.page.click('.litemenu-entry:has-text("Unpin")')
await comfyPage.nextFrame() await comfyPage.nextFrame()
await comfyPage.dragAndDrop({ x: 496, y: 618 }, { x: 200, y: 590 }) await comfyPage.canvasOps.dragAndDrop(
{ x: 496, y: 618 },
{ x: 200, y: 590 }
)
await expect(comfyPage.canvas).toHaveScreenshot( await expect(comfyPage.canvas).toHaveScreenshot(
'right-click-unpinned-node-moved.png' 'right-click-unpinned-node-moved.png'
) )
}) })
test('Can pin/unpin selected nodes', async ({ comfyPage }) => { test('Can pin/unpin selected nodes', async ({ comfyPage }) => {
await comfyPage.select2Nodes() await comfyPage.nodeOps.select2Nodes()
await comfyPage.page.keyboard.down('Control') await comfyPage.page.keyboard.down('Control')
await comfyPage.rightClickEmptyLatentNode() await comfyPage.rightClickEmptyLatentNode()
await comfyPage.page.click('.litemenu-entry:has-text("Pin")') await comfyPage.page.click('.litemenu-entry:has-text("Pin")')
@@ -147,8 +150,8 @@ test.describe('Node Right Click Menu', { tag: ['@screenshot', '@ui'] }, () => {
}) })
test('Can clone pinned nodes', async ({ comfyPage }) => { test('Can clone pinned nodes', async ({ comfyPage }) => {
const nodeCount = await comfyPage.getGraphNodesCount() const nodeCount = await comfyPage.nodeOps.getGraphNodesCount()
const node = (await comfyPage.getFirstNodeRef())! const node = (await comfyPage.nodeOps.getFirstNodeRef())!
await node.clickContextMenuOption('Pin') await node.clickContextMenuOption('Pin')
await comfyPage.nextFrame() await comfyPage.nextFrame()
await node.click('title', { button: 'right' }) await node.click('title', { button: 'right' })
@@ -161,6 +164,6 @@ test.describe('Node Right Click Menu', { tag: ['@screenshot', '@ui'] }, () => {
await cloneItem.click() await cloneItem.click()
await expect(cloneItem).toHaveCount(0) await expect(cloneItem).toHaveCount(0)
await comfyPage.nextFrame() await comfyPage.nextFrame()
expect(await comfyPage.getGraphNodesCount()).toBe(nodeCount + 1) expect(await comfyPage.nodeOps.getGraphNodesCount()).toBe(nodeCount + 1)
}) })
}) })

View File

@@ -20,7 +20,10 @@ test.describe('Selection Toolbox', { tag: ['@screenshot', '@ui'] }, () => {
await expect(comfyPage.selectionToolbox).not.toBeVisible() await expect(comfyPage.selectionToolbox).not.toBeVisible()
// Select multiple nodes // Select multiple nodes
await comfyPage.selectNodes(['KSampler', 'CLIP Text Encode (Prompt)']) await comfyPage.nodeOps.selectNodes([
'KSampler',
'CLIP Text Encode (Prompt)'
])
// Selection toolbox should be visible with multiple nodes selected // Selection toolbox should be visible with multiple nodes selected
await expect(comfyPage.selectionToolbox).toBeVisible() await expect(comfyPage.selectionToolbox).toBeVisible()
@@ -34,7 +37,7 @@ test.describe('Selection Toolbox', { tag: ['@screenshot', '@ui'] }, () => {
comfyPage comfyPage
}) => { }) => {
await comfyPage.loadWorkflow('nodes/single_ksampler') await comfyPage.loadWorkflow('nodes/single_ksampler')
await comfyPage.selectNodes(['KSampler']) await comfyPage.nodeOps.selectNodes(['KSampler'])
await comfyPage.ctrlC() await comfyPage.ctrlC()
await comfyPage.page.mouse.move(100, 100) await comfyPage.page.mouse.move(100, 100)
await comfyPage.ctrlV() await comfyPage.ctrlV()
@@ -55,7 +58,7 @@ test.describe('Selection Toolbox', { tag: ['@screenshot', '@ui'] }, () => {
comfyPage comfyPage
}) => { }) => {
await comfyPage.loadWorkflow('nodes/single_ksampler') await comfyPage.loadWorkflow('nodes/single_ksampler')
const node = (await comfyPage.getNodeRefsByTitle('KSampler'))[0] const node = (await comfyPage.nodeOps.getNodeRefsByTitle('KSampler'))[0]
const nodePos = await node.getPosition() const nodePos = await node.getPosition()
// Drag on the title of the node // Drag on the title of the node
@@ -68,7 +71,7 @@ test.describe('Selection Toolbox', { tag: ['@screenshot', '@ui'] }, () => {
test('shows border only with multiple selections', async ({ comfyPage }) => { test('shows border only with multiple selections', async ({ comfyPage }) => {
// Select single node // Select single node
await comfyPage.selectNodes(['KSampler']) await comfyPage.nodeOps.selectNodes(['KSampler'])
// Selection toolbox should be visible but without border // Selection toolbox should be visible but without border
await expect(comfyPage.selectionToolbox).toBeVisible() await expect(comfyPage.selectionToolbox).toBeVisible()
@@ -78,7 +81,10 @@ test.describe('Selection Toolbox', { tag: ['@screenshot', '@ui'] }, () => {
) )
// Select multiple nodes // Select multiple nodes
await comfyPage.selectNodes(['KSampler', 'CLIP Text Encode (Prompt)']) await comfyPage.nodeOps.selectNodes([
'KSampler',
'CLIP Text Encode (Prompt)'
])
// Selection border should show with multiple selections (canvas-based) // Selection border should show with multiple selections (canvas-based)
await expect(comfyPage.canvas).toHaveScreenshot( await expect(comfyPage.canvas).toHaveScreenshot(
@@ -86,7 +92,7 @@ test.describe('Selection Toolbox', { tag: ['@screenshot', '@ui'] }, () => {
) )
// Deselect to single node // Deselect to single node
await comfyPage.selectNodes(['CLIP Text Encode (Prompt)']) await comfyPage.nodeOps.selectNodes(['CLIP Text Encode (Prompt)'])
// Border should be hidden again (canvas-based) // Border should be hidden again (canvas-based)
await expect(comfyPage.canvas).toHaveScreenshot( await expect(comfyPage.canvas).toHaveScreenshot(
@@ -110,7 +116,7 @@ test.describe('Selection Toolbox', { tag: ['@screenshot', '@ui'] }, () => {
).toBeVisible() ).toBeVisible()
// Deselect node (Only group is selected) should hide bypass button // Deselect node (Only group is selected) should hide bypass button
await comfyPage.selectNodes(['KSampler']) await comfyPage.nodeOps.selectNodes(['KSampler'])
await expect( await expect(
comfyPage.page.locator( comfyPage.page.locator(
'.selection-toolbox *[data-testid="bypass-button"]' '.selection-toolbox *[data-testid="bypass-button"]'
@@ -123,7 +129,7 @@ test.describe('Selection Toolbox', { tag: ['@screenshot', '@ui'] }, () => {
comfyPage comfyPage
}) => { }) => {
// Select a node // Select a node
await comfyPage.selectNodes(['KSampler']) await comfyPage.nodeOps.selectNodes(['KSampler'])
// Color picker button should be visible // Color picker button should be visible
const colorPickerButton = comfyPage.page.locator( const colorPickerButton = comfyPage.page.locator(
@@ -151,7 +157,9 @@ test.describe('Selection Toolbox', { tag: ['@screenshot', '@ui'] }, () => {
// Node should have the selected color class/style // Node should have the selected color class/style
// Note: Exact verification method depends on how color is applied to nodes // Note: Exact verification method depends on how color is applied to nodes
const selectedNode = (await comfyPage.getNodeRefsByTitle('KSampler'))[0] const selectedNode = (
await comfyPage.nodeOps.getNodeRefsByTitle('KSampler')
)[0]
expect(await selectedNode.getProperty('color')).not.toBeNull() expect(await selectedNode.getProperty('color')).not.toBeNull()
}) })
@@ -159,7 +167,10 @@ test.describe('Selection Toolbox', { tag: ['@screenshot', '@ui'] }, () => {
comfyPage comfyPage
}) => { }) => {
// Select multiple nodes // Select multiple nodes
await comfyPage.selectNodes(['KSampler', 'CLIP Text Encode (Prompt)']) await comfyPage.nodeOps.selectNodes([
'KSampler',
'CLIP Text Encode (Prompt)'
])
const colorPickerButton = comfyPage.page.locator( const colorPickerButton = comfyPage.page.locator(
'.selection-toolbox .pi-circle-fill' '.selection-toolbox .pi-circle-fill'
@@ -183,22 +194,25 @@ test.describe('Selection Toolbox', { tag: ['@screenshot', '@ui'] }, () => {
comfyPage comfyPage
}) => { }) => {
// Select first node and color it // Select first node and color it
await comfyPage.selectNodes(['KSampler']) await comfyPage.nodeOps.selectNodes(['KSampler'])
await comfyPage.page.locator('.selection-toolbox .pi-circle-fill').click() await comfyPage.page.locator('.selection-toolbox .pi-circle-fill').click()
await comfyPage.page await comfyPage.page
.locator('.color-picker-container i[data-testid="blue"]') .locator('.color-picker-container i[data-testid="blue"]')
.click() .click()
await comfyPage.selectNodes(['KSampler']) await comfyPage.nodeOps.selectNodes(['KSampler'])
// Select second node and color it differently // Select second node and color it differently
await comfyPage.selectNodes(['CLIP Text Encode (Prompt)']) await comfyPage.nodeOps.selectNodes(['CLIP Text Encode (Prompt)'])
await comfyPage.page.locator('.selection-toolbox .pi-circle-fill').click() await comfyPage.page.locator('.selection-toolbox .pi-circle-fill').click()
await comfyPage.page await comfyPage.page
.locator('.color-picker-container i[data-testid="red"]') .locator('.color-picker-container i[data-testid="red"]')
.click() .click()
// Select both nodes // Select both nodes
await comfyPage.selectNodes(['KSampler', 'CLIP Text Encode (Prompt)']) await comfyPage.nodeOps.selectNodes([
'KSampler',
'CLIP Text Encode (Prompt)'
])
// Color picker should show null/mixed state // Color picker should show null/mixed state
const colorPickerButton = comfyPage.page.locator( const colorPickerButton = comfyPage.page.locator(
@@ -211,17 +225,17 @@ test.describe('Selection Toolbox', { tag: ['@screenshot', '@ui'] }, () => {
comfyPage comfyPage
}) => { }) => {
// First color a node // First color a node
await comfyPage.selectNodes(['KSampler']) await comfyPage.nodeOps.selectNodes(['KSampler'])
await comfyPage.page.locator('.selection-toolbox .pi-circle-fill').click() await comfyPage.page.locator('.selection-toolbox .pi-circle-fill').click()
await comfyPage.page await comfyPage.page
.locator('.color-picker-container i[data-testid="blue"]') .locator('.color-picker-container i[data-testid="blue"]')
.click() .click()
// Clear selection // Clear selection
await comfyPage.selectNodes(['KSampler']) await comfyPage.nodeOps.selectNodes(['KSampler'])
// Re-select the node // Re-select the node
await comfyPage.selectNodes(['KSampler']) await comfyPage.nodeOps.selectNodes(['KSampler'])
// Color picker button should show the correct color // Color picker button should show the correct color
const colorPickerButton = comfyPage.page.locator( const colorPickerButton = comfyPage.page.locator(
@@ -234,7 +248,7 @@ test.describe('Selection Toolbox', { tag: ['@screenshot', '@ui'] }, () => {
comfyPage comfyPage
}) => { }) => {
// Select a node and color it // Select a node and color it
await comfyPage.selectNodes(['KSampler']) await comfyPage.nodeOps.selectNodes(['KSampler'])
await comfyPage.page.locator('.selection-toolbox .pi-circle-fill').click() await comfyPage.page.locator('.selection-toolbox .pi-circle-fill').click()
await comfyPage.page await comfyPage.page
.locator('.color-picker-container i[data-testid="blue"]') .locator('.color-picker-container i[data-testid="blue"]')
@@ -245,7 +259,9 @@ test.describe('Selection Toolbox', { tag: ['@screenshot', '@ui'] }, () => {
await comfyPage.nextFrame() await comfyPage.nextFrame()
// Node should be uncolored again // Node should be uncolored again
const selectedNode = (await comfyPage.getNodeRefsByTitle('KSampler'))[0] const selectedNode = (
await comfyPage.nodeOps.getNodeRefsByTitle('KSampler')
)[0]
expect(await selectedNode.getProperty('color')).toBeUndefined() expect(await selectedNode.getProperty('color')).toBeUndefined()
}) })
}) })

View File

@@ -15,12 +15,13 @@ test.describe(
await comfyPage.setSetting('Comfy.Canvas.SelectionToolbox', true) await comfyPage.setSetting('Comfy.Canvas.SelectionToolbox', true)
await comfyPage.loadWorkflow('nodes/single_ksampler') await comfyPage.loadWorkflow('nodes/single_ksampler')
await comfyPage.nextFrame() await comfyPage.nextFrame()
await comfyPage.selectNodes(['KSampler']) await comfyPage.nodeOps.selectNodes(['KSampler'])
await comfyPage.nextFrame() await comfyPage.nextFrame()
}) })
const openMoreOptions = async (comfyPage: ComfyPage) => { const openMoreOptions = async (comfyPage: ComfyPage) => {
const ksamplerNodes = await comfyPage.getNodeRefsByTitle('KSampler') const ksamplerNodes =
await comfyPage.nodeOps.getNodeRefsByTitle('KSampler')
if (ksamplerNodes.length === 0) { if (ksamplerNodes.length === 0) {
throw new Error('No KSampler nodes found') throw new Error('No KSampler nodes found')
} }
@@ -30,7 +31,7 @@ test.describe(
const viewportSize = comfyPage.page.viewportSize() const viewportSize = comfyPage.page.viewportSize()
const centerX = viewportSize.width / 3 const centerX = viewportSize.width / 3
const centerY = viewportSize.height / 2 const centerY = viewportSize.height / 2
await comfyPage.dragAndDrop( await comfyPage.canvasOps.dragAndDrop(
{ x: nodePos.x, y: nodePos.y }, { x: nodePos.x, y: nodePos.y },
{ x: centerX, y: centerY } { x: centerX, y: centerY }
) )
@@ -85,7 +86,9 @@ test.describe(
}) })
test('changes node shape via Shape submenu', async ({ comfyPage }) => { test('changes node shape via Shape submenu', async ({ comfyPage }) => {
const nodeRef = (await comfyPage.getNodeRefsByTitle('KSampler'))[0] const nodeRef = (
await comfyPage.nodeOps.getNodeRefsByTitle('KSampler')
)[0]
const initialShape = await nodeRef.getProperty<number>('shape') const initialShape = await nodeRef.getProperty<number>('shape')
await openMoreOptions(comfyPage) await openMoreOptions(comfyPage)
@@ -106,7 +109,9 @@ test.describe(
test('changes node color via Color submenu swatch', async ({ test('changes node color via Color submenu swatch', async ({
comfyPage comfyPage
}) => { }) => {
const nodeRef = (await comfyPage.getNodeRefsByTitle('KSampler'))[0] const nodeRef = (
await comfyPage.nodeOps.getNodeRefsByTitle('KSampler')
)[0]
const initialColor = await nodeRef.getProperty<string | undefined>( const initialColor = await nodeRef.getProperty<string | undefined>(
'color' 'color'
) )
@@ -126,7 +131,9 @@ test.describe(
}) })
test('renames a node using Rename action', async ({ comfyPage }) => { test('renames a node using Rename action', async ({ comfyPage }) => {
const nodeRef = (await comfyPage.getNodeRefsByTitle('KSampler'))[0] const nodeRef = (
await comfyPage.nodeOps.getNodeRefsByTitle('KSampler')
)[0]
await openMoreOptions(comfyPage) await openMoreOptions(comfyPage)
await comfyPage.page await comfyPage.page
.getByText('Rename', { exact: true }) .getByText('Rename', { exact: true })

View File

@@ -26,7 +26,7 @@ test.describe('Node library sidebar', () => {
) )
expect(previewVisible).toBe(true) expect(previewVisible).toBe(true)
const count = await comfyPage.getGraphNodesCount() const count = await comfyPage.nodeOps.getGraphNodesCount()
// Drag the node onto the canvas // Drag the node onto the canvas
const canvasSelector = '#graph-canvas' const canvasSelector = '#graph-canvas'
@@ -46,7 +46,7 @@ test.describe('Node library sidebar', () => {
}) })
// Verify the node is added to the canvas // Verify the node is added to the canvas
expect(await comfyPage.getGraphNodesCount()).toBe(count + 1) expect(await comfyPage.nodeOps.getGraphNodesCount()).toBe(count + 1)
}) })
test('Bookmark node', async ({ comfyPage }) => { test('Bookmark node', async ({ comfyPage }) => {

View File

@@ -80,15 +80,17 @@ test.describe('Workflows sidebar', () => {
const tab = comfyPage.menu.workflowsTab const tab = comfyPage.menu.workflowsTab
await tab.open() await tab.open()
await comfyPage.executeCommand('Comfy.LoadDefaultWorkflow') await comfyPage.executeCommand('Comfy.LoadDefaultWorkflow')
const originalNodeCount = (await comfyPage.getNodes()).length const originalNodeCount = (await comfyPage.nodeOps.getNodes()).length
await tab.insertWorkflow(tab.getPersistedItem('workflow1.json')) await tab.insertWorkflow(tab.getPersistedItem('workflow1.json'))
await comfyPage.nextFrame() await comfyPage.nextFrame()
expect((await comfyPage.getNodes()).length).toEqual(originalNodeCount + 1) expect((await comfyPage.nodeOps.getNodes()).length).toEqual(
originalNodeCount + 1
)
await tab.getPersistedItem('workflow1.json').click() await tab.getPersistedItem('workflow1.json').click()
await comfyPage.nextFrame() await comfyPage.nextFrame()
expect((await comfyPage.getNodes()).length).toEqual(1) expect((await comfyPage.nodeOps.getNodes()).length).toEqual(1)
}) })
test('Can rename nested workflow from opened workflow item', async ({ test('Can rename nested workflow from opened workflow item', async ({
@@ -345,7 +347,7 @@ test.describe('Workflows sidebar', () => {
comfyPage.menu.workflowsTab.getPersistedItem('workflow1.json') comfyPage.menu.workflowsTab.getPersistedItem('workflow1.json')
await expect(workflowItem).toBeVisible({ timeout: 3000 }) await expect(workflowItem).toBeVisible({ timeout: 3000 })
const nodeCount = await comfyPage.getGraphNodesCount() const nodeCount = await comfyPage.nodeOps.getGraphNodesCount()
// Get the bounding box of the canvas element // Get the bounding box of the canvas element
const canvasBoundingBox = (await comfyPage.page const canvasBoundingBox = (await comfyPage.page
@@ -366,7 +368,7 @@ test.describe('Workflows sidebar', () => {
// Wait for nodes to be inserted after drag-drop with retryable assertion // Wait for nodes to be inserted after drag-drop with retryable assertion
await expect await expect
.poll(() => comfyPage.getGraphNodesCount(), { timeout: 3000 }) .poll(() => comfyPage.nodeOps.getGraphNodesCount(), { timeout: 3000 })
.toBe(nodeCount * 2) .toBe(nodeCount * 2)
}) })
}) })

View File

@@ -22,7 +22,7 @@ test.describe('Subgraph Slot Rename Dialog', { tag: '@subgraph' }, () => {
}) => { }) => {
await comfyPage.loadWorkflow('subgraphs/basic-subgraph') await comfyPage.loadWorkflow('subgraphs/basic-subgraph')
const subgraphNode = await comfyPage.getNodeRefById('2') const subgraphNode = await comfyPage.nodeOps.getNodeRefById('2')
await subgraphNode.navigateIntoSubgraph() await subgraphNode.navigateIntoSubgraph()
// Get initial slot label // Get initial slot label
@@ -32,7 +32,7 @@ test.describe('Subgraph Slot Rename Dialog', { tag: '@subgraph' }, () => {
}) })
// First rename // First rename
await comfyPage.rightClickSubgraphInputSlot(initialInputLabel) await comfyPage.subgraph.rightClickInputSlot(initialInputLabel)
await comfyPage.clickLitegraphContextMenuItem('Rename Slot') await comfyPage.clickLitegraphContextMenuItem('Rename Slot')
await comfyPage.page.waitForSelector(SELECTORS.promptDialog, { await comfyPage.page.waitForSelector(SELECTORS.promptDialog, {
@@ -67,7 +67,7 @@ test.describe('Subgraph Slot Rename Dialog', { tag: '@subgraph' }, () => {
// Now rename again - this is where the bug would show // Now rename again - this is where the bug would show
// We need to use the index-based approach since the method looks for slot.name // We need to use the index-based approach since the method looks for slot.name
await comfyPage.rightClickSubgraphInputSlot() await comfyPage.subgraph.rightClickInputSlot()
await comfyPage.clickLitegraphContextMenuItem('Rename Slot') await comfyPage.clickLitegraphContextMenuItem('Rename Slot')
await comfyPage.page.waitForSelector(SELECTORS.promptDialog, { await comfyPage.page.waitForSelector(SELECTORS.promptDialog, {
@@ -108,7 +108,7 @@ test.describe('Subgraph Slot Rename Dialog', { tag: '@subgraph' }, () => {
}) => { }) => {
await comfyPage.loadWorkflow('subgraphs/basic-subgraph') await comfyPage.loadWorkflow('subgraphs/basic-subgraph')
const subgraphNode = await comfyPage.getNodeRefById('2') const subgraphNode = await comfyPage.nodeOps.getNodeRefById('2')
await subgraphNode.navigateIntoSubgraph() await subgraphNode.navigateIntoSubgraph()
// Get initial output slot label // Get initial output slot label
@@ -118,7 +118,7 @@ test.describe('Subgraph Slot Rename Dialog', { tag: '@subgraph' }, () => {
}) })
// First rename // First rename
await comfyPage.rightClickSubgraphOutputSlot(initialOutputLabel) await comfyPage.subgraph.rightClickOutputSlot(initialOutputLabel)
await comfyPage.clickLitegraphContextMenuItem('Rename Slot') await comfyPage.clickLitegraphContextMenuItem('Rename Slot')
await comfyPage.page.waitForSelector(SELECTORS.promptDialog, { await comfyPage.page.waitForSelector(SELECTORS.promptDialog, {
@@ -141,7 +141,7 @@ test.describe('Subgraph Slot Rename Dialog', { tag: '@subgraph' }, () => {
// Now rename again to check for stale content // Now rename again to check for stale content
// We need to use the index-based approach since the method looks for slot.name // We need to use the index-based approach since the method looks for slot.name
await comfyPage.rightClickSubgraphOutputSlot() await comfyPage.subgraph.rightClickOutputSlot()
await comfyPage.clickLitegraphContextMenuItem('Rename Slot') await comfyPage.clickLitegraphContextMenuItem('Rename Slot')
await comfyPage.page.waitForSelector(SELECTORS.promptDialog, { await comfyPage.page.waitForSelector(SELECTORS.promptDialog, {

View File

@@ -54,13 +54,13 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
test('Can add input slots to subgraph', async ({ comfyPage }) => { test('Can add input slots to subgraph', async ({ comfyPage }) => {
await comfyPage.loadWorkflow('subgraphs/basic-subgraph') await comfyPage.loadWorkflow('subgraphs/basic-subgraph')
const subgraphNode = await comfyPage.getNodeRefById('2') const subgraphNode = await comfyPage.nodeOps.getNodeRefById('2')
await subgraphNode.navigateIntoSubgraph() await subgraphNode.navigateIntoSubgraph()
const initialCount = await getSubgraphSlotCount(comfyPage, 'inputs') const initialCount = await getSubgraphSlotCount(comfyPage, 'inputs')
const vaeEncodeNode = await comfyPage.getNodeRefById('2') const vaeEncodeNode = await comfyPage.nodeOps.getNodeRefById('2')
await comfyPage.connectFromSubgraphInput(vaeEncodeNode, 0) await comfyPage.subgraph.connectFromInput(vaeEncodeNode, 0)
await comfyPage.nextFrame() await comfyPage.nextFrame()
const finalCount = await getSubgraphSlotCount(comfyPage, 'inputs') const finalCount = await getSubgraphSlotCount(comfyPage, 'inputs')
@@ -70,13 +70,13 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
test('Can add output slots to subgraph', async ({ comfyPage }) => { test('Can add output slots to subgraph', async ({ comfyPage }) => {
await comfyPage.loadWorkflow('subgraphs/basic-subgraph') await comfyPage.loadWorkflow('subgraphs/basic-subgraph')
const subgraphNode = await comfyPage.getNodeRefById('2') const subgraphNode = await comfyPage.nodeOps.getNodeRefById('2')
await subgraphNode.navigateIntoSubgraph() await subgraphNode.navigateIntoSubgraph()
const initialCount = await getSubgraphSlotCount(comfyPage, 'outputs') const initialCount = await getSubgraphSlotCount(comfyPage, 'outputs')
const vaeEncodeNode = await comfyPage.getNodeRefById('2') const vaeEncodeNode = await comfyPage.nodeOps.getNodeRefById('2')
await comfyPage.connectToSubgraphOutput(vaeEncodeNode, 0) await comfyPage.subgraph.connectToOutput(vaeEncodeNode, 0)
await comfyPage.nextFrame() await comfyPage.nextFrame()
const finalCount = await getSubgraphSlotCount(comfyPage, 'outputs') const finalCount = await getSubgraphSlotCount(comfyPage, 'outputs')
@@ -86,13 +86,13 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
test('Can remove input slots from subgraph', async ({ comfyPage }) => { test('Can remove input slots from subgraph', async ({ comfyPage }) => {
await comfyPage.loadWorkflow('subgraphs/basic-subgraph') await comfyPage.loadWorkflow('subgraphs/basic-subgraph')
const subgraphNode = await comfyPage.getNodeRefById('2') const subgraphNode = await comfyPage.nodeOps.getNodeRefById('2')
await subgraphNode.navigateIntoSubgraph() await subgraphNode.navigateIntoSubgraph()
const initialCount = await getSubgraphSlotCount(comfyPage, 'inputs') const initialCount = await getSubgraphSlotCount(comfyPage, 'inputs')
expect(initialCount).toBeGreaterThan(0) expect(initialCount).toBeGreaterThan(0)
await comfyPage.rightClickSubgraphInputSlot() await comfyPage.subgraph.rightClickInputSlot()
await comfyPage.clickLitegraphContextMenuItem('Remove Slot') await comfyPage.clickLitegraphContextMenuItem('Remove Slot')
// Force re-render // Force re-render
@@ -106,13 +106,13 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
test('Can remove output slots from subgraph', async ({ comfyPage }) => { test('Can remove output slots from subgraph', async ({ comfyPage }) => {
await comfyPage.loadWorkflow('subgraphs/basic-subgraph') await comfyPage.loadWorkflow('subgraphs/basic-subgraph')
const subgraphNode = await comfyPage.getNodeRefById('2') const subgraphNode = await comfyPage.nodeOps.getNodeRefById('2')
await subgraphNode.navigateIntoSubgraph() await subgraphNode.navigateIntoSubgraph()
const initialCount = await getSubgraphSlotCount(comfyPage, 'outputs') const initialCount = await getSubgraphSlotCount(comfyPage, 'outputs')
expect(initialCount).toBeGreaterThan(0) expect(initialCount).toBeGreaterThan(0)
await comfyPage.rightClickSubgraphOutputSlot() await comfyPage.subgraph.rightClickOutputSlot()
await comfyPage.clickLitegraphContextMenuItem('Remove Slot') await comfyPage.clickLitegraphContextMenuItem('Remove Slot')
// Force re-render // Force re-render
@@ -126,7 +126,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
test('Can rename I/O slots', async ({ comfyPage }) => { test('Can rename I/O slots', async ({ comfyPage }) => {
await comfyPage.loadWorkflow('subgraphs/basic-subgraph') await comfyPage.loadWorkflow('subgraphs/basic-subgraph')
const subgraphNode = await comfyPage.getNodeRefById('2') const subgraphNode = await comfyPage.nodeOps.getNodeRefById('2')
await subgraphNode.navigateIntoSubgraph() await subgraphNode.navigateIntoSubgraph()
const initialInputLabel = await comfyPage.page.evaluate(() => { const initialInputLabel = await comfyPage.page.evaluate(() => {
@@ -134,7 +134,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
return graph.inputs?.[0]?.label || null return graph.inputs?.[0]?.label || null
}) })
await comfyPage.rightClickSubgraphInputSlot(initialInputLabel) await comfyPage.subgraph.rightClickInputSlot(initialInputLabel)
await comfyPage.clickLitegraphContextMenuItem('Rename Slot') await comfyPage.clickLitegraphContextMenuItem('Rename Slot')
await comfyPage.page.waitForSelector(SELECTORS.promptDialog, { await comfyPage.page.waitForSelector(SELECTORS.promptDialog, {
@@ -159,7 +159,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
test('Can rename input slots via double-click', async ({ comfyPage }) => { test('Can rename input slots via double-click', async ({ comfyPage }) => {
await comfyPage.loadWorkflow('subgraphs/basic-subgraph') await comfyPage.loadWorkflow('subgraphs/basic-subgraph')
const subgraphNode = await comfyPage.getNodeRefById('2') const subgraphNode = await comfyPage.nodeOps.getNodeRefById('2')
await subgraphNode.navigateIntoSubgraph() await subgraphNode.navigateIntoSubgraph()
const initialInputLabel = await comfyPage.page.evaluate(() => { const initialInputLabel = await comfyPage.page.evaluate(() => {
@@ -167,7 +167,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
return graph.inputs?.[0]?.label || null return graph.inputs?.[0]?.label || null
}) })
await comfyPage.doubleClickSubgraphInputSlot(initialInputLabel) await comfyPage.subgraph.doubleClickInputSlot(initialInputLabel)
await comfyPage.page.waitForSelector(SELECTORS.promptDialog, { await comfyPage.page.waitForSelector(SELECTORS.promptDialog, {
state: 'visible' state: 'visible'
@@ -191,7 +191,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
test('Can rename output slots via double-click', async ({ comfyPage }) => { test('Can rename output slots via double-click', async ({ comfyPage }) => {
await comfyPage.loadWorkflow('subgraphs/basic-subgraph') await comfyPage.loadWorkflow('subgraphs/basic-subgraph')
const subgraphNode = await comfyPage.getNodeRefById('2') const subgraphNode = await comfyPage.nodeOps.getNodeRefById('2')
await subgraphNode.navigateIntoSubgraph() await subgraphNode.navigateIntoSubgraph()
const initialOutputLabel = await comfyPage.page.evaluate(() => { const initialOutputLabel = await comfyPage.page.evaluate(() => {
@@ -199,7 +199,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
return graph.outputs?.[0]?.label || null return graph.outputs?.[0]?.label || null
}) })
await comfyPage.doubleClickSubgraphOutputSlot(initialOutputLabel) await comfyPage.subgraph.doubleClickOutputSlot(initialOutputLabel)
await comfyPage.page.waitForSelector(SELECTORS.promptDialog, { await comfyPage.page.waitForSelector(SELECTORS.promptDialog, {
state: 'visible' state: 'visible'
@@ -226,7 +226,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
}) => { }) => {
await comfyPage.loadWorkflow('subgraphs/basic-subgraph') await comfyPage.loadWorkflow('subgraphs/basic-subgraph')
const subgraphNode = await comfyPage.getNodeRefById('2') const subgraphNode = await comfyPage.nodeOps.getNodeRefById('2')
await subgraphNode.navigateIntoSubgraph() await subgraphNode.navigateIntoSubgraph()
const initialInputLabel = await comfyPage.page.evaluate(() => { const initialInputLabel = await comfyPage.page.evaluate(() => {
@@ -235,7 +235,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
}) })
// Test that right-click still works for renaming // Test that right-click still works for renaming
await comfyPage.rightClickSubgraphInputSlot(initialInputLabel) await comfyPage.subgraph.rightClickInputSlot(initialInputLabel)
await comfyPage.clickLitegraphContextMenuItem('Rename Slot') await comfyPage.clickLitegraphContextMenuItem('Rename Slot')
await comfyPage.page.waitForSelector(SELECTORS.promptDialog, { await comfyPage.page.waitForSelector(SELECTORS.promptDialog, {
@@ -263,7 +263,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
}) => { }) => {
await comfyPage.loadWorkflow('subgraphs/basic-subgraph') await comfyPage.loadWorkflow('subgraphs/basic-subgraph')
const subgraphNode = await comfyPage.getNodeRefById('2') const subgraphNode = await comfyPage.nodeOps.getNodeRefById('2')
await subgraphNode.navigateIntoSubgraph() await subgraphNode.navigateIntoSubgraph()
const initialInputLabel = await comfyPage.page.evaluate(() => { const initialInputLabel = await comfyPage.page.evaluate(() => {
@@ -349,12 +349,12 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
await comfyPage.ctrlA() await comfyPage.ctrlA()
await comfyPage.nextFrame() await comfyPage.nextFrame()
const node = await comfyPage.getNodeRefById('5') const node = await comfyPage.nodeOps.getNodeRefById('5')
await node.convertToSubgraph() await node.convertToSubgraph()
await comfyPage.nextFrame() await comfyPage.nextFrame()
const subgraphNodes = const subgraphNodes =
await comfyPage.getNodeRefsByTitle(NEW_SUBGRAPH_TITLE) await comfyPage.nodeOps.getNodeRefsByTitle(NEW_SUBGRAPH_TITLE)
expect(subgraphNodes.length).toBe(1) expect(subgraphNodes.length).toBe(1)
const finalNodeCount = await getGraphNodeCount(comfyPage) const finalNodeCount = await getGraphNodeCount(comfyPage)
@@ -364,7 +364,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
test('Can delete subgraph node', async ({ comfyPage }) => { test('Can delete subgraph node', async ({ comfyPage }) => {
await comfyPage.loadWorkflow('subgraphs/basic-subgraph') await comfyPage.loadWorkflow('subgraphs/basic-subgraph')
const subgraphNode = await comfyPage.getNodeRefById('2') const subgraphNode = await comfyPage.nodeOps.getNodeRefById('2')
expect(await subgraphNode.exists()).toBe(true) expect(await subgraphNode.exists()).toBe(true)
const initialNodeCount = await getGraphNodeCount(comfyPage) const initialNodeCount = await getGraphNodeCount(comfyPage)
@@ -376,7 +376,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
const finalNodeCount = await getGraphNodeCount(comfyPage) const finalNodeCount = await getGraphNodeCount(comfyPage)
expect(finalNodeCount).toBe(initialNodeCount - 1) expect(finalNodeCount).toBe(initialNodeCount - 1)
const deletedNode = await comfyPage.getNodeRefById('2') const deletedNode = await comfyPage.nodeOps.getNodeRefById('2')
expect(await deletedNode.exists()).toBe(false) expect(await deletedNode.exists()).toBe(false)
}) })
@@ -386,7 +386,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
}) => { }) => {
await comfyPage.loadWorkflow('subgraphs/basic-subgraph') await comfyPage.loadWorkflow('subgraphs/basic-subgraph')
const subgraphNode = await comfyPage.getNodeRefById('2') const subgraphNode = await comfyPage.nodeOps.getNodeRefById('2')
// Get position of subgraph node // Get position of subgraph node
const subgraphPos = await subgraphNode.getPosition() const subgraphPos = await subgraphNode.getPosition()
@@ -404,7 +404,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
// Find all subgraph nodes // Find all subgraph nodes
const subgraphNodes = const subgraphNodes =
await comfyPage.getNodeRefsByTitle(NEW_SUBGRAPH_TITLE) await comfyPage.nodeOps.getNodeRefsByTitle(NEW_SUBGRAPH_TITLE)
// Expect a second subgraph node to be created (2 total) // Expect a second subgraph node to be created (2 total)
expect(subgraphNodes.length).toBe(2) expect(subgraphNodes.length).toBe(2)
@@ -415,7 +415,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
}) => { }) => {
await comfyPage.loadWorkflow('subgraphs/basic-subgraph') await comfyPage.loadWorkflow('subgraphs/basic-subgraph')
const subgraphNode = await comfyPage.getNodeRefById('2') const subgraphNode = await comfyPage.nodeOps.getNodeRefById('2')
// Get position of subgraph node // Get position of subgraph node
const subgraphPos = await subgraphNode.getPosition() const subgraphPos = await subgraphNode.getPosition()
@@ -433,7 +433,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
// Find all subgraph nodes and expect all unique IDs // Find all subgraph nodes and expect all unique IDs
const subgraphNodes = const subgraphNodes =
await comfyPage.getNodeRefsByTitle(NEW_SUBGRAPH_TITLE) await comfyPage.nodeOps.getNodeRefsByTitle(NEW_SUBGRAPH_TITLE)
// Expect the second subgraph node to have a unique type // Expect the second subgraph node to have a unique type
const nodeType1 = await subgraphNodes[0].getType() const nodeType1 = await subgraphNodes[0].getType()
@@ -447,7 +447,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
test('Can copy and paste nodes in subgraph', async ({ comfyPage }) => { test('Can copy and paste nodes in subgraph', async ({ comfyPage }) => {
await comfyPage.loadWorkflow('subgraphs/basic-subgraph') await comfyPage.loadWorkflow('subgraphs/basic-subgraph')
const subgraphNode = await comfyPage.getNodeRefById('2') const subgraphNode = await comfyPage.nodeOps.getNodeRefById('2')
await subgraphNode.navigateIntoSubgraph() await subgraphNode.navigateIntoSubgraph()
const initialNodeCount = await getGraphNodeCount(comfyPage) const initialNodeCount = await getGraphNodeCount(comfyPage)
@@ -459,7 +459,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
expect(nodesInSubgraph).not.toBeNull() expect(nodesInSubgraph).not.toBeNull()
const nodeToClone = await comfyPage.getNodeRefById( const nodeToClone = await comfyPage.nodeOps.getNodeRefById(
String(nodesInSubgraph) String(nodesInSubgraph)
) )
await nodeToClone.click('title') await nodeToClone.click('title')
@@ -478,11 +478,11 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
test('Can undo and redo operations in subgraph', async ({ comfyPage }) => { test('Can undo and redo operations in subgraph', async ({ comfyPage }) => {
await comfyPage.loadWorkflow('subgraphs/basic-subgraph') await comfyPage.loadWorkflow('subgraphs/basic-subgraph')
const subgraphNode = await comfyPage.getNodeRefById('2') const subgraphNode = await comfyPage.nodeOps.getNodeRefById('2')
await subgraphNode.navigateIntoSubgraph() await subgraphNode.navigateIntoSubgraph()
// Add a node // Add a node
await comfyPage.doubleClickCanvas() await comfyPage.canvasOps.doubleClick()
await comfyPage.searchBox.fillAndSelectFirstNode('Note') await comfyPage.searchBox.fillAndSelectFirstNode('Note')
await comfyPage.nextFrame() await comfyPage.nextFrame()
@@ -516,7 +516,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
await comfyPage.loadWorkflow('subgraphs/nested-subgraph') await comfyPage.loadWorkflow('subgraphs/nested-subgraph')
await comfyPage.nextFrame() await comfyPage.nextFrame()
const subgraphNode = await comfyPage.getNodeRefById('10') const subgraphNode = await comfyPage.nodeOps.getNodeRefById('10')
const nodePos = await subgraphNode.getPosition() const nodePos = await subgraphNode.getPosition()
const nodeSize = await subgraphNode.getSize() const nodeSize = await subgraphNode.getSize()
@@ -575,7 +575,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
await expect(parentTextarea).toBeVisible() await expect(parentTextarea).toBeVisible()
await expect(parentTextarea).toHaveCount(1) await expect(parentTextarea).toHaveCount(1)
const subgraphNode = await comfyPage.getNodeRefById('11') const subgraphNode = await comfyPage.nodeOps.getNodeRefById('11')
expect(await subgraphNode.exists()).toBe(true) expect(await subgraphNode.exists()).toBe(true)
await subgraphNode.navigateIntoSubgraph() await subgraphNode.navigateIntoSubgraph()
@@ -605,7 +605,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
const textarea = comfyPage.page.locator(SELECTORS.domWidget) const textarea = comfyPage.page.locator(SELECTORS.domWidget)
await textarea.fill(TEST_WIDGET_CONTENT) await textarea.fill(TEST_WIDGET_CONTENT)
const subgraphNode = await comfyPage.getNodeRefById('11') const subgraphNode = await comfyPage.nodeOps.getNodeRefById('11')
await subgraphNode.navigateIntoSubgraph() await subgraphNode.navigateIntoSubgraph()
const subgraphTextarea = comfyPage.page.locator(SELECTORS.domWidget) const subgraphTextarea = comfyPage.page.locator(SELECTORS.domWidget)
@@ -630,7 +630,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
.count() .count()
expect(initialCount).toBe(1) expect(initialCount).toBe(1)
const subgraphNode = await comfyPage.getNodeRefById('11') const subgraphNode = await comfyPage.nodeOps.getNodeRefById('11')
await subgraphNode.click('title') await subgraphNode.click('title')
await comfyPage.page.keyboard.press('Delete') await comfyPage.page.keyboard.press('Delete')
@@ -656,12 +656,12 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
.count() .count()
expect(textareaCount).toBe(1) expect(textareaCount).toBe(1)
const subgraphNode = await comfyPage.getNodeRefById('11') const subgraphNode = await comfyPage.nodeOps.getNodeRefById('11')
// Navigate into subgraph (method now handles retries internally) // Navigate into subgraph (method now handles retries internally)
await subgraphNode.navigateIntoSubgraph() await subgraphNode.navigateIntoSubgraph()
await comfyPage.rightClickSubgraphInputSlot('text') await comfyPage.subgraph.rightClickInputSlot('text')
await comfyPage.clickLitegraphContextMenuItem('Remove Slot') await comfyPage.clickLitegraphContextMenuItem('Remove Slot')
// Wait for breadcrumb to be visible // Wait for breadcrumb to be visible
@@ -700,7 +700,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
.count() .count()
expect(parentCount).toBeGreaterThan(1) expect(parentCount).toBeGreaterThan(1)
const subgraphNode = await comfyPage.getNodeRefById('11') const subgraphNode = await comfyPage.nodeOps.getNodeRefById('11')
await subgraphNode.navigateIntoSubgraph() await subgraphNode.navigateIntoSubgraph()
const subgraphCount = await comfyPage.page const subgraphCount = await comfyPage.page
@@ -757,7 +757,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
await comfyPage.setup() await comfyPage.setup()
// Navigate into subgraph // Navigate into subgraph
const subgraphNode = await comfyPage.getNodeRefById('2') const subgraphNode = await comfyPage.nodeOps.getNodeRefById('2')
await subgraphNode.navigateIntoSubgraph() await subgraphNode.navigateIntoSubgraph()
await comfyPage.page.waitForSelector(SELECTORS.breadcrumb) await comfyPage.page.waitForSelector(SELECTORS.breadcrumb)
@@ -783,7 +783,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
await comfyPage.loadWorkflow('subgraphs/basic-subgraph') await comfyPage.loadWorkflow('subgraphs/basic-subgraph')
await comfyPage.nextFrame() await comfyPage.nextFrame()
const subgraphNode = await comfyPage.getNodeRefById('2') const subgraphNode = await comfyPage.nodeOps.getNodeRefById('2')
await subgraphNode.navigateIntoSubgraph() await subgraphNode.navigateIntoSubgraph()
await comfyPage.page.waitForSelector(SELECTORS.breadcrumb) await comfyPage.page.waitForSelector(SELECTORS.breadcrumb)

View File

@@ -74,7 +74,7 @@ test.describe('Templates', { tag: ['@slow', '@workflow'] }, () => {
await comfyPage.menu.workflowsTab.open() await comfyPage.menu.workflowsTab.open()
await comfyPage.executeCommand('Comfy.NewBlankWorkflow') await comfyPage.executeCommand('Comfy.NewBlankWorkflow')
await expect(async () => { await expect(async () => {
expect(await comfyPage.getGraphNodesCount()).toBe(0) expect(await comfyPage.nodeOps.getGraphNodesCount()).toBe(0)
}).toPass({ timeout: 250 }) }).toPass({ timeout: 250 })
// Load a template // Load a template
@@ -89,7 +89,7 @@ test.describe('Templates', { tag: ['@slow', '@workflow'] }, () => {
// Ensure we now have some nodes // Ensure we now have some nodes
await expect(async () => { await expect(async () => {
expect(await comfyPage.getGraphNodesCount()).toBeGreaterThan(0) expect(await comfyPage.nodeOps.getGraphNodesCount()).toBeGreaterThan(0)
}).toPass({ timeout: 250 }) }).toPass({ timeout: 250 })
}) })

View File

@@ -13,7 +13,10 @@ test.describe('Vue Nodes Canvas Pan', () => {
'@mobile Can pan with touch', '@mobile Can pan with touch',
{ tag: '@screenshot' }, { tag: '@screenshot' },
async ({ comfyPage }) => { async ({ comfyPage }) => {
await comfyPage.panWithTouch({ x: 64, y: 64 }, { x: 256, y: 256 }) await comfyPage.canvasOps.panWithTouch(
{ x: 64, y: 64 },
{ x: 256, y: 256 }
)
await expect(comfyPage.canvas).toHaveScreenshot( await expect(comfyPage.canvas).toHaveScreenshot(
'vue-nodes-paned-with-touch.png' 'vue-nodes-paned-with-touch.png'
) )

View File

@@ -26,7 +26,7 @@ test.describe('Vue Nodes Zoom', () => {
// the node. The node should not capture the drag while drag-zooming. // the node. The node should not capture the drag while drag-zooming.
await comfyPage.page.keyboard.down('Control') await comfyPage.page.keyboard.down('Control')
await comfyPage.page.keyboard.down('Shift') await comfyPage.page.keyboard.down('Shift')
await comfyPage.dragAndDrop( await comfyPage.canvasOps.dragAndDrop(
{ x: 200, y: 300 }, { x: 200, y: 300 },
{ x: nodeMidpointX, y: nodeMidpointY } { x: nodeMidpointX, y: nodeMidpointY }
) )

View File

@@ -112,7 +112,9 @@ test.describe('Vue Node Link Interaction', { tag: '@screenshot' }, () => {
comfyPage, comfyPage,
comfyMouse comfyMouse
}) => { }) => {
const samplerNode = (await comfyPage.getNodeRefsByType('KSampler'))[0] const samplerNode = (
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
)[0]
expect(samplerNode).toBeTruthy() expect(samplerNode).toBeTruthy()
const slot = slotLocator(comfyPage.page, samplerNode.id, 0, false) const slot = slotLocator(comfyPage.page, samplerNode.id, 0, false)
@@ -142,8 +144,10 @@ test.describe('Vue Node Link Interaction', { tag: '@screenshot' }, () => {
test('should create a link when dropping on a compatible slot', async ({ test('should create a link when dropping on a compatible slot', async ({
comfyPage comfyPage
}) => { }) => {
const samplerNode = (await comfyPage.getNodeRefsByType('KSampler'))[0] const samplerNode = (
const vaeNode = (await comfyPage.getNodeRefsByType('VAEDecode'))[0] await comfyPage.nodeOps.getNodeRefsByType('KSampler')
)[0]
const vaeNode = (await comfyPage.nodeOps.getNodeRefsByType('VAEDecode'))[0]
expect(samplerNode && vaeNode).toBeTruthy() expect(samplerNode && vaeNode).toBeTruthy()
const samplerOutput = await samplerNode.getOutput(0) const samplerOutput = await samplerNode.getOutput(0)
@@ -172,8 +176,12 @@ test.describe('Vue Node Link Interaction', { tag: '@screenshot' }, () => {
test('should not create a link when slot types are incompatible', async ({ test('should not create a link when slot types are incompatible', async ({
comfyPage comfyPage
}) => { }) => {
const samplerNode = (await comfyPage.getNodeRefsByType('KSampler'))[0] const samplerNode = (
const clipNode = (await comfyPage.getNodeRefsByType('CLIPTextEncode'))[0] await comfyPage.nodeOps.getNodeRefsByType('KSampler')
)[0]
const clipNode = (
await comfyPage.nodeOps.getNodeRefsByType('CLIPTextEncode')
)[0]
expect(samplerNode && clipNode).toBeTruthy() expect(samplerNode && clipNode).toBeTruthy()
const samplerOutput = await samplerNode.getOutput(0) const samplerOutput = await samplerNode.getOutput(0)
@@ -200,7 +208,9 @@ test.describe('Vue Node Link Interaction', { tag: '@screenshot' }, () => {
test('should not create a link when dropping onto a slot on the same node', async ({ test('should not create a link when dropping onto a slot on the same node', async ({
comfyPage comfyPage
}) => { }) => {
const samplerNode = (await comfyPage.getNodeRefsByType('KSampler'))[0] const samplerNode = (
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
)[0]
expect(samplerNode).toBeTruthy() expect(samplerNode).toBeTruthy()
const samplerOutput = await samplerNode.getOutput(0) const samplerOutput = await samplerNode.getOutput(0)
@@ -221,8 +231,10 @@ test.describe('Vue Node Link Interaction', { tag: '@screenshot' }, () => {
comfyPage, comfyPage,
comfyMouse comfyMouse
}) => { }) => {
const samplerNode = (await comfyPage.getNodeRefsByType('KSampler'))[0] const samplerNode = (
const vaeNode = (await comfyPage.getNodeRefsByType('VAEDecode'))[0] await comfyPage.nodeOps.getNodeRefsByType('KSampler')
)[0]
const vaeNode = (await comfyPage.nodeOps.getNodeRefsByType('VAEDecode'))[0]
expect(samplerNode && vaeNode).toBeTruthy() expect(samplerNode && vaeNode).toBeTruthy()
const samplerOutputCenter = await getSlotCenter( const samplerOutputCenter = await getSlotCenter(
comfyPage.page, comfyPage.page,
@@ -258,8 +270,10 @@ test.describe('Vue Node Link Interaction', { tag: '@screenshot' }, () => {
comfyPage, comfyPage,
comfyMouse comfyMouse
}) => { }) => {
const samplerNode = (await comfyPage.getNodeRefsByType('KSampler'))[0] const samplerNode = (
const vaeNode = (await comfyPage.getNodeRefsByType('VAEDecode'))[0] await comfyPage.nodeOps.getNodeRefsByType('KSampler')
)[0]
const vaeNode = (await comfyPage.nodeOps.getNodeRefsByType('VAEDecode'))[0]
expect(samplerNode && vaeNode).toBeTruthy() expect(samplerNode && vaeNode).toBeTruthy()
const samplerOutput = await samplerNode.getOutput(0) const samplerOutput = await samplerNode.getOutput(0)
@@ -315,8 +329,10 @@ test.describe('Vue Node Link Interaction', { tag: '@screenshot' }, () => {
comfyPage, comfyPage,
comfyMouse comfyMouse
}) => { }) => {
const samplerNode = (await comfyPage.getNodeRefsByType('KSampler'))[0] const samplerNode = (
const vaeNode = (await comfyPage.getNodeRefsByType('VAEDecode'))[0] await comfyPage.nodeOps.getNodeRefsByType('KSampler')
)[0]
const vaeNode = (await comfyPage.nodeOps.getNodeRefsByType('VAEDecode'))[0]
expect(samplerNode && vaeNode).toBeTruthy() expect(samplerNode && vaeNode).toBeTruthy()
const samplerOutput = await samplerNode.getOutput(0) const samplerOutput = await samplerNode.getOutput(0)
@@ -398,8 +414,10 @@ test.describe('Vue Node Link Interaction', { tag: '@screenshot' }, () => {
comfyPage, comfyPage,
comfyMouse comfyMouse
}) => { }) => {
const samplerNode = (await comfyPage.getNodeRefsByType('KSampler'))[0] const samplerNode = (
const vaeNode = (await comfyPage.getNodeRefsByType('VAEDecode'))[0] await comfyPage.nodeOps.getNodeRefsByType('KSampler')
)[0]
const vaeNode = (await comfyPage.nodeOps.getNodeRefsByType('VAEDecode'))[0]
const samplerOutput = await samplerNode.getOutput(0) const samplerOutput = await samplerNode.getOutput(0)
const vaeInput = await vaeNode.getInput(0) const vaeInput = await vaeNode.getInput(0)
@@ -483,8 +501,10 @@ test.describe('Vue Node Link Interaction', { tag: '@screenshot' }, () => {
comfyPage, comfyPage,
comfyMouse comfyMouse
}) => { }) => {
const samplerNode = (await comfyPage.getNodeRefsByType('KSampler'))[0] const samplerNode = (
const vaeNode = (await comfyPage.getNodeRefsByType('VAEDecode'))[0] await comfyPage.nodeOps.getNodeRefsByType('KSampler')
)[0]
const vaeNode = (await comfyPage.nodeOps.getNodeRefsByType('VAEDecode'))[0]
expect(samplerNode && vaeNode).toBeTruthy() expect(samplerNode && vaeNode).toBeTruthy()
const samplerOutput = await samplerNode.getOutput(0) const samplerOutput = await samplerNode.getOutput(0)
@@ -572,8 +592,12 @@ test.describe('Vue Node Link Interaction', { tag: '@screenshot' }, () => {
comfyPage, comfyPage,
comfyMouse comfyMouse
}) => { }) => {
const clipNode = (await comfyPage.getNodeRefsByType('CLIPTextEncode'))[0] const clipNode = (
const samplerNode = (await comfyPage.getNodeRefsByType('KSampler'))[0] await comfyPage.nodeOps.getNodeRefsByType('CLIPTextEncode')
)[0]
const samplerNode = (
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
)[0]
expect(clipNode && samplerNode).toBeTruthy() expect(clipNode && samplerNode).toBeTruthy()
// Step 1: Connect CLIP's only output (index 0) to KSampler's second input (index 1) // Step 1: Connect CLIP's only output (index 0) to KSampler's second input (index 1)
@@ -642,8 +666,12 @@ test.describe('Vue Node Link Interaction', { tag: '@screenshot' }, () => {
comfyPage, comfyPage,
comfyMouse comfyMouse
}) => { }) => {
const clipNode = (await comfyPage.getNodeRefsByType('CLIPTextEncode'))[0] const clipNode = (
const samplerNode = (await comfyPage.getNodeRefsByType('KSampler'))[0] await comfyPage.nodeOps.getNodeRefsByType('CLIPTextEncode')
)[0]
const samplerNode = (
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
)[0]
expect(clipNode && samplerNode).toBeTruthy() expect(clipNode && samplerNode).toBeTruthy()
const clipOutput = await clipNode.getOutput(0) const clipOutput = await clipNode.getOutput(0)
@@ -697,8 +725,12 @@ test.describe('Vue Node Link Interaction', { tag: '@screenshot' }, () => {
comfyPage, comfyPage,
comfyMouse comfyMouse
}) => { }) => {
const clipNode = (await comfyPage.getNodeRefsByType('CLIPTextEncode'))[0] const clipNode = (
const samplerNode = (await comfyPage.getNodeRefsByType('KSampler'))[0] await comfyPage.nodeOps.getNodeRefsByType('CLIPTextEncode')
)[0]
const samplerNode = (
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
)[0]
expect(clipNode && samplerNode).toBeTruthy() expect(clipNode && samplerNode).toBeTruthy()
// Start drag from CLIP output[0] // Start drag from CLIP output[0]
@@ -746,8 +778,12 @@ test.describe('Vue Node Link Interaction', { tag: '@screenshot' }, () => {
comfyPage, comfyPage,
comfyMouse comfyMouse
}) => { }) => {
const clipNode = (await comfyPage.getNodeRefsByType('CLIPTextEncode'))[0] const clipNode = (
const samplerNode = (await comfyPage.getNodeRefsByType('KSampler'))[0] await comfyPage.nodeOps.getNodeRefsByType('CLIPTextEncode')
)[0]
const samplerNode = (
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
)[0]
expect(clipNode && samplerNode).toBeTruthy() expect(clipNode && samplerNode).toBeTruthy()
// Drag from CLIP output[0] to KSampler input[2] (third slot) which is the // Drag from CLIP output[0] to KSampler input[2] (third slot) which is the
@@ -791,8 +827,12 @@ test.describe('Vue Node Link Interaction', { tag: '@screenshot' }, () => {
test('should batch disconnect all links with ctrl+alt+click on slot', async ({ test('should batch disconnect all links with ctrl+alt+click on slot', async ({
comfyPage comfyPage
}) => { }) => {
const clipNode = (await comfyPage.getNodeRefsByType('CLIPTextEncode'))[0] const clipNode = (
const samplerNode = (await comfyPage.getNodeRefsByType('KSampler'))[0] await comfyPage.nodeOps.getNodeRefsByType('CLIPTextEncode')
)[0]
const samplerNode = (
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
)[0]
expect(clipNode && samplerNode).toBeTruthy() expect(clipNode && samplerNode).toBeTruthy()
await connectSlots( await connectSlots(
@@ -837,7 +877,9 @@ test.describe('Vue Node Link Interaction', { tag: '@screenshot' }, () => {
'context menu' 'context menu'
) )
const samplerNode = (await comfyPage.getNodeRefsByType('KSampler'))[0] const samplerNode = (
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
)[0]
expect(samplerNode).toBeTruthy() expect(samplerNode).toBeTruthy()
const outputCenter = await getSlotCenter( const outputCenter = await getSlotCenter(
@@ -888,7 +930,9 @@ test.describe('Vue Node Link Interaction', { tag: '@screenshot' }, () => {
) )
await comfyPage.setSetting('Comfy.NodeSearchBoxImpl', 'default') await comfyPage.setSetting('Comfy.NodeSearchBoxImpl', 'default')
const samplerNode = (await comfyPage.getNodeRefsByType('KSampler'))[0] const samplerNode = (
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
)[0]
expect(samplerNode).toBeTruthy() expect(samplerNode).toBeTruthy()
const outputCenter = await getSlotCenter( const outputCenter = await getSlotCenter(
@@ -928,7 +972,7 @@ test.describe('Vue Node Link Interaction', { tag: '@screenshot' }, () => {
expect(await samplerOutput.getLinkCount()).toBe(1) expect(await samplerOutput.getLinkCount()).toBe(1)
// One of the VAEDecode nodes should have an incoming link on input[0] // One of the VAEDecode nodes should have an incoming link on input[0]
const vaeNodes = await comfyPage.getNodeRefsByType('VAEDecode') const vaeNodes = await comfyPage.nodeOps.getNodeRefsByType('VAEDecode')
let linked = false let linked = false
for (const vae of vaeNodes) { for (const vae of vaeNodes) {
const details = await getInputLinkDetails(comfyPage.page, vae.id, 0) const details = await getInputLinkDetails(comfyPage.page, vae.id, 0)
@@ -947,7 +991,9 @@ test.describe('Vue Node Link Interaction', { tag: '@screenshot' }, () => {
}) => { }) => {
await comfyPage.setSetting('Comfy.LinkRelease.ActionShift', 'search box') await comfyPage.setSetting('Comfy.LinkRelease.ActionShift', 'search box')
const samplerNode = (await comfyPage.getNodeRefsByType('KSampler'))[0] const samplerNode = (
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
)[0]
expect(samplerNode).toBeTruthy() expect(samplerNode).toBeTruthy()
const outputCenter = await getSlotCenter( const outputCenter = await getSlotCenter(
@@ -980,7 +1026,7 @@ test.describe('Vue Node Link Interaction', { tag: '@screenshot' }, () => {
const samplerOutput = await samplerNode.getOutput(0) const samplerOutput = await samplerNode.getOutput(0)
expect(await samplerOutput.getLinkCount()).toBe(1) expect(await samplerOutput.getLinkCount()).toBe(1)
const vaeNodes = await comfyPage.getNodeRefsByType('VAEDecode') const vaeNodes = await comfyPage.nodeOps.getNodeRefsByType('VAEDecode')
let linked = false let linked = false
for (const vae of vaeNodes) { for (const vae of vaeNodes) {
const details = await getInputLinkDetails(comfyPage.page, vae.id, 0) const details = await getInputLinkDetails(comfyPage.page, vae.id, 0)
@@ -1007,7 +1053,9 @@ test.describe('Vue Node Link Interaction', { tag: '@screenshot' }, () => {
await comfyPage.waitForGraphNodes(1) await comfyPage.waitForGraphNodes(1)
// Convert the KSampler node to a subgraph // Convert the KSampler node to a subgraph
let ksamplerNode = (await comfyPage.getNodeRefsByType('KSampler'))?.[0] let ksamplerNode = (
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
)?.[0]
await comfyPage.vueNodes.selectNode(String(ksamplerNode.id)) await comfyPage.vueNodes.selectNode(String(ksamplerNode.id))
await comfyPage.executeCommand('Comfy.Graph.ConvertToSubgraph') await comfyPage.executeCommand('Comfy.Graph.ConvertToSubgraph')
@@ -1016,7 +1064,9 @@ test.describe('Vue Node Link Interaction', { tag: '@screenshot' }, () => {
await fitToViewInstant(comfyPage) await fitToViewInstant(comfyPage)
// Get the KSampler node inside the subgraph // Get the KSampler node inside the subgraph
ksamplerNode = (await comfyPage.getNodeRefsByType('KSampler', true))?.[0] ksamplerNode = (
await comfyPage.nodeOps.getNodeRefsByType('KSampler', true)
)?.[0]
const positiveInput = await ksamplerNode.getInput(1) const positiveInput = await ksamplerNode.getInput(1)
const negativeInput = await ksamplerNode.getInput(2) const negativeInput = await ksamplerNode.getInput(2)
@@ -1027,7 +1077,7 @@ test.describe('Vue Node Link Interaction', { tag: '@screenshot' }, () => {
true true
) )
const sourceSlot = await comfyPage.getSubgraphInputSlot() const sourceSlot = await comfyPage.subgraph.getInputSlot()
const calculatedSourcePos = await sourceSlot.getOpenSlotPosition() const calculatedSourcePos = await sourceSlot.getOpenSlotPosition()
await comfyMouse.move(calculatedSourcePos) await comfyMouse.move(calculatedSourcePos)

View File

@@ -61,7 +61,7 @@ test.describe('Vue Node Bring to Front', { tag: '@screenshot' }, () => {
if (!ksamplerHeader) throw new Error('KSampler header not found') if (!ksamplerHeader) throw new Error('KSampler header not found')
// Drag KSampler on top of CLIP Text Encode // Drag KSampler on top of CLIP Text Encode
await comfyPage.dragAndDrop( await comfyPage.canvasOps.dragAndDrop(
{ x: ksamplerHeader.x + 50, y: ksamplerHeader.y + 10 }, { x: ksamplerHeader.x + 50, y: ksamplerHeader.y + 10 },
clipCenter clipCenter
) )
@@ -108,7 +108,7 @@ test.describe('Vue Node Bring to Front', { tag: '@screenshot' }, () => {
const vaeHeader = await comfyPage.page.getByText('VAE Decode').boundingBox() const vaeHeader = await comfyPage.page.getByText('VAE Decode').boundingBox()
if (!vaeHeader) throw new Error('VAE Decode header not found') if (!vaeHeader) throw new Error('VAE Decode header not found')
await comfyPage.dragAndDrop( await comfyPage.canvasOps.dragAndDrop(
{ x: vaeHeader.x + 50, y: vaeHeader.y + 10 }, { x: vaeHeader.x + 50, y: vaeHeader.y + 10 },
{ x: clipCenter.x - 50, y: clipCenter.y } { x: clipCenter.x - 50, y: clipCenter.y }
) )

View File

@@ -35,7 +35,7 @@ test.describe('Vue Node Moving', () => {
async ({ comfyPage }) => { async ({ comfyPage }) => {
const loadCheckpointHeaderPos = const loadCheckpointHeaderPos =
await getLoadCheckpointHeaderPos(comfyPage) await getLoadCheckpointHeaderPos(comfyPage)
await comfyPage.dragAndDrop(loadCheckpointHeaderPos, { await comfyPage.canvasOps.dragAndDrop(loadCheckpointHeaderPos, {
x: 256, x: 256,
y: 256 y: 256
}) })
@@ -56,7 +56,7 @@ test.describe('Vue Node Moving', () => {
const loadCheckpointHeaderPos = const loadCheckpointHeaderPos =
await getLoadCheckpointHeaderPos(comfyPage) await getLoadCheckpointHeaderPos(comfyPage)
await comfyPage.panWithTouch( await comfyPage.canvasOps.panWithTouch(
{ {
x: 64, x: 64,
y: 64 y: 64

View File

@@ -83,7 +83,7 @@ test.describe('Vue Nodes - Delete Key Interaction', () => {
test('Delete key does not delete node when typing in Vue node widgets', async ({ test('Delete key does not delete node when typing in Vue node widgets', async ({
comfyPage comfyPage
}) => { }) => {
const initialNodeCount = await comfyPage.getGraphNodesCount() const initialNodeCount = await comfyPage.nodeOps.getGraphNodesCount()
// Find a text input widget in a Vue node // Find a text input widget in a Vue node
const textWidget = comfyPage.page const textWidget = comfyPage.page
@@ -98,7 +98,7 @@ test.describe('Vue Nodes - Delete Key Interaction', () => {
await textWidget.press('Delete') await textWidget.press('Delete')
// Node count should remain the same // Node count should remain the same
const finalNodeCount = await comfyPage.getGraphNodesCount() const finalNodeCount = await comfyPage.nodeOps.getGraphNodesCount()
expect(finalNodeCount).toBe(initialNodeCount) expect(finalNodeCount).toBe(initialNodeCount)
}) })

View File

@@ -78,7 +78,7 @@ test.describe('Vue Node Selection', () => {
const initialPos = await checkpointNodeHeader.boundingBox() const initialPos = await checkpointNodeHeader.boundingBox()
if (!initialPos) throw new Error('Failed to get header position') if (!initialPos) throw new Error('Failed to get header position')
await comfyPage.dragAndDrop( await comfyPage.canvasOps.dragAndDrop(
{ x: initialPos.x + 10, y: initialPos.y + 10 }, { x: initialPos.x + 10, y: initialPos.y + 10 },
{ x: initialPos.x + 100, y: initialPos.y + 100 } { x: initialPos.x + 100, y: initialPos.y + 100 }
) )

View File

@@ -55,7 +55,7 @@ test.describe('Vue Node Pin', () => {
// Try to drag the node // Try to drag the node
const headerPos = await checkpointNodeHeader.boundingBox() const headerPos = await checkpointNodeHeader.boundingBox()
if (!headerPos) throw new Error('Failed to get header position') if (!headerPos) throw new Error('Failed to get header position')
await comfyPage.dragAndDrop( await comfyPage.canvasOps.dragAndDrop(
{ x: headerPos.x, y: headerPos.y }, { x: headerPos.x, y: headerPos.y },
{ x: headerPos.x + 256, y: headerPos.y + 256 } { x: headerPos.x + 256, y: headerPos.y + 256 }
) )
@@ -71,7 +71,7 @@ test.describe('Vue Node Pin', () => {
await comfyPage.page.keyboard.press(PIN_HOTKEY) await comfyPage.page.keyboard.press(PIN_HOTKEY)
// Try to drag the node again // Try to drag the node again
await comfyPage.dragAndDrop( await comfyPage.canvasOps.dragAndDrop(
{ x: headerPos.x, y: headerPos.y }, { x: headerPos.x, y: headerPos.y },
{ x: headerPos.x + 256, y: headerPos.y + 256 } { x: headerPos.x + 256, y: headerPos.y + 256 }
) )

View File

@@ -83,7 +83,7 @@ test.describe('Boolean widget', { tag: ['@screenshot', '@widget'] }, () => {
test('Can toggle', async ({ comfyPage }) => { test('Can toggle', async ({ comfyPage }) => {
await comfyPage.loadWorkflow('widgets/boolean_widget') await comfyPage.loadWorkflow('widgets/boolean_widget')
await expect(comfyPage.canvas).toHaveScreenshot('boolean_widget.png') await expect(comfyPage.canvas).toHaveScreenshot('boolean_widget.png')
const node = (await comfyPage.getFirstNodeRef())! const node = (await comfyPage.nodeOps.getFirstNodeRef())!
const widget = await node.getWidget(0) const widget = await node.getWidget(0)
await widget.click() await widget.click()
await expect(comfyPage.canvas).toHaveScreenshot( await expect(comfyPage.canvas).toHaveScreenshot(
@@ -95,7 +95,7 @@ test.describe('Boolean widget', { tag: ['@screenshot', '@widget'] }, () => {
test.describe('Slider widget', { tag: ['@screenshot', '@widget'] }, () => { test.describe('Slider widget', { tag: ['@screenshot', '@widget'] }, () => {
test('Can drag adjust value', async ({ comfyPage }) => { test('Can drag adjust value', async ({ comfyPage }) => {
await comfyPage.loadWorkflow('inputs/simple_slider') await comfyPage.loadWorkflow('inputs/simple_slider')
const node = (await comfyPage.getFirstNodeRef())! const node = (await comfyPage.nodeOps.getFirstNodeRef())!
const widget = await node.getWidget(0) const widget = await node.getWidget(0)
await comfyPage.page.evaluate(() => { await comfyPage.page.evaluate(() => {
@@ -117,7 +117,7 @@ test.describe('Number widget', { tag: ['@screenshot', '@widget'] }, () => {
test('Can drag adjust value', async ({ comfyPage }) => { test('Can drag adjust value', async ({ comfyPage }) => {
await comfyPage.loadWorkflow('widgets/seed_widget') await comfyPage.loadWorkflow('widgets/seed_widget')
const node = (await comfyPage.getFirstNodeRef())! const node = (await comfyPage.nodeOps.getFirstNodeRef())!
const widget = await node.getWidget(0) const widget = await node.getWidget(0)
await comfyPage.page.evaluate(() => { await comfyPage.page.evaluate(() => {
const widget = window['app'].graph.nodes[0].widgets[0] const widget = window['app'].graph.nodes[0].widgets[0]
@@ -165,7 +165,7 @@ test.describe('Image widget', { tag: ['@screenshot', '@widget'] }, () => {
await comfyPage.loadWorkflow('widgets/load_image_widget') await comfyPage.loadWorkflow('widgets/load_image_widget')
// Get position of the load image node // Get position of the load image node
const nodes = await comfyPage.getNodeRefsByType('LoadImage') const nodes = await comfyPage.nodeOps.getNodeRefsByType('LoadImage')
const loadImageNode = nodes[0] const loadImageNode = nodes[0]
const { x, y } = await loadImageNode.getPosition() const { x, y } = await loadImageNode.getPosition()
@@ -189,7 +189,7 @@ test.describe('Image widget', { tag: ['@screenshot', '@widget'] }, () => {
comfyPage comfyPage
}) => { }) => {
await comfyPage.loadWorkflow('widgets/load_image_widget') await comfyPage.loadWorkflow('widgets/load_image_widget')
const nodes = await comfyPage.getNodeRefsByType('LoadImage') const nodes = await comfyPage.nodeOps.getNodeRefsByType('LoadImage')
const loadImageNode = nodes[0] const loadImageNode = nodes[0]
// Click the combo widget used to select the image filename // Click the combo widget used to select the image filename
@@ -253,7 +253,7 @@ test.describe(
await comfyPage.loadWorkflow('widgets/load_animated_webp') await comfyPage.loadWorkflow('widgets/load_animated_webp')
// Get position of the load animated webp node // Get position of the load animated webp node
const nodes = await comfyPage.getNodeRefsByType( const nodes = await comfyPage.nodeOps.getNodeRefsByType(
'DevToolsLoadAnimatedImageTest' 'DevToolsLoadAnimatedImageTest'
) )
const loadAnimatedWebpNode = nodes[0] const loadAnimatedWebpNode = nodes[0]
@@ -282,7 +282,7 @@ test.describe(
await comfyPage.loadWorkflow('widgets/load_animated_webp') await comfyPage.loadWorkflow('widgets/load_animated_webp')
// Get position of the load animated webp node // Get position of the load animated webp node
const nodes = await comfyPage.getNodeRefsByType( const nodes = await comfyPage.nodeOps.getNodeRefsByType(
'DevToolsLoadAnimatedImageTest' 'DevToolsLoadAnimatedImageTest'
) )
const loadAnimatedWebpNode = nodes[0] const loadAnimatedWebpNode = nodes[0]
@@ -304,7 +304,7 @@ test.describe(
await comfyPage.loadWorkflow('widgets/save_animated_webp') await comfyPage.loadWorkflow('widgets/save_animated_webp')
// Get position of the load animated webp node // Get position of the load animated webp node
const loadNodes = await comfyPage.getNodeRefsByType( const loadNodes = await comfyPage.nodeOps.getNodeRefsByType(
'DevToolsLoadAnimatedImageTest' 'DevToolsLoadAnimatedImageTest'
) )
const loadAnimatedWebpNode = loadNodes[0] const loadAnimatedWebpNode = loadNodes[0]
@@ -317,7 +317,8 @@ test.describe(
await comfyPage.nextFrame() await comfyPage.nextFrame()
// Get the SaveAnimatedWEBP node // Get the SaveAnimatedWEBP node
const saveNodes = await comfyPage.getNodeRefsByType('SaveAnimatedWEBP') const saveNodes =
await comfyPage.nodeOps.getNodeRefsByType('SaveAnimatedWEBP')
const saveAnimatedWebpNode = saveNodes[0] const saveAnimatedWebpNode = saveNodes[0]
if (!saveAnimatedWebpNode) if (!saveAnimatedWebpNode)
throw new Error('SaveAnimatedWEBP node not found') throw new Error('SaveAnimatedWEBP node not found')

View File

@@ -92,7 +92,7 @@ test.describe('Workflow Tab Thumbnails', { tag: '@workflow' }, () => {
) )
await comfyPage.delay(300) // Wait for the popover to hide await comfyPage.delay(300) // Wait for the popover to hide
await comfyPage.rightClickCanvas(200, 200) await comfyPage.canvasOps.rightClick(200, 200)
await comfyPage.page.getByText('Add Node').click() await comfyPage.page.getByText('Add Node').click()
await comfyPage.nextFrame() await comfyPage.nextFrame()
await comfyPage.page.getByText(category).click() await comfyPage.page.getByText(category).click()