Skip to content

Commit f85df30

Browse files
[fix] show tooltip on color picker button in selection toolbox (#4612)
1 parent b2b50ac commit f85df30

File tree

2 files changed

+136
-0
lines changed

2 files changed

+136
-0
lines changed
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import { mount } from '@vue/test-utils'
2+
import { createPinia, setActivePinia } from 'pinia'
3+
import PrimeVue from 'primevue/config'
4+
import Tooltip from 'primevue/tooltip'
5+
import { beforeEach, describe, expect, it, vi } from 'vitest'
6+
import { createI18n } from 'vue-i18n'
7+
8+
// Import after mocks
9+
import ColorPickerButton from '@/components/graph/selectionToolbox/ColorPickerButton.vue'
10+
import { useCanvasStore } from '@/stores/graphStore'
11+
import { useWorkflowStore } from '@/stores/workflowStore'
12+
13+
// Mock the litegraph module
14+
vi.mock('@comfyorg/litegraph', async () => {
15+
const actual = await vi.importActual('@comfyorg/litegraph')
16+
return {
17+
...actual,
18+
LGraphCanvas: {
19+
node_colors: {
20+
red: { bgcolor: '#ff0000' },
21+
green: { bgcolor: '#00ff00' },
22+
blue: { bgcolor: '#0000ff' }
23+
}
24+
},
25+
LiteGraph: {
26+
NODE_DEFAULT_BGCOLOR: '#353535'
27+
},
28+
isColorable: vi.fn(() => true)
29+
}
30+
})
31+
32+
// Mock the colorUtil module
33+
vi.mock('@/utils/colorUtil', () => ({
34+
adjustColor: vi.fn((color: string) => color + '_light')
35+
}))
36+
37+
// Mock the litegraphUtil module
38+
vi.mock('@/utils/litegraphUtil', () => ({
39+
getItemsColorOption: vi.fn(() => null),
40+
isLGraphNode: vi.fn((item) => item?.type === 'LGraphNode'),
41+
isLGraphGroup: vi.fn((item) => item?.type === 'LGraphGroup'),
42+
isReroute: vi.fn(() => false)
43+
}))
44+
45+
describe('ColorPickerButton', () => {
46+
let canvasStore: ReturnType<typeof useCanvasStore>
47+
let workflowStore: ReturnType<typeof useWorkflowStore>
48+
49+
const i18n = createI18n({
50+
legacy: false,
51+
locale: 'en',
52+
messages: {
53+
en: {
54+
color: {
55+
noColor: 'No Color',
56+
red: 'Red',
57+
green: 'Green',
58+
blue: 'Blue'
59+
}
60+
}
61+
}
62+
})
63+
64+
beforeEach(() => {
65+
setActivePinia(createPinia())
66+
canvasStore = useCanvasStore()
67+
workflowStore = useWorkflowStore()
68+
69+
// Set up default store state
70+
canvasStore.selectedItems = []
71+
72+
// Mock workflow store
73+
workflowStore.activeWorkflow = {
74+
changeTracker: {
75+
checkState: vi.fn()
76+
}
77+
} as any
78+
})
79+
80+
const createWrapper = () => {
81+
return mount(ColorPickerButton, {
82+
global: {
83+
plugins: [PrimeVue, i18n],
84+
directives: {
85+
tooltip: Tooltip
86+
}
87+
}
88+
})
89+
}
90+
91+
it('should render when nodes are selected', () => {
92+
// Add a mock node to selectedItems
93+
canvasStore.selectedItems = [{ type: 'LGraphNode' } as any]
94+
const wrapper = createWrapper()
95+
expect(wrapper.find('button').exists()).toBe(true)
96+
})
97+
98+
it('should not render when nothing is selected', () => {
99+
// Keep selectedItems empty
100+
canvasStore.selectedItems = []
101+
const wrapper = createWrapper()
102+
// The button exists but is hidden with v-show
103+
expect(wrapper.find('button').exists()).toBe(true)
104+
expect(wrapper.find('button').attributes('style')).toContain(
105+
'display: none'
106+
)
107+
})
108+
109+
it('should toggle color picker visibility on button click', async () => {
110+
canvasStore.selectedItems = [{ type: 'LGraphNode' } as any]
111+
const wrapper = createWrapper()
112+
const button = wrapper.find('button')
113+
114+
expect(wrapper.find('.color-picker-container').exists()).toBe(false)
115+
116+
await button.trigger('click')
117+
expect(wrapper.find('.color-picker-container').exists()).toBe(true)
118+
119+
await button.trigger('click')
120+
expect(wrapper.find('.color-picker-container').exists()).toBe(false)
121+
})
122+
})

src/components/graph/selectionToolbox/ColorPickerButton.vue

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
<div class="relative">
33
<Button
44
v-show="canvasStore.nodeSelected || canvasStore.groupSelected"
5+
v-tooltip.top="{
6+
value: localizedCurrentColorName ?? t('color.noColor'),
7+
showDelay: 512
8+
}"
59
severity="secondary"
610
text
711
@click="() => (showColorPicker = !showColorPicker)"
@@ -123,6 +127,16 @@ const currentColor = computed(() =>
123127
: null
124128
)
125129
130+
const localizedCurrentColorName = computed(() => {
131+
if (!currentColorOption.value?.bgcolor) return null
132+
const colorOption = colorOptions.find(
133+
(option) =>
134+
option.value.dark === currentColorOption.value?.bgcolor ||
135+
option.value.light === currentColorOption.value?.bgcolor
136+
)
137+
return colorOption?.localizedName ?? NO_COLOR_OPTION.localizedName
138+
})
139+
126140
watch(
127141
() => canvasStore.selectedItems,
128142
(newSelectedItems) => {

0 commit comments

Comments
 (0)