Files
ComfyUI_frontend/browser_tests/tests/rendererToggleStability.spec.ts
Alexander Brown b4ae6344d7 Brand local node IDs (#13085)
## 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>
2026-06-26 22:54:04 +00:00

106 lines
2.6 KiB
TypeScript

import {
comfyExpect as expect,
comfyPageFixture as test
} from '@e2e/fixtures/ComfyPage'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
import type { Position } from '@e2e/fixtures/types'
import type { NodeId } from '@/types/nodeId'
type NodeSnapshot = { id: NodeId } & Position
async function getAllNodePositions(
comfyPage: ComfyPage
): Promise<NodeSnapshot[]> {
return comfyPage.page.evaluate(() =>
window.app!.graph.nodes.map((n) => ({
id: n.id,
x: n.pos[0],
y: n.pos[1]
}))
)
}
async function getNodePosition(
comfyPage: ComfyPage,
nodeId: NodeId
): Promise<Position | undefined> {
return comfyPage.page.evaluate((targetNodeId) => {
const node = window.app!.graph.nodes.find((n) => n.id === targetNodeId)
if (!node) return
return {
x: node.pos[0],
y: node.pos[1]
}
}, nodeId)
}
async function expectNodePositionStable(
comfyPage: ComfyPage,
initial: NodeSnapshot,
mode: string
) {
await expect
.poll(
async () => {
const current = await getNodePosition(comfyPage, initial.id)
return current?.x ?? Number.NaN
},
{ message: `node ${initial.id} x drifted in ${mode} mode` }
)
.toBeCloseTo(initial.x, 1)
await expect
.poll(
async () => {
const current = await getNodePosition(comfyPage, initial.id)
return current?.y ?? Number.NaN
},
{ message: `node ${initial.id} y drifted in ${mode} mode` }
)
.toBeCloseTo(initial.y, 1)
}
async function setVueMode(comfyPage: ComfyPage, enabled: boolean) {
await comfyPage.settings.setSetting('Comfy.VueNodes.Enabled', enabled)
if (enabled) {
await comfyPage.vueNodes.waitForNodes()
}
await comfyPage.nextFrame()
}
test.describe(
'Renderer toggle stability',
{ tag: ['@node', '@canvas'] },
() => {
test('node positions do not drift when toggling between Vue and LiteGraph renderers', async ({
comfyPage
}) => {
const TOGGLE_COUNT = 5
const initialPositions = await getAllNodePositions(comfyPage)
expect(initialPositions.length).toBeGreaterThan(0)
for (let i = 0; i < TOGGLE_COUNT; i++) {
await setVueMode(comfyPage, true)
for (const initial of initialPositions) {
await expectNodePositionStable(
comfyPage,
initial,
`Vue toggle ${i + 1}`
)
}
await setVueMode(comfyPage, false)
for (const initial of initialPositions) {
await expectNodePositionStable(
comfyPage,
initial,
`LiteGraph toggle ${i + 1}`
)
}
}
})
}
)