diff --git a/markitect/clean_document_manager.py b/markitect/clean_document_manager.py index d3d3cd72..fa92f8f4 100644 --- a/markitect/clean_document_manager.py +++ b/markitect/clean_document_manager.py @@ -1238,7 +1238,16 @@ document.addEventListener('DOMContentLoaded', function() { }, 'reset-all': () => { console.log('Reset all clicked'); - // TODO: Implement reset functionality + // Hide any open editors + domRenderer.hideCurrentEditor(); + // Reset all sections to original state + const allSections = Array.from(sectionManager.sections.values()); + allSections.forEach(section => { + section.resetToOriginal(); + }); + // Re-render all sections + domRenderer.renderAllSections(allSections); + debugPanel.addMessage(`Reset all sections to original state`, 'INFO'); }, 'show-status': () => { const status = sectionManager.getDocumentStatus(); @@ -1260,6 +1269,16 @@ document.addEventListener('DOMContentLoaded', function() { sectionManager.on('changes-accepted', (data) => { debugPanel.addMessage(`Changes accepted for section: ${data.sectionId}`, 'SUCCESS'); + // Re-render the section to show updated content + const section = sectionManager.sections.get(data.sectionId); + if (section) { + const sectionElement = domRenderer.findSectionElement(data.sectionId); + if (sectionElement) { + const newElement = domRenderer.renderSection(section); + sectionElement.parentNode.replaceChild(newElement, sectionElement); + debugPanel.addMessage(`DOM updated for section: ${data.sectionId}`, 'INFO'); + } + } }); sectionManager.on('changes-cancelled', (data) => { diff --git a/markitect/static/js/tests/test-real-user-functionality.js b/markitect/static/js/tests/test-real-user-functionality.js new file mode 100644 index 00000000..3d7fddef --- /dev/null +++ b/markitect/static/js/tests/test-real-user-functionality.js @@ -0,0 +1,285 @@ +#!/usr/bin/env node + +/** + * Real User Functionality Tests + * + * This test file validates the actual functionality that users experience, + * not just internal API calls. It tests the complete user workflow. + */ + +const RefactorTestRunner = require('./refactor-test-runner.js'); + +const runner = new RefactorTestRunner(); + +runner.describe('Real User Functionality Tests', () => { + + runner.it('should allow users to edit content and see changes in DOM', () => { + // Load all extracted components + const sectionModule = require('../core/section-manager.js'); + const domModule = require('../components/dom-renderer.js'); + const debugModule = require('../components/debug-panel.js'); + const controlsModule = require('../components/document-controls.js'); + + const { SectionManager } = sectionModule; + const { DOMRenderer } = domModule; + const { DebugPanel } = debugModule; + const { DocumentControls } = controlsModule; + + // Setup DOM container + const container = document.createElement('div'); + container.innerHTML = '
'; + document.body.appendChild(container); + + // Create components + const sectionManager = new SectionManager(); + const domRenderer = new DOMRenderer(sectionManager, container); + const debugPanel = new DebugPanel(); + const documentControls = new DocumentControls(); + + // Setup document controls + documentControls.create(); + + // Create sections from test markdown + const testMarkdown = `# Original Title\nOriginal content that should be editable.`; + const sections = sectionManager.createSectionsFromMarkdown(testMarkdown); + domRenderer.renderAllSections(sections); + + const firstSection = sections[0]; + const sectionElement = container.querySelector(`[data-section-id="${firstSection.id}"]`); + + // Verify original content is rendered + runner.expect(sectionElement.innerHTML).toContain('Original Title'); + + // Simulate user clicking on section + const clickEvent = new Event('click', { bubbles: true }); + sectionElement.dispatchEvent(clickEvent); + + // Verify editing state is active + runner.expect(firstSection.isEditing()).toBeTruthy(); + + // Find the floating menu and edit controls + const floatingMenu = document.querySelector('.ui-edit-floating-menu'); + runner.expect(floatingMenu).toBeTruthy(); + + const textarea = floatingMenu.querySelector('textarea'); + const acceptButton = Array.from(floatingMenu.querySelectorAll('button')).find(btn => btn.textContent.includes('Accept')); + + runner.expect(textarea).toBeTruthy(); + runner.expect(acceptButton).toBeTruthy(); + + // Simulate user editing content + const newContent = '# Updated Title\nCompletely new content added by user.'; + textarea.value = newContent; + + // Simulate user clicking accept + acceptButton.click(); + + // Verify section is no longer editing + runner.expect(firstSection.isEditing()).toBeFalsy(); + + // Verify floating menu is gone + const menuAfterAccept = document.querySelector('.ui-edit-floating-menu'); + runner.expect(menuAfterAccept).toBeFalsy(); + + // CRITICAL TEST: Verify DOM was actually updated with new content + const updatedElement = container.querySelector(`[data-section-id="${firstSection.id}"]`); + runner.expect(updatedElement.innerHTML).toContain('Updated Title'); + runner.expect(updatedElement.innerHTML).toContain('Completely new content'); + runner.expect(updatedElement.innerHTML).not.toContain('Original Title'); + + // Cleanup + document.body.removeChild(container); + documentControls.destroy(); + }); + + runner.it('should allow users to reset all changes', () => { + // Setup similar to above + const sectionModule = require('../core/section-manager.js'); + const domModule = require('../components/dom-renderer.js'); + const controlsModule = require('../components/document-controls.js'); + + const { SectionManager } = sectionModule; + const { DOMRenderer } = domModule; + const { DocumentControls } = controlsModule; + + const container = document.createElement('div'); + container.innerHTML = '
'; + document.body.appendChild(container); + + const sectionManager = new SectionManager(); + const domRenderer = new DOMRenderer(sectionManager, container); + const documentControls = new DocumentControls(); + + documentControls.create(); + + // Create and modify content + const testMarkdown = `# Test Section\nOriginal content for reset test.`; + const sections = sectionManager.createSectionsFromMarkdown(testMarkdown); + domRenderer.renderAllSections(sections); + + const firstSection = sections[0]; + + // Make changes to the section + sectionManager.startEditing(firstSection.id); + sectionManager.updateContent(firstSection.id, '# Modified Title\nModified content.'); + sectionManager.acceptChanges(firstSection.id); + + // Verify changes are applied + let sectionElement = container.querySelector(`[data-section-id="${firstSection.id}"]`); + runner.expect(sectionElement.innerHTML).toContain('Modified Title'); + runner.expect(firstSection.hasChanges()).toBeTruthy(); + + // Test reset functionality + const resetButton = documentControls.getButton('reset-all'); + runner.expect(resetButton).toBeTruthy(); + + // Click reset button + resetButton.click(); + + // Verify content is reset + sectionElement = container.querySelector(`[data-section-id="${firstSection.id}"]`); + runner.expect(sectionElement.innerHTML).toContain('Test Section'); + runner.expect(sectionElement.innerHTML).not.toContain('Modified Title'); + runner.expect(firstSection.hasChanges()).toBeFalsy(); + + // Cleanup + document.body.removeChild(container); + documentControls.destroy(); + }); + + runner.it('should handle cancel operations correctly', () => { + const sectionModule = require('../core/section-manager.js'); + const domModule = require('../components/dom-renderer.js'); + + const { SectionManager } = sectionModule; + const { DOMRenderer } = domModule; + + const container = document.createElement('div'); + container.innerHTML = '
'; + document.body.appendChild(container); + + const sectionManager = new SectionManager(); + const domRenderer = new DOMRenderer(sectionManager, container); + + const testMarkdown = `# Cancel Test\nContent that should remain unchanged.`; + const sections = sectionManager.createSectionsFromMarkdown(testMarkdown); + domRenderer.renderAllSections(sections); + + const firstSection = sections[0]; + const originalContent = firstSection.currentMarkdown; + + // Start editing + const sectionElement = container.querySelector(`[data-section-id="${firstSection.id}"]`); + sectionElement.click(); + + // Make changes but cancel them + const floatingMenu = document.querySelector('.ui-edit-floating-menu'); + const textarea = floatingMenu.querySelector('textarea'); + const cancelButton = Array.from(floatingMenu.querySelectorAll('button')).find(btn => btn.textContent.includes('Cancel')); + + textarea.value = '# This should be cancelled\nThis content should not appear.'; + cancelButton.click(); + + // Verify content is unchanged + const unchangedElement = container.querySelector(`[data-section-id="${firstSection.id}"]`); + runner.expect(unchangedElement.innerHTML).toContain('Cancel Test'); + runner.expect(unchangedElement.innerHTML).not.toContain('This should be cancelled'); + runner.expect(firstSection.currentMarkdown).toBe(originalContent); + + // Cleanup + document.body.removeChild(container); + }); + + runner.it('should validate the complete editing workflow', () => { + // This test validates the entire user experience end-to-end + const sectionModule = require('../core/section-manager.js'); + const domModule = require('../components/dom-renderer.js'); + const debugModule = require('../components/debug-panel.js'); + const controlsModule = require('../components/document-controls.js'); + + const { SectionManager } = sectionModule; + const { DOMRenderer } = domModule; + const { DebugPanel } = debugModule; + const { DocumentControls } = controlsModule; + + const container = document.createElement('div'); + container.innerHTML = '
'; + document.body.appendChild(container); + + const sectionManager = new SectionManager(); + const domRenderer = new DOMRenderer(sectionManager, container); + const debugPanel = new DebugPanel(); + const documentControls = new DocumentControls(); + + documentControls.create(); + + // Multi-section document + const testMarkdown = `# Document Title +Introduction paragraph. + +## Section A +Content for section A. + +## Section B +Content for section B.`; + + const sections = sectionManager.createSectionsFromMarkdown(testMarkdown); + domRenderer.renderAllSections(sections); + + // Verify all sections are rendered + const renderedSections = container.querySelectorAll('.ui-edit-section'); + runner.expect(renderedSections.length).toBe(sections.length); + + // Test editing multiple sections + const firstSection = sections[0]; + const secondSection = sections[2]; // Section A + + // Edit first section + renderedSections[0].click(); + let floatingMenu = document.querySelector('.ui-edit-floating-menu'); + let textarea = floatingMenu.querySelector('textarea'); + let acceptButton = Array.from(floatingMenu.querySelectorAll('button')).find(btn => btn.textContent.includes('Accept')); + + textarea.value = '# Updated Document Title\nUpdated introduction.'; + acceptButton.click(); + + // Edit second section + renderedSections[2].click(); + floatingMenu = document.querySelector('.ui-edit-floating-menu'); + textarea = floatingMenu.querySelector('textarea'); + acceptButton = Array.from(floatingMenu.querySelectorAll('button')).find(btn => btn.textContent.includes('Accept')); + + textarea.value = '## Updated Section A\nCompletely new content for section A.'; + acceptButton.click(); + + // Verify both sections were updated + const updatedSections = container.querySelectorAll('.ui-edit-section'); + runner.expect(updatedSections[0].innerHTML).toContain('Updated Document Title'); + runner.expect(updatedSections[2].innerHTML).toContain('Updated Section A'); + + // Test reset restores all sections + const resetButton = documentControls.getButton('reset-all'); + resetButton.click(); + + const resetSections = container.querySelectorAll('.ui-edit-section'); + runner.expect(resetSections[0].innerHTML).toContain('Document Title'); + runner.expect(resetSections[0].innerHTML).not.toContain('Updated Document Title'); + runner.expect(resetSections[2].innerHTML).toContain('Section A'); + runner.expect(resetSections[2].innerHTML).not.toContain('Updated Section A'); + + // Cleanup + document.body.removeChild(container); + documentControls.destroy(); + }); +}); + +module.exports = runner; + +// Run tests if called directly +if (require.main === module) { + console.log('🧪 Running Real User Functionality Tests'); + runner.run().then(() => { + console.log('✅ Real user functionality tests completed'); + console.log('These tests validate what users actually experience, not just internal APIs'); + }); +} \ No newline at end of file