/** * Tests for DrawerManager */ import { DrawerManager } from '../../resources/js/modules/livecomponent/DrawerManager.js'; describe('DrawerManager', () => { let manager; let container; beforeEach(() => { // Create container for testing container = document.createElement('div'); document.body.appendChild(container); manager = new DrawerManager(); }); afterEach(() => { manager.destroy(); if (container && container.parentNode) { container.parentNode.removeChild(container); } // Clean up any remaining drawers document.querySelectorAll('.drawer').forEach(el => el.remove()); document.querySelectorAll('.drawer-overlay').forEach(el => el.remove()); }); describe('open', () => { it('should create and show drawer', (done) => { const drawer = manager.open('test-drawer', { title: 'Test Drawer', content: '
Test content
', position: 'left', width: '400px' }); expect(drawer).toBeDefined(); expect(drawer.drawer).toBeDefined(); const drawerElement = document.querySelector('.drawer'); expect(drawerElement).toBeTruthy(); expect(drawerElement.classList.contains('drawer--left')).toBe(true); // Wait for animation frame requestAnimationFrame(() => { expect(drawer.isOpen()).toBe(true); done(); }); }); it('should create overlay when showOverlay is true', () => { manager.open('test-drawer', { showOverlay: true }); const overlay = document.querySelector('.drawer-overlay'); expect(overlay).toBeTruthy(); }); it('should not create overlay when showOverlay is false', () => { manager.open('test-drawer', { showOverlay: false }); const overlay = document.querySelector('.drawer-overlay'); expect(overlay).toBeFalsy(); }); it('should add drawer to stack', () => { manager.open('drawer-1', {}); manager.open('drawer-2', {}); expect(manager.drawerStack.length).toBe(2); expect(manager.isOpen('drawer-1')).toBe(true); expect(manager.isOpen('drawer-2')).toBe(true); }); it('should set correct z-index for stacked drawers', () => { const drawer1 = manager.open('drawer-1', {}); const drawer2 = manager.open('drawer-2', {}); const zIndex1 = parseInt(drawer1.drawer.style.zIndex); const zIndex2 = parseInt(drawer2.drawer.style.zIndex); expect(zIndex2).toBeGreaterThan(zIndex1); }); }); describe('close', () => { it('should close drawer', () => { const drawer = manager.open('test-drawer', {}); expect(manager.isOpen('test-drawer')).toBe(true); manager.close('test-drawer'); // Wait for animation setTimeout(() => { expect(manager.isOpen('test-drawer')).toBe(false); }, 350); }); it('should remove drawer from stack', () => { manager.open('drawer-1', {}); manager.open('drawer-2', {}); manager.close('drawer-1'); expect(manager.drawerStack.length).toBe(1); expect(manager.isOpen('drawer-1')).toBe(false); expect(manager.isOpen('drawer-2')).toBe(true); }); it('should handle closing non-existent drawer gracefully', () => { expect(() => { manager.close('non-existent'); }).not.toThrow(); }); }); describe('closeAll', () => { it('should close all drawers', () => { manager.open('drawer-1', {}); manager.open('drawer-2', {}); manager.open('drawer-3', {}); expect(manager.drawerStack.length).toBe(3); manager.closeAll(); expect(manager.drawerStack.length).toBe(0); }); }); describe('isOpen', () => { it('should return true for open drawer', () => { manager.open('test-drawer', {}); expect(manager.isOpen('test-drawer')).toBe(true); }); it('should return false for closed drawer', () => { expect(manager.isOpen('test-drawer')).toBe(false); }); }); describe('getTopDrawer', () => { it('should return topmost drawer', () => { manager.open('drawer-1', {}); manager.open('drawer-2', {}); const topDrawer = manager.getTopDrawer(); expect(topDrawer).toBeDefined(); expect(topDrawer.componentId).toBe('drawer-2'); }); it('should return null when no drawers are open', () => { expect(manager.getTopDrawer()).toBeNull(); }); }); describe('ESC key handling', () => { it('should close drawer on ESC when closeOnEscape is true', () => { manager.open('test-drawer', { closeOnEscape: true }); const escapeEvent = new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }); document.dispatchEvent(escapeEvent); setTimeout(() => { expect(manager.isOpen('test-drawer')).toBe(false); }, 100); }); it('should not close drawer on ESC when closeOnEscape is false', () => { manager.open('test-drawer', { closeOnEscape: false }); const escapeEvent = new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }); document.dispatchEvent(escapeEvent); expect(manager.isOpen('test-drawer')).toBe(true); }); it('should only close topmost drawer on ESC', () => { manager.open('drawer-1', { closeOnEscape: true }); manager.open('drawer-2', { closeOnEscape: true }); const escapeEvent = new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }); document.dispatchEvent(escapeEvent); setTimeout(() => { expect(manager.isOpen('drawer-2')).toBe(false); expect(manager.isOpen('drawer-1')).toBe(true); }, 100); }); }); describe('overlay click handling', () => { it('should close drawer on overlay click when closeOnOverlay is true', () => { manager.open('test-drawer', { showOverlay: true, closeOnOverlay: true }); const overlay = document.querySelector('.drawer-overlay'); overlay.click(); setTimeout(() => { expect(manager.isOpen('test-drawer')).toBe(false); }, 100); }); }); describe('focus management', () => { it('should focus drawer when opened', () => { const drawer = manager.open('test-drawer', { content: '' }); // Wait for focus setTimeout(() => { const focusedElement = document.activeElement; expect(focusedElement.closest('.drawer')).toBeTruthy(); }, 50); }); }); describe('destroy', () => { it('should cleanup all drawers and handlers', () => { manager.open('drawer-1', {}); manager.open('drawer-2', {}); manager.destroy(); expect(manager.drawerStack.length).toBe(0); expect(manager.escapeHandler).toBeNull(); }); }); });