Files
md_to_gost/tests/test_mermaid_renderer.py
Igor20264 1a5b35eb54
Python application / build (push) Has been cancelled
BigUpdate 0.5.0
- add Local Render Mermaid
- add page-starе для указания смещения страниц
- add Гиперссылки в документе на списки литературы
2026-09-07 09:54:33 +03:00

154 lines
5.2 KiB
Python

"""Tests for local Mermaid rendering chain."""
from __future__ import annotations
from pathlib import Path
from unittest.mock import patch
import pytest
from md2gost.diagram_renderer import configure_diagrams, render_diagram
from md2gost.mermaid_renderer import (
CACHE_KEY_PREFIX,
render_mermaid_local,
write_mermaid_outputs,
)
def test_cache_key_prefix_stable():
assert CACHE_KEY_PREFIX.startswith("mmd-local")
def test_prepare_mermaid_source_injects_init():
from md2gost.mermaid_renderer import prepare_mermaid_source
out = prepare_mermaid_source("flowchart LR\nA-->B", html_labels=True)
assert out.startswith("%%{init")
assert "htmlLabels': true" in out
assert "flowchart LR" in out
assert prepare_mermaid_source(out) == out
qj = prepare_mermaid_source("flowchart LR\nA-->B", html_labels=False)
assert "htmlLabels': false" in qj
def test_quickjs_cyrillic_no_foreign_object():
"""QuickJS uses htmlLabels:false → SVG text; resvg can paint Cyrillic."""
from md2gost.mermaid_renderer import _render_quickjs
got = _render_quickjs('flowchart LR\nA["Акционеры"] --> B["Тест"]', scale=1)
assert got is not None
svg, png = got
assert "Акционеры" in svg
assert "foreignObject" not in svg
assert "<text" in svg
assert png.startswith(b"\x89PNG")
assert len(png) > 2000
def test_write_mermaid_outputs_quickjs(tmp_path, monkeypatch):
png = b"\x89PNG\r\n\x1a\n" + b"\x00" * 40
svg = '<svg xmlns="http://www.w3.org/2000/svg"><rect/></svg>'
def fake_local(source, *, scale=1.0):
assert "flowchart" in source
return svg, png, "quickjs"
monkeypatch.setattr(
"md2gost.mermaid_renderer.render_mermaid_local", fake_local,
)
out_png = tmp_path / "a.png"
out_svg = tmp_path / "a.svg"
assert write_mermaid_outputs("flowchart LR\nA-->B", out_png, out_svg, scale=2)
assert out_png.read_bytes().startswith(b"\x89PNG")
assert "<svg" in out_svg.read_text(encoding="utf-8")
def test_render_mermaid_local_order_browser_then_quickjs(monkeypatch):
calls = []
def fake_browser(source, *, scale=1.0):
calls.append("browser")
return None
def fake_qj(source, *, scale=1.0):
calls.append("quickjs")
return (
'<svg xmlns="http://www.w3.org/2000/svg"/>',
b"\x89PNG\r\n\x1a\n" + b"\x00" * 20,
)
monkeypatch.setattr("md2gost.mermaid_renderer._render_browser", fake_browser)
monkeypatch.setattr("md2gost.mermaid_renderer._render_quickjs", fake_qj)
got = render_mermaid_local("flowchart LR\nA-->B")
assert got is not None
assert got[2] == "quickjs"
assert calls == ["browser", "quickjs"]
def test_render_diagram_uses_local_before_kroki(tmp_path):
png = b"\x89PNG\r\n\x1a\n" + b"\x00" * 20
svg = b'<svg xmlns="http://www.w3.org/2000/svg"/>'
kroki_calls = []
def fake_write(source, out_png, out_svg, *, scale=1.0):
Path(out_png).write_bytes(png)
if out_svg is not None:
Path(out_svg).write_bytes(svg)
return True
def fake_kroki(source, diagram_type, base_url, out_path, fmt="png"):
kroki_calls.append((diagram_type, fmt, base_url))
return False
configure_diagrams(fallback="remote", cache_dir=str(tmp_path), diagram_scale=2)
with patch("md2gost.diagram_renderer._render_plantuml_jar", return_value=False), \
patch("md2gost.mermaid_renderer.write_mermaid_outputs", side_effect=fake_write), \
patch("md2gost.diagram_renderer._render_kroki", side_effect=fake_kroki):
result = render_diagram(
"mermaid", "flowchart LR\nA-->B", cache_dir=str(tmp_path),
)
assert kroki_calls == []
assert Path(result.png_path).read_bytes().startswith(b"\x89PNG")
assert result.pixel_scale == 2.0
def test_render_diagram_falls_to_kroki_if_local_fails(tmp_path):
png = b"\x89PNG\r\n\x1a\n" + b"\x00" * 20
kroki_calls = []
def fake_write(*args, **kwargs):
return False
def fake_kroki(source, diagram_type, base_url, out_path, fmt="png"):
kroki_calls.append((diagram_type, fmt, base_url))
if fmt == "png":
out_path.write_bytes(png)
else:
out_path.write_bytes(b"<svg xmlns='http://www.w3.org/2000/svg'/>")
return True
configure_diagrams(fallback="remote", cache_dir=str(tmp_path))
with patch("md2gost.diagram_renderer._render_plantuml_jar", return_value=False), \
patch("md2gost.mermaid_renderer.write_mermaid_outputs", side_effect=fake_write), \
patch("md2gost.diagram_renderer._render_kroki", side_effect=fake_kroki):
result = render_diagram("mermaid", "flowchart LR\nA-->B", cache_dir=str(tmp_path))
assert any(t == "mermaid" and f == "png" for t, f, _ in kroki_calls)
assert Path(result.png_path).read_bytes().startswith(b"\x89PNG")
assert result.pixel_scale == 1.0
@pytest.mark.skipif(
__import__("importlib").util.find_spec("mermaidx") is None,
reason="mermaidx not installed",
)
def test_quickjs_real_render():
from md2gost.mermaid_renderer import _render_quickjs
got = _render_quickjs("flowchart LR\nA-->B", scale=1)
assert got is not None
svg, png = got
assert "<svg" in svg.lower()
assert png.startswith(b"\x89PNG")