#!/usr/bin/env node /** * TDD Test for Extracted SectionManager Component * * Tests the extracted SectionManager component independently from the monolith. * Verifies that all functionality is preserved after extraction. */ const RefactorTestRunner = require('./refactor-test-runner.js'); const runner = new RefactorTestRunner(); runner.describe('Extracted SectionManager Component', () => { runner.it('should load extracted SectionManager component', () => { // Load the extracted component delete require.cache[require.resolve('../core/section-manager.js')]; try { const module = require('../core/section-manager.js'); runner.expect(module.SectionManager).toBeTruthy(); runner.expect(module.Section).toBeTruthy(); runner.expect(module.EditState).toBeTruthy(); runner.expect(module.SectionType).toBeTruthy(); // Set globals for other tests global.ExtractedSectionManager = module.SectionManager; global.ExtractedSection = module.Section; global.ExtractedEditState = module.EditState; global.ExtractedSectionType = module.SectionType; } catch (error) { throw new Error(`Failed to load extracted SectionManager: ${error.message}`); } }); runner.it('should preserve constructor functionality', () => { const SectionManager = global.ExtractedSectionManager; const manager = new SectionManager(); runner.expect(manager).toBeInstanceOf(SectionManager); runner.expect(manager.sections).toBeInstanceOf(Map); runner.expect(manager.listeners).toBeInstanceOf(Map); }); runner.it('should preserve section creation functionality', () => { const SectionManager = global.ExtractedSectionManager; const manager = new SectionManager(); const testMarkdown = `# Heading 1\nContent 1\n\n## Heading 2\nContent 2`; const sections = manager.createSectionsFromMarkdown(testMarkdown); runner.expect(Array.isArray(sections)).toBeTruthy(); runner.expect(sections.length).toBe(2); runner.expect(sections[0].currentMarkdown).toContain('Heading 1'); runner.expect(sections[1].currentMarkdown).toContain('Heading 2'); }); runner.it('should preserve section editing functionality', () => { const SectionManager = global.ExtractedSectionManager; const manager = new SectionManager(); const sections = manager.createSectionsFromMarkdown('# Test\nContent'); const sectionId = sections[0].id; // Test start editing const content = manager.startEditing(sectionId); runner.expect(content).toContain('Test'); const section = manager.sections.get(sectionId); runner.expect(section.isEditing()).toBeTruthy(); // Test stop editing section.stopEditing(); runner.expect(section.isEditing()).toBeFalsy(); }); runner.it('should preserve event system functionality', () => { const SectionManager = global.ExtractedSectionManager; const manager = new SectionManager(); let eventFired = false; let eventData = null; manager.on('test-event', (data) => { eventFired = true; eventData = data; }); manager.emit('test-event', { test: 'data' }); runner.expect(eventFired).toBeTruthy(); runner.expect(eventData).toEqual({ test: 'data' }); }); runner.it('should preserve document status functionality', () => { const SectionManager = global.ExtractedSectionManager; const manager = new SectionManager(); manager.createSectionsFromMarkdown('# Test\nContent'); const status = manager.getDocumentStatus(); runner.expect(status).toHaveProperty('totalSections'); runner.expect(status).toHaveProperty('editingSections'); runner.expect(status.totalSections).toBe(1); }); runner.it('should preserve getAllSections functionality', () => { const SectionManager = global.ExtractedSectionManager; const manager = new SectionManager(); const testMarkdown = '# One\nContent\n\n# Two\nMore content'; manager.createSectionsFromMarkdown(testMarkdown); const allSections = manager.getAllSections(); runner.expect(Array.isArray(allSections)).toBeTruthy(); runner.expect(allSections.length).toBe(2); }); runner.it('should preserve section splitting functionality', () => { const SectionManager = global.ExtractedSectionManager; const manager = new SectionManager(); const sections = manager.createSectionsFromMarkdown('# Original\nContent'); const sectionId = sections[0].id; const newContent = '# Split 1\nContent 1\n\n# Split 2\nContent 2'; const newSections = manager.handleSectionSplit(sectionId, newContent); runner.expect(Array.isArray(newSections)).toBeTruthy(); runner.expect(newSections.length).toBe(2); runner.expect(manager.sections.has(sectionId)).toBeFalsy(); // Original removed }); runner.it('should preserve Section class functionality', () => { const Section = global.ExtractedSection; const EditState = global.ExtractedEditState; const section = new Section('test-id', '# Test Content', 'heading'); runner.expect(section.id).toBe('test-id'); runner.expect(section.currentMarkdown).toBe('# Test Content'); runner.expect(section.type).toBe('heading'); runner.expect(section.state).toBe(EditState.ORIGINAL); }); runner.it('should preserve Section ID generation', () => { const Section = global.ExtractedSection; const id1 = Section.generateId('# Test Heading', 0); const id2 = Section.generateId('# Different Heading', 1); runner.expect(typeof id1 === 'string').toBeTruthy(); runner.expect(typeof id2 === 'string').toBeTruthy(); runner.expect(id1).toContain('section-'); runner.expect(id2).toContain('section-'); runner.expect(id1 !== id2).toBeTruthy(); // Should be unique }); runner.it('should preserve Section type detection', () => { const Section = global.ExtractedSection; const SectionType = global.ExtractedSectionType; runner.expect(Section.detectType('# Heading')).toBe(SectionType.HEADING); runner.expect(Section.detectType('![Image](url)')).toBe(SectionType.IMAGE); runner.expect(Section.detectType('```code```')).toBe(SectionType.CODE); runner.expect(Section.detectType('Regular paragraph')).toBe(SectionType.PARAGRAPH); }); // Comparative test - verify extracted component behaves identically to original runner.it('should behave identically to original monolithic component', () => { // Load both components const originalModule = require('/home/worsch/markitect_project/markitect/static/editor.js'); const extractedModule = require('../core/section-manager.js'); const originalManager = new originalModule.SectionManager(); const extractedManager = new extractedModule.SectionManager(); const testMarkdown = '# Test\nContent\n\n## Subheading\nMore content'; // Debug: Check what each component produces console.log('Creating sections with original component...'); const originalSections = originalManager.createSectionsFromMarkdown(testMarkdown); console.log(`Original produced ${originalSections.length} sections`); console.log('Creating sections with extracted component...'); const extractedSections = extractedManager.createSectionsFromMarkdown(testMarkdown); console.log(`Extracted produced ${extractedSections.length} sections`); if (originalSections.length > 0) { console.log('Original first section:', originalSections[0].currentMarkdown); } if (extractedSections.length > 0) { console.log('Extracted first section:', extractedSections[0].currentMarkdown); } // Should have same number of sections runner.expect(extractedSections.length).toBe(originalSections.length); // Should have same content for (let i = 0; i < originalSections.length; i++) { runner.expect(extractedSections[i].currentMarkdown).toBe(originalSections[i].currentMarkdown); runner.expect(extractedSections[i].type).toBe(originalSections[i].type); } // Should have same document status structure const originalStatus = originalManager.getDocumentStatus(); const extractedStatus = extractedManager.getDocumentStatus(); console.log('Original status:', originalStatus); console.log('Extracted status:', extractedStatus); runner.expect(extractedStatus.totalSections).toBe(originalStatus.totalSections); runner.expect(extractedStatus.editingSections).toBe(originalStatus.editingSections); }); }); module.exports = runner; // Run tests if called directly if (require.main === module) { console.log('🧪 Testing Extracted SectionManager Component'); runner.run().then(() => { console.log('✅ Extracted SectionManager tests completed'); }); }