diff --git a/browser_tests/ComfyPage.ts b/browser_tests/ComfyPage.ts index d06ef86f9..3d8deeab2 100644 --- a/browser_tests/ComfyPage.ts +++ b/browser_tests/ComfyPage.ts @@ -608,6 +608,16 @@ export class ComfyPage { revertAfter ) } + + async convertAllNodesToGroupNode(groupNodeName: string) { + this.page.on('dialog', async (dialog) => { + await dialog.accept(groupNodeName) + }) + await this.canvas.press('Control+a') + await this.rightClickEmptyLatentNode() + await this.page.getByText('Convert to Group Node').click() + await this.nextFrame() + } } export const comfyPageFixture = base.extend<{ comfyPage: ComfyPage }>({ diff --git a/browser_tests/groupNode.spec.ts b/browser_tests/groupNode.spec.ts new file mode 100644 index 000000000..2b14f7a45 --- /dev/null +++ b/browser_tests/groupNode.spec.ts @@ -0,0 +1,22 @@ +import { expect } from '@playwright/test' +import { comfyPageFixture as test } from './ComfyPage' + +test.describe('Group Node', () => { + test('Can be added with search', async ({ comfyPage }) => { + const groupNodeName = 'DefautWorkflowGroupNode' + await comfyPage.convertAllNodesToGroupNode(groupNodeName) + await comfyPage.doubleClickCanvas() + await comfyPage.searchBox.fillAndSelectFirstNode(groupNodeName) + await expect(comfyPage.canvas).toHaveScreenshot( + 'group-node-copy-added-from-search.png' + ) + }) + + test('Displays tooltip on title hover', async ({ comfyPage }) => { + await comfyPage.convertAllNodesToGroupNode('Group Node') + await comfyPage.page.mouse.move(47, 173) + const tooltipTimeout = 500 + await comfyPage.page.waitForTimeout(tooltipTimeout + 16) + await expect(comfyPage.page.locator('.node-tooltip')).toBeVisible() + }) +}) diff --git a/browser_tests/groupNode.spec.ts-snapshots/group-node-copy-added-from-search-chromium-2x-linux.png b/browser_tests/groupNode.spec.ts-snapshots/group-node-copy-added-from-search-chromium-2x-linux.png new file mode 100644 index 000000000..894517ea4 Binary files /dev/null and b/browser_tests/groupNode.spec.ts-snapshots/group-node-copy-added-from-search-chromium-2x-linux.png differ diff --git a/browser_tests/groupNode.spec.ts-snapshots/group-node-copy-added-from-search-chromium-linux.png b/browser_tests/groupNode.spec.ts-snapshots/group-node-copy-added-from-search-chromium-linux.png new file mode 100644 index 000000000..60d6feab2 Binary files /dev/null and b/browser_tests/groupNode.spec.ts-snapshots/group-node-copy-added-from-search-chromium-linux.png differ diff --git a/src/extensions/core/groupNode.ts b/src/extensions/core/groupNode.ts index 9701b12d4..822df7b7d 100644 --- a/src/extensions/core/groupNode.ts +++ b/src/extensions/core/groupNode.ts @@ -4,6 +4,7 @@ import { mergeIfValid } from './widgetInputs' import { ManageGroupDialog } from './groupNodeManage' import type { LGraphNode } from '@comfyorg/litegraph' import { LGraphCanvas, LiteGraph } from '@comfyorg/litegraph' +import { useNodeDefStore } from '@/stores/nodeDefStore' const GROUP = Symbol() @@ -194,6 +195,10 @@ export class GroupNodeConfig { display_name: this.name, category: 'group nodes' + ('/' + source), input: { required: {} }, + description: `Group node combining ${this.nodeData.nodes + .map((n) => n.type) + .join(', ')}`, + python_module: 'custom_nodes.' + this.name, [GROUP]: this } @@ -212,6 +217,7 @@ export class GroupNodeConfig { } this.#convertedToProcess = null await app.registerNodeDef('workflow/' + this.name, this.nodeDef) + useNodeDefStore().addNodeDef(this.nodeDef) } getLinks() { diff --git a/src/stores/nodeDefStore.ts b/src/stores/nodeDefStore.ts index 11845c602..6710d72b5 100644 --- a/src/stores/nodeDefStore.ts +++ b/src/stores/nodeDefStore.ts @@ -314,6 +314,11 @@ export const useNodeDefStore = defineStore('nodeDef', { this.nodeDefsByName = newNodeDefsByName this.nodeDefsByDisplayName = nodeDefsByDisplayName }, + addNodeDef(nodeDef: ComfyNodeDef) { + const nodeDefImpl = plainToClass(ComfyNodeDefImpl, nodeDef) + this.nodeDefsByName[nodeDef.name] = nodeDefImpl + this.nodeDefsByDisplayName[nodeDef.display_name] = nodeDefImpl + }, updateWidgets(widgets: Record) { this.widgets = widgets }, diff --git a/tests-ui/utils/index.ts b/tests-ui/utils/index.ts index c4c38c407..8fc0910ae 100644 --- a/tests-ui/utils/index.ts +++ b/tests-ui/utils/index.ts @@ -1,4 +1,4 @@ -import { APIConfig, mockApi, mockSettingStore } from './setup' +import { APIConfig, mockApi, mockSettingStore, mockNodeDefStore } from './setup' import { Ez, EzGraph, EzNameSpace } from './ezgraph' import lg from './litegraph' import fs from 'fs' @@ -44,6 +44,7 @@ export async function start(config: StartConfig = {}): Promise { const { app } = await import('../../src/scripts/app') const { useSettingStore } = await import('../../src/stores/settingStore') useSettingStore().addSettings(app.ui.settings) + mockNodeDefStore() const { LiteGraph, LGraphCanvas } = await import('@comfyorg/litegraph') config.preSetup?.(app) diff --git a/tests-ui/utils/setup.ts b/tests-ui/utils/setup.ts index 6857b1a6b..7f3a37737 100644 --- a/tests-ui/utils/setup.ts +++ b/tests-ui/utils/setup.ts @@ -1,6 +1,7 @@ import type { ComfySettingsDialog } from '@/scripts/ui/settings' import type { ComfyApp } from '@/scripts/app' import '../../src/scripts/api' +import { ComfyNodeDef } from '@/types/apiTypes' const fs = require('fs') const path = require('path') @@ -124,3 +125,13 @@ export const mockSettingStore = () => { useSettingStore: jest.fn(() => mockedSettingStore) })) } + +export const mockNodeDefStore = () => { + const mockedNodeDefStore = { + addNodeDef: jest.fn((nodeDef: ComfyNodeDef) => {}) + } + + jest.mock('@/stores/nodeDefStore', () => ({ + useNodeDefStore: jest.fn(() => mockedNodeDefStore) + })) +}