#!/usr/bin/env node /** * TDD Test for Extracted DOMRenderer Component * * Tests the extracted DOMRenderer component independently from the monolith. * Verifies that core functionality is preserved after extraction. */ const RefactorTestRunner = require('./refactor-test-runner.js'); const runner = new RefactorTestRunner(); runner.describe('Extracted DOMRenderer Component', () => { runner.it('should load extracted DOMRenderer component', () => { // Load the extracted component delete require.cache[require.resolve('../components/dom-renderer.js')]; try { const module = require('../components/dom-renderer.js'); runner.expect(module.DOMRenderer).toBeTruthy(); runner.expect(module.FloatingMenu).toBeTruthy(); // Set globals for other tests global.ExtractedDOMRenderer = module.DOMRenderer; global.ExtractedFloatingMenu = module.FloatingMenu; } catch (error) { throw new Error(`Failed to load extracted DOMRenderer: ${error.message}`); } }); runner.it('should preserve constructor functionality', () => { const DOMRenderer = global.ExtractedDOMRenderer; // Load SectionManager from our extracted core const sectionModule = require('../core/section-manager.js'); const SectionManager = sectionModule.SectionManager; const container = document.createElement('div'); const sectionManager = new SectionManager(); const renderer = new DOMRenderer(sectionManager, container); runner.expect(renderer).toBeInstanceOf(DOMRenderer); runner.expect(renderer.sectionManager).toBe(sectionManager); runner.expect(renderer.container).toBe(container); runner.expect(renderer.editingSections).toBeInstanceOf(Set); }); runner.it('should preserve section rendering functionality', () => { const DOMRenderer = global.ExtractedDOMRenderer; const sectionModule = require('../core/section-manager.js'); const SectionManager = sectionModule.SectionManager; const container = document.createElement('div'); container.innerHTML = '
'; const sectionManager = new SectionManager(); const renderer = new DOMRenderer(sectionManager, container); const testMarkdown = '# Test Heading\nTest content'; const sections = sectionManager.createSectionsFromMarkdown(testMarkdown); // This should not throw an error renderer.renderAllSections(sections); // Check that content was rendered runner.expect(container.innerHTML.length > 100).toBeTruthy(); runner.expect(container.innerHTML).toContain('Test Heading'); }); runner.it('should preserve findSectionElement functionality', () => { const DOMRenderer = global.ExtractedDOMRenderer; const sectionModule = require('../core/section-manager.js'); const SectionManager = sectionModule.SectionManager; const container = document.createElement('div'); container.innerHTML = '
'; const sectionManager = new SectionManager(); const renderer = new DOMRenderer(sectionManager, container); const testMarkdown = '# Test Heading\nTest content'; const sections = sectionManager.createSectionsFromMarkdown(testMarkdown); renderer.renderAllSections(sections); const sectionId = sections[0].id; const element = renderer.findSectionElement(sectionId); runner.expect(element).toBeTruthy(); runner.expect(element.getAttribute('data-section-id')).toBe(sectionId); }); runner.it('should preserve event tracking functionality', () => { const DOMRenderer = global.ExtractedDOMRenderer; const sectionModule = require('../core/section-manager.js'); const SectionManager = sectionModule.SectionManager; const container = document.createElement('div'); const sectionManager = new SectionManager(); const renderer = new DOMRenderer(sectionManager, container); // Should have trackEvent method runner.expect(typeof renderer.trackEvent === 'function').toBeTruthy(); // Should be able to track an event renderer.trackEvent('test-event', { data: 'test' }); // Should have getEventStats method runner.expect(typeof renderer.getEventStats === 'function').toBeTruthy(); const stats = renderer.getEventStats(); runner.expect(typeof stats === 'object').toBeTruthy(); runner.expect(stats).toHaveProperty('stats'); runner.expect(stats).toHaveProperty('totalEvents'); runner.expect(stats).toHaveProperty('recentEvents'); }); runner.it('should preserve editor showing functionality', () => { const DOMRenderer = global.ExtractedDOMRenderer; const sectionModule = require('../core/section-manager.js'); const SectionManager = sectionModule.SectionManager; const container = document.createElement('div'); container.innerHTML = '
'; const sectionManager = new SectionManager(); const renderer = new DOMRenderer(sectionManager, container); const testMarkdown = '# Test Heading\nTest content'; const sections = sectionManager.createSectionsFromMarkdown(testMarkdown); renderer.renderAllSections(sections); const sectionId = sections[0].id; // showEditor should not throw error try { renderer.showEditor(sectionId, 'test content'); runner.expect(true).toBeTruthy(); // If we get here, no error was thrown // Check that editing state was set runner.expect(renderer.editingSections.has(sectionId)).toBeTruthy(); } catch (error) { throw new Error(`showEditor failed: ${error.message}`); } }); runner.it('should preserve FloatingMenu functionality', () => { const FloatingMenu = global.ExtractedFloatingMenu; const DOMRenderer = global.ExtractedDOMRenderer; const sectionModule = require('../core/section-manager.js'); const SectionManager = sectionModule.SectionManager; const container = document.createElement('div'); container.innerHTML = '
'; const sectionManager = new SectionManager(); const renderer = new DOMRenderer(sectionManager, container); const testMarkdown = '# Test Heading\nTest content'; const sections = sectionManager.createSectionsFromMarkdown(testMarkdown); renderer.renderAllSections(sections); const sectionId = sections[0].id; const floatingMenu = new FloatingMenu(sectionId, 'text', renderer); runner.expect(floatingMenu.sectionId).toBe(sectionId); runner.expect(floatingMenu.type).toBe('text'); runner.expect(floatingMenu.renderer).toBe(renderer); runner.expect(floatingMenu.isVisible).toBeFalsy(); // Test show/hide functionality const content = document.createElement('div'); content.textContent = 'Test content'; floatingMenu.show(content); runner.expect(floatingMenu.isVisible).toBeTruthy(); floatingMenu.hide(); runner.expect(floatingMenu.isVisible).toBeFalsy(); }); runner.it('should handle section click events', () => { const DOMRenderer = global.ExtractedDOMRenderer; const sectionModule = require('../core/section-manager.js'); const SectionManager = sectionModule.SectionManager; const container = document.createElement('div'); container.innerHTML = '
'; const sectionManager = new SectionManager(); const renderer = new DOMRenderer(sectionManager, container); const testMarkdown = '# Test Heading\nTest content'; const sections = sectionManager.createSectionsFromMarkdown(testMarkdown); renderer.renderAllSections(sections); const sectionId = sections[0].id; const element = renderer.findSectionElement(sectionId); // Simulate a click event const clickEvent = new Event('click', { bubbles: true }); Object.defineProperty(clickEvent, 'target', { value: element }); // Should not throw error try { renderer.handleSectionClick(clickEvent); runner.expect(true).toBeTruthy(); } catch (error) { throw new Error(`handleSectionClick failed: ${error.message}`); } }); // Comparative test - verify extracted component behaves similarly to original runner.it('should behave similarly to original monolithic component', () => { // Load both components const originalModule = require('/home/worsch/markitect_project/markitect/static/editor.js'); const extractedModule = require('../components/dom-renderer.js'); const sectionModule = require('../core/section-manager.js'); const originalSectionManager = new originalModule.SectionManager(); const extractedSectionManager = new sectionModule.SectionManager(); const originalContainer = document.createElement('div'); originalContainer.innerHTML = '
'; const extractedContainer = document.createElement('div'); extractedContainer.innerHTML = '
'; const originalRenderer = new originalModule.DOMRenderer(originalSectionManager, originalContainer); const extractedRenderer = new extractedModule.DOMRenderer(extractedSectionManager, extractedContainer); const testMarkdown = '# Test\nContent\n\n## Subheading\nMore content'; // Create sections with both const originalSections = originalSectionManager.createSectionsFromMarkdown(testMarkdown); const extractedSections = extractedSectionManager.createSectionsFromMarkdown(testMarkdown); // Render with both originalRenderer.renderAllSections(originalSections); extractedRenderer.renderAllSections(extractedSections); // Should have rendered content runner.expect(originalContainer.innerHTML.length > 100).toBeTruthy(); runner.expect(extractedContainer.innerHTML.length > 100).toBeTruthy(); // Should have same number of section elements const originalSectionElements = originalContainer.querySelectorAll('.ui-edit-section'); const extractedSectionElements = extractedContainer.querySelectorAll('.ui-edit-section'); runner.expect(extractedSectionElements.length).toBe(originalSectionElements.length); // Should have similar event stats structure const originalStats = originalRenderer.getEventStats(); const extractedStats = extractedRenderer.getEventStats(); runner.expect(extractedStats).toHaveProperty('stats'); runner.expect(extractedStats).toHaveProperty('totalEvents'); runner.expect(extractedStats).toHaveProperty('recentEvents'); }); }); module.exports = runner; // Run tests if called directly if (require.main === module) { console.log('🧪 Testing Extracted DOMRenderer Component'); runner.run().then(() => { console.log('✅ Extracted DOMRenderer tests completed'); }); }