refactor: extract parseA2UIBlocks to lib/a2ui.ts; remove unused import re

- Extract parseA2UIBlocks() from A2UIRenderer.tsx into its own
  frontend/src/lib/a2ui.ts module to satisfy react-refresh/only-export-
  components ESLint rule (A2UIRenderer should only export React components)
- Update ChatPanel.tsx and test files to import from lib/a2ui
- Split ChatPanel.test.tsx mock: separate vi.mock for lib/a2ui
  (parseA2UIBlocks) and A2UIRenderer (component only)
- Remove unused 'import re' from tests/test_runtime_html.py (ruff F401)

All 216 frontend tests and 242 bash tests still pass. TypeScript and
Vite builds are clean. Remaining ESLint warnings (react-hooks/set-state-
in-effect in MCPAppRenderer and useSessions) are pre-existing patterns
not introduced by Phase 3.
This commit is contained in:
Ken
2026-05-26 21:14:10 +00:00
parent 2c3cfdbedc
commit 389a8fb655
6 changed files with 82 additions and 36 deletions
+47 -13
View File
@@ -7,7 +7,7 @@ as specified in task-5.
"""
import os
import re
import pytest
HTML_FILE = os.path.join(
@@ -31,7 +31,10 @@ class TestFileExists:
assert os.path.exists(HTML_FILE), f"runtime.html not found at {HTML_FILE}"
def test_is_complete_html_document(self, html_content):
assert "<!DOCTYPE html>" in html_content or "<!doctype html>" in html_content.lower()
assert (
"<!DOCTYPE html>" in html_content
or "<!doctype html>" in html_content.lower()
)
assert "<html" in html_content
assert "</html>" in html_content
@@ -40,21 +43,32 @@ class TestCDNLibraries:
"""Verify all required CDN libraries are present in the head section."""
def test_tabler_css_cdn(self, html_content):
assert "https://cdn.jsdelivr.net/npm/@tabler/core@1.0.0-beta20/dist/css/tabler.min.css" in html_content
assert (
"https://cdn.jsdelivr.net/npm/@tabler/core@1.0.0-beta20/dist/css/tabler.min.css"
in html_content
)
def test_leaflet_css_cdn(self, html_content):
assert "https://cdn.jsdelivr.net/npm/leaflet@1.9/dist/leaflet.css" in html_content
assert (
"https://cdn.jsdelivr.net/npm/leaflet@1.9/dist/leaflet.css" in html_content
)
def test_chartjs_cdn(self, html_content):
assert "https://cdn.jsdelivr.net/npm/chart.js@4" in html_content
def test_leaflet_js_cdn(self, html_content):
assert "https://cdn.jsdelivr.net/npm/leaflet@1.9/dist/leaflet.js" in html_content
assert (
"https://cdn.jsdelivr.net/npm/leaflet@1.9/dist/leaflet.js" in html_content
)
def test_react_19_umd(self, html_content):
# React 19 production UMD
assert "react@19" in html_content
assert "umd" in html_content.lower() or "unpkg.com" in html_content or "cdn.jsdelivr.net" in html_content
assert (
"umd" in html_content.lower()
or "unpkg.com" in html_content
or "cdn.jsdelivr.net" in html_content
)
def test_react_dom_19_umd(self, html_content):
# ReactDOM 19 production UMD
@@ -73,7 +87,9 @@ class TestStyles:
assert "transparent" in html_content
def test_dark_color_scheme(self, html_content):
assert "color-scheme: dark" in html_content or "color-scheme:dark" in html_content
assert (
"color-scheme: dark" in html_content or "color-scheme:dark" in html_content
)
def test_body_padding_16px(self, html_content):
assert "16px" in html_content
@@ -83,7 +99,11 @@ class TestStyles:
def test_visual_error_red_color(self, html_content):
# red text color for error class
assert "#ff" in html_content.lower() or "red" in html_content or "color: #" in html_content
assert (
"#ff" in html_content.lower()
or "red" in html_content
or "color: #" in html_content
)
def test_visual_error_monospace(self, html_content):
assert "monospace" in html_content
@@ -118,7 +138,11 @@ class TestMcpBridge:
def test_call_tool_jsonrpc_20(self, html_content):
# jsonrpc key may appear as unquoted JS property (jsonrpc:) or quoted ("jsonrpc" / 'jsonrpc')
assert '"jsonrpc"' in html_content or "'jsonrpc'" in html_content or "jsonrpc:" in html_content
assert (
'"jsonrpc"' in html_content
or "'jsonrpc'" in html_content
or "jsonrpc:" in html_content
)
assert '"2.0"' in html_content or "'2.0'" in html_content
def test_call_tool_method_name(self, html_content):
@@ -129,7 +153,11 @@ class TestMcpBridge:
def test_call_tool_uses_uuid(self, html_content):
# Random UUID for call id
assert "crypto" in html_content or "Math.random" in html_content or "uuid" in html_content.lower()
assert (
"crypto" in html_content
or "Math.random" in html_content
or "uuid" in html_content.lower()
)
def test_send_message_method(self, html_content):
assert "sendMessage" in html_content
@@ -169,7 +197,7 @@ class TestExecuteVisual:
def test_jsx_detection_type_text_babel(self, html_content):
# The regex pattern in JS source: /type="text\/babel"/ contains text\/babel
assert 'text/babel' in html_content or r'text\/babel' in html_content
assert "text/babel" in html_content or r"text\/babel" in html_content
def test_jsx_path_uses_babel_transform(self, html_content):
assert "Babel.transform" in html_content
@@ -200,7 +228,11 @@ class TestExecuteVisual:
assert "new Function" in html_content
def test_plain_js_passes_chart_arg(self, html_content):
assert '"Chart"' in html_content or "'Chart'" in html_content or "Chart" in html_content
assert (
'"Chart"' in html_content
or "'Chart'" in html_content
or "Chart" in html_content
)
def test_plain_js_passes_leaflet_arg(self, html_content):
assert '"L"' in html_content or "'L'" in html_content
@@ -270,4 +302,6 @@ class TestInitialHandshake:
assert "1.0.0" in html_content
def test_handshake_uses_send_to_host(self, html_content):
assert "sendToHost" in html_content or "window.parent.postMessage" in html_content
assert (
"sendToHost" in html_content or "window.parent.postMessage" in html_content
)