From d044bed9b28616f5fce45ea52506cda3c07f8ac7 Mon Sep 17 00:00:00 2001 From: Csongor Czezar <44126075+csongorczezar@users.noreply.github.com> Date: Tue, 10 Feb 2026 19:18:48 -0800 Subject: [PATCH] feat: use object info display_name as fallback before node name (#7622) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description Implements fallback to object info display_name before using internal node name when display_name is unavailable. ## Related Issue Related to backend PR: comfyanonymous/ComfyUI#11340 ## Changes - Modified `getNodeDefs()` to use object info `display_name` before falling back to `name` - Added unit tests for display name fallback behavior ## Testing - All existing tests pass - Added 4 new unit tests covering various display_name scenarios ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-7622-W-I-P-feat-use-object-info-display_name-as-fallback-before-node-name-2cd6d73d365081deb22fe5ed00e6dc2e) by [Unito](https://www.unito.io) --- src/scripts/app.ts | 33 ++++--- .../tests/scripts/app.getNodeDefs.test.ts | 94 +++++++++++++++++++ 2 files changed, 113 insertions(+), 14 deletions(-) create mode 100644 tests-ui/tests/scripts/app.getNodeDefs.test.ts diff --git a/src/scripts/app.ts b/src/scripts/app.ts index b38b7ac534..e16575d40e 100644 --- a/src/scripts/app.ts +++ b/src/scripts/app.ts @@ -953,20 +953,25 @@ export class ComfyApp { } async getNodeDefs(): Promise> { - const translateNodeDef = (def: ComfyNodeDefV1): ComfyNodeDefV1 => ({ - ...def, - display_name: st( - `nodeDefs.${def.name}.display_name`, - def.display_name ?? def.name - ), - description: def.description - ? st(`nodeDefs.${def.name}.description`, def.description) - : '', - category: def.category - .split('/') - .map((category: string) => st(`nodeCategories.${category}`, category)) - .join('/') - }) + const translateNodeDef = (def: ComfyNodeDefV1): ComfyNodeDefV1 => { + // Use object info display_name as fallback before using name + const objectInfoDisplayName = def.display_name || def.name + + return { + ...def, + display_name: st( + `nodeDefs.${def.name}.display_name`, + objectInfoDisplayName + ), + description: def.description + ? st(`nodeDefs.${def.name}.description`, def.description) + : '', + category: def.category + .split('/') + .map((category: string) => st(`nodeCategories.${category}`, category)) + .join('/') + } + } return _.mapValues(await api.getNodeDefs(), (def) => translateNodeDef(def)) } diff --git a/tests-ui/tests/scripts/app.getNodeDefs.test.ts b/tests-ui/tests/scripts/app.getNodeDefs.test.ts new file mode 100644 index 0000000000..d2b6e355cd --- /dev/null +++ b/tests-ui/tests/scripts/app.getNodeDefs.test.ts @@ -0,0 +1,94 @@ +import { beforeEach, describe, expect, test, vi } from 'vitest' + +import { st } from '@/i18n' +import type { ComfyNodeDef as ComfyNodeDefV1 } from '@/schemas/nodeDefSchema' +import { api } from '@/scripts/api' +import { app as comfyApp } from '@/scripts/app' + +vi.mock('@/scripts/api', () => ({ + api: { + getNodeDefs: vi.fn(), + apiURL: vi.fn((path: string) => path), + addEventListener: vi.fn(), + getUserData: vi.fn(), + storeUserData: vi.fn() + } +})) + +vi.mock('@/i18n', () => ({ + st: vi.fn((_key: string, fallback: string) => fallback), + t: vi.fn((key: string) => key), + te: vi.fn(() => false) +})) + +describe('ComfyApp.getNodeDefs', () => { + beforeEach(() => { + vi.clearAllMocks() + }) + + test('should use object info display_name when available', async () => { + const mockNodeDefs: Record = { + TestNode: { + name: 'TestNode', + display_name: 'Custom Display Name', + category: 'test', + description: 'Test description', + input: {}, + output: [], + output_node: false, + python_module: 'test.module' + } + } + + vi.mocked(api.getNodeDefs).mockResolvedValue(mockNodeDefs) + + const result = await comfyApp.getNodeDefs() + + expect(result.TestNode.display_name).toBe('Custom Display Name') + }) + + test('should fall back to name when display_name is missing', async () => { + const mockNodeDefs: Record = { + TestNode: { + name: 'TestNode', + display_name: '', + category: 'test', + description: 'Test description', + input: {}, + output: [], + output_node: false, + python_module: 'test.module' + } + } + + vi.mocked(api.getNodeDefs).mockResolvedValue(mockNodeDefs) + + const result = await comfyApp.getNodeDefs() + + // When display_name is empty, should fall back to name + expect(result.TestNode.display_name).toBe('TestNode') + }) + + test('should prioritize translation over object info display_name', async () => { + const mockNodeDefs: Record = { + TestNode: { + name: 'TestNode', + display_name: 'Object Info Display Name', + category: 'test', + description: 'Test description', + input: {}, + output: [], + output_node: false, + python_module: 'test.module' + } + } + + vi.mocked(api.getNodeDefs).mockResolvedValue(mockNodeDefs) + // Mock st to return a translation instead of fallback + vi.mocked(st).mockReturnValue('Translated Display Name') + + const result = await comfyApp.getNodeDefs() + + expect(result.TestNode.display_name).toBe('Translated Display Name') + }) +})