mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-07-02 21:28:08 +00:00
## Summary Adds a branded local `NodeId` helper and starts separating local node identity from serialized workflow IDs. ## Changes - **What**: Adds central `NodeId` parsing/branding helpers, migrates nearby widget identity types, keeps queue results at the serialized boundary, and removes misleading workflow `NodeId` usage from execution error maps. ## Review Focus Check that the first migration slice keeps serialized/API IDs as raw `number | string` while local UI/store IDs use the branded string type. ## Caveat `SUBGRAPH_INPUT_ID` and `SUBGRAPH_OUTPUT_ID` are now branded local `NodeId` string values internally instead of numeric sentinels. Reviewers should double-check extension compatibility for callers that import `Constants` and compare those values numerically. ## Screenshots (if applicable) N/A --------- Co-authored-by: GitHub Action <action@github.com> Co-authored-by: AustinMroz <austin@comfy.org> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
101 lines
2.9 KiB
TypeScript
101 lines
2.9 KiB
TypeScript
import { render } from '@testing-library/vue'
|
|
import { createPinia, setActivePinia } from 'pinia'
|
|
import { defineComponent } from 'vue'
|
|
import { createI18n } from 'vue-i18n'
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
import { useNodeMenuOptions } from '@/composables/graph/useNodeMenuOptions'
|
|
import type { Positionable } from '@/lib/litegraph/src/litegraph'
|
|
import { LGraphEventMode, LGraphNode } from '@/lib/litegraph/src/litegraph'
|
|
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
|
|
import { toNodeId } from '@/types/nodeId'
|
|
|
|
// canvasStore transitively imports the app singleton; stub it so the real
|
|
// ComfyApp module never loads during these unit tests.
|
|
vi.mock('@/scripts/app', () => ({
|
|
app: { canvas: { selected_nodes: null } }
|
|
}))
|
|
|
|
vi.mock('@/composables/graph/useNodeCustomization', () => ({
|
|
useNodeCustomization: () => ({
|
|
shapeOptions: [],
|
|
applyShape: vi.fn(),
|
|
applyColor: vi.fn(),
|
|
colorOptions: [],
|
|
isLightTheme: { value: false }
|
|
})
|
|
}))
|
|
|
|
vi.mock('@/composables/graph/useSelectedNodeActions', () => ({
|
|
useSelectedNodeActions: () => ({
|
|
adjustNodeSize: vi.fn(),
|
|
toggleNodeCollapse: vi.fn(),
|
|
toggleNodePin: vi.fn(),
|
|
toggleNodeBypass: vi.fn(),
|
|
runBranch: vi.fn()
|
|
})
|
|
}))
|
|
|
|
const i18n = createI18n({
|
|
legacy: false,
|
|
locale: 'en',
|
|
messages: { en: {} },
|
|
missingWarn: false,
|
|
fallbackWarn: false
|
|
})
|
|
|
|
const nodeWithMode = (mode: LGraphEventMode, id = 1): LGraphNode => {
|
|
const node = new LGraphNode('Test')
|
|
node.id = toNodeId(id)
|
|
node.mode = mode
|
|
return node
|
|
}
|
|
|
|
const getBypassLabel = (selected: LGraphNode[]): string => {
|
|
const canvasStore = useCanvasStore()
|
|
vi.spyOn(canvasStore, 'canvas', 'get').mockReturnValue({
|
|
selectedItems: new Set<Positionable>(selected)
|
|
} as ReturnType<typeof canvasStore.getCanvas>)
|
|
|
|
let label = ''
|
|
const Wrapper = defineComponent({
|
|
setup() {
|
|
const { getBypassOption } = useNodeMenuOptions()
|
|
label = getBypassOption(() => {}).label ?? ''
|
|
return () => null
|
|
}
|
|
})
|
|
render(Wrapper, { global: { plugins: [i18n] } })
|
|
return label
|
|
}
|
|
|
|
describe('useNodeMenuOptions.getBypassOption', () => {
|
|
beforeEach(() => {
|
|
setActivePinia(createPinia())
|
|
})
|
|
|
|
it('labels as "Bypass" when no node is bypassed', () => {
|
|
expect(getBypassLabel([nodeWithMode(LGraphEventMode.ALWAYS, 1)])).toBe(
|
|
'contextMenu.Bypass'
|
|
)
|
|
})
|
|
|
|
it('labels as "Remove Bypass" when every selected node is bypassed', () => {
|
|
expect(
|
|
getBypassLabel([
|
|
nodeWithMode(LGraphEventMode.BYPASS, 1),
|
|
nodeWithMode(LGraphEventMode.BYPASS, 2)
|
|
])
|
|
).toBe('contextMenu.Remove Bypass')
|
|
})
|
|
|
|
it('labels as "Bypass" on mixed selection so it matches the toggle action', () => {
|
|
expect(
|
|
getBypassLabel([
|
|
nodeWithMode(LGraphEventMode.BYPASS, 1),
|
|
nodeWithMode(LGraphEventMode.ALWAYS, 2)
|
|
])
|
|
).toBe('contextMenu.Bypass')
|
|
})
|
|
})
|