"""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 " 2000 def test_write_mermaid_outputs_quickjs(tmp_path, monkeypatch): png = b"\x89PNG\r\n\x1a\n" + b"\x00" * 40 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 "', 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'' 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"") 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 "