"""Parser and browser coverage for document heading navigation.""" import json import subprocess from pathlib import Path ROOT = Path(__file__).resolve().parents[1] DOC_JS = (ROOT / "static/js/document.js").read_text(encoding="utf-8") STYLE = (ROOT / "static/style.css").read_text(encoding="utf-8") def _run_node(script: str): result = subprocess.run( ["node", "--input-type=module", "-e", script], cwd=ROOT, check=False, capture_output=True, text=True, ) assert result.returncode == 0, result.stderr return json.loads(result.stdout) def test_markdown_outline_parses_structure_and_ignores_fenced_code(): data = _run_node( r""" import { parseMarkdownOutline } from './static/js/documentOutline.js'; const source = [ '# Overview', '', '## [Linked section](https://example.com) ##', '', '```md', '# Not a real heading', '```', '', 'Setext title', '------------', '', '#### Final `code` section', ].join('\n'); console.log(JSON.stringify(parseMarkdownOutline(source))); """ ) assert [(entry["level"], entry["text"]) for entry in data] == [ (1, "Overview"), (2, "Linked section"), (2, "Setext title"), (4, "Final code section"), ] source_slice = data[1]["end"] - data[1]["start"] assert source_slice > len("Linked section") assert data[2]["line"] == 8 def test_outline_control_is_mode_aware_live_and_accessible(): assert 'id="doc-outline-toolbar-btn"' in DOC_JS assert 'aria-haspopup="true"' in DOC_JS assert "language === 'markdown' || _isRichTextLang(language)" in DOC_JS assert "_refreshDocumentOutline();" in DOC_JS assert "bindMenuDismiss(menu" in DOC_JS assert ".doc-outline-menu" in STYLE assert "@media (max-width: 768px)" in STYLE def test_outline_jumps_in_markdown_and_rich_text_and_fits_mobile(): data = _run_node( r""" import { chromium } from 'playwright'; const browser = await chromium.launch({ headless: true }); const page = await browser.newPage({ viewport: { width: 900, height: 700 } }); await page.goto('http://127.0.0.1:7011/static/js/documentOutline.js'); await page.setContent('
'); await page.evaluate(async () => { const mod = await import('/static/js/document.js?v=20260831richtexttools91&outline-test=1'); mod.init('/api'); mod.injectFreshDoc({ id: 'outline-md', title: 'Outline', language: 'markdown', current_content: '# Intro\n\nBody\n\n## Details\n\nMore\n\n### End', version_count: 1, }); await new Promise(resolve => setTimeout(resolve, 100)); }); await page.locator('#doc-outline-toolbar-btn').click(); const markdownLabels = await page.locator('.doc-outline-label').allTextContents(); await page.keyboard.press('ArrowDown'); await page.keyboard.press('Enter'); const selected = await page.locator('#doc-editor-textarea').evaluate(el => el.value.slice(el.selectionStart, el.selectionEnd)); await page.locator('#doc-outline-toolbar-btn').click(); await page.locator('#doc-editor-textarea').evaluate(el => { el.value += '\n\n#### Added live'; el.dispatchEvent(new Event('input', { bubbles: true })); }); const liveLabels = await page.locator('.doc-outline-label').allTextContents(); await page.keyboard.press('Escape'); await page.setViewportSize({ width: 390, height: 844 }); await page.locator('#doc-outline-toolbar-btn').click(); const mobileBox = await page.locator('#doc-outline-menu').boundingBox(); await page.keyboard.press('Escape'); await page.evaluate(() => { window.documentModule.injectFreshDoc({ id: 'outline-rich', title: 'Rich outline', language: 'richtext', current_content: 'Body