Add modal graph node inspection
This commit is contained in:
parent
5f3d938adc
commit
4c82e1643d
13 changed files with 179 additions and 25 deletions
|
|
@ -88,7 +88,7 @@ class DocForgeMcpTests(unittest.IsolatedAsyncioTestCase):
|
|||
visualization = results[11].structuredContent["visualization"]
|
||||
self.assertTrue(visualization["read_only"])
|
||||
self.assertTrue(visualization["project_bound"])
|
||||
self.assertEqual("graph-browser@2", visualization["template"])
|
||||
self.assertEqual("graph-browser@3", visualization["template"])
|
||||
self.assertTrue(visualization["url"].startswith("http://127.0.0.1:"))
|
||||
context = results[8].structuredContent
|
||||
self.assertLessEqual(context["estimated_tokens"], 180)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ from __future__ import annotations
|
|||
|
||||
import json
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
import unittest
|
||||
import urllib.error
|
||||
|
|
@ -13,6 +14,7 @@ from docforge.errors import DocForgeError
|
|||
from docforge.index import ProjectIndex
|
||||
from docforge.project import Project
|
||||
from docforge.visualization import (
|
||||
_GRAPH_BROWSER_HTML,
|
||||
VISUALIZATION_TEMPLATE,
|
||||
VisualizationIndexSnapshot,
|
||||
VisualizationRunner,
|
||||
|
|
@ -59,6 +61,21 @@ class VisualizationTests(unittest.TestCase):
|
|||
with self.assertRaisesRegex(DocForgeError, "safety boundary"):
|
||||
snapshot.node("guide.workflow", depth=1, limit=401)
|
||||
|
||||
@unittest.skipUnless(shutil.which("node"), "Node.js is required for embedded script validation")
|
||||
def test_embedded_browser_javascript_is_valid(self) -> None:
|
||||
script = _GRAPH_BROWSER_HTML.split("<script>", 1)[1].split("</script>", 1)[0]
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
path = Path(directory) / "graph-browser.js"
|
||||
path.write_text(script, encoding="utf-8")
|
||||
result = subprocess.run(
|
||||
["node", "--check", str(path)],
|
||||
check=False,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
self.assertEqual("", result.stderr)
|
||||
self.assertEqual(0, result.returncode)
|
||||
|
||||
def test_runner_serves_only_token_bound_read_only_graph_endpoints(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
root = self.copy_fixture("alpha", Path(directory))
|
||||
|
|
@ -84,8 +101,13 @@ class VisualizationTests(unittest.TestCase):
|
|||
self.assertIn('id="zoom-in"', html)
|
||||
self.assertIn('id="zoom-out"', html)
|
||||
self.assertIn('id="reset-view"', html)
|
||||
self.assertIn('id="node-dialog"', html)
|
||||
self.assertIn('id="explore-node"', html)
|
||||
self.assertIn('addEventListener("wheel"', html)
|
||||
self.assertIn('addEventListener("pointermove"', html)
|
||||
self.assertIn("inspectNode(node.node_id)", html)
|
||||
self.assertIn('dialog.showModal()', html)
|
||||
self.assertIn("await loadNode(nodeId)", html)
|
||||
self.assertIn("left-drag to pan", html)
|
||||
self.assertIn("default-src 'none'", headers["Content-Security-Policy"])
|
||||
self.assertEqual("no-store", headers["Cache-Control"])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue