"""Tests for incremental streaming-markdown (smd) integration in messages.js. PR: feat: use streaming-markdown for incremental live rendering The change replaces the per-rAF `assistantBody.innerHTML = renderMd(...)` call with an incremental DOM-building approach powered by the streaming-markdown library (https://github.com/nicholasgasior/streaming-markdown): - During streaming: smd.parser_write() feeds new text deltas into a live DOM tree — no full re-render per frame, no innerHTML thrash. - On done/apperror/cancel: smd.parser_end() flushes remaining parser state, then Prism / copy buttons / KaTeX are run on the live segment. - On tool event: smd.parser_end() finalises the current segment; the next token after the tool creates a fresh parser bound to the new assistantBody. - Fallback: when window.smd is not yet loaded, the old renderMd path is used. - Reconnect: _smdReconnect flag clears stale DOM from the previous parser run and restarts the smd parser from the reconnect point. Tests are static (regex / AST-level) — no browser required. """ import pathlib import re REPO = pathlib.Path(__file__).parent.parent MESSAGES_JS = (REPO / "static" / "messages.js").read_text(encoding="utf-8") INDEX_HTML = (REPO / "static" / "index.html").read_text(encoding="utf-8") # ── Helpers ─────────────────────────────────────────────────────────────────── def extract_fn(src, name, *, brace_depth=1): """Return the text of a JS function starting from `function ` to its closing brace. Works for both standalone and closure-local functions. Does a simple brace-counting walk so it handles nested blocks correctly. """ pattern = rf"function {re.escape(name)}\s*\(" m = re.search(pattern, src) if not m: return None start = m.start() # Find the opening brace brace_pos = src.index("{", m.end()) depth = 1 pos = brace_pos + 1 while pos < len(src) and depth > 0: ch = src[pos] if ch == "{": depth += 1 elif ch == "}": depth -= 1 pos += 1 return src[start:pos] def extract_event_handler(src, event_name): """Return the text of a source.addEventListener('', ...) block.""" pattern = rf"source\.addEventListener\('{re.escape(event_name)}'" m = re.search(pattern, src) if not m: return None # Walk forward to collect the matching parenthesis paren_depth = 0 start = m.start() pos = m.end() # Count back to the opening paren paren_depth = 1 while pos < len(src) and paren_depth > 0: ch = src[pos] if ch == "(": paren_depth += 1 elif ch == ")": paren_depth -= 1 pos += 1 return src[start:pos] def extract_attach_live_stream_prelude(src): """Return the text from attachLiveStream opening to the first nested fn.""" m = re.search(r"function attachLiveStream\(", src) if not m: return None # Find the first nested function definition inside the closure inner = re.search(r"\bfunction _isActiveSession\b", src[m.start():]) if not inner: return src[m.start(): m.start() + 5000] return src[m.start(): m.start() + inner.start()] # ── 1. index.html: smd script tag ───────────────────────────────────────────── class TestIndexHtmlSmdScript: """streaming-markdown must be loaded in index.html before messages.js uses it.""" def test_smd_cdn_url_present(self): assert "streaming-markdown" in INDEX_HTML, ( "index.html must include a