import { mount } from '@vue/test-utils' import { createPinia, setActivePinia } from 'pinia' import PrimeVue from 'primevue/config' import { beforeEach, describe, expect, it, vi } from 'vitest' import { createI18n } from 'vue-i18n' import SelectionToolbox from '@/components/graph/SelectionToolbox.vue' import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode' import { useCanvasStore } from '@/renderer/core/canvas/canvasStore' import { useCanvasInteractions } from '@/renderer/core/canvas/useCanvasInteractions' import { useExtensionService } from '@/services/extensionService' import { createMockCanvas, createMockPositionable } from '@/utils/__tests__/litegraphTestUtils' import * as litegraphUtil from '@/utils/litegraphUtil' import * as nodeFilterUtil from '@/utils/nodeFilterUtil' function createMockExtensionService(): ReturnType { return { extensionCommands: { value: new Map() }, loadExtensions: vi.fn(), registerExtension: vi.fn(), invokeExtensions: vi.fn(() => []), invokeExtensionsAsync: vi.fn() } as Partial> as ReturnType< typeof useExtensionService > } // Mock the composables and services vi.mock('@/renderer/core/canvas/useCanvasInteractions', () => ({ useCanvasInteractions: vi.fn(() => ({ handleWheel: vi.fn() })) })) vi.mock('@/composables/canvas/useSelectionToolboxPosition', () => ({ useSelectionToolboxPosition: vi.fn(() => ({ visible: { value: true } })), resetMoreOptionsState: vi.fn() })) vi.mock('@/composables/element/useRetriggerableAnimation', () => ({ useRetriggerableAnimation: vi.fn(() => ({ shouldAnimate: { value: false } })) })) vi.mock('@/renderer/extensions/minimap/composables/useMinimap', () => ({ useMinimap: vi.fn(() => ({ containerStyles: { value: { backgroundColor: '#ffffff' } } })) })) vi.mock('@/services/extensionService', () => ({ useExtensionService: vi.fn(() => ({ extensionCommands: { value: new Map() }, invokeExtensions: vi.fn(() => []) })) })) vi.mock('@/utils/litegraphUtil', () => ({ isLGraphNode: vi.fn(() => true), isImageNode: vi.fn(() => false), isLoad3dNode: vi.fn(() => false) })) vi.mock('@/utils/nodeFilterUtil', () => ({ isOutputNode: vi.fn(() => false), filterOutputNodes: vi.fn((nodes) => nodes.filter(() => false)) })) vi.mock('@/platform/settings/settingStore', () => ({ useSettingStore: () => ({ get: vi.fn((key: string) => { if (key === 'Comfy.Load3D.3DViewerEnable') return true return null }) }) })) vi.mock('@/stores/commandStore', () => ({ useCommandStore: () => ({ getCommand: vi.fn(() => ({ id: 'test-command', title: 'Test Command' })) }) })) let nodeDefMock = { type: 'TestNode', title: 'Test Node' } as unknown vi.mock('@/stores/nodeDefStore', () => ({ useNodeDefStore: () => ({ fromLGraphNode: vi.fn(() => nodeDefMock) }) })) describe('SelectionToolbox', () => { let canvasStore: ReturnType const i18n = createI18n({ legacy: false, locale: 'en', messages: { en: { g: { info: 'Node Info', bookmark: 'Save to Library', frameNodes: 'Frame Nodes', moreOptions: 'More Options', refreshNode: 'Refresh Node' } } } }) const mockProvide = { isVisible: { value: true }, selectedItems: [] } beforeEach(() => { setActivePinia(createPinia()) canvasStore = useCanvasStore() // Mock the canvas to avoid "getCanvas: canvas is null" errors canvasStore.canvas = createMockCanvas() vi.resetAllMocks() }) const mountComponent = (props = {}) => { return mount(SelectionToolbox, { props, global: { plugins: [i18n, PrimeVue], provide: { [Symbol.for('SelectionOverlay')]: mockProvide }, stubs: { Panel: { template: '
', props: ['pt', 'style', 'class'] }, NodeContextMenu: { template: '
' }, InfoButton: { template: '
' }, ColorPickerButton: { template: '