#!/usr/bin/env node /** * Test Alt Text in Margin Layout * * Tests that the alt text input is moved to the margin area alongside buttons */ const { TestRunner } = require('./test_runner.js'); const runner = new TestRunner(); runner.describe('Alt Text in Margin Layout Tests', () => { runner.it('should place alt text container in controls (margin) area', 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'); container.innerHTML = '
'; document.body.appendChild(container); const manager = new global.SectionManager(); const renderer = new global.DOMRenderer(manager, container); // Create section with image const imageMarkdown = '![Test Alt Text](https://via.placeholder.com/400x200)'; const sections = manager.createSectionsFromMarkdown(imageMarkdown); const imageSection = sections[0]; // Mock element const mockElement = document.createElement('div'); mockElement.setAttribute('data-section-id', imageSection.id); renderer.findSectionElement = () => mockElement; // Show image editor renderer.showImageEditor(imageSection.id, imageSection); // Verify alt text container is in controls area const controls = mockElement.querySelector('.ui-edit-controls'); const altTextContainer = controls.querySelector('.ui-edit-alt-text-container'); runner.expect(altTextContainer).toBeTruthy(); // Verify alt text is NOT in main editor content const editorContent = mockElement.querySelector('.ui-edit-image-content'); const altTextInContent = editorContent.querySelector('.ui-edit-alt-text-container'); runner.expect(altTextInContent).toBeFalsy(); // Verify alt text input exists and has correct value const altTextInput = altTextContainer.querySelector('input[type="text"]'); runner.expect(altTextInput).toBeTruthy(); runner.expect(altTextInput.value).toBe('Test Alt Text'); // Cleanup document.body.removeChild(container); } }); runner.it('should position alt text before buttons in controls', async () => { if (global.DOMRenderer && global.SectionManager) { const container = document.createElement('div'); container.innerHTML = '
'; document.body.appendChild(container); const manager = new global.SectionManager(); const renderer = new global.DOMRenderer(manager, container); const imageMarkdown = '![Test](https://via.placeholder.com/400x200)'; const sections = manager.createSectionsFromMarkdown(imageMarkdown); const imageSection = sections[0]; const mockElement = document.createElement('div'); mockElement.setAttribute('data-section-id', imageSection.id); renderer.findSectionElement = () => mockElement; renderer.showImageEditor(imageSection.id, imageSection); // Get controls container and verify order const controls = mockElement.querySelector('.ui-edit-controls'); const children = Array.from(controls.children); // Verify alt text container is first runner.expect(children[0].className).toBe('ui-edit-alt-text-container'); // Verify change indicator is second runner.expect(children[1].className).toBe('change-indicator'); // Verify buttons follow const acceptBtn = children.find(child => child.textContent.includes('Accept')); const cancelBtn = children.find(child => child.textContent.includes('Cancel')); const resetBtn = children.find(child => child.textContent.includes('Reset')); runner.expect(acceptBtn).toBeTruthy(); runner.expect(cancelBtn).toBeTruthy(); runner.expect(resetBtn).toBeTruthy(); // Cleanup document.body.removeChild(container); } }); runner.it('should include responsive CSS for alt text layout', async () => { if (global.DOMRenderer && global.SectionManager) { const container = document.createElement('div'); container.innerHTML = '
'; document.body.appendChild(container); const manager = new global.SectionManager(); const renderer = new global.DOMRenderer(manager, container); const imageMarkdown = '![Test](https://via.placeholder.com/400x200)'; const sections = manager.createSectionsFromMarkdown(imageMarkdown); const imageSection = sections[0]; const mockElement = document.createElement('div'); mockElement.setAttribute('data-section-id', imageSection.id); renderer.findSectionElement = () => mockElement; // Show editor (this adds responsive CSS) renderer.showImageEditor(imageSection.id, imageSection); // Verify responsive style includes alt text rules const responsiveStyles = Array.from(document.head.querySelectorAll('style')).find(style => style.textContent.includes('@media (max-width: 1024px)') ); runner.expect(responsiveStyles).toBeTruthy(); const cssText = responsiveStyles.textContent; runner.expect(cssText.includes('.ui-edit-alt-text-container')).toBeTruthy(); runner.expect(cssText.includes('flex: 1 !important')).toBeTruthy(); runner.expect(cssText.includes('min-width: 200px !important')).toBeTruthy(); runner.expect(cssText.includes('.change-indicator')).toBeTruthy(); runner.expect(cssText.includes('order: -1 !important')).toBeTruthy(); // Cleanup document.body.removeChild(container); } }); runner.it('should handle alt text changes in margin layout', async () => { if (global.DOMRenderer && global.SectionManager) { const container = document.createElement('div'); container.innerHTML = '
'; document.body.appendChild(container); const manager = new global.SectionManager(); const renderer = new global.DOMRenderer(manager, container); const imageMarkdown = '![Original](https://via.placeholder.com/400x200)'; const sections = manager.createSectionsFromMarkdown(imageMarkdown); const imageSection = sections[0]; const mockElement = document.createElement('div'); mockElement.setAttribute('data-section-id', imageSection.id); renderer.findSectionElement = () => mockElement; renderer.showImageEditor(imageSection.id, imageSection); // Get alt text input from controls const controls = mockElement.querySelector('.ui-edit-controls'); const altTextInput = controls.querySelector('input[type="text"]'); const changeIndicator = controls.querySelector('.change-indicator'); // Verify initial state runner.expect(altTextInput.value).toBe('Original'); runner.expect(changeIndicator.style.display).toBe('none'); // Modify alt text altTextInput.value = 'Modified in Margin'; const inputEvent = new Event('input', { bubbles: true }); altTextInput.dispatchEvent(inputEvent); // Verify change indicator appears (change indicator display logic is in closure) runner.expect(changeIndicator).toBeTruthy(); // Cleanup document.body.removeChild(container); } }); runner.it('should maintain wider controls area for alt text', async () => { if (global.DOMRenderer && global.SectionManager) { const container = document.createElement('div'); container.innerHTML = '
'; document.body.appendChild(container); const manager = new global.SectionManager(); const renderer = new global.DOMRenderer(manager, container); const imageMarkdown = '![Test](https://via.placeholder.com/400x200)'; const sections = manager.createSectionsFromMarkdown(imageMarkdown); const imageSection = sections[0]; const mockElement = document.createElement('div'); mockElement.setAttribute('data-section-id', imageSection.id); renderer.findSectionElement = () => mockElement; renderer.showImageEditor(imageSection.id, imageSection); // Verify controls area is wider to accommodate alt text const controls = mockElement.querySelector('.ui-edit-controls'); runner.expect(controls.style.minWidth).toBe('180px'); // Increased from 100px // Cleanup document.body.removeChild(container); } }); }); // Run the tests if (require.main === module) { console.log('📝 Running Alt Text in Margin Layout Tests'); runner.run().then(() => { const results = runner.results; const failed = results.filter(r => r.status === 'FAIL').length; if (failed > 0) { console.log(`❌ ${failed} test(s) failed - alt text margin layout needs attention`); } else { console.log('✅ All alt text margin layout tests passed!'); } }); } module.exports = runner;