Files
ObsiGate/tests/test_webrender.py
T
bruno 6a58a59a11
CI / lint (push) Successful in 1m37s
CI / security (push) Successful in 1m1s
CI / test (push) Successful in 3m26s
CI / build (push) Successful in 1m44s
CI / e2e (push) Successful in 11m1s
feat(ai): ecosysteme d'outils phase 2 - recherche a cle, cache/retry, Playwright, crawl, Gitea/GitHub, documents (#92)
2026-09-17 11:52:03 -04:00

74 lines
2.8 KiB
Python

"""Unit tests for the dynamic rendering path (#92): fetch_url(render=True)."""
import pytest
import backend.tools.web as web
from backend.tools import webrender
from backend.tools.context import ToolContext, ToolError, ToolMode
from backend.tools.registry import get_tool
def _ctx() -> ToolContext:
return ToolContext(user={"username": "tester", "vaults": []}, mode=ToolMode.IN_APP)
class TestRegistration:
def test_render_param_exposed_in_schema(self):
spec = get_tool("fetch_url")
assert spec is not None
assert "render" in spec.input_model.model_fields
class TestRenderUnavailable:
def test_missing_playwright_clear_error(self, monkeypatch):
monkeypatch.setattr(webrender, "_playwright_available", lambda: False)
with pytest.raises(ToolError) as ei:
web.fetch_url(_ctx(), web.FetchUrlInput(
url="https://example.com/spa", render=True))
assert ei.value.code == "playwright_unavailable"
def test_ssrf_guard_applied_before_render(self, monkeypatch):
monkeypatch.setattr(webrender, "_playwright_available", lambda: True)
with pytest.raises(ToolError) as ei:
web.fetch_url(_ctx(), web.FetchUrlInput(
url="http://127.0.0.1:9222/devtools", render=True))
assert ei.value.code in ("ssrf_blocked", "dns_error")
class TestRenderSuccess:
def test_fetch_url_delegates_to_worker(self, monkeypatch):
captured = {}
def fake_render(url):
captured["url"] = url
return {"url": url, "status": 200, "title": "SPA",
"text": "dynamic content", "rendered": True, "truncated": False}
monkeypatch.setattr(webrender, "render_page", fake_render)
out = web.fetch_url(_ctx(), web.FetchUrlInput(
url="https://example.com/spa", render=True))
assert captured["url"] == "https://example.com/spa"
assert out["rendered"] is True
assert "dynamic content" in out["text"]
def test_worker_failure_maps_to_tool_error(self, monkeypatch):
monkeypatch.setattr(webrender, "_playwright_available", lambda: True)
def boom(url):
raise RuntimeError("chromium crashed")
# The executor re-raises the worker exception on .result(); render_page
# must wrap it into a ToolError instead of leaking a bare exception.
monkeypatch.setattr(webrender, "_render_in_worker", boom)
with pytest.raises(ToolError) as ei:
web.fetch_url(_ctx(), web.FetchUrlInput(
url="https://example.com/spa", render=True))
assert ei.value.code == "render_unavailable"
class TestMarkdownExtraction:
def test_html_to_text_reused(self):
text = webrender._html_to_text("<html><body><p>hello</p><script>x()</script></body></html>")
assert "hello" in text
assert "x()" not in text