Files
AEmotionStudio-ComfyUI-Magn…/tests/unit/StateManager.test.ts
T

269 lines
8.4 KiB
TypeScript

/**
* StateManager Unit Tests
*
* Tests for the StateManager class which manages info panel state.
*/
import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
// Mock localStorage
const localStorageMock = (() => {
let store: Record<string, string> = {};
return {
getItem: (key: string) => store[key] || null,
setItem: (key: string, value: string) => { store[key] = value; },
removeItem: (key: string) => { delete store[key]; },
clear: () => { store = {}; }
};
})();
Object.defineProperty(globalThis, 'localStorage', {
value: localStorageMock
});
// Mock window
Object.defineProperty(globalThis, 'window', {
value: {
matchMedia: () => ({
addListener: vi.fn(),
addEventListener: vi.fn(),
removeEventListener: vi.fn(),
}),
infoPanelManager: null
},
writable: true
});
// Mock document
Object.defineProperty(globalThis, 'document', {
value: {
body: {
getAttribute: () => null,
className: ''
},
documentElement: {
getAttribute: () => null,
className: ''
},
querySelector: () => null,
querySelectorAll: () => [],
addEventListener: vi.fn()
},
writable: true
});
// Mock getComputedStyle
(globalThis as any).getComputedStyle = () => ({
backgroundColor: 'rgb(30, 30, 30)'
});
// Mock MutationObserver
(globalThis as any).MutationObserver = class {
observe = vi.fn();
disconnect = vi.fn();
takeRecords = vi.fn();
};
// Mock app object for settings
vi.mock('/scripts/app.js', () => ({
app: {
ui: {
settings: {
getSettingValue: (key: string) => undefined
}
}
}
}));
import { StateManager } from '../../src/info-panel/StateManager';
describe('StateManager', () => {
let stateManager: StateManager;
beforeEach(() => {
vi.useFakeTimers();
stateManager = new StateManager();
});
afterEach(() => {
vi.useRealTimers();
stateManager.cleanup();
});
describe('constructor', () => {
it('should initialize with default state values', () => {
expect(stateManager.state.isPanelVisible).toBe(false);
expect(stateManager.state.isPanelMinimized).toBe(false);
expect(stateManager.state.isPanelPinned).toBe(false);
expect(stateManager.state.isPanelLocked).toBe(false);
});
it('should initialize glass preview as visible', () => {
expect(stateManager.state.isGlassPreviewVisible).toBe(true);
});
it('should initialize with node section expanded', () => {
expect(stateManager.state.expandedSections.has('node')).toBe(true);
});
it('should initialize currentInfo as null', () => {
expect(stateManager.state.currentInfo).toBeNull();
});
it('should initialize with dark theme as default', () => {
expect(stateManager.state.currentTheme).toBe('dark');
});
});
describe('togglePanelVisibility', () => {
it('should toggle panel visibility', () => {
expect(stateManager.state.isPanelVisible).toBe(false);
stateManager.togglePanelVisibility();
expect(stateManager.state.isPanelVisible).toBe(true);
stateManager.togglePanelVisibility();
expect(stateManager.state.isPanelVisible).toBe(false);
});
it('should return new visibility state', () => {
expect(stateManager.togglePanelVisibility()).toBe(true);
expect(stateManager.togglePanelVisibility()).toBe(false);
});
});
describe('toggleGlassPreview', () => {
it('should toggle glass preview visibility', () => {
expect(stateManager.state.isGlassPreviewVisible).toBe(true);
stateManager.toggleGlassPreview();
expect(stateManager.state.isGlassPreviewVisible).toBe(false);
stateManager.toggleGlassPreview();
expect(stateManager.state.isGlassPreviewVisible).toBe(true);
});
});
describe('togglePinning', () => {
it('should toggle pinned state', () => {
expect(stateManager.state.isPanelPinned).toBe(false);
stateManager.togglePinning();
expect(stateManager.state.isPanelPinned).toBe(true);
stateManager.togglePinning();
expect(stateManager.state.isPanelPinned).toBe(false);
});
it('should clear locked state when unpinning', () => {
stateManager.state.isPanelPinned = true;
stateManager.state.isPanelLocked = true;
stateManager.togglePinning(); // Unpin
expect(stateManager.state.isPanelLocked).toBe(false);
});
});
describe('toggleLocking', () => {
it('should not allow locking when not pinned', () => {
stateManager.state.isPanelPinned = false;
const result = stateManager.toggleLocking();
expect(result).toBe(false);
expect(stateManager.state.isPanelLocked).toBe(false);
});
it('should toggle locking when pinned', () => {
stateManager.state.isPanelPinned = true;
stateManager.toggleLocking();
expect(stateManager.state.isPanelLocked).toBe(true);
stateManager.toggleLocking();
expect(stateManager.state.isPanelLocked).toBe(false);
});
});
describe('toggleMinimized', () => {
it('should toggle minimized state', () => {
expect(stateManager.state.isPanelMinimized).toBe(false);
stateManager.toggleMinimized();
expect(stateManager.state.isPanelMinimized).toBe(true);
stateManager.toggleMinimized();
expect(stateManager.state.isPanelMinimized).toBe(false);
});
});
describe('toggleSection', () => {
it('should not toggle node section (always expanded)', () => {
const result = stateManager.toggleSection('node');
expect(result).toBe(false);
});
it('should toggle other sections', () => {
expect(stateManager.state.expandedSections.has('media')).toBe(false);
stateManager.toggleSection('media');
expect(stateManager.state.expandedSections.has('media')).toBe(true);
stateManager.toggleSection('media');
expect(stateManager.state.expandedSections.has('media')).toBe(false);
});
});
describe('setPinnedPosition', () => {
it('should set pinned position', () => {
stateManager.setPinnedPosition(100, 200);
expect(stateManager.state.pinnedPosition).toEqual({ x: 100, y: 200 });
expect(stateManager.state.lastPinnedPosition).toEqual({ x: 100, y: 200 });
});
});
describe('setCurrentInfo', () => {
it('should set current info', () => {
const mockInfo = {
timestamp: Date.now(),
cursor: { screenX: 0, screenY: 0, canvasX: 0, canvasY: 0 },
zoom: 1,
nodeCount: 5,
hoveredNode: null,
hoveredWidget: null,
mediaElement: null
};
stateManager.setCurrentInfo(mockInfo);
expect(stateManager.state.currentInfo).toEqual(mockInfo);
});
});
describe('expandNodeSections', () => {
it('should expand all node-related sections', () => {
stateManager.expandNodeSections();
expect(stateManager.state.expandedSections.has('hoveredNode')).toBe(true);
expect(stateManager.state.expandedSections.has('node')).toBe(true);
expect(stateManager.state.expandedSections.has('cursor')).toBe(true);
expect(stateManager.state.expandedSections.has('canvas')).toBe(true);
expect(stateManager.state.expandedSections.has('magnifier')).toBe(true);
});
});
describe('collapseNodeSections', () => {
it('should collapse node-related sections', () => {
stateManager.state.expandedSections.add('hoveredNode');
stateManager.state.expandedSections.add('widget');
stateManager.collapseNodeSections();
expect(stateManager.state.expandedSections.has('hoveredNode')).toBe(false);
expect(stateManager.state.expandedSections.has('widget')).toBe(false);
});
});
});