Files
markitect-main/test_enhanced_dom_events.js
tegwick c5a5b26797
Some checks failed
Test Suite / code-quality (push) Has been cancelled
Test Suite / unit-tests (3.11) (push) Has been cancelled
Test Suite / unit-tests (3.12) (push) Has been cancelled
Test Suite / security-scan (push) Has been cancelled
Test Suite / integration-tests (push) Has been cancelled
Test Suite / e2e-tests (push) Has been cancelled
Test Suite / performance-tests (push) Has been cancelled
Test Suite / test-summary (push) Has been cancelled
refactor: Still trying to reorganize edit mode to be more robust
2025-11-04 21:59:22 +01:00

305 lines
13 KiB
JavaScript

#!/usr/bin/env node
/**
* TDD Tests for Enhanced DOM Event System Features
*/
const { TestRunner } = require('./test_runner.js');
const runner = new TestRunner();
// Test enhanced DOM event system advanced features
runner.describe('Enhanced DOM Event System Advanced Features', () => {
runner.it('should track event statistics and history', async () => {
// Load editor
delete require.cache[require.resolve('/home/worsch/markitect_project/markitect/static/editor.js')];
require('/home/worsch/markitect_project/markitect/static/editor.js');
if (global.DOMRenderer && global.SectionManager) {
const container = document.createElement('div');
const manager = new global.SectionManager();
const renderer = new global.DOMRenderer(manager, container);
// Verify event tracking capabilities
runner.expect(typeof renderer.getEventStats).toBe('function');
runner.expect(Array.isArray(renderer.eventHistory)).toBeTruthy();
runner.expect(typeof renderer.eventStats).toBe('object');
// Initial state should be empty
const initialStats = renderer.getEventStats();
runner.expect(initialStats.totalEvents).toBe(0);
runner.expect(initialStats.recentEvents.length).toBe(0);
}
});
runner.it('should track section-click events with detailed data', async () => {
if (global.DOMRenderer && global.SectionManager) {
const container = document.createElement('div');
const manager = new global.SectionManager();
const renderer = new global.DOMRenderer(manager, container);
const sections = manager.createSectionsFromMarkdown('# Test Section\n\nTest content');
// Simulate click and verify tracking
const sectionElement = container.querySelector('[data-section-id]');
if (sectionElement) {
const clickEvent = new Event('click', { bubbles: true });
sectionElement.dispatchEvent(clickEvent);
const stats = renderer.getEventStats();
runner.expect(stats.stats['section-click']).toBe(1);
runner.expect(stats.recentEvents.length).toBe(1);
runner.expect(stats.recentEvents[0].type).toBe('section-click');
runner.expect(stats.recentEvents[0].data.sectionId).toBeTruthy();
}
}
});
runner.it('should track hover events separately for enter/leave', async () => {
if (global.DOMRenderer && global.SectionManager) {
const container = document.createElement('div');
const manager = new global.SectionManager();
const renderer = new global.DOMRenderer(manager, container);
const sections = manager.createSectionsFromMarkdown('# Test Section\n\nTest content');
const sectionElement = container.querySelector('[data-section-id]');
if (sectionElement) {
// Simulate hover enter and leave
const mouseEnterEvent = new Event('mouseenter');
const mouseLeaveEvent = new Event('mouseleave');
sectionElement.dispatchEvent(mouseEnterEvent);
sectionElement.dispatchEvent(mouseLeaveEvent);
const stats = renderer.getEventStats();
runner.expect(stats.stats['section-hover-enter']).toBe(1);
runner.expect(stats.stats['section-hover-leave']).toBe(1);
}
}
});
runner.it('should track keyboard shortcuts with action data', async () => {
if (global.DOMRenderer && global.SectionManager) {
const container = document.createElement('div');
const manager = new global.SectionManager();
const renderer = new global.DOMRenderer(manager, container);
const sections = manager.createSectionsFromMarkdown('# Test Section\n\nTest content');
manager.startEditing(sections[0].id);
const textarea = container.querySelector('textarea');
if (textarea) {
// Simulate Ctrl+Enter
const keyEvent = new KeyboardEvent('keydown', {
key: 'Enter',
ctrlKey: true,
bubbles: true
});
textarea.dispatchEvent(keyEvent);
const stats = renderer.getEventStats();
runner.expect(stats.stats['keyboard-shortcut']).toBe(1);
const shortcutEvent = stats.recentEvents.find(e => e.type === 'keyboard-shortcut');
if (shortcutEvent) {
runner.expect(shortcutEvent.data.shortcut).toBe('ctrl+enter');
runner.expect(shortcutEvent.data.action).toBe('accept');
}
}
}
});
runner.it('should make sections draggable with proper attributes', async () => {
if (global.DOMRenderer && global.SectionManager) {
const container = document.createElement('div');
const manager = new global.SectionManager();
const renderer = new global.DOMRenderer(manager, container);
const sections = manager.createSectionsFromMarkdown('# Test Section\n\nTest content');
const sectionElements = container.querySelectorAll('[data-section-id]');
runner.expect(sectionElements.length).toBeGreaterThan(0);
if (sectionElements.length > 0) {
const sectionElement = sectionElements[0];
// Check draggable attribute
runner.expect(sectionElement.draggable).toBeTruthy();
// Check accessibility attributes
runner.expect(sectionElement.tabIndex).toBe(0);
runner.expect(sectionElement.getAttribute('role')).toBe('article');
runner.expect(sectionElement.getAttribute('aria-label')).toBeTruthy();
// Check for drag handle
const dragHandle = sectionElement.querySelector('.ui-edit-drag-handle');
runner.expect(dragHandle).toBeTruthy();
}
}
});
runner.it('should support context menu with proper menu items', async () => {
if (global.DOMRenderer && global.SectionManager) {
const container = document.createElement('div');
const manager = new global.SectionManager();
const renderer = new global.DOMRenderer(manager, container);
const sections = manager.createSectionsFromMarkdown('# Test Section\n\nTest content');
const sectionElement = container.querySelector('[data-section-id]');
if (sectionElement) {
// Simulate right-click
const contextMenuEvent = new Event('contextmenu', { bubbles: true });
Object.defineProperty(contextMenuEvent, 'clientX', { value: 100 });
Object.defineProperty(contextMenuEvent, 'clientY', { value: 200 });
sectionElement.dispatchEvent(contextMenuEvent);
// Check if context menu was created
const contextMenu = document.querySelector('.ui-edit-context-menu');
runner.expect(contextMenu).toBeTruthy();
if (contextMenu) {
// Should have menu items
const menuItems = contextMenu.querySelectorAll('div');
runner.expect(menuItems.length).toBeGreaterThan(3); // At least 4 items
// Clean up
contextMenu.remove();
}
// Should track the event
const stats = renderer.getEventStats();
runner.expect(stats.stats['section-context-menu']).toBe(1);
}
}
});
runner.it('should support drag and drop event tracking', async () => {
if (global.DOMRenderer && global.SectionManager) {
const container = document.createElement('div');
const manager = new global.SectionManager();
const renderer = new global.DOMRenderer(manager, container);
const sections = manager.createSectionsFromMarkdown('# Section 1\n\nContent 1\n\n# Section 2\n\nContent 2');
const sectionElements = container.querySelectorAll('[data-section-id]');
if (sectionElements.length >= 2) {
const source = sectionElements[0];
const target = sectionElements[1];
// Simulate drag start
const dragStartEvent = new Event('dragstart');
Object.defineProperty(dragStartEvent, 'dataTransfer', {
value: {
setData: () => {},
effectAllowed: null
}
});
source.dispatchEvent(dragStartEvent);
// Simulate drag over
const dragOverEvent = new Event('dragover');
Object.defineProperty(dragOverEvent, 'dataTransfer', {
value: { dropEffect: null }
});
Object.defineProperty(dragOverEvent, 'preventDefault', {
value: () => {}
});
target.dispatchEvent(dragOverEvent);
const stats = renderer.getEventStats();
runner.expect(stats.stats['section-drag-start']).toBe(1);
runner.expect(stats.stats['section-drag-over']).toBe(1);
}
}
});
runner.it('should handle multiple keyboard shortcuts correctly', async () => {
if (global.DOMRenderer && global.SectionManager) {
const container = document.createElement('div');
const manager = new global.SectionManager();
const renderer = new global.DOMRenderer(manager, container);
const sections = manager.createSectionsFromMarkdown('# Test Section\n\nTest content');
manager.startEditing(sections[0].id);
const textarea = container.querySelector('textarea');
if (textarea) {
// Test different shortcuts
const shortcuts = [
{ key: 'Enter', ctrlKey: true, expected: 'ctrl+enter' },
{ key: 's', ctrlKey: true, expected: 'ctrl+s' },
{ key: 'Escape', ctrlKey: false, expected: 'escape' }
];
for (const shortcut of shortcuts) {
// Need to restart editing for each test
if (!sections[0].isEditing()) {
manager.startEditing(sections[0].id);
}
const keyEvent = new KeyboardEvent('keydown', {
key: shortcut.key,
ctrlKey: shortcut.ctrlKey,
bubbles: true
});
textarea.dispatchEvent(keyEvent);
}
const stats = renderer.getEventStats();
runner.expect(stats.stats['keyboard-shortcut']).toBeGreaterThanOrEqual(3);
}
}
});
runner.it('should support event history with timestamps', async () => {
if (global.DOMRenderer && global.SectionManager) {
const container = document.createElement('div');
const manager = new global.SectionManager();
const renderer = new global.DOMRenderer(manager, container);
const sections = manager.createSectionsFromMarkdown('# Test Section\n\nTest content');
// Generate multiple events
const sectionElement = container.querySelector('[data-section-id]');
if (sectionElement) {
// Click event
const clickEvent = new Event('click', { bubbles: true });
sectionElement.dispatchEvent(clickEvent);
// Hover events
const mouseEnterEvent = new Event('mouseenter');
const mouseLeaveEvent = new Event('mouseleave');
sectionElement.dispatchEvent(mouseEnterEvent);
sectionElement.dispatchEvent(mouseLeaveEvent);
const stats = renderer.getEventStats();
runner.expect(stats.totalEvents).toBe(3);
runner.expect(stats.recentEvents.length).toBe(3);
// Check that events have timestamps
const hasTimestamps = stats.recentEvents.every(event =>
event.timestamp && typeof event.timestamp === 'string'
);
runner.expect(hasTimestamps).toBeTruthy();
// Check that events are properly typed
const eventTypes = stats.recentEvents.map(e => e.type);
runner.expect(eventTypes.includes('section-click')).toBeTruthy();
runner.expect(eventTypes.includes('section-hover-enter')).toBeTruthy();
runner.expect(eventTypes.includes('section-hover-leave')).toBeTruthy();
}
}
});
});
// Run the tests
if (require.main === module) {
console.log('⚡ Running Enhanced DOM Event System Advanced Feature Tests');
runner.run().then(() => {
console.log('✅ Enhanced DOM event system tests complete!');
});
}
module.exports = runner;