mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-11 16:30:57 +00:00
## Summary Add frontend-only display name mappings for nodes shown in the Essentials tab, plus parse the new `essentials_category` field from the backend. ## Changes - **What**: Created `src/constants/essentialsDisplayNames.ts` with a static mapping of node names to user-friendly display names (e.g. `CLIPTextEncode` → "Text", `ImageScale` → "Resize Image"). Regular nodes use exact name matching; blueprint nodes use prefix matching since their filenames include model-specific suffixes. Integrated into `NodeLibrarySidebarTab.vue`'s `renderedRoot` computed for leaf node labels with fallback to `display_name`. Added `essentials_category` (z.string().optional()) to the node def schema and `ComfyNodeDefImpl` to parse the field already sent by the backend (PR #12357). ## Review Focus Display names are resolved only in the Essentials tab tree view (`NodeLibrarySidebarTab.vue`), not globally, to avoid side effects on search, bookmarks, or other views. Blueprint prefix matching is ordered longest-first so more specific prefixes (e.g. `image_inpainting_`) match before shorter ones (e.g. `image_edit`). ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9072-feat-add-display-name-mappings-for-Essentials-tab-nodes-30f6d73d3650817c9acdc9b0315ed0be) by [Unito](https://www.unito.io)
106 lines
3.5 KiB
TypeScript
106 lines
3.5 KiB
TypeScript
import { describe, expect, it, vi } from 'vitest'
|
|
|
|
vi.mock('@/i18n', () => ({
|
|
t: vi.fn((key: string) => key)
|
|
}))
|
|
|
|
import { resolveEssentialsDisplayName } from '@/constants/essentialsDisplayNames'
|
|
|
|
describe('resolveEssentialsDisplayName', () => {
|
|
describe('exact name matches', () => {
|
|
it.each([
|
|
['LoadImage', 'essentials.loadImage'],
|
|
['SaveImage', 'essentials.saveImage'],
|
|
['PrimitiveStringMultiline', 'essentials.text'],
|
|
['ImageScale', 'essentials.resizeImage'],
|
|
['LoraLoader', 'essentials.loadStyleLora'],
|
|
['OpenAIChatNode', 'essentials.textGenerationLLM'],
|
|
['RecraftRemoveBackgroundNode', 'essentials.removeBackground'],
|
|
['ImageCompare', 'essentials.imageCompare'],
|
|
['StabilityTextToAudio', 'essentials.musicGeneration'],
|
|
['BatchImagesNode', 'essentials.batchImage'],
|
|
['Video Slice', 'essentials.extractFrame'],
|
|
['KlingLipSyncAudioToVideoNode', 'essentials.lipsync'],
|
|
['KlingLipSyncTextToVideoNode', 'essentials.lipsync']
|
|
])('%s -> %s', (name, expected) => {
|
|
expect(resolveEssentialsDisplayName({ name })).toBe(expected)
|
|
})
|
|
})
|
|
|
|
describe('3D API node alternatives', () => {
|
|
it.each([
|
|
['TencentTextToModelNode', 'essentials.textTo3DModel'],
|
|
['MeshyTextToModelNode', 'essentials.textTo3DModel'],
|
|
['TripoTextToModelNode', 'essentials.textTo3DModel'],
|
|
['TencentImageToModelNode', 'essentials.imageTo3DModel'],
|
|
['MeshyImageToModelNode', 'essentials.imageTo3DModel'],
|
|
['TripoImageToModelNode', 'essentials.imageTo3DModel']
|
|
])('%s -> %s', (name, expected) => {
|
|
expect(resolveEssentialsDisplayName({ name })).toBe(expected)
|
|
})
|
|
})
|
|
|
|
describe('blueprint prefix matches', () => {
|
|
it.each([
|
|
[
|
|
'SubgraphBlueprint.text_to_image_flux_schnell.json',
|
|
'essentials.textToImage'
|
|
],
|
|
['SubgraphBlueprint.text_to_image_sd15.json', 'essentials.textToImage'],
|
|
[
|
|
'SubgraphBlueprint.image_edit_something.json',
|
|
'essentials.imageToImage'
|
|
],
|
|
['SubgraphBlueprint.pose_to_image_v2.json', 'essentials.poseToImage'],
|
|
[
|
|
'SubgraphBlueprint.canny_to_image_z_image_turbo.json',
|
|
'essentials.cannyToImage'
|
|
],
|
|
[
|
|
'SubgraphBlueprint.depth_to_image_z_image_turbo.json',
|
|
'essentials.depthToImage'
|
|
],
|
|
['SubgraphBlueprint.text_to_video_ltx.json', 'essentials.textToVideo'],
|
|
['SubgraphBlueprint.image_to_video_wan.json', 'essentials.imageToVideo'],
|
|
[
|
|
'SubgraphBlueprint.pose_to_video_ltx_2_0.json',
|
|
'essentials.poseToVideo'
|
|
],
|
|
[
|
|
'SubgraphBlueprint.canny_to_video_ltx_2_0.json',
|
|
'essentials.cannyToVideo'
|
|
],
|
|
[
|
|
'SubgraphBlueprint.depth_to_video_ltx_2_0.json',
|
|
'essentials.depthToVideo'
|
|
],
|
|
[
|
|
'SubgraphBlueprint.image_inpainting_qwen_image_instantx.json',
|
|
'essentials.inpaintImage'
|
|
],
|
|
[
|
|
'SubgraphBlueprint.image_outpainting_qwen_image_instantx.json',
|
|
'essentials.outpaintImage'
|
|
]
|
|
])('%s -> %s', (name, expected) => {
|
|
expect(resolveEssentialsDisplayName({ name })).toBe(expected)
|
|
})
|
|
})
|
|
|
|
describe('unmapped nodes', () => {
|
|
it('returns undefined for unknown node names', () => {
|
|
expect(resolveEssentialsDisplayName({ name: 'SomeRandomNode' })).toBe(
|
|
undefined
|
|
)
|
|
})
|
|
|
|
it('returns undefined for unknown blueprint prefixes', () => {
|
|
expect(
|
|
resolveEssentialsDisplayName({
|
|
name: 'SubgraphBlueprint.unknown_workflow.json'
|
|
})
|
|
).toBe(undefined)
|
|
})
|
|
})
|
|
})
|