/** * Section Splitting Functionality Tests * * Tests dynamic section splitting when headings are detected * Based on functionality from history/javascript-dev-tests/test_section_splitting.js */ describe('Section Splitting', () => { let sectionManager; beforeEach(() => { // Setup DOM document.body.innerHTML = `

Original content

`; // Load components require('../core/section-manager.js'); if (global.SectionManager) { sectionManager = new global.SectionManager(); } }); afterEach(() => { document.body.innerHTML = ''; jest.clearAllMocks(); }); describe('Heading detection', () => { test('should detect new headings in content', () => { const textWithHeading = ` This is some content. # New Heading This should be a new section. `; // Test heading detection with regex const lines = textWithHeading.trim().split('\n'); const headingLine = lines.find(line => /^#+ /.test(line.trim())); expect(headingLine).toBeTruthy(); expect(headingLine.trim()).toBe('# New Heading'); }); test('should identify different heading levels', () => { const headingTests = [ { text: '# Heading 1', level: 1 }, { text: '## Heading 2', level: 2 }, { text: '### Heading 3', level: 3 }, { text: '#### Heading 4', level: 4 } ]; headingTests.forEach(({ text, level }) => { const match = text.match(/^(#+) /); expect(match).toBeTruthy(); if (match) { expect(match[1].length).toBe(level); } }); }); test('should distinguish headings from regular text', () => { const testCases = [ { text: '# This is a heading', isHeading: true }, { text: 'This is not a heading', isHeading: false }, { text: 'Neither is this # hash in middle', isHeading: false }, { text: '## Another heading', isHeading: true } ]; testCases.forEach(({ text, isHeading }) => { const match = /^#+\s/.test(text.trim()); expect(match).toBe(isHeading); }); }); }); describe('Section splitting logic', () => { test('should split content when heading is detected', () => { const originalContent = 'Original content without headings'; const newContent = ` ${originalContent} # New Section New section content `; // Simulate section splitting logic const parts = newContent.split(/\n(?=#)/); if (parts.length > 1) { expect(parts.length).toBeGreaterThan(1); expect(parts[0]).toContain('Original content'); expect(parts[1]).toContain('# New Section'); } }); test('should preserve content when no headings are present', () => { const content = 'Just regular content without any headings'; const parts = content.split(/\n(?=#)/); expect(parts.length).toBe(1); expect(parts[0]).toBe(content); }); test('should handle multiple headings correctly', () => { const contentWithMultipleHeadings = `Initial content # First Heading First section content ## Second Heading Second section content # Third Heading Third section content`; // Split on lines that start with headings const parts = contentWithMultipleHeadings.split(/\n(?=#)/); // Should split into multiple sections expect(parts.length).toBeGreaterThanOrEqual(2); // Find heading lines const headings = contentWithMultipleHeadings.match(/^#+.*$/gm); expect(headings).toBeTruthy(); expect(headings.length).toBe(3); }); }); describe('SectionManager integration', () => { test('should have handleSectionSplit method', () => { if (!sectionManager) { console.warn('SectionManager not available, skipping test'); return; } expect(typeof sectionManager.handleSectionSplit).toBe('function'); }); test('should maintain section state during splits', () => { if (!sectionManager) return; const originalSectionCount = document.querySelectorAll('.section').length; // Mock section splitting const mockNewSection = document.createElement('div'); mockNewSection.className = 'section'; mockNewSection.setAttribute('data-section-id', 'split-section'); if (originalSectionCount > 0) { expect(originalSectionCount).toBeGreaterThan(0); } }); }); describe('Dynamic section creation', () => { test('should create new section elements when splitting', () => { const sectionContent = ` Original content # New Section Title New section content `; // Simulate section creation const newSection = document.createElement('div'); newSection.className = 'section'; newSection.setAttribute('data-section-id', 'generated-section-id'); const contentDiv = document.createElement('div'); contentDiv.className = 'section-content'; contentDiv.textContent = 'New section content'; newSection.appendChild(contentDiv); expect(newSection.className).toBe('section'); expect(newSection.getAttribute('data-section-id')).toBeTruthy(); expect(newSection.querySelector('.section-content')).toBeTruthy(); }); test('should generate unique section IDs', () => { const headingText = 'My New Section'; // Simulate ID generation from heading const sectionId = headingText .toLowerCase() .replace(/[^a-z0-9]+/g, '-') .replace(/^-+|-+$/g, ''); expect(sectionId).toBe('my-new-section'); }); test('should preserve section hierarchy', () => { const hierarchicalContent = ` # Main Section Main content ## Subsection Sub content ### Sub-subsection Sub-sub content `; const headings = hierarchicalContent.match(/^#+.*$/gm); if (headings) { expect(headings.length).toBe(3); expect(headings[0]).toMatch(/^# /); expect(headings[1]).toMatch(/^## /); expect(headings[2]).toMatch(/^### /); } }); }); describe('Section splitting edge cases', () => { test('should handle empty headings gracefully', () => { const contentWithEmptyHeading = ` Content before # Content after `; const parts = contentWithEmptyHeading.split(/\n(?=#)/); expect(parts.length).toBeGreaterThanOrEqual(1); }); test('should handle headings at the start of content', () => { const contentStartingWithHeading = `# First Heading Content for first section # Second Heading Content for second section `; const parts = contentStartingWithHeading.split(/\n(?=#)/); expect(parts[0]).toContain('# First Heading'); }); test('should handle malformed headings', () => { const malformedHeadings = [ '#NoSpace', '# ', '########## Too many hashes', 'Not a heading # at all' ]; malformedHeadings.forEach(text => { const isValidHeading = /^#{1,6}\s+\S/.test(text); // Most should be invalid except properly formatted ones expect(typeof isValidHeading).toBe('boolean'); }); }); }); });