mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-01-27 11:29:53 +00:00
## Summary Fixes an issue where trying to uncolor a node broke the vue color syncing. ## Changes - **What**: Changes litegraph property removal from `delete` to `= undefined` ## Screenshots ### Before https://github.com/user-attachments/assets/81a1ad40-ba5d-4dec-8f90-5b61eb804a16 ### After https://github.com/user-attachments/assets/459d2d15-c728-49d2-abd9-6e255e5383e5 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5991-Fix-Allow-uncoloring-Vue-Nodes-2876d73d365081f4a74fc9fa423aae1c) by [Unito](https://www.unito.io)
153 lines
4.3 KiB
TypeScript
153 lines
4.3 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
import { LGraphNodeProperties } from '@/lib/litegraph/src/LGraphNodeProperties'
|
|
|
|
describe('LGraphNodeProperties', () => {
|
|
let mockNode: any
|
|
let mockGraph: any
|
|
|
|
beforeEach(() => {
|
|
mockGraph = {
|
|
trigger: vi.fn()
|
|
}
|
|
|
|
mockNode = {
|
|
id: 123,
|
|
title: 'Test Node',
|
|
flags: {},
|
|
graph: mockGraph
|
|
}
|
|
})
|
|
|
|
describe('property tracking', () => {
|
|
it('should track changes to existing properties', () => {
|
|
new LGraphNodeProperties(mockNode)
|
|
|
|
mockNode.title = 'New Title'
|
|
|
|
expect(mockGraph.trigger).toHaveBeenCalledWith('node:property:changed', {
|
|
nodeId: mockNode.id,
|
|
property: 'title',
|
|
oldValue: 'Test Node',
|
|
newValue: 'New Title'
|
|
})
|
|
})
|
|
|
|
it('should track changes to nested properties', () => {
|
|
new LGraphNodeProperties(mockNode)
|
|
|
|
mockNode.flags.collapsed = true
|
|
|
|
expect(mockGraph.trigger).toHaveBeenCalledWith('node:property:changed', {
|
|
nodeId: mockNode.id,
|
|
property: 'flags.collapsed',
|
|
oldValue: undefined,
|
|
newValue: true
|
|
})
|
|
})
|
|
|
|
it('should emit event when value is set to the same value', () => {
|
|
new LGraphNodeProperties(mockNode)
|
|
|
|
mockNode.title = 'Test Node' // Same value as original
|
|
|
|
expect(mockGraph.trigger).toHaveBeenCalledTimes(1)
|
|
})
|
|
|
|
it('should not emit events when node has no graph', () => {
|
|
mockNode.graph = null
|
|
new LGraphNodeProperties(mockNode)
|
|
|
|
// Should not throw
|
|
expect(() => {
|
|
mockNode.title = 'New Title'
|
|
}).not.toThrow()
|
|
})
|
|
})
|
|
|
|
describe('isTracked', () => {
|
|
it('should correctly identify tracked properties', () => {
|
|
const propManager = new LGraphNodeProperties(mockNode)
|
|
|
|
expect(propManager.isTracked('title')).toBe(true)
|
|
expect(propManager.isTracked('flags.collapsed')).toBe(true)
|
|
expect(propManager.isTracked('untracked')).toBe(false)
|
|
})
|
|
})
|
|
|
|
describe('serialization behavior', () => {
|
|
it('should not make non-existent properties enumerable', () => {
|
|
new LGraphNodeProperties(mockNode)
|
|
|
|
// flags.collapsed doesn't exist initially
|
|
const descriptor = Object.getOwnPropertyDescriptor(
|
|
mockNode.flags,
|
|
'collapsed'
|
|
)
|
|
expect(descriptor?.enumerable).toBe(false)
|
|
})
|
|
|
|
it('should make properties enumerable when set to non-default values', () => {
|
|
new LGraphNodeProperties(mockNode)
|
|
|
|
mockNode.flags.collapsed = true
|
|
|
|
const descriptor = Object.getOwnPropertyDescriptor(
|
|
mockNode.flags,
|
|
'collapsed'
|
|
)
|
|
expect(descriptor?.enumerable).toBe(true)
|
|
})
|
|
|
|
it('should make properties non-enumerable when set back to undefined', () => {
|
|
new LGraphNodeProperties(mockNode)
|
|
|
|
mockNode.flags.collapsed = true
|
|
mockNode.flags.collapsed = undefined
|
|
|
|
const descriptor = Object.getOwnPropertyDescriptor(
|
|
mockNode.flags,
|
|
'collapsed'
|
|
)
|
|
expect(descriptor?.enumerable).toBe(false)
|
|
})
|
|
|
|
it('should keep existing properties enumerable', () => {
|
|
// title exists initially
|
|
const initialDescriptor = Object.getOwnPropertyDescriptor(
|
|
mockNode,
|
|
'title'
|
|
)
|
|
expect(initialDescriptor?.enumerable).toBe(true)
|
|
|
|
new LGraphNodeProperties(mockNode)
|
|
|
|
const afterDescriptor = Object.getOwnPropertyDescriptor(mockNode, 'title')
|
|
expect(afterDescriptor?.enumerable).toBe(true)
|
|
})
|
|
|
|
it('should only include non-undefined values in JSON.stringify', () => {
|
|
new LGraphNodeProperties(mockNode)
|
|
|
|
// Initially, flags.collapsed shouldn't appear
|
|
let json = JSON.parse(JSON.stringify(mockNode))
|
|
expect(json.flags.collapsed).toBeUndefined()
|
|
|
|
// After setting to true, it should appear
|
|
mockNode.flags.collapsed = true
|
|
json = JSON.parse(JSON.stringify(mockNode))
|
|
expect(json.flags.collapsed).toBe(true)
|
|
|
|
// After setting to false, it should still appear (false is not undefined)
|
|
mockNode.flags.collapsed = false
|
|
json = JSON.parse(JSON.stringify(mockNode))
|
|
expect(json.flags.collapsed).toBe(false)
|
|
|
|
// After setting back to undefined, it should disappear
|
|
mockNode.flags.collapsed = undefined
|
|
json = JSON.parse(JSON.stringify(mockNode))
|
|
expect(json.flags.collapsed).toBeUndefined()
|
|
})
|
|
})
|
|
})
|