Some checks failed
Deploy Application / deploy (push) Has been cancelled
255 lines
7.8 KiB
JavaScript
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();
|
|
});
|
|
});
|
|
});
|
|
|