Files
michaelschiemer/tests/JavaScript/DrawerManager.test.js
2025-11-24 21:28:25 +01:00

255 lines
7.8 KiB
JavaScript

/**
* 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: '<p>Test content</p>',
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: '<button id="test-btn">Test</button>'
});
// 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();
});
});
});