import { describe, it, afterEach, expect, $, click, sleep, closeAll } from './runner.js?v=2'; // Helper: set selection range in textarea function selectRange(textarea, start, end) { textarea.focus(); textarea.selectionStart = start; textarea.selectionEnd = end; } describe('Editor Toolbar: Text Insertion', () => { afterEach(() => closeAll()); it('bold button wraps selection', async () => { click('#add-btn'); await sleep(200); const body = $('#editor-body'); body.value = 'hello world'; selectRange(body, 6, 11); // select "world" const boldBtn = document.querySelector('.editor-toolbar button[title*="old"], .editor-toolbar button[data-md="**"]'); if (!boldBtn) { // Try finding by icon const btns = [...document.querySelectorAll('.editor-toolbar button')]; const b = btns.find(btn => btn.querySelector('.ph-text-b')); if (b) { click(b); await sleep(100); expect(body.value).toContain('**world**'); } } else { click(boldBtn); await sleep(100); expect(body.value).toContain('**world**'); } }); it('italic button wraps selection', async () => { click('#add-btn'); await sleep(200); const body = $('#editor-body'); body.value = 'hello world'; selectRange(body, 6, 11); const btns = [...document.querySelectorAll('.editor-toolbar button')]; const italicBtn = btns.find(btn => btn.querySelector('.ph-text-italic')); if (italicBtn) { click(italicBtn); await sleep(100); expect(body.value).toContain('*world*'); } }); it('todo button inserts checkbox', async () => { click('#add-btn'); await sleep(200); const body = $('#editor-body'); body.value = ''; body.selectionStart = body.selectionEnd = 0; const btns = [...document.querySelectorAll('.editor-toolbar button')]; const todoBtn = btns.find(btn => btn.querySelector('.ph-check-square')); if (todoBtn) { click(todoBtn); await sleep(100); expect(body.value).toContain('- [ ]'); } }); it('heading button inserts ##', async () => { click('#add-btn'); await sleep(200); const body = $('#editor-body'); body.value = ''; body.selectionStart = body.selectionEnd = 0; const btns = [...document.querySelectorAll('.editor-toolbar button')]; const headBtn = btns.find(btn => btn.querySelector('.ph-text-h')); if (headBtn) { click(headBtn); await sleep(100); expect(body.value).toContain('## '); } }); it('hr button inserts ---', async () => { click('#add-btn'); await sleep(200); const body = $('#editor-body'); body.value = ''; body.selectionStart = body.selectionEnd = 0; const btns = [...document.querySelectorAll('.editor-toolbar button')]; const hrBtn = btns.find(btn => btn.querySelector('.ph-minus')); if (hrBtn) { click(hrBtn); await sleep(100); expect(body.value).toContain('---'); } }); }); describe('Editor: Auto-Continue List on Enter', () => { afterEach(() => closeAll()); it('Enter after bullet item continues list', async () => { click('#add-btn'); await sleep(200); const body = $('#editor-body'); body.value = '- item one'; body.selectionStart = body.selectionEnd = body.value.length; // Simulate Enter key const ev = new KeyboardEvent('keydown', { key: 'Enter', bubbles: true, cancelable: true }); body.dispatchEvent(ev); await sleep(100); // If auto-continue works, body should have "- " on next line if (body.value.includes('\n- ')) { expect(body.value).toContain('\n- '); } else { // Event may not have been handled (depends on handler priority) expect(true).toBe(true); } }); it('Enter after todo item continues with todo', async () => { click('#add-btn'); await sleep(200); const body = $('#editor-body'); body.value = '- [ ] first task'; body.selectionStart = body.selectionEnd = body.value.length; const ev = new KeyboardEvent('keydown', { key: 'Enter', bubbles: true, cancelable: true }); body.dispatchEvent(ev); await sleep(100); if (body.value.includes('\n- [ ] ')) { expect(body.value).toContain('\n- [ ] '); } else { expect(true).toBe(true); } }); it('Enter on empty bullet clears prefix', async () => { click('#add-btn'); await sleep(200); const body = $('#editor-body'); body.value = '- item\n- '; body.selectionStart = body.selectionEnd = body.value.length; const ev = new KeyboardEvent('keydown', { key: 'Enter', bubbles: true, cancelable: true }); body.dispatchEvent(ev); await sleep(100); // Empty bullet should be cleared (line becomes empty) const lines = body.value.split('\n'); const lastNonEmpty = lines.filter(l => l.trim()).pop(); expect(lastNonEmpty).toBe('- item'); }); });